uqa_sql/schema/
dependencies.rs1pub fn walk_schema_expr_mut(
10 expression: &mut crate::ast::Expr,
11 visit: &mut impl FnMut(&mut crate::ast::Expr) -> Result<(), String>,
12) -> Result<(), String> {
13 use crate::ast::{Expr, FrameBound};
14
15 visit(expression)?;
16 match expression {
17 Expr::Func {
18 args,
19 order_by,
20 filter,
21 ..
22 } => {
23 for argument in args {
24 walk_schema_expr_mut(argument, visit)?;
25 }
26 for order in order_by {
27 walk_schema_expr_mut(&mut order.expr, visit)?;
28 }
29 if let Some(filter) = filter {
30 walk_schema_expr_mut(filter, visit)?;
31 }
32 }
33 Expr::Array(items) | Expr::Row(items) | Expr::And(items) | Expr::Or(items) => {
34 for item in items {
35 walk_schema_expr_mut(item, visit)?;
36 }
37 }
38 Expr::Binary { lhs, rhs, .. } => {
39 walk_schema_expr_mut(lhs, visit)?;
40 walk_schema_expr_mut(rhs, visit)?;
41 }
42 Expr::Not(inner)
43 | Expr::UnaryMinus(inner)
44 | Expr::IsNull { expr: inner, .. }
45 | Expr::Cast { expr: inner, .. } => {
46 walk_schema_expr_mut(inner, visit)?;
47 }
48 Expr::Between { expr, low, high } => {
49 walk_schema_expr_mut(expr, visit)?;
50 walk_schema_expr_mut(low, visit)?;
51 walk_schema_expr_mut(high, visit)?;
52 }
53 Expr::InList { expr, list, .. } => {
54 walk_schema_expr_mut(expr, visit)?;
55 for item in list {
56 walk_schema_expr_mut(item, visit)?;
57 }
58 }
59 Expr::WindowCall { args, spec, .. } => {
60 for argument in args.iter_mut().chain(&mut spec.partition_by) {
61 walk_schema_expr_mut(argument, visit)?;
62 }
63 for order in &mut spec.order_by {
64 walk_schema_expr_mut(&mut order.expr, visit)?;
65 }
66 if let Some(frame) = &mut spec.frame {
67 for bound in [&mut frame.start, &mut frame.end] {
68 match bound {
69 FrameBound::Preceding(expression) | FrameBound::Following(expression) => {
70 walk_schema_expr_mut(expression, visit)?;
71 }
72 FrameBound::UnboundedPreceding
73 | FrameBound::UnboundedFollowing
74 | FrameBound::CurrentRow => {}
75 }
76 }
77 }
78 }
79 Expr::Case {
80 base,
81 when,
82 else_branch,
83 } => {
84 if let Some(base) = base {
85 walk_schema_expr_mut(base, visit)?;
86 }
87 for (condition, result) in when {
88 walk_schema_expr_mut(condition, visit)?;
89 walk_schema_expr_mut(result, visit)?;
90 }
91 if let Some(else_branch) = else_branch {
92 walk_schema_expr_mut(else_branch, visit)?;
93 }
94 }
95 Expr::ScalarSubquery(_) | Expr::Exists { .. } | Expr::InSubquery { .. } => {
96 return Err(
97 "schema expression contains a subquery whose dependencies cannot be rewritten safely"
98 .into(),
99 );
100 }
101 Expr::Default
102 | Expr::Star
103 | Expr::QualifiedStar(_)
104 | Expr::Column(_)
105 | Expr::QualifiedColumn { .. }
106 | Expr::InternalColumn(_)
107 | Expr::Literal(_)
108 | Expr::TypedLiteral { .. }
109 | Expr::Param(_) => {}
110 }
111 Ok(())
112}
113
114pub fn schema_expr_references_column(expression: &crate::ast::Expr, column: &str) -> bool {
115 let mut expression = expression.clone();
116 let mut referenced = false;
117 let result = walk_schema_expr_mut(&mut expression, &mut |node| {
118 referenced |= match node {
119 crate::ast::Expr::Star | crate::ast::Expr::QualifiedStar(_) => true,
120 crate::ast::Expr::Column(name)
121 | crate::ast::Expr::QualifiedColumn { column: name, .. } => name == column,
122 _ => false,
123 };
124 Ok(())
125 });
126 result.is_err() || referenced
127}
128
129pub mod regclass;
130pub mod registration;
131pub mod rewrites;