sqltk_parser/ast/
query.rs

1// Licensed to the Apache Software Foundation (ASF) under one
2// or more contributor license agreements.  See the NOTICE file
3// distributed with this work for additional information
4// regarding copyright ownership.  The ASF licenses this file
5// to you under the Apache License, Version 2.0 (the
6// "License"); you may not use this file except in compliance
7// with the License.  You may obtain a copy of the License at
8//
9//   http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing,
12// software distributed under the License is distributed on an
13// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14// KIND, either express or implied.  See the License for the
15// specific language governing permissions and limitations
16// under the License.
17
18#[cfg(not(feature = "std"))]
19use alloc::{boxed::Box, vec::Vec};
20
21#[cfg(feature = "serde")]
22use serde::{Deserialize, Serialize};
23
24#[cfg(feature = "visitor")]
25use sqltk_parser_derive::{Visit, VisitMut};
26
27use crate::ast::*;
28
29/// The most complete variant of a `SELECT` query expression, optionally
30/// including `WITH`, `UNION` / other set operations, and `ORDER BY`.
31#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
32#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
33#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
34#[cfg_attr(feature = "visitor", visit(with = "visit_query"))]
35pub struct Query {
36    /// WITH (common table expressions, or CTEs)
37    pub with: Option<With>,
38    /// SELECT or UNION / EXCEPT / INTERSECT
39    pub body: Box<SetExpr>,
40    /// ORDER BY
41    pub order_by: Option<OrderBy>,
42    /// `LIMIT { <N> | ALL }`
43    pub limit: Option<Expr>,
44
45    /// `LIMIT { <N> } BY { <expr>,<expr>,... } }`
46    pub limit_by: Vec<Expr>,
47
48    /// `OFFSET <N> [ { ROW | ROWS } ]`
49    pub offset: Option<Offset>,
50    /// `FETCH { FIRST | NEXT } <N> [ PERCENT ] { ROW | ROWS } | { ONLY | WITH TIES }`
51    pub fetch: Option<Fetch>,
52    /// `FOR { UPDATE | SHARE } [ OF table_name ] [ SKIP LOCKED | NOWAIT ]`
53    pub locks: Vec<LockClause>,
54    /// `FOR XML { RAW | AUTO | EXPLICIT | PATH } [ , ELEMENTS ]`
55    /// `FOR JSON { AUTO | PATH } [ , INCLUDE_NULL_VALUES ]`
56    /// (MSSQL-specific)
57    pub for_clause: Option<ForClause>,
58    /// ClickHouse syntax: `SELECT * FROM t SETTINGS key1 = value1, key2 = value2`
59    ///
60    /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/select#settings-in-select-query)
61    pub settings: Option<Vec<Setting>>,
62    /// `SELECT * FROM t FORMAT JSONCompact`
63    ///
64    /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/select/format)
65    /// (ClickHouse-specific)
66    pub format_clause: Option<FormatClause>,
67}
68
69impl fmt::Display for Query {
70    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
71        if let Some(ref with) = self.with {
72            write!(f, "{with} ")?;
73        }
74        write!(f, "{}", self.body)?;
75        if let Some(ref order_by) = self.order_by {
76            write!(f, " {order_by}")?;
77        }
78        if let Some(ref limit) = self.limit {
79            write!(f, " LIMIT {limit}")?;
80        }
81        if let Some(ref offset) = self.offset {
82            write!(f, " {offset}")?;
83        }
84        if !self.limit_by.is_empty() {
85            write!(f, " BY {}", display_separated(&self.limit_by, ", "))?;
86        }
87        if let Some(ref settings) = self.settings {
88            write!(f, " SETTINGS {}", display_comma_separated(settings))?;
89        }
90        if let Some(ref fetch) = self.fetch {
91            write!(f, " {fetch}")?;
92        }
93        if !self.locks.is_empty() {
94            write!(f, " {}", display_separated(&self.locks, " "))?;
95        }
96        if let Some(ref for_clause) = self.for_clause {
97            write!(f, " {}", for_clause)?;
98        }
99        if let Some(ref format) = self.format_clause {
100            write!(f, " {}", format)?;
101        }
102        Ok(())
103    }
104}
105
106/// Query syntax for ClickHouse ADD PROJECTION statement.
107/// Its syntax is similar to SELECT statement, but it is used to add a new projection to a table.
108/// Syntax is `SELECT <COLUMN LIST EXPR> [GROUP BY] [ORDER BY]`
109///
110/// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/alter/projection#add-projection)
111#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
112#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
113#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
114pub struct ProjectionSelect {
115    pub projection: Vec<SelectItem>,
116    pub order_by: Option<OrderBy>,
117    pub group_by: Option<GroupByExpr>,
118}
119
120impl fmt::Display for ProjectionSelect {
121    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
122        write!(f, "SELECT {}", display_comma_separated(&self.projection))?;
123        if let Some(ref group_by) = self.group_by {
124            write!(f, " {group_by}")?;
125        }
126        if let Some(ref order_by) = self.order_by {
127            write!(f, " {order_by}")?;
128        }
129        Ok(())
130    }
131}
132
133/// A node in a tree, representing a "query body" expression, roughly:
134/// `SELECT ... [ {UNION|EXCEPT|INTERSECT} SELECT ...]`
135#[allow(clippy::large_enum_variant)]
136#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
137#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
138#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
139pub enum SetExpr {
140    /// Restricted SELECT .. FROM .. HAVING (no ORDER BY or set operations)
141    Select(Box<Select>),
142    /// Parenthesized SELECT subquery, which may include more set operations
143    /// in its body and an optional ORDER BY / LIMIT.
144    Query(Box<Query>),
145    /// UNION/EXCEPT/INTERSECT of two queries
146    SetOperation {
147        op: SetOperator,
148        set_quantifier: SetQuantifier,
149        left: Box<SetExpr>,
150        right: Box<SetExpr>,
151    },
152    Values(Values),
153    Insert(Statement),
154    Update(Statement),
155    Table(Box<Table>),
156}
157
158impl SetExpr {
159    /// If this `SetExpr` is a `SELECT`, returns the [`Select`].
160    pub fn as_select(&self) -> Option<&Select> {
161        if let Self::Select(select) = self {
162            Some(&**select)
163        } else {
164            None
165        }
166    }
167}
168
169impl fmt::Display for SetExpr {
170    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
171        match self {
172            SetExpr::Select(s) => write!(f, "{s}"),
173            SetExpr::Query(q) => write!(f, "({q})"),
174            SetExpr::Values(v) => write!(f, "{v}"),
175            SetExpr::Insert(v) => write!(f, "{v}"),
176            SetExpr::Update(v) => write!(f, "{v}"),
177            SetExpr::Table(t) => write!(f, "{t}"),
178            SetExpr::SetOperation {
179                left,
180                right,
181                op,
182                set_quantifier,
183            } => {
184                write!(f, "{left} {op}")?;
185                match set_quantifier {
186                    SetQuantifier::All
187                    | SetQuantifier::Distinct
188                    | SetQuantifier::ByName
189                    | SetQuantifier::AllByName
190                    | SetQuantifier::DistinctByName => write!(f, " {set_quantifier}")?,
191                    SetQuantifier::None => write!(f, "{set_quantifier}")?,
192                }
193                write!(f, " {right}")?;
194                Ok(())
195            }
196        }
197    }
198}
199
200#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
201#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
202#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
203pub enum SetOperator {
204    Union,
205    Except,
206    Intersect,
207}
208
209impl fmt::Display for SetOperator {
210    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
211        f.write_str(match self {
212            SetOperator::Union => "UNION",
213            SetOperator::Except => "EXCEPT",
214            SetOperator::Intersect => "INTERSECT",
215        })
216    }
217}
218
219/// A quantifier for [SetOperator].
220// TODO: Restrict parsing specific SetQuantifier in some specific dialects.
221// For example, BigQuery does not support `DISTINCT` for `EXCEPT` and `INTERSECT`
222#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
223#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
224#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
225pub enum SetQuantifier {
226    All,
227    Distinct,
228    ByName,
229    AllByName,
230    DistinctByName,
231    None,
232}
233
234impl fmt::Display for SetQuantifier {
235    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
236        match self {
237            SetQuantifier::All => write!(f, "ALL"),
238            SetQuantifier::Distinct => write!(f, "DISTINCT"),
239            SetQuantifier::ByName => write!(f, "BY NAME"),
240            SetQuantifier::AllByName => write!(f, "ALL BY NAME"),
241            SetQuantifier::DistinctByName => write!(f, "DISTINCT BY NAME"),
242            SetQuantifier::None => write!(f, ""),
243        }
244    }
245}
246
247#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
248#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
249/// A [`TABLE` command]( https://www.postgresql.org/docs/current/sql-select.html#SQL-TABLE)
250#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
251pub struct Table {
252    pub table_name: Option<String>,
253    pub schema_name: Option<String>,
254}
255
256impl fmt::Display for Table {
257    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
258        if let Some(ref schema_name) = self.schema_name {
259            write!(
260                f,
261                "TABLE {}.{}",
262                schema_name,
263                self.table_name.as_ref().unwrap(),
264            )?;
265        } else {
266            write!(f, "TABLE {}", self.table_name.as_ref().unwrap(),)?;
267        }
268        Ok(())
269    }
270}
271
272/// A restricted variant of `SELECT` (without CTEs/`ORDER BY`), which may
273/// appear either as the only body item of a `Query`, or as an operand
274/// to a set operation like `UNION`.
275#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
276#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
277#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
278pub struct Select {
279    pub distinct: Option<Distinct>,
280    /// MSSQL syntax: `TOP (<N>) [ PERCENT ] [ WITH TIES ]`
281    pub top: Option<Top>,
282    /// Whether the top was located before `ALL`/`DISTINCT`
283    pub top_before_distinct: bool,
284    /// projection expressions
285    pub projection: Vec<SelectItem>,
286    /// INTO
287    pub into: Option<SelectInto>,
288    /// FROM
289    pub from: Vec<TableWithJoins>,
290    /// LATERAL VIEWs
291    pub lateral_views: Vec<LateralView>,
292    /// ClickHouse syntax: `PREWHERE a = 1 WHERE b = 2`,
293    /// and it can be used together with WHERE selection.
294    ///
295    /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/select/prewhere)
296    pub prewhere: Option<Expr>,
297    /// WHERE
298    pub selection: Option<Expr>,
299    /// GROUP BY
300    pub group_by: GroupByExpr,
301    /// CLUSTER BY (Hive)
302    pub cluster_by: Vec<Expr>,
303    /// DISTRIBUTE BY (Hive)
304    pub distribute_by: Vec<Expr>,
305    /// SORT BY (Hive)
306    pub sort_by: Vec<Expr>,
307    /// HAVING
308    pub having: Option<Expr>,
309    /// WINDOW AS
310    pub named_window: Vec<NamedWindowDefinition>,
311    /// QUALIFY (Snowflake)
312    pub qualify: Option<Expr>,
313    /// The positioning of QUALIFY and WINDOW clauses differ between dialects.
314    /// e.g. BigQuery requires that WINDOW comes after QUALIFY, while DUCKDB accepts
315    /// WINDOW before QUALIFY.
316    /// We accept either positioning and flag the accepted variant.
317    pub window_before_qualify: bool,
318    /// BigQuery syntax: `SELECT AS VALUE | SELECT AS STRUCT`
319    pub value_table_mode: Option<ValueTableMode>,
320    /// STARTING WITH .. CONNECT BY
321    pub connect_by: Option<ConnectBy>,
322}
323
324impl fmt::Display for Select {
325    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
326        write!(f, "SELECT")?;
327
328        if let Some(value_table_mode) = self.value_table_mode {
329            write!(f, " {value_table_mode}")?;
330        }
331
332        if let Some(ref top) = self.top {
333            if self.top_before_distinct {
334                write!(f, " {top}")?;
335            }
336        }
337        if let Some(ref distinct) = self.distinct {
338            write!(f, " {distinct}")?;
339        }
340        if let Some(ref top) = self.top {
341            if !self.top_before_distinct {
342                write!(f, " {top}")?;
343            }
344        }
345
346        write!(f, " {}", display_comma_separated(&self.projection))?;
347
348        if let Some(ref into) = self.into {
349            write!(f, " {into}")?;
350        }
351
352        if !self.from.is_empty() {
353            write!(f, " FROM {}", display_comma_separated(&self.from))?;
354        }
355        if !self.lateral_views.is_empty() {
356            for lv in &self.lateral_views {
357                write!(f, "{lv}")?;
358            }
359        }
360        if let Some(ref prewhere) = self.prewhere {
361            write!(f, " PREWHERE {prewhere}")?;
362        }
363        if let Some(ref selection) = self.selection {
364            write!(f, " WHERE {selection}")?;
365        }
366        match &self.group_by {
367            GroupByExpr::All(_) => write!(f, " {}", self.group_by)?,
368            GroupByExpr::Expressions(exprs, _) => {
369                if !exprs.is_empty() {
370                    write!(f, " {}", self.group_by)?
371                }
372            }
373        }
374        if !self.cluster_by.is_empty() {
375            write!(
376                f,
377                " CLUSTER BY {}",
378                display_comma_separated(&self.cluster_by)
379            )?;
380        }
381        if !self.distribute_by.is_empty() {
382            write!(
383                f,
384                " DISTRIBUTE BY {}",
385                display_comma_separated(&self.distribute_by)
386            )?;
387        }
388        if !self.sort_by.is_empty() {
389            write!(f, " SORT BY {}", display_comma_separated(&self.sort_by))?;
390        }
391        if let Some(ref having) = self.having {
392            write!(f, " HAVING {having}")?;
393        }
394        if self.window_before_qualify {
395            if !self.named_window.is_empty() {
396                write!(f, " WINDOW {}", display_comma_separated(&self.named_window))?;
397            }
398            if let Some(ref qualify) = self.qualify {
399                write!(f, " QUALIFY {qualify}")?;
400            }
401        } else {
402            if let Some(ref qualify) = self.qualify {
403                write!(f, " QUALIFY {qualify}")?;
404            }
405            if !self.named_window.is_empty() {
406                write!(f, " WINDOW {}", display_comma_separated(&self.named_window))?;
407            }
408        }
409        if let Some(ref connect_by) = self.connect_by {
410            write!(f, " {connect_by}")?;
411        }
412        Ok(())
413    }
414}
415
416/// A hive LATERAL VIEW with potential column aliases
417#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
418#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
419#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
420pub struct LateralView {
421    /// LATERAL VIEW
422    pub lateral_view: Expr,
423    /// LATERAL VIEW table name
424    pub lateral_view_name: ObjectName,
425    /// LATERAL VIEW optional column aliases
426    pub lateral_col_alias: Vec<Ident>,
427    /// LATERAL VIEW OUTER
428    pub outer: bool,
429}
430
431impl fmt::Display for LateralView {
432    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
433        write!(
434            f,
435            " LATERAL VIEW{outer} {} {}",
436            self.lateral_view,
437            self.lateral_view_name,
438            outer = if self.outer { " OUTER" } else { "" }
439        )?;
440        if !self.lateral_col_alias.is_empty() {
441            write!(
442                f,
443                " AS {}",
444                display_comma_separated(&self.lateral_col_alias)
445            )?;
446        }
447        Ok(())
448    }
449}
450
451/// An expression used in a named window declaration.
452///
453/// ```sql
454/// WINDOW mywindow AS [named_window_expr]
455/// ```
456#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
457#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
458#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
459pub enum NamedWindowExpr {
460    /// A direct reference to another named window definition.
461    /// [BigQuery]
462    ///
463    /// Example:
464    /// ```sql
465    /// WINDOW mywindow AS prev_window
466    /// ```
467    ///
468    /// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/window-function-calls#ref_named_window
469    NamedWindow(Ident),
470    /// A window expression.
471    ///
472    /// Example:
473    /// ```sql
474    /// WINDOW mywindow AS (ORDER BY 1)
475    /// ```
476    WindowSpec(WindowSpec),
477}
478
479impl fmt::Display for NamedWindowExpr {
480    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
481        match self {
482            NamedWindowExpr::NamedWindow(named_window) => {
483                write!(f, "{named_window}")?;
484            }
485            NamedWindowExpr::WindowSpec(window_spec) => {
486                write!(f, "({window_spec})")?;
487            }
488        };
489        Ok(())
490    }
491}
492
493#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
494#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
495#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
496pub struct NamedWindowDefinition(pub Ident, pub NamedWindowExpr);
497
498impl fmt::Display for NamedWindowDefinition {
499    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
500        write!(f, "{} AS {}", self.0, self.1)
501    }
502}
503
504#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
505#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
506#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
507pub struct With {
508    pub recursive: bool,
509    pub cte_tables: Vec<Cte>,
510}
511
512impl fmt::Display for With {
513    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
514        write!(
515            f,
516            "WITH {}{}",
517            if self.recursive { "RECURSIVE " } else { "" },
518            display_comma_separated(&self.cte_tables)
519        )
520    }
521}
522
523#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
524#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
525#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
526pub enum CteAsMaterialized {
527    /// The `WITH` statement specifies `AS MATERIALIZED` behavior
528    Materialized,
529    /// The `WITH` statement specifies `AS NOT MATERIALIZED` behavior
530    NotMaterialized,
531}
532
533impl fmt::Display for CteAsMaterialized {
534    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
535        match *self {
536            CteAsMaterialized::Materialized => {
537                write!(f, "MATERIALIZED")?;
538            }
539            CteAsMaterialized::NotMaterialized => {
540                write!(f, "NOT MATERIALIZED")?;
541            }
542        };
543        Ok(())
544    }
545}
546
547/// A single CTE (used after `WITH`): `<alias> [(col1, col2, ...)] AS <materialized> ( <query> )`
548/// The names in the column list before `AS`, when specified, replace the names
549/// of the columns returned by the query. The parser does not validate that the
550/// number of columns in the query matches the number of columns in the query.
551#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
552#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
553#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
554pub struct Cte {
555    pub alias: TableAlias,
556    pub query: Box<Query>,
557    pub from: Option<Ident>,
558    pub materialized: Option<CteAsMaterialized>,
559}
560
561impl fmt::Display for Cte {
562    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
563        match self.materialized.as_ref() {
564            None => write!(f, "{} AS ({})", self.alias, self.query)?,
565            Some(materialized) => write!(f, "{} AS {materialized} ({})", self.alias, self.query)?,
566        };
567        if let Some(ref fr) = self.from {
568            write!(f, " FROM {fr}")?;
569        }
570        Ok(())
571    }
572}
573
574/// One item of the comma-separated list following `SELECT`
575#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
576#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
577#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
578pub enum SelectItem {
579    /// Any expression, not followed by `[ AS ] alias`
580    UnnamedExpr(Expr),
581    /// An expression, followed by `[ AS ] alias`
582    ExprWithAlias { expr: Expr, alias: Ident },
583    /// `alias.*` or even `schema.table.*`
584    QualifiedWildcard(ObjectName, WildcardAdditionalOptions),
585    /// An unqualified `*`
586    Wildcard(WildcardAdditionalOptions),
587}
588
589/// Single aliased identifier
590///
591/// # Syntax
592/// ```plaintext
593/// <ident> AS <alias>
594/// ```
595#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
596#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
597#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
598pub struct IdentWithAlias {
599    pub ident: Ident,
600    pub alias: Ident,
601}
602
603impl fmt::Display for IdentWithAlias {
604    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
605        write!(f, "{} AS {}", self.ident, self.alias)
606    }
607}
608
609/// Additional options for wildcards, e.g. Snowflake `EXCLUDE`/`RENAME` and Bigquery `EXCEPT`.
610#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Default)]
611#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
612#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
613pub struct WildcardAdditionalOptions {
614    /// `[ILIKE...]`.
615    ///  Snowflake syntax: <https://docs.snowflake.com/en/sql-reference/sql/select#parameters>
616    pub opt_ilike: Option<IlikeSelectItem>,
617    /// `[EXCLUDE...]`.
618    pub opt_exclude: Option<ExcludeSelectItem>,
619    /// `[EXCEPT...]`.
620    ///  Clickhouse syntax: <https://clickhouse.com/docs/en/sql-reference/statements/select#except>
621    pub opt_except: Option<ExceptSelectItem>,
622    /// `[REPLACE]`
623    ///  BigQuery syntax: <https://cloud.google.com/bigquery/docs/reference/standard-sql/query-syntax#select_replace>
624    ///  Clickhouse syntax: <https://clickhouse.com/docs/en/sql-reference/statements/select#replace>
625    ///  Snowflake syntax: <https://docs.snowflake.com/en/sql-reference/sql/select#parameters>
626    pub opt_replace: Option<ReplaceSelectItem>,
627    /// `[RENAME ...]`.
628    pub opt_rename: Option<RenameSelectItem>,
629}
630
631impl fmt::Display for WildcardAdditionalOptions {
632    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
633        if let Some(ilike) = &self.opt_ilike {
634            write!(f, " {ilike}")?;
635        }
636        if let Some(exclude) = &self.opt_exclude {
637            write!(f, " {exclude}")?;
638        }
639        if let Some(except) = &self.opt_except {
640            write!(f, " {except}")?;
641        }
642        if let Some(replace) = &self.opt_replace {
643            write!(f, " {replace}")?;
644        }
645        if let Some(rename) = &self.opt_rename {
646            write!(f, " {rename}")?;
647        }
648        Ok(())
649    }
650}
651
652/// Snowflake `ILIKE` information.
653///
654/// # Syntax
655/// ```plaintext
656/// ILIKE <value>
657/// ```
658#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
659#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
660#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
661pub struct IlikeSelectItem {
662    pub pattern: String,
663}
664
665impl fmt::Display for IlikeSelectItem {
666    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
667        write!(
668            f,
669            "ILIKE '{}'",
670            value::escape_single_quote_string(&self.pattern)
671        )?;
672        Ok(())
673    }
674}
675/// Snowflake `EXCLUDE` information.
676///
677/// # Syntax
678/// ```plaintext
679/// <col_name>
680/// | (<col_name>, <col_name>, ...)
681/// ```
682#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
683#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
684#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
685pub enum ExcludeSelectItem {
686    /// Single column name without parenthesis.
687    ///
688    /// # Syntax
689    /// ```plaintext
690    /// <col_name>
691    /// ```
692    Single(Ident),
693    /// Multiple column names inside parenthesis.
694    /// # Syntax
695    /// ```plaintext
696    /// (<col_name>, <col_name>, ...)
697    /// ```
698    Multiple(Vec<Ident>),
699}
700
701impl fmt::Display for ExcludeSelectItem {
702    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
703        write!(f, "EXCLUDE")?;
704        match self {
705            Self::Single(column) => {
706                write!(f, " {column}")?;
707            }
708            Self::Multiple(columns) => {
709                write!(f, " ({})", display_comma_separated(columns))?;
710            }
711        }
712        Ok(())
713    }
714}
715
716/// Snowflake `RENAME` information.
717///
718/// # Syntax
719/// ```plaintext
720/// <col_name> AS <col_alias>
721/// | (<col_name> AS <col_alias>, <col_name> AS <col_alias>, ...)
722/// ```
723#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
724#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
725#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
726pub enum RenameSelectItem {
727    /// Single column name with alias without parenthesis.
728    ///
729    /// # Syntax
730    /// ```plaintext
731    /// <col_name> AS <col_alias>
732    /// ```
733    Single(IdentWithAlias),
734    /// Multiple column names with aliases inside parenthesis.
735    /// # Syntax
736    /// ```plaintext
737    /// (<col_name> AS <col_alias>, <col_name> AS <col_alias>, ...)
738    /// ```
739    Multiple(Vec<IdentWithAlias>),
740}
741
742impl fmt::Display for RenameSelectItem {
743    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
744        write!(f, "RENAME")?;
745        match self {
746            Self::Single(column) => {
747                write!(f, " {column}")?;
748            }
749            Self::Multiple(columns) => {
750                write!(f, " ({})", display_comma_separated(columns))?;
751            }
752        }
753        Ok(())
754    }
755}
756
757/// Bigquery `EXCEPT` information, with at least one column.
758///
759/// # Syntax
760/// ```plaintext
761/// EXCEPT (<col_name> [, ...])
762/// ```
763#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
764#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
765#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
766pub struct ExceptSelectItem {
767    /// First guaranteed column.
768    pub first_element: Ident,
769    /// Additional columns. This list can be empty.
770    pub additional_elements: Vec<Ident>,
771}
772
773impl fmt::Display for ExceptSelectItem {
774    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
775        write!(f, "EXCEPT ")?;
776        if self.additional_elements.is_empty() {
777            write!(f, "({})", self.first_element)?;
778        } else {
779            write!(
780                f,
781                "({}, {})",
782                self.first_element,
783                display_comma_separated(&self.additional_elements)
784            )?;
785        }
786        Ok(())
787    }
788}
789
790/// Bigquery `REPLACE` information.
791///
792/// # Syntax
793/// ```plaintext
794/// REPLACE (<new_expr> [AS] <col_name>)
795/// REPLACE (<col_name> [AS] <col_alias>, <col_name> [AS] <col_alias>, ...)
796/// ```
797#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
798#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
799#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
800pub struct ReplaceSelectItem {
801    pub items: Vec<Box<ReplaceSelectElement>>,
802}
803
804impl fmt::Display for ReplaceSelectItem {
805    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
806        write!(f, "REPLACE")?;
807        write!(f, " ({})", display_comma_separated(&self.items))?;
808        Ok(())
809    }
810}
811
812/// # Syntax
813/// ```plaintext
814/// <expr> [AS] <column_name>
815/// ```
816#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
817#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
818#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
819pub struct ReplaceSelectElement {
820    pub expr: Expr,
821    pub column_name: Ident,
822    pub as_keyword: bool,
823}
824
825impl fmt::Display for ReplaceSelectElement {
826    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
827        if self.as_keyword {
828            write!(f, "{} AS {}", self.expr, self.column_name)
829        } else {
830            write!(f, "{} {}", self.expr, self.column_name)
831        }
832    }
833}
834
835impl fmt::Display for SelectItem {
836    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
837        match &self {
838            SelectItem::UnnamedExpr(expr) => write!(f, "{expr}"),
839            SelectItem::ExprWithAlias { expr, alias } => write!(f, "{expr} AS {alias}"),
840            SelectItem::QualifiedWildcard(prefix, additional_options) => {
841                write!(f, "{prefix}.*")?;
842                write!(f, "{additional_options}")?;
843                Ok(())
844            }
845            SelectItem::Wildcard(additional_options) => {
846                write!(f, "*")?;
847                write!(f, "{additional_options}")?;
848                Ok(())
849            }
850        }
851    }
852}
853
854#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
855#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
856#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
857pub struct TableWithJoins {
858    pub relation: TableFactor,
859    pub joins: Vec<Join>,
860}
861
862impl fmt::Display for TableWithJoins {
863    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
864        write!(f, "{}", self.relation)?;
865        for join in &self.joins {
866            write!(f, "{join}")?;
867        }
868        Ok(())
869    }
870}
871
872/// Joins a table to itself to process hierarchical data in the table.
873///
874/// See <https://docs.snowflake.com/en/sql-reference/constructs/connect-by>.
875#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
876#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
877#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
878pub struct ConnectBy {
879    /// START WITH
880    pub condition: Expr,
881    /// CONNECT BY
882    pub relationships: Vec<Expr>,
883}
884
885impl fmt::Display for ConnectBy {
886    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
887        write!(
888            f,
889            "START WITH {condition} CONNECT BY {relationships}",
890            condition = self.condition,
891            relationships = display_comma_separated(&self.relationships)
892        )
893    }
894}
895
896#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
897#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
898#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
899pub struct Setting {
900    pub key: Ident,
901    pub value: Value,
902}
903
904impl fmt::Display for Setting {
905    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
906        write!(f, "{} = {}", self.key, self.value)
907    }
908}
909
910/// An expression optionally followed by an alias.
911///
912/// Example:
913/// ```sql
914/// 42 AS myint
915/// ```
916#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
917#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
918#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
919pub struct ExprWithAlias {
920    pub expr: Expr,
921    pub alias: Option<Ident>,
922}
923
924impl fmt::Display for ExprWithAlias {
925    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
926        let ExprWithAlias { expr, alias } = self;
927        write!(f, "{expr}")?;
928        if let Some(alias) = alias {
929            write!(f, " AS {alias}")?;
930        }
931        Ok(())
932    }
933}
934
935/// Arguments to a table-valued function
936#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
937#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
938#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
939pub struct TableFunctionArgs {
940    pub args: Vec<FunctionArg>,
941    /// ClickHouse-specific SETTINGS clause.
942    /// For example,
943    /// `SELECT * FROM executable('generate_random.py', TabSeparated, 'id UInt32, random String', SETTINGS send_chunk_header = false, pool_size = 16)`
944    /// [`executable` table function](https://clickhouse.com/docs/en/engines/table-functions/executable)
945    pub settings: Option<Vec<Setting>>,
946}
947
948/// A table name or a parenthesized subquery with an optional alias
949#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
950#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
951#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
952#[cfg_attr(feature = "visitor", visit(with = "visit_table_factor"))]
953pub enum TableFactor {
954    Table {
955        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
956        name: ObjectName,
957        alias: Option<TableAlias>,
958        /// Arguments of a table-valued function, as supported by Postgres
959        /// and MSSQL. Note that deprecated MSSQL `FROM foo (NOLOCK)` syntax
960        /// will also be parsed as `args`.
961        ///
962        /// This field's value is `Some(v)`, where `v` is a (possibly empty)
963        /// vector of arguments, in the case of a table-valued function call,
964        /// whereas it's `None` in the case of a regular table name.
965        args: Option<TableFunctionArgs>,
966        /// MSSQL-specific `WITH (...)` hints such as NOLOCK.
967        with_hints: Vec<Expr>,
968        /// Optional version qualifier to facilitate table time-travel, as
969        /// supported by BigQuery and MSSQL.
970        version: Option<TableVersion>,
971        //  Optional table function modifier to generate the ordinality for column.
972        /// For example, `SELECT * FROM generate_series(1, 10) WITH ORDINALITY AS t(a, b);`
973        /// [WITH ORDINALITY](https://www.postgresql.org/docs/current/functions-srf.html), supported by Postgres.
974        with_ordinality: bool,
975        /// [Partition selection](https://dev.mysql.com/doc/refman/8.0/en/partitioning-selection.html), supported by MySQL.
976        partitions: Vec<Ident>,
977    },
978    Derived {
979        lateral: bool,
980        subquery: Box<Query>,
981        alias: Option<TableAlias>,
982    },
983    /// `TABLE(<expr>)[ AS <alias> ]`
984    TableFunction {
985        expr: Expr,
986        alias: Option<TableAlias>,
987    },
988    /// `e.g. LATERAL FLATTEN(<args>)[ AS <alias> ]`
989    Function {
990        lateral: bool,
991        name: ObjectName,
992        args: Vec<FunctionArg>,
993        alias: Option<TableAlias>,
994    },
995    /// ```sql
996    /// SELECT * FROM UNNEST ([10,20,30]) as numbers WITH OFFSET;
997    /// +---------+--------+
998    /// | numbers | offset |
999    /// +---------+--------+
1000    /// | 10      | 0      |
1001    /// | 20      | 1      |
1002    /// | 30      | 2      |
1003    /// +---------+--------+
1004    /// ```
1005    UNNEST {
1006        alias: Option<TableAlias>,
1007        array_exprs: Vec<Expr>,
1008        with_offset: bool,
1009        with_offset_alias: Option<Ident>,
1010        with_ordinality: bool,
1011    },
1012    /// The `JSON_TABLE` table-valued function.
1013    /// Part of the SQL standard, but implemented only by MySQL, Oracle, and DB2.
1014    ///
1015    /// <https://modern-sql.com/blog/2017-06/whats-new-in-sql-2016#json_table>
1016    /// <https://dev.mysql.com/doc/refman/8.0/en/json-table-functions.html#function_json-table>
1017    ///
1018    /// ```sql
1019    /// SELECT * FROM JSON_TABLE(
1020    ///    '[{"a": 1, "b": 2}, {"a": 3, "b": 4}]',
1021    ///    '$[*]' COLUMNS(
1022    ///        a INT PATH '$.a' DEFAULT '0' ON EMPTY,
1023    ///        b INT PATH '$.b' NULL ON ERROR
1024    ///     )
1025    /// ) AS jt;
1026    /// ````
1027    JsonTable {
1028        /// The JSON expression to be evaluated. It must evaluate to a json string
1029        json_expr: Expr,
1030        /// The path to the array or object to be iterated over.
1031        /// It must evaluate to a json array or object.
1032        json_path: Value,
1033        /// The columns to be extracted from each element of the array or object.
1034        /// Each column must have a name and a type.
1035        columns: Vec<JsonTableColumn>,
1036        /// The alias for the table.
1037        alias: Option<TableAlias>,
1038    },
1039    /// Represents a parenthesized table factor. The SQL spec only allows a
1040    /// join expression (`(foo <JOIN> bar [ <JOIN> baz ... ])`) to be nested,
1041    /// possibly several times.
1042    ///
1043    /// The parser may also accept non-standard nesting of bare tables for some
1044    /// dialects, but the information about such nesting is stripped from AST.
1045    NestedJoin {
1046        table_with_joins: Box<TableWithJoins>,
1047        alias: Option<TableAlias>,
1048    },
1049    /// Represents PIVOT operation on a table.
1050    /// For example `FROM monthly_sales PIVOT(sum(amount) FOR MONTH IN ('JAN', 'FEB'))`
1051    ///
1052    /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/query-syntax#pivot_operator)
1053    /// [Snowflake](https://docs.snowflake.com/en/sql-reference/constructs/pivot)
1054    Pivot {
1055        table: Box<TableFactor>,
1056        aggregate_functions: Vec<ExprWithAlias>, // Function expression
1057        value_column: Vec<Ident>,
1058        value_source: PivotValueSource,
1059        default_on_null: Option<Expr>,
1060        alias: Option<TableAlias>,
1061    },
1062    /// An UNPIVOT operation on a table.
1063    ///
1064    /// Syntax:
1065    /// ```sql
1066    /// table UNPIVOT(value FOR name IN (column1, [ column2, ... ])) [ alias ]
1067    /// ```
1068    ///
1069    /// See <https://docs.snowflake.com/en/sql-reference/constructs/unpivot>.
1070    Unpivot {
1071        table: Box<TableFactor>,
1072        value: Ident,
1073        name: Ident,
1074        columns: Vec<Ident>,
1075        alias: Option<TableAlias>,
1076    },
1077    /// A `MATCH_RECOGNIZE` operation on a table.
1078    ///
1079    /// See <https://docs.snowflake.com/en/sql-reference/constructs/match_recognize>.
1080    MatchRecognize {
1081        table: Box<TableFactor>,
1082        /// `PARTITION BY <expr> [, ... ]`
1083        partition_by: Vec<Expr>,
1084        /// `ORDER BY <expr> [, ... ]`
1085        order_by: Vec<OrderByExpr>,
1086        /// `MEASURES <expr> [AS] <alias> [, ... ]`
1087        measures: Vec<Measure>,
1088        /// `ONE ROW PER MATCH | ALL ROWS PER MATCH [ <option> ]`
1089        rows_per_match: Option<RowsPerMatch>,
1090        /// `AFTER MATCH SKIP <option>`
1091        after_match_skip: Option<AfterMatchSkip>,
1092        /// `PATTERN ( <pattern> )`
1093        pattern: MatchRecognizePattern,
1094        /// `DEFINE <symbol> AS <expr> [, ... ]`
1095        symbols: Vec<SymbolDefinition>,
1096        alias: Option<TableAlias>,
1097    },
1098}
1099
1100/// The source of values in a `PIVOT` operation.
1101#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1102#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1103#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1104pub enum PivotValueSource {
1105    /// Pivot on a static list of values.
1106    ///
1107    /// See <https://docs.snowflake.com/en/sql-reference/constructs/pivot#pivot-on-a-specified-list-of-column-values-for-the-pivot-column>.
1108    List(Vec<ExprWithAlias>),
1109    /// Pivot on all distinct values of the pivot column.
1110    ///
1111    /// See <https://docs.snowflake.com/en/sql-reference/constructs/pivot#pivot-on-all-distinct-column-values-automatically-with-dynamic-pivot>.
1112    Any(Vec<OrderByExpr>),
1113    /// Pivot on all values returned by a subquery.
1114    ///
1115    /// See <https://docs.snowflake.com/en/sql-reference/constructs/pivot#pivot-on-column-values-using-a-subquery-with-dynamic-pivot>.
1116    Subquery(Box<Query>),
1117}
1118
1119impl fmt::Display for PivotValueSource {
1120    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1121        match self {
1122            PivotValueSource::List(values) => write!(f, "{}", display_comma_separated(values)),
1123            PivotValueSource::Any(order_by) => {
1124                write!(f, "ANY")?;
1125                if !order_by.is_empty() {
1126                    write!(f, " ORDER BY {}", display_comma_separated(order_by))?;
1127                }
1128                Ok(())
1129            }
1130            PivotValueSource::Subquery(query) => write!(f, "{query}"),
1131        }
1132    }
1133}
1134
1135/// An item in the `MEASURES` subclause of a `MATCH_RECOGNIZE` operation.
1136///
1137/// See <https://docs.snowflake.com/en/sql-reference/constructs/match_recognize#measures-specifying-additional-output-columns>.
1138#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1139#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1140#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1141pub struct Measure {
1142    pub expr: Expr,
1143    pub alias: Ident,
1144}
1145
1146impl fmt::Display for Measure {
1147    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1148        write!(f, "{} AS {}", self.expr, self.alias)
1149    }
1150}
1151
1152/// The rows per match option in a `MATCH_RECOGNIZE` operation.
1153///
1154/// See <https://docs.snowflake.com/en/sql-reference/constructs/match_recognize#row-s-per-match-specifying-the-rows-to-return>.
1155#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1156#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1157#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1158pub enum RowsPerMatch {
1159    /// `ONE ROW PER MATCH`
1160    OneRow,
1161    /// `ALL ROWS PER MATCH <mode>`
1162    AllRows(Option<EmptyMatchesMode>),
1163}
1164
1165impl fmt::Display for RowsPerMatch {
1166    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1167        match self {
1168            RowsPerMatch::OneRow => write!(f, "ONE ROW PER MATCH"),
1169            RowsPerMatch::AllRows(mode) => {
1170                write!(f, "ALL ROWS PER MATCH")?;
1171                if let Some(mode) = mode {
1172                    write!(f, " {}", mode)?;
1173                }
1174                Ok(())
1175            }
1176        }
1177    }
1178}
1179
1180/// The after match skip option in a `MATCH_RECOGNIZE` operation.
1181///
1182/// See <https://docs.snowflake.com/en/sql-reference/constructs/match_recognize#after-match-skip-specifying-where-to-continue-after-a-match>.
1183#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1184#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1185#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1186pub enum AfterMatchSkip {
1187    /// `PAST LAST ROW`
1188    PastLastRow,
1189    /// `TO NEXT ROW`
1190    ToNextRow,
1191    /// `TO FIRST <symbol>`
1192    ToFirst(Ident),
1193    /// `TO LAST <symbol>`
1194    ToLast(Ident),
1195}
1196
1197impl fmt::Display for AfterMatchSkip {
1198    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1199        write!(f, "AFTER MATCH SKIP ")?;
1200        match self {
1201            AfterMatchSkip::PastLastRow => write!(f, "PAST LAST ROW"),
1202            AfterMatchSkip::ToNextRow => write!(f, " TO NEXT ROW"),
1203            AfterMatchSkip::ToFirst(symbol) => write!(f, "TO FIRST {symbol}"),
1204            AfterMatchSkip::ToLast(symbol) => write!(f, "TO LAST {symbol}"),
1205        }
1206    }
1207}
1208
1209#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1210#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1211#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1212pub enum EmptyMatchesMode {
1213    /// `SHOW EMPTY MATCHES`
1214    Show,
1215    /// `OMIT EMPTY MATCHES`
1216    Omit,
1217    /// `WITH UNMATCHED ROWS`
1218    WithUnmatched,
1219}
1220
1221impl fmt::Display for EmptyMatchesMode {
1222    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1223        match self {
1224            EmptyMatchesMode::Show => write!(f, "SHOW EMPTY MATCHES"),
1225            EmptyMatchesMode::Omit => write!(f, "OMIT EMPTY MATCHES"),
1226            EmptyMatchesMode::WithUnmatched => write!(f, "WITH UNMATCHED ROWS"),
1227        }
1228    }
1229}
1230
1231/// A symbol defined in a `MATCH_RECOGNIZE` operation.
1232///
1233/// See <https://docs.snowflake.com/en/sql-reference/constructs/match_recognize#define-defining-symbols>.
1234#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1235#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1236#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1237pub struct SymbolDefinition {
1238    pub symbol: Ident,
1239    pub definition: Expr,
1240}
1241
1242impl fmt::Display for SymbolDefinition {
1243    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1244        write!(f, "{} AS {}", self.symbol, self.definition)
1245    }
1246}
1247
1248/// A symbol in a `MATCH_RECOGNIZE` pattern.
1249#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1250#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1251#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1252pub enum MatchRecognizeSymbol {
1253    /// A named symbol, e.g. `S1`.
1254    Named(Ident),
1255    /// A virtual symbol representing the start of the of partition (`^`).
1256    Start,
1257    /// A virtual symbol representing the end of the partition (`$`).
1258    End,
1259}
1260
1261impl fmt::Display for MatchRecognizeSymbol {
1262    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1263        match self {
1264            MatchRecognizeSymbol::Named(symbol) => write!(f, "{symbol}"),
1265            MatchRecognizeSymbol::Start => write!(f, "^"),
1266            MatchRecognizeSymbol::End => write!(f, "$"),
1267        }
1268    }
1269}
1270
1271/// The pattern in a `MATCH_RECOGNIZE` operation.
1272///
1273/// See <https://docs.snowflake.com/en/sql-reference/constructs/match_recognize#pattern-specifying-the-pattern-to-match>.
1274#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1275#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1276#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1277pub enum MatchRecognizePattern {
1278    /// A named symbol such as `S1` or a virtual symbol such as `^`.
1279    Symbol(MatchRecognizeSymbol),
1280    /// {- symbol -}
1281    Exclude(MatchRecognizeSymbol),
1282    /// PERMUTE(symbol_1, ..., symbol_n)
1283    Permute(Vec<MatchRecognizeSymbol>),
1284    /// pattern_1 pattern_2 ... pattern_n
1285    Concat(Vec<MatchRecognizePattern>),
1286    /// ( pattern )
1287    Group(Box<MatchRecognizePattern>),
1288    /// pattern_1 | pattern_2 | ... | pattern_n
1289    Alternation(Vec<MatchRecognizePattern>),
1290    /// e.g. pattern*
1291    Repetition(Box<MatchRecognizePattern>, RepetitionQuantifier),
1292}
1293
1294impl fmt::Display for MatchRecognizePattern {
1295    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1296        use MatchRecognizePattern::*;
1297        match self {
1298            Symbol(symbol) => write!(f, "{}", symbol),
1299            Exclude(symbol) => write!(f, "{{- {symbol} -}}"),
1300            Permute(symbols) => write!(f, "PERMUTE({})", display_comma_separated(symbols)),
1301            Concat(patterns) => write!(f, "{}", display_separated(patterns, " ")),
1302            Group(pattern) => write!(f, "( {pattern} )"),
1303            Alternation(patterns) => write!(f, "{}", display_separated(patterns, " | ")),
1304            Repetition(pattern, op) => write!(f, "{pattern}{op}"),
1305        }
1306    }
1307}
1308
1309/// Determines the minimum and maximum allowed occurrences of a pattern in a
1310/// `MATCH_RECOGNIZE` operation.
1311#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1312#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1313#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1314pub enum RepetitionQuantifier {
1315    /// `*`
1316    ZeroOrMore,
1317    /// `+`
1318    OneOrMore,
1319    /// `?`
1320    AtMostOne,
1321    /// `{n}`
1322    Exactly(u32),
1323    /// `{n,}`
1324    AtLeast(u32),
1325    /// `{,n}`
1326    AtMost(u32),
1327    /// `{n,m}
1328    Range(u32, u32),
1329}
1330
1331impl fmt::Display for RepetitionQuantifier {
1332    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1333        use RepetitionQuantifier::*;
1334        match self {
1335            ZeroOrMore => write!(f, "*"),
1336            OneOrMore => write!(f, "+"),
1337            AtMostOne => write!(f, "?"),
1338            Exactly(n) => write!(f, "{{{n}}}"),
1339            AtLeast(n) => write!(f, "{{{n},}}"),
1340            AtMost(n) => write!(f, "{{,{n}}}"),
1341            Range(n, m) => write!(f, "{{{n},{m}}}"),
1342        }
1343    }
1344}
1345
1346impl fmt::Display for TableFactor {
1347    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1348        match self {
1349            TableFactor::Table {
1350                name,
1351                alias,
1352                args,
1353                with_hints,
1354                version,
1355                partitions,
1356                with_ordinality,
1357            } => {
1358                write!(f, "{name}")?;
1359                if !partitions.is_empty() {
1360                    write!(f, "PARTITION ({})", display_comma_separated(partitions))?;
1361                }
1362                if let Some(args) = args {
1363                    write!(f, "(")?;
1364                    write!(f, "{}", display_comma_separated(&args.args))?;
1365                    if let Some(ref settings) = args.settings {
1366                        if !args.args.is_empty() {
1367                            write!(f, ", ")?;
1368                        }
1369                        write!(f, "SETTINGS {}", display_comma_separated(settings))?;
1370                    }
1371                    write!(f, ")")?;
1372                }
1373                if *with_ordinality {
1374                    write!(f, " WITH ORDINALITY")?;
1375                }
1376                if let Some(alias) = alias {
1377                    write!(f, " AS {alias}")?;
1378                }
1379                if !with_hints.is_empty() {
1380                    write!(f, " WITH ({})", display_comma_separated(with_hints))?;
1381                }
1382                if let Some(version) = version {
1383                    write!(f, "{version}")?;
1384                }
1385                Ok(())
1386            }
1387            TableFactor::Derived {
1388                lateral,
1389                subquery,
1390                alias,
1391            } => {
1392                if *lateral {
1393                    write!(f, "LATERAL ")?;
1394                }
1395                write!(f, "({subquery})")?;
1396                if let Some(alias) = alias {
1397                    write!(f, " AS {alias}")?;
1398                }
1399                Ok(())
1400            }
1401            TableFactor::Function {
1402                lateral,
1403                name,
1404                args,
1405                alias,
1406            } => {
1407                if *lateral {
1408                    write!(f, "LATERAL ")?;
1409                }
1410                write!(f, "{name}")?;
1411                write!(f, "({})", display_comma_separated(args))?;
1412                if let Some(alias) = alias {
1413                    write!(f, " AS {alias}")?;
1414                }
1415                Ok(())
1416            }
1417            TableFactor::TableFunction { expr, alias } => {
1418                write!(f, "TABLE({expr})")?;
1419                if let Some(alias) = alias {
1420                    write!(f, " AS {alias}")?;
1421                }
1422                Ok(())
1423            }
1424            TableFactor::UNNEST {
1425                alias,
1426                array_exprs,
1427                with_offset,
1428                with_offset_alias,
1429                with_ordinality,
1430            } => {
1431                write!(f, "UNNEST({})", display_comma_separated(array_exprs))?;
1432
1433                if *with_ordinality {
1434                    write!(f, " WITH ORDINALITY")?;
1435                }
1436
1437                if let Some(alias) = alias {
1438                    write!(f, " AS {alias}")?;
1439                }
1440                if *with_offset {
1441                    write!(f, " WITH OFFSET")?;
1442                }
1443                if let Some(alias) = with_offset_alias {
1444                    write!(f, " AS {alias}")?;
1445                }
1446                Ok(())
1447            }
1448            TableFactor::JsonTable {
1449                json_expr,
1450                json_path,
1451                columns,
1452                alias,
1453            } => {
1454                write!(
1455                    f,
1456                    "JSON_TABLE({json_expr}, {json_path} COLUMNS({columns}))",
1457                    columns = display_comma_separated(columns)
1458                )?;
1459                if let Some(alias) = alias {
1460                    write!(f, " AS {alias}")?;
1461                }
1462                Ok(())
1463            }
1464            TableFactor::NestedJoin {
1465                table_with_joins,
1466                alias,
1467            } => {
1468                write!(f, "({table_with_joins})")?;
1469                if let Some(alias) = alias {
1470                    write!(f, " AS {alias}")?;
1471                }
1472                Ok(())
1473            }
1474            TableFactor::Pivot {
1475                table,
1476                aggregate_functions,
1477                value_column,
1478                value_source,
1479                default_on_null,
1480                alias,
1481            } => {
1482                write!(
1483                    f,
1484                    "{table} PIVOT({} FOR {} IN ({value_source})",
1485                    display_comma_separated(aggregate_functions),
1486                    Expr::CompoundIdentifier(value_column.to_vec()),
1487                )?;
1488                if let Some(expr) = default_on_null {
1489                    write!(f, " DEFAULT ON NULL ({expr})")?;
1490                }
1491                write!(f, ")")?;
1492                if alias.is_some() {
1493                    write!(f, " AS {}", alias.as_ref().unwrap())?;
1494                }
1495                Ok(())
1496            }
1497            TableFactor::Unpivot {
1498                table,
1499                value,
1500                name,
1501                columns,
1502                alias,
1503            } => {
1504                write!(
1505                    f,
1506                    "{} UNPIVOT({} FOR {} IN ({}))",
1507                    table,
1508                    value,
1509                    name,
1510                    display_comma_separated(columns)
1511                )?;
1512                if alias.is_some() {
1513                    write!(f, " AS {}", alias.as_ref().unwrap())?;
1514                }
1515                Ok(())
1516            }
1517            TableFactor::MatchRecognize {
1518                table,
1519                partition_by,
1520                order_by,
1521                measures,
1522                rows_per_match,
1523                after_match_skip,
1524                pattern,
1525                symbols,
1526                alias,
1527            } => {
1528                write!(f, "{table} MATCH_RECOGNIZE(")?;
1529                if !partition_by.is_empty() {
1530                    write!(f, "PARTITION BY {} ", display_comma_separated(partition_by))?;
1531                }
1532                if !order_by.is_empty() {
1533                    write!(f, "ORDER BY {} ", display_comma_separated(order_by))?;
1534                }
1535                if !measures.is_empty() {
1536                    write!(f, "MEASURES {} ", display_comma_separated(measures))?;
1537                }
1538                if let Some(rows_per_match) = rows_per_match {
1539                    write!(f, "{rows_per_match} ")?;
1540                }
1541                if let Some(after_match_skip) = after_match_skip {
1542                    write!(f, "{after_match_skip} ")?;
1543                }
1544                write!(f, "PATTERN ({pattern}) ")?;
1545                write!(f, "DEFINE {})", display_comma_separated(symbols))?;
1546                if alias.is_some() {
1547                    write!(f, " AS {}", alias.as_ref().unwrap())?;
1548                }
1549                Ok(())
1550            }
1551        }
1552    }
1553}
1554
1555#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1556#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1557#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1558pub struct TableAlias {
1559    pub name: Ident,
1560    pub columns: Vec<Ident>,
1561}
1562
1563impl fmt::Display for TableAlias {
1564    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1565        write!(f, "{}", self.name)?;
1566        if !self.columns.is_empty() {
1567            write!(f, " ({})", display_comma_separated(&self.columns))?;
1568        }
1569        Ok(())
1570    }
1571}
1572
1573#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1574#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1575#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1576pub enum TableVersion {
1577    ForSystemTimeAsOf(Expr),
1578}
1579
1580impl Display for TableVersion {
1581    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1582        match self {
1583            TableVersion::ForSystemTimeAsOf(e) => write!(f, " FOR SYSTEM_TIME AS OF {e}")?,
1584        }
1585        Ok(())
1586    }
1587}
1588
1589#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1590#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1591#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1592pub struct Join {
1593    pub relation: TableFactor,
1594    /// ClickHouse supports the optional `GLOBAL` keyword before the join operator.
1595    /// See [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/select/join)
1596    pub global: bool,
1597    pub join_operator: JoinOperator,
1598}
1599
1600impl fmt::Display for Join {
1601    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1602        fn prefix(constraint: &JoinConstraint) -> &'static str {
1603            match constraint {
1604                JoinConstraint::Natural => "NATURAL ",
1605                _ => "",
1606            }
1607        }
1608        fn suffix(constraint: &'_ JoinConstraint) -> impl fmt::Display + '_ {
1609            struct Suffix<'a>(&'a JoinConstraint);
1610            impl<'a> fmt::Display for Suffix<'a> {
1611                fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1612                    match self.0 {
1613                        JoinConstraint::On(expr) => write!(f, " ON {expr}"),
1614                        JoinConstraint::Using(attrs) => {
1615                            write!(f, " USING({})", display_comma_separated(attrs))
1616                        }
1617                        _ => Ok(()),
1618                    }
1619                }
1620            }
1621            Suffix(constraint)
1622        }
1623        if self.global {
1624            write!(f, " GLOBAL")?;
1625        }
1626
1627        match &self.join_operator {
1628            JoinOperator::Inner(constraint) => write!(
1629                f,
1630                " {}JOIN {}{}",
1631                prefix(constraint),
1632                self.relation,
1633                suffix(constraint)
1634            ),
1635            JoinOperator::LeftOuter(constraint) => write!(
1636                f,
1637                " {}LEFT JOIN {}{}",
1638                prefix(constraint),
1639                self.relation,
1640                suffix(constraint)
1641            ),
1642            JoinOperator::RightOuter(constraint) => write!(
1643                f,
1644                " {}RIGHT JOIN {}{}",
1645                prefix(constraint),
1646                self.relation,
1647                suffix(constraint)
1648            ),
1649            JoinOperator::FullOuter(constraint) => write!(
1650                f,
1651                " {}FULL JOIN {}{}",
1652                prefix(constraint),
1653                self.relation,
1654                suffix(constraint)
1655            ),
1656            JoinOperator::CrossJoin => write!(f, " CROSS JOIN {}", self.relation),
1657            JoinOperator::LeftSemi(constraint) => write!(
1658                f,
1659                " {}LEFT SEMI JOIN {}{}",
1660                prefix(constraint),
1661                self.relation,
1662                suffix(constraint)
1663            ),
1664            JoinOperator::RightSemi(constraint) => write!(
1665                f,
1666                " {}RIGHT SEMI JOIN {}{}",
1667                prefix(constraint),
1668                self.relation,
1669                suffix(constraint)
1670            ),
1671            JoinOperator::LeftAnti(constraint) => write!(
1672                f,
1673                " {}LEFT ANTI JOIN {}{}",
1674                prefix(constraint),
1675                self.relation,
1676                suffix(constraint)
1677            ),
1678            JoinOperator::RightAnti(constraint) => write!(
1679                f,
1680                " {}RIGHT ANTI JOIN {}{}",
1681                prefix(constraint),
1682                self.relation,
1683                suffix(constraint)
1684            ),
1685            JoinOperator::CrossApply => write!(f, " CROSS APPLY {}", self.relation),
1686            JoinOperator::OuterApply => write!(f, " OUTER APPLY {}", self.relation),
1687            JoinOperator::AsOf {
1688                match_condition,
1689                constraint,
1690            } => write!(
1691                f,
1692                " ASOF JOIN {} MATCH_CONDITION ({match_condition}){}",
1693                self.relation,
1694                suffix(constraint)
1695            ),
1696        }
1697    }
1698}
1699
1700#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1701#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1702#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1703pub enum JoinOperator {
1704    Inner(JoinConstraint),
1705    LeftOuter(JoinConstraint),
1706    RightOuter(JoinConstraint),
1707    FullOuter(JoinConstraint),
1708    CrossJoin,
1709    /// LEFT SEMI (non-standard)
1710    LeftSemi(JoinConstraint),
1711    /// RIGHT SEMI (non-standard)
1712    RightSemi(JoinConstraint),
1713    /// LEFT ANTI (non-standard)
1714    LeftAnti(JoinConstraint),
1715    /// RIGHT ANTI (non-standard)
1716    RightAnti(JoinConstraint),
1717    /// CROSS APPLY (non-standard)
1718    CrossApply,
1719    /// OUTER APPLY (non-standard)
1720    OuterApply,
1721    /// `ASOF` joins are used for joining tables containing time-series data
1722    /// whose timestamp columns do not match exactly.
1723    ///
1724    /// See <https://docs.snowflake.com/en/sql-reference/constructs/asof-join>.
1725    AsOf {
1726        match_condition: Expr,
1727        constraint: JoinConstraint,
1728    },
1729}
1730
1731#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1732#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1733#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1734pub enum JoinConstraint {
1735    On(Expr),
1736    Using(Vec<Ident>),
1737    Natural,
1738    None,
1739}
1740
1741#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1742#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1743#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1744pub struct OrderBy {
1745    pub exprs: Vec<OrderByExpr>,
1746    /// Optional: `INTERPOLATE`
1747    /// Supported by [ClickHouse syntax]
1748    ///
1749    /// [ClickHouse syntax]: <https://clickhouse.com/docs/en/sql-reference/statements/select/order-by#order-by-expr-with-fill-modifier>
1750    pub interpolate: Option<Interpolate>,
1751}
1752
1753impl fmt::Display for OrderBy {
1754    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1755        write!(f, "ORDER BY")?;
1756        if !self.exprs.is_empty() {
1757            write!(f, " {}", display_comma_separated(&self.exprs))?;
1758        }
1759        if let Some(ref interpolate) = self.interpolate {
1760            match &interpolate.exprs {
1761                Some(exprs) => write!(f, " INTERPOLATE ({})", display_comma_separated(exprs))?,
1762                None => write!(f, " INTERPOLATE")?,
1763            }
1764        }
1765        Ok(())
1766    }
1767}
1768
1769/// An `ORDER BY` expression
1770#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1771#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1772#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1773pub struct OrderByExpr {
1774    pub expr: Expr,
1775    /// Optional `ASC` or `DESC`
1776    pub asc: Option<bool>,
1777    /// Optional `NULLS FIRST` or `NULLS LAST`
1778    pub nulls_first: Option<bool>,
1779    /// Optional: `WITH FILL`
1780    /// Supported by [ClickHouse syntax]: <https://clickhouse.com/docs/en/sql-reference/statements/select/order-by#order-by-expr-with-fill-modifier>
1781    pub with_fill: Option<WithFill>,
1782}
1783
1784impl fmt::Display for OrderByExpr {
1785    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1786        write!(f, "{}", self.expr)?;
1787        match self.asc {
1788            Some(true) => write!(f, " ASC")?,
1789            Some(false) => write!(f, " DESC")?,
1790            None => (),
1791        }
1792        match self.nulls_first {
1793            Some(true) => write!(f, " NULLS FIRST")?,
1794            Some(false) => write!(f, " NULLS LAST")?,
1795            None => (),
1796        }
1797        if let Some(ref with_fill) = self.with_fill {
1798            write!(f, " {}", with_fill)?
1799        }
1800        Ok(())
1801    }
1802}
1803
1804/// ClickHouse `WITH FILL` modifier for `ORDER BY` clause.
1805/// Supported by [ClickHouse syntax]
1806///
1807/// [ClickHouse syntax]: <https://clickhouse.com/docs/en/sql-reference/statements/select/order-by#order-by-expr-with-fill-modifier>
1808#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1809#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1810#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1811pub struct WithFill {
1812    pub from: Option<Expr>,
1813    pub to: Option<Expr>,
1814    pub step: Option<Expr>,
1815}
1816
1817impl fmt::Display for WithFill {
1818    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1819        write!(f, "WITH FILL")?;
1820        if let Some(ref from) = self.from {
1821            write!(f, " FROM {}", from)?;
1822        }
1823        if let Some(ref to) = self.to {
1824            write!(f, " TO {}", to)?;
1825        }
1826        if let Some(ref step) = self.step {
1827            write!(f, " STEP {}", step)?;
1828        }
1829        Ok(())
1830    }
1831}
1832
1833/// ClickHouse `INTERPOLATE` clause for use in `ORDER BY` clause when using `WITH FILL` modifier.
1834/// Supported by [ClickHouse syntax]
1835///
1836/// [ClickHouse syntax]: <https://clickhouse.com/docs/en/sql-reference/statements/select/order-by#order-by-expr-with-fill-modifier>
1837#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1838#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1839#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1840pub struct InterpolateExpr {
1841    pub column: Ident,
1842    pub expr: Option<Expr>,
1843}
1844
1845#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1846#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1847#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1848pub struct Interpolate {
1849    pub exprs: Option<Vec<InterpolateExpr>>,
1850}
1851
1852impl fmt::Display for InterpolateExpr {
1853    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1854        write!(f, "{}", self.column)?;
1855        if let Some(ref expr) = self.expr {
1856            write!(f, " AS {}", expr)?;
1857        }
1858        Ok(())
1859    }
1860}
1861
1862#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1863#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1864#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1865pub struct Offset {
1866    pub value: Expr,
1867    pub rows: OffsetRows,
1868}
1869
1870impl fmt::Display for Offset {
1871    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1872        write!(f, "OFFSET {}{}", self.value, self.rows)
1873    }
1874}
1875
1876/// Stores the keyword after `OFFSET <number>`
1877#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1878#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1879#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1880pub enum OffsetRows {
1881    /// Omitting ROW/ROWS is non-standard MySQL quirk.
1882    None,
1883    Row,
1884    Rows,
1885}
1886
1887impl fmt::Display for OffsetRows {
1888    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1889        match self {
1890            OffsetRows::None => Ok(()),
1891            OffsetRows::Row => write!(f, " ROW"),
1892            OffsetRows::Rows => write!(f, " ROWS"),
1893        }
1894    }
1895}
1896
1897#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1898#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1899#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1900pub struct Fetch {
1901    pub with_ties: bool,
1902    pub percent: bool,
1903    pub quantity: Option<Expr>,
1904}
1905
1906impl fmt::Display for Fetch {
1907    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1908        let extension = if self.with_ties { "WITH TIES" } else { "ONLY" };
1909        if let Some(ref quantity) = self.quantity {
1910            let percent = if self.percent { " PERCENT" } else { "" };
1911            write!(f, "FETCH FIRST {quantity}{percent} ROWS {extension}")
1912        } else {
1913            write!(f, "FETCH FIRST ROWS {extension}")
1914        }
1915    }
1916}
1917
1918#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1919#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1920#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1921pub struct LockClause {
1922    pub lock_type: LockType,
1923    pub of: Option<ObjectName>,
1924    pub nonblock: Option<NonBlock>,
1925}
1926
1927impl fmt::Display for LockClause {
1928    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1929        write!(f, "FOR {}", &self.lock_type)?;
1930        if let Some(ref of) = self.of {
1931            write!(f, " OF {of}")?;
1932        }
1933        if let Some(ref nb) = self.nonblock {
1934            write!(f, " {nb}")?;
1935        }
1936        Ok(())
1937    }
1938}
1939
1940#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1941#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1942#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1943pub enum LockType {
1944    Share,
1945    Update,
1946}
1947
1948impl fmt::Display for LockType {
1949    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1950        let select_lock = match self {
1951            LockType::Share => "SHARE",
1952            LockType::Update => "UPDATE",
1953        };
1954        write!(f, "{select_lock}")
1955    }
1956}
1957
1958#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1959#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1960#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1961pub enum NonBlock {
1962    Nowait,
1963    SkipLocked,
1964}
1965
1966impl fmt::Display for NonBlock {
1967    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1968        let nonblock = match self {
1969            NonBlock::Nowait => "NOWAIT",
1970            NonBlock::SkipLocked => "SKIP LOCKED",
1971        };
1972        write!(f, "{nonblock}")
1973    }
1974}
1975
1976#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1977#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1978#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1979pub enum Distinct {
1980    /// DISTINCT
1981    Distinct,
1982
1983    /// DISTINCT ON({column names})
1984    On(Vec<Expr>),
1985}
1986
1987impl fmt::Display for Distinct {
1988    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1989        match self {
1990            Distinct::Distinct => write!(f, "DISTINCT"),
1991            Distinct::On(col_names) => {
1992                let col_names = display_comma_separated(col_names);
1993                write!(f, "DISTINCT ON ({col_names})")
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 Top {
2003    /// SQL semantic equivalent of LIMIT but with same structure as FETCH.
2004    /// MSSQL only.
2005    pub with_ties: bool,
2006    /// MSSQL only.
2007    pub percent: bool,
2008    pub quantity: Option<TopQuantity>,
2009}
2010
2011#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2012#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2013#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2014pub enum TopQuantity {
2015    // A parenthesized expression. MSSQL only.
2016    Expr(Expr),
2017    // An unparenthesized integer constant.
2018    Constant(u64),
2019}
2020
2021impl fmt::Display for Top {
2022    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2023        let extension = if self.with_ties { " WITH TIES" } else { "" };
2024        if let Some(ref quantity) = self.quantity {
2025            let percent = if self.percent { " PERCENT" } else { "" };
2026            match quantity {
2027                TopQuantity::Expr(quantity) => write!(f, "TOP ({quantity}){percent}{extension}"),
2028                TopQuantity::Constant(quantity) => {
2029                    write!(f, "TOP {quantity}{percent}{extension}")
2030                }
2031            }
2032        } else {
2033            write!(f, "TOP{extension}")
2034        }
2035    }
2036}
2037
2038#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2039#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2040#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2041pub struct Values {
2042    /// Was there an explicit ROWs keyword (MySQL)?
2043    /// <https://dev.mysql.com/doc/refman/8.0/en/values.html>
2044    pub explicit_row: bool,
2045    pub rows: Vec<Vec<Expr>>,
2046}
2047
2048impl fmt::Display for Values {
2049    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2050        write!(f, "VALUES ")?;
2051        let prefix = if self.explicit_row { "ROW" } else { "" };
2052        let mut delim = "";
2053        for row in &self.rows {
2054            write!(f, "{delim}")?;
2055            delim = ", ";
2056            write!(f, "{prefix}({})", display_comma_separated(row))?;
2057        }
2058        Ok(())
2059    }
2060}
2061
2062#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2063#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2064#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2065pub struct SelectInto {
2066    pub temporary: bool,
2067    pub unlogged: bool,
2068    pub table: bool,
2069    pub name: ObjectName,
2070}
2071
2072impl fmt::Display for SelectInto {
2073    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2074        let temporary = if self.temporary { " TEMPORARY" } else { "" };
2075        let unlogged = if self.unlogged { " UNLOGGED" } else { "" };
2076        let table = if self.table { " TABLE" } else { "" };
2077
2078        write!(f, "INTO{}{}{} {}", temporary, unlogged, table, self.name)
2079    }
2080}
2081
2082/// ClickHouse supports GROUP BY WITH modifiers(includes ROLLUP|CUBE|TOTALS).
2083/// e.g. GROUP BY year WITH ROLLUP WITH TOTALS
2084///
2085/// [ClickHouse]: <https://clickhouse.com/docs/en/sql-reference/statements/select/group-by#rollup-modifier>
2086#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2087#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2088#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2089pub enum GroupByWithModifier {
2090    Rollup,
2091    Cube,
2092    Totals,
2093}
2094
2095impl fmt::Display for GroupByWithModifier {
2096    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2097        match self {
2098            GroupByWithModifier::Rollup => write!(f, "WITH ROLLUP"),
2099            GroupByWithModifier::Cube => write!(f, "WITH CUBE"),
2100            GroupByWithModifier::Totals => write!(f, "WITH TOTALS"),
2101        }
2102    }
2103}
2104
2105#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2106#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2107#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2108pub enum GroupByExpr {
2109    /// ALL syntax of [Snowflake], [DuckDB] and [ClickHouse].
2110    ///
2111    /// [Snowflake]: <https://docs.snowflake.com/en/sql-reference/constructs/group-by#label-group-by-all-columns>
2112    /// [DuckDB]:  <https://duckdb.org/docs/sql/query_syntax/groupby.html>
2113    /// [ClickHouse]: <https://clickhouse.com/docs/en/sql-reference/statements/select/group-by#group-by-all>
2114    ///
2115    /// ClickHouse also supports WITH modifiers after GROUP BY ALL and expressions.
2116    ///
2117    /// [ClickHouse]: <https://clickhouse.com/docs/en/sql-reference/statements/select/group-by#rollup-modifier>
2118    All(Vec<GroupByWithModifier>),
2119
2120    /// Expressions
2121    Expressions(Vec<Expr>, Vec<GroupByWithModifier>),
2122}
2123
2124impl fmt::Display for GroupByExpr {
2125    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2126        match self {
2127            GroupByExpr::All(modifiers) => {
2128                write!(f, "GROUP BY ALL")?;
2129                if !modifiers.is_empty() {
2130                    write!(f, " {}", display_separated(modifiers, " "))?;
2131                }
2132                Ok(())
2133            }
2134            GroupByExpr::Expressions(col_names, modifiers) => {
2135                let col_names = display_comma_separated(col_names);
2136                write!(f, "GROUP BY {col_names}")?;
2137                if !modifiers.is_empty() {
2138                    write!(f, " {}", display_separated(modifiers, " "))?;
2139                }
2140                Ok(())
2141            }
2142        }
2143    }
2144}
2145
2146/// FORMAT identifier or FORMAT NULL clause, specific to ClickHouse.
2147///
2148/// [ClickHouse]: <https://clickhouse.com/docs/en/sql-reference/statements/select/format>
2149#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2150#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2151#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2152pub enum FormatClause {
2153    Identifier(Ident),
2154    Null,
2155}
2156
2157impl fmt::Display for FormatClause {
2158    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2159        match self {
2160            FormatClause::Identifier(ident) => write!(f, "FORMAT {}", ident),
2161            FormatClause::Null => write!(f, "FORMAT NULL"),
2162        }
2163    }
2164}
2165
2166/// FOR XML or FOR JSON clause, specific to MSSQL
2167/// (formats the output of a query as XML or JSON)
2168#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2169#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2170#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2171pub enum ForClause {
2172    Browse,
2173    Json {
2174        for_json: ForJson,
2175        root: Option<String>,
2176        include_null_values: bool,
2177        without_array_wrapper: bool,
2178    },
2179    Xml {
2180        for_xml: ForXml,
2181        elements: bool,
2182        binary_base64: bool,
2183        root: Option<String>,
2184        r#type: bool,
2185    },
2186}
2187
2188impl fmt::Display for ForClause {
2189    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2190        match self {
2191            ForClause::Browse => write!(f, "FOR BROWSE"),
2192            ForClause::Json {
2193                for_json,
2194                root,
2195                include_null_values,
2196                without_array_wrapper,
2197            } => {
2198                write!(f, "FOR JSON ")?;
2199                write!(f, "{}", for_json)?;
2200                if let Some(root) = root {
2201                    write!(f, ", ROOT('{}')", root)?;
2202                }
2203                if *include_null_values {
2204                    write!(f, ", INCLUDE_NULL_VALUES")?;
2205                }
2206                if *without_array_wrapper {
2207                    write!(f, ", WITHOUT_ARRAY_WRAPPER")?;
2208                }
2209                Ok(())
2210            }
2211            ForClause::Xml {
2212                for_xml,
2213                elements,
2214                binary_base64,
2215                root,
2216                r#type,
2217            } => {
2218                write!(f, "FOR XML ")?;
2219                write!(f, "{}", for_xml)?;
2220                if *binary_base64 {
2221                    write!(f, ", BINARY BASE64")?;
2222                }
2223                if *r#type {
2224                    write!(f, ", TYPE")?;
2225                }
2226                if let Some(root) = root {
2227                    write!(f, ", ROOT('{}')", root)?;
2228                }
2229                if *elements {
2230                    write!(f, ", ELEMENTS")?;
2231                }
2232                Ok(())
2233            }
2234        }
2235    }
2236}
2237
2238#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2239#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2240#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2241pub enum ForXml {
2242    Raw(Option<String>),
2243    Auto,
2244    Explicit,
2245    Path(Option<String>),
2246}
2247
2248impl fmt::Display for ForXml {
2249    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2250        match self {
2251            ForXml::Raw(root) => {
2252                write!(f, "RAW")?;
2253                if let Some(root) = root {
2254                    write!(f, "('{}')", root)?;
2255                }
2256                Ok(())
2257            }
2258            ForXml::Auto => write!(f, "AUTO"),
2259            ForXml::Explicit => write!(f, "EXPLICIT"),
2260            ForXml::Path(root) => {
2261                write!(f, "PATH")?;
2262                if let Some(root) = root {
2263                    write!(f, "('{}')", root)?;
2264                }
2265                Ok(())
2266            }
2267        }
2268    }
2269}
2270
2271#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2272#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2273#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2274pub enum ForJson {
2275    Auto,
2276    Path,
2277}
2278
2279impl fmt::Display for ForJson {
2280    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2281        match self {
2282            ForJson::Auto => write!(f, "AUTO"),
2283            ForJson::Path => write!(f, "PATH"),
2284        }
2285    }
2286}
2287
2288/// A single column definition in MySQL's `JSON_TABLE` table valued function.
2289///
2290/// See
2291/// - [MySQL's JSON_TABLE documentation](https://dev.mysql.com/doc/refman/8.0/en/json-table-functions.html#function_json-table)
2292/// - [Oracle's JSON_TABLE documentation](https://docs.oracle.com/en/database/oracle/oracle-database/21/sqlrf/JSON_TABLE.html)
2293/// - [MariaDB's JSON_TABLE documentation](https://mariadb.com/kb/en/json_table/)
2294///
2295/// ```sql
2296/// SELECT *
2297/// FROM JSON_TABLE(
2298///     '["a", "b"]',
2299///     '$[*]' COLUMNS (
2300///         name FOR ORDINALITY,
2301///         value VARCHAR(20) PATH '$',
2302///         NESTED PATH '$[*]' COLUMNS (
2303///             value VARCHAR(20) PATH '$'
2304///         )
2305///     )
2306/// ) AS jt;
2307/// ```
2308#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2309#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2310#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2311pub enum JsonTableColumn {
2312    /// A named column with a JSON path
2313    Named(JsonTableNamedColumn),
2314    /// The FOR ORDINALITY column, which is a special column that returns the index of the current row in a JSON array.
2315    ForOrdinality(Ident),
2316    /// A set of nested columns, which extracts data from a nested JSON array.
2317    Nested(JsonTableNestedColumn),
2318}
2319
2320impl fmt::Display for JsonTableColumn {
2321    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2322        match self {
2323            JsonTableColumn::Named(json_table_named_column) => {
2324                write!(f, "{json_table_named_column}")
2325            }
2326            JsonTableColumn::ForOrdinality(ident) => write!(f, "{} FOR ORDINALITY", ident),
2327            JsonTableColumn::Nested(json_table_nested_column) => {
2328                write!(f, "{json_table_nested_column}")
2329            }
2330        }
2331    }
2332}
2333
2334/// A nested column in a JSON_TABLE column list
2335///
2336/// See <https://mariadb.com/kb/en/json_table/#nested-paths>
2337#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2338#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2339#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2340pub struct JsonTableNestedColumn {
2341    pub path: Value,
2342    pub columns: Vec<JsonTableColumn>,
2343}
2344
2345impl fmt::Display for JsonTableNestedColumn {
2346    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2347        write!(
2348            f,
2349            "NESTED PATH {} COLUMNS ({})",
2350            self.path,
2351            display_comma_separated(&self.columns)
2352        )
2353    }
2354}
2355
2356/// A single column definition in MySQL's `JSON_TABLE` table valued function.
2357///
2358/// See <https://mariadb.com/kb/en/json_table/#path-columns>
2359///
2360/// ```sql
2361///         value VARCHAR(20) PATH '$'
2362/// ```
2363#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2364#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2365#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2366pub struct JsonTableNamedColumn {
2367    /// The name of the column to be extracted.
2368    pub name: Ident,
2369    /// The type of the column to be extracted.
2370    pub r#type: DataType,
2371    /// The path to the column to be extracted. Must be a literal string.
2372    pub path: Value,
2373    /// true if the column is a boolean set to true if the given path exists
2374    pub exists: bool,
2375    /// The empty handling clause of the column
2376    pub on_empty: Option<JsonTableColumnErrorHandling>,
2377    /// The error handling clause of the column
2378    pub on_error: Option<JsonTableColumnErrorHandling>,
2379}
2380
2381impl fmt::Display for JsonTableNamedColumn {
2382    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2383        write!(
2384            f,
2385            "{} {}{} PATH {}",
2386            self.name,
2387            self.r#type,
2388            if self.exists { " EXISTS" } else { "" },
2389            self.path
2390        )?;
2391        if let Some(on_empty) = &self.on_empty {
2392            write!(f, " {} ON EMPTY", on_empty)?;
2393        }
2394        if let Some(on_error) = &self.on_error {
2395            write!(f, " {} ON ERROR", on_error)?;
2396        }
2397        Ok(())
2398    }
2399}
2400
2401/// Stores the error handling clause of a `JSON_TABLE` table valued function:
2402/// {NULL | DEFAULT json_string | ERROR} ON {ERROR | EMPTY }
2403#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2404#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2405#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2406pub enum JsonTableColumnErrorHandling {
2407    Null,
2408    Default(Value),
2409    Error,
2410}
2411
2412impl fmt::Display for JsonTableColumnErrorHandling {
2413    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2414        match self {
2415            JsonTableColumnErrorHandling::Null => write!(f, "NULL"),
2416            JsonTableColumnErrorHandling::Default(json_string) => {
2417                write!(f, "DEFAULT {}", json_string)
2418            }
2419            JsonTableColumnErrorHandling::Error => write!(f, "ERROR"),
2420        }
2421    }
2422}
2423
2424/// BigQuery supports ValueTables which have 2 modes:
2425/// `SELECT AS STRUCT`
2426/// `SELECT AS VALUE`
2427/// <https://cloud.google.com/bigquery/docs/reference/standard-sql/query-syntax#value_tables>
2428#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2429#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2430#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2431pub enum ValueTableMode {
2432    AsStruct,
2433    AsValue,
2434}
2435
2436impl fmt::Display for ValueTableMode {
2437    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2438        match self {
2439            ValueTableMode::AsStruct => write!(f, "AS STRUCT"),
2440            ValueTableMode::AsValue => write!(f, "AS VALUE"),
2441        }
2442    }
2443}