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    string::{String, ToString},
18    vec::Vec,
19};
20use core::fmt;
21
22#[cfg(feature = "serde")]
23use serde::{Deserialize, Serialize};
24
25#[cfg(feature = "visitor")]
26use sqlparser_derive::{Visit, VisitMut};
27
28pub use self::data_type::{
29    CharLengthUnits, CharacterLength, DataType, ExactNumberInfo, TimezoneInfo,
30};
31pub use self::ddl::{
32    AlterColumnOperation, AlterIndexOperation, AlterTableOperation, ColumnDef, ColumnOption,
33    ColumnOptionDef, GeneratedAs, IndexType, KeyOrIndexDisplay, ReferentialAction, TableConstraint,
34};
35pub use self::operator::{BinaryOperator, UnaryOperator};
36pub use self::query::{
37    Cte, ExceptSelectItem, ExcludeSelectItem, Fetch, IdentWithAlias, Join, JoinConstraint,
38    JoinOperator, LateralView, LockClause, LockType, NonBlock, Offset, OffsetRows, OrderByExpr,
39    Query, RenameSelectItem, ReplaceSelectElement, ReplaceSelectItem, Select, SelectInto,
40    SelectItem, SetExpr, SetOperator, SetQuantifier, Table, TableAlias, TableFactor,
41    TableWithJoins, Top, Values, WildcardAdditionalOptions, With,
42};
43pub use self::value::{
44    escape_quoted_string, DateTimeField, DollarQuotedString, TrimWhereField, Value,
45};
46
47#[cfg(feature = "visitor")]
48pub use visitor::*;
49
50mod data_type;
51mod ddl;
52pub mod helpers;
53mod operator;
54mod query;
55mod value;
56
57#[cfg(feature = "visitor")]
58mod visitor;
59
60struct DisplaySeparated<'a, T>
61where
62    T: fmt::Display,
63{
64    slice: &'a [T],
65    sep: &'static str,
66}
67
68impl<'a, T> fmt::Display for DisplaySeparated<'a, T>
69where
70    T: fmt::Display,
71{
72    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
73        let mut delim = "";
74        for t in self.slice {
75            write!(f, "{delim}")?;
76            delim = self.sep;
77            write!(f, "{t}")?;
78        }
79        Ok(())
80    }
81}
82
83fn display_separated<'a, T>(slice: &'a [T], sep: &'static str) -> DisplaySeparated<'a, T>
84where
85    T: fmt::Display,
86{
87    DisplaySeparated { slice, sep }
88}
89
90fn display_comma_separated<T>(slice: &[T]) -> DisplaySeparated<'_, T>
91where
92    T: fmt::Display,
93{
94    DisplaySeparated { slice, sep: ", " }
95}
96
97/// An identifier, decomposed into its value or character data and the quote style.
98#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
99#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
100#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
101pub struct Ident {
102    /// The value of the identifier without quotes.
103    pub value: String,
104    /// The starting quote if any. Valid quote characters are the single quote,
105    /// double quote, backtick, and opening square bracket.
106    pub quote_style: Option<char>,
107}
108
109impl Ident {
110    /// Create a new identifier with the given value and no quotes.
111    pub fn new<S>(value: S) -> Self
112    where
113        S: Into<String>,
114    {
115        Ident {
116            value: value.into(),
117            quote_style: None,
118        }
119    }
120
121    /// Create a new quoted identifier with the given quote and value. This function
122    /// panics if the given quote is not a valid quote character.
123    pub fn with_quote<S>(quote: char, value: S) -> Self
124    where
125        S: Into<String>,
126    {
127        assert!(quote == '\'' || quote == '"' || quote == '`' || quote == '[');
128        Ident {
129            value: value.into(),
130            quote_style: Some(quote),
131        }
132    }
133}
134
135impl From<&str> for Ident {
136    fn from(value: &str) -> Self {
137        Ident {
138            value: value.to_string(),
139            quote_style: None,
140        }
141    }
142}
143
144impl fmt::Display for Ident {
145    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
146        match self.quote_style {
147            Some(q) if q == '"' || q == '\'' || q == '`' => {
148                let escaped = value::escape_quoted_string(&self.value, q);
149                write!(f, "{q}{escaped}{q}")
150            }
151            Some(q) if q == '[' => write!(f, "[{}]", self.value),
152            None => f.write_str(&self.value),
153            _ => panic!("unexpected quote style"),
154        }
155    }
156}
157
158/// A name of a table, view, custom type, etc., possibly multi-part, i.e. db.schema.obj
159#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
160#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
161#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
162pub struct ObjectName(pub Vec<Ident>);
163
164impl fmt::Display for ObjectName {
165    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
166        write!(f, "{}", display_separated(&self.0, "."))
167    }
168}
169
170/// Represents an Array Expression, either
171/// `ARRAY[..]`, or `[..]`
172#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
173#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
174#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
175pub struct Array {
176    /// The list of expressions between brackets
177    pub elem: Vec<Expr>,
178
179    /// `true` for  `ARRAY[..]`, `false` for `[..]`
180    pub named: bool,
181}
182
183impl fmt::Display for Array {
184    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
185        write!(
186            f,
187            "{}[{}]",
188            if self.named { "ARRAY" } else { "" },
189            display_comma_separated(&self.elem)
190        )
191    }
192}
193
194/// JsonOperator
195#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
196#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
197#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
198pub enum JsonOperator {
199    /// -> keeps the value as json
200    Arrow,
201    /// ->> keeps the value as text or int.
202    LongArrow,
203    /// #> Extracts JSON sub-object at the specified path
204    HashArrow,
205    /// #>> Extracts JSON sub-object at the specified path as text
206    HashLongArrow,
207    /// : Colon is used by Snowflake (Which is similar to LongArrow)
208    Colon,
209    /// jsonb @> jsonb -> boolean: Test whether left json contains the right json
210    AtArrow,
211    /// jsonb <@ jsonb -> boolean: Test whether right json contains the left json
212    ArrowAt,
213    /// jsonb #- text[] -> jsonb: Deletes the field or array element at the specified
214    /// path, where path elements can be either field keys or array indexes.
215    HashMinus,
216    /// jsonb @? jsonpath -> boolean: Does JSON path return any item for the specified
217    /// JSON value?
218    AtQuestion,
219    /// jsonb @@ jsonpath → boolean: Returns the result of a JSON path predicate check
220    /// for the specified JSON value. Only the first item of the result is taken into
221    /// account. If the result is not Boolean, then NULL is returned.
222    AtAt,
223}
224
225impl fmt::Display for JsonOperator {
226    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
227        match self {
228            JsonOperator::Arrow => {
229                write!(f, "->")
230            }
231            JsonOperator::LongArrow => {
232                write!(f, "->>")
233            }
234            JsonOperator::HashArrow => {
235                write!(f, "#>")
236            }
237            JsonOperator::HashLongArrow => {
238                write!(f, "#>>")
239            }
240            JsonOperator::Colon => {
241                write!(f, ":")
242            }
243            JsonOperator::AtArrow => {
244                write!(f, "@>")
245            }
246            JsonOperator::ArrowAt => write!(f, "<@"),
247            JsonOperator::HashMinus => write!(f, "#-"),
248            JsonOperator::AtQuestion => write!(f, "@?"),
249            JsonOperator::AtAt => write!(f, "@@"),
250        }
251    }
252}
253
254/// An SQL expression of any type.
255///
256/// The parser does not distinguish between expressions of different types
257/// (e.g. boolean vs string), so the caller must handle expressions of
258/// inappropriate type, like `WHERE 1` or `SELECT 1=1`, as necessary.
259#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
260#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
261#[cfg_attr(
262    feature = "visitor",
263    derive(Visit, VisitMut),
264    visit(with = "visit_expr")
265)]
266pub enum Expr {
267    /// Identifier e.g. table name or column name
268    Identifier(Ident),
269    /// Multi-part identifier, e.g. `table_alias.column` or `schema.table.col`
270    CompoundIdentifier(Vec<Ident>),
271    /// JSON access (postgres)  eg: data->'tags'
272    JsonAccess {
273        left: Box<Expr>,
274        operator: JsonOperator,
275        right: Box<Expr>,
276    },
277    /// CompositeAccess (postgres) eg: SELECT (information_schema._pg_expandarray(array['i','i'])).n
278    CompositeAccess { expr: Box<Expr>, key: Ident },
279    /// `IS FALSE` operator
280    IsFalse(Box<Expr>),
281    /// `IS NOT FALSE` operator
282    IsNotFalse(Box<Expr>),
283    /// `IS TRUE` operator
284    IsTrue(Box<Expr>),
285    /// `IS NOT TRUE` operator
286    IsNotTrue(Box<Expr>),
287    /// `IS NULL` operator
288    IsNull(Box<Expr>),
289    /// `IS NOT NULL` operator
290    IsNotNull(Box<Expr>),
291    /// `IS UNKNOWN` operator
292    IsUnknown(Box<Expr>),
293    /// `IS NOT UNKNOWN` operator
294    IsNotUnknown(Box<Expr>),
295    /// `IS DISTINCT FROM` operator
296    IsDistinctFrom(Box<Expr>, Box<Expr>),
297    /// `IS NOT DISTINCT FROM` operator
298    IsNotDistinctFrom(Box<Expr>, Box<Expr>),
299    /// `[ NOT ] IN (val1, val2, ...)`
300    InList {
301        expr: Box<Expr>,
302        list: Vec<Expr>,
303        negated: bool,
304    },
305    /// `[ NOT ] IN (SELECT ...)`
306    InSubquery {
307        expr: Box<Expr>,
308        subquery: Box<Query>,
309        negated: bool,
310    },
311    /// `[ NOT ] IN UNNEST(array_expression)`
312    InUnnest {
313        expr: Box<Expr>,
314        array_expr: Box<Expr>,
315        negated: bool,
316    },
317    /// `<expr> [ NOT ] BETWEEN <low> AND <high>`
318    Between {
319        expr: Box<Expr>,
320        negated: bool,
321        low: Box<Expr>,
322        high: Box<Expr>,
323    },
324    /// Binary operation e.g. `1 + 1` or `foo > bar`
325    BinaryOp {
326        left: Box<Expr>,
327        op: BinaryOperator,
328        right: Box<Expr>,
329    },
330    /// LIKE
331    Like {
332        negated: bool,
333        expr: Box<Expr>,
334        pattern: Box<Expr>,
335        escape_char: Option<char>,
336    },
337    /// ILIKE (case-insensitive LIKE)
338    ILike {
339        negated: bool,
340        expr: Box<Expr>,
341        pattern: Box<Expr>,
342        escape_char: Option<char>,
343    },
344    /// SIMILAR TO regex
345    SimilarTo {
346        negated: bool,
347        expr: Box<Expr>,
348        pattern: Box<Expr>,
349        escape_char: Option<char>,
350    },
351    /// Any operation e.g. `1 ANY (1)` or `foo > ANY(bar)`, It will be wrapped in the right side of BinaryExpr
352    AnyOp(Box<Expr>),
353    /// ALL operation e.g. `1 ALL (1)` or `foo > ALL(bar)`, It will be wrapped in the right side of BinaryExpr
354    AllOp(Box<Expr>),
355    /// Unary operation e.g. `NOT foo`
356    UnaryOp { op: UnaryOperator, expr: Box<Expr> },
357    /// CAST an expression to a different data type e.g. `CAST(foo AS VARCHAR(123))`
358    Cast {
359        expr: Box<Expr>,
360        data_type: DataType,
361    },
362    /// TRY_CAST an expression to a different data type e.g. `TRY_CAST(foo AS VARCHAR(123))`
363    //  this differs from CAST in the choice of how to implement invalid conversions
364    TryCast {
365        expr: Box<Expr>,
366        data_type: DataType,
367    },
368    /// SAFE_CAST an expression to a different data type e.g. `SAFE_CAST(foo AS FLOAT64)`
369    //  only available for BigQuery: https://cloud.google.com/bigquery/docs/reference/standard-sql/functions-and-operators#safe_casting
370    //  this works the same as `TRY_CAST`
371    SafeCast {
372        expr: Box<Expr>,
373        data_type: DataType,
374    },
375    /// AT a timestamp to a different timezone e.g. `FROM_UNIXTIME(0) AT TIME ZONE 'UTC-06:00'`
376    AtTimeZone {
377        timestamp: Box<Expr>,
378        time_zone: String,
379    },
380    /// ```sql
381    /// EXTRACT(DateTimeField FROM <expr>)
382    /// ```
383    Extract {
384        field: DateTimeField,
385        expr: Box<Expr>,
386    },
387    /// ```sql
388    /// CEIL(<expr> [TO DateTimeField])
389    /// ```
390    Ceil {
391        expr: Box<Expr>,
392        field: DateTimeField,
393    },
394    /// ```sql
395    /// FLOOR(<expr> [TO DateTimeField])
396    /// ```
397    Floor {
398        expr: Box<Expr>,
399        field: DateTimeField,
400    },
401    /// ```sql
402    /// POSITION(<expr> in <expr>)
403    /// ```
404    Position { expr: Box<Expr>, r#in: Box<Expr> },
405    /// ```sql
406    /// SUBSTRING(<expr> [FROM <expr>] [FOR <expr>])
407    /// ```
408    Substring {
409        expr: Box<Expr>,
410        substring_from: Option<Box<Expr>>,
411        substring_for: Option<Box<Expr>>,
412    },
413    /// ```sql
414    /// TRIM([BOTH | LEADING | TRAILING] [<expr> FROM] <expr>)
415    /// TRIM(<expr>)
416    /// ```
417    Trim {
418        expr: Box<Expr>,
419        // ([BOTH | LEADING | TRAILING]
420        trim_where: Option<TrimWhereField>,
421        trim_what: Option<Box<Expr>>,
422    },
423    /// ```sql
424    /// OVERLAY(<expr> PLACING <expr> FROM <expr>[ FOR <expr> ]
425    /// ```
426    Overlay {
427        expr: Box<Expr>,
428        overlay_what: Box<Expr>,
429        overlay_from: Box<Expr>,
430        overlay_for: Option<Box<Expr>>,
431    },
432    /// `expr COLLATE collation`
433    Collate {
434        expr: Box<Expr>,
435        collation: ObjectName,
436    },
437    /// Nested expression e.g. `(foo > bar)` or `(1)`
438    Nested(Box<Expr>),
439    /// A literal value, such as string, number, date or NULL
440    Value(Value),
441    /// <https://dev.mysql.com/doc/refman/8.0/en/charset-introducer.html>
442    IntroducedString { introducer: String, value: Value },
443    /// A constant of form `<data_type> 'value'`.
444    /// This can represent ANSI SQL `DATE`, `TIME`, and `TIMESTAMP` literals (such as `DATE '2020-01-01'`),
445    /// as well as constants of other types (a non-standard PostgreSQL extension).
446    TypedString { data_type: DataType, value: String },
447    /// Access a map-like object by field (e.g. `column['field']` or `column[4]`
448    /// Note that depending on the dialect, struct like accesses may be
449    /// parsed as [`ArrayIndex`](Self::ArrayIndex) or [`MapAccess`](Self::MapAccess)
450    /// <https://clickhouse.com/docs/en/sql-reference/data-types/map/>
451    MapAccess { column: Box<Expr>, keys: Vec<Expr> },
452    /// Scalar function call e.g. `LEFT(foo, 5)`
453    Function(Function),
454    /// Aggregate function with filter
455    AggregateExpressionWithFilter { expr: Box<Expr>, filter: Box<Expr> },
456    /// `CASE [<operand>] WHEN <condition> THEN <result> ... [ELSE <result>] END`
457    ///
458    /// Note we only recognize a complete single expression as `<condition>`,
459    /// not `< 0` nor `1, 2, 3` as allowed in a `<simple when clause>` per
460    /// <https://jakewheat.github.io/sql-overview/sql-2011-foundation-grammar.html#simple-when-clause>
461    Case {
462        operand: Option<Box<Expr>>,
463        conditions: Vec<Expr>,
464        results: Vec<Expr>,
465        else_result: Option<Box<Expr>>,
466    },
467    /// An exists expression `[ NOT ] EXISTS(SELECT ...)`, used in expressions like
468    /// `WHERE [ NOT ] EXISTS (SELECT ...)`.
469    Exists { subquery: Box<Query>, negated: bool },
470    /// A parenthesized subquery `(SELECT ...)`, used in expression like
471    /// `SELECT (subquery) AS x` or `WHERE (subquery) = x`
472    Subquery(Box<Query>),
473    /// An array subquery constructor, e.g. `SELECT ARRAY(SELECT 1 UNION SELECT 2)`
474    ArraySubquery(Box<Query>),
475    /// The `LISTAGG` function `SELECT LISTAGG(...) WITHIN GROUP (ORDER BY ...)`
476    ListAgg(ListAgg),
477    /// The `ARRAY_AGG` function `SELECT ARRAY_AGG(... ORDER BY ...)`
478    ArrayAgg(ArrayAgg),
479    /// The `GROUPING SETS` expr.
480    GroupingSets(Vec<Vec<Expr>>),
481    /// The `CUBE` expr.
482    Cube(Vec<Vec<Expr>>),
483    /// The `ROLLUP` expr.
484    Rollup(Vec<Vec<Expr>>),
485    /// ROW / TUPLE a single value, such as `SELECT (1, 2)`
486    Tuple(Vec<Expr>),
487    /// An array index expression e.g. `(ARRAY[1, 2])[1]` or `(current_schemas(FALSE))[1]`
488    ArrayIndex { obj: Box<Expr>, indexes: Vec<Expr> },
489    /// An array expression e.g. `ARRAY[1, 2]`
490    Array(Array),
491    /// INTERVAL literals, roughly in the following format:
492    /// `INTERVAL '<value>' [ <leading_field> [ (<leading_precision>) ] ]
493    /// [ TO <last_field> [ (<fractional_seconds_precision>) ] ]`,
494    /// e.g. `INTERVAL '123:45.67' MINUTE(3) TO SECOND(2)`.
495    ///
496    /// The parser does not validate the `<value>`, nor does it ensure
497    /// that the `<leading_field>` units >= the units in `<last_field>`,
498    /// so the user will have to reject intervals like `HOUR TO YEAR`.
499    Interval {
500        value: Box<Expr>,
501        leading_field: Option<DateTimeField>,
502        leading_precision: Option<u64>,
503        last_field: Option<DateTimeField>,
504        /// The seconds precision can be specified in SQL source as
505        /// `INTERVAL '__' SECOND(_, x)` (in which case the `leading_field`
506        /// will be `Second` and the `last_field` will be `None`),
507        /// or as `__ TO SECOND(x)`.
508        fractional_seconds_precision: Option<u64>,
509    },
510    /// `MySQL` specific text search function [(1)].
511    ///
512    /// Syntax:
513    /// ```sql
514    /// MARCH (<col>, <col>, ...) AGAINST (<expr> [<search modifier>])
515    ///
516    /// <col> = CompoundIdentifier
517    /// <expr> = String literal
518    /// ```
519    ///
520    ///
521    /// [(1)]: https://dev.mysql.com/doc/refman/8.0/en/fulltext-search.html#function_match
522    MatchAgainst {
523        /// `(<col>, <col>, ...)`.
524        columns: Vec<Ident>,
525        /// `<expr>`.
526        match_value: Value,
527        /// `<search modifier>`
528        opt_search_modifier: Option<SearchModifier>,
529    },
530}
531
532impl fmt::Display for Expr {
533    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
534        match self {
535            Expr::Identifier(s) => write!(f, "{s}"),
536            Expr::MapAccess { column, keys } => {
537                write!(f, "{column}")?;
538                for k in keys {
539                    match k {
540                        k @ Expr::Value(Value::Number(_, _)) => write!(f, "[{k}]")?,
541                        Expr::Value(Value::SingleQuotedString(s)) => write!(f, "[\"{s}\"]")?,
542                        _ => write!(f, "[{k}]")?,
543                    }
544                }
545                Ok(())
546            }
547            Expr::CompoundIdentifier(s) => write!(f, "{}", display_separated(s, ".")),
548            Expr::IsTrue(ast) => write!(f, "{ast} IS TRUE"),
549            Expr::IsNotTrue(ast) => write!(f, "{ast} IS NOT TRUE"),
550            Expr::IsFalse(ast) => write!(f, "{ast} IS FALSE"),
551            Expr::IsNotFalse(ast) => write!(f, "{ast} IS NOT FALSE"),
552            Expr::IsNull(ast) => write!(f, "{ast} IS NULL"),
553            Expr::IsNotNull(ast) => write!(f, "{ast} IS NOT NULL"),
554            Expr::IsUnknown(ast) => write!(f, "{ast} IS UNKNOWN"),
555            Expr::IsNotUnknown(ast) => write!(f, "{ast} IS NOT UNKNOWN"),
556            Expr::InList {
557                expr,
558                list,
559                negated,
560            } => write!(
561                f,
562                "{} {}IN ({})",
563                expr,
564                if *negated { "NOT " } else { "" },
565                display_comma_separated(list)
566            ),
567            Expr::InSubquery {
568                expr,
569                subquery,
570                negated,
571            } => write!(
572                f,
573                "{} {}IN ({})",
574                expr,
575                if *negated { "NOT " } else { "" },
576                subquery
577            ),
578            Expr::InUnnest {
579                expr,
580                array_expr,
581                negated,
582            } => write!(
583                f,
584                "{} {}IN UNNEST({})",
585                expr,
586                if *negated { "NOT " } else { "" },
587                array_expr
588            ),
589            Expr::Between {
590                expr,
591                negated,
592                low,
593                high,
594            } => write!(
595                f,
596                "{} {}BETWEEN {} AND {}",
597                expr,
598                if *negated { "NOT " } else { "" },
599                low,
600                high
601            ),
602            Expr::BinaryOp { left, op, right } => write!(f, "{left} {op} {right}"),
603            Expr::Like {
604                negated,
605                expr,
606                pattern,
607                escape_char,
608            } => match escape_char {
609                Some(ch) => write!(
610                    f,
611                    "{} {}LIKE {} ESCAPE '{}'",
612                    expr,
613                    if *negated { "NOT " } else { "" },
614                    pattern,
615                    ch
616                ),
617                _ => write!(
618                    f,
619                    "{} {}LIKE {}",
620                    expr,
621                    if *negated { "NOT " } else { "" },
622                    pattern
623                ),
624            },
625            Expr::ILike {
626                negated,
627                expr,
628                pattern,
629                escape_char,
630            } => match escape_char {
631                Some(ch) => write!(
632                    f,
633                    "{} {}ILIKE {} ESCAPE '{}'",
634                    expr,
635                    if *negated { "NOT " } else { "" },
636                    pattern,
637                    ch
638                ),
639                _ => write!(
640                    f,
641                    "{} {}ILIKE {}",
642                    expr,
643                    if *negated { "NOT " } else { "" },
644                    pattern
645                ),
646            },
647            Expr::SimilarTo {
648                negated,
649                expr,
650                pattern,
651                escape_char,
652            } => match escape_char {
653                Some(ch) => write!(
654                    f,
655                    "{} {}SIMILAR TO {} ESCAPE '{}'",
656                    expr,
657                    if *negated { "NOT " } else { "" },
658                    pattern,
659                    ch
660                ),
661                _ => write!(
662                    f,
663                    "{} {}SIMILAR TO {}",
664                    expr,
665                    if *negated { "NOT " } else { "" },
666                    pattern
667                ),
668            },
669            Expr::AnyOp(expr) => write!(f, "ANY({expr})"),
670            Expr::AllOp(expr) => write!(f, "ALL({expr})"),
671            Expr::UnaryOp { op, expr } => {
672                if op == &UnaryOperator::PGPostfixFactorial {
673                    write!(f, "{expr}{op}")
674                } else if op == &UnaryOperator::Not {
675                    write!(f, "{op} {expr}")
676                } else {
677                    write!(f, "{op}{expr}")
678                }
679            }
680            Expr::Cast { expr, data_type } => write!(f, "CAST({expr} AS {data_type})"),
681            Expr::TryCast { expr, data_type } => write!(f, "TRY_CAST({expr} AS {data_type})"),
682            Expr::SafeCast { expr, data_type } => write!(f, "SAFE_CAST({expr} AS {data_type})"),
683            Expr::Extract { field, expr } => write!(f, "EXTRACT({field} FROM {expr})"),
684            Expr::Ceil { expr, field } => {
685                if field == &DateTimeField::NoDateTime {
686                    write!(f, "CEIL({expr})")
687                } else {
688                    write!(f, "CEIL({expr} TO {field})")
689                }
690            }
691            Expr::Floor { expr, field } => {
692                if field == &DateTimeField::NoDateTime {
693                    write!(f, "FLOOR({expr})")
694                } else {
695                    write!(f, "FLOOR({expr} TO {field})")
696                }
697            }
698            Expr::Position { expr, r#in } => write!(f, "POSITION({expr} IN {in})"),
699            Expr::Collate { expr, collation } => write!(f, "{expr} COLLATE {collation}"),
700            Expr::Nested(ast) => write!(f, "({ast})"),
701            Expr::Value(v) => write!(f, "{v}"),
702            Expr::IntroducedString { introducer, value } => write!(f, "{introducer} {value}"),
703            Expr::TypedString { data_type, value } => {
704                write!(f, "{data_type}")?;
705                write!(f, " '{}'", &value::escape_single_quote_string(value))
706            }
707            Expr::Function(fun) => write!(f, "{fun}"),
708            Expr::AggregateExpressionWithFilter { expr, filter } => {
709                write!(f, "{expr} FILTER (WHERE {filter})")
710            }
711            Expr::Case {
712                operand,
713                conditions,
714                results,
715                else_result,
716            } => {
717                write!(f, "CASE")?;
718                if let Some(operand) = operand {
719                    write!(f, " {operand}")?;
720                }
721                for (c, r) in conditions.iter().zip(results) {
722                    write!(f, " WHEN {c} THEN {r}")?;
723                }
724
725                if let Some(else_result) = else_result {
726                    write!(f, " ELSE {else_result}")?;
727                }
728                write!(f, " END")
729            }
730            Expr::Exists { subquery, negated } => write!(
731                f,
732                "{}EXISTS ({})",
733                if *negated { "NOT " } else { "" },
734                subquery
735            ),
736            Expr::Subquery(s) => write!(f, "({s})"),
737            Expr::ArraySubquery(s) => write!(f, "ARRAY({s})"),
738            Expr::ListAgg(listagg) => write!(f, "{listagg}"),
739            Expr::ArrayAgg(arrayagg) => write!(f, "{arrayagg}"),
740            Expr::GroupingSets(sets) => {
741                write!(f, "GROUPING SETS (")?;
742                let mut sep = "";
743                for set in sets {
744                    write!(f, "{sep}")?;
745                    sep = ", ";
746                    write!(f, "({})", display_comma_separated(set))?;
747                }
748                write!(f, ")")
749            }
750            Expr::Cube(sets) => {
751                write!(f, "CUBE (")?;
752                let mut sep = "";
753                for set in sets {
754                    write!(f, "{sep}")?;
755                    sep = ", ";
756                    if set.len() == 1 {
757                        write!(f, "{}", set[0])?;
758                    } else {
759                        write!(f, "({})", display_comma_separated(set))?;
760                    }
761                }
762                write!(f, ")")
763            }
764            Expr::Rollup(sets) => {
765                write!(f, "ROLLUP (")?;
766                let mut sep = "";
767                for set in sets {
768                    write!(f, "{sep}")?;
769                    sep = ", ";
770                    if set.len() == 1 {
771                        write!(f, "{}", set[0])?;
772                    } else {
773                        write!(f, "({})", display_comma_separated(set))?;
774                    }
775                }
776                write!(f, ")")
777            }
778            Expr::Substring {
779                expr,
780                substring_from,
781                substring_for,
782            } => {
783                write!(f, "SUBSTRING({expr}")?;
784                if let Some(from_part) = substring_from {
785                    write!(f, " FROM {from_part}")?;
786                }
787                if let Some(for_part) = substring_for {
788                    write!(f, " FOR {for_part}")?;
789                }
790
791                write!(f, ")")
792            }
793            Expr::Overlay {
794                expr,
795                overlay_what,
796                overlay_from,
797                overlay_for,
798            } => {
799                write!(
800                    f,
801                    "OVERLAY({expr} PLACING {overlay_what} FROM {overlay_from}"
802                )?;
803                if let Some(for_part) = overlay_for {
804                    write!(f, " FOR {for_part}")?;
805                }
806
807                write!(f, ")")
808            }
809            Expr::IsDistinctFrom(a, b) => write!(f, "{a} IS DISTINCT FROM {b}"),
810            Expr::IsNotDistinctFrom(a, b) => write!(f, "{a} IS NOT DISTINCT FROM {b}"),
811            Expr::Trim {
812                expr,
813                trim_where,
814                trim_what,
815            } => {
816                write!(f, "TRIM(")?;
817                if let Some(ident) = trim_where {
818                    write!(f, "{ident} ")?;
819                }
820                if let Some(trim_char) = trim_what {
821                    write!(f, "{trim_char} FROM {expr}")?;
822                } else {
823                    write!(f, "{expr}")?;
824                }
825
826                write!(f, ")")
827            }
828            Expr::Tuple(exprs) => {
829                write!(f, "({})", display_comma_separated(exprs))
830            }
831            Expr::ArrayIndex { obj, indexes } => {
832                write!(f, "{obj}")?;
833                for i in indexes {
834                    write!(f, "[{i}]")?;
835                }
836                Ok(())
837            }
838            Expr::Array(set) => {
839                write!(f, "{set}")
840            }
841            Expr::JsonAccess {
842                left,
843                operator,
844                right,
845            } => {
846                if operator == &JsonOperator::Colon {
847                    write!(f, "{left}{operator}{right}")
848                } else {
849                    write!(f, "{left} {operator} {right}")
850                }
851            }
852            Expr::CompositeAccess { expr, key } => {
853                write!(f, "{expr}.{key}")
854            }
855            Expr::AtTimeZone {
856                timestamp,
857                time_zone,
858            } => {
859                write!(f, "{timestamp} AT TIME ZONE '{time_zone}'")
860            }
861            Expr::Interval {
862                value,
863                leading_field: Some(DateTimeField::Second),
864                leading_precision: Some(leading_precision),
865                last_field,
866                fractional_seconds_precision: Some(fractional_seconds_precision),
867            } => {
868                // When the leading field is SECOND, the parser guarantees that
869                // the last field is None.
870                assert!(last_field.is_none());
871                write!(
872                    f,
873                    "INTERVAL {value} SECOND ({leading_precision}, {fractional_seconds_precision})"
874                )
875            }
876            Expr::Interval {
877                value,
878                leading_field,
879                leading_precision,
880                last_field,
881                fractional_seconds_precision,
882            } => {
883                write!(f, "INTERVAL {value}")?;
884                if let Some(leading_field) = leading_field {
885                    write!(f, " {leading_field}")?;
886                }
887                if let Some(leading_precision) = leading_precision {
888                    write!(f, " ({leading_precision})")?;
889                }
890                if let Some(last_field) = last_field {
891                    write!(f, " TO {last_field}")?;
892                }
893                if let Some(fractional_seconds_precision) = fractional_seconds_precision {
894                    write!(f, " ({fractional_seconds_precision})")?;
895                }
896                Ok(())
897            }
898            Expr::MatchAgainst {
899                columns,
900                match_value: match_expr,
901                opt_search_modifier,
902            } => {
903                write!(f, "MATCH ({}) AGAINST ", display_comma_separated(columns),)?;
904
905                if let Some(search_modifier) = opt_search_modifier {
906                    write!(f, "({match_expr} {search_modifier})")?;
907                } else {
908                    write!(f, "({match_expr})")?;
909                }
910
911                Ok(())
912            }
913        }
914    }
915}
916
917/// A window specification (i.e. `OVER (PARTITION BY .. ORDER BY .. etc.)`)
918#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
919#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
920#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
921pub struct WindowSpec {
922    pub partition_by: Vec<Expr>,
923    pub order_by: Vec<OrderByExpr>,
924    pub window_frame: Option<WindowFrame>,
925}
926
927impl fmt::Display for WindowSpec {
928    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
929        let mut delim = "";
930        if !self.partition_by.is_empty() {
931            delim = " ";
932            write!(
933                f,
934                "PARTITION BY {}",
935                display_comma_separated(&self.partition_by)
936            )?;
937        }
938        if !self.order_by.is_empty() {
939            f.write_str(delim)?;
940            delim = " ";
941            write!(f, "ORDER BY {}", display_comma_separated(&self.order_by))?;
942        }
943        if let Some(window_frame) = &self.window_frame {
944            f.write_str(delim)?;
945            if let Some(end_bound) = &window_frame.end_bound {
946                write!(
947                    f,
948                    "{} BETWEEN {} AND {}",
949                    window_frame.units, window_frame.start_bound, end_bound
950                )?;
951            } else {
952                write!(f, "{} {}", window_frame.units, window_frame.start_bound)?;
953            }
954        }
955        Ok(())
956    }
957}
958
959/// Specifies the data processed by a window function, e.g.
960/// `RANGE UNBOUNDED PRECEDING` or `ROWS BETWEEN 5 PRECEDING AND CURRENT ROW`.
961///
962/// Note: The parser does not validate the specified bounds; the caller should
963/// reject invalid bounds like `ROWS UNBOUNDED FOLLOWING` before execution.
964#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
965#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
966#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
967pub struct WindowFrame {
968    pub units: WindowFrameUnits,
969    pub start_bound: WindowFrameBound,
970    /// The right bound of the `BETWEEN .. AND` clause. The end bound of `None`
971    /// indicates the shorthand form (e.g. `ROWS 1 PRECEDING`), which must
972    /// behave the same as `end_bound = WindowFrameBound::CurrentRow`.
973    pub end_bound: Option<WindowFrameBound>,
974    // TBD: EXCLUDE
975}
976
977impl Default for WindowFrame {
978    /// Returns default value for window frame
979    ///
980    /// See [this page](https://www.sqlite.org/windowfunctions.html#frame_specifications) for more details.
981    fn default() -> Self {
982        Self {
983            units: WindowFrameUnits::Range,
984            start_bound: WindowFrameBound::Preceding(None),
985            end_bound: None,
986        }
987    }
988}
989
990#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
991#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
992#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
993pub enum WindowFrameUnits {
994    Rows,
995    Range,
996    Groups,
997}
998
999impl fmt::Display for WindowFrameUnits {
1000    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1001        f.write_str(match self {
1002            WindowFrameUnits::Rows => "ROWS",
1003            WindowFrameUnits::Range => "RANGE",
1004            WindowFrameUnits::Groups => "GROUPS",
1005        })
1006    }
1007}
1008
1009/// Specifies [WindowFrame]'s `start_bound` and `end_bound`
1010#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1011#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1012#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1013pub enum WindowFrameBound {
1014    /// `CURRENT ROW`
1015    CurrentRow,
1016    /// `<N> PRECEDING` or `UNBOUNDED PRECEDING`
1017    Preceding(Option<Box<Expr>>),
1018    /// `<N> FOLLOWING` or `UNBOUNDED FOLLOWING`.
1019    Following(Option<Box<Expr>>),
1020}
1021
1022impl fmt::Display for WindowFrameBound {
1023    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1024        match self {
1025            WindowFrameBound::CurrentRow => f.write_str("CURRENT ROW"),
1026            WindowFrameBound::Preceding(None) => f.write_str("UNBOUNDED PRECEDING"),
1027            WindowFrameBound::Following(None) => f.write_str("UNBOUNDED FOLLOWING"),
1028            WindowFrameBound::Preceding(Some(n)) => write!(f, "{n} PRECEDING"),
1029            WindowFrameBound::Following(Some(n)) => write!(f, "{n} FOLLOWING"),
1030        }
1031    }
1032}
1033
1034#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1035#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1036#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1037pub enum AddDropSync {
1038    ADD,
1039    DROP,
1040    SYNC,
1041}
1042
1043impl fmt::Display for AddDropSync {
1044    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1045        match self {
1046            AddDropSync::SYNC => f.write_str("SYNC PARTITIONS"),
1047            AddDropSync::DROP => f.write_str("DROP PARTITIONS"),
1048            AddDropSync::ADD => f.write_str("ADD PARTITIONS"),
1049        }
1050    }
1051}
1052
1053#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1054#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1055#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1056pub enum ShowCreateObject {
1057    Event,
1058    Function,
1059    Procedure,
1060    Table,
1061    Trigger,
1062    View,
1063}
1064
1065impl fmt::Display for ShowCreateObject {
1066    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1067        match self {
1068            ShowCreateObject::Event => f.write_str("EVENT"),
1069            ShowCreateObject::Function => f.write_str("FUNCTION"),
1070            ShowCreateObject::Procedure => f.write_str("PROCEDURE"),
1071            ShowCreateObject::Table => f.write_str("TABLE"),
1072            ShowCreateObject::Trigger => f.write_str("TRIGGER"),
1073            ShowCreateObject::View => f.write_str("VIEW"),
1074        }
1075    }
1076}
1077
1078#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1079#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1080#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1081pub enum CommentObject {
1082    Column,
1083    Table,
1084}
1085
1086impl fmt::Display for CommentObject {
1087    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1088        match self {
1089            CommentObject::Column => f.write_str("COLUMN"),
1090            CommentObject::Table => f.write_str("TABLE"),
1091        }
1092    }
1093}
1094
1095#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1096#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1097#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1098pub enum Password {
1099    Password(Expr),
1100    NullPassword,
1101}
1102
1103/// A top-level statement (SELECT, INSERT, CREATE, etc.)
1104#[allow(clippy::large_enum_variant)]
1105#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1106#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1107#[cfg_attr(
1108    feature = "visitor",
1109    derive(Visit, VisitMut),
1110    visit(with = "visit_statement")
1111)]
1112pub enum Statement {
1113    /// Analyze (Hive)
1114    Analyze {
1115        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
1116        table_name: ObjectName,
1117        partitions: Option<Vec<Expr>>,
1118        for_columns: bool,
1119        columns: Vec<Ident>,
1120        cache_metadata: bool,
1121        noscan: bool,
1122        compute_statistics: bool,
1123    },
1124    /// Truncate (Hive)
1125    Truncate {
1126        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
1127        table_name: ObjectName,
1128        partitions: Option<Vec<Expr>>,
1129    },
1130    /// Msck (Hive)
1131    Msck {
1132        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
1133        table_name: ObjectName,
1134        repair: bool,
1135        partition_action: Option<AddDropSync>,
1136    },
1137    /// SELECT
1138    Query(Box<Query>),
1139    /// INSERT
1140    Insert {
1141        /// Only for Sqlite
1142        or: Option<SqliteOnConflict>,
1143        /// INTO - optional keyword
1144        into: bool,
1145        /// TABLE
1146        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
1147        table_name: ObjectName,
1148        /// COLUMNS
1149        columns: Vec<Ident>,
1150        /// Overwrite (Hive)
1151        overwrite: bool,
1152        /// A SQL query that specifies what to insert
1153        source: Box<Query>,
1154        /// partitioned insert (Hive)
1155        partitioned: Option<Vec<Expr>>,
1156        /// Columns defined after PARTITION
1157        after_columns: Vec<Ident>,
1158        /// whether the insert has the table keyword (Hive)
1159        table: bool,
1160        on: Option<OnInsert>,
1161        /// RETURNING
1162        returning: Option<Vec<SelectItem>>,
1163    },
1164    // TODO: Support ROW FORMAT
1165    Directory {
1166        overwrite: bool,
1167        local: bool,
1168        path: String,
1169        file_format: Option<FileFormat>,
1170        source: Box<Query>,
1171    },
1172    Copy {
1173        /// TABLE
1174        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
1175        table_name: ObjectName,
1176        /// COLUMNS
1177        columns: Vec<Ident>,
1178        /// If true, is a 'COPY TO' statement. If false is a 'COPY FROM'
1179        to: bool,
1180        /// The source of 'COPY FROM', or the target of 'COPY TO'
1181        target: CopyTarget,
1182        /// WITH options (from PostgreSQL version 9.0)
1183        options: Vec<CopyOption>,
1184        /// WITH options (before PostgreSQL version 9.0)
1185        legacy_options: Vec<CopyLegacyOption>,
1186        /// VALUES a vector of values to be copied
1187        values: Vec<Option<String>>,
1188    },
1189    /// Close - closes the portal underlying an open cursor.
1190    Close {
1191        /// Cursor name
1192        cursor: CloseCursor,
1193    },
1194    /// UPDATE
1195    Update {
1196        /// TABLE
1197        table: TableWithJoins,
1198        /// Column assignments
1199        assignments: Vec<Assignment>,
1200        /// Table which provide value to be set
1201        from: Option<TableWithJoins>,
1202        /// WHERE
1203        selection: Option<Expr>,
1204        /// RETURNING
1205        returning: Option<Vec<SelectItem>>,
1206    },
1207    /// DELETE
1208    Delete {
1209        /// FROM
1210        table_name: TableFactor,
1211        /// USING (Snowflake, Postgres)
1212        using: Option<TableFactor>,
1213        /// WHERE
1214        selection: Option<Expr>,
1215        /// RETURNING
1216        returning: Option<Vec<SelectItem>>,
1217    },
1218    /// CREATE VIEW
1219    CreateView {
1220        or_replace: bool,
1221        materialized: bool,
1222        /// View name
1223        name: ObjectName,
1224        columns: Vec<Ident>,
1225        query: Box<Query>,
1226        with_options: Vec<SqlOption>,
1227        cluster_by: Vec<Ident>,
1228    },
1229    /// CREATE TABLE
1230    CreateTable {
1231        or_replace: bool,
1232        temporary: bool,
1233        external: bool,
1234        global: Option<bool>,
1235        if_not_exists: bool,
1236        transient: bool,
1237        /// Table name
1238        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
1239        name: ObjectName,
1240        /// Optional schema
1241        columns: Vec<ColumnDef>,
1242        constraints: Vec<TableConstraint>,
1243        hive_distribution: HiveDistributionStyle,
1244        hive_formats: Option<HiveFormat>,
1245        table_properties: Vec<SqlOption>,
1246        with_options: Vec<SqlOption>,
1247        file_format: Option<FileFormat>,
1248        location: Option<String>,
1249        query: Option<Box<Query>>,
1250        without_rowid: bool,
1251        like: Option<ObjectName>,
1252        clone: Option<ObjectName>,
1253        engine: Option<String>,
1254        default_charset: Option<String>,
1255        collation: Option<String>,
1256        on_commit: Option<OnCommit>,
1257        /// ClickHouse "ON CLUSTER" clause:
1258        /// <https://clickhouse.com/docs/en/sql-reference/distributed-ddl/>
1259        on_cluster: Option<String>,
1260        /// ClickHouse "ORDER BY " clause. Note that omitted ORDER BY is different
1261        /// than empty (represented as ()), the latter meaning "no sorting".
1262        /// <https://clickhouse.com/docs/en/sql-reference/statements/create/table/>
1263        order_by: Option<Vec<Ident>>,
1264    },
1265    /// SQLite's `CREATE VIRTUAL TABLE .. USING <module_name> (<module_args>)`
1266    CreateVirtualTable {
1267        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
1268        name: ObjectName,
1269        if_not_exists: bool,
1270        module_name: Ident,
1271        module_args: Vec<Ident>,
1272    },
1273    /// CREATE INDEX
1274    CreateIndex {
1275        /// index name
1276        name: ObjectName,
1277        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
1278        table_name: ObjectName,
1279        using: Option<Ident>,
1280        columns: Vec<OrderByExpr>,
1281        unique: bool,
1282        if_not_exists: bool,
1283    },
1284    /// CREATE ROLE
1285    /// See [postgres](https://www.postgresql.org/docs/current/sql-createrole.html)
1286    CreateRole {
1287        names: Vec<ObjectName>,
1288        if_not_exists: bool,
1289        // Postgres
1290        login: Option<bool>,
1291        inherit: Option<bool>,
1292        bypassrls: Option<bool>,
1293        password: Option<Password>,
1294        superuser: Option<bool>,
1295        create_db: Option<bool>,
1296        create_role: Option<bool>,
1297        replication: Option<bool>,
1298        connection_limit: Option<Expr>,
1299        valid_until: Option<Expr>,
1300        in_role: Vec<Ident>,
1301        in_group: Vec<Ident>,
1302        role: Vec<Ident>,
1303        user: Vec<Ident>,
1304        admin: Vec<Ident>,
1305        // MSSQL
1306        authorization_owner: Option<ObjectName>,
1307    },
1308    /// ALTER TABLE
1309    AlterTable {
1310        /// Table name
1311        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
1312        name: ObjectName,
1313        operation: AlterTableOperation,
1314    },
1315    AlterIndex {
1316        name: ObjectName,
1317        operation: AlterIndexOperation,
1318    },
1319    /// DROP
1320    Drop {
1321        /// The type of the object to drop: TABLE, VIEW, etc.
1322        object_type: ObjectType,
1323        /// An optional `IF EXISTS` clause. (Non-standard.)
1324        if_exists: bool,
1325        /// One or more objects to drop. (ANSI SQL requires exactly one.)
1326        names: Vec<ObjectName>,
1327        /// Whether `CASCADE` was specified. This will be `false` when
1328        /// `RESTRICT` or no drop behavior at all was specified.
1329        cascade: bool,
1330        /// Whether `RESTRICT` was specified. This will be `false` when
1331        /// `CASCADE` or no drop behavior at all was specified.
1332        restrict: bool,
1333        /// Hive allows you specify whether the table's stored data will be
1334        /// deleted along with the dropped table
1335        purge: bool,
1336    },
1337    /// DROP Function
1338    DropFunction {
1339        if_exists: bool,
1340        /// One or more function to drop
1341        func_desc: Vec<DropFunctionDesc>,
1342        /// `CASCADE` or `RESTRICT`
1343        option: Option<ReferentialAction>,
1344    },
1345    /// DECLARE - Declaring Cursor Variables
1346    ///
1347    /// Note: this is a PostgreSQL-specific statement,
1348    /// but may also compatible with other SQL.
1349    Declare {
1350        /// Cursor name
1351        name: Ident,
1352        /// Causes the cursor to return data in binary rather than in text format.
1353        binary: bool,
1354        /// None = Not specified
1355        /// Some(true) = INSENSITIVE
1356        /// Some(false) = ASENSITIVE
1357        sensitive: Option<bool>,
1358        /// None = Not specified
1359        /// Some(true) = SCROLL
1360        /// Some(false) = NO SCROLL
1361        scroll: Option<bool>,
1362        /// None = Not specified
1363        /// Some(true) = WITH HOLD, specifies that the cursor can continue to be used after the transaction that created it successfully commits
1364        /// Some(false) = WITHOUT HOLD, specifies that the cursor cannot be used outside of the transaction that created it
1365        hold: Option<bool>,
1366        query: Box<Query>,
1367    },
1368    /// FETCH - retrieve rows from a query using a cursor
1369    ///
1370    /// Note: this is a PostgreSQL-specific statement,
1371    /// but may also compatible with other SQL.
1372    Fetch {
1373        /// Cursor name
1374        name: Ident,
1375        direction: FetchDirection,
1376        /// Optional, It's possible to fetch rows form cursor to the table
1377        into: Option<ObjectName>,
1378    },
1379    /// DISCARD [ ALL | PLANS | SEQUENCES | TEMPORARY | TEMP ]
1380    ///
1381    /// Note: this is a PostgreSQL-specific statement,
1382    /// but may also compatible with other SQL.
1383    Discard { object_type: DiscardObject },
1384    /// SET `[ SESSION | LOCAL ]` ROLE role_name. Examples: [ANSI][1], [Postgresql][2], [MySQL][3], and [Oracle][4].
1385    ///
1386    /// [1]: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#set-role-statement
1387    /// [2]: https://www.postgresql.org/docs/14/sql-set-role.html
1388    /// [3]: https://dev.mysql.com/doc/refman/8.0/en/set-role.html
1389    /// [4]: https://docs.oracle.com/cd/B19306_01/server.102/b14200/statements_10004.htm
1390    SetRole {
1391        /// Non-ANSI optional identifier to inform if the role is defined inside the current session (`SESSION`) or transaction (`LOCAL`).
1392        context_modifier: ContextModifier,
1393        /// Role name. If NONE is specified, then the current role name is removed.
1394        role_name: Option<Ident>,
1395    },
1396    /// ```sql
1397    /// SET <variable>
1398    /// ```
1399    ///
1400    /// Note: this is not a standard SQL statement, but it is supported by at
1401    /// least MySQL and PostgreSQL. Not all MySQL-specific syntatic forms are
1402    /// supported yet.
1403    SetVariable {
1404        local: bool,
1405        hivevar: bool,
1406        variable: ObjectName,
1407        value: Vec<Expr>,
1408    },
1409    /// ```sql
1410    /// SET TIME ZONE <value>
1411    /// ```
1412    ///
1413    /// Note: this is a PostgreSQL-specific statements
1414    /// `SET TIME ZONE <value>` is an alias for `SET timezone TO <value>` in PostgreSQL
1415    SetTimeZone { local: bool, value: Expr },
1416    /// SET NAMES 'charset_name' [COLLATE 'collation_name']
1417    ///
1418    /// Note: this is a MySQL-specific statement.
1419    SetNames {
1420        charset_name: String,
1421        collation_name: Option<String>,
1422    },
1423    /// SET NAMES DEFAULT
1424    ///
1425    /// Note: this is a MySQL-specific statement.
1426    SetNamesDefault {},
1427    /// SHOW FUNCTIONS
1428    ///
1429    /// Note: this is a Presto-specific statement.
1430    ShowFunctions { filter: Option<ShowStatementFilter> },
1431    /// ```sql
1432    /// SHOW <variable>
1433    /// ```
1434    ///
1435    /// Note: this is a PostgreSQL-specific statement.
1436    ShowVariable { variable: Vec<Ident> },
1437    /// SHOW VARIABLES
1438    ///
1439    /// Note: this is a MySQL-specific statement.
1440    ShowVariables { filter: Option<ShowStatementFilter> },
1441    /// SHOW CREATE TABLE
1442    ///
1443    /// Note: this is a MySQL-specific statement.
1444    ShowCreate {
1445        obj_type: ShowCreateObject,
1446        obj_name: ObjectName,
1447    },
1448    /// SHOW COLUMNS
1449    ///
1450    /// Note: this is a MySQL-specific statement.
1451    ShowColumns {
1452        extended: bool,
1453        full: bool,
1454        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
1455        table_name: ObjectName,
1456        filter: Option<ShowStatementFilter>,
1457    },
1458    /// SHOW TABLES
1459    ///
1460    /// Note: this is a MySQL-specific statement.
1461    ShowTables {
1462        extended: bool,
1463        full: bool,
1464        db_name: Option<Ident>,
1465        filter: Option<ShowStatementFilter>,
1466    },
1467    /// SHOW COLLATION
1468    ///
1469    /// Note: this is a MySQL-specific statement.
1470    ShowCollation { filter: Option<ShowStatementFilter> },
1471    /// USE
1472    ///
1473    /// Note: This is a MySQL-specific statement.
1474    Use { db_name: Ident },
1475    /// `{ BEGIN [ TRANSACTION | WORK ] | START TRANSACTION } ...`
1476    StartTransaction { modes: Vec<TransactionMode> },
1477    /// `SET TRANSACTION ...`
1478    SetTransaction {
1479        modes: Vec<TransactionMode>,
1480        snapshot: Option<Value>,
1481        session: bool,
1482    },
1483    /// `COMMENT ON ...`
1484    ///
1485    /// Note: this is a PostgreSQL-specific statement.
1486    Comment {
1487        object_type: CommentObject,
1488        object_name: ObjectName,
1489        comment: Option<String>,
1490        /// An optional `IF EXISTS` clause. (Non-standard.)
1491        /// See <https://docs.snowflake.com/en/sql-reference/sql/comment>
1492        if_exists: bool,
1493    },
1494    /// `COMMIT [ TRANSACTION | WORK ] [ AND [ NO ] CHAIN ]`
1495    Commit { chain: bool },
1496    /// `ROLLBACK [ TRANSACTION | WORK ] [ AND [ NO ] CHAIN ]`
1497    Rollback { chain: bool },
1498    /// CREATE SCHEMA
1499    CreateSchema {
1500        /// `<schema name> | AUTHORIZATION <schema authorization identifier>  | <schema name>  AUTHORIZATION <schema authorization identifier>`
1501        schema_name: SchemaName,
1502        if_not_exists: bool,
1503    },
1504    /// CREATE DATABASE
1505    CreateDatabase {
1506        db_name: ObjectName,
1507        if_not_exists: bool,
1508        location: Option<String>,
1509        managed_location: Option<String>,
1510    },
1511    /// ```sql
1512    /// CREATE FUNCTION
1513    /// ```
1514    ///
1515    /// Supported variants:
1516    /// 1. [Hive](https://cwiki.apache.org/confluence/display/hive/languagemanual+ddl#LanguageManualDDL-Create/Drop/ReloadFunction)
1517    /// 2. [Postgres](https://www.postgresql.org/docs/15/sql-createfunction.html)
1518    CreateFunction {
1519        or_replace: bool,
1520        temporary: bool,
1521        name: ObjectName,
1522        args: Option<Vec<OperateFunctionArg>>,
1523        return_type: Option<DataType>,
1524        /// Optional parameters.
1525        params: CreateFunctionBody,
1526    },
1527    /// `ASSERT <condition> [AS <message>]`
1528    Assert {
1529        condition: Expr,
1530        message: Option<Expr>,
1531    },
1532    /// GRANT privileges ON objects TO grantees
1533    Grant {
1534        privileges: Privileges,
1535        objects: GrantObjects,
1536        grantees: Vec<Ident>,
1537        with_grant_option: bool,
1538        granted_by: Option<Ident>,
1539    },
1540    /// REVOKE privileges ON objects FROM grantees
1541    Revoke {
1542        privileges: Privileges,
1543        objects: GrantObjects,
1544        grantees: Vec<Ident>,
1545        granted_by: Option<Ident>,
1546        cascade: bool,
1547    },
1548    /// `DEALLOCATE [ PREPARE ] { name | ALL }`
1549    ///
1550    /// Note: this is a PostgreSQL-specific statement.
1551    Deallocate { name: Ident, prepare: bool },
1552    /// `EXECUTE name [ ( parameter [, ...] ) ]`
1553    ///
1554    /// Note: this is a PostgreSQL-specific statement.
1555    Execute { name: Ident, parameters: Vec<Expr> },
1556    /// `PREPARE name [ ( data_type [, ...] ) ] AS statement`
1557    ///
1558    /// Note: this is a PostgreSQL-specific statement.
1559    Prepare {
1560        name: Ident,
1561        data_types: Vec<DataType>,
1562        statement: Box<Statement>,
1563    },
1564    /// KILL [CONNECTION | QUERY | MUTATION]
1565    ///
1566    /// See <https://clickhouse.com/docs/ru/sql-reference/statements/kill/>
1567    /// See <https://dev.mysql.com/doc/refman/8.0/en/kill.html>
1568    Kill {
1569        modifier: Option<KillType>,
1570        // processlist_id
1571        id: u64,
1572    },
1573    /// EXPLAIN TABLE
1574    /// Note: this is a MySQL-specific statement. See <https://dev.mysql.com/doc/refman/8.0/en/explain.html>
1575    ExplainTable {
1576        /// If true, query used the MySQL `DESCRIBE` alias for explain
1577        describe_alias: bool,
1578        /// Table name
1579        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
1580        table_name: ObjectName,
1581    },
1582    /// EXPLAIN / DESCRIBE for select_statement
1583    Explain {
1584        // If true, query used the MySQL `DESCRIBE` alias for explain
1585        describe_alias: bool,
1586        /// Carry out the command and show actual run times and other statistics.
1587        analyze: bool,
1588        // Display additional information regarding the plan.
1589        verbose: bool,
1590        /// A SQL query that specifies what to explain
1591        statement: Box<Statement>,
1592        /// Optional output format of explain
1593        format: Option<AnalyzeFormat>,
1594    },
1595    /// SAVEPOINT -- define a new savepoint within the current transaction
1596    Savepoint { name: Ident },
1597    // MERGE INTO statement, based on Snowflake. See <https://docs.snowflake.com/en/sql-reference/sql/merge.html>
1598    Merge {
1599        // optional INTO keyword
1600        into: bool,
1601        // Specifies the table to merge
1602        table: TableFactor,
1603        // Specifies the table or subquery to join with the target table
1604        source: TableFactor,
1605        // Specifies the expression on which to join the target table and source
1606        on: Box<Expr>,
1607        // Specifies the actions to perform when values match or do not match.
1608        clauses: Vec<MergeClause>,
1609    },
1610    /// `CACHE [ FLAG ] TABLE <table_name> [ OPTIONS('K1' = 'V1', 'K2' = V2) ] [ AS ] [ <query> ]`.
1611    ///
1612    /// See [Spark SQL docs] for more details.
1613    ///
1614    /// [Spark SQL docs]: https://docs.databricks.com/spark/latest/spark-sql/language-manual/sql-ref-syntax-aux-cache-cache-table.html
1615    Cache {
1616        /// Table flag
1617        table_flag: Option<ObjectName>,
1618        /// Table name
1619
1620        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
1621        table_name: ObjectName,
1622        has_as: bool,
1623        /// Table confs
1624        options: Vec<SqlOption>,
1625        /// Cache table as a Query
1626        query: Option<Query>,
1627    },
1628    /// UNCACHE TABLE [ IF EXISTS ]  <table_name>
1629    UNCache {
1630        /// Table name
1631        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
1632        table_name: ObjectName,
1633        if_exists: bool,
1634    },
1635    ///CreateSequence -- define a new sequence
1636    /// CREATE [ { TEMPORARY | TEMP } ] SEQUENCE [ IF NOT EXISTS ] <sequence_name>
1637    CreateSequence {
1638        temporary: bool,
1639        if_not_exists: bool,
1640        name: ObjectName,
1641        data_type: Option<DataType>,
1642        sequence_options: Vec<SequenceOptions>,
1643        owned_by: Option<ObjectName>,
1644    },
1645}
1646
1647impl fmt::Display for Statement {
1648    // Clippy thinks this function is too complicated, but it is painful to
1649    // split up without extracting structs for each `Statement` variant.
1650    #[allow(clippy::cognitive_complexity)]
1651    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1652        match self {
1653            Statement::Kill { modifier, id } => {
1654                write!(f, "KILL ")?;
1655
1656                if let Some(m) = modifier {
1657                    write!(f, "{m} ")?;
1658                }
1659
1660                write!(f, "{id}")
1661            }
1662            Statement::ExplainTable {
1663                describe_alias,
1664                table_name,
1665            } => {
1666                if *describe_alias {
1667                    write!(f, "DESCRIBE ")?;
1668                } else {
1669                    write!(f, "EXPLAIN ")?;
1670                }
1671
1672                write!(f, "{table_name}")
1673            }
1674            Statement::Explain {
1675                describe_alias,
1676                verbose,
1677                analyze,
1678                statement,
1679                format,
1680            } => {
1681                if *describe_alias {
1682                    write!(f, "DESCRIBE ")?;
1683                } else {
1684                    write!(f, "EXPLAIN ")?;
1685                }
1686
1687                if *analyze {
1688                    write!(f, "ANALYZE ")?;
1689                }
1690
1691                if *verbose {
1692                    write!(f, "VERBOSE ")?;
1693                }
1694
1695                if let Some(format) = format {
1696                    write!(f, "FORMAT {format} ")?;
1697                }
1698
1699                write!(f, "{statement}")
1700            }
1701            Statement::Query(s) => write!(f, "{s}"),
1702            Statement::Declare {
1703                name,
1704                binary,
1705                sensitive,
1706                scroll,
1707                hold,
1708                query,
1709            } => {
1710                write!(f, "DECLARE {name} ")?;
1711
1712                if *binary {
1713                    write!(f, "BINARY ")?;
1714                }
1715
1716                if let Some(sensitive) = sensitive {
1717                    if *sensitive {
1718                        write!(f, "INSENSITIVE ")?;
1719                    } else {
1720                        write!(f, "ASENSITIVE ")?;
1721                    }
1722                }
1723
1724                if let Some(scroll) = scroll {
1725                    if *scroll {
1726                        write!(f, "SCROLL ")?;
1727                    } else {
1728                        write!(f, "NO SCROLL ")?;
1729                    }
1730                }
1731
1732                write!(f, "CURSOR ")?;
1733
1734                if let Some(hold) = hold {
1735                    if *hold {
1736                        write!(f, "WITH HOLD ")?;
1737                    } else {
1738                        write!(f, "WITHOUT HOLD ")?;
1739                    }
1740                }
1741
1742                write!(f, "FOR {query}")
1743            }
1744            Statement::Fetch {
1745                name,
1746                direction,
1747                into,
1748            } => {
1749                write!(f, "FETCH {direction} ")?;
1750
1751                write!(f, "IN {name}")?;
1752
1753                if let Some(into) = into {
1754                    write!(f, " INTO {into}")?;
1755                }
1756
1757                Ok(())
1758            }
1759            Statement::Directory {
1760                overwrite,
1761                local,
1762                path,
1763                file_format,
1764                source,
1765            } => {
1766                write!(
1767                    f,
1768                    "INSERT{overwrite}{local} DIRECTORY '{path}'",
1769                    overwrite = if *overwrite { " OVERWRITE" } else { "" },
1770                    local = if *local { " LOCAL" } else { "" },
1771                    path = path
1772                )?;
1773                if let Some(ref ff) = file_format {
1774                    write!(f, " STORED AS {ff}")?
1775                }
1776                write!(f, " {source}")
1777            }
1778            Statement::Msck {
1779                table_name,
1780                repair,
1781                partition_action,
1782            } => {
1783                write!(
1784                    f,
1785                    "MSCK {repair}TABLE {table}",
1786                    repair = if *repair { "REPAIR " } else { "" },
1787                    table = table_name
1788                )?;
1789                if let Some(pa) = partition_action {
1790                    write!(f, " {pa}")?;
1791                }
1792                Ok(())
1793            }
1794            Statement::Truncate {
1795                table_name,
1796                partitions,
1797            } => {
1798                write!(f, "TRUNCATE TABLE {table_name}")?;
1799                if let Some(ref parts) = partitions {
1800                    if !parts.is_empty() {
1801                        write!(f, " PARTITION ({})", display_comma_separated(parts))?;
1802                    }
1803                }
1804                Ok(())
1805            }
1806            Statement::Analyze {
1807                table_name,
1808                partitions,
1809                for_columns,
1810                columns,
1811                cache_metadata,
1812                noscan,
1813                compute_statistics,
1814            } => {
1815                write!(f, "ANALYZE TABLE {table_name}")?;
1816                if let Some(ref parts) = partitions {
1817                    if !parts.is_empty() {
1818                        write!(f, " PARTITION ({})", display_comma_separated(parts))?;
1819                    }
1820                }
1821
1822                if *compute_statistics {
1823                    write!(f, " COMPUTE STATISTICS")?;
1824                }
1825                if *noscan {
1826                    write!(f, " NOSCAN")?;
1827                }
1828                if *cache_metadata {
1829                    write!(f, " CACHE METADATA")?;
1830                }
1831                if *for_columns {
1832                    write!(f, " FOR COLUMNS")?;
1833                    if !columns.is_empty() {
1834                        write!(f, " {}", display_comma_separated(columns))?;
1835                    }
1836                }
1837                Ok(())
1838            }
1839            Statement::Insert {
1840                or,
1841                into,
1842                table_name,
1843                overwrite,
1844                partitioned,
1845                columns,
1846                after_columns,
1847                source,
1848                table,
1849                on,
1850                returning,
1851            } => {
1852                if let Some(action) = or {
1853                    write!(f, "INSERT OR {action} INTO {table_name} ")?;
1854                } else {
1855                    write!(
1856                        f,
1857                        "INSERT{over}{int}{tbl} {table_name} ",
1858                        table_name = table_name,
1859                        over = if *overwrite { " OVERWRITE" } else { "" },
1860                        int = if *into { " INTO" } else { "" },
1861                        tbl = if *table { " TABLE" } else { "" }
1862                    )?;
1863                }
1864                if !columns.is_empty() {
1865                    write!(f, "({}) ", display_comma_separated(columns))?;
1866                }
1867                if let Some(ref parts) = partitioned {
1868                    if !parts.is_empty() {
1869                        write!(f, "PARTITION ({}) ", display_comma_separated(parts))?;
1870                    }
1871                }
1872                if !after_columns.is_empty() {
1873                    write!(f, "({}) ", display_comma_separated(after_columns))?;
1874                }
1875                write!(f, "{source}")?;
1876
1877                if let Some(on) = on {
1878                    write!(f, "{on}")?;
1879                }
1880
1881                if let Some(returning) = returning {
1882                    write!(f, " RETURNING {}", display_comma_separated(returning))?;
1883                }
1884
1885                Ok(())
1886            }
1887
1888            Statement::Copy {
1889                table_name,
1890                columns,
1891                to,
1892                target,
1893                options,
1894                legacy_options,
1895                values,
1896            } => {
1897                write!(f, "COPY {table_name}")?;
1898                if !columns.is_empty() {
1899                    write!(f, " ({})", display_comma_separated(columns))?;
1900                }
1901                write!(f, " {} {}", if *to { "TO" } else { "FROM" }, target)?;
1902                if !options.is_empty() {
1903                    write!(f, " ({})", display_comma_separated(options))?;
1904                }
1905                if !legacy_options.is_empty() {
1906                    write!(f, " {}", display_separated(legacy_options, " "))?;
1907                }
1908                if !values.is_empty() {
1909                    writeln!(f, ";")?;
1910                    let mut delim = "";
1911                    for v in values {
1912                        write!(f, "{delim}")?;
1913                        delim = "\t";
1914                        if let Some(v) = v {
1915                            write!(f, "{v}")?;
1916                        } else {
1917                            write!(f, "\\N")?;
1918                        }
1919                    }
1920                    write!(f, "\n\\.")?;
1921                }
1922                Ok(())
1923            }
1924            Statement::Update {
1925                table,
1926                assignments,
1927                from,
1928                selection,
1929                returning,
1930            } => {
1931                write!(f, "UPDATE {table}")?;
1932                if !assignments.is_empty() {
1933                    write!(f, " SET {}", display_comma_separated(assignments))?;
1934                }
1935                if let Some(from) = from {
1936                    write!(f, " FROM {from}")?;
1937                }
1938                if let Some(selection) = selection {
1939                    write!(f, " WHERE {selection}")?;
1940                }
1941                if let Some(returning) = returning {
1942                    write!(f, " RETURNING {}", display_comma_separated(returning))?;
1943                }
1944                Ok(())
1945            }
1946            Statement::Delete {
1947                table_name,
1948                using,
1949                selection,
1950                returning,
1951            } => {
1952                write!(f, "DELETE FROM {table_name}")?;
1953                if let Some(using) = using {
1954                    write!(f, " USING {using}")?;
1955                }
1956                if let Some(selection) = selection {
1957                    write!(f, " WHERE {selection}")?;
1958                }
1959                if let Some(returning) = returning {
1960                    write!(f, " RETURNING {}", display_comma_separated(returning))?;
1961                }
1962                Ok(())
1963            }
1964            Statement::Close { cursor } => {
1965                write!(f, "CLOSE {cursor}")?;
1966
1967                Ok(())
1968            }
1969            Statement::CreateDatabase {
1970                db_name,
1971                if_not_exists,
1972                location,
1973                managed_location,
1974            } => {
1975                write!(f, "CREATE DATABASE")?;
1976                if *if_not_exists {
1977                    write!(f, " IF NOT EXISTS")?;
1978                }
1979                write!(f, " {db_name}")?;
1980                if let Some(l) = location {
1981                    write!(f, " LOCATION '{l}'")?;
1982                }
1983                if let Some(ml) = managed_location {
1984                    write!(f, " MANAGEDLOCATION '{ml}'")?;
1985                }
1986                Ok(())
1987            }
1988            Statement::CreateFunction {
1989                or_replace,
1990                temporary,
1991                name,
1992                args,
1993                return_type,
1994                params,
1995            } => {
1996                write!(
1997                    f,
1998                    "CREATE {or_replace}{temp}FUNCTION {name}",
1999                    temp = if *temporary { "TEMPORARY " } else { "" },
2000                    or_replace = if *or_replace { "OR REPLACE " } else { "" },
2001                )?;
2002                if let Some(args) = args {
2003                    write!(f, "({})", display_comma_separated(args))?;
2004                }
2005                if let Some(return_type) = return_type {
2006                    write!(f, " RETURNS {return_type}")?;
2007                }
2008                write!(f, "{params}")?;
2009                Ok(())
2010            }
2011            Statement::CreateView {
2012                name,
2013                or_replace,
2014                columns,
2015                query,
2016                materialized,
2017                with_options,
2018                cluster_by,
2019            } => {
2020                write!(
2021                    f,
2022                    "CREATE {or_replace}{materialized}VIEW {name}",
2023                    or_replace = if *or_replace { "OR REPLACE " } else { "" },
2024                    materialized = if *materialized { "MATERIALIZED " } else { "" },
2025                    name = name
2026                )?;
2027                if !with_options.is_empty() {
2028                    write!(f, " WITH ({})", display_comma_separated(with_options))?;
2029                }
2030                if !columns.is_empty() {
2031                    write!(f, " ({})", display_comma_separated(columns))?;
2032                }
2033                if !cluster_by.is_empty() {
2034                    write!(f, " CLUSTER BY ({})", display_comma_separated(cluster_by))?;
2035                }
2036                write!(f, " AS {query}")
2037            }
2038            Statement::CreateTable {
2039                name,
2040                columns,
2041                constraints,
2042                table_properties,
2043                with_options,
2044                or_replace,
2045                if_not_exists,
2046                transient,
2047                hive_distribution,
2048                hive_formats,
2049                external,
2050                global,
2051                temporary,
2052                file_format,
2053                location,
2054                query,
2055                without_rowid,
2056                like,
2057                clone,
2058                default_charset,
2059                engine,
2060                collation,
2061                on_commit,
2062                on_cluster,
2063                order_by,
2064            } => {
2065                // We want to allow the following options
2066                // Empty column list, allowed by PostgreSQL:
2067                //   `CREATE TABLE t ()`
2068                // No columns provided for CREATE TABLE AS:
2069                //   `CREATE TABLE t AS SELECT a from t2`
2070                // Columns provided for CREATE TABLE AS:
2071                //   `CREATE TABLE t (a INT) AS SELECT a from t2`
2072                write!(
2073                    f,
2074                    "CREATE {or_replace}{external}{global}{temporary}{transient}TABLE {if_not_exists}{name}",
2075                    or_replace = if *or_replace { "OR REPLACE " } else { "" },
2076                    external = if *external { "EXTERNAL " } else { "" },
2077                    global = global
2078                        .map(|global| {
2079                            if global {
2080                                "GLOBAL "
2081                            } else {
2082                                "LOCAL "
2083                            }
2084                        })
2085                        .unwrap_or(""),
2086                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
2087                    temporary = if *temporary { "TEMPORARY " } else { "" },
2088                    transient = if *transient { "TRANSIENT " } else { "" },
2089                    name = name,
2090                )?;
2091                if let Some(on_cluster) = on_cluster {
2092                    write!(
2093                        f,
2094                        " ON CLUSTER {}",
2095                        on_cluster.replace('{', "'{").replace('}', "}'")
2096                    )?;
2097                }
2098                if !columns.is_empty() || !constraints.is_empty() {
2099                    write!(f, " ({}", display_comma_separated(columns))?;
2100                    if !columns.is_empty() && !constraints.is_empty() {
2101                        write!(f, ", ")?;
2102                    }
2103                    write!(f, "{})", display_comma_separated(constraints))?;
2104                } else if query.is_none() && like.is_none() && clone.is_none() {
2105                    // PostgreSQL allows `CREATE TABLE t ();`, but requires empty parens
2106                    write!(f, " ()")?;
2107                }
2108                // Only for SQLite
2109                if *without_rowid {
2110                    write!(f, " WITHOUT ROWID")?;
2111                }
2112
2113                // Only for Hive
2114                if let Some(l) = like {
2115                    write!(f, " LIKE {l}")?;
2116                }
2117
2118                if let Some(c) = clone {
2119                    write!(f, " CLONE {c}")?;
2120                }
2121
2122                match hive_distribution {
2123                    HiveDistributionStyle::PARTITIONED { columns } => {
2124                        write!(f, " PARTITIONED BY ({})", display_comma_separated(columns))?;
2125                    }
2126                    HiveDistributionStyle::CLUSTERED {
2127                        columns,
2128                        sorted_by,
2129                        num_buckets,
2130                    } => {
2131                        write!(f, " CLUSTERED BY ({})", display_comma_separated(columns))?;
2132                        if !sorted_by.is_empty() {
2133                            write!(f, " SORTED BY ({})", display_comma_separated(sorted_by))?;
2134                        }
2135                        if *num_buckets > 0 {
2136                            write!(f, " INTO {num_buckets} BUCKETS")?;
2137                        }
2138                    }
2139                    HiveDistributionStyle::SKEWED {
2140                        columns,
2141                        on,
2142                        stored_as_directories,
2143                    } => {
2144                        write!(
2145                            f,
2146                            " SKEWED BY ({})) ON ({})",
2147                            display_comma_separated(columns),
2148                            display_comma_separated(on)
2149                        )?;
2150                        if *stored_as_directories {
2151                            write!(f, " STORED AS DIRECTORIES")?;
2152                        }
2153                    }
2154                    _ => (),
2155                }
2156
2157                if let Some(HiveFormat {
2158                    row_format,
2159                    storage,
2160                    location,
2161                }) = hive_formats
2162                {
2163                    match row_format {
2164                        Some(HiveRowFormat::SERDE { class }) => {
2165                            write!(f, " ROW FORMAT SERDE '{class}'")?
2166                        }
2167                        Some(HiveRowFormat::DELIMITED) => write!(f, " ROW FORMAT DELIMITED")?,
2168                        None => (),
2169                    }
2170                    match storage {
2171                        Some(HiveIOFormat::IOF {
2172                            input_format,
2173                            output_format,
2174                        }) => write!(
2175                            f,
2176                            " STORED AS INPUTFORMAT {input_format} OUTPUTFORMAT {output_format}"
2177                        )?,
2178                        Some(HiveIOFormat::FileFormat { format }) if !*external => {
2179                            write!(f, " STORED AS {format}")?
2180                        }
2181                        _ => (),
2182                    }
2183                    if !*external {
2184                        if let Some(loc) = location {
2185                            write!(f, " LOCATION '{loc}'")?;
2186                        }
2187                    }
2188                }
2189                if *external {
2190                    write!(
2191                        f,
2192                        " STORED AS {} LOCATION '{}'",
2193                        file_format.as_ref().unwrap(),
2194                        location.as_ref().unwrap()
2195                    )?;
2196                }
2197                if !table_properties.is_empty() {
2198                    write!(
2199                        f,
2200                        " TBLPROPERTIES ({})",
2201                        display_comma_separated(table_properties)
2202                    )?;
2203                }
2204                if !with_options.is_empty() {
2205                    write!(f, " WITH ({})", display_comma_separated(with_options))?;
2206                }
2207                if let Some(engine) = engine {
2208                    write!(f, " ENGINE={engine}")?;
2209                }
2210                if let Some(order_by) = order_by {
2211                    write!(f, " ORDER BY ({})", display_comma_separated(order_by))?;
2212                }
2213                if let Some(query) = query {
2214                    write!(f, " AS {query}")?;
2215                }
2216                if let Some(default_charset) = default_charset {
2217                    write!(f, " DEFAULT CHARSET={default_charset}")?;
2218                }
2219                if let Some(collation) = collation {
2220                    write!(f, " COLLATE={collation}")?;
2221                }
2222
2223                if on_commit.is_some() {
2224                    let on_commit = match on_commit {
2225                        Some(OnCommit::DeleteRows) => "ON COMMIT DELETE ROWS",
2226                        Some(OnCommit::PreserveRows) => "ON COMMIT PRESERVE ROWS",
2227                        Some(OnCommit::Drop) => "ON COMMIT DROP",
2228                        None => "",
2229                    };
2230                    write!(f, " {on_commit}")?;
2231                }
2232
2233                Ok(())
2234            }
2235            Statement::CreateVirtualTable {
2236                name,
2237                if_not_exists,
2238                module_name,
2239                module_args,
2240            } => {
2241                write!(
2242                    f,
2243                    "CREATE VIRTUAL TABLE {if_not_exists}{name} USING {module_name}",
2244                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
2245                    name = name,
2246                    module_name = module_name
2247                )?;
2248                if !module_args.is_empty() {
2249                    write!(f, " ({})", display_comma_separated(module_args))?;
2250                }
2251                Ok(())
2252            }
2253            Statement::CreateIndex {
2254                name,
2255                table_name,
2256                using,
2257                columns,
2258                unique,
2259                if_not_exists,
2260            } => {
2261                write!(
2262                    f,
2263                    "CREATE {unique}INDEX {if_not_exists}{name} ON {table_name}",
2264                    unique = if *unique { "UNIQUE " } else { "" },
2265                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
2266                    name = name,
2267                    table_name = table_name
2268                )?;
2269                if let Some(value) = using {
2270                    write!(f, " USING {value} ")?;
2271                }
2272                write!(f, "({})", display_separated(columns, ","))
2273            }
2274            Statement::CreateRole {
2275                names,
2276                if_not_exists,
2277                inherit,
2278                login,
2279                bypassrls,
2280                password,
2281                create_db,
2282                create_role,
2283                superuser,
2284                replication,
2285                connection_limit,
2286                valid_until,
2287                in_role,
2288                in_group,
2289                role,
2290                user,
2291                admin,
2292                authorization_owner,
2293            } => {
2294                write!(
2295                    f,
2296                    "CREATE ROLE {if_not_exists}{names}{superuser}{create_db}{create_role}{inherit}{login}{replication}{bypassrls}",
2297                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
2298                    names = display_separated(names, ", "),
2299                    superuser = match *superuser {
2300                        Some(true) => " SUPERUSER",
2301                        Some(false) => " NOSUPERUSER",
2302                        None => ""
2303                    },
2304                    create_db = match *create_db {
2305                        Some(true) => " CREATEDB",
2306                        Some(false) => " NOCREATEDB",
2307                        None => ""
2308                    },
2309                    create_role = match *create_role {
2310                        Some(true) => " CREATEROLE",
2311                        Some(false) => " NOCREATEROLE",
2312                        None => ""
2313                    },
2314                    inherit = match *inherit {
2315                        Some(true) => " INHERIT",
2316                        Some(false) => " NOINHERIT",
2317                        None => ""
2318                    },
2319                    login = match *login {
2320                        Some(true) => " LOGIN",
2321                        Some(false) => " NOLOGIN",
2322                        None => ""
2323                    },
2324                    replication = match *replication {
2325                        Some(true) => " REPLICATION",
2326                        Some(false) => " NOREPLICATION",
2327                        None => ""
2328                    },
2329                    bypassrls = match *bypassrls {
2330                        Some(true) => " BYPASSRLS",
2331                        Some(false) => " NOBYPASSRLS",
2332                        None => ""
2333                    }
2334                )?;
2335                if let Some(limit) = connection_limit {
2336                    write!(f, " CONNECTION LIMIT {limit}")?;
2337                }
2338                match password {
2339                    Some(Password::Password(pass)) => write!(f, " PASSWORD {pass}"),
2340                    Some(Password::NullPassword) => write!(f, " PASSWORD NULL"),
2341                    None => Ok(()),
2342                }?;
2343                if let Some(until) = valid_until {
2344                    write!(f, " VALID UNTIL {until}")?;
2345                }
2346                if !in_role.is_empty() {
2347                    write!(f, " IN ROLE {}", display_comma_separated(in_role))?;
2348                }
2349                if !in_group.is_empty() {
2350                    write!(f, " IN GROUP {}", display_comma_separated(in_group))?;
2351                }
2352                if !role.is_empty() {
2353                    write!(f, " ROLE {}", display_comma_separated(role))?;
2354                }
2355                if !user.is_empty() {
2356                    write!(f, " USER {}", display_comma_separated(user))?;
2357                }
2358                if !admin.is_empty() {
2359                    write!(f, " ADMIN {}", display_comma_separated(admin))?;
2360                }
2361                if let Some(owner) = authorization_owner {
2362                    write!(f, " AUTHORIZATION {owner}")?;
2363                }
2364                Ok(())
2365            }
2366            Statement::AlterTable { name, operation } => {
2367                write!(f, "ALTER TABLE {name} {operation}")
2368            }
2369            Statement::AlterIndex { name, operation } => {
2370                write!(f, "ALTER INDEX {name} {operation}")
2371            }
2372            Statement::Drop {
2373                object_type,
2374                if_exists,
2375                names,
2376                cascade,
2377                restrict,
2378                purge,
2379            } => write!(
2380                f,
2381                "DROP {}{} {}{}{}{}",
2382                object_type,
2383                if *if_exists { " IF EXISTS" } else { "" },
2384                display_comma_separated(names),
2385                if *cascade { " CASCADE" } else { "" },
2386                if *restrict { " RESTRICT" } else { "" },
2387                if *purge { " PURGE" } else { "" }
2388            ),
2389            Statement::DropFunction {
2390                if_exists,
2391                func_desc,
2392                option,
2393            } => {
2394                write!(
2395                    f,
2396                    "DROP FUNCTION{} {}",
2397                    if *if_exists { " IF EXISTS" } else { "" },
2398                    display_comma_separated(func_desc),
2399                )?;
2400                if let Some(op) = option {
2401                    write!(f, " {op}")?;
2402                }
2403                Ok(())
2404            }
2405            Statement::Discard { object_type } => {
2406                write!(f, "DISCARD {object_type}")?;
2407                Ok(())
2408            }
2409            Self::SetRole {
2410                context_modifier,
2411                role_name,
2412            } => {
2413                let role_name = role_name.clone().unwrap_or_else(|| Ident::new("NONE"));
2414                write!(f, "SET{context_modifier} ROLE {role_name}")
2415            }
2416            Statement::SetVariable {
2417                local,
2418                variable,
2419                hivevar,
2420                value,
2421            } => {
2422                f.write_str("SET ")?;
2423                if *local {
2424                    f.write_str("LOCAL ")?;
2425                }
2426                write!(
2427                    f,
2428                    "{hivevar}{name} = {value}",
2429                    hivevar = if *hivevar { "HIVEVAR:" } else { "" },
2430                    name = variable,
2431                    value = display_comma_separated(value)
2432                )
2433            }
2434            Statement::SetTimeZone { local, value } => {
2435                f.write_str("SET ")?;
2436                if *local {
2437                    f.write_str("LOCAL ")?;
2438                }
2439                write!(f, "TIME ZONE {value}")
2440            }
2441            Statement::SetNames {
2442                charset_name,
2443                collation_name,
2444            } => {
2445                f.write_str("SET NAMES ")?;
2446                f.write_str(charset_name)?;
2447
2448                if let Some(collation) = collation_name {
2449                    f.write_str(" COLLATE ")?;
2450                    f.write_str(collation)?;
2451                };
2452
2453                Ok(())
2454            }
2455            Statement::SetNamesDefault {} => {
2456                f.write_str("SET NAMES DEFAULT")?;
2457
2458                Ok(())
2459            }
2460            Statement::ShowVariable { variable } => {
2461                write!(f, "SHOW")?;
2462                if !variable.is_empty() {
2463                    write!(f, " {}", display_separated(variable, " "))?;
2464                }
2465                Ok(())
2466            }
2467            Statement::ShowVariables { filter } => {
2468                write!(f, "SHOW VARIABLES")?;
2469                if filter.is_some() {
2470                    write!(f, " {}", filter.as_ref().unwrap())?;
2471                }
2472                Ok(())
2473            }
2474            Statement::ShowCreate { obj_type, obj_name } => {
2475                write!(f, "SHOW CREATE {obj_type} {obj_name}",)?;
2476                Ok(())
2477            }
2478            Statement::ShowColumns {
2479                extended,
2480                full,
2481                table_name,
2482                filter,
2483            } => {
2484                write!(
2485                    f,
2486                    "SHOW {extended}{full}COLUMNS FROM {table_name}",
2487                    extended = if *extended { "EXTENDED " } else { "" },
2488                    full = if *full { "FULL " } else { "" },
2489                    table_name = table_name,
2490                )?;
2491                if let Some(filter) = filter {
2492                    write!(f, " {filter}")?;
2493                }
2494                Ok(())
2495            }
2496            Statement::ShowTables {
2497                extended,
2498                full,
2499                db_name,
2500                filter,
2501            } => {
2502                write!(
2503                    f,
2504                    "SHOW {extended}{full}TABLES",
2505                    extended = if *extended { "EXTENDED " } else { "" },
2506                    full = if *full { "FULL " } else { "" },
2507                )?;
2508                if let Some(db_name) = db_name {
2509                    write!(f, " FROM {db_name}")?;
2510                }
2511                if let Some(filter) = filter {
2512                    write!(f, " {filter}")?;
2513                }
2514                Ok(())
2515            }
2516            Statement::ShowFunctions { filter } => {
2517                write!(f, "SHOW FUNCTIONS")?;
2518                if let Some(filter) = filter {
2519                    write!(f, " {filter}")?;
2520                }
2521                Ok(())
2522            }
2523            Statement::Use { db_name } => {
2524                write!(f, "USE {db_name}")?;
2525                Ok(())
2526            }
2527            Statement::ShowCollation { filter } => {
2528                write!(f, "SHOW COLLATION")?;
2529                if let Some(filter) = filter {
2530                    write!(f, " {filter}")?;
2531                }
2532                Ok(())
2533            }
2534            Statement::StartTransaction { modes } => {
2535                write!(f, "START TRANSACTION")?;
2536                if !modes.is_empty() {
2537                    write!(f, " {}", display_comma_separated(modes))?;
2538                }
2539                Ok(())
2540            }
2541            Statement::SetTransaction {
2542                modes,
2543                snapshot,
2544                session,
2545            } => {
2546                if *session {
2547                    write!(f, "SET SESSION CHARACTERISTICS AS TRANSACTION")?;
2548                } else {
2549                    write!(f, "SET TRANSACTION")?;
2550                }
2551                if !modes.is_empty() {
2552                    write!(f, " {}", display_comma_separated(modes))?;
2553                }
2554                if let Some(snapshot_id) = snapshot {
2555                    write!(f, " SNAPSHOT {snapshot_id}")?;
2556                }
2557                Ok(())
2558            }
2559            Statement::Commit { chain } => {
2560                write!(f, "COMMIT{}", if *chain { " AND CHAIN" } else { "" },)
2561            }
2562            Statement::Rollback { chain } => {
2563                write!(f, "ROLLBACK{}", if *chain { " AND CHAIN" } else { "" },)
2564            }
2565            Statement::CreateSchema {
2566                schema_name,
2567                if_not_exists,
2568            } => write!(
2569                f,
2570                "CREATE SCHEMA {if_not_exists}{name}",
2571                if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
2572                name = schema_name
2573            ),
2574            Statement::Assert { condition, message } => {
2575                write!(f, "ASSERT {condition}")?;
2576                if let Some(m) = message {
2577                    write!(f, " AS {m}")?;
2578                }
2579                Ok(())
2580            }
2581            Statement::Grant {
2582                privileges,
2583                objects,
2584                grantees,
2585                with_grant_option,
2586                granted_by,
2587            } => {
2588                write!(f, "GRANT {privileges} ")?;
2589                write!(f, "ON {objects} ")?;
2590                write!(f, "TO {}", display_comma_separated(grantees))?;
2591                if *with_grant_option {
2592                    write!(f, " WITH GRANT OPTION")?;
2593                }
2594                if let Some(grantor) = granted_by {
2595                    write!(f, " GRANTED BY {grantor}")?;
2596                }
2597                Ok(())
2598            }
2599            Statement::Revoke {
2600                privileges,
2601                objects,
2602                grantees,
2603                granted_by,
2604                cascade,
2605            } => {
2606                write!(f, "REVOKE {privileges} ")?;
2607                write!(f, "ON {objects} ")?;
2608                write!(f, "FROM {}", display_comma_separated(grantees))?;
2609                if let Some(grantor) = granted_by {
2610                    write!(f, " GRANTED BY {grantor}")?;
2611                }
2612                write!(f, " {}", if *cascade { "CASCADE" } else { "RESTRICT" })?;
2613                Ok(())
2614            }
2615            Statement::Deallocate { name, prepare } => write!(
2616                f,
2617                "DEALLOCATE {prepare}{name}",
2618                prepare = if *prepare { "PREPARE " } else { "" },
2619                name = name,
2620            ),
2621            Statement::Execute { name, parameters } => {
2622                write!(f, "EXECUTE {name}")?;
2623                if !parameters.is_empty() {
2624                    write!(f, "({})", display_comma_separated(parameters))?;
2625                }
2626                Ok(())
2627            }
2628            Statement::Prepare {
2629                name,
2630                data_types,
2631                statement,
2632            } => {
2633                write!(f, "PREPARE {name} ")?;
2634                if !data_types.is_empty() {
2635                    write!(f, "({}) ", display_comma_separated(data_types))?;
2636                }
2637                write!(f, "AS {statement}")
2638            }
2639            Statement::Comment {
2640                object_type,
2641                object_name,
2642                comment,
2643                if_exists,
2644            } => {
2645                write!(f, "COMMENT ")?;
2646                if *if_exists {
2647                    write!(f, "IF EXISTS ")?
2648                };
2649                write!(f, "ON {object_type} {object_name} IS ")?;
2650                if let Some(c) = comment {
2651                    write!(f, "'{c}'")
2652                } else {
2653                    write!(f, "NULL")
2654                }
2655            }
2656            Statement::Savepoint { name } => {
2657                write!(f, "SAVEPOINT ")?;
2658                write!(f, "{name}")
2659            }
2660            Statement::Merge {
2661                into,
2662                table,
2663                source,
2664                on,
2665                clauses,
2666            } => {
2667                write!(
2668                    f,
2669                    "MERGE{int} {table} USING {source} ",
2670                    int = if *into { " INTO" } else { "" }
2671                )?;
2672                write!(f, "ON {on} ")?;
2673                write!(f, "{}", display_separated(clauses, " "))
2674            }
2675            Statement::Cache {
2676                table_name,
2677                table_flag,
2678                has_as,
2679                options,
2680                query,
2681            } => {
2682                if table_flag.is_some() {
2683                    write!(
2684                        f,
2685                        "CACHE {table_flag} TABLE {table_name}",
2686                        table_flag = table_flag.clone().unwrap(),
2687                        table_name = table_name,
2688                    )?;
2689                } else {
2690                    write!(f, "CACHE TABLE {table_name}",)?;
2691                }
2692
2693                if !options.is_empty() {
2694                    write!(f, " OPTIONS({})", display_comma_separated(options))?;
2695                }
2696
2697                let has_query = query.is_some();
2698                if *has_as && has_query {
2699                    write!(f, " AS {query}", query = query.clone().unwrap())
2700                } else if !has_as && has_query {
2701                    write!(f, " {query}", query = query.clone().unwrap())
2702                } else if *has_as && !has_query {
2703                    write!(f, " AS")
2704                } else {
2705                    Ok(())
2706                }
2707            }
2708            Statement::UNCache {
2709                table_name,
2710                if_exists,
2711            } => {
2712                if *if_exists {
2713                    write!(f, "UNCACHE TABLE IF EXISTS {table_name}")
2714                } else {
2715                    write!(f, "UNCACHE TABLE {table_name}")
2716                }
2717            }
2718            Statement::CreateSequence {
2719                temporary,
2720                if_not_exists,
2721                name,
2722                data_type,
2723                sequence_options,
2724                owned_by,
2725            } => {
2726                let as_type: String = if let Some(dt) = data_type.as_ref() {
2727                    //Cannot use format!(" AS {}", dt), due to format! is not available in --target thumbv6m-none-eabi
2728                    // " AS ".to_owned() + &dt.to_string()
2729                    [" AS ", &dt.to_string()].concat()
2730                } else {
2731                    "".to_string()
2732                };
2733                write!(
2734                    f,
2735                    "CREATE {temporary}SEQUENCE {if_not_exists}{name}{as_type}",
2736                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
2737                    temporary = if *temporary { "TEMPORARY " } else { "" },
2738                    name = name,
2739                    as_type = as_type
2740                )?;
2741                for sequence_option in sequence_options {
2742                    write!(f, "{sequence_option}")?;
2743                }
2744                if let Some(ob) = owned_by.as_ref() {
2745                    write!(f, " OWNED BY {ob}")?;
2746                }
2747                write!(f, "")
2748            }
2749        }
2750    }
2751}
2752
2753/// Can use to describe options in create sequence or table column type identity
2754/// ```sql
2755/// [ INCREMENT [ BY ] increment ]
2756///     [ MINVALUE minvalue | NO MINVALUE ] [ MAXVALUE maxvalue | NO MAXVALUE ]
2757///     [ START [ WITH ] start ] [ CACHE cache ] [ [ NO ] CYCLE ]
2758/// ```
2759#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2760#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2761#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2762pub enum SequenceOptions {
2763    IncrementBy(Expr, bool),
2764    MinValue(MinMaxValue),
2765    MaxValue(MinMaxValue),
2766    StartWith(Expr, bool),
2767    Cache(Expr),
2768    Cycle(bool),
2769}
2770
2771impl fmt::Display for SequenceOptions {
2772    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2773        match self {
2774            SequenceOptions::IncrementBy(increment, by) => {
2775                write!(
2776                    f,
2777                    " INCREMENT{by} {increment}",
2778                    by = if *by { " BY" } else { "" },
2779                    increment = increment
2780                )
2781            }
2782            SequenceOptions::MinValue(value) => match value {
2783                MinMaxValue::Empty => {
2784                    write!(f, "")
2785                }
2786                MinMaxValue::None => {
2787                    write!(f, " NO MINVALUE")
2788                }
2789                MinMaxValue::Some(minvalue) => {
2790                    write!(f, " MINVALUE {minvalue}")
2791                }
2792            },
2793            SequenceOptions::MaxValue(value) => match value {
2794                MinMaxValue::Empty => {
2795                    write!(f, "")
2796                }
2797                MinMaxValue::None => {
2798                    write!(f, " NO MAXVALUE")
2799                }
2800                MinMaxValue::Some(maxvalue) => {
2801                    write!(f, " MAXVALUE {maxvalue}")
2802                }
2803            },
2804            SequenceOptions::StartWith(start, with) => {
2805                write!(
2806                    f,
2807                    " START{with} {start}",
2808                    with = if *with { " WITH" } else { "" },
2809                    start = start
2810                )
2811            }
2812            SequenceOptions::Cache(cache) => {
2813                write!(f, " CACHE {}", *cache)
2814            }
2815            SequenceOptions::Cycle(no) => {
2816                write!(f, " {}CYCLE", if *no { "NO " } else { "" })
2817            }
2818        }
2819    }
2820}
2821
2822/// Can use to describe options in  create sequence or table column type identity
2823/// [ MINVALUE minvalue | NO MINVALUE ] [ MAXVALUE maxvalue | NO MAXVALUE ]
2824#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2825#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2826#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2827pub enum MinMaxValue {
2828    // clause is not specified
2829    Empty,
2830    // NO MINVALUE/NO MAXVALUE
2831    None,
2832    // MINVALUE <expr> / MAXVALUE <expr>
2833    Some(Expr),
2834}
2835
2836#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2837#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2838#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2839#[non_exhaustive]
2840pub enum OnInsert {
2841    /// ON DUPLICATE KEY UPDATE (MySQL when the key already exists, then execute an update instead)
2842    DuplicateKeyUpdate(Vec<Assignment>),
2843    /// ON CONFLICT is a PostgreSQL and Sqlite extension
2844    OnConflict(OnConflict),
2845}
2846
2847#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2848#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2849#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2850pub struct OnConflict {
2851    pub conflict_target: Option<ConflictTarget>,
2852    pub action: OnConflictAction,
2853}
2854#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2855#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2856#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2857pub enum ConflictTarget {
2858    Columns(Vec<Ident>),
2859    OnConstraint(ObjectName),
2860}
2861#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2862#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2863#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2864pub enum OnConflictAction {
2865    DoNothing,
2866    DoUpdate(DoUpdate),
2867}
2868
2869#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2870#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2871#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2872pub struct DoUpdate {
2873    /// Column assignments
2874    pub assignments: Vec<Assignment>,
2875    /// WHERE
2876    pub selection: Option<Expr>,
2877}
2878
2879impl fmt::Display for OnInsert {
2880    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2881        match self {
2882            Self::DuplicateKeyUpdate(expr) => write!(
2883                f,
2884                " ON DUPLICATE KEY UPDATE {}",
2885                display_comma_separated(expr)
2886            ),
2887            Self::OnConflict(o) => write!(f, " {o}"),
2888        }
2889    }
2890}
2891impl fmt::Display for OnConflict {
2892    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2893        write!(f, " ON CONFLICT")?;
2894        if let Some(target) = &self.conflict_target {
2895            write!(f, "{target}")?;
2896        }
2897        write!(f, " {}", self.action)
2898    }
2899}
2900impl fmt::Display for ConflictTarget {
2901    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2902        match self {
2903            ConflictTarget::Columns(cols) => write!(f, "({})", display_comma_separated(cols)),
2904            ConflictTarget::OnConstraint(name) => write!(f, " ON CONSTRAINT {name}"),
2905        }
2906    }
2907}
2908impl fmt::Display for OnConflictAction {
2909    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2910        match self {
2911            Self::DoNothing => write!(f, "DO NOTHING"),
2912            Self::DoUpdate(do_update) => {
2913                write!(f, "DO UPDATE")?;
2914                if !do_update.assignments.is_empty() {
2915                    write!(
2916                        f,
2917                        " SET {}",
2918                        display_comma_separated(&do_update.assignments)
2919                    )?;
2920                }
2921                if let Some(selection) = &do_update.selection {
2922                    write!(f, " WHERE {selection}")?;
2923                }
2924                Ok(())
2925            }
2926        }
2927    }
2928}
2929
2930/// Privileges granted in a GRANT statement or revoked in a REVOKE statement.
2931#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2932#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2933#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2934pub enum Privileges {
2935    /// All privileges applicable to the object type
2936    All {
2937        /// Optional keyword from the spec, ignored in practice
2938        with_privileges_keyword: bool,
2939    },
2940    /// Specific privileges (e.g. `SELECT`, `INSERT`)
2941    Actions(Vec<Action>),
2942}
2943
2944impl fmt::Display for Privileges {
2945    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2946        match self {
2947            Privileges::All {
2948                with_privileges_keyword,
2949            } => {
2950                write!(
2951                    f,
2952                    "ALL{}",
2953                    if *with_privileges_keyword {
2954                        " PRIVILEGES"
2955                    } else {
2956                        ""
2957                    }
2958                )
2959            }
2960            Privileges::Actions(actions) => {
2961                write!(f, "{}", display_comma_separated(actions))
2962            }
2963        }
2964    }
2965}
2966
2967/// Specific direction for FETCH statement
2968#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2969#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2970#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2971pub enum FetchDirection {
2972    Count { limit: Value },
2973    Next,
2974    Prior,
2975    First,
2976    Last,
2977    Absolute { limit: Value },
2978    Relative { limit: Value },
2979    All,
2980    // FORWARD
2981    // FORWARD count
2982    Forward { limit: Option<Value> },
2983    ForwardAll,
2984    // BACKWARD
2985    // BACKWARD count
2986    Backward { limit: Option<Value> },
2987    BackwardAll,
2988}
2989
2990impl fmt::Display for FetchDirection {
2991    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2992        match self {
2993            FetchDirection::Count { limit } => f.write_str(&limit.to_string())?,
2994            FetchDirection::Next => f.write_str("NEXT")?,
2995            FetchDirection::Prior => f.write_str("PRIOR")?,
2996            FetchDirection::First => f.write_str("FIRST")?,
2997            FetchDirection::Last => f.write_str("LAST")?,
2998            FetchDirection::Absolute { limit } => {
2999                f.write_str("ABSOLUTE ")?;
3000                f.write_str(&limit.to_string())?;
3001            }
3002            FetchDirection::Relative { limit } => {
3003                f.write_str("RELATIVE ")?;
3004                f.write_str(&limit.to_string())?;
3005            }
3006            FetchDirection::All => f.write_str("ALL")?,
3007            FetchDirection::Forward { limit } => {
3008                f.write_str("FORWARD")?;
3009
3010                if let Some(l) = limit {
3011                    f.write_str(" ")?;
3012                    f.write_str(&l.to_string())?;
3013                }
3014            }
3015            FetchDirection::ForwardAll => f.write_str("FORWARD ALL")?,
3016            FetchDirection::Backward { limit } => {
3017                f.write_str("BACKWARD")?;
3018
3019                if let Some(l) = limit {
3020                    f.write_str(" ")?;
3021                    f.write_str(&l.to_string())?;
3022                }
3023            }
3024            FetchDirection::BackwardAll => f.write_str("BACKWARD ALL")?,
3025        };
3026
3027        Ok(())
3028    }
3029}
3030
3031/// A privilege on a database object (table, sequence, etc.).
3032#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3033#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3034#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3035pub enum Action {
3036    Connect,
3037    Create,
3038    Delete,
3039    Execute,
3040    Insert { columns: Option<Vec<Ident>> },
3041    References { columns: Option<Vec<Ident>> },
3042    Select { columns: Option<Vec<Ident>> },
3043    Temporary,
3044    Trigger,
3045    Truncate,
3046    Update { columns: Option<Vec<Ident>> },
3047    Usage,
3048}
3049
3050impl fmt::Display for Action {
3051    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3052        match self {
3053            Action::Connect => f.write_str("CONNECT")?,
3054            Action::Create => f.write_str("CREATE")?,
3055            Action::Delete => f.write_str("DELETE")?,
3056            Action::Execute => f.write_str("EXECUTE")?,
3057            Action::Insert { .. } => f.write_str("INSERT")?,
3058            Action::References { .. } => f.write_str("REFERENCES")?,
3059            Action::Select { .. } => f.write_str("SELECT")?,
3060            Action::Temporary => f.write_str("TEMPORARY")?,
3061            Action::Trigger => f.write_str("TRIGGER")?,
3062            Action::Truncate => f.write_str("TRUNCATE")?,
3063            Action::Update { .. } => f.write_str("UPDATE")?,
3064            Action::Usage => f.write_str("USAGE")?,
3065        };
3066        match self {
3067            Action::Insert { columns }
3068            | Action::References { columns }
3069            | Action::Select { columns }
3070            | Action::Update { columns } => {
3071                if let Some(columns) = columns {
3072                    write!(f, " ({})", display_comma_separated(columns))?;
3073                }
3074            }
3075            _ => (),
3076        };
3077        Ok(())
3078    }
3079}
3080
3081/// Objects on which privileges are granted in a GRANT statement.
3082#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3083#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3084#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3085pub enum GrantObjects {
3086    /// Grant privileges on `ALL SEQUENCES IN SCHEMA <schema_name> [, ...]`
3087    AllSequencesInSchema { schemas: Vec<ObjectName> },
3088    /// Grant privileges on `ALL TABLES IN SCHEMA <schema_name> [, ...]`
3089    AllTablesInSchema { schemas: Vec<ObjectName> },
3090    /// Grant privileges on specific schemas
3091    Schemas(Vec<ObjectName>),
3092    /// Grant privileges on specific sequences
3093    Sequences(Vec<ObjectName>),
3094    /// Grant privileges on specific tables
3095    Tables(Vec<ObjectName>),
3096}
3097
3098impl fmt::Display for GrantObjects {
3099    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3100        match self {
3101            GrantObjects::Sequences(sequences) => {
3102                write!(f, "SEQUENCE {}", display_comma_separated(sequences))
3103            }
3104            GrantObjects::Schemas(schemas) => {
3105                write!(f, "SCHEMA {}", display_comma_separated(schemas))
3106            }
3107            GrantObjects::Tables(tables) => {
3108                write!(f, "{}", display_comma_separated(tables))
3109            }
3110            GrantObjects::AllSequencesInSchema { schemas } => {
3111                write!(
3112                    f,
3113                    "ALL SEQUENCES IN SCHEMA {}",
3114                    display_comma_separated(schemas)
3115                )
3116            }
3117            GrantObjects::AllTablesInSchema { schemas } => {
3118                write!(
3119                    f,
3120                    "ALL TABLES IN SCHEMA {}",
3121                    display_comma_separated(schemas)
3122                )
3123            }
3124        }
3125    }
3126}
3127
3128/// SQL assignment `foo = expr` as used in SQLUpdate
3129#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3130#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3131#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3132pub struct Assignment {
3133    pub id: Vec<Ident>,
3134    pub value: Expr,
3135}
3136
3137impl fmt::Display for Assignment {
3138    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3139        write!(f, "{} = {}", display_separated(&self.id, "."), self.value)
3140    }
3141}
3142
3143#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3144#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3145#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3146pub enum FunctionArgExpr {
3147    Expr(Expr),
3148    /// Qualified wildcard, e.g. `alias.*` or `schema.table.*`.
3149    QualifiedWildcard(ObjectName),
3150    /// An unqualified `*`
3151    Wildcard,
3152}
3153
3154impl fmt::Display for FunctionArgExpr {
3155    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3156        match self {
3157            FunctionArgExpr::Expr(expr) => write!(f, "{expr}"),
3158            FunctionArgExpr::QualifiedWildcard(prefix) => write!(f, "{prefix}.*"),
3159            FunctionArgExpr::Wildcard => f.write_str("*"),
3160        }
3161    }
3162}
3163
3164#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3165#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3166#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3167pub enum FunctionArg {
3168    Named { name: Ident, arg: FunctionArgExpr },
3169    Unnamed(FunctionArgExpr),
3170}
3171
3172impl fmt::Display for FunctionArg {
3173    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3174        match self {
3175            FunctionArg::Named { name, arg } => write!(f, "{name} => {arg}"),
3176            FunctionArg::Unnamed(unnamed_arg) => write!(f, "{unnamed_arg}"),
3177        }
3178    }
3179}
3180
3181#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3182#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3183#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3184pub enum CloseCursor {
3185    All,
3186    Specific { name: Ident },
3187}
3188
3189impl fmt::Display for CloseCursor {
3190    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3191        match self {
3192            CloseCursor::All => write!(f, "ALL"),
3193            CloseCursor::Specific { name } => write!(f, "{name}"),
3194        }
3195    }
3196}
3197
3198/// A function call
3199#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3200#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3201#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3202pub struct Function {
3203    pub name: ObjectName,
3204    pub args: Vec<FunctionArg>,
3205    pub over: Option<WindowSpec>,
3206    // aggregate functions may specify eg `COUNT(DISTINCT x)`
3207    pub distinct: bool,
3208    // Some functions must be called without trailing parentheses, for example Postgres
3209    // do it for current_catalog, current_schema, etc. This flags is used for formatting.
3210    pub special: bool,
3211}
3212
3213#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3214#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3215#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3216pub enum AnalyzeFormat {
3217    TEXT,
3218    GRAPHVIZ,
3219    JSON,
3220}
3221
3222impl fmt::Display for AnalyzeFormat {
3223    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
3224        f.write_str(match self {
3225            AnalyzeFormat::TEXT => "TEXT",
3226            AnalyzeFormat::GRAPHVIZ => "GRAPHVIZ",
3227            AnalyzeFormat::JSON => "JSON",
3228        })
3229    }
3230}
3231
3232impl fmt::Display for Function {
3233    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3234        if self.special {
3235            write!(f, "{}", self.name)?;
3236        } else {
3237            write!(
3238                f,
3239                "{}({}{})",
3240                self.name,
3241                if self.distinct { "DISTINCT " } else { "" },
3242                display_comma_separated(&self.args),
3243            )?;
3244
3245            if let Some(o) = &self.over {
3246                write!(f, " OVER ({o})")?;
3247            }
3248        }
3249
3250        Ok(())
3251    }
3252}
3253
3254/// External table's available file format
3255#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3256#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3257#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3258pub enum FileFormat {
3259    TEXTFILE,
3260    SEQUENCEFILE,
3261    ORC,
3262    PARQUET,
3263    AVRO,
3264    RCFILE,
3265    JSONFILE,
3266}
3267
3268impl fmt::Display for FileFormat {
3269    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3270        use self::FileFormat::*;
3271        f.write_str(match self {
3272            TEXTFILE => "TEXTFILE",
3273            SEQUENCEFILE => "SEQUENCEFILE",
3274            ORC => "ORC",
3275            PARQUET => "PARQUET",
3276            AVRO => "AVRO",
3277            RCFILE => "RCFILE",
3278            JSONFILE => "JSONFILE",
3279        })
3280    }
3281}
3282
3283/// A `LISTAGG` invocation `LISTAGG( [ DISTINCT ] <expr>[, <separator> ] [ON OVERFLOW <on_overflow>] ) )
3284/// [ WITHIN GROUP (ORDER BY <within_group1>[, ...] ) ]`
3285#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3286#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3287#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3288pub struct ListAgg {
3289    pub distinct: bool,
3290    pub expr: Box<Expr>,
3291    pub separator: Option<Box<Expr>>,
3292    pub on_overflow: Option<ListAggOnOverflow>,
3293    pub within_group: Vec<OrderByExpr>,
3294}
3295
3296impl fmt::Display for ListAgg {
3297    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3298        write!(
3299            f,
3300            "LISTAGG({}{}",
3301            if self.distinct { "DISTINCT " } else { "" },
3302            self.expr
3303        )?;
3304        if let Some(separator) = &self.separator {
3305            write!(f, ", {separator}")?;
3306        }
3307        if let Some(on_overflow) = &self.on_overflow {
3308            write!(f, "{on_overflow}")?;
3309        }
3310        write!(f, ")")?;
3311        if !self.within_group.is_empty() {
3312            write!(
3313                f,
3314                " WITHIN GROUP (ORDER BY {})",
3315                display_comma_separated(&self.within_group)
3316            )?;
3317        }
3318        Ok(())
3319    }
3320}
3321
3322/// The `ON OVERFLOW` clause of a LISTAGG invocation
3323#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3324#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3325#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3326pub enum ListAggOnOverflow {
3327    /// `ON OVERFLOW ERROR`
3328    Error,
3329
3330    /// `ON OVERFLOW TRUNCATE [ <filler> ] WITH[OUT] COUNT`
3331    Truncate {
3332        filler: Option<Box<Expr>>,
3333        with_count: bool,
3334    },
3335}
3336
3337impl fmt::Display for ListAggOnOverflow {
3338    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3339        write!(f, " ON OVERFLOW")?;
3340        match self {
3341            ListAggOnOverflow::Error => write!(f, " ERROR"),
3342            ListAggOnOverflow::Truncate { filler, with_count } => {
3343                write!(f, " TRUNCATE")?;
3344                if let Some(filler) = filler {
3345                    write!(f, " {filler}")?;
3346                }
3347                if *with_count {
3348                    write!(f, " WITH")?;
3349                } else {
3350                    write!(f, " WITHOUT")?;
3351                }
3352                write!(f, " COUNT")
3353            }
3354        }
3355    }
3356}
3357
3358/// An `ARRAY_AGG` invocation `ARRAY_AGG( [ DISTINCT ] <expr> [ORDER BY <expr>] [LIMIT <n>] )`
3359/// Or `ARRAY_AGG( [ DISTINCT ] <expr> ) [ WITHIN GROUP ( ORDER BY <expr> ) ]`
3360/// ORDER BY position is defined differently for BigQuery, Postgres and Snowflake.
3361#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3362#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3363#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3364pub struct ArrayAgg {
3365    pub distinct: bool,
3366    pub expr: Box<Expr>,
3367    pub order_by: Option<Box<OrderByExpr>>,
3368    pub limit: Option<Box<Expr>>,
3369    pub within_group: bool, // order by is used inside a within group or not
3370}
3371
3372impl fmt::Display for ArrayAgg {
3373    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3374        write!(
3375            f,
3376            "ARRAY_AGG({}{}",
3377            if self.distinct { "DISTINCT " } else { "" },
3378            self.expr
3379        )?;
3380        if !self.within_group {
3381            if let Some(order_by) = &self.order_by {
3382                write!(f, " ORDER BY {order_by}")?;
3383            }
3384            if let Some(limit) = &self.limit {
3385                write!(f, " LIMIT {limit}")?;
3386            }
3387        }
3388        write!(f, ")")?;
3389        if self.within_group {
3390            if let Some(order_by) = &self.order_by {
3391                write!(f, " WITHIN GROUP (ORDER BY {order_by})")?;
3392            }
3393        }
3394        Ok(())
3395    }
3396}
3397
3398#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3399#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3400#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3401pub enum ObjectType {
3402    Table,
3403    View,
3404    Index,
3405    Schema,
3406    Role,
3407    Sequence,
3408}
3409
3410impl fmt::Display for ObjectType {
3411    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3412        f.write_str(match self {
3413            ObjectType::Table => "TABLE",
3414            ObjectType::View => "VIEW",
3415            ObjectType::Index => "INDEX",
3416            ObjectType::Schema => "SCHEMA",
3417            ObjectType::Role => "ROLE",
3418            ObjectType::Sequence => "SEQUENCE",
3419        })
3420    }
3421}
3422
3423#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3424#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3425#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3426pub enum KillType {
3427    Connection,
3428    Query,
3429    Mutation,
3430}
3431
3432impl fmt::Display for KillType {
3433    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3434        f.write_str(match self {
3435            // MySQL
3436            KillType::Connection => "CONNECTION",
3437            KillType::Query => "QUERY",
3438            // Clickhouse supports Mutation
3439            KillType::Mutation => "MUTATION",
3440        })
3441    }
3442}
3443
3444#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3445#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3446#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3447pub enum HiveDistributionStyle {
3448    PARTITIONED {
3449        columns: Vec<ColumnDef>,
3450    },
3451    CLUSTERED {
3452        columns: Vec<Ident>,
3453        sorted_by: Vec<ColumnDef>,
3454        num_buckets: i32,
3455    },
3456    SKEWED {
3457        columns: Vec<ColumnDef>,
3458        on: Vec<ColumnDef>,
3459        stored_as_directories: bool,
3460    },
3461    NONE,
3462}
3463
3464#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3465#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3466#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3467pub enum HiveRowFormat {
3468    SERDE { class: String },
3469    DELIMITED,
3470}
3471
3472#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3473#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3474#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3475#[allow(clippy::large_enum_variant)]
3476pub enum HiveIOFormat {
3477    IOF {
3478        input_format: Expr,
3479        output_format: Expr,
3480    },
3481    FileFormat {
3482        format: FileFormat,
3483    },
3484}
3485
3486#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Default)]
3487#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3488#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3489pub struct HiveFormat {
3490    pub row_format: Option<HiveRowFormat>,
3491    pub storage: Option<HiveIOFormat>,
3492    pub location: Option<String>,
3493}
3494
3495#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3496#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3497#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3498pub struct SqlOption {
3499    pub name: Ident,
3500    pub value: Value,
3501}
3502
3503impl fmt::Display for SqlOption {
3504    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3505        write!(f, "{} = {}", self.name, self.value)
3506    }
3507}
3508
3509#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3510#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3511#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3512pub enum TransactionMode {
3513    AccessMode(TransactionAccessMode),
3514    IsolationLevel(TransactionIsolationLevel),
3515}
3516
3517impl fmt::Display for TransactionMode {
3518    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3519        use TransactionMode::*;
3520        match self {
3521            AccessMode(access_mode) => write!(f, "{access_mode}"),
3522            IsolationLevel(iso_level) => write!(f, "ISOLATION LEVEL {iso_level}"),
3523        }
3524    }
3525}
3526
3527#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3528#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3529#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3530pub enum TransactionAccessMode {
3531    ReadOnly,
3532    ReadWrite,
3533}
3534
3535impl fmt::Display for TransactionAccessMode {
3536    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3537        use TransactionAccessMode::*;
3538        f.write_str(match self {
3539            ReadOnly => "READ ONLY",
3540            ReadWrite => "READ WRITE",
3541        })
3542    }
3543}
3544
3545#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3546#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3547#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3548pub enum TransactionIsolationLevel {
3549    ReadUncommitted,
3550    ReadCommitted,
3551    RepeatableRead,
3552    Serializable,
3553}
3554
3555impl fmt::Display for TransactionIsolationLevel {
3556    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3557        use TransactionIsolationLevel::*;
3558        f.write_str(match self {
3559            ReadUncommitted => "READ UNCOMMITTED",
3560            ReadCommitted => "READ COMMITTED",
3561            RepeatableRead => "REPEATABLE READ",
3562            Serializable => "SERIALIZABLE",
3563        })
3564    }
3565}
3566
3567#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3568#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3569#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3570pub enum ShowStatementFilter {
3571    Like(String),
3572    ILike(String),
3573    Where(Expr),
3574}
3575
3576impl fmt::Display for ShowStatementFilter {
3577    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3578        use ShowStatementFilter::*;
3579        match self {
3580            Like(pattern) => write!(f, "LIKE '{}'", value::escape_single_quote_string(pattern)),
3581            ILike(pattern) => write!(f, "ILIKE {}", value::escape_single_quote_string(pattern)),
3582            Where(expr) => write!(f, "WHERE {expr}"),
3583        }
3584    }
3585}
3586
3587/// Sqlite specific syntax
3588///
3589/// See [Sqlite documentation](https://sqlite.org/lang_conflict.html)
3590/// for more details.
3591#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3592#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3593#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3594pub enum SqliteOnConflict {
3595    Rollback,
3596    Abort,
3597    Fail,
3598    Ignore,
3599    Replace,
3600}
3601
3602impl fmt::Display for SqliteOnConflict {
3603    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3604        use SqliteOnConflict::*;
3605        match self {
3606            Rollback => write!(f, "ROLLBACK"),
3607            Abort => write!(f, "ABORT"),
3608            Fail => write!(f, "FAIL"),
3609            Ignore => write!(f, "IGNORE"),
3610            Replace => write!(f, "REPLACE"),
3611        }
3612    }
3613}
3614
3615#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3616#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3617#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3618pub enum CopyTarget {
3619    Stdin,
3620    Stdout,
3621    File {
3622        /// The path name of the input or output file.
3623        filename: String,
3624    },
3625    Program {
3626        /// A command to execute
3627        command: String,
3628    },
3629}
3630
3631impl fmt::Display for CopyTarget {
3632    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3633        use CopyTarget::*;
3634        match self {
3635            Stdin { .. } => write!(f, "STDIN"),
3636            Stdout => write!(f, "STDOUT"),
3637            File { filename } => write!(f, "'{}'", value::escape_single_quote_string(filename)),
3638            Program { command } => write!(
3639                f,
3640                "PROGRAM '{}'",
3641                value::escape_single_quote_string(command)
3642            ),
3643        }
3644    }
3645}
3646
3647#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3648#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3649#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3650pub enum OnCommit {
3651    DeleteRows,
3652    PreserveRows,
3653    Drop,
3654}
3655
3656/// An option in `COPY` statement.
3657///
3658/// <https://www.postgresql.org/docs/14/sql-copy.html>
3659#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3660#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3661#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3662pub enum CopyOption {
3663    /// FORMAT format_name
3664    Format(Ident),
3665    /// FREEZE \[ boolean \]
3666    Freeze(bool),
3667    /// DELIMITER 'delimiter_character'
3668    Delimiter(char),
3669    /// NULL 'null_string'
3670    Null(String),
3671    /// HEADER \[ boolean \]
3672    Header(bool),
3673    /// QUOTE 'quote_character'
3674    Quote(char),
3675    /// ESCAPE 'escape_character'
3676    Escape(char),
3677    /// FORCE_QUOTE { ( column_name [, ...] ) | * }
3678    ForceQuote(Vec<Ident>),
3679    /// FORCE_NOT_NULL ( column_name [, ...] )
3680    ForceNotNull(Vec<Ident>),
3681    /// FORCE_NULL ( column_name [, ...] )
3682    ForceNull(Vec<Ident>),
3683    /// ENCODING 'encoding_name'
3684    Encoding(String),
3685}
3686
3687impl fmt::Display for CopyOption {
3688    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3689        use CopyOption::*;
3690        match self {
3691            Format(name) => write!(f, "FORMAT {name}"),
3692            Freeze(true) => write!(f, "FREEZE"),
3693            Freeze(false) => write!(f, "FREEZE FALSE"),
3694            Delimiter(char) => write!(f, "DELIMITER '{char}'"),
3695            Null(string) => write!(f, "NULL '{}'", value::escape_single_quote_string(string)),
3696            Header(true) => write!(f, "HEADER"),
3697            Header(false) => write!(f, "HEADER FALSE"),
3698            Quote(char) => write!(f, "QUOTE '{char}'"),
3699            Escape(char) => write!(f, "ESCAPE '{char}'"),
3700            ForceQuote(columns) => write!(f, "FORCE_QUOTE ({})", display_comma_separated(columns)),
3701            ForceNotNull(columns) => {
3702                write!(f, "FORCE_NOT_NULL ({})", display_comma_separated(columns))
3703            }
3704            ForceNull(columns) => write!(f, "FORCE_NULL ({})", display_comma_separated(columns)),
3705            Encoding(name) => write!(f, "ENCODING '{}'", value::escape_single_quote_string(name)),
3706        }
3707    }
3708}
3709
3710/// An option in `COPY` statement before PostgreSQL version 9.0.
3711///
3712/// <https://www.postgresql.org/docs/8.4/sql-copy.html>
3713#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3714#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3715#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3716pub enum CopyLegacyOption {
3717    /// BINARY
3718    Binary,
3719    /// DELIMITER \[ AS \] 'delimiter_character'
3720    Delimiter(char),
3721    /// NULL \[ AS \] 'null_string'
3722    Null(String),
3723    /// CSV ...
3724    Csv(Vec<CopyLegacyCsvOption>),
3725}
3726
3727impl fmt::Display for CopyLegacyOption {
3728    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3729        use CopyLegacyOption::*;
3730        match self {
3731            Binary => write!(f, "BINARY"),
3732            Delimiter(char) => write!(f, "DELIMITER '{char}'"),
3733            Null(string) => write!(f, "NULL '{}'", value::escape_single_quote_string(string)),
3734            Csv(opts) => write!(f, "CSV {}", display_separated(opts, " ")),
3735        }
3736    }
3737}
3738
3739/// A `CSV` option in `COPY` statement before PostgreSQL version 9.0.
3740///
3741/// <https://www.postgresql.org/docs/8.4/sql-copy.html>
3742#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3743#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3744#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3745pub enum CopyLegacyCsvOption {
3746    /// HEADER
3747    Header,
3748    /// QUOTE \[ AS \] 'quote_character'
3749    Quote(char),
3750    /// ESCAPE \[ AS \] 'escape_character'
3751    Escape(char),
3752    /// FORCE QUOTE { column_name [, ...] | * }
3753    ForceQuote(Vec<Ident>),
3754    /// FORCE NOT NULL column_name [, ...]
3755    ForceNotNull(Vec<Ident>),
3756}
3757
3758impl fmt::Display for CopyLegacyCsvOption {
3759    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3760        use CopyLegacyCsvOption::*;
3761        match self {
3762            Header => write!(f, "HEADER"),
3763            Quote(char) => write!(f, "QUOTE '{char}'"),
3764            Escape(char) => write!(f, "ESCAPE '{char}'"),
3765            ForceQuote(columns) => write!(f, "FORCE QUOTE {}", display_comma_separated(columns)),
3766            ForceNotNull(columns) => {
3767                write!(f, "FORCE NOT NULL {}", display_comma_separated(columns))
3768            }
3769        }
3770    }
3771}
3772
3773///
3774#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3775#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3776#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3777pub enum MergeClause {
3778    MatchedUpdate {
3779        predicate: Option<Expr>,
3780        assignments: Vec<Assignment>,
3781    },
3782    MatchedDelete(Option<Expr>),
3783    NotMatched {
3784        predicate: Option<Expr>,
3785        columns: Vec<Ident>,
3786        values: Values,
3787    },
3788}
3789
3790impl fmt::Display for MergeClause {
3791    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3792        use MergeClause::*;
3793        write!(f, "WHEN")?;
3794        match self {
3795            MatchedUpdate {
3796                predicate,
3797                assignments,
3798            } => {
3799                write!(f, " MATCHED")?;
3800                if let Some(pred) = predicate {
3801                    write!(f, " AND {pred}")?;
3802                }
3803                write!(
3804                    f,
3805                    " THEN UPDATE SET {}",
3806                    display_comma_separated(assignments)
3807                )
3808            }
3809            MatchedDelete(predicate) => {
3810                write!(f, " MATCHED")?;
3811                if let Some(pred) = predicate {
3812                    write!(f, " AND {pred}")?;
3813                }
3814                write!(f, " THEN DELETE")
3815            }
3816            NotMatched {
3817                predicate,
3818                columns,
3819                values,
3820            } => {
3821                write!(f, " NOT MATCHED")?;
3822                if let Some(pred) = predicate {
3823                    write!(f, " AND {pred}")?;
3824                }
3825                write!(
3826                    f,
3827                    " THEN INSERT ({}) {}",
3828                    display_comma_separated(columns),
3829                    values
3830                )
3831            }
3832        }
3833    }
3834}
3835
3836#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3837#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3838#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3839pub enum DiscardObject {
3840    ALL,
3841    PLANS,
3842    SEQUENCES,
3843    TEMP,
3844}
3845
3846impl fmt::Display for DiscardObject {
3847    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3848        match self {
3849            DiscardObject::ALL => f.write_str("ALL"),
3850            DiscardObject::PLANS => f.write_str("PLANS"),
3851            DiscardObject::SEQUENCES => f.write_str("SEQUENCES"),
3852            DiscardObject::TEMP => f.write_str("TEMP"),
3853        }
3854    }
3855}
3856
3857/// Optional context modifier for statements that can be or `LOCAL`, or `SESSION`.
3858#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3859#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3860#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3861pub enum ContextModifier {
3862    /// No context defined. Each dialect defines the default in this scenario.
3863    None,
3864    /// `LOCAL` identifier, usually related to transactional states.
3865    Local,
3866    /// `SESSION` identifier
3867    Session,
3868}
3869
3870impl fmt::Display for ContextModifier {
3871    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3872        match self {
3873            Self::None => {
3874                write!(f, "")
3875            }
3876            Self::Local => {
3877                write!(f, " LOCAL")
3878            }
3879            Self::Session => {
3880                write!(f, " SESSION")
3881            }
3882        }
3883    }
3884}
3885
3886/// Function describe in DROP FUNCTION.
3887#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3888#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3889pub enum DropFunctionOption {
3890    Restrict,
3891    Cascade,
3892}
3893
3894impl fmt::Display for DropFunctionOption {
3895    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3896        match self {
3897            DropFunctionOption::Restrict => write!(f, "RESTRICT "),
3898            DropFunctionOption::Cascade => write!(f, "CASCADE  "),
3899        }
3900    }
3901}
3902
3903/// Function describe in DROP FUNCTION.
3904#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3905#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3906#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3907pub struct DropFunctionDesc {
3908    pub name: ObjectName,
3909    pub args: Option<Vec<OperateFunctionArg>>,
3910}
3911
3912impl fmt::Display for DropFunctionDesc {
3913    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3914        write!(f, "{}", self.name)?;
3915        if let Some(args) = &self.args {
3916            write!(f, "({})", display_comma_separated(args))?;
3917        }
3918        Ok(())
3919    }
3920}
3921
3922/// Function argument in CREATE OR DROP FUNCTION.
3923#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3924#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3925#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3926pub struct OperateFunctionArg {
3927    pub mode: Option<ArgMode>,
3928    pub name: Option<Ident>,
3929    pub data_type: DataType,
3930    pub default_expr: Option<Expr>,
3931}
3932
3933impl OperateFunctionArg {
3934    /// Returns an unnamed argument.
3935    pub fn unnamed(data_type: DataType) -> Self {
3936        Self {
3937            mode: None,
3938            name: None,
3939            data_type,
3940            default_expr: None,
3941        }
3942    }
3943
3944    /// Returns an argument with name.
3945    pub fn with_name(name: &str, data_type: DataType) -> Self {
3946        Self {
3947            mode: None,
3948            name: Some(name.into()),
3949            data_type,
3950            default_expr: None,
3951        }
3952    }
3953}
3954
3955impl fmt::Display for OperateFunctionArg {
3956    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3957        if let Some(mode) = &self.mode {
3958            write!(f, "{mode} ")?;
3959        }
3960        if let Some(name) = &self.name {
3961            write!(f, "{name} ")?;
3962        }
3963        write!(f, "{}", self.data_type)?;
3964        if let Some(default_expr) = &self.default_expr {
3965            write!(f, " = {default_expr}")?;
3966        }
3967        Ok(())
3968    }
3969}
3970
3971/// The mode of an argument in CREATE FUNCTION.
3972#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3973#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3974#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3975pub enum ArgMode {
3976    In,
3977    Out,
3978    InOut,
3979}
3980
3981impl fmt::Display for ArgMode {
3982    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3983        match self {
3984            ArgMode::In => write!(f, "IN"),
3985            ArgMode::Out => write!(f, "OUT"),
3986            ArgMode::InOut => write!(f, "INOUT"),
3987        }
3988    }
3989}
3990
3991/// These attributes inform the query optimizer about the behavior of the function.
3992#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3993#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3994#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3995pub enum FunctionBehavior {
3996    Immutable,
3997    Stable,
3998    Volatile,
3999}
4000
4001impl fmt::Display for FunctionBehavior {
4002    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
4003        match self {
4004            FunctionBehavior::Immutable => write!(f, "IMMUTABLE"),
4005            FunctionBehavior::Stable => write!(f, "STABLE"),
4006            FunctionBehavior::Volatile => write!(f, "VOLATILE"),
4007        }
4008    }
4009}
4010
4011#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
4012#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4013#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
4014pub enum FunctionDefinition {
4015    SingleQuotedDef(String),
4016    DoubleDollarDef(String),
4017}
4018
4019impl fmt::Display for FunctionDefinition {
4020    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
4021        match self {
4022            FunctionDefinition::SingleQuotedDef(s) => write!(f, "'{s}'")?,
4023            FunctionDefinition::DoubleDollarDef(s) => write!(f, "$${s}$$")?,
4024        }
4025        Ok(())
4026    }
4027}
4028
4029/// Postgres specific feature.
4030///
4031/// See [Postgresdocs](https://www.postgresql.org/docs/15/sql-createfunction.html)
4032/// for more details
4033#[derive(Debug, Default, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
4034#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4035#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
4036pub struct CreateFunctionBody {
4037    /// LANGUAGE lang_name
4038    pub language: Option<Ident>,
4039    /// IMMUTABLE | STABLE | VOLATILE
4040    pub behavior: Option<FunctionBehavior>,
4041    /// AS 'definition'
4042    ///
4043    /// Note that Hive's `AS class_name` is also parsed here.
4044    pub as_: Option<FunctionDefinition>,
4045    /// RETURN expression
4046    pub return_: Option<Expr>,
4047    /// USING ... (Hive only)
4048    pub using: Option<CreateFunctionUsing>,
4049}
4050
4051impl fmt::Display for CreateFunctionBody {
4052    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
4053        if let Some(language) = &self.language {
4054            write!(f, " LANGUAGE {language}")?;
4055        }
4056        if let Some(behavior) = &self.behavior {
4057            write!(f, " {behavior}")?;
4058        }
4059        if let Some(definition) = &self.as_ {
4060            write!(f, " AS {definition}")?;
4061        }
4062        if let Some(expr) = &self.return_ {
4063            write!(f, " RETURN {expr}")?;
4064        }
4065        if let Some(using) = &self.using {
4066            write!(f, " {using}")?;
4067        }
4068        Ok(())
4069    }
4070}
4071
4072#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
4073#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4074#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
4075pub enum CreateFunctionUsing {
4076    Jar(String),
4077    File(String),
4078    Archive(String),
4079}
4080
4081impl fmt::Display for CreateFunctionUsing {
4082    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
4083        write!(f, "USING ")?;
4084        match self {
4085            CreateFunctionUsing::Jar(uri) => write!(f, "JAR '{uri}'"),
4086            CreateFunctionUsing::File(uri) => write!(f, "FILE '{uri}'"),
4087            CreateFunctionUsing::Archive(uri) => write!(f, "ARCHIVE '{uri}'"),
4088        }
4089    }
4090}
4091
4092/// Schema possible naming variants ([1]).
4093///
4094/// [1]: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#schema-definition
4095#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
4096#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4097#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
4098pub enum SchemaName {
4099    /// Only schema name specified: `<schema name>`.
4100    Simple(ObjectName),
4101    /// Only authorization identifier specified: `AUTHORIZATION <schema authorization identifier>`.
4102    UnnamedAuthorization(Ident),
4103    /// Both schema name and authorization identifier specified: `<schema name>  AUTHORIZATION <schema authorization identifier>`.
4104    NamedAuthorization(ObjectName, Ident),
4105}
4106
4107impl fmt::Display for SchemaName {
4108    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
4109        match self {
4110            SchemaName::Simple(name) => {
4111                write!(f, "{name}")
4112            }
4113            SchemaName::UnnamedAuthorization(authorization) => {
4114                write!(f, "AUTHORIZATION {authorization}")
4115            }
4116            SchemaName::NamedAuthorization(name, authorization) => {
4117                write!(f, "{name} AUTHORIZATION {authorization}")
4118            }
4119        }
4120    }
4121}
4122
4123/// Fulltext search modifiers ([1]).
4124///
4125/// [1]: https://dev.mysql.com/doc/refman/8.0/en/fulltext-search.html#function_match
4126#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
4127#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4128#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
4129pub enum SearchModifier {
4130    /// `IN NATURAL LANGUAGE MODE`.
4131    InNaturalLanguageMode,
4132    /// `IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION`.
4133    InNaturalLanguageModeWithQueryExpansion,
4134    ///`IN BOOLEAN MODE`.
4135    InBooleanMode,
4136    ///`WITH QUERY EXPANSION`.
4137    WithQueryExpansion,
4138}
4139
4140impl fmt::Display for SearchModifier {
4141    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
4142        match self {
4143            Self::InNaturalLanguageMode => {
4144                write!(f, "IN NATURAL LANGUAGE MODE")?;
4145            }
4146            Self::InNaturalLanguageModeWithQueryExpansion => {
4147                write!(f, "IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION")?;
4148            }
4149            Self::InBooleanMode => {
4150                write!(f, "IN BOOLEAN MODE")?;
4151            }
4152            Self::WithQueryExpansion => {
4153                write!(f, "WITH QUERY EXPANSION")?;
4154            }
4155        }
4156
4157        Ok(())
4158    }
4159}
4160
4161#[cfg(test)]
4162mod tests {
4163    use super::*;
4164
4165    #[test]
4166    fn test_window_frame_default() {
4167        let window_frame = WindowFrame::default();
4168        assert_eq!(WindowFrameBound::Preceding(None), window_frame.start_bound);
4169    }
4170
4171    #[test]
4172    fn test_grouping_sets_display() {
4173        // a and b in different group
4174        let grouping_sets = Expr::GroupingSets(vec![
4175            vec![Expr::Identifier(Ident::new("a"))],
4176            vec![Expr::Identifier(Ident::new("b"))],
4177        ]);
4178        assert_eq!("GROUPING SETS ((a), (b))", format!("{grouping_sets}"));
4179
4180        // a and b in the same group
4181        let grouping_sets = Expr::GroupingSets(vec![vec![
4182            Expr::Identifier(Ident::new("a")),
4183            Expr::Identifier(Ident::new("b")),
4184        ]]);
4185        assert_eq!("GROUPING SETS ((a, b))", format!("{grouping_sets}"));
4186
4187        // (a, b) and (c, d) in different group
4188        let grouping_sets = Expr::GroupingSets(vec![
4189            vec![
4190                Expr::Identifier(Ident::new("a")),
4191                Expr::Identifier(Ident::new("b")),
4192            ],
4193            vec![
4194                Expr::Identifier(Ident::new("c")),
4195                Expr::Identifier(Ident::new("d")),
4196            ],
4197        ]);
4198        assert_eq!("GROUPING SETS ((a, b), (c, d))", format!("{grouping_sets}"));
4199    }
4200
4201    #[test]
4202    fn test_rollup_display() {
4203        let rollup = Expr::Rollup(vec![vec![Expr::Identifier(Ident::new("a"))]]);
4204        assert_eq!("ROLLUP (a)", format!("{rollup}"));
4205
4206        let rollup = Expr::Rollup(vec![vec![
4207            Expr::Identifier(Ident::new("a")),
4208            Expr::Identifier(Ident::new("b")),
4209        ]]);
4210        assert_eq!("ROLLUP ((a, b))", format!("{rollup}"));
4211
4212        let rollup = Expr::Rollup(vec![
4213            vec![Expr::Identifier(Ident::new("a"))],
4214            vec![Expr::Identifier(Ident::new("b"))],
4215        ]);
4216        assert_eq!("ROLLUP (a, b)", format!("{rollup}"));
4217
4218        let rollup = Expr::Rollup(vec![
4219            vec![Expr::Identifier(Ident::new("a"))],
4220            vec![
4221                Expr::Identifier(Ident::new("b")),
4222                Expr::Identifier(Ident::new("c")),
4223            ],
4224            vec![Expr::Identifier(Ident::new("d"))],
4225        ]);
4226        assert_eq!("ROLLUP (a, (b, c), d)", format!("{rollup}"));
4227    }
4228
4229    #[test]
4230    fn test_cube_display() {
4231        let cube = Expr::Cube(vec![vec![Expr::Identifier(Ident::new("a"))]]);
4232        assert_eq!("CUBE (a)", format!("{cube}"));
4233
4234        let cube = Expr::Cube(vec![vec![
4235            Expr::Identifier(Ident::new("a")),
4236            Expr::Identifier(Ident::new("b")),
4237        ]]);
4238        assert_eq!("CUBE ((a, b))", format!("{cube}"));
4239
4240        let cube = Expr::Cube(vec![
4241            vec![Expr::Identifier(Ident::new("a"))],
4242            vec![Expr::Identifier(Ident::new("b"))],
4243        ]);
4244        assert_eq!("CUBE (a, b)", format!("{cube}"));
4245
4246        let cube = Expr::Cube(vec![
4247            vec![Expr::Identifier(Ident::new("a"))],
4248            vec![
4249                Expr::Identifier(Ident::new("b")),
4250                Expr::Identifier(Ident::new("c")),
4251            ],
4252            vec![Expr::Identifier(Ident::new("d"))],
4253        ]);
4254        assert_eq!("CUBE (a, (b, c), d)", format!("{cube}"));
4255    }
4256}