uqa_sql/binding/stored_routines/
analysis.rs1use super::{BoundStatementRoutines, CatalogRoutineContext};
10use crate::{
11 ast::ColumnType,
12 binding::statements::{StatementAnalysisOperation, StatementBindingScope},
13 plan::{ExpressionPlan, UnifiedPlan},
14 routines::RoutineResolution,
15 RowSchema, SQLError, SQLParam,
16};
17
18pub trait CatalogRoutineScopes {
20 fn with_catalog_scope(&self, analyze: StatementAnalysisOperation<'_>) -> Result<(), SQLError>;
21}
22#[derive(Clone, Copy)]
23pub struct CatalogRoutineAnalysisContext<'a> {
24 pub scopes: &'a dyn CatalogRoutineScopes,
25 pub routines: &'a dyn RoutineResolution,
26}
27impl CatalogRoutineAnalysisContext<'_> {
28 fn with_scope_result<T>(
29 &self,
30 mut analyze: impl FnMut(&dyn StatementBindingScope) -> Result<T, SQLError>,
31 ) -> Result<T, SQLError> {
32 let mut result = None;
33 self.scopes.with_catalog_scope(&mut |scope| {
34 result = Some(analyze(scope)?);
35 Ok(())
36 })?;
37 result.ok_or_else(|| {
38 SQLError::Internal("catalog routine scope did not invoke analysis".into())
39 })
40 }
41 pub fn bind_statement(&self, plan: &UnifiedPlan) -> Result<BoundStatementRoutines, SQLError> {
42 self.with_scope_result(|scope| {
43 let binding = scope.binding_context()?;
44 super::bind_catalog_statement_routines(
45 &CatalogRoutineContext {
46 routines: self.routines,
47 binding: &binding,
48 },
49 plan,
50 )
51 })
52 }
53 pub fn bind_expression(
54 &self,
55 expression: &mut ExpressionPlan,
56 params: &[SQLParam],
57 outer: &RowSchema,
58 ) -> Result<Option<ColumnType>, SQLError> {
59 self.with_scope_result(|scope| {
60 crate::binding::bind_expression_plan_routines_for_storage(
61 self.routines,
62 expression,
63 params,
64 &scope.binding_context()?,
65 outer,
66 )
67 })
68 }
69}
70
71#[cfg(test)]
72mod tests;