Skip to main content

mz_sql_parser/ast/defs/
expr.rs

1// Copyright 2018 sqlparser-rs contributors. All rights reserved.
2// Copyright Materialize, Inc. and contributors. All rights reserved.
3//
4// This file is derived from the sqlparser-rs project, available at
5// https://github.com/andygrove/sqlparser-rs. It was incorporated
6// directly into Materialize on December 21, 2019.
7//
8// Licensed under the Apache License, Version 2.0 (the "License");
9// you may not use this file except in compliance with the License.
10// You may obtain a copy of the License in the LICENSE file at the
11// root of this repository, or online at
12//
13//     http://www.apache.org/licenses/LICENSE-2.0
14//
15// Unless required by applicable law or agreed to in writing, software
16// distributed under the License is distributed on an "AS IS" BASIS,
17// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18// See the License for the specific language governing permissions and
19// limitations under the License.
20
21use std::{fmt, mem};
22
23use itertools::Itertools;
24use mz_ore::soft_assert_eq_or_log;
25use mz_sql_lexer::keywords::*;
26
27use crate::ast::display::{self, AstDisplay, AstFormatter};
28use crate::ast::{AstInfo, Ident, OrderByExpr, Query, UnresolvedItemName, Value};
29
30/// An SQL expression of any type.
31///
32/// The parser does not distinguish between expressions of different types
33/// (e.g. boolean vs string), so the caller must handle expressions of
34/// inappropriate type, like `WHERE 1` or `SELECT 1=1`, as necessary.
35#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
36pub enum Expr<T: AstInfo> {
37    /// Identifier e.g. table name or column name. The parser always
38    /// constructs this with a non-empty `Vec`.
39    Identifier(Vec<Ident>),
40    /// Qualified wildcard, e.g. `alias.*` or `schema.table.*`.
41    QualifiedWildcard(Vec<Ident>),
42    /// A field access, like `(expr).foo`.
43    FieldAccess {
44        expr: Box<Expr<T>>,
45        field: Ident,
46    },
47    /// A wildcard field access, like `(expr).*`.
48    ///
49    /// Note that this is different from `QualifiedWildcard` in that the
50    /// wildcard access occurs on an arbitrary expression, rather than a
51    /// qualified name. The distinction is important for PostgreSQL
52    /// compatibility.
53    WildcardAccess(Box<Expr<T>>),
54    /// A positional parameter, e.g., `$1` or `$42`
55    Parameter(usize),
56    /// Boolean negation
57    Not {
58        expr: Box<Expr<T>>,
59    },
60    /// Boolean and
61    And {
62        left: Box<Expr<T>>,
63        right: Box<Expr<T>>,
64    },
65    /// Boolean or
66    Or {
67        left: Box<Expr<T>>,
68        right: Box<Expr<T>>,
69    },
70    /// `IS {NULL, TRUE, FALSE, UNKNOWN}` expression
71    IsExpr {
72        expr: Box<Expr<T>>,
73        construct: IsExprConstruct<T>,
74        negated: bool,
75    },
76    /// `[ NOT ] IN (val1, val2, ...)`
77    InList {
78        expr: Box<Expr<T>>,
79        list: Vec<Expr<T>>,
80        negated: bool,
81    },
82    /// `[ NOT ] IN (SELECT ...)`
83    InSubquery {
84        expr: Box<Expr<T>>,
85        subquery: Box<Query<T>>,
86        negated: bool,
87    },
88    /// `<expr> [ NOT ] {LIKE, ILIKE} <pattern> [ ESCAPE <escape> ]`
89    Like {
90        expr: Box<Expr<T>>,
91        pattern: Box<Expr<T>>,
92        escape: Option<Box<Expr<T>>>,
93        case_insensitive: bool,
94        negated: bool,
95    },
96    /// `<expr> [ NOT ] BETWEEN <low> AND <high>`
97    Between {
98        expr: Box<Expr<T>>,
99        negated: bool,
100        low: Box<Expr<T>>,
101        high: Box<Expr<T>>,
102    },
103    /// Unary or binary operator
104    Op {
105        op: Op,
106        expr1: Box<Expr<T>>,
107        expr2: Option<Box<Expr<T>>>,
108    },
109    /// CAST an expression to a different data type, e.g. `CAST(foo AS VARCHAR(123))`
110    /// or `TRY_CAST(foo AS int4)`.
111    Cast {
112        expr: Box<Expr<T>>,
113        data_type: T::DataType,
114        failure_mode: CastFailureMode,
115    },
116    /// `expr COLLATE collation`
117    Collate {
118        expr: Box<Expr<T>>,
119        collation: UnresolvedItemName,
120    },
121    /// `COALESCE(<expr>, ...)` or `GREATEST(<expr>, ...)` or `LEAST(<expr>`, ...)
122    ///
123    /// While COALESCE/GREATEST/LEAST have the same syntax as a function call,
124    /// their semantics are extremely unusual, and are better captured with a
125    /// dedicated AST node.
126    HomogenizingFunction {
127        function: HomogenizingFunction,
128        exprs: Vec<Expr<T>>,
129    },
130    /// NULLIF(expr, expr)
131    ///
132    /// While NULLIF has the same syntax as a function call, it is not evaluated
133    /// as a function within Postgres.
134    NullIf {
135        l_expr: Box<Expr<T>>,
136        r_expr: Box<Expr<T>>,
137    },
138    /// Nested expression e.g. `(foo > bar)` or `(1)`
139    Nested(Box<Expr<T>>),
140    /// A row constructor like `ROW(<expr>...)` or `(<expr>, <expr>...)`.
141    Row {
142        exprs: Vec<Expr<T>>,
143    },
144    /// A literal value, such as string, number, date or NULL
145    Value(Value),
146    /// Scalar function call e.g. `LEFT(foo, 5)`
147    Function(Function<T>),
148    /// `CASE [<operand>] WHEN <condition> THEN <result> ... [ELSE <result>] END`
149    ///
150    /// Note we only recognize a complete single expression as `<condition>`,
151    /// not `< 0` nor `1, 2, 3` as allowed in a `<simple when clause>` per
152    /// <https://jakewheat.github.io/sql-overview/sql-2011-foundation-grammar.html#simple-when-clause>
153    Case {
154        operand: Option<Box<Expr<T>>>,
155        conditions: Vec<Expr<T>>,
156        results: Vec<Expr<T>>,
157        else_result: Option<Box<Expr<T>>>,
158    },
159    /// An exists expression `EXISTS(SELECT ...)`, used in expressions like
160    /// `WHERE EXISTS (SELECT ...)`.
161    Exists(Box<Query<T>>),
162    /// A parenthesized subquery `(SELECT ...)`, used in expression like
163    /// `SELECT (subquery) AS x` or `WHERE (subquery) = x`
164    Subquery(Box<Query<T>>),
165    /// `<expr> <op> ANY/SOME (<query>)`
166    AnySubquery {
167        left: Box<Expr<T>>,
168        op: Op,
169        right: Box<Query<T>>,
170    },
171    /// `<expr> <op> ANY (<array_expr>)`
172    AnyExpr {
173        left: Box<Expr<T>>,
174        op: Op,
175        right: Box<Expr<T>>,
176    },
177    /// `<expr> <op> ALL (<query>)`
178    AllSubquery {
179        left: Box<Expr<T>>,
180        op: Op,
181        right: Box<Query<T>>,
182    },
183    /// `<expr> <op> ALL (<array_expr>)`
184    AllExpr {
185        left: Box<Expr<T>>,
186        op: Op,
187        right: Box<Expr<T>>,
188    },
189    /// `ARRAY[<expr>*]`
190    Array(Vec<Expr<T>>),
191    ArraySubquery(Box<Query<T>>),
192    /// `LIST[<expr>*]`
193    List(Vec<Expr<T>>),
194    ListSubquery(Box<Query<T>>),
195    /// `MAP[<expr>*]`
196    Map(Vec<MapEntry<T>>),
197    MapSubquery(Box<Query<T>>),
198    /// `<expr>([<expr>(:<expr>)?])+`
199    Subscript {
200        expr: Box<Expr<T>>,
201        positions: Vec<SubscriptPosition<T>>,
202    },
203}
204
205impl<T: AstInfo> AstDisplay for Expr<T> {
206    fn fmt<W: fmt::Write>(&self, f: &mut AstFormatter<W>) {
207        match self {
208            Expr::Identifier(s) => f.write_node(&display::separated(s, ".")),
209            Expr::QualifiedWildcard(q) => {
210                f.write_node(&display::separated(q, "."));
211                f.write_str(".*");
212            }
213            Expr::FieldAccess { expr, field } => {
214                write_dot_receiver(f, expr);
215                f.write_str(".");
216                f.write_node(field);
217            }
218            Expr::WildcardAccess(expr) => {
219                write_dot_receiver(f, expr);
220                f.write_str(".*");
221            }
222            Expr::Parameter(n) => f.write_str(&format!("${}", n)),
223            Expr::Not { expr } => {
224                f.write_str("NOT ");
225                // `NOT` binds tighter than `AND`/`OR`, so an operand exposing a
226                // looser operator on its left spine (`NOT (a OR b)`) must keep its
227                // parens once `Nested` is stripped. We use `left_edge`, since the
228                // `NOT` sits to the operand's left.
229                write_binary_operand(f, expr, left_edge(expr) < prec::NOT);
230            }
231            Expr::And { left, right } => {
232                write_binary_operand(f, left, right_edge(left) < prec::AND);
233                f.write_str(" AND ");
234                write_binary_operand(f, right, left_edge(right) <= prec::AND);
235            }
236            Expr::Or { left, right } => {
237                write_binary_operand(f, left, right_edge(left) < prec::OR);
238                f.write_str(" OR ");
239                write_binary_operand(f, right, left_edge(right) <= prec::OR);
240            }
241            Expr::IsExpr {
242                expr,
243                negated,
244                construct,
245            } => {
246                write_binary_operand(f, expr, right_edge(expr) < prec::IS);
247                f.write_str(" IS ");
248                if *negated {
249                    f.write_str("NOT ");
250                }
251                // `IS DISTINCT FROM <rhs>` parses the RHS at the `IS` precedence
252                // (see `Parser::parse_is`), so a RHS whose left spine binds at or
253                // below `IS` re-associates out of the `IS` unless parenthesized
254                // (`a IS DISTINCT FROM b OR c` is `(a IS DISTINCT FROM b) OR c`).
255                // The other constructs (`NULL`/`TRUE`/…) are bare keywords.
256                if let IsExprConstruct::DistinctFrom(rhs) = construct {
257                    f.write_str("DISTINCT FROM ");
258                    write_binary_operand(f, rhs, left_edge(rhs) <= prec::IS);
259                } else {
260                    f.write_node(construct);
261                }
262            }
263            Expr::InList {
264                expr,
265                list,
266                negated,
267            } => {
268                write_binary_operand(f, expr, right_edge(expr) < prec::LIKE);
269                f.write_str(" ");
270                if *negated {
271                    f.write_str("NOT ");
272                }
273                f.write_str("IN (");
274                f.write_node(&display::comma_separated(list));
275                f.write_str(")");
276            }
277            Expr::InSubquery {
278                expr,
279                subquery,
280                negated,
281            } => {
282                write_binary_operand(f, expr, right_edge(expr) < prec::LIKE);
283                f.write_str(" ");
284                if *negated {
285                    f.write_str("NOT ");
286                }
287                f.write_str("IN (");
288                f.write_node(&subquery);
289                f.write_str(")");
290            }
291            Expr::Like {
292                expr,
293                pattern,
294                escape,
295                case_insensitive,
296                negated,
297            } => {
298                write_binary_operand(f, expr, right_edge(expr) < prec::LIKE);
299                f.write_str(" ");
300                if *negated {
301                    f.write_str("NOT ");
302                }
303                if *case_insensitive {
304                    f.write_str("I");
305                }
306                f.write_str("LIKE ");
307                // The pattern and escape parse at `Like` precedence and sit to the
308                // right of the keyword, so an operand exposing a precedence at or
309                // below `Like` on its left spine (e.g. an `IN`/`LIKE`/`BETWEEN` at
310                // equal precedence) re-associates unless parenthesized.
311                // `a LIKE b IN (q)` parses as `(a LIKE b) IN (q)`. When an `ESCAPE`
312                // follows, the pattern is *also* immediately left of `ESCAPE`: a
313                // `[I]LIKE` exposed on the pattern's right spine would steal the
314                // `ESCAPE` as its own (`a LIKE NOT b LIKE c ESCAPE d` parses the
315                // escape onto the inner `b LIKE c`), so guard the right edge too.
316                let pattern_parens = left_edge(pattern) <= prec::LIKE
317                    || (escape.is_some() && right_edge(pattern) <= prec::LIKE);
318                write_binary_operand(f, pattern, pattern_parens);
319                if let Some(escape) = escape {
320                    f.write_str(" ESCAPE ");
321                    write_binary_operand(f, escape, left_edge(escape) <= prec::LIKE);
322                }
323            }
324            Expr::Between {
325                expr,
326                negated,
327                low,
328                high,
329            } => {
330                // The subject is the LHS of the `BETWEEN` infix (parsed at
331                // `Like`). A spine exposed at or below `Like` on its right would
332                // pull `BETWEEN` inside it (`a OR b BETWEEN …` is `a OR (b BETWEEN
333                // …)`), so parenthesize via `right_edge`. Parser ASTs wrap such a
334                // subject in `Nested` (`ATOM`), so they're unaffected.
335                write_binary_operand(f, expr, right_edge(expr) < prec::LIKE);
336                if *negated {
337                    f.write_str(" NOT");
338                }
339                f.write_str(" BETWEEN ");
340                write_between_bound(f, low);
341                f.write_str(" AND ");
342                write_between_bound(f, high);
343            }
344            Expr::Op { op, expr1, expr2 } => {
345                if let Some(expr2) = expr2 {
346                    // Binary operators are left-associative: parenthesize an
347                    // operand that would re-associate once `Nested` is stripped.
348                    // The left by its `right_edge` (strictly looser than `op`), the
349                    // right by its `left_edge` (equal-or-looser, as equal
350                    // re-associates left). See those helpers for the spine
351                    // reasoning.
352                    let p = binary_op_precedence(op);
353                    write_binary_operand(f, expr1, right_edge(expr1) < p);
354                    f.write_str(" ");
355                    f.write_str(op);
356                    f.write_str(" ");
357                    write_binary_operand(f, expr2, left_edge(expr2) <= p);
358                } else {
359                    f.write_str(op);
360                    f.write_str(" ");
361                    if prefix_operand_needs_parens(op, expr1.as_ref()) {
362                        f.write_str("(");
363                        f.write_node(&expr1);
364                        f.write_str(")");
365                    } else {
366                        f.write_node(&expr1);
367                    }
368                }
369            }
370            Expr::Cast {
371                expr,
372                data_type,
373                failure_mode: CastFailureMode::Error,
374            } => {
375                // `::` binds very tightly, so a non-self-delimiting operand must
376                // be parenthesized or the cast re-associates into its spine.
377                // `CAST(-0 AS int4)` (i.e. `Cast(- 0)`) would otherwise print as
378                // `- 0::int4` and reparse as `- (0::int4)`. The parser wraps such
379                // operands in `Expr::Nested`, but `normalize` strips those, so the
380                // printer must re-add them (mirroring the `Collate` arm). `Nested`
381                // is itself self-delimiting, so parser-produced ASTs don't double up.
382                if prints_self_delimiting(expr) {
383                    f.write_node(&expr);
384                } else {
385                    f.write_str("(");
386                    f.write_node(&expr);
387                    f.write_str(")");
388                }
389                f.write_str("::");
390                f.write_node(data_type);
391            }
392            Expr::Cast {
393                expr,
394                data_type,
395                failure_mode: CastFailureMode::NullFallback,
396            } => {
397                f.write_str("TRY_CAST(");
398                f.write_node(&expr);
399                f.write_str(" AS ");
400                f.write_node(data_type);
401                f.write_str(")");
402            }
403            Expr::Collate { expr, collation } => {
404                // `COLLATE` binds very tightly (`PostfixCollateAt`), so a
405                // low-precedence operand must be parenthesized or the collation
406                // re-associates onto its rightmost sub-operand — `a + b COLLATE c`
407                // would reparse as `a + (b COLLATE c)`. (Round-trip parens are
408                // stripped by `normalize`, so the printer must re-add them.)
409                if prints_self_delimiting(expr) {
410                    f.write_node(&expr);
411                } else {
412                    f.write_str("(");
413                    f.write_node(&expr);
414                    f.write_str(")");
415                }
416                f.write_str(" COLLATE ");
417                f.write_node(&collation);
418            }
419            Expr::HomogenizingFunction { function, exprs } => {
420                f.write_node(function);
421                f.write_str("(");
422                f.write_node(&display::comma_separated(exprs));
423                f.write_str(")");
424            }
425            Expr::NullIf { l_expr, r_expr } => {
426                f.write_str("NULLIF(");
427                f.write_node(&display::comma_separated(&[l_expr, r_expr]));
428                f.write_str(")");
429            }
430            Expr::Nested(ast) => {
431                f.write_str("(");
432                f.write_node(&ast);
433                f.write_str(")");
434            }
435            Expr::Row { exprs } => {
436                f.write_str("ROW(");
437                f.write_node(&display::comma_separated(exprs));
438                f.write_str(")");
439            }
440            Expr::Value(v) => {
441                f.write_node(v);
442            }
443            Expr::Function(fun) => {
444                f.write_node(fun);
445            }
446            Expr::Case {
447                operand,
448                conditions,
449                results,
450                else_result,
451            } => {
452                f.write_str("CASE");
453                if let Some(operand) = operand {
454                    f.write_str(" ");
455                    f.write_node(&operand);
456                }
457                for (c, r) in conditions.iter().zip_eq(results) {
458                    f.write_str(" WHEN ");
459                    f.write_node(c);
460                    f.write_str(" THEN ");
461                    f.write_node(r);
462                }
463
464                if let Some(else_result) = else_result {
465                    f.write_str(" ELSE ");
466                    f.write_node(&else_result);
467                }
468                f.write_str(" END")
469            }
470            Expr::Exists(s) => {
471                f.write_str("EXISTS (");
472                f.write_node(&s);
473                f.write_str(")");
474            }
475            Expr::Subquery(s) => {
476                f.write_str("(");
477                f.write_node(&s);
478                f.write_str(")");
479            }
480            Expr::AnySubquery { left, op, right } => {
481                write_quantified_left(f, left, op);
482                f.write_str(" ");
483                f.write_str(op);
484                f.write_str(" ANY (");
485                f.write_node(&right);
486                f.write_str(")");
487            }
488            Expr::AnyExpr { left, op, right } => {
489                write_quantified_left(f, left, op);
490                f.write_str(" ");
491                f.write_str(op);
492                f.write_str(" ANY (");
493                f.write_node(&right);
494                f.write_str(")");
495            }
496            Expr::AllSubquery { left, op, right } => {
497                write_quantified_left(f, left, op);
498                f.write_str(" ");
499                f.write_str(op);
500                f.write_str(" ALL (");
501                f.write_node(&right);
502                f.write_str(")");
503            }
504            Expr::AllExpr { left, op, right } => {
505                write_quantified_left(f, left, op);
506                f.write_str(" ");
507                f.write_str(op);
508                f.write_str(" ALL (");
509                f.write_node(&right);
510                f.write_str(")");
511            }
512            Expr::Array(exprs) => {
513                f.write_str("ARRAY[");
514                f.write_node(&display::comma_separated(exprs));
515                f.write_str("]");
516            }
517            Expr::ArraySubquery(s) => {
518                f.write_str("ARRAY(");
519                f.write_node(&s);
520                f.write_str(")");
521            }
522            Expr::List(exprs) => {
523                f.write_str("LIST[");
524                f.write_node(&display::comma_separated(exprs));
525                f.write_str("]");
526            }
527            Expr::ListSubquery(s) => {
528                f.write_str("LIST(");
529                f.write_node(&s);
530                f.write_str(")");
531            }
532            Expr::Map(exprs) => {
533                f.write_str("MAP[");
534                f.write_node(&display::comma_separated(exprs));
535                f.write_str("]");
536            }
537            Expr::MapSubquery(s) => {
538                f.write_str("MAP(");
539                f.write_node(&s);
540                f.write_str(")");
541            }
542            Expr::Subscript { expr, positions } => {
543                write_subscript_receiver(f, expr);
544                f.write_str("[");
545
546                let mut first = true;
547
548                for p in positions {
549                    if first {
550                        first = false
551                    } else {
552                        f.write_str("][");
553                    }
554                    f.write_node(p);
555                }
556
557                f.write_str("]");
558            }
559        }
560    }
561}
562impl_display_t!(Expr);
563
564/// Write `expr` as the receiver of a `.` operator (used by `FieldAccess` and
565/// `WildcardAccess`), parenthesizing when the receiver could re-bind the
566/// trailing dot on reparse. The `.` token has very high precedence and both
567/// the lexer and parser greedily extend adjacent tokens: `1.x` tokenizes the
568/// number `1.` and leaves `x` as an alias, and `'a'::T.x` consumes `T.x` as a
569/// qualified type name. The whitelist below covers receivers that print as
570/// self-terminating syntax (parenthesized exprs, function calls, bracketed
571/// collections, etc.). Anything else gets explicit parens.
572///
573/// A bare `Identifier`/`QualifiedWildcard` receiver is *not* safe: `a` then
574/// `.b`/`.*` prints as `a.b`/`a.*`, which reparses as the qualified identifier
575/// `Identifier([a, b])` / `QualifiedWildcard([a])` rather than a field/wildcard
576/// access. The parser only ever builds those accesses over a parenthesized
577/// receiver (`(a).b`), so it wraps the name in `Expr::Nested`. A bare name here
578/// is a `Nested`-stripped AST and must be re-parenthesized. A `FieldAccess` /
579/// `WildcardAccess` receiver *is* safe, because its own printing already
580/// parenthesizes a bare-name base (`(a).b.c`), so the chain stays self-delimiting.
581///
582/// The quantified-subquery forms (`AnySubquery`/`AllSubquery`, printed
583/// `<expr> <op> ANY (<query>)`) are likewise *not* safe: they end in a `(query)`
584/// that is only a sub-part, so a trailing `.x`/`.*` binds to that inner subquery
585/// rather than the whole expression. (Contrast `Subquery`/`ArraySubquery`/… which
586/// are a single `(…)`/`ARRAY(…)` primary, so a trailing dot attaches to the whole
587/// thing.)
588fn write_dot_receiver<W: fmt::Write, T: AstInfo>(f: &mut AstFormatter<W>, expr: &Expr<T>) {
589    let safe = matches!(
590        expr,
591        Expr::FieldAccess { .. }
592            | Expr::WildcardAccess(_)
593            | Expr::Parameter(_)
594            | Expr::Nested(_)
595            | Expr::Row { .. }
596            | Expr::Function(_)
597            | Expr::Case { .. }
598            | Expr::Exists(_)
599            | Expr::Subquery(_)
600            | Expr::Array(_)
601            | Expr::ArraySubquery(_)
602            | Expr::List(_)
603            | Expr::ListSubquery(_)
604            | Expr::Map(_)
605            | Expr::MapSubquery(_)
606            | Expr::Subscript { .. }
607            | Expr::HomogenizingFunction { .. }
608            | Expr::NullIf { .. }
609            | Expr::Value(
610                Value::String(_)
611                    | Value::Boolean(_)
612                    | Value::Null
613                    | Value::HexString(_)
614                    | Value::Interval(_)
615            )
616    );
617    if safe {
618        f.write_node(expr);
619    } else {
620        f.write_str("(");
621        f.write_node(expr);
622        f.write_str(")");
623    }
624}
625
626/// Write `left` as the LHS of `<left> <op> ANY/ALL (...)`. The printed `<op>` is an
627/// ordinary binary infix. It can be any operator the parser accepts here, from
628/// `=`/`<` (`Cmp`) all the way down to `*`/`/`/`%` (`MultiplyDivide`), and on
629/// reparse it binds into any operator exposed on `left`'s right spine that is
630/// *strictly looser* than `<op>` itself, stealing that suffix into the quantified
631/// expression's left rather than wrapping the whole `left`. So parenthesize
632/// exactly when `left`'s [`right_edge`] binds looser than `<op>`'s own precedence
633/// ([`binary_op_precedence`]), mirroring the binary-`Op` arm. Using the operator's
634/// real precedence (not a fixed `Like` threshold) both parenthesizes a
635/// tighter-binding `<op>` over a looser left and leaves an equal-or-tighter left
636/// bare (`a = b = ANY (…)`, `a LIKE b = ANY (…)`), which the old fixed threshold
637/// over-parenthesized. The tighter-binding case, `(a + b) * ANY (…)`, would
638/// otherwise print `a + b * ANY (…)` and reparse as the different
639/// `a + (b * ANY (…))`. [`right_edge`] also sees a looser spine hidden under
640/// right-transparent prefixes, e.g. the `NOT`'s `IN` in `- NOT a IN (b) = ANY (…)`.
641fn write_quantified_left<W: fmt::Write, T: AstInfo>(
642    f: &mut AstFormatter<W>,
643    expr: &Expr<T>,
644    op: &Op,
645) {
646    let needs_parens = right_edge(expr) < binary_op_precedence(op);
647    if needs_parens {
648        f.write_str("(");
649        f.write_node(expr);
650        f.write_str(")");
651    } else {
652        f.write_node(expr);
653    }
654}
655
656/// Write `bound` as a `BETWEEN … AND …` bound. The parser parses both bounds with
657/// `parse_subexpr(Precedence::Like)` (see `Parser::parse_between`), starting fresh
658/// with nothing to the bound's left, so it walks the bound's *left spine* and
659/// stops at the first operator binding at or below `Like`, leaving that operator
660/// outside the bound (`x BETWEEN 1 IS NULL AND y` parses `1` as the bound, then
661/// expects `AND` but finds `IS`). A bound is therefore safe bare only when its
662/// left edge binds strictly above `Like`. Use [`left_edge`] (not [`right_edge`],
663/// which closes at `ATOM` for the right-closing `IS NULL`/`= ANY (…)`/`IN (…)`
664/// forms whose looseness is on the left). The parser wraps these bounds in
665/// `Expr::Nested` (which is `ATOM`, so it prints bare). This re-adds the parens
666/// for ASTs where that wrapper is absent.
667fn write_between_bound<W: fmt::Write, T: AstInfo>(f: &mut AstFormatter<W>, bound: &Expr<T>) {
668    let needs_parens = left_edge(bound) <= prec::LIKE;
669    if needs_parens {
670        f.write_str("(");
671        f.write_node(bound);
672        f.write_str(")");
673    } else {
674        f.write_node(bound);
675    }
676}
677
678/// Output-precedence ranks, derived directly from the parser's [`Precedence`]
679/// ladder (higher binds tighter) so it stays the single source of truth:
680/// reordering or inserting a parser level reranks these automatically, and only
681/// the variant each rank maps to is maintained by hand. They classify the *top*
682/// operator an expr prints with, so the binary-operator printer can parenthesize
683/// an operand that would otherwise re-associate on reparse. `ATOM`, the one rank
684/// with no parser counterpart, is layered one above the tightest parser level to
685/// mark the self-delimiting primaries. They never need parens.
686///
687/// [`Precedence`]: crate::parser::Precedence
688// `Precedence` is a fieldless enum with a handful of variants, so reading each
689// discriminant with `as u8` is exact and lossless.
690#[allow(clippy::as_conversions)]
691mod prec {
692    use crate::parser::Precedence;
693
694    pub const OR: u8 = Precedence::Or as u8;
695    pub const AND: u8 = Precedence::And as u8;
696    pub const NOT: u8 = Precedence::PrefixNot as u8;
697    pub const IS: u8 = Precedence::Is as u8;
698    pub const CMP: u8 = Precedence::Cmp as u8;
699    pub const LIKE: u8 = Precedence::Like as u8;
700    pub const OTHER: u8 = Precedence::Other as u8;
701    pub const PLUS_MINUS: u8 = Precedence::PlusMinus as u8;
702    pub const MULTIPLY_DIVIDE: u8 = Precedence::MultiplyDivide as u8;
703    // The `COLLATE` and postfix (`::`/`[…]`) parser levels live between
704    // `MULTIPLY_DIVIDE` and `ATOM`, but neither edge function ever *returns* them:
705    // those forms are self-delimiting (their own operand is parenthesized when it
706    // isn't), so both their edges rank `ATOM`. Kept for parity with the ladder.
707    #[allow(dead_code)]
708    pub const COLLATE: u8 = Precedence::PostfixCollateAt as u8;
709    pub const PREFIX: u8 = Precedence::PrefixPlusMinus as u8;
710    #[allow(dead_code)]
711    pub const POSTFIX: u8 = Precedence::PostfixSubscriptCast as u8;
712    pub const ATOM: u8 = Precedence::PostfixSubscriptCast as u8 + 1;
713}
714
715/// The precedence of a binary operator, mirroring `Parser::get_next_precedence`.
716/// A namespaced `OPERATOR(...)` binds at `OTHER`, like the parser.
717fn binary_op_precedence(op: &Op) -> u8 {
718    if op.namespace.is_some() {
719        return prec::OTHER;
720    }
721    match op.op.as_str() {
722        "=" | "<" | "<=" | "<>" | "!=" | ">" | ">=" => prec::CMP,
723        "+" | "-" => prec::PLUS_MINUS,
724        "*" | "/" | "%" => prec::MULTIPLY_DIVIDE,
725        _ => prec::OTHER,
726    }
727}
728
729/// The precedence at which a prefix operator (`Op` with no second operand)
730/// parses its operand, mirroring `Parser::parse_prefix`: `-`/`+` at
731/// `PrefixPlusMinus`, but `~` (and namespaced prefixes) at `Other`, so `~ a + b`
732/// parses as `~ (a + b)`. `~` binds looser than `+`/`-`/`*`.
733fn unary_prec(op: &Op) -> u8 {
734    if op.namespace.is_none() && (op.op == "-" || op.op == "+") {
735        prec::PREFIX
736    } else {
737        prec::OTHER
738    }
739}
740
741/// The loosest precedence exposed on `expr`'s *right spine*, the precedence at
742/// which an operator printed immediately to its right would bind *into* it
743/// rather than wrap it. For a left operand / subject of a construct that prints
744/// to its right, this is what decides parenthesization (its mirror, [`left_edge`],
745/// decides right operands), because a prefix operator and the right operand of a
746/// binary/`BETWEEN`/`LIKE`/`IS DISTINCT FROM` are right-transparent:
747/// `- NOT a IN (b)` exposes the `NOT`'s `IN` on the right even though its top node
748/// is unary `-`. Forms that close with a bracket on the right (`(…)`, `[…]`,
749/// `::type`, `IS NULL`) are `ATOM`.
750fn right_edge<T: AstInfo>(expr: &Expr<T>) -> u8 {
751    match expr {
752        // Right-transparent binary infixes: an operator tighter than this one
753        // binds into the right operand, which itself may expose a looser spine.
754        Expr::Or { right, .. } => prec::OR.min(right_edge(right)),
755        Expr::And { right, .. } => prec::AND.min(right_edge(right)),
756        Expr::Op {
757            op, expr2: Some(r), ..
758        } => binary_op_precedence(op).min(right_edge(r)),
759        // Prefix operators expose their operand's right spine.
760        Expr::Op {
761            op,
762            expr1,
763            expr2: None,
764        } => unary_prec(op).min(right_edge(expr1)),
765        Expr::Not { expr } => prec::NOT.min(right_edge(expr)),
766        // `IS DISTINCT FROM x` exposes `x`, while `IS NULL`/`TRUE`/… close.
767        Expr::IsExpr {
768            construct: IsExprConstruct::DistinctFrom(x),
769            ..
770        } => prec::IS.min(right_edge(x)),
771        // `… BETWEEN low AND high` exposes `high`. `… [I]LIKE pat [ESCAPE esc]`
772        // exposes the rightmost of `esc`/`pat`.
773        Expr::Between { high, .. } => prec::LIKE.min(right_edge(high)),
774        Expr::Like {
775            pattern, escape, ..
776        } => {
777            let rightmost = escape.as_deref().unwrap_or_else(|| pattern.as_ref());
778            prec::LIKE.min(right_edge(rightmost))
779        }
780        // Everything else closes on the right (a bracket, a keyword, a literal,
781        // or `IS NULL`-style), so nothing binds into it.
782        _ => prec::ATOM,
783    }
784}
785
786/// The loosest precedence exposed on `expr`'s *left spine*, the mirror of
787/// [`right_edge`]. For a *right* operand (an operator on its left), this is what
788/// decides parenthesization: a left-associative operator printed to its left
789/// reaches into the left spine and re-associates if that spine exposes a
790/// precedence at or below the operator's. The top operator alone is not enough,
791/// because a left-nested chain can bury a looser operator down its left edge:
792/// `387 = ANY (...) LIKE a IN (...)` has a top `IN` (`Like`) but exposes the
793/// `= ANY` (`Cmp`) on its left, so a tighter `<>` to its left
794/// (`48 <> 387 = ANY (...) ...`) would steal the `<>` into the `= ANY`'s left
795/// rather than leave it as the `<>`'s right operand. Forms that open with their
796/// own token on the left (a prefix operator, a keyword, `(…)`, a literal) are
797/// `ATOM`.
798fn left_edge<T: AstInfo>(expr: &Expr<T>) -> u8 {
799    match expr {
800        // Left-transparent infixes / postfix-keyword constructs: the subject (or
801        // left operand) sits on the left spine, so descend into it.
802        Expr::Or { left, .. } => prec::OR.min(left_edge(left)),
803        Expr::And { left, .. } => prec::AND.min(left_edge(left)),
804        Expr::Op {
805            op,
806            expr1,
807            expr2: Some(_),
808        } => binary_op_precedence(op).min(left_edge(expr1)),
809        Expr::IsExpr { expr, .. } => prec::IS.min(left_edge(expr)),
810        Expr::AnyExpr { left, .. }
811        | Expr::AllExpr { left, .. }
812        | Expr::AnySubquery { left, .. }
813        | Expr::AllSubquery { left, .. } => prec::CMP.min(left_edge(left)),
814        Expr::Like { expr, .. }
815        | Expr::Between { expr, .. }
816        | Expr::InList { expr, .. }
817        | Expr::InSubquery { expr, .. } => prec::LIKE.min(left_edge(expr)),
818        // Everything else leads with its own token on the left: a prefix
819        // operator (`-`/`+`/`~`/`NOT`), a keyword, `(…)`, `ARRAY[…]`, a literal,
820        // or a `COLLATE`/`::`/`[…]` whose own operand the printer parenthesizes
821        // when it isn't self-delimiting. Nothing to the left binds into it.
822        _ => prec::ATOM,
823    }
824}
825
826/// Write `operand` for a binary operator, parenthesizing it iff `needs_parens`.
827fn write_binary_operand<W: fmt::Write, T: AstInfo>(
828    f: &mut AstFormatter<W>,
829    operand: &Expr<T>,
830    needs_parens: bool,
831) {
832    if needs_parens {
833        f.write_str("(");
834        f.write_node(operand);
835        f.write_str(")");
836    } else {
837        f.write_node(operand);
838    }
839}
840
841/// Whether `expr` prints in a *self-delimiting* form — atomic, or wrapped in its
842/// own brackets/parens (`name(...)`, `(…)`, `ARRAY[…]`, `CASE … END`, …) — so it
843/// is safe to print immediately to the left of a tight postfix operator (`::`,
844/// `COLLATE`, or the `IN` delimiter of the `position(<needle> IN …)` special
845/// form) without the operator re-associating into the expression's spine.
846///
847/// Anything with an exposed operator spine is *not* self-delimiting: a tight
848/// postfix would bind to its rightmost sub-operand (`a + b COLLATE c` parses as
849/// `a + (b COLLATE c)`), and the `position` `IN` delimiter would split on an
850/// inner `IN`/comparison (`a IN (q) ->> b`). Callers must parenthesize / fall
851/// back for those. Postfix forms (`::`/`COLLATE`/`[…]`) are self-delimiting only
852/// when their own inner operand is.
853fn prints_self_delimiting<T: AstInfo>(expr: &Expr<T>) -> bool {
854    match expr {
855        Expr::Value(_)
856        | Expr::Identifier(_)
857        | Expr::QualifiedWildcard(_)
858        | Expr::Parameter(_)
859        | Expr::Function(_)
860        | Expr::HomogenizingFunction { .. }
861        | Expr::NullIf { .. }
862        | Expr::Subquery(_)
863        | Expr::Exists(_)
864        | Expr::Nested(_)
865        | Expr::Array(_)
866        | Expr::ArraySubquery(_)
867        | Expr::List(_)
868        | Expr::ListSubquery(_)
869        | Expr::Map(_)
870        | Expr::MapSubquery(_)
871        | Expr::Case { .. }
872        | Expr::Row { .. }
873        | Expr::Cast {
874            failure_mode: CastFailureMode::NullFallback,
875            ..
876        } => true,
877        // The postfix `::` / `COLLATE` / `[…]` forms print as `<inner><suffix>`,
878        // so they are safe only when their inner operand is.
879        Expr::Cast { expr, .. } | Expr::Collate { expr, .. } | Expr::Subscript { expr, .. } => {
880            prints_self_delimiting(expr)
881        }
882        _ => false,
883    }
884}
885
886/// Whether the operand of a prefix operator (an `Op` with no second operand)
887/// must be parenthesized so the printed expression reparses to the same tree.
888/// Both printers (`AstDisplay` and `mz-sql-pretty`) must use it, so they agree.
889pub fn prefix_operand_needs_parens<T: AstInfo>(op: &Op, operand: &Expr<T>) -> bool {
890    if unary_prec(op) == prec::PREFIX {
891        bare_prefix_operand_needs_parens(operand)
892    } else {
893        // An `Other`-level prefix (`~`, a namespaced `OPERATOR(...)`) reparses
894        // its operand at `Other`, so the operand re-associates exactly when its
895        // left spine exposes that level or looser, as for the right operand of
896        // a binary operator.
897        left_edge(operand) <= prec::OTHER
898    }
899}
900
901/// Whether the operand of a bare prefix `-`/`+` must be parenthesized to
902/// round-trip. Such a prefix op binds *tighter* than `COLLATE`/`AT TIME ZONE`
903/// and the binary/comparison operators, but *looser* than the postfix
904/// `::`/`[…]` forms, and `- <number>` additionally lexes as a negative literal.
905/// So peel the tight postfixes (`::`/`[…]`). If the chain bottoms out at a
906/// numeric literal, the sign would fold into it, and if it bottoms out at
907/// anything other than a self-delimiting non-`COLLATE` primary (a `COLLATE`, a
908/// binary op, …), the prefix op would re-associate. Both need parens.
909/// (`a + b COLLATE c` reparses as `a + (b COLLATE c)`, and `- x COLLATE c` as
910/// `(- x) COLLATE c`.)
911fn bare_prefix_operand_needs_parens<T: AstInfo>(operand: &Expr<T>) -> bool {
912    let mut e = operand;
913    let mut saw_postfix = false;
914    loop {
915        match e {
916            Expr::Cast {
917                expr,
918                failure_mode: CastFailureMode::Error,
919                ..
920            }
921            | Expr::Subscript { expr, .. } => {
922                saw_postfix = true;
923                e = expr.as_ref();
924            }
925            Expr::Value(Value::Number(_)) => return saw_postfix,
926            // Another prefix operator (`+ + x`, `- ~ x`, `NOT NOT x`) stacks
927            // directly: prefix operators don't re-associate, and the inner
928            // operator symbol sits between the outer one and any digit so there
929            // is no `- <number>` fold. Always safe — and crucially, NOT adding
930            // parens here keeps deep unary chains from exploding the nesting
931            // depth (and overflowing the stack) on reparse.
932            Expr::Op { expr2: None, .. } | Expr::Not { .. } => return false,
933            // Self-delimiting, but a top-level `COLLATE` binds looser than the
934            // prefix op, so it (unlike `::`/`[…]`) is not safe here.
935            _ => return !(prints_self_delimiting(e) && !matches!(e, Expr::Collate { .. })),
936        }
937    }
938}
939
940/// Write `expr` as the receiver of a `[…]` subscript. An unparenthesized
941/// `Identifier(["map"])` reparses as `Token::Keyword(MAP)` followed by `[`,
942/// which dispatches to `parse_map` (the map-literal grammar) instead of a
943/// regular subscript. Parenthesize identifiers whose last component is a
944/// context-sensitive keyword so the round trip stays an identifier subscript.
945fn write_subscript_receiver<W: fmt::Write, T: AstInfo>(f: &mut AstFormatter<W>, expr: &Expr<T>) {
946    let needs_parens = match expr {
947        // A bare keyword identifier (`map`, `list`, …) dispatches to the
948        // map/list-literal grammar before `[`, so it needs parens even though
949        // identifiers are otherwise safe receivers.
950        Expr::Identifier(idents) => idents
951            .last()
952            .and_then(|id| id.as_keyword())
953            .map(|kw| kw.is_context_sensitive_keyword())
954            .unwrap_or(false),
955        // Self-delimiting primaries, the bracketed collections, and the postfix
956        // forms that end in an identifier or `)` are safe: a following `[…]`
957        // attaches to the whole receiver as a fresh subscript.
958        Expr::QualifiedWildcard(_)
959        | Expr::Parameter(_)
960        | Expr::Value(_)
961        | Expr::Function(_)
962        | Expr::HomogenizingFunction { .. }
963        | Expr::NullIf { .. }
964        | Expr::Nested(_)
965        | Expr::Subquery(_)
966        | Expr::Exists(_)
967        | Expr::Case { .. }
968        | Expr::Row { .. }
969        | Expr::Array(_)
970        | Expr::ArraySubquery(_)
971        | Expr::List(_)
972        | Expr::ListSubquery(_)
973        | Expr::Map(_)
974        | Expr::MapSubquery(_)
975        | Expr::FieldAccess { .. }
976        | Expr::WildcardAccess(_)
977        | Expr::Collate { .. }
978        | Expr::Cast {
979            failure_mode: CastFailureMode::NullFallback,
980            ..
981        } => false,
982        // `::` `Cast`: the type parser swallows a following `[…]` as an array suffix
983        // (`a::int4[1]` is `a` cast to `int4[]`, not a subscript of `a::int4`).
984        // `Subscript`: consecutive `[…]` flatten into one node (`a[1][2]` is a
985        // single subscript), so a nested subscript receiver must be parenthesized
986        // to stay nested. Everything else (operators, `IS`/`LIKE`/… constructs)
987        // binds looser than `[` and would re-associate, so parenthesize by default.
988        _ => true,
989    };
990    if needs_parens {
991        f.write_str("(");
992        f.write_node(expr);
993        f.write_str(")");
994    } else {
995        f.write_node(expr);
996    }
997}
998
999impl<T: AstInfo> Expr<T> {
1000    pub fn null() -> Expr<T> {
1001        Expr::Value(Value::Null)
1002    }
1003
1004    pub fn number<S>(n: S) -> Expr<T>
1005    where
1006        S: Into<String>,
1007    {
1008        Expr::Value(Value::Number(n.into()))
1009    }
1010
1011    pub fn negate(self) -> Expr<T> {
1012        Expr::Not {
1013            expr: Box::new(self),
1014        }
1015    }
1016
1017    pub fn and(self, right: Expr<T>) -> Expr<T> {
1018        Expr::And {
1019            left: Box::new(self),
1020            right: Box::new(right),
1021        }
1022    }
1023
1024    pub fn or(self, right: Expr<T>) -> Expr<T> {
1025        Expr::Or {
1026            left: Box::new(self),
1027            right: Box::new(right),
1028        }
1029    }
1030
1031    pub fn binop(self, op: Op, right: Expr<T>) -> Expr<T> {
1032        Expr::Op {
1033            op,
1034            expr1: Box::new(self),
1035            expr2: Some(Box::new(right)),
1036        }
1037    }
1038
1039    pub fn lt(self, right: Expr<T>) -> Expr<T> {
1040        self.binop(Op::bare("<"), right)
1041    }
1042
1043    pub fn lt_eq(self, right: Expr<T>) -> Expr<T> {
1044        self.binop(Op::bare("<="), right)
1045    }
1046
1047    pub fn gt(self, right: Expr<T>) -> Expr<T> {
1048        self.binop(Op::bare(">"), right)
1049    }
1050
1051    pub fn gt_eq(self, right: Expr<T>) -> Expr<T> {
1052        self.binop(Op::bare(">="), right)
1053    }
1054
1055    pub fn equals(self, right: Expr<T>) -> Expr<T> {
1056        self.binop(Op::bare("="), right)
1057    }
1058
1059    pub fn not_equals(self, right: Expr<T>) -> Expr<T> {
1060        self.binop(Op::bare("<>"), right)
1061    }
1062
1063    pub fn minus(self, right: Expr<T>) -> Expr<T> {
1064        self.binop(Op::bare("-"), right)
1065    }
1066
1067    pub fn multiply(self, right: Expr<T>) -> Expr<T> {
1068        self.binop(Op::bare("*"), right)
1069    }
1070
1071    pub fn modulo(self, right: Expr<T>) -> Expr<T> {
1072        self.binop(Op::bare("%"), right)
1073    }
1074
1075    pub fn divide(self, right: Expr<T>) -> Expr<T> {
1076        self.binop(Op::bare("/"), right)
1077    }
1078
1079    pub fn cast(self, data_type: T::DataType) -> Expr<T> {
1080        Expr::Cast {
1081            expr: Box::new(self),
1082            data_type,
1083            failure_mode: CastFailureMode::Error,
1084        }
1085    }
1086
1087    pub fn call(name: T::ItemName, args: Vec<Expr<T>>) -> Expr<T> {
1088        Expr::Function(Function {
1089            name,
1090            args: FunctionArgs::args(args),
1091            filter: None,
1092            over: None,
1093            distinct: false,
1094        })
1095    }
1096
1097    pub fn call_nullary(name: T::ItemName) -> Expr<T> {
1098        Expr::call(name, vec![])
1099    }
1100
1101    pub fn call_unary(self, name: T::ItemName) -> Expr<T> {
1102        Expr::call(name, vec![self])
1103    }
1104
1105    pub fn take(&mut self) -> Expr<T> {
1106        mem::replace(self, Expr::Identifier(vec![]))
1107    }
1108}
1109
1110/// A reference to an operator.
1111#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
1112pub struct Op {
1113    /// Any namespaces that preceded the operator.
1114    pub namespace: Option<Vec<Ident>>,
1115    /// The operator itself.
1116    pub op: String,
1117}
1118
1119impl AstDisplay for Op {
1120    fn fmt<W: fmt::Write>(&self, f: &mut AstFormatter<W>) {
1121        if let Some(namespace) = &self.namespace {
1122            f.write_str("OPERATOR(");
1123            for name in namespace {
1124                f.write_node(name);
1125                f.write_str(".");
1126            }
1127            f.write_str(&self.op);
1128            f.write_str(")");
1129        } else {
1130            f.write_str(&self.op)
1131        }
1132    }
1133}
1134impl_display!(Op);
1135
1136impl Op {
1137    /// Constructs a new unqualified operator reference.
1138    pub fn bare<S>(op: S) -> Op
1139    where
1140        S: Into<String>,
1141    {
1142        Op {
1143            namespace: None,
1144            op: op.into(),
1145        }
1146    }
1147}
1148
1149/// What a cast does when the value cannot be converted to the target type.
1150#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
1151pub enum CastFailureMode {
1152    /// The cast raises an error, as `CAST(expr AS type)` and `expr::type` do.
1153    Error,
1154    /// The cast evaluates to `NULL`, as `TRY_CAST(expr AS type)` does. Errors
1155    /// raised while evaluating `expr` itself still propagate.
1156    NullFallback,
1157}
1158
1159#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
1160pub enum HomogenizingFunction {
1161    Coalesce,
1162    Greatest,
1163    Least,
1164}
1165
1166impl AstDisplay for HomogenizingFunction {
1167    fn fmt<W: fmt::Write>(&self, f: &mut AstFormatter<W>) {
1168        match self {
1169            HomogenizingFunction::Coalesce => f.write_str("COALESCE"),
1170            HomogenizingFunction::Greatest => f.write_str("GREATEST"),
1171            HomogenizingFunction::Least => f.write_str("LEAST"),
1172        }
1173    }
1174}
1175impl_display!(HomogenizingFunction);
1176
1177#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
1178pub struct MapEntry<T: AstInfo> {
1179    pub key: Expr<T>,
1180    pub value: Expr<T>,
1181}
1182
1183impl<T: AstInfo> AstDisplay for MapEntry<T> {
1184    fn fmt<W: fmt::Write>(&self, f: &mut AstFormatter<W>) {
1185        f.write_node(&self.key);
1186        f.write_str(" => ");
1187        f.write_node(&self.value);
1188    }
1189}
1190impl_display_t!(MapEntry);
1191
1192#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
1193pub struct SubscriptPosition<T: AstInfo> {
1194    pub start: Option<Expr<T>>,
1195    pub end: Option<Expr<T>>,
1196    // i.e. did this subscript include a colon
1197    pub explicit_slice: bool,
1198}
1199
1200impl<T: AstInfo> AstDisplay for SubscriptPosition<T> {
1201    fn fmt<W: fmt::Write>(&self, f: &mut AstFormatter<W>) {
1202        if let Some(start) = &self.start {
1203            f.write_node(start);
1204        }
1205        if self.explicit_slice {
1206            f.write_str(":");
1207            if let Some(end) = &self.end {
1208                f.write_node(end);
1209            }
1210        }
1211    }
1212}
1213impl_display_t!(SubscriptPosition);
1214
1215/// A window specification (i.e. `OVER (PARTITION BY .. ORDER BY .. etc.)`)
1216/// Includes potential IGNORE NULLS or RESPECT NULLS from before the OVER clause.
1217#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
1218pub struct WindowSpec<T: AstInfo> {
1219    pub partition_by: Vec<Expr<T>>,
1220    pub order_by: Vec<OrderByExpr<T>>,
1221    pub window_frame: Option<WindowFrame>,
1222    // Note that IGNORE NULLS and RESPECT NULLS are mutually exclusive. We validate that not both
1223    // are present during HIR planning.
1224    pub ignore_nulls: bool,
1225    pub respect_nulls: bool,
1226}
1227
1228impl<T: AstInfo> AstDisplay for WindowSpec<T> {
1229    fn fmt<W: fmt::Write>(&self, f: &mut AstFormatter<W>) {
1230        if self.ignore_nulls {
1231            f.write_str(" IGNORE NULLS");
1232        }
1233        if self.respect_nulls {
1234            f.write_str(" RESPECT NULLS");
1235        }
1236        f.write_str(" OVER (");
1237        let mut delim = "";
1238        if !self.partition_by.is_empty() {
1239            delim = " ";
1240            f.write_str("PARTITION BY ");
1241            f.write_node(&display::comma_separated(&self.partition_by));
1242        }
1243        if !self.order_by.is_empty() {
1244            f.write_str(delim);
1245            delim = " ";
1246            f.write_str("ORDER BY ");
1247            f.write_node(&display::comma_separated(&self.order_by));
1248        }
1249        if let Some(window_frame) = &self.window_frame {
1250            if let Some(end_bound) = &window_frame.end_bound {
1251                f.write_str(delim);
1252                f.write_node(&window_frame.units);
1253                f.write_str(" BETWEEN ");
1254                f.write_node(&window_frame.start_bound);
1255                f.write_str(" AND ");
1256                f.write_node(&*end_bound);
1257            } else {
1258                f.write_str(delim);
1259                f.write_node(&window_frame.units);
1260                f.write_str(" ");
1261                f.write_node(&window_frame.start_bound);
1262            }
1263        }
1264        f.write_str(")");
1265    }
1266}
1267impl_display_t!(WindowSpec);
1268
1269/// Specifies the data processed by a window function, e.g.
1270/// `RANGE UNBOUNDED PRECEDING` or `ROWS BETWEEN 5 PRECEDING AND CURRENT ROW`.
1271///
1272/// Note: The parser does not validate the specified bounds; the caller should
1273/// reject invalid bounds like `ROWS UNBOUNDED FOLLOWING` before execution.
1274#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
1275pub struct WindowFrame {
1276    pub units: WindowFrameUnits,
1277    pub start_bound: WindowFrameBound,
1278    /// The right bound of the `BETWEEN .. AND` clause. The end bound of `None`
1279    /// indicates the shorthand form (e.g. `ROWS 1 PRECEDING`), which must
1280    /// behave the same as `end_bound = WindowFrameBound::CurrentRow`.
1281    pub end_bound: Option<WindowFrameBound>,
1282    // TBD: EXCLUDE
1283}
1284
1285#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
1286pub enum WindowFrameUnits {
1287    Rows,
1288    Range,
1289    Groups,
1290}
1291
1292impl AstDisplay for WindowFrameUnits {
1293    fn fmt<W: fmt::Write>(&self, f: &mut AstFormatter<W>) {
1294        f.write_str(match self {
1295            WindowFrameUnits::Rows => "ROWS",
1296            WindowFrameUnits::Range => "RANGE",
1297            WindowFrameUnits::Groups => "GROUPS",
1298        })
1299    }
1300}
1301impl_display!(WindowFrameUnits);
1302
1303/// Specifies [WindowFrame]'s `start_bound` and `end_bound`
1304#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
1305pub enum WindowFrameBound {
1306    /// `CURRENT ROW`
1307    CurrentRow,
1308    /// `<N> PRECEDING` or `UNBOUNDED PRECEDING`
1309    Preceding(Option<u64>),
1310    /// `<N> FOLLOWING` or `UNBOUNDED FOLLOWING`.
1311    Following(Option<u64>),
1312}
1313
1314impl AstDisplay for WindowFrameBound {
1315    fn fmt<W: fmt::Write>(&self, f: &mut AstFormatter<W>) {
1316        match self {
1317            WindowFrameBound::CurrentRow => f.write_str("CURRENT ROW"),
1318            WindowFrameBound::Preceding(None) => f.write_str("UNBOUNDED PRECEDING"),
1319            WindowFrameBound::Following(None) => f.write_str("UNBOUNDED FOLLOWING"),
1320            WindowFrameBound::Preceding(Some(n)) => {
1321                f.write_str(n);
1322                f.write_str(" PRECEDING");
1323            }
1324            WindowFrameBound::Following(Some(n)) => {
1325                f.write_str(n);
1326                f.write_str(" FOLLOWING");
1327            }
1328        }
1329    }
1330}
1331impl_display!(WindowFrameBound);
1332
1333/// A function call
1334#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
1335pub struct Function<T: AstInfo> {
1336    pub name: T::ItemName,
1337    pub args: FunctionArgs<T>,
1338    // aggregate functions may specify e.g. `COUNT(DISTINCT X) FILTER (WHERE ...)`
1339    pub filter: Option<Box<Expr<T>>>,
1340    pub over: Option<WindowSpec<T>>,
1341    // aggregate functions may specify eg `COUNT(DISTINCT x)`
1342    pub distinct: bool,
1343}
1344
1345impl<T: AstInfo> AstDisplay for Function<T> {
1346    fn fmt<W: fmt::Write>(&self, f: &mut AstFormatter<W>) {
1347        self.fmt_call(f, true);
1348    }
1349}
1350
1351impl<T: AstInfo> Function<T> {
1352    /// Render this call in table-function position (`FROM f(...)`, `ROWS FROM
1353    /// (f(...))`), where the `extract(a FROM b)` / `position(a IN b)` special
1354    /// forms are *not* valid syntax — only the scalar-expression parser
1355    /// dispatches to them. Forces the plain comma form (with the name quoted
1356    /// to dodge the special grammar) so the round trip stays stable.
1357    pub(crate) fn fmt_table_call<W: fmt::Write>(&self, f: &mut AstFormatter<W>) {
1358        self.fmt_call(f, false);
1359    }
1360
1361    fn fmt_call<W: fmt::Write>(&self, f: &mut AstFormatter<W>, allow_special_form: bool) {
1362        // This block handles printing function calls that have special parsing. In stable mode, the
1363        // name is quoted and so won't get the special parsing. We only need to print the special
1364        // formats in non-stable mode.
1365        //
1366        // The special forms (`position(a IN b)`, `extract(field FROM source)`)
1367        // have no syntax for `DISTINCT`, a within-group `ORDER BY`, a `FILTER`,
1368        // or an `OVER` window. A call literally named `"position"`/`"extract"`
1369        // that carries any of those modifiers (only reachable via the quoted
1370        // name — the real special grammar doesn't accept them) must therefore
1371        // fall through to the plain quoted-call form, or the special form
1372        // silently drops them on display.
1373        let has_call_modifiers = self.distinct
1374            || self.filter.is_some()
1375            || self.over.is_some()
1376            || matches!(&self.args, FunctionArgs::Args { order_by, .. } if !order_by.is_empty());
1377        if allow_special_form && !f.stable() && !has_call_modifiers {
1378            let special: Option<(&str, &[Option<Keyword>])> =
1379                match self.name.to_ast_string_stable().as_str() {
1380                    // `extract(field FROM source)` parses `field` into a string
1381                    // literal, so the special form only round-trips when arg0 is
1382                    // a string. A generic `"extract"(a, b)` with a non-string
1383                    // first arg must use the plain (quoted) call form.
1384                    r#""extract""#
1385                        if self.args.len() == Some(2)
1386                            && matches!(self.args.first(), Some(Expr::Value(Value::String(_)))) =>
1387                    {
1388                        Some(("extract", &[None, Some(FROM)]))
1389                    }
1390                    // `position(<needle> IN <haystack>)` parses the needle at
1391                    // `Precedence::Like`, so a low-precedence needle (`NOT`, a
1392                    // comparison, `IS`, a boolean connective, a quantified
1393                    // comparison, ...) printed bare before the `IN` would swallow
1394                    // or stop short of the delimiter. Only use the special form
1395                    // with a needle that's safe to sit left of `IN`.
1396                    r#""position""#
1397                        if self.args.len() == Some(2)
1398                            && self.args.first().is_some_and(prints_self_delimiting) =>
1399                    {
1400                        Some(("position", &[None, Some(IN)]))
1401                    }
1402
1403                    // "trim" doesn't need to appear here because it changes the function name (to
1404                    // "btrim", "ltrim", or "rtrim"), but only "trim" is parsed specially. "substring"
1405                    // supports comma-delimited arguments, so doesn't need to be here.
1406                    _ => None,
1407                };
1408            if let Some((name, kws)) = special {
1409                f.write_str(name);
1410                f.write_str("(");
1411                self.args.intersperse_function_argument_keywords(f, kws);
1412                f.write_str(")");
1413                return;
1414            }
1415        }
1416
1417        // If the function name clashes with a keyword that has its own special
1418        // parser form, an unquoted name on reparse would trigger the
1419        // special-grammar parser instead of a regular function call. Emit the
1420        // always-quoted stable form so the regular function-call path is
1421        // preserved. The list tracks the `(Token::Keyword(KW), Some(Token::LParen))`
1422        // dispatch in `parse_prefix` (array, coalesce, ...); add a new entry
1423        // whenever a keyword grows special-grammar parens. (The `ANY`/`ALL`/`SOME`
1424        // quantifier keywords are handled more generally by `can_be_printed_bare`,
1425        // since they're also unsafe as bare identifiers, e.g. `0 # some`.)
1426        let name_stable = self.name.to_ast_string_stable();
1427        let needs_quote_to_disambiguate = matches!(
1428            name_stable.as_str(),
1429            r#""array""#
1430                | r#""coalesce""#
1431                | r#""exists""#
1432                | r#""extract""#
1433                | r#""greatest""#
1434                | r#""least""#
1435                | r#""list""#
1436                | r#""map""#
1437                | r#""normalize""#
1438                | r#""nullif""#
1439                | r#""operator""#
1440                | r#""position""#
1441                | r#""row""#
1442                | r#""substring""#
1443                | r#""trim""#
1444        );
1445        if needs_quote_to_disambiguate {
1446            f.write_str(&name_stable);
1447        } else {
1448            f.write_node(&self.name);
1449        }
1450        f.write_str("(");
1451        if self.distinct {
1452            f.write_str("DISTINCT ")
1453        }
1454        f.write_node(&self.args);
1455        f.write_str(")");
1456        if let Some(filter) = &self.filter {
1457            f.write_str(" FILTER (WHERE ");
1458            f.write_node(&filter);
1459            f.write_str(")");
1460        }
1461        if let Some(o) = &self.over {
1462            f.write_node(o);
1463        }
1464    }
1465}
1466impl_display_t!(Function);
1467
1468/// Arguments for a function call.
1469#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
1470pub enum FunctionArgs<T: AstInfo> {
1471    /// The special star argument, as in `count(*)`.
1472    Star,
1473    /// A normal list of arguments.
1474    Args {
1475        args: Vec<Expr<T>>,
1476        order_by: Vec<OrderByExpr<T>>,
1477    },
1478}
1479
1480impl<T: AstInfo> FunctionArgs<T> {
1481    pub fn args(args: Vec<Expr<T>>) -> Self {
1482        Self::Args {
1483            args,
1484            order_by: vec![],
1485        }
1486    }
1487
1488    /// The first positional argument, if any (the `*` form has none).
1489    pub fn first(&self) -> Option<&Expr<T>> {
1490        match self {
1491            FunctionArgs::Star => None,
1492            FunctionArgs::Args { args, .. } => args.first(),
1493        }
1494    }
1495
1496    /// Returns the number of arguments. Star (`*`) is None.
1497    pub fn len(&self) -> Option<usize> {
1498        match self {
1499            FunctionArgs::Star => None,
1500            FunctionArgs::Args { args, .. } => Some(args.len()),
1501        }
1502    }
1503
1504    /// Prints associated keywords before each argument
1505    fn intersperse_function_argument_keywords<W: fmt::Write>(
1506        &self,
1507        f: &mut AstFormatter<W>,
1508        kws: &[Option<Keyword>],
1509    ) {
1510        let args = match self {
1511            FunctionArgs::Star => unreachable!(),
1512            FunctionArgs::Args { args, .. } => args,
1513        };
1514        soft_assert_eq_or_log!(args.len(), kws.len());
1515        let mut delim = "";
1516        for (arg, kw) in args.iter().zip_eq(kws) {
1517            if let Some(kw) = kw {
1518                f.write_str(delim);
1519                f.write_str(kw.as_str());
1520                delim = " ";
1521            }
1522            f.write_str(delim);
1523            f.write_node(arg);
1524            delim = " ";
1525        }
1526    }
1527}
1528
1529impl<T: AstInfo> AstDisplay for FunctionArgs<T> {
1530    fn fmt<W: fmt::Write>(&self, f: &mut AstFormatter<W>) {
1531        match self {
1532            FunctionArgs::Star => f.write_str("*"),
1533            FunctionArgs::Args { args, order_by } => {
1534                f.write_node(&display::comma_separated(args));
1535                if !order_by.is_empty() {
1536                    f.write_str(" ORDER BY ");
1537                    f.write_node(&display::comma_separated(order_by));
1538                }
1539            }
1540        }
1541    }
1542}
1543impl_display_t!(FunctionArgs);
1544
1545#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
1546pub enum IsExprConstruct<T: AstInfo> {
1547    Null,
1548    True,
1549    False,
1550    Unknown,
1551    DistinctFrom(Box<Expr<T>>),
1552}
1553
1554impl<T: AstInfo> AstDisplay for IsExprConstruct<T> {
1555    fn fmt<W: fmt::Write>(&self, f: &mut AstFormatter<W>) {
1556        match self {
1557            IsExprConstruct::Null => f.write_str("NULL"),
1558            IsExprConstruct::True => f.write_str("TRUE"),
1559            IsExprConstruct::False => f.write_str("FALSE"),
1560            IsExprConstruct::Unknown => f.write_str("UNKNOWN"),
1561            IsExprConstruct::DistinctFrom(e) => {
1562                f.write_str("DISTINCT FROM ");
1563                e.fmt(f);
1564            }
1565        }
1566    }
1567}
1568impl_display_t!(IsExprConstruct);