refactor: use walk_expr() in table_mask_from_expr()

This commit is contained in:
Jussi Saurio
2025-05-23 16:03:40 +03:00
parent 3835a29f47
commit 9ec84e3905

View File

@@ -597,133 +597,17 @@ impl TableMask {
/// Returns a [TableMask] representing the tables referenced in the given expression.
/// Used in the optimizer for constraint analysis.
pub fn table_mask_from_expr(expr: &Expr) -> Result<TableMask> {
pub fn table_mask_from_expr(top_level_expr: &Expr) -> Result<TableMask> {
let mut mask = TableMask::new();
match expr {
Expr::Binary(e1, _, e2) => {
mask |= table_mask_from_expr(e1)?;
mask |= table_mask_from_expr(e2)?;
}
Expr::Column { table, .. } | Expr::RowId { table, .. } => {
mask.add_table(*table);
}
Expr::Between {
lhs,
not: _,
start,
end,
} => {
mask |= table_mask_from_expr(lhs)?;
mask |= table_mask_from_expr(start)?;
mask |= table_mask_from_expr(end)?;
}
Expr::Case {
base,
when_then_pairs,
else_expr,
} => {
if let Some(base) = base {
mask |= table_mask_from_expr(base)?;
}
for (when, then) in when_then_pairs {
mask |= table_mask_from_expr(when)?;
mask |= table_mask_from_expr(then)?;
}
if let Some(else_expr) = else_expr {
mask |= table_mask_from_expr(else_expr)?;
walk_expr(top_level_expr, &mut |expr: &Expr| -> Result<()> {
match expr {
Expr::Column { table, .. } | Expr::RowId { table, .. } => {
mask.add_table(*table);
}
_ => {}
}
Expr::Cast { expr, .. } => {
mask |= table_mask_from_expr(expr)?;
}
Expr::Collate(expr, _) => {
mask |= table_mask_from_expr(expr)?;
}
Expr::DoublyQualified(_, _, _) => {
crate::bail_parse_error!(
"DoublyQualified should be resolved to a Column before resolving table mask"
);
}
Expr::Exists(_) => {
todo!();
}
Expr::FunctionCall {
args,
order_by,
filter_over: _,
..
} => {
if let Some(args) = args {
for arg in args.iter() {
mask |= table_mask_from_expr(arg)?;
}
}
if let Some(order_by) = order_by {
for term in order_by.iter() {
mask |= table_mask_from_expr(&term.expr)?;
}
}
}
Expr::FunctionCallStar { .. } => {}
Expr::Id(_) => panic!("Id should be resolved to a Column before resolving table mask"),
Expr::InList { lhs, not: _, rhs } => {
mask |= table_mask_from_expr(lhs)?;
if let Some(rhs) = rhs {
for rhs_expr in rhs.iter() {
mask |= table_mask_from_expr(rhs_expr)?;
}
}
}
Expr::InSelect { .. } => todo!(),
Expr::InTable {
lhs,
not: _,
rhs: _,
args,
} => {
mask |= table_mask_from_expr(lhs)?;
if let Some(args) = args {
for arg in args.iter() {
mask |= table_mask_from_expr(arg)?;
}
}
}
Expr::IsNull(expr) => {
mask |= table_mask_from_expr(expr)?;
}
Expr::Like {
lhs,
not: _,
op: _,
rhs,
escape,
} => {
mask |= table_mask_from_expr(lhs)?;
mask |= table_mask_from_expr(rhs)?;
if let Some(escape) = escape {
mask |= table_mask_from_expr(escape)?;
}
}
Expr::Literal(_) => {}
Expr::Name(_) => {}
Expr::NotNull(expr) => {
mask |= table_mask_from_expr(expr)?;
}
Expr::Parenthesized(exprs) => {
for expr in exprs.iter() {
mask |= table_mask_from_expr(expr)?;
}
}
Expr::Qualified(_, _) => {
panic!("Qualified should be resolved to a Column before resolving table mask");
}
Expr::Raise(_, _) => todo!(),
Expr::Subquery(_) => todo!(),
Expr::Unary(_, expr) => {
mask |= table_mask_from_expr(expr)?;
}
Expr::Variable(_) => {}
}
Ok(())
})?;
Ok(mask)
}