use std::sync::Arc;
use surrealdb_types::{SqlFormat, ToSql};
use super::helpers::{args_access_mode, args_required_context, evaluate_args};
use crate::exec::physical_expr::{EvalContext, PhysicalExpr};
use crate::exec::{AccessMode, BoxFut};
use crate::expr::FlowResult;
use crate::val::Value;
#[derive(Debug)]
pub struct IndexFunctionExec {
pub(crate) name: String,
pub(crate) arguments: Vec<Arc<dyn PhysicalExpr>>,
pub(crate) index_ctx: crate::exec::function::IndexContext,
pub(crate) func_required_context: crate::exec::ContextLevel,
}
impl PhysicalExpr for IndexFunctionExec {
fn name(&self) -> &'static str {
"IndexFunction"
}
fn as_any(&self) -> &dyn std::any::Any {
self
}
fn required_context(&self) -> crate::exec::ContextLevel {
let args_ctx = args_required_context(&self.arguments);
args_ctx.max(self.func_required_context)
}
fn access_mode(&self) -> AccessMode {
args_access_mode(&self.arguments)
}
fn evaluate<'a>(&'a self, ctx: EvalContext<'a>) -> BoxFut<'a, FlowResult<Value>> {
Box::pin(async move {
let registry = ctx.exec_ctx.function_registry();
let func = registry.get_index_function(&self.name).ok_or_else(|| {
anyhow::anyhow!(
"Unknown index function '{}' - not found in function registry",
self.name
)
})?;
let args = evaluate_args(&self.arguments, ctx.clone()).await?;
Ok(func.invoke_async(&ctx, &self.index_ctx, args).await?)
})
}
}
impl ToSql for IndexFunctionExec {
fn fmt_sql(&self, f: &mut String, _fmt: SqlFormat) {
f.push_str(&self.name);
f.push_str("(...)");
}
}
impl Clone for IndexFunctionExec {
fn clone(&self) -> Self {
Self {
name: self.name.clone(),
arguments: self.arguments.clone(),
index_ctx: self.index_ctx.clone(),
func_required_context: self.func_required_context,
}
}
}