1mod event;
16mod layer;
17
18use std::sync::Arc;
19
20use common_function::function::FunctionContext;
21use common_function::function_registry::{FUNCTION_REGISTRY, get_admin_function};
22use common_query::Output;
23use common_recordbatch::{RecordBatch, RecordBatches};
24use common_sql::convert::sql_value_to_value;
25use common_telemetry::tracing;
26use common_time::Timezone;
27use datafusion_expr::TypeSignature;
28use datatypes::arrow::datatypes::DataType as ArrowDataType;
29use datatypes::data_type::DataType;
30use datatypes::prelude::ConcreteDataType;
31use datatypes::schema::{ColumnSchema, Schema};
32use datatypes::value::Value;
33use datatypes::vectors::VectorRef;
34pub use layer::{
35 AdminEventRecorderHandle, AdminFunctionLayer, AdminFunctionLayerRef,
36 AdminFunctionRecordingLayer,
37};
38use session::context::QueryContextRef;
39use snafu::{OptionExt, ResultExt, ensure};
40use sql::ast::{Expr, FunctionArg, FunctionArgExpr, FunctionArguments, Value as SqlValue};
41use sql::statements::admin::Admin;
42
43use crate::error::{self, CastSnafu, ExecuteAdminFunctionSnafu, Result};
44use crate::statement::StatementExecutor;
45
46const DUMMY_COLUMN: &str = "<dummy>";
47
48#[derive(Clone)]
50pub struct AdminFunctionRequest {
51 pub statement: Admin,
53 pub query_ctx: QueryContextRef,
55}
56
57pub struct AdminFunctionResponse {
59 pub output: Output,
61 pub immediate_result: Option<Value>,
63}
64
65#[async_trait::async_trait]
67pub trait AdminFunctionService: Send + Sync {
68 async fn call(&self, request: AdminFunctionRequest) -> Result<AdminFunctionResponse>;
70}
71
72pub type AdminFunctionServiceRef = Arc<dyn AdminFunctionService>;
74
75#[derive(Clone)]
76struct CoreAdminFunctionService {
77 query_engine: query::QueryEngineRef,
78}
79
80impl CoreAdminFunctionService {
81 fn new(query_engine: query::QueryEngineRef) -> Self {
82 Self { query_engine }
83 }
84
85 async fn execute(&self, request: AdminFunctionRequest) -> Result<AdminFunctionResponse> {
86 let AdminFunctionRequest {
87 statement: stmt,
88 query_ctx,
89 } = request;
90
91 let Admin::Func(func) = &stmt;
92 let func_name = func.name.to_string().to_lowercase();
94 let factory = get_admin_function(&func_name)
95 .or_else(|| FUNCTION_REGISTRY.get_function(&func_name))
96 .context(error::AdminFunctionNotFoundSnafu {
97 name: func_name.clone(),
98 })?;
99
100 let func_ctx = FunctionContext {
101 query_ctx: query_ctx.clone(),
102 state: self.query_engine.engine_state().function_state(),
103 };
104
105 let admin_udf = factory.provide(func_ctx);
106 let admin_async_fn = admin_udf
107 .as_async()
108 .context(error::AdminFunctionNotFoundSnafu { name: func_name })?;
109
110 let fn_name = admin_udf.name();
111 let signature = admin_udf.signature();
112
113 let FunctionArguments::List(args) = &func.args else {
115 return error::BuildAdminFunctionArgsSnafu {
116 msg: format!("unsupported function args {} for {}", func.args, fn_name),
117 }
118 .fail();
119 };
120 let arg_values = args
121 .args
122 .iter()
123 .map(|arg| {
124 let FunctionArg::Unnamed(FunctionArgExpr::Expr(Expr::Value(value))) = arg else {
125 return error::BuildAdminFunctionArgsSnafu {
126 msg: format!("unsupported function arg {arg} for {}", fn_name),
127 }
128 .fail();
129 };
130 Ok(&value.value)
131 })
132 .collect::<Result<Vec<_>>>()?;
133
134 let args = args_to_vector(&signature.type_signature, &arg_values, &query_ctx)?;
135 let arg_types = args
136 .iter()
137 .map(|arg| arg.data_type().as_arrow_type())
138 .collect::<Vec<_>>();
139 let ret_type = admin_udf.return_type(&arg_types).map_err(|e| {
140 error::Error::BuildAdminFunctionArgs {
141 msg: format!(
142 "Failed to get return type of admin function {}: {}",
143 fn_name, e
144 ),
145 }
146 })?;
147
148 let columnar_args: Vec<datafusion_expr::ColumnarValue> = args
150 .iter()
151 .map(|vector| datafusion_expr::ColumnarValue::Array(vector.to_arrow_array()))
152 .collect();
153
154 let func_args = datafusion::logical_expr::ScalarFunctionArgs {
156 args: columnar_args,
157 arg_fields: args
158 .iter()
159 .enumerate()
160 .map(|(i, vector)| {
161 Arc::new(arrow::datatypes::Field::new(
162 format!("arg_{}", i),
163 arg_types[i].clone(),
164 vector.null_count() > 0,
165 ))
166 })
167 .collect(),
168 return_field: Arc::new(arrow::datatypes::Field::new("result", ret_type, true)),
169 number_rows: if args.is_empty() { 1 } else { args[0].len() },
170 config_options: Arc::new(query_ctx.create_config_options()),
171 };
172
173 let result_columnar = admin_async_fn
175 .invoke_async_with_args(func_args)
176 .await
177 .with_context(|_| ExecuteAdminFunctionSnafu {
178 msg: fn_name.to_string(),
179 })?;
180
181 let result_columnar: common_query::prelude::ColumnarValue =
183 (&result_columnar).try_into().context(CastSnafu)?;
184
185 let result_vector: VectorRef = result_columnar.try_into_vector(1).context(CastSnafu)?;
186 let immediate_result = immediate_result(&result_vector);
187
188 let column_schemas = vec![ColumnSchema::new(
189 stmt.to_string(),
191 result_vector.data_type(),
192 false,
193 )];
194 let schema = Arc::new(Schema::new(column_schemas));
195 let batch = RecordBatch::new(schema.clone(), vec![result_vector])
196 .context(error::BuildRecordBatchSnafu)?;
197 let batches =
198 RecordBatches::try_new(schema, vec![batch]).context(error::BuildRecordBatchSnafu)?;
199
200 Ok(AdminFunctionResponse {
201 output: Output::new_with_record_batches(batches),
202 immediate_result,
203 })
204 }
205}
206
207fn immediate_result(result_vector: &VectorRef) -> Option<Value> {
208 (!result_vector.is_empty()).then(|| result_vector.get(0))
209}
210
211#[async_trait::async_trait]
212impl AdminFunctionService for CoreAdminFunctionService {
213 async fn call(&self, request: AdminFunctionRequest) -> Result<AdminFunctionResponse> {
214 self.execute(request).await
215 }
216}
217
218pub(crate) fn new_admin_function_service(
220 query_engine: query::QueryEngineRef,
221) -> AdminFunctionServiceRef {
222 Arc::new(CoreAdminFunctionService::new(query_engine))
223}
224
225impl StatementExecutor {
226 #[tracing::instrument(skip_all)]
228 pub(crate) async fn execute_admin_command(
229 &self,
230 stmt: Admin,
231 query_ctx: QueryContextRef,
232 ) -> Result<Output> {
233 self.admin_function_service
234 .call(AdminFunctionRequest {
235 statement: stmt,
236 query_ctx,
237 })
238 .await
239 .map(|response| response.output)
240 }
241}
242
243fn args_to_vector(
245 type_signature: &TypeSignature,
246 args: &Vec<&SqlValue>,
247 query_ctx: &QueryContextRef,
248) -> Result<Vec<VectorRef>> {
249 let tz = query_ctx.timezone();
250
251 match type_signature {
252 TypeSignature::Variadic(valid_types) => {
253 values_to_vectors_by_valid_types(valid_types, args, Some(&tz))
254 }
255
256 TypeSignature::Uniform(arity, valid_types) => {
257 ensure!(
258 *arity == args.len(),
259 error::FunctionArityMismatchSnafu {
260 actual: args.len(),
261 expected: *arity,
262 }
263 );
264
265 values_to_vectors_by_valid_types(valid_types, args, Some(&tz))
266 }
267
268 TypeSignature::Exact(data_types) => {
269 values_to_vectors_by_exact_types(data_types, args, Some(&tz))
270 }
271
272 TypeSignature::VariadicAny => {
273 let data_types = args
274 .iter()
275 .map(|value| try_get_data_type_for_sql_value(value))
276 .collect::<Result<Vec<_>>>()?;
277
278 values_to_vectors_by_exact_types(&data_types, args, Some(&tz))
279 }
280
281 TypeSignature::Any(arity) => {
282 ensure!(
283 *arity == args.len(),
284 error::FunctionArityMismatchSnafu {
285 actual: args.len(),
286 expected: *arity,
287 }
288 );
289
290 let data_types = args
291 .iter()
292 .map(|value| try_get_data_type_for_sql_value(value))
293 .collect::<Result<Vec<_>>>()?;
294
295 values_to_vectors_by_exact_types(&data_types, args, Some(&tz))
296 }
297
298 TypeSignature::OneOf(type_sigs) => {
299 for type_sig in type_sigs {
300 if let Ok(vectors) = args_to_vector(type_sig, args, query_ctx) {
301 return Ok(vectors);
302 }
303 }
304
305 error::BuildAdminFunctionArgsSnafu {
306 msg: "function signature not match",
307 }
308 .fail()
309 }
310
311 _ => error::BuildAdminFunctionArgsSnafu {
312 msg: format!("unknown function type signature: {type_signature:?}"),
313 }
314 .fail(),
315 }
316}
317
318fn values_to_vectors_by_exact_types(
320 exact_types: &[ArrowDataType],
321 args: &[&SqlValue],
322 tz: Option<&Timezone>,
323) -> Result<Vec<VectorRef>> {
324 args.iter()
325 .zip(exact_types.iter())
326 .map(|(value, data_type)| {
327 let schema = ColumnSchema::new(
328 DUMMY_COLUMN,
329 ConcreteDataType::from_arrow_type(data_type),
330 true,
331 );
332 let value = sql_value_to_value(&schema, value, tz, None, false)
333 .context(error::SqlCommonSnafu)?;
334
335 Ok(value_to_vector(value))
336 })
337 .collect()
338}
339
340fn values_to_vectors_by_valid_types(
342 valid_types: &[ArrowDataType],
343 args: &[&SqlValue],
344 tz: Option<&Timezone>,
345) -> Result<Vec<VectorRef>> {
346 args.iter()
347 .map(|value| {
348 for data_type in valid_types {
349 let schema = ColumnSchema::new(
350 DUMMY_COLUMN,
351 ConcreteDataType::from_arrow_type(data_type),
352 true,
353 );
354 if let Ok(value) = sql_value_to_value(&schema, value, tz, None, false) {
355 return Ok(value_to_vector(value));
356 }
357 }
358
359 error::BuildAdminFunctionArgsSnafu {
360 msg: format!("failed to cast {value}"),
361 }
362 .fail()
363 })
364 .collect::<Result<Vec<_>>>()
365}
366
367fn value_to_vector(value: Value) -> VectorRef {
369 let data_type = value.data_type();
370 let mut mutable_vector = data_type.create_mutable_vector(1);
371 mutable_vector.push_value_ref(&value.as_value_ref());
372
373 mutable_vector.to_vector()
374}
375
376fn try_get_data_type_for_sql_value(value: &SqlValue) -> Result<ArrowDataType> {
378 match value {
379 SqlValue::Number(_, _) => Ok(ArrowDataType::Float64),
380 SqlValue::Null => Ok(ArrowDataType::Null),
381 SqlValue::Boolean(_) => Ok(ArrowDataType::Boolean),
382 SqlValue::HexStringLiteral(_)
383 | SqlValue::DoubleQuotedString(_)
384 | SqlValue::SingleQuotedString(_) => Ok(ArrowDataType::Utf8),
385 _ => error::BuildAdminFunctionArgsSnafu {
386 msg: format!("unsupported sql value: {value}"),
387 }
388 .fail(),
389 }
390}
391
392#[cfg(test)]
393mod tests {
394 use std::sync::Arc;
395
396 use datatypes::vectors::{Int32Vector, VectorRef};
397
398 use crate::statement::admin::immediate_result;
399
400 #[test]
401 fn empty_admin_function_result_has_no_immediate_value() {
402 let result_vector: VectorRef = Arc::new(Int32Vector::from(vec![]));
403
404 assert_eq!(immediate_result(&result_vector), None);
405 }
406}