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