sqlparser/ast/
query.rs

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