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