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