sqltk_parser/ast/
query.rs

1// Licensed to the Apache Software Foundation (ASF) under one
2// or more contributor license agreements.  See the NOTICE file
3// distributed with this work for additional information
4// regarding copyright ownership.  The ASF licenses this file
5// to you under the Apache License, Version 2.0 (the
6// "License"); you may not use this file except in compliance
7// with the License.  You may obtain a copy of the License at
8//
9//   http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing,
12// software distributed under the License is distributed on an
13// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14// KIND, either express or implied.  See the License for the
15// specific language governing permissions and limitations
16// under the License.
17
18#[cfg(not(feature = "std"))]
19use alloc::{boxed::Box, vec::Vec};
20
21use helpers::attached_token::AttachedToken;
22#[cfg(feature = "serde")]
23use serde::{Deserialize, Serialize};
24
25#[cfg(feature = "visitor")]
26use sqltk_parser_derive::{Visit, VisitMut};
27
28use crate::{
29    ast::*,
30    tokenizer::{Token, TokenWithSpan},
31};
32
33/// The most complete variant of a `SELECT` query expression, optionally
34/// including `WITH`, `UNION` / other set operations, and `ORDER BY`.
35#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
36#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
37#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
38#[cfg_attr(feature = "visitor", visit(with = "visit_query"))]
39pub struct Query {
40    /// WITH (common table expressions, or CTEs)
41    pub with: Option<With>,
42    /// SELECT or UNION / EXCEPT / INTERSECT
43    pub body: Box<SetExpr>,
44    /// ORDER BY
45    pub order_by: Option<OrderBy>,
46    /// `LIMIT ... OFFSET ... | LIMIT <offset>, <limit>`
47    pub limit_clause: Option<LimitClause>,
48    /// `FETCH { FIRST | NEXT } <N> [ PERCENT ] { ROW | ROWS } | { ONLY | WITH TIES }`
49    pub fetch: Option<Fetch>,
50    /// `FOR { UPDATE | SHARE } [ OF table_name ] [ SKIP LOCKED | NOWAIT ]`
51    pub locks: Vec<LockClause>,
52    /// `FOR XML { RAW | AUTO | EXPLICIT | PATH } [ , ELEMENTS ]`
53    /// `FOR JSON { AUTO | PATH } [ , INCLUDE_NULL_VALUES ]`
54    /// (MSSQL-specific)
55    pub for_clause: Option<ForClause>,
56    /// ClickHouse syntax: `SELECT * FROM t SETTINGS key1 = value1, key2 = value2`
57    ///
58    /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/select#settings-in-select-query)
59    pub settings: Option<Vec<Setting>>,
60    /// `SELECT * FROM t FORMAT JSONCompact`
61    ///
62    /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/select/format)
63    /// (ClickHouse-specific)
64    pub format_clause: Option<FormatClause>,
65
66    /// Pipe operator
67    pub pipe_operators: Vec<PipeOperator>,
68}
69
70impl fmt::Display for Query {
71    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
72        if let Some(ref with) = self.with {
73            write!(f, "{with} ")?;
74        }
75        write!(f, "{}", self.body)?;
76        if let Some(ref order_by) = self.order_by {
77            write!(f, " {order_by}")?;
78        }
79
80        if let Some(ref limit_clause) = self.limit_clause {
81            limit_clause.fmt(f)?;
82        }
83        if let Some(ref settings) = self.settings {
84            write!(f, " SETTINGS {}", display_comma_separated(settings))?;
85        }
86        if let Some(ref fetch) = self.fetch {
87            write!(f, " {fetch}")?;
88        }
89        if !self.locks.is_empty() {
90            write!(f, " {}", display_separated(&self.locks, " "))?;
91        }
92        if let Some(ref for_clause) = self.for_clause {
93            write!(f, " {}", for_clause)?;
94        }
95        if let Some(ref format) = self.format_clause {
96            write!(f, " {}", format)?;
97        }
98        for pipe_operator in &self.pipe_operators {
99            write!(f, " |> {}", pipe_operator)?;
100        }
101        Ok(())
102    }
103}
104
105/// Query syntax for ClickHouse ADD PROJECTION statement.
106/// Its syntax is similar to SELECT statement, but it is used to add a new projection to a table.
107/// Syntax is `SELECT <COLUMN LIST EXPR> [GROUP BY] [ORDER BY]`
108///
109/// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/alter/projection#add-projection)
110#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
111#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
112#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
113pub struct ProjectionSelect {
114    pub projection: Vec<SelectItem>,
115    pub order_by: Option<OrderBy>,
116    pub group_by: Option<GroupByExpr>,
117}
118
119impl fmt::Display for ProjectionSelect {
120    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
121        write!(f, "SELECT {}", display_comma_separated(&self.projection))?;
122        if let Some(ref group_by) = self.group_by {
123            write!(f, " {group_by}")?;
124        }
125        if let Some(ref order_by) = self.order_by {
126            write!(f, " {order_by}")?;
127        }
128        Ok(())
129    }
130}
131
132/// A node in a tree, representing a "query body" expression, roughly:
133/// `SELECT ... [ {UNION|EXCEPT|INTERSECT} SELECT ...]`
134#[allow(clippy::large_enum_variant)]
135#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
136#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
137#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
138pub enum SetExpr {
139    /// Restricted SELECT .. FROM .. HAVING (no ORDER BY or set operations)
140    Select(Box<Select>),
141    /// Parenthesized SELECT subquery, which may include more set operations
142    /// in its body and an optional ORDER BY / LIMIT.
143    Query(Box<Query>),
144    /// UNION/EXCEPT/INTERSECT of two queries
145    SetOperation {
146        op: SetOperator,
147        set_quantifier: SetQuantifier,
148        left: Box<SetExpr>,
149        right: Box<SetExpr>,
150    },
151    Values(Values),
152    Insert(Statement),
153    Update(Statement),
154    Delete(Statement),
155    Table(Box<Table>),
156}
157
158impl SetExpr {
159    /// If this `SetExpr` is a `SELECT`, returns the [`Select`].
160    pub fn as_select(&self) -> Option<&Select> {
161        if let Self::Select(select) = self {
162            Some(&**select)
163        } else {
164            None
165        }
166    }
167}
168
169impl fmt::Display for SetExpr {
170    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
171        match self {
172            SetExpr::Select(s) => write!(f, "{s}"),
173            SetExpr::Query(q) => write!(f, "({q})"),
174            SetExpr::Values(v) => write!(f, "{v}"),
175            SetExpr::Insert(v) => write!(f, "{v}"),
176            SetExpr::Update(v) => write!(f, "{v}"),
177            SetExpr::Delete(v) => write!(f, "{v}"),
178            SetExpr::Table(t) => write!(f, "{t}"),
179            SetExpr::SetOperation {
180                left,
181                right,
182                op,
183                set_quantifier,
184            } => {
185                write!(f, "{left} {op}")?;
186                match set_quantifier {
187                    SetQuantifier::All
188                    | SetQuantifier::Distinct
189                    | SetQuantifier::ByName
190                    | SetQuantifier::AllByName
191                    | SetQuantifier::DistinctByName => write!(f, " {set_quantifier}")?,
192                    SetQuantifier::None => write!(f, "{set_quantifier}")?,
193                }
194                write!(f, " {right}")?;
195                Ok(())
196            }
197        }
198    }
199}
200
201#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
202#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
203#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
204pub enum SetOperator {
205    Union,
206    Except,
207    Intersect,
208    Minus,
209}
210
211impl fmt::Display for SetOperator {
212    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
213        f.write_str(match self {
214            SetOperator::Union => "UNION",
215            SetOperator::Except => "EXCEPT",
216            SetOperator::Intersect => "INTERSECT",
217            SetOperator::Minus => "MINUS",
218        })
219    }
220}
221
222/// A quantifier for [SetOperator].
223// TODO: Restrict parsing specific SetQuantifier in some specific dialects.
224// For example, BigQuery does not support `DISTINCT` for `EXCEPT` and `INTERSECT`
225#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
226#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
227#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
228pub enum SetQuantifier {
229    All,
230    Distinct,
231    ByName,
232    AllByName,
233    DistinctByName,
234    None,
235}
236
237impl fmt::Display for SetQuantifier {
238    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
239        match self {
240            SetQuantifier::All => write!(f, "ALL"),
241            SetQuantifier::Distinct => write!(f, "DISTINCT"),
242            SetQuantifier::ByName => write!(f, "BY NAME"),
243            SetQuantifier::AllByName => write!(f, "ALL BY NAME"),
244            SetQuantifier::DistinctByName => write!(f, "DISTINCT BY NAME"),
245            SetQuantifier::None => write!(f, ""),
246        }
247    }
248}
249
250#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
251#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
252/// A [`TABLE` command]( https://www.postgresql.org/docs/current/sql-select.html#SQL-TABLE)
253#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
254pub struct Table {
255    pub table_name: Option<String>,
256    pub schema_name: Option<String>,
257}
258
259impl fmt::Display for Table {
260    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
261        if let Some(ref schema_name) = self.schema_name {
262            write!(
263                f,
264                "TABLE {}.{}",
265                schema_name,
266                self.table_name.as_ref().unwrap(),
267            )?;
268        } else {
269            write!(f, "TABLE {}", self.table_name.as_ref().unwrap(),)?;
270        }
271        Ok(())
272    }
273}
274
275/// What did this select look like?
276#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
277#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
278#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
279pub enum SelectFlavor {
280    /// `SELECT *`
281    Standard,
282    /// `FROM ... SELECT *`
283    FromFirst,
284    /// `FROM *`
285    FromFirstNoSelect,
286}
287
288/// A restricted variant of `SELECT` (without CTEs/`ORDER BY`), which may
289/// appear either as the only body item of a `Query`, or as an operand
290/// to a set operation like `UNION`.
291#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
292#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
293#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
294pub struct Select {
295    /// Token for the `SELECT` keyword
296    pub select_token: AttachedToken,
297    /// `SELECT [DISTINCT] ...`
298    pub distinct: Option<Distinct>,
299    /// MSSQL syntax: `TOP (<N>) [ PERCENT ] [ WITH TIES ]`
300    pub top: Option<Top>,
301    /// Whether the top was located before `ALL`/`DISTINCT`
302    pub top_before_distinct: bool,
303    /// projection expressions
304    pub projection: Vec<SelectItem>,
305    /// INTO
306    pub into: Option<SelectInto>,
307    /// FROM
308    pub from: Vec<TableWithJoins>,
309    /// LATERAL VIEWs
310    pub lateral_views: Vec<LateralView>,
311    /// ClickHouse syntax: `PREWHERE a = 1 WHERE b = 2`,
312    /// and it can be used together with WHERE selection.
313    ///
314    /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/select/prewhere)
315    pub prewhere: Option<Expr>,
316    /// WHERE
317    pub selection: Option<Expr>,
318    /// GROUP BY
319    pub group_by: GroupByExpr,
320    /// CLUSTER BY (Hive)
321    pub cluster_by: Vec<Expr>,
322    /// DISTRIBUTE BY (Hive)
323    pub distribute_by: Vec<Expr>,
324    /// SORT BY (Hive)
325    pub sort_by: Vec<Expr>,
326    /// HAVING
327    pub having: Option<Expr>,
328    /// WINDOW AS
329    pub named_window: Vec<NamedWindowDefinition>,
330    /// QUALIFY (Snowflake)
331    pub qualify: Option<Expr>,
332    /// The positioning of QUALIFY and WINDOW clauses differ between dialects.
333    /// e.g. BigQuery requires that WINDOW comes after QUALIFY, while DUCKDB accepts
334    /// WINDOW before QUALIFY.
335    /// We accept either positioning and flag the accepted variant.
336    pub window_before_qualify: bool,
337    /// BigQuery syntax: `SELECT AS VALUE | SELECT AS STRUCT`
338    pub value_table_mode: Option<ValueTableMode>,
339    /// STARTING WITH .. CONNECT BY
340    pub connect_by: Option<ConnectBy>,
341    /// Was this a FROM-first query?
342    pub flavor: SelectFlavor,
343}
344
345impl fmt::Display for Select {
346    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
347        match self.flavor {
348            SelectFlavor::Standard => {
349                write!(f, "SELECT")?;
350            }
351            SelectFlavor::FromFirst => {
352                write!(f, "FROM {} SELECT", display_comma_separated(&self.from))?;
353            }
354            SelectFlavor::FromFirstNoSelect => {
355                write!(f, "FROM {}", display_comma_separated(&self.from))?;
356            }
357        }
358
359        if let Some(value_table_mode) = self.value_table_mode {
360            write!(f, " {value_table_mode}")?;
361        }
362
363        if let Some(ref top) = self.top {
364            if self.top_before_distinct {
365                write!(f, " {top}")?;
366            }
367        }
368        if let Some(ref distinct) = self.distinct {
369            write!(f, " {distinct}")?;
370        }
371        if let Some(ref top) = self.top {
372            if !self.top_before_distinct {
373                write!(f, " {top}")?;
374            }
375        }
376
377        if !self.projection.is_empty() {
378            write!(f, " {}", display_comma_separated(&self.projection))?;
379        }
380
381        if let Some(ref into) = self.into {
382            write!(f, " {into}")?;
383        }
384
385        if self.flavor == SelectFlavor::Standard && !self.from.is_empty() {
386            write!(f, " FROM {}", display_comma_separated(&self.from))?;
387        }
388        if !self.lateral_views.is_empty() {
389            for lv in &self.lateral_views {
390                write!(f, "{lv}")?;
391            }
392        }
393        if let Some(ref prewhere) = self.prewhere {
394            write!(f, " PREWHERE {prewhere}")?;
395        }
396        if let Some(ref selection) = self.selection {
397            write!(f, " WHERE {selection}")?;
398        }
399        match &self.group_by {
400            GroupByExpr::All(_) => write!(f, " {}", self.group_by)?,
401            GroupByExpr::Expressions(exprs, _) => {
402                if !exprs.is_empty() {
403                    write!(f, " {}", self.group_by)?
404                }
405            }
406        }
407        if !self.cluster_by.is_empty() {
408            write!(
409                f,
410                " CLUSTER BY {}",
411                display_comma_separated(&self.cluster_by)
412            )?;
413        }
414        if !self.distribute_by.is_empty() {
415            write!(
416                f,
417                " DISTRIBUTE BY {}",
418                display_comma_separated(&self.distribute_by)
419            )?;
420        }
421        if !self.sort_by.is_empty() {
422            write!(f, " SORT BY {}", display_comma_separated(&self.sort_by))?;
423        }
424        if let Some(ref having) = self.having {
425            write!(f, " HAVING {having}")?;
426        }
427        if self.window_before_qualify {
428            if !self.named_window.is_empty() {
429                write!(f, " WINDOW {}", display_comma_separated(&self.named_window))?;
430            }
431            if let Some(ref qualify) = self.qualify {
432                write!(f, " QUALIFY {qualify}")?;
433            }
434        } else {
435            if let Some(ref qualify) = self.qualify {
436                write!(f, " QUALIFY {qualify}")?;
437            }
438            if !self.named_window.is_empty() {
439                write!(f, " WINDOW {}", display_comma_separated(&self.named_window))?;
440            }
441        }
442        if let Some(ref connect_by) = self.connect_by {
443            write!(f, " {connect_by}")?;
444        }
445        Ok(())
446    }
447}
448
449/// A hive LATERAL VIEW with potential column aliases
450#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
451#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
452#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
453pub struct LateralView {
454    /// LATERAL VIEW
455    pub lateral_view: Expr,
456    /// LATERAL VIEW table name
457    pub lateral_view_name: ObjectName,
458    /// LATERAL VIEW optional column aliases
459    pub lateral_col_alias: Vec<Ident>,
460    /// LATERAL VIEW OUTER
461    pub outer: bool,
462}
463
464impl fmt::Display for LateralView {
465    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
466        write!(
467            f,
468            " LATERAL VIEW{outer} {} {}",
469            self.lateral_view,
470            self.lateral_view_name,
471            outer = if self.outer { " OUTER" } else { "" }
472        )?;
473        if !self.lateral_col_alias.is_empty() {
474            write!(
475                f,
476                " AS {}",
477                display_comma_separated(&self.lateral_col_alias)
478            )?;
479        }
480        Ok(())
481    }
482}
483
484/// An expression used in a named window declaration.
485///
486/// ```sql
487/// WINDOW mywindow AS [named_window_expr]
488/// ```
489#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
490#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
491#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
492pub enum NamedWindowExpr {
493    /// A direct reference to another named window definition.
494    /// [BigQuery]
495    ///
496    /// Example:
497    /// ```sql
498    /// WINDOW mywindow AS prev_window
499    /// ```
500    ///
501    /// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/window-function-calls#ref_named_window
502    NamedWindow(Ident),
503    /// A window expression.
504    ///
505    /// Example:
506    /// ```sql
507    /// WINDOW mywindow AS (ORDER BY 1)
508    /// ```
509    WindowSpec(WindowSpec),
510}
511
512impl fmt::Display for NamedWindowExpr {
513    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
514        match self {
515            NamedWindowExpr::NamedWindow(named_window) => {
516                write!(f, "{named_window}")?;
517            }
518            NamedWindowExpr::WindowSpec(window_spec) => {
519                write!(f, "({window_spec})")?;
520            }
521        };
522        Ok(())
523    }
524}
525
526#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
527#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
528#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
529pub struct NamedWindowDefinition(pub Ident, pub NamedWindowExpr);
530
531impl fmt::Display for NamedWindowDefinition {
532    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
533        write!(f, "{} AS {}", self.0, self.1)
534    }
535}
536
537#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
538#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
539#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
540pub struct With {
541    /// Token for the "WITH" keyword
542    pub with_token: AttachedToken,
543    pub recursive: bool,
544    pub cte_tables: Vec<Cte>,
545}
546
547impl fmt::Display for With {
548    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
549        write!(
550            f,
551            "WITH {}{}",
552            if self.recursive { "RECURSIVE " } else { "" },
553            display_comma_separated(&self.cte_tables)
554        )
555    }
556}
557
558#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
559#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
560#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
561pub enum CteAsMaterialized {
562    /// The `WITH` statement specifies `AS MATERIALIZED` behavior
563    Materialized,
564    /// The `WITH` statement specifies `AS NOT MATERIALIZED` behavior
565    NotMaterialized,
566}
567
568impl fmt::Display for CteAsMaterialized {
569    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
570        match *self {
571            CteAsMaterialized::Materialized => {
572                write!(f, "MATERIALIZED")?;
573            }
574            CteAsMaterialized::NotMaterialized => {
575                write!(f, "NOT MATERIALIZED")?;
576            }
577        };
578        Ok(())
579    }
580}
581
582/// A single CTE (used after `WITH`): `<alias> [(col1, col2, ...)] AS <materialized> ( <query> )`
583/// The names in the column list before `AS`, when specified, replace the names
584/// of the columns returned by the query. The parser does not validate that the
585/// number of columns in the query matches the number of columns in the query.
586#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
587#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
588#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
589pub struct Cte {
590    pub alias: TableAlias,
591    pub query: Box<Query>,
592    pub from: Option<Ident>,
593    pub materialized: Option<CteAsMaterialized>,
594    /// Token for the closing parenthesis
595    pub closing_paren_token: AttachedToken,
596}
597
598impl fmt::Display for Cte {
599    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
600        match self.materialized.as_ref() {
601            None => write!(f, "{} AS ({})", self.alias, self.query)?,
602            Some(materialized) => write!(f, "{} AS {materialized} ({})", self.alias, self.query)?,
603        };
604        if let Some(ref fr) = self.from {
605            write!(f, " FROM {fr}")?;
606        }
607        Ok(())
608    }
609}
610
611/// Represents an expression behind a wildcard expansion in a projection.
612/// `SELECT T.* FROM T;
613#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
614#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
615#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
616pub enum SelectItemQualifiedWildcardKind {
617    /// Expression is an object name.
618    /// e.g. `alias.*` or even `schema.table.*`
619    ObjectName(ObjectName),
620    /// Select star on an arbitrary expression.
621    /// e.g. `STRUCT<STRING>('foo').*`
622    Expr(Expr),
623}
624
625/// One item of the comma-separated list following `SELECT`
626#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
627#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
628#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
629pub enum SelectItem {
630    /// Any expression, not followed by `[ AS ] alias`
631    UnnamedExpr(Expr),
632    /// An expression, followed by `[ AS ] alias`
633    ExprWithAlias { expr: Expr, alias: Ident },
634    /// An expression, followed by a wildcard expansion.
635    /// e.g. `alias.*`, `STRUCT<STRING>('foo').*`
636    QualifiedWildcard(SelectItemQualifiedWildcardKind, WildcardAdditionalOptions),
637    /// An unqualified `*`
638    Wildcard(WildcardAdditionalOptions),
639}
640
641impl fmt::Display for SelectItemQualifiedWildcardKind {
642    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
643        match &self {
644            SelectItemQualifiedWildcardKind::ObjectName(object_name) => {
645                write!(f, "{object_name}.*")
646            }
647            SelectItemQualifiedWildcardKind::Expr(expr) => write!(f, "{expr}.*"),
648        }
649    }
650}
651
652/// Single aliased identifier
653///
654/// # Syntax
655/// ```plaintext
656/// <ident> AS <alias>
657/// ```
658#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
659#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
660#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
661pub struct IdentWithAlias {
662    pub ident: Ident,
663    pub alias: Ident,
664}
665
666impl fmt::Display for IdentWithAlias {
667    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
668        write!(f, "{} AS {}", self.ident, self.alias)
669    }
670}
671
672/// Additional options for wildcards, e.g. Snowflake `EXCLUDE`/`RENAME` and Bigquery `EXCEPT`.
673#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
674#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
675#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
676pub struct WildcardAdditionalOptions {
677    /// The wildcard token `*`
678    pub wildcard_token: AttachedToken,
679    /// `[ILIKE...]`.
680    ///  Snowflake syntax: <https://docs.snowflake.com/en/sql-reference/sql/select#parameters>
681    pub opt_ilike: Option<IlikeSelectItem>,
682    /// `[EXCLUDE...]`.
683    pub opt_exclude: Option<ExcludeSelectItem>,
684    /// `[EXCEPT...]`.
685    ///  Clickhouse syntax: <https://clickhouse.com/docs/en/sql-reference/statements/select#except>
686    pub opt_except: Option<ExceptSelectItem>,
687    /// `[REPLACE]`
688    ///  BigQuery syntax: <https://cloud.google.com/bigquery/docs/reference/standard-sql/query-syntax#select_replace>
689    ///  Clickhouse syntax: <https://clickhouse.com/docs/en/sql-reference/statements/select#replace>
690    ///  Snowflake syntax: <https://docs.snowflake.com/en/sql-reference/sql/select#parameters>
691    pub opt_replace: Option<ReplaceSelectItem>,
692    /// `[RENAME ...]`.
693    pub opt_rename: Option<RenameSelectItem>,
694}
695
696impl Default for WildcardAdditionalOptions {
697    fn default() -> Self {
698        Self {
699            wildcard_token: TokenWithSpan::wrap(Token::Mul).into(),
700            opt_ilike: None,
701            opt_exclude: None,
702            opt_except: None,
703            opt_replace: None,
704            opt_rename: None,
705        }
706    }
707}
708
709impl fmt::Display for WildcardAdditionalOptions {
710    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
711        if let Some(ilike) = &self.opt_ilike {
712            write!(f, " {ilike}")?;
713        }
714        if let Some(exclude) = &self.opt_exclude {
715            write!(f, " {exclude}")?;
716        }
717        if let Some(except) = &self.opt_except {
718            write!(f, " {except}")?;
719        }
720        if let Some(replace) = &self.opt_replace {
721            write!(f, " {replace}")?;
722        }
723        if let Some(rename) = &self.opt_rename {
724            write!(f, " {rename}")?;
725        }
726        Ok(())
727    }
728}
729
730/// Snowflake `ILIKE` information.
731///
732/// # Syntax
733/// ```plaintext
734/// ILIKE <value>
735/// ```
736#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
737#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
738#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
739pub struct IlikeSelectItem {
740    pub pattern: String,
741}
742
743impl fmt::Display for IlikeSelectItem {
744    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
745        write!(
746            f,
747            "ILIKE '{}'",
748            value::escape_single_quote_string(&self.pattern)
749        )?;
750        Ok(())
751    }
752}
753/// Snowflake `EXCLUDE` information.
754///
755/// # Syntax
756/// ```plaintext
757/// <col_name>
758/// | (<col_name>, <col_name>, ...)
759/// ```
760#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
761#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
762#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
763pub enum ExcludeSelectItem {
764    /// Single column name without parenthesis.
765    ///
766    /// # Syntax
767    /// ```plaintext
768    /// <col_name>
769    /// ```
770    Single(Ident),
771    /// Multiple column names inside parenthesis.
772    /// # Syntax
773    /// ```plaintext
774    /// (<col_name>, <col_name>, ...)
775    /// ```
776    Multiple(Vec<Ident>),
777}
778
779impl fmt::Display for ExcludeSelectItem {
780    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
781        write!(f, "EXCLUDE")?;
782        match self {
783            Self::Single(column) => {
784                write!(f, " {column}")?;
785            }
786            Self::Multiple(columns) => {
787                write!(f, " ({})", display_comma_separated(columns))?;
788            }
789        }
790        Ok(())
791    }
792}
793
794/// Snowflake `RENAME` information.
795///
796/// # Syntax
797/// ```plaintext
798/// <col_name> AS <col_alias>
799/// | (<col_name> AS <col_alias>, <col_name> AS <col_alias>, ...)
800/// ```
801#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
802#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
803#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
804pub enum RenameSelectItem {
805    /// Single column name with alias without parenthesis.
806    ///
807    /// # Syntax
808    /// ```plaintext
809    /// <col_name> AS <col_alias>
810    /// ```
811    Single(IdentWithAlias),
812    /// Multiple column names with aliases inside parenthesis.
813    /// # Syntax
814    /// ```plaintext
815    /// (<col_name> AS <col_alias>, <col_name> AS <col_alias>, ...)
816    /// ```
817    Multiple(Vec<IdentWithAlias>),
818}
819
820impl fmt::Display for RenameSelectItem {
821    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
822        write!(f, "RENAME")?;
823        match self {
824            Self::Single(column) => {
825                write!(f, " {column}")?;
826            }
827            Self::Multiple(columns) => {
828                write!(f, " ({})", display_comma_separated(columns))?;
829            }
830        }
831        Ok(())
832    }
833}
834
835/// Bigquery `EXCEPT` information, with at least one column.
836///
837/// # Syntax
838/// ```plaintext
839/// EXCEPT (<col_name> [, ...])
840/// ```
841#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
842#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
843#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
844pub struct ExceptSelectItem {
845    /// First guaranteed column.
846    pub first_element: Ident,
847    /// Additional columns. This list can be empty.
848    pub additional_elements: Vec<Ident>,
849}
850
851impl fmt::Display for ExceptSelectItem {
852    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
853        write!(f, "EXCEPT ")?;
854        if self.additional_elements.is_empty() {
855            write!(f, "({})", self.first_element)?;
856        } else {
857            write!(
858                f,
859                "({}, {})",
860                self.first_element,
861                display_comma_separated(&self.additional_elements)
862            )?;
863        }
864        Ok(())
865    }
866}
867
868/// Bigquery `REPLACE` information.
869///
870/// # Syntax
871/// ```plaintext
872/// REPLACE (<new_expr> [AS] <col_name>)
873/// REPLACE (<col_name> [AS] <col_alias>, <col_name> [AS] <col_alias>, ...)
874/// ```
875#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
876#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
877#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
878pub struct ReplaceSelectItem {
879    pub items: Vec<Box<ReplaceSelectElement>>,
880}
881
882impl fmt::Display for ReplaceSelectItem {
883    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
884        write!(f, "REPLACE")?;
885        write!(f, " ({})", display_comma_separated(&self.items))?;
886        Ok(())
887    }
888}
889
890/// # Syntax
891/// ```plaintext
892/// <expr> [AS] <column_name>
893/// ```
894#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
895#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
896#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
897pub struct ReplaceSelectElement {
898    pub expr: Expr,
899    pub column_name: Ident,
900    pub as_keyword: bool,
901}
902
903impl fmt::Display for ReplaceSelectElement {
904    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
905        if self.as_keyword {
906            write!(f, "{} AS {}", self.expr, self.column_name)
907        } else {
908            write!(f, "{} {}", self.expr, self.column_name)
909        }
910    }
911}
912
913impl fmt::Display for SelectItem {
914    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
915        match &self {
916            SelectItem::UnnamedExpr(expr) => write!(f, "{expr}"),
917            SelectItem::ExprWithAlias { expr, alias } => write!(f, "{expr} AS {alias}"),
918            SelectItem::QualifiedWildcard(kind, additional_options) => {
919                write!(f, "{kind}")?;
920                write!(f, "{additional_options}")?;
921                Ok(())
922            }
923            SelectItem::Wildcard(additional_options) => {
924                write!(f, "*")?;
925                write!(f, "{additional_options}")?;
926                Ok(())
927            }
928        }
929    }
930}
931
932#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
933#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
934#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
935pub struct TableWithJoins {
936    pub relation: TableFactor,
937    pub joins: Vec<Join>,
938}
939
940impl fmt::Display for TableWithJoins {
941    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
942        write!(f, "{}", self.relation)?;
943        for join in &self.joins {
944            write!(f, "{join}")?;
945        }
946        Ok(())
947    }
948}
949
950/// Joins a table to itself to process hierarchical data in the table.
951///
952/// See <https://docs.snowflake.com/en/sql-reference/constructs/connect-by>.
953#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
954#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
955#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
956pub struct ConnectBy {
957    /// START WITH
958    pub condition: Expr,
959    /// CONNECT BY
960    pub relationships: Vec<Expr>,
961}
962
963impl fmt::Display for ConnectBy {
964    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
965        write!(
966            f,
967            "START WITH {condition} CONNECT BY {relationships}",
968            condition = self.condition,
969            relationships = display_comma_separated(&self.relationships)
970        )
971    }
972}
973
974#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
975#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
976#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
977pub struct Setting {
978    pub key: Ident,
979    pub value: Value,
980}
981
982impl fmt::Display for Setting {
983    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
984        write!(f, "{} = {}", self.key, self.value)
985    }
986}
987
988/// An expression optionally followed by an alias.
989///
990/// Example:
991/// ```sql
992/// 42 AS myint
993/// ```
994#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
995#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
996#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
997pub struct ExprWithAlias {
998    pub expr: Expr,
999    pub alias: Option<Ident>,
1000}
1001
1002impl fmt::Display for ExprWithAlias {
1003    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1004        let ExprWithAlias { expr, alias } = self;
1005        write!(f, "{expr}")?;
1006        if let Some(alias) = alias {
1007            write!(f, " AS {alias}")?;
1008        }
1009        Ok(())
1010    }
1011}
1012
1013/// An expression optionally followed by an alias and order by options.
1014///
1015/// Example:
1016/// ```sql
1017/// 42 AS myint ASC
1018/// ```
1019#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1020#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1021#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1022pub struct ExprWithAliasAndOrderBy {
1023    pub expr: ExprWithAlias,
1024    pub order_by: OrderByOptions,
1025}
1026
1027impl fmt::Display for ExprWithAliasAndOrderBy {
1028    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1029        write!(f, "{}{}", self.expr, self.order_by)
1030    }
1031}
1032
1033/// Arguments to a table-valued function
1034#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1035#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1036#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1037pub struct TableFunctionArgs {
1038    pub args: Vec<FunctionArg>,
1039    /// ClickHouse-specific SETTINGS clause.
1040    /// For example,
1041    /// `SELECT * FROM executable('generate_random.py', TabSeparated, 'id UInt32, random String', SETTINGS send_chunk_header = false, pool_size = 16)`
1042    /// [`executable` table function](https://clickhouse.com/docs/en/engines/table-functions/executable)
1043    pub settings: Option<Vec<Setting>>,
1044}
1045
1046#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1047#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1048#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1049pub enum TableIndexHintType {
1050    Use,
1051    Ignore,
1052    Force,
1053}
1054
1055impl fmt::Display for TableIndexHintType {
1056    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1057        f.write_str(match self {
1058            TableIndexHintType::Use => "USE",
1059            TableIndexHintType::Ignore => "IGNORE",
1060            TableIndexHintType::Force => "FORCE",
1061        })
1062    }
1063}
1064
1065#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1066#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1067#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1068pub enum TableIndexType {
1069    Index,
1070    Key,
1071}
1072
1073impl fmt::Display for TableIndexType {
1074    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1075        f.write_str(match self {
1076            TableIndexType::Index => "INDEX",
1077            TableIndexType::Key => "KEY",
1078        })
1079    }
1080}
1081
1082#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1083#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1084#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1085pub enum TableIndexHintForClause {
1086    Join,
1087    OrderBy,
1088    GroupBy,
1089}
1090
1091impl fmt::Display for TableIndexHintForClause {
1092    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1093        f.write_str(match self {
1094            TableIndexHintForClause::Join => "JOIN",
1095            TableIndexHintForClause::OrderBy => "ORDER BY",
1096            TableIndexHintForClause::GroupBy => "GROUP BY",
1097        })
1098    }
1099}
1100
1101#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1102#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1103#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1104pub struct TableIndexHints {
1105    pub hint_type: TableIndexHintType,
1106    pub index_type: TableIndexType,
1107    pub for_clause: Option<TableIndexHintForClause>,
1108    pub index_names: Vec<Ident>,
1109}
1110
1111impl fmt::Display for TableIndexHints {
1112    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1113        write!(f, "{} {} ", self.hint_type, self.index_type)?;
1114        if let Some(for_clause) = &self.for_clause {
1115            write!(f, "FOR {} ", for_clause)?;
1116        }
1117        write!(f, "({})", display_comma_separated(&self.index_names))
1118    }
1119}
1120
1121/// A table name or a parenthesized subquery with an optional alias
1122#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1123#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1124#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1125#[cfg_attr(feature = "visitor", visit(with = "visit_table_factor"))]
1126pub enum TableFactor {
1127    Table {
1128        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
1129        name: ObjectName,
1130        alias: Option<TableAlias>,
1131        /// Arguments of a table-valued function, as supported by Postgres
1132        /// and MSSQL. Note that deprecated MSSQL `FROM foo (NOLOCK)` syntax
1133        /// will also be parsed as `args`.
1134        ///
1135        /// This field's value is `Some(v)`, where `v` is a (possibly empty)
1136        /// vector of arguments, in the case of a table-valued function call,
1137        /// whereas it's `None` in the case of a regular table name.
1138        args: Option<TableFunctionArgs>,
1139        /// MSSQL-specific `WITH (...)` hints such as NOLOCK.
1140        with_hints: Vec<Expr>,
1141        /// Optional version qualifier to facilitate table time-travel, as
1142        /// supported by BigQuery and MSSQL.
1143        version: Option<TableVersion>,
1144        //  Optional table function modifier to generate the ordinality for column.
1145        /// For example, `SELECT * FROM generate_series(1, 10) WITH ORDINALITY AS t(a, b);`
1146        /// [WITH ORDINALITY](https://www.postgresql.org/docs/current/functions-srf.html), supported by Postgres.
1147        with_ordinality: bool,
1148        /// [Partition selection](https://dev.mysql.com/doc/refman/8.0/en/partitioning-selection.html), supported by MySQL.
1149        partitions: Vec<Ident>,
1150        /// Optional PartiQL JsonPath: <https://partiql.org/dql/from.html>
1151        json_path: Option<JsonPath>,
1152        /// Optional table sample modifier
1153        /// See: <https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#sample-clause>
1154        sample: Option<TableSampleKind>,
1155        /// Optional index hints(mysql)
1156        /// See: <https://dev.mysql.com/doc/refman/8.4/en/index-hints.html>
1157        index_hints: Vec<TableIndexHints>,
1158    },
1159    Derived {
1160        lateral: bool,
1161        subquery: Box<Query>,
1162        alias: Option<TableAlias>,
1163    },
1164    /// `TABLE(<expr>)[ AS <alias> ]`
1165    TableFunction {
1166        expr: Expr,
1167        alias: Option<TableAlias>,
1168    },
1169    /// `e.g. LATERAL FLATTEN(<args>)[ AS <alias> ]`
1170    Function {
1171        lateral: bool,
1172        name: ObjectName,
1173        args: Vec<FunctionArg>,
1174        alias: Option<TableAlias>,
1175    },
1176    /// ```sql
1177    /// SELECT * FROM UNNEST ([10,20,30]) as numbers WITH OFFSET;
1178    /// +---------+--------+
1179    /// | numbers | offset |
1180    /// +---------+--------+
1181    /// | 10      | 0      |
1182    /// | 20      | 1      |
1183    /// | 30      | 2      |
1184    /// +---------+--------+
1185    /// ```
1186    UNNEST {
1187        alias: Option<TableAlias>,
1188        array_exprs: Vec<Expr>,
1189        with_offset: bool,
1190        with_offset_alias: Option<Ident>,
1191        with_ordinality: bool,
1192    },
1193    /// The `JSON_TABLE` table-valued function.
1194    /// Part of the SQL standard, but implemented only by MySQL, Oracle, and DB2.
1195    ///
1196    /// <https://modern-sql.com/blog/2017-06/whats-new-in-sql-2016#json_table>
1197    /// <https://dev.mysql.com/doc/refman/8.0/en/json-table-functions.html#function_json-table>
1198    ///
1199    /// ```sql
1200    /// SELECT * FROM JSON_TABLE(
1201    ///    '[{"a": 1, "b": 2}, {"a": 3, "b": 4}]',
1202    ///    '$[*]' COLUMNS(
1203    ///        a INT PATH '$.a' DEFAULT '0' ON EMPTY,
1204    ///        b INT PATH '$.b' NULL ON ERROR
1205    ///     )
1206    /// ) AS jt;
1207    /// ````
1208    JsonTable {
1209        /// The JSON expression to be evaluated. It must evaluate to a json string
1210        json_expr: Expr,
1211        /// The path to the array or object to be iterated over.
1212        /// It must evaluate to a json array or object.
1213        json_path: Value,
1214        /// The columns to be extracted from each element of the array or object.
1215        /// Each column must have a name and a type.
1216        columns: Vec<JsonTableColumn>,
1217        /// The alias for the table.
1218        alias: Option<TableAlias>,
1219    },
1220    /// The MSSQL's `OPENJSON` table-valued function.
1221    ///
1222    /// ```sql
1223    /// OPENJSON( jsonExpression [ , path ] )  [ <with_clause> ]
1224    ///
1225    /// <with_clause> ::= WITH ( { colName type [ column_path ] [ AS JSON ] } [ ,...n ] )
1226    /// ````
1227    ///
1228    /// Reference: <https://learn.microsoft.com/en-us/sql/t-sql/functions/openjson-transact-sql?view=sql-server-ver16#syntax>
1229    OpenJsonTable {
1230        /// The JSON expression to be evaluated. It must evaluate to a json string
1231        json_expr: Expr,
1232        /// The path to the array or object to be iterated over.
1233        /// It must evaluate to a json array or object.
1234        json_path: Option<Value>,
1235        /// The columns to be extracted from each element of the array or object.
1236        /// Each column must have a name and a type.
1237        columns: Vec<OpenJsonTableColumn>,
1238        /// The alias for the table.
1239        alias: Option<TableAlias>,
1240    },
1241    /// Represents a parenthesized table factor. The SQL spec only allows a
1242    /// join expression (`(foo <JOIN> bar [ <JOIN> baz ... ])`) to be nested,
1243    /// possibly several times.
1244    ///
1245    /// The parser may also accept non-standard nesting of bare tables for some
1246    /// dialects, but the information about such nesting is stripped from AST.
1247    NestedJoin {
1248        table_with_joins: Box<TableWithJoins>,
1249        alias: Option<TableAlias>,
1250    },
1251    /// Represents PIVOT operation on a table.
1252    /// For example `FROM monthly_sales PIVOT(sum(amount) FOR MONTH IN ('JAN', 'FEB'))`
1253    ///
1254    /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/query-syntax#pivot_operator)
1255    /// [Snowflake](https://docs.snowflake.com/en/sql-reference/constructs/pivot)
1256    Pivot {
1257        table: Box<TableFactor>,
1258        aggregate_functions: Vec<ExprWithAlias>, // Function expression
1259        value_column: Vec<Ident>,
1260        value_source: PivotValueSource,
1261        default_on_null: Option<Expr>,
1262        alias: Option<TableAlias>,
1263    },
1264    /// An UNPIVOT operation on a table.
1265    ///
1266    /// Syntax:
1267    /// ```sql
1268    /// table UNPIVOT(value FOR name IN (column1, [ column2, ... ])) [ alias ]
1269    /// ```
1270    ///
1271    /// See <https://docs.snowflake.com/en/sql-reference/constructs/unpivot>.
1272    Unpivot {
1273        table: Box<TableFactor>,
1274        value: Ident,
1275        name: Ident,
1276        columns: Vec<Ident>,
1277        alias: Option<TableAlias>,
1278    },
1279    /// A `MATCH_RECOGNIZE` operation on a table.
1280    ///
1281    /// See <https://docs.snowflake.com/en/sql-reference/constructs/match_recognize>.
1282    MatchRecognize {
1283        table: Box<TableFactor>,
1284        /// `PARTITION BY <expr> [, ... ]`
1285        partition_by: Vec<Expr>,
1286        /// `ORDER BY <expr> [, ... ]`
1287        order_by: Vec<OrderByExpr>,
1288        /// `MEASURES <expr> [AS] <alias> [, ... ]`
1289        measures: Vec<Measure>,
1290        /// `ONE ROW PER MATCH | ALL ROWS PER MATCH [ <option> ]`
1291        rows_per_match: Option<RowsPerMatch>,
1292        /// `AFTER MATCH SKIP <option>`
1293        after_match_skip: Option<AfterMatchSkip>,
1294        /// `PATTERN ( <pattern> )`
1295        pattern: MatchRecognizePattern,
1296        /// `DEFINE <symbol> AS <expr> [, ... ]`
1297        symbols: Vec<SymbolDefinition>,
1298        alias: Option<TableAlias>,
1299    },
1300    /// The `XMLTABLE` table-valued function.
1301    /// Part of the SQL standard, supported by PostgreSQL, Oracle, and DB2.
1302    ///
1303    /// <https://www.postgresql.org/docs/15/functions-xml.html#FUNCTIONS-XML-PROCESSING>
1304    ///
1305    /// ```sql
1306    /// SELECT xmltable.*
1307    /// FROM xmldata,
1308    /// XMLTABLE('//ROWS/ROW'
1309    ///     PASSING data
1310    ///     COLUMNS id int PATH '@id',
1311    ///     ordinality FOR ORDINALITY,
1312    ///     "COUNTRY_NAME" text,
1313    ///     country_id text PATH 'COUNTRY_ID',
1314    ///     size_sq_km float PATH 'SIZE[@unit = "sq_km"]',
1315    ///     size_other text PATH 'concat(SIZE[@unit!="sq_km"], " ", SIZE[@unit!="sq_km"]/@unit)',
1316    ///     premier_name text PATH 'PREMIER_NAME' DEFAULT 'not specified'
1317    /// );
1318    /// ````
1319    XmlTable {
1320        /// Optional XMLNAMESPACES clause (empty if not present)
1321        namespaces: Vec<XmlNamespaceDefinition>,
1322        /// The row-generating XPath expression.
1323        row_expression: Expr,
1324        /// The PASSING clause specifying the document expression.
1325        passing: XmlPassingClause,
1326        /// The columns to be extracted from each generated row.
1327        columns: Vec<XmlTableColumn>,
1328        /// The alias for the table.
1329        alias: Option<TableAlias>,
1330    },
1331}
1332
1333/// The table sample modifier options
1334#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1335#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1336#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1337
1338pub enum TableSampleKind {
1339    /// Table sample located before the table alias option
1340    BeforeTableAlias(Box<TableSample>),
1341    /// Table sample located after the table alias option
1342    AfterTableAlias(Box<TableSample>),
1343}
1344
1345#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1346#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1347#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1348pub struct TableSample {
1349    pub modifier: TableSampleModifier,
1350    pub name: Option<TableSampleMethod>,
1351    pub quantity: Option<TableSampleQuantity>,
1352    pub seed: Option<TableSampleSeed>,
1353    pub bucket: Option<TableSampleBucket>,
1354    pub offset: Option<Expr>,
1355}
1356
1357#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1358#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1359#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1360pub enum TableSampleModifier {
1361    Sample,
1362    TableSample,
1363}
1364
1365impl fmt::Display for TableSampleModifier {
1366    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1367        match self {
1368            TableSampleModifier::Sample => write!(f, "SAMPLE")?,
1369            TableSampleModifier::TableSample => write!(f, "TABLESAMPLE")?,
1370        }
1371        Ok(())
1372    }
1373}
1374
1375#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1376#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1377#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1378pub struct TableSampleQuantity {
1379    pub parenthesized: bool,
1380    pub value: Expr,
1381    pub unit: Option<TableSampleUnit>,
1382}
1383
1384impl fmt::Display for TableSampleQuantity {
1385    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1386        if self.parenthesized {
1387            write!(f, "(")?;
1388        }
1389        write!(f, "{}", self.value)?;
1390        if let Some(unit) = &self.unit {
1391            write!(f, " {}", unit)?;
1392        }
1393        if self.parenthesized {
1394            write!(f, ")")?;
1395        }
1396        Ok(())
1397    }
1398}
1399
1400/// The table sample method names
1401#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1402#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1403#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1404pub enum TableSampleMethod {
1405    Row,
1406    Bernoulli,
1407    System,
1408    Block,
1409}
1410
1411impl fmt::Display for TableSampleMethod {
1412    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1413        match self {
1414            TableSampleMethod::Bernoulli => write!(f, "BERNOULLI"),
1415            TableSampleMethod::Row => write!(f, "ROW"),
1416            TableSampleMethod::System => write!(f, "SYSTEM"),
1417            TableSampleMethod::Block => write!(f, "BLOCK"),
1418        }
1419    }
1420}
1421
1422#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1423#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1424#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1425pub struct TableSampleSeed {
1426    pub modifier: TableSampleSeedModifier,
1427    pub value: Value,
1428}
1429
1430impl fmt::Display for TableSampleSeed {
1431    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1432        write!(f, "{} ({})", self.modifier, self.value)?;
1433        Ok(())
1434    }
1435}
1436
1437#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1438#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1439#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1440pub enum TableSampleSeedModifier {
1441    Repeatable,
1442    Seed,
1443}
1444
1445impl fmt::Display for TableSampleSeedModifier {
1446    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1447        match self {
1448            TableSampleSeedModifier::Repeatable => write!(f, "REPEATABLE"),
1449            TableSampleSeedModifier::Seed => write!(f, "SEED"),
1450        }
1451    }
1452}
1453
1454#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1455#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1456#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1457pub enum TableSampleUnit {
1458    Rows,
1459    Percent,
1460}
1461
1462impl fmt::Display for TableSampleUnit {
1463    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1464        match self {
1465            TableSampleUnit::Percent => write!(f, "PERCENT"),
1466            TableSampleUnit::Rows => write!(f, "ROWS"),
1467        }
1468    }
1469}
1470
1471#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1472#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1473#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1474pub struct TableSampleBucket {
1475    pub bucket: Value,
1476    pub total: Value,
1477    pub on: Option<Expr>,
1478}
1479
1480impl fmt::Display for TableSampleBucket {
1481    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1482        write!(f, "BUCKET {} OUT OF {}", self.bucket, self.total)?;
1483        if let Some(on) = &self.on {
1484            write!(f, " ON {}", on)?;
1485        }
1486        Ok(())
1487    }
1488}
1489impl fmt::Display for TableSample {
1490    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1491        write!(f, " {}", self.modifier)?;
1492        if let Some(name) = &self.name {
1493            write!(f, " {}", name)?;
1494        }
1495        if let Some(quantity) = &self.quantity {
1496            write!(f, " {}", quantity)?;
1497        }
1498        if let Some(seed) = &self.seed {
1499            write!(f, " {}", seed)?;
1500        }
1501        if let Some(bucket) = &self.bucket {
1502            write!(f, " ({})", bucket)?;
1503        }
1504        if let Some(offset) = &self.offset {
1505            write!(f, " OFFSET {}", offset)?;
1506        }
1507        Ok(())
1508    }
1509}
1510
1511/// The source of values in a `PIVOT` operation.
1512#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1513#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1514#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1515pub enum PivotValueSource {
1516    /// Pivot on a static list of values.
1517    ///
1518    /// See <https://docs.snowflake.com/en/sql-reference/constructs/pivot#pivot-on-a-specified-list-of-column-values-for-the-pivot-column>.
1519    List(Vec<ExprWithAlias>),
1520    /// Pivot on all distinct values of the pivot column.
1521    ///
1522    /// See <https://docs.snowflake.com/en/sql-reference/constructs/pivot#pivot-on-all-distinct-column-values-automatically-with-dynamic-pivot>.
1523    Any(Vec<OrderByExpr>),
1524    /// Pivot on all values returned by a subquery.
1525    ///
1526    /// See <https://docs.snowflake.com/en/sql-reference/constructs/pivot#pivot-on-column-values-using-a-subquery-with-dynamic-pivot>.
1527    Subquery(Box<Query>),
1528}
1529
1530impl fmt::Display for PivotValueSource {
1531    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1532        match self {
1533            PivotValueSource::List(values) => write!(f, "{}", display_comma_separated(values)),
1534            PivotValueSource::Any(order_by) => {
1535                write!(f, "ANY")?;
1536                if !order_by.is_empty() {
1537                    write!(f, " ORDER BY {}", display_comma_separated(order_by))?;
1538                }
1539                Ok(())
1540            }
1541            PivotValueSource::Subquery(query) => write!(f, "{query}"),
1542        }
1543    }
1544}
1545
1546/// An item in the `MEASURES` subclause of a `MATCH_RECOGNIZE` operation.
1547///
1548/// See <https://docs.snowflake.com/en/sql-reference/constructs/match_recognize#measures-specifying-additional-output-columns>.
1549#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1550#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1551#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1552pub struct Measure {
1553    pub expr: Expr,
1554    pub alias: Ident,
1555}
1556
1557impl fmt::Display for Measure {
1558    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1559        write!(f, "{} AS {}", self.expr, self.alias)
1560    }
1561}
1562
1563/// The rows per match option in a `MATCH_RECOGNIZE` operation.
1564///
1565/// See <https://docs.snowflake.com/en/sql-reference/constructs/match_recognize#row-s-per-match-specifying-the-rows-to-return>.
1566#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1567#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1568#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1569pub enum RowsPerMatch {
1570    /// `ONE ROW PER MATCH`
1571    OneRow,
1572    /// `ALL ROWS PER MATCH <mode>`
1573    AllRows(Option<EmptyMatchesMode>),
1574}
1575
1576impl fmt::Display for RowsPerMatch {
1577    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1578        match self {
1579            RowsPerMatch::OneRow => write!(f, "ONE ROW PER MATCH"),
1580            RowsPerMatch::AllRows(mode) => {
1581                write!(f, "ALL ROWS PER MATCH")?;
1582                if let Some(mode) = mode {
1583                    write!(f, " {}", mode)?;
1584                }
1585                Ok(())
1586            }
1587        }
1588    }
1589}
1590
1591/// The after match skip option in a `MATCH_RECOGNIZE` operation.
1592///
1593/// See <https://docs.snowflake.com/en/sql-reference/constructs/match_recognize#after-match-skip-specifying-where-to-continue-after-a-match>.
1594#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1595#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1596#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1597pub enum AfterMatchSkip {
1598    /// `PAST LAST ROW`
1599    PastLastRow,
1600    /// `TO NEXT ROW`
1601    ToNextRow,
1602    /// `TO FIRST <symbol>`
1603    ToFirst(Ident),
1604    /// `TO LAST <symbol>`
1605    ToLast(Ident),
1606}
1607
1608impl fmt::Display for AfterMatchSkip {
1609    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1610        write!(f, "AFTER MATCH SKIP ")?;
1611        match self {
1612            AfterMatchSkip::PastLastRow => write!(f, "PAST LAST ROW"),
1613            AfterMatchSkip::ToNextRow => write!(f, " TO NEXT ROW"),
1614            AfterMatchSkip::ToFirst(symbol) => write!(f, "TO FIRST {symbol}"),
1615            AfterMatchSkip::ToLast(symbol) => write!(f, "TO LAST {symbol}"),
1616        }
1617    }
1618}
1619
1620#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1621#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1622#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1623pub enum EmptyMatchesMode {
1624    /// `SHOW EMPTY MATCHES`
1625    Show,
1626    /// `OMIT EMPTY MATCHES`
1627    Omit,
1628    /// `WITH UNMATCHED ROWS`
1629    WithUnmatched,
1630}
1631
1632impl fmt::Display for EmptyMatchesMode {
1633    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1634        match self {
1635            EmptyMatchesMode::Show => write!(f, "SHOW EMPTY MATCHES"),
1636            EmptyMatchesMode::Omit => write!(f, "OMIT EMPTY MATCHES"),
1637            EmptyMatchesMode::WithUnmatched => write!(f, "WITH UNMATCHED ROWS"),
1638        }
1639    }
1640}
1641
1642/// A symbol defined in a `MATCH_RECOGNIZE` operation.
1643///
1644/// See <https://docs.snowflake.com/en/sql-reference/constructs/match_recognize#define-defining-symbols>.
1645#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1646#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1647#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1648pub struct SymbolDefinition {
1649    pub symbol: Ident,
1650    pub definition: Expr,
1651}
1652
1653impl fmt::Display for SymbolDefinition {
1654    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1655        write!(f, "{} AS {}", self.symbol, self.definition)
1656    }
1657}
1658
1659/// A symbol in a `MATCH_RECOGNIZE` pattern.
1660#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1661#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1662#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1663pub enum MatchRecognizeSymbol {
1664    /// A named symbol, e.g. `S1`.
1665    Named(Ident),
1666    /// A virtual symbol representing the start of the of partition (`^`).
1667    Start,
1668    /// A virtual symbol representing the end of the partition (`$`).
1669    End,
1670}
1671
1672impl fmt::Display for MatchRecognizeSymbol {
1673    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1674        match self {
1675            MatchRecognizeSymbol::Named(symbol) => write!(f, "{symbol}"),
1676            MatchRecognizeSymbol::Start => write!(f, "^"),
1677            MatchRecognizeSymbol::End => write!(f, "$"),
1678        }
1679    }
1680}
1681
1682/// The pattern in a `MATCH_RECOGNIZE` operation.
1683///
1684/// See <https://docs.snowflake.com/en/sql-reference/constructs/match_recognize#pattern-specifying-the-pattern-to-match>.
1685#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1686#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1687#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1688pub enum MatchRecognizePattern {
1689    /// A named symbol such as `S1` or a virtual symbol such as `^`.
1690    Symbol(MatchRecognizeSymbol),
1691    /// {- symbol -}
1692    Exclude(MatchRecognizeSymbol),
1693    /// PERMUTE(symbol_1, ..., symbol_n)
1694    Permute(Vec<MatchRecognizeSymbol>),
1695    /// pattern_1 pattern_2 ... pattern_n
1696    Concat(Vec<MatchRecognizePattern>),
1697    /// ( pattern )
1698    Group(Box<MatchRecognizePattern>),
1699    /// pattern_1 | pattern_2 | ... | pattern_n
1700    Alternation(Vec<MatchRecognizePattern>),
1701    /// e.g. pattern*
1702    Repetition(Box<MatchRecognizePattern>, RepetitionQuantifier),
1703}
1704
1705impl fmt::Display for MatchRecognizePattern {
1706    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1707        use MatchRecognizePattern::*;
1708        match self {
1709            Symbol(symbol) => write!(f, "{}", symbol),
1710            Exclude(symbol) => write!(f, "{{- {symbol} -}}"),
1711            Permute(symbols) => write!(f, "PERMUTE({})", display_comma_separated(symbols)),
1712            Concat(patterns) => write!(f, "{}", display_separated(patterns, " ")),
1713            Group(pattern) => write!(f, "( {pattern} )"),
1714            Alternation(patterns) => write!(f, "{}", display_separated(patterns, " | ")),
1715            Repetition(pattern, op) => write!(f, "{pattern}{op}"),
1716        }
1717    }
1718}
1719
1720/// Determines the minimum and maximum allowed occurrences of a pattern in a
1721/// `MATCH_RECOGNIZE` operation.
1722#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1723#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1724#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1725pub enum RepetitionQuantifier {
1726    /// `*`
1727    ZeroOrMore,
1728    /// `+`
1729    OneOrMore,
1730    /// `?`
1731    AtMostOne,
1732    /// `{n}`
1733    Exactly(u32),
1734    /// `{n,}`
1735    AtLeast(u32),
1736    /// `{,n}`
1737    AtMost(u32),
1738    /// `{n,m}
1739    Range(u32, u32),
1740}
1741
1742impl fmt::Display for RepetitionQuantifier {
1743    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1744        use RepetitionQuantifier::*;
1745        match self {
1746            ZeroOrMore => write!(f, "*"),
1747            OneOrMore => write!(f, "+"),
1748            AtMostOne => write!(f, "?"),
1749            Exactly(n) => write!(f, "{{{n}}}"),
1750            AtLeast(n) => write!(f, "{{{n},}}"),
1751            AtMost(n) => write!(f, "{{,{n}}}"),
1752            Range(n, m) => write!(f, "{{{n},{m}}}"),
1753        }
1754    }
1755}
1756
1757impl fmt::Display for TableFactor {
1758    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1759        match self {
1760            TableFactor::Table {
1761                name,
1762                alias,
1763                args,
1764                with_hints,
1765                version,
1766                partitions,
1767                with_ordinality,
1768                json_path,
1769                sample,
1770                index_hints,
1771            } => {
1772                write!(f, "{name}")?;
1773                if let Some(json_path) = json_path {
1774                    write!(f, "{json_path}")?;
1775                }
1776                if !partitions.is_empty() {
1777                    write!(f, "PARTITION ({})", display_comma_separated(partitions))?;
1778                }
1779                if let Some(args) = args {
1780                    write!(f, "(")?;
1781                    write!(f, "{}", display_comma_separated(&args.args))?;
1782                    if let Some(ref settings) = args.settings {
1783                        if !args.args.is_empty() {
1784                            write!(f, ", ")?;
1785                        }
1786                        write!(f, "SETTINGS {}", display_comma_separated(settings))?;
1787                    }
1788                    write!(f, ")")?;
1789                }
1790                if *with_ordinality {
1791                    write!(f, " WITH ORDINALITY")?;
1792                }
1793                if let Some(TableSampleKind::BeforeTableAlias(sample)) = sample {
1794                    write!(f, "{sample}")?;
1795                }
1796                if let Some(alias) = alias {
1797                    write!(f, " AS {alias}")?;
1798                }
1799                if !index_hints.is_empty() {
1800                    write!(f, " {}", display_separated(index_hints, " "))?;
1801                }
1802                if !with_hints.is_empty() {
1803                    write!(f, " WITH ({})", display_comma_separated(with_hints))?;
1804                }
1805                if let Some(version) = version {
1806                    write!(f, "{version}")?;
1807                }
1808                if let Some(TableSampleKind::AfterTableAlias(sample)) = sample {
1809                    write!(f, "{sample}")?;
1810                }
1811                Ok(())
1812            }
1813            TableFactor::Derived {
1814                lateral,
1815                subquery,
1816                alias,
1817            } => {
1818                if *lateral {
1819                    write!(f, "LATERAL ")?;
1820                }
1821                write!(f, "({subquery})")?;
1822                if let Some(alias) = alias {
1823                    write!(f, " AS {alias}")?;
1824                }
1825                Ok(())
1826            }
1827            TableFactor::Function {
1828                lateral,
1829                name,
1830                args,
1831                alias,
1832            } => {
1833                if *lateral {
1834                    write!(f, "LATERAL ")?;
1835                }
1836                write!(f, "{name}")?;
1837                write!(f, "({})", display_comma_separated(args))?;
1838                if let Some(alias) = alias {
1839                    write!(f, " AS {alias}")?;
1840                }
1841                Ok(())
1842            }
1843            TableFactor::TableFunction { expr, alias } => {
1844                write!(f, "TABLE({expr})")?;
1845                if let Some(alias) = alias {
1846                    write!(f, " AS {alias}")?;
1847                }
1848                Ok(())
1849            }
1850            TableFactor::UNNEST {
1851                alias,
1852                array_exprs,
1853                with_offset,
1854                with_offset_alias,
1855                with_ordinality,
1856            } => {
1857                write!(f, "UNNEST({})", display_comma_separated(array_exprs))?;
1858
1859                if *with_ordinality {
1860                    write!(f, " WITH ORDINALITY")?;
1861                }
1862
1863                if let Some(alias) = alias {
1864                    write!(f, " AS {alias}")?;
1865                }
1866                if *with_offset {
1867                    write!(f, " WITH OFFSET")?;
1868                }
1869                if let Some(alias) = with_offset_alias {
1870                    write!(f, " AS {alias}")?;
1871                }
1872                Ok(())
1873            }
1874            TableFactor::JsonTable {
1875                json_expr,
1876                json_path,
1877                columns,
1878                alias,
1879            } => {
1880                write!(
1881                    f,
1882                    "JSON_TABLE({json_expr}, {json_path} COLUMNS({columns}))",
1883                    columns = display_comma_separated(columns)
1884                )?;
1885                if let Some(alias) = alias {
1886                    write!(f, " AS {alias}")?;
1887                }
1888                Ok(())
1889            }
1890            TableFactor::OpenJsonTable {
1891                json_expr,
1892                json_path,
1893                columns,
1894                alias,
1895            } => {
1896                write!(f, "OPENJSON({json_expr}")?;
1897                if let Some(json_path) = json_path {
1898                    write!(f, ", {json_path}")?;
1899                }
1900                write!(f, ")")?;
1901                if !columns.is_empty() {
1902                    write!(f, " WITH ({})", display_comma_separated(columns))?;
1903                }
1904                if let Some(alias) = alias {
1905                    write!(f, " AS {alias}")?;
1906                }
1907                Ok(())
1908            }
1909            TableFactor::NestedJoin {
1910                table_with_joins,
1911                alias,
1912            } => {
1913                write!(f, "({table_with_joins})")?;
1914                if let Some(alias) = alias {
1915                    write!(f, " AS {alias}")?;
1916                }
1917                Ok(())
1918            }
1919            TableFactor::Pivot {
1920                table,
1921                aggregate_functions,
1922                value_column,
1923                value_source,
1924                default_on_null,
1925                alias,
1926            } => {
1927                write!(
1928                    f,
1929                    "{table} PIVOT({} FOR {} IN ({value_source})",
1930                    display_comma_separated(aggregate_functions),
1931                    Expr::CompoundIdentifier(value_column.to_vec()),
1932                )?;
1933                if let Some(expr) = default_on_null {
1934                    write!(f, " DEFAULT ON NULL ({expr})")?;
1935                }
1936                write!(f, ")")?;
1937                if alias.is_some() {
1938                    write!(f, " AS {}", alias.as_ref().unwrap())?;
1939                }
1940                Ok(())
1941            }
1942            TableFactor::Unpivot {
1943                table,
1944                value,
1945                name,
1946                columns,
1947                alias,
1948            } => {
1949                write!(
1950                    f,
1951                    "{} UNPIVOT({} FOR {} IN ({}))",
1952                    table,
1953                    value,
1954                    name,
1955                    display_comma_separated(columns)
1956                )?;
1957                if alias.is_some() {
1958                    write!(f, " AS {}", alias.as_ref().unwrap())?;
1959                }
1960                Ok(())
1961            }
1962            TableFactor::MatchRecognize {
1963                table,
1964                partition_by,
1965                order_by,
1966                measures,
1967                rows_per_match,
1968                after_match_skip,
1969                pattern,
1970                symbols,
1971                alias,
1972            } => {
1973                write!(f, "{table} MATCH_RECOGNIZE(")?;
1974                if !partition_by.is_empty() {
1975                    write!(f, "PARTITION BY {} ", display_comma_separated(partition_by))?;
1976                }
1977                if !order_by.is_empty() {
1978                    write!(f, "ORDER BY {} ", display_comma_separated(order_by))?;
1979                }
1980                if !measures.is_empty() {
1981                    write!(f, "MEASURES {} ", display_comma_separated(measures))?;
1982                }
1983                if let Some(rows_per_match) = rows_per_match {
1984                    write!(f, "{rows_per_match} ")?;
1985                }
1986                if let Some(after_match_skip) = after_match_skip {
1987                    write!(f, "{after_match_skip} ")?;
1988                }
1989                write!(f, "PATTERN ({pattern}) ")?;
1990                write!(f, "DEFINE {})", display_comma_separated(symbols))?;
1991                if alias.is_some() {
1992                    write!(f, " AS {}", alias.as_ref().unwrap())?;
1993                }
1994                Ok(())
1995            }
1996            TableFactor::XmlTable {
1997                row_expression,
1998                passing,
1999                columns,
2000                alias,
2001                namespaces,
2002            } => {
2003                write!(f, "XMLTABLE(")?;
2004                if !namespaces.is_empty() {
2005                    write!(
2006                        f,
2007                        "XMLNAMESPACES({}), ",
2008                        display_comma_separated(namespaces)
2009                    )?;
2010                }
2011                write!(
2012                    f,
2013                    "{row_expression}{passing} COLUMNS {columns})",
2014                    columns = display_comma_separated(columns)
2015                )?;
2016                if let Some(alias) = alias {
2017                    write!(f, " AS {alias}")?;
2018                }
2019                Ok(())
2020            }
2021        }
2022    }
2023}
2024
2025#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2026#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2027#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2028pub struct TableAlias {
2029    pub name: Ident,
2030    pub columns: Vec<TableAliasColumnDef>,
2031}
2032
2033impl fmt::Display for TableAlias {
2034    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2035        write!(f, "{}", self.name)?;
2036        if !self.columns.is_empty() {
2037            write!(f, " ({})", display_comma_separated(&self.columns))?;
2038        }
2039        Ok(())
2040    }
2041}
2042
2043/// SQL column definition in a table expression alias.
2044/// Most of the time, the data type is not specified.
2045/// But some table-valued functions do require specifying the data type.
2046///
2047/// See <https://www.postgresql.org/docs/17/queries-table-expressions.html#QUERIES-TABLEFUNCTIONS>
2048#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2049#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2050#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2051pub struct TableAliasColumnDef {
2052    /// Column name alias
2053    pub name: Ident,
2054    /// Some table-valued functions require specifying the data type in the alias.
2055    pub data_type: Option<DataType>,
2056}
2057
2058impl TableAliasColumnDef {
2059    /// Create a new table alias column definition with only a name and no type
2060    pub fn from_name<S: Into<String>>(name: S) -> Self {
2061        TableAliasColumnDef {
2062            name: Ident::new(name),
2063            data_type: None,
2064        }
2065    }
2066}
2067
2068impl fmt::Display for TableAliasColumnDef {
2069    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2070        write!(f, "{}", self.name)?;
2071        if let Some(ref data_type) = self.data_type {
2072            write!(f, " {}", data_type)?;
2073        }
2074        Ok(())
2075    }
2076}
2077
2078#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2079#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2080#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2081pub enum TableVersion {
2082    /// When the table version is defined using `FOR SYSTEM_TIME AS OF`.
2083    /// For example: `SELECT * FROM tbl FOR SYSTEM_TIME AS OF TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 1 HOUR)`
2084    ForSystemTimeAsOf(Expr),
2085    /// When the table version is defined using a function.
2086    /// For example: `SELECT * FROM tbl AT(TIMESTAMP => '2020-08-14 09:30:00')`
2087    Function(Expr),
2088}
2089
2090impl Display for TableVersion {
2091    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2092        match self {
2093            TableVersion::ForSystemTimeAsOf(e) => write!(f, " FOR SYSTEM_TIME AS OF {e}")?,
2094            TableVersion::Function(func) => write!(f, " {func}")?,
2095        }
2096        Ok(())
2097    }
2098}
2099
2100#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2101#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2102#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2103pub struct Join {
2104    pub relation: TableFactor,
2105    /// ClickHouse supports the optional `GLOBAL` keyword before the join operator.
2106    /// See [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/select/join)
2107    pub global: bool,
2108    pub join_operator: JoinOperator,
2109}
2110
2111impl fmt::Display for Join {
2112    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2113        fn prefix(constraint: &JoinConstraint) -> &'static str {
2114            match constraint {
2115                JoinConstraint::Natural => "NATURAL ",
2116                _ => "",
2117            }
2118        }
2119        fn suffix(constraint: &'_ JoinConstraint) -> impl fmt::Display + '_ {
2120            struct Suffix<'a>(&'a JoinConstraint);
2121            impl fmt::Display for Suffix<'_> {
2122                fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2123                    match self.0 {
2124                        JoinConstraint::On(expr) => write!(f, " ON {expr}"),
2125                        JoinConstraint::Using(attrs) => {
2126                            write!(f, " USING({})", display_comma_separated(attrs))
2127                        }
2128                        _ => Ok(()),
2129                    }
2130                }
2131            }
2132            Suffix(constraint)
2133        }
2134        if self.global {
2135            write!(f, " GLOBAL")?;
2136        }
2137
2138        match &self.join_operator {
2139            JoinOperator::Join(constraint) => write!(
2140                f,
2141                " {}JOIN {}{}",
2142                prefix(constraint),
2143                self.relation,
2144                suffix(constraint)
2145            ),
2146            JoinOperator::Inner(constraint) => write!(
2147                f,
2148                " {}INNER JOIN {}{}",
2149                prefix(constraint),
2150                self.relation,
2151                suffix(constraint)
2152            ),
2153            JoinOperator::Left(constraint) => write!(
2154                f,
2155                " {}LEFT JOIN {}{}",
2156                prefix(constraint),
2157                self.relation,
2158                suffix(constraint)
2159            ),
2160            JoinOperator::LeftOuter(constraint) => write!(
2161                f,
2162                " {}LEFT OUTER JOIN {}{}",
2163                prefix(constraint),
2164                self.relation,
2165                suffix(constraint)
2166            ),
2167            JoinOperator::Right(constraint) => write!(
2168                f,
2169                " {}RIGHT JOIN {}{}",
2170                prefix(constraint),
2171                self.relation,
2172                suffix(constraint)
2173            ),
2174            JoinOperator::RightOuter(constraint) => write!(
2175                f,
2176                " {}RIGHT OUTER JOIN {}{}",
2177                prefix(constraint),
2178                self.relation,
2179                suffix(constraint)
2180            ),
2181            JoinOperator::FullOuter(constraint) => write!(
2182                f,
2183                " {}FULL JOIN {}{}",
2184                prefix(constraint),
2185                self.relation,
2186                suffix(constraint)
2187            ),
2188            JoinOperator::CrossJoin => write!(f, " CROSS JOIN {}", self.relation),
2189            JoinOperator::Semi(constraint) => write!(
2190                f,
2191                " {}SEMI JOIN {}{}",
2192                prefix(constraint),
2193                self.relation,
2194                suffix(constraint)
2195            ),
2196            JoinOperator::LeftSemi(constraint) => write!(
2197                f,
2198                " {}LEFT SEMI JOIN {}{}",
2199                prefix(constraint),
2200                self.relation,
2201                suffix(constraint)
2202            ),
2203            JoinOperator::RightSemi(constraint) => write!(
2204                f,
2205                " {}RIGHT SEMI JOIN {}{}",
2206                prefix(constraint),
2207                self.relation,
2208                suffix(constraint)
2209            ),
2210            JoinOperator::Anti(constraint) => write!(
2211                f,
2212                " {}ANTI JOIN {}{}",
2213                prefix(constraint),
2214                self.relation,
2215                suffix(constraint)
2216            ),
2217            JoinOperator::LeftAnti(constraint) => write!(
2218                f,
2219                " {}LEFT ANTI JOIN {}{}",
2220                prefix(constraint),
2221                self.relation,
2222                suffix(constraint)
2223            ),
2224            JoinOperator::RightAnti(constraint) => write!(
2225                f,
2226                " {}RIGHT ANTI JOIN {}{}",
2227                prefix(constraint),
2228                self.relation,
2229                suffix(constraint)
2230            ),
2231            JoinOperator::CrossApply => write!(f, " CROSS APPLY {}", self.relation),
2232            JoinOperator::OuterApply => write!(f, " OUTER APPLY {}", self.relation),
2233            JoinOperator::AsOf {
2234                match_condition,
2235                constraint,
2236            } => write!(
2237                f,
2238                " ASOF JOIN {} MATCH_CONDITION ({match_condition}){}",
2239                self.relation,
2240                suffix(constraint)
2241            ),
2242            JoinOperator::StraightJoin(constraint) => {
2243                write!(f, " STRAIGHT_JOIN {}{}", self.relation, suffix(constraint))
2244            }
2245        }
2246    }
2247}
2248
2249#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2250#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2251#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2252pub enum JoinOperator {
2253    Join(JoinConstraint),
2254    Inner(JoinConstraint),
2255    Left(JoinConstraint),
2256    LeftOuter(JoinConstraint),
2257    Right(JoinConstraint),
2258    RightOuter(JoinConstraint),
2259    FullOuter(JoinConstraint),
2260    CrossJoin,
2261    /// SEMI (non-standard)
2262    Semi(JoinConstraint),
2263    /// LEFT SEMI (non-standard)
2264    LeftSemi(JoinConstraint),
2265    /// RIGHT SEMI (non-standard)
2266    RightSemi(JoinConstraint),
2267    /// ANTI (non-standard)
2268    Anti(JoinConstraint),
2269    /// LEFT ANTI (non-standard)
2270    LeftAnti(JoinConstraint),
2271    /// RIGHT ANTI (non-standard)
2272    RightAnti(JoinConstraint),
2273    /// CROSS APPLY (non-standard)
2274    CrossApply,
2275    /// OUTER APPLY (non-standard)
2276    OuterApply,
2277    /// `ASOF` joins are used for joining tables containing time-series data
2278    /// whose timestamp columns do not match exactly.
2279    ///
2280    /// See <https://docs.snowflake.com/en/sql-reference/constructs/asof-join>.
2281    AsOf {
2282        match_condition: Expr,
2283        constraint: JoinConstraint,
2284    },
2285    /// STRAIGHT_JOIN (non-standard)
2286    ///
2287    /// See <https://dev.mysql.com/doc/refman/8.4/en/join.html>.
2288    StraightJoin(JoinConstraint),
2289}
2290
2291#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2292#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2293#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2294pub enum JoinConstraint {
2295    On(Expr),
2296    Using(Vec<ObjectName>),
2297    Natural,
2298    None,
2299}
2300
2301#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2302#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2303#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2304pub enum OrderByKind {
2305    /// ALL syntax of [DuckDB] and [ClickHouse].
2306    ///
2307    /// [DuckDB]:  <https://duckdb.org/docs/sql/query_syntax/orderby>
2308    /// [ClickHouse]: <https://clickhouse.com/docs/en/sql-reference/statements/select/order-by>
2309    All(OrderByOptions),
2310
2311    /// Expressions
2312    Expressions(Vec<OrderByExpr>),
2313}
2314
2315#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2316#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2317#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2318pub struct OrderBy {
2319    pub kind: OrderByKind,
2320
2321    /// Optional: `INTERPOLATE`
2322    /// Supported by [ClickHouse syntax]
2323    pub interpolate: Option<Interpolate>,
2324}
2325
2326impl fmt::Display for OrderBy {
2327    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2328        write!(f, "ORDER BY")?;
2329        match &self.kind {
2330            OrderByKind::Expressions(exprs) => {
2331                write!(f, " {}", display_comma_separated(exprs))?;
2332            }
2333            OrderByKind::All(all) => {
2334                write!(f, " ALL{}", all)?;
2335            }
2336        }
2337
2338        if let Some(ref interpolate) = self.interpolate {
2339            match &interpolate.exprs {
2340                Some(exprs) => write!(f, " INTERPOLATE ({})", display_comma_separated(exprs))?,
2341                None => write!(f, " INTERPOLATE")?,
2342            }
2343        }
2344
2345        Ok(())
2346    }
2347}
2348
2349/// An `ORDER BY` expression
2350#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2351#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2352#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2353pub struct OrderByExpr {
2354    pub expr: Expr,
2355    pub options: OrderByOptions,
2356    /// Optional: `WITH FILL`
2357    /// Supported by [ClickHouse syntax]: <https://clickhouse.com/docs/en/sql-reference/statements/select/order-by#order-by-expr-with-fill-modifier>
2358    pub with_fill: Option<WithFill>,
2359}
2360
2361impl fmt::Display for OrderByExpr {
2362    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2363        write!(f, "{}{}", self.expr, self.options)?;
2364        if let Some(ref with_fill) = self.with_fill {
2365            write!(f, " {}", with_fill)?
2366        }
2367        Ok(())
2368    }
2369}
2370
2371/// ClickHouse `WITH FILL` modifier for `ORDER BY` clause.
2372/// Supported by [ClickHouse syntax]
2373///
2374/// [ClickHouse syntax]: <https://clickhouse.com/docs/en/sql-reference/statements/select/order-by#order-by-expr-with-fill-modifier>
2375#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2376#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2377#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2378pub struct WithFill {
2379    pub from: Option<Expr>,
2380    pub to: Option<Expr>,
2381    pub step: Option<Expr>,
2382}
2383
2384impl fmt::Display for WithFill {
2385    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2386        write!(f, "WITH FILL")?;
2387        if let Some(ref from) = self.from {
2388            write!(f, " FROM {}", from)?;
2389        }
2390        if let Some(ref to) = self.to {
2391            write!(f, " TO {}", to)?;
2392        }
2393        if let Some(ref step) = self.step {
2394            write!(f, " STEP {}", step)?;
2395        }
2396        Ok(())
2397    }
2398}
2399
2400/// ClickHouse `INTERPOLATE` clause for use in `ORDER BY` clause when using `WITH FILL` modifier.
2401/// Supported by [ClickHouse syntax]
2402///
2403/// [ClickHouse syntax]: <https://clickhouse.com/docs/en/sql-reference/statements/select/order-by#order-by-expr-with-fill-modifier>
2404#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2405#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2406#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2407pub struct InterpolateExpr {
2408    pub column: Ident,
2409    pub expr: Option<Expr>,
2410}
2411
2412#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2413#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2414#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2415pub struct Interpolate {
2416    pub exprs: Option<Vec<InterpolateExpr>>,
2417}
2418
2419impl fmt::Display for InterpolateExpr {
2420    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2421        write!(f, "{}", self.column)?;
2422        if let Some(ref expr) = self.expr {
2423            write!(f, " AS {}", expr)?;
2424        }
2425        Ok(())
2426    }
2427}
2428
2429#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2430#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2431#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2432pub struct OrderByOptions {
2433    /// Optional `ASC` or `DESC`
2434    pub asc: Option<bool>,
2435    /// Optional `NULLS FIRST` or `NULLS LAST`
2436    pub nulls_first: Option<bool>,
2437}
2438
2439impl fmt::Display for OrderByOptions {
2440    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2441        match self.asc {
2442            Some(true) => write!(f, " ASC")?,
2443            Some(false) => write!(f, " DESC")?,
2444            None => (),
2445        }
2446        match self.nulls_first {
2447            Some(true) => write!(f, " NULLS FIRST")?,
2448            Some(false) => write!(f, " NULLS LAST")?,
2449            None => (),
2450        }
2451        Ok(())
2452    }
2453}
2454
2455#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2456#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2457#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2458pub enum LimitClause {
2459    /// Standard SQL syntax
2460    ///
2461    /// `LIMIT <limit> [BY <expr>,<expr>,...] [OFFSET <offset>]`
2462    LimitOffset {
2463        /// `LIMIT { <N> | ALL }`
2464        limit: Option<Expr>,
2465        /// `OFFSET <N> [ { ROW | ROWS } ]`
2466        offset: Option<Offset>,
2467        /// `BY { <expr>,<expr>,... } }`
2468        ///
2469        /// [ClickHouse](https://clickhouse.com/docs/sql-reference/statements/select/limit-by)
2470        limit_by: Vec<Expr>,
2471    },
2472    /// [MySQL]-specific syntax; the order of expressions is reversed.
2473    ///
2474    /// `LIMIT <offset>, <limit>`
2475    ///
2476    /// [MySQL]: https://dev.mysql.com/doc/refman/8.4/en/select.html
2477    OffsetCommaLimit { offset: Expr, limit: Expr },
2478}
2479
2480impl fmt::Display for LimitClause {
2481    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2482        match self {
2483            LimitClause::LimitOffset {
2484                limit,
2485                limit_by,
2486                offset,
2487            } => {
2488                if let Some(ref limit) = limit {
2489                    write!(f, " LIMIT {limit}")?;
2490                }
2491                if let Some(ref offset) = offset {
2492                    write!(f, " {offset}")?;
2493                }
2494                if !limit_by.is_empty() {
2495                    debug_assert!(limit.is_some());
2496                    write!(f, " BY {}", display_separated(limit_by, ", "))?;
2497                }
2498                Ok(())
2499            }
2500            LimitClause::OffsetCommaLimit { offset, limit } => {
2501                write!(f, " LIMIT {}, {}", offset, limit)
2502            }
2503        }
2504    }
2505}
2506
2507#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2508#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2509#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2510pub struct Offset {
2511    pub value: Expr,
2512    pub rows: OffsetRows,
2513}
2514
2515impl fmt::Display for Offset {
2516    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2517        write!(f, "OFFSET {}{}", self.value, self.rows)
2518    }
2519}
2520
2521/// Stores the keyword after `OFFSET <number>`
2522#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2523#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2524#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2525pub enum OffsetRows {
2526    /// Omitting ROW/ROWS is non-standard MySQL quirk.
2527    None,
2528    Row,
2529    Rows,
2530}
2531
2532impl fmt::Display for OffsetRows {
2533    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2534        match self {
2535            OffsetRows::None => Ok(()),
2536            OffsetRows::Row => write!(f, " ROW"),
2537            OffsetRows::Rows => write!(f, " ROWS"),
2538        }
2539    }
2540}
2541
2542/// Pipe syntax, first introduced in Google BigQuery.
2543/// Example:
2544///
2545/// ```sql
2546/// FROM Produce
2547/// |> WHERE sales > 0
2548/// |> AGGREGATE SUM(sales) AS total_sales, COUNT(*) AS num_sales
2549///    GROUP BY item;
2550/// ```
2551///
2552/// See <https://cloud.google.com/bigquery/docs/reference/standard-sql/pipe-syntax#pipe_syntax>
2553#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2554#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2555#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2556pub enum PipeOperator {
2557    /// Limits the number of rows to return in a query, with an optional OFFSET clause to skip over rows.
2558    ///
2559    /// Syntax: `|> LIMIT <n> [OFFSET <m>]`
2560    ///
2561    /// See more at <https://cloud.google.com/bigquery/docs/reference/standard-sql/pipe-syntax#limit_pipe_operator>
2562    Limit { expr: Expr, offset: Option<Expr> },
2563    /// Filters the results of the input table.
2564    ///
2565    /// Syntax: `|> WHERE <condition>`
2566    ///
2567    /// See more at <https://cloud.google.com/bigquery/docs/reference/standard-sql/pipe-syntax#where_pipe_operator>
2568    Where { expr: Expr },
2569    /// `ORDER BY <expr> [ASC|DESC], ...`
2570    OrderBy { exprs: Vec<OrderByExpr> },
2571    /// Produces a new table with the listed columns, similar to the outermost SELECT clause in a table subquery in standard syntax.
2572    ///
2573    /// Syntax `|> SELECT <expr> [[AS] alias], ...`
2574    ///
2575    /// See more at <https://cloud.google.com/bigquery/docs/reference/standard-sql/pipe-syntax#select_pipe_operator>
2576    Select { exprs: Vec<SelectItem> },
2577    /// Propagates the existing table and adds computed columns, similar to SELECT *, new_column in standard syntax.
2578    ///
2579    /// Syntax: `|> EXTEND <expr> [[AS] alias], ...`
2580    ///
2581    /// See more at <https://cloud.google.com/bigquery/docs/reference/standard-sql/pipe-syntax#extend_pipe_operator>
2582    Extend { exprs: Vec<SelectItem> },
2583    /// Replaces the value of a column in the current table, similar to SELECT * REPLACE (expression AS column) in standard syntax.
2584    ///
2585    /// Syntax: `|> SET <column> = <expression>, ...`
2586    ///
2587    /// See more at <https://cloud.google.com/bigquery/docs/reference/standard-sql/pipe-syntax#set_pipe_operator>
2588    Set { assignments: Vec<Assignment> },
2589    /// Removes listed columns from the current table, similar to SELECT * EXCEPT (column) in standard syntax.
2590    ///
2591    /// Syntax: `|> DROP <column>, ...`
2592    ///
2593    /// See more at <https://cloud.google.com/bigquery/docs/reference/standard-sql/pipe-syntax#drop_pipe_operator>
2594    Drop { columns: Vec<Ident> },
2595    /// Introduces a table alias for the input table, similar to applying the AS alias clause on a table subquery in standard syntax.
2596    ///
2597    /// Syntax: `|> AS <alias>`
2598    ///
2599    /// See more at <https://cloud.google.com/bigquery/docs/reference/standard-sql/pipe-syntax#as_pipe_operator>
2600    As { alias: Ident },
2601    /// Performs aggregation on data across grouped rows or an entire table.
2602    ///
2603    /// Syntax: `|> AGGREGATE <agg_expr> [[AS] alias], ...`
2604    ///
2605    /// Syntax:
2606    /// ```norust
2607    /// |> AGGREGATE [<agg_expr> [[AS] alias], ...]
2608    /// GROUP BY <grouping_expr> [AS alias], ...
2609    /// ```
2610    ///
2611    /// See more at <https://cloud.google.com/bigquery/docs/reference/standard-sql/pipe-syntax#aggregate_pipe_operator>
2612    Aggregate {
2613        full_table_exprs: Vec<ExprWithAliasAndOrderBy>,
2614        group_by_expr: Vec<ExprWithAliasAndOrderBy>,
2615    },
2616}
2617
2618impl fmt::Display for PipeOperator {
2619    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2620        match self {
2621            PipeOperator::Select { exprs } => {
2622                write!(f, "SELECT {}", display_comma_separated(exprs.as_slice()))
2623            }
2624            PipeOperator::Extend { exprs } => {
2625                write!(f, "EXTEND {}", display_comma_separated(exprs.as_slice()))
2626            }
2627            PipeOperator::Set { assignments } => {
2628                write!(f, "SET {}", display_comma_separated(assignments.as_slice()))
2629            }
2630            PipeOperator::Drop { columns } => {
2631                write!(f, "DROP {}", display_comma_separated(columns.as_slice()))
2632            }
2633            PipeOperator::As { alias } => {
2634                write!(f, "AS {}", alias)
2635            }
2636            PipeOperator::Limit { expr, offset } => {
2637                write!(f, "LIMIT {}", expr)?;
2638                if let Some(offset) = offset {
2639                    write!(f, " OFFSET {}", offset)?;
2640                }
2641                Ok(())
2642            }
2643            PipeOperator::Aggregate {
2644                full_table_exprs,
2645                group_by_expr,
2646            } => {
2647                write!(f, "AGGREGATE")?;
2648                if !full_table_exprs.is_empty() {
2649                    write!(
2650                        f,
2651                        " {}",
2652                        display_comma_separated(full_table_exprs.as_slice())
2653                    )?;
2654                }
2655                if !group_by_expr.is_empty() {
2656                    write!(f, " GROUP BY {}", display_comma_separated(group_by_expr))?;
2657                }
2658                Ok(())
2659            }
2660
2661            PipeOperator::Where { expr } => {
2662                write!(f, "WHERE {}", expr)
2663            }
2664            PipeOperator::OrderBy { exprs } => {
2665                write!(f, "ORDER BY {}", display_comma_separated(exprs.as_slice()))
2666            }
2667        }
2668    }
2669}
2670
2671#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2672#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2673#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2674pub struct Fetch {
2675    pub with_ties: bool,
2676    pub percent: bool,
2677    pub quantity: Option<Expr>,
2678}
2679
2680impl fmt::Display for Fetch {
2681    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2682        let extension = if self.with_ties { "WITH TIES" } else { "ONLY" };
2683        if let Some(ref quantity) = self.quantity {
2684            let percent = if self.percent { " PERCENT" } else { "" };
2685            write!(f, "FETCH FIRST {quantity}{percent} ROWS {extension}")
2686        } else {
2687            write!(f, "FETCH FIRST ROWS {extension}")
2688        }
2689    }
2690}
2691
2692#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2693#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2694#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2695pub struct LockClause {
2696    pub lock_type: LockType,
2697    pub of: Option<ObjectName>,
2698    pub nonblock: Option<NonBlock>,
2699}
2700
2701impl fmt::Display for LockClause {
2702    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2703        write!(f, "FOR {}", &self.lock_type)?;
2704        if let Some(ref of) = self.of {
2705            write!(f, " OF {of}")?;
2706        }
2707        if let Some(ref nb) = self.nonblock {
2708            write!(f, " {nb}")?;
2709        }
2710        Ok(())
2711    }
2712}
2713
2714#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2715#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2716#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2717pub enum LockType {
2718    Share,
2719    Update,
2720}
2721
2722impl fmt::Display for LockType {
2723    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2724        let select_lock = match self {
2725            LockType::Share => "SHARE",
2726            LockType::Update => "UPDATE",
2727        };
2728        write!(f, "{select_lock}")
2729    }
2730}
2731
2732#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2733#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2734#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2735pub enum NonBlock {
2736    Nowait,
2737    SkipLocked,
2738}
2739
2740impl fmt::Display for NonBlock {
2741    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2742        let nonblock = match self {
2743            NonBlock::Nowait => "NOWAIT",
2744            NonBlock::SkipLocked => "SKIP LOCKED",
2745        };
2746        write!(f, "{nonblock}")
2747    }
2748}
2749
2750#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2751#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2752#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2753pub enum Distinct {
2754    /// DISTINCT
2755    Distinct,
2756
2757    /// DISTINCT ON({column names})
2758    On(Vec<Expr>),
2759}
2760
2761impl fmt::Display for Distinct {
2762    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2763        match self {
2764            Distinct::Distinct => write!(f, "DISTINCT"),
2765            Distinct::On(col_names) => {
2766                let col_names = display_comma_separated(col_names);
2767                write!(f, "DISTINCT ON ({col_names})")
2768            }
2769        }
2770    }
2771}
2772
2773#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2774#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2775#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2776pub struct Top {
2777    /// SQL semantic equivalent of LIMIT but with same structure as FETCH.
2778    /// MSSQL only.
2779    pub with_ties: bool,
2780    /// MSSQL only.
2781    pub percent: bool,
2782    pub quantity: Option<TopQuantity>,
2783}
2784
2785#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2786#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2787#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2788pub enum TopQuantity {
2789    // A parenthesized expression. MSSQL only.
2790    Expr(Expr),
2791    // An unparenthesized integer constant.
2792    Constant(u64),
2793}
2794
2795impl fmt::Display for Top {
2796    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2797        let extension = if self.with_ties { " WITH TIES" } else { "" };
2798        if let Some(ref quantity) = self.quantity {
2799            let percent = if self.percent { " PERCENT" } else { "" };
2800            match quantity {
2801                TopQuantity::Expr(quantity) => write!(f, "TOP ({quantity}){percent}{extension}"),
2802                TopQuantity::Constant(quantity) => {
2803                    write!(f, "TOP {quantity}{percent}{extension}")
2804                }
2805            }
2806        } else {
2807            write!(f, "TOP{extension}")
2808        }
2809    }
2810}
2811
2812#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2813#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2814#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2815pub struct Values {
2816    /// Was there an explicit ROWs keyword (MySQL)?
2817    /// <https://dev.mysql.com/doc/refman/8.0/en/values.html>
2818    pub explicit_row: bool,
2819    pub rows: Vec<Vec<Expr>>,
2820}
2821
2822impl fmt::Display for Values {
2823    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2824        write!(f, "VALUES ")?;
2825        let prefix = if self.explicit_row { "ROW" } else { "" };
2826        let mut delim = "";
2827        for row in &self.rows {
2828            write!(f, "{delim}")?;
2829            delim = ", ";
2830            write!(f, "{prefix}({})", display_comma_separated(row))?;
2831        }
2832        Ok(())
2833    }
2834}
2835
2836#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2837#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2838#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2839pub struct SelectInto {
2840    pub temporary: bool,
2841    pub unlogged: bool,
2842    pub table: bool,
2843    pub name: ObjectName,
2844}
2845
2846impl fmt::Display for SelectInto {
2847    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2848        let temporary = if self.temporary { " TEMPORARY" } else { "" };
2849        let unlogged = if self.unlogged { " UNLOGGED" } else { "" };
2850        let table = if self.table { " TABLE" } else { "" };
2851
2852        write!(f, "INTO{}{}{} {}", temporary, unlogged, table, self.name)
2853    }
2854}
2855
2856/// ClickHouse supports GROUP BY WITH modifiers(includes ROLLUP|CUBE|TOTALS).
2857/// e.g. GROUP BY year WITH ROLLUP WITH TOTALS
2858///
2859/// [ClickHouse]: <https://clickhouse.com/docs/en/sql-reference/statements/select/group-by#rollup-modifier>
2860#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2861#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2862#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2863pub enum GroupByWithModifier {
2864    Rollup,
2865    Cube,
2866    Totals,
2867    /// Hive supports GROUP BY GROUPING SETS syntax.
2868    /// e.g. GROUP BY year , month GROUPING SETS((year,month),(year),(month))
2869    ///
2870    /// [Hive]: <https://cwiki.apache.org/confluence/pages/viewpage.action?pageId=30151323#EnhancedAggregation,Cube,GroupingandRollup-GROUPINGSETSclause>
2871    GroupingSets(Expr),
2872}
2873
2874impl fmt::Display for GroupByWithModifier {
2875    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2876        match self {
2877            GroupByWithModifier::Rollup => write!(f, "WITH ROLLUP"),
2878            GroupByWithModifier::Cube => write!(f, "WITH CUBE"),
2879            GroupByWithModifier::Totals => write!(f, "WITH TOTALS"),
2880            GroupByWithModifier::GroupingSets(expr) => {
2881                write!(f, "{expr}")
2882            }
2883        }
2884    }
2885}
2886
2887#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2888#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2889#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2890pub enum GroupByExpr {
2891    /// ALL syntax of [Snowflake], [DuckDB] and [ClickHouse].
2892    ///
2893    /// [Snowflake]: <https://docs.snowflake.com/en/sql-reference/constructs/group-by#label-group-by-all-columns>
2894    /// [DuckDB]:  <https://duckdb.org/docs/sql/query_syntax/groupby.html>
2895    /// [ClickHouse]: <https://clickhouse.com/docs/en/sql-reference/statements/select/group-by#group-by-all>
2896    ///
2897    /// ClickHouse also supports WITH modifiers after GROUP BY ALL and expressions.
2898    ///
2899    /// [ClickHouse]: <https://clickhouse.com/docs/en/sql-reference/statements/select/group-by#rollup-modifier>
2900    All(Vec<GroupByWithModifier>),
2901
2902    /// Expressions
2903    Expressions(Vec<Expr>, Vec<GroupByWithModifier>),
2904}
2905
2906impl fmt::Display for GroupByExpr {
2907    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2908        match self {
2909            GroupByExpr::All(modifiers) => {
2910                write!(f, "GROUP BY ALL")?;
2911                if !modifiers.is_empty() {
2912                    write!(f, " {}", display_separated(modifiers, " "))?;
2913                }
2914                Ok(())
2915            }
2916            GroupByExpr::Expressions(col_names, modifiers) => {
2917                let col_names = display_comma_separated(col_names);
2918                write!(f, "GROUP BY {col_names}")?;
2919                if !modifiers.is_empty() {
2920                    write!(f, " {}", display_separated(modifiers, " "))?;
2921                }
2922                Ok(())
2923            }
2924        }
2925    }
2926}
2927
2928/// FORMAT identifier or FORMAT NULL clause, specific to ClickHouse.
2929///
2930/// [ClickHouse]: <https://clickhouse.com/docs/en/sql-reference/statements/select/format>
2931#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2932#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2933#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2934pub enum FormatClause {
2935    Identifier(Ident),
2936    Null,
2937}
2938
2939impl fmt::Display for FormatClause {
2940    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2941        match self {
2942            FormatClause::Identifier(ident) => write!(f, "FORMAT {}", ident),
2943            FormatClause::Null => write!(f, "FORMAT NULL"),
2944        }
2945    }
2946}
2947
2948/// FORMAT identifier in input context, specific to ClickHouse.
2949///
2950/// [ClickHouse]: <https://clickhouse.com/docs/en/interfaces/formats>
2951#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2952#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2953#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2954pub struct InputFormatClause {
2955    pub ident: Ident,
2956    pub values: Vec<Expr>,
2957}
2958
2959impl fmt::Display for InputFormatClause {
2960    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2961        write!(f, "FORMAT {}", self.ident)?;
2962
2963        if !self.values.is_empty() {
2964            write!(f, " {}", display_comma_separated(self.values.as_slice()))?;
2965        }
2966
2967        Ok(())
2968    }
2969}
2970
2971/// FOR XML or FOR JSON clause, specific to MSSQL
2972/// (formats the output of a query as XML or JSON)
2973#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2974#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2975#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2976pub enum ForClause {
2977    Browse,
2978    Json {
2979        for_json: ForJson,
2980        root: Option<String>,
2981        include_null_values: bool,
2982        without_array_wrapper: bool,
2983    },
2984    Xml {
2985        for_xml: ForXml,
2986        elements: bool,
2987        binary_base64: bool,
2988        root: Option<String>,
2989        r#type: bool,
2990    },
2991}
2992
2993impl fmt::Display for ForClause {
2994    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2995        match self {
2996            ForClause::Browse => write!(f, "FOR BROWSE"),
2997            ForClause::Json {
2998                for_json,
2999                root,
3000                include_null_values,
3001                without_array_wrapper,
3002            } => {
3003                write!(f, "FOR JSON ")?;
3004                write!(f, "{}", for_json)?;
3005                if let Some(root) = root {
3006                    write!(f, ", ROOT('{}')", root)?;
3007                }
3008                if *include_null_values {
3009                    write!(f, ", INCLUDE_NULL_VALUES")?;
3010                }
3011                if *without_array_wrapper {
3012                    write!(f, ", WITHOUT_ARRAY_WRAPPER")?;
3013                }
3014                Ok(())
3015            }
3016            ForClause::Xml {
3017                for_xml,
3018                elements,
3019                binary_base64,
3020                root,
3021                r#type,
3022            } => {
3023                write!(f, "FOR XML ")?;
3024                write!(f, "{}", for_xml)?;
3025                if *binary_base64 {
3026                    write!(f, ", BINARY BASE64")?;
3027                }
3028                if *r#type {
3029                    write!(f, ", TYPE")?;
3030                }
3031                if let Some(root) = root {
3032                    write!(f, ", ROOT('{}')", root)?;
3033                }
3034                if *elements {
3035                    write!(f, ", ELEMENTS")?;
3036                }
3037                Ok(())
3038            }
3039        }
3040    }
3041}
3042
3043#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3044#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3045#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3046pub enum ForXml {
3047    Raw(Option<String>),
3048    Auto,
3049    Explicit,
3050    Path(Option<String>),
3051}
3052
3053impl fmt::Display for ForXml {
3054    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3055        match self {
3056            ForXml::Raw(root) => {
3057                write!(f, "RAW")?;
3058                if let Some(root) = root {
3059                    write!(f, "('{}')", root)?;
3060                }
3061                Ok(())
3062            }
3063            ForXml::Auto => write!(f, "AUTO"),
3064            ForXml::Explicit => write!(f, "EXPLICIT"),
3065            ForXml::Path(root) => {
3066                write!(f, "PATH")?;
3067                if let Some(root) = root {
3068                    write!(f, "('{}')", root)?;
3069                }
3070                Ok(())
3071            }
3072        }
3073    }
3074}
3075
3076#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3077#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3078#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3079pub enum ForJson {
3080    Auto,
3081    Path,
3082}
3083
3084impl fmt::Display for ForJson {
3085    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3086        match self {
3087            ForJson::Auto => write!(f, "AUTO"),
3088            ForJson::Path => write!(f, "PATH"),
3089        }
3090    }
3091}
3092
3093/// A single column definition in MySQL's `JSON_TABLE` table valued function.
3094///
3095/// See
3096/// - [MySQL's JSON_TABLE documentation](https://dev.mysql.com/doc/refman/8.0/en/json-table-functions.html#function_json-table)
3097/// - [Oracle's JSON_TABLE documentation](https://docs.oracle.com/en/database/oracle/oracle-database/21/sqlrf/JSON_TABLE.html)
3098/// - [MariaDB's JSON_TABLE documentation](https://mariadb.com/kb/en/json_table/)
3099///
3100/// ```sql
3101/// SELECT *
3102/// FROM JSON_TABLE(
3103///     '["a", "b"]',
3104///     '$[*]' COLUMNS (
3105///         name FOR ORDINALITY,
3106///         value VARCHAR(20) PATH '$',
3107///         NESTED PATH '$[*]' COLUMNS (
3108///             value VARCHAR(20) PATH '$'
3109///         )
3110///     )
3111/// ) AS jt;
3112/// ```
3113#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3114#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3115#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3116pub enum JsonTableColumn {
3117    /// A named column with a JSON path
3118    Named(JsonTableNamedColumn),
3119    /// The FOR ORDINALITY column, which is a special column that returns the index of the current row in a JSON array.
3120    ForOrdinality(Ident),
3121    /// A set of nested columns, which extracts data from a nested JSON array.
3122    Nested(JsonTableNestedColumn),
3123}
3124
3125impl fmt::Display for JsonTableColumn {
3126    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3127        match self {
3128            JsonTableColumn::Named(json_table_named_column) => {
3129                write!(f, "{json_table_named_column}")
3130            }
3131            JsonTableColumn::ForOrdinality(ident) => write!(f, "{} FOR ORDINALITY", ident),
3132            JsonTableColumn::Nested(json_table_nested_column) => {
3133                write!(f, "{json_table_nested_column}")
3134            }
3135        }
3136    }
3137}
3138
3139/// A nested column in a JSON_TABLE column list
3140///
3141/// See <https://mariadb.com/kb/en/json_table/#nested-paths>
3142#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3143#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3144#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3145pub struct JsonTableNestedColumn {
3146    pub path: Value,
3147    pub columns: Vec<JsonTableColumn>,
3148}
3149
3150impl fmt::Display for JsonTableNestedColumn {
3151    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3152        write!(
3153            f,
3154            "NESTED PATH {} COLUMNS ({})",
3155            self.path,
3156            display_comma_separated(&self.columns)
3157        )
3158    }
3159}
3160
3161/// A single column definition in MySQL's `JSON_TABLE` table valued function.
3162///
3163/// See <https://mariadb.com/kb/en/json_table/#path-columns>
3164///
3165/// ```sql
3166///         value VARCHAR(20) PATH '$'
3167/// ```
3168#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3169#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3170#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3171pub struct JsonTableNamedColumn {
3172    /// The name of the column to be extracted.
3173    pub name: Ident,
3174    /// The type of the column to be extracted.
3175    pub r#type: DataType,
3176    /// The path to the column to be extracted. Must be a literal string.
3177    pub path: Value,
3178    /// true if the column is a boolean set to true if the given path exists
3179    pub exists: bool,
3180    /// The empty handling clause of the column
3181    pub on_empty: Option<JsonTableColumnErrorHandling>,
3182    /// The error handling clause of the column
3183    pub on_error: Option<JsonTableColumnErrorHandling>,
3184}
3185
3186impl fmt::Display for JsonTableNamedColumn {
3187    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3188        write!(
3189            f,
3190            "{} {}{} PATH {}",
3191            self.name,
3192            self.r#type,
3193            if self.exists { " EXISTS" } else { "" },
3194            self.path
3195        )?;
3196        if let Some(on_empty) = &self.on_empty {
3197            write!(f, " {} ON EMPTY", on_empty)?;
3198        }
3199        if let Some(on_error) = &self.on_error {
3200            write!(f, " {} ON ERROR", on_error)?;
3201        }
3202        Ok(())
3203    }
3204}
3205
3206/// Stores the error handling clause of a `JSON_TABLE` table valued function:
3207/// {NULL | DEFAULT json_string | ERROR} ON {ERROR | EMPTY }
3208#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3209#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3210#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3211pub enum JsonTableColumnErrorHandling {
3212    Null,
3213    Default(Value),
3214    Error,
3215}
3216
3217impl fmt::Display for JsonTableColumnErrorHandling {
3218    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3219        match self {
3220            JsonTableColumnErrorHandling::Null => write!(f, "NULL"),
3221            JsonTableColumnErrorHandling::Default(json_string) => {
3222                write!(f, "DEFAULT {}", json_string)
3223            }
3224            JsonTableColumnErrorHandling::Error => write!(f, "ERROR"),
3225        }
3226    }
3227}
3228
3229/// A single column definition in MSSQL's `OPENJSON WITH` clause.
3230///
3231/// ```sql
3232/// colName type [ column_path ] [ AS JSON ]
3233/// ```
3234///
3235/// Reference: <https://learn.microsoft.com/en-us/sql/t-sql/functions/openjson-transact-sql?view=sql-server-ver16#syntax>
3236#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3237#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3238#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3239pub struct OpenJsonTableColumn {
3240    /// The name of the column to be extracted.
3241    pub name: Ident,
3242    /// The type of the column to be extracted.
3243    pub r#type: DataType,
3244    /// The path to the column to be extracted. Must be a literal string.
3245    pub path: Option<String>,
3246    /// The `AS JSON` option.
3247    pub as_json: bool,
3248}
3249
3250impl fmt::Display for OpenJsonTableColumn {
3251    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3252        write!(f, "{} {}", self.name, self.r#type)?;
3253        if let Some(path) = &self.path {
3254            write!(f, " '{}'", value::escape_single_quote_string(path))?;
3255        }
3256        if self.as_json {
3257            write!(f, " AS JSON")?;
3258        }
3259        Ok(())
3260    }
3261}
3262
3263/// BigQuery supports ValueTables which have 2 modes:
3264/// `SELECT AS STRUCT`
3265/// `SELECT AS VALUE`
3266/// <https://cloud.google.com/bigquery/docs/reference/standard-sql/query-syntax#value_tables>
3267#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3268#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3269#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3270pub enum ValueTableMode {
3271    AsStruct,
3272    AsValue,
3273}
3274
3275impl fmt::Display for ValueTableMode {
3276    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3277        match self {
3278            ValueTableMode::AsStruct => write!(f, "AS STRUCT"),
3279            ValueTableMode::AsValue => write!(f, "AS VALUE"),
3280        }
3281    }
3282}
3283
3284/// The `FROM` clause of an `UPDATE TABLE` statement
3285#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3286#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3287#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3288pub enum UpdateTableFromKind {
3289    /// Update Statement where the 'FROM' clause is before the 'SET' keyword (Supported by Snowflake)
3290    /// For Example: `UPDATE FROM t1 SET t1.name='aaa'`
3291    BeforeSet(Vec<TableWithJoins>),
3292    /// Update Statement where the 'FROM' clause is after the 'SET' keyword (Which is the standard way)
3293    /// For Example: `UPDATE SET t1.name='aaa' FROM t1`
3294    AfterSet(Vec<TableWithJoins>),
3295}
3296
3297/// Defines the options for an XmlTable column: Named or ForOrdinality
3298#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3299#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3300#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3301pub enum XmlTableColumnOption {
3302    /// A named column with a type, optional path, and default value.
3303    NamedInfo {
3304        /// The type of the column to be extracted.
3305        r#type: DataType,
3306        /// The path to the column to be extracted. If None, defaults to the column name.
3307        path: Option<Expr>,
3308        /// Default value if path does not match
3309        default: Option<Expr>,
3310        /// Whether the column is nullable (NULL=true, NOT NULL=false)
3311        nullable: bool,
3312    },
3313    /// The FOR ORDINALITY marker
3314    ForOrdinality,
3315}
3316
3317/// A single column definition in XMLTABLE
3318///
3319/// ```sql
3320/// COLUMNS
3321///     id int PATH '@id',
3322///     ordinality FOR ORDINALITY,
3323///     "COUNTRY_NAME" text,
3324///     country_id text PATH 'COUNTRY_ID',
3325///     size_sq_km float PATH 'SIZE[@unit = "sq_km"]',
3326///     size_other text PATH 'concat(SIZE[@unit!="sq_km"], " ", SIZE[@unit!="sq_km"]/@unit)',
3327///     premier_name text PATH 'PREMIER_NAME' DEFAULT 'not specified'
3328/// ```
3329#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3330#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3331#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3332pub struct XmlTableColumn {
3333    /// The name of the column.
3334    pub name: Ident,
3335    /// Column options: type/path/default or FOR ORDINALITY
3336    pub option: XmlTableColumnOption,
3337}
3338
3339impl fmt::Display for XmlTableColumn {
3340    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3341        write!(f, "{}", self.name)?;
3342        match &self.option {
3343            XmlTableColumnOption::NamedInfo {
3344                r#type,
3345                path,
3346                default,
3347                nullable,
3348            } => {
3349                write!(f, " {}", r#type)?;
3350                if let Some(p) = path {
3351                    write!(f, " PATH {}", p)?;
3352                }
3353                if let Some(d) = default {
3354                    write!(f, " DEFAULT {}", d)?;
3355                }
3356                if !*nullable {
3357                    write!(f, " NOT NULL")?;
3358                }
3359                Ok(())
3360            }
3361            XmlTableColumnOption::ForOrdinality => {
3362                write!(f, " FOR ORDINALITY")
3363            }
3364        }
3365    }
3366}
3367
3368/// Argument passed in the XMLTABLE PASSING clause
3369#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3370#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3371#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3372pub struct XmlPassingArgument {
3373    pub expr: Expr,
3374    pub alias: Option<Ident>,
3375    pub by_value: bool, // True if BY VALUE is specified
3376}
3377
3378impl fmt::Display for XmlPassingArgument {
3379    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3380        if self.by_value {
3381            write!(f, "BY VALUE ")?;
3382        }
3383        write!(f, "{}", self.expr)?;
3384        if let Some(alias) = &self.alias {
3385            write!(f, " AS {}", alias)?;
3386        }
3387        Ok(())
3388    }
3389}
3390
3391/// The PASSING clause for XMLTABLE
3392#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3393#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3394#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3395pub struct XmlPassingClause {
3396    pub arguments: Vec<XmlPassingArgument>,
3397}
3398
3399impl fmt::Display for XmlPassingClause {
3400    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3401        if !self.arguments.is_empty() {
3402            write!(f, " PASSING {}", display_comma_separated(&self.arguments))?;
3403        }
3404        Ok(())
3405    }
3406}
3407
3408/// Represents a single XML namespace definition in the XMLNAMESPACES clause.
3409///
3410/// `namespace_uri AS namespace_name`
3411#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3412#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3413#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3414pub struct XmlNamespaceDefinition {
3415    /// The namespace URI (a text expression).
3416    pub uri: Expr,
3417    /// The alias for the namespace (a simple identifier).
3418    pub name: Ident,
3419}
3420
3421impl fmt::Display for XmlNamespaceDefinition {
3422    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3423        write!(f, "{} AS {}", self.uri, self.name)
3424    }
3425}