uqa-engine 0.4.0

Engine: schema-aware table store, catalog restore, transactions
//
// Unified Query Algebra
//
// Copyright (c) 2023-2026 Cognica, Inc.
//

//! Compose routine invocation with the active interpreter, catalog, and retained session state.
use crate::{Engine, SQLTableFunctionResult};
use uqa_core::Value;
use uqa_execution::routines::{
    invocation::{
        self,
        context::{
            AnonymousBlockContext, RoutineInvocationContext, RoutineInvocationSession,
            RoutineInvocationState,
        },
    },
    TriggerRoutineContext,
};
use uqa_sql::catalog::roles::RoleReference;
use uqa_sql::{
    ast::FunctionBinding,
    routines::{resolution::RoutineOverloadContext, SQLUserFunction},
    SQLError,
};
impl RoutineInvocationState for crate::roles::RoutineSessionStateGuard<'_> {
    fn finish(&mut self) {
        self.finish();
    }
}
impl RoutineInvocationSession for Engine {
    fn depth_limit(&self) -> usize {
        self.sql_function_depth_limit()
    }
    fn state_guard(
        &self,
        configured: bool,
        security_definer: bool,
    ) -> Box<dyn RoutineInvocationState + '_> {
        Box::new(self.routine_invocation_state_guard(configured, security_definer))
    }
    fn set_current_user(&self, user: uqa_core::catalog_role::RoleIdentity) -> Result<(), SQLError> {
        let RoleReference::Bound(role) =
            RoleReference::from_identity(user, &self.durable.roles.read())?
        else {
            unreachable!("identity lookup returns a bound role")
        };
        self.session.state.write().authorization.set_effective(role);
        Ok(())
    }
    fn set_configured_parameter(&self, name: &str, value: &str) -> Result<(), SQLError> {
        Engine::set_configured_parameter(self, name, value)
    }
}
impl Engine {
    pub(crate) fn routine_invocation_context(&self) -> RoutineInvocationContext<'_> {
        RoutineInvocationContext {
            runtime: self.routine_execution_context(),
            session: self,
            lookup: self,
            overloads: RoutineOverloadContext { catalog: self },
            types: self,
            authority: self,
        }
    }
    pub(crate) fn anonymous_block_context(&self) -> AnonymousBlockContext<'_> {
        AnonymousBlockContext {
            runtime: self.routine_execution_context(),
            session: self,
            types: self,
            parsers: self,
        }
    }
}
type AnonymousRecordDefinition<'a> = (&'a [String], &'a [String]);
pub(crate) fn call_user_scalar_function(
    engine: &Engine,
    name: &str,
    args: &[(Option<String>, Value)],
) -> Option<Result<Value, SQLError>> {
    invocation::call_user_scalar_function(&engine.routine_invocation_context(), name, args)
}
pub(crate) fn call_bound_user_scalar_function(
    engine: &Engine,
    binding: &FunctionBinding,
    args: &[(Option<String>, Value)],
) -> Option<Result<Value, SQLError>> {
    invocation::call_bound_user_scalar_function(&engine.routine_invocation_context(), binding, args)
}
pub(crate) fn resolved_user_function_returns_set(
    engine: &Engine,
    name: &str,
    args: &[(Option<String>, Value)],
) -> Option<Result<bool, SQLError>> {
    invocation::resolved_user_function_returns_set(&engine.routine_invocation_context(), name, args)
}
pub(crate) fn resolved_bound_user_function_returns_set(
    engine: &Engine,
    binding: &FunctionBinding,
    args: &[(Option<String>, Value)],
) -> Option<Result<bool, SQLError>> {
    invocation::resolved_bound_user_function_returns_set(
        &engine.routine_invocation_context(),
        binding,
        args,
    )
}
pub(crate) fn call_user_table_function(
    engine: &Engine,
    name: &str,
    args: &[(Option<String>, Value)],
    record_definition: Option<AnonymousRecordDefinition<'_>>,
) -> Option<Result<SQLTableFunctionResult, SQLError>> {
    invocation::call_user_table_function(
        &engine.routine_invocation_context(),
        name,
        args,
        record_definition,
    )
}
pub(crate) fn call_bound_user_table_function(
    engine: &Engine,
    binding: &FunctionBinding,
    args: &[(Option<String>, Value)],
    record_definition: Option<AnonymousRecordDefinition<'_>>,
) -> Option<Result<SQLTableFunctionResult, SQLError>> {
    invocation::call_bound_user_table_function(
        &engine.routine_invocation_context(),
        binding,
        args,
        record_definition,
    )
}
pub(crate) fn execute_trigger_routine(
    engine: &Engine,
    function: &SQLUserFunction,
    context: &TriggerRoutineContext,
) -> Result<Value, SQLError> {
    invocation::execute_trigger_routine(&engine.routine_invocation_context(), function, context)
}