common_function/system/
database.rs1use std::fmt::{self};
16use std::sync::Arc;
17
18use common_query::error::Result;
19use common_query::prelude::{Signature, Volatility};
20use datatypes::prelude::{ConcreteDataType, ScalarVector};
21use datatypes::vectors::{StringVector, VectorRef};
22
23use crate::function::{Function, FunctionContext};
24
25#[derive(Clone, Debug, Default)]
27pub struct DatabaseFunction;
28
29#[derive(Clone, Debug, Default)]
30pub struct CurrentSchemaFunction;
31pub struct SessionUserFunction;
32
33pub struct ReadPreferenceFunction;
34
35const DATABASE_FUNCTION_NAME: &str = "database";
36const CURRENT_SCHEMA_FUNCTION_NAME: &str = "current_schema";
37const SESSION_USER_FUNCTION_NAME: &str = "session_user";
38const READ_PREFERENCE_FUNCTION_NAME: &str = "read_preference";
39
40impl Function for DatabaseFunction {
41 fn name(&self) -> &str {
42 DATABASE_FUNCTION_NAME
43 }
44
45 fn return_type(&self, _input_types: &[ConcreteDataType]) -> Result<ConcreteDataType> {
46 Ok(ConcreteDataType::string_datatype())
47 }
48
49 fn signature(&self) -> Signature {
50 Signature::nullary(Volatility::Immutable)
51 }
52
53 fn eval(&self, func_ctx: &FunctionContext, _columns: &[VectorRef]) -> Result<VectorRef> {
54 let db = func_ctx.query_ctx.current_schema();
55
56 Ok(Arc::new(StringVector::from_slice(&[&db])) as _)
57 }
58}
59
60impl Function for CurrentSchemaFunction {
61 fn name(&self) -> &str {
62 CURRENT_SCHEMA_FUNCTION_NAME
63 }
64
65 fn return_type(&self, _input_types: &[ConcreteDataType]) -> Result<ConcreteDataType> {
66 Ok(ConcreteDataType::string_datatype())
67 }
68
69 fn signature(&self) -> Signature {
70 Signature::uniform(0, vec![], Volatility::Immutable)
71 }
72
73 fn eval(&self, func_ctx: &FunctionContext, _columns: &[VectorRef]) -> Result<VectorRef> {
74 let db = func_ctx.query_ctx.current_schema();
75
76 Ok(Arc::new(StringVector::from_slice(&[&db])) as _)
77 }
78}
79
80impl Function for SessionUserFunction {
81 fn name(&self) -> &str {
82 SESSION_USER_FUNCTION_NAME
83 }
84
85 fn return_type(&self, _input_types: &[ConcreteDataType]) -> Result<ConcreteDataType> {
86 Ok(ConcreteDataType::string_datatype())
87 }
88
89 fn signature(&self) -> Signature {
90 Signature::uniform(0, vec![], Volatility::Immutable)
91 }
92
93 fn eval(&self, func_ctx: &FunctionContext, _columns: &[VectorRef]) -> Result<VectorRef> {
94 let user = func_ctx.query_ctx.current_user();
95
96 Ok(Arc::new(StringVector::from_slice(&[user.username()])) as _)
97 }
98}
99
100impl Function for ReadPreferenceFunction {
101 fn name(&self) -> &str {
102 READ_PREFERENCE_FUNCTION_NAME
103 }
104
105 fn return_type(&self, _input_types: &[ConcreteDataType]) -> Result<ConcreteDataType> {
106 Ok(ConcreteDataType::string_datatype())
107 }
108
109 fn signature(&self) -> Signature {
110 Signature::nullary(Volatility::Immutable)
111 }
112
113 fn eval(&self, func_ctx: &FunctionContext, _columns: &[VectorRef]) -> Result<VectorRef> {
114 let read_preference = func_ctx.query_ctx.read_preference();
115
116 Ok(Arc::new(StringVector::from_slice(&[read_preference.as_ref()])) as _)
117 }
118}
119
120impl fmt::Display for DatabaseFunction {
121 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
122 write!(f, "DATABASE")
123 }
124}
125
126impl fmt::Display for CurrentSchemaFunction {
127 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
128 write!(f, "CURRENT_SCHEMA")
129 }
130}
131
132impl fmt::Display for SessionUserFunction {
133 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
134 write!(f, "SESSION_USER")
135 }
136}
137
138impl fmt::Display for ReadPreferenceFunction {
139 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
140 write!(f, "READ_PREFERENCE")
141 }
142}
143
144#[cfg(test)]
145mod tests {
146 use std::sync::Arc;
147
148 use session::context::QueryContextBuilder;
149
150 use super::*;
151 #[test]
152 fn test_build_function() {
153 let build = DatabaseFunction;
154 assert_eq!("database", build.name());
155 assert_eq!(
156 ConcreteDataType::string_datatype(),
157 build.return_type(&[]).unwrap()
158 );
159 assert_eq!(build.signature(), Signature::nullary(Volatility::Immutable));
160
161 let query_ctx = QueryContextBuilder::default()
162 .current_schema("test_db".to_string())
163 .build()
164 .into();
165
166 let func_ctx = FunctionContext {
167 query_ctx,
168 ..Default::default()
169 };
170 let vector = build.eval(&func_ctx, &[]).unwrap();
171 let expect: VectorRef = Arc::new(StringVector::from(vec!["test_db"]));
172 assert_eq!(expect, vector);
173 }
174}