sqlparser/ast/
query.rs

1// Licensed under the Apache License, Version 2.0 (the "License");
2// you may not use this file except in compliance with the License.
3// You may obtain a copy of the License at
4//
5// http://www.apache.org/licenses/LICENSE-2.0
6//
7// Unless required by applicable law or agreed to in writing, software
8// distributed under the License is distributed on an "AS IS" BASIS,
9// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10// See the License for the specific language governing permissions and
11// limitations under the License.
12
13#[cfg(not(feature = "std"))]
14use alloc::{boxed::Box, vec::Vec};
15
16#[cfg(feature = "serde")]
17use serde::{Deserialize, Serialize};
18
19#[cfg(feature = "visitor")]
20use sqlparser_derive::{Visit, VisitMut};
21
22use crate::ast::*;
23
24/// The most complete variant of a `SELECT` query expression, optionally
25/// including `WITH`, `UNION` / other set operations, and `ORDER BY`.
26#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
27#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
28#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
29pub struct Query {
30    /// WITH (common table expressions, or CTEs)
31    pub with: Option<With>,
32    /// SELECT or UNION / EXCEPT / INTERSECT
33    pub body: Box<SetExpr>,
34    /// ORDER BY
35    pub order_by: Vec<OrderByExpr>,
36    /// `LIMIT { <N> | ALL }`
37    pub limit: Option<Expr>,
38    /// `OFFSET <N> [ { ROW | ROWS } ]`
39    pub offset: Option<Offset>,
40    /// `FETCH { FIRST | NEXT } <N> [ PERCENT ] { ROW | ROWS } | { ONLY | WITH TIES }`
41    pub fetch: Option<Fetch>,
42    /// `FOR { UPDATE | SHARE } [ OF table_name ] [ SKIP LOCKED | NOWAIT ]`
43    pub locks: Vec<LockClause>,
44}
45
46impl fmt::Display for Query {
47    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
48        if let Some(ref with) = self.with {
49            write!(f, "{with} ")?;
50        }
51        write!(f, "{}", self.body)?;
52        if !self.order_by.is_empty() {
53            write!(f, " ORDER BY {}", display_comma_separated(&self.order_by))?;
54        }
55        if let Some(ref limit) = self.limit {
56            write!(f, " LIMIT {limit}")?;
57        }
58        if let Some(ref offset) = self.offset {
59            write!(f, " {offset}")?;
60        }
61        if let Some(ref fetch) = self.fetch {
62            write!(f, " {fetch}")?;
63        }
64        if !self.locks.is_empty() {
65            write!(f, " {}", display_separated(&self.locks, " "))?;
66        }
67        Ok(())
68    }
69}
70
71/// A node in a tree, representing a "query body" expression, roughly:
72/// `SELECT ... [ {UNION|EXCEPT|INTERSECT} SELECT ...]`
73#[allow(clippy::large_enum_variant)]
74#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
75#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
76#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
77pub enum SetExpr {
78    /// Restricted SELECT .. FROM .. HAVING (no ORDER BY or set operations)
79    Select(Box<Select>),
80    /// Parenthesized SELECT subquery, which may include more set operations
81    /// in its body and an optional ORDER BY / LIMIT.
82    Query(Box<Query>),
83    /// UNION/EXCEPT/INTERSECT of two queries
84    SetOperation {
85        op: SetOperator,
86        set_quantifier: SetQuantifier,
87        left: Box<SetExpr>,
88        right: Box<SetExpr>,
89    },
90    Values(Values),
91    Insert(Statement),
92    Table(Box<Table>),
93}
94
95impl fmt::Display for SetExpr {
96    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
97        match self {
98            SetExpr::Select(s) => write!(f, "{s}"),
99            SetExpr::Query(q) => write!(f, "({q})"),
100            SetExpr::Values(v) => write!(f, "{v}"),
101            SetExpr::Insert(v) => write!(f, "{v}"),
102            SetExpr::Table(t) => write!(f, "{t}"),
103            SetExpr::SetOperation {
104                left,
105                right,
106                op,
107                set_quantifier,
108            } => {
109                write!(f, "{left} {op}")?;
110                match set_quantifier {
111                    SetQuantifier::All | SetQuantifier::Distinct => write!(f, " {set_quantifier}")?,
112                    SetQuantifier::None => write!(f, "{set_quantifier}")?,
113                }
114                write!(f, " {right}")?;
115                Ok(())
116            }
117        }
118    }
119}
120
121#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
122#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
123#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
124pub enum SetOperator {
125    Union,
126    Except,
127    Intersect,
128}
129
130impl fmt::Display for SetOperator {
131    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
132        f.write_str(match self {
133            SetOperator::Union => "UNION",
134            SetOperator::Except => "EXCEPT",
135            SetOperator::Intersect => "INTERSECT",
136        })
137    }
138}
139
140/// A quantifier for [SetOperator].
141// TODO: Restrict parsing specific SetQuantifier in some specific dialects.
142// For example, BigQuery does not support `DISTINCT` for `EXCEPT` and `INTERSECT`
143#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
144#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
145#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
146pub enum SetQuantifier {
147    All,
148    Distinct,
149    None,
150}
151
152impl fmt::Display for SetQuantifier {
153    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
154        match self {
155            SetQuantifier::All => write!(f, "ALL"),
156            SetQuantifier::Distinct => write!(f, "DISTINCT"),
157            SetQuantifier::None => write!(f, ""),
158        }
159    }
160}
161
162#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
163#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
164/// A [`TABLE` command]( https://www.postgresql.org/docs/current/sql-select.html#SQL-TABLE)
165#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
166pub struct Table {
167    pub table_name: Option<String>,
168    pub schema_name: Option<String>,
169}
170
171impl fmt::Display for Table {
172    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
173        if let Some(ref schema_name) = self.schema_name {
174            write!(
175                f,
176                "TABLE {}.{}",
177                schema_name,
178                self.table_name.as_ref().unwrap(),
179            )?;
180        } else {
181            write!(f, "TABLE {}", self.table_name.as_ref().unwrap(),)?;
182        }
183        Ok(())
184    }
185}
186
187/// A restricted variant of `SELECT` (without CTEs/`ORDER BY`), which may
188/// appear either as the only body item of a `Query`, or as an operand
189/// to a set operation like `UNION`.
190#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
191#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
192#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
193pub struct Select {
194    pub distinct: bool,
195    /// MSSQL syntax: `TOP (<N>) [ PERCENT ] [ WITH TIES ]`
196    pub top: Option<Top>,
197    /// projection expressions
198    pub projection: Vec<SelectItem>,
199    /// INTO
200    pub into: Option<SelectInto>,
201    /// FROM
202    pub from: Vec<TableWithJoins>,
203    /// LATERAL VIEWs
204    pub lateral_views: Vec<LateralView>,
205    /// WHERE
206    pub selection: Option<Expr>,
207    /// GROUP BY
208    pub group_by: Vec<Expr>,
209    /// CLUSTER BY (Hive)
210    pub cluster_by: Vec<Expr>,
211    /// DISTRIBUTE BY (Hive)
212    pub distribute_by: Vec<Expr>,
213    /// SORT BY (Hive)
214    pub sort_by: Vec<Expr>,
215    /// HAVING
216    pub having: Option<Expr>,
217    /// QUALIFY (Snowflake)
218    pub qualify: Option<Expr>,
219}
220
221impl fmt::Display for Select {
222    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
223        write!(f, "SELECT{}", if self.distinct { " DISTINCT" } else { "" })?;
224        if let Some(ref top) = self.top {
225            write!(f, " {top}")?;
226        }
227        write!(f, " {}", display_comma_separated(&self.projection))?;
228
229        if let Some(ref into) = self.into {
230            write!(f, " {into}")?;
231        }
232
233        if !self.from.is_empty() {
234            write!(f, " FROM {}", display_comma_separated(&self.from))?;
235        }
236        if !self.lateral_views.is_empty() {
237            for lv in &self.lateral_views {
238                write!(f, "{lv}")?;
239            }
240        }
241        if let Some(ref selection) = self.selection {
242            write!(f, " WHERE {selection}")?;
243        }
244        if !self.group_by.is_empty() {
245            write!(f, " GROUP BY {}", display_comma_separated(&self.group_by))?;
246        }
247        if !self.cluster_by.is_empty() {
248            write!(
249                f,
250                " CLUSTER BY {}",
251                display_comma_separated(&self.cluster_by)
252            )?;
253        }
254        if !self.distribute_by.is_empty() {
255            write!(
256                f,
257                " DISTRIBUTE BY {}",
258                display_comma_separated(&self.distribute_by)
259            )?;
260        }
261        if !self.sort_by.is_empty() {
262            write!(f, " SORT BY {}", display_comma_separated(&self.sort_by))?;
263        }
264        if let Some(ref having) = self.having {
265            write!(f, " HAVING {having}")?;
266        }
267        if let Some(ref qualify) = self.qualify {
268            write!(f, " QUALIFY {qualify}")?;
269        }
270        Ok(())
271    }
272}
273
274/// A hive LATERAL VIEW with potential column aliases
275#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
276#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
277#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
278pub struct LateralView {
279    /// LATERAL VIEW
280    pub lateral_view: Expr,
281    /// LATERAL VIEW table name
282    pub lateral_view_name: ObjectName,
283    /// LATERAL VIEW optional column aliases
284    pub lateral_col_alias: Vec<Ident>,
285    /// LATERAL VIEW OUTER
286    pub outer: bool,
287}
288
289impl fmt::Display for LateralView {
290    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
291        write!(
292            f,
293            " LATERAL VIEW{outer} {} {}",
294            self.lateral_view,
295            self.lateral_view_name,
296            outer = if self.outer { " OUTER" } else { "" }
297        )?;
298        if !self.lateral_col_alias.is_empty() {
299            write!(
300                f,
301                " AS {}",
302                display_comma_separated(&self.lateral_col_alias)
303            )?;
304        }
305        Ok(())
306    }
307}
308
309#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
310#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
311#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
312pub struct With {
313    pub recursive: bool,
314    pub cte_tables: Vec<Cte>,
315}
316
317impl fmt::Display for With {
318    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
319        write!(
320            f,
321            "WITH {}{}",
322            if self.recursive { "RECURSIVE " } else { "" },
323            display_comma_separated(&self.cte_tables)
324        )
325    }
326}
327
328/// A single CTE (used after `WITH`): `alias [(col1, col2, ...)] AS ( query )`
329/// The names in the column list before `AS`, when specified, replace the names
330/// of the columns returned by the query. The parser does not validate that the
331/// number of columns in the query matches the number of columns in the query.
332#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
333#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
334#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
335pub struct Cte {
336    pub alias: TableAlias,
337    pub query: Box<Query>,
338    pub from: Option<Ident>,
339}
340
341impl fmt::Display for Cte {
342    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
343        write!(f, "{} AS ({})", self.alias, self.query)?;
344        if let Some(ref fr) = self.from {
345            write!(f, " FROM {fr}")?;
346        }
347        Ok(())
348    }
349}
350
351/// One item of the comma-separated list following `SELECT`
352#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
353#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
354#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
355pub enum SelectItem {
356    /// Any expression, not followed by `[ AS ] alias`
357    UnnamedExpr(Expr),
358    /// An expression, followed by `[ AS ] alias`
359    ExprWithAlias { expr: Expr, alias: Ident },
360    /// `alias.*` or even `schema.table.*`
361    QualifiedWildcard(ObjectName, WildcardAdditionalOptions),
362    /// An unqualified `*`
363    Wildcard(WildcardAdditionalOptions),
364}
365
366/// Single aliased identifier
367///
368/// # Syntax
369/// ```plaintext
370/// <ident> AS <alias>
371/// ```
372#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
373#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
374#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
375pub struct IdentWithAlias {
376    pub ident: Ident,
377    pub alias: Ident,
378}
379
380impl fmt::Display for IdentWithAlias {
381    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
382        write!(f, "{} AS {}", self.ident, self.alias)
383    }
384}
385
386/// Additional options for wildcards, e.g. Snowflake `EXCLUDE`/`RENAME` and Bigquery `EXCEPT`.
387#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Default)]
388#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
389#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
390pub struct WildcardAdditionalOptions {
391    /// `[EXCLUDE...]`.
392    pub opt_exclude: Option<ExcludeSelectItem>,
393    /// `[EXCEPT...]`.
394    pub opt_except: Option<ExceptSelectItem>,
395    /// `[RENAME ...]`.
396    pub opt_rename: Option<RenameSelectItem>,
397    /// `[REPLACE]`
398    ///  BigQuery syntax: <https://cloud.google.com/bigquery/docs/reference/standard-sql/query-syntax#select_replace>
399    pub opt_replace: Option<ReplaceSelectItem>,
400}
401
402impl fmt::Display for WildcardAdditionalOptions {
403    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
404        if let Some(exclude) = &self.opt_exclude {
405            write!(f, " {exclude}")?;
406        }
407        if let Some(except) = &self.opt_except {
408            write!(f, " {except}")?;
409        }
410        if let Some(rename) = &self.opt_rename {
411            write!(f, " {rename}")?;
412        }
413        if let Some(replace) = &self.opt_replace {
414            write!(f, " {replace}")?;
415        }
416        Ok(())
417    }
418}
419
420/// Snowflake `EXCLUDE` information.
421///
422/// # Syntax
423/// ```plaintext
424/// <col_name>
425/// | (<col_name>, <col_name>, ...)
426/// ```
427#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
428#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
429#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
430pub enum ExcludeSelectItem {
431    /// Single column name without parenthesis.
432    ///
433    /// # Syntax
434    /// ```plaintext
435    /// <col_name>
436    /// ```
437    Single(Ident),
438    /// Multiple column names inside parenthesis.
439    /// # Syntax
440    /// ```plaintext
441    /// (<col_name>, <col_name>, ...)
442    /// ```
443    Multiple(Vec<Ident>),
444}
445
446impl fmt::Display for ExcludeSelectItem {
447    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
448        write!(f, "EXCLUDE")?;
449        match self {
450            Self::Single(column) => {
451                write!(f, " {column}")?;
452            }
453            Self::Multiple(columns) => {
454                write!(f, " ({})", display_comma_separated(columns))?;
455            }
456        }
457        Ok(())
458    }
459}
460
461/// Snowflake `RENAME` information.
462///
463/// # Syntax
464/// ```plaintext
465/// <col_name> AS <col_alias>
466/// | (<col_name> AS <col_alias>, <col_name> AS <col_alias>, ...)
467/// ```
468#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
469#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
470#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
471pub enum RenameSelectItem {
472    /// Single column name with alias without parenthesis.
473    ///
474    /// # Syntax
475    /// ```plaintext
476    /// <col_name> AS <col_alias>
477    /// ```
478    Single(IdentWithAlias),
479    /// Multiple column names with aliases inside parenthesis.
480    /// # Syntax
481    /// ```plaintext
482    /// (<col_name> AS <col_alias>, <col_name> AS <col_alias>, ...)
483    /// ```
484    Multiple(Vec<IdentWithAlias>),
485}
486
487impl fmt::Display for RenameSelectItem {
488    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
489        write!(f, "RENAME")?;
490        match self {
491            Self::Single(column) => {
492                write!(f, " {column}")?;
493            }
494            Self::Multiple(columns) => {
495                write!(f, " ({})", display_comma_separated(columns))?;
496            }
497        }
498        Ok(())
499    }
500}
501
502/// Bigquery `EXCEPT` information, with at least one column.
503///
504/// # Syntax
505/// ```plaintext
506/// EXCEPT (<col_name> [, ...])
507/// ```
508#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
509#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
510#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
511pub struct ExceptSelectItem {
512    /// First guaranteed column.
513    pub first_element: Ident,
514    /// Additional columns. This list can be empty.
515    pub additional_elements: Vec<Ident>,
516}
517
518impl fmt::Display for ExceptSelectItem {
519    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
520        write!(f, "EXCEPT ")?;
521        if self.additional_elements.is_empty() {
522            write!(f, "({})", self.first_element)?;
523        } else {
524            write!(
525                f,
526                "({}, {})",
527                self.first_element,
528                display_comma_separated(&self.additional_elements)
529            )?;
530        }
531        Ok(())
532    }
533}
534
535/// Bigquery `REPLACE` information.
536///
537/// # Syntax
538/// ```plaintext
539/// REPLACE (<new_expr> [AS] <col_name>)
540/// REPLACE (<col_name> [AS] <col_alias>, <col_name> [AS] <col_alias>, ...)
541/// ```
542#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
543#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
544#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
545pub struct ReplaceSelectItem {
546    pub items: Vec<Box<ReplaceSelectElement>>,
547}
548
549impl fmt::Display for ReplaceSelectItem {
550    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
551        write!(f, "REPLACE")?;
552        write!(f, " ({})", display_comma_separated(&self.items))?;
553        Ok(())
554    }
555}
556
557/// # Syntax
558/// ```plaintext
559/// <expr> [AS] <column_name>
560/// ```
561#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
562#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
563#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
564pub struct ReplaceSelectElement {
565    pub expr: Expr,
566    pub column_name: Ident,
567    pub as_keyword: bool,
568}
569
570impl fmt::Display for ReplaceSelectElement {
571    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
572        if self.as_keyword {
573            write!(f, "{} AS {}", self.expr, self.column_name)
574        } else {
575            write!(f, "{} {}", self.expr, self.column_name)
576        }
577    }
578}
579
580impl fmt::Display for SelectItem {
581    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
582        match &self {
583            SelectItem::UnnamedExpr(expr) => write!(f, "{expr}"),
584            SelectItem::ExprWithAlias { expr, alias } => write!(f, "{expr} AS {alias}"),
585            SelectItem::QualifiedWildcard(prefix, additional_options) => {
586                write!(f, "{prefix}.*")?;
587                write!(f, "{additional_options}")?;
588                Ok(())
589            }
590            SelectItem::Wildcard(additional_options) => {
591                write!(f, "*")?;
592                write!(f, "{additional_options}")?;
593                Ok(())
594            }
595        }
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 TableWithJoins {
603    pub relation: TableFactor,
604    pub joins: Vec<Join>,
605}
606
607impl fmt::Display for TableWithJoins {
608    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
609        write!(f, "{}", self.relation)?;
610        for join in &self.joins {
611            write!(f, "{join}")?;
612        }
613        Ok(())
614    }
615}
616
617/// A table name or a parenthesized subquery with an optional alias
618#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
619#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
620#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
621pub enum TableFactor {
622    Table {
623        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
624        name: ObjectName,
625        alias: Option<TableAlias>,
626        /// Arguments of a table-valued function, as supported by Postgres
627        /// and MSSQL. Note that deprecated MSSQL `FROM foo (NOLOCK)` syntax
628        /// will also be parsed as `args`.
629        ///
630        /// This field's value is `Some(v)`, where `v` is a (possibly empty)
631        /// vector of arguments, in the case of a table-valued function call,
632        /// whereas it's `None` in the case of a regular table name.
633        args: Option<Vec<FunctionArg>>,
634        /// MSSQL-specific `WITH (...)` hints such as NOLOCK.
635        with_hints: Vec<Expr>,
636    },
637    Derived {
638        lateral: bool,
639        subquery: Box<Query>,
640        alias: Option<TableAlias>,
641    },
642    /// `TABLE(<expr>)[ AS <alias> ]`
643    TableFunction {
644        expr: Expr,
645        alias: Option<TableAlias>,
646    },
647    /// ```sql
648    /// SELECT * FROM UNNEST ([10,20,30]) as numbers WITH OFFSET;
649    /// +---------+--------+
650    /// | numbers | offset |
651    /// +---------+--------+
652    /// | 10      | 0      |
653    /// | 20      | 1      |
654    /// | 30      | 2      |
655    /// +---------+--------+
656    /// ```
657    UNNEST {
658        alias: Option<TableAlias>,
659        array_expr: Box<Expr>,
660        with_offset: bool,
661        with_offset_alias: Option<Ident>,
662    },
663    /// Represents a parenthesized table factor. The SQL spec only allows a
664    /// join expression (`(foo <JOIN> bar [ <JOIN> baz ... ])`) to be nested,
665    /// possibly several times.
666    ///
667    /// The parser may also accept non-standard nesting of bare tables for some
668    /// dialects, but the information about such nesting is stripped from AST.
669    NestedJoin {
670        table_with_joins: Box<TableWithJoins>,
671        alias: Option<TableAlias>,
672    },
673}
674
675impl fmt::Display for TableFactor {
676    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
677        match self {
678            TableFactor::Table {
679                name,
680                alias,
681                args,
682                with_hints,
683            } => {
684                write!(f, "{name}")?;
685                if let Some(args) = args {
686                    write!(f, "({})", display_comma_separated(args))?;
687                }
688                if let Some(alias) = alias {
689                    write!(f, " AS {alias}")?;
690                }
691                if !with_hints.is_empty() {
692                    write!(f, " WITH ({})", display_comma_separated(with_hints))?;
693                }
694                Ok(())
695            }
696            TableFactor::Derived {
697                lateral,
698                subquery,
699                alias,
700            } => {
701                if *lateral {
702                    write!(f, "LATERAL ")?;
703                }
704                write!(f, "({subquery})")?;
705                if let Some(alias) = alias {
706                    write!(f, " AS {alias}")?;
707                }
708                Ok(())
709            }
710            TableFactor::TableFunction { expr, alias } => {
711                write!(f, "TABLE({expr})")?;
712                if let Some(alias) = alias {
713                    write!(f, " AS {alias}")?;
714                }
715                Ok(())
716            }
717            TableFactor::UNNEST {
718                alias,
719                array_expr,
720                with_offset,
721                with_offset_alias,
722            } => {
723                write!(f, "UNNEST({array_expr})")?;
724                if let Some(alias) = alias {
725                    write!(f, " AS {alias}")?;
726                }
727                if *with_offset {
728                    write!(f, " WITH OFFSET")?;
729                }
730                if let Some(alias) = with_offset_alias {
731                    write!(f, " AS {alias}")?;
732                }
733                Ok(())
734            }
735            TableFactor::NestedJoin {
736                table_with_joins,
737                alias,
738            } => {
739                write!(f, "({table_with_joins})")?;
740                if let Some(alias) = alias {
741                    write!(f, " AS {alias}")?;
742                }
743                Ok(())
744            }
745        }
746    }
747}
748
749#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
750#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
751#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
752pub struct TableAlias {
753    pub name: Ident,
754    pub columns: Vec<Ident>,
755}
756
757impl fmt::Display for TableAlias {
758    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
759        write!(f, "{}", self.name)?;
760        if !self.columns.is_empty() {
761            write!(f, " ({})", display_comma_separated(&self.columns))?;
762        }
763        Ok(())
764    }
765}
766
767#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
768#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
769#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
770pub struct Join {
771    pub relation: TableFactor,
772    pub join_operator: JoinOperator,
773}
774
775impl fmt::Display for Join {
776    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
777        fn prefix(constraint: &JoinConstraint) -> &'static str {
778            match constraint {
779                JoinConstraint::Natural => "NATURAL ",
780                _ => "",
781            }
782        }
783        fn suffix(constraint: &'_ JoinConstraint) -> impl fmt::Display + '_ {
784            struct Suffix<'a>(&'a JoinConstraint);
785            impl<'a> fmt::Display for Suffix<'a> {
786                fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
787                    match self.0 {
788                        JoinConstraint::On(expr) => write!(f, " ON {expr}"),
789                        JoinConstraint::Using(attrs) => {
790                            write!(f, " USING({})", display_comma_separated(attrs))
791                        }
792                        _ => Ok(()),
793                    }
794                }
795            }
796            Suffix(constraint)
797        }
798        match &self.join_operator {
799            JoinOperator::Inner(constraint) => write!(
800                f,
801                " {}JOIN {}{}",
802                prefix(constraint),
803                self.relation,
804                suffix(constraint)
805            ),
806            JoinOperator::LeftOuter(constraint) => write!(
807                f,
808                " {}LEFT JOIN {}{}",
809                prefix(constraint),
810                self.relation,
811                suffix(constraint)
812            ),
813            JoinOperator::RightOuter(constraint) => write!(
814                f,
815                " {}RIGHT JOIN {}{}",
816                prefix(constraint),
817                self.relation,
818                suffix(constraint)
819            ),
820            JoinOperator::FullOuter(constraint) => write!(
821                f,
822                " {}FULL JOIN {}{}",
823                prefix(constraint),
824                self.relation,
825                suffix(constraint)
826            ),
827            JoinOperator::CrossJoin => write!(f, " CROSS JOIN {}", self.relation),
828            JoinOperator::LeftSemi(constraint) => write!(
829                f,
830                " {}LEFT SEMI JOIN {}{}",
831                prefix(constraint),
832                self.relation,
833                suffix(constraint)
834            ),
835            JoinOperator::RightSemi(constraint) => write!(
836                f,
837                " {}RIGHT SEMI JOIN {}{}",
838                prefix(constraint),
839                self.relation,
840                suffix(constraint)
841            ),
842            JoinOperator::LeftAnti(constraint) => write!(
843                f,
844                " {}LEFT ANTI JOIN {}{}",
845                prefix(constraint),
846                self.relation,
847                suffix(constraint)
848            ),
849            JoinOperator::RightAnti(constraint) => write!(
850                f,
851                " {}RIGHT ANTI JOIN {}{}",
852                prefix(constraint),
853                self.relation,
854                suffix(constraint)
855            ),
856            JoinOperator::CrossApply => write!(f, " CROSS APPLY {}", self.relation),
857            JoinOperator::OuterApply => write!(f, " OUTER APPLY {}", self.relation),
858        }
859    }
860}
861
862#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
863#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
864#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
865pub enum JoinOperator {
866    Inner(JoinConstraint),
867    LeftOuter(JoinConstraint),
868    RightOuter(JoinConstraint),
869    FullOuter(JoinConstraint),
870    CrossJoin,
871    /// LEFT SEMI (non-standard)
872    LeftSemi(JoinConstraint),
873    /// RIGHT SEMI (non-standard)
874    RightSemi(JoinConstraint),
875    /// LEFT ANTI (non-standard)
876    LeftAnti(JoinConstraint),
877    /// RIGHT ANTI (non-standard)
878    RightAnti(JoinConstraint),
879    /// CROSS APPLY (non-standard)
880    CrossApply,
881    /// OUTER APPLY (non-standard)
882    OuterApply,
883}
884
885#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
886#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
887#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
888pub enum JoinConstraint {
889    On(Expr),
890    Using(Vec<Ident>),
891    Natural,
892    None,
893}
894
895/// An `ORDER BY` expression
896#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
897#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
898#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
899pub struct OrderByExpr {
900    pub expr: Expr,
901    /// Optional `ASC` or `DESC`
902    pub asc: Option<bool>,
903    /// Optional `NULLS FIRST` or `NULLS LAST`
904    pub nulls_first: Option<bool>,
905}
906
907impl fmt::Display for OrderByExpr {
908    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
909        write!(f, "{}", self.expr)?;
910        match self.asc {
911            Some(true) => write!(f, " ASC")?,
912            Some(false) => write!(f, " DESC")?,
913            None => (),
914        }
915        match self.nulls_first {
916            Some(true) => write!(f, " NULLS FIRST")?,
917            Some(false) => write!(f, " NULLS LAST")?,
918            None => (),
919        }
920        Ok(())
921    }
922}
923
924#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
925#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
926#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
927pub struct Offset {
928    pub value: Expr,
929    pub rows: OffsetRows,
930}
931
932impl fmt::Display for Offset {
933    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
934        write!(f, "OFFSET {}{}", self.value, self.rows)
935    }
936}
937
938/// Stores the keyword after `OFFSET <number>`
939#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
940#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
941#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
942pub enum OffsetRows {
943    /// Omitting ROW/ROWS is non-standard MySQL quirk.
944    None,
945    Row,
946    Rows,
947}
948
949impl fmt::Display for OffsetRows {
950    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
951        match self {
952            OffsetRows::None => Ok(()),
953            OffsetRows::Row => write!(f, " ROW"),
954            OffsetRows::Rows => write!(f, " ROWS"),
955        }
956    }
957}
958
959#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
960#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
961#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
962pub struct Fetch {
963    pub with_ties: bool,
964    pub percent: bool,
965    pub quantity: Option<Expr>,
966}
967
968impl fmt::Display for Fetch {
969    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
970        let extension = if self.with_ties { "WITH TIES" } else { "ONLY" };
971        if let Some(ref quantity) = self.quantity {
972            let percent = if self.percent { " PERCENT" } else { "" };
973            write!(f, "FETCH FIRST {quantity}{percent} ROWS {extension}")
974        } else {
975            write!(f, "FETCH FIRST ROWS {extension}")
976        }
977    }
978}
979
980#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
981#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
982#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
983pub struct LockClause {
984    pub lock_type: LockType,
985    pub of: Option<ObjectName>,
986    pub nonblock: Option<NonBlock>,
987}
988
989impl fmt::Display for LockClause {
990    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
991        write!(f, "FOR {}", &self.lock_type)?;
992        if let Some(ref of) = self.of {
993            write!(f, " OF {of}")?;
994        }
995        if let Some(ref nb) = self.nonblock {
996            write!(f, " {nb}")?;
997        }
998        Ok(())
999    }
1000}
1001
1002#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1003#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1004#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1005pub enum LockType {
1006    Share,
1007    Update,
1008}
1009
1010impl fmt::Display for LockType {
1011    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1012        let select_lock = match self {
1013            LockType::Share => "SHARE",
1014            LockType::Update => "UPDATE",
1015        };
1016        write!(f, "{select_lock}")
1017    }
1018}
1019
1020#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1021#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1022#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1023pub enum NonBlock {
1024    Nowait,
1025    SkipLocked,
1026}
1027
1028impl fmt::Display for NonBlock {
1029    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1030        let nonblock = match self {
1031            NonBlock::Nowait => "NOWAIT",
1032            NonBlock::SkipLocked => "SKIP LOCKED",
1033        };
1034        write!(f, "{nonblock}")
1035    }
1036}
1037
1038#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1039#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1040#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1041pub struct Top {
1042    /// SQL semantic equivalent of LIMIT but with same structure as FETCH.
1043    pub with_ties: bool,
1044    pub percent: bool,
1045    pub quantity: Option<Expr>,
1046}
1047
1048impl fmt::Display for Top {
1049    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1050        let extension = if self.with_ties { " WITH TIES" } else { "" };
1051        if let Some(ref quantity) = self.quantity {
1052            let percent = if self.percent { " PERCENT" } else { "" };
1053            write!(f, "TOP ({quantity}){percent}{extension}")
1054        } else {
1055            write!(f, "TOP{extension}")
1056        }
1057    }
1058}
1059
1060#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1061#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1062#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1063pub struct Values {
1064    /// Was there an explict ROWs keyword (MySQL)?
1065    /// <https://dev.mysql.com/doc/refman/8.0/en/values.html>
1066    pub explicit_row: bool,
1067    pub rows: Vec<Vec<Expr>>,
1068}
1069
1070impl fmt::Display for Values {
1071    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1072        write!(f, "VALUES ")?;
1073        let prefix = if self.explicit_row { "ROW" } else { "" };
1074        let mut delim = "";
1075        for row in &self.rows {
1076            write!(f, "{delim}")?;
1077            delim = ", ";
1078            write!(f, "{prefix}({})", display_comma_separated(row))?;
1079        }
1080        Ok(())
1081    }
1082}
1083
1084#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1085#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1086#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1087pub struct SelectInto {
1088    pub temporary: bool,
1089    pub unlogged: bool,
1090    pub table: bool,
1091    pub name: ObjectName,
1092}
1093
1094impl fmt::Display for SelectInto {
1095    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1096        let temporary = if self.temporary { " TEMPORARY" } else { "" };
1097        let unlogged = if self.unlogged { " UNLOGGED" } else { "" };
1098        let table = if self.table { " TABLE" } else { "" };
1099
1100        write!(f, "INTO{}{}{} {}", temporary, unlogged, table, self.name)
1101    }
1102}