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 { name, binding, .. } = expression else {
22 return;
23 };
24 changed |= FunctionBinding::upgrade_legacy_serialized_dispatch(name, binding);
25 });
26 plan.visit_sources_mut(&mut |source| match source {
27 crate::plan::SourcePlan::Function { binding, args, .. } => {
28 changed |= crate::semantics::upgrade_legacy_table_function_binding(binding, args.len());
29 }
30 crate::plan::SourcePlan::FunctionGroup { functions, .. } => {
31 for function in functions {
32 changed |= crate::semantics::upgrade_legacy_table_function_binding(
33 &mut function.binding,
34 function.args.len(),
35 );
36 }
37 }
38 _ => {}
39 });
40 changed
41}
42
43pub fn bind_stored_view_relations(
44 plan: &mut QueryPlan,
45 relations: &std::collections::BTreeSet<RelationIdentity>,
46) -> Result<(), String> {
47 bind_query_plan_relations(plan, &std::collections::BTreeSet::new(), &mut |reference| {
48 if let Some(canonical) = canonical_virtual_relation_reference(reference) {
49 return Ok(canonical);
50 }
51 let (schema, local_name) = RelationIdentity::parse_reference(reference)
52 .map_err(|error| format!("invalid stored view source `{reference}`: {error}"))?;
53 if let Some(schema) = schema {
54 let candidate = RelationIdentity::new(schema, local_name);
55 if relations.contains(&candidate) {
56 return Ok(candidate.qualified_name());
57 }
58 } else {
59 let candidates = relations
60 .iter()
61 .filter(|candidate| candidate.name == local_name)
62 .map(RelationIdentity::qualified_name)
63 .collect::<Vec<_>>();
64 match candidates.as_slice() {
65 [candidate] => return Ok(candidate.clone()),
66 [] => {}
67 _ => {
68 return Err(format!(
69 "ambiguous stored view source `{reference}` matches {}",
70 candidates.join(", ")
71 ));
72 }
73 }
74 }
75 Err(format!(
76 "stored view source relation `{reference}` does not exist"
77 ))
78 })
79}
80
81#[cfg(test)]
82mod tests;