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