Skip to main content

uqa_sql/semantics/
mutation_inputs.rs

1//
2// Unified Query Algebra
3//
4// Copyright (c) 2023-2026 Cognica, Inc.
5//
6
7//! Row-independent mutation input shapes.
8use crate::ScalarExpr;
9
10pub fn top_level_column(expr: &ScalarExpr) -> Option<&str> {
11    match expr {
12        ScalarExpr::Column(name) => Some(name),
13        ScalarExpr::QualifiedColumn { column, .. } => Some(column),
14        _ => None,
15    }
16}
17
18pub fn expr_is_row_independent(expr: &ScalarExpr) -> bool {
19    match expr {
20        ScalarExpr::Literal(_) | ScalarExpr::TypedLiteral { .. } | ScalarExpr::Param(_) => true,
21        ScalarExpr::Array(items)
22        | ScalarExpr::Row(items)
23        | ScalarExpr::And(items)
24        | ScalarExpr::Or(items) => items.iter().all(expr_is_row_independent),
25        ScalarExpr::Binary { lhs, rhs, .. } => {
26            expr_is_row_independent(lhs) && expr_is_row_independent(rhs)
27        }
28        ScalarExpr::Not(inner) | ScalarExpr::UnaryMinus(inner) => expr_is_row_independent(inner),
29        ScalarExpr::IsNull { expr, .. } => expr_is_row_independent(expr),
30        ScalarExpr::Between { expr, low, high } => {
31            expr_is_row_independent(expr)
32                && expr_is_row_independent(low)
33                && expr_is_row_independent(high)
34        }
35        ScalarExpr::InList { expr, list, .. } => {
36            expr_is_row_independent(expr) && list.iter().all(expr_is_row_independent)
37        }
38        ScalarExpr::Case {
39            base,
40            when,
41            else_branch,
42        } => {
43            base.as_deref().map_or(true, expr_is_row_independent)
44                && when.iter().all(|(condition, result)| {
45                    expr_is_row_independent(condition) && expr_is_row_independent(result)
46                })
47                && else_branch.as_deref().map_or(true, expr_is_row_independent)
48        }
49        ScalarExpr::Cast { expr, .. } => expr_is_row_independent(expr),
50        ScalarExpr::Default
51        | ScalarExpr::Star
52        | ScalarExpr::QualifiedStar(_)
53        | ScalarExpr::Column(_)
54        | ScalarExpr::Position(_)
55        | ScalarExpr::InternalColumn(_)
56        | ScalarExpr::QualifiedColumn { .. }
57        | ScalarExpr::Func { .. }
58        | ScalarExpr::WindowCall { .. }
59        | ScalarExpr::ScalarSubquery(_)
60        | ScalarExpr::Exists { .. }
61        | ScalarExpr::InSubquery { .. } => false,
62    }
63}