Skip to main content

toasty_core/stmt/
expr.rs

1use crate::stmt::{ExprExists, Input};
2
3use super::{
4    Entry, EntryMut, EntryPath, ExprAllOp, ExprAnd, ExprAny, ExprAnyOp, ExprArg, ExprBinaryOp,
5    ExprCast, ExprError, ExprFunc, ExprInList, ExprInSubquery, ExprIntersects, ExprIsNull,
6    ExprIsSuperset, ExprIsVariant, ExprLength, ExprLet, ExprLike, ExprList, ExprMap, ExprMatch,
7    ExprNot, ExprOr, ExprProject, ExprRecord, ExprStartsWith, ExprStmt, Node, Projection,
8    Substitute, Value, Visit, VisitMut, expr_reference::ExprReference,
9};
10use std::fmt;
11
12/// An expression node in Toasty's query AST.
13///
14/// `Expr` is the central type in the statement intermediate representation. Every
15/// filter, projection, value, and computed result in a Toasty query is
16/// represented as an `Expr` tree. The query engine compiles these trees through
17/// several phases (simplify, lower, plan, execute) before they reach a database
18/// driver.
19///
20/// # Examples
21///
22/// ```ignore
23/// use toasty_core::stmt::{Expr, Value};
24///
25/// // Constant value expressions
26/// let t = Expr::TRUE;
27/// assert!(t.is_true());
28///
29/// let n = Expr::null();
30/// assert!(n.is_value_null());
31///
32/// // From conversions
33/// let i: Expr = 42i64.into();
34/// assert!(i.is_value());
35/// ```
36#[derive(Clone, PartialEq)]
37pub enum Expr {
38    /// `lhs <op> ALL(rhs)` predicate against an array-valued operand. See [`ExprAllOp`].
39    AllOp(ExprAllOp),
40
41    /// Logical AND of multiple expressions. See [`ExprAnd`].
42    And(ExprAnd),
43
44    /// Returns `true` if any item in a collection is truthy. See [`ExprAny`].
45    Any(ExprAny),
46
47    /// `lhs <op> ANY(rhs)` predicate against an array-valued operand. See [`ExprAnyOp`].
48    AnyOp(ExprAnyOp),
49
50    /// Positional argument placeholder. See [`ExprArg`].
51    Arg(ExprArg),
52
53    /// Binary comparison or arithmetic operation. See [`ExprBinaryOp`].
54    BinaryOp(ExprBinaryOp),
55
56    /// Type cast. See [`ExprCast`].
57    Cast(ExprCast),
58
59    /// Instructs the database to use its default value for a column. Useful for
60    /// auto-increment fields and other columns with server-side defaults.
61    Default,
62
63    /// An error expression that fails evaluation with a message. See [`ExprError`].
64    Error(ExprError),
65
66    /// `[NOT] EXISTS(SELECT ...)` check. See [`ExprExists`].
67    Exists(ExprExists),
68
69    /// Aggregate or scalar function call. See [`ExprFunc`].
70    Func(ExprFunc),
71
72    /// An **unresolved** reference to a name (e.g. a column name in a DDL
73    /// context).
74    ///
75    /// Unlike [`Expr::Reference`] / [`ExprReference`], which hold **resolved**
76    /// index-based references into the schema, `Ident` carries only the raw
77    /// name string. It is used in contexts where schema resolution is not
78    /// applicable, such as CHECK constraints in CREATE TABLE statements.
79    Ident(String),
80
81    /// `expr IN (list)` membership test. See [`ExprInList`].
82    InList(ExprInList),
83
84    /// `expr IN (SELECT ...)` membership test. See [`ExprInSubquery`].
85    InSubquery(ExprInSubquery),
86
87    /// Boolean: two array operands share at least one element
88    /// (PostgreSQL `&&`). See [`ExprIntersects`].
89    Intersects(ExprIntersects),
90
91    /// `IS [NOT] NULL` check. Separate from binary operators because of
92    /// three-valued logic semantics in SQL. See [`ExprIsNull`].
93    IsNull(ExprIsNull),
94
95    /// Boolean: an array operand contains every element of another
96    /// (PostgreSQL `@>`). See [`ExprIsSuperset`].
97    IsSuperset(ExprIsSuperset),
98
99    /// Tests whether a value is a specific enum variant. See [`ExprIsVariant`].
100    IsVariant(ExprIsVariant),
101
102    /// Integer: the cardinality of an array (PostgreSQL `cardinality(expr)`).
103    /// See [`ExprLength`].
104    Length(ExprLength),
105
106    /// Scoped binding expression (transient -- inlined before planning).
107    /// See [`ExprLet`].
108    Let(ExprLet),
109
110    /// SQL `LIKE` pattern match: `expr LIKE pattern`. See [`ExprLike`].
111    Like(ExprLike),
112
113    /// Applies a transformation to each item in a collection. See [`ExprMap`].
114    Map(ExprMap),
115
116    /// Pattern-match dispatching on a subject. See [`ExprMatch`].
117    Match(ExprMatch),
118
119    /// Boolean negation. See [`ExprNot`].
120    Not(ExprNot),
121
122    /// Logical OR of multiple expressions. See [`ExprOr`].
123    Or(ExprOr),
124
125    /// Field projection from a composite value. See [`ExprProject`].
126    Project(ExprProject),
127
128    /// Fixed-size heterogeneous tuple of expressions. See [`ExprRecord`].
129    Record(ExprRecord),
130
131    // TODO: delete this
132    /// Reference to a field, column, or model in the current or an outer query
133    /// scope. See [`ExprReference`].
134    Reference(ExprReference),
135
136    /// Ordered, homogeneous collection of expressions. See [`ExprList`].
137    List(ExprList),
138
139    /// String prefix match: `starts_with(expr, prefix)`. See [`ExprStartsWith`].
140    StartsWith(ExprStartsWith),
141
142    /// Embedded sub-statement (e.g., a subquery). See [`ExprStmt`].
143    Stmt(ExprStmt),
144
145    /// Constant value. See [`Value`].
146    Value(Value),
147}
148
149impl Expr {
150    /// The boolean `true` constant expression.
151    pub const TRUE: Expr = Expr::Value(Value::Bool(true));
152
153    /// The boolean `false` constant expression.
154    pub const FALSE: Expr = Expr::Value(Value::Bool(false));
155
156    /// Alias for [`Expr::Default`] as a constant.
157    pub const DEFAULT: Expr = Expr::Default;
158
159    /// Creates a null value expression.
160    pub fn null() -> Self {
161        Self::Value(Value::Null)
162    }
163
164    /// Is a value that evaluates to null
165    pub fn is_value_null(&self) -> bool {
166        matches!(self, Self::Value(Value::Null))
167    }
168
169    /// Returns true if the expression is the `true` boolean expression
170    pub fn is_true(&self) -> bool {
171        matches!(self, Self::Value(Value::Bool(true)))
172    }
173
174    /// Returns `true` if the expression is the `false` boolean expression
175    pub fn is_false(&self) -> bool {
176        matches!(self, Self::Value(Value::Bool(false)))
177    }
178
179    /// Returns `true` if the expression can never evaluate to `true`.
180    ///
181    /// In SQL's three-valued logic, both `false` and `null` are unsatisfiable:
182    /// a filter producing either value will never match any rows.
183    pub fn is_unsatisfiable(&self) -> bool {
184        self.is_false() || self.is_value_null()
185    }
186
187    /// Returns `true` if the expression is the default expression
188    pub fn is_default(&self) -> bool {
189        matches!(self, Self::Default)
190    }
191
192    /// Returns true if the expression is a constant value.
193    pub fn is_value(&self) -> bool {
194        matches!(self, Self::Value(..))
195    }
196
197    /// Returns `true` if the expression is a sub-statement.
198    pub fn is_stmt(&self) -> bool {
199        matches!(self, Self::Stmt(..))
200    }
201
202    /// Returns true if the expression is a binary operation
203    pub fn is_binary_op(&self) -> bool {
204        matches!(self, Self::BinaryOp(..))
205    }
206
207    /// Returns `true` if the expression is an argument placeholder.
208    pub fn is_arg(&self) -> bool {
209        matches!(self, Self::Arg(_))
210    }
211
212    /// Returns true if the expression is always non-nullable.
213    ///
214    /// This method is conservative and only returns true for expressions we can
215    /// prove are non-nullable.
216    pub fn is_always_non_nullable(&self) -> bool {
217        match self {
218            // A constant value is non-nullable if it's not null.
219            Self::Value(value) => !value.is_null(),
220            // Boolean logic expressions always evaluate to true or false.
221            Self::And(_) | Self::Or(_) | Self::Not(_) => true,
222            // ANY returns true if any item matches, always boolean.
223            Self::Any(_) => true,
224            // ANY/ALL array predicates always evaluate to true or false.
225            Self::AnyOp(_) | Self::AllOp(_) => true,
226            // Comparisons always evaluate to true or false.
227            Self::BinaryOp(_) => true,
228            // IS NULL checks always evaluate to true or false.
229            Self::IsNull(_) => true,
230            // Variant checks always evaluate to true or false.
231            Self::IsVariant(_) => true,
232            // EXISTS checks always evaluate to true or false.
233            Self::Exists(_) => true,
234            // IN expressions always evaluate to true or false.
235            Self::InList(_) | Self::InSubquery(_) => true,
236            // Array predicates always evaluate to true or false.
237            Self::IsSuperset(_) | Self::Intersects(_) => true,
238            // Array length is an integer — non-null when the array is non-null.
239            Self::Length(_) => true,
240            // For other expressions, we cannot prove non-nullability.
241            _ => false,
242        }
243    }
244
245    /// Consumes the expression and returns the inner [`Value`].
246    ///
247    /// # Panics
248    ///
249    /// Panics (via `todo!()`) if `self` is not an `Expr::Value`.
250    pub fn into_value(self) -> Value {
251        match self {
252            Self::Value(value) => value,
253            _ => todo!(),
254        }
255    }
256
257    /// Consumes the expression and returns the inner [`ExprStmt`].
258    ///
259    /// # Panics
260    ///
261    /// Panics (via `todo!()`) if `self` is not an `Expr::Stmt`.
262    pub fn into_stmt(self) -> ExprStmt {
263        match self {
264            Self::Stmt(stmt) => stmt,
265            _ => todo!(),
266        }
267    }
268
269    /// Returns `true` if the expression is stable
270    ///
271    /// An expression is stable if it yields the same value each time it is evaluated
272    pub fn is_stable(&self) -> bool {
273        match self {
274            // Always stable - constant values
275            Self::Value(_) => true,
276
277            // Unresolved identifiers refer to external state (e.g. a column)
278            Self::Ident(_) => false,
279
280            // Never stable - generates new values each evaluation
281            Self::Default => false,
282
283            // Error expressions are stable (they always produce the same error)
284            Self::Error(_) => true,
285
286            // Stable if all children are stable
287            Self::Record(expr_record) => expr_record.iter().all(|expr| expr.is_stable()),
288            Self::List(expr_list) => expr_list.items.iter().all(|expr| expr.is_stable()),
289            Self::Cast(expr_cast) => expr_cast.expr.is_stable(),
290            Self::StartsWith(e) => e.expr.is_stable() && e.prefix.is_stable(),
291            Self::Like(e) => e.expr.is_stable() && e.pattern.is_stable(),
292            Self::BinaryOp(expr_binary) => {
293                expr_binary.lhs.is_stable() && expr_binary.rhs.is_stable()
294            }
295            Self::And(expr_and) => expr_and.iter().all(|expr| expr.is_stable()),
296            Self::Any(expr_any) => expr_any.expr.is_stable(),
297            Self::AnyOp(e) => e.lhs.is_stable() && e.rhs.is_stable(),
298            Self::AllOp(e) => e.lhs.is_stable() && e.rhs.is_stable(),
299            Self::Or(expr_or) => expr_or.iter().all(|expr| expr.is_stable()),
300            Self::IsNull(expr_is_null) => expr_is_null.expr.is_stable(),
301            Self::IsVariant(expr_is_variant) => expr_is_variant.expr.is_stable(),
302            Self::Not(expr_not) => expr_not.expr.is_stable(),
303            Self::InList(expr_in_list) => {
304                expr_in_list.expr.is_stable() && expr_in_list.list.is_stable()
305            }
306            Self::Project(expr_project) => expr_project.base.is_stable(),
307            Self::Let(expr_let) => {
308                expr_let.bindings.iter().all(|b| b.is_stable()) && expr_let.body.is_stable()
309            }
310            Self::Map(expr_map) => expr_map.base.is_stable() && expr_map.map.is_stable(),
311            Self::Match(expr_match) => {
312                expr_match.subject.is_stable()
313                    && expr_match.arms.iter().all(|arm| arm.expr.is_stable())
314            }
315
316            // References and statements - stable (they reference existing data)
317            Self::Reference(_) | Self::Arg(_) => true,
318
319            // Array predicates and length — stable if all operands are stable.
320            Self::IsSuperset(e) => e.lhs.is_stable() && e.rhs.is_stable(),
321            Self::Intersects(e) => e.lhs.is_stable() && e.rhs.is_stable(),
322            Self::Length(e) => e.expr.is_stable(),
323
324            // Subqueries and functions - could be unstable
325            // For now, conservatively mark as unstable
326            Self::Stmt(_) | Self::Func(_) | Self::InSubquery(_) | Self::Exists(_) => false,
327        }
328    }
329
330    /// Returns `true` if `self` and `other` are syntactically identical **and**
331    /// both sides are stable.
332    ///
333    /// This is the soundness-preserving comparison used by simplification
334    /// rules that rewrite on the assumption that two equal sub-expressions
335    /// produce the same value (idempotent, absorption, complement,
336    /// range-to-equality, OR-to-IN, factoring, variant tautology).
337    ///
338    /// Syntactic identity alone is not enough: `LAST_INSERT_ID() =
339    /// LAST_INSERT_ID()` is two independent evaluations and may yield
340    /// different values, so rewriting `a AND a` to `a` would be unsound when
341    /// `a` is non-deterministic. Gating on [`Self::is_stable`] excludes any
342    /// sub-expression whose value may change across evaluations.
343    pub fn is_equivalent_to(&self, other: &Self) -> bool {
344        self == other && self.is_stable()
345    }
346
347    /// Returns `true` if the expression is a constant expression.
348    ///
349    /// A constant expression is one that does not reference any external data.
350    /// This means it contains no `Reference`, `Stmt`, or `Arg` expressions that
351    /// reference external inputs.
352    ///
353    /// `Arg` expressions inside `Map` bodies *with `nesting` less than the current
354    /// map depth* are local bindings (bound to the mapped element), not external
355    /// inputs, and are therefore considered const in that context.
356    pub fn is_const(&self) -> bool {
357        self.is_const_at_depth(0)
358    }
359
360    /// Inner implementation of [`is_const`] that tracks the number of enclosing
361    /// `Map` scopes. An `Arg` with `nesting < map_depth` is a local binding
362    /// introduced by one of those `Map`s and does not count as external input.
363    fn is_const_at_depth(&self, map_depth: usize) -> bool {
364        match self {
365            // Always constant
366            Self::Value(_) => true,
367
368            // Unresolved identifiers reference external data
369            Self::Ident(_) => false,
370
371            // Arg: local if nesting is within map_depth, otherwise external
372            Self::Arg(arg) => arg.nesting < map_depth,
373
374            // Error expressions are constant (no external data)
375            Self::Error(_) => true,
376
377            // Never constant - references external data
378            Self::Reference(_)
379            | Self::Stmt(_)
380            | Self::InSubquery(_)
381            | Self::Exists(_)
382            | Self::Default
383            | Self::Func(_) => false,
384
385            // Const if all children are const at the same depth
386            Self::Record(expr_record) => expr_record
387                .iter()
388                .all(|expr| expr.is_const_at_depth(map_depth)),
389            Self::List(expr_list) => expr_list
390                .items
391                .iter()
392                .all(|expr| expr.is_const_at_depth(map_depth)),
393            Self::Cast(expr_cast) => expr_cast.expr.is_const_at_depth(map_depth),
394            Self::StartsWith(e) => {
395                e.expr.is_const_at_depth(map_depth) && e.prefix.is_const_at_depth(map_depth)
396            }
397            Self::Like(e) => {
398                e.expr.is_const_at_depth(map_depth) && e.pattern.is_const_at_depth(map_depth)
399            }
400            Self::BinaryOp(expr_binary) => {
401                expr_binary.lhs.is_const_at_depth(map_depth)
402                    && expr_binary.rhs.is_const_at_depth(map_depth)
403            }
404            Self::And(expr_and) => expr_and
405                .iter()
406                .all(|expr| expr.is_const_at_depth(map_depth)),
407            Self::Any(expr_any) => expr_any.expr.is_const_at_depth(map_depth),
408            Self::AnyOp(e) => {
409                e.lhs.is_const_at_depth(map_depth) && e.rhs.is_const_at_depth(map_depth)
410            }
411            Self::AllOp(e) => {
412                e.lhs.is_const_at_depth(map_depth) && e.rhs.is_const_at_depth(map_depth)
413            }
414            Self::Not(expr_not) => expr_not.expr.is_const_at_depth(map_depth),
415            Self::Or(expr_or) => expr_or.iter().all(|expr| expr.is_const_at_depth(map_depth)),
416            Self::IsNull(expr_is_null) => expr_is_null.expr.is_const_at_depth(map_depth),
417            Self::IsVariant(expr_is_variant) => expr_is_variant.expr.is_const_at_depth(map_depth),
418            Self::InList(expr_in_list) => {
419                expr_in_list.expr.is_const_at_depth(map_depth)
420                    && expr_in_list.list.is_const_at_depth(map_depth)
421            }
422            Self::Project(expr_project) => expr_project.base.is_const_at_depth(map_depth),
423
424            // Let: binding is checked at the current depth; the body is checked
425            // at depth+1 so that arg(nesting=0) in the body is treated as local.
426            Self::Let(expr_let) => {
427                expr_let
428                    .bindings
429                    .iter()
430                    .all(|b| b.is_const_at_depth(map_depth))
431                    && expr_let.body.is_const_at_depth(map_depth + 1)
432            }
433            // Map: base is checked at the current depth; the map body is checked
434            // at depth+1 so that arg(nesting=0) in the body is treated as local.
435            Self::Map(expr_map) => {
436                expr_map.base.is_const_at_depth(map_depth)
437                    && expr_map.map.is_const_at_depth(map_depth + 1)
438            }
439            Self::Match(expr_match) => {
440                expr_match.subject.is_const_at_depth(map_depth)
441                    && expr_match
442                        .arms
443                        .iter()
444                        .all(|arm| arm.expr.is_const_at_depth(map_depth))
445            }
446
447            // Array predicates and length: const iff all operands are const.
448            Self::IsSuperset(e) => {
449                e.lhs.is_const_at_depth(map_depth) && e.rhs.is_const_at_depth(map_depth)
450            }
451            Self::Intersects(e) => {
452                e.lhs.is_const_at_depth(map_depth) && e.rhs.is_const_at_depth(map_depth)
453            }
454            Self::Length(e) => e.expr.is_const_at_depth(map_depth),
455        }
456    }
457
458    /// Returns `true` if the expression can be evaluated.
459    ///
460    /// An expression can be evaluated if it doesn't contain references to external
461    /// data sources like subqueries or references. Args are allowed since they
462    /// represent function parameters that can be bound at evaluation time.
463    pub fn is_eval(&self) -> bool {
464        match self {
465            // Always evaluable
466            Self::Value(_) => true,
467
468            // Unresolved identifiers cannot be evaluated
469            Self::Ident(_) => false,
470
471            // Args are OK for evaluation
472            Self::Arg(_) => true,
473
474            // Error expressions are evaluable (they produce an error)
475            Self::Error(_) => true,
476
477            // Never evaluable - references external data or requires a database driver
478            Self::Default
479            | Self::Reference(_)
480            | Self::Stmt(_)
481            | Self::InSubquery(_)
482            | Self::Exists(_)
483            | Self::StartsWith(_)
484            | Self::Like(_) => false,
485
486            // Evaluable if all children are evaluable
487            Self::Record(expr_record) => expr_record.iter().all(|expr| expr.is_eval()),
488            Self::List(expr_list) => expr_list.items.iter().all(|expr| expr.is_eval()),
489            Self::Cast(expr_cast) => expr_cast.expr.is_eval(),
490            Self::BinaryOp(expr_binary) => expr_binary.lhs.is_eval() && expr_binary.rhs.is_eval(),
491            Self::And(expr_and) => expr_and.iter().all(|expr| expr.is_eval()),
492            Self::Any(expr_any) => expr_any.expr.is_eval(),
493            Self::AnyOp(e) => e.lhs.is_eval() && e.rhs.is_eval(),
494            Self::AllOp(e) => e.lhs.is_eval() && e.rhs.is_eval(),
495            Self::Or(expr_or) => expr_or.iter().all(|expr| expr.is_eval()),
496            Self::Not(expr_not) => expr_not.expr.is_eval(),
497            Self::IsNull(expr_is_null) => expr_is_null.expr.is_eval(),
498            Self::IsVariant(expr_is_variant) => expr_is_variant.expr.is_eval(),
499            Self::InList(expr_in_list) => {
500                expr_in_list.expr.is_eval() && expr_in_list.list.is_eval()
501            }
502            Self::Project(expr_project) => expr_project.base.is_eval(),
503            Self::Let(expr_let) => {
504                expr_let.bindings.iter().all(|b| b.is_eval()) && expr_let.body.is_eval()
505            }
506            Self::Map(expr_map) => expr_map.base.is_eval() && expr_map.map.is_eval(),
507            Self::Match(expr_match) => {
508                expr_match.subject.is_eval() && expr_match.arms.iter().all(|arm| arm.expr.is_eval())
509            }
510            Self::Func(_) => false,
511            // Array predicates and length: evaluable iff all operands are.
512            Self::IsSuperset(e) => e.lhs.is_eval() && e.rhs.is_eval(),
513            Self::Intersects(e) => e.lhs.is_eval() && e.rhs.is_eval(),
514            Self::Length(e) => e.expr.is_eval(),
515        }
516    }
517
518    /// Returns a clone of this expression with all [`Projection`] nodes
519    /// transformed by `f`.
520    pub fn map_projections(&self, f: impl FnMut(&Projection) -> Projection) -> Self {
521        struct MapProjections<T>(T);
522
523        impl<T: FnMut(&Projection) -> Projection> VisitMut for MapProjections<T> {
524            fn visit_projection_mut(&mut self, i: &mut Projection) {
525                *i = self.0(i);
526            }
527        }
528
529        let mut mapped = self.clone();
530        MapProjections(f).visit_expr_mut(&mut mapped);
531        mapped
532    }
533
534    /// Navigates into a nested record or list expression by `path` and returns
535    /// a read-only [`Entry`] reference.
536    ///
537    /// Returns `None` if the path cannot be followed (e.g., the expression is
538    /// not a record or list at the expected depth).
539    #[track_caller]
540    pub fn entry(&self, path: impl EntryPath) -> Option<Entry<'_>> {
541        let mut ret = Entry::Expr(self);
542
543        for step in path.step_iter() {
544            ret = match ret {
545                Entry::Expr(Self::Record(expr)) => Entry::Expr(&expr[step]),
546                Entry::Expr(Self::List(expr)) => Entry::Expr(&expr.items[step]),
547                Entry::Value(Value::Record(record))
548                | Entry::Expr(Self::Value(Value::Record(record))) => Entry::Value(&record[step]),
549                Entry::Value(Value::List(items)) | Entry::Expr(Self::Value(Value::List(items))) => {
550                    Entry::Value(&items[step])
551                }
552                _ => return None,
553            }
554        }
555
556        Some(ret)
557    }
558
559    /// Navigates into a nested record or list expression by `path` and returns
560    /// a mutable [`EntryMut`] reference.
561    ///
562    /// # Panics
563    ///
564    /// Panics if the path cannot be followed on the current expression shape.
565    #[track_caller]
566    pub fn entry_mut(&mut self, path: impl EntryPath) -> EntryMut<'_> {
567        let mut ret = EntryMut::Expr(self);
568
569        for step in path.step_iter() {
570            ret = match ret {
571                EntryMut::Expr(Self::Record(expr)) => EntryMut::Expr(&mut expr[step]),
572                EntryMut::Value(Value::Record(record))
573                | EntryMut::Expr(Self::Value(Value::Record(record))) => {
574                    EntryMut::Value(&mut record[step])
575                }
576                _ => todo!("ret={ret:#?}; step={step:#?}"),
577            }
578        }
579
580        ret
581    }
582
583    /// Takes the expression out, leaving `Expr::Value(Value::Null)` in its
584    /// place. Equivalent to `std::mem::replace(self, Expr::null())`.
585    pub fn take(&mut self) -> Self {
586        std::mem::replace(self, Self::Value(Value::Null))
587    }
588
589    /// Replaces every [`ExprArg`] in this expression tree with the
590    /// corresponding value from `input`.
591    pub fn substitute(&mut self, input: impl Input) {
592        Substitute::new(input).visit_expr_mut(self);
593    }
594}
595
596impl Node for Expr {
597    fn visit<V: Visit>(&self, mut visit: V) {
598        visit.visit_expr(self);
599    }
600
601    fn visit_mut<V: VisitMut>(&mut self, mut visit: V) {
602        visit.visit_expr_mut(self);
603    }
604}
605
606// === Conversions ===
607
608impl From<bool> for Expr {
609    fn from(value: bool) -> Self {
610        Self::Value(Value::from(value))
611    }
612}
613
614impl From<i64> for Expr {
615    fn from(value: i64) -> Self {
616        Self::Value(value.into())
617    }
618}
619
620impl From<&i64> for Expr {
621    fn from(value: &i64) -> Self {
622        Self::Value(value.into())
623    }
624}
625
626impl From<String> for Expr {
627    fn from(value: String) -> Self {
628        Self::Value(value.into())
629    }
630}
631
632impl From<&String> for Expr {
633    fn from(value: &String) -> Self {
634        Self::Value(value.into())
635    }
636}
637
638impl From<&str> for Expr {
639    fn from(value: &str) -> Self {
640        Self::Value(value.into())
641    }
642}
643
644impl From<Value> for Expr {
645    fn from(value: Value) -> Self {
646        Self::Value(value)
647    }
648}
649
650impl<E1, E2> From<(E1, E2)> for Expr
651where
652    E1: Into<Self>,
653    E2: Into<Self>,
654{
655    fn from(value: (E1, E2)) -> Self {
656        Self::Record(value.into())
657    }
658}
659
660impl fmt::Debug for Expr {
661    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
662        match self {
663            Self::AllOp(e) => e.fmt(f),
664            Self::And(e) => e.fmt(f),
665            Self::Any(e) => e.fmt(f),
666            Self::AnyOp(e) => e.fmt(f),
667            Self::Arg(e) => e.fmt(f),
668            Self::BinaryOp(e) => e.fmt(f),
669            Self::Cast(e) => e.fmt(f),
670            Self::Default => write!(f, "Default"),
671            Self::Error(e) => e.fmt(f),
672            Self::Exists(e) => e.fmt(f),
673            Self::Func(e) => e.fmt(f),
674            Self::Ident(e) => write!(f, "Ident({e:?})"),
675            Self::InList(e) => e.fmt(f),
676            Self::InSubquery(e) => e.fmt(f),
677            Self::Intersects(e) => e.fmt(f),
678            Self::IsNull(e) => e.fmt(f),
679            Self::IsSuperset(e) => e.fmt(f),
680            Self::IsVariant(e) => e.fmt(f),
681            Self::Length(e) => e.fmt(f),
682            Self::Let(e) => e.fmt(f),
683            Self::Like(e) => e.fmt(f),
684            Self::Map(e) => e.fmt(f),
685            Self::Match(e) => e.fmt(f),
686            Self::Not(e) => e.fmt(f),
687            Self::Or(e) => e.fmt(f),
688            Self::Project(e) => e.fmt(f),
689            Self::Record(e) => e.fmt(f),
690            Self::Reference(e) => e.fmt(f),
691            Self::List(e) => e.fmt(f),
692            Self::StartsWith(e) => e.fmt(f),
693            Self::Stmt(e) => e.fmt(f),
694            Self::Value(e) => e.fmt(f),
695        }
696    }
697}