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 mz_ore::soft_assert_eq_or_log;
24use mz_sql_lexer::keywords::*;
25
26use crate::ast::display::{self, AstDisplay, AstFormatter};
27use crate::ast::{AstInfo, Ident, OrderByExpr, Query, UnresolvedItemName, Value};
28
29/// An SQL expression of any type.
30///
31/// The parser does not distinguish between expressions of different types
32/// (e.g. boolean vs string), so the caller must handle expressions of
33/// inappropriate type, like `WHERE 1` or `SELECT 1=1`, as necessary.
34#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
35pub enum Expr<T: AstInfo> {
36    /// Identifier e.g. table name or column name
37    Identifier(Vec<Ident>),
38    /// Qualified wildcard, e.g. `alias.*` or `schema.table.*`.
39    QualifiedWildcard(Vec<Ident>),
40    /// A field access, like `(expr).foo`.
41    FieldAccess {
42        expr: Box<Expr<T>>,
43        field: Ident,
44    },
45    /// A wildcard field access, like `(expr).*`.
46    ///
47    /// Note that this is different from `QualifiedWildcard` in that the
48    /// wildcard access occurs on an arbitrary expression, rather than a
49    /// qualified name. The distinction is important for PostgreSQL
50    /// compatibility.
51    WildcardAccess(Box<Expr<T>>),
52    /// A positional parameter, e.g., `$1` or `$42`
53    Parameter(usize),
54    /// Boolean negation
55    Not {
56        expr: Box<Expr<T>>,
57    },
58    /// Boolean and
59    And {
60        left: Box<Expr<T>>,
61        right: Box<Expr<T>>,
62    },
63    /// Boolean or
64    Or {
65        left: Box<Expr<T>>,
66        right: Box<Expr<T>>,
67    },
68    /// `IS {NULL, TRUE, FALSE, UNKNOWN}` expression
69    IsExpr {
70        expr: Box<Expr<T>>,
71        construct: IsExprConstruct<T>,
72        negated: bool,
73    },
74    /// `[ NOT ] IN (val1, val2, ...)`
75    InList {
76        expr: Box<Expr<T>>,
77        list: Vec<Expr<T>>,
78        negated: bool,
79    },
80    /// `[ NOT ] IN (SELECT ...)`
81    InSubquery {
82        expr: Box<Expr<T>>,
83        subquery: Box<Query<T>>,
84        negated: bool,
85    },
86    /// `<expr> [ NOT ] {LIKE, ILIKE} <pattern> [ ESCAPE <escape> ]`
87    Like {
88        expr: Box<Expr<T>>,
89        pattern: Box<Expr<T>>,
90        escape: Option<Box<Expr<T>>>,
91        case_insensitive: bool,
92        negated: bool,
93    },
94    /// `<expr> [ NOT ] BETWEEN <low> AND <high>`
95    Between {
96        expr: Box<Expr<T>>,
97        negated: bool,
98        low: Box<Expr<T>>,
99        high: Box<Expr<T>>,
100    },
101    /// Unary or binary operator
102    Op {
103        op: Op,
104        expr1: Box<Expr<T>>,
105        expr2: Option<Box<Expr<T>>>,
106    },
107    /// CAST an expression to a different data type e.g. `CAST(foo AS VARCHAR(123))`
108    Cast {
109        expr: Box<Expr<T>>,
110        data_type: T::DataType,
111    },
112    /// `expr COLLATE collation`
113    Collate {
114        expr: Box<Expr<T>>,
115        collation: UnresolvedItemName,
116    },
117    /// `COALESCE(<expr>, ...)` or `GREATEST(<expr>, ...)` or `LEAST(<expr>`, ...)
118    ///
119    /// While COALESCE/GREATEST/LEAST have the same syntax as a function call,
120    /// their semantics are extremely unusual, and are better captured with a
121    /// dedicated AST node.
122    HomogenizingFunction {
123        function: HomogenizingFunction,
124        exprs: Vec<Expr<T>>,
125    },
126    /// NULLIF(expr, expr)
127    ///
128    /// While NULLIF has the same syntax as a function call, it is not evaluated
129    /// as a function within Postgres.
130    NullIf {
131        l_expr: Box<Expr<T>>,
132        r_expr: Box<Expr<T>>,
133    },
134    /// Nested expression e.g. `(foo > bar)` or `(1)`
135    Nested(Box<Expr<T>>),
136    /// A row constructor like `ROW(<expr>...)` or `(<expr>, <expr>...)`.
137    Row {
138        exprs: Vec<Expr<T>>,
139    },
140    /// A literal value, such as string, number, date or NULL
141    Value(Value),
142    /// Scalar function call e.g. `LEFT(foo, 5)`
143    Function(Function<T>),
144    /// `CASE [<operand>] WHEN <condition> THEN <result> ... [ELSE <result>] END`
145    ///
146    /// Note we only recognize a complete single expression as `<condition>`,
147    /// not `< 0` nor `1, 2, 3` as allowed in a `<simple when clause>` per
148    /// <https://jakewheat.github.io/sql-overview/sql-2011-foundation-grammar.html#simple-when-clause>
149    Case {
150        operand: Option<Box<Expr<T>>>,
151        conditions: Vec<Expr<T>>,
152        results: Vec<Expr<T>>,
153        else_result: Option<Box<Expr<T>>>,
154    },
155    /// An exists expression `EXISTS(SELECT ...)`, used in expressions like
156    /// `WHERE EXISTS (SELECT ...)`.
157    Exists(Box<Query<T>>),
158    /// A parenthesized subquery `(SELECT ...)`, used in expression like
159    /// `SELECT (subquery) AS x` or `WHERE (subquery) = x`
160    Subquery(Box<Query<T>>),
161    /// `<expr> <op> ANY/SOME (<query>)`
162    AnySubquery {
163        left: Box<Expr<T>>,
164        op: Op,
165        right: Box<Query<T>>,
166    },
167    /// `<expr> <op> ANY (<array_expr>)`
168    AnyExpr {
169        left: Box<Expr<T>>,
170        op: Op,
171        right: Box<Expr<T>>,
172    },
173    /// `<expr> <op> ALL (<query>)`
174    AllSubquery {
175        left: Box<Expr<T>>,
176        op: Op,
177        right: Box<Query<T>>,
178    },
179    /// `<expr> <op> ALL (<array_expr>)`
180    AllExpr {
181        left: Box<Expr<T>>,
182        op: Op,
183        right: Box<Expr<T>>,
184    },
185    /// `ARRAY[<expr>*]`
186    Array(Vec<Expr<T>>),
187    ArraySubquery(Box<Query<T>>),
188    /// `LIST[<expr>*]`
189    List(Vec<Expr<T>>),
190    ListSubquery(Box<Query<T>>),
191    /// `MAP[<expr>*]`
192    Map(Vec<MapEntry<T>>),
193    MapSubquery(Box<Query<T>>),
194    /// `<expr>([<expr>(:<expr>)?])+`
195    Subscript {
196        expr: Box<Expr<T>>,
197        positions: Vec<SubscriptPosition<T>>,
198    },
199}
200
201impl<T: AstInfo> AstDisplay for Expr<T> {
202    fn fmt<W: fmt::Write>(&self, f: &mut AstFormatter<W>) {
203        match self {
204            Expr::Identifier(s) => f.write_node(&display::separated(s, ".")),
205            Expr::QualifiedWildcard(q) => {
206                f.write_node(&display::separated(q, "."));
207                f.write_str(".*");
208            }
209            Expr::FieldAccess { expr, field } => {
210                f.write_node(expr);
211                f.write_str(".");
212                f.write_node(field);
213            }
214            Expr::WildcardAccess(expr) => {
215                f.write_node(expr);
216                f.write_str(".*");
217            }
218            Expr::Parameter(n) => f.write_str(&format!("${}", n)),
219            Expr::Not { expr } => {
220                f.write_str("NOT ");
221                f.write_node(expr);
222            }
223            Expr::And { left, right } => {
224                f.write_node(left);
225                f.write_str(" AND ");
226                f.write_node(right);
227            }
228            Expr::Or { left, right } => {
229                f.write_node(left);
230                f.write_str(" OR ");
231                f.write_node(right);
232            }
233            Expr::IsExpr {
234                expr,
235                negated,
236                construct,
237            } => {
238                f.write_node(&expr);
239                f.write_str(" IS ");
240                if *negated {
241                    f.write_str("NOT ");
242                }
243                f.write_node(construct);
244            }
245            Expr::InList {
246                expr,
247                list,
248                negated,
249            } => {
250                f.write_node(&expr);
251                f.write_str(" ");
252                if *negated {
253                    f.write_str("NOT ");
254                }
255                f.write_str("IN (");
256                f.write_node(&display::comma_separated(list));
257                f.write_str(")");
258            }
259            Expr::InSubquery {
260                expr,
261                subquery,
262                negated,
263            } => {
264                f.write_node(&expr);
265                f.write_str(" ");
266                if *negated {
267                    f.write_str("NOT ");
268                }
269                f.write_str("IN (");
270                f.write_node(&subquery);
271                f.write_str(")");
272            }
273            Expr::Like {
274                expr,
275                pattern,
276                escape,
277                case_insensitive,
278                negated,
279            } => {
280                f.write_node(&expr);
281                f.write_str(" ");
282                if *negated {
283                    f.write_str("NOT ");
284                }
285                if *case_insensitive {
286                    f.write_str("I");
287                }
288                f.write_str("LIKE ");
289                f.write_node(&pattern);
290                if let Some(escape) = escape {
291                    f.write_str(" ESCAPE ");
292                    f.write_node(escape);
293                }
294            }
295            Expr::Between {
296                expr,
297                negated,
298                low,
299                high,
300            } => {
301                f.write_node(&expr);
302                if *negated {
303                    f.write_str(" NOT");
304                }
305                f.write_str(" BETWEEN ");
306                f.write_node(&low);
307                f.write_str(" AND ");
308                f.write_node(&high);
309            }
310            Expr::Op { op, expr1, expr2 } => {
311                if let Some(expr2) = expr2 {
312                    f.write_node(&expr1);
313                    f.write_str(" ");
314                    f.write_str(op);
315                    f.write_str(" ");
316                    f.write_node(&expr2);
317                } else {
318                    f.write_str(op);
319                    f.write_str(" ");
320                    f.write_node(&expr1);
321                }
322            }
323            Expr::Cast { expr, data_type } => {
324                f.write_node(&expr);
325                f.write_str("::");
326                f.write_node(data_type);
327            }
328            Expr::Collate { expr, collation } => {
329                f.write_node(&expr);
330                f.write_str(" COLLATE ");
331                f.write_node(&collation);
332            }
333            Expr::HomogenizingFunction { function, exprs } => {
334                f.write_node(function);
335                f.write_str("(");
336                f.write_node(&display::comma_separated(exprs));
337                f.write_str(")");
338            }
339            Expr::NullIf { l_expr, r_expr } => {
340                f.write_str("NULLIF(");
341                f.write_node(&display::comma_separated(&[l_expr, r_expr]));
342                f.write_str(")");
343            }
344            Expr::Nested(ast) => {
345                f.write_str("(");
346                f.write_node(&ast);
347                f.write_str(")");
348            }
349            Expr::Row { exprs } => {
350                f.write_str("ROW(");
351                f.write_node(&display::comma_separated(exprs));
352                f.write_str(")");
353            }
354            Expr::Value(v) => {
355                f.write_node(v);
356            }
357            Expr::Function(fun) => {
358                f.write_node(fun);
359            }
360            Expr::Case {
361                operand,
362                conditions,
363                results,
364                else_result,
365            } => {
366                f.write_str("CASE");
367                if let Some(operand) = operand {
368                    f.write_str(" ");
369                    f.write_node(&operand);
370                }
371                for (c, r) in conditions.iter().zip(results) {
372                    f.write_str(" WHEN ");
373                    f.write_node(c);
374                    f.write_str(" THEN ");
375                    f.write_node(r);
376                }
377
378                if let Some(else_result) = else_result {
379                    f.write_str(" ELSE ");
380                    f.write_node(&else_result);
381                }
382                f.write_str(" END")
383            }
384            Expr::Exists(s) => {
385                f.write_str("EXISTS (");
386                f.write_node(&s);
387                f.write_str(")");
388            }
389            Expr::Subquery(s) => {
390                f.write_str("(");
391                f.write_node(&s);
392                f.write_str(")");
393            }
394            Expr::AnySubquery { left, op, right } => {
395                f.write_node(&left);
396                f.write_str(" ");
397                f.write_str(op);
398                f.write_str(" ANY (");
399                f.write_node(&right);
400                f.write_str(")");
401            }
402            Expr::AnyExpr { left, op, right } => {
403                f.write_node(&left);
404                f.write_str(" ");
405                f.write_str(op);
406                f.write_str(" ANY (");
407                f.write_node(&right);
408                f.write_str(")");
409            }
410            Expr::AllSubquery { left, op, right } => {
411                f.write_node(&left);
412                f.write_str(" ");
413                f.write_str(op);
414                f.write_str(" ALL (");
415                f.write_node(&right);
416                f.write_str(")");
417            }
418            Expr::AllExpr { left, op, right } => {
419                f.write_node(&left);
420                f.write_str(" ");
421                f.write_str(op);
422                f.write_str(" ALL (");
423                f.write_node(&right);
424                f.write_str(")");
425            }
426            Expr::Array(exprs) => {
427                f.write_str("ARRAY[");
428                f.write_node(&display::comma_separated(exprs));
429                f.write_str("]");
430            }
431            Expr::ArraySubquery(s) => {
432                f.write_str("ARRAY(");
433                f.write_node(&s);
434                f.write_str(")");
435            }
436            Expr::List(exprs) => {
437                f.write_str("LIST[");
438                f.write_node(&display::comma_separated(exprs));
439                f.write_str("]");
440            }
441            Expr::ListSubquery(s) => {
442                f.write_str("LIST(");
443                f.write_node(&s);
444                f.write_str(")");
445            }
446            Expr::Map(exprs) => {
447                f.write_str("MAP[");
448                f.write_node(&display::comma_separated(exprs));
449                f.write_str("]");
450            }
451            Expr::MapSubquery(s) => {
452                f.write_str("MAP(");
453                f.write_node(&s);
454                f.write_str(")");
455            }
456            Expr::Subscript { expr, positions } => {
457                f.write_node(&expr);
458                f.write_str("[");
459
460                let mut first = true;
461
462                for p in positions {
463                    if first {
464                        first = false
465                    } else {
466                        f.write_str("][");
467                    }
468                    f.write_node(p);
469                }
470
471                f.write_str("]");
472            }
473        }
474    }
475}
476impl_display_t!(Expr);
477
478impl<T: AstInfo> Expr<T> {
479    pub fn null() -> Expr<T> {
480        Expr::Value(Value::Null)
481    }
482
483    pub fn number<S>(n: S) -> Expr<T>
484    where
485        S: Into<String>,
486    {
487        Expr::Value(Value::Number(n.into()))
488    }
489
490    pub fn negate(self) -> Expr<T> {
491        Expr::Not {
492            expr: Box::new(self),
493        }
494    }
495
496    pub fn and(self, right: Expr<T>) -> Expr<T> {
497        Expr::And {
498            left: Box::new(self),
499            right: Box::new(right),
500        }
501    }
502
503    pub fn or(self, right: Expr<T>) -> Expr<T> {
504        Expr::Or {
505            left: Box::new(self),
506            right: Box::new(right),
507        }
508    }
509
510    pub fn binop(self, op: Op, right: Expr<T>) -> Expr<T> {
511        Expr::Op {
512            op,
513            expr1: Box::new(self),
514            expr2: Some(Box::new(right)),
515        }
516    }
517
518    pub fn lt(self, right: Expr<T>) -> Expr<T> {
519        self.binop(Op::bare("<"), right)
520    }
521
522    pub fn lt_eq(self, right: Expr<T>) -> Expr<T> {
523        self.binop(Op::bare("<="), right)
524    }
525
526    pub fn gt(self, right: Expr<T>) -> Expr<T> {
527        self.binop(Op::bare(">"), right)
528    }
529
530    pub fn gt_eq(self, right: Expr<T>) -> Expr<T> {
531        self.binop(Op::bare(">="), right)
532    }
533
534    pub fn equals(self, right: Expr<T>) -> Expr<T> {
535        self.binop(Op::bare("="), right)
536    }
537
538    pub fn not_equals(self, right: Expr<T>) -> Expr<T> {
539        self.binop(Op::bare("<>"), right)
540    }
541
542    pub fn minus(self, right: Expr<T>) -> Expr<T> {
543        self.binop(Op::bare("-"), right)
544    }
545
546    pub fn multiply(self, right: Expr<T>) -> Expr<T> {
547        self.binop(Op::bare("*"), right)
548    }
549
550    pub fn modulo(self, right: Expr<T>) -> Expr<T> {
551        self.binop(Op::bare("%"), right)
552    }
553
554    pub fn divide(self, right: Expr<T>) -> Expr<T> {
555        self.binop(Op::bare("/"), right)
556    }
557
558    pub fn cast(self, data_type: T::DataType) -> Expr<T> {
559        Expr::Cast {
560            expr: Box::new(self),
561            data_type,
562        }
563    }
564
565    pub fn call(name: T::ItemName, args: Vec<Expr<T>>) -> Expr<T> {
566        Expr::Function(Function {
567            name,
568            args: FunctionArgs::args(args),
569            filter: None,
570            over: None,
571            distinct: false,
572        })
573    }
574
575    pub fn call_nullary(name: T::ItemName) -> Expr<T> {
576        Expr::call(name, vec![])
577    }
578
579    pub fn call_unary(self, name: T::ItemName) -> Expr<T> {
580        Expr::call(name, vec![self])
581    }
582
583    pub fn take(&mut self) -> Expr<T> {
584        mem::replace(self, Expr::Identifier(vec![]))
585    }
586}
587
588/// A reference to an operator.
589#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
590pub struct Op {
591    /// Any namespaces that preceded the operator.
592    pub namespace: Option<Vec<Ident>>,
593    /// The operator itself.
594    pub op: String,
595}
596
597impl AstDisplay for Op {
598    fn fmt<W: fmt::Write>(&self, f: &mut AstFormatter<W>) {
599        if let Some(namespace) = &self.namespace {
600            f.write_str("OPERATOR(");
601            for name in namespace {
602                f.write_node(name);
603                f.write_str(".");
604            }
605            f.write_str(&self.op);
606            f.write_str(")");
607        } else {
608            f.write_str(&self.op)
609        }
610    }
611}
612impl_display!(Op);
613
614impl Op {
615    /// Constructs a new unqualified operator reference.
616    pub fn bare<S>(op: S) -> Op
617    where
618        S: Into<String>,
619    {
620        Op {
621            namespace: None,
622            op: op.into(),
623        }
624    }
625}
626
627#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
628pub enum HomogenizingFunction {
629    Coalesce,
630    Greatest,
631    Least,
632}
633
634impl AstDisplay for HomogenizingFunction {
635    fn fmt<W: fmt::Write>(&self, f: &mut AstFormatter<W>) {
636        match self {
637            HomogenizingFunction::Coalesce => f.write_str("COALESCE"),
638            HomogenizingFunction::Greatest => f.write_str("GREATEST"),
639            HomogenizingFunction::Least => f.write_str("LEAST"),
640        }
641    }
642}
643impl_display!(HomogenizingFunction);
644
645#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
646pub struct MapEntry<T: AstInfo> {
647    pub key: Expr<T>,
648    pub value: Expr<T>,
649}
650
651impl<T: AstInfo> AstDisplay for MapEntry<T> {
652    fn fmt<W: fmt::Write>(&self, f: &mut AstFormatter<W>) {
653        f.write_node(&self.key);
654        f.write_str(" => ");
655        f.write_node(&self.value);
656    }
657}
658impl_display_t!(MapEntry);
659
660#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
661pub struct SubscriptPosition<T: AstInfo> {
662    pub start: Option<Expr<T>>,
663    pub end: Option<Expr<T>>,
664    // i.e. did this subscript include a colon
665    pub explicit_slice: bool,
666}
667
668impl<T: AstInfo> AstDisplay for SubscriptPosition<T> {
669    fn fmt<W: fmt::Write>(&self, f: &mut AstFormatter<W>) {
670        if let Some(start) = &self.start {
671            f.write_node(start);
672        }
673        if self.explicit_slice {
674            f.write_str(":");
675            if let Some(end) = &self.end {
676                f.write_node(end);
677            }
678        }
679    }
680}
681impl_display_t!(SubscriptPosition);
682
683/// A window specification (i.e. `OVER (PARTITION BY .. ORDER BY .. etc.)`)
684/// Includes potential IGNORE NULLS or RESPECT NULLS from before the OVER clause.
685#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
686pub struct WindowSpec<T: AstInfo> {
687    pub partition_by: Vec<Expr<T>>,
688    pub order_by: Vec<OrderByExpr<T>>,
689    pub window_frame: Option<WindowFrame>,
690    // Note that IGNORE NULLS and RESPECT NULLS are mutually exclusive. We validate that not both
691    // are present during HIR planning.
692    pub ignore_nulls: bool,
693    pub respect_nulls: bool,
694}
695
696impl<T: AstInfo> AstDisplay for WindowSpec<T> {
697    fn fmt<W: fmt::Write>(&self, f: &mut AstFormatter<W>) {
698        if self.ignore_nulls {
699            f.write_str(" IGNORE NULLS");
700        }
701        if self.respect_nulls {
702            f.write_str(" RESPECT NULLS");
703        }
704        f.write_str(" OVER (");
705        let mut delim = "";
706        if !self.partition_by.is_empty() {
707            delim = " ";
708            f.write_str("PARTITION BY ");
709            f.write_node(&display::comma_separated(&self.partition_by));
710        }
711        if !self.order_by.is_empty() {
712            f.write_str(delim);
713            delim = " ";
714            f.write_str("ORDER BY ");
715            f.write_node(&display::comma_separated(&self.order_by));
716        }
717        if let Some(window_frame) = &self.window_frame {
718            if let Some(end_bound) = &window_frame.end_bound {
719                f.write_str(delim);
720                f.write_node(&window_frame.units);
721                f.write_str(" BETWEEN ");
722                f.write_node(&window_frame.start_bound);
723                f.write_str(" AND ");
724                f.write_node(&*end_bound);
725            } else {
726                f.write_str(delim);
727                f.write_node(&window_frame.units);
728                f.write_str(" ");
729                f.write_node(&window_frame.start_bound);
730            }
731        }
732        f.write_str(")");
733    }
734}
735impl_display_t!(WindowSpec);
736
737/// Specifies the data processed by a window function, e.g.
738/// `RANGE UNBOUNDED PRECEDING` or `ROWS BETWEEN 5 PRECEDING AND CURRENT ROW`.
739///
740/// Note: The parser does not validate the specified bounds; the caller should
741/// reject invalid bounds like `ROWS UNBOUNDED FOLLOWING` before execution.
742#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
743pub struct WindowFrame {
744    pub units: WindowFrameUnits,
745    pub start_bound: WindowFrameBound,
746    /// The right bound of the `BETWEEN .. AND` clause. The end bound of `None`
747    /// indicates the shorthand form (e.g. `ROWS 1 PRECEDING`), which must
748    /// behave the same as `end_bound = WindowFrameBound::CurrentRow`.
749    pub end_bound: Option<WindowFrameBound>,
750    // TBD: EXCLUDE
751}
752
753#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
754pub enum WindowFrameUnits {
755    Rows,
756    Range,
757    Groups,
758}
759
760impl AstDisplay for WindowFrameUnits {
761    fn fmt<W: fmt::Write>(&self, f: &mut AstFormatter<W>) {
762        f.write_str(match self {
763            WindowFrameUnits::Rows => "ROWS",
764            WindowFrameUnits::Range => "RANGE",
765            WindowFrameUnits::Groups => "GROUPS",
766        })
767    }
768}
769impl_display!(WindowFrameUnits);
770
771/// Specifies [WindowFrame]'s `start_bound` and `end_bound`
772#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
773pub enum WindowFrameBound {
774    /// `CURRENT ROW`
775    CurrentRow,
776    /// `<N> PRECEDING` or `UNBOUNDED PRECEDING`
777    Preceding(Option<u64>),
778    /// `<N> FOLLOWING` or `UNBOUNDED FOLLOWING`.
779    Following(Option<u64>),
780}
781
782impl AstDisplay for WindowFrameBound {
783    fn fmt<W: fmt::Write>(&self, f: &mut AstFormatter<W>) {
784        match self {
785            WindowFrameBound::CurrentRow => f.write_str("CURRENT ROW"),
786            WindowFrameBound::Preceding(None) => f.write_str("UNBOUNDED PRECEDING"),
787            WindowFrameBound::Following(None) => f.write_str("UNBOUNDED FOLLOWING"),
788            WindowFrameBound::Preceding(Some(n)) => {
789                f.write_str(n);
790                f.write_str(" PRECEDING");
791            }
792            WindowFrameBound::Following(Some(n)) => {
793                f.write_str(n);
794                f.write_str(" FOLLOWING");
795            }
796        }
797    }
798}
799impl_display!(WindowFrameBound);
800
801/// A function call
802#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
803pub struct Function<T: AstInfo> {
804    pub name: T::ItemName,
805    pub args: FunctionArgs<T>,
806    // aggregate functions may specify e.g. `COUNT(DISTINCT X) FILTER (WHERE ...)`
807    pub filter: Option<Box<Expr<T>>>,
808    pub over: Option<WindowSpec<T>>,
809    // aggregate functions may specify eg `COUNT(DISTINCT x)`
810    pub distinct: bool,
811}
812
813impl<T: AstInfo> AstDisplay for Function<T> {
814    fn fmt<W: fmt::Write>(&self, f: &mut AstFormatter<W>) {
815        // This block handles printing function calls that have special parsing. In stable mode, the
816        // name is quoted and so won't get the special parsing. We only need to print the special
817        // formats in non-stable mode.
818        if !f.stable() {
819            let special: Option<(&str, &[Option<Keyword>])> =
820                match self.name.to_ast_string_stable().as_str() {
821                    r#""extract""# if self.args.len() == Some(2) => {
822                        Some(("extract", &[None, Some(FROM)]))
823                    }
824                    r#""position""# if self.args.len() == Some(2) => {
825                        Some(("position", &[None, Some(IN)]))
826                    }
827
828                    // "trim" doesn't need to appear here because it changes the function name (to
829                    // "btrim", "ltrim", or "rtrim"), but only "trim" is parsed specially. "substring"
830                    // supports comma-delimited arguments, so doesn't need to be here.
831                    _ => None,
832                };
833            if let Some((name, kws)) = special {
834                f.write_str(name);
835                f.write_str("(");
836                self.args.intersperse_function_argument_keywords(f, kws);
837                f.write_str(")");
838                return;
839            }
840        }
841
842        f.write_node(&self.name);
843        f.write_str("(");
844        if self.distinct {
845            f.write_str("DISTINCT ")
846        }
847        f.write_node(&self.args);
848        f.write_str(")");
849        if let Some(filter) = &self.filter {
850            f.write_str(" FILTER (WHERE ");
851            f.write_node(&filter);
852            f.write_str(")");
853        }
854        if let Some(o) = &self.over {
855            f.write_node(o);
856        }
857    }
858}
859impl_display_t!(Function);
860
861/// Arguments for a function call.
862#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
863pub enum FunctionArgs<T: AstInfo> {
864    /// The special star argument, as in `count(*)`.
865    Star,
866    /// A normal list of arguments.
867    Args {
868        args: Vec<Expr<T>>,
869        order_by: Vec<OrderByExpr<T>>,
870    },
871}
872
873impl<T: AstInfo> FunctionArgs<T> {
874    pub fn args(args: Vec<Expr<T>>) -> Self {
875        Self::Args {
876            args,
877            order_by: vec![],
878        }
879    }
880
881    /// Returns the number of arguments. Star (`*`) is None.
882    pub fn len(&self) -> Option<usize> {
883        match self {
884            FunctionArgs::Star => None,
885            FunctionArgs::Args { args, .. } => Some(args.len()),
886        }
887    }
888
889    /// Prints associated keywords before each argument
890    fn intersperse_function_argument_keywords<W: fmt::Write>(
891        &self,
892        f: &mut AstFormatter<W>,
893        kws: &[Option<Keyword>],
894    ) {
895        let args = match self {
896            FunctionArgs::Star => unreachable!(),
897            FunctionArgs::Args { args, .. } => args,
898        };
899        soft_assert_eq_or_log!(args.len(), kws.len());
900        let mut delim = "";
901        for (arg, kw) in args.iter().zip(kws) {
902            if let Some(kw) = kw {
903                f.write_str(delim);
904                f.write_str(kw.as_str());
905                delim = " ";
906            }
907            f.write_str(delim);
908            f.write_node(arg);
909            delim = " ";
910        }
911    }
912}
913
914impl<T: AstInfo> AstDisplay for FunctionArgs<T> {
915    fn fmt<W: fmt::Write>(&self, f: &mut AstFormatter<W>) {
916        match self {
917            FunctionArgs::Star => f.write_str("*"),
918            FunctionArgs::Args { args, order_by } => {
919                f.write_node(&display::comma_separated(args));
920                if !order_by.is_empty() {
921                    f.write_str(" ORDER BY ");
922                    f.write_node(&display::comma_separated(order_by));
923                }
924            }
925        }
926    }
927}
928impl_display_t!(FunctionArgs);
929
930#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
931pub enum IsExprConstruct<T: AstInfo> {
932    Null,
933    True,
934    False,
935    Unknown,
936    DistinctFrom(Box<Expr<T>>),
937}
938
939impl<T: AstInfo> AstDisplay for IsExprConstruct<T> {
940    fn fmt<W: fmt::Write>(&self, f: &mut AstFormatter<W>) {
941        match self {
942            IsExprConstruct::Null => f.write_str("NULL"),
943            IsExprConstruct::True => f.write_str("TRUE"),
944            IsExprConstruct::False => f.write_str("FALSE"),
945            IsExprConstruct::Unknown => f.write_str("UNKNOWN"),
946            IsExprConstruct::DistinctFrom(e) => {
947                f.write_str("DISTINCT FROM ");
948                e.fmt(f);
949            }
950        }
951    }
952}
953impl_display_t!(IsExprConstruct);