sqltk_parser/ast/
query.rs

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