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