use crate::{Arc, Engine};
use uqa_sql::{
ast::{ColumnType, FunctionBinding},
routines::{
resolution::{RoutineOverloadCatalog, RoutineOverloadContext, RoutineTypeSnapshot},
RoutineResolution, SQLUserFunction, StaticFunctionMatch,
},
type_resolution::{BuiltinFunctionOverload, FunctionTypeResolver, ResolvedFunctionOverload},
SQLError,
};
impl RoutineOverloadCatalog for Engine {
fn routine_type_snapshot(&self) -> RoutineTypeSnapshot {
self.catalog_read_view().domain_snapshot()
}
fn routine_search_path(&self) -> Vec<String> {
crate::session::effective_search_path(&self.session.state.read())
}
fn has_registered_scalar_function(&self, name: &str) -> bool {
Engine::has_registered_scalar_function(self, name)
}
fn lookup_sql_routine_candidates(
&self,
name: &str,
) -> Result<Option<Vec<Arc<SQLUserFunction>>>, SQLError> {
Engine::lookup_sql_routine_candidates(self, name)
}
fn lookup_bound_sql_routine_candidates_by_binding(
&self,
binding: &FunctionBinding,
) -> Option<Vec<Arc<SQLUserFunction>>> {
Engine::lookup_bound_sql_routine_candidates_by_binding(self, binding)
}
fn lookup_bound_sql_functions_by_binding(
&self,
binding: &FunctionBinding,
) -> Option<Vec<Arc<SQLUserFunction>>> {
Engine::lookup_bound_sql_functions_by_binding(self, binding)
}
}
impl RoutineResolution for Engine {
fn routine_body(
&self,
function: &SQLUserFunction,
) -> Result<Arc<uqa_sql::routines::CompiledFunctionBody>, SQLError> {
self.session.routine_bodies.body(function, |def| {
uqa_execution::routines::invocation::bodies::compile_session_body(
self,
&self.routine_definition_context().compilation.analysis,
def,
)
})
}
fn routine_analysis_body(
&self,
function: &SQLUserFunction,
) -> Result<Arc<uqa_sql::routines::CompiledFunctionBody>, SQLError> {
if matches!(function.body, uqa_sql::routines::RoutineBody::Source) {
self.session.routine_bodies.inspect(function, |definition| {
uqa_execution::routines::invocation::bodies::compile_analysis_body(
self,
&self.routine_compilation_context(),
definition,
)
})
} else {
self.routine_body(function)
}
}
fn lookup_bound_sql_functions(&self, name: &str) -> Option<Vec<Arc<SQLUserFunction>>> {
Engine::lookup_bound_sql_functions(self, name)
}
fn lookup_bound_sql_functions_by_binding(
&self,
binding: &FunctionBinding,
) -> Option<Vec<Arc<SQLUserFunction>>> {
Engine::lookup_bound_sql_functions_by_binding(self, binding)
}
fn has_registered_scalar_function(&self, name: &str) -> bool {
Engine::has_registered_scalar_function(self, name)
}
fn has_registered_table_function(&self, name: &str) -> bool {
Engine::has_registered_table_function(self, name)
}
fn has_registered_aggregate_function(&self, name: &str) -> bool {
Engine::has_registered_aggregate_function(self, name)
}
fn lookup_visible_sql_functions(
&self,
name: &str,
) -> Result<Option<Vec<Arc<SQLUserFunction>>>, SQLError> {
Engine::lookup_visible_sql_functions(self, name)
}
fn lookup_visible_sql_functions_for_analysis(
&self,
name: &str,
) -> Result<Option<Vec<Arc<SQLUserFunction>>>, SQLError> {
Engine::lookup_visible_sql_functions_for_analysis(self, name)
}
fn resolve_static_sql_function(
&self,
name: &str,
binding: Option<&FunctionBinding>,
argument_names: &[Option<String>],
argument_types: &[Option<ColumnType>],
explicit_variadic: bool,
) -> Result<Option<Arc<SQLUserFunction>>, SQLError> {
Engine::resolve_static_sql_function(
self,
name,
binding,
argument_names,
argument_types,
explicit_variadic,
)
}
fn resolve_static_sql_function_match(
&self,
name: &str,
binding: Option<&FunctionBinding>,
argument_names: &[Option<String>],
argument_types: &[Option<ColumnType>],
explicit_variadic: bool,
) -> Result<Option<StaticFunctionMatch>, SQLError> {
Engine::resolve_static_sql_function_match(
self,
name,
binding,
argument_names,
argument_types,
explicit_variadic,
)
}
fn resolve_table_function_overload_with_builtins(
&self,
name: &str,
binding: Option<&FunctionBinding>,
argument_names: &[Option<String>],
argument_types: &[Option<ColumnType>],
explicit_variadic: bool,
builtins: &[BuiltinFunctionOverload],
) -> Result<Option<ResolvedFunctionOverload>, SQLError> {
Engine::resolve_table_function_overload_with_builtins(
self,
name,
binding,
argument_names,
argument_types,
explicit_variadic,
builtins,
)
}
}
impl FunctionTypeResolver for Engine {
fn has_untyped_function(&self, name: &str) -> bool {
self.routine_overload_context().has_untyped_function(name)
}
fn resolve_type_name(&self, name: &str) -> Result<Option<ColumnType>, SQLError> {
self.routine_overload_context().resolve_type_name(name)
}
fn enum_labels(&self) -> Option<&dyn uqa_sql::expr::enums::EnumLabelCatalog> {
Some(self)
}
fn catalog_input_functions(&self) -> Option<&dyn uqa_sql::expr::CatalogInputFunctions> {
Some(self)
}
fn composite_types(&self) -> Option<&dyn uqa_sql::expr::composites::CompositeTypeCatalog> {
Some(self)
}
fn require_type_usage(&self, ty: &ColumnType) -> Result<(), SQLError> {
uqa_execution::catalog::security::type_inquiry::require_type_usage(
&self.catalog_execution(),
ty,
)
}
fn resolve_function_type(
&self,
name: &str,
binding: Option<&FunctionBinding>,
argument_names: &[Option<String>],
argument_types: &[Option<ColumnType>],
explicit_variadic: bool,
) -> Result<Option<ColumnType>, SQLError> {
self.routine_overload_context().resolve_function_type(
name,
binding,
argument_names,
argument_types,
explicit_variadic,
)
}
fn resolve_function_overload(
&self,
name: &str,
binding: Option<&FunctionBinding>,
argument_names: &[Option<String>],
argument_types: &[Option<ColumnType>],
explicit_variadic: bool,
) -> Result<Option<ResolvedFunctionOverload>, SQLError> {
self.routine_overload_context().resolve_function_overload(
name,
binding,
argument_names,
argument_types,
explicit_variadic,
)
}
fn is_scalar_function_binding(&self, binding: &FunctionBinding) -> Result<bool, SQLError> {
self.routine_overload_context()
.is_scalar_function_binding(binding)
}
fn resolve_function_overload_with_builtins(
&self,
name: &str,
binding: Option<&FunctionBinding>,
argument_names: &[Option<String>],
argument_types: &[Option<ColumnType>],
explicit_variadic: bool,
builtins: &[BuiltinFunctionOverload],
) -> Result<Option<ResolvedFunctionOverload>, SQLError> {
self.routine_overload_context()
.resolve_function_overload_with_builtins(
name,
binding,
argument_names,
argument_types,
explicit_variadic,
builtins,
)
}
}
impl uqa_sql::expr::CatalogInputFunctions for Engine {
fn read_unknown_input(
&self,
text: &str,
target: &ColumnType,
) -> Result<uqa_core::Value, SQLError> {
uqa_sql::expr::read_catalog_input(text, target, self)
}
}
impl Engine {
fn routine_overload_context(&self) -> RoutineOverloadContext<'_> {
RoutineOverloadContext { catalog: self }
}
pub(crate) fn resolve_static_sql_function(
&self,
name: &str,
binding: Option<&FunctionBinding>,
argument_names: &[Option<String>],
argument_types: &[Option<ColumnType>],
explicit_variadic: bool,
) -> Result<Option<Arc<SQLUserFunction>>, SQLError> {
self.routine_overload_context().resolve_static_sql_function(
name,
binding,
argument_names,
argument_types,
explicit_variadic,
)
}
pub(crate) fn resolve_static_sql_function_match(
&self,
name: &str,
binding: Option<&FunctionBinding>,
argument_names: &[Option<String>],
argument_types: &[Option<ColumnType>],
explicit_variadic: bool,
) -> Result<Option<StaticFunctionMatch>, SQLError> {
self.routine_overload_context()
.resolve_static_sql_function_match(
name,
binding,
argument_names,
argument_types,
explicit_variadic,
)
}
pub(crate) fn resolve_table_function_overload_with_builtins(
&self,
name: &str,
binding: Option<&FunctionBinding>,
argument_names: &[Option<String>],
argument_types: &[Option<ColumnType>],
explicit_variadic: bool,
builtins: &[BuiltinFunctionOverload],
) -> Result<Option<ResolvedFunctionOverload>, SQLError> {
self.routine_overload_context()
.resolve_table_function_overload_with_builtins(
name,
binding,
argument_names,
argument_types,
explicit_variadic,
builtins,
)
}
}