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}