uqa_sql/binding/statements/
procedural.rs1use super::{AnalyzedResult, BindingContext, StatementAnalysisContext};
10use crate::{
11 catalog::resolution::EffectiveSearchPath,
12 plan::{CommandPlan, UnifiedPlan},
13 prepared::dependencies::{PreparedAnalysisDependencies, PreparedDependencySnapshot},
14 routines::{declaration::RoutineTypeCatalog, resolution::RoutineOverloadContext},
15 SQLError, SQLParam,
16};
17
18#[derive(Debug)]
19pub struct ProceduralPlanAnalysis {
20 pub result: AnalyzedResult,
21 pub dependencies: PreparedAnalysisDependencies,
22 pub effective_search_path: Option<EffectiveSearchPath>,
23 pub dependency_snapshot: Option<PreparedDependencySnapshot>,
24}
25
26pub fn analyze_procedural_plan(
29 context: &StatementAnalysisContext<'_>,
30 overloads: &RoutineOverloadContext<'_>,
31 types: &dyn RoutineTypeCatalog,
32 plan: &mut UnifiedPlan,
33 params: &[SQLParam],
34) -> Result<ProceduralPlanAnalysis, SQLError> {
35 let mut analyzed = None;
36 context.scopes.with_scope(&mut |scope| {
37 let binding = scope.binding_context()?;
38 let (result, dependencies) =
39 analyze_inputs(context, overloads, types, plan, params, &binding)?;
40 crate::routines::compilation::bind_analyzed_sql_body_types(types, plan)?;
41 let effective_search_path = binding.catalog.effective_search_path(&binding.resolution)?;
42 let dependency_snapshot = binding
43 .catalog
44 .prepared_dependency_snapshot(&dependencies)?;
45 analyzed = Some(ProceduralPlanAnalysis {
46 result,
47 dependencies,
48 effective_search_path,
49 dependency_snapshot,
50 });
51 Ok(())
52 })?;
53 analyzed.ok_or_else(|| SQLError::Internal("procedural analysis scope did not run".into()))
54}
55
56fn analyze_inputs(
57 context: &StatementAnalysisContext<'_>,
58 overloads: &RoutineOverloadContext<'_>,
59 types: &dyn RoutineTypeCatalog,
60 plan: &mut UnifiedPlan,
61 params: &[SQLParam],
62 binding: &BindingContext<'_>,
63) -> Result<(AnalyzedResult, PreparedAnalysisDependencies), SQLError> {
64 if let UnifiedPlan::Command(command) = plan {
65 match command.as_mut() {
66 CommandPlan::Call { .. } => {
67 return crate::binding::preparation::prepare_procedure_call(
68 context, overloads, types, plan, params, binding,
69 );
70 }
71 CommandPlan::Explain { body, .. } => {
72 let (_, dependencies) =
73 analyze_inputs(context, overloads, types, body, params, binding)?;
74 return Ok((AnalyzedResult::Command, dependencies));
75 }
76 _ => {}
77 }
78 }
79 let dependencies = crate::binding::preparation::read_procedural_inputs(
80 context.routines,
81 plan,
82 params,
83 binding,
84 context.aliases,
85 )?;
86 let result = super::analyze_bound_result(context.routines, plan, params, binding)?;
87 Ok((result, dependencies))
88}