uqa_sql/binding/view_dependencies/
restoration.rs1use super::{bind_query_plan_relations, canonical_virtual_relation_reference};
9use crate::{ast::FunctionBinding, plan::QueryPlan};
10use uqa_core::RelationIdentity;
11
12pub fn upgrade_legacy_view_expressions(plan: &mut QueryPlan) -> Result<bool, crate::SQLError> {
14 let dispatches = upgrade_legacy_view_dispatches(plan);
15 Ok(crate::type_resolution::between::restore_query(plan)? || dispatches)
16}
17
18pub fn upgrade_legacy_view_dispatches(plan: &mut QueryPlan) -> bool {
19 let mut changed = false;
20 plan.rewrite_scalar_expressions(&mut |expression| {
21 let crate::ScalarExpr::Func {
22 name,
23 binding,
24 args,
25 ..
26 } = expression
27 else {
28 return;
29 };
30 changed |= FunctionBinding::upgrade_legacy_serialized_dispatch(name, binding);
31 changed |= FunctionBinding::upgrade_legacy_array_slices(binding, args.len(), |index| {
32 matches!(
33 args[index],
34 crate::ScalarExpr::Literal(uqa_core::Value::Null)
35 )
36 });
37 });
38 plan.visit_sources_mut(&mut |source| match source {
39 crate::plan::SourcePlan::Function { binding, args, .. } => {
40 changed |= crate::semantics::upgrade_legacy_table_function_binding(binding, args.len());
41 }
42 crate::plan::SourcePlan::FunctionGroup { functions, .. } => {
43 for function in functions {
44 changed |= crate::semantics::upgrade_legacy_table_function_binding(
45 &mut function.binding,
46 function.args.len(),
47 );
48 }
49 }
50 _ => {}
51 });
52 changed
53}
54
55pub fn bind_stored_view_relations(
56 plan: &mut QueryPlan,
57 relations: &std::collections::BTreeSet<RelationIdentity>,
58) -> Result<(), String> {
59 bind_query_plan_relations(plan, &std::collections::BTreeSet::new(), &mut |reference| {
60 if let Some(canonical) = canonical_virtual_relation_reference(reference) {
61 return Ok(canonical);
62 }
63 let (schema, local_name) = RelationIdentity::parse_reference(reference)
64 .map_err(|error| format!("invalid stored view source `{reference}`: {error}"))?;
65 if let Some(schema) = schema {
66 let candidate = RelationIdentity::new(schema, local_name);
67 if relations.contains(&candidate) {
68 return Ok(candidate.qualified_name());
69 }
70 } else {
71 let candidates = relations
72 .iter()
73 .filter(|candidate| candidate.name == local_name)
74 .map(RelationIdentity::qualified_name)
75 .collect::<Vec<_>>();
76 match candidates.as_slice() {
77 [candidate] => return Ok(candidate.clone()),
78 [] => {}
79 _ => {
80 return Err(format!(
81 "ambiguous stored view source `{reference}` matches {}",
82 candidates.join(", ")
83 ));
84 }
85 }
86 }
87 Err(format!(
88 "stored view source relation `{reference}` does not exist"
89 ))
90 })
91}
92
93#[cfg(test)]
94mod tests;