sqlparser/ast/
mod.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//! SQL Abstract Syntax Tree (AST) types
14#[cfg(not(feature = "std"))]
15use alloc::{
16    boxed::Box,
17    format,
18    string::{String, ToString},
19    vec::Vec,
20};
21use core::fmt::{self, Display};
22
23#[cfg(feature = "serde")]
24use serde::{Deserialize, Serialize};
25
26#[cfg(feature = "visitor")]
27use sqlparser_derive::{Visit, VisitMut};
28
29pub use self::data_type::{
30    ArrayElemTypeDef, CharLengthUnits, CharacterLength, DataType, ExactNumberInfo, TimezoneInfo,
31};
32pub use self::dcl::{AlterRoleOperation, ResetConfig, RoleOption, SetConfigValue};
33pub use self::ddl::{
34    AlterColumnOperation, AlterIndexOperation, AlterTableOperation, ColumnDef, ColumnOption,
35    ColumnOptionDef, ConstraintCharacteristics, DeferrableInitial, GeneratedAs,
36    GeneratedExpressionMode, IndexType, KeyOrIndexDisplay, Partition, ProcedureParam,
37    ReferentialAction, TableConstraint, UserDefinedTypeCompositeAttributeDef,
38    UserDefinedTypeRepresentation, ViewColumnDef,
39};
40pub use self::operator::{BinaryOperator, UnaryOperator};
41pub use self::query::{
42    Cte, Distinct, ExceptSelectItem, ExcludeSelectItem, Fetch, ForClause, ForJson, ForXml,
43    GroupByExpr, IdentWithAlias, Join, JoinConstraint, JoinOperator, JsonTableColumn,
44    JsonTableColumnErrorHandling, LateralView, LockClause, LockType, NamedWindowDefinition,
45    NonBlock, Offset, OffsetRows, OrderByExpr, Query, RenameSelectItem, ReplaceSelectElement,
46    ReplaceSelectItem, Select, SelectInto, SelectItem, SetExpr, SetOperator, SetQuantifier, Table,
47    TableAlias, TableFactor, TableVersion, TableWithJoins, Top, TopQuantity, Values,
48    WildcardAdditionalOptions, With,
49};
50pub use self::value::{
51    escape_quoted_string, DateTimeField, DollarQuotedString, TrimWhereField, Value,
52};
53
54use crate::ast::helpers::stmt_data_loading::{
55    DataLoadingOptions, StageLoadSelectItem, StageParamsObject,
56};
57#[cfg(feature = "visitor")]
58pub use visitor::*;
59
60mod data_type;
61mod dcl;
62mod ddl;
63pub mod helpers;
64mod operator;
65mod query;
66mod value;
67
68#[cfg(feature = "visitor")]
69mod visitor;
70
71struct DisplaySeparated<'a, T>
72where
73    T: fmt::Display,
74{
75    slice: &'a [T],
76    sep: &'static str,
77}
78
79impl<'a, T> fmt::Display for DisplaySeparated<'a, T>
80where
81    T: fmt::Display,
82{
83    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
84        let mut delim = "";
85        for t in self.slice {
86            write!(f, "{delim}")?;
87            delim = self.sep;
88            write!(f, "{t}")?;
89        }
90        Ok(())
91    }
92}
93
94fn display_separated<'a, T>(slice: &'a [T], sep: &'static str) -> DisplaySeparated<'a, T>
95where
96    T: fmt::Display,
97{
98    DisplaySeparated { slice, sep }
99}
100
101fn display_comma_separated<T>(slice: &[T]) -> DisplaySeparated<'_, T>
102where
103    T: fmt::Display,
104{
105    DisplaySeparated { slice, sep: ", " }
106}
107
108/// An identifier, decomposed into its value or character data and the quote style.
109#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
110#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
111#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
112pub struct Ident {
113    /// The value of the identifier without quotes.
114    pub value: String,
115    /// The starting quote if any. Valid quote characters are the single quote,
116    /// double quote, backtick, and opening square bracket.
117    pub quote_style: Option<char>,
118}
119
120impl Ident {
121    /// Create a new identifier with the given value and no quotes.
122    pub fn new<S>(value: S) -> Self
123    where
124        S: Into<String>,
125    {
126        Ident {
127            value: value.into(),
128            quote_style: None,
129        }
130    }
131
132    /// Create a new quoted identifier with the given quote and value. This function
133    /// panics if the given quote is not a valid quote character.
134    pub fn with_quote<S>(quote: char, value: S) -> Self
135    where
136        S: Into<String>,
137    {
138        assert!(quote == '\'' || quote == '"' || quote == '`' || quote == '[');
139        Ident {
140            value: value.into(),
141            quote_style: Some(quote),
142        }
143    }
144}
145
146impl From<&str> for Ident {
147    fn from(value: &str) -> Self {
148        Ident {
149            value: value.to_string(),
150            quote_style: None,
151        }
152    }
153}
154
155impl fmt::Display for Ident {
156    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
157        match self.quote_style {
158            Some(q) if q == '"' || q == '\'' || q == '`' => {
159                let escaped = value::escape_quoted_string(&self.value, q);
160                write!(f, "{q}{escaped}{q}")
161            }
162            Some('[') => write!(f, "[{}]", self.value),
163            None => f.write_str(&self.value),
164            _ => panic!("unexpected quote style"),
165        }
166    }
167}
168
169/// A name of a table, view, custom type, etc., possibly multi-part, i.e. db.schema.obj
170#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
171#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
172#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
173pub struct ObjectName(pub Vec<Ident>);
174
175impl fmt::Display for ObjectName {
176    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
177        write!(f, "{}", display_separated(&self.0, "."))
178    }
179}
180
181/// Represents an Array Expression, either
182/// `ARRAY[..]`, or `[..]`
183#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
184#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
185#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
186pub struct Array {
187    /// The list of expressions between brackets
188    pub elem: Vec<Expr>,
189
190    /// `true` for  `ARRAY[..]`, `false` for `[..]`
191    pub named: bool,
192}
193
194impl fmt::Display for Array {
195    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
196        write!(
197            f,
198            "{}[{}]",
199            if self.named { "ARRAY" } else { "" },
200            display_comma_separated(&self.elem)
201        )
202    }
203}
204
205/// Represents an INTERVAL expression, roughly in the following format:
206/// `INTERVAL '<value>' [ <leading_field> [ (<leading_precision>) ] ]
207/// [ TO <last_field> [ (<fractional_seconds_precision>) ] ]`,
208/// e.g. `INTERVAL '123:45.67' MINUTE(3) TO SECOND(2)`.
209///
210/// The parser does not validate the `<value>`, nor does it ensure
211/// that the `<leading_field>` units >= the units in `<last_field>`,
212/// so the user will have to reject intervals like `HOUR TO YEAR`.
213#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
214#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
215#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
216pub struct Interval {
217    pub value: Box<Expr>,
218    pub leading_field: Option<DateTimeField>,
219    pub leading_precision: Option<u64>,
220    pub last_field: Option<DateTimeField>,
221    /// The seconds precision can be specified in SQL source as
222    /// `INTERVAL '__' SECOND(_, x)` (in which case the `leading_field`
223    /// will be `Second` and the `last_field` will be `None`),
224    /// or as `__ TO SECOND(x)`.
225    pub fractional_seconds_precision: Option<u64>,
226}
227
228impl fmt::Display for Interval {
229    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
230        let value = self.value.as_ref();
231        match (
232            self.leading_field,
233            self.leading_precision,
234            self.fractional_seconds_precision,
235        ) {
236            (
237                Some(DateTimeField::Second),
238                Some(leading_precision),
239                Some(fractional_seconds_precision),
240            ) => {
241                // When the leading field is SECOND, the parser guarantees that
242                // the last field is None.
243                assert!(self.last_field.is_none());
244                write!(
245                    f,
246                    "INTERVAL {value} SECOND ({leading_precision}, {fractional_seconds_precision})"
247                )
248            }
249            _ => {
250                write!(f, "INTERVAL {value}")?;
251                if let Some(leading_field) = self.leading_field {
252                    write!(f, " {leading_field}")?;
253                }
254                if let Some(leading_precision) = self.leading_precision {
255                    write!(f, " ({leading_precision})")?;
256                }
257                if let Some(last_field) = self.last_field {
258                    write!(f, " TO {last_field}")?;
259                }
260                if let Some(fractional_seconds_precision) = self.fractional_seconds_precision {
261                    write!(f, " ({fractional_seconds_precision})")?;
262                }
263                Ok(())
264            }
265        }
266    }
267}
268
269/// JsonOperator
270#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
271#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
272#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
273pub enum JsonOperator {
274    /// -> keeps the value as json
275    Arrow,
276    /// ->> keeps the value as text or int.
277    LongArrow,
278    /// #> Extracts JSON sub-object at the specified path
279    HashArrow,
280    /// #>> Extracts JSON sub-object at the specified path as text
281    HashLongArrow,
282    /// : Colon is used by Snowflake (Which is similar to LongArrow)
283    Colon,
284    /// jsonb @> jsonb -> boolean: Test whether left json contains the right json
285    AtArrow,
286    /// jsonb <@ jsonb -> boolean: Test whether right json contains the left json
287    ArrowAt,
288    /// jsonb #- text[] -> jsonb: Deletes the field or array element at the specified
289    /// path, where path elements can be either field keys or array indexes.
290    HashMinus,
291    /// jsonb @? jsonpath -> boolean: Does JSON path return any item for the specified
292    /// JSON value?
293    AtQuestion,
294    /// jsonb @@ jsonpath → boolean: Returns the result of a JSON path predicate check
295    /// for the specified JSON value. Only the first item of the result is taken into
296    /// account. If the result is not Boolean, then NULL is returned.
297    AtAt,
298}
299
300impl fmt::Display for JsonOperator {
301    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
302        match self {
303            JsonOperator::Arrow => {
304                write!(f, "->")
305            }
306            JsonOperator::LongArrow => {
307                write!(f, "->>")
308            }
309            JsonOperator::HashArrow => {
310                write!(f, "#>")
311            }
312            JsonOperator::HashLongArrow => {
313                write!(f, "#>>")
314            }
315            JsonOperator::Colon => {
316                write!(f, ":")
317            }
318            JsonOperator::AtArrow => {
319                write!(f, "@>")
320            }
321            JsonOperator::ArrowAt => write!(f, "<@"),
322            JsonOperator::HashMinus => write!(f, "#-"),
323            JsonOperator::AtQuestion => write!(f, "@?"),
324            JsonOperator::AtAt => write!(f, "@@"),
325        }
326    }
327}
328
329/// A field definition within a struct.
330///
331/// [bigquery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-types#struct_type
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 StructField {
336    pub field_name: Option<Ident>,
337    pub field_type: DataType,
338}
339
340impl fmt::Display for StructField {
341    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
342        if let Some(name) = &self.field_name {
343            write!(f, "{name} {}", self.field_type)
344        } else {
345            write!(f, "{}", self.field_type)
346        }
347    }
348}
349
350/// Options for `CAST` / `TRY_CAST`
351/// BigQuery: <https://cloud.google.com/bigquery/docs/reference/standard-sql/format-elements#formatting_syntax>
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 CastFormat {
356    Value(Value),
357    ValueAtTimeZone(Value, Value),
358}
359
360/// An SQL expression of any type.
361///
362/// The parser does not distinguish between expressions of different types
363/// (e.g. boolean vs string), so the caller must handle expressions of
364/// inappropriate type, like `WHERE 1` or `SELECT 1=1`, as necessary.
365#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
366#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
367#[cfg_attr(
368    feature = "visitor",
369    derive(Visit, VisitMut),
370    visit(with = "visit_expr")
371)]
372pub enum Expr {
373    /// Identifier e.g. table name or column name
374    Identifier(Ident),
375    /// Multi-part identifier, e.g. `table_alias.column` or `schema.table.col`
376    CompoundIdentifier(Vec<Ident>),
377    /// JSON access (postgres)  eg: data->'tags'
378    JsonAccess {
379        left: Box<Expr>,
380        operator: JsonOperator,
381        right: Box<Expr>,
382    },
383    /// CompositeAccess (postgres) eg: SELECT (information_schema._pg_expandarray(array['i','i'])).n
384    CompositeAccess {
385        expr: Box<Expr>,
386        key: Ident,
387    },
388    /// `IS FALSE` operator
389    IsFalse(Box<Expr>),
390    /// `IS NOT FALSE` operator
391    IsNotFalse(Box<Expr>),
392    /// `IS TRUE` operator
393    IsTrue(Box<Expr>),
394    /// `IS NOT TRUE` operator
395    IsNotTrue(Box<Expr>),
396    /// `IS NULL` operator
397    IsNull(Box<Expr>),
398    /// `IS NOT NULL` operator
399    IsNotNull(Box<Expr>),
400    /// `IS UNKNOWN` operator
401    IsUnknown(Box<Expr>),
402    /// `IS NOT UNKNOWN` operator
403    IsNotUnknown(Box<Expr>),
404    /// `IS DISTINCT FROM` operator
405    IsDistinctFrom(Box<Expr>, Box<Expr>),
406    /// `IS NOT DISTINCT FROM` operator
407    IsNotDistinctFrom(Box<Expr>, Box<Expr>),
408    /// `[ NOT ] IN (val1, val2, ...)`
409    InList {
410        expr: Box<Expr>,
411        list: Vec<Expr>,
412        negated: bool,
413    },
414    /// `[ NOT ] IN (SELECT ...)`
415    InSubquery {
416        expr: Box<Expr>,
417        subquery: Box<Query>,
418        negated: bool,
419    },
420    /// `[ NOT ] IN UNNEST(array_expression)`
421    InUnnest {
422        expr: Box<Expr>,
423        array_expr: Box<Expr>,
424        negated: bool,
425    },
426    /// `<expr> [ NOT ] BETWEEN <low> AND <high>`
427    Between {
428        expr: Box<Expr>,
429        negated: bool,
430        low: Box<Expr>,
431        high: Box<Expr>,
432    },
433    /// Binary operation e.g. `1 + 1` or `foo > bar`
434    BinaryOp {
435        left: Box<Expr>,
436        op: BinaryOperator,
437        right: Box<Expr>,
438    },
439    /// `[NOT] LIKE <pattern> [ESCAPE <escape_character>]`
440    Like {
441        negated: bool,
442        expr: Box<Expr>,
443        pattern: Box<Expr>,
444        escape_char: Option<char>,
445    },
446    /// `ILIKE` (case-insensitive `LIKE`)
447    ILike {
448        negated: bool,
449        expr: Box<Expr>,
450        pattern: Box<Expr>,
451        escape_char: Option<char>,
452    },
453    /// SIMILAR TO regex
454    SimilarTo {
455        negated: bool,
456        expr: Box<Expr>,
457        pattern: Box<Expr>,
458        escape_char: Option<char>,
459    },
460    /// MySQL: RLIKE regex or REGEXP regex
461    RLike {
462        negated: bool,
463        expr: Box<Expr>,
464        pattern: Box<Expr>,
465        // true for REGEXP, false for RLIKE (no difference in semantics)
466        regexp: bool,
467    },
468    /// `ANY` operation e.g. `foo > ANY(bar)`, comparison operator is one of `[=, >, <, =>, =<, !=]`
469    AnyOp {
470        left: Box<Expr>,
471        compare_op: BinaryOperator,
472        right: Box<Expr>,
473    },
474    /// `ALL` operation e.g. `foo > ALL(bar)`, comparison operator is one of `[=, >, <, =>, =<, !=]`
475    AllOp {
476        left: Box<Expr>,
477        compare_op: BinaryOperator,
478        right: Box<Expr>,
479    },
480    /// Unary operation e.g. `NOT foo`
481    UnaryOp {
482        op: UnaryOperator,
483        expr: Box<Expr>,
484    },
485    /// CONVERT a value to a different data type or character encoding. e.g. `CONVERT(foo USING utf8mb4)`
486    Convert {
487        /// The expression to convert
488        expr: Box<Expr>,
489        /// The target data type
490        data_type: Option<DataType>,
491        /// The target character encoding
492        charset: Option<ObjectName>,
493        /// whether the target comes before the expr (MSSQL syntax)
494        target_before_value: bool,
495    },
496    /// `CAST` an expression to a different data type e.g. `CAST(foo AS VARCHAR(123))`
497    Cast {
498        expr: Box<Expr>,
499        data_type: DataType,
500        // Optional CAST(string_expression AS type FORMAT format_string_expression) as used by BigQuery
501        // https://cloud.google.com/bigquery/docs/reference/standard-sql/format-elements#formatting_syntax
502        format: Option<CastFormat>,
503    },
504    /// `TRY_CAST` an expression to a different data type e.g. `TRY_CAST(foo AS VARCHAR(123))`
505    //  this differs from CAST in the choice of how to implement invalid conversions
506    TryCast {
507        expr: Box<Expr>,
508        data_type: DataType,
509        // Optional CAST(string_expression AS type FORMAT format_string_expression) as used by BigQuery
510        // https://cloud.google.com/bigquery/docs/reference/standard-sql/format-elements#formatting_syntax
511        format: Option<CastFormat>,
512    },
513    /// `SAFE_CAST` an expression to a different data type e.g. `SAFE_CAST(foo AS FLOAT64)`
514    //  only available for BigQuery: https://cloud.google.com/bigquery/docs/reference/standard-sql/functions-and-operators#safe_casting
515    //  this works the same as `TRY_CAST`
516    SafeCast {
517        expr: Box<Expr>,
518        data_type: DataType,
519        // Optional CAST(string_expression AS type FORMAT format_string_expression) as used by BigQuery
520        // https://cloud.google.com/bigquery/docs/reference/standard-sql/format-elements#formatting_syntax
521        format: Option<CastFormat>,
522    },
523    /// AT a timestamp to a different timezone e.g. `FROM_UNIXTIME(0) AT TIME ZONE 'UTC-06:00'`
524    AtTimeZone {
525        timestamp: Box<Expr>,
526        time_zone: String,
527    },
528    /// Extract a field from a timestamp e.g. `EXTRACT(MONTH FROM foo)`
529    ///
530    /// Syntax:
531    /// ```sql
532    /// EXTRACT(DateTimeField FROM <expr>)
533    /// ```
534    Extract {
535        field: DateTimeField,
536        expr: Box<Expr>,
537    },
538    /// ```sql
539    /// CEIL(<expr> [TO DateTimeField])
540    /// ```
541    Ceil {
542        expr: Box<Expr>,
543        field: DateTimeField,
544    },
545    /// ```sql
546    /// FLOOR(<expr> [TO DateTimeField])
547    /// ```
548    Floor {
549        expr: Box<Expr>,
550        field: DateTimeField,
551    },
552    /// ```sql
553    /// POSITION(<expr> in <expr>)
554    /// ```
555    Position {
556        expr: Box<Expr>,
557        r#in: Box<Expr>,
558    },
559    /// ```sql
560    /// SUBSTRING(<expr> [FROM <expr>] [FOR <expr>])
561    /// ```
562    Substring {
563        expr: Box<Expr>,
564        substring_from: Option<Box<Expr>>,
565        substring_for: Option<Box<Expr>>,
566
567        // Some dialects use `SUBSTRING(expr [FROM start] [FOR len])` syntax while others omit FROM,
568        // FOR keywords (e.g. Microsoft SQL Server). This flags is used for formatting.
569        special: bool,
570    },
571    /// ```sql
572    /// TRIM([BOTH | LEADING | TRAILING] [<expr> FROM] <expr>)
573    /// TRIM(<expr>)
574    /// TRIM(<expr>, [, characters]) -- only Snowflake or Bigquery
575    /// ```
576    Trim {
577        expr: Box<Expr>,
578        // ([BOTH | LEADING | TRAILING]
579        trim_where: Option<TrimWhereField>,
580        trim_what: Option<Box<Expr>>,
581        trim_characters: Option<Vec<Expr>>,
582    },
583    /// ```sql
584    /// OVERLAY(<expr> PLACING <expr> FROM <expr>[ FOR <expr> ]
585    /// ```
586    Overlay {
587        expr: Box<Expr>,
588        overlay_what: Box<Expr>,
589        overlay_from: Box<Expr>,
590        overlay_for: Option<Box<Expr>>,
591    },
592    /// `expr COLLATE collation`
593    Collate {
594        expr: Box<Expr>,
595        collation: ObjectName,
596    },
597    /// Nested expression e.g. `(foo > bar)` or `(1)`
598    Nested(Box<Expr>),
599    /// A literal value, such as string, number, date or NULL
600    Value(Value),
601    /// <https://dev.mysql.com/doc/refman/8.0/en/charset-introducer.html>
602    IntroducedString {
603        introducer: String,
604        value: Value,
605    },
606    /// A constant of form `<data_type> 'value'`.
607    /// This can represent ANSI SQL `DATE`, `TIME`, and `TIMESTAMP` literals (such as `DATE '2020-01-01'`),
608    /// as well as constants of other types (a non-standard PostgreSQL extension).
609    TypedString {
610        data_type: DataType,
611        value: String,
612    },
613    /// Access a map-like object by field (e.g. `column['field']` or `column[4]`
614    /// Note that depending on the dialect, struct like accesses may be
615    /// parsed as [`ArrayIndex`](Self::ArrayIndex) or [`MapAccess`](Self::MapAccess)
616    /// <https://clickhouse.com/docs/en/sql-reference/data-types/map/>
617    MapAccess {
618        column: Box<Expr>,
619        keys: Vec<Expr>,
620    },
621    /// Scalar function call e.g. `LEFT(foo, 5)`
622    Function(Function),
623    /// Aggregate function with filter
624    AggregateExpressionWithFilter {
625        expr: Box<Expr>,
626        filter: Box<Expr>,
627    },
628    /// `CASE [<operand>] WHEN <condition> THEN <result> ... [ELSE <result>] END`
629    ///
630    /// Note we only recognize a complete single expression as `<condition>`,
631    /// not `< 0` nor `1, 2, 3` as allowed in a `<simple when clause>` per
632    /// <https://jakewheat.github.io/sql-overview/sql-2011-foundation-grammar.html#simple-when-clause>
633    Case {
634        operand: Option<Box<Expr>>,
635        conditions: Vec<Expr>,
636        results: Vec<Expr>,
637        else_result: Option<Box<Expr>>,
638    },
639    /// An exists expression `[ NOT ] EXISTS(SELECT ...)`, used in expressions like
640    /// `WHERE [ NOT ] EXISTS (SELECT ...)`.
641    Exists {
642        subquery: Box<Query>,
643        negated: bool,
644    },
645    /// A parenthesized subquery `(SELECT ...)`, used in expression like
646    /// `SELECT (subquery) AS x` or `WHERE (subquery) = x`
647    Subquery(Box<Query>),
648    /// An array subquery constructor, e.g. `SELECT ARRAY(SELECT 1 UNION SELECT 2)`
649    ArraySubquery(Box<Query>),
650    /// The `LISTAGG` function `SELECT LISTAGG(...) WITHIN GROUP (ORDER BY ...)`
651    ListAgg(ListAgg),
652    /// The `ARRAY_AGG` function `SELECT ARRAY_AGG(... ORDER BY ...)`
653    ArrayAgg(ArrayAgg),
654    /// The `GROUPING SETS` expr.
655    GroupingSets(Vec<Vec<Expr>>),
656    /// The `CUBE` expr.
657    Cube(Vec<Vec<Expr>>),
658    /// The `ROLLUP` expr.
659    Rollup(Vec<Vec<Expr>>),
660    /// ROW / TUPLE a single value, such as `SELECT (1, 2)`
661    Tuple(Vec<Expr>),
662    /// `BigQuery` specific `Struct` literal expression [1]
663    /// Syntax:
664    /// ```sql
665    /// STRUCT<[field_name] field_type, ...>( expr1 [, ... ])
666    /// ```
667    /// [1]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-types#struct_type
668    Struct {
669        /// Struct values.
670        values: Vec<Expr>,
671        /// Struct field definitions.
672        fields: Vec<StructField>,
673    },
674    /// `BigQuery` specific: An named expression in a typeless struct [1]
675    ///
676    /// Syntax
677    /// ```sql
678    /// 1 AS A
679    /// ```
680    /// [1]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-types#struct_type
681    Named {
682        expr: Box<Expr>,
683        name: Ident,
684    },
685    /// An array index expression e.g. `(ARRAY[1, 2])[1]` or `(current_schemas(FALSE))[1]`
686    ArrayIndex {
687        obj: Box<Expr>,
688        indexes: Vec<Expr>,
689    },
690    /// An array expression e.g. `ARRAY[1, 2]`
691    Array(Array),
692    /// An interval expression e.g. `INTERVAL '1' YEAR`
693    Interval(Interval),
694    /// `MySQL` specific text search function [(1)].
695    ///
696    /// Syntax:
697    /// ```sql
698    /// MATCH (<col>, <col>, ...) AGAINST (<expr> [<search modifier>])
699    ///
700    /// <col> = CompoundIdentifier
701    /// <expr> = String literal
702    /// ```
703    /// [(1)]: https://dev.mysql.com/doc/refman/8.0/en/fulltext-search.html#function_match
704    MatchAgainst {
705        /// `(<col>, <col>, ...)`.
706        columns: Vec<Ident>,
707        /// `<expr>`.
708        match_value: Value,
709        /// `<search modifier>`
710        opt_search_modifier: Option<SearchModifier>,
711    },
712    Wildcard,
713    /// Qualified wildcard, e.g. `alias.*` or `schema.table.*`.
714    /// (Same caveats apply to `QualifiedWildcard` as to `Wildcard`.)
715    QualifiedWildcard(ObjectName),
716}
717
718impl fmt::Display for CastFormat {
719    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
720        match self {
721            CastFormat::Value(v) => write!(f, "{v}"),
722            CastFormat::ValueAtTimeZone(v, tz) => write!(f, "{v} AT TIME ZONE {tz}"),
723        }
724    }
725}
726
727impl fmt::Display for Expr {
728    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
729        match self {
730            Expr::Identifier(s) => write!(f, "{s}"),
731            Expr::MapAccess { column, keys } => {
732                write!(f, "{column}")?;
733                for k in keys {
734                    match k {
735                        k @ Expr::Value(Value::Number(_, _)) => write!(f, "[{k}]")?,
736                        Expr::Value(Value::SingleQuotedString(s)) => write!(f, "[\"{s}\"]")?,
737                        _ => write!(f, "[{k}]")?,
738                    }
739                }
740                Ok(())
741            }
742            Expr::Wildcard => f.write_str("*"),
743            Expr::QualifiedWildcard(prefix) => write!(f, "{}.*", prefix),
744            Expr::CompoundIdentifier(s) => write!(f, "{}", display_separated(s, ".")),
745            Expr::IsTrue(ast) => write!(f, "{ast} IS TRUE"),
746            Expr::IsNotTrue(ast) => write!(f, "{ast} IS NOT TRUE"),
747            Expr::IsFalse(ast) => write!(f, "{ast} IS FALSE"),
748            Expr::IsNotFalse(ast) => write!(f, "{ast} IS NOT FALSE"),
749            Expr::IsNull(ast) => write!(f, "{ast} IS NULL"),
750            Expr::IsNotNull(ast) => write!(f, "{ast} IS NOT NULL"),
751            Expr::IsUnknown(ast) => write!(f, "{ast} IS UNKNOWN"),
752            Expr::IsNotUnknown(ast) => write!(f, "{ast} IS NOT UNKNOWN"),
753            Expr::InList {
754                expr,
755                list,
756                negated,
757            } => write!(
758                f,
759                "{} {}IN ({})",
760                expr,
761                if *negated { "NOT " } else { "" },
762                display_comma_separated(list)
763            ),
764            Expr::InSubquery {
765                expr,
766                subquery,
767                negated,
768            } => write!(
769                f,
770                "{} {}IN ({})",
771                expr,
772                if *negated { "NOT " } else { "" },
773                subquery
774            ),
775            Expr::InUnnest {
776                expr,
777                array_expr,
778                negated,
779            } => write!(
780                f,
781                "{} {}IN UNNEST({})",
782                expr,
783                if *negated { "NOT " } else { "" },
784                array_expr
785            ),
786            Expr::Between {
787                expr,
788                negated,
789                low,
790                high,
791            } => write!(
792                f,
793                "{} {}BETWEEN {} AND {}",
794                expr,
795                if *negated { "NOT " } else { "" },
796                low,
797                high
798            ),
799            Expr::BinaryOp { left, op, right } => write!(f, "{left} {op} {right}"),
800            Expr::Like {
801                negated,
802                expr,
803                pattern,
804                escape_char,
805            } => match escape_char {
806                Some(ch) => write!(
807                    f,
808                    "{} {}LIKE {} ESCAPE '{}'",
809                    expr,
810                    if *negated { "NOT " } else { "" },
811                    pattern,
812                    ch
813                ),
814                _ => write!(
815                    f,
816                    "{} {}LIKE {}",
817                    expr,
818                    if *negated { "NOT " } else { "" },
819                    pattern
820                ),
821            },
822            Expr::ILike {
823                negated,
824                expr,
825                pattern,
826                escape_char,
827            } => match escape_char {
828                Some(ch) => write!(
829                    f,
830                    "{} {}ILIKE {} ESCAPE '{}'",
831                    expr,
832                    if *negated { "NOT " } else { "" },
833                    pattern,
834                    ch
835                ),
836                _ => write!(
837                    f,
838                    "{} {}ILIKE {}",
839                    expr,
840                    if *negated { "NOT " } else { "" },
841                    pattern
842                ),
843            },
844            Expr::RLike {
845                negated,
846                expr,
847                pattern,
848                regexp,
849            } => write!(
850                f,
851                "{} {}{} {}",
852                expr,
853                if *negated { "NOT " } else { "" },
854                if *regexp { "REGEXP" } else { "RLIKE" },
855                pattern
856            ),
857            Expr::SimilarTo {
858                negated,
859                expr,
860                pattern,
861                escape_char,
862            } => match escape_char {
863                Some(ch) => write!(
864                    f,
865                    "{} {}SIMILAR TO {} ESCAPE '{}'",
866                    expr,
867                    if *negated { "NOT " } else { "" },
868                    pattern,
869                    ch
870                ),
871                _ => write!(
872                    f,
873                    "{} {}SIMILAR TO {}",
874                    expr,
875                    if *negated { "NOT " } else { "" },
876                    pattern
877                ),
878            },
879            Expr::AnyOp {
880                left,
881                compare_op,
882                right,
883            } => write!(f, "{left} {compare_op} ANY({right})"),
884            Expr::AllOp {
885                left,
886                compare_op,
887                right,
888            } => write!(f, "{left} {compare_op} ALL({right})"),
889            Expr::UnaryOp { op, expr } => {
890                if op == &UnaryOperator::PGPostfixFactorial {
891                    write!(f, "{expr}{op}")
892                } else if op == &UnaryOperator::Not {
893                    write!(f, "{op} {expr}")
894                } else {
895                    write!(f, "{op}{expr}")
896                }
897            }
898            Expr::Convert {
899                expr,
900                target_before_value,
901                data_type,
902                charset,
903            } => {
904                write!(f, "CONVERT(")?;
905                if let Some(data_type) = data_type {
906                    if let Some(charset) = charset {
907                        write!(f, "{expr}, {data_type} CHARACTER SET {charset}")
908                    } else if *target_before_value {
909                        write!(f, "{data_type}, {expr}")
910                    } else {
911                        write!(f, "{expr}, {data_type}")
912                    }
913                } else if let Some(charset) = charset {
914                    write!(f, "{expr} USING {charset}")
915                } else {
916                    write!(f, "{expr}") // This should never happen
917                }?;
918                write!(f, ")")
919            }
920            Expr::Cast {
921                expr,
922                data_type,
923                format,
924            } => {
925                if let Some(format) = format {
926                    write!(f, "CAST({expr} AS {data_type} FORMAT {format})")
927                } else {
928                    write!(f, "CAST({expr} AS {data_type})")
929                }
930            }
931            Expr::TryCast {
932                expr,
933                data_type,
934                format,
935            } => {
936                if let Some(format) = format {
937                    write!(f, "TRY_CAST({expr} AS {data_type} FORMAT {format})")
938                } else {
939                    write!(f, "TRY_CAST({expr} AS {data_type})")
940                }
941            }
942            Expr::SafeCast {
943                expr,
944                data_type,
945                format,
946            } => {
947                if let Some(format) = format {
948                    write!(f, "SAFE_CAST({expr} AS {data_type} FORMAT {format})")
949                } else {
950                    write!(f, "SAFE_CAST({expr} AS {data_type})")
951                }
952            }
953            Expr::Extract { field, expr } => write!(f, "EXTRACT({field} FROM {expr})"),
954            Expr::Ceil { expr, field } => {
955                if field == &DateTimeField::NoDateTime {
956                    write!(f, "CEIL({expr})")
957                } else {
958                    write!(f, "CEIL({expr} TO {field})")
959                }
960            }
961            Expr::Floor { expr, field } => {
962                if field == &DateTimeField::NoDateTime {
963                    write!(f, "FLOOR({expr})")
964                } else {
965                    write!(f, "FLOOR({expr} TO {field})")
966                }
967            }
968            Expr::Position { expr, r#in } => write!(f, "POSITION({expr} IN {in})"),
969            Expr::Collate { expr, collation } => write!(f, "{expr} COLLATE {collation}"),
970            Expr::Nested(ast) => write!(f, "({ast})"),
971            Expr::Value(v) => write!(f, "{v}"),
972            Expr::IntroducedString { introducer, value } => write!(f, "{introducer} {value}"),
973            Expr::TypedString { data_type, value } => {
974                write!(f, "{data_type}")?;
975                write!(f, " '{}'", &value::escape_single_quote_string(value))
976            }
977            Expr::Function(fun) => write!(f, "{fun}"),
978            Expr::AggregateExpressionWithFilter { expr, filter } => {
979                write!(f, "{expr} FILTER (WHERE {filter})")
980            }
981            Expr::Case {
982                operand,
983                conditions,
984                results,
985                else_result,
986            } => {
987                write!(f, "CASE")?;
988                if let Some(operand) = operand {
989                    write!(f, " {operand}")?;
990                }
991                for (c, r) in conditions.iter().zip(results) {
992                    write!(f, " WHEN {c} THEN {r}")?;
993                }
994
995                if let Some(else_result) = else_result {
996                    write!(f, " ELSE {else_result}")?;
997                }
998                write!(f, " END")
999            }
1000            Expr::Exists { subquery, negated } => write!(
1001                f,
1002                "{}EXISTS ({})",
1003                if *negated { "NOT " } else { "" },
1004                subquery
1005            ),
1006            Expr::Subquery(s) => write!(f, "({s})"),
1007            Expr::ArraySubquery(s) => write!(f, "ARRAY({s})"),
1008            Expr::ListAgg(listagg) => write!(f, "{listagg}"),
1009            Expr::ArrayAgg(arrayagg) => write!(f, "{arrayagg}"),
1010            Expr::GroupingSets(sets) => {
1011                write!(f, "GROUPING SETS (")?;
1012                let mut sep = "";
1013                for set in sets {
1014                    write!(f, "{sep}")?;
1015                    sep = ", ";
1016                    write!(f, "({})", display_comma_separated(set))?;
1017                }
1018                write!(f, ")")
1019            }
1020            Expr::Cube(sets) => {
1021                write!(f, "CUBE (")?;
1022                let mut sep = "";
1023                for set in sets {
1024                    write!(f, "{sep}")?;
1025                    sep = ", ";
1026                    if set.len() == 1 {
1027                        write!(f, "{}", set[0])?;
1028                    } else {
1029                        write!(f, "({})", display_comma_separated(set))?;
1030                    }
1031                }
1032                write!(f, ")")
1033            }
1034            Expr::Rollup(sets) => {
1035                write!(f, "ROLLUP (")?;
1036                let mut sep = "";
1037                for set in sets {
1038                    write!(f, "{sep}")?;
1039                    sep = ", ";
1040                    if set.len() == 1 {
1041                        write!(f, "{}", set[0])?;
1042                    } else {
1043                        write!(f, "({})", display_comma_separated(set))?;
1044                    }
1045                }
1046                write!(f, ")")
1047            }
1048            Expr::Substring {
1049                expr,
1050                substring_from,
1051                substring_for,
1052                special,
1053            } => {
1054                write!(f, "SUBSTRING({expr}")?;
1055                if let Some(from_part) = substring_from {
1056                    if *special {
1057                        write!(f, ", {from_part}")?;
1058                    } else {
1059                        write!(f, " FROM {from_part}")?;
1060                    }
1061                }
1062                if let Some(for_part) = substring_for {
1063                    if *special {
1064                        write!(f, ", {for_part}")?;
1065                    } else {
1066                        write!(f, " FOR {for_part}")?;
1067                    }
1068                }
1069
1070                write!(f, ")")
1071            }
1072            Expr::Overlay {
1073                expr,
1074                overlay_what,
1075                overlay_from,
1076                overlay_for,
1077            } => {
1078                write!(
1079                    f,
1080                    "OVERLAY({expr} PLACING {overlay_what} FROM {overlay_from}"
1081                )?;
1082                if let Some(for_part) = overlay_for {
1083                    write!(f, " FOR {for_part}")?;
1084                }
1085
1086                write!(f, ")")
1087            }
1088            Expr::IsDistinctFrom(a, b) => write!(f, "{a} IS DISTINCT FROM {b}"),
1089            Expr::IsNotDistinctFrom(a, b) => write!(f, "{a} IS NOT DISTINCT FROM {b}"),
1090            Expr::Trim {
1091                expr,
1092                trim_where,
1093                trim_what,
1094                trim_characters,
1095            } => {
1096                write!(f, "TRIM(")?;
1097                if let Some(ident) = trim_where {
1098                    write!(f, "{ident} ")?;
1099                }
1100                if let Some(trim_char) = trim_what {
1101                    write!(f, "{trim_char} FROM {expr}")?;
1102                } else {
1103                    write!(f, "{expr}")?;
1104                }
1105                if let Some(characters) = trim_characters {
1106                    write!(f, ", {}", display_comma_separated(characters))?;
1107                }
1108
1109                write!(f, ")")
1110            }
1111            Expr::Tuple(exprs) => {
1112                write!(f, "({})", display_comma_separated(exprs))
1113            }
1114            Expr::Struct { values, fields } => {
1115                if !fields.is_empty() {
1116                    write!(
1117                        f,
1118                        "STRUCT<{}>({})",
1119                        display_comma_separated(fields),
1120                        display_comma_separated(values)
1121                    )
1122                } else {
1123                    write!(f, "STRUCT({})", display_comma_separated(values))
1124                }
1125            }
1126            Expr::Named { expr, name } => {
1127                write!(f, "{} AS {}", expr, name)
1128            }
1129            Expr::ArrayIndex { obj, indexes } => {
1130                write!(f, "{obj}")?;
1131                for i in indexes {
1132                    write!(f, "[{i}]")?;
1133                }
1134                Ok(())
1135            }
1136            Expr::Array(set) => {
1137                write!(f, "{set}")
1138            }
1139            Expr::JsonAccess {
1140                left,
1141                operator,
1142                right,
1143            } => {
1144                if operator == &JsonOperator::Colon {
1145                    write!(f, "{left}{operator}{right}")
1146                } else {
1147                    write!(f, "{left} {operator} {right}")
1148                }
1149            }
1150            Expr::CompositeAccess { expr, key } => {
1151                write!(f, "{expr}.{key}")
1152            }
1153            Expr::AtTimeZone {
1154                timestamp,
1155                time_zone,
1156            } => {
1157                write!(f, "{timestamp} AT TIME ZONE '{time_zone}'")
1158            }
1159            Expr::Interval(interval) => {
1160                write!(f, "{interval}")
1161            }
1162            Expr::MatchAgainst {
1163                columns,
1164                match_value: match_expr,
1165                opt_search_modifier,
1166            } => {
1167                write!(f, "MATCH ({}) AGAINST ", display_comma_separated(columns),)?;
1168
1169                if let Some(search_modifier) = opt_search_modifier {
1170                    write!(f, "({match_expr} {search_modifier})")?;
1171                } else {
1172                    write!(f, "({match_expr})")?;
1173                }
1174
1175                Ok(())
1176            }
1177        }
1178    }
1179}
1180
1181#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1182#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1183#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1184pub enum WindowType {
1185    WindowSpec(WindowSpec),
1186    NamedWindow(Ident),
1187}
1188
1189impl Display for WindowType {
1190    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1191        match self {
1192            WindowType::WindowSpec(spec) => write!(f, "({})", spec),
1193            WindowType::NamedWindow(name) => write!(f, "{}", name),
1194        }
1195    }
1196}
1197
1198/// A window specification (i.e. `OVER (PARTITION BY .. ORDER BY .. etc.)`)
1199#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1200#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1201#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1202pub struct WindowSpec {
1203    /// `OVER (PARTITION BY ...)`
1204    pub partition_by: Vec<Expr>,
1205    /// `OVER (ORDER BY ...)`
1206    pub order_by: Vec<OrderByExpr>,
1207    /// `OVER (window frame)`
1208    pub window_frame: Option<WindowFrame>,
1209}
1210
1211impl fmt::Display for WindowSpec {
1212    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1213        let mut delim = "";
1214        if !self.partition_by.is_empty() {
1215            delim = " ";
1216            write!(
1217                f,
1218                "PARTITION BY {}",
1219                display_comma_separated(&self.partition_by)
1220            )?;
1221        }
1222        if !self.order_by.is_empty() {
1223            f.write_str(delim)?;
1224            delim = " ";
1225            write!(f, "ORDER BY {}", display_comma_separated(&self.order_by))?;
1226        }
1227        if let Some(window_frame) = &self.window_frame {
1228            f.write_str(delim)?;
1229            if let Some(end_bound) = &window_frame.end_bound {
1230                write!(
1231                    f,
1232                    "{} BETWEEN {} AND {}",
1233                    window_frame.units, window_frame.start_bound, end_bound
1234                )?;
1235            } else {
1236                write!(f, "{} {}", window_frame.units, window_frame.start_bound)?;
1237            }
1238        }
1239        Ok(())
1240    }
1241}
1242
1243/// Specifies the data processed by a window function, e.g.
1244/// `RANGE UNBOUNDED PRECEDING` or `ROWS BETWEEN 5 PRECEDING AND CURRENT ROW`.
1245///
1246/// Note: The parser does not validate the specified bounds; the caller should
1247/// reject invalid bounds like `ROWS UNBOUNDED FOLLOWING` before execution.
1248#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1249#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1250#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1251pub struct WindowFrame {
1252    pub units: WindowFrameUnits,
1253    pub start_bound: WindowFrameBound,
1254    /// The right bound of the `BETWEEN .. AND` clause. The end bound of `None`
1255    /// indicates the shorthand form (e.g. `ROWS 1 PRECEDING`), which must
1256    /// behave the same as `end_bound = WindowFrameBound::CurrentRow`.
1257    pub end_bound: Option<WindowFrameBound>,
1258    // TBD: EXCLUDE
1259}
1260
1261impl Default for WindowFrame {
1262    /// Returns default value for window frame
1263    ///
1264    /// See [this page](https://www.sqlite.org/windowfunctions.html#frame_specifications) for more details.
1265    fn default() -> Self {
1266        Self {
1267            units: WindowFrameUnits::Range,
1268            start_bound: WindowFrameBound::Preceding(None),
1269            end_bound: None,
1270        }
1271    }
1272}
1273
1274#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1275#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1276#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1277pub enum WindowFrameUnits {
1278    Rows,
1279    Range,
1280    Groups,
1281}
1282
1283impl fmt::Display for WindowFrameUnits {
1284    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1285        f.write_str(match self {
1286            WindowFrameUnits::Rows => "ROWS",
1287            WindowFrameUnits::Range => "RANGE",
1288            WindowFrameUnits::Groups => "GROUPS",
1289        })
1290    }
1291}
1292
1293/// Specifies Ignore / Respect NULL within window functions.
1294/// For example
1295/// `FIRST_VALUE(column2) IGNORE NULLS OVER (PARTITION BY column1)`
1296#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1297#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1298#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1299pub enum NullTreatment {
1300    IgnoreNulls,
1301    RespectNulls,
1302}
1303
1304impl fmt::Display for NullTreatment {
1305    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1306        f.write_str(match self {
1307            NullTreatment::IgnoreNulls => "IGNORE NULLS",
1308            NullTreatment::RespectNulls => "RESPECT NULLS",
1309        })
1310    }
1311}
1312
1313/// Specifies [WindowFrame]'s `start_bound` and `end_bound`
1314#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1315#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1316#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1317pub enum WindowFrameBound {
1318    /// `CURRENT ROW`
1319    CurrentRow,
1320    /// `<N> PRECEDING` or `UNBOUNDED PRECEDING`
1321    Preceding(Option<Box<Expr>>),
1322    /// `<N> FOLLOWING` or `UNBOUNDED FOLLOWING`.
1323    Following(Option<Box<Expr>>),
1324}
1325
1326impl fmt::Display for WindowFrameBound {
1327    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1328        match self {
1329            WindowFrameBound::CurrentRow => f.write_str("CURRENT ROW"),
1330            WindowFrameBound::Preceding(None) => f.write_str("UNBOUNDED PRECEDING"),
1331            WindowFrameBound::Following(None) => f.write_str("UNBOUNDED FOLLOWING"),
1332            WindowFrameBound::Preceding(Some(n)) => write!(f, "{n} PRECEDING"),
1333            WindowFrameBound::Following(Some(n)) => write!(f, "{n} FOLLOWING"),
1334        }
1335    }
1336}
1337
1338#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1339#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1340#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1341pub enum AddDropSync {
1342    ADD,
1343    DROP,
1344    SYNC,
1345}
1346
1347impl fmt::Display for AddDropSync {
1348    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1349        match self {
1350            AddDropSync::SYNC => f.write_str("SYNC PARTITIONS"),
1351            AddDropSync::DROP => f.write_str("DROP PARTITIONS"),
1352            AddDropSync::ADD => f.write_str("ADD PARTITIONS"),
1353        }
1354    }
1355}
1356
1357#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1358#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1359#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1360pub enum ShowCreateObject {
1361    Event,
1362    Function,
1363    Procedure,
1364    Table,
1365    Trigger,
1366    View,
1367}
1368
1369impl fmt::Display for ShowCreateObject {
1370    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1371        match self {
1372            ShowCreateObject::Event => f.write_str("EVENT"),
1373            ShowCreateObject::Function => f.write_str("FUNCTION"),
1374            ShowCreateObject::Procedure => f.write_str("PROCEDURE"),
1375            ShowCreateObject::Table => f.write_str("TABLE"),
1376            ShowCreateObject::Trigger => f.write_str("TRIGGER"),
1377            ShowCreateObject::View => f.write_str("VIEW"),
1378        }
1379    }
1380}
1381
1382#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1383#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1384#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1385pub enum CommentObject {
1386    Column,
1387    Table,
1388}
1389
1390impl fmt::Display for CommentObject {
1391    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1392        match self {
1393            CommentObject::Column => f.write_str("COLUMN"),
1394            CommentObject::Table => f.write_str("TABLE"),
1395        }
1396    }
1397}
1398
1399#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1400#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1401#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1402pub enum Password {
1403    Password(Expr),
1404    NullPassword,
1405}
1406
1407/// Sql options of a `CREATE TABLE` statement.
1408#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1409#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1410#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1411pub enum CreateTableOptions {
1412    None,
1413    /// Options specified using the `WITH` keyword.
1414    /// e.g. `WITH (description = "123")`
1415    ///
1416    /// <https://www.postgresql.org/docs/current/sql-createtable.html>
1417    With(Vec<SqlOption>),
1418    /// Options specified using the `OPTIONS` keyword.
1419    /// e.g. `OPTIONS(description = "123")`
1420    ///
1421    /// <https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#table_option_list>
1422    Options(Vec<SqlOption>),
1423}
1424
1425impl fmt::Display for CreateTableOptions {
1426    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1427        match self {
1428            CreateTableOptions::With(with_options) => {
1429                write!(f, "WITH ({})", display_comma_separated(with_options))
1430            }
1431            CreateTableOptions::Options(options) => {
1432                write!(f, "OPTIONS({})", display_comma_separated(options))
1433            }
1434            CreateTableOptions::None => Ok(()),
1435        }
1436    }
1437}
1438
1439/// A top-level statement (SELECT, INSERT, CREATE, etc.)
1440#[allow(clippy::large_enum_variant)]
1441#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1442#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1443#[cfg_attr(
1444    feature = "visitor",
1445    derive(Visit, VisitMut),
1446    visit(with = "visit_statement")
1447)]
1448pub enum Statement {
1449    /// ```sql
1450    /// ANALYZE
1451    /// ```
1452    /// Analyze (Hive)
1453    Analyze {
1454        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
1455        table_name: ObjectName,
1456        partitions: Option<Vec<Expr>>,
1457        for_columns: bool,
1458        columns: Vec<Ident>,
1459        cache_metadata: bool,
1460        noscan: bool,
1461        compute_statistics: bool,
1462    },
1463    /// ```sql
1464    /// TRUNCATE
1465    /// ```
1466    /// Truncate (Hive)
1467    Truncate {
1468        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
1469        table_name: ObjectName,
1470        partitions: Option<Vec<Expr>>,
1471        /// TABLE - optional keyword;
1472        table: bool,
1473    },
1474    /// ```sql
1475    /// MSCK
1476    /// ```
1477    /// Msck (Hive)
1478    Msck {
1479        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
1480        table_name: ObjectName,
1481        repair: bool,
1482        partition_action: Option<AddDropSync>,
1483    },
1484    /// ```sql
1485    /// SELECT
1486    /// ```
1487    Query(Box<Query>),
1488    /// ```sql
1489    /// INSERT
1490    /// ```
1491    Insert {
1492        /// Only for Sqlite
1493        or: Option<SqliteOnConflict>,
1494        /// Only for mysql
1495        ignore: bool,
1496        /// INTO - optional keyword
1497        into: bool,
1498        /// TABLE
1499        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
1500        table_name: ObjectName,
1501        /// table_name as foo (for PostgreSQL)
1502        table_alias: Option<Ident>,
1503        /// COLUMNS
1504        columns: Vec<Ident>,
1505        /// Overwrite (Hive)
1506        overwrite: bool,
1507        /// A SQL query that specifies what to insert
1508        source: Option<Box<Query>>,
1509        /// partitioned insert (Hive)
1510        partitioned: Option<Vec<Expr>>,
1511        /// Columns defined after PARTITION
1512        after_columns: Vec<Ident>,
1513        /// whether the insert has the table keyword (Hive)
1514        table: bool,
1515        /// Only for mysql
1516        as_table: Option<ObjectName>,
1517        /// Only for mysql
1518        as_table_after_columns: Vec<Ident>,
1519        on: Option<OnInsert>,
1520        /// RETURNING
1521        returning: Option<Vec<SelectItem>>,
1522        /// Only for mysql
1523        replace_into: bool,
1524        /// Only for mysql
1525        priority: Option<MysqlInsertPriority>,
1526    },
1527    // TODO: Support ROW FORMAT
1528    Directory {
1529        overwrite: bool,
1530        local: bool,
1531        path: String,
1532        file_format: Option<FileFormat>,
1533        source: Box<Query>,
1534    },
1535    /// ```sql
1536    /// CALL <function>
1537    /// ```
1538    Call(Function),
1539    /// ```sql
1540    /// COPY [TO | FROM] ...
1541    /// ```
1542    Copy {
1543        /// The source of 'COPY TO', or the target of 'COPY FROM'
1544        source: CopySource,
1545        /// If true, is a 'COPY TO' statement. If false is a 'COPY FROM'
1546        to: bool,
1547        /// The target of 'COPY TO', or the source of 'COPY FROM'
1548        target: CopyTarget,
1549        /// WITH options (from PostgreSQL version 9.0)
1550        options: Vec<CopyOption>,
1551        /// WITH options (before PostgreSQL version 9.0)
1552        legacy_options: Vec<CopyLegacyOption>,
1553        /// VALUES a vector of values to be copied
1554        values: Vec<Option<String>>,
1555    },
1556    /// ```sql
1557    /// COPY INTO
1558    /// ```
1559    /// See <https://docs.snowflake.com/en/sql-reference/sql/copy-into-table>
1560    /// Copy Into syntax available for Snowflake is different than the one implemented in
1561    /// Postgres. Although they share common prefix, it is reasonable to implement them
1562    /// in different enums. This can be refactored later once custom dialects
1563    /// are allowed to have custom Statements.
1564    CopyIntoSnowflake {
1565        into: ObjectName,
1566        from_stage: ObjectName,
1567        from_stage_alias: Option<Ident>,
1568        stage_params: StageParamsObject,
1569        from_transformations: Option<Vec<StageLoadSelectItem>>,
1570        files: Option<Vec<String>>,
1571        pattern: Option<String>,
1572        file_format: DataLoadingOptions,
1573        copy_options: DataLoadingOptions,
1574        validation_mode: Option<String>,
1575    },
1576    /// ```sql
1577    /// CLOSE
1578    /// ```
1579    /// Closes the portal underlying an open cursor.
1580    Close {
1581        /// Cursor name
1582        cursor: CloseCursor,
1583    },
1584    /// ```sql
1585    /// UPDATE
1586    /// ```
1587    Update {
1588        /// TABLE
1589        table: TableWithJoins,
1590        /// Column assignments
1591        assignments: Vec<Assignment>,
1592        /// Table which provide value to be set
1593        from: Option<TableWithJoins>,
1594        /// WHERE
1595        selection: Option<Expr>,
1596        /// RETURNING
1597        returning: Option<Vec<SelectItem>>,
1598    },
1599    /// ```sql
1600    /// DELETE
1601    /// ```
1602    Delete {
1603        /// Multi tables delete are supported in mysql
1604        tables: Vec<ObjectName>,
1605        /// FROM
1606        from: Vec<TableWithJoins>,
1607        /// USING (Snowflake, Postgres, MySQL)
1608        using: Option<Vec<TableWithJoins>>,
1609        /// WHERE
1610        selection: Option<Expr>,
1611        /// RETURNING
1612        returning: Option<Vec<SelectItem>>,
1613        /// ORDER BY (MySQL)
1614        order_by: Vec<OrderByExpr>,
1615        /// LIMIT (MySQL)
1616        limit: Option<Expr>,
1617    },
1618    /// ```sql
1619    /// CREATE VIEW
1620    /// ```
1621    CreateView {
1622        or_replace: bool,
1623        materialized: bool,
1624        /// View name
1625        name: ObjectName,
1626        columns: Vec<ViewColumnDef>,
1627        query: Box<Query>,
1628        options: CreateTableOptions,
1629        cluster_by: Vec<Ident>,
1630        /// if true, has RedShift [`WITH NO SCHEMA BINDING`] clause <https://docs.aws.amazon.com/redshift/latest/dg/r_CREATE_VIEW.html>
1631        with_no_schema_binding: bool,
1632        /// if true, has SQLite `IF NOT EXISTS` clause <https://www.sqlite.org/lang_createview.html>
1633        if_not_exists: bool,
1634        /// if true, has SQLite `TEMP` or `TEMPORARY` clause <https://www.sqlite.org/lang_createview.html>
1635        temporary: bool,
1636    },
1637    /// ```sql
1638    /// CREATE TABLE
1639    /// ```
1640    CreateTable {
1641        or_replace: bool,
1642        temporary: bool,
1643        external: bool,
1644        global: Option<bool>,
1645        if_not_exists: bool,
1646        transient: bool,
1647        /// Table name
1648        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
1649        name: ObjectName,
1650        /// Optional schema
1651        columns: Vec<ColumnDef>,
1652        constraints: Vec<TableConstraint>,
1653        hive_distribution: HiveDistributionStyle,
1654        hive_formats: Option<HiveFormat>,
1655        table_properties: Vec<SqlOption>,
1656        with_options: Vec<SqlOption>,
1657        file_format: Option<FileFormat>,
1658        location: Option<String>,
1659        query: Option<Box<Query>>,
1660        without_rowid: bool,
1661        like: Option<ObjectName>,
1662        clone: Option<ObjectName>,
1663        engine: Option<String>,
1664        comment: Option<String>,
1665        auto_increment_offset: Option<u32>,
1666        default_charset: Option<String>,
1667        collation: Option<String>,
1668        on_commit: Option<OnCommit>,
1669        /// ClickHouse "ON CLUSTER" clause:
1670        /// <https://clickhouse.com/docs/en/sql-reference/distributed-ddl/>
1671        on_cluster: Option<String>,
1672        /// ClickHouse "ORDER BY " clause. Note that omitted ORDER BY is different
1673        /// than empty (represented as ()), the latter meaning "no sorting".
1674        /// <https://clickhouse.com/docs/en/sql-reference/statements/create/table/>
1675        order_by: Option<Vec<Ident>>,
1676        /// BigQuery: A partition expression for the table.
1677        /// <https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#partition_expression>
1678        partition_by: Option<Box<Expr>>,
1679        /// BigQuery: Table clustering column list.
1680        /// <https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#table_option_list>
1681        cluster_by: Option<Vec<Ident>>,
1682        /// BigQuery: Table options list.
1683        /// <https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#table_option_list>
1684        options: Option<Vec<SqlOption>>,
1685        /// SQLite "STRICT" clause.
1686        /// if the "STRICT" table-option keyword is added to the end, after the closing ")",
1687        /// then strict typing rules apply to that table.
1688        strict: bool,
1689    },
1690    /// ```sql
1691    /// CREATE VIRTUAL TABLE .. USING <module_name> (<module_args>)`
1692    /// ```
1693    /// Sqlite specific statement
1694    CreateVirtualTable {
1695        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
1696        name: ObjectName,
1697        if_not_exists: bool,
1698        module_name: Ident,
1699        module_args: Vec<Ident>,
1700    },
1701    /// ```sql
1702    /// `CREATE INDEX`
1703    /// ```
1704    CreateIndex {
1705        /// index name
1706        name: Option<ObjectName>,
1707        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
1708        table_name: ObjectName,
1709        using: Option<Ident>,
1710        columns: Vec<OrderByExpr>,
1711        unique: bool,
1712        concurrently: bool,
1713        if_not_exists: bool,
1714        include: Vec<Ident>,
1715        nulls_distinct: Option<bool>,
1716        predicate: Option<Expr>,
1717    },
1718    /// ```sql
1719    /// CREATE ROLE
1720    /// ```
1721    /// See [postgres](https://www.postgresql.org/docs/current/sql-createrole.html)
1722    CreateRole {
1723        names: Vec<ObjectName>,
1724        if_not_exists: bool,
1725        // Postgres
1726        login: Option<bool>,
1727        inherit: Option<bool>,
1728        bypassrls: Option<bool>,
1729        password: Option<Password>,
1730        superuser: Option<bool>,
1731        create_db: Option<bool>,
1732        create_role: Option<bool>,
1733        replication: Option<bool>,
1734        connection_limit: Option<Expr>,
1735        valid_until: Option<Expr>,
1736        in_role: Vec<Ident>,
1737        in_group: Vec<Ident>,
1738        role: Vec<Ident>,
1739        user: Vec<Ident>,
1740        admin: Vec<Ident>,
1741        // MSSQL
1742        authorization_owner: Option<ObjectName>,
1743    },
1744    /// ```sql
1745    /// ALTER TABLE
1746    /// ```
1747    AlterTable {
1748        /// Table name
1749        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
1750        name: ObjectName,
1751        if_exists: bool,
1752        only: bool,
1753        operations: Vec<AlterTableOperation>,
1754    },
1755    /// ```sql
1756    /// ALTER INDEX
1757    /// ```
1758    AlterIndex {
1759        name: ObjectName,
1760        operation: AlterIndexOperation,
1761    },
1762    /// ```sql
1763    /// ALTER VIEW
1764    /// ```
1765    AlterView {
1766        /// View name
1767        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
1768        name: ObjectName,
1769        columns: Vec<Ident>,
1770        query: Box<Query>,
1771        with_options: Vec<SqlOption>,
1772    },
1773    /// ```sql
1774    /// ALTER ROLE
1775    /// ```
1776    AlterRole {
1777        name: Ident,
1778        operation: AlterRoleOperation,
1779    },
1780    /// ```sql
1781    /// ATTACH DATABASE 'path/to/file' AS alias
1782    /// ```
1783    /// (SQLite-specific)
1784    AttachDatabase {
1785        /// The name to bind to the newly attached database
1786        schema_name: Ident,
1787        /// An expression that indicates the path to the database file
1788        database_file_name: Expr,
1789        /// true if the syntax is 'ATTACH DATABASE', false if it's just 'ATTACH'
1790        database: bool,
1791    },
1792    /// ```sql
1793    /// DROP [TABLE, VIEW, ...]
1794    /// ```
1795    Drop {
1796        /// The type of the object to drop: TABLE, VIEW, etc.
1797        object_type: ObjectType,
1798        /// An optional `IF EXISTS` clause. (Non-standard.)
1799        if_exists: bool,
1800        /// One or more objects to drop. (ANSI SQL requires exactly one.)
1801        names: Vec<ObjectName>,
1802        /// Whether `CASCADE` was specified. This will be `false` when
1803        /// `RESTRICT` or no drop behavior at all was specified.
1804        cascade: bool,
1805        /// Whether `RESTRICT` was specified. This will be `false` when
1806        /// `CASCADE` or no drop behavior at all was specified.
1807        restrict: bool,
1808        /// Hive allows you specify whether the table's stored data will be
1809        /// deleted along with the dropped table
1810        purge: bool,
1811        /// MySQL-specific "TEMPORARY" keyword
1812        temporary: bool,
1813    },
1814    /// ```sql
1815    /// DROP FUNCTION
1816    /// ```
1817    DropFunction {
1818        if_exists: bool,
1819        /// One or more function to drop
1820        func_desc: Vec<DropFunctionDesc>,
1821        /// `CASCADE` or `RESTRICT`
1822        option: Option<ReferentialAction>,
1823    },
1824    /// ```sql
1825    /// DECLARE
1826    /// ```
1827    /// Declare Cursor Variables
1828    ///
1829    /// Note: this is a PostgreSQL-specific statement,
1830    /// but may also compatible with other SQL.
1831    Declare {
1832        /// Cursor name
1833        name: Ident,
1834        /// Causes the cursor to return data in binary rather than in text format.
1835        binary: bool,
1836        /// None = Not specified
1837        /// Some(true) = INSENSITIVE
1838        /// Some(false) = ASENSITIVE
1839        sensitive: Option<bool>,
1840        /// None = Not specified
1841        /// Some(true) = SCROLL
1842        /// Some(false) = NO SCROLL
1843        scroll: Option<bool>,
1844        /// None = Not specified
1845        /// Some(true) = WITH HOLD, specifies that the cursor can continue to be used after the transaction that created it successfully commits
1846        /// Some(false) = WITHOUT HOLD, specifies that the cursor cannot be used outside of the transaction that created it
1847        hold: Option<bool>,
1848        query: Box<Query>,
1849    },
1850    /// ```sql
1851    /// CREATE EXTENSION [ IF NOT EXISTS ] extension_name
1852    ///     [ WITH ] [ SCHEMA schema_name ]
1853    ///              [ VERSION version ]
1854    ///              [ CASCADE ]
1855    /// ```
1856    ///
1857    /// Note: this is a PostgreSQL-specific statement,
1858    CreateExtension {
1859        name: Ident,
1860        if_not_exists: bool,
1861        cascade: bool,
1862        schema: Option<Ident>,
1863        version: Option<Ident>,
1864    },
1865    /// ```sql
1866    /// FETCH
1867    /// ```
1868    /// Retrieve rows from a query using a cursor
1869    ///
1870    /// Note: this is a PostgreSQL-specific statement,
1871    /// but may also compatible with other SQL.
1872    Fetch {
1873        /// Cursor name
1874        name: Ident,
1875        direction: FetchDirection,
1876        /// Optional, It's possible to fetch rows form cursor to the table
1877        into: Option<ObjectName>,
1878    },
1879    /// ```sql
1880    /// FLUSH [NO_WRITE_TO_BINLOG | LOCAL] flush_option [, flush_option] ... | tables_option
1881    /// ```
1882    ///
1883    /// Note: this is a Mysql-specific statement,
1884    /// but may also compatible with other SQL.
1885    Flush {
1886        object_type: FlushType,
1887        location: Option<FlushLocation>,
1888        channel: Option<String>,
1889        read_lock: bool,
1890        export: bool,
1891        tables: Vec<ObjectName>,
1892    },
1893    /// ```sql
1894    /// DISCARD [ ALL | PLANS | SEQUENCES | TEMPORARY | TEMP ]
1895    /// ```
1896    ///
1897    /// Note: this is a PostgreSQL-specific statement,
1898    /// but may also compatible with other SQL.
1899    Discard { object_type: DiscardObject },
1900    /// ```sql
1901    /// SET [ SESSION | LOCAL ] ROLE role_name
1902    /// ```
1903    ///
1904    /// Sets sesssion state. Examples: [ANSI][1], [Postgresql][2], [MySQL][3], and [Oracle][4]
1905    ///
1906    /// [1]: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#set-role-statement
1907    /// [2]: https://www.postgresql.org/docs/14/sql-set-role.html
1908    /// [3]: https://dev.mysql.com/doc/refman/8.0/en/set-role.html
1909    /// [4]: https://docs.oracle.com/cd/B19306_01/server.102/b14200/statements_10004.htm
1910    SetRole {
1911        /// Non-ANSI optional identifier to inform if the role is defined inside the current session (`SESSION`) or transaction (`LOCAL`).
1912        context_modifier: ContextModifier,
1913        /// Role name. If NONE is specified, then the current role name is removed.
1914        role_name: Option<Ident>,
1915    },
1916    /// ```sql
1917    /// SET <variable>
1918    /// ```
1919    ///
1920    /// Note: this is not a standard SQL statement, but it is supported by at
1921    /// least MySQL and PostgreSQL. Not all MySQL-specific syntatic forms are
1922    /// supported yet.
1923    SetVariable {
1924        local: bool,
1925        hivevar: bool,
1926        variable: ObjectName,
1927        value: Vec<Expr>,
1928    },
1929    /// ```sql
1930    /// SET TIME ZONE <value>
1931    /// ```
1932    ///
1933    /// Note: this is a PostgreSQL-specific statements
1934    /// `SET TIME ZONE <value>` is an alias for `SET timezone TO <value>` in PostgreSQL
1935    SetTimeZone { local: bool, value: Expr },
1936    /// ```sql
1937    /// SET NAMES 'charset_name' [COLLATE 'collation_name']
1938    /// ```
1939    ///
1940    /// Note: this is a MySQL-specific statement.
1941    SetNames {
1942        charset_name: String,
1943        collation_name: Option<String>,
1944    },
1945    /// ```sql
1946    /// SET NAMES DEFAULT
1947    /// ```
1948    ///
1949    /// Note: this is a MySQL-specific statement.
1950    SetNamesDefault {},
1951    /// `SHOW FUNCTIONS`
1952    ///
1953    /// Note: this is a Presto-specific statement.
1954    ShowFunctions { filter: Option<ShowStatementFilter> },
1955    /// ```sql
1956    /// SHOW <variable>
1957    /// ```
1958    ///
1959    /// Note: this is a PostgreSQL-specific statement.
1960    ShowVariable { variable: Vec<Ident> },
1961    /// ```sql
1962    /// SHOW VARIABLES
1963    /// ```
1964    ///
1965    /// Note: this is a MySQL-specific statement.
1966    ShowVariables {
1967        filter: Option<ShowStatementFilter>,
1968        global: bool,
1969        session: bool,
1970    },
1971    /// ```sql
1972    /// SHOW CREATE TABLE
1973    /// ```
1974    ///
1975    /// Note: this is a MySQL-specific statement.
1976    ShowCreate {
1977        obj_type: ShowCreateObject,
1978        obj_name: ObjectName,
1979    },
1980    /// ```sql
1981    /// SHOW COLUMNS
1982    /// ```
1983    ///
1984    /// Note: this is a MySQL-specific statement.
1985    ShowColumns {
1986        extended: bool,
1987        full: bool,
1988        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
1989        table_name: ObjectName,
1990        filter: Option<ShowStatementFilter>,
1991    },
1992    /// ```sql
1993    /// SHOW TABLES
1994    /// ```
1995    /// Note: this is a MySQL-specific statement.
1996    ShowTables {
1997        extended: bool,
1998        full: bool,
1999        db_name: Option<Ident>,
2000        filter: Option<ShowStatementFilter>,
2001    },
2002    /// ```sql
2003    /// SHOW COLLATION
2004    /// ```
2005    ///
2006    /// Note: this is a MySQL-specific statement.
2007    ShowCollation { filter: Option<ShowStatementFilter> },
2008    /// ```sql
2009    /// USE
2010    /// ```
2011    ///
2012    /// Note: This is a MySQL-specific statement.
2013    Use { db_name: Ident },
2014    /// ```sql
2015    /// START  [ TRANSACTION | WORK ] | START TRANSACTION } ...
2016    /// ```
2017    /// If `begin` is false.
2018    ///
2019    /// ```sql
2020    /// `BEGIN  [ TRANSACTION | WORK ] | START TRANSACTION } ...`
2021    /// ```
2022    /// If `begin` is true
2023    StartTransaction {
2024        modes: Vec<TransactionMode>,
2025        begin: bool,
2026        /// Only for SQLite
2027        modifier: Option<TransactionModifier>,
2028    },
2029    /// ```sql
2030    /// SET TRANSACTION ...
2031    /// ```
2032    SetTransaction {
2033        modes: Vec<TransactionMode>,
2034        snapshot: Option<Value>,
2035        session: bool,
2036    },
2037    /// ```sql
2038    /// COMMENT ON ...
2039    /// ```
2040    ///
2041    /// Note: this is a PostgreSQL-specific statement.
2042    Comment {
2043        object_type: CommentObject,
2044        object_name: ObjectName,
2045        comment: Option<String>,
2046        /// An optional `IF EXISTS` clause. (Non-standard.)
2047        /// See <https://docs.snowflake.com/en/sql-reference/sql/comment>
2048        if_exists: bool,
2049    },
2050    /// ```sql
2051    /// COMMIT [ TRANSACTION | WORK ] [ AND [ NO ] CHAIN ]
2052    /// ```
2053    Commit { chain: bool },
2054    /// ```sql
2055    /// ROLLBACK [ TRANSACTION | WORK ] [ AND [ NO ] CHAIN ] [ TO [ SAVEPOINT ] savepoint_name ]
2056    /// ```
2057    Rollback {
2058        chain: bool,
2059        savepoint: Option<Ident>,
2060    },
2061    /// ```sql
2062    /// CREATE SCHEMA
2063    /// ```
2064    CreateSchema {
2065        /// `<schema name> | AUTHORIZATION <schema authorization identifier>  | <schema name>  AUTHORIZATION <schema authorization identifier>`
2066        schema_name: SchemaName,
2067        if_not_exists: bool,
2068    },
2069    /// ```sql
2070    /// CREATE DATABASE
2071    /// ```
2072    CreateDatabase {
2073        db_name: ObjectName,
2074        if_not_exists: bool,
2075        location: Option<String>,
2076        managed_location: Option<String>,
2077    },
2078    /// ```sql
2079    /// CREATE FUNCTION
2080    /// ```
2081    ///
2082    /// Supported variants:
2083    /// 1. [Hive](https://cwiki.apache.org/confluence/display/hive/languagemanual+ddl#LanguageManualDDL-Create/Drop/ReloadFunction)
2084    /// 2. [Postgres](https://www.postgresql.org/docs/15/sql-createfunction.html)
2085    CreateFunction {
2086        or_replace: bool,
2087        temporary: bool,
2088        name: ObjectName,
2089        args: Option<Vec<OperateFunctionArg>>,
2090        return_type: Option<DataType>,
2091        /// Optional parameters.
2092        params: CreateFunctionBody,
2093    },
2094    /// ```sql
2095    /// CREATE PROCEDURE
2096    /// ```
2097    CreateProcedure {
2098        or_alter: bool,
2099        name: ObjectName,
2100        params: Option<Vec<ProcedureParam>>,
2101        body: Vec<Statement>,
2102    },
2103    /// ```sql
2104    /// CREATE MACRO
2105    /// ```
2106    ///
2107    /// Supported variants:
2108    /// 1. [DuckDB](https://duckdb.org/docs/sql/statements/create_macro)
2109    CreateMacro {
2110        or_replace: bool,
2111        temporary: bool,
2112        name: ObjectName,
2113        args: Option<Vec<MacroArg>>,
2114        definition: MacroDefinition,
2115    },
2116    /// ```sql
2117    /// CREATE STAGE
2118    /// ```
2119    /// See <https://docs.snowflake.com/en/sql-reference/sql/create-stage>
2120    CreateStage {
2121        or_replace: bool,
2122        temporary: bool,
2123        if_not_exists: bool,
2124        name: ObjectName,
2125        stage_params: StageParamsObject,
2126        directory_table_params: DataLoadingOptions,
2127        file_format: DataLoadingOptions,
2128        copy_options: DataLoadingOptions,
2129        comment: Option<String>,
2130    },
2131    /// ```sql
2132    /// ASSERT <condition> [AS <message>]
2133    /// ```
2134    Assert {
2135        condition: Expr,
2136        message: Option<Expr>,
2137    },
2138    /// ```sql
2139    /// GRANT privileges ON objects TO grantees
2140    /// ```
2141    Grant {
2142        privileges: Privileges,
2143        objects: GrantObjects,
2144        grantees: Vec<Ident>,
2145        with_grant_option: bool,
2146        granted_by: Option<Ident>,
2147    },
2148    /// ```sql
2149    /// REVOKE privileges ON objects FROM grantees
2150    /// ```
2151    Revoke {
2152        privileges: Privileges,
2153        objects: GrantObjects,
2154        grantees: Vec<Ident>,
2155        granted_by: Option<Ident>,
2156        cascade: bool,
2157    },
2158    /// ```sql
2159    /// DEALLOCATE [ PREPARE ] { name | ALL }
2160    /// ```
2161    ///
2162    /// Note: this is a PostgreSQL-specific statement.
2163    Deallocate { name: Ident, prepare: bool },
2164    /// ```sql
2165    /// EXECUTE name [ ( parameter [, ...] ) ]
2166    /// ```
2167    ///
2168    /// Note: this is a PostgreSQL-specific statement.
2169    Execute { name: Ident, parameters: Vec<Expr> },
2170    /// ```sql
2171    /// PREPARE name [ ( data_type [, ...] ) ] AS statement
2172    /// ```
2173    ///
2174    /// Note: this is a PostgreSQL-specific statement.
2175    Prepare {
2176        name: Ident,
2177        data_types: Vec<DataType>,
2178        statement: Box<Statement>,
2179    },
2180    /// ```sql
2181    /// KILL [CONNECTION | QUERY | MUTATION]
2182    /// ```
2183    ///
2184    /// See <https://clickhouse.com/docs/ru/sql-reference/statements/kill/>
2185    /// See <https://dev.mysql.com/doc/refman/8.0/en/kill.html>
2186    Kill {
2187        modifier: Option<KillType>,
2188        // processlist_id
2189        id: u64,
2190    },
2191    /// ```sql
2192    /// EXPLAIN TABLE
2193    /// ```
2194    /// Note: this is a MySQL-specific statement. See <https://dev.mysql.com/doc/refman/8.0/en/explain.html>
2195    ExplainTable {
2196        /// If true, query used the MySQL `DESCRIBE` alias for explain
2197        describe_alias: bool,
2198        /// Table name
2199        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
2200        table_name: ObjectName,
2201    },
2202    /// ```sql
2203    /// [EXPLAIN | DESCRIBE <select statement>
2204    /// ```
2205    Explain {
2206        // If true, query used the MySQL `DESCRIBE` alias for explain
2207        describe_alias: bool,
2208        /// Carry out the command and show actual run times and other statistics.
2209        analyze: bool,
2210        // Display additional information regarding the plan.
2211        verbose: bool,
2212        /// A SQL query that specifies what to explain
2213        statement: Box<Statement>,
2214        /// Optional output format of explain
2215        format: Option<AnalyzeFormat>,
2216    },
2217    /// ```sql
2218    /// SAVEPOINT
2219    /// ```
2220    /// Define a new savepoint within the current transaction
2221    Savepoint { name: Ident },
2222    /// ```sql
2223    /// RELEASE [ SAVEPOINT ] savepoint_name
2224    /// ```
2225    ReleaseSavepoint { name: Ident },
2226    /// ```sql
2227    /// MERGE INTO <statement>
2228    /// ```
2229    /// Based on Snowflake. See <https://docs.snowflake.com/en/sql-reference/sql/merge.html>
2230    Merge {
2231        // optional INTO keyword
2232        into: bool,
2233        // Specifies the table to merge
2234        table: TableFactor,
2235        // Specifies the table or subquery to join with the target table
2236        source: TableFactor,
2237        // Specifies the expression on which to join the target table and source
2238        on: Box<Expr>,
2239        // Specifies the actions to perform when values match or do not match.
2240        clauses: Vec<MergeClause>,
2241    },
2242    /// ```sql
2243    /// CACHE [ FLAG ] TABLE <table_name> [ OPTIONS('K1' = 'V1', 'K2' = V2) ] [ AS ] [ <query> ]
2244    /// ```
2245    ///
2246    /// See [Spark SQL docs] for more details.
2247    ///
2248    /// [Spark SQL docs]: https://docs.databricks.com/spark/latest/spark-sql/language-manual/sql-ref-syntax-aux-cache-cache-table.html
2249    Cache {
2250        /// Table flag
2251        table_flag: Option<ObjectName>,
2252        /// Table name
2253
2254        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
2255        table_name: ObjectName,
2256        has_as: bool,
2257        /// Table confs
2258        options: Vec<SqlOption>,
2259        /// Cache table as a Query
2260        query: Option<Query>,
2261    },
2262    /// ```sql
2263    /// UNCACHE TABLE [ IF EXISTS ]  <table_name>
2264    /// ```
2265    UNCache {
2266        /// Table name
2267        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
2268        table_name: ObjectName,
2269        if_exists: bool,
2270    },
2271    /// ```sql
2272    /// CREATE [ { TEMPORARY | TEMP } ] SEQUENCE [ IF NOT EXISTS ] <sequence_name>
2273    /// ```
2274    /// Define a new sequence:
2275    CreateSequence {
2276        temporary: bool,
2277        if_not_exists: bool,
2278        name: ObjectName,
2279        data_type: Option<DataType>,
2280        sequence_options: Vec<SequenceOptions>,
2281        owned_by: Option<ObjectName>,
2282    },
2283    /// ```sql
2284    /// CREATE TYPE <name>
2285    /// ```
2286    CreateType {
2287        name: ObjectName,
2288        representation: UserDefinedTypeRepresentation,
2289    },
2290    /// ```sql
2291    /// PRAGMA <schema-name>.<pragma-name> = <pragma-value>
2292    /// ```
2293    Pragma {
2294        name: ObjectName,
2295        value: Option<Value>,
2296        is_eq: bool,
2297    },
2298    /// ```sql
2299    /// LOCK TABLES <table_name> [READ [LOCAL] | [LOW_PRIORITY] WRITE]
2300    /// ```
2301    /// Note: this is a MySQL-specific statement. See <https://dev.mysql.com/doc/refman/8.0/en/lock-tables.html>
2302    LockTables { tables: Vec<LockTable> },
2303    /// ```sql
2304    /// UNLOCK TABLES
2305    /// ```
2306    /// Note: this is a MySQL-specific statement. See <https://dev.mysql.com/doc/refman/8.0/en/lock-tables.html>
2307    UnlockTables,
2308}
2309
2310impl fmt::Display for Statement {
2311    // Clippy thinks this function is too complicated, but it is painful to
2312    // split up without extracting structs for each `Statement` variant.
2313    #[allow(clippy::cognitive_complexity)]
2314    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2315        match self {
2316            Statement::Flush {
2317                object_type,
2318                location,
2319                channel,
2320                read_lock,
2321                export,
2322                tables,
2323            } => {
2324                write!(f, "FLUSH")?;
2325                if let Some(location) = location {
2326                    write!(f, " {location}")?;
2327                }
2328                write!(f, " {object_type}")?;
2329
2330                if let Some(channel) = channel {
2331                    write!(f, " FOR CHANNEL {channel}")?;
2332                }
2333
2334                write!(
2335                    f,
2336                    "{tables}{read}{export}",
2337                    tables = if !tables.is_empty() {
2338                        " ".to_string() + &display_comma_separated(tables).to_string()
2339                    } else {
2340                        "".to_string()
2341                    },
2342                    export = if *export { " FOR EXPORT" } else { "" },
2343                    read = if *read_lock { " WITH READ LOCK" } else { "" }
2344                )
2345            }
2346            Statement::Kill { modifier, id } => {
2347                write!(f, "KILL ")?;
2348
2349                if let Some(m) = modifier {
2350                    write!(f, "{m} ")?;
2351                }
2352
2353                write!(f, "{id}")
2354            }
2355            Statement::ExplainTable {
2356                describe_alias,
2357                table_name,
2358            } => {
2359                if *describe_alias {
2360                    write!(f, "DESCRIBE ")?;
2361                } else {
2362                    write!(f, "EXPLAIN ")?;
2363                }
2364
2365                write!(f, "{table_name}")
2366            }
2367            Statement::Explain {
2368                describe_alias,
2369                verbose,
2370                analyze,
2371                statement,
2372                format,
2373            } => {
2374                if *describe_alias {
2375                    write!(f, "DESCRIBE ")?;
2376                } else {
2377                    write!(f, "EXPLAIN ")?;
2378                }
2379
2380                if *analyze {
2381                    write!(f, "ANALYZE ")?;
2382                }
2383
2384                if *verbose {
2385                    write!(f, "VERBOSE ")?;
2386                }
2387
2388                if let Some(format) = format {
2389                    write!(f, "FORMAT {format} ")?;
2390                }
2391
2392                write!(f, "{statement}")
2393            }
2394            Statement::Query(s) => write!(f, "{s}"),
2395            Statement::Declare {
2396                name,
2397                binary,
2398                sensitive,
2399                scroll,
2400                hold,
2401                query,
2402            } => {
2403                write!(f, "DECLARE {name} ")?;
2404
2405                if *binary {
2406                    write!(f, "BINARY ")?;
2407                }
2408
2409                if let Some(sensitive) = sensitive {
2410                    if *sensitive {
2411                        write!(f, "INSENSITIVE ")?;
2412                    } else {
2413                        write!(f, "ASENSITIVE ")?;
2414                    }
2415                }
2416
2417                if let Some(scroll) = scroll {
2418                    if *scroll {
2419                        write!(f, "SCROLL ")?;
2420                    } else {
2421                        write!(f, "NO SCROLL ")?;
2422                    }
2423                }
2424
2425                write!(f, "CURSOR ")?;
2426
2427                if let Some(hold) = hold {
2428                    if *hold {
2429                        write!(f, "WITH HOLD ")?;
2430                    } else {
2431                        write!(f, "WITHOUT HOLD ")?;
2432                    }
2433                }
2434
2435                write!(f, "FOR {query}")
2436            }
2437            Statement::Fetch {
2438                name,
2439                direction,
2440                into,
2441            } => {
2442                write!(f, "FETCH {direction} ")?;
2443
2444                write!(f, "IN {name}")?;
2445
2446                if let Some(into) = into {
2447                    write!(f, " INTO {into}")?;
2448                }
2449
2450                Ok(())
2451            }
2452            Statement::Directory {
2453                overwrite,
2454                local,
2455                path,
2456                file_format,
2457                source,
2458            } => {
2459                write!(
2460                    f,
2461                    "INSERT{overwrite}{local} DIRECTORY '{path}'",
2462                    overwrite = if *overwrite { " OVERWRITE" } else { "" },
2463                    local = if *local { " LOCAL" } else { "" },
2464                    path = path
2465                )?;
2466                if let Some(ref ff) = file_format {
2467                    write!(f, " STORED AS {ff}")?
2468                }
2469                write!(f, " {source}")
2470            }
2471            Statement::Msck {
2472                table_name,
2473                repair,
2474                partition_action,
2475            } => {
2476                write!(
2477                    f,
2478                    "MSCK {repair}TABLE {table}",
2479                    repair = if *repair { "REPAIR " } else { "" },
2480                    table = table_name
2481                )?;
2482                if let Some(pa) = partition_action {
2483                    write!(f, " {pa}")?;
2484                }
2485                Ok(())
2486            }
2487            Statement::Truncate {
2488                table_name,
2489                partitions,
2490                table,
2491            } => {
2492                let table = if *table { "TABLE " } else { "" };
2493                write!(f, "TRUNCATE {table}{table_name}")?;
2494                if let Some(ref parts) = partitions {
2495                    if !parts.is_empty() {
2496                        write!(f, " PARTITION ({})", display_comma_separated(parts))?;
2497                    }
2498                }
2499                Ok(())
2500            }
2501            Statement::AttachDatabase {
2502                schema_name,
2503                database_file_name,
2504                database,
2505            } => {
2506                let keyword = if *database { "DATABASE " } else { "" };
2507                write!(f, "ATTACH {keyword}{database_file_name} AS {schema_name}")
2508            }
2509            Statement::Analyze {
2510                table_name,
2511                partitions,
2512                for_columns,
2513                columns,
2514                cache_metadata,
2515                noscan,
2516                compute_statistics,
2517            } => {
2518                write!(f, "ANALYZE TABLE {table_name}")?;
2519                if let Some(ref parts) = partitions {
2520                    if !parts.is_empty() {
2521                        write!(f, " PARTITION ({})", display_comma_separated(parts))?;
2522                    }
2523                }
2524
2525                if *compute_statistics {
2526                    write!(f, " COMPUTE STATISTICS")?;
2527                }
2528                if *noscan {
2529                    write!(f, " NOSCAN")?;
2530                }
2531                if *cache_metadata {
2532                    write!(f, " CACHE METADATA")?;
2533                }
2534                if *for_columns {
2535                    write!(f, " FOR COLUMNS")?;
2536                    if !columns.is_empty() {
2537                        write!(f, " {}", display_comma_separated(columns))?;
2538                    }
2539                }
2540                Ok(())
2541            }
2542            Statement::Insert {
2543                or,
2544                ignore,
2545                into,
2546                table_name,
2547                table_alias,
2548                overwrite,
2549                partitioned,
2550                columns,
2551                after_columns,
2552                source,
2553                table,
2554                as_table,
2555                as_table_after_columns,
2556                on,
2557                returning,
2558                replace_into,
2559                priority,
2560            } => {
2561                let table_name = if let Some(alias) = table_alias {
2562                    format!("{table_name} AS {alias}")
2563                } else {
2564                    table_name.to_string()
2565                };
2566
2567                if let Some(action) = or {
2568                    write!(f, "INSERT OR {action} INTO {table_name} ")?;
2569                } else {
2570                    write!(
2571                        f,
2572                        "{start}",
2573                        start = if *replace_into { "REPLACE" } else { "INSERT" },
2574                    )?;
2575                    if let Some(priority) = priority {
2576                        write!(f, " {priority}",)?;
2577                    }
2578
2579                    write!(
2580                        f,
2581                        "{ignore}{over}{int}{tbl} {table_name} ",
2582                        table_name = table_name,
2583                        ignore = if *ignore { " IGNORE" } else { "" },
2584                        over = if *overwrite { " OVERWRITE" } else { "" },
2585                        int = if *into { " INTO" } else { "" },
2586                        tbl = if *table { " TABLE" } else { "" },
2587                    )?;
2588                }
2589                if !columns.is_empty() {
2590                    write!(f, "({}) ", display_comma_separated(columns))?;
2591                }
2592                if let Some(ref parts) = partitioned {
2593                    if !parts.is_empty() {
2594                        write!(f, "PARTITION ({}) ", display_comma_separated(parts))?;
2595                    }
2596                }
2597                if !after_columns.is_empty() {
2598                    write!(f, "({}) ", display_comma_separated(after_columns))?;
2599                }
2600
2601                if let Some(source) = source {
2602                    write!(f, "{source}")?;
2603                }
2604
2605                if source.is_none() && columns.is_empty() {
2606                    write!(f, "DEFAULT VALUES")?;
2607                }
2608
2609                if let Some(as_table) = as_table {
2610                    write!(f, " AS {as_table}")?;
2611
2612                    if !as_table_after_columns.is_empty() {
2613                        write!(f, " ({}) ", display_comma_separated(as_table_after_columns))?;
2614                    }
2615                }
2616
2617                if let Some(on) = on {
2618                    write!(f, "{on}")?;
2619                }
2620
2621                if let Some(returning) = returning {
2622                    write!(f, " RETURNING {}", display_comma_separated(returning))?;
2623                }
2624
2625                Ok(())
2626            }
2627
2628            Statement::Call(function) => write!(f, "CALL {function}"),
2629
2630            Statement::Copy {
2631                source,
2632                to,
2633                target,
2634                options,
2635                legacy_options,
2636                values,
2637            } => {
2638                write!(f, "COPY")?;
2639                match source {
2640                    CopySource::Query(query) => write!(f, " ({query})")?,
2641                    CopySource::Table {
2642                        table_name,
2643                        columns,
2644                    } => {
2645                        write!(f, " {table_name}")?;
2646                        if !columns.is_empty() {
2647                            write!(f, " ({})", display_comma_separated(columns))?;
2648                        }
2649                    }
2650                }
2651                write!(f, " {} {}", if *to { "TO" } else { "FROM" }, target)?;
2652                if !options.is_empty() {
2653                    write!(f, " ({})", display_comma_separated(options))?;
2654                }
2655                if !legacy_options.is_empty() {
2656                    write!(f, " {}", display_separated(legacy_options, " "))?;
2657                }
2658                if !values.is_empty() {
2659                    writeln!(f, ";")?;
2660                    let mut delim = "";
2661                    for v in values {
2662                        write!(f, "{delim}")?;
2663                        delim = "\t";
2664                        if let Some(v) = v {
2665                            write!(f, "{v}")?;
2666                        } else {
2667                            write!(f, "\\N")?;
2668                        }
2669                    }
2670                    write!(f, "\n\\.")?;
2671                }
2672                Ok(())
2673            }
2674            Statement::Update {
2675                table,
2676                assignments,
2677                from,
2678                selection,
2679                returning,
2680            } => {
2681                write!(f, "UPDATE {table}")?;
2682                if !assignments.is_empty() {
2683                    write!(f, " SET {}", display_comma_separated(assignments))?;
2684                }
2685                if let Some(from) = from {
2686                    write!(f, " FROM {from}")?;
2687                }
2688                if let Some(selection) = selection {
2689                    write!(f, " WHERE {selection}")?;
2690                }
2691                if let Some(returning) = returning {
2692                    write!(f, " RETURNING {}", display_comma_separated(returning))?;
2693                }
2694                Ok(())
2695            }
2696            Statement::Delete {
2697                tables,
2698                from,
2699                using,
2700                selection,
2701                returning,
2702                order_by,
2703                limit,
2704            } => {
2705                write!(f, "DELETE ")?;
2706                if !tables.is_empty() {
2707                    write!(f, "{} ", display_comma_separated(tables))?;
2708                }
2709                write!(f, "FROM {}", display_comma_separated(from))?;
2710                if let Some(using) = using {
2711                    write!(f, " USING {}", display_comma_separated(using))?;
2712                }
2713                if let Some(selection) = selection {
2714                    write!(f, " WHERE {selection}")?;
2715                }
2716                if let Some(returning) = returning {
2717                    write!(f, " RETURNING {}", display_comma_separated(returning))?;
2718                }
2719                if !order_by.is_empty() {
2720                    write!(f, " ORDER BY {}", display_comma_separated(order_by))?;
2721                }
2722                if let Some(limit) = limit {
2723                    write!(f, " LIMIT {limit}")?;
2724                }
2725                Ok(())
2726            }
2727            Statement::Close { cursor } => {
2728                write!(f, "CLOSE {cursor}")?;
2729
2730                Ok(())
2731            }
2732            Statement::CreateDatabase {
2733                db_name,
2734                if_not_exists,
2735                location,
2736                managed_location,
2737            } => {
2738                write!(f, "CREATE DATABASE")?;
2739                if *if_not_exists {
2740                    write!(f, " IF NOT EXISTS")?;
2741                }
2742                write!(f, " {db_name}")?;
2743                if let Some(l) = location {
2744                    write!(f, " LOCATION '{l}'")?;
2745                }
2746                if let Some(ml) = managed_location {
2747                    write!(f, " MANAGEDLOCATION '{ml}'")?;
2748                }
2749                Ok(())
2750            }
2751            Statement::CreateFunction {
2752                or_replace,
2753                temporary,
2754                name,
2755                args,
2756                return_type,
2757                params,
2758            } => {
2759                write!(
2760                    f,
2761                    "CREATE {or_replace}{temp}FUNCTION {name}",
2762                    temp = if *temporary { "TEMPORARY " } else { "" },
2763                    or_replace = if *or_replace { "OR REPLACE " } else { "" },
2764                )?;
2765                if let Some(args) = args {
2766                    write!(f, "({})", display_comma_separated(args))?;
2767                }
2768                if let Some(return_type) = return_type {
2769                    write!(f, " RETURNS {return_type}")?;
2770                }
2771                write!(f, "{params}")?;
2772                Ok(())
2773            }
2774            Statement::CreateProcedure {
2775                name,
2776                or_alter,
2777                params,
2778                body,
2779            } => {
2780                write!(
2781                    f,
2782                    "CREATE {or_alter}PROCEDURE {name}",
2783                    or_alter = if *or_alter { "OR ALTER " } else { "" },
2784                    name = name
2785                )?;
2786
2787                if let Some(p) = params {
2788                    if !p.is_empty() {
2789                        write!(f, " ({})", display_comma_separated(p))?;
2790                    }
2791                }
2792                write!(
2793                    f,
2794                    " AS BEGIN {body} END",
2795                    body = display_separated(body, "; ")
2796                )
2797            }
2798            Statement::CreateMacro {
2799                or_replace,
2800                temporary,
2801                name,
2802                args,
2803                definition,
2804            } => {
2805                write!(
2806                    f,
2807                    "CREATE {or_replace}{temp}MACRO {name}",
2808                    temp = if *temporary { "TEMPORARY " } else { "" },
2809                    or_replace = if *or_replace { "OR REPLACE " } else { "" },
2810                )?;
2811                if let Some(args) = args {
2812                    write!(f, "({})", display_comma_separated(args))?;
2813                }
2814                match definition {
2815                    MacroDefinition::Expr(expr) => write!(f, " AS {expr}")?,
2816                    MacroDefinition::Table(query) => write!(f, " AS TABLE {query}")?,
2817                }
2818                Ok(())
2819            }
2820            Statement::CreateView {
2821                name,
2822                or_replace,
2823                columns,
2824                query,
2825                materialized,
2826                options,
2827                cluster_by,
2828                with_no_schema_binding,
2829                if_not_exists,
2830                temporary,
2831            } => {
2832                write!(
2833                    f,
2834                    "CREATE {or_replace}{materialized}{temporary}VIEW {if_not_exists}{name}",
2835                    or_replace = if *or_replace { "OR REPLACE " } else { "" },
2836                    materialized = if *materialized { "MATERIALIZED " } else { "" },
2837                    name = name,
2838                    temporary = if *temporary { "TEMPORARY " } else { "" },
2839                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" }
2840                )?;
2841                if matches!(options, CreateTableOptions::With(_)) {
2842                    write!(f, " {options}")?;
2843                }
2844                if !columns.is_empty() {
2845                    write!(f, " ({})", display_comma_separated(columns))?;
2846                }
2847                if !cluster_by.is_empty() {
2848                    write!(f, " CLUSTER BY ({})", display_comma_separated(cluster_by))?;
2849                }
2850                if matches!(options, CreateTableOptions::Options(_)) {
2851                    write!(f, " {options}")?;
2852                }
2853                write!(f, " AS {query}")?;
2854                if *with_no_schema_binding {
2855                    write!(f, " WITH NO SCHEMA BINDING")?;
2856                }
2857                Ok(())
2858            }
2859            Statement::CreateTable {
2860                name,
2861                columns,
2862                constraints,
2863                table_properties,
2864                with_options,
2865                or_replace,
2866                if_not_exists,
2867                transient,
2868                hive_distribution,
2869                hive_formats,
2870                external,
2871                global,
2872                temporary,
2873                file_format,
2874                location,
2875                query,
2876                without_rowid,
2877                like,
2878                clone,
2879                default_charset,
2880                engine,
2881                comment,
2882                auto_increment_offset,
2883                collation,
2884                on_commit,
2885                on_cluster,
2886                order_by,
2887                partition_by,
2888                cluster_by,
2889                options,
2890                strict,
2891            } => {
2892                // We want to allow the following options
2893                // Empty column list, allowed by PostgreSQL:
2894                //   `CREATE TABLE t ()`
2895                // No columns provided for CREATE TABLE AS:
2896                //   `CREATE TABLE t AS SELECT a from t2`
2897                // Columns provided for CREATE TABLE AS:
2898                //   `CREATE TABLE t (a INT) AS SELECT a from t2`
2899                write!(
2900                    f,
2901                    "CREATE {or_replace}{external}{global}{temporary}{transient}TABLE {if_not_exists}{name}",
2902                    or_replace = if *or_replace { "OR REPLACE " } else { "" },
2903                    external = if *external { "EXTERNAL " } else { "" },
2904                    global = global
2905                        .map(|global| {
2906                            if global {
2907                                "GLOBAL "
2908                            } else {
2909                                "LOCAL "
2910                            }
2911                        })
2912                        .unwrap_or(""),
2913                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
2914                    temporary = if *temporary { "TEMPORARY " } else { "" },
2915                    transient = if *transient { "TRANSIENT " } else { "" },
2916                    name = name,
2917                )?;
2918                if let Some(on_cluster) = on_cluster {
2919                    write!(
2920                        f,
2921                        " ON CLUSTER {}",
2922                        on_cluster.replace('{', "'{").replace('}', "}'")
2923                    )?;
2924                }
2925                if !columns.is_empty() || !constraints.is_empty() {
2926                    write!(f, " ({}", display_comma_separated(columns))?;
2927                    if !columns.is_empty() && !constraints.is_empty() {
2928                        write!(f, ", ")?;
2929                    }
2930                    write!(f, "{})", display_comma_separated(constraints))?;
2931                } else if query.is_none() && like.is_none() && clone.is_none() {
2932                    // PostgreSQL allows `CREATE TABLE t ();`, but requires empty parens
2933                    write!(f, " ()")?;
2934                }
2935                // Only for SQLite
2936                if *without_rowid {
2937                    write!(f, " WITHOUT ROWID")?;
2938                }
2939
2940                // Only for Hive
2941                if let Some(l) = like {
2942                    write!(f, " LIKE {l}")?;
2943                }
2944
2945                if let Some(c) = clone {
2946                    write!(f, " CLONE {c}")?;
2947                }
2948
2949                match hive_distribution {
2950                    HiveDistributionStyle::PARTITIONED { columns } => {
2951                        write!(f, " PARTITIONED BY ({})", display_comma_separated(columns))?;
2952                    }
2953                    HiveDistributionStyle::CLUSTERED {
2954                        columns,
2955                        sorted_by,
2956                        num_buckets,
2957                    } => {
2958                        write!(f, " CLUSTERED BY ({})", display_comma_separated(columns))?;
2959                        if !sorted_by.is_empty() {
2960                            write!(f, " SORTED BY ({})", display_comma_separated(sorted_by))?;
2961                        }
2962                        if *num_buckets > 0 {
2963                            write!(f, " INTO {num_buckets} BUCKETS")?;
2964                        }
2965                    }
2966                    HiveDistributionStyle::SKEWED {
2967                        columns,
2968                        on,
2969                        stored_as_directories,
2970                    } => {
2971                        write!(
2972                            f,
2973                            " SKEWED BY ({})) ON ({})",
2974                            display_comma_separated(columns),
2975                            display_comma_separated(on)
2976                        )?;
2977                        if *stored_as_directories {
2978                            write!(f, " STORED AS DIRECTORIES")?;
2979                        }
2980                    }
2981                    _ => (),
2982                }
2983
2984                if let Some(HiveFormat {
2985                    row_format,
2986                    storage,
2987                    location,
2988                }) = hive_formats
2989                {
2990                    match row_format {
2991                        Some(HiveRowFormat::SERDE { class }) => {
2992                            write!(f, " ROW FORMAT SERDE '{class}'")?
2993                        }
2994                        Some(HiveRowFormat::DELIMITED) => write!(f, " ROW FORMAT DELIMITED")?,
2995                        None => (),
2996                    }
2997                    match storage {
2998                        Some(HiveIOFormat::IOF {
2999                            input_format,
3000                            output_format,
3001                        }) => write!(
3002                            f,
3003                            " STORED AS INPUTFORMAT {input_format} OUTPUTFORMAT {output_format}"
3004                        )?,
3005                        Some(HiveIOFormat::FileFormat { format }) if !*external => {
3006                            write!(f, " STORED AS {format}")?
3007                        }
3008                        _ => (),
3009                    }
3010                    if !*external {
3011                        if let Some(loc) = location {
3012                            write!(f, " LOCATION '{loc}'")?;
3013                        }
3014                    }
3015                }
3016                if *external {
3017                    write!(
3018                        f,
3019                        " STORED AS {} LOCATION '{}'",
3020                        file_format.as_ref().unwrap(),
3021                        location.as_ref().unwrap()
3022                    )?;
3023                }
3024                if !table_properties.is_empty() {
3025                    write!(
3026                        f,
3027                        " TBLPROPERTIES ({})",
3028                        display_comma_separated(table_properties)
3029                    )?;
3030                }
3031                if !with_options.is_empty() {
3032                    write!(f, " WITH ({})", display_comma_separated(with_options))?;
3033                }
3034                if let Some(engine) = engine {
3035                    write!(f, " ENGINE={engine}")?;
3036                }
3037                if let Some(comment) = comment {
3038                    write!(f, " COMMENT '{comment}'")?;
3039                }
3040                if let Some(auto_increment_offset) = auto_increment_offset {
3041                    write!(f, " AUTO_INCREMENT {auto_increment_offset}")?;
3042                }
3043                if let Some(order_by) = order_by {
3044                    write!(f, " ORDER BY ({})", display_comma_separated(order_by))?;
3045                }
3046                if let Some(partition_by) = partition_by.as_ref() {
3047                    write!(f, " PARTITION BY {partition_by}")?;
3048                }
3049                if let Some(cluster_by) = cluster_by.as_ref() {
3050                    write!(
3051                        f,
3052                        " CLUSTER BY {}",
3053                        display_comma_separated(cluster_by.as_slice())
3054                    )?;
3055                }
3056                if let Some(options) = options.as_ref() {
3057                    write!(
3058                        f,
3059                        " OPTIONS({})",
3060                        display_comma_separated(options.as_slice())
3061                    )?;
3062                }
3063                if let Some(query) = query {
3064                    write!(f, " AS {query}")?;
3065                }
3066                if let Some(default_charset) = default_charset {
3067                    write!(f, " DEFAULT CHARSET={default_charset}")?;
3068                }
3069                if let Some(collation) = collation {
3070                    write!(f, " COLLATE={collation}")?;
3071                }
3072
3073                if on_commit.is_some() {
3074                    let on_commit = match on_commit {
3075                        Some(OnCommit::DeleteRows) => "ON COMMIT DELETE ROWS",
3076                        Some(OnCommit::PreserveRows) => "ON COMMIT PRESERVE ROWS",
3077                        Some(OnCommit::Drop) => "ON COMMIT DROP",
3078                        None => "",
3079                    };
3080                    write!(f, " {on_commit}")?;
3081                }
3082                if *strict {
3083                    write!(f, " STRICT")?;
3084                }
3085                Ok(())
3086            }
3087            Statement::CreateVirtualTable {
3088                name,
3089                if_not_exists,
3090                module_name,
3091                module_args,
3092            } => {
3093                write!(
3094                    f,
3095                    "CREATE VIRTUAL TABLE {if_not_exists}{name} USING {module_name}",
3096                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
3097                    name = name,
3098                    module_name = module_name
3099                )?;
3100                if !module_args.is_empty() {
3101                    write!(f, " ({})", display_comma_separated(module_args))?;
3102                }
3103                Ok(())
3104            }
3105            Statement::CreateIndex {
3106                name,
3107                table_name,
3108                using,
3109                columns,
3110                unique,
3111                concurrently,
3112                if_not_exists,
3113                include,
3114                nulls_distinct,
3115                predicate,
3116            } => {
3117                write!(
3118                    f,
3119                    "CREATE {unique}INDEX {concurrently}{if_not_exists}",
3120                    unique = if *unique { "UNIQUE " } else { "" },
3121                    concurrently = if *concurrently { "CONCURRENTLY " } else { "" },
3122                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
3123                )?;
3124                if let Some(value) = name {
3125                    write!(f, "{value} ")?;
3126                }
3127                write!(f, "ON {table_name}")?;
3128                if let Some(value) = using {
3129                    write!(f, " USING {value} ")?;
3130                }
3131                write!(f, "({})", display_separated(columns, ","))?;
3132                if !include.is_empty() {
3133                    write!(f, " INCLUDE ({})", display_separated(include, ","))?;
3134                }
3135                if let Some(value) = nulls_distinct {
3136                    if *value {
3137                        write!(f, " NULLS DISTINCT")?;
3138                    } else {
3139                        write!(f, " NULLS NOT DISTINCT")?;
3140                    }
3141                }
3142                if let Some(predicate) = predicate {
3143                    write!(f, " WHERE {predicate}")?;
3144                }
3145                Ok(())
3146            }
3147            Statement::CreateExtension {
3148                name,
3149                if_not_exists,
3150                cascade,
3151                schema,
3152                version,
3153            } => {
3154                write!(
3155                    f,
3156                    "CREATE EXTENSION {if_not_exists}{name}",
3157                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" }
3158                )?;
3159                if *cascade || schema.is_some() || version.is_some() {
3160                    write!(f, " WITH")?;
3161
3162                    if let Some(name) = schema {
3163                        write!(f, " SCHEMA {name}")?;
3164                    }
3165                    if let Some(version) = version {
3166                        write!(f, " VERSION {version}")?;
3167                    }
3168                    if *cascade {
3169                        write!(f, " CASCADE")?;
3170                    }
3171                }
3172
3173                Ok(())
3174            }
3175            Statement::CreateRole {
3176                names,
3177                if_not_exists,
3178                inherit,
3179                login,
3180                bypassrls,
3181                password,
3182                create_db,
3183                create_role,
3184                superuser,
3185                replication,
3186                connection_limit,
3187                valid_until,
3188                in_role,
3189                in_group,
3190                role,
3191                user,
3192                admin,
3193                authorization_owner,
3194            } => {
3195                write!(
3196                    f,
3197                    "CREATE ROLE {if_not_exists}{names}{superuser}{create_db}{create_role}{inherit}{login}{replication}{bypassrls}",
3198                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
3199                    names = display_separated(names, ", "),
3200                    superuser = match *superuser {
3201                        Some(true) => " SUPERUSER",
3202                        Some(false) => " NOSUPERUSER",
3203                        None => ""
3204                    },
3205                    create_db = match *create_db {
3206                        Some(true) => " CREATEDB",
3207                        Some(false) => " NOCREATEDB",
3208                        None => ""
3209                    },
3210                    create_role = match *create_role {
3211                        Some(true) => " CREATEROLE",
3212                        Some(false) => " NOCREATEROLE",
3213                        None => ""
3214                    },
3215                    inherit = match *inherit {
3216                        Some(true) => " INHERIT",
3217                        Some(false) => " NOINHERIT",
3218                        None => ""
3219                    },
3220                    login = match *login {
3221                        Some(true) => " LOGIN",
3222                        Some(false) => " NOLOGIN",
3223                        None => ""
3224                    },
3225                    replication = match *replication {
3226                        Some(true) => " REPLICATION",
3227                        Some(false) => " NOREPLICATION",
3228                        None => ""
3229                    },
3230                    bypassrls = match *bypassrls {
3231                        Some(true) => " BYPASSRLS",
3232                        Some(false) => " NOBYPASSRLS",
3233                        None => ""
3234                    }
3235                )?;
3236                if let Some(limit) = connection_limit {
3237                    write!(f, " CONNECTION LIMIT {limit}")?;
3238                }
3239                match password {
3240                    Some(Password::Password(pass)) => write!(f, " PASSWORD {pass}"),
3241                    Some(Password::NullPassword) => write!(f, " PASSWORD NULL"),
3242                    None => Ok(()),
3243                }?;
3244                if let Some(until) = valid_until {
3245                    write!(f, " VALID UNTIL {until}")?;
3246                }
3247                if !in_role.is_empty() {
3248                    write!(f, " IN ROLE {}", display_comma_separated(in_role))?;
3249                }
3250                if !in_group.is_empty() {
3251                    write!(f, " IN GROUP {}", display_comma_separated(in_group))?;
3252                }
3253                if !role.is_empty() {
3254                    write!(f, " ROLE {}", display_comma_separated(role))?;
3255                }
3256                if !user.is_empty() {
3257                    write!(f, " USER {}", display_comma_separated(user))?;
3258                }
3259                if !admin.is_empty() {
3260                    write!(f, " ADMIN {}", display_comma_separated(admin))?;
3261                }
3262                if let Some(owner) = authorization_owner {
3263                    write!(f, " AUTHORIZATION {owner}")?;
3264                }
3265                Ok(())
3266            }
3267            Statement::AlterTable {
3268                name,
3269                if_exists,
3270                only,
3271                operations,
3272            } => {
3273                write!(f, "ALTER TABLE ")?;
3274                if *if_exists {
3275                    write!(f, "IF EXISTS ")?;
3276                }
3277                if *only {
3278                    write!(f, "ONLY ")?;
3279                }
3280                write!(
3281                    f,
3282                    "{name} {operations}",
3283                    operations = display_comma_separated(operations)
3284                )
3285            }
3286            Statement::AlterIndex { name, operation } => {
3287                write!(f, "ALTER INDEX {name} {operation}")
3288            }
3289            Statement::AlterView {
3290                name,
3291                columns,
3292                query,
3293                with_options,
3294            } => {
3295                write!(f, "ALTER VIEW {name}")?;
3296                if !with_options.is_empty() {
3297                    write!(f, " WITH ({})", display_comma_separated(with_options))?;
3298                }
3299                if !columns.is_empty() {
3300                    write!(f, " ({})", display_comma_separated(columns))?;
3301                }
3302                write!(f, " AS {query}")
3303            }
3304            Statement::AlterRole { name, operation } => {
3305                write!(f, "ALTER ROLE {name} {operation}")
3306            }
3307            Statement::Drop {
3308                object_type,
3309                if_exists,
3310                names,
3311                cascade,
3312                restrict,
3313                purge,
3314                temporary,
3315            } => write!(
3316                f,
3317                "DROP {}{}{} {}{}{}{}",
3318                if *temporary { "TEMPORARY " } else { "" },
3319                object_type,
3320                if *if_exists { " IF EXISTS" } else { "" },
3321                display_comma_separated(names),
3322                if *cascade { " CASCADE" } else { "" },
3323                if *restrict { " RESTRICT" } else { "" },
3324                if *purge { " PURGE" } else { "" }
3325            ),
3326            Statement::DropFunction {
3327                if_exists,
3328                func_desc,
3329                option,
3330            } => {
3331                write!(
3332                    f,
3333                    "DROP FUNCTION{} {}",
3334                    if *if_exists { " IF EXISTS" } else { "" },
3335                    display_comma_separated(func_desc),
3336                )?;
3337                if let Some(op) = option {
3338                    write!(f, " {op}")?;
3339                }
3340                Ok(())
3341            }
3342            Statement::Discard { object_type } => {
3343                write!(f, "DISCARD {object_type}")?;
3344                Ok(())
3345            }
3346            Self::SetRole {
3347                context_modifier,
3348                role_name,
3349            } => {
3350                let role_name = role_name.clone().unwrap_or_else(|| Ident::new("NONE"));
3351                write!(f, "SET{context_modifier} ROLE {role_name}")
3352            }
3353            Statement::SetVariable {
3354                local,
3355                variable,
3356                hivevar,
3357                value,
3358            } => {
3359                f.write_str("SET ")?;
3360                if *local {
3361                    f.write_str("LOCAL ")?;
3362                }
3363                write!(
3364                    f,
3365                    "{hivevar}{name} = {value}",
3366                    hivevar = if *hivevar { "HIVEVAR:" } else { "" },
3367                    name = variable,
3368                    value = display_comma_separated(value)
3369                )
3370            }
3371            Statement::SetTimeZone { local, value } => {
3372                f.write_str("SET ")?;
3373                if *local {
3374                    f.write_str("LOCAL ")?;
3375                }
3376                write!(f, "TIME ZONE {value}")
3377            }
3378            Statement::SetNames {
3379                charset_name,
3380                collation_name,
3381            } => {
3382                f.write_str("SET NAMES ")?;
3383                f.write_str(charset_name)?;
3384
3385                if let Some(collation) = collation_name {
3386                    f.write_str(" COLLATE ")?;
3387                    f.write_str(collation)?;
3388                };
3389
3390                Ok(())
3391            }
3392            Statement::SetNamesDefault {} => {
3393                f.write_str("SET NAMES DEFAULT")?;
3394
3395                Ok(())
3396            }
3397            Statement::ShowVariable { variable } => {
3398                write!(f, "SHOW")?;
3399                if !variable.is_empty() {
3400                    write!(f, " {}", display_separated(variable, " "))?;
3401                }
3402                Ok(())
3403            }
3404            Statement::ShowVariables {
3405                filter,
3406                global,
3407                session,
3408            } => {
3409                write!(f, "SHOW")?;
3410                if *global {
3411                    write!(f, " GLOBAL")?;
3412                }
3413                if *session {
3414                    write!(f, " SESSION")?;
3415                }
3416                write!(f, " VARIABLES")?;
3417                if filter.is_some() {
3418                    write!(f, " {}", filter.as_ref().unwrap())?;
3419                }
3420                Ok(())
3421            }
3422            Statement::ShowCreate { obj_type, obj_name } => {
3423                write!(f, "SHOW CREATE {obj_type} {obj_name}",)?;
3424                Ok(())
3425            }
3426            Statement::ShowColumns {
3427                extended,
3428                full,
3429                table_name,
3430                filter,
3431            } => {
3432                write!(
3433                    f,
3434                    "SHOW {extended}{full}COLUMNS FROM {table_name}",
3435                    extended = if *extended { "EXTENDED " } else { "" },
3436                    full = if *full { "FULL " } else { "" },
3437                    table_name = table_name,
3438                )?;
3439                if let Some(filter) = filter {
3440                    write!(f, " {filter}")?;
3441                }
3442                Ok(())
3443            }
3444            Statement::ShowTables {
3445                extended,
3446                full,
3447                db_name,
3448                filter,
3449            } => {
3450                write!(
3451                    f,
3452                    "SHOW {extended}{full}TABLES",
3453                    extended = if *extended { "EXTENDED " } else { "" },
3454                    full = if *full { "FULL " } else { "" },
3455                )?;
3456                if let Some(db_name) = db_name {
3457                    write!(f, " FROM {db_name}")?;
3458                }
3459                if let Some(filter) = filter {
3460                    write!(f, " {filter}")?;
3461                }
3462                Ok(())
3463            }
3464            Statement::ShowFunctions { filter } => {
3465                write!(f, "SHOW FUNCTIONS")?;
3466                if let Some(filter) = filter {
3467                    write!(f, " {filter}")?;
3468                }
3469                Ok(())
3470            }
3471            Statement::Use { db_name } => {
3472                write!(f, "USE {db_name}")?;
3473                Ok(())
3474            }
3475            Statement::ShowCollation { filter } => {
3476                write!(f, "SHOW COLLATION")?;
3477                if let Some(filter) = filter {
3478                    write!(f, " {filter}")?;
3479                }
3480                Ok(())
3481            }
3482            Statement::StartTransaction {
3483                modes,
3484                begin: syntax_begin,
3485                modifier,
3486            } => {
3487                if *syntax_begin {
3488                    if let Some(modifier) = *modifier {
3489                        write!(f, "BEGIN {} TRANSACTION", modifier)?;
3490                    } else {
3491                        write!(f, "BEGIN TRANSACTION")?;
3492                    }
3493                } else {
3494                    write!(f, "START TRANSACTION")?;
3495                }
3496                if !modes.is_empty() {
3497                    write!(f, " {}", display_comma_separated(modes))?;
3498                }
3499                Ok(())
3500            }
3501            Statement::SetTransaction {
3502                modes,
3503                snapshot,
3504                session,
3505            } => {
3506                if *session {
3507                    write!(f, "SET SESSION CHARACTERISTICS AS TRANSACTION")?;
3508                } else {
3509                    write!(f, "SET TRANSACTION")?;
3510                }
3511                if !modes.is_empty() {
3512                    write!(f, " {}", display_comma_separated(modes))?;
3513                }
3514                if let Some(snapshot_id) = snapshot {
3515                    write!(f, " SNAPSHOT {snapshot_id}")?;
3516                }
3517                Ok(())
3518            }
3519            Statement::Commit { chain } => {
3520                write!(f, "COMMIT{}", if *chain { " AND CHAIN" } else { "" },)
3521            }
3522            Statement::Rollback { chain, savepoint } => {
3523                write!(f, "ROLLBACK")?;
3524
3525                if *chain {
3526                    write!(f, " AND CHAIN")?;
3527                }
3528
3529                if let Some(savepoint) = savepoint {
3530                    write!(f, " TO SAVEPOINT {savepoint}")?;
3531                }
3532
3533                Ok(())
3534            }
3535            Statement::CreateSchema {
3536                schema_name,
3537                if_not_exists,
3538            } => write!(
3539                f,
3540                "CREATE SCHEMA {if_not_exists}{name}",
3541                if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
3542                name = schema_name
3543            ),
3544            Statement::Assert { condition, message } => {
3545                write!(f, "ASSERT {condition}")?;
3546                if let Some(m) = message {
3547                    write!(f, " AS {m}")?;
3548                }
3549                Ok(())
3550            }
3551            Statement::Grant {
3552                privileges,
3553                objects,
3554                grantees,
3555                with_grant_option,
3556                granted_by,
3557            } => {
3558                write!(f, "GRANT {privileges} ")?;
3559                write!(f, "ON {objects} ")?;
3560                write!(f, "TO {}", display_comma_separated(grantees))?;
3561                if *with_grant_option {
3562                    write!(f, " WITH GRANT OPTION")?;
3563                }
3564                if let Some(grantor) = granted_by {
3565                    write!(f, " GRANTED BY {grantor}")?;
3566                }
3567                Ok(())
3568            }
3569            Statement::Revoke {
3570                privileges,
3571                objects,
3572                grantees,
3573                granted_by,
3574                cascade,
3575            } => {
3576                write!(f, "REVOKE {privileges} ")?;
3577                write!(f, "ON {objects} ")?;
3578                write!(f, "FROM {}", display_comma_separated(grantees))?;
3579                if let Some(grantor) = granted_by {
3580                    write!(f, " GRANTED BY {grantor}")?;
3581                }
3582                write!(f, " {}", if *cascade { "CASCADE" } else { "RESTRICT" })?;
3583                Ok(())
3584            }
3585            Statement::Deallocate { name, prepare } => write!(
3586                f,
3587                "DEALLOCATE {prepare}{name}",
3588                prepare = if *prepare { "PREPARE " } else { "" },
3589                name = name,
3590            ),
3591            Statement::Execute { name, parameters } => {
3592                write!(f, "EXECUTE {name}")?;
3593                if !parameters.is_empty() {
3594                    write!(f, "({})", display_comma_separated(parameters))?;
3595                }
3596                Ok(())
3597            }
3598            Statement::Prepare {
3599                name,
3600                data_types,
3601                statement,
3602            } => {
3603                write!(f, "PREPARE {name} ")?;
3604                if !data_types.is_empty() {
3605                    write!(f, "({}) ", display_comma_separated(data_types))?;
3606                }
3607                write!(f, "AS {statement}")
3608            }
3609            Statement::Comment {
3610                object_type,
3611                object_name,
3612                comment,
3613                if_exists,
3614            } => {
3615                write!(f, "COMMENT ")?;
3616                if *if_exists {
3617                    write!(f, "IF EXISTS ")?
3618                };
3619                write!(f, "ON {object_type} {object_name} IS ")?;
3620                if let Some(c) = comment {
3621                    write!(f, "'{c}'")
3622                } else {
3623                    write!(f, "NULL")
3624                }
3625            }
3626            Statement::Savepoint { name } => {
3627                write!(f, "SAVEPOINT ")?;
3628                write!(f, "{name}")
3629            }
3630            Statement::ReleaseSavepoint { name } => {
3631                write!(f, "RELEASE SAVEPOINT {name}")
3632            }
3633            Statement::Merge {
3634                into,
3635                table,
3636                source,
3637                on,
3638                clauses,
3639            } => {
3640                write!(
3641                    f,
3642                    "MERGE{int} {table} USING {source} ",
3643                    int = if *into { " INTO" } else { "" }
3644                )?;
3645                write!(f, "ON {on} ")?;
3646                write!(f, "{}", display_separated(clauses, " "))
3647            }
3648            Statement::Cache {
3649                table_name,
3650                table_flag,
3651                has_as,
3652                options,
3653                query,
3654            } => {
3655                if table_flag.is_some() {
3656                    write!(
3657                        f,
3658                        "CACHE {table_flag} TABLE {table_name}",
3659                        table_flag = table_flag.clone().unwrap(),
3660                        table_name = table_name,
3661                    )?;
3662                } else {
3663                    write!(f, "CACHE TABLE {table_name}",)?;
3664                }
3665
3666                if !options.is_empty() {
3667                    write!(f, " OPTIONS({})", display_comma_separated(options))?;
3668                }
3669
3670                let has_query = query.is_some();
3671                if *has_as && has_query {
3672                    write!(f, " AS {query}", query = query.clone().unwrap())
3673                } else if !has_as && has_query {
3674                    write!(f, " {query}", query = query.clone().unwrap())
3675                } else if *has_as && !has_query {
3676                    write!(f, " AS")
3677                } else {
3678                    Ok(())
3679                }
3680            }
3681            Statement::UNCache {
3682                table_name,
3683                if_exists,
3684            } => {
3685                if *if_exists {
3686                    write!(f, "UNCACHE TABLE IF EXISTS {table_name}")
3687                } else {
3688                    write!(f, "UNCACHE TABLE {table_name}")
3689                }
3690            }
3691            Statement::CreateSequence {
3692                temporary,
3693                if_not_exists,
3694                name,
3695                data_type,
3696                sequence_options,
3697                owned_by,
3698            } => {
3699                let as_type: String = if let Some(dt) = data_type.as_ref() {
3700                    //Cannot use format!(" AS {}", dt), due to format! is not available in --target thumbv6m-none-eabi
3701                    // " AS ".to_owned() + &dt.to_string()
3702                    [" AS ", &dt.to_string()].concat()
3703                } else {
3704                    "".to_string()
3705                };
3706                write!(
3707                    f,
3708                    "CREATE {temporary}SEQUENCE {if_not_exists}{name}{as_type}",
3709                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
3710                    temporary = if *temporary { "TEMPORARY " } else { "" },
3711                    name = name,
3712                    as_type = as_type
3713                )?;
3714                for sequence_option in sequence_options {
3715                    write!(f, "{sequence_option}")?;
3716                }
3717                if let Some(ob) = owned_by.as_ref() {
3718                    write!(f, " OWNED BY {ob}")?;
3719                }
3720                write!(f, "")
3721            }
3722            Statement::CreateStage {
3723                or_replace,
3724                temporary,
3725                if_not_exists,
3726                name,
3727                stage_params,
3728                directory_table_params,
3729                file_format,
3730                copy_options,
3731                comment,
3732                ..
3733            } => {
3734                write!(
3735                    f,
3736                    "CREATE {or_replace}{temp}STAGE {if_not_exists}{name}{stage_params}",
3737                    temp = if *temporary { "TEMPORARY " } else { "" },
3738                    or_replace = if *or_replace { "OR REPLACE " } else { "" },
3739                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
3740                )?;
3741                if !directory_table_params.options.is_empty() {
3742                    write!(f, " DIRECTORY=({})", directory_table_params)?;
3743                }
3744                if !file_format.options.is_empty() {
3745                    write!(f, " FILE_FORMAT=({})", file_format)?;
3746                }
3747                if !copy_options.options.is_empty() {
3748                    write!(f, " COPY_OPTIONS=({})", copy_options)?;
3749                }
3750                if comment.is_some() {
3751                    write!(f, " COMMENT='{}'", comment.as_ref().unwrap())?;
3752                }
3753                Ok(())
3754            }
3755            Statement::CopyIntoSnowflake {
3756                into,
3757                from_stage,
3758                from_stage_alias,
3759                stage_params,
3760                from_transformations,
3761                files,
3762                pattern,
3763                file_format,
3764                copy_options,
3765                validation_mode,
3766            } => {
3767                write!(f, "COPY INTO {}", into)?;
3768                if from_transformations.is_none() {
3769                    // Standard data load
3770                    write!(f, " FROM {}{}", from_stage, stage_params)?;
3771                    if from_stage_alias.as_ref().is_some() {
3772                        write!(f, " AS {}", from_stage_alias.as_ref().unwrap())?;
3773                    }
3774                } else {
3775                    // Data load with transformation
3776                    write!(
3777                        f,
3778                        " FROM (SELECT {} FROM {}{}",
3779                        display_separated(from_transformations.as_ref().unwrap(), ", "),
3780                        from_stage,
3781                        stage_params,
3782                    )?;
3783                    if from_stage_alias.as_ref().is_some() {
3784                        write!(f, " AS {}", from_stage_alias.as_ref().unwrap())?;
3785                    }
3786                    write!(f, ")")?;
3787                }
3788                if files.is_some() {
3789                    write!(
3790                        f,
3791                        " FILES = ('{}')",
3792                        display_separated(files.as_ref().unwrap(), "', '")
3793                    )?;
3794                }
3795                if pattern.is_some() {
3796                    write!(f, " PATTERN = '{}'", pattern.as_ref().unwrap())?;
3797                }
3798                if !file_format.options.is_empty() {
3799                    write!(f, " FILE_FORMAT=({})", file_format)?;
3800                }
3801                if !copy_options.options.is_empty() {
3802                    write!(f, " COPY_OPTIONS=({})", copy_options)?;
3803                }
3804                if validation_mode.is_some() {
3805                    write!(
3806                        f,
3807                        " VALIDATION_MODE = {}",
3808                        validation_mode.as_ref().unwrap()
3809                    )?;
3810                }
3811                Ok(())
3812            }
3813            Statement::CreateType {
3814                name,
3815                representation,
3816            } => {
3817                write!(f, "CREATE TYPE {name} AS {representation}")
3818            }
3819            Statement::Pragma { name, value, is_eq } => {
3820                write!(f, "PRAGMA {name}")?;
3821                if value.is_some() {
3822                    let val = value.as_ref().unwrap();
3823                    if *is_eq {
3824                        write!(f, " = {val}")?;
3825                    } else {
3826                        write!(f, "({val})")?;
3827                    }
3828                }
3829                Ok(())
3830            }
3831            Statement::LockTables { tables } => {
3832                write!(f, "LOCK TABLES {}", display_comma_separated(tables))
3833            }
3834            Statement::UnlockTables => {
3835                write!(f, "UNLOCK TABLES")
3836            }
3837        }
3838    }
3839}
3840
3841/// Can use to describe options in create sequence or table column type identity
3842/// ```sql
3843/// [ INCREMENT [ BY ] increment ]
3844///     [ MINVALUE minvalue | NO MINVALUE ] [ MAXVALUE maxvalue | NO MAXVALUE ]
3845///     [ START [ WITH ] start ] [ CACHE cache ] [ [ NO ] CYCLE ]
3846/// ```
3847#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3848#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3849#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3850pub enum SequenceOptions {
3851    IncrementBy(Expr, bool),
3852    MinValue(Option<Expr>),
3853    MaxValue(Option<Expr>),
3854    StartWith(Expr, bool),
3855    Cache(Expr),
3856    Cycle(bool),
3857}
3858
3859impl fmt::Display for SequenceOptions {
3860    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3861        match self {
3862            SequenceOptions::IncrementBy(increment, by) => {
3863                write!(
3864                    f,
3865                    " INCREMENT{by} {increment}",
3866                    by = if *by { " BY" } else { "" },
3867                    increment = increment
3868                )
3869            }
3870            SequenceOptions::MinValue(Some(expr)) => {
3871                write!(f, " MINVALUE {expr}")
3872            }
3873            SequenceOptions::MinValue(None) => {
3874                write!(f, " NO MINVALUE")
3875            }
3876            SequenceOptions::MaxValue(Some(expr)) => {
3877                write!(f, " MAXVALUE {expr}")
3878            }
3879            SequenceOptions::MaxValue(None) => {
3880                write!(f, " NO MAXVALUE")
3881            }
3882            SequenceOptions::StartWith(start, with) => {
3883                write!(
3884                    f,
3885                    " START{with} {start}",
3886                    with = if *with { " WITH" } else { "" },
3887                    start = start
3888                )
3889            }
3890            SequenceOptions::Cache(cache) => {
3891                write!(f, " CACHE {}", *cache)
3892            }
3893            SequenceOptions::Cycle(no) => {
3894                write!(f, " {}CYCLE", if *no { "NO " } else { "" })
3895            }
3896        }
3897    }
3898}
3899
3900/// Can use to describe options in  create sequence or table column type identity
3901/// [ MINVALUE minvalue | NO MINVALUE ] [ MAXVALUE maxvalue | NO MAXVALUE ]
3902#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3903#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3904#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3905pub enum MinMaxValue {
3906    // clause is not specified
3907    Empty,
3908    // NO MINVALUE/NO MAXVALUE
3909    None,
3910    // MINVALUE <expr> / MAXVALUE <expr>
3911    Some(Expr),
3912}
3913
3914#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3915#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3916#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3917#[non_exhaustive]
3918pub enum OnInsert {
3919    /// ON DUPLICATE KEY UPDATE (MySQL when the key already exists, then execute an update instead)
3920    DuplicateKeyUpdate(Vec<Assignment>),
3921    /// ON CONFLICT is a PostgreSQL and Sqlite extension
3922    OnConflict(OnConflict),
3923}
3924
3925#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3926#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3927#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3928pub struct OnConflict {
3929    pub conflict_target: Option<ConflictTarget>,
3930    pub action: OnConflictAction,
3931}
3932#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3933#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3934#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3935pub enum ConflictTarget {
3936    Columns(Vec<Ident>),
3937    OnConstraint(ObjectName),
3938}
3939#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3940#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3941#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3942pub enum OnConflictAction {
3943    DoNothing,
3944    DoUpdate(DoUpdate),
3945}
3946
3947#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3948#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3949#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3950pub struct DoUpdate {
3951    /// Column assignments
3952    pub assignments: Vec<Assignment>,
3953    /// WHERE
3954    pub selection: Option<Expr>,
3955}
3956
3957impl fmt::Display for OnInsert {
3958    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3959        match self {
3960            Self::DuplicateKeyUpdate(expr) => write!(
3961                f,
3962                " ON DUPLICATE KEY UPDATE {}",
3963                display_comma_separated(expr)
3964            ),
3965            Self::OnConflict(o) => write!(f, "{o}"),
3966        }
3967    }
3968}
3969impl fmt::Display for OnConflict {
3970    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3971        write!(f, " ON CONFLICT")?;
3972        if let Some(target) = &self.conflict_target {
3973            write!(f, "{target}")?;
3974        }
3975        write!(f, " {}", self.action)
3976    }
3977}
3978impl fmt::Display for ConflictTarget {
3979    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3980        match self {
3981            ConflictTarget::Columns(cols) => write!(f, "({})", display_comma_separated(cols)),
3982            ConflictTarget::OnConstraint(name) => write!(f, " ON CONSTRAINT {name}"),
3983        }
3984    }
3985}
3986impl fmt::Display for OnConflictAction {
3987    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3988        match self {
3989            Self::DoNothing => write!(f, "DO NOTHING"),
3990            Self::DoUpdate(do_update) => {
3991                write!(f, "DO UPDATE")?;
3992                if !do_update.assignments.is_empty() {
3993                    write!(
3994                        f,
3995                        " SET {}",
3996                        display_comma_separated(&do_update.assignments)
3997                    )?;
3998                }
3999                if let Some(selection) = &do_update.selection {
4000                    write!(f, " WHERE {selection}")?;
4001                }
4002                Ok(())
4003            }
4004        }
4005    }
4006}
4007
4008/// Privileges granted in a GRANT statement or revoked in a REVOKE statement.
4009#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
4010#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4011#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
4012pub enum Privileges {
4013    /// All privileges applicable to the object type
4014    All {
4015        /// Optional keyword from the spec, ignored in practice
4016        with_privileges_keyword: bool,
4017    },
4018    /// Specific privileges (e.g. `SELECT`, `INSERT`)
4019    Actions(Vec<Action>),
4020}
4021
4022impl fmt::Display for Privileges {
4023    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
4024        match self {
4025            Privileges::All {
4026                with_privileges_keyword,
4027            } => {
4028                write!(
4029                    f,
4030                    "ALL{}",
4031                    if *with_privileges_keyword {
4032                        " PRIVILEGES"
4033                    } else {
4034                        ""
4035                    }
4036                )
4037            }
4038            Privileges::Actions(actions) => {
4039                write!(f, "{}", display_comma_separated(actions))
4040            }
4041        }
4042    }
4043}
4044
4045/// Specific direction for FETCH statement
4046#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
4047#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4048#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
4049pub enum FetchDirection {
4050    Count { limit: Value },
4051    Next,
4052    Prior,
4053    First,
4054    Last,
4055    Absolute { limit: Value },
4056    Relative { limit: Value },
4057    All,
4058    // FORWARD
4059    // FORWARD count
4060    Forward { limit: Option<Value> },
4061    ForwardAll,
4062    // BACKWARD
4063    // BACKWARD count
4064    Backward { limit: Option<Value> },
4065    BackwardAll,
4066}
4067
4068impl fmt::Display for FetchDirection {
4069    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
4070        match self {
4071            FetchDirection::Count { limit } => f.write_str(&limit.to_string())?,
4072            FetchDirection::Next => f.write_str("NEXT")?,
4073            FetchDirection::Prior => f.write_str("PRIOR")?,
4074            FetchDirection::First => f.write_str("FIRST")?,
4075            FetchDirection::Last => f.write_str("LAST")?,
4076            FetchDirection::Absolute { limit } => {
4077                f.write_str("ABSOLUTE ")?;
4078                f.write_str(&limit.to_string())?;
4079            }
4080            FetchDirection::Relative { limit } => {
4081                f.write_str("RELATIVE ")?;
4082                f.write_str(&limit.to_string())?;
4083            }
4084            FetchDirection::All => f.write_str("ALL")?,
4085            FetchDirection::Forward { limit } => {
4086                f.write_str("FORWARD")?;
4087
4088                if let Some(l) = limit {
4089                    f.write_str(" ")?;
4090                    f.write_str(&l.to_string())?;
4091                }
4092            }
4093            FetchDirection::ForwardAll => f.write_str("FORWARD ALL")?,
4094            FetchDirection::Backward { limit } => {
4095                f.write_str("BACKWARD")?;
4096
4097                if let Some(l) = limit {
4098                    f.write_str(" ")?;
4099                    f.write_str(&l.to_string())?;
4100                }
4101            }
4102            FetchDirection::BackwardAll => f.write_str("BACKWARD ALL")?,
4103        };
4104
4105        Ok(())
4106    }
4107}
4108
4109/// A privilege on a database object (table, sequence, etc.).
4110#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
4111#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4112#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
4113pub enum Action {
4114    Connect,
4115    Create,
4116    Delete,
4117    Execute,
4118    Insert { columns: Option<Vec<Ident>> },
4119    References { columns: Option<Vec<Ident>> },
4120    Select { columns: Option<Vec<Ident>> },
4121    Temporary,
4122    Trigger,
4123    Truncate,
4124    Update { columns: Option<Vec<Ident>> },
4125    Usage,
4126}
4127
4128impl fmt::Display for Action {
4129    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
4130        match self {
4131            Action::Connect => f.write_str("CONNECT")?,
4132            Action::Create => f.write_str("CREATE")?,
4133            Action::Delete => f.write_str("DELETE")?,
4134            Action::Execute => f.write_str("EXECUTE")?,
4135            Action::Insert { .. } => f.write_str("INSERT")?,
4136            Action::References { .. } => f.write_str("REFERENCES")?,
4137            Action::Select { .. } => f.write_str("SELECT")?,
4138            Action::Temporary => f.write_str("TEMPORARY")?,
4139            Action::Trigger => f.write_str("TRIGGER")?,
4140            Action::Truncate => f.write_str("TRUNCATE")?,
4141            Action::Update { .. } => f.write_str("UPDATE")?,
4142            Action::Usage => f.write_str("USAGE")?,
4143        };
4144        match self {
4145            Action::Insert { columns }
4146            | Action::References { columns }
4147            | Action::Select { columns }
4148            | Action::Update { columns } => {
4149                if let Some(columns) = columns {
4150                    write!(f, " ({})", display_comma_separated(columns))?;
4151                }
4152            }
4153            _ => (),
4154        };
4155        Ok(())
4156    }
4157}
4158
4159/// Objects on which privileges are granted in a GRANT statement.
4160#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
4161#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4162#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
4163pub enum GrantObjects {
4164    /// Grant privileges on `ALL SEQUENCES IN SCHEMA <schema_name> [, ...]`
4165    AllSequencesInSchema { schemas: Vec<ObjectName> },
4166    /// Grant privileges on `ALL TABLES IN SCHEMA <schema_name> [, ...]`
4167    AllTablesInSchema { schemas: Vec<ObjectName> },
4168    /// Grant privileges on specific schemas
4169    Schemas(Vec<ObjectName>),
4170    /// Grant privileges on specific sequences
4171    Sequences(Vec<ObjectName>),
4172    /// Grant privileges on specific tables
4173    Tables(Vec<ObjectName>),
4174}
4175
4176impl fmt::Display for GrantObjects {
4177    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
4178        match self {
4179            GrantObjects::Sequences(sequences) => {
4180                write!(f, "SEQUENCE {}", display_comma_separated(sequences))
4181            }
4182            GrantObjects::Schemas(schemas) => {
4183                write!(f, "SCHEMA {}", display_comma_separated(schemas))
4184            }
4185            GrantObjects::Tables(tables) => {
4186                write!(f, "{}", display_comma_separated(tables))
4187            }
4188            GrantObjects::AllSequencesInSchema { schemas } => {
4189                write!(
4190                    f,
4191                    "ALL SEQUENCES IN SCHEMA {}",
4192                    display_comma_separated(schemas)
4193                )
4194            }
4195            GrantObjects::AllTablesInSchema { schemas } => {
4196                write!(
4197                    f,
4198                    "ALL TABLES IN SCHEMA {}",
4199                    display_comma_separated(schemas)
4200                )
4201            }
4202        }
4203    }
4204}
4205
4206/// SQL assignment `foo = expr` as used in SQLUpdate
4207#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
4208#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4209#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
4210pub struct Assignment {
4211    pub id: Vec<Ident>,
4212    pub value: Expr,
4213}
4214
4215impl fmt::Display for Assignment {
4216    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
4217        write!(f, "{} = {}", display_separated(&self.id, "."), self.value)
4218    }
4219}
4220
4221#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
4222#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4223#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
4224pub enum FunctionArgExpr {
4225    Expr(Expr),
4226    /// Qualified wildcard, e.g. `alias.*` or `schema.table.*`.
4227    QualifiedWildcard(ObjectName),
4228    /// An unqualified `*`
4229    Wildcard,
4230}
4231
4232impl From<Expr> for FunctionArgExpr {
4233    fn from(wildcard_expr: Expr) -> Self {
4234        match wildcard_expr {
4235            Expr::QualifiedWildcard(prefix) => Self::QualifiedWildcard(prefix),
4236            Expr::Wildcard => Self::Wildcard,
4237            expr => Self::Expr(expr),
4238        }
4239    }
4240}
4241
4242impl fmt::Display for FunctionArgExpr {
4243    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
4244        match self {
4245            FunctionArgExpr::Expr(expr) => write!(f, "{expr}"),
4246            FunctionArgExpr::QualifiedWildcard(prefix) => write!(f, "{prefix}.*"),
4247            FunctionArgExpr::Wildcard => f.write_str("*"),
4248        }
4249    }
4250}
4251
4252#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
4253#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4254#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
4255pub enum FunctionArg {
4256    Named { name: Ident, arg: FunctionArgExpr },
4257    Unnamed(FunctionArgExpr),
4258}
4259
4260impl fmt::Display for FunctionArg {
4261    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
4262        match self {
4263            FunctionArg::Named { name, arg } => write!(f, "{name} => {arg}"),
4264            FunctionArg::Unnamed(unnamed_arg) => write!(f, "{unnamed_arg}"),
4265        }
4266    }
4267}
4268
4269#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
4270#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4271#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
4272pub enum CloseCursor {
4273    All,
4274    Specific { name: Ident },
4275}
4276
4277impl fmt::Display for CloseCursor {
4278    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
4279        match self {
4280            CloseCursor::All => write!(f, "ALL"),
4281            CloseCursor::Specific { name } => write!(f, "{name}"),
4282        }
4283    }
4284}
4285
4286/// A function call
4287#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
4288#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4289#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
4290pub struct Function {
4291    pub name: ObjectName,
4292    pub args: Vec<FunctionArg>,
4293    /// e.g. `x > 5` in `COUNT(x) FILTER (WHERE x > 5)`
4294    pub filter: Option<Box<Expr>>,
4295    // Snowflake/MSSQL supports diffrent options for null treatment in rank functions
4296    pub null_treatment: Option<NullTreatment>,
4297    pub over: Option<WindowType>,
4298    // aggregate functions may specify eg `COUNT(DISTINCT x)`
4299    pub distinct: bool,
4300    // Some functions must be called without trailing parentheses, for example Postgres
4301    // do it for current_catalog, current_schema, etc. This flags is used for formatting.
4302    pub special: bool,
4303    // Required ordering for the function (if empty, there is no requirement).
4304    pub order_by: Vec<OrderByExpr>,
4305}
4306
4307#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
4308#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4309#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
4310pub enum AnalyzeFormat {
4311    TEXT,
4312    GRAPHVIZ,
4313    JSON,
4314}
4315
4316impl fmt::Display for AnalyzeFormat {
4317    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
4318        f.write_str(match self {
4319            AnalyzeFormat::TEXT => "TEXT",
4320            AnalyzeFormat::GRAPHVIZ => "GRAPHVIZ",
4321            AnalyzeFormat::JSON => "JSON",
4322        })
4323    }
4324}
4325
4326impl fmt::Display for Function {
4327    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
4328        if self.special {
4329            write!(f, "{}", self.name)?;
4330        } else {
4331            let order_by = if !self.order_by.is_empty() {
4332                " ORDER BY "
4333            } else {
4334                ""
4335            };
4336            write!(
4337                f,
4338                "{}({}{}{order_by}{})",
4339                self.name,
4340                if self.distinct { "DISTINCT " } else { "" },
4341                display_comma_separated(&self.args),
4342                display_comma_separated(&self.order_by),
4343            )?;
4344
4345            if let Some(filter_cond) = &self.filter {
4346                write!(f, " FILTER (WHERE {filter_cond})")?;
4347            }
4348
4349            if let Some(o) = &self.null_treatment {
4350                write!(f, " {o}")?;
4351            }
4352
4353            if let Some(o) = &self.over {
4354                write!(f, " OVER {o}")?;
4355            }
4356        }
4357
4358        Ok(())
4359    }
4360}
4361
4362/// External table's available file format
4363#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
4364#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4365#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
4366pub enum FileFormat {
4367    TEXTFILE,
4368    SEQUENCEFILE,
4369    ORC,
4370    PARQUET,
4371    AVRO,
4372    RCFILE,
4373    JSONFILE,
4374}
4375
4376impl fmt::Display for FileFormat {
4377    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
4378        use self::FileFormat::*;
4379        f.write_str(match self {
4380            TEXTFILE => "TEXTFILE",
4381            SEQUENCEFILE => "SEQUENCEFILE",
4382            ORC => "ORC",
4383            PARQUET => "PARQUET",
4384            AVRO => "AVRO",
4385            RCFILE => "RCFILE",
4386            JSONFILE => "JSONFILE",
4387        })
4388    }
4389}
4390
4391/// A `LISTAGG` invocation `LISTAGG( [ DISTINCT ] <expr>[, <separator> ] [ON OVERFLOW <on_overflow>] ) )
4392/// [ WITHIN GROUP (ORDER BY <within_group1>[, ...] ) ]`
4393#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
4394#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4395#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
4396pub struct ListAgg {
4397    pub distinct: bool,
4398    pub expr: Box<Expr>,
4399    pub separator: Option<Box<Expr>>,
4400    pub on_overflow: Option<ListAggOnOverflow>,
4401    pub within_group: Vec<OrderByExpr>,
4402}
4403
4404impl fmt::Display for ListAgg {
4405    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
4406        write!(
4407            f,
4408            "LISTAGG({}{}",
4409            if self.distinct { "DISTINCT " } else { "" },
4410            self.expr
4411        )?;
4412        if let Some(separator) = &self.separator {
4413            write!(f, ", {separator}")?;
4414        }
4415        if let Some(on_overflow) = &self.on_overflow {
4416            write!(f, "{on_overflow}")?;
4417        }
4418        write!(f, ")")?;
4419        if !self.within_group.is_empty() {
4420            write!(
4421                f,
4422                " WITHIN GROUP (ORDER BY {})",
4423                display_comma_separated(&self.within_group)
4424            )?;
4425        }
4426        Ok(())
4427    }
4428}
4429
4430/// The `ON OVERFLOW` clause of a LISTAGG invocation
4431#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
4432#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4433#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
4434pub enum ListAggOnOverflow {
4435    /// `ON OVERFLOW ERROR`
4436    Error,
4437
4438    /// `ON OVERFLOW TRUNCATE [ <filler> ] WITH[OUT] COUNT`
4439    Truncate {
4440        filler: Option<Box<Expr>>,
4441        with_count: bool,
4442    },
4443}
4444
4445impl fmt::Display for ListAggOnOverflow {
4446    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
4447        write!(f, " ON OVERFLOW")?;
4448        match self {
4449            ListAggOnOverflow::Error => write!(f, " ERROR"),
4450            ListAggOnOverflow::Truncate { filler, with_count } => {
4451                write!(f, " TRUNCATE")?;
4452                if let Some(filler) = filler {
4453                    write!(f, " {filler}")?;
4454                }
4455                if *with_count {
4456                    write!(f, " WITH")?;
4457                } else {
4458                    write!(f, " WITHOUT")?;
4459                }
4460                write!(f, " COUNT")
4461            }
4462        }
4463    }
4464}
4465
4466/// An `ARRAY_AGG` invocation `ARRAY_AGG( [ DISTINCT ] <expr> [ORDER BY <expr>] [LIMIT <n>] )`
4467/// Or `ARRAY_AGG( [ DISTINCT ] <expr> ) [ WITHIN GROUP ( ORDER BY <expr> ) ]`
4468/// ORDER BY position is defined differently for BigQuery, Postgres and Snowflake.
4469#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
4470#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4471#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
4472pub struct ArrayAgg {
4473    pub distinct: bool,
4474    pub expr: Box<Expr>,
4475    pub order_by: Option<Vec<OrderByExpr>>,
4476    pub limit: Option<Box<Expr>>,
4477    pub within_group: bool, // order by is used inside a within group or not
4478}
4479
4480impl fmt::Display for ArrayAgg {
4481    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
4482        write!(
4483            f,
4484            "ARRAY_AGG({}{}",
4485            if self.distinct { "DISTINCT " } else { "" },
4486            self.expr
4487        )?;
4488        if !self.within_group {
4489            if let Some(order_by) = &self.order_by {
4490                write!(f, " ORDER BY {}", display_comma_separated(order_by))?;
4491            }
4492            if let Some(limit) = &self.limit {
4493                write!(f, " LIMIT {limit}")?;
4494            }
4495        }
4496        write!(f, ")")?;
4497        if self.within_group {
4498            if let Some(order_by) = &self.order_by {
4499                write!(
4500                    f,
4501                    " WITHIN GROUP (ORDER BY {})",
4502                    display_comma_separated(order_by)
4503                )?;
4504            }
4505        }
4506        Ok(())
4507    }
4508}
4509
4510#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
4511#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4512#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
4513pub enum ObjectType {
4514    Table,
4515    View,
4516    Index,
4517    Schema,
4518    Role,
4519    Sequence,
4520    Stage,
4521}
4522
4523impl fmt::Display for ObjectType {
4524    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
4525        f.write_str(match self {
4526            ObjectType::Table => "TABLE",
4527            ObjectType::View => "VIEW",
4528            ObjectType::Index => "INDEX",
4529            ObjectType::Schema => "SCHEMA",
4530            ObjectType::Role => "ROLE",
4531            ObjectType::Sequence => "SEQUENCE",
4532            ObjectType::Stage => "STAGE",
4533        })
4534    }
4535}
4536
4537#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
4538#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4539#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
4540pub enum KillType {
4541    Connection,
4542    Query,
4543    Mutation,
4544}
4545
4546impl fmt::Display for KillType {
4547    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
4548        f.write_str(match self {
4549            // MySQL
4550            KillType::Connection => "CONNECTION",
4551            KillType::Query => "QUERY",
4552            // Clickhouse supports Mutation
4553            KillType::Mutation => "MUTATION",
4554        })
4555    }
4556}
4557
4558#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
4559#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4560#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
4561pub enum HiveDistributionStyle {
4562    PARTITIONED {
4563        columns: Vec<ColumnDef>,
4564    },
4565    CLUSTERED {
4566        columns: Vec<Ident>,
4567        sorted_by: Vec<ColumnDef>,
4568        num_buckets: i32,
4569    },
4570    SKEWED {
4571        columns: Vec<ColumnDef>,
4572        on: Vec<ColumnDef>,
4573        stored_as_directories: bool,
4574    },
4575    NONE,
4576}
4577
4578#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
4579#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4580#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
4581pub enum HiveRowFormat {
4582    SERDE { class: String },
4583    DELIMITED,
4584}
4585
4586#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
4587#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4588#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
4589#[allow(clippy::large_enum_variant)]
4590pub enum HiveIOFormat {
4591    IOF {
4592        input_format: Expr,
4593        output_format: Expr,
4594    },
4595    FileFormat {
4596        format: FileFormat,
4597    },
4598}
4599
4600#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Default)]
4601#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4602#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
4603pub struct HiveFormat {
4604    pub row_format: Option<HiveRowFormat>,
4605    pub storage: Option<HiveIOFormat>,
4606    pub location: Option<String>,
4607}
4608
4609#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
4610#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4611#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
4612pub struct SqlOption {
4613    pub name: Ident,
4614    pub value: Expr,
4615}
4616
4617impl fmt::Display for SqlOption {
4618    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
4619        write!(f, "{} = {}", self.name, self.value)
4620    }
4621}
4622
4623#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
4624#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4625#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
4626pub enum TransactionMode {
4627    AccessMode(TransactionAccessMode),
4628    IsolationLevel(TransactionIsolationLevel),
4629}
4630
4631impl fmt::Display for TransactionMode {
4632    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
4633        use TransactionMode::*;
4634        match self {
4635            AccessMode(access_mode) => write!(f, "{access_mode}"),
4636            IsolationLevel(iso_level) => write!(f, "ISOLATION LEVEL {iso_level}"),
4637        }
4638    }
4639}
4640
4641#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
4642#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4643#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
4644pub enum TransactionAccessMode {
4645    ReadOnly,
4646    ReadWrite,
4647}
4648
4649impl fmt::Display for TransactionAccessMode {
4650    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
4651        use TransactionAccessMode::*;
4652        f.write_str(match self {
4653            ReadOnly => "READ ONLY",
4654            ReadWrite => "READ WRITE",
4655        })
4656    }
4657}
4658
4659#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
4660#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4661#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
4662pub enum TransactionIsolationLevel {
4663    ReadUncommitted,
4664    ReadCommitted,
4665    RepeatableRead,
4666    Serializable,
4667}
4668
4669impl fmt::Display for TransactionIsolationLevel {
4670    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
4671        use TransactionIsolationLevel::*;
4672        f.write_str(match self {
4673            ReadUncommitted => "READ UNCOMMITTED",
4674            ReadCommitted => "READ COMMITTED",
4675            RepeatableRead => "REPEATABLE READ",
4676            Serializable => "SERIALIZABLE",
4677        })
4678    }
4679}
4680
4681/// SQLite specific syntax
4682///
4683/// <https://sqlite.org/lang_transaction.html>
4684#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
4685#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4686#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
4687pub enum TransactionModifier {
4688    Deferred,
4689    Immediate,
4690    Exclusive,
4691}
4692
4693impl fmt::Display for TransactionModifier {
4694    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
4695        use TransactionModifier::*;
4696        f.write_str(match self {
4697            Deferred => "DEFERRED",
4698            Immediate => "IMMEDIATE",
4699            Exclusive => "EXCLUSIVE",
4700        })
4701    }
4702}
4703
4704#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
4705#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4706#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
4707pub enum ShowStatementFilter {
4708    Like(String),
4709    ILike(String),
4710    Where(Expr),
4711}
4712
4713impl fmt::Display for ShowStatementFilter {
4714    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
4715        use ShowStatementFilter::*;
4716        match self {
4717            Like(pattern) => write!(f, "LIKE '{}'", value::escape_single_quote_string(pattern)),
4718            ILike(pattern) => write!(f, "ILIKE {}", value::escape_single_quote_string(pattern)),
4719            Where(expr) => write!(f, "WHERE {expr}"),
4720        }
4721    }
4722}
4723
4724/// Sqlite specific syntax
4725///
4726/// See [Sqlite documentation](https://sqlite.org/lang_conflict.html)
4727/// for more details.
4728#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
4729#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4730#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
4731pub enum SqliteOnConflict {
4732    Rollback,
4733    Abort,
4734    Fail,
4735    Ignore,
4736    Replace,
4737}
4738
4739impl fmt::Display for SqliteOnConflict {
4740    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
4741        use SqliteOnConflict::*;
4742        match self {
4743            Rollback => write!(f, "ROLLBACK"),
4744            Abort => write!(f, "ABORT"),
4745            Fail => write!(f, "FAIL"),
4746            Ignore => write!(f, "IGNORE"),
4747            Replace => write!(f, "REPLACE"),
4748        }
4749    }
4750}
4751
4752/// Mysql specific syntax
4753///
4754/// See [Mysql documentation](https://dev.mysql.com/doc/refman/8.0/en/replace.html)
4755/// See [Mysql documentation](https://dev.mysql.com/doc/refman/8.0/en/insert.html)
4756/// for more details.
4757#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
4758#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4759#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
4760pub enum MysqlInsertPriority {
4761    LowPriority,
4762    Delayed,
4763    HighPriority,
4764}
4765
4766impl fmt::Display for crate::ast::MysqlInsertPriority {
4767    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
4768        use MysqlInsertPriority::*;
4769        match self {
4770            LowPriority => write!(f, "LOW_PRIORITY"),
4771            Delayed => write!(f, "DELAYED"),
4772            HighPriority => write!(f, "HIGH_PRIORITY"),
4773        }
4774    }
4775}
4776
4777#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
4778#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4779#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
4780pub enum CopySource {
4781    Table {
4782        /// The name of the table to copy from.
4783        table_name: ObjectName,
4784        /// A list of column names to copy. Empty list means that all columns
4785        /// are copied.
4786        columns: Vec<Ident>,
4787    },
4788    Query(Box<Query>),
4789}
4790
4791#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
4792#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4793#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
4794pub enum CopyTarget {
4795    Stdin,
4796    Stdout,
4797    File {
4798        /// The path name of the input or output file.
4799        filename: String,
4800    },
4801    Program {
4802        /// A command to execute
4803        command: String,
4804    },
4805}
4806
4807impl fmt::Display for CopyTarget {
4808    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
4809        use CopyTarget::*;
4810        match self {
4811            Stdin { .. } => write!(f, "STDIN"),
4812            Stdout => write!(f, "STDOUT"),
4813            File { filename } => write!(f, "'{}'", value::escape_single_quote_string(filename)),
4814            Program { command } => write!(
4815                f,
4816                "PROGRAM '{}'",
4817                value::escape_single_quote_string(command)
4818            ),
4819        }
4820    }
4821}
4822
4823#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
4824#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4825#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
4826pub enum OnCommit {
4827    DeleteRows,
4828    PreserveRows,
4829    Drop,
4830}
4831
4832/// An option in `COPY` statement.
4833///
4834/// <https://www.postgresql.org/docs/14/sql-copy.html>
4835#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
4836#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4837#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
4838pub enum CopyOption {
4839    /// FORMAT format_name
4840    Format(Ident),
4841    /// FREEZE \[ boolean \]
4842    Freeze(bool),
4843    /// DELIMITER 'delimiter_character'
4844    Delimiter(char),
4845    /// NULL 'null_string'
4846    Null(String),
4847    /// HEADER \[ boolean \]
4848    Header(bool),
4849    /// QUOTE 'quote_character'
4850    Quote(char),
4851    /// ESCAPE 'escape_character'
4852    Escape(char),
4853    /// FORCE_QUOTE { ( column_name [, ...] ) | * }
4854    ForceQuote(Vec<Ident>),
4855    /// FORCE_NOT_NULL ( column_name [, ...] )
4856    ForceNotNull(Vec<Ident>),
4857    /// FORCE_NULL ( column_name [, ...] )
4858    ForceNull(Vec<Ident>),
4859    /// ENCODING 'encoding_name'
4860    Encoding(String),
4861}
4862
4863impl fmt::Display for CopyOption {
4864    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
4865        use CopyOption::*;
4866        match self {
4867            Format(name) => write!(f, "FORMAT {name}"),
4868            Freeze(true) => write!(f, "FREEZE"),
4869            Freeze(false) => write!(f, "FREEZE FALSE"),
4870            Delimiter(char) => write!(f, "DELIMITER '{char}'"),
4871            Null(string) => write!(f, "NULL '{}'", value::escape_single_quote_string(string)),
4872            Header(true) => write!(f, "HEADER"),
4873            Header(false) => write!(f, "HEADER FALSE"),
4874            Quote(char) => write!(f, "QUOTE '{char}'"),
4875            Escape(char) => write!(f, "ESCAPE '{char}'"),
4876            ForceQuote(columns) => write!(f, "FORCE_QUOTE ({})", display_comma_separated(columns)),
4877            ForceNotNull(columns) => {
4878                write!(f, "FORCE_NOT_NULL ({})", display_comma_separated(columns))
4879            }
4880            ForceNull(columns) => write!(f, "FORCE_NULL ({})", display_comma_separated(columns)),
4881            Encoding(name) => write!(f, "ENCODING '{}'", value::escape_single_quote_string(name)),
4882        }
4883    }
4884}
4885
4886/// An option in `COPY` statement before PostgreSQL version 9.0.
4887///
4888/// <https://www.postgresql.org/docs/8.4/sql-copy.html>
4889#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
4890#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4891#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
4892pub enum CopyLegacyOption {
4893    /// BINARY
4894    Binary,
4895    /// DELIMITER \[ AS \] 'delimiter_character'
4896    Delimiter(char),
4897    /// NULL \[ AS \] 'null_string'
4898    Null(String),
4899    /// CSV ...
4900    Csv(Vec<CopyLegacyCsvOption>),
4901}
4902
4903impl fmt::Display for CopyLegacyOption {
4904    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
4905        use CopyLegacyOption::*;
4906        match self {
4907            Binary => write!(f, "BINARY"),
4908            Delimiter(char) => write!(f, "DELIMITER '{char}'"),
4909            Null(string) => write!(f, "NULL '{}'", value::escape_single_quote_string(string)),
4910            Csv(opts) => write!(f, "CSV {}", display_separated(opts, " ")),
4911        }
4912    }
4913}
4914
4915/// A `CSV` option in `COPY` statement before PostgreSQL version 9.0.
4916///
4917/// <https://www.postgresql.org/docs/8.4/sql-copy.html>
4918#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
4919#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4920#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
4921pub enum CopyLegacyCsvOption {
4922    /// HEADER
4923    Header,
4924    /// QUOTE \[ AS \] 'quote_character'
4925    Quote(char),
4926    /// ESCAPE \[ AS \] 'escape_character'
4927    Escape(char),
4928    /// FORCE QUOTE { column_name [, ...] | * }
4929    ForceQuote(Vec<Ident>),
4930    /// FORCE NOT NULL column_name [, ...]
4931    ForceNotNull(Vec<Ident>),
4932}
4933
4934impl fmt::Display for CopyLegacyCsvOption {
4935    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
4936        use CopyLegacyCsvOption::*;
4937        match self {
4938            Header => write!(f, "HEADER"),
4939            Quote(char) => write!(f, "QUOTE '{char}'"),
4940            Escape(char) => write!(f, "ESCAPE '{char}'"),
4941            ForceQuote(columns) => write!(f, "FORCE QUOTE {}", display_comma_separated(columns)),
4942            ForceNotNull(columns) => {
4943                write!(f, "FORCE NOT NULL {}", display_comma_separated(columns))
4944            }
4945        }
4946    }
4947}
4948
4949///
4950#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
4951#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4952#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
4953pub enum MergeClause {
4954    MatchedUpdate {
4955        predicate: Option<Expr>,
4956        assignments: Vec<Assignment>,
4957    },
4958    MatchedDelete(Option<Expr>),
4959    NotMatched {
4960        predicate: Option<Expr>,
4961        columns: Vec<Ident>,
4962        values: Values,
4963    },
4964}
4965
4966impl fmt::Display for MergeClause {
4967    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
4968        use MergeClause::*;
4969        write!(f, "WHEN")?;
4970        match self {
4971            MatchedUpdate {
4972                predicate,
4973                assignments,
4974            } => {
4975                write!(f, " MATCHED")?;
4976                if let Some(pred) = predicate {
4977                    write!(f, " AND {pred}")?;
4978                }
4979                write!(
4980                    f,
4981                    " THEN UPDATE SET {}",
4982                    display_comma_separated(assignments)
4983                )
4984            }
4985            MatchedDelete(predicate) => {
4986                write!(f, " MATCHED")?;
4987                if let Some(pred) = predicate {
4988                    write!(f, " AND {pred}")?;
4989                }
4990                write!(f, " THEN DELETE")
4991            }
4992            NotMatched {
4993                predicate,
4994                columns,
4995                values,
4996            } => {
4997                write!(f, " NOT MATCHED")?;
4998                if let Some(pred) = predicate {
4999                    write!(f, " AND {pred}")?;
5000                }
5001                write!(
5002                    f,
5003                    " THEN INSERT ({}) {}",
5004                    display_comma_separated(columns),
5005                    values
5006                )
5007            }
5008        }
5009    }
5010}
5011
5012#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
5013#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
5014#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
5015pub enum DiscardObject {
5016    ALL,
5017    PLANS,
5018    SEQUENCES,
5019    TEMP,
5020}
5021
5022impl fmt::Display for DiscardObject {
5023    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
5024        match self {
5025            DiscardObject::ALL => f.write_str("ALL"),
5026            DiscardObject::PLANS => f.write_str("PLANS"),
5027            DiscardObject::SEQUENCES => f.write_str("SEQUENCES"),
5028            DiscardObject::TEMP => f.write_str("TEMP"),
5029        }
5030    }
5031}
5032
5033#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
5034#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
5035#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
5036pub enum FlushType {
5037    BinaryLogs,
5038    EngineLogs,
5039    ErrorLogs,
5040    GeneralLogs,
5041    Hosts,
5042    Logs,
5043    Privileges,
5044    OptimizerCosts,
5045    RelayLogs,
5046    SlowLogs,
5047    Status,
5048    UserResources,
5049    Tables,
5050}
5051
5052impl fmt::Display for FlushType {
5053    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
5054        match self {
5055            FlushType::BinaryLogs => f.write_str("BINARY LOGS"),
5056            FlushType::EngineLogs => f.write_str("ENGINE LOGS"),
5057            FlushType::ErrorLogs => f.write_str("ERROR LOGS"),
5058            FlushType::GeneralLogs => f.write_str("GENERAL LOGS"),
5059            FlushType::Hosts => f.write_str("HOSTS"),
5060            FlushType::Logs => f.write_str("LOGS"),
5061            FlushType::Privileges => f.write_str("PRIVILEGES"),
5062            FlushType::OptimizerCosts => f.write_str("OPTIMIZER_COSTS"),
5063            FlushType::RelayLogs => f.write_str("RELAY LOGS"),
5064            FlushType::SlowLogs => f.write_str("SLOW LOGS"),
5065            FlushType::Status => f.write_str("STATUS"),
5066            FlushType::UserResources => f.write_str("USER_RESOURCES"),
5067            FlushType::Tables => f.write_str("TABLES"),
5068        }
5069    }
5070}
5071
5072#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
5073#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
5074#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
5075pub enum FlushLocation {
5076    NoWriteToBinlog,
5077    Local,
5078}
5079
5080impl fmt::Display for FlushLocation {
5081    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
5082        match self {
5083            FlushLocation::NoWriteToBinlog => f.write_str("NO_WRITE_TO_BINLOG"),
5084            FlushLocation::Local => f.write_str("LOCAL"),
5085        }
5086    }
5087}
5088
5089/// Optional context modifier for statements that can be or `LOCAL`, or `SESSION`.
5090#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
5091#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
5092#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
5093pub enum ContextModifier {
5094    /// No context defined. Each dialect defines the default in this scenario.
5095    None,
5096    /// `LOCAL` identifier, usually related to transactional states.
5097    Local,
5098    /// `SESSION` identifier
5099    Session,
5100}
5101
5102impl fmt::Display for ContextModifier {
5103    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
5104        match self {
5105            Self::None => {
5106                write!(f, "")
5107            }
5108            Self::Local => {
5109                write!(f, " LOCAL")
5110            }
5111            Self::Session => {
5112                write!(f, " SESSION")
5113            }
5114        }
5115    }
5116}
5117
5118/// Function describe in DROP FUNCTION.
5119#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
5120#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
5121pub enum DropFunctionOption {
5122    Restrict,
5123    Cascade,
5124}
5125
5126impl fmt::Display for DropFunctionOption {
5127    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
5128        match self {
5129            DropFunctionOption::Restrict => write!(f, "RESTRICT "),
5130            DropFunctionOption::Cascade => write!(f, "CASCADE  "),
5131        }
5132    }
5133}
5134
5135/// Function describe in DROP FUNCTION.
5136#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
5137#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
5138#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
5139pub struct DropFunctionDesc {
5140    pub name: ObjectName,
5141    pub args: Option<Vec<OperateFunctionArg>>,
5142}
5143
5144impl fmt::Display for DropFunctionDesc {
5145    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
5146        write!(f, "{}", self.name)?;
5147        if let Some(args) = &self.args {
5148            write!(f, "({})", display_comma_separated(args))?;
5149        }
5150        Ok(())
5151    }
5152}
5153
5154/// Function argument in CREATE OR DROP FUNCTION.
5155#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
5156#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
5157#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
5158pub struct OperateFunctionArg {
5159    pub mode: Option<ArgMode>,
5160    pub name: Option<Ident>,
5161    pub data_type: DataType,
5162    pub default_expr: Option<Expr>,
5163}
5164
5165impl OperateFunctionArg {
5166    /// Returns an unnamed argument.
5167    pub fn unnamed(data_type: DataType) -> Self {
5168        Self {
5169            mode: None,
5170            name: None,
5171            data_type,
5172            default_expr: None,
5173        }
5174    }
5175
5176    /// Returns an argument with name.
5177    pub fn with_name(name: &str, data_type: DataType) -> Self {
5178        Self {
5179            mode: None,
5180            name: Some(name.into()),
5181            data_type,
5182            default_expr: None,
5183        }
5184    }
5185}
5186
5187impl fmt::Display for OperateFunctionArg {
5188    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
5189        if let Some(mode) = &self.mode {
5190            write!(f, "{mode} ")?;
5191        }
5192        if let Some(name) = &self.name {
5193            write!(f, "{name} ")?;
5194        }
5195        write!(f, "{}", self.data_type)?;
5196        if let Some(default_expr) = &self.default_expr {
5197            write!(f, " = {default_expr}")?;
5198        }
5199        Ok(())
5200    }
5201}
5202
5203/// The mode of an argument in CREATE FUNCTION.
5204#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
5205#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
5206#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
5207pub enum ArgMode {
5208    In,
5209    Out,
5210    InOut,
5211}
5212
5213impl fmt::Display for ArgMode {
5214    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
5215        match self {
5216            ArgMode::In => write!(f, "IN"),
5217            ArgMode::Out => write!(f, "OUT"),
5218            ArgMode::InOut => write!(f, "INOUT"),
5219        }
5220    }
5221}
5222
5223/// These attributes inform the query optimizer about the behavior of the function.
5224#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
5225#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
5226#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
5227pub enum FunctionBehavior {
5228    Immutable,
5229    Stable,
5230    Volatile,
5231}
5232
5233impl fmt::Display for FunctionBehavior {
5234    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
5235        match self {
5236            FunctionBehavior::Immutable => write!(f, "IMMUTABLE"),
5237            FunctionBehavior::Stable => write!(f, "STABLE"),
5238            FunctionBehavior::Volatile => write!(f, "VOLATILE"),
5239        }
5240    }
5241}
5242
5243#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
5244#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
5245#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
5246pub enum FunctionDefinition {
5247    SingleQuotedDef(String),
5248    DoubleDollarDef(String),
5249}
5250
5251impl fmt::Display for FunctionDefinition {
5252    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
5253        match self {
5254            FunctionDefinition::SingleQuotedDef(s) => write!(f, "'{s}'")?,
5255            FunctionDefinition::DoubleDollarDef(s) => write!(f, "$${s}$$")?,
5256        }
5257        Ok(())
5258    }
5259}
5260
5261/// Postgres specific feature.
5262///
5263/// See [Postgresdocs](https://www.postgresql.org/docs/15/sql-createfunction.html)
5264/// for more details
5265#[derive(Debug, Default, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
5266#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
5267#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
5268pub struct CreateFunctionBody {
5269    /// LANGUAGE lang_name
5270    pub language: Option<Ident>,
5271    /// IMMUTABLE | STABLE | VOLATILE
5272    pub behavior: Option<FunctionBehavior>,
5273    /// AS 'definition'
5274    ///
5275    /// Note that Hive's `AS class_name` is also parsed here.
5276    pub as_: Option<FunctionDefinition>,
5277    /// RETURN expression
5278    pub return_: Option<Expr>,
5279    /// USING ... (Hive only)
5280    pub using: Option<CreateFunctionUsing>,
5281}
5282
5283impl fmt::Display for CreateFunctionBody {
5284    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
5285        if let Some(language) = &self.language {
5286            write!(f, " LANGUAGE {language}")?;
5287        }
5288        if let Some(behavior) = &self.behavior {
5289            write!(f, " {behavior}")?;
5290        }
5291        if let Some(definition) = &self.as_ {
5292            write!(f, " AS {definition}")?;
5293        }
5294        if let Some(expr) = &self.return_ {
5295            write!(f, " RETURN {expr}")?;
5296        }
5297        if let Some(using) = &self.using {
5298            write!(f, " {using}")?;
5299        }
5300        Ok(())
5301    }
5302}
5303
5304#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
5305#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
5306#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
5307pub enum CreateFunctionUsing {
5308    Jar(String),
5309    File(String),
5310    Archive(String),
5311}
5312
5313impl fmt::Display for CreateFunctionUsing {
5314    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
5315        write!(f, "USING ")?;
5316        match self {
5317            CreateFunctionUsing::Jar(uri) => write!(f, "JAR '{uri}'"),
5318            CreateFunctionUsing::File(uri) => write!(f, "FILE '{uri}'"),
5319            CreateFunctionUsing::Archive(uri) => write!(f, "ARCHIVE '{uri}'"),
5320        }
5321    }
5322}
5323
5324/// `NAME = <EXPR>` arguments for DuckDB macros
5325///
5326/// See [Create Macro - DuckDB](https://duckdb.org/docs/sql/statements/create_macro)
5327/// for more details
5328#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
5329#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
5330#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
5331pub struct MacroArg {
5332    pub name: Ident,
5333    pub default_expr: Option<Expr>,
5334}
5335
5336impl MacroArg {
5337    /// Returns an argument with name.
5338    pub fn new(name: &str) -> Self {
5339        Self {
5340            name: name.into(),
5341            default_expr: None,
5342        }
5343    }
5344}
5345
5346impl fmt::Display for MacroArg {
5347    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
5348        write!(f, "{}", self.name)?;
5349        if let Some(default_expr) = &self.default_expr {
5350            write!(f, " := {default_expr}")?;
5351        }
5352        Ok(())
5353    }
5354}
5355
5356#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
5357#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
5358#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
5359pub enum MacroDefinition {
5360    Expr(Expr),
5361    Table(Query),
5362}
5363
5364impl fmt::Display for MacroDefinition {
5365    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
5366        match self {
5367            MacroDefinition::Expr(expr) => write!(f, "{expr}")?,
5368            MacroDefinition::Table(query) => write!(f, "{query}")?,
5369        }
5370        Ok(())
5371    }
5372}
5373
5374/// Schema possible naming variants ([1]).
5375///
5376/// [1]: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#schema-definition
5377#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
5378#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
5379#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
5380pub enum SchemaName {
5381    /// Only schema name specified: `<schema name>`.
5382    Simple(ObjectName),
5383    /// Only authorization identifier specified: `AUTHORIZATION <schema authorization identifier>`.
5384    UnnamedAuthorization(Ident),
5385    /// Both schema name and authorization identifier specified: `<schema name>  AUTHORIZATION <schema authorization identifier>`.
5386    NamedAuthorization(ObjectName, Ident),
5387}
5388
5389impl fmt::Display for SchemaName {
5390    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
5391        match self {
5392            SchemaName::Simple(name) => {
5393                write!(f, "{name}")
5394            }
5395            SchemaName::UnnamedAuthorization(authorization) => {
5396                write!(f, "AUTHORIZATION {authorization}")
5397            }
5398            SchemaName::NamedAuthorization(name, authorization) => {
5399                write!(f, "{name} AUTHORIZATION {authorization}")
5400            }
5401        }
5402    }
5403}
5404
5405/// Fulltext search modifiers ([1]).
5406///
5407/// [1]: https://dev.mysql.com/doc/refman/8.0/en/fulltext-search.html#function_match
5408#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
5409#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
5410#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
5411pub enum SearchModifier {
5412    /// `IN NATURAL LANGUAGE MODE`.
5413    InNaturalLanguageMode,
5414    /// `IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION`.
5415    InNaturalLanguageModeWithQueryExpansion,
5416    ///`IN BOOLEAN MODE`.
5417    InBooleanMode,
5418    ///`WITH QUERY EXPANSION`.
5419    WithQueryExpansion,
5420}
5421
5422impl fmt::Display for SearchModifier {
5423    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
5424        match self {
5425            Self::InNaturalLanguageMode => {
5426                write!(f, "IN NATURAL LANGUAGE MODE")?;
5427            }
5428            Self::InNaturalLanguageModeWithQueryExpansion => {
5429                write!(f, "IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION")?;
5430            }
5431            Self::InBooleanMode => {
5432                write!(f, "IN BOOLEAN MODE")?;
5433            }
5434            Self::WithQueryExpansion => {
5435                write!(f, "WITH QUERY EXPANSION")?;
5436            }
5437        }
5438
5439        Ok(())
5440    }
5441}
5442
5443#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
5444#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
5445#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
5446pub struct LockTable {
5447    pub table: Ident,
5448    pub alias: Option<Ident>,
5449    pub lock_type: LockTableType,
5450}
5451
5452impl fmt::Display for LockTable {
5453    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
5454        let Self {
5455            table: tbl_name,
5456            alias,
5457            lock_type,
5458        } = self;
5459
5460        write!(f, "{tbl_name} ")?;
5461        if let Some(alias) = alias {
5462            write!(f, "AS {alias} ")?;
5463        }
5464        write!(f, "{lock_type}")?;
5465        Ok(())
5466    }
5467}
5468
5469#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
5470#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
5471#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
5472pub enum LockTableType {
5473    Read { local: bool },
5474    Write { low_priority: bool },
5475}
5476
5477impl fmt::Display for LockTableType {
5478    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
5479        match self {
5480            Self::Read { local } => {
5481                write!(f, "READ")?;
5482                if *local {
5483                    write!(f, " LOCAL")?;
5484                }
5485            }
5486            Self::Write { low_priority } => {
5487                if *low_priority {
5488                    write!(f, "LOW_PRIORITY ")?;
5489                }
5490                write!(f, "WRITE")?;
5491            }
5492        }
5493
5494        Ok(())
5495    }
5496}
5497
5498#[cfg(test)]
5499mod tests {
5500    use super::*;
5501
5502    #[test]
5503    fn test_window_frame_default() {
5504        let window_frame = WindowFrame::default();
5505        assert_eq!(WindowFrameBound::Preceding(None), window_frame.start_bound);
5506    }
5507
5508    #[test]
5509    fn test_grouping_sets_display() {
5510        // a and b in different group
5511        let grouping_sets = Expr::GroupingSets(vec![
5512            vec![Expr::Identifier(Ident::new("a"))],
5513            vec![Expr::Identifier(Ident::new("b"))],
5514        ]);
5515        assert_eq!("GROUPING SETS ((a), (b))", format!("{grouping_sets}"));
5516
5517        // a and b in the same group
5518        let grouping_sets = Expr::GroupingSets(vec![vec![
5519            Expr::Identifier(Ident::new("a")),
5520            Expr::Identifier(Ident::new("b")),
5521        ]]);
5522        assert_eq!("GROUPING SETS ((a, b))", format!("{grouping_sets}"));
5523
5524        // (a, b) and (c, d) in different group
5525        let grouping_sets = Expr::GroupingSets(vec![
5526            vec![
5527                Expr::Identifier(Ident::new("a")),
5528                Expr::Identifier(Ident::new("b")),
5529            ],
5530            vec![
5531                Expr::Identifier(Ident::new("c")),
5532                Expr::Identifier(Ident::new("d")),
5533            ],
5534        ]);
5535        assert_eq!("GROUPING SETS ((a, b), (c, d))", format!("{grouping_sets}"));
5536    }
5537
5538    #[test]
5539    fn test_rollup_display() {
5540        let rollup = Expr::Rollup(vec![vec![Expr::Identifier(Ident::new("a"))]]);
5541        assert_eq!("ROLLUP (a)", format!("{rollup}"));
5542
5543        let rollup = Expr::Rollup(vec![vec![
5544            Expr::Identifier(Ident::new("a")),
5545            Expr::Identifier(Ident::new("b")),
5546        ]]);
5547        assert_eq!("ROLLUP ((a, b))", format!("{rollup}"));
5548
5549        let rollup = Expr::Rollup(vec![
5550            vec![Expr::Identifier(Ident::new("a"))],
5551            vec![Expr::Identifier(Ident::new("b"))],
5552        ]);
5553        assert_eq!("ROLLUP (a, b)", format!("{rollup}"));
5554
5555        let rollup = Expr::Rollup(vec![
5556            vec![Expr::Identifier(Ident::new("a"))],
5557            vec![
5558                Expr::Identifier(Ident::new("b")),
5559                Expr::Identifier(Ident::new("c")),
5560            ],
5561            vec![Expr::Identifier(Ident::new("d"))],
5562        ]);
5563        assert_eq!("ROLLUP (a, (b, c), d)", format!("{rollup}"));
5564    }
5565
5566    #[test]
5567    fn test_cube_display() {
5568        let cube = Expr::Cube(vec![vec![Expr::Identifier(Ident::new("a"))]]);
5569        assert_eq!("CUBE (a)", format!("{cube}"));
5570
5571        let cube = Expr::Cube(vec![vec![
5572            Expr::Identifier(Ident::new("a")),
5573            Expr::Identifier(Ident::new("b")),
5574        ]]);
5575        assert_eq!("CUBE ((a, b))", format!("{cube}"));
5576
5577        let cube = Expr::Cube(vec![
5578            vec![Expr::Identifier(Ident::new("a"))],
5579            vec![Expr::Identifier(Ident::new("b"))],
5580        ]);
5581        assert_eq!("CUBE (a, b)", format!("{cube}"));
5582
5583        let cube = Expr::Cube(vec![
5584            vec![Expr::Identifier(Ident::new("a"))],
5585            vec![
5586                Expr::Identifier(Ident::new("b")),
5587                Expr::Identifier(Ident::new("c")),
5588            ],
5589            vec![Expr::Identifier(Ident::new("d"))],
5590        ]);
5591        assert_eq!("CUBE (a, (b, c), d)", format!("{cube}"));
5592    }
5593
5594    #[test]
5595    fn test_interval_display() {
5596        let interval = Expr::Interval(Interval {
5597            value: Box::new(Expr::Value(Value::SingleQuotedString(String::from(
5598                "123:45.67",
5599            )))),
5600            leading_field: Some(DateTimeField::Minute),
5601            leading_precision: Some(10),
5602            last_field: Some(DateTimeField::Second),
5603            fractional_seconds_precision: Some(9),
5604        });
5605        assert_eq!(
5606            "INTERVAL '123:45.67' MINUTE (10) TO SECOND (9)",
5607            format!("{interval}"),
5608        );
5609
5610        let interval = Expr::Interval(Interval {
5611            value: Box::new(Expr::Value(Value::SingleQuotedString(String::from("5")))),
5612            leading_field: Some(DateTimeField::Second),
5613            leading_precision: Some(1),
5614            last_field: None,
5615            fractional_seconds_precision: Some(3),
5616        });
5617        assert_eq!("INTERVAL '5' SECOND (1, 3)", format!("{interval}"));
5618    }
5619}