sqlparser/ast/
mod.rs

1// Licensed to the Apache Software Foundation (ASF) under one
2// or more contributor license agreements.  See the NOTICE file
3// distributed with this work for additional information
4// regarding copyright ownership.  The ASF licenses this file
5// to you under the Apache License, Version 2.0 (the
6// "License"); you may not use this file except in compliance
7// with the License.  You may obtain a copy of the License at
8//
9//   http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing,
12// software distributed under the License is distributed on an
13// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14// KIND, either express or implied.  See the License for the
15// specific language governing permissions and limitations
16// under the License.
17
18//! SQL Abstract Syntax Tree (AST) types
19#[cfg(not(feature = "std"))]
20use alloc::{
21    boxed::Box,
22    format,
23    string::{String, ToString},
24    vec,
25    vec::Vec,
26};
27use helpers::{
28    attached_token::AttachedToken,
29    stmt_data_loading::{FileStagingCommand, StageLoadSelectItemKind},
30};
31
32use core::cmp::Ordering;
33use core::ops::Deref;
34use core::{
35    fmt::{self, Display},
36    hash,
37};
38
39#[cfg(feature = "serde")]
40use serde::{Deserialize, Serialize};
41
42#[cfg(feature = "visitor")]
43use yachtsql_sqlparser_derive::{Visit, VisitMut};
44
45use crate::{
46    display_utils::{indented_list, SpaceOrNewline},
47    tokenizer::{Span, Token},
48};
49use crate::{
50    display_utils::{Indent, NewLine},
51    keywords::Keyword,
52};
53
54pub use self::data_type::{
55    ArrayElemTypeDef, BinaryLength, CharLengthUnits, CharacterLength, DataType, EnumMember,
56    ExactNumberInfo, IntervalFields, StructBracketKind, TimezoneInfo,
57};
58pub use self::dcl::{
59    AlterRoleOperation, ResetConfig, RoleOption, SecondaryRoles, SetConfigValue, Use,
60};
61pub use self::ddl::{
62    AlterColumnOperation, AlterConnectorOwner, AlterIndexOperation, AlterPolicyOperation,
63    AlterSchema, AlterSchemaOperation, AlterTableAlgorithm, AlterTableLock, AlterTableOperation, AlterViewOperation,
64    AlterType, AlterTypeAddValue, AlterTypeAddValuePosition, AlterTypeOperation, AlterTypeRename,
65    AlterTypeRenameValue, ClusteredBy, ColumnDef, ColumnOption, ColumnOptionDef, ColumnOptions,
66    ColumnPolicy, ColumnPolicyProperty, ConstraintCharacteristics, CreateConnector, CreateDomain,
67    CreateFunction, CreateIndex, CreateTable, CreateTrigger, Deduplicate, DeferrableInitial,
68    DropBehavior, DropTrigger, GeneratedAs, GeneratedExpressionMode, IdentityParameters,
69    IdentityProperty, IdentityPropertyFormatKind, IdentityPropertyKind, IdentityPropertyOrder,
70    IndexColumn, IndexOption, IndexType, KeyOrIndexDisplay, NullsDistinctOption, Owner, Partition,
71    ProcedureParam, ReferentialAction, RenameTableNameKind, ReplicaIdentity, SqlSecurity,
72    TableConstraint, TagsColumnOption, UserDefinedTypeCompositeAttributeDef,
73    UserDefinedTypeRepresentation, ViewColumnDef,
74};
75pub use self::dml::{Delete, Insert};
76pub use self::operator::{BinaryOperator, UnaryOperator};
77pub use self::query::{
78    AfterMatchSkip, ConnectBy, Cte, CteAsMaterialized, Distinct, EmptyMatchesMode,
79    ExceptSelectItem, ExcludeSelectItem, ExprWithAlias, ExprWithAliasAndOrderBy, Fetch, ForClause,
80    ForJson, ForXml, FormatClause, GroupByExpr, GroupByWithModifier, IdentWithAlias,
81    IlikeSelectItem, InputFormatClause, Interpolate, InterpolateExpr, Join, JoinConstraint,
82    JoinOperator, JsonTableColumn, JsonTableColumnErrorHandling, JsonTableNamedColumn,
83    JsonTableNestedColumn, LateralView, LimitClause, LockClause, LockType, MatchRecognizePattern,
84    MatchRecognizeSymbol, Measure, NamedWindowDefinition, NamedWindowExpr, NonBlock, Offset,
85    OffsetRows, OpenJsonTableColumn, OrderBy, OrderByExpr, OrderByKind, OrderByOptions,
86    PipeOperator, PivotValueSource, ProjectionSelect, Query, RenameSelectItem,
87    RepetitionQuantifier, ReplaceSelectElement, ReplaceSelectItem, RowsPerMatch, Select,
88    SelectFlavor, SelectInto, SelectItem, SelectItemQualifiedWildcardKind, SetExpr, SetOperator,
89    SetQuantifier, Setting, SymbolDefinition, Table, TableAlias, TableAliasColumnDef, TableFactor,
90    TableFunctionArgs, TableIndexHintForClause, TableIndexHintType, TableIndexHints,
91    TableIndexType, TableSample, TableSampleBucket, TableSampleKind, TableSampleMethod,
92    TableSampleModifier, TableSampleQuantity, TableSampleSeed, TableSampleSeedModifier,
93    TableSampleUnit, TableVersion, TableWithJoins, Top, TopQuantity, UpdateTableFromKind,
94    ValueTableMode, Values, WildcardAdditionalOptions, With, WithFill, XmlNamespaceDefinition,
95    XmlPassingArgument, XmlPassingClause, XmlTableColumn, XmlTableColumnOption,
96};
97
98pub use self::trigger::{
99    TriggerEvent, TriggerExecBody, TriggerExecBodyType, TriggerObject, TriggerPeriod,
100    TriggerReferencing, TriggerReferencingType,
101};
102
103pub use self::value::{
104    escape_double_quote_string, escape_quoted_string, DateTimeField, DollarQuotedString,
105    NormalizationForm, TrimWhereField, Value, ValueWithSpan,
106};
107
108use crate::ast::helpers::key_value_options::KeyValueOptions;
109use crate::ast::helpers::stmt_data_loading::StageParamsObject;
110
111#[cfg(feature = "visitor")]
112pub use visitor::*;
113
114pub use self::data_type::GeometricTypeKind;
115
116mod data_type;
117mod dcl;
118mod ddl;
119mod dml;
120pub mod helpers;
121mod operator;
122mod query;
123mod spans;
124pub use spans::Spanned;
125
126mod trigger;
127mod value;
128
129#[cfg(feature = "visitor")]
130mod visitor;
131
132pub struct DisplaySeparated<'a, T>
133where
134    T: fmt::Display,
135{
136    slice: &'a [T],
137    sep: &'static str,
138}
139
140impl<T> fmt::Display for DisplaySeparated<'_, T>
141where
142    T: fmt::Display,
143{
144    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
145        let mut delim = "";
146        for t in self.slice {
147            f.write_str(delim)?;
148            delim = self.sep;
149            t.fmt(f)?;
150        }
151        Ok(())
152    }
153}
154
155pub fn display_separated<'a, T>(slice: &'a [T], sep: &'static str) -> DisplaySeparated<'a, T>
156where
157    T: fmt::Display,
158{
159    DisplaySeparated { slice, sep }
160}
161
162pub fn display_comma_separated<T>(slice: &[T]) -> DisplaySeparated<'_, T>
163where
164    T: fmt::Display,
165{
166    DisplaySeparated { slice, sep: ", " }
167}
168
169/// Writes the given statements to the formatter, each ending with
170/// a semicolon and space separated.
171fn format_statement_list(f: &mut fmt::Formatter, statements: &[Statement]) -> fmt::Result {
172    write!(f, "{}", display_separated(statements, "; "))?;
173    // We manually insert semicolon for the last statement,
174    // since display_separated doesn't handle that case.
175    write!(f, ";")
176}
177
178/// An identifier, decomposed into its value or character data and the quote style.
179#[derive(Debug, Clone)]
180#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
181#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
182pub struct Ident {
183    /// The value of the identifier without quotes.
184    pub value: String,
185    /// The starting quote if any. Valid quote characters are the single quote,
186    /// double quote, backtick, and opening square bracket.
187    pub quote_style: Option<char>,
188    /// The span of the identifier in the original SQL string.
189    pub span: Span,
190}
191
192impl PartialEq for Ident {
193    fn eq(&self, other: &Self) -> bool {
194        let Ident {
195            value,
196            quote_style,
197            // exhaustiveness check; we ignore spans in comparisons
198            span: _,
199        } = self;
200
201        value == &other.value && quote_style == &other.quote_style
202    }
203}
204
205impl core::hash::Hash for Ident {
206    fn hash<H: hash::Hasher>(&self, state: &mut H) {
207        let Ident {
208            value,
209            quote_style,
210            // exhaustiveness check; we ignore spans in hashes
211            span: _,
212        } = self;
213
214        value.hash(state);
215        quote_style.hash(state);
216    }
217}
218
219impl Eq for Ident {}
220
221impl PartialOrd for Ident {
222    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
223        Some(self.cmp(other))
224    }
225}
226
227impl Ord for Ident {
228    fn cmp(&self, other: &Self) -> Ordering {
229        let Ident {
230            value,
231            quote_style,
232            // exhaustiveness check; we ignore spans in ordering
233            span: _,
234        } = self;
235
236        let Ident {
237            value: other_value,
238            quote_style: other_quote_style,
239            // exhaustiveness check; we ignore spans in ordering
240            span: _,
241        } = other;
242
243        // First compare by value, then by quote_style
244        value
245            .cmp(other_value)
246            .then_with(|| quote_style.cmp(other_quote_style))
247    }
248}
249
250impl Ident {
251    /// Create a new identifier with the given value and no quotes and an empty span.
252    pub fn new<S>(value: S) -> Self
253    where
254        S: Into<String>,
255    {
256        Ident {
257            value: value.into(),
258            quote_style: None,
259            span: Span::empty(),
260        }
261    }
262
263    /// Create a new quoted identifier with the given quote and value. This function
264    /// panics if the given quote is not a valid quote character.
265    pub fn with_quote<S>(quote: char, value: S) -> Self
266    where
267        S: Into<String>,
268    {
269        assert!(quote == '\'' || quote == '"' || quote == '`' || quote == '[');
270        Ident {
271            value: value.into(),
272            quote_style: Some(quote),
273            span: Span::empty(),
274        }
275    }
276
277    pub fn with_span<S>(span: Span, value: S) -> Self
278    where
279        S: Into<String>,
280    {
281        Ident {
282            value: value.into(),
283            quote_style: None,
284            span,
285        }
286    }
287
288    pub fn with_quote_and_span<S>(quote: char, span: Span, value: S) -> Self
289    where
290        S: Into<String>,
291    {
292        assert!(quote == '\'' || quote == '"' || quote == '`' || quote == '[');
293        Ident {
294            value: value.into(),
295            quote_style: Some(quote),
296            span,
297        }
298    }
299}
300
301impl From<&str> for Ident {
302    fn from(value: &str) -> Self {
303        Ident {
304            value: value.to_string(),
305            quote_style: None,
306            span: Span::empty(),
307        }
308    }
309}
310
311impl fmt::Display for Ident {
312    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
313        match self.quote_style {
314            Some(q) if q == '"' || q == '\'' || q == '`' => {
315                let escaped = value::escape_quoted_string(&self.value, q);
316                write!(f, "{q}{escaped}{q}")
317            }
318            Some('[') => write!(f, "[{}]", self.value),
319            None => f.write_str(&self.value),
320            _ => panic!("unexpected quote style"),
321        }
322    }
323}
324
325/// A name of a table, view, custom type, etc., possibly multi-part, i.e. db.schema.obj
326#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
327#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
328#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
329pub struct ObjectName(pub Vec<ObjectNamePart>);
330
331impl From<Vec<Ident>> for ObjectName {
332    fn from(idents: Vec<Ident>) -> Self {
333        ObjectName(idents.into_iter().map(ObjectNamePart::Identifier).collect())
334    }
335}
336
337impl fmt::Display for ObjectName {
338    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
339        write!(f, "{}", display_separated(&self.0, "."))
340    }
341}
342
343/// A single part of an ObjectName
344#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
345#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
346#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
347pub enum ObjectNamePart {
348    Identifier(Ident),
349    Function(ObjectNamePartFunction),
350}
351
352impl ObjectNamePart {
353    pub fn as_ident(&self) -> Option<&Ident> {
354        match self {
355            ObjectNamePart::Identifier(ident) => Some(ident),
356            ObjectNamePart::Function(_) => None,
357        }
358    }
359}
360
361impl fmt::Display for ObjectNamePart {
362    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
363        match self {
364            ObjectNamePart::Identifier(ident) => write!(f, "{ident}"),
365            ObjectNamePart::Function(func) => write!(f, "{func}"),
366        }
367    }
368}
369
370/// An object name part that consists of a function that dynamically
371/// constructs identifiers.
372///
373/// - [Snowflake](https://docs.snowflake.com/en/sql-reference/identifier-literal)
374#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
375#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
376#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
377pub struct ObjectNamePartFunction {
378    pub name: Ident,
379    pub args: Vec<FunctionArg>,
380}
381
382impl fmt::Display for ObjectNamePartFunction {
383    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
384        write!(f, "{}(", self.name)?;
385        write!(f, "{})", display_comma_separated(&self.args))
386    }
387}
388
389/// Represents an Array Expression, either
390/// `ARRAY[..]`, or `[..]`
391#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
392#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
393#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
394pub struct Array {
395    /// The list of expressions between brackets
396    pub elem: Vec<Expr>,
397
398    /// `true` for  `ARRAY[..]`, `false` for `[..]`
399    pub named: bool,
400
401    /// Optional element type for typed array literals like `ARRAY<INT64>[1, 2, 3]`
402    pub element_type: Option<Box<DataType>>,
403}
404
405impl fmt::Display for Array {
406    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
407        if self.named {
408            write!(f, "ARRAY")?;
409        }
410        if let Some(ref elem_type) = self.element_type {
411            write!(f, "<{}>", elem_type)?;
412        }
413        write!(f, "[{}]", display_comma_separated(&self.elem))
414    }
415}
416
417/// Represents an INTERVAL expression, roughly in the following format:
418/// `INTERVAL '<value>' [ <leading_field> [ (<leading_precision>) ] ]
419/// [ TO <last_field> [ (<fractional_seconds_precision>) ] ]`,
420/// e.g. `INTERVAL '123:45.67' MINUTE(3) TO SECOND(2)`.
421///
422/// The parser does not validate the `<value>`, nor does it ensure
423/// that the `<leading_field>` units >= the units in `<last_field>`,
424/// so the user will have to reject intervals like `HOUR TO YEAR`.
425#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
426#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
427#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
428pub struct Interval {
429    pub value: Box<Expr>,
430    pub leading_field: Option<DateTimeField>,
431    pub leading_precision: Option<u64>,
432    pub last_field: Option<DateTimeField>,
433    /// The seconds precision can be specified in SQL source as
434    /// `INTERVAL '__' SECOND(_, x)` (in which case the `leading_field`
435    /// will be `Second` and the `last_field` will be `None`),
436    /// or as `__ TO SECOND(x)`.
437    pub fractional_seconds_precision: Option<u64>,
438}
439
440impl fmt::Display for Interval {
441    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
442        let value = self.value.as_ref();
443        match (
444            &self.leading_field,
445            self.leading_precision,
446            self.fractional_seconds_precision,
447        ) {
448            (
449                Some(DateTimeField::Second),
450                Some(leading_precision),
451                Some(fractional_seconds_precision),
452            ) => {
453                // When the leading field is SECOND, the parser guarantees that
454                // the last field is None.
455                assert!(self.last_field.is_none());
456                write!(
457                    f,
458                    "INTERVAL {value} SECOND ({leading_precision}, {fractional_seconds_precision})"
459                )
460            }
461            _ => {
462                write!(f, "INTERVAL {value}")?;
463                if let Some(leading_field) = &self.leading_field {
464                    write!(f, " {leading_field}")?;
465                }
466                if let Some(leading_precision) = self.leading_precision {
467                    write!(f, " ({leading_precision})")?;
468                }
469                if let Some(last_field) = &self.last_field {
470                    write!(f, " TO {last_field}")?;
471                }
472                if let Some(fractional_seconds_precision) = self.fractional_seconds_precision {
473                    write!(f, " ({fractional_seconds_precision})")?;
474                }
475                Ok(())
476            }
477        }
478    }
479}
480
481/// A field definition within a struct
482///
483/// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-types#struct_type
484#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
485#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
486#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
487pub struct StructField {
488    pub field_name: Option<Ident>,
489    pub field_type: DataType,
490    /// Whether the field is NOT NULL
491    pub not_null: bool,
492    /// Struct field options.
493    /// See [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#column_name_and_column_schema)
494    pub options: Option<Vec<SqlOption>>,
495}
496
497impl fmt::Display for StructField {
498    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
499        if let Some(name) = &self.field_name {
500            write!(f, "{name} {}", self.field_type)?;
501        } else {
502            write!(f, "{}", self.field_type)?;
503        }
504        if self.not_null {
505            write!(f, " NOT NULL")?;
506        }
507        if let Some(options) = &self.options {
508            write!(f, " OPTIONS({})", display_separated(options, ", "))?;
509        }
510        Ok(())
511    }
512}
513
514/// A field definition within a union
515///
516/// [DuckDB]: https://duckdb.org/docs/sql/data_types/union.html
517#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
518#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
519#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
520pub struct UnionField {
521    pub field_name: Ident,
522    pub field_type: DataType,
523}
524
525impl fmt::Display for UnionField {
526    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
527        write!(f, "{} {}", self.field_name, self.field_type)
528    }
529}
530
531/// A dictionary field within a dictionary.
532///
533/// [DuckDB]: https://duckdb.org/docs/sql/data_types/struct#creating-structs
534#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
535#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
536#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
537pub struct DictionaryField {
538    pub key: Ident,
539    pub value: Box<Expr>,
540}
541
542impl fmt::Display for DictionaryField {
543    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
544        write!(f, "{}: {}", self.key, self.value)
545    }
546}
547
548/// Represents a Map expression.
549#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
550#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
551#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
552pub struct Map {
553    pub entries: Vec<MapEntry>,
554}
555
556impl Display for Map {
557    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
558        write!(f, "MAP {{{}}}", display_comma_separated(&self.entries))
559    }
560}
561
562/// A map field within a map.
563///
564/// [DuckDB]: https://duckdb.org/docs/sql/data_types/map.html#creating-maps
565#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
566#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
567#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
568pub struct MapEntry {
569    pub key: Box<Expr>,
570    pub value: Box<Expr>,
571}
572
573impl fmt::Display for MapEntry {
574    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
575        write!(f, "{}: {}", self.key, self.value)
576    }
577}
578
579/// Options for `CAST` / `TRY_CAST`
580/// BigQuery: <https://cloud.google.com/bigquery/docs/reference/standard-sql/format-elements#formatting_syntax>
581#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
582#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
583#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
584pub enum CastFormat {
585    Value(Value),
586    ValueAtTimeZone(Value, Value),
587}
588
589/// An element of a JSON path.
590#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
591#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
592#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
593pub enum JsonPathElem {
594    /// Accesses an object field using dot notation, e.g. `obj:foo.bar.baz`.
595    ///
596    /// See <https://docs.snowflake.com/en/user-guide/querying-semistructured#dot-notation>.
597    Dot { key: String, quoted: bool },
598    /// Accesses an object field or array element using bracket notation,
599    /// e.g. `obj['foo']`.
600    ///
601    /// See <https://docs.snowflake.com/en/user-guide/querying-semistructured#bracket-notation>.
602    Bracket { key: Expr },
603}
604
605/// A JSON path.
606///
607/// See <https://docs.snowflake.com/en/user-guide/querying-semistructured>.
608/// See <https://docs.databricks.com/en/sql/language-manual/sql-ref-json-path-expression.html>.
609#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
610#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
611#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
612pub struct JsonPath {
613    pub path: Vec<JsonPathElem>,
614}
615
616impl fmt::Display for JsonPath {
617    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
618        for (i, elem) in self.path.iter().enumerate() {
619            match elem {
620                JsonPathElem::Dot { key, quoted } => {
621                    if i == 0 {
622                        write!(f, ":")?;
623                    } else {
624                        write!(f, ".")?;
625                    }
626
627                    if *quoted {
628                        write!(f, "\"{}\"", escape_double_quote_string(key))?;
629                    } else {
630                        write!(f, "{key}")?;
631                    }
632                }
633                JsonPathElem::Bracket { key } => {
634                    write!(f, "[{key}]")?;
635                }
636            }
637        }
638        Ok(())
639    }
640}
641
642/// The syntax used for in a cast expression.
643#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
644#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
645#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
646pub enum CastKind {
647    /// The standard SQL cast syntax, e.g. `CAST(<expr> as <datatype>)`
648    Cast,
649    /// A cast that returns `NULL` on failure, e.g. `TRY_CAST(<expr> as <datatype>)`.
650    ///
651    /// See <https://docs.snowflake.com/en/sql-reference/functions/try_cast>.
652    /// See <https://learn.microsoft.com/en-us/sql/t-sql/functions/try-cast-transact-sql>.
653    TryCast,
654    /// A cast that returns `NULL` on failure, bigQuery-specific ,  e.g. `SAFE_CAST(<expr> as <datatype>)`.
655    ///
656    /// See <https://cloud.google.com/bigquery/docs/reference/standard-sql/functions-and-operators#safe_casting>.
657    SafeCast,
658    /// `<expr> :: <datatype>`
659    DoubleColon,
660}
661
662/// `EXTRACT` syntax variants.
663///
664/// In Snowflake dialect, the `EXTRACT` expression can support either the `from` syntax
665/// or the comma syntax.
666///
667/// See <https://docs.snowflake.com/en/sql-reference/functions/extract>
668#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
669#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
670#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
671pub enum ExtractSyntax {
672    /// `EXTRACT( <date_or_time_part> FROM <date_or_time_expr> )`
673    From,
674    /// `EXTRACT( <date_or_time_part> , <date_or_timestamp_expr> )`
675    Comma,
676}
677
678/// The syntax used in a CEIL or FLOOR expression.
679///
680/// The `CEIL/FLOOR(<datetime value expression> TO <time unit>)` is an Amazon Kinesis Data Analytics extension.
681/// See <https://docs.aws.amazon.com/kinesisanalytics/latest/sqlref/sql-reference-ceil.html> for
682/// details.
683///
684/// Other dialects either support `CEIL/FLOOR( <expr> [, <scale>])` format or just
685/// `CEIL/FLOOR(<expr>)`.
686#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
687#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
688#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
689pub enum CeilFloorKind {
690    /// `CEIL( <expr> TO <DateTimeField>)`
691    DateTimeField(DateTimeField),
692    /// `CEIL( <expr> [, <scale>])`
693    Scale(Value),
694}
695
696/// A WHEN clause in a CASE expression containing both
697/// the condition and its corresponding result
698#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
699#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
700#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
701pub struct CaseWhen {
702    pub condition: Expr,
703    pub result: Expr,
704}
705
706impl fmt::Display for CaseWhen {
707    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
708        f.write_str("WHEN ")?;
709        self.condition.fmt(f)?;
710        f.write_str(" THEN")?;
711        SpaceOrNewline.fmt(f)?;
712        Indent(&self.result).fmt(f)?;
713        Ok(())
714    }
715}
716
717/// An SQL expression of any type.
718///
719/// # Semantics / Type Checking
720///
721/// The parser does not distinguish between expressions of different types
722/// (e.g. boolean vs string). The caller is responsible for detecting and
723/// validating types as necessary (for example  `WHERE 1` vs `SELECT 1=1`)
724/// See the [README.md] for more details.
725///
726/// [README.md]: https://github.com/apache/datafusion-sqlparser-rs/blob/main/README.md#syntax-vs-semantics
727///
728/// # Equality and Hashing Does not Include Source Locations
729///
730/// The `Expr` type implements `PartialEq` and `Eq` based on the semantic value
731/// of the expression (not bitwise comparison). This means that `Expr` instances
732/// that are semantically equivalent but have different spans (locations in the
733/// source tree) will compare as equal.
734#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
735#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
736#[cfg_attr(
737    feature = "visitor",
738    derive(Visit, VisitMut),
739    visit(with = "visit_expr")
740)]
741pub enum Expr {
742    /// Identifier e.g. table name or column name
743    Identifier(Ident),
744    /// Multi-part identifier, e.g. `table_alias.column` or `schema.table.col`
745    CompoundIdentifier(Vec<Ident>),
746    /// Multi-part expression access.
747    ///
748    /// This structure represents an access chain in structured / nested types
749    /// such as maps, arrays, and lists:
750    /// - Array
751    ///     - A 1-dim array `a[1]` will be represented like:
752    ///       `CompoundFieldAccess(Ident('a'), vec![Subscript(1)]`
753    ///     - A 2-dim array `a[1][2]` will be represented like:
754    ///       `CompoundFieldAccess(Ident('a'), vec![Subscript(1), Subscript(2)]`
755    /// - Map or Struct (Bracket-style)
756    ///     - A map `a['field1']` will be represented like:
757    ///       `CompoundFieldAccess(Ident('a'), vec![Subscript('field')]`
758    ///     - A 2-dim map `a['field1']['field2']` will be represented like:
759    ///       `CompoundFieldAccess(Ident('a'), vec![Subscript('field1'), Subscript('field2')]`
760    /// - Struct (Dot-style) (only effect when the chain contains both subscript and expr)
761    ///     - A struct access `a[field1].field2` will be represented like:
762    ///       `CompoundFieldAccess(Ident('a'), vec![Subscript('field1'), Ident('field2')]`
763    /// - If a struct access likes `a.field1.field2`, it will be represented by CompoundIdentifier([a, field1, field2])
764    CompoundFieldAccess {
765        root: Box<Expr>,
766        access_chain: Vec<AccessExpr>,
767    },
768    /// Access data nested in a value containing semi-structured data, such as
769    /// the `VARIANT` type on Snowflake. for example `src:customer[0].name`.
770    ///
771    /// See <https://docs.snowflake.com/en/user-guide/querying-semistructured>.
772    /// See <https://docs.databricks.com/en/sql/language-manual/functions/colonsign.html>.
773    JsonAccess {
774        /// The value being queried.
775        value: Box<Expr>,
776        /// The path to the data to extract.
777        path: JsonPath,
778    },
779    /// `IS FALSE` operator
780    IsFalse(Box<Expr>),
781    /// `IS NOT FALSE` operator
782    IsNotFalse(Box<Expr>),
783    /// `IS TRUE` operator
784    IsTrue(Box<Expr>),
785    /// `IS NOT TRUE` operator
786    IsNotTrue(Box<Expr>),
787    /// `IS NULL` operator
788    IsNull(Box<Expr>),
789    /// `IS NOT NULL` operator
790    IsNotNull(Box<Expr>),
791    /// `IS UNKNOWN` operator
792    IsUnknown(Box<Expr>),
793    /// `IS NOT UNKNOWN` operator
794    IsNotUnknown(Box<Expr>),
795    /// `IS DISTINCT FROM` operator
796    IsDistinctFrom(Box<Expr>, Box<Expr>),
797    /// `IS NOT DISTINCT FROM` operator
798    IsNotDistinctFrom(Box<Expr>, Box<Expr>),
799    /// `<expr> IS [ NOT ] [ form ] NORMALIZED`
800    IsNormalized {
801        expr: Box<Expr>,
802        form: Option<NormalizationForm>,
803        negated: bool,
804    },
805    /// `[ NOT ] IN (val1, val2, ...)`
806    InList {
807        expr: Box<Expr>,
808        list: Vec<Expr>,
809        negated: bool,
810    },
811    /// `[ NOT ] IN (SELECT ...)`
812    InSubquery {
813        expr: Box<Expr>,
814        subquery: Box<Query>,
815        negated: bool,
816    },
817    /// `[ NOT ] IN UNNEST(array_expression)`
818    InUnnest {
819        expr: Box<Expr>,
820        array_expr: Box<Expr>,
821        negated: bool,
822    },
823    /// `<expr> [ NOT ] BETWEEN <low> AND <high>`
824    Between {
825        expr: Box<Expr>,
826        negated: bool,
827        low: Box<Expr>,
828        high: Box<Expr>,
829    },
830    /// Binary operation e.g. `1 + 1` or `foo > bar`
831    BinaryOp {
832        left: Box<Expr>,
833        op: BinaryOperator,
834        right: Box<Expr>,
835    },
836    /// `[NOT] LIKE <pattern> [ESCAPE <escape_character>]`
837    Like {
838        negated: bool,
839        // Snowflake supports the ANY keyword to match against a list of patterns
840        // https://docs.snowflake.com/en/sql-reference/functions/like_any
841        any: bool,
842        expr: Box<Expr>,
843        pattern: Box<Expr>,
844        escape_char: Option<Value>,
845    },
846    /// `ILIKE` (case-insensitive `LIKE`)
847    ILike {
848        negated: bool,
849        // Snowflake supports the ANY keyword to match against a list of patterns
850        // https://docs.snowflake.com/en/sql-reference/functions/like_any
851        any: bool,
852        expr: Box<Expr>,
853        pattern: Box<Expr>,
854        escape_char: Option<Value>,
855    },
856    /// SIMILAR TO regex
857    SimilarTo {
858        negated: bool,
859        expr: Box<Expr>,
860        pattern: Box<Expr>,
861        escape_char: Option<Value>,
862    },
863    /// MySQL: RLIKE regex or REGEXP regex
864    RLike {
865        negated: bool,
866        expr: Box<Expr>,
867        pattern: Box<Expr>,
868        // true for REGEXP, false for RLIKE (no difference in semantics)
869        regexp: bool,
870    },
871    /// `ANY` operation e.g. `foo > ANY(bar)`, comparison operator is one of `[=, >, <, =>, =<, !=]`
872    /// <https://docs.snowflake.com/en/sql-reference/operators-subquery#all-any>
873    AnyOp {
874        left: Box<Expr>,
875        compare_op: BinaryOperator,
876        right: Box<Expr>,
877        // ANY and SOME are synonymous: https://docs.cloudera.com/cdw-runtime/cloud/using-hiveql/topics/hive_comparison_predicates.html
878        is_some: bool,
879    },
880    /// `ALL` operation e.g. `foo > ALL(bar)`, comparison operator is one of `[=, >, <, =>, =<, !=]`
881    /// <https://docs.snowflake.com/en/sql-reference/operators-subquery#all-any>
882    AllOp {
883        left: Box<Expr>,
884        compare_op: BinaryOperator,
885        right: Box<Expr>,
886    },
887    /// Unary operation e.g. `NOT foo`
888    UnaryOp {
889        op: UnaryOperator,
890        expr: Box<Expr>,
891    },
892    /// CONVERT a value to a different data type or character encoding. e.g. `CONVERT(foo USING utf8mb4)`
893    Convert {
894        /// CONVERT (false) or TRY_CONVERT (true)
895        /// <https://learn.microsoft.com/en-us/sql/t-sql/functions/try-convert-transact-sql?view=sql-server-ver16>
896        is_try: bool,
897        /// The expression to convert
898        expr: Box<Expr>,
899        /// The target data type
900        data_type: Option<DataType>,
901        /// The target character encoding
902        charset: Option<ObjectName>,
903        /// whether the target comes before the expr (MSSQL syntax)
904        target_before_value: bool,
905        /// How to translate the expression.
906        ///
907        /// [MSSQL]: https://learn.microsoft.com/en-us/sql/t-sql/functions/cast-and-convert-transact-sql?view=sql-server-ver16#style
908        styles: Vec<Expr>,
909    },
910    /// `CAST` an expression to a different data type e.g. `CAST(foo AS VARCHAR(123))`
911    Cast {
912        kind: CastKind,
913        expr: Box<Expr>,
914        data_type: DataType,
915        /// Optional CAST(string_expression AS type FORMAT format_string_expression) as used by [BigQuery]
916        ///
917        /// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/format-elements#formatting_syntax
918        format: Option<CastFormat>,
919    },
920    /// AT a timestamp to a different timezone e.g. `FROM_UNIXTIME(0) AT TIME ZONE 'UTC-06:00'`
921    AtTimeZone {
922        timestamp: Box<Expr>,
923        time_zone: Box<Expr>,
924    },
925    /// Extract a field from a timestamp e.g. `EXTRACT(MONTH FROM foo)`
926    /// Or `EXTRACT(MONTH, foo)`
927    ///
928    /// Syntax:
929    /// ```sql
930    /// EXTRACT(DateTimeField FROM <expr>) | EXTRACT(DateTimeField, <expr>)
931    /// ```
932    Extract {
933        field: DateTimeField,
934        syntax: ExtractSyntax,
935        expr: Box<Expr>,
936    },
937    /// ```sql
938    /// CEIL(<expr> [TO DateTimeField])
939    /// ```
940    /// ```sql
941    /// CEIL( <input_expr> [, <scale_expr> ] )
942    /// ```
943    Ceil {
944        expr: Box<Expr>,
945        field: CeilFloorKind,
946    },
947    /// ```sql
948    /// FLOOR(<expr> [TO DateTimeField])
949    /// ```
950    /// ```sql
951    /// FLOOR( <input_expr> [, <scale_expr> ] )
952    ///
953    Floor {
954        expr: Box<Expr>,
955        field: CeilFloorKind,
956    },
957    /// ```sql
958    /// POSITION(<expr> in <expr>)
959    /// ```
960    Position {
961        expr: Box<Expr>,
962        r#in: Box<Expr>,
963    },
964    /// ```sql
965    /// SUBSTRING(<expr> [FROM <expr>] [FOR <expr>])
966    /// ```
967    /// or
968    /// ```sql
969    /// SUBSTRING(<expr>, <expr>, <expr>)
970    /// ```
971    Substring {
972        expr: Box<Expr>,
973        substring_from: Option<Box<Expr>>,
974        substring_for: Option<Box<Expr>>,
975
976        /// false if the expression is represented using the `SUBSTRING(expr [FROM start] [FOR len])` syntax
977        /// true if the expression is represented using the `SUBSTRING(expr, start, len)` syntax
978        /// This flag is used for formatting.
979        special: bool,
980
981        /// true if the expression is represented using the `SUBSTR` shorthand
982        /// This flag is used for formatting.
983        shorthand: bool,
984    },
985    /// ```sql
986    /// TRIM([BOTH | LEADING | TRAILING] [<expr> FROM] <expr>)
987    /// TRIM(<expr>)
988    /// TRIM(<expr>, [, characters]) -- only Snowflake or Bigquery
989    /// ```
990    Trim {
991        expr: Box<Expr>,
992        // ([BOTH | LEADING | TRAILING]
993        trim_where: Option<TrimWhereField>,
994        trim_what: Option<Box<Expr>>,
995        trim_characters: Option<Vec<Expr>>,
996    },
997    /// ```sql
998    /// OVERLAY(<expr> PLACING <expr> FROM <expr>[ FOR <expr> ]
999    /// ```
1000    Overlay {
1001        expr: Box<Expr>,
1002        overlay_what: Box<Expr>,
1003        overlay_from: Box<Expr>,
1004        overlay_for: Option<Box<Expr>>,
1005    },
1006    /// `expr COLLATE collation`
1007    Collate {
1008        expr: Box<Expr>,
1009        collation: ObjectName,
1010    },
1011    /// Nested expression e.g. `(foo > bar)` or `(1)`
1012    Nested(Box<Expr>),
1013    /// A literal value, such as string, number, date or NULL
1014    Value(ValueWithSpan),
1015    /// Prefixed expression, e.g. introducer strings, projection prefix
1016    /// <https://dev.mysql.com/doc/refman/8.0/en/charset-introducer.html>
1017    /// <https://docs.snowflake.com/en/sql-reference/constructs/connect-by>
1018    Prefixed {
1019        prefix: Ident,
1020        /// The value of the constant.
1021        /// Hint: you can unwrap the string value using `value.into_string()`.
1022        value: Box<Expr>,
1023    },
1024    /// A constant of form `<data_type> 'value'`.
1025    /// This can represent ANSI SQL `DATE`, `TIME`, and `TIMESTAMP` literals (such as `DATE '2020-01-01'`),
1026    /// as well as constants of other types (a non-standard PostgreSQL extension).
1027    TypedString(TypedString),
1028    /// Scalar function call e.g. `LEFT(foo, 5)`
1029    Function(Function),
1030    /// `CASE [<operand>] WHEN <condition> THEN <result> ... [ELSE <result>] END`
1031    ///
1032    /// Note we only recognize a complete single expression as `<condition>`,
1033    /// not `< 0` nor `1, 2, 3` as allowed in a `<simple when clause>` per
1034    /// <https://jakewheat.github.io/sql-overview/sql-2011-foundation-grammar.html#simple-when-clause>
1035    Case {
1036        case_token: AttachedToken,
1037        end_token: AttachedToken,
1038        operand: Option<Box<Expr>>,
1039        conditions: Vec<CaseWhen>,
1040        else_result: Option<Box<Expr>>,
1041    },
1042    /// An exists expression `[ NOT ] EXISTS(SELECT ...)`, used in expressions like
1043    /// `WHERE [ NOT ] EXISTS (SELECT ...)`.
1044    Exists {
1045        subquery: Box<Query>,
1046        negated: bool,
1047    },
1048    /// A parenthesized subquery `(SELECT ...)`, used in expression like
1049    /// `SELECT (subquery) AS x` or `WHERE (subquery) = x`
1050    Subquery(Box<Query>),
1051    /// The `GROUPING SETS` expr.
1052    GroupingSets(Vec<Vec<Expr>>),
1053    /// The `CUBE` expr.
1054    Cube(Vec<Vec<Expr>>),
1055    /// The `ROLLUP` expr.
1056    Rollup(Vec<Vec<Expr>>),
1057    /// ROW / TUPLE a single value, such as `SELECT (1, 2)`
1058    Tuple(Vec<Expr>),
1059    /// `Struct` literal expression
1060    /// Syntax:
1061    /// ```sql
1062    /// STRUCT<[field_name] field_type, ...>( expr1 [, ... ])
1063    ///
1064    /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-types#struct_type)
1065    /// [Databricks](https://docs.databricks.com/en/sql/language-manual/functions/struct.html)
1066    /// ```
1067    Struct {
1068        /// Struct values.
1069        values: Vec<Expr>,
1070        /// Struct field definitions.
1071        fields: Vec<StructField>,
1072    },
1073    /// `BigQuery` specific: An named expression in a typeless struct [1]
1074    ///
1075    /// Syntax
1076    /// ```sql
1077    /// 1 AS A
1078    /// ```
1079    /// [1]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-types#struct_type
1080    Named {
1081        expr: Box<Expr>,
1082        name: Ident,
1083    },
1084    /// `DuckDB` specific `Struct` literal expression [1]
1085    ///
1086    /// Syntax:
1087    /// ```sql
1088    /// syntax: {'field_name': expr1[, ... ]}
1089    /// ```
1090    /// [1]: https://duckdb.org/docs/sql/data_types/struct#creating-structs
1091    Dictionary(Vec<DictionaryField>),
1092    /// `DuckDB` specific `Map` literal expression [1]
1093    ///
1094    /// Syntax:
1095    /// ```sql
1096    /// syntax: Map {key1: value1[, ... ]}
1097    /// ```
1098    /// [1]: https://duckdb.org/docs/sql/data_types/map#creating-maps
1099    Map(Map),
1100    /// An array expression e.g. `ARRAY[1, 2]`
1101    Array(Array),
1102    /// An interval expression e.g. `INTERVAL '1' YEAR`
1103    Interval(Interval),
1104    /// `MySQL` specific text search function [(1)].
1105    ///
1106    /// Syntax:
1107    /// ```sql
1108    /// MATCH (<col>, <col>, ...) AGAINST (<expr> [<search modifier>])
1109    ///
1110    /// <col> = CompoundIdentifier
1111    /// <expr> = String literal
1112    /// ```
1113    /// [(1)]: https://dev.mysql.com/doc/refman/8.0/en/fulltext-search.html#function_match
1114    MatchAgainst {
1115        /// `(<col>, <col>, ...)`.
1116        columns: Vec<ObjectName>,
1117        /// `<expr>`.
1118        match_value: Value,
1119        /// `<search modifier>`
1120        opt_search_modifier: Option<SearchModifier>,
1121    },
1122    Wildcard(AttachedToken),
1123    /// Qualified wildcard, e.g. `alias.*` or `schema.table.*`.
1124    /// (Same caveats apply to `QualifiedWildcard` as to `Wildcard`.)
1125    QualifiedWildcard(ObjectName, AttachedToken),
1126    /// Some dialects support an older syntax for outer joins where columns are
1127    /// marked with the `(+)` operator in the WHERE clause, for example:
1128    ///
1129    /// ```sql
1130    /// SELECT t1.c1, t2.c2 FROM t1, t2 WHERE t1.c1 = t2.c2 (+)
1131    /// ```
1132    ///
1133    /// which is equivalent to
1134    ///
1135    /// ```sql
1136    /// SELECT t1.c1, t2.c2 FROM t1 LEFT OUTER JOIN t2 ON t1.c1 = t2.c2
1137    /// ```
1138    ///
1139    /// See <https://docs.snowflake.com/en/sql-reference/constructs/where#joins-in-the-where-clause>.
1140    OuterJoin(Box<Expr>),
1141    /// A reference to the prior level in a CONNECT BY clause.
1142    Prior(Box<Expr>),
1143    /// A lambda function.
1144    ///
1145    /// Syntax:
1146    /// ```plaintext
1147    /// param -> expr | (param1, ...) -> expr
1148    /// ```
1149    ///
1150    /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/functions#higher-order-functions---operator-and-lambdaparams-expr-function)
1151    /// [Databricks](https://docs.databricks.com/en/sql/language-manual/sql-ref-lambda-functions.html)
1152    /// [DuckDB](https://duckdb.org/docs/stable/sql/functions/lambda)
1153    Lambda(LambdaFunction),
1154    /// Checks membership of a value in a JSON array
1155    MemberOf(MemberOf),
1156}
1157
1158impl Expr {
1159    /// Creates a new [`Expr::Value`]
1160    pub fn value(value: impl Into<ValueWithSpan>) -> Self {
1161        Expr::Value(value.into())
1162    }
1163}
1164
1165/// The contents inside the `[` and `]` in a subscript expression.
1166#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1167#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1168#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1169pub enum Subscript {
1170    /// Accesses the element of the array at the given index.
1171    Index { index: Expr },
1172
1173    /// Accesses a slice of an array on PostgreSQL, e.g.
1174    ///
1175    /// ```plaintext
1176    /// => select (array[1,2,3,4,5,6])[2:5];
1177    /// -----------
1178    /// {2,3,4,5}
1179    /// ```
1180    ///
1181    /// The lower and/or upper bound can be omitted to slice from the start or
1182    /// end of the array respectively.
1183    ///
1184    /// See <https://www.postgresql.org/docs/current/arrays.html#ARRAYS-ACCESSING>.
1185    ///
1186    /// Also supports an optional "stride" as the last element (this is not
1187    /// supported by postgres), e.g.
1188    ///
1189    /// ```plaintext
1190    /// => select (array[1,2,3,4,5,6])[1:6:2];
1191    /// -----------
1192    /// {1,3,5}
1193    /// ```
1194    Slice {
1195        lower_bound: Option<Expr>,
1196        upper_bound: Option<Expr>,
1197        stride: Option<Expr>,
1198    },
1199}
1200
1201impl fmt::Display for Subscript {
1202    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1203        match self {
1204            Subscript::Index { index } => write!(f, "{index}"),
1205            Subscript::Slice {
1206                lower_bound,
1207                upper_bound,
1208                stride,
1209            } => {
1210                if let Some(lower) = lower_bound {
1211                    write!(f, "{lower}")?;
1212                }
1213                write!(f, ":")?;
1214                if let Some(upper) = upper_bound {
1215                    write!(f, "{upper}")?;
1216                }
1217                if let Some(stride) = stride {
1218                    write!(f, ":")?;
1219                    write!(f, "{stride}")?;
1220                }
1221                Ok(())
1222            }
1223        }
1224    }
1225}
1226
1227/// An element of a [`Expr::CompoundFieldAccess`].
1228/// It can be an expression or a subscript.
1229#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1230#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1231#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1232pub enum AccessExpr {
1233    /// Accesses a field using dot notation, e.g. `foo.bar.baz`.
1234    Dot(Expr),
1235    /// Accesses a field or array element using bracket notation, e.g. `foo['bar']`.
1236    Subscript(Subscript),
1237}
1238
1239impl fmt::Display for AccessExpr {
1240    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1241        match self {
1242            AccessExpr::Dot(expr) => write!(f, ".{expr}"),
1243            AccessExpr::Subscript(subscript) => write!(f, "[{subscript}]"),
1244        }
1245    }
1246}
1247
1248/// A lambda function.
1249#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1250#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1251#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1252pub struct LambdaFunction {
1253    /// The parameters to the lambda function.
1254    pub params: OneOrManyWithParens<Ident>,
1255    /// The body of the lambda function.
1256    pub body: Box<Expr>,
1257}
1258
1259impl fmt::Display for LambdaFunction {
1260    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1261        write!(f, "{} -> {}", self.params, self.body)
1262    }
1263}
1264
1265/// Encapsulates the common pattern in SQL where either one unparenthesized item
1266/// such as an identifier or expression is permitted, or multiple of the same
1267/// item in a parenthesized list. For accessing items regardless of the form,
1268/// `OneOrManyWithParens` implements `Deref<Target = [T]>` and `IntoIterator`,
1269/// so you can call slice methods on it and iterate over items
1270/// # Examples
1271/// Accessing as a slice:
1272/// ```
1273/// # use sqlparser::ast::OneOrManyWithParens;
1274/// let one = OneOrManyWithParens::One("a");
1275///
1276/// assert_eq!(one[0], "a");
1277/// assert_eq!(one.len(), 1);
1278/// ```
1279/// Iterating:
1280/// ```
1281/// # use sqlparser::ast::OneOrManyWithParens;
1282/// let one = OneOrManyWithParens::One("a");
1283/// let many = OneOrManyWithParens::Many(vec!["a", "b"]);
1284///
1285/// assert_eq!(one.into_iter().chain(many).collect::<Vec<_>>(), vec!["a", "a", "b"] );
1286/// ```
1287#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1288#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1289#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1290pub enum OneOrManyWithParens<T> {
1291    /// A single `T`, unparenthesized.
1292    One(T),
1293    /// One or more `T`s, parenthesized.
1294    Many(Vec<T>),
1295}
1296
1297impl<T> Deref for OneOrManyWithParens<T> {
1298    type Target = [T];
1299
1300    fn deref(&self) -> &[T] {
1301        match self {
1302            OneOrManyWithParens::One(one) => core::slice::from_ref(one),
1303            OneOrManyWithParens::Many(many) => many,
1304        }
1305    }
1306}
1307
1308impl<T> AsRef<[T]> for OneOrManyWithParens<T> {
1309    fn as_ref(&self) -> &[T] {
1310        self
1311    }
1312}
1313
1314impl<'a, T> IntoIterator for &'a OneOrManyWithParens<T> {
1315    type Item = &'a T;
1316    type IntoIter = core::slice::Iter<'a, T>;
1317
1318    fn into_iter(self) -> Self::IntoIter {
1319        self.iter()
1320    }
1321}
1322
1323/// Owned iterator implementation of `OneOrManyWithParens`
1324#[derive(Debug, Clone)]
1325pub struct OneOrManyWithParensIntoIter<T> {
1326    inner: OneOrManyWithParensIntoIterInner<T>,
1327}
1328
1329#[derive(Debug, Clone)]
1330enum OneOrManyWithParensIntoIterInner<T> {
1331    One(core::iter::Once<T>),
1332    Many(<Vec<T> as IntoIterator>::IntoIter),
1333}
1334
1335impl<T> core::iter::FusedIterator for OneOrManyWithParensIntoIter<T>
1336where
1337    core::iter::Once<T>: core::iter::FusedIterator,
1338    <Vec<T> as IntoIterator>::IntoIter: core::iter::FusedIterator,
1339{
1340}
1341
1342impl<T> core::iter::ExactSizeIterator for OneOrManyWithParensIntoIter<T>
1343where
1344    core::iter::Once<T>: core::iter::ExactSizeIterator,
1345    <Vec<T> as IntoIterator>::IntoIter: core::iter::ExactSizeIterator,
1346{
1347}
1348
1349impl<T> core::iter::Iterator for OneOrManyWithParensIntoIter<T> {
1350    type Item = T;
1351
1352    fn next(&mut self) -> Option<Self::Item> {
1353        match &mut self.inner {
1354            OneOrManyWithParensIntoIterInner::One(one) => one.next(),
1355            OneOrManyWithParensIntoIterInner::Many(many) => many.next(),
1356        }
1357    }
1358
1359    fn size_hint(&self) -> (usize, Option<usize>) {
1360        match &self.inner {
1361            OneOrManyWithParensIntoIterInner::One(one) => one.size_hint(),
1362            OneOrManyWithParensIntoIterInner::Many(many) => many.size_hint(),
1363        }
1364    }
1365
1366    fn count(self) -> usize
1367    where
1368        Self: Sized,
1369    {
1370        match self.inner {
1371            OneOrManyWithParensIntoIterInner::One(one) => one.count(),
1372            OneOrManyWithParensIntoIterInner::Many(many) => many.count(),
1373        }
1374    }
1375
1376    fn fold<B, F>(mut self, init: B, f: F) -> B
1377    where
1378        Self: Sized,
1379        F: FnMut(B, Self::Item) -> B,
1380    {
1381        match &mut self.inner {
1382            OneOrManyWithParensIntoIterInner::One(one) => one.fold(init, f),
1383            OneOrManyWithParensIntoIterInner::Many(many) => many.fold(init, f),
1384        }
1385    }
1386}
1387
1388impl<T> core::iter::DoubleEndedIterator for OneOrManyWithParensIntoIter<T> {
1389    fn next_back(&mut self) -> Option<Self::Item> {
1390        match &mut self.inner {
1391            OneOrManyWithParensIntoIterInner::One(one) => one.next_back(),
1392            OneOrManyWithParensIntoIterInner::Many(many) => many.next_back(),
1393        }
1394    }
1395}
1396
1397impl<T> IntoIterator for OneOrManyWithParens<T> {
1398    type Item = T;
1399
1400    type IntoIter = OneOrManyWithParensIntoIter<T>;
1401
1402    fn into_iter(self) -> Self::IntoIter {
1403        let inner = match self {
1404            OneOrManyWithParens::One(one) => {
1405                OneOrManyWithParensIntoIterInner::One(core::iter::once(one))
1406            }
1407            OneOrManyWithParens::Many(many) => {
1408                OneOrManyWithParensIntoIterInner::Many(many.into_iter())
1409            }
1410        };
1411
1412        OneOrManyWithParensIntoIter { inner }
1413    }
1414}
1415
1416impl<T> fmt::Display for OneOrManyWithParens<T>
1417where
1418    T: fmt::Display,
1419{
1420    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1421        match self {
1422            OneOrManyWithParens::One(value) => write!(f, "{value}"),
1423            OneOrManyWithParens::Many(values) => {
1424                write!(f, "({})", display_comma_separated(values))
1425            }
1426        }
1427    }
1428}
1429
1430impl fmt::Display for CastFormat {
1431    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1432        match self {
1433            CastFormat::Value(v) => write!(f, "{v}"),
1434            CastFormat::ValueAtTimeZone(v, tz) => write!(f, "{v} AT TIME ZONE {tz}"),
1435        }
1436    }
1437}
1438
1439impl fmt::Display for Expr {
1440    #[cfg_attr(feature = "recursive-protection", recursive::recursive)]
1441    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1442        match self {
1443            Expr::Identifier(s) => write!(f, "{s}"),
1444            Expr::Wildcard(_) => f.write_str("*"),
1445            Expr::QualifiedWildcard(prefix, _) => write!(f, "{prefix}.*"),
1446            Expr::CompoundIdentifier(s) => write!(f, "{}", display_separated(s, ".")),
1447            Expr::CompoundFieldAccess { root, access_chain } => {
1448                write!(f, "{root}")?;
1449                for field in access_chain {
1450                    write!(f, "{field}")?;
1451                }
1452                Ok(())
1453            }
1454            Expr::IsTrue(ast) => write!(f, "{ast} IS TRUE"),
1455            Expr::IsNotTrue(ast) => write!(f, "{ast} IS NOT TRUE"),
1456            Expr::IsFalse(ast) => write!(f, "{ast} IS FALSE"),
1457            Expr::IsNotFalse(ast) => write!(f, "{ast} IS NOT FALSE"),
1458            Expr::IsNull(ast) => write!(f, "{ast} IS NULL"),
1459            Expr::IsNotNull(ast) => write!(f, "{ast} IS NOT NULL"),
1460            Expr::IsUnknown(ast) => write!(f, "{ast} IS UNKNOWN"),
1461            Expr::IsNotUnknown(ast) => write!(f, "{ast} IS NOT UNKNOWN"),
1462            Expr::InList {
1463                expr,
1464                list,
1465                negated,
1466            } => write!(
1467                f,
1468                "{} {}IN ({})",
1469                expr,
1470                if *negated { "NOT " } else { "" },
1471                display_comma_separated(list)
1472            ),
1473            Expr::InSubquery {
1474                expr,
1475                subquery,
1476                negated,
1477            } => write!(
1478                f,
1479                "{} {}IN ({})",
1480                expr,
1481                if *negated { "NOT " } else { "" },
1482                subquery
1483            ),
1484            Expr::InUnnest {
1485                expr,
1486                array_expr,
1487                negated,
1488            } => write!(
1489                f,
1490                "{} {}IN UNNEST({})",
1491                expr,
1492                if *negated { "NOT " } else { "" },
1493                array_expr
1494            ),
1495            Expr::Between {
1496                expr,
1497                negated,
1498                low,
1499                high,
1500            } => write!(
1501                f,
1502                "{} {}BETWEEN {} AND {}",
1503                expr,
1504                if *negated { "NOT " } else { "" },
1505                low,
1506                high
1507            ),
1508            Expr::BinaryOp { left, op, right } => write!(f, "{left} {op} {right}"),
1509            Expr::Like {
1510                negated,
1511                expr,
1512                pattern,
1513                escape_char,
1514                any,
1515            } => match escape_char {
1516                Some(ch) => write!(
1517                    f,
1518                    "{} {}LIKE {}{} ESCAPE {}",
1519                    expr,
1520                    if *negated { "NOT " } else { "" },
1521                    if *any { "ANY " } else { "" },
1522                    pattern,
1523                    ch
1524                ),
1525                _ => write!(
1526                    f,
1527                    "{} {}LIKE {}{}",
1528                    expr,
1529                    if *negated { "NOT " } else { "" },
1530                    if *any { "ANY " } else { "" },
1531                    pattern
1532                ),
1533            },
1534            Expr::ILike {
1535                negated,
1536                expr,
1537                pattern,
1538                escape_char,
1539                any,
1540            } => match escape_char {
1541                Some(ch) => write!(
1542                    f,
1543                    "{} {}ILIKE {}{} ESCAPE {}",
1544                    expr,
1545                    if *negated { "NOT " } else { "" },
1546                    if *any { "ANY" } else { "" },
1547                    pattern,
1548                    ch
1549                ),
1550                _ => write!(
1551                    f,
1552                    "{} {}ILIKE {}{}",
1553                    expr,
1554                    if *negated { "NOT " } else { "" },
1555                    if *any { "ANY " } else { "" },
1556                    pattern
1557                ),
1558            },
1559            Expr::RLike {
1560                negated,
1561                expr,
1562                pattern,
1563                regexp,
1564            } => write!(
1565                f,
1566                "{} {}{} {}",
1567                expr,
1568                if *negated { "NOT " } else { "" },
1569                if *regexp { "REGEXP" } else { "RLIKE" },
1570                pattern
1571            ),
1572            Expr::IsNormalized {
1573                expr,
1574                form,
1575                negated,
1576            } => {
1577                let not_ = if *negated { "NOT " } else { "" };
1578                if form.is_none() {
1579                    write!(f, "{expr} IS {not_}NORMALIZED")
1580                } else {
1581                    write!(
1582                        f,
1583                        "{} IS {}{} NORMALIZED",
1584                        expr,
1585                        not_,
1586                        form.as_ref().unwrap()
1587                    )
1588                }
1589            }
1590            Expr::SimilarTo {
1591                negated,
1592                expr,
1593                pattern,
1594                escape_char,
1595            } => match escape_char {
1596                Some(ch) => write!(
1597                    f,
1598                    "{} {}SIMILAR TO {} ESCAPE {}",
1599                    expr,
1600                    if *negated { "NOT " } else { "" },
1601                    pattern,
1602                    ch
1603                ),
1604                _ => write!(
1605                    f,
1606                    "{} {}SIMILAR TO {}",
1607                    expr,
1608                    if *negated { "NOT " } else { "" },
1609                    pattern
1610                ),
1611            },
1612            Expr::AnyOp {
1613                left,
1614                compare_op,
1615                right,
1616                is_some,
1617            } => {
1618                let add_parens = !matches!(right.as_ref(), Expr::Subquery(_));
1619                write!(
1620                    f,
1621                    "{left} {compare_op} {}{}{right}{}",
1622                    if *is_some { "SOME" } else { "ANY" },
1623                    if add_parens { "(" } else { "" },
1624                    if add_parens { ")" } else { "" },
1625                )
1626            }
1627            Expr::AllOp {
1628                left,
1629                compare_op,
1630                right,
1631            } => {
1632                let add_parens = !matches!(right.as_ref(), Expr::Subquery(_));
1633                write!(
1634                    f,
1635                    "{left} {compare_op} ALL{}{right}{}",
1636                    if add_parens { "(" } else { "" },
1637                    if add_parens { ")" } else { "" },
1638                )
1639            }
1640            Expr::UnaryOp { op, expr } => {
1641                if op == &UnaryOperator::PGPostfixFactorial {
1642                    write!(f, "{expr}{op}")
1643                } else if matches!(
1644                    op,
1645                    UnaryOperator::Not
1646                        | UnaryOperator::Hash
1647                        | UnaryOperator::AtDashAt
1648                        | UnaryOperator::DoubleAt
1649                        | UnaryOperator::QuestionDash
1650                        | UnaryOperator::QuestionPipe
1651                ) {
1652                    write!(f, "{op} {expr}")
1653                } else {
1654                    write!(f, "{op}{expr}")
1655                }
1656            }
1657            Expr::Convert {
1658                is_try,
1659                expr,
1660                target_before_value,
1661                data_type,
1662                charset,
1663                styles,
1664            } => {
1665                write!(f, "{}CONVERT(", if *is_try { "TRY_" } else { "" })?;
1666                if let Some(data_type) = data_type {
1667                    if let Some(charset) = charset {
1668                        write!(f, "{expr}, {data_type} CHARACTER SET {charset}")
1669                    } else if *target_before_value {
1670                        write!(f, "{data_type}, {expr}")
1671                    } else {
1672                        write!(f, "{expr}, {data_type}")
1673                    }
1674                } else if let Some(charset) = charset {
1675                    write!(f, "{expr} USING {charset}")
1676                } else {
1677                    write!(f, "{expr}") // This should never happen
1678                }?;
1679                if !styles.is_empty() {
1680                    write!(f, ", {}", display_comma_separated(styles))?;
1681                }
1682                write!(f, ")")
1683            }
1684            Expr::Cast {
1685                kind,
1686                expr,
1687                data_type,
1688                format,
1689            } => match kind {
1690                CastKind::Cast => {
1691                    if let Some(format) = format {
1692                        write!(f, "CAST({expr} AS {data_type} FORMAT {format})")
1693                    } else {
1694                        write!(f, "CAST({expr} AS {data_type})")
1695                    }
1696                }
1697                CastKind::TryCast => {
1698                    if let Some(format) = format {
1699                        write!(f, "TRY_CAST({expr} AS {data_type} FORMAT {format})")
1700                    } else {
1701                        write!(f, "TRY_CAST({expr} AS {data_type})")
1702                    }
1703                }
1704                CastKind::SafeCast => {
1705                    if let Some(format) = format {
1706                        write!(f, "SAFE_CAST({expr} AS {data_type} FORMAT {format})")
1707                    } else {
1708                        write!(f, "SAFE_CAST({expr} AS {data_type})")
1709                    }
1710                }
1711                CastKind::DoubleColon => {
1712                    write!(f, "{expr}::{data_type}")
1713                }
1714            },
1715            Expr::Extract {
1716                field,
1717                syntax,
1718                expr,
1719            } => match syntax {
1720                ExtractSyntax::From => write!(f, "EXTRACT({field} FROM {expr})"),
1721                ExtractSyntax::Comma => write!(f, "EXTRACT({field}, {expr})"),
1722            },
1723            Expr::Ceil { expr, field } => match field {
1724                CeilFloorKind::DateTimeField(DateTimeField::NoDateTime) => {
1725                    write!(f, "CEIL({expr})")
1726                }
1727                CeilFloorKind::DateTimeField(dt_field) => write!(f, "CEIL({expr} TO {dt_field})"),
1728                CeilFloorKind::Scale(s) => write!(f, "CEIL({expr}, {s})"),
1729            },
1730            Expr::Floor { expr, field } => match field {
1731                CeilFloorKind::DateTimeField(DateTimeField::NoDateTime) => {
1732                    write!(f, "FLOOR({expr})")
1733                }
1734                CeilFloorKind::DateTimeField(dt_field) => write!(f, "FLOOR({expr} TO {dt_field})"),
1735                CeilFloorKind::Scale(s) => write!(f, "FLOOR({expr}, {s})"),
1736            },
1737            Expr::Position { expr, r#in } => write!(f, "POSITION({expr} IN {in})"),
1738            Expr::Collate { expr, collation } => write!(f, "{expr} COLLATE {collation}"),
1739            Expr::Nested(ast) => write!(f, "({ast})"),
1740            Expr::Value(v) => write!(f, "{v}"),
1741            Expr::Prefixed { prefix, value } => write!(f, "{prefix} {value}"),
1742            Expr::TypedString(ts) => ts.fmt(f),
1743            Expr::Function(fun) => fun.fmt(f),
1744            Expr::Case {
1745                case_token: _,
1746                end_token: _,
1747                operand,
1748                conditions,
1749                else_result,
1750            } => {
1751                f.write_str("CASE")?;
1752                if let Some(operand) = operand {
1753                    f.write_str(" ")?;
1754                    operand.fmt(f)?;
1755                }
1756                for when in conditions {
1757                    SpaceOrNewline.fmt(f)?;
1758                    Indent(when).fmt(f)?;
1759                }
1760                if let Some(else_result) = else_result {
1761                    SpaceOrNewline.fmt(f)?;
1762                    Indent("ELSE").fmt(f)?;
1763                    SpaceOrNewline.fmt(f)?;
1764                    Indent(Indent(else_result)).fmt(f)?;
1765                }
1766                SpaceOrNewline.fmt(f)?;
1767                f.write_str("END")
1768            }
1769            Expr::Exists { subquery, negated } => write!(
1770                f,
1771                "{}EXISTS ({})",
1772                if *negated { "NOT " } else { "" },
1773                subquery
1774            ),
1775            Expr::Subquery(s) => write!(f, "({s})"),
1776            Expr::GroupingSets(sets) => {
1777                write!(f, "GROUPING SETS (")?;
1778                let mut sep = "";
1779                for set in sets {
1780                    write!(f, "{sep}")?;
1781                    sep = ", ";
1782                    write!(f, "({})", display_comma_separated(set))?;
1783                }
1784                write!(f, ")")
1785            }
1786            Expr::Cube(sets) => {
1787                write!(f, "CUBE (")?;
1788                let mut sep = "";
1789                for set in sets {
1790                    write!(f, "{sep}")?;
1791                    sep = ", ";
1792                    if set.len() == 1 {
1793                        write!(f, "{}", set[0])?;
1794                    } else {
1795                        write!(f, "({})", display_comma_separated(set))?;
1796                    }
1797                }
1798                write!(f, ")")
1799            }
1800            Expr::Rollup(sets) => {
1801                write!(f, "ROLLUP (")?;
1802                let mut sep = "";
1803                for set in sets {
1804                    write!(f, "{sep}")?;
1805                    sep = ", ";
1806                    if set.len() == 1 {
1807                        write!(f, "{}", set[0])?;
1808                    } else {
1809                        write!(f, "({})", display_comma_separated(set))?;
1810                    }
1811                }
1812                write!(f, ")")
1813            }
1814            Expr::Substring {
1815                expr,
1816                substring_from,
1817                substring_for,
1818                special,
1819                shorthand,
1820            } => {
1821                f.write_str("SUBSTR")?;
1822                if !*shorthand {
1823                    f.write_str("ING")?;
1824                }
1825                write!(f, "({expr}")?;
1826                if let Some(from_part) = substring_from {
1827                    if *special {
1828                        write!(f, ", {from_part}")?;
1829                    } else {
1830                        write!(f, " FROM {from_part}")?;
1831                    }
1832                }
1833                if let Some(for_part) = substring_for {
1834                    if *special {
1835                        write!(f, ", {for_part}")?;
1836                    } else {
1837                        write!(f, " FOR {for_part}")?;
1838                    }
1839                }
1840
1841                write!(f, ")")
1842            }
1843            Expr::Overlay {
1844                expr,
1845                overlay_what,
1846                overlay_from,
1847                overlay_for,
1848            } => {
1849                write!(
1850                    f,
1851                    "OVERLAY({expr} PLACING {overlay_what} FROM {overlay_from}"
1852                )?;
1853                if let Some(for_part) = overlay_for {
1854                    write!(f, " FOR {for_part}")?;
1855                }
1856
1857                write!(f, ")")
1858            }
1859            Expr::IsDistinctFrom(a, b) => write!(f, "{a} IS DISTINCT FROM {b}"),
1860            Expr::IsNotDistinctFrom(a, b) => write!(f, "{a} IS NOT DISTINCT FROM {b}"),
1861            Expr::Trim {
1862                expr,
1863                trim_where,
1864                trim_what,
1865                trim_characters,
1866            } => {
1867                write!(f, "TRIM(")?;
1868                if let Some(ident) = trim_where {
1869                    write!(f, "{ident} ")?;
1870                }
1871                if let Some(trim_char) = trim_what {
1872                    write!(f, "{trim_char} FROM {expr}")?;
1873                } else {
1874                    write!(f, "{expr}")?;
1875                }
1876                if let Some(characters) = trim_characters {
1877                    write!(f, ", {}", display_comma_separated(characters))?;
1878                }
1879
1880                write!(f, ")")
1881            }
1882            Expr::Tuple(exprs) => {
1883                write!(f, "({})", display_comma_separated(exprs))
1884            }
1885            Expr::Struct { values, fields } => {
1886                if !fields.is_empty() {
1887                    write!(
1888                        f,
1889                        "STRUCT<{}>({})",
1890                        display_comma_separated(fields),
1891                        display_comma_separated(values)
1892                    )
1893                } else {
1894                    write!(f, "STRUCT({})", display_comma_separated(values))
1895                }
1896            }
1897            Expr::Named { expr, name } => {
1898                write!(f, "{expr} AS {name}")
1899            }
1900            Expr::Dictionary(fields) => {
1901                write!(f, "{{{}}}", display_comma_separated(fields))
1902            }
1903            Expr::Map(map) => {
1904                write!(f, "{map}")
1905            }
1906            Expr::Array(set) => {
1907                write!(f, "{set}")
1908            }
1909            Expr::JsonAccess { value, path } => {
1910                write!(f, "{value}{path}")
1911            }
1912            Expr::AtTimeZone {
1913                timestamp,
1914                time_zone,
1915            } => {
1916                write!(f, "{timestamp} AT TIME ZONE {time_zone}")
1917            }
1918            Expr::Interval(interval) => {
1919                write!(f, "{interval}")
1920            }
1921            Expr::MatchAgainst {
1922                columns,
1923                match_value: match_expr,
1924                opt_search_modifier,
1925            } => {
1926                write!(f, "MATCH ({}) AGAINST ", display_comma_separated(columns),)?;
1927
1928                if let Some(search_modifier) = opt_search_modifier {
1929                    write!(f, "({match_expr} {search_modifier})")?;
1930                } else {
1931                    write!(f, "({match_expr})")?;
1932                }
1933
1934                Ok(())
1935            }
1936            Expr::OuterJoin(expr) => {
1937                write!(f, "{expr} (+)")
1938            }
1939            Expr::Prior(expr) => write!(f, "PRIOR {expr}"),
1940            Expr::Lambda(lambda) => write!(f, "{lambda}"),
1941            Expr::MemberOf(member_of) => write!(f, "{member_of}"),
1942        }
1943    }
1944}
1945
1946#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1947#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1948#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1949pub enum WindowType {
1950    WindowSpec(WindowSpec),
1951    NamedWindow(Ident),
1952}
1953
1954impl Display for WindowType {
1955    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1956        match self {
1957            WindowType::WindowSpec(spec) => {
1958                f.write_str("(")?;
1959                NewLine.fmt(f)?;
1960                Indent(spec).fmt(f)?;
1961                NewLine.fmt(f)?;
1962                f.write_str(")")
1963            }
1964            WindowType::NamedWindow(name) => name.fmt(f),
1965        }
1966    }
1967}
1968
1969/// A window specification (i.e. `OVER ([window_name] PARTITION BY .. ORDER BY .. etc.)`)
1970#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1971#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1972#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1973pub struct WindowSpec {
1974    /// Optional window name.
1975    ///
1976    /// You can find it at least in [MySQL][1], [BigQuery][2], [PostgreSQL][3]
1977    ///
1978    /// [1]: https://dev.mysql.com/doc/refman/8.0/en/window-functions-named-windows.html
1979    /// [2]: https://cloud.google.com/bigquery/docs/reference/standard-sql/window-function-calls
1980    /// [3]: https://www.postgresql.org/docs/current/sql-expressions.html#SYNTAX-WINDOW-FUNCTIONS
1981    pub window_name: Option<Ident>,
1982    /// `OVER (PARTITION BY ...)`
1983    pub partition_by: Vec<Expr>,
1984    /// `OVER (ORDER BY ...)`
1985    pub order_by: Vec<OrderByExpr>,
1986    /// `OVER (window frame)`
1987    pub window_frame: Option<WindowFrame>,
1988}
1989
1990impl fmt::Display for WindowSpec {
1991    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1992        let mut is_first = true;
1993        if let Some(window_name) = &self.window_name {
1994            if !is_first {
1995                SpaceOrNewline.fmt(f)?;
1996            }
1997            is_first = false;
1998            write!(f, "{window_name}")?;
1999        }
2000        if !self.partition_by.is_empty() {
2001            if !is_first {
2002                SpaceOrNewline.fmt(f)?;
2003            }
2004            is_first = false;
2005            write!(
2006                f,
2007                "PARTITION BY {}",
2008                display_comma_separated(&self.partition_by)
2009            )?;
2010        }
2011        if !self.order_by.is_empty() {
2012            if !is_first {
2013                SpaceOrNewline.fmt(f)?;
2014            }
2015            is_first = false;
2016            write!(f, "ORDER BY {}", display_comma_separated(&self.order_by))?;
2017        }
2018        if let Some(window_frame) = &self.window_frame {
2019            if !is_first {
2020                SpaceOrNewline.fmt(f)?;
2021            }
2022            if let Some(end_bound) = &window_frame.end_bound {
2023                write!(
2024                    f,
2025                    "{} BETWEEN {} AND {}",
2026                    window_frame.units, window_frame.start_bound, end_bound
2027                )?;
2028            } else {
2029                write!(f, "{} {}", window_frame.units, window_frame.start_bound)?;
2030            }
2031        }
2032        Ok(())
2033    }
2034}
2035
2036/// Specifies the data processed by a window function, e.g.
2037/// `RANGE UNBOUNDED PRECEDING` or `ROWS BETWEEN 5 PRECEDING AND CURRENT ROW`.
2038///
2039/// Note: The parser does not validate the specified bounds; the caller should
2040/// reject invalid bounds like `ROWS UNBOUNDED FOLLOWING` before execution.
2041#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2042#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2043#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2044pub struct WindowFrame {
2045    pub units: WindowFrameUnits,
2046    pub start_bound: WindowFrameBound,
2047    /// The right bound of the `BETWEEN .. AND` clause. The end bound of `None`
2048    /// indicates the shorthand form (e.g. `ROWS 1 PRECEDING`), which must
2049    /// behave the same as `end_bound = WindowFrameBound::CurrentRow`.
2050    pub end_bound: Option<WindowFrameBound>,
2051    // TBD: EXCLUDE
2052}
2053
2054impl Default for WindowFrame {
2055    /// Returns default value for window frame
2056    ///
2057    /// See [this page](https://www.sqlite.org/windowfunctions.html#frame_specifications) for more details.
2058    fn default() -> Self {
2059        Self {
2060            units: WindowFrameUnits::Range,
2061            start_bound: WindowFrameBound::Preceding(None),
2062            end_bound: None,
2063        }
2064    }
2065}
2066
2067#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2068#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2069#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2070pub enum WindowFrameUnits {
2071    Rows,
2072    Range,
2073    Groups,
2074}
2075
2076impl fmt::Display for WindowFrameUnits {
2077    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2078        f.write_str(match self {
2079            WindowFrameUnits::Rows => "ROWS",
2080            WindowFrameUnits::Range => "RANGE",
2081            WindowFrameUnits::Groups => "GROUPS",
2082        })
2083    }
2084}
2085
2086/// Specifies Ignore / Respect NULL within window functions.
2087/// For example
2088/// `FIRST_VALUE(column2) IGNORE NULLS OVER (PARTITION BY column1)`
2089#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2090#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2091#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2092pub enum NullTreatment {
2093    IgnoreNulls,
2094    RespectNulls,
2095}
2096
2097impl fmt::Display for NullTreatment {
2098    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2099        f.write_str(match self {
2100            NullTreatment::IgnoreNulls => "IGNORE NULLS",
2101            NullTreatment::RespectNulls => "RESPECT NULLS",
2102        })
2103    }
2104}
2105
2106/// Specifies [WindowFrame]'s `start_bound` and `end_bound`
2107#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2108#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2109#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2110pub enum WindowFrameBound {
2111    /// `CURRENT ROW`
2112    CurrentRow,
2113    /// `<N> PRECEDING` or `UNBOUNDED PRECEDING`
2114    Preceding(Option<Box<Expr>>),
2115    /// `<N> FOLLOWING` or `UNBOUNDED FOLLOWING`.
2116    Following(Option<Box<Expr>>),
2117}
2118
2119impl fmt::Display for WindowFrameBound {
2120    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2121        match self {
2122            WindowFrameBound::CurrentRow => f.write_str("CURRENT ROW"),
2123            WindowFrameBound::Preceding(None) => f.write_str("UNBOUNDED PRECEDING"),
2124            WindowFrameBound::Following(None) => f.write_str("UNBOUNDED FOLLOWING"),
2125            WindowFrameBound::Preceding(Some(n)) => write!(f, "{n} PRECEDING"),
2126            WindowFrameBound::Following(Some(n)) => write!(f, "{n} FOLLOWING"),
2127        }
2128    }
2129}
2130
2131#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2132#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2133#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2134pub enum AddDropSync {
2135    ADD,
2136    DROP,
2137    SYNC,
2138}
2139
2140impl fmt::Display for AddDropSync {
2141    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2142        match self {
2143            AddDropSync::SYNC => f.write_str("SYNC PARTITIONS"),
2144            AddDropSync::DROP => f.write_str("DROP PARTITIONS"),
2145            AddDropSync::ADD => f.write_str("ADD PARTITIONS"),
2146        }
2147    }
2148}
2149
2150#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2151#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2152#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2153pub enum ShowCreateObject {
2154    Event,
2155    Function,
2156    Procedure,
2157    Table,
2158    Trigger,
2159    View,
2160}
2161
2162impl fmt::Display for ShowCreateObject {
2163    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2164        match self {
2165            ShowCreateObject::Event => f.write_str("EVENT"),
2166            ShowCreateObject::Function => f.write_str("FUNCTION"),
2167            ShowCreateObject::Procedure => f.write_str("PROCEDURE"),
2168            ShowCreateObject::Table => f.write_str("TABLE"),
2169            ShowCreateObject::Trigger => f.write_str("TRIGGER"),
2170            ShowCreateObject::View => f.write_str("VIEW"),
2171        }
2172    }
2173}
2174
2175#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2176#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2177#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2178pub enum CommentObject {
2179    Column,
2180    Table,
2181    Extension,
2182    Schema,
2183    Database,
2184    User,
2185    Role,
2186}
2187
2188impl fmt::Display for CommentObject {
2189    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2190        match self {
2191            CommentObject::Column => f.write_str("COLUMN"),
2192            CommentObject::Table => f.write_str("TABLE"),
2193            CommentObject::Extension => f.write_str("EXTENSION"),
2194            CommentObject::Schema => f.write_str("SCHEMA"),
2195            CommentObject::Database => f.write_str("DATABASE"),
2196            CommentObject::User => f.write_str("USER"),
2197            CommentObject::Role => f.write_str("ROLE"),
2198        }
2199    }
2200}
2201
2202#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2203#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2204#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2205pub enum Password {
2206    Password(Expr),
2207    NullPassword,
2208}
2209
2210/// A `CASE` statement.
2211///
2212/// Examples:
2213/// ```sql
2214/// CASE
2215///     WHEN EXISTS(SELECT 1)
2216///         THEN SELECT 1 FROM T;
2217///     WHEN EXISTS(SELECT 2)
2218///         THEN SELECT 1 FROM U;
2219///     ELSE
2220///         SELECT 1 FROM V;
2221/// END CASE;
2222/// ```
2223///
2224/// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#case_search_expression)
2225/// [Snowflake](https://docs.snowflake.com/en/sql-reference/snowflake-scripting/case)
2226#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2227#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2228#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2229pub struct CaseStatement {
2230    /// The `CASE` token that starts the statement.
2231    pub case_token: AttachedToken,
2232    pub match_expr: Option<Expr>,
2233    pub when_blocks: Vec<ConditionalStatementBlock>,
2234    pub else_block: Option<ConditionalStatementBlock>,
2235    /// The last token of the statement (`END` or `CASE`).
2236    pub end_case_token: AttachedToken,
2237}
2238
2239impl fmt::Display for CaseStatement {
2240    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2241        let CaseStatement {
2242            case_token: _,
2243            match_expr,
2244            when_blocks,
2245            else_block,
2246            end_case_token: AttachedToken(end),
2247        } = self;
2248
2249        write!(f, "CASE")?;
2250
2251        if let Some(expr) = match_expr {
2252            write!(f, " {expr}")?;
2253        }
2254
2255        if !when_blocks.is_empty() {
2256            write!(f, " {}", display_separated(when_blocks, " "))?;
2257        }
2258
2259        if let Some(else_block) = else_block {
2260            write!(f, " {else_block}")?;
2261        }
2262
2263        write!(f, " END")?;
2264
2265        if let Token::Word(w) = &end.token {
2266            if w.keyword == Keyword::CASE {
2267                write!(f, " CASE")?;
2268            }
2269        }
2270
2271        Ok(())
2272    }
2273}
2274
2275/// An `IF` statement.
2276///
2277/// Example (BigQuery or Snowflake):
2278/// ```sql
2279/// IF TRUE THEN
2280///     SELECT 1;
2281///     SELECT 2;
2282/// ELSEIF TRUE THEN
2283///     SELECT 3;
2284/// ELSE
2285///     SELECT 4;
2286/// END IF
2287/// ```
2288/// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#if)
2289/// [Snowflake](https://docs.snowflake.com/en/sql-reference/snowflake-scripting/if)
2290///
2291/// Example (MSSQL):
2292/// ```sql
2293/// IF 1=1 SELECT 1 ELSE SELECT 2
2294/// ```
2295/// [MSSQL](https://learn.microsoft.com/en-us/sql/t-sql/language-elements/if-else-transact-sql?view=sql-server-ver16)
2296#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2297#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2298#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2299pub struct IfStatement {
2300    pub if_block: ConditionalStatementBlock,
2301    pub elseif_blocks: Vec<ConditionalStatementBlock>,
2302    pub else_block: Option<ConditionalStatementBlock>,
2303    pub end_token: Option<AttachedToken>,
2304}
2305
2306impl fmt::Display for IfStatement {
2307    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2308        let IfStatement {
2309            if_block,
2310            elseif_blocks,
2311            else_block,
2312            end_token,
2313        } = self;
2314
2315        write!(f, "{if_block}")?;
2316
2317        for elseif_block in elseif_blocks {
2318            write!(f, " {elseif_block}")?;
2319        }
2320
2321        if let Some(else_block) = else_block {
2322            write!(f, " {else_block}")?;
2323        }
2324
2325        if let Some(AttachedToken(end_token)) = end_token {
2326            write!(f, " END {end_token}")?;
2327        }
2328
2329        Ok(())
2330    }
2331}
2332
2333/// A `WHILE` statement.
2334///
2335/// Example:
2336/// ```sql
2337/// WHILE @@FETCH_STATUS = 0
2338/// BEGIN
2339///    FETCH NEXT FROM c1 INTO @var1, @var2;
2340/// END
2341/// ```
2342///
2343/// [MsSql](https://learn.microsoft.com/en-us/sql/t-sql/language-elements/while-transact-sql)
2344#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2345#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2346#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2347pub struct WhileStatement {
2348    pub label: Option<Ident>,
2349    pub while_block: ConditionalStatementBlock,
2350}
2351
2352impl fmt::Display for WhileStatement {
2353    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2354        let WhileStatement { label, while_block } = self;
2355        if let Some(l) = label {
2356            write!(f, "{}: ", l)?;
2357        }
2358        write!(f, "{while_block}")?;
2359        Ok(())
2360    }
2361}
2362
2363#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2364#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2365#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2366pub struct LoopStatement {
2367    pub label: Option<Ident>,
2368    pub body: Vec<Statement>,
2369}
2370
2371impl fmt::Display for LoopStatement {
2372    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2373        if let Some(label) = &self.label {
2374            write!(f, "{}: ", label)?;
2375        }
2376        write!(f, "LOOP ")?;
2377        format_statement_list(f, &self.body)?;
2378        write!(f, " END LOOP")?;
2379        if let Some(label) = &self.label {
2380            write!(f, " {}", label)?;
2381        }
2382        Ok(())
2383    }
2384}
2385
2386#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2387#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2388#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2389pub struct ForStatement {
2390    pub variable: Ident,
2391    pub query: Box<Query>,
2392    pub body: Vec<Statement>,
2393}
2394
2395impl fmt::Display for ForStatement {
2396    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2397        write!(f, "FOR {} IN (", self.variable)?;
2398        self.query.fmt(f)?;
2399        write!(f, ") DO ")?;
2400        format_statement_list(f, &self.body)?;
2401        write!(f, " END FOR")?;
2402        Ok(())
2403    }
2404}
2405
2406#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2407#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2408#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2409pub struct RepeatStatement {
2410    pub body: Vec<Statement>,
2411    pub until_condition: Expr,
2412}
2413
2414impl fmt::Display for RepeatStatement {
2415    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2416        write!(f, "REPEAT ")?;
2417        format_statement_list(f, &self.body)?;
2418        write!(f, " UNTIL ")?;
2419        self.until_condition.fmt(f)?;
2420        write!(f, " END REPEAT")?;
2421        Ok(())
2422    }
2423}
2424
2425/// A block within a [Statement::Case] or [Statement::If] or [Statement::While]-like statement
2426///
2427/// Example 1:
2428/// ```sql
2429/// WHEN EXISTS(SELECT 1) THEN SELECT 1;
2430/// ```
2431///
2432/// Example 2:
2433/// ```sql
2434/// IF TRUE THEN SELECT 1; SELECT 2;
2435/// ```
2436///
2437/// Example 3:
2438/// ```sql
2439/// ELSE SELECT 1; SELECT 2;
2440/// ```
2441///
2442/// Example 4:
2443/// ```sql
2444/// WHILE @@FETCH_STATUS = 0
2445/// BEGIN
2446///    FETCH NEXT FROM c1 INTO @var1, @var2;
2447/// END
2448/// ```
2449#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2450#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2451#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2452pub struct ConditionalStatementBlock {
2453    pub start_token: AttachedToken,
2454    pub condition: Option<Expr>,
2455    pub then_token: Option<AttachedToken>,
2456    pub conditional_statements: ConditionalStatements,
2457}
2458
2459impl ConditionalStatementBlock {
2460    pub fn statements(&self) -> &Vec<Statement> {
2461        self.conditional_statements.statements()
2462    }
2463}
2464
2465impl fmt::Display for ConditionalStatementBlock {
2466    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2467        let ConditionalStatementBlock {
2468            start_token: AttachedToken(start_token),
2469            condition,
2470            then_token,
2471            conditional_statements,
2472        } = self;
2473
2474        write!(f, "{start_token}")?;
2475
2476        if let Some(condition) = condition {
2477            write!(f, " {condition}")?;
2478        }
2479
2480        if then_token.is_some() {
2481            write!(f, " THEN")?;
2482        }
2483
2484        if !conditional_statements.statements().is_empty() {
2485            write!(f, " {conditional_statements}")?;
2486        }
2487
2488        Ok(())
2489    }
2490}
2491
2492/// A list of statements in a [ConditionalStatementBlock].
2493#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2494#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2495#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2496pub enum ConditionalStatements {
2497    /// SELECT 1; SELECT 2; SELECT 3; ...
2498    Sequence { statements: Vec<Statement> },
2499    /// BEGIN SELECT 1; SELECT 2; SELECT 3; ... END
2500    BeginEnd(BeginEndStatements),
2501}
2502
2503impl ConditionalStatements {
2504    pub fn statements(&self) -> &Vec<Statement> {
2505        match self {
2506            ConditionalStatements::Sequence { statements } => statements,
2507            ConditionalStatements::BeginEnd(bes) => &bes.statements,
2508        }
2509    }
2510}
2511
2512impl fmt::Display for ConditionalStatements {
2513    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2514        match self {
2515            ConditionalStatements::Sequence { statements } => {
2516                if !statements.is_empty() {
2517                    format_statement_list(f, statements)?;
2518                }
2519                Ok(())
2520            }
2521            ConditionalStatements::BeginEnd(bes) => write!(f, "{bes}"),
2522        }
2523    }
2524}
2525
2526/// Represents a list of statements enclosed within `BEGIN` and `END` keywords.
2527/// Example:
2528/// ```sql
2529/// BEGIN
2530///     SELECT 1;
2531///     SELECT 2;
2532/// END
2533/// ```
2534#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2535#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2536#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2537pub struct BeginEndStatements {
2538    pub begin_token: AttachedToken,
2539    pub statements: Vec<Statement>,
2540    pub end_token: AttachedToken,
2541}
2542
2543impl fmt::Display for BeginEndStatements {
2544    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2545        let BeginEndStatements {
2546            begin_token: AttachedToken(begin_token),
2547            statements,
2548            end_token: AttachedToken(end_token),
2549        } = self;
2550
2551        if begin_token.token != Token::EOF {
2552            write!(f, "{begin_token} ")?;
2553        }
2554        if !statements.is_empty() {
2555            format_statement_list(f, statements)?;
2556        }
2557        if end_token.token != Token::EOF {
2558            write!(f, " {end_token}")?;
2559        }
2560        Ok(())
2561    }
2562}
2563
2564/// A `RAISE` statement.
2565///
2566/// Examples:
2567/// ```sql
2568/// RAISE USING MESSAGE = 'error';
2569///
2570/// RAISE myerror;
2571/// ```
2572///
2573/// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#raise)
2574/// [Snowflake](https://docs.snowflake.com/en/sql-reference/snowflake-scripting/raise)
2575#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2576#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2577#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2578pub struct RaiseStatement {
2579    pub value: Option<RaiseStatementValue>,
2580}
2581
2582impl fmt::Display for RaiseStatement {
2583    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2584        let RaiseStatement { value } = self;
2585
2586        write!(f, "RAISE")?;
2587        if let Some(value) = value {
2588            write!(f, " {value}")?;
2589        }
2590
2591        Ok(())
2592    }
2593}
2594
2595/// Represents the error value of a [RaiseStatement].
2596#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2597#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2598#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2599pub enum RaiseStatementValue {
2600    /// `RAISE USING MESSAGE = 'error'`
2601    UsingMessage(Expr),
2602    /// `RAISE myerror`
2603    Expr(Expr),
2604}
2605
2606impl fmt::Display for RaiseStatementValue {
2607    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2608        match self {
2609            RaiseStatementValue::Expr(expr) => write!(f, "{expr}"),
2610            RaiseStatementValue::UsingMessage(expr) => write!(f, "USING MESSAGE = {expr}"),
2611        }
2612    }
2613}
2614
2615/// Represents an expression assignment within a variable `DECLARE` statement.
2616///
2617/// Examples:
2618/// ```sql
2619/// DECLARE variable_name := 42
2620/// DECLARE variable_name DEFAULT 42
2621/// ```
2622#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2623#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2624#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2625pub enum DeclareAssignment {
2626    /// Plain expression specified.
2627    Expr(Box<Expr>),
2628
2629    /// Expression assigned via the `DEFAULT` keyword
2630    Default(Box<Expr>),
2631
2632    /// Expression assigned via the `:=` syntax
2633    ///
2634    /// Example:
2635    /// ```sql
2636    /// DECLARE variable_name := 42;
2637    /// ```
2638    DuckAssignment(Box<Expr>),
2639
2640    /// Expression via the `FOR` keyword
2641    ///
2642    /// Example:
2643    /// ```sql
2644    /// DECLARE c1 CURSOR FOR res
2645    /// ```
2646    For(Box<Expr>),
2647
2648    /// Expression via the `=` syntax.
2649    ///
2650    /// Example:
2651    /// ```sql
2652    /// DECLARE @variable AS INT = 100
2653    /// ```
2654    MsSqlAssignment(Box<Expr>),
2655}
2656
2657impl fmt::Display for DeclareAssignment {
2658    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2659        match self {
2660            DeclareAssignment::Expr(expr) => {
2661                write!(f, "{expr}")
2662            }
2663            DeclareAssignment::Default(expr) => {
2664                write!(f, "DEFAULT {expr}")
2665            }
2666            DeclareAssignment::DuckAssignment(expr) => {
2667                write!(f, ":= {expr}")
2668            }
2669            DeclareAssignment::MsSqlAssignment(expr) => {
2670                write!(f, "= {expr}")
2671            }
2672            DeclareAssignment::For(expr) => {
2673                write!(f, "FOR {expr}")
2674            }
2675        }
2676    }
2677}
2678
2679/// Represents the type of a `DECLARE` statement.
2680#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2681#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2682#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2683pub enum DeclareType {
2684    /// Cursor variable type. e.g. [Snowflake] [PostgreSQL] [MsSql]
2685    ///
2686    /// [Snowflake]: https://docs.snowflake.com/en/developer-guide/snowflake-scripting/cursors#declaring-a-cursor
2687    /// [PostgreSQL]: https://www.postgresql.org/docs/current/plpgsql-cursors.html
2688    /// [MsSql]: https://learn.microsoft.com/en-us/sql/t-sql/language-elements/declare-cursor-transact-sql
2689    Cursor,
2690
2691    /// Result set variable type. [Snowflake]
2692    ///
2693    /// Syntax:
2694    /// ```text
2695    /// <resultset_name> RESULTSET [ { DEFAULT | := } ( <query> ) ] ;
2696    /// ```
2697    /// [Snowflake]: https://docs.snowflake.com/en/sql-reference/snowflake-scripting/declare#resultset-declaration-syntax
2698    ResultSet,
2699
2700    /// Exception declaration syntax. [Snowflake]
2701    ///
2702    /// Syntax:
2703    /// ```text
2704    /// <exception_name> EXCEPTION [ ( <exception_number> , '<exception_message>' ) ] ;
2705    /// ```
2706    /// [Snowflake]: https://docs.snowflake.com/en/sql-reference/snowflake-scripting/declare#exception-declaration-syntax
2707    Exception,
2708}
2709
2710impl fmt::Display for DeclareType {
2711    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2712        match self {
2713            DeclareType::Cursor => {
2714                write!(f, "CURSOR")
2715            }
2716            DeclareType::ResultSet => {
2717                write!(f, "RESULTSET")
2718            }
2719            DeclareType::Exception => {
2720                write!(f, "EXCEPTION")
2721            }
2722        }
2723    }
2724}
2725
2726/// A `DECLARE` statement.
2727/// [PostgreSQL] [Snowflake] [BigQuery]
2728///
2729/// Examples:
2730/// ```sql
2731/// DECLARE variable_name := 42
2732/// DECLARE liahona CURSOR FOR SELECT * FROM films;
2733/// ```
2734///
2735/// [PostgreSQL]: https://www.postgresql.org/docs/current/sql-declare.html
2736/// [Snowflake]: https://docs.snowflake.com/en/sql-reference/snowflake-scripting/declare
2737/// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#declare
2738#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2739#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2740#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2741pub struct Declare {
2742    /// The name(s) being declared.
2743    /// Example: `DECLARE a, b, c DEFAULT 42;
2744    pub names: Vec<Ident>,
2745    /// Data-type assigned to the declared variable.
2746    /// Example: `DECLARE x INT64 DEFAULT 42;
2747    pub data_type: Option<DataType>,
2748    /// Expression being assigned to the declared variable.
2749    pub assignment: Option<DeclareAssignment>,
2750    /// Represents the type of the declared variable.
2751    pub declare_type: Option<DeclareType>,
2752    /// Causes the cursor to return data in binary rather than in text format.
2753    pub binary: Option<bool>,
2754    /// None = Not specified
2755    /// Some(true) = INSENSITIVE
2756    /// Some(false) = ASENSITIVE
2757    pub sensitive: Option<bool>,
2758    /// None = Not specified
2759    /// Some(true) = SCROLL
2760    /// Some(false) = NO SCROLL
2761    pub scroll: Option<bool>,
2762    /// None = Not specified
2763    /// Some(true) = WITH HOLD, specifies that the cursor can continue to be used after the transaction that created it successfully commits
2764    /// Some(false) = WITHOUT HOLD, specifies that the cursor cannot be used outside of the transaction that created it
2765    pub hold: Option<bool>,
2766    /// `FOR <query>` clause in a CURSOR declaration.
2767    pub for_query: Option<Box<Query>>,
2768}
2769
2770impl fmt::Display for Declare {
2771    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2772        let Declare {
2773            names,
2774            data_type,
2775            assignment,
2776            declare_type,
2777            binary,
2778            sensitive,
2779            scroll,
2780            hold,
2781            for_query,
2782        } = self;
2783        write!(f, "{}", display_comma_separated(names))?;
2784
2785        if let Some(true) = binary {
2786            write!(f, " BINARY")?;
2787        }
2788
2789        if let Some(sensitive) = sensitive {
2790            if *sensitive {
2791                write!(f, " INSENSITIVE")?;
2792            } else {
2793                write!(f, " ASENSITIVE")?;
2794            }
2795        }
2796
2797        if let Some(scroll) = scroll {
2798            if *scroll {
2799                write!(f, " SCROLL")?;
2800            } else {
2801                write!(f, " NO SCROLL")?;
2802            }
2803        }
2804
2805        if let Some(declare_type) = declare_type {
2806            write!(f, " {declare_type}")?;
2807        }
2808
2809        if let Some(hold) = hold {
2810            if *hold {
2811                write!(f, " WITH HOLD")?;
2812            } else {
2813                write!(f, " WITHOUT HOLD")?;
2814            }
2815        }
2816
2817        if let Some(query) = for_query {
2818            write!(f, " FOR {query}")?;
2819        }
2820
2821        if let Some(data_type) = data_type {
2822            write!(f, " {data_type}")?;
2823        }
2824
2825        if let Some(expr) = assignment {
2826            write!(f, " {expr}")?;
2827        }
2828        Ok(())
2829    }
2830}
2831
2832/// Sql options of a `CREATE TABLE` statement.
2833#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2834#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2835#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2836pub enum CreateTableOptions {
2837    None,
2838    /// Options specified using the `WITH` keyword.
2839    /// e.g. `WITH (description = "123")`
2840    ///
2841    /// <https://www.postgresql.org/docs/current/sql-createtable.html>
2842    ///
2843    /// MSSQL supports more specific options that's not only key-value pairs.
2844    ///
2845    /// WITH (
2846    ///     DISTRIBUTION = ROUND_ROBIN,
2847    ///     CLUSTERED INDEX (column_a DESC, column_b)
2848    /// )
2849    ///
2850    /// <https://learn.microsoft.com/en-us/sql/t-sql/statements/create-table-azure-sql-data-warehouse?view=aps-pdw-2016-au7#syntax>
2851    With(Vec<SqlOption>),
2852    /// Options specified using the `OPTIONS` keyword.
2853    /// e.g. `OPTIONS(description = "123")`
2854    ///
2855    /// <https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#table_option_list>
2856    Options(Vec<SqlOption>),
2857
2858    /// Plain options, options which are not part on any declerative statement e.g. WITH/OPTIONS/...
2859    /// <https://dev.mysql.com/doc/refman/8.4/en/create-table.html>
2860    Plain(Vec<SqlOption>),
2861
2862    TableProperties(Vec<SqlOption>),
2863}
2864
2865impl Default for CreateTableOptions {
2866    fn default() -> Self {
2867        Self::None
2868    }
2869}
2870
2871impl fmt::Display for CreateTableOptions {
2872    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2873        match self {
2874            CreateTableOptions::With(with_options) => {
2875                write!(f, "WITH ({})", display_comma_separated(with_options))
2876            }
2877            CreateTableOptions::Options(options) => {
2878                write!(f, "OPTIONS({})", display_comma_separated(options))
2879            }
2880            CreateTableOptions::TableProperties(options) => {
2881                write!(f, "TBLPROPERTIES ({})", display_comma_separated(options))
2882            }
2883            CreateTableOptions::Plain(options) => {
2884                write!(f, "{}", display_separated(options, " "))
2885            }
2886            CreateTableOptions::None => Ok(()),
2887        }
2888    }
2889}
2890
2891/// A `FROM` clause within a `DELETE` statement.
2892///
2893/// Syntax
2894/// ```sql
2895/// [FROM] table
2896/// ```
2897#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2898#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2899#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2900pub enum FromTable {
2901    /// An explicit `FROM` keyword was specified.
2902    WithFromKeyword(Vec<TableWithJoins>),
2903    /// BigQuery: `FROM` keyword was omitted.
2904    /// <https://cloud.google.com/bigquery/docs/reference/standard-sql/dml-syntax#delete_statement>
2905    WithoutKeyword(Vec<TableWithJoins>),
2906}
2907impl Display for FromTable {
2908    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2909        match self {
2910            FromTable::WithFromKeyword(tables) => {
2911                write!(f, "FROM {}", display_comma_separated(tables))
2912            }
2913            FromTable::WithoutKeyword(tables) => {
2914                write!(f, "{}", display_comma_separated(tables))
2915            }
2916        }
2917    }
2918}
2919
2920/// Policy type for a `CREATE POLICY` statement.
2921/// ```sql
2922/// AS [ PERMISSIVE | RESTRICTIVE ]
2923/// ```
2924/// [PostgreSQL](https://www.postgresql.org/docs/current/sql-createpolicy.html)
2925#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2926#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2927#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2928pub enum CreatePolicyType {
2929    Permissive,
2930    Restrictive,
2931}
2932
2933/// Policy command for a `CREATE POLICY` statement.
2934/// ```sql
2935/// FOR [ALL | SELECT | INSERT | UPDATE | DELETE]
2936/// ```
2937/// [PostgreSQL](https://www.postgresql.org/docs/current/sql-createpolicy.html)
2938#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2939#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2940#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2941pub enum CreatePolicyCommand {
2942    All,
2943    Select,
2944    Insert,
2945    Update,
2946    Delete,
2947}
2948
2949#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2950#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2951#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2952pub enum Set {
2953    /// SQL Standard-style
2954    /// SET a = 1;
2955    SingleAssignment {
2956        scope: Option<ContextModifier>,
2957        hivevar: bool,
2958        variable: ObjectName,
2959        values: Vec<Expr>,
2960    },
2961    /// Snowflake-style
2962    /// SET (a, b, ..) = (1, 2, ..);
2963    ParenthesizedAssignments {
2964        variables: Vec<ObjectName>,
2965        values: Vec<Expr>,
2966    },
2967    /// MySQL-style
2968    /// SET a = 1, b = 2, ..;
2969    MultipleAssignments { assignments: Vec<SetAssignment> },
2970    /// MS-SQL session
2971    ///
2972    /// See <https://learn.microsoft.com/en-us/sql/t-sql/statements/set-statements-transact-sql>
2973    SetSessionParam(SetSessionParamKind),
2974    /// ```sql
2975    /// SET [ SESSION | LOCAL ] ROLE role_name
2976    /// ```
2977    ///
2978    /// Sets session state. Examples: [ANSI][1], [Postgresql][2], [MySQL][3], and [Oracle][4]
2979    ///
2980    /// [1]: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#set-role-statement
2981    /// [2]: https://www.postgresql.org/docs/14/sql-set-role.html
2982    /// [3]: https://dev.mysql.com/doc/refman/8.0/en/set-role.html
2983    /// [4]: https://docs.oracle.com/cd/B19306_01/server.102/b14200/statements_10004.htm
2984    SetRole {
2985        /// Non-ANSI optional identifier to inform if the role is defined inside the current session (`SESSION`) or transaction (`LOCAL`).
2986        context_modifier: Option<ContextModifier>,
2987        /// Role name. If NONE is specified, then the current role name is removed.
2988        role_name: Option<Ident>,
2989    },
2990    /// ```sql
2991    /// SET TIME ZONE <value>
2992    /// ```
2993    ///
2994    /// Note: this is a PostgreSQL-specific statements
2995    /// `SET TIME ZONE <value>` is an alias for `SET timezone TO <value>` in PostgreSQL
2996    /// However, we allow it for all dialects.
2997    SetTimeZone { local: bool, value: Expr },
2998    /// ```sql
2999    /// SET NAMES 'charset_name' [COLLATE 'collation_name']
3000    /// ```
3001    SetNames {
3002        charset_name: Ident,
3003        collation_name: Option<String>,
3004    },
3005    /// ```sql
3006    /// SET NAMES DEFAULT
3007    /// ```
3008    ///
3009    /// Note: this is a MySQL-specific statement.
3010    SetNamesDefault {},
3011    /// ```sql
3012    /// SET TRANSACTION ...
3013    /// ```
3014    SetTransaction {
3015        modes: Vec<TransactionMode>,
3016        snapshot: Option<Value>,
3017        session: bool,
3018    },
3019}
3020
3021impl Display for Set {
3022    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3023        match self {
3024            Self::ParenthesizedAssignments { variables, values } => write!(
3025                f,
3026                "SET ({}) = ({})",
3027                display_comma_separated(variables),
3028                display_comma_separated(values)
3029            ),
3030            Self::MultipleAssignments { assignments } => {
3031                write!(f, "SET {}", display_comma_separated(assignments))
3032            }
3033            Self::SetRole {
3034                context_modifier,
3035                role_name,
3036            } => {
3037                let role_name = role_name.clone().unwrap_or_else(|| Ident::new("NONE"));
3038                write!(
3039                    f,
3040                    "SET {modifier}ROLE {role_name}",
3041                    modifier = context_modifier.map(|m| format!("{m}")).unwrap_or_default()
3042                )
3043            }
3044            Self::SetSessionParam(kind) => write!(f, "SET {kind}"),
3045            Self::SetTransaction {
3046                modes,
3047                snapshot,
3048                session,
3049            } => {
3050                if *session {
3051                    write!(f, "SET SESSION CHARACTERISTICS AS TRANSACTION")?;
3052                } else {
3053                    write!(f, "SET TRANSACTION")?;
3054                }
3055                if !modes.is_empty() {
3056                    write!(f, " {}", display_comma_separated(modes))?;
3057                }
3058                if let Some(snapshot_id) = snapshot {
3059                    write!(f, " SNAPSHOT {snapshot_id}")?;
3060                }
3061                Ok(())
3062            }
3063            Self::SetTimeZone { local, value } => {
3064                f.write_str("SET ")?;
3065                if *local {
3066                    f.write_str("LOCAL ")?;
3067                }
3068                write!(f, "TIME ZONE {value}")
3069            }
3070            Self::SetNames {
3071                charset_name,
3072                collation_name,
3073            } => {
3074                write!(f, "SET NAMES {charset_name}")?;
3075
3076                if let Some(collation) = collation_name {
3077                    f.write_str(" COLLATE ")?;
3078                    f.write_str(collation)?;
3079                };
3080
3081                Ok(())
3082            }
3083            Self::SetNamesDefault {} => {
3084                f.write_str("SET NAMES DEFAULT")?;
3085
3086                Ok(())
3087            }
3088            Set::SingleAssignment {
3089                scope,
3090                hivevar,
3091                variable,
3092                values,
3093            } => {
3094                write!(
3095                    f,
3096                    "SET {}{}{} = {}",
3097                    scope.map(|s| format!("{s}")).unwrap_or_default(),
3098                    if *hivevar { "HIVEVAR:" } else { "" },
3099                    variable,
3100                    display_comma_separated(values)
3101                )
3102            }
3103        }
3104    }
3105}
3106
3107/// A representation of a `WHEN` arm with all the identifiers catched and the statements to execute
3108/// for the arm.
3109///
3110/// Snowflake: <https://docs.snowflake.com/en/sql-reference/snowflake-scripting/exception>
3111/// BigQuery: <https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#beginexceptionend>
3112#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3113#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3114#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3115pub struct ExceptionWhen {
3116    pub idents: Vec<Ident>,
3117    pub statements: Vec<Statement>,
3118}
3119
3120impl Display for ExceptionWhen {
3121    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3122        write!(
3123            f,
3124            "WHEN {idents} THEN",
3125            idents = display_separated(&self.idents, " OR ")
3126        )?;
3127
3128        if !self.statements.is_empty() {
3129            write!(f, " ")?;
3130            format_statement_list(f, &self.statements)?;
3131        }
3132
3133        Ok(())
3134    }
3135}
3136
3137/// A top-level statement (SELECT, INSERT, CREATE, etc.)
3138#[allow(clippy::large_enum_variant)]
3139#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3140#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3141#[cfg_attr(
3142    feature = "visitor",
3143    derive(Visit, VisitMut),
3144    visit(with = "visit_statement")
3145)]
3146pub enum Statement {
3147    /// ```sql
3148    /// ANALYZE
3149    /// ```
3150    /// Analyze (Hive)
3151    Analyze {
3152        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
3153        table_name: ObjectName,
3154        partitions: Option<Vec<Expr>>,
3155        for_columns: bool,
3156        columns: Vec<Ident>,
3157        cache_metadata: bool,
3158        noscan: bool,
3159        compute_statistics: bool,
3160        has_table_keyword: bool,
3161    },
3162    Set(Set),
3163    /// ```sql
3164    /// TRUNCATE
3165    /// ```
3166    /// Truncate (Hive)
3167    Truncate {
3168        table_names: Vec<TruncateTableTarget>,
3169        partitions: Option<Vec<Expr>>,
3170        /// TABLE - optional keyword;
3171        table: bool,
3172        /// Postgres-specific option
3173        /// [ RESTART IDENTITY | CONTINUE IDENTITY ]
3174        identity: Option<TruncateIdentityOption>,
3175        /// Postgres-specific option
3176        /// [ CASCADE | RESTRICT ]
3177        cascade: Option<CascadeOption>,
3178        /// ClickHouse-specific option
3179        /// [ ON CLUSTER cluster_name ]
3180        ///
3181        /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/truncate/)
3182        on_cluster: Option<Ident>,
3183    },
3184    /// ```sql
3185    /// MSCK
3186    /// ```
3187    /// Msck (Hive)
3188    Msck {
3189        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
3190        table_name: ObjectName,
3191        repair: bool,
3192        partition_action: Option<AddDropSync>,
3193    },
3194    /// ```sql
3195    /// SELECT
3196    /// ```
3197    Query(Box<Query>),
3198    /// ```sql
3199    /// INSERT
3200    /// ```
3201    Insert(Insert),
3202    /// ```sql
3203    /// INSTALL
3204    /// ```
3205    Install {
3206        /// Only for DuckDB
3207        extension_name: Ident,
3208    },
3209    /// ```sql
3210    /// LOAD
3211    /// ```
3212    Load {
3213        /// Only for DuckDB
3214        extension_name: Ident,
3215    },
3216    // TODO: Support ROW FORMAT
3217    Directory {
3218        overwrite: bool,
3219        local: bool,
3220        path: String,
3221        file_format: Option<FileFormat>,
3222        source: Box<Query>,
3223    },
3224    /// A `CASE` statement.
3225    Case(CaseStatement),
3226    /// An `IF` statement.
3227    If(IfStatement),
3228    /// A `WHILE` statement.
3229    While(WhileStatement),
3230    /// A `LOOP` statement (BigQuery).
3231    Loop(LoopStatement),
3232    /// A `FOR` statement (BigQuery).
3233    For(ForStatement),
3234    /// A `REPEAT` statement (BigQuery).
3235    Repeat(RepeatStatement),
3236    /// A `LEAVE` statement (exits a loop or block).
3237    Leave {
3238        label: Option<Ident>,
3239    },
3240    /// An `ITERATE` statement (continues to next loop iteration).
3241    Iterate {
3242        label: Option<Ident>,
3243    },
3244    /// A `BREAK` statement (exits a loop, alias for LEAVE in BigQuery).
3245    Break {
3246        label: Option<Ident>,
3247    },
3248    /// A `CONTINUE` statement (continues to next loop iteration).
3249    Continue {
3250        label: Option<Ident>,
3251    },
3252    /// A `RAISE` statement.
3253    Raise(RaiseStatement),
3254    /// ```sql
3255    /// CALL <function>
3256    /// ```
3257    Call(Function),
3258    /// ```sql
3259    /// COPY [TO | FROM] ...
3260    /// ```
3261    Copy {
3262        /// The source of 'COPY TO', or the target of 'COPY FROM'
3263        source: CopySource,
3264        /// If true, is a 'COPY TO' statement. If false is a 'COPY FROM'
3265        to: bool,
3266        /// The target of 'COPY TO', or the source of 'COPY FROM'
3267        target: CopyTarget,
3268        /// WITH options (from PostgreSQL version 9.0)
3269        options: Vec<CopyOption>,
3270        /// WITH options (before PostgreSQL version 9.0)
3271        legacy_options: Vec<CopyLegacyOption>,
3272        /// VALUES a vector of values to be copied
3273        values: Vec<Option<String>>,
3274    },
3275    /// ```sql
3276    /// COPY INTO <table> | <location>
3277    /// ```
3278    /// See:
3279    /// <https://docs.snowflake.com/en/sql-reference/sql/copy-into-table>
3280    /// <https://docs.snowflake.com/en/sql-reference/sql/copy-into-location>
3281    ///
3282    /// Copy Into syntax available for Snowflake is different than the one implemented in
3283    /// Postgres. Although they share common prefix, it is reasonable to implement them
3284    /// in different enums. This can be refactored later once custom dialects
3285    /// are allowed to have custom Statements.
3286    CopyIntoSnowflake {
3287        kind: CopyIntoSnowflakeKind,
3288        into: ObjectName,
3289        into_columns: Option<Vec<Ident>>,
3290        from_obj: Option<ObjectName>,
3291        from_obj_alias: Option<Ident>,
3292        stage_params: StageParamsObject,
3293        from_transformations: Option<Vec<StageLoadSelectItemKind>>,
3294        from_query: Option<Box<Query>>,
3295        files: Option<Vec<String>>,
3296        pattern: Option<String>,
3297        file_format: KeyValueOptions,
3298        copy_options: KeyValueOptions,
3299        validation_mode: Option<String>,
3300        partition: Option<Box<Expr>>,
3301    },
3302    /// ```sql
3303    /// OPEN cursor_name
3304    /// ```
3305    /// Opens a cursor.
3306    Open(OpenStatement),
3307    /// ```sql
3308    /// CLOSE
3309    /// ```
3310    /// Closes the portal underlying an open cursor.
3311    Close {
3312        /// Cursor name
3313        cursor: CloseCursor,
3314    },
3315    /// ```sql
3316    /// UPDATE
3317    /// ```
3318    Update {
3319        /// TABLE
3320        table: TableWithJoins,
3321        /// Column assignments
3322        assignments: Vec<Assignment>,
3323        /// Table which provide value to be set
3324        from: Option<UpdateTableFromKind>,
3325        /// WHERE
3326        selection: Option<Expr>,
3327        /// RETURNING
3328        returning: Option<Vec<SelectItem>>,
3329        /// SQLite-specific conflict resolution clause
3330        or: Option<SqliteOnConflict>,
3331        /// LIMIT
3332        limit: Option<Expr>,
3333    },
3334    /// ```sql
3335    /// DELETE
3336    /// ```
3337    Delete(Delete),
3338    /// ```sql
3339    /// CREATE VIEW
3340    /// ```
3341    CreateView {
3342        /// True if this is a `CREATE OR ALTER VIEW` statement
3343        ///
3344        /// [MsSql](https://learn.microsoft.com/en-us/sql/t-sql/statements/create-view-transact-sql)
3345        or_alter: bool,
3346        or_replace: bool,
3347        materialized: bool,
3348        /// Snowflake: SECURE view modifier
3349        /// <https://docs.snowflake.com/en/sql-reference/sql/create-view#syntax>
3350        secure: bool,
3351        /// View name
3352        name: ObjectName,
3353        /// If `if_not_exists` is true, this flag is set to true if the view name comes before the `IF NOT EXISTS` clause.
3354        /// Example:
3355        /// ```sql
3356        /// CREATE VIEW myview IF NOT EXISTS AS SELECT 1`
3357        ///  ```
3358        /// Otherwise, the flag is set to false if the view name comes after the clause
3359        /// Example:
3360        /// ```sql
3361        /// CREATE VIEW IF NOT EXISTS myview AS SELECT 1`
3362        ///  ```
3363        name_before_not_exists: bool,
3364        columns: Vec<ViewColumnDef>,
3365        query: Box<Query>,
3366        options: CreateTableOptions,
3367        partition_by: Option<Box<Expr>>,
3368        cluster_by: Vec<Ident>,
3369        /// Snowflake: Views can have comments in Snowflake.
3370        /// <https://docs.snowflake.com/en/sql-reference/sql/create-view#syntax>
3371        comment: Option<String>,
3372        /// if true, has RedShift [`WITH NO SCHEMA BINDING`] clause <https://docs.aws.amazon.com/redshift/latest/dg/r_CREATE_VIEW.html>
3373        with_no_schema_binding: bool,
3374        /// if true, has SQLite `IF NOT EXISTS` clause <https://www.sqlite.org/lang_createview.html>
3375        if_not_exists: bool,
3376        /// if true, has SQLite `TEMP` or `TEMPORARY` clause <https://www.sqlite.org/lang_createview.html>
3377        temporary: bool,
3378        /// if not None, has Clickhouse `TO` clause, specify the table into which to insert results
3379        /// <https://clickhouse.com/docs/en/sql-reference/statements/create/view#materialized-view>
3380        to: Option<ObjectName>,
3381        /// MySQL: Optional parameters for the view algorithm, definer, and security context
3382        params: Option<CreateViewParams>,
3383        /// BigQuery: SQL SECURITY DEFINER/INVOKER
3384        sql_security: Option<SqlSecurity>,
3385    },
3386    /// ```sql
3387    /// CREATE MATERIALIZED VIEW REPLICA name AS REPLICA OF source
3388    /// ```
3389    CreateMaterializedViewReplica {
3390        name: ObjectName,
3391        source: ObjectName,
3392        if_not_exists: bool,
3393    },
3394    /// ```sql
3395    /// CREATE TABLE
3396    /// ```
3397    CreateTable(CreateTable),
3398    /// ```sql
3399    /// CREATE VIRTUAL TABLE .. USING <module_name> (<module_args>)`
3400    /// ```
3401    /// Sqlite specific statement
3402    CreateVirtualTable {
3403        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
3404        name: ObjectName,
3405        if_not_exists: bool,
3406        module_name: Ident,
3407        module_args: Vec<Ident>,
3408    },
3409    /// ```sql
3410    /// `CREATE INDEX`
3411    /// ```
3412    CreateIndex(CreateIndex),
3413    /// ```sql
3414    /// CREATE SEARCH INDEX (BigQuery)
3415    /// ```
3416    CreateSearchIndex {
3417        or_replace: bool,
3418        if_not_exists: bool,
3419        name: ObjectName,
3420        table_name: ObjectName,
3421        columns: Vec<Ident>,
3422        all_columns: bool,
3423        options: Vec<SqlOption>,
3424    },
3425    /// ```sql
3426    /// CREATE VECTOR INDEX (BigQuery)
3427    /// ```
3428    CreateVectorIndex {
3429        or_replace: bool,
3430        if_not_exists: bool,
3431        name: ObjectName,
3432        table_name: ObjectName,
3433        column: Ident,
3434        storing: Vec<Ident>,
3435        options: Vec<SqlOption>,
3436    },
3437    /// ```sql
3438    /// CREATE ROW ACCESS POLICY (BigQuery)
3439    /// ```
3440    CreateRowAccessPolicy {
3441        or_replace: bool,
3442        if_not_exists: bool,
3443        name: ObjectName,
3444        table_name: ObjectName,
3445        grant_to: Vec<Expr>,
3446        filter_using: Expr,
3447    },
3448    /// ```sql
3449    /// DROP SEARCH INDEX (BigQuery)
3450    /// ```
3451    DropSearchIndex {
3452        if_exists: bool,
3453        name: ObjectName,
3454        table_name: ObjectName,
3455    },
3456    /// ```sql
3457    /// DROP VECTOR INDEX (BigQuery)
3458    /// ```
3459    DropVectorIndex {
3460        if_exists: bool,
3461        name: ObjectName,
3462        table_name: ObjectName,
3463    },
3464    /// ```sql
3465    /// DROP ROW ACCESS POLICY (BigQuery)
3466    /// ```
3467    DropRowAccessPolicy {
3468        if_exists: bool,
3469        name: ObjectName,
3470        table_name: ObjectName,
3471    },
3472    /// ```sql
3473    /// DROP ALL ROW ACCESS POLICIES (BigQuery)
3474    /// ```
3475    DropAllRowAccessPolicies {
3476        table_name: ObjectName,
3477    },
3478    /// ```sql
3479    /// CREATE ROLE
3480    /// ```
3481    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createrole.html)
3482    CreateRole {
3483        names: Vec<ObjectName>,
3484        if_not_exists: bool,
3485        // Postgres
3486        login: Option<bool>,
3487        inherit: Option<bool>,
3488        bypassrls: Option<bool>,
3489        password: Option<Password>,
3490        superuser: Option<bool>,
3491        create_db: Option<bool>,
3492        create_role: Option<bool>,
3493        replication: Option<bool>,
3494        connection_limit: Option<Expr>,
3495        valid_until: Option<Expr>,
3496        in_role: Vec<Ident>,
3497        in_group: Vec<Ident>,
3498        role: Vec<Ident>,
3499        user: Vec<Ident>,
3500        admin: Vec<Ident>,
3501        // MSSQL
3502        authorization_owner: Option<ObjectName>,
3503    },
3504    /// ```sql
3505    /// CREATE SECRET
3506    /// ```
3507    /// See [DuckDB](https://duckdb.org/docs/sql/statements/create_secret.html)
3508    CreateSecret {
3509        or_replace: bool,
3510        temporary: Option<bool>,
3511        if_not_exists: bool,
3512        name: Option<Ident>,
3513        storage_specifier: Option<Ident>,
3514        secret_type: Ident,
3515        options: Vec<SecretOption>,
3516    },
3517    /// A `CREATE SERVER` statement.
3518    CreateServer(CreateServerStatement),
3519    /// ```sql
3520    /// CREATE POLICY
3521    /// ```
3522    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createpolicy.html)
3523    CreatePolicy {
3524        name: Ident,
3525        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
3526        table_name: ObjectName,
3527        policy_type: Option<CreatePolicyType>,
3528        command: Option<CreatePolicyCommand>,
3529        to: Option<Vec<Owner>>,
3530        using: Option<Expr>,
3531        with_check: Option<Expr>,
3532    },
3533    /// ```sql
3534    /// CREATE CONNECTOR
3535    /// ```
3536    /// See [Hive](https://cwiki.apache.org/confluence/pages/viewpage.action?pageId=27362034#LanguageManualDDL-CreateDataConnectorCreateConnector)
3537    CreateConnector(CreateConnector),
3538    /// ```sql
3539    /// ALTER TABLE
3540    /// ```
3541    AlterTable {
3542        /// Table name
3543        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
3544        name: ObjectName,
3545        if_exists: bool,
3546        only: bool,
3547        operations: Vec<AlterTableOperation>,
3548        location: Option<HiveSetLocation>,
3549        /// ClickHouse dialect supports `ON CLUSTER` clause for ALTER TABLE
3550        /// For example: `ALTER TABLE table_name ON CLUSTER cluster_name ADD COLUMN c UInt32`
3551        /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/alter/update)
3552        on_cluster: Option<Ident>,
3553        /// Snowflake "ICEBERG" clause for Iceberg tables
3554        /// <https://docs.snowflake.com/en/sql-reference/sql/alter-iceberg-table>
3555        iceberg: bool,
3556        /// Token that represents the end of the statement (semicolon or EOF)
3557        end_token: AttachedToken,
3558    },
3559    /// ```sql
3560    /// ALTER SCHEMA
3561    /// ```
3562    /// See [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#alter_schema_collate_statement)
3563    AlterSchema(AlterSchema),
3564    /// ```sql
3565    /// ALTER INDEX
3566    /// ```
3567    AlterIndex {
3568        name: ObjectName,
3569        operation: AlterIndexOperation,
3570    },
3571    /// ```sql
3572    /// ALTER VIEW
3573    /// ```
3574    AlterView {
3575        /// View name
3576        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
3577        name: ObjectName,
3578        columns: Vec<Ident>,
3579        query: Box<Query>,
3580        with_options: Vec<SqlOption>,
3581    },
3582    /// ```sql
3583    /// ALTER MATERIALIZED VIEW
3584    /// ```
3585    AlterMaterializedView {
3586        /// Materialized view name
3587        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
3588        name: ObjectName,
3589        options: Vec<SqlOption>,
3590        operations: Vec<AlterViewOperation>,
3591    },
3592    /// ```sql
3593    /// ALTER VIEW ... SET OPTIONS / ALTER COLUMN (BigQuery-style)
3594    /// ```
3595    AlterViewWithOperations {
3596        /// View name
3597        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
3598        name: ObjectName,
3599        operations: Vec<AlterViewOperation>,
3600    },
3601    /// ```sql
3602    /// ALTER FUNCTION ... SET OPTIONS (BigQuery)
3603    /// ```
3604    AlterFunction {
3605        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
3606        name: ObjectName,
3607        options: Vec<SqlOption>,
3608    },
3609    /// ```sql
3610    /// ALTER PROCEDURE ... SET OPTIONS (BigQuery)
3611    /// ```
3612    AlterProcedure {
3613        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
3614        name: ObjectName,
3615        options: Vec<SqlOption>,
3616    },
3617    /// ```sql
3618    /// ALTER TYPE
3619    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-altertype.html)
3620    /// ```
3621    AlterType(AlterType),
3622    /// ```sql
3623    /// ALTER ROLE
3624    /// ```
3625    AlterRole {
3626        name: Ident,
3627        operation: AlterRoleOperation,
3628    },
3629    /// ```sql
3630    /// ALTER POLICY <NAME> ON <TABLE NAME> [<OPERATION>]
3631    /// ```
3632    /// (Postgresql-specific)
3633    AlterPolicy {
3634        name: Ident,
3635        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
3636        table_name: ObjectName,
3637        operation: AlterPolicyOperation,
3638    },
3639    /// ```sql
3640    /// ALTER CONNECTOR connector_name SET DCPROPERTIES(property_name=property_value, ...);
3641    /// or
3642    /// ALTER CONNECTOR connector_name SET URL new_url;
3643    /// or
3644    /// ALTER CONNECTOR connector_name SET OWNER [USER|ROLE] user_or_role;
3645    /// ```
3646    /// (Hive-specific)
3647    AlterConnector {
3648        name: Ident,
3649        properties: Option<Vec<SqlOption>>,
3650        url: Option<String>,
3651        owner: Option<ddl::AlterConnectorOwner>,
3652    },
3653    /// ```sql
3654    /// ALTER SESSION SET sessionParam
3655    /// ALTER SESSION UNSET <param_name> [ , <param_name> , ... ]
3656    /// ```
3657    /// See <https://docs.snowflake.com/en/sql-reference/sql/alter-session>
3658    AlterSession {
3659        /// true is to set for the session parameters, false is to unset
3660        set: bool,
3661        /// The session parameters to set or unset
3662        session_params: KeyValueOptions,
3663    },
3664    /// ```sql
3665    /// ATTACH DATABASE 'path/to/file' AS alias
3666    /// ```
3667    /// (SQLite-specific)
3668    AttachDatabase {
3669        /// The name to bind to the newly attached database
3670        schema_name: Ident,
3671        /// An expression that indicates the path to the database file
3672        database_file_name: Expr,
3673        /// true if the syntax is 'ATTACH DATABASE', false if it's just 'ATTACH'
3674        database: bool,
3675    },
3676    /// (DuckDB-specific)
3677    /// ```sql
3678    /// ATTACH 'sqlite_file.db' AS sqlite_db (READ_ONLY, TYPE SQLITE);
3679    /// ```
3680    /// See <https://duckdb.org/docs/sql/statements/attach.html>
3681    AttachDuckDBDatabase {
3682        if_not_exists: bool,
3683        /// true if the syntax is 'ATTACH DATABASE', false if it's just 'ATTACH'
3684        database: bool,
3685        /// An expression that indicates the path to the database file
3686        database_path: Ident,
3687        database_alias: Option<Ident>,
3688        attach_options: Vec<AttachDuckDBDatabaseOption>,
3689    },
3690    /// (DuckDB-specific)
3691    /// ```sql
3692    /// DETACH db_alias;
3693    /// ```
3694    /// See <https://duckdb.org/docs/sql/statements/attach.html>
3695    DetachDuckDBDatabase {
3696        if_exists: bool,
3697        /// true if the syntax is 'DETACH DATABASE', false if it's just 'DETACH'
3698        database: bool,
3699        database_alias: Ident,
3700    },
3701    /// ```sql
3702    /// DROP [TABLE, VIEW, ...]
3703    /// ```
3704    Drop {
3705        /// The type of the object to drop: TABLE, VIEW, etc.
3706        object_type: ObjectType,
3707        /// An optional `IF EXISTS` clause. (Non-standard.)
3708        if_exists: bool,
3709        /// One or more objects to drop. (ANSI SQL requires exactly one.)
3710        names: Vec<ObjectName>,
3711        /// Whether `CASCADE` was specified. This will be `false` when
3712        /// `RESTRICT` or no drop behavior at all was specified.
3713        cascade: bool,
3714        /// Whether `RESTRICT` was specified. This will be `false` when
3715        /// `CASCADE` or no drop behavior at all was specified.
3716        restrict: bool,
3717        /// Hive allows you specify whether the table's stored data will be
3718        /// deleted along with the dropped table
3719        purge: bool,
3720        /// MySQL-specific "TEMPORARY" keyword
3721        temporary: bool,
3722        /// MySQL-specific drop index syntax, which requires table specification
3723        /// See <https://dev.mysql.com/doc/refman/8.4/en/drop-index.html>
3724        table: Option<ObjectName>,
3725    },
3726    /// ```sql
3727    /// DROP FUNCTION
3728    /// ```
3729    DropFunction {
3730        if_exists: bool,
3731        /// One or more function to drop
3732        func_desc: Vec<FunctionDesc>,
3733        /// `CASCADE` or `RESTRICT`
3734        drop_behavior: Option<DropBehavior>,
3735    },
3736    /// ```sql
3737    /// DROP DOMAIN
3738    /// ```
3739    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-dropdomain.html)
3740    ///
3741    /// DROP DOMAIN [ IF EXISTS ] name [, ...] [ CASCADE | RESTRICT ]
3742    ///
3743    DropDomain(DropDomain),
3744    /// ```sql
3745    /// DROP PROCEDURE
3746    /// ```
3747    DropProcedure {
3748        if_exists: bool,
3749        /// One or more function to drop
3750        proc_desc: Vec<FunctionDesc>,
3751        /// `CASCADE` or `RESTRICT`
3752        drop_behavior: Option<DropBehavior>,
3753    },
3754    /// ```sql
3755    /// DROP SECRET
3756    /// ```
3757    DropSecret {
3758        if_exists: bool,
3759        temporary: Option<bool>,
3760        name: Ident,
3761        storage_specifier: Option<Ident>,
3762    },
3763    ///```sql
3764    /// DROP POLICY
3765    /// ```
3766    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-droppolicy.html)
3767    DropPolicy {
3768        if_exists: bool,
3769        name: Ident,
3770        table_name: ObjectName,
3771        drop_behavior: Option<DropBehavior>,
3772    },
3773    /// ```sql
3774    /// DROP CONNECTOR
3775    /// ```
3776    /// See [Hive](https://cwiki.apache.org/confluence/pages/viewpage.action?pageId=27362034#LanguageManualDDL-DropConnector)
3777    DropConnector {
3778        if_exists: bool,
3779        name: Ident,
3780    },
3781    /// ```sql
3782    /// UNDROP SCHEMA schema_name
3783    /// ```
3784    /// BigQuery-specific statement to restore a dropped schema
3785    UndropSchema {
3786        if_not_exists: bool,
3787        schema_name: ObjectName,
3788    },
3789    /// ```sql
3790    /// DECLARE
3791    /// ```
3792    /// Declare Cursor Variables
3793    ///
3794    /// Note: this is a PostgreSQL-specific statement,
3795    /// but may also compatible with other SQL.
3796    Declare {
3797        stmts: Vec<Declare>,
3798    },
3799    /// ```sql
3800    /// CREATE EXTENSION [ IF NOT EXISTS ] extension_name
3801    ///     [ WITH ] [ SCHEMA schema_name ]
3802    ///              [ VERSION version ]
3803    ///              [ CASCADE ]
3804    /// ```
3805    ///
3806    /// Note: this is a PostgreSQL-specific statement,
3807    CreateExtension {
3808        name: Ident,
3809        if_not_exists: bool,
3810        cascade: bool,
3811        schema: Option<Ident>,
3812        version: Option<Ident>,
3813    },
3814    /// ```sql
3815    /// DROP EXTENSION [ IF EXISTS ] name [, ...] [ CASCADE | RESTRICT ]
3816    ///
3817    /// Note: this is a PostgreSQL-specific statement.
3818    /// https://www.postgresql.org/docs/current/sql-dropextension.html
3819    /// ```
3820    DropExtension {
3821        names: Vec<Ident>,
3822        if_exists: bool,
3823        /// `CASCADE` or `RESTRICT`
3824        cascade_or_restrict: Option<ReferentialAction>,
3825    },
3826    /// ```sql
3827    /// FETCH
3828    /// ```
3829    /// Retrieve rows from a query using a cursor
3830    ///
3831    /// Note: this is a PostgreSQL-specific statement,
3832    /// but may also compatible with other SQL.
3833    Fetch {
3834        /// Cursor name
3835        name: Ident,
3836        direction: FetchDirection,
3837        position: FetchPosition,
3838        /// Optional, It's possible to fetch rows form cursor to the table
3839        into: Option<ObjectName>,
3840    },
3841    /// ```sql
3842    /// FLUSH [NO_WRITE_TO_BINLOG | LOCAL] flush_option [, flush_option] ... | tables_option
3843    /// ```
3844    ///
3845    /// Note: this is a Mysql-specific statement,
3846    /// but may also compatible with other SQL.
3847    Flush {
3848        object_type: FlushType,
3849        location: Option<FlushLocation>,
3850        channel: Option<String>,
3851        read_lock: bool,
3852        export: bool,
3853        tables: Vec<ObjectName>,
3854    },
3855    /// ```sql
3856    /// DISCARD [ ALL | PLANS | SEQUENCES | TEMPORARY | TEMP ]
3857    /// ```
3858    ///
3859    /// Note: this is a PostgreSQL-specific statement,
3860    /// but may also compatible with other SQL.
3861    Discard {
3862        object_type: DiscardObject,
3863    },
3864    /// `SHOW FUNCTIONS`
3865    ///
3866    /// Note: this is a Presto-specific statement.
3867    ShowFunctions {
3868        filter: Option<ShowStatementFilter>,
3869    },
3870    /// ```sql
3871    /// SHOW <variable>
3872    /// ```
3873    ///
3874    /// Note: this is a PostgreSQL-specific statement.
3875    ShowVariable {
3876        variable: Vec<Ident>,
3877    },
3878    /// ```sql
3879    /// SHOW [GLOBAL | SESSION] STATUS [LIKE 'pattern' | WHERE expr]
3880    /// ```
3881    ///
3882    /// Note: this is a MySQL-specific statement.
3883    ShowStatus {
3884        filter: Option<ShowStatementFilter>,
3885        global: bool,
3886        session: bool,
3887    },
3888    /// ```sql
3889    /// SHOW VARIABLES
3890    /// ```
3891    ///
3892    /// Note: this is a MySQL-specific statement.
3893    ShowVariables {
3894        filter: Option<ShowStatementFilter>,
3895        global: bool,
3896        session: bool,
3897    },
3898    /// ```sql
3899    /// SHOW CREATE TABLE
3900    /// ```
3901    ///
3902    /// Note: this is a MySQL-specific statement.
3903    ShowCreate {
3904        obj_type: ShowCreateObject,
3905        obj_name: ObjectName,
3906    },
3907    /// ```sql
3908    /// SHOW COLUMNS
3909    /// ```
3910    ShowColumns {
3911        extended: bool,
3912        full: bool,
3913        show_options: ShowStatementOptions,
3914    },
3915    /// ```sql
3916    /// SHOW DATABASES
3917    /// ```
3918    ShowDatabases {
3919        terse: bool,
3920        history: bool,
3921        show_options: ShowStatementOptions,
3922    },
3923    /// ```sql
3924    /// SHOW SCHEMAS
3925    /// ```
3926    ShowSchemas {
3927        terse: bool,
3928        history: bool,
3929        show_options: ShowStatementOptions,
3930    },
3931    // ```sql
3932    // SHOW {CHARACTER SET | CHARSET}
3933    // ```
3934    // [MySQL]:
3935    // <https://dev.mysql.com/doc/refman/8.4/en/show.html#:~:text=SHOW%20%7BCHARACTER%20SET%20%7C%20CHARSET%7D%20%5Blike_or_where%5D>
3936    ShowCharset(ShowCharset),
3937    /// ```sql
3938    /// SHOW OBJECTS LIKE 'line%' IN mydb.public
3939    /// ```
3940    /// Snowflake-specific statement
3941    /// <https://docs.snowflake.com/en/sql-reference/sql/show-objects>
3942    ShowObjects(ShowObjects),
3943    /// ```sql
3944    /// SHOW TABLES
3945    /// ```
3946    ShowTables {
3947        terse: bool,
3948        history: bool,
3949        extended: bool,
3950        full: bool,
3951        external: bool,
3952        show_options: ShowStatementOptions,
3953    },
3954    /// ```sql
3955    /// SHOW VIEWS
3956    /// ```
3957    ShowViews {
3958        terse: bool,
3959        materialized: bool,
3960        show_options: ShowStatementOptions,
3961    },
3962    /// ```sql
3963    /// SHOW COLLATION
3964    /// ```
3965    ///
3966    /// Note: this is a MySQL-specific statement.
3967    ShowCollation {
3968        filter: Option<ShowStatementFilter>,
3969    },
3970    /// ```sql
3971    /// `USE ...`
3972    /// ```
3973    Use(Use),
3974    /// ```sql
3975    /// START  [ TRANSACTION | WORK ] | START TRANSACTION } ...
3976    /// ```
3977    /// If `begin` is false.
3978    ///
3979    /// ```sql
3980    /// `BEGIN  [ TRANSACTION | WORK ] | START TRANSACTION } ...`
3981    /// ```
3982    /// If `begin` is true
3983    StartTransaction {
3984        modes: Vec<TransactionMode>,
3985        begin: bool,
3986        transaction: Option<BeginTransactionKind>,
3987        modifier: Option<TransactionModifier>,
3988        /// List of statements belonging to the `BEGIN` block.
3989        /// Example:
3990        /// ```sql
3991        /// BEGIN
3992        ///     SELECT 1;
3993        ///     SELECT 2;
3994        /// END;
3995        /// ```
3996        statements: Vec<Statement>,
3997        /// Exception handling with exception clauses.
3998        /// Example:
3999        /// ```sql
4000        /// EXCEPTION
4001        ///     WHEN EXCEPTION_1 THEN
4002        ///         SELECT 2;
4003        ///     WHEN EXCEPTION_2 OR EXCEPTION_3 THEN
4004        ///         SELECT 3;
4005        ///     WHEN OTHER THEN
4006        ///         SELECT 4;
4007        /// ```
4008        /// <https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#beginexceptionend>
4009        /// <https://docs.snowflake.com/en/sql-reference/snowflake-scripting/exception>
4010        exception: Option<Vec<ExceptionWhen>>,
4011        /// TRUE if the statement has an `END` keyword.
4012        has_end_keyword: bool,
4013        /// Optional label for the BEGIN block (e.g., `my_block: BEGIN ... END my_block`)
4014        label: Option<Ident>,
4015    },
4016    /// ```sql
4017    /// COMMENT ON ...
4018    /// ```
4019    ///
4020    /// Note: this is a PostgreSQL-specific statement.
4021    Comment {
4022        object_type: CommentObject,
4023        object_name: ObjectName,
4024        comment: Option<String>,
4025        /// An optional `IF EXISTS` clause. (Non-standard.)
4026        /// See <https://docs.snowflake.com/en/sql-reference/sql/comment>
4027        if_exists: bool,
4028    },
4029    /// ```sql
4030    /// COMMIT [ TRANSACTION | WORK ] [ AND [ NO ] CHAIN ]
4031    /// ```
4032    /// If `end` is false
4033    ///
4034    /// ```sql
4035    /// END [ TRY | CATCH ]
4036    /// ```
4037    /// If `end` is true
4038    Commit {
4039        chain: bool,
4040        end: bool,
4041        modifier: Option<TransactionModifier>,
4042    },
4043    /// ```sql
4044    /// ROLLBACK [ TRANSACTION | WORK ] [ AND [ NO ] CHAIN ] [ TO [ SAVEPOINT ] savepoint_name ]
4045    /// ```
4046    Rollback {
4047        chain: bool,
4048        savepoint: Option<Ident>,
4049    },
4050    /// ```sql
4051    /// CREATE SCHEMA
4052    /// ```
4053    CreateSchema {
4054        /// `<schema name> | AUTHORIZATION <schema authorization identifier>  | <schema name>  AUTHORIZATION <schema authorization identifier>`
4055        schema_name: SchemaName,
4056        if_not_exists: bool,
4057        or_replace: bool,
4058        /// Schema properties.
4059        ///
4060        /// ```sql
4061        /// CREATE SCHEMA myschema WITH (key1='value1');
4062        /// ```
4063        ///
4064        /// [Trino](https://trino.io/docs/current/sql/create-schema.html)
4065        with: Option<Vec<SqlOption>>,
4066        /// Schema options.
4067        ///
4068        /// ```sql
4069        /// CREATE SCHEMA myschema OPTIONS(key1='value1');
4070        /// ```
4071        ///
4072        /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_schema_statement)
4073        options: Option<Vec<SqlOption>>,
4074        /// Default collation specification for the schema.
4075        ///
4076        /// ```sql
4077        /// CREATE SCHEMA myschema DEFAULT COLLATE 'und:ci';
4078        /// ```
4079        ///
4080        /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_schema_statement)
4081        default_collate_spec: Option<Expr>,
4082        /// Clones a schema
4083        ///
4084        /// ```sql
4085        /// CREATE SCHEMA myschema CLONE otherschema
4086        /// ```
4087        ///
4088        /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-clone#databases-schemas)
4089        clone: Option<ObjectName>,
4090    },
4091    /// ```sql
4092    /// CREATE DATABASE
4093    /// ```
4094    /// See:
4095    /// <https://docs.snowflake.com/en/sql-reference/sql/create-database>
4096    CreateDatabase {
4097        db_name: ObjectName,
4098        if_not_exists: bool,
4099        location: Option<String>,
4100        managed_location: Option<String>,
4101        or_replace: bool,
4102        transient: bool,
4103        clone: Option<ObjectName>,
4104        data_retention_time_in_days: Option<u64>,
4105        max_data_extension_time_in_days: Option<u64>,
4106        external_volume: Option<String>,
4107        catalog: Option<String>,
4108        replace_invalid_characters: Option<bool>,
4109        default_ddl_collation: Option<String>,
4110        storage_serialization_policy: Option<StorageSerializationPolicy>,
4111        comment: Option<String>,
4112        catalog_sync: Option<String>,
4113        catalog_sync_namespace_mode: Option<CatalogSyncNamespaceMode>,
4114        catalog_sync_namespace_flatten_delimiter: Option<String>,
4115        with_tags: Option<Vec<Tag>>,
4116        with_contacts: Option<Vec<ContactEntry>>,
4117    },
4118    /// ```sql
4119    /// CREATE FUNCTION
4120    /// ```
4121    ///
4122    /// Supported variants:
4123    /// 1. [Hive](https://cwiki.apache.org/confluence/display/hive/languagemanual+ddl#LanguageManualDDL-Create/Drop/ReloadFunction)
4124    /// 2. [PostgreSQL](https://www.postgresql.org/docs/15/sql-createfunction.html)
4125    /// 3. [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_function_statement)
4126    /// 4. [MsSql](https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql)
4127    CreateFunction(CreateFunction),
4128    /// CREATE TRIGGER statement. See struct [CreateTrigger] for details.
4129    CreateTrigger(CreateTrigger),
4130    /// DROP TRIGGER statement. See struct [DropTrigger] for details.
4131    DropTrigger(DropTrigger),
4132    /// ```sql
4133    /// CREATE PROCEDURE
4134    /// ```
4135    CreateProcedure {
4136        or_alter: bool,
4137        if_not_exists: bool,
4138        name: ObjectName,
4139        params: Option<Vec<ProcedureParam>>,
4140        language: Option<Ident>,
4141        options: Option<Vec<SqlOption>>,
4142        body: ConditionalStatements,
4143    },
4144    /// ```sql
4145    /// CREATE MACRO
4146    /// ```
4147    ///
4148    /// Supported variants:
4149    /// 1. [DuckDB](https://duckdb.org/docs/sql/statements/create_macro)
4150    CreateMacro {
4151        or_replace: bool,
4152        temporary: bool,
4153        name: ObjectName,
4154        args: Option<Vec<MacroArg>>,
4155        definition: MacroDefinition,
4156    },
4157    /// ```sql
4158    /// CREATE STAGE
4159    /// ```
4160    /// See <https://docs.snowflake.com/en/sql-reference/sql/create-stage>
4161    CreateStage {
4162        or_replace: bool,
4163        temporary: bool,
4164        if_not_exists: bool,
4165        name: ObjectName,
4166        stage_params: StageParamsObject,
4167        directory_table_params: KeyValueOptions,
4168        file_format: KeyValueOptions,
4169        copy_options: KeyValueOptions,
4170        comment: Option<String>,
4171    },
4172    /// ```sql
4173    /// ASSERT <condition> [AS <message>]
4174    /// ```
4175    Assert {
4176        condition: Expr,
4177        message: Option<Expr>,
4178    },
4179    /// ```sql
4180    /// GRANT privileges ON objects TO grantees
4181    /// ```
4182    Grant {
4183        privileges: Privileges,
4184        objects: Option<GrantObjects>,
4185        grantees: Vec<Grantee>,
4186        with_grant_option: bool,
4187        as_grantor: Option<Ident>,
4188        granted_by: Option<Ident>,
4189        current_grants: Option<CurrentGrantsKind>,
4190    },
4191    /// ```sql
4192    /// DENY privileges ON object TO grantees
4193    /// ```
4194    Deny(DenyStatement),
4195    /// ```sql
4196    /// REVOKE privileges ON objects FROM grantees
4197    /// ```
4198    Revoke {
4199        privileges: Privileges,
4200        objects: Option<GrantObjects>,
4201        grantees: Vec<Grantee>,
4202        granted_by: Option<Ident>,
4203        cascade: Option<CascadeOption>,
4204    },
4205    /// ```sql
4206    /// DEALLOCATE [ PREPARE ] { name | ALL }
4207    /// ```
4208    ///
4209    /// Note: this is a PostgreSQL-specific statement.
4210    Deallocate {
4211        name: Ident,
4212        prepare: bool,
4213    },
4214    /// ```sql
4215    /// An `EXECUTE` statement
4216    /// ```
4217    ///
4218    /// Postgres: <https://www.postgresql.org/docs/current/sql-execute.html>
4219    /// MSSQL: <https://learn.microsoft.com/en-us/sql/relational-databases/stored-procedures/execute-a-stored-procedure>
4220    /// BigQuery: <https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#execute_immediate>
4221    /// Snowflake: <https://docs.snowflake.com/en/sql-reference/sql/execute-immediate>
4222    Execute {
4223        name: Option<ObjectName>,
4224        parameters: Vec<Expr>,
4225        has_parentheses: bool,
4226        /// Is this an `EXECUTE IMMEDIATE`
4227        immediate: bool,
4228        into: Vec<Ident>,
4229        using: Vec<ExprWithAlias>,
4230        /// Whether the last parameter is the return value of the procedure
4231        /// MSSQL: <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/execute-transact-sql?view=sql-server-ver17#output>
4232        output: bool,
4233        /// Whether to invoke the procedure with the default parameter values
4234        /// MSSQL: <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/execute-transact-sql?view=sql-server-ver17#default>
4235        default: bool,
4236    },
4237    /// ```sql
4238    /// PREPARE name [ ( data_type [, ...] ) ] AS statement
4239    /// ```
4240    ///
4241    /// Note: this is a PostgreSQL-specific statement.
4242    Prepare {
4243        name: Ident,
4244        data_types: Vec<DataType>,
4245        statement: Box<Statement>,
4246    },
4247    /// ```sql
4248    /// KILL [CONNECTION | QUERY | MUTATION]
4249    /// ```
4250    ///
4251    /// See <https://clickhouse.com/docs/en/sql-reference/statements/kill/>
4252    /// See <https://dev.mysql.com/doc/refman/8.0/en/kill.html>
4253    Kill {
4254        modifier: Option<KillType>,
4255        // processlist_id
4256        id: u64,
4257    },
4258    /// ```sql
4259    /// [EXPLAIN | DESC | DESCRIBE] TABLE
4260    /// ```
4261    /// Note: this is a MySQL-specific statement. See <https://dev.mysql.com/doc/refman/8.0/en/explain.html>
4262    ExplainTable {
4263        /// `EXPLAIN | DESC | DESCRIBE`
4264        describe_alias: DescribeAlias,
4265        /// Hive style `FORMATTED | EXTENDED`
4266        hive_format: Option<HiveDescribeFormat>,
4267        /// Snowflake and ClickHouse support `DESC|DESCRIBE TABLE <table_name>` syntax
4268        ///
4269        /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/desc-table.html)
4270        /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/describe-table)
4271        has_table_keyword: bool,
4272        /// Table name
4273        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
4274        table_name: ObjectName,
4275    },
4276    /// ```sql
4277    /// [EXPLAIN | DESC | DESCRIBE]  <statement>
4278    /// ```
4279    Explain {
4280        /// `EXPLAIN | DESC | DESCRIBE`
4281        describe_alias: DescribeAlias,
4282        /// Carry out the command and show actual run times and other statistics.
4283        analyze: bool,
4284        // Display additional information regarding the plan.
4285        verbose: bool,
4286        /// `EXPLAIN QUERY PLAN`
4287        /// Display the query plan without running the query.
4288        ///
4289        /// [SQLite](https://sqlite.org/lang_explain.html)
4290        query_plan: bool,
4291        /// `EXPLAIN ESTIMATE`
4292        /// [Clickhouse](https://clickhouse.com/docs/en/sql-reference/statements/explain#explain-estimate)
4293        estimate: bool,
4294        /// A SQL query that specifies what to explain
4295        statement: Box<Statement>,
4296        /// Optional output format of explain
4297        format: Option<AnalyzeFormatKind>,
4298        /// Postgres style utility options, `(analyze, verbose true)`
4299        options: Option<Vec<UtilityOption>>,
4300    },
4301    /// ```sql
4302    /// SAVEPOINT
4303    /// ```
4304    /// Define a new savepoint within the current transaction
4305    Savepoint {
4306        name: Ident,
4307    },
4308    /// ```sql
4309    /// RELEASE [ SAVEPOINT ] savepoint_name
4310    /// ```
4311    ReleaseSavepoint {
4312        name: Ident,
4313    },
4314    /// A `MERGE` statement.
4315    ///
4316    /// ```sql
4317    /// MERGE INTO <target_table> USING <source> ON <join_expr> { matchedClause | notMatchedClause } [ ... ]
4318    /// ```
4319    /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/merge)
4320    /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/dml-syntax#merge_statement)
4321    /// [MSSQL](https://learn.microsoft.com/en-us/sql/t-sql/statements/merge-transact-sql?view=sql-server-ver16)
4322    Merge {
4323        /// optional INTO keyword
4324        into: bool,
4325        /// Specifies the table to merge
4326        table: TableFactor,
4327        /// Specifies the table or subquery to join with the target table
4328        source: TableFactor,
4329        /// Specifies the expression on which to join the target table and source
4330        on: Box<Expr>,
4331        /// Specifies the actions to perform when values match or do not match.
4332        clauses: Vec<MergeClause>,
4333        // Specifies the output to save changes in MSSQL
4334        output: Option<OutputClause>,
4335    },
4336    /// ```sql
4337    /// CACHE [ FLAG ] TABLE <table_name> [ OPTIONS('K1' = 'V1', 'K2' = V2) ] [ AS ] [ <query> ]
4338    /// ```
4339    ///
4340    /// See [Spark SQL docs] for more details.
4341    ///
4342    /// [Spark SQL docs]: https://docs.databricks.com/spark/latest/spark-sql/language-manual/sql-ref-syntax-aux-cache-cache-table.html
4343    Cache {
4344        /// Table flag
4345        table_flag: Option<ObjectName>,
4346        /// Table name
4347
4348        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
4349        table_name: ObjectName,
4350        has_as: bool,
4351        /// Table confs
4352        options: Vec<SqlOption>,
4353        /// Cache table as a Query
4354        query: Option<Box<Query>>,
4355    },
4356    /// ```sql
4357    /// UNCACHE TABLE [ IF EXISTS ]  <table_name>
4358    /// ```
4359    UNCache {
4360        /// Table name
4361        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
4362        table_name: ObjectName,
4363        if_exists: bool,
4364    },
4365    /// ```sql
4366    /// CREATE [ { TEMPORARY | TEMP } ] SEQUENCE [ IF NOT EXISTS ] <sequence_name>
4367    /// ```
4368    /// Define a new sequence:
4369    CreateSequence {
4370        temporary: bool,
4371        if_not_exists: bool,
4372        name: ObjectName,
4373        data_type: Option<DataType>,
4374        sequence_options: Vec<SequenceOptions>,
4375        owned_by: Option<ObjectName>,
4376    },
4377    /// A `CREATE DOMAIN` statement.
4378    CreateDomain(CreateDomain),
4379    /// ```sql
4380    /// CREATE TYPE <name>
4381    /// ```
4382    CreateType {
4383        name: ObjectName,
4384        representation: UserDefinedTypeRepresentation,
4385    },
4386    /// ```sql
4387    /// PRAGMA <schema-name>.<pragma-name> = <pragma-value>
4388    /// ```
4389    Pragma {
4390        name: ObjectName,
4391        value: Option<Value>,
4392        is_eq: bool,
4393    },
4394    /// ```sql
4395    /// LOCK TABLES <table_name> [READ [LOCAL] | [LOW_PRIORITY] WRITE]
4396    /// ```
4397    /// Note: this is a MySQL-specific statement. See <https://dev.mysql.com/doc/refman/8.0/en/lock-tables.html>
4398    LockTables {
4399        tables: Vec<LockTable>,
4400    },
4401    /// ```sql
4402    /// UNLOCK TABLES
4403    /// ```
4404    /// Note: this is a MySQL-specific statement. See <https://dev.mysql.com/doc/refman/8.0/en/lock-tables.html>
4405    UnlockTables,
4406    /// Unloads the result of a query to file
4407    ///
4408    /// [Athena](https://docs.aws.amazon.com/athena/latest/ug/unload.html):
4409    /// ```sql
4410    /// UNLOAD(statement) TO <destination> [ WITH options ]
4411    /// ```
4412    ///
4413    /// [Redshift](https://docs.aws.amazon.com/redshift/latest/dg/r_UNLOAD.html):
4414    /// ```sql
4415    /// UNLOAD('statement') TO <destination> [ OPTIONS ]
4416    /// ```
4417    Unload {
4418        query: Option<Box<Query>>,
4419        query_text: Option<String>,
4420        to: Ident,
4421        auth: Option<IamRoleKind>,
4422        with: Vec<SqlOption>,
4423        options: Vec<CopyLegacyOption>,
4424    },
4425    /// ```sql
4426    /// OPTIMIZE TABLE [db.]name [ON CLUSTER cluster] [PARTITION partition | PARTITION ID 'partition_id'] [FINAL] [DEDUPLICATE [BY expression]]
4427    /// ```
4428    ///
4429    /// See ClickHouse <https://clickhouse.com/docs/en/sql-reference/statements/optimize>
4430    OptimizeTable {
4431        name: ObjectName,
4432        on_cluster: Option<Ident>,
4433        partition: Option<Partition>,
4434        include_final: bool,
4435        deduplicate: Option<Deduplicate>,
4436    },
4437    /// ```sql
4438    /// LISTEN
4439    /// ```
4440    /// listen for a notification channel
4441    ///
4442    /// See Postgres <https://www.postgresql.org/docs/current/sql-listen.html>
4443    LISTEN {
4444        channel: Ident,
4445    },
4446    /// ```sql
4447    /// UNLISTEN
4448    /// ```
4449    /// stop listening for a notification
4450    ///
4451    /// See Postgres <https://www.postgresql.org/docs/current/sql-unlisten.html>
4452    UNLISTEN {
4453        channel: Ident,
4454    },
4455    /// ```sql
4456    /// NOTIFY channel [ , payload ]
4457    /// ```
4458    /// send a notification event together with an optional "payload" string to channel
4459    ///
4460    /// See Postgres <https://www.postgresql.org/docs/current/sql-notify.html>
4461    NOTIFY {
4462        channel: Ident,
4463        payload: Option<String>,
4464    },
4465    /// ```sql
4466    /// LOAD DATA [LOCAL] INPATH 'filepath' [OVERWRITE] INTO TABLE tablename
4467    /// [PARTITION (partcol1=val1, partcol2=val2 ...)]
4468    /// [INPUTFORMAT 'inputformat' SERDE 'serde']
4469    /// ```
4470    /// Loading files into tables
4471    ///
4472    /// See Hive <https://cwiki.apache.org/confluence/pages/viewpage.action?pageId=27362036#LanguageManualDML-Loadingfilesintotables>
4473    LoadData {
4474        local: bool,
4475        inpath: String,
4476        overwrite: bool,
4477        table_name: ObjectName,
4478        partitioned: Option<Vec<Expr>>,
4479        table_format: Option<HiveLoadDataFormat>,
4480    },
4481    /// ```sql
4482    /// Rename TABLE tbl_name TO new_tbl_name[, tbl_name2 TO new_tbl_name2] ...
4483    /// ```
4484    /// Renames one or more tables
4485    ///
4486    /// See Mysql <https://dev.mysql.com/doc/refman/9.1/en/rename-table.html>
4487    RenameTable(Vec<RenameTable>),
4488    /// Snowflake `LIST`
4489    /// See: <https://docs.snowflake.com/en/sql-reference/sql/list>
4490    List(FileStagingCommand),
4491    /// Snowflake `REMOVE`
4492    /// See: <https://docs.snowflake.com/en/sql-reference/sql/remove>
4493    Remove(FileStagingCommand),
4494    /// RaiseError (MSSQL)
4495    /// RAISERROR ( { msg_id | msg_str | @local_variable }
4496    /// { , severity , state }
4497    /// [ , argument [ , ...n ] ] )
4498    /// [ WITH option [ , ...n ] ]
4499    /// See <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/raiserror-transact-sql?view=sql-server-ver16>
4500    RaisError {
4501        message: Box<Expr>,
4502        severity: Box<Expr>,
4503        state: Box<Expr>,
4504        arguments: Vec<Expr>,
4505        options: Vec<RaisErrorOption>,
4506    },
4507    /// ```sql
4508    /// PRINT msg_str | @local_variable | string_expr
4509    /// ```
4510    ///
4511    /// See: <https://learn.microsoft.com/en-us/sql/t-sql/statements/print-transact-sql>
4512    Print(PrintStatement),
4513    /// ```sql
4514    /// RETURN [ expression ]
4515    /// ```
4516    ///
4517    /// See [ReturnStatement]
4518    Return(ReturnStatement),
4519    /// Export data statement
4520    ///
4521    /// Example:
4522    /// ```sql
4523    /// EXPORT DATA OPTIONS(uri='gs://bucket/folder/*', format='PARQUET', overwrite=true) AS
4524    /// SELECT field1, field2 FROM mydataset.table1 ORDER BY field1 LIMIT 10
4525    /// ```
4526    /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/export-statements)
4527    ExportData(ExportData),
4528    /// ```sql
4529    /// CREATE [OR REPLACE] USER <user> [IF NOT EXISTS]
4530    /// ```
4531    /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-user)
4532    CreateUser(CreateUser),
4533    /// Re-sorts rows and reclaims space in either a specified table or all tables in the current database
4534    ///
4535    /// ```sql
4536    /// VACUUM tbl
4537    /// ```
4538    /// [Redshift](https://docs.aws.amazon.com/redshift/latest/dg/r_VACUUM_command.html)
4539    Vacuum(VacuumStatement),
4540}
4541
4542/// ```sql
4543/// {COPY | REVOKE} CURRENT GRANTS
4544/// ```
4545///
4546/// - [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/grant-ownership#optional-parameters)
4547#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
4548#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4549#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
4550pub enum CurrentGrantsKind {
4551    CopyCurrentGrants,
4552    RevokeCurrentGrants,
4553}
4554
4555impl fmt::Display for CurrentGrantsKind {
4556    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
4557        match self {
4558            CurrentGrantsKind::CopyCurrentGrants => write!(f, "COPY CURRENT GRANTS"),
4559            CurrentGrantsKind::RevokeCurrentGrants => write!(f, "REVOKE CURRENT GRANTS"),
4560        }
4561    }
4562}
4563
4564#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
4565#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4566#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
4567pub enum RaisErrorOption {
4568    Log,
4569    NoWait,
4570    SetError,
4571}
4572
4573impl fmt::Display for RaisErrorOption {
4574    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
4575        match self {
4576            RaisErrorOption::Log => write!(f, "LOG"),
4577            RaisErrorOption::NoWait => write!(f, "NOWAIT"),
4578            RaisErrorOption::SetError => write!(f, "SETERROR"),
4579        }
4580    }
4581}
4582
4583impl fmt::Display for Statement {
4584    /// Formats a SQL statement with support for pretty printing.
4585    ///
4586    /// When using the alternate flag (`{:#}`), the statement will be formatted with proper
4587    /// indentation and line breaks. For example:
4588    ///
4589    /// ```
4590    /// # use sqlparser::dialect::GenericDialect;
4591    /// # use sqlparser::parser::Parser;
4592    /// let sql = "SELECT a, b FROM table_1";
4593    /// let ast = Parser::parse_sql(&GenericDialect, sql).unwrap();
4594    ///
4595    /// // Regular formatting
4596    /// assert_eq!(format!("{}", ast[0]), "SELECT a, b FROM table_1");
4597    ///
4598    /// // Pretty printing
4599    /// assert_eq!(format!("{:#}", ast[0]),
4600    /// r#"SELECT
4601    ///   a,
4602    ///   b
4603    /// FROM
4604    ///   table_1"#);
4605    /// ```
4606    // Clippy thinks this function is too complicated, but it is painful to
4607    // split up without extracting structs for each `Statement` variant.
4608    #[allow(clippy::cognitive_complexity)]
4609    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
4610        match self {
4611            Statement::Flush {
4612                object_type,
4613                location,
4614                channel,
4615                read_lock,
4616                export,
4617                tables,
4618            } => {
4619                write!(f, "FLUSH")?;
4620                if let Some(location) = location {
4621                    f.write_str(" ")?;
4622                    location.fmt(f)?;
4623                }
4624                write!(f, " {object_type}")?;
4625
4626                if let Some(channel) = channel {
4627                    write!(f, " FOR CHANNEL {channel}")?;
4628                }
4629
4630                write!(
4631                    f,
4632                    "{tables}{read}{export}",
4633                    tables = if !tables.is_empty() {
4634                        " ".to_string() + &display_comma_separated(tables).to_string()
4635                    } else {
4636                        "".to_string()
4637                    },
4638                    export = if *export { " FOR EXPORT" } else { "" },
4639                    read = if *read_lock { " WITH READ LOCK" } else { "" }
4640                )
4641            }
4642            Statement::Kill { modifier, id } => {
4643                write!(f, "KILL ")?;
4644
4645                if let Some(m) = modifier {
4646                    write!(f, "{m} ")?;
4647                }
4648
4649                write!(f, "{id}")
4650            }
4651            Statement::ExplainTable {
4652                describe_alias,
4653                hive_format,
4654                has_table_keyword,
4655                table_name,
4656            } => {
4657                write!(f, "{describe_alias} ")?;
4658
4659                if let Some(format) = hive_format {
4660                    write!(f, "{format} ")?;
4661                }
4662                if *has_table_keyword {
4663                    write!(f, "TABLE ")?;
4664                }
4665
4666                write!(f, "{table_name}")
4667            }
4668            Statement::Explain {
4669                describe_alias,
4670                verbose,
4671                analyze,
4672                query_plan,
4673                estimate,
4674                statement,
4675                format,
4676                options,
4677            } => {
4678                write!(f, "{describe_alias} ")?;
4679
4680                if *query_plan {
4681                    write!(f, "QUERY PLAN ")?;
4682                }
4683                if *analyze {
4684                    write!(f, "ANALYZE ")?;
4685                }
4686                if *estimate {
4687                    write!(f, "ESTIMATE ")?;
4688                }
4689
4690                if *verbose {
4691                    write!(f, "VERBOSE ")?;
4692                }
4693
4694                if let Some(format) = format {
4695                    write!(f, "{format} ")?;
4696                }
4697
4698                if let Some(options) = options {
4699                    write!(f, "({}) ", display_comma_separated(options))?;
4700                }
4701
4702                write!(f, "{statement}")
4703            }
4704            Statement::Query(s) => s.fmt(f),
4705            Statement::Declare { stmts } => {
4706                write!(f, "DECLARE ")?;
4707                write!(f, "{}", display_separated(stmts, "; "))
4708            }
4709            Statement::Fetch {
4710                name,
4711                direction,
4712                position,
4713                into,
4714            } => {
4715                write!(f, "FETCH {direction} {position} {name}")?;
4716
4717                if let Some(into) = into {
4718                    write!(f, " INTO {into}")?;
4719                }
4720
4721                Ok(())
4722            }
4723            Statement::Directory {
4724                overwrite,
4725                local,
4726                path,
4727                file_format,
4728                source,
4729            } => {
4730                write!(
4731                    f,
4732                    "INSERT{overwrite}{local} DIRECTORY '{path}'",
4733                    overwrite = if *overwrite { " OVERWRITE" } else { "" },
4734                    local = if *local { " LOCAL" } else { "" },
4735                    path = path
4736                )?;
4737                if let Some(ref ff) = file_format {
4738                    write!(f, " STORED AS {ff}")?
4739                }
4740                write!(f, " {source}")
4741            }
4742            Statement::Msck {
4743                table_name,
4744                repair,
4745                partition_action,
4746            } => {
4747                write!(
4748                    f,
4749                    "MSCK {repair}TABLE {table}",
4750                    repair = if *repair { "REPAIR " } else { "" },
4751                    table = table_name
4752                )?;
4753                if let Some(pa) = partition_action {
4754                    write!(f, " {pa}")?;
4755                }
4756                Ok(())
4757            }
4758            Statement::Truncate {
4759                table_names,
4760                partitions,
4761                table,
4762                identity,
4763                cascade,
4764                on_cluster,
4765            } => {
4766                let table = if *table { "TABLE " } else { "" };
4767
4768                write!(
4769                    f,
4770                    "TRUNCATE {table}{table_names}",
4771                    table_names = display_comma_separated(table_names)
4772                )?;
4773
4774                if let Some(identity) = identity {
4775                    match identity {
4776                        TruncateIdentityOption::Restart => write!(f, " RESTART IDENTITY")?,
4777                        TruncateIdentityOption::Continue => write!(f, " CONTINUE IDENTITY")?,
4778                    }
4779                }
4780                if let Some(cascade) = cascade {
4781                    match cascade {
4782                        CascadeOption::Cascade => write!(f, " CASCADE")?,
4783                        CascadeOption::Restrict => write!(f, " RESTRICT")?,
4784                    }
4785                }
4786
4787                if let Some(ref parts) = partitions {
4788                    if !parts.is_empty() {
4789                        write!(f, " PARTITION ({})", display_comma_separated(parts))?;
4790                    }
4791                }
4792                if let Some(on_cluster) = on_cluster {
4793                    write!(f, " ON CLUSTER {on_cluster}")?;
4794                }
4795                Ok(())
4796            }
4797            Statement::Case(stmt) => {
4798                write!(f, "{stmt}")
4799            }
4800            Statement::If(stmt) => {
4801                write!(f, "{stmt}")
4802            }
4803            Statement::While(stmt) => {
4804                write!(f, "{stmt}")
4805            }
4806            Statement::Loop(stmt) => {
4807                write!(f, "{stmt}")
4808            }
4809            Statement::For(stmt) => {
4810                write!(f, "{stmt}")
4811            }
4812            Statement::Repeat(stmt) => {
4813                write!(f, "{stmt}")
4814            }
4815            Statement::Leave { label } => {
4816                write!(f, "LEAVE")?;
4817                if let Some(l) = label {
4818                    write!(f, " {l}")?;
4819                }
4820                Ok(())
4821            }
4822            Statement::Iterate { label } => {
4823                write!(f, "ITERATE")?;
4824                if let Some(l) = label {
4825                    write!(f, " {l}")?;
4826                }
4827                Ok(())
4828            }
4829            Statement::Break { label } => {
4830                write!(f, "BREAK")?;
4831                if let Some(l) = label {
4832                    write!(f, " {l}")?;
4833                }
4834                Ok(())
4835            }
4836            Statement::Continue { label } => {
4837                write!(f, "CONTINUE")?;
4838                if let Some(l) = label {
4839                    write!(f, " {l}")?;
4840                }
4841                Ok(())
4842            }
4843            Statement::Raise(stmt) => {
4844                write!(f, "{stmt}")
4845            }
4846            Statement::AttachDatabase {
4847                schema_name,
4848                database_file_name,
4849                database,
4850            } => {
4851                let keyword = if *database { "DATABASE " } else { "" };
4852                write!(f, "ATTACH {keyword}{database_file_name} AS {schema_name}")
4853            }
4854            Statement::AttachDuckDBDatabase {
4855                if_not_exists,
4856                database,
4857                database_path,
4858                database_alias,
4859                attach_options,
4860            } => {
4861                write!(
4862                    f,
4863                    "ATTACH{database}{if_not_exists} {database_path}",
4864                    database = if *database { " DATABASE" } else { "" },
4865                    if_not_exists = if *if_not_exists { " IF NOT EXISTS" } else { "" },
4866                )?;
4867                if let Some(alias) = database_alias {
4868                    write!(f, " AS {alias}")?;
4869                }
4870                if !attach_options.is_empty() {
4871                    write!(f, " ({})", display_comma_separated(attach_options))?;
4872                }
4873                Ok(())
4874            }
4875            Statement::DetachDuckDBDatabase {
4876                if_exists,
4877                database,
4878                database_alias,
4879            } => {
4880                write!(
4881                    f,
4882                    "DETACH{database}{if_exists} {database_alias}",
4883                    database = if *database { " DATABASE" } else { "" },
4884                    if_exists = if *if_exists { " IF EXISTS" } else { "" },
4885                )?;
4886                Ok(())
4887            }
4888            Statement::Analyze {
4889                table_name,
4890                partitions,
4891                for_columns,
4892                columns,
4893                cache_metadata,
4894                noscan,
4895                compute_statistics,
4896                has_table_keyword,
4897            } => {
4898                write!(
4899                    f,
4900                    "ANALYZE{}{table_name}",
4901                    if *has_table_keyword { " TABLE " } else { " " }
4902                )?;
4903                if let Some(ref parts) = partitions {
4904                    if !parts.is_empty() {
4905                        write!(f, " PARTITION ({})", display_comma_separated(parts))?;
4906                    }
4907                }
4908
4909                if *compute_statistics {
4910                    write!(f, " COMPUTE STATISTICS")?;
4911                }
4912                if *noscan {
4913                    write!(f, " NOSCAN")?;
4914                }
4915                if *cache_metadata {
4916                    write!(f, " CACHE METADATA")?;
4917                }
4918                if *for_columns {
4919                    write!(f, " FOR COLUMNS")?;
4920                    if !columns.is_empty() {
4921                        write!(f, " {}", display_comma_separated(columns))?;
4922                    }
4923                }
4924                Ok(())
4925            }
4926            Statement::Insert(insert) => insert.fmt(f),
4927            Statement::Install {
4928                extension_name: name,
4929            } => write!(f, "INSTALL {name}"),
4930
4931            Statement::Load {
4932                extension_name: name,
4933            } => write!(f, "LOAD {name}"),
4934
4935            Statement::Call(function) => write!(f, "CALL {function}"),
4936
4937            Statement::Copy {
4938                source,
4939                to,
4940                target,
4941                options,
4942                legacy_options,
4943                values,
4944            } => {
4945                write!(f, "COPY")?;
4946                match source {
4947                    CopySource::Query(query) => write!(f, " ({query})")?,
4948                    CopySource::Table {
4949                        table_name,
4950                        columns,
4951                    } => {
4952                        write!(f, " {table_name}")?;
4953                        if !columns.is_empty() {
4954                            write!(f, " ({})", display_comma_separated(columns))?;
4955                        }
4956                    }
4957                }
4958                write!(f, " {} {}", if *to { "TO" } else { "FROM" }, target)?;
4959                if !options.is_empty() {
4960                    write!(f, " ({})", display_comma_separated(options))?;
4961                }
4962                if !legacy_options.is_empty() {
4963                    write!(f, " {}", display_separated(legacy_options, " "))?;
4964                }
4965                if !values.is_empty() {
4966                    writeln!(f, ";")?;
4967                    let mut delim = "";
4968                    for v in values {
4969                        write!(f, "{delim}")?;
4970                        delim = "\t";
4971                        if let Some(v) = v {
4972                            write!(f, "{v}")?;
4973                        } else {
4974                            write!(f, "\\N")?;
4975                        }
4976                    }
4977                    write!(f, "\n\\.")?;
4978                }
4979                Ok(())
4980            }
4981            Statement::Update {
4982                table,
4983                assignments,
4984                from,
4985                selection,
4986                returning,
4987                or,
4988                limit,
4989            } => {
4990                f.write_str("UPDATE ")?;
4991                if let Some(or) = or {
4992                    or.fmt(f)?;
4993                    f.write_str(" ")?;
4994                }
4995                table.fmt(f)?;
4996                if let Some(UpdateTableFromKind::BeforeSet(from)) = from {
4997                    SpaceOrNewline.fmt(f)?;
4998                    f.write_str("FROM")?;
4999                    indented_list(f, from)?;
5000                }
5001                if !assignments.is_empty() {
5002                    SpaceOrNewline.fmt(f)?;
5003                    f.write_str("SET")?;
5004                    indented_list(f, assignments)?;
5005                }
5006                if let Some(UpdateTableFromKind::AfterSet(from)) = from {
5007                    SpaceOrNewline.fmt(f)?;
5008                    f.write_str("FROM")?;
5009                    indented_list(f, from)?;
5010                }
5011                if let Some(selection) = selection {
5012                    SpaceOrNewline.fmt(f)?;
5013                    f.write_str("WHERE")?;
5014                    SpaceOrNewline.fmt(f)?;
5015                    Indent(selection).fmt(f)?;
5016                }
5017                if let Some(returning) = returning {
5018                    SpaceOrNewline.fmt(f)?;
5019                    f.write_str("RETURNING")?;
5020                    indented_list(f, returning)?;
5021                }
5022                if let Some(limit) = limit {
5023                    SpaceOrNewline.fmt(f)?;
5024                    write!(f, "LIMIT {limit}")?;
5025                }
5026                Ok(())
5027            }
5028            Statement::Delete(delete) => delete.fmt(f),
5029            Statement::Open(open) => open.fmt(f),
5030            Statement::Close { cursor } => {
5031                write!(f, "CLOSE {cursor}")?;
5032
5033                Ok(())
5034            }
5035            Statement::CreateDatabase {
5036                db_name,
5037                if_not_exists,
5038                location,
5039                managed_location,
5040                or_replace,
5041                transient,
5042                clone,
5043                data_retention_time_in_days,
5044                max_data_extension_time_in_days,
5045                external_volume,
5046                catalog,
5047                replace_invalid_characters,
5048                default_ddl_collation,
5049                storage_serialization_policy,
5050                comment,
5051                catalog_sync,
5052                catalog_sync_namespace_mode,
5053                catalog_sync_namespace_flatten_delimiter,
5054                with_tags,
5055                with_contacts,
5056            } => {
5057                write!(
5058                    f,
5059                    "CREATE {or_replace}{transient}DATABASE {if_not_exists}{name}",
5060                    or_replace = if *or_replace { "OR REPLACE " } else { "" },
5061                    transient = if *transient { "TRANSIENT " } else { "" },
5062                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
5063                    name = db_name,
5064                )?;
5065
5066                if let Some(l) = location {
5067                    write!(f, " LOCATION '{l}'")?;
5068                }
5069                if let Some(ml) = managed_location {
5070                    write!(f, " MANAGEDLOCATION '{ml}'")?;
5071                }
5072                if let Some(clone) = clone {
5073                    write!(f, " CLONE {clone}")?;
5074                }
5075
5076                if let Some(value) = data_retention_time_in_days {
5077                    write!(f, " DATA_RETENTION_TIME_IN_DAYS = {value}")?;
5078                }
5079
5080                if let Some(value) = max_data_extension_time_in_days {
5081                    write!(f, " MAX_DATA_EXTENSION_TIME_IN_DAYS = {value}")?;
5082                }
5083
5084                if let Some(vol) = external_volume {
5085                    write!(f, " EXTERNAL_VOLUME = '{vol}'")?;
5086                }
5087
5088                if let Some(cat) = catalog {
5089                    write!(f, " CATALOG = '{cat}'")?;
5090                }
5091
5092                if let Some(true) = replace_invalid_characters {
5093                    write!(f, " REPLACE_INVALID_CHARACTERS = TRUE")?;
5094                } else if let Some(false) = replace_invalid_characters {
5095                    write!(f, " REPLACE_INVALID_CHARACTERS = FALSE")?;
5096                }
5097
5098                if let Some(collation) = default_ddl_collation {
5099                    write!(f, " DEFAULT_DDL_COLLATION = '{collation}'")?;
5100                }
5101
5102                if let Some(policy) = storage_serialization_policy {
5103                    write!(f, " STORAGE_SERIALIZATION_POLICY = {policy}")?;
5104                }
5105
5106                if let Some(comment) = comment {
5107                    write!(f, " COMMENT = '{comment}'")?;
5108                }
5109
5110                if let Some(sync) = catalog_sync {
5111                    write!(f, " CATALOG_SYNC = '{sync}'")?;
5112                }
5113
5114                if let Some(mode) = catalog_sync_namespace_mode {
5115                    write!(f, " CATALOG_SYNC_NAMESPACE_MODE = {mode}")?;
5116                }
5117
5118                if let Some(delim) = catalog_sync_namespace_flatten_delimiter {
5119                    write!(f, " CATALOG_SYNC_NAMESPACE_FLATTEN_DELIMITER = '{delim}'")?;
5120                }
5121
5122                if let Some(tags) = with_tags {
5123                    write!(f, " WITH TAG ({})", display_comma_separated(tags))?;
5124                }
5125
5126                if let Some(contacts) = with_contacts {
5127                    write!(f, " WITH CONTACT ({})", display_comma_separated(contacts))?;
5128                }
5129                Ok(())
5130            }
5131            Statement::CreateFunction(create_function) => create_function.fmt(f),
5132            Statement::CreateDomain(create_domain) => create_domain.fmt(f),
5133            Statement::CreateTrigger(create_trigger) => create_trigger.fmt(f),
5134            Statement::DropTrigger(drop_trigger) => drop_trigger.fmt(f),
5135            Statement::CreateProcedure {
5136                name,
5137                or_alter,
5138                if_not_exists,
5139                params,
5140                language,
5141                options,
5142                body,
5143            } => {
5144                write!(
5145                    f,
5146                    "CREATE {or_alter}PROCEDURE {if_not_exists}{name}",
5147                    or_alter = if *or_alter { "OR ALTER " } else { "" },
5148                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
5149                    name = name
5150                )?;
5151
5152                if let Some(p) = params {
5153                    if !p.is_empty() {
5154                        write!(f, " ({})", display_comma_separated(p))?;
5155                    }
5156                }
5157
5158                if let Some(language) = language {
5159                    write!(f, " LANGUAGE {language}")?;
5160                }
5161
5162                if let Some(opts) = options {
5163                    if !opts.is_empty() {
5164                        write!(f, " OPTIONS ({})", display_comma_separated(opts))?;
5165                    }
5166                }
5167
5168                write!(f, " AS {body}")
5169            }
5170            Statement::CreateMacro {
5171                or_replace,
5172                temporary,
5173                name,
5174                args,
5175                definition,
5176            } => {
5177                write!(
5178                    f,
5179                    "CREATE {or_replace}{temp}MACRO {name}",
5180                    temp = if *temporary { "TEMPORARY " } else { "" },
5181                    or_replace = if *or_replace { "OR REPLACE " } else { "" },
5182                )?;
5183                if let Some(args) = args {
5184                    write!(f, "({})", display_comma_separated(args))?;
5185                }
5186                match definition {
5187                    MacroDefinition::Expr(expr) => write!(f, " AS {expr}")?,
5188                    MacroDefinition::Table(query) => write!(f, " AS TABLE {query}")?,
5189                }
5190                Ok(())
5191            }
5192            Statement::CreateView {
5193                or_alter,
5194                name,
5195                or_replace,
5196                columns,
5197                query,
5198                materialized,
5199                secure,
5200                options,
5201                partition_by,
5202                cluster_by,
5203                comment,
5204                with_no_schema_binding,
5205                if_not_exists,
5206                temporary,
5207                to,
5208                params,
5209                name_before_not_exists,
5210                sql_security,
5211            } => {
5212                write!(
5213                    f,
5214                    "CREATE {or_alter}{or_replace}",
5215                    or_alter = if *or_alter { "OR ALTER " } else { "" },
5216                    or_replace = if *or_replace { "OR REPLACE " } else { "" },
5217                )?;
5218                if let Some(params) = params {
5219                    params.fmt(f)?;
5220                }
5221                write!(
5222                    f,
5223                    "{secure}{materialized}{temporary}VIEW {if_not_and_name}{to}",
5224                    if_not_and_name = if *if_not_exists {
5225                        if *name_before_not_exists {
5226                            format!("{name} IF NOT EXISTS")
5227                        } else {
5228                            format!("IF NOT EXISTS {name}")
5229                        }
5230                    } else {
5231                        format!("{name}")
5232                    },
5233                    secure = if *secure { "SECURE " } else { "" },
5234                    materialized = if *materialized { "MATERIALIZED " } else { "" },
5235                    temporary = if *temporary { "TEMPORARY " } else { "" },
5236                    to = to
5237                        .as_ref()
5238                        .map(|to| format!(" TO {to}"))
5239                        .unwrap_or_default()
5240                )?;
5241                if !columns.is_empty() {
5242                    write!(f, " ({})", display_comma_separated(columns))?;
5243                }
5244                if matches!(options, CreateTableOptions::With(_)) {
5245                    write!(f, " {options}")?;
5246                }
5247                if let Some(comment) = comment {
5248                    write!(
5249                        f,
5250                        " COMMENT = '{}'",
5251                        value::escape_single_quote_string(comment)
5252                    )?;
5253                }
5254                if let Some(partition_by) = partition_by {
5255                    write!(f, " PARTITION BY {partition_by}")?;
5256                }
5257                if !cluster_by.is_empty() {
5258                    write!(f, " CLUSTER BY {}", display_comma_separated(cluster_by))?;
5259                }
5260                if matches!(options, CreateTableOptions::Options(_)) {
5261                    write!(f, " {options}")?;
5262                }
5263                if let Some(security) = sql_security {
5264                    write!(f, " {security}")?;
5265                }
5266                f.write_str(" AS")?;
5267                SpaceOrNewline.fmt(f)?;
5268                query.fmt(f)?;
5269                if *with_no_schema_binding {
5270                    write!(f, " WITH NO SCHEMA BINDING")?;
5271                }
5272                Ok(())
5273            }
5274            Statement::CreateMaterializedViewReplica {
5275                name,
5276                source,
5277                if_not_exists,
5278            } => {
5279                write!(f, "CREATE MATERIALIZED VIEW REPLICA ")?;
5280                if *if_not_exists {
5281                    write!(f, "IF NOT EXISTS ")?;
5282                }
5283                write!(f, "{name} AS REPLICA OF {source}")
5284            }
5285            Statement::CreateTable(create_table) => create_table.fmt(f),
5286            Statement::LoadData {
5287                local,
5288                inpath,
5289                overwrite,
5290                table_name,
5291                partitioned,
5292                table_format,
5293            } => {
5294                write!(
5295                    f,
5296                    "LOAD DATA {local}INPATH '{inpath}' {overwrite}INTO TABLE {table_name}",
5297                    local = if *local { "LOCAL " } else { "" },
5298                    inpath = inpath,
5299                    overwrite = if *overwrite { "OVERWRITE " } else { "" },
5300                    table_name = table_name,
5301                )?;
5302                if let Some(ref parts) = &partitioned {
5303                    if !parts.is_empty() {
5304                        write!(f, " PARTITION ({})", display_comma_separated(parts))?;
5305                    }
5306                }
5307                if let Some(HiveLoadDataFormat {
5308                    serde,
5309                    input_format,
5310                }) = &table_format
5311                {
5312                    write!(f, " INPUTFORMAT {input_format} SERDE {serde}")?;
5313                }
5314                Ok(())
5315            }
5316            Statement::CreateVirtualTable {
5317                name,
5318                if_not_exists,
5319                module_name,
5320                module_args,
5321            } => {
5322                write!(
5323                    f,
5324                    "CREATE VIRTUAL TABLE {if_not_exists}{name} USING {module_name}",
5325                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
5326                    name = name,
5327                    module_name = module_name
5328                )?;
5329                if !module_args.is_empty() {
5330                    write!(f, " ({})", display_comma_separated(module_args))?;
5331                }
5332                Ok(())
5333            }
5334            Statement::CreateIndex(create_index) => create_index.fmt(f),
5335            Statement::CreateSearchIndex {
5336                or_replace,
5337                if_not_exists,
5338                name,
5339                table_name,
5340                columns,
5341                all_columns,
5342                options,
5343            } => {
5344                write!(
5345                    f,
5346                    "CREATE {or_replace}SEARCH INDEX {if_not_exists}{name} ON {table_name}",
5347                    or_replace = if *or_replace { "OR REPLACE " } else { "" },
5348                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
5349                )?;
5350                if *all_columns {
5351                    write!(f, " (ALL COLUMNS)")?;
5352                } else if !columns.is_empty() {
5353                    write!(f, " ({})", display_comma_separated(columns))?;
5354                }
5355                if !options.is_empty() {
5356                    write!(f, " OPTIONS ({})", display_comma_separated(options))?;
5357                }
5358                Ok(())
5359            }
5360            Statement::CreateVectorIndex {
5361                or_replace,
5362                if_not_exists,
5363                name,
5364                table_name,
5365                column,
5366                storing,
5367                options,
5368            } => {
5369                write!(
5370                    f,
5371                    "CREATE {or_replace}VECTOR INDEX {if_not_exists}{name} ON {table_name} ({column})",
5372                    or_replace = if *or_replace { "OR REPLACE " } else { "" },
5373                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
5374                )?;
5375                if !storing.is_empty() {
5376                    write!(f, " STORING ({})", display_comma_separated(storing))?;
5377                }
5378                if !options.is_empty() {
5379                    write!(f, " OPTIONS ({})", display_comma_separated(options))?;
5380                }
5381                Ok(())
5382            }
5383            Statement::CreateRowAccessPolicy {
5384                or_replace,
5385                if_not_exists,
5386                name,
5387                table_name,
5388                grant_to,
5389                filter_using,
5390            } => {
5391                write!(
5392                    f,
5393                    "CREATE {or_replace}ROW ACCESS POLICY {if_not_exists}{name} ON {table_name}",
5394                    or_replace = if *or_replace { "OR REPLACE " } else { "" },
5395                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
5396                )?;
5397                write!(f, " GRANT TO ({})", display_comma_separated(grant_to))?;
5398                write!(f, " FILTER USING ({filter_using})")?;
5399                Ok(())
5400            }
5401            Statement::DropSearchIndex {
5402                if_exists,
5403                name,
5404                table_name,
5405            } => {
5406                write!(
5407                    f,
5408                    "DROP SEARCH INDEX {if_exists}{name} ON {table_name}",
5409                    if_exists = if *if_exists { "IF EXISTS " } else { "" },
5410                )
5411            }
5412            Statement::DropVectorIndex {
5413                if_exists,
5414                name,
5415                table_name,
5416            } => {
5417                write!(
5418                    f,
5419                    "DROP VECTOR INDEX {if_exists}{name} ON {table_name}",
5420                    if_exists = if *if_exists { "IF EXISTS " } else { "" },
5421                )
5422            }
5423            Statement::DropRowAccessPolicy {
5424                if_exists,
5425                name,
5426                table_name,
5427            } => {
5428                write!(
5429                    f,
5430                    "DROP ROW ACCESS POLICY {if_exists}{name} ON {table_name}",
5431                    if_exists = if *if_exists { "IF EXISTS " } else { "" },
5432                )
5433            }
5434            Statement::DropAllRowAccessPolicies { table_name } => {
5435                write!(f, "DROP ALL ROW ACCESS POLICIES ON {table_name}")
5436            }
5437            Statement::CreateExtension {
5438                name,
5439                if_not_exists,
5440                cascade,
5441                schema,
5442                version,
5443            } => {
5444                write!(
5445                    f,
5446                    "CREATE EXTENSION {if_not_exists}{name}",
5447                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" }
5448                )?;
5449                if *cascade || schema.is_some() || version.is_some() {
5450                    write!(f, " WITH")?;
5451
5452                    if let Some(name) = schema {
5453                        write!(f, " SCHEMA {name}")?;
5454                    }
5455                    if let Some(version) = version {
5456                        write!(f, " VERSION {version}")?;
5457                    }
5458                    if *cascade {
5459                        write!(f, " CASCADE")?;
5460                    }
5461                }
5462
5463                Ok(())
5464            }
5465            Statement::DropExtension {
5466                names,
5467                if_exists,
5468                cascade_or_restrict,
5469            } => {
5470                write!(f, "DROP EXTENSION")?;
5471                if *if_exists {
5472                    write!(f, " IF EXISTS")?;
5473                }
5474                write!(f, " {}", display_comma_separated(names))?;
5475                if let Some(cascade_or_restrict) = cascade_or_restrict {
5476                    write!(f, " {cascade_or_restrict}")?;
5477                }
5478                Ok(())
5479            }
5480            Statement::CreateRole {
5481                names,
5482                if_not_exists,
5483                inherit,
5484                login,
5485                bypassrls,
5486                password,
5487                create_db,
5488                create_role,
5489                superuser,
5490                replication,
5491                connection_limit,
5492                valid_until,
5493                in_role,
5494                in_group,
5495                role,
5496                user,
5497                admin,
5498                authorization_owner,
5499            } => {
5500                write!(
5501                    f,
5502                    "CREATE ROLE {if_not_exists}{names}{superuser}{create_db}{create_role}{inherit}{login}{replication}{bypassrls}",
5503                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
5504                    names = display_separated(names, ", "),
5505                    superuser = match *superuser {
5506                        Some(true) => " SUPERUSER",
5507                        Some(false) => " NOSUPERUSER",
5508                        None => ""
5509                    },
5510                    create_db = match *create_db {
5511                        Some(true) => " CREATEDB",
5512                        Some(false) => " NOCREATEDB",
5513                        None => ""
5514                    },
5515                    create_role = match *create_role {
5516                        Some(true) => " CREATEROLE",
5517                        Some(false) => " NOCREATEROLE",
5518                        None => ""
5519                    },
5520                    inherit = match *inherit {
5521                        Some(true) => " INHERIT",
5522                        Some(false) => " NOINHERIT",
5523                        None => ""
5524                    },
5525                    login = match *login {
5526                        Some(true) => " LOGIN",
5527                        Some(false) => " NOLOGIN",
5528                        None => ""
5529                    },
5530                    replication = match *replication {
5531                        Some(true) => " REPLICATION",
5532                        Some(false) => " NOREPLICATION",
5533                        None => ""
5534                    },
5535                    bypassrls = match *bypassrls {
5536                        Some(true) => " BYPASSRLS",
5537                        Some(false) => " NOBYPASSRLS",
5538                        None => ""
5539                    }
5540                )?;
5541                if let Some(limit) = connection_limit {
5542                    write!(f, " CONNECTION LIMIT {limit}")?;
5543                }
5544                match password {
5545                    Some(Password::Password(pass)) => write!(f, " PASSWORD {pass}"),
5546                    Some(Password::NullPassword) => write!(f, " PASSWORD NULL"),
5547                    None => Ok(()),
5548                }?;
5549                if let Some(until) = valid_until {
5550                    write!(f, " VALID UNTIL {until}")?;
5551                }
5552                if !in_role.is_empty() {
5553                    write!(f, " IN ROLE {}", display_comma_separated(in_role))?;
5554                }
5555                if !in_group.is_empty() {
5556                    write!(f, " IN GROUP {}", display_comma_separated(in_group))?;
5557                }
5558                if !role.is_empty() {
5559                    write!(f, " ROLE {}", display_comma_separated(role))?;
5560                }
5561                if !user.is_empty() {
5562                    write!(f, " USER {}", display_comma_separated(user))?;
5563                }
5564                if !admin.is_empty() {
5565                    write!(f, " ADMIN {}", display_comma_separated(admin))?;
5566                }
5567                if let Some(owner) = authorization_owner {
5568                    write!(f, " AUTHORIZATION {owner}")?;
5569                }
5570                Ok(())
5571            }
5572            Statement::CreateSecret {
5573                or_replace,
5574                temporary,
5575                if_not_exists,
5576                name,
5577                storage_specifier,
5578                secret_type,
5579                options,
5580            } => {
5581                write!(
5582                    f,
5583                    "CREATE {or_replace}",
5584                    or_replace = if *or_replace { "OR REPLACE " } else { "" },
5585                )?;
5586                if let Some(t) = temporary {
5587                    write!(f, "{}", if *t { "TEMPORARY " } else { "PERSISTENT " })?;
5588                }
5589                write!(
5590                    f,
5591                    "SECRET {if_not_exists}",
5592                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
5593                )?;
5594                if let Some(n) = name {
5595                    write!(f, "{n} ")?;
5596                };
5597                if let Some(s) = storage_specifier {
5598                    write!(f, "IN {s} ")?;
5599                }
5600                write!(f, "( TYPE {secret_type}",)?;
5601                if !options.is_empty() {
5602                    write!(f, ", {o}", o = display_comma_separated(options))?;
5603                }
5604                write!(f, " )")?;
5605                Ok(())
5606            }
5607            Statement::CreateServer(stmt) => {
5608                write!(f, "{stmt}")
5609            }
5610            Statement::CreatePolicy {
5611                name,
5612                table_name,
5613                policy_type,
5614                command,
5615                to,
5616                using,
5617                with_check,
5618            } => {
5619                write!(f, "CREATE POLICY {name} ON {table_name}")?;
5620
5621                if let Some(policy_type) = policy_type {
5622                    match policy_type {
5623                        CreatePolicyType::Permissive => write!(f, " AS PERMISSIVE")?,
5624                        CreatePolicyType::Restrictive => write!(f, " AS RESTRICTIVE")?,
5625                    }
5626                }
5627
5628                if let Some(command) = command {
5629                    match command {
5630                        CreatePolicyCommand::All => write!(f, " FOR ALL")?,
5631                        CreatePolicyCommand::Select => write!(f, " FOR SELECT")?,
5632                        CreatePolicyCommand::Insert => write!(f, " FOR INSERT")?,
5633                        CreatePolicyCommand::Update => write!(f, " FOR UPDATE")?,
5634                        CreatePolicyCommand::Delete => write!(f, " FOR DELETE")?,
5635                    }
5636                }
5637
5638                if let Some(to) = to {
5639                    write!(f, " TO {}", display_comma_separated(to))?;
5640                }
5641
5642                if let Some(using) = using {
5643                    write!(f, " USING ({using})")?;
5644                }
5645
5646                if let Some(with_check) = with_check {
5647                    write!(f, " WITH CHECK ({with_check})")?;
5648                }
5649
5650                Ok(())
5651            }
5652            Statement::CreateConnector(create_connector) => create_connector.fmt(f),
5653            Statement::AlterTable {
5654                name,
5655                if_exists,
5656                only,
5657                operations,
5658                location,
5659                on_cluster,
5660                iceberg,
5661                end_token: _,
5662            } => {
5663                if *iceberg {
5664                    write!(f, "ALTER ICEBERG TABLE ")?;
5665                } else {
5666                    write!(f, "ALTER TABLE ")?;
5667                }
5668
5669                if *if_exists {
5670                    write!(f, "IF EXISTS ")?;
5671                }
5672                if *only {
5673                    write!(f, "ONLY ")?;
5674                }
5675                write!(f, "{name} ")?;
5676                if let Some(cluster) = on_cluster {
5677                    write!(f, "ON CLUSTER {cluster} ")?;
5678                }
5679                write!(
5680                    f,
5681                    "{operations}",
5682                    operations = display_comma_separated(operations)
5683                )?;
5684                if let Some(loc) = location {
5685                    write!(f, " {loc}")?
5686                }
5687                Ok(())
5688            }
5689            Statement::AlterIndex { name, operation } => {
5690                write!(f, "ALTER INDEX {name} {operation}")
5691            }
5692            Statement::AlterView {
5693                name,
5694                columns,
5695                query,
5696                with_options,
5697            } => {
5698                write!(f, "ALTER VIEW {name}")?;
5699                if !with_options.is_empty() {
5700                    write!(f, " WITH ({})", display_comma_separated(with_options))?;
5701                }
5702                if !columns.is_empty() {
5703                    write!(f, " ({})", display_comma_separated(columns))?;
5704                }
5705                write!(f, " AS {query}")
5706            }
5707            Statement::AlterMaterializedView { name, options, operations } => {
5708                write!(f, "ALTER MATERIALIZED VIEW {name}")?;
5709                if !options.is_empty() {
5710                    write!(f, " SET OPTIONS ({})", display_comma_separated(options))?;
5711                }
5712                for operation in operations {
5713                    write!(f, " {}", operation)?;
5714                }
5715                Ok(())
5716            }
5717            Statement::AlterViewWithOperations { name, operations } => {
5718                write!(f, "ALTER VIEW {name}")?;
5719                for operation in operations {
5720                    write!(f, " {}", operation)?;
5721                }
5722                Ok(())
5723            }
5724            Statement::AlterFunction { name, options } => {
5725                write!(f, "ALTER FUNCTION {name} SET OPTIONS ({})", display_comma_separated(options))
5726            }
5727            Statement::AlterProcedure { name, options } => {
5728                write!(f, "ALTER PROCEDURE {name} SET OPTIONS ({})", display_comma_separated(options))
5729            }
5730            Statement::AlterType(AlterType { name, operation }) => {
5731                write!(f, "ALTER TYPE {name} {operation}")
5732            }
5733            Statement::AlterRole { name, operation } => {
5734                write!(f, "ALTER ROLE {name} {operation}")
5735            }
5736            Statement::AlterPolicy {
5737                name,
5738                table_name,
5739                operation,
5740            } => {
5741                write!(f, "ALTER POLICY {name} ON {table_name}{operation}")
5742            }
5743            Statement::AlterConnector {
5744                name,
5745                properties,
5746                url,
5747                owner,
5748            } => {
5749                write!(f, "ALTER CONNECTOR {name}")?;
5750                if let Some(properties) = properties {
5751                    write!(
5752                        f,
5753                        " SET DCPROPERTIES({})",
5754                        display_comma_separated(properties)
5755                    )?;
5756                }
5757                if let Some(url) = url {
5758                    write!(f, " SET URL '{url}'")?;
5759                }
5760                if let Some(owner) = owner {
5761                    write!(f, " SET OWNER {owner}")?;
5762                }
5763                Ok(())
5764            }
5765            Statement::AlterSession {
5766                set,
5767                session_params,
5768            } => {
5769                write!(
5770                    f,
5771                    "ALTER SESSION {set}",
5772                    set = if *set { "SET" } else { "UNSET" }
5773                )?;
5774                if !session_params.options.is_empty() {
5775                    if *set {
5776                        write!(f, " {session_params}")?;
5777                    } else {
5778                        let options = session_params
5779                            .options
5780                            .iter()
5781                            .map(|p| p.option_name.clone())
5782                            .collect::<Vec<_>>();
5783                        write!(f, " {}", display_separated(&options, ", "))?;
5784                    }
5785                }
5786                Ok(())
5787            }
5788            Statement::Drop {
5789                object_type,
5790                if_exists,
5791                names,
5792                cascade,
5793                restrict,
5794                purge,
5795                temporary,
5796                table,
5797            } => {
5798                write!(
5799                    f,
5800                    "DROP {}{}{} {}{}{}{}",
5801                    if *temporary { "TEMPORARY " } else { "" },
5802                    object_type,
5803                    if *if_exists { " IF EXISTS" } else { "" },
5804                    display_comma_separated(names),
5805                    if *cascade { " CASCADE" } else { "" },
5806                    if *restrict { " RESTRICT" } else { "" },
5807                    if *purge { " PURGE" } else { "" },
5808                )?;
5809                if let Some(table_name) = table.as_ref() {
5810                    write!(f, " ON {table_name}")?;
5811                };
5812                Ok(())
5813            }
5814            Statement::DropFunction {
5815                if_exists,
5816                func_desc,
5817                drop_behavior,
5818            } => {
5819                write!(
5820                    f,
5821                    "DROP FUNCTION{} {}",
5822                    if *if_exists { " IF EXISTS" } else { "" },
5823                    display_comma_separated(func_desc),
5824                )?;
5825                if let Some(op) = drop_behavior {
5826                    write!(f, " {op}")?;
5827                }
5828                Ok(())
5829            }
5830            Statement::DropDomain(DropDomain {
5831                if_exists,
5832                name,
5833                drop_behavior,
5834            }) => {
5835                write!(
5836                    f,
5837                    "DROP DOMAIN{} {name}",
5838                    if *if_exists { " IF EXISTS" } else { "" },
5839                )?;
5840                if let Some(op) = drop_behavior {
5841                    write!(f, " {op}")?;
5842                }
5843                Ok(())
5844            }
5845            Statement::DropProcedure {
5846                if_exists,
5847                proc_desc,
5848                drop_behavior,
5849            } => {
5850                write!(
5851                    f,
5852                    "DROP PROCEDURE{} {}",
5853                    if *if_exists { " IF EXISTS" } else { "" },
5854                    display_comma_separated(proc_desc),
5855                )?;
5856                if let Some(op) = drop_behavior {
5857                    write!(f, " {op}")?;
5858                }
5859                Ok(())
5860            }
5861            Statement::DropSecret {
5862                if_exists,
5863                temporary,
5864                name,
5865                storage_specifier,
5866            } => {
5867                write!(f, "DROP ")?;
5868                if let Some(t) = temporary {
5869                    write!(f, "{}", if *t { "TEMPORARY " } else { "PERSISTENT " })?;
5870                }
5871                write!(
5872                    f,
5873                    "SECRET {if_exists}{name}",
5874                    if_exists = if *if_exists { "IF EXISTS " } else { "" },
5875                )?;
5876                if let Some(s) = storage_specifier {
5877                    write!(f, " FROM {s}")?;
5878                }
5879                Ok(())
5880            }
5881            Statement::DropPolicy {
5882                if_exists,
5883                name,
5884                table_name,
5885                drop_behavior,
5886            } => {
5887                write!(f, "DROP POLICY")?;
5888                if *if_exists {
5889                    write!(f, " IF EXISTS")?;
5890                }
5891                write!(f, " {name} ON {table_name}")?;
5892                if let Some(drop_behavior) = drop_behavior {
5893                    write!(f, " {drop_behavior}")?;
5894                }
5895                Ok(())
5896            }
5897            Statement::DropConnector { if_exists, name } => {
5898                write!(
5899                    f,
5900                    "DROP CONNECTOR {if_exists}{name}",
5901                    if_exists = if *if_exists { "IF EXISTS " } else { "" }
5902                )?;
5903                Ok(())
5904            }
5905            Statement::UndropSchema {
5906                if_not_exists,
5907                schema_name,
5908            } => {
5909                write!(
5910                    f,
5911                    "UNDROP SCHEMA {if_not_exists}{schema_name}",
5912                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" }
5913                )?;
5914                Ok(())
5915            }
5916            Statement::Discard { object_type } => {
5917                write!(f, "DISCARD {object_type}")?;
5918                Ok(())
5919            }
5920            Self::Set(set) => write!(f, "{set}"),
5921            Statement::ShowVariable { variable } => {
5922                write!(f, "SHOW")?;
5923                if !variable.is_empty() {
5924                    write!(f, " {}", display_separated(variable, " "))?;
5925                }
5926                Ok(())
5927            }
5928            Statement::ShowStatus {
5929                filter,
5930                global,
5931                session,
5932            } => {
5933                write!(f, "SHOW")?;
5934                if *global {
5935                    write!(f, " GLOBAL")?;
5936                }
5937                if *session {
5938                    write!(f, " SESSION")?;
5939                }
5940                write!(f, " STATUS")?;
5941                if filter.is_some() {
5942                    write!(f, " {}", filter.as_ref().unwrap())?;
5943                }
5944                Ok(())
5945            }
5946            Statement::ShowVariables {
5947                filter,
5948                global,
5949                session,
5950            } => {
5951                write!(f, "SHOW")?;
5952                if *global {
5953                    write!(f, " GLOBAL")?;
5954                }
5955                if *session {
5956                    write!(f, " SESSION")?;
5957                }
5958                write!(f, " VARIABLES")?;
5959                if filter.is_some() {
5960                    write!(f, " {}", filter.as_ref().unwrap())?;
5961                }
5962                Ok(())
5963            }
5964            Statement::ShowCreate { obj_type, obj_name } => {
5965                write!(f, "SHOW CREATE {obj_type} {obj_name}",)?;
5966                Ok(())
5967            }
5968            Statement::ShowColumns {
5969                extended,
5970                full,
5971                show_options,
5972            } => {
5973                write!(
5974                    f,
5975                    "SHOW {extended}{full}COLUMNS{show_options}",
5976                    extended = if *extended { "EXTENDED " } else { "" },
5977                    full = if *full { "FULL " } else { "" },
5978                )?;
5979                Ok(())
5980            }
5981            Statement::ShowDatabases {
5982                terse,
5983                history,
5984                show_options,
5985            } => {
5986                write!(
5987                    f,
5988                    "SHOW {terse}DATABASES{history}{show_options}",
5989                    terse = if *terse { "TERSE " } else { "" },
5990                    history = if *history { " HISTORY" } else { "" },
5991                )?;
5992                Ok(())
5993            }
5994            Statement::ShowSchemas {
5995                terse,
5996                history,
5997                show_options,
5998            } => {
5999                write!(
6000                    f,
6001                    "SHOW {terse}SCHEMAS{history}{show_options}",
6002                    terse = if *terse { "TERSE " } else { "" },
6003                    history = if *history { " HISTORY" } else { "" },
6004                )?;
6005                Ok(())
6006            }
6007            Statement::ShowObjects(ShowObjects {
6008                terse,
6009                show_options,
6010            }) => {
6011                write!(
6012                    f,
6013                    "SHOW {terse}OBJECTS{show_options}",
6014                    terse = if *terse { "TERSE " } else { "" },
6015                )?;
6016                Ok(())
6017            }
6018            Statement::ShowTables {
6019                terse,
6020                history,
6021                extended,
6022                full,
6023                external,
6024                show_options,
6025            } => {
6026                write!(
6027                    f,
6028                    "SHOW {terse}{extended}{full}{external}TABLES{history}{show_options}",
6029                    terse = if *terse { "TERSE " } else { "" },
6030                    extended = if *extended { "EXTENDED " } else { "" },
6031                    full = if *full { "FULL " } else { "" },
6032                    external = if *external { "EXTERNAL " } else { "" },
6033                    history = if *history { " HISTORY" } else { "" },
6034                )?;
6035                Ok(())
6036            }
6037            Statement::ShowViews {
6038                terse,
6039                materialized,
6040                show_options,
6041            } => {
6042                write!(
6043                    f,
6044                    "SHOW {terse}{materialized}VIEWS{show_options}",
6045                    terse = if *terse { "TERSE " } else { "" },
6046                    materialized = if *materialized { "MATERIALIZED " } else { "" }
6047                )?;
6048                Ok(())
6049            }
6050            Statement::ShowFunctions { filter } => {
6051                write!(f, "SHOW FUNCTIONS")?;
6052                if let Some(filter) = filter {
6053                    write!(f, " {filter}")?;
6054                }
6055                Ok(())
6056            }
6057            Statement::Use(use_expr) => use_expr.fmt(f),
6058            Statement::ShowCollation { filter } => {
6059                write!(f, "SHOW COLLATION")?;
6060                if let Some(filter) = filter {
6061                    write!(f, " {filter}")?;
6062                }
6063                Ok(())
6064            }
6065            Statement::ShowCharset(show_stm) => show_stm.fmt(f),
6066            Statement::StartTransaction {
6067                modes,
6068                begin: syntax_begin,
6069                transaction,
6070                modifier,
6071                statements,
6072                exception,
6073                has_end_keyword,
6074                label,
6075            } => {
6076                if let Some(lbl) = label {
6077                    write!(f, "{}: ", lbl)?;
6078                }
6079                if *syntax_begin {
6080                    if let Some(modifier) = *modifier {
6081                        write!(f, "BEGIN {modifier}")?;
6082                    } else {
6083                        write!(f, "BEGIN")?;
6084                    }
6085                } else {
6086                    write!(f, "START")?;
6087                }
6088                if let Some(transaction) = transaction {
6089                    write!(f, " {transaction}")?;
6090                }
6091                if !modes.is_empty() {
6092                    write!(f, " {}", display_comma_separated(modes))?;
6093                }
6094                if !statements.is_empty() {
6095                    write!(f, " ")?;
6096                    format_statement_list(f, statements)?;
6097                }
6098                if let Some(exception_when) = exception {
6099                    write!(f, " EXCEPTION")?;
6100                    for when in exception_when {
6101                        write!(f, " {when}")?;
6102                    }
6103                }
6104                if *has_end_keyword {
6105                    write!(f, " END")?;
6106                }
6107                Ok(())
6108            }
6109            Statement::Commit {
6110                chain,
6111                end: end_syntax,
6112                modifier,
6113            } => {
6114                if *end_syntax {
6115                    write!(f, "END")?;
6116                    if let Some(modifier) = *modifier {
6117                        write!(f, " {modifier}")?;
6118                    }
6119                    if *chain {
6120                        write!(f, " AND CHAIN")?;
6121                    }
6122                } else {
6123                    write!(f, "COMMIT{}", if *chain { " AND CHAIN" } else { "" })?;
6124                }
6125                Ok(())
6126            }
6127            Statement::Rollback { chain, savepoint } => {
6128                write!(f, "ROLLBACK")?;
6129
6130                if *chain {
6131                    write!(f, " AND CHAIN")?;
6132                }
6133
6134                if let Some(savepoint) = savepoint {
6135                    write!(f, " TO SAVEPOINT {savepoint}")?;
6136                }
6137
6138                Ok(())
6139            }
6140            Statement::CreateSchema {
6141                schema_name,
6142                if_not_exists,
6143                or_replace,
6144                with,
6145                options,
6146                default_collate_spec,
6147                clone,
6148            } => {
6149                write!(
6150                    f,
6151                    "CREATE {or_replace}SCHEMA {if_not_exists}{name}",
6152                    or_replace = if *or_replace { "OR REPLACE " } else { "" },
6153                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
6154                    name = schema_name
6155                )?;
6156
6157                if let Some(collate) = default_collate_spec {
6158                    write!(f, " DEFAULT COLLATE {collate}")?;
6159                }
6160
6161                if let Some(with) = with {
6162                    write!(f, " WITH ({})", display_comma_separated(with))?;
6163                }
6164
6165                if let Some(options) = options {
6166                    write!(f, " OPTIONS({})", display_comma_separated(options))?;
6167                }
6168
6169                if let Some(clone) = clone {
6170                    write!(f, " CLONE {clone}")?;
6171                }
6172                Ok(())
6173            }
6174            Statement::Assert { condition, message } => {
6175                write!(f, "ASSERT {condition}")?;
6176                if let Some(m) = message {
6177                    write!(f, " AS {m}")?;
6178                }
6179                Ok(())
6180            }
6181            Statement::Grant {
6182                privileges,
6183                objects,
6184                grantees,
6185                with_grant_option,
6186                as_grantor,
6187                granted_by,
6188                current_grants,
6189            } => {
6190                write!(f, "GRANT {privileges} ")?;
6191                if let Some(objects) = objects {
6192                    write!(f, "ON {objects} ")?;
6193                }
6194                write!(f, "TO {}", display_comma_separated(grantees))?;
6195                if *with_grant_option {
6196                    write!(f, " WITH GRANT OPTION")?;
6197                }
6198                if let Some(current_grants) = current_grants {
6199                    write!(f, " {current_grants}")?;
6200                }
6201                if let Some(grantor) = as_grantor {
6202                    write!(f, " AS {grantor}")?;
6203                }
6204                if let Some(grantor) = granted_by {
6205                    write!(f, " GRANTED BY {grantor}")?;
6206                }
6207                Ok(())
6208            }
6209            Statement::Deny(s) => write!(f, "{s}"),
6210            Statement::Revoke {
6211                privileges,
6212                objects,
6213                grantees,
6214                granted_by,
6215                cascade,
6216            } => {
6217                write!(f, "REVOKE {privileges} ")?;
6218                if let Some(objects) = objects {
6219                    write!(f, "ON {objects} ")?;
6220                }
6221                write!(f, "FROM {}", display_comma_separated(grantees))?;
6222                if let Some(grantor) = granted_by {
6223                    write!(f, " GRANTED BY {grantor}")?;
6224                }
6225                if let Some(cascade) = cascade {
6226                    write!(f, " {cascade}")?;
6227                }
6228                Ok(())
6229            }
6230            Statement::Deallocate { name, prepare } => write!(
6231                f,
6232                "DEALLOCATE {prepare}{name}",
6233                prepare = if *prepare { "PREPARE " } else { "" },
6234                name = name,
6235            ),
6236            Statement::Execute {
6237                name,
6238                parameters,
6239                has_parentheses,
6240                immediate,
6241                into,
6242                using,
6243                output,
6244                default,
6245            } => {
6246                let (open, close) = if *has_parentheses {
6247                    ("(", ")")
6248                } else {
6249                    (if parameters.is_empty() { "" } else { " " }, "")
6250                };
6251                write!(f, "EXECUTE")?;
6252                if *immediate {
6253                    write!(f, " IMMEDIATE")?;
6254                }
6255                if let Some(name) = name {
6256                    write!(f, " {name}")?;
6257                }
6258                write!(f, "{open}{}{close}", display_comma_separated(parameters),)?;
6259                if !into.is_empty() {
6260                    write!(f, " INTO {}", display_comma_separated(into))?;
6261                }
6262                if !using.is_empty() {
6263                    write!(f, " USING {}", display_comma_separated(using))?;
6264                };
6265                if *output {
6266                    write!(f, " OUTPUT")?;
6267                }
6268                if *default {
6269                    write!(f, " DEFAULT")?;
6270                }
6271                Ok(())
6272            }
6273            Statement::Prepare {
6274                name,
6275                data_types,
6276                statement,
6277            } => {
6278                write!(f, "PREPARE {name} ")?;
6279                if !data_types.is_empty() {
6280                    write!(f, "({}) ", display_comma_separated(data_types))?;
6281                }
6282                write!(f, "AS {statement}")
6283            }
6284            Statement::Comment {
6285                object_type,
6286                object_name,
6287                comment,
6288                if_exists,
6289            } => {
6290                write!(f, "COMMENT ")?;
6291                if *if_exists {
6292                    write!(f, "IF EXISTS ")?
6293                };
6294                write!(f, "ON {object_type} {object_name} IS ")?;
6295                if let Some(c) = comment {
6296                    write!(f, "'{c}'")
6297                } else {
6298                    write!(f, "NULL")
6299                }
6300            }
6301            Statement::Savepoint { name } => {
6302                write!(f, "SAVEPOINT ")?;
6303                write!(f, "{name}")
6304            }
6305            Statement::ReleaseSavepoint { name } => {
6306                write!(f, "RELEASE SAVEPOINT {name}")
6307            }
6308            Statement::Merge {
6309                into,
6310                table,
6311                source,
6312                on,
6313                clauses,
6314                output,
6315            } => {
6316                write!(
6317                    f,
6318                    "MERGE{int} {table} USING {source} ",
6319                    int = if *into { " INTO" } else { "" }
6320                )?;
6321                write!(f, "ON {on} ")?;
6322                write!(f, "{}", display_separated(clauses, " "))?;
6323                if let Some(output) = output {
6324                    write!(f, " {output}")?;
6325                }
6326                Ok(())
6327            }
6328            Statement::Cache {
6329                table_name,
6330                table_flag,
6331                has_as,
6332                options,
6333                query,
6334            } => {
6335                if let Some(table_flag) = table_flag {
6336                    write!(f, "CACHE {table_flag} TABLE {table_name}")?;
6337                } else {
6338                    write!(f, "CACHE TABLE {table_name}")?;
6339                }
6340
6341                if !options.is_empty() {
6342                    write!(f, " OPTIONS({})", display_comma_separated(options))?;
6343                }
6344
6345                match (*has_as, query) {
6346                    (true, Some(query)) => write!(f, " AS {query}"),
6347                    (true, None) => f.write_str(" AS"),
6348                    (false, Some(query)) => write!(f, " {query}"),
6349                    (false, None) => Ok(()),
6350                }
6351            }
6352            Statement::UNCache {
6353                table_name,
6354                if_exists,
6355            } => {
6356                if *if_exists {
6357                    write!(f, "UNCACHE TABLE IF EXISTS {table_name}")
6358                } else {
6359                    write!(f, "UNCACHE TABLE {table_name}")
6360                }
6361            }
6362            Statement::CreateSequence {
6363                temporary,
6364                if_not_exists,
6365                name,
6366                data_type,
6367                sequence_options,
6368                owned_by,
6369            } => {
6370                let as_type: String = if let Some(dt) = data_type.as_ref() {
6371                    //Cannot use format!(" AS {}", dt), due to format! is not available in --target thumbv6m-none-eabi
6372                    // " AS ".to_owned() + &dt.to_string()
6373                    [" AS ", &dt.to_string()].concat()
6374                } else {
6375                    "".to_string()
6376                };
6377                write!(
6378                    f,
6379                    "CREATE {temporary}SEQUENCE {if_not_exists}{name}{as_type}",
6380                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
6381                    temporary = if *temporary { "TEMPORARY " } else { "" },
6382                    name = name,
6383                    as_type = as_type
6384                )?;
6385                for sequence_option in sequence_options {
6386                    write!(f, "{sequence_option}")?;
6387                }
6388                if let Some(ob) = owned_by.as_ref() {
6389                    write!(f, " OWNED BY {ob}")?;
6390                }
6391                write!(f, "")
6392            }
6393            Statement::CreateStage {
6394                or_replace,
6395                temporary,
6396                if_not_exists,
6397                name,
6398                stage_params,
6399                directory_table_params,
6400                file_format,
6401                copy_options,
6402                comment,
6403                ..
6404            } => {
6405                write!(
6406                    f,
6407                    "CREATE {or_replace}{temp}STAGE {if_not_exists}{name}{stage_params}",
6408                    temp = if *temporary { "TEMPORARY " } else { "" },
6409                    or_replace = if *or_replace { "OR REPLACE " } else { "" },
6410                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
6411                )?;
6412                if !directory_table_params.options.is_empty() {
6413                    write!(f, " DIRECTORY=({directory_table_params})")?;
6414                }
6415                if !file_format.options.is_empty() {
6416                    write!(f, " FILE_FORMAT=({file_format})")?;
6417                }
6418                if !copy_options.options.is_empty() {
6419                    write!(f, " COPY_OPTIONS=({copy_options})")?;
6420                }
6421                if comment.is_some() {
6422                    write!(f, " COMMENT='{}'", comment.as_ref().unwrap())?;
6423                }
6424                Ok(())
6425            }
6426            Statement::CopyIntoSnowflake {
6427                kind,
6428                into,
6429                into_columns,
6430                from_obj,
6431                from_obj_alias,
6432                stage_params,
6433                from_transformations,
6434                from_query,
6435                files,
6436                pattern,
6437                file_format,
6438                copy_options,
6439                validation_mode,
6440                partition,
6441            } => {
6442                write!(f, "COPY INTO {into}")?;
6443                if let Some(into_columns) = into_columns {
6444                    write!(f, " ({})", display_comma_separated(into_columns))?;
6445                }
6446                if let Some(from_transformations) = from_transformations {
6447                    // Data load with transformation
6448                    if let Some(from_stage) = from_obj {
6449                        write!(
6450                            f,
6451                            " FROM (SELECT {} FROM {}{}",
6452                            display_separated(from_transformations, ", "),
6453                            from_stage,
6454                            stage_params
6455                        )?;
6456                    }
6457                    if let Some(from_obj_alias) = from_obj_alias {
6458                        write!(f, " AS {from_obj_alias}")?;
6459                    }
6460                    write!(f, ")")?;
6461                } else if let Some(from_obj) = from_obj {
6462                    // Standard data load
6463                    write!(f, " FROM {from_obj}{stage_params}")?;
6464                    if let Some(from_obj_alias) = from_obj_alias {
6465                        write!(f, " AS {from_obj_alias}")?;
6466                    }
6467                } else if let Some(from_query) = from_query {
6468                    // Data unload from query
6469                    write!(f, " FROM ({from_query})")?;
6470                }
6471
6472                if let Some(files) = files {
6473                    write!(f, " FILES = ('{}')", display_separated(files, "', '"))?;
6474                }
6475                if let Some(pattern) = pattern {
6476                    write!(f, " PATTERN = '{pattern}'")?;
6477                }
6478                if let Some(partition) = partition {
6479                    write!(f, " PARTITION BY {partition}")?;
6480                }
6481                if !file_format.options.is_empty() {
6482                    write!(f, " FILE_FORMAT=({file_format})")?;
6483                }
6484                if !copy_options.options.is_empty() {
6485                    match kind {
6486                        CopyIntoSnowflakeKind::Table => {
6487                            write!(f, " COPY_OPTIONS=({copy_options})")?
6488                        }
6489                        CopyIntoSnowflakeKind::Location => write!(f, " {copy_options}")?,
6490                    }
6491                }
6492                if let Some(validation_mode) = validation_mode {
6493                    write!(f, " VALIDATION_MODE = {validation_mode}")?;
6494                }
6495                Ok(())
6496            }
6497            Statement::CreateType {
6498                name,
6499                representation,
6500            } => {
6501                write!(f, "CREATE TYPE {name} AS {representation}")
6502            }
6503            Statement::Pragma { name, value, is_eq } => {
6504                write!(f, "PRAGMA {name}")?;
6505                if value.is_some() {
6506                    let val = value.as_ref().unwrap();
6507                    if *is_eq {
6508                        write!(f, " = {val}")?;
6509                    } else {
6510                        write!(f, "({val})")?;
6511                    }
6512                }
6513                Ok(())
6514            }
6515            Statement::LockTables { tables } => {
6516                write!(f, "LOCK TABLES {}", display_comma_separated(tables))
6517            }
6518            Statement::UnlockTables => {
6519                write!(f, "UNLOCK TABLES")
6520            }
6521            Statement::Unload {
6522                query,
6523                query_text,
6524                to,
6525                auth,
6526                with,
6527                options,
6528            } => {
6529                write!(f, "UNLOAD(")?;
6530                if let Some(query) = query {
6531                    write!(f, "{query}")?;
6532                }
6533                if let Some(query_text) = query_text {
6534                    write!(f, "'{query_text}'")?;
6535                }
6536                write!(f, ") TO {to}")?;
6537                if let Some(auth) = auth {
6538                    write!(f, " IAM_ROLE {auth}")?;
6539                }
6540                if !with.is_empty() {
6541                    write!(f, " WITH ({})", display_comma_separated(with))?;
6542                }
6543                if !options.is_empty() {
6544                    write!(f, " {}", display_separated(options, " "))?;
6545                }
6546                Ok(())
6547            }
6548            Statement::OptimizeTable {
6549                name,
6550                on_cluster,
6551                partition,
6552                include_final,
6553                deduplicate,
6554            } => {
6555                write!(f, "OPTIMIZE TABLE {name}")?;
6556                if let Some(on_cluster) = on_cluster {
6557                    write!(f, " ON CLUSTER {on_cluster}")?;
6558                }
6559                if let Some(partition) = partition {
6560                    write!(f, " {partition}")?;
6561                }
6562                if *include_final {
6563                    write!(f, " FINAL")?;
6564                }
6565                if let Some(deduplicate) = deduplicate {
6566                    write!(f, " {deduplicate}")?;
6567                }
6568                Ok(())
6569            }
6570            Statement::LISTEN { channel } => {
6571                write!(f, "LISTEN {channel}")?;
6572                Ok(())
6573            }
6574            Statement::UNLISTEN { channel } => {
6575                write!(f, "UNLISTEN {channel}")?;
6576                Ok(())
6577            }
6578            Statement::NOTIFY { channel, payload } => {
6579                write!(f, "NOTIFY {channel}")?;
6580                if let Some(payload) = payload {
6581                    write!(f, ", '{payload}'")?;
6582                }
6583                Ok(())
6584            }
6585            Statement::RenameTable(rename_tables) => {
6586                write!(f, "RENAME TABLE {}", display_comma_separated(rename_tables))
6587            }
6588            Statement::RaisError {
6589                message,
6590                severity,
6591                state,
6592                arguments,
6593                options,
6594            } => {
6595                write!(f, "RAISERROR({message}, {severity}, {state}")?;
6596                if !arguments.is_empty() {
6597                    write!(f, ", {}", display_comma_separated(arguments))?;
6598                }
6599                write!(f, ")")?;
6600                if !options.is_empty() {
6601                    write!(f, " WITH {}", display_comma_separated(options))?;
6602                }
6603                Ok(())
6604            }
6605            Statement::Print(s) => write!(f, "{s}"),
6606            Statement::Return(r) => write!(f, "{r}"),
6607            Statement::List(command) => write!(f, "LIST {command}"),
6608            Statement::Remove(command) => write!(f, "REMOVE {command}"),
6609            Statement::ExportData(e) => write!(f, "{e}"),
6610            Statement::CreateUser(s) => write!(f, "{s}"),
6611            Statement::AlterSchema(s) => write!(f, "{s}"),
6612            Statement::Vacuum(s) => write!(f, "{s}"),
6613        }
6614    }
6615}
6616
6617/// Can use to describe options in create sequence or table column type identity
6618/// ```sql
6619/// [ INCREMENT [ BY ] increment ]
6620///     [ MINVALUE minvalue | NO MINVALUE ] [ MAXVALUE maxvalue | NO MAXVALUE ]
6621///     [ START [ WITH ] start ] [ CACHE cache ] [ [ NO ] CYCLE ]
6622/// ```
6623#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6624#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6625#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6626pub enum SequenceOptions {
6627    IncrementBy(Expr, bool),
6628    MinValue(Option<Expr>),
6629    MaxValue(Option<Expr>),
6630    StartWith(Expr, bool),
6631    Cache(Expr),
6632    Cycle(bool),
6633}
6634
6635impl fmt::Display for SequenceOptions {
6636    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6637        match self {
6638            SequenceOptions::IncrementBy(increment, by) => {
6639                write!(
6640                    f,
6641                    " INCREMENT{by} {increment}",
6642                    by = if *by { " BY" } else { "" },
6643                    increment = increment
6644                )
6645            }
6646            SequenceOptions::MinValue(Some(expr)) => {
6647                write!(f, " MINVALUE {expr}")
6648            }
6649            SequenceOptions::MinValue(None) => {
6650                write!(f, " NO MINVALUE")
6651            }
6652            SequenceOptions::MaxValue(Some(expr)) => {
6653                write!(f, " MAXVALUE {expr}")
6654            }
6655            SequenceOptions::MaxValue(None) => {
6656                write!(f, " NO MAXVALUE")
6657            }
6658            SequenceOptions::StartWith(start, with) => {
6659                write!(
6660                    f,
6661                    " START{with} {start}",
6662                    with = if *with { " WITH" } else { "" },
6663                    start = start
6664                )
6665            }
6666            SequenceOptions::Cache(cache) => {
6667                write!(f, " CACHE {}", *cache)
6668            }
6669            SequenceOptions::Cycle(no) => {
6670                write!(f, " {}CYCLE", if *no { "NO " } else { "" })
6671            }
6672        }
6673    }
6674}
6675
6676/// Assignment for a `SET` statement (name [=|TO] value)
6677#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6678#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6679#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6680pub struct SetAssignment {
6681    pub scope: Option<ContextModifier>,
6682    pub name: ObjectName,
6683    pub value: Expr,
6684}
6685
6686impl fmt::Display for SetAssignment {
6687    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6688        write!(
6689            f,
6690            "{}{} = {}",
6691            self.scope.map(|s| format!("{s}")).unwrap_or_default(),
6692            self.name,
6693            self.value
6694        )
6695    }
6696}
6697
6698/// Target of a `TRUNCATE TABLE` command
6699///
6700/// Note this is its own struct because `visit_relation` requires an `ObjectName` (not a `Vec<ObjectName>`)
6701#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6702#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6703#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6704pub struct TruncateTableTarget {
6705    /// name of the table being truncated
6706    #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
6707    pub name: ObjectName,
6708    /// Postgres-specific option
6709    /// [ TRUNCATE TABLE ONLY ]
6710    /// <https://www.postgresql.org/docs/current/sql-truncate.html>
6711    pub only: bool,
6712}
6713
6714impl fmt::Display for TruncateTableTarget {
6715    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6716        if self.only {
6717            write!(f, "ONLY ")?;
6718        };
6719        write!(f, "{}", self.name)
6720    }
6721}
6722
6723/// PostgreSQL identity option for TRUNCATE table
6724/// [ RESTART IDENTITY | CONTINUE IDENTITY ]
6725#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6726#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6727#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6728pub enum TruncateIdentityOption {
6729    Restart,
6730    Continue,
6731}
6732
6733/// Cascade/restrict option for Postgres TRUNCATE table, MySQL GRANT/REVOKE, etc.
6734/// [ CASCADE | RESTRICT ]
6735#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6736#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6737#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6738pub enum CascadeOption {
6739    Cascade,
6740    Restrict,
6741}
6742
6743impl Display for CascadeOption {
6744    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6745        match self {
6746            CascadeOption::Cascade => write!(f, "CASCADE"),
6747            CascadeOption::Restrict => write!(f, "RESTRICT"),
6748        }
6749    }
6750}
6751
6752/// Transaction started with [ TRANSACTION | WORK ]
6753#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6754#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6755#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6756pub enum BeginTransactionKind {
6757    Transaction,
6758    Work,
6759}
6760
6761impl Display for BeginTransactionKind {
6762    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6763        match self {
6764            BeginTransactionKind::Transaction => write!(f, "TRANSACTION"),
6765            BeginTransactionKind::Work => write!(f, "WORK"),
6766        }
6767    }
6768}
6769
6770/// Can use to describe options in  create sequence or table column type identity
6771/// [ MINVALUE minvalue | NO MINVALUE ] [ MAXVALUE maxvalue | NO MAXVALUE ]
6772#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6773#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6774#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6775pub enum MinMaxValue {
6776    // clause is not specified
6777    Empty,
6778    // NO MINVALUE/NO MAXVALUE
6779    None,
6780    // MINVALUE <expr> / MAXVALUE <expr>
6781    Some(Expr),
6782}
6783
6784#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6785#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6786#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6787#[non_exhaustive]
6788pub enum OnInsert {
6789    /// ON DUPLICATE KEY UPDATE (MySQL when the key already exists, then execute an update instead)
6790    DuplicateKeyUpdate(Vec<Assignment>),
6791    /// ON CONFLICT is a PostgreSQL and Sqlite extension
6792    OnConflict(OnConflict),
6793}
6794
6795#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6796#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6797#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6798pub struct InsertAliases {
6799    pub row_alias: ObjectName,
6800    pub col_aliases: Option<Vec<Ident>>,
6801}
6802
6803#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6804#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6805#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6806pub struct OnConflict {
6807    pub conflict_target: Option<ConflictTarget>,
6808    pub action: OnConflictAction,
6809}
6810#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6811#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6812#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6813pub enum ConflictTarget {
6814    Columns(Vec<Ident>),
6815    OnConstraint(ObjectName),
6816}
6817#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6818#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6819#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6820pub enum OnConflictAction {
6821    DoNothing,
6822    DoUpdate(DoUpdate),
6823}
6824
6825#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6826#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6827#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6828pub struct DoUpdate {
6829    /// Column assignments
6830    pub assignments: Vec<Assignment>,
6831    /// WHERE
6832    pub selection: Option<Expr>,
6833}
6834
6835impl fmt::Display for OnInsert {
6836    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6837        match self {
6838            Self::DuplicateKeyUpdate(expr) => write!(
6839                f,
6840                " ON DUPLICATE KEY UPDATE {}",
6841                display_comma_separated(expr)
6842            ),
6843            Self::OnConflict(o) => write!(f, "{o}"),
6844        }
6845    }
6846}
6847impl fmt::Display for OnConflict {
6848    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6849        write!(f, " ON CONFLICT")?;
6850        if let Some(target) = &self.conflict_target {
6851            write!(f, "{target}")?;
6852        }
6853        write!(f, " {}", self.action)
6854    }
6855}
6856impl fmt::Display for ConflictTarget {
6857    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6858        match self {
6859            ConflictTarget::Columns(cols) => write!(f, "({})", display_comma_separated(cols)),
6860            ConflictTarget::OnConstraint(name) => write!(f, " ON CONSTRAINT {name}"),
6861        }
6862    }
6863}
6864impl fmt::Display for OnConflictAction {
6865    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6866        match self {
6867            Self::DoNothing => write!(f, "DO NOTHING"),
6868            Self::DoUpdate(do_update) => {
6869                write!(f, "DO UPDATE")?;
6870                if !do_update.assignments.is_empty() {
6871                    write!(
6872                        f,
6873                        " SET {}",
6874                        display_comma_separated(&do_update.assignments)
6875                    )?;
6876                }
6877                if let Some(selection) = &do_update.selection {
6878                    write!(f, " WHERE {selection}")?;
6879                }
6880                Ok(())
6881            }
6882        }
6883    }
6884}
6885
6886/// Privileges granted in a GRANT statement or revoked in a REVOKE statement.
6887#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6888#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6889#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6890pub enum Privileges {
6891    /// All privileges applicable to the object type
6892    All {
6893        /// Optional keyword from the spec, ignored in practice
6894        with_privileges_keyword: bool,
6895    },
6896    /// Specific privileges (e.g. `SELECT`, `INSERT`)
6897    Actions(Vec<Action>),
6898}
6899
6900impl fmt::Display for Privileges {
6901    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6902        match self {
6903            Privileges::All {
6904                with_privileges_keyword,
6905            } => {
6906                write!(
6907                    f,
6908                    "ALL{}",
6909                    if *with_privileges_keyword {
6910                        " PRIVILEGES"
6911                    } else {
6912                        ""
6913                    }
6914                )
6915            }
6916            Privileges::Actions(actions) => {
6917                write!(f, "{}", display_comma_separated(actions))
6918            }
6919        }
6920    }
6921}
6922
6923/// Specific direction for FETCH statement
6924#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6925#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6926#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6927pub enum FetchDirection {
6928    Count { limit: Value },
6929    Next,
6930    Prior,
6931    First,
6932    Last,
6933    Absolute { limit: Value },
6934    Relative { limit: Value },
6935    All,
6936    // FORWARD
6937    // FORWARD count
6938    Forward { limit: Option<Value> },
6939    ForwardAll,
6940    // BACKWARD
6941    // BACKWARD count
6942    Backward { limit: Option<Value> },
6943    BackwardAll,
6944}
6945
6946impl fmt::Display for FetchDirection {
6947    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6948        match self {
6949            FetchDirection::Count { limit } => f.write_str(&limit.to_string())?,
6950            FetchDirection::Next => f.write_str("NEXT")?,
6951            FetchDirection::Prior => f.write_str("PRIOR")?,
6952            FetchDirection::First => f.write_str("FIRST")?,
6953            FetchDirection::Last => f.write_str("LAST")?,
6954            FetchDirection::Absolute { limit } => {
6955                f.write_str("ABSOLUTE ")?;
6956                f.write_str(&limit.to_string())?;
6957            }
6958            FetchDirection::Relative { limit } => {
6959                f.write_str("RELATIVE ")?;
6960                f.write_str(&limit.to_string())?;
6961            }
6962            FetchDirection::All => f.write_str("ALL")?,
6963            FetchDirection::Forward { limit } => {
6964                f.write_str("FORWARD")?;
6965
6966                if let Some(l) = limit {
6967                    f.write_str(" ")?;
6968                    f.write_str(&l.to_string())?;
6969                }
6970            }
6971            FetchDirection::ForwardAll => f.write_str("FORWARD ALL")?,
6972            FetchDirection::Backward { limit } => {
6973                f.write_str("BACKWARD")?;
6974
6975                if let Some(l) = limit {
6976                    f.write_str(" ")?;
6977                    f.write_str(&l.to_string())?;
6978                }
6979            }
6980            FetchDirection::BackwardAll => f.write_str("BACKWARD ALL")?,
6981        };
6982
6983        Ok(())
6984    }
6985}
6986
6987/// The "position" for a FETCH statement.
6988///
6989/// [MsSql](https://learn.microsoft.com/en-us/sql/t-sql/language-elements/fetch-transact-sql)
6990#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6991#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6992#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6993pub enum FetchPosition {
6994    From,
6995    In,
6996}
6997
6998impl fmt::Display for FetchPosition {
6999    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7000        match self {
7001            FetchPosition::From => f.write_str("FROM")?,
7002            FetchPosition::In => f.write_str("IN")?,
7003        };
7004
7005        Ok(())
7006    }
7007}
7008
7009/// A privilege on a database object (table, sequence, etc.).
7010#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7011#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7012#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7013pub enum Action {
7014    AddSearchOptimization,
7015    Apply {
7016        apply_type: ActionApplyType,
7017    },
7018    ApplyBudget,
7019    AttachListing,
7020    AttachPolicy,
7021    Audit,
7022    BindServiceEndpoint,
7023    Connect,
7024    Create {
7025        obj_type: Option<ActionCreateObjectType>,
7026    },
7027    DatabaseRole {
7028        role: ObjectName,
7029    },
7030    Delete,
7031    Drop,
7032    EvolveSchema,
7033    Exec {
7034        obj_type: Option<ActionExecuteObjectType>,
7035    },
7036    Execute {
7037        obj_type: Option<ActionExecuteObjectType>,
7038    },
7039    Failover,
7040    ImportedPrivileges,
7041    ImportShare,
7042    Insert {
7043        columns: Option<Vec<Ident>>,
7044    },
7045    Manage {
7046        manage_type: ActionManageType,
7047    },
7048    ManageReleases,
7049    ManageVersions,
7050    Modify {
7051        modify_type: Option<ActionModifyType>,
7052    },
7053    Monitor {
7054        monitor_type: Option<ActionMonitorType>,
7055    },
7056    Operate,
7057    OverrideShareRestrictions,
7058    Ownership,
7059    PurchaseDataExchangeListing,
7060    Read,
7061    ReadSession,
7062    References {
7063        columns: Option<Vec<Ident>>,
7064    },
7065    Replicate,
7066    ResolveAll,
7067    Role {
7068        role: ObjectName,
7069    },
7070    Select {
7071        columns: Option<Vec<Ident>>,
7072    },
7073    Temporary,
7074    Trigger,
7075    Truncate,
7076    Update {
7077        columns: Option<Vec<Ident>>,
7078    },
7079    Usage,
7080}
7081
7082impl fmt::Display for Action {
7083    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7084        match self {
7085            Action::AddSearchOptimization => f.write_str("ADD SEARCH OPTIMIZATION")?,
7086            Action::Apply { apply_type } => write!(f, "APPLY {apply_type}")?,
7087            Action::ApplyBudget => f.write_str("APPLYBUDGET")?,
7088            Action::AttachListing => f.write_str("ATTACH LISTING")?,
7089            Action::AttachPolicy => f.write_str("ATTACH POLICY")?,
7090            Action::Audit => f.write_str("AUDIT")?,
7091            Action::BindServiceEndpoint => f.write_str("BIND SERVICE ENDPOINT")?,
7092            Action::Connect => f.write_str("CONNECT")?,
7093            Action::Create { obj_type } => {
7094                f.write_str("CREATE")?;
7095                if let Some(obj_type) = obj_type {
7096                    write!(f, " {obj_type}")?
7097                }
7098            }
7099            Action::DatabaseRole { role } => write!(f, "DATABASE ROLE {role}")?,
7100            Action::Delete => f.write_str("DELETE")?,
7101            Action::Drop => f.write_str("DROP")?,
7102            Action::EvolveSchema => f.write_str("EVOLVE SCHEMA")?,
7103            Action::Exec { obj_type } => {
7104                f.write_str("EXEC")?;
7105                if let Some(obj_type) = obj_type {
7106                    write!(f, " {obj_type}")?
7107                }
7108            }
7109            Action::Execute { obj_type } => {
7110                f.write_str("EXECUTE")?;
7111                if let Some(obj_type) = obj_type {
7112                    write!(f, " {obj_type}")?
7113                }
7114            }
7115            Action::Failover => f.write_str("FAILOVER")?,
7116            Action::ImportedPrivileges => f.write_str("IMPORTED PRIVILEGES")?,
7117            Action::ImportShare => f.write_str("IMPORT SHARE")?,
7118            Action::Insert { .. } => f.write_str("INSERT")?,
7119            Action::Manage { manage_type } => write!(f, "MANAGE {manage_type}")?,
7120            Action::ManageReleases => f.write_str("MANAGE RELEASES")?,
7121            Action::ManageVersions => f.write_str("MANAGE VERSIONS")?,
7122            Action::Modify { modify_type } => {
7123                write!(f, "MODIFY")?;
7124                if let Some(modify_type) = modify_type {
7125                    write!(f, " {modify_type}")?;
7126                }
7127            }
7128            Action::Monitor { monitor_type } => {
7129                write!(f, "MONITOR")?;
7130                if let Some(monitor_type) = monitor_type {
7131                    write!(f, " {monitor_type}")?
7132                }
7133            }
7134            Action::Operate => f.write_str("OPERATE")?,
7135            Action::OverrideShareRestrictions => f.write_str("OVERRIDE SHARE RESTRICTIONS")?,
7136            Action::Ownership => f.write_str("OWNERSHIP")?,
7137            Action::PurchaseDataExchangeListing => f.write_str("PURCHASE DATA EXCHANGE LISTING")?,
7138            Action::Read => f.write_str("READ")?,
7139            Action::ReadSession => f.write_str("READ SESSION")?,
7140            Action::References { .. } => f.write_str("REFERENCES")?,
7141            Action::Replicate => f.write_str("REPLICATE")?,
7142            Action::ResolveAll => f.write_str("RESOLVE ALL")?,
7143            Action::Role { role } => write!(f, "ROLE {role}")?,
7144            Action::Select { .. } => f.write_str("SELECT")?,
7145            Action::Temporary => f.write_str("TEMPORARY")?,
7146            Action::Trigger => f.write_str("TRIGGER")?,
7147            Action::Truncate => f.write_str("TRUNCATE")?,
7148            Action::Update { .. } => f.write_str("UPDATE")?,
7149            Action::Usage => f.write_str("USAGE")?,
7150        };
7151        match self {
7152            Action::Insert { columns }
7153            | Action::References { columns }
7154            | Action::Select { columns }
7155            | Action::Update { columns } => {
7156                if let Some(columns) = columns {
7157                    write!(f, " ({})", display_comma_separated(columns))?;
7158                }
7159            }
7160            _ => (),
7161        };
7162        Ok(())
7163    }
7164}
7165
7166#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7167#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7168#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7169/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
7170/// under `globalPrivileges` in the `CREATE` privilege.
7171pub enum ActionCreateObjectType {
7172    Account,
7173    Application,
7174    ApplicationPackage,
7175    ComputePool,
7176    DataExchangeListing,
7177    Database,
7178    ExternalVolume,
7179    FailoverGroup,
7180    Integration,
7181    NetworkPolicy,
7182    OrganiationListing,
7183    ReplicationGroup,
7184    Role,
7185    Schema,
7186    Share,
7187    User,
7188    Warehouse,
7189}
7190
7191impl fmt::Display for ActionCreateObjectType {
7192    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7193        match self {
7194            ActionCreateObjectType::Account => write!(f, "ACCOUNT"),
7195            ActionCreateObjectType::Application => write!(f, "APPLICATION"),
7196            ActionCreateObjectType::ApplicationPackage => write!(f, "APPLICATION PACKAGE"),
7197            ActionCreateObjectType::ComputePool => write!(f, "COMPUTE POOL"),
7198            ActionCreateObjectType::DataExchangeListing => write!(f, "DATA EXCHANGE LISTING"),
7199            ActionCreateObjectType::Database => write!(f, "DATABASE"),
7200            ActionCreateObjectType::ExternalVolume => write!(f, "EXTERNAL VOLUME"),
7201            ActionCreateObjectType::FailoverGroup => write!(f, "FAILOVER GROUP"),
7202            ActionCreateObjectType::Integration => write!(f, "INTEGRATION"),
7203            ActionCreateObjectType::NetworkPolicy => write!(f, "NETWORK POLICY"),
7204            ActionCreateObjectType::OrganiationListing => write!(f, "ORGANIZATION LISTING"),
7205            ActionCreateObjectType::ReplicationGroup => write!(f, "REPLICATION GROUP"),
7206            ActionCreateObjectType::Role => write!(f, "ROLE"),
7207            ActionCreateObjectType::Schema => write!(f, "SCHEMA"),
7208            ActionCreateObjectType::Share => write!(f, "SHARE"),
7209            ActionCreateObjectType::User => write!(f, "USER"),
7210            ActionCreateObjectType::Warehouse => write!(f, "WAREHOUSE"),
7211        }
7212    }
7213}
7214
7215#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7216#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7217#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7218/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
7219/// under `globalPrivileges` in the `APPLY` privilege.
7220pub enum ActionApplyType {
7221    AggregationPolicy,
7222    AuthenticationPolicy,
7223    JoinPolicy,
7224    MaskingPolicy,
7225    PackagesPolicy,
7226    PasswordPolicy,
7227    ProjectionPolicy,
7228    RowAccessPolicy,
7229    SessionPolicy,
7230    Tag,
7231}
7232
7233impl fmt::Display for ActionApplyType {
7234    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7235        match self {
7236            ActionApplyType::AggregationPolicy => write!(f, "AGGREGATION POLICY"),
7237            ActionApplyType::AuthenticationPolicy => write!(f, "AUTHENTICATION POLICY"),
7238            ActionApplyType::JoinPolicy => write!(f, "JOIN POLICY"),
7239            ActionApplyType::MaskingPolicy => write!(f, "MASKING POLICY"),
7240            ActionApplyType::PackagesPolicy => write!(f, "PACKAGES POLICY"),
7241            ActionApplyType::PasswordPolicy => write!(f, "PASSWORD POLICY"),
7242            ActionApplyType::ProjectionPolicy => write!(f, "PROJECTION POLICY"),
7243            ActionApplyType::RowAccessPolicy => write!(f, "ROW ACCESS POLICY"),
7244            ActionApplyType::SessionPolicy => write!(f, "SESSION POLICY"),
7245            ActionApplyType::Tag => write!(f, "TAG"),
7246        }
7247    }
7248}
7249
7250#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7251#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7252#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7253/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
7254/// under `globalPrivileges` in the `EXECUTE` privilege.
7255pub enum ActionExecuteObjectType {
7256    Alert,
7257    DataMetricFunction,
7258    ManagedAlert,
7259    ManagedTask,
7260    Task,
7261}
7262
7263impl fmt::Display for ActionExecuteObjectType {
7264    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7265        match self {
7266            ActionExecuteObjectType::Alert => write!(f, "ALERT"),
7267            ActionExecuteObjectType::DataMetricFunction => write!(f, "DATA METRIC FUNCTION"),
7268            ActionExecuteObjectType::ManagedAlert => write!(f, "MANAGED ALERT"),
7269            ActionExecuteObjectType::ManagedTask => write!(f, "MANAGED TASK"),
7270            ActionExecuteObjectType::Task => write!(f, "TASK"),
7271        }
7272    }
7273}
7274
7275#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7276#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7277#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7278/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
7279/// under `globalPrivileges` in the `MANAGE` privilege.
7280pub enum ActionManageType {
7281    AccountSupportCases,
7282    EventSharing,
7283    Grants,
7284    ListingAutoFulfillment,
7285    OrganizationSupportCases,
7286    UserSupportCases,
7287    Warehouses,
7288}
7289
7290impl fmt::Display for ActionManageType {
7291    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7292        match self {
7293            ActionManageType::AccountSupportCases => write!(f, "ACCOUNT SUPPORT CASES"),
7294            ActionManageType::EventSharing => write!(f, "EVENT SHARING"),
7295            ActionManageType::Grants => write!(f, "GRANTS"),
7296            ActionManageType::ListingAutoFulfillment => write!(f, "LISTING AUTO FULFILLMENT"),
7297            ActionManageType::OrganizationSupportCases => write!(f, "ORGANIZATION SUPPORT CASES"),
7298            ActionManageType::UserSupportCases => write!(f, "USER SUPPORT CASES"),
7299            ActionManageType::Warehouses => write!(f, "WAREHOUSES"),
7300        }
7301    }
7302}
7303
7304#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7305#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7306#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7307/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
7308/// under `globalPrivileges` in the `MODIFY` privilege.
7309pub enum ActionModifyType {
7310    LogLevel,
7311    TraceLevel,
7312    SessionLogLevel,
7313    SessionTraceLevel,
7314}
7315
7316impl fmt::Display for ActionModifyType {
7317    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7318        match self {
7319            ActionModifyType::LogLevel => write!(f, "LOG LEVEL"),
7320            ActionModifyType::TraceLevel => write!(f, "TRACE LEVEL"),
7321            ActionModifyType::SessionLogLevel => write!(f, "SESSION LOG LEVEL"),
7322            ActionModifyType::SessionTraceLevel => write!(f, "SESSION TRACE LEVEL"),
7323        }
7324    }
7325}
7326
7327#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7328#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7329#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7330/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
7331/// under `globalPrivileges` in the `MONITOR` privilege.
7332pub enum ActionMonitorType {
7333    Execution,
7334    Security,
7335    Usage,
7336}
7337
7338impl fmt::Display for ActionMonitorType {
7339    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7340        match self {
7341            ActionMonitorType::Execution => write!(f, "EXECUTION"),
7342            ActionMonitorType::Security => write!(f, "SECURITY"),
7343            ActionMonitorType::Usage => write!(f, "USAGE"),
7344        }
7345    }
7346}
7347
7348/// The principal that receives the privileges
7349#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7350#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7351#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7352pub struct Grantee {
7353    pub grantee_type: GranteesType,
7354    pub name: Option<GranteeName>,
7355}
7356
7357impl fmt::Display for Grantee {
7358    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7359        match self.grantee_type {
7360            GranteesType::Role => {
7361                write!(f, "ROLE ")?;
7362            }
7363            GranteesType::Share => {
7364                write!(f, "SHARE ")?;
7365            }
7366            GranteesType::User => {
7367                write!(f, "USER ")?;
7368            }
7369            GranteesType::Group => {
7370                write!(f, "GROUP ")?;
7371            }
7372            GranteesType::Public => {
7373                write!(f, "PUBLIC ")?;
7374            }
7375            GranteesType::DatabaseRole => {
7376                write!(f, "DATABASE ROLE ")?;
7377            }
7378            GranteesType::Application => {
7379                write!(f, "APPLICATION ")?;
7380            }
7381            GranteesType::ApplicationRole => {
7382                write!(f, "APPLICATION ROLE ")?;
7383            }
7384            GranteesType::None => (),
7385        }
7386        if let Some(ref name) = self.name {
7387            name.fmt(f)?;
7388        }
7389        Ok(())
7390    }
7391}
7392
7393#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7394#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7395#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7396pub enum GranteesType {
7397    Role,
7398    Share,
7399    User,
7400    Group,
7401    Public,
7402    DatabaseRole,
7403    Application,
7404    ApplicationRole,
7405    None,
7406}
7407
7408/// Users/roles designated in a GRANT/REVOKE
7409#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7410#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7411#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7412pub enum GranteeName {
7413    /// A bare identifier
7414    ObjectName(ObjectName),
7415    /// A MySQL user/host pair such as 'root'@'%'
7416    UserHost { user: Ident, host: Ident },
7417}
7418
7419impl fmt::Display for GranteeName {
7420    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7421        match self {
7422            GranteeName::ObjectName(name) => name.fmt(f),
7423            GranteeName::UserHost { user, host } => {
7424                write!(f, "{user}@{host}")
7425            }
7426        }
7427    }
7428}
7429
7430/// Objects on which privileges are granted in a GRANT statement.
7431#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7432#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7433#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7434pub enum GrantObjects {
7435    /// Grant privileges on `ALL SEQUENCES IN SCHEMA <schema_name> [, ...]`
7436    AllSequencesInSchema { schemas: Vec<ObjectName> },
7437    /// Grant privileges on `ALL TABLES IN SCHEMA <schema_name> [, ...]`
7438    AllTablesInSchema { schemas: Vec<ObjectName> },
7439    /// Grant privileges on `ALL VIEWS IN SCHEMA <schema_name> [, ...]`
7440    AllViewsInSchema { schemas: Vec<ObjectName> },
7441    /// Grant privileges on `ALL MATERIALIZED VIEWS IN SCHEMA <schema_name> [, ...]`
7442    AllMaterializedViewsInSchema { schemas: Vec<ObjectName> },
7443    /// Grant privileges on `ALL EXTERNAL TABLES IN SCHEMA <schema_name> [, ...]`
7444    AllExternalTablesInSchema { schemas: Vec<ObjectName> },
7445    /// Grant privileges on `ALL FUNCTIONS IN SCHEMA <schema_name> [, ...]`
7446    AllFunctionsInSchema { schemas: Vec<ObjectName> },
7447    /// Grant privileges on `FUTURE SCHEMAS IN DATABASE <database_name> [, ...]`
7448    FutureSchemasInDatabase { databases: Vec<ObjectName> },
7449    /// Grant privileges on `FUTURE TABLES IN SCHEMA <schema_name> [, ...]`
7450    FutureTablesInSchema { schemas: Vec<ObjectName> },
7451    /// Grant privileges on `FUTURE VIEWS IN SCHEMA <schema_name> [, ...]`
7452    FutureViewsInSchema { schemas: Vec<ObjectName> },
7453    /// Grant privileges on `FUTURE EXTERNAL TABLES IN SCHEMA <schema_name> [, ...]`
7454    FutureExternalTablesInSchema { schemas: Vec<ObjectName> },
7455    /// Grant privileges on `FUTURE MATERIALIZED VIEWS IN SCHEMA <schema_name> [, ...]`
7456    FutureMaterializedViewsInSchema { schemas: Vec<ObjectName> },
7457    /// Grant privileges on `FUTURE SEQUENCES IN SCHEMA <schema_name> [, ...]`
7458    FutureSequencesInSchema { schemas: Vec<ObjectName> },
7459    /// Grant privileges on specific databases
7460    Databases(Vec<ObjectName>),
7461    /// Grant privileges on specific schemas
7462    Schemas(Vec<ObjectName>),
7463    /// Grant privileges on specific sequences
7464    Sequences(Vec<ObjectName>),
7465    /// Grant privileges on specific tables
7466    Tables(Vec<ObjectName>),
7467    /// Grant privileges on specific views
7468    Views(Vec<ObjectName>),
7469    /// Grant privileges on specific warehouses
7470    Warehouses(Vec<ObjectName>),
7471    /// Grant privileges on specific integrations
7472    Integrations(Vec<ObjectName>),
7473    /// Grant privileges on resource monitors
7474    ResourceMonitors(Vec<ObjectName>),
7475    /// Grant privileges on users
7476    Users(Vec<ObjectName>),
7477    /// Grant privileges on compute pools
7478    ComputePools(Vec<ObjectName>),
7479    /// Grant privileges on connections
7480    Connections(Vec<ObjectName>),
7481    /// Grant privileges on failover groups
7482    FailoverGroup(Vec<ObjectName>),
7483    /// Grant privileges on replication group
7484    ReplicationGroup(Vec<ObjectName>),
7485    /// Grant privileges on external volumes
7486    ExternalVolumes(Vec<ObjectName>),
7487    /// Grant privileges on a procedure. In dialects that
7488    /// support overloading, the argument types must be specified.
7489    ///
7490    /// For example:
7491    /// `GRANT USAGE ON PROCEDURE foo(varchar) TO ROLE role1`
7492    Procedure {
7493        name: ObjectName,
7494        arg_types: Vec<DataType>,
7495    },
7496
7497    /// Grant privileges on a function. In dialects that
7498    /// support overloading, the argument types must be specified.
7499    ///
7500    /// For example:
7501    /// `GRANT USAGE ON FUNCTION foo(varchar) TO ROLE role1`
7502    Function {
7503        name: ObjectName,
7504        arg_types: Vec<DataType>,
7505    },
7506}
7507
7508impl fmt::Display for GrantObjects {
7509    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7510        match self {
7511            GrantObjects::Sequences(sequences) => {
7512                write!(f, "SEQUENCE {}", display_comma_separated(sequences))
7513            }
7514            GrantObjects::Databases(databases) => {
7515                write!(f, "DATABASE {}", display_comma_separated(databases))
7516            }
7517            GrantObjects::Schemas(schemas) => {
7518                write!(f, "SCHEMA {}", display_comma_separated(schemas))
7519            }
7520            GrantObjects::Tables(tables) => {
7521                write!(f, "{}", display_comma_separated(tables))
7522            }
7523            GrantObjects::Views(views) => {
7524                write!(f, "VIEW {}", display_comma_separated(views))
7525            }
7526            GrantObjects::Warehouses(warehouses) => {
7527                write!(f, "WAREHOUSE {}", display_comma_separated(warehouses))
7528            }
7529            GrantObjects::Integrations(integrations) => {
7530                write!(f, "INTEGRATION {}", display_comma_separated(integrations))
7531            }
7532            GrantObjects::AllSequencesInSchema { schemas } => {
7533                write!(
7534                    f,
7535                    "ALL SEQUENCES IN SCHEMA {}",
7536                    display_comma_separated(schemas)
7537                )
7538            }
7539            GrantObjects::AllTablesInSchema { schemas } => {
7540                write!(
7541                    f,
7542                    "ALL TABLES IN SCHEMA {}",
7543                    display_comma_separated(schemas)
7544                )
7545            }
7546            GrantObjects::AllExternalTablesInSchema { schemas } => {
7547                write!(
7548                    f,
7549                    "ALL EXTERNAL TABLES IN SCHEMA {}",
7550                    display_comma_separated(schemas)
7551                )
7552            }
7553            GrantObjects::AllViewsInSchema { schemas } => {
7554                write!(
7555                    f,
7556                    "ALL VIEWS IN SCHEMA {}",
7557                    display_comma_separated(schemas)
7558                )
7559            }
7560            GrantObjects::AllMaterializedViewsInSchema { schemas } => {
7561                write!(
7562                    f,
7563                    "ALL MATERIALIZED VIEWS IN SCHEMA {}",
7564                    display_comma_separated(schemas)
7565                )
7566            }
7567            GrantObjects::AllFunctionsInSchema { schemas } => {
7568                write!(
7569                    f,
7570                    "ALL FUNCTIONS IN SCHEMA {}",
7571                    display_comma_separated(schemas)
7572                )
7573            }
7574            GrantObjects::FutureSchemasInDatabase { databases } => {
7575                write!(
7576                    f,
7577                    "FUTURE SCHEMAS IN DATABASE {}",
7578                    display_comma_separated(databases)
7579                )
7580            }
7581            GrantObjects::FutureTablesInSchema { schemas } => {
7582                write!(
7583                    f,
7584                    "FUTURE TABLES IN SCHEMA {}",
7585                    display_comma_separated(schemas)
7586                )
7587            }
7588            GrantObjects::FutureExternalTablesInSchema { schemas } => {
7589                write!(
7590                    f,
7591                    "FUTURE EXTERNAL TABLES IN SCHEMA {}",
7592                    display_comma_separated(schemas)
7593                )
7594            }
7595            GrantObjects::FutureViewsInSchema { schemas } => {
7596                write!(
7597                    f,
7598                    "FUTURE VIEWS IN SCHEMA {}",
7599                    display_comma_separated(schemas)
7600                )
7601            }
7602            GrantObjects::FutureMaterializedViewsInSchema { schemas } => {
7603                write!(
7604                    f,
7605                    "FUTURE MATERIALIZED VIEWS IN SCHEMA {}",
7606                    display_comma_separated(schemas)
7607                )
7608            }
7609            GrantObjects::FutureSequencesInSchema { schemas } => {
7610                write!(
7611                    f,
7612                    "FUTURE SEQUENCES IN SCHEMA {}",
7613                    display_comma_separated(schemas)
7614                )
7615            }
7616            GrantObjects::ResourceMonitors(objects) => {
7617                write!(f, "RESOURCE MONITOR {}", display_comma_separated(objects))
7618            }
7619            GrantObjects::Users(objects) => {
7620                write!(f, "USER {}", display_comma_separated(objects))
7621            }
7622            GrantObjects::ComputePools(objects) => {
7623                write!(f, "COMPUTE POOL {}", display_comma_separated(objects))
7624            }
7625            GrantObjects::Connections(objects) => {
7626                write!(f, "CONNECTION {}", display_comma_separated(objects))
7627            }
7628            GrantObjects::FailoverGroup(objects) => {
7629                write!(f, "FAILOVER GROUP {}", display_comma_separated(objects))
7630            }
7631            GrantObjects::ReplicationGroup(objects) => {
7632                write!(f, "REPLICATION GROUP {}", display_comma_separated(objects))
7633            }
7634            GrantObjects::ExternalVolumes(objects) => {
7635                write!(f, "EXTERNAL VOLUME {}", display_comma_separated(objects))
7636            }
7637            GrantObjects::Procedure { name, arg_types } => {
7638                write!(f, "PROCEDURE {name}")?;
7639                if !arg_types.is_empty() {
7640                    write!(f, "({})", display_comma_separated(arg_types))?;
7641                }
7642                Ok(())
7643            }
7644            GrantObjects::Function { name, arg_types } => {
7645                write!(f, "FUNCTION {name}")?;
7646                if !arg_types.is_empty() {
7647                    write!(f, "({})", display_comma_separated(arg_types))?;
7648                }
7649                Ok(())
7650            }
7651        }
7652    }
7653}
7654
7655/// A `DENY` statement
7656///
7657/// [MsSql](https://learn.microsoft.com/en-us/sql/t-sql/statements/deny-transact-sql)
7658#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7659#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7660#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7661pub struct DenyStatement {
7662    pub privileges: Privileges,
7663    pub objects: GrantObjects,
7664    pub grantees: Vec<Grantee>,
7665    pub granted_by: Option<Ident>,
7666    pub cascade: Option<CascadeOption>,
7667}
7668
7669impl fmt::Display for DenyStatement {
7670    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7671        write!(f, "DENY {}", self.privileges)?;
7672        write!(f, " ON {}", self.objects)?;
7673        if !self.grantees.is_empty() {
7674            write!(f, " TO {}", display_comma_separated(&self.grantees))?;
7675        }
7676        if let Some(cascade) = &self.cascade {
7677            write!(f, " {cascade}")?;
7678        }
7679        if let Some(granted_by) = &self.granted_by {
7680            write!(f, " AS {granted_by}")?;
7681        }
7682        Ok(())
7683    }
7684}
7685
7686/// SQL assignment `foo = expr` as used in SQLUpdate
7687#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7688#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7689#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7690pub struct Assignment {
7691    pub target: AssignmentTarget,
7692    pub value: Expr,
7693}
7694
7695impl fmt::Display for Assignment {
7696    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7697        write!(f, "{} = {}", self.target, self.value)
7698    }
7699}
7700
7701/// Left-hand side of an assignment in an UPDATE statement,
7702/// e.g. `foo` in `foo = 5` (ColumnName assignment) or
7703/// `(a, b)` in `(a, b) = (1, 2)` (Tuple assignment).
7704#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7705#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7706#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7707pub enum AssignmentTarget {
7708    /// A single column
7709    ColumnName(ObjectName),
7710    /// A tuple of columns
7711    Tuple(Vec<ObjectName>),
7712}
7713
7714impl fmt::Display for AssignmentTarget {
7715    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7716        match self {
7717            AssignmentTarget::ColumnName(column) => write!(f, "{column}"),
7718            AssignmentTarget::Tuple(columns) => write!(f, "({})", display_comma_separated(columns)),
7719        }
7720    }
7721}
7722
7723#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7724#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7725#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7726pub enum FunctionArgExpr {
7727    Expr(Expr),
7728    /// Qualified wildcard, e.g. `alias.*` or `schema.table.*`.
7729    QualifiedWildcard(ObjectName),
7730    /// An unqualified `*`
7731    Wildcard,
7732    /// A table reference, e.g. `TABLE table_name` in function arguments
7733    TableRef(ObjectName),
7734}
7735
7736impl From<Expr> for FunctionArgExpr {
7737    fn from(wildcard_expr: Expr) -> Self {
7738        match wildcard_expr {
7739            Expr::QualifiedWildcard(prefix, _) => Self::QualifiedWildcard(prefix),
7740            Expr::Wildcard(_) => Self::Wildcard,
7741            expr => Self::Expr(expr),
7742        }
7743    }
7744}
7745
7746impl fmt::Display for FunctionArgExpr {
7747    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7748        match self {
7749            FunctionArgExpr::Expr(expr) => write!(f, "{expr}"),
7750            FunctionArgExpr::QualifiedWildcard(prefix) => write!(f, "{prefix}.*"),
7751            FunctionArgExpr::Wildcard => f.write_str("*"),
7752            FunctionArgExpr::TableRef(name) => write!(f, "TABLE {name}"),
7753        }
7754    }
7755}
7756
7757#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7758#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7759#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7760/// Operator used to separate function arguments
7761pub enum FunctionArgOperator {
7762    /// function(arg1 = value1)
7763    Equals,
7764    /// function(arg1 => value1)
7765    RightArrow,
7766    /// function(arg1 := value1)
7767    Assignment,
7768    /// function(arg1 : value1)
7769    Colon,
7770    /// function(arg1 VALUE value1)
7771    Value,
7772}
7773
7774impl fmt::Display for FunctionArgOperator {
7775    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7776        match self {
7777            FunctionArgOperator::Equals => f.write_str("="),
7778            FunctionArgOperator::RightArrow => f.write_str("=>"),
7779            FunctionArgOperator::Assignment => f.write_str(":="),
7780            FunctionArgOperator::Colon => f.write_str(":"),
7781            FunctionArgOperator::Value => f.write_str("VALUE"),
7782        }
7783    }
7784}
7785
7786#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7787#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7788#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7789pub enum FunctionArg {
7790    /// `name` is identifier
7791    ///
7792    /// Enabled when `Dialect::supports_named_fn_args_with_expr_name` returns 'false'
7793    Named {
7794        name: Ident,
7795        arg: FunctionArgExpr,
7796        operator: FunctionArgOperator,
7797    },
7798    /// `name` is arbitrary expression
7799    ///
7800    /// Enabled when `Dialect::supports_named_fn_args_with_expr_name` returns 'true'
7801    ExprNamed {
7802        name: Expr,
7803        arg: FunctionArgExpr,
7804        operator: FunctionArgOperator,
7805    },
7806    Unnamed(FunctionArgExpr),
7807}
7808
7809impl fmt::Display for FunctionArg {
7810    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7811        match self {
7812            FunctionArg::Named {
7813                name,
7814                arg,
7815                operator,
7816            } => write!(f, "{name} {operator} {arg}"),
7817            FunctionArg::ExprNamed {
7818                name,
7819                arg,
7820                operator,
7821            } => write!(f, "{name} {operator} {arg}"),
7822            FunctionArg::Unnamed(unnamed_arg) => write!(f, "{unnamed_arg}"),
7823        }
7824    }
7825}
7826
7827#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7828#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7829#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7830pub enum CloseCursor {
7831    All,
7832    Specific { name: Ident },
7833}
7834
7835impl fmt::Display for CloseCursor {
7836    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7837        match self {
7838            CloseCursor::All => write!(f, "ALL"),
7839            CloseCursor::Specific { name } => write!(f, "{name}"),
7840        }
7841    }
7842}
7843
7844/// A Drop Domain statement
7845#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7846#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7847#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7848pub struct DropDomain {
7849    /// Whether to drop the domain if it exists
7850    pub if_exists: bool,
7851    /// The name of the domain to drop
7852    pub name: ObjectName,
7853    /// The behavior to apply when dropping the domain
7854    pub drop_behavior: Option<DropBehavior>,
7855}
7856
7857/// A constant of form `<data_type> 'value'`.
7858/// This can represent ANSI SQL `DATE`, `TIME`, and `TIMESTAMP` literals (such as `DATE '2020-01-01'`),
7859/// as well as constants of other types (a non-standard PostgreSQL extension).
7860#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7861#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7862#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7863pub struct TypedString {
7864    pub data_type: DataType,
7865    /// The value of the constant.
7866    /// Hint: you can unwrap the string value using `value.into_string()`.
7867    pub value: ValueWithSpan,
7868    /// Flags whether this TypedString uses the [ODBC syntax].
7869    ///
7870    /// Example:
7871    /// ```sql
7872    /// -- An ODBC date literal:
7873    /// SELECT {d '2025-07-16'}
7874    /// -- This is equivalent to the standard ANSI SQL literal:
7875    /// SELECT DATE '2025-07-16'
7876    ///
7877    /// [ODBC syntax]: https://learn.microsoft.com/en-us/sql/odbc/reference/develop-app/date-time-and-timestamp-literals?view=sql-server-2017
7878    pub uses_odbc_syntax: bool,
7879}
7880
7881impl fmt::Display for TypedString {
7882    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7883        let data_type = &self.data_type;
7884        let value = &self.value;
7885        match self.uses_odbc_syntax {
7886            false => {
7887                write!(f, "{data_type}")?;
7888                write!(f, " {value}")
7889            }
7890            true => {
7891                let prefix = match data_type {
7892                    DataType::Date => "d",
7893                    DataType::Time(..) => "t",
7894                    DataType::Timestamp(..) => "ts",
7895                    _ => "?",
7896                };
7897                write!(f, "{{{prefix} {value}}}")
7898            }
7899        }
7900    }
7901}
7902
7903/// A function call
7904#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7905#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7906#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7907pub struct Function {
7908    pub name: ObjectName,
7909    /// Flags whether this function call uses the [ODBC syntax].
7910    ///
7911    /// Example:
7912    /// ```sql
7913    /// SELECT {fn CONCAT('foo', 'bar')}
7914    /// ```
7915    ///
7916    /// [ODBC syntax]: https://learn.microsoft.com/en-us/sql/odbc/reference/develop-app/scalar-function-calls?view=sql-server-2017
7917    pub uses_odbc_syntax: bool,
7918    /// The parameters to the function, including any options specified within the
7919    /// delimiting parentheses.
7920    ///
7921    /// Example:
7922    /// ```plaintext
7923    /// HISTOGRAM(0.5, 0.6)(x, y)
7924    /// ```
7925    ///
7926    /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/aggregate-functions/parametric-functions)
7927    pub parameters: FunctionArguments,
7928    /// The arguments to the function, including any options specified within the
7929    /// delimiting parentheses.
7930    pub args: FunctionArguments,
7931    /// e.g. `x > 5` in `COUNT(x) FILTER (WHERE x > 5)`
7932    pub filter: Option<Box<Expr>>,
7933    /// Indicates how `NULL`s should be handled in the calculation.
7934    ///
7935    /// Example:
7936    /// ```plaintext
7937    /// FIRST_VALUE( <expr> ) [ { IGNORE | RESPECT } NULLS ] OVER ...
7938    /// ```
7939    ///
7940    /// [Snowflake](https://docs.snowflake.com/en/sql-reference/functions/first_value)
7941    pub null_treatment: Option<NullTreatment>,
7942    /// The `OVER` clause, indicating a window function call.
7943    pub over: Option<WindowType>,
7944    /// A clause used with certain aggregate functions to control the ordering
7945    /// within grouped sets before the function is applied.
7946    ///
7947    /// Syntax:
7948    /// ```plaintext
7949    /// <aggregate_function>(expression) WITHIN GROUP (ORDER BY key [ASC | DESC], ...)
7950    /// ```
7951    pub within_group: Vec<OrderByExpr>,
7952}
7953
7954impl fmt::Display for Function {
7955    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7956        if self.uses_odbc_syntax {
7957            write!(f, "{{fn ")?;
7958        }
7959
7960        write!(f, "{}{}{}", self.name, self.parameters, self.args)?;
7961
7962        if !self.within_group.is_empty() {
7963            write!(
7964                f,
7965                " WITHIN GROUP (ORDER BY {})",
7966                display_comma_separated(&self.within_group)
7967            )?;
7968        }
7969
7970        if let Some(filter_cond) = &self.filter {
7971            write!(f, " FILTER (WHERE {filter_cond})")?;
7972        }
7973
7974        if let Some(null_treatment) = &self.null_treatment {
7975            write!(f, " {null_treatment}")?;
7976        }
7977
7978        if let Some(o) = &self.over {
7979            f.write_str(" OVER ")?;
7980            o.fmt(f)?;
7981        }
7982
7983        if self.uses_odbc_syntax {
7984            write!(f, "}}")?;
7985        }
7986
7987        Ok(())
7988    }
7989}
7990
7991/// The arguments passed to a function call.
7992#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7993#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7994#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7995pub enum FunctionArguments {
7996    /// Used for special functions like `CURRENT_TIMESTAMP` that are invoked
7997    /// without parentheses.
7998    None,
7999    /// On some dialects, a subquery can be passed without surrounding
8000    /// parentheses if it's the sole argument to the function.
8001    Subquery(Box<Query>),
8002    /// A normal function argument list, including any clauses within it such as
8003    /// `DISTINCT` or `ORDER BY`.
8004    List(FunctionArgumentList),
8005}
8006
8007impl fmt::Display for FunctionArguments {
8008    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8009        match self {
8010            FunctionArguments::None => Ok(()),
8011            FunctionArguments::Subquery(query) => write!(f, "({query})"),
8012            FunctionArguments::List(args) => write!(f, "({args})"),
8013        }
8014    }
8015}
8016
8017/// This represents everything inside the parentheses when calling a function.
8018#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8019#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8020#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8021pub struct FunctionArgumentList {
8022    /// `[ ALL | DISTINCT ]`
8023    pub duplicate_treatment: Option<DuplicateTreatment>,
8024    /// The function arguments.
8025    pub args: Vec<FunctionArg>,
8026    /// Additional clauses specified within the argument list.
8027    pub clauses: Vec<FunctionArgumentClause>,
8028}
8029
8030impl fmt::Display for FunctionArgumentList {
8031    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8032        if let Some(duplicate_treatment) = self.duplicate_treatment {
8033            write!(f, "{duplicate_treatment} ")?;
8034        }
8035        write!(f, "{}", display_comma_separated(&self.args))?;
8036        if !self.clauses.is_empty() {
8037            if !self.args.is_empty() {
8038                write!(f, " ")?;
8039            }
8040            write!(f, "{}", display_separated(&self.clauses, " "))?;
8041        }
8042        Ok(())
8043    }
8044}
8045
8046#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8047#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8048#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8049pub enum FunctionArgumentClause {
8050    /// Indicates how `NULL`s should be handled in the calculation, e.g. in `FIRST_VALUE` on [BigQuery].
8051    ///
8052    /// Syntax:
8053    /// ```plaintext
8054    /// { IGNORE | RESPECT } NULLS ]
8055    /// ```
8056    ///
8057    /// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/navigation_functions#first_value
8058    IgnoreOrRespectNulls(NullTreatment),
8059    /// Specifies the the ordering for some ordered set aggregates, e.g. `ARRAY_AGG` on [BigQuery].
8060    ///
8061    /// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/aggregate_functions#array_agg
8062    OrderBy(Vec<OrderByExpr>),
8063    /// Specifies a limit for the `ARRAY_AGG` and `ARRAY_CONCAT_AGG` functions on BigQuery.
8064    Limit(Expr),
8065    /// Specifies the behavior on overflow of the `LISTAGG` function.
8066    ///
8067    /// See <https://trino.io/docs/current/functions/aggregate.html>.
8068    OnOverflow(ListAggOnOverflow),
8069    /// Specifies a minimum or maximum bound on the input to [`ANY_VALUE`] on BigQuery.
8070    ///
8071    /// Syntax:
8072    /// ```plaintext
8073    /// HAVING { MAX | MIN } expression
8074    /// ```
8075    ///
8076    /// [`ANY_VALUE`]: https://cloud.google.com/bigquery/docs/reference/standard-sql/aggregate_functions#any_value
8077    Having(HavingBound),
8078    /// The `SEPARATOR` clause to the [`GROUP_CONCAT`] function in MySQL.
8079    ///
8080    /// [`GROUP_CONCAT`]: https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html#function_group-concat
8081    Separator(Value),
8082    /// The `ON NULL` clause for some JSON functions.
8083    ///
8084    /// [MSSQL `JSON_ARRAY`](https://learn.microsoft.com/en-us/sql/t-sql/functions/json-array-transact-sql?view=sql-server-ver16)
8085    /// [MSSQL `JSON_OBJECT`](https://learn.microsoft.com/en-us/sql/t-sql/functions/json-object-transact-sql?view=sql-server-ver16>)
8086    /// [PostgreSQL JSON functions](https://www.postgresql.org/docs/current/functions-json.html#FUNCTIONS-JSON-PROCESSING)
8087    JsonNullClause(JsonNullClause),
8088    /// The `RETURNING` clause for some JSON functions in PostgreSQL
8089    ///
8090    /// [`JSON_OBJECT`](https://www.postgresql.org/docs/current/functions-json.html#:~:text=json_object)
8091    JsonReturningClause(JsonReturningClause),
8092}
8093
8094impl fmt::Display for FunctionArgumentClause {
8095    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8096        match self {
8097            FunctionArgumentClause::IgnoreOrRespectNulls(null_treatment) => {
8098                write!(f, "{null_treatment}")
8099            }
8100            FunctionArgumentClause::OrderBy(order_by) => {
8101                write!(f, "ORDER BY {}", display_comma_separated(order_by))
8102            }
8103            FunctionArgumentClause::Limit(limit) => write!(f, "LIMIT {limit}"),
8104            FunctionArgumentClause::OnOverflow(on_overflow) => write!(f, "{on_overflow}"),
8105            FunctionArgumentClause::Having(bound) => write!(f, "{bound}"),
8106            FunctionArgumentClause::Separator(sep) => write!(f, "SEPARATOR {sep}"),
8107            FunctionArgumentClause::JsonNullClause(null_clause) => write!(f, "{null_clause}"),
8108            FunctionArgumentClause::JsonReturningClause(returning_clause) => {
8109                write!(f, "{returning_clause}")
8110            }
8111        }
8112    }
8113}
8114
8115/// A method call
8116#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8117#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8118#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8119pub struct Method {
8120    pub expr: Box<Expr>,
8121    // always non-empty
8122    pub method_chain: Vec<Function>,
8123}
8124
8125impl fmt::Display for Method {
8126    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8127        write!(
8128            f,
8129            "{}.{}",
8130            self.expr,
8131            display_separated(&self.method_chain, ".")
8132        )
8133    }
8134}
8135
8136#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8137#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8138#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8139pub enum DuplicateTreatment {
8140    /// Perform the calculation only unique values.
8141    Distinct,
8142    /// Retain all duplicate values (the default).
8143    All,
8144}
8145
8146impl fmt::Display for DuplicateTreatment {
8147    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8148        match self {
8149            DuplicateTreatment::Distinct => write!(f, "DISTINCT"),
8150            DuplicateTreatment::All => write!(f, "ALL"),
8151        }
8152    }
8153}
8154
8155#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8156#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8157#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8158pub enum AnalyzeFormatKind {
8159    /// e.g. `EXPLAIN ANALYZE FORMAT JSON SELECT * FROM tbl`
8160    Keyword(AnalyzeFormat),
8161    /// e.g. `EXPLAIN ANALYZE FORMAT=JSON SELECT * FROM tbl`
8162    Assignment(AnalyzeFormat),
8163}
8164
8165impl fmt::Display for AnalyzeFormatKind {
8166    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
8167        match self {
8168            AnalyzeFormatKind::Keyword(format) => write!(f, "FORMAT {format}"),
8169            AnalyzeFormatKind::Assignment(format) => write!(f, "FORMAT={format}"),
8170        }
8171    }
8172}
8173
8174#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8175#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8176#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8177pub enum AnalyzeFormat {
8178    TEXT,
8179    GRAPHVIZ,
8180    JSON,
8181    TRADITIONAL,
8182    TREE,
8183}
8184
8185impl fmt::Display for AnalyzeFormat {
8186    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
8187        f.write_str(match self {
8188            AnalyzeFormat::TEXT => "TEXT",
8189            AnalyzeFormat::GRAPHVIZ => "GRAPHVIZ",
8190            AnalyzeFormat::JSON => "JSON",
8191            AnalyzeFormat::TRADITIONAL => "TRADITIONAL",
8192            AnalyzeFormat::TREE => "TREE",
8193        })
8194    }
8195}
8196
8197/// External table's available file format
8198#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8199#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8200#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8201pub enum FileFormat {
8202    TEXTFILE,
8203    SEQUENCEFILE,
8204    ORC,
8205    PARQUET,
8206    AVRO,
8207    RCFILE,
8208    JSONFILE,
8209}
8210
8211impl fmt::Display for FileFormat {
8212    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8213        use self::FileFormat::*;
8214        f.write_str(match self {
8215            TEXTFILE => "TEXTFILE",
8216            SEQUENCEFILE => "SEQUENCEFILE",
8217            ORC => "ORC",
8218            PARQUET => "PARQUET",
8219            AVRO => "AVRO",
8220            RCFILE => "RCFILE",
8221            JSONFILE => "JSONFILE",
8222        })
8223    }
8224}
8225
8226/// The `ON OVERFLOW` clause of a LISTAGG invocation
8227#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8228#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8229#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8230pub enum ListAggOnOverflow {
8231    /// `ON OVERFLOW ERROR`
8232    Error,
8233
8234    /// `ON OVERFLOW TRUNCATE [ <filler> ] WITH[OUT] COUNT`
8235    Truncate {
8236        filler: Option<Box<Expr>>,
8237        with_count: bool,
8238    },
8239}
8240
8241impl fmt::Display for ListAggOnOverflow {
8242    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8243        write!(f, "ON OVERFLOW")?;
8244        match self {
8245            ListAggOnOverflow::Error => write!(f, " ERROR"),
8246            ListAggOnOverflow::Truncate { filler, with_count } => {
8247                write!(f, " TRUNCATE")?;
8248                if let Some(filler) = filler {
8249                    write!(f, " {filler}")?;
8250                }
8251                if *with_count {
8252                    write!(f, " WITH")?;
8253                } else {
8254                    write!(f, " WITHOUT")?;
8255                }
8256                write!(f, " COUNT")
8257            }
8258        }
8259    }
8260}
8261
8262/// The `HAVING` clause in a call to `ANY_VALUE` on BigQuery.
8263#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8264#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8265#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8266pub struct HavingBound(pub HavingBoundKind, pub Expr);
8267
8268impl fmt::Display for HavingBound {
8269    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8270        write!(f, "HAVING {} {}", self.0, self.1)
8271    }
8272}
8273
8274#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8275#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8276#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8277pub enum HavingBoundKind {
8278    Min,
8279    Max,
8280}
8281
8282impl fmt::Display for HavingBoundKind {
8283    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8284        match self {
8285            HavingBoundKind::Min => write!(f, "MIN"),
8286            HavingBoundKind::Max => write!(f, "MAX"),
8287        }
8288    }
8289}
8290
8291#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8292#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8293#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8294pub enum ObjectType {
8295    Table,
8296    View,
8297    MaterializedView,
8298    Index,
8299    Schema,
8300    Database,
8301    Role,
8302    Sequence,
8303    Stage,
8304    Type,
8305    User,
8306    Stream,
8307}
8308
8309impl fmt::Display for ObjectType {
8310    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8311        f.write_str(match self {
8312            ObjectType::Table => "TABLE",
8313            ObjectType::View => "VIEW",
8314            ObjectType::MaterializedView => "MATERIALIZED VIEW",
8315            ObjectType::Index => "INDEX",
8316            ObjectType::Schema => "SCHEMA",
8317            ObjectType::Database => "DATABASE",
8318            ObjectType::Role => "ROLE",
8319            ObjectType::Sequence => "SEQUENCE",
8320            ObjectType::Stage => "STAGE",
8321            ObjectType::Type => "TYPE",
8322            ObjectType::User => "USER",
8323            ObjectType::Stream => "STREAM",
8324        })
8325    }
8326}
8327
8328#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8329#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8330#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8331pub enum KillType {
8332    Connection,
8333    Query,
8334    Mutation,
8335}
8336
8337impl fmt::Display for KillType {
8338    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8339        f.write_str(match self {
8340            // MySQL
8341            KillType::Connection => "CONNECTION",
8342            KillType::Query => "QUERY",
8343            // Clickhouse supports Mutation
8344            KillType::Mutation => "MUTATION",
8345        })
8346    }
8347}
8348
8349#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8350#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8351#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8352pub enum HiveDistributionStyle {
8353    PARTITIONED {
8354        columns: Vec<ColumnDef>,
8355    },
8356    SKEWED {
8357        columns: Vec<ColumnDef>,
8358        on: Vec<ColumnDef>,
8359        stored_as_directories: bool,
8360    },
8361    NONE,
8362}
8363
8364#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8365#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8366#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8367pub enum HiveRowFormat {
8368    SERDE { class: String },
8369    DELIMITED { delimiters: Vec<HiveRowDelimiter> },
8370}
8371
8372#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8373#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8374#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8375pub struct HiveLoadDataFormat {
8376    pub serde: Expr,
8377    pub input_format: Expr,
8378}
8379
8380#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8381#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8382#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8383pub struct HiveRowDelimiter {
8384    pub delimiter: HiveDelimiter,
8385    pub char: Ident,
8386}
8387
8388impl fmt::Display for HiveRowDelimiter {
8389    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8390        write!(f, "{} ", self.delimiter)?;
8391        write!(f, "{}", self.char)
8392    }
8393}
8394
8395#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8396#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8397#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8398pub enum HiveDelimiter {
8399    FieldsTerminatedBy,
8400    FieldsEscapedBy,
8401    CollectionItemsTerminatedBy,
8402    MapKeysTerminatedBy,
8403    LinesTerminatedBy,
8404    NullDefinedAs,
8405}
8406
8407impl fmt::Display for HiveDelimiter {
8408    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8409        use HiveDelimiter::*;
8410        f.write_str(match self {
8411            FieldsTerminatedBy => "FIELDS TERMINATED BY",
8412            FieldsEscapedBy => "ESCAPED BY",
8413            CollectionItemsTerminatedBy => "COLLECTION ITEMS TERMINATED BY",
8414            MapKeysTerminatedBy => "MAP KEYS TERMINATED BY",
8415            LinesTerminatedBy => "LINES TERMINATED BY",
8416            NullDefinedAs => "NULL DEFINED AS",
8417        })
8418    }
8419}
8420
8421#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8422#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8423#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8424pub enum HiveDescribeFormat {
8425    Extended,
8426    Formatted,
8427}
8428
8429impl fmt::Display for HiveDescribeFormat {
8430    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8431        use HiveDescribeFormat::*;
8432        f.write_str(match self {
8433            Extended => "EXTENDED",
8434            Formatted => "FORMATTED",
8435        })
8436    }
8437}
8438
8439#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8440#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8441#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8442pub enum DescribeAlias {
8443    Describe,
8444    Explain,
8445    Desc,
8446}
8447
8448impl fmt::Display for DescribeAlias {
8449    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8450        use DescribeAlias::*;
8451        f.write_str(match self {
8452            Describe => "DESCRIBE",
8453            Explain => "EXPLAIN",
8454            Desc => "DESC",
8455        })
8456    }
8457}
8458
8459#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8460#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8461#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8462#[allow(clippy::large_enum_variant)]
8463pub enum HiveIOFormat {
8464    IOF {
8465        input_format: Expr,
8466        output_format: Expr,
8467    },
8468    FileFormat {
8469        format: FileFormat,
8470    },
8471}
8472
8473#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Default)]
8474#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8475#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8476pub struct HiveFormat {
8477    pub row_format: Option<HiveRowFormat>,
8478    pub serde_properties: Option<Vec<SqlOption>>,
8479    pub storage: Option<HiveIOFormat>,
8480    pub location: Option<String>,
8481}
8482
8483#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8484#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8485#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8486pub struct ClusteredIndex {
8487    pub name: Ident,
8488    pub asc: Option<bool>,
8489}
8490
8491impl fmt::Display for ClusteredIndex {
8492    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8493        write!(f, "{}", self.name)?;
8494        match self.asc {
8495            Some(true) => write!(f, " ASC"),
8496            Some(false) => write!(f, " DESC"),
8497            _ => Ok(()),
8498        }
8499    }
8500}
8501
8502#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8503#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8504#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8505pub enum TableOptionsClustered {
8506    ColumnstoreIndex,
8507    ColumnstoreIndexOrder(Vec<Ident>),
8508    Index(Vec<ClusteredIndex>),
8509}
8510
8511impl fmt::Display for TableOptionsClustered {
8512    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8513        match self {
8514            TableOptionsClustered::ColumnstoreIndex => {
8515                write!(f, "CLUSTERED COLUMNSTORE INDEX")
8516            }
8517            TableOptionsClustered::ColumnstoreIndexOrder(values) => {
8518                write!(
8519                    f,
8520                    "CLUSTERED COLUMNSTORE INDEX ORDER ({})",
8521                    display_comma_separated(values)
8522                )
8523            }
8524            TableOptionsClustered::Index(values) => {
8525                write!(f, "CLUSTERED INDEX ({})", display_comma_separated(values))
8526            }
8527        }
8528    }
8529}
8530
8531/// Specifies which partition the boundary values on table partitioning belongs to.
8532#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8533#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8534#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8535pub enum PartitionRangeDirection {
8536    Left,
8537    Right,
8538}
8539
8540#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8541#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8542#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8543pub enum SqlOption {
8544    /// Clustered represents the clustered version of table storage for MSSQL.
8545    ///
8546    /// <https://learn.microsoft.com/en-us/sql/t-sql/statements/create-table-azure-sql-data-warehouse?view=aps-pdw-2016-au7#TableOptions>
8547    Clustered(TableOptionsClustered),
8548    /// Single identifier options, e.g. `HEAP` for MSSQL.
8549    ///
8550    /// <https://learn.microsoft.com/en-us/sql/t-sql/statements/create-table-azure-sql-data-warehouse?view=aps-pdw-2016-au7#TableOptions>
8551    Ident(Ident),
8552    /// Any option that consists of a key value pair where the value is an expression. e.g.
8553    ///
8554    ///   WITH(DISTRIBUTION = ROUND_ROBIN)
8555    KeyValue { key: Ident, value: Expr },
8556    /// One or more table partitions and represents which partition the boundary values belong to,
8557    /// e.g.
8558    ///
8559    ///   PARTITION (id RANGE LEFT FOR VALUES (10, 20, 30, 40))
8560    ///
8561    /// <https://learn.microsoft.com/en-us/sql/t-sql/statements/create-table-azure-sql-data-warehouse?view=aps-pdw-2016-au7#TablePartitionOptions>
8562    Partition {
8563        column_name: Ident,
8564        range_direction: Option<PartitionRangeDirection>,
8565        for_values: Vec<Expr>,
8566    },
8567    /// Comment parameter (supports `=` and no `=` syntax)
8568    Comment(CommentDef),
8569    /// MySQL TableSpace option
8570    /// <https://dev.mysql.com/doc/refman/8.4/en/create-table.html>
8571    TableSpace(TablespaceOption),
8572    /// An option representing a key value pair, where the value is a parenthesized list and with an optional name
8573    /// e.g.
8574    ///
8575    ///   UNION  = (tbl_name\[,tbl_name\]...) <https://dev.mysql.com/doc/refman/8.4/en/create-table.html>
8576    ///   ENGINE = ReplicatedMergeTree('/table_name','{replica}', ver) <https://clickhouse.com/docs/engines/table-engines/mergetree-family/replication>
8577    ///   ENGINE = SummingMergeTree(\[columns\]) <https://clickhouse.com/docs/engines/table-engines/mergetree-family/summingmergetree>
8578    NamedParenthesizedList(NamedParenthesizedList),
8579}
8580
8581impl fmt::Display for SqlOption {
8582    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8583        match self {
8584            SqlOption::Clustered(c) => write!(f, "{c}"),
8585            SqlOption::Ident(ident) => {
8586                write!(f, "{ident}")
8587            }
8588            SqlOption::KeyValue { key: name, value } => {
8589                write!(f, "{name} = {value}")
8590            }
8591            SqlOption::Partition {
8592                column_name,
8593                range_direction,
8594                for_values,
8595            } => {
8596                let direction = match range_direction {
8597                    Some(PartitionRangeDirection::Left) => " LEFT",
8598                    Some(PartitionRangeDirection::Right) => " RIGHT",
8599                    None => "",
8600                };
8601
8602                write!(
8603                    f,
8604                    "PARTITION ({} RANGE{} FOR VALUES ({}))",
8605                    column_name,
8606                    direction,
8607                    display_comma_separated(for_values)
8608                )
8609            }
8610            SqlOption::TableSpace(tablespace_option) => {
8611                write!(f, "TABLESPACE {}", tablespace_option.name)?;
8612                match tablespace_option.storage {
8613                    Some(StorageType::Disk) => write!(f, " STORAGE DISK"),
8614                    Some(StorageType::Memory) => write!(f, " STORAGE MEMORY"),
8615                    None => Ok(()),
8616                }
8617            }
8618            SqlOption::Comment(comment) => match comment {
8619                CommentDef::WithEq(comment) => {
8620                    write!(f, "COMMENT = '{comment}'")
8621                }
8622                CommentDef::WithoutEq(comment) => {
8623                    write!(f, "COMMENT '{comment}'")
8624                }
8625            },
8626            SqlOption::NamedParenthesizedList(value) => {
8627                write!(f, "{} = ", value.key)?;
8628                if let Some(key) = &value.name {
8629                    write!(f, "{key}")?;
8630                }
8631                if !value.values.is_empty() {
8632                    write!(f, "({})", display_comma_separated(&value.values))?
8633                }
8634                Ok(())
8635            }
8636        }
8637    }
8638}
8639
8640#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
8641#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8642#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8643pub enum StorageType {
8644    Disk,
8645    Memory,
8646}
8647
8648#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
8649#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8650#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8651/// MySql TableSpace option
8652/// <https://dev.mysql.com/doc/refman/8.4/en/create-table.html>
8653pub struct TablespaceOption {
8654    pub name: String,
8655    pub storage: Option<StorageType>,
8656}
8657
8658#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8659#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8660#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8661pub struct SecretOption {
8662    pub key: Ident,
8663    pub value: Ident,
8664}
8665
8666impl fmt::Display for SecretOption {
8667    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8668        write!(f, "{} {}", self.key, self.value)
8669    }
8670}
8671
8672/// A `CREATE SERVER` statement.
8673///
8674/// [PostgreSQL Documentation](https://www.postgresql.org/docs/current/sql-createserver.html)
8675#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8676#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8677#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8678pub struct CreateServerStatement {
8679    pub name: ObjectName,
8680    pub if_not_exists: bool,
8681    pub server_type: Option<Ident>,
8682    pub version: Option<Ident>,
8683    pub foreign_data_wrapper: ObjectName,
8684    pub options: Option<Vec<CreateServerOption>>,
8685}
8686
8687impl fmt::Display for CreateServerStatement {
8688    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8689        let CreateServerStatement {
8690            name,
8691            if_not_exists,
8692            server_type,
8693            version,
8694            foreign_data_wrapper,
8695            options,
8696        } = self;
8697
8698        write!(
8699            f,
8700            "CREATE SERVER {if_not_exists}{name} ",
8701            if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
8702        )?;
8703
8704        if let Some(st) = server_type {
8705            write!(f, "TYPE {st} ")?;
8706        }
8707
8708        if let Some(v) = version {
8709            write!(f, "VERSION {v} ")?;
8710        }
8711
8712        write!(f, "FOREIGN DATA WRAPPER {foreign_data_wrapper}")?;
8713
8714        if let Some(o) = options {
8715            write!(f, " OPTIONS ({o})", o = display_comma_separated(o))?;
8716        }
8717
8718        Ok(())
8719    }
8720}
8721
8722#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8723#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8724#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8725pub struct CreateServerOption {
8726    pub key: Ident,
8727    pub value: Ident,
8728}
8729
8730impl fmt::Display for CreateServerOption {
8731    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8732        write!(f, "{} {}", self.key, self.value)
8733    }
8734}
8735
8736#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8737#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8738#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8739pub enum AttachDuckDBDatabaseOption {
8740    ReadOnly(Option<bool>),
8741    Type(Ident),
8742}
8743
8744impl fmt::Display for AttachDuckDBDatabaseOption {
8745    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8746        match self {
8747            AttachDuckDBDatabaseOption::ReadOnly(Some(true)) => write!(f, "READ_ONLY true"),
8748            AttachDuckDBDatabaseOption::ReadOnly(Some(false)) => write!(f, "READ_ONLY false"),
8749            AttachDuckDBDatabaseOption::ReadOnly(None) => write!(f, "READ_ONLY"),
8750            AttachDuckDBDatabaseOption::Type(t) => write!(f, "TYPE {t}"),
8751        }
8752    }
8753}
8754
8755#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8756#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8757#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8758pub enum TransactionMode {
8759    AccessMode(TransactionAccessMode),
8760    IsolationLevel(TransactionIsolationLevel),
8761}
8762
8763impl fmt::Display for TransactionMode {
8764    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8765        use TransactionMode::*;
8766        match self {
8767            AccessMode(access_mode) => write!(f, "{access_mode}"),
8768            IsolationLevel(iso_level) => write!(f, "ISOLATION LEVEL {iso_level}"),
8769        }
8770    }
8771}
8772
8773#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8774#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8775#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8776pub enum TransactionAccessMode {
8777    ReadOnly,
8778    ReadWrite,
8779}
8780
8781impl fmt::Display for TransactionAccessMode {
8782    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8783        use TransactionAccessMode::*;
8784        f.write_str(match self {
8785            ReadOnly => "READ ONLY",
8786            ReadWrite => "READ WRITE",
8787        })
8788    }
8789}
8790
8791#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8792#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8793#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8794pub enum TransactionIsolationLevel {
8795    ReadUncommitted,
8796    ReadCommitted,
8797    RepeatableRead,
8798    Serializable,
8799    Snapshot,
8800}
8801
8802impl fmt::Display for TransactionIsolationLevel {
8803    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8804        use TransactionIsolationLevel::*;
8805        f.write_str(match self {
8806            ReadUncommitted => "READ UNCOMMITTED",
8807            ReadCommitted => "READ COMMITTED",
8808            RepeatableRead => "REPEATABLE READ",
8809            Serializable => "SERIALIZABLE",
8810            Snapshot => "SNAPSHOT",
8811        })
8812    }
8813}
8814
8815/// Modifier for the transaction in the `BEGIN` syntax
8816///
8817/// SQLite: <https://sqlite.org/lang_transaction.html>
8818/// MS-SQL: <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/try-catch-transact-sql>
8819#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8820#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8821#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8822pub enum TransactionModifier {
8823    Deferred,
8824    Immediate,
8825    Exclusive,
8826    Try,
8827    Catch,
8828}
8829
8830impl fmt::Display for TransactionModifier {
8831    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8832        use TransactionModifier::*;
8833        f.write_str(match self {
8834            Deferred => "DEFERRED",
8835            Immediate => "IMMEDIATE",
8836            Exclusive => "EXCLUSIVE",
8837            Try => "TRY",
8838            Catch => "CATCH",
8839        })
8840    }
8841}
8842
8843#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8844#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8845#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8846pub enum ShowStatementFilter {
8847    Like(String),
8848    ILike(String),
8849    Where(Expr),
8850    NoKeyword(String),
8851}
8852
8853impl fmt::Display for ShowStatementFilter {
8854    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8855        use ShowStatementFilter::*;
8856        match self {
8857            Like(pattern) => write!(f, "LIKE '{}'", value::escape_single_quote_string(pattern)),
8858            ILike(pattern) => write!(f, "ILIKE {}", value::escape_single_quote_string(pattern)),
8859            Where(expr) => write!(f, "WHERE {expr}"),
8860            NoKeyword(pattern) => write!(f, "'{}'", value::escape_single_quote_string(pattern)),
8861        }
8862    }
8863}
8864
8865#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8866#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8867#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8868pub enum ShowStatementInClause {
8869    IN,
8870    FROM,
8871}
8872
8873impl fmt::Display for ShowStatementInClause {
8874    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8875        use ShowStatementInClause::*;
8876        match self {
8877            FROM => write!(f, "FROM"),
8878            IN => write!(f, "IN"),
8879        }
8880    }
8881}
8882
8883/// Sqlite specific syntax
8884///
8885/// See [Sqlite documentation](https://sqlite.org/lang_conflict.html)
8886/// for more details.
8887#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8888#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8889#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8890pub enum SqliteOnConflict {
8891    Rollback,
8892    Abort,
8893    Fail,
8894    Ignore,
8895    Replace,
8896}
8897
8898impl fmt::Display for SqliteOnConflict {
8899    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8900        use SqliteOnConflict::*;
8901        match self {
8902            Rollback => write!(f, "OR ROLLBACK"),
8903            Abort => write!(f, "OR ABORT"),
8904            Fail => write!(f, "OR FAIL"),
8905            Ignore => write!(f, "OR IGNORE"),
8906            Replace => write!(f, "OR REPLACE"),
8907        }
8908    }
8909}
8910
8911/// Mysql specific syntax
8912///
8913/// See [Mysql documentation](https://dev.mysql.com/doc/refman/8.0/en/replace.html)
8914/// See [Mysql documentation](https://dev.mysql.com/doc/refman/8.0/en/insert.html)
8915/// for more details.
8916#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8917#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8918#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8919pub enum MysqlInsertPriority {
8920    LowPriority,
8921    Delayed,
8922    HighPriority,
8923}
8924
8925impl fmt::Display for crate::ast::MysqlInsertPriority {
8926    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8927        use MysqlInsertPriority::*;
8928        match self {
8929            LowPriority => write!(f, "LOW_PRIORITY"),
8930            Delayed => write!(f, "DELAYED"),
8931            HighPriority => write!(f, "HIGH_PRIORITY"),
8932        }
8933    }
8934}
8935
8936#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8937#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8938#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8939pub enum CopySource {
8940    Table {
8941        /// The name of the table to copy from.
8942        table_name: ObjectName,
8943        /// A list of column names to copy. Empty list means that all columns
8944        /// are copied.
8945        columns: Vec<Ident>,
8946    },
8947    Query(Box<Query>),
8948}
8949
8950#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8951#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8952#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8953pub enum CopyTarget {
8954    Stdin,
8955    Stdout,
8956    File {
8957        /// The path name of the input or output file.
8958        filename: String,
8959    },
8960    Program {
8961        /// A command to execute
8962        command: String,
8963    },
8964}
8965
8966impl fmt::Display for CopyTarget {
8967    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8968        use CopyTarget::*;
8969        match self {
8970            Stdin => write!(f, "STDIN"),
8971            Stdout => write!(f, "STDOUT"),
8972            File { filename } => write!(f, "'{}'", value::escape_single_quote_string(filename)),
8973            Program { command } => write!(
8974                f,
8975                "PROGRAM '{}'",
8976                value::escape_single_quote_string(command)
8977            ),
8978        }
8979    }
8980}
8981
8982#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8983#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8984#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8985pub enum OnCommit {
8986    DeleteRows,
8987    PreserveRows,
8988    Drop,
8989}
8990
8991/// An option in `COPY` statement.
8992///
8993/// <https://www.postgresql.org/docs/14/sql-copy.html>
8994#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8995#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8996#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8997pub enum CopyOption {
8998    /// FORMAT format_name
8999    Format(Ident),
9000    /// FREEZE \[ boolean \]
9001    Freeze(bool),
9002    /// DELIMITER 'delimiter_character'
9003    Delimiter(char),
9004    /// NULL 'null_string'
9005    Null(String),
9006    /// HEADER \[ boolean \]
9007    Header(bool),
9008    /// QUOTE 'quote_character'
9009    Quote(char),
9010    /// ESCAPE 'escape_character'
9011    Escape(char),
9012    /// FORCE_QUOTE { ( column_name [, ...] ) | * }
9013    ForceQuote(Vec<Ident>),
9014    /// FORCE_NOT_NULL ( column_name [, ...] )
9015    ForceNotNull(Vec<Ident>),
9016    /// FORCE_NULL ( column_name [, ...] )
9017    ForceNull(Vec<Ident>),
9018    /// ENCODING 'encoding_name'
9019    Encoding(String),
9020}
9021
9022impl fmt::Display for CopyOption {
9023    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9024        use CopyOption::*;
9025        match self {
9026            Format(name) => write!(f, "FORMAT {name}"),
9027            Freeze(true) => write!(f, "FREEZE"),
9028            Freeze(false) => write!(f, "FREEZE FALSE"),
9029            Delimiter(char) => write!(f, "DELIMITER '{char}'"),
9030            Null(string) => write!(f, "NULL '{}'", value::escape_single_quote_string(string)),
9031            Header(true) => write!(f, "HEADER"),
9032            Header(false) => write!(f, "HEADER FALSE"),
9033            Quote(char) => write!(f, "QUOTE '{char}'"),
9034            Escape(char) => write!(f, "ESCAPE '{char}'"),
9035            ForceQuote(columns) => write!(f, "FORCE_QUOTE ({})", display_comma_separated(columns)),
9036            ForceNotNull(columns) => {
9037                write!(f, "FORCE_NOT_NULL ({})", display_comma_separated(columns))
9038            }
9039            ForceNull(columns) => write!(f, "FORCE_NULL ({})", display_comma_separated(columns)),
9040            Encoding(name) => write!(f, "ENCODING '{}'", value::escape_single_quote_string(name)),
9041        }
9042    }
9043}
9044
9045/// An option in `COPY` statement before PostgreSQL version 9.0.
9046///
9047/// [PostgreSQL](https://www.postgresql.org/docs/8.4/sql-copy.html)
9048/// [Redshift](https://docs.aws.amazon.com/redshift/latest/dg/r_COPY-alphabetical-parm-list.html)
9049#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9050#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9051#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9052pub enum CopyLegacyOption {
9053    /// ACCEPTANYDATE
9054    AcceptAnyDate,
9055    /// ACCEPTINVCHARS
9056    AcceptInvChars(Option<String>),
9057    /// ADDQUOTES
9058    AddQuotes,
9059    /// ALLOWOVERWRITE
9060    AllowOverwrite,
9061    /// BINARY
9062    Binary,
9063    /// BLANKSASNULL
9064    BlankAsNull,
9065    /// BZIP2
9066    Bzip2,
9067    /// CLEANPATH
9068    CleanPath,
9069    /// CSV ...
9070    Csv(Vec<CopyLegacyCsvOption>),
9071    /// DATEFORMAT \[ AS \] {'dateformat_string' | 'auto' }
9072    DateFormat(Option<String>),
9073    /// DELIMITER \[ AS \] 'delimiter_character'
9074    Delimiter(char),
9075    /// EMPTYASNULL
9076    EmptyAsNull,
9077    /// ENCRYPTED \[ AUTO \]
9078    Encrypted { auto: bool },
9079    /// ESCAPE
9080    Escape,
9081    /// EXTENSION 'extension-name'
9082    Extension(String),
9083    /// FIXEDWIDTH \[ AS \] 'fixedwidth-spec'
9084    FixedWidth(String),
9085    /// GZIP
9086    Gzip,
9087    /// HEADER
9088    Header,
9089    /// IAM_ROLE { DEFAULT | 'arn:aws:iam::123456789:role/role1' }
9090    IamRole(IamRoleKind),
9091    /// IGNOREHEADER \[ AS \] number_rows
9092    IgnoreHeader(u64),
9093    /// JSON
9094    Json,
9095    /// MANIFEST \[ VERBOSE \]
9096    Manifest { verbose: bool },
9097    /// MAXFILESIZE \[ AS \] max-size \[ MB | GB \]
9098    MaxFileSize(FileSize),
9099    /// NULL \[ AS \] 'null_string'
9100    Null(String),
9101    /// PARALLEL [ { ON | TRUE } | { OFF | FALSE } ]
9102    Parallel(Option<bool>),
9103    /// PARQUET
9104    Parquet,
9105    /// PARTITION BY ( column_name [, ... ] ) \[ INCLUDE \]
9106    PartitionBy(UnloadPartitionBy),
9107    /// REGION \[ AS \] 'aws-region' }
9108    Region(String),
9109    /// ROWGROUPSIZE \[ AS \] size \[ MB | GB \]
9110    RowGroupSize(FileSize),
9111    /// TIMEFORMAT \[ AS \] {'timeformat_string' | 'auto' | 'epochsecs' | 'epochmillisecs' }
9112    TimeFormat(Option<String>),
9113    /// TRUNCATECOLUMNS
9114    TruncateColumns,
9115    /// ZSTD
9116    Zstd,
9117}
9118
9119impl fmt::Display for CopyLegacyOption {
9120    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9121        use CopyLegacyOption::*;
9122        match self {
9123            AcceptAnyDate => write!(f, "ACCEPTANYDATE"),
9124            AcceptInvChars(ch) => {
9125                write!(f, "ACCEPTINVCHARS")?;
9126                if let Some(ch) = ch {
9127                    write!(f, " '{}'", value::escape_single_quote_string(ch))?;
9128                }
9129                Ok(())
9130            }
9131            AddQuotes => write!(f, "ADDQUOTES"),
9132            AllowOverwrite => write!(f, "ALLOWOVERWRITE"),
9133            Binary => write!(f, "BINARY"),
9134            BlankAsNull => write!(f, "BLANKSASNULL"),
9135            Bzip2 => write!(f, "BZIP2"),
9136            CleanPath => write!(f, "CLEANPATH"),
9137            Csv(opts) => {
9138                write!(f, "CSV")?;
9139                if !opts.is_empty() {
9140                    write!(f, " {}", display_separated(opts, " "))?;
9141                }
9142                Ok(())
9143            }
9144            DateFormat(fmt) => {
9145                write!(f, "DATEFORMAT")?;
9146                if let Some(fmt) = fmt {
9147                    write!(f, " '{}'", value::escape_single_quote_string(fmt))?;
9148                }
9149                Ok(())
9150            }
9151            Delimiter(char) => write!(f, "DELIMITER '{char}'"),
9152            EmptyAsNull => write!(f, "EMPTYASNULL"),
9153            Encrypted { auto } => write!(f, "ENCRYPTED{}", if *auto { " AUTO" } else { "" }),
9154            Escape => write!(f, "ESCAPE"),
9155            Extension(ext) => write!(f, "EXTENSION '{}'", value::escape_single_quote_string(ext)),
9156            FixedWidth(spec) => write!(
9157                f,
9158                "FIXEDWIDTH '{}'",
9159                value::escape_single_quote_string(spec)
9160            ),
9161            Gzip => write!(f, "GZIP"),
9162            Header => write!(f, "HEADER"),
9163            IamRole(role) => write!(f, "IAM_ROLE {role}"),
9164            IgnoreHeader(num_rows) => write!(f, "IGNOREHEADER {num_rows}"),
9165            Json => write!(f, "JSON"),
9166            Manifest { verbose } => write!(f, "MANIFEST{}", if *verbose { " VERBOSE" } else { "" }),
9167            MaxFileSize(file_size) => write!(f, "MAXFILESIZE {file_size}"),
9168            Null(string) => write!(f, "NULL '{}'", value::escape_single_quote_string(string)),
9169            Parallel(enabled) => {
9170                write!(
9171                    f,
9172                    "PARALLEL{}",
9173                    match enabled {
9174                        Some(true) => " TRUE",
9175                        Some(false) => " FALSE",
9176                        _ => "",
9177                    }
9178                )
9179            }
9180            Parquet => write!(f, "PARQUET"),
9181            PartitionBy(p) => write!(f, "{p}"),
9182            Region(region) => write!(f, "REGION '{}'", value::escape_single_quote_string(region)),
9183            RowGroupSize(file_size) => write!(f, "ROWGROUPSIZE {file_size}"),
9184            TimeFormat(fmt) => {
9185                write!(f, "TIMEFORMAT")?;
9186                if let Some(fmt) = fmt {
9187                    write!(f, " '{}'", value::escape_single_quote_string(fmt))?;
9188                }
9189                Ok(())
9190            }
9191            TruncateColumns => write!(f, "TRUNCATECOLUMNS"),
9192            Zstd => write!(f, "ZSTD"),
9193        }
9194    }
9195}
9196
9197/// ```sql
9198/// SIZE \[ MB | GB \]
9199/// ```
9200#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9201#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9202#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9203pub struct FileSize {
9204    pub size: Value,
9205    pub unit: Option<FileSizeUnit>,
9206}
9207
9208impl fmt::Display for FileSize {
9209    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9210        write!(f, "{}", self.size)?;
9211        if let Some(unit) = &self.unit {
9212            write!(f, " {unit}")?;
9213        }
9214        Ok(())
9215    }
9216}
9217
9218#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9219#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9220#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9221pub enum FileSizeUnit {
9222    MB,
9223    GB,
9224}
9225
9226impl fmt::Display for FileSizeUnit {
9227    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9228        match self {
9229            FileSizeUnit::MB => write!(f, "MB"),
9230            FileSizeUnit::GB => write!(f, "GB"),
9231        }
9232    }
9233}
9234
9235/// Specifies the partition keys for the unload operation
9236///
9237/// ```sql
9238/// PARTITION BY ( column_name [, ... ] ) [ INCLUDE ]
9239/// ```
9240#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9241#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9242#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9243pub struct UnloadPartitionBy {
9244    pub columns: Vec<Ident>,
9245    pub include: bool,
9246}
9247
9248impl fmt::Display for UnloadPartitionBy {
9249    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9250        write!(
9251            f,
9252            "PARTITION BY ({}){}",
9253            display_comma_separated(&self.columns),
9254            if self.include { " INCLUDE" } else { "" }
9255        )
9256    }
9257}
9258
9259/// An `IAM_ROLE` option in the AWS ecosystem
9260///
9261/// [Redshift COPY](https://docs.aws.amazon.com/redshift/latest/dg/copy-parameters-authorization.html#copy-iam-role)
9262#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9263#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9264#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9265pub enum IamRoleKind {
9266    /// Default role
9267    Default,
9268    /// Specific role ARN, for example: `arn:aws:iam::123456789:role/role1`
9269    Arn(String),
9270}
9271
9272impl fmt::Display for IamRoleKind {
9273    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9274        match self {
9275            IamRoleKind::Default => write!(f, "DEFAULT"),
9276            IamRoleKind::Arn(arn) => write!(f, "'{arn}'"),
9277        }
9278    }
9279}
9280
9281/// A `CSV` option in `COPY` statement before PostgreSQL version 9.0.
9282///
9283/// <https://www.postgresql.org/docs/8.4/sql-copy.html>
9284#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9285#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9286#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9287pub enum CopyLegacyCsvOption {
9288    /// HEADER
9289    Header,
9290    /// QUOTE \[ AS \] 'quote_character'
9291    Quote(char),
9292    /// ESCAPE \[ AS \] 'escape_character'
9293    Escape(char),
9294    /// FORCE QUOTE { column_name [, ...] | * }
9295    ForceQuote(Vec<Ident>),
9296    /// FORCE NOT NULL column_name [, ...]
9297    ForceNotNull(Vec<Ident>),
9298}
9299
9300impl fmt::Display for CopyLegacyCsvOption {
9301    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9302        use CopyLegacyCsvOption::*;
9303        match self {
9304            Header => write!(f, "HEADER"),
9305            Quote(char) => write!(f, "QUOTE '{char}'"),
9306            Escape(char) => write!(f, "ESCAPE '{char}'"),
9307            ForceQuote(columns) => write!(f, "FORCE QUOTE {}", display_comma_separated(columns)),
9308            ForceNotNull(columns) => {
9309                write!(f, "FORCE NOT NULL {}", display_comma_separated(columns))
9310            }
9311        }
9312    }
9313}
9314
9315/// Variant of `WHEN` clause used within a `MERGE` Statement.
9316///
9317/// Example:
9318/// ```sql
9319/// MERGE INTO T USING U ON FALSE WHEN MATCHED THEN DELETE
9320/// ```
9321/// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/merge)
9322/// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/dml-syntax#merge_statement)
9323#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9324#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9325#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9326pub enum MergeClauseKind {
9327    /// `WHEN MATCHED`
9328    Matched,
9329    /// `WHEN NOT MATCHED`
9330    NotMatched,
9331    /// `WHEN MATCHED BY TARGET`
9332    ///
9333    /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/dml-syntax#merge_statement)
9334    NotMatchedByTarget,
9335    /// `WHEN MATCHED BY SOURCE`
9336    ///
9337    /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/dml-syntax#merge_statement)
9338    NotMatchedBySource,
9339}
9340
9341impl Display for MergeClauseKind {
9342    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9343        match self {
9344            MergeClauseKind::Matched => write!(f, "MATCHED"),
9345            MergeClauseKind::NotMatched => write!(f, "NOT MATCHED"),
9346            MergeClauseKind::NotMatchedByTarget => write!(f, "NOT MATCHED BY TARGET"),
9347            MergeClauseKind::NotMatchedBySource => write!(f, "NOT MATCHED BY SOURCE"),
9348        }
9349    }
9350}
9351
9352/// The type of expression used to insert rows within a `MERGE` statement.
9353///
9354/// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/merge)
9355/// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/dml-syntax#merge_statement)
9356#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9357#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9358#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9359pub enum MergeInsertKind {
9360    /// The insert expression is defined from an explicit `VALUES` clause
9361    ///
9362    /// Example:
9363    /// ```sql
9364    /// INSERT VALUES(product, quantity)
9365    /// ```
9366    Values(Values),
9367    /// The insert expression is defined using only the `ROW` keyword.
9368    ///
9369    /// Example:
9370    /// ```sql
9371    /// INSERT ROW
9372    /// ```
9373    /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/dml-syntax#merge_statement)
9374    Row,
9375}
9376
9377impl Display for MergeInsertKind {
9378    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9379        match self {
9380            MergeInsertKind::Values(values) => {
9381                write!(f, "{values}")
9382            }
9383            MergeInsertKind::Row => {
9384                write!(f, "ROW")
9385            }
9386        }
9387    }
9388}
9389
9390/// The expression used to insert rows within a `MERGE` statement.
9391///
9392/// Examples
9393/// ```sql
9394/// INSERT (product, quantity) VALUES(product, quantity)
9395/// INSERT ROW
9396/// ```
9397///
9398/// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/merge)
9399/// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/dml-syntax#merge_statement)
9400#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9401#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9402#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9403pub struct MergeInsertExpr {
9404    /// Columns (if any) specified by the insert.
9405    ///
9406    /// Example:
9407    /// ```sql
9408    /// INSERT (product, quantity) VALUES(product, quantity)
9409    /// INSERT (product, quantity) ROW
9410    /// ```
9411    pub columns: Vec<Ident>,
9412    /// The insert type used by the statement.
9413    pub kind: MergeInsertKind,
9414}
9415
9416impl Display for MergeInsertExpr {
9417    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9418        if !self.columns.is_empty() {
9419            write!(f, "({}) ", display_comma_separated(self.columns.as_slice()))?;
9420        }
9421        write!(f, "{}", self.kind)
9422    }
9423}
9424
9425/// Underlying statement of a when clause within a `MERGE` Statement
9426///
9427/// Example
9428/// ```sql
9429/// INSERT (product, quantity) VALUES(product, quantity)
9430/// ```
9431///
9432/// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/merge)
9433/// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/dml-syntax#merge_statement)
9434#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9435#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9436#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9437pub enum MergeAction {
9438    /// An `INSERT` clause
9439    ///
9440    /// Example:
9441    /// ```sql
9442    /// INSERT (product, quantity) VALUES(product, quantity)
9443    /// ```
9444    Insert(MergeInsertExpr),
9445    /// An `UPDATE` clause
9446    ///
9447    /// Example:
9448    /// ```sql
9449    /// UPDATE SET quantity = T.quantity + S.quantity
9450    /// ```
9451    Update { assignments: Vec<Assignment> },
9452    /// A plain `DELETE` clause
9453    Delete,
9454}
9455
9456impl Display for MergeAction {
9457    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9458        match self {
9459            MergeAction::Insert(insert) => {
9460                write!(f, "INSERT {insert}")
9461            }
9462            MergeAction::Update { assignments } => {
9463                write!(f, "UPDATE SET {}", display_comma_separated(assignments))
9464            }
9465            MergeAction::Delete => {
9466                write!(f, "DELETE")
9467            }
9468        }
9469    }
9470}
9471
9472/// A when clause within a `MERGE` Statement
9473///
9474/// Example:
9475/// ```sql
9476/// WHEN NOT MATCHED BY SOURCE AND product LIKE '%washer%' THEN DELETE
9477/// ```
9478/// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/merge)
9479/// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/dml-syntax#merge_statement)
9480#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9481#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9482#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9483pub struct MergeClause {
9484    pub clause_kind: MergeClauseKind,
9485    pub predicate: Option<Expr>,
9486    pub action: MergeAction,
9487}
9488
9489impl Display for MergeClause {
9490    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9491        let MergeClause {
9492            clause_kind,
9493            predicate,
9494            action,
9495        } = self;
9496
9497        write!(f, "WHEN {clause_kind}")?;
9498        if let Some(pred) = predicate {
9499            write!(f, " AND {pred}")?;
9500        }
9501        write!(f, " THEN {action}")
9502    }
9503}
9504
9505/// A Output Clause in the end of a 'MERGE' Statement
9506///
9507/// Example:
9508/// OUTPUT $action, deleted.* INTO dbo.temp_products;
9509/// [mssql](https://learn.microsoft.com/en-us/sql/t-sql/queries/output-clause-transact-sql)
9510#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9511#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9512#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9513pub enum OutputClause {
9514    Output {
9515        select_items: Vec<SelectItem>,
9516        into_table: Option<SelectInto>,
9517    },
9518    Returning {
9519        select_items: Vec<SelectItem>,
9520    },
9521}
9522
9523impl fmt::Display for OutputClause {
9524    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9525        match self {
9526            OutputClause::Output {
9527                select_items,
9528                into_table,
9529            } => {
9530                f.write_str("OUTPUT ")?;
9531                display_comma_separated(select_items).fmt(f)?;
9532                if let Some(into_table) = into_table {
9533                    f.write_str(" ")?;
9534                    into_table.fmt(f)?;
9535                }
9536                Ok(())
9537            }
9538            OutputClause::Returning { select_items } => {
9539                f.write_str("RETURNING ")?;
9540                display_comma_separated(select_items).fmt(f)
9541            }
9542        }
9543    }
9544}
9545
9546#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9547#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9548#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9549pub enum DiscardObject {
9550    ALL,
9551    PLANS,
9552    SEQUENCES,
9553    TEMP,
9554}
9555
9556impl fmt::Display for DiscardObject {
9557    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9558        match self {
9559            DiscardObject::ALL => f.write_str("ALL"),
9560            DiscardObject::PLANS => f.write_str("PLANS"),
9561            DiscardObject::SEQUENCES => f.write_str("SEQUENCES"),
9562            DiscardObject::TEMP => f.write_str("TEMP"),
9563        }
9564    }
9565}
9566
9567#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9568#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9569#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9570pub enum FlushType {
9571    BinaryLogs,
9572    EngineLogs,
9573    ErrorLogs,
9574    GeneralLogs,
9575    Hosts,
9576    Logs,
9577    Privileges,
9578    OptimizerCosts,
9579    RelayLogs,
9580    SlowLogs,
9581    Status,
9582    UserResources,
9583    Tables,
9584}
9585
9586impl fmt::Display for FlushType {
9587    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9588        match self {
9589            FlushType::BinaryLogs => f.write_str("BINARY LOGS"),
9590            FlushType::EngineLogs => f.write_str("ENGINE LOGS"),
9591            FlushType::ErrorLogs => f.write_str("ERROR LOGS"),
9592            FlushType::GeneralLogs => f.write_str("GENERAL LOGS"),
9593            FlushType::Hosts => f.write_str("HOSTS"),
9594            FlushType::Logs => f.write_str("LOGS"),
9595            FlushType::Privileges => f.write_str("PRIVILEGES"),
9596            FlushType::OptimizerCosts => f.write_str("OPTIMIZER_COSTS"),
9597            FlushType::RelayLogs => f.write_str("RELAY LOGS"),
9598            FlushType::SlowLogs => f.write_str("SLOW LOGS"),
9599            FlushType::Status => f.write_str("STATUS"),
9600            FlushType::UserResources => f.write_str("USER_RESOURCES"),
9601            FlushType::Tables => f.write_str("TABLES"),
9602        }
9603    }
9604}
9605
9606#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9607#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9608#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9609pub enum FlushLocation {
9610    NoWriteToBinlog,
9611    Local,
9612}
9613
9614impl fmt::Display for FlushLocation {
9615    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9616        match self {
9617            FlushLocation::NoWriteToBinlog => f.write_str("NO_WRITE_TO_BINLOG"),
9618            FlushLocation::Local => f.write_str("LOCAL"),
9619        }
9620    }
9621}
9622
9623/// Optional context modifier for statements that can be or `LOCAL`, `GLOBAL`, or `SESSION`.
9624#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9625#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9626#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9627pub enum ContextModifier {
9628    /// `LOCAL` identifier, usually related to transactional states.
9629    Local,
9630    /// `SESSION` identifier
9631    Session,
9632    /// `GLOBAL` identifier
9633    Global,
9634}
9635
9636impl fmt::Display for ContextModifier {
9637    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9638        match self {
9639            Self::Local => {
9640                write!(f, "LOCAL ")
9641            }
9642            Self::Session => {
9643                write!(f, "SESSION ")
9644            }
9645            Self::Global => {
9646                write!(f, "GLOBAL ")
9647            }
9648        }
9649    }
9650}
9651
9652/// Function describe in DROP FUNCTION.
9653#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9654#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9655pub enum DropFunctionOption {
9656    Restrict,
9657    Cascade,
9658}
9659
9660impl fmt::Display for DropFunctionOption {
9661    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9662        match self {
9663            DropFunctionOption::Restrict => write!(f, "RESTRICT "),
9664            DropFunctionOption::Cascade => write!(f, "CASCADE  "),
9665        }
9666    }
9667}
9668
9669/// Generic function description for DROP FUNCTION and CREATE TRIGGER.
9670#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9671#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9672#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9673pub struct FunctionDesc {
9674    pub name: ObjectName,
9675    pub args: Option<Vec<OperateFunctionArg>>,
9676}
9677
9678impl fmt::Display for FunctionDesc {
9679    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9680        write!(f, "{}", self.name)?;
9681        if let Some(args) = &self.args {
9682            write!(f, "({})", display_comma_separated(args))?;
9683        }
9684        Ok(())
9685    }
9686}
9687
9688/// Function argument in CREATE OR DROP FUNCTION.
9689#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9690#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9691#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9692pub struct OperateFunctionArg {
9693    pub mode: Option<ArgMode>,
9694    pub name: Option<Ident>,
9695    pub data_type: DataType,
9696    pub default_expr: Option<Expr>,
9697}
9698
9699impl OperateFunctionArg {
9700    /// Returns an unnamed argument.
9701    pub fn unnamed(data_type: DataType) -> Self {
9702        Self {
9703            mode: None,
9704            name: None,
9705            data_type,
9706            default_expr: None,
9707        }
9708    }
9709
9710    /// Returns an argument with name.
9711    pub fn with_name(name: &str, data_type: DataType) -> Self {
9712        Self {
9713            mode: None,
9714            name: Some(name.into()),
9715            data_type,
9716            default_expr: None,
9717        }
9718    }
9719}
9720
9721impl fmt::Display for OperateFunctionArg {
9722    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9723        if let Some(mode) = &self.mode {
9724            write!(f, "{mode} ")?;
9725        }
9726        if let Some(name) = &self.name {
9727            write!(f, "{name} ")?;
9728        }
9729        write!(f, "{}", self.data_type)?;
9730        if let Some(default_expr) = &self.default_expr {
9731            write!(f, " = {default_expr}")?;
9732        }
9733        Ok(())
9734    }
9735}
9736
9737/// The mode of an argument in CREATE FUNCTION.
9738#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9739#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9740#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9741pub enum ArgMode {
9742    In,
9743    Out,
9744    InOut,
9745}
9746
9747impl fmt::Display for ArgMode {
9748    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9749        match self {
9750            ArgMode::In => write!(f, "IN"),
9751            ArgMode::Out => write!(f, "OUT"),
9752            ArgMode::InOut => write!(f, "INOUT"),
9753        }
9754    }
9755}
9756
9757/// These attributes inform the query optimizer about the behavior of the function.
9758#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9759#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9760#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9761pub enum FunctionBehavior {
9762    Immutable,
9763    Stable,
9764    Volatile,
9765}
9766
9767impl fmt::Display for FunctionBehavior {
9768    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9769        match self {
9770            FunctionBehavior::Immutable => write!(f, "IMMUTABLE"),
9771            FunctionBehavior::Stable => write!(f, "STABLE"),
9772            FunctionBehavior::Volatile => write!(f, "VOLATILE"),
9773        }
9774    }
9775}
9776
9777/// These attributes describe the behavior of the function when called with a null argument.
9778#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9779#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9780#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9781pub enum FunctionCalledOnNull {
9782    CalledOnNullInput,
9783    ReturnsNullOnNullInput,
9784    Strict,
9785}
9786
9787impl fmt::Display for FunctionCalledOnNull {
9788    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9789        match self {
9790            FunctionCalledOnNull::CalledOnNullInput => write!(f, "CALLED ON NULL INPUT"),
9791            FunctionCalledOnNull::ReturnsNullOnNullInput => write!(f, "RETURNS NULL ON NULL INPUT"),
9792            FunctionCalledOnNull::Strict => write!(f, "STRICT"),
9793        }
9794    }
9795}
9796
9797/// If it is safe for PostgreSQL to call the function from multiple threads at once
9798#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9799#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9800#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9801pub enum FunctionParallel {
9802    Unsafe,
9803    Restricted,
9804    Safe,
9805}
9806
9807impl fmt::Display for FunctionParallel {
9808    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9809        match self {
9810            FunctionParallel::Unsafe => write!(f, "PARALLEL UNSAFE"),
9811            FunctionParallel::Restricted => write!(f, "PARALLEL RESTRICTED"),
9812            FunctionParallel::Safe => write!(f, "PARALLEL SAFE"),
9813        }
9814    }
9815}
9816
9817/// [BigQuery] Determinism specifier used in a UDF definition.
9818///
9819/// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#syntax_11
9820#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9821#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9822#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9823pub enum FunctionDeterminismSpecifier {
9824    Deterministic,
9825    NotDeterministic,
9826}
9827
9828impl fmt::Display for FunctionDeterminismSpecifier {
9829    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9830        match self {
9831            FunctionDeterminismSpecifier::Deterministic => {
9832                write!(f, "DETERMINISTIC")
9833            }
9834            FunctionDeterminismSpecifier::NotDeterministic => {
9835                write!(f, "NOT DETERMINISTIC")
9836            }
9837        }
9838    }
9839}
9840
9841/// Represent the expression body of a `CREATE FUNCTION` statement as well as
9842/// where within the statement, the body shows up.
9843///
9844/// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#syntax_11
9845/// [PostgreSQL]: https://www.postgresql.org/docs/15/sql-createfunction.html
9846/// [MsSql]: https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql
9847#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9848#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9849#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9850pub enum CreateFunctionBody {
9851    /// A function body expression using the 'AS' keyword and shows up
9852    /// before any `OPTIONS` clause.
9853    ///
9854    /// Example:
9855    /// ```sql
9856    /// CREATE FUNCTION myfunc(x FLOAT64, y FLOAT64) RETURNS FLOAT64
9857    /// AS (x * y)
9858    /// OPTIONS(description="desc");
9859    /// ```
9860    ///
9861    /// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#syntax_11
9862    AsBeforeOptions(Expr),
9863    /// A function body expression using the 'AS' keyword and shows up
9864    /// after any `OPTIONS` clause.
9865    ///
9866    /// Example:
9867    /// ```sql
9868    /// CREATE FUNCTION myfunc(x FLOAT64, y FLOAT64) RETURNS FLOAT64
9869    /// OPTIONS(description="desc")
9870    /// AS (x * y);
9871    /// ```
9872    ///
9873    /// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#syntax_11
9874    AsAfterOptions(Expr),
9875    /// Function body with statements before the `RETURN` keyword.
9876    ///
9877    /// Example:
9878    /// ```sql
9879    /// CREATE FUNCTION my_scalar_udf(a INT, b INT)
9880    /// RETURNS INT
9881    /// AS
9882    /// BEGIN
9883    ///     DECLARE c INT;
9884    ///     SET c = a + b;
9885    ///     RETURN c;
9886    /// END
9887    /// ```
9888    ///
9889    /// [MsSql]: https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql
9890    AsBeginEnd(BeginEndStatements),
9891    /// Function body expression using the 'RETURN' keyword.
9892    ///
9893    /// Example:
9894    /// ```sql
9895    /// CREATE FUNCTION myfunc(a INTEGER, IN b INTEGER = 1) RETURNS INTEGER
9896    /// LANGUAGE SQL
9897    /// RETURN a + b;
9898    /// ```
9899    ///
9900    /// [PostgreSQL]: https://www.postgresql.org/docs/current/sql-createfunction.html
9901    Return(Expr),
9902
9903    /// Function body expression using the 'AS RETURN' keywords
9904    ///
9905    /// Example:
9906    /// ```sql
9907    /// CREATE FUNCTION myfunc(a INT, b INT)
9908    /// RETURNS TABLE
9909    /// AS RETURN (SELECT a + b AS sum);
9910    /// ```
9911    ///
9912    /// [MsSql]: https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql
9913    AsReturnExpr(Expr),
9914
9915    /// Function body expression using the 'AS RETURN' keywords, with an un-parenthesized SELECT query
9916    ///
9917    /// Example:
9918    /// ```sql
9919    /// CREATE FUNCTION myfunc(a INT, b INT)
9920    /// RETURNS TABLE
9921    /// AS RETURN SELECT a + b AS sum;
9922    /// ```
9923    ///
9924    /// [MsSql]: https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql?view=sql-server-ver16#select_stmt
9925    AsReturnSelect(Select),
9926}
9927
9928#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9929#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9930#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9931pub enum CreateFunctionUsing {
9932    Jar(String),
9933    File(String),
9934    Archive(String),
9935}
9936
9937impl fmt::Display for CreateFunctionUsing {
9938    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9939        write!(f, "USING ")?;
9940        match self {
9941            CreateFunctionUsing::Jar(uri) => write!(f, "JAR '{uri}'"),
9942            CreateFunctionUsing::File(uri) => write!(f, "FILE '{uri}'"),
9943            CreateFunctionUsing::Archive(uri) => write!(f, "ARCHIVE '{uri}'"),
9944        }
9945    }
9946}
9947
9948/// `NAME = <EXPR>` arguments for DuckDB macros
9949///
9950/// See [Create Macro - DuckDB](https://duckdb.org/docs/sql/statements/create_macro)
9951/// for more details
9952#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9953#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9954#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9955pub struct MacroArg {
9956    pub name: Ident,
9957    pub default_expr: Option<Expr>,
9958}
9959
9960impl MacroArg {
9961    /// Returns an argument with name.
9962    pub fn new(name: &str) -> Self {
9963        Self {
9964            name: name.into(),
9965            default_expr: None,
9966        }
9967    }
9968}
9969
9970impl fmt::Display for MacroArg {
9971    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9972        write!(f, "{}", self.name)?;
9973        if let Some(default_expr) = &self.default_expr {
9974            write!(f, " := {default_expr}")?;
9975        }
9976        Ok(())
9977    }
9978}
9979
9980#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9981#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9982#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9983pub enum MacroDefinition {
9984    Expr(Expr),
9985    Table(Box<Query>),
9986}
9987
9988impl fmt::Display for MacroDefinition {
9989    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9990        match self {
9991            MacroDefinition::Expr(expr) => write!(f, "{expr}")?,
9992            MacroDefinition::Table(query) => write!(f, "{query}")?,
9993        }
9994        Ok(())
9995    }
9996}
9997
9998/// Schema possible naming variants ([1]).
9999///
10000/// [1]: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#schema-definition
10001#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10002#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10003#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10004pub enum SchemaName {
10005    /// Only schema name specified: `<schema name>`.
10006    Simple(ObjectName),
10007    /// Only authorization identifier specified: `AUTHORIZATION <schema authorization identifier>`.
10008    UnnamedAuthorization(Ident),
10009    /// Both schema name and authorization identifier specified: `<schema name>  AUTHORIZATION <schema authorization identifier>`.
10010    NamedAuthorization(ObjectName, Ident),
10011}
10012
10013impl fmt::Display for SchemaName {
10014    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10015        match self {
10016            SchemaName::Simple(name) => {
10017                write!(f, "{name}")
10018            }
10019            SchemaName::UnnamedAuthorization(authorization) => {
10020                write!(f, "AUTHORIZATION {authorization}")
10021            }
10022            SchemaName::NamedAuthorization(name, authorization) => {
10023                write!(f, "{name} AUTHORIZATION {authorization}")
10024            }
10025        }
10026    }
10027}
10028
10029/// Fulltext search modifiers ([1]).
10030///
10031/// [1]: https://dev.mysql.com/doc/refman/8.0/en/fulltext-search.html#function_match
10032#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10033#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10034#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10035pub enum SearchModifier {
10036    /// `IN NATURAL LANGUAGE MODE`.
10037    InNaturalLanguageMode,
10038    /// `IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION`.
10039    InNaturalLanguageModeWithQueryExpansion,
10040    ///`IN BOOLEAN MODE`.
10041    InBooleanMode,
10042    ///`WITH QUERY EXPANSION`.
10043    WithQueryExpansion,
10044}
10045
10046impl fmt::Display for SearchModifier {
10047    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10048        match self {
10049            Self::InNaturalLanguageMode => {
10050                write!(f, "IN NATURAL LANGUAGE MODE")?;
10051            }
10052            Self::InNaturalLanguageModeWithQueryExpansion => {
10053                write!(f, "IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION")?;
10054            }
10055            Self::InBooleanMode => {
10056                write!(f, "IN BOOLEAN MODE")?;
10057            }
10058            Self::WithQueryExpansion => {
10059                write!(f, "WITH QUERY EXPANSION")?;
10060            }
10061        }
10062
10063        Ok(())
10064    }
10065}
10066
10067#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10068#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10069#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10070pub struct LockTable {
10071    pub table: Ident,
10072    pub alias: Option<Ident>,
10073    pub lock_type: LockTableType,
10074}
10075
10076impl fmt::Display for LockTable {
10077    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10078        let Self {
10079            table: tbl_name,
10080            alias,
10081            lock_type,
10082        } = self;
10083
10084        write!(f, "{tbl_name} ")?;
10085        if let Some(alias) = alias {
10086            write!(f, "AS {alias} ")?;
10087        }
10088        write!(f, "{lock_type}")?;
10089        Ok(())
10090    }
10091}
10092
10093#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10094#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10095#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10096pub enum LockTableType {
10097    Read { local: bool },
10098    Write { low_priority: bool },
10099}
10100
10101impl fmt::Display for LockTableType {
10102    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10103        match self {
10104            Self::Read { local } => {
10105                write!(f, "READ")?;
10106                if *local {
10107                    write!(f, " LOCAL")?;
10108                }
10109            }
10110            Self::Write { low_priority } => {
10111                if *low_priority {
10112                    write!(f, "LOW_PRIORITY ")?;
10113                }
10114                write!(f, "WRITE")?;
10115            }
10116        }
10117
10118        Ok(())
10119    }
10120}
10121
10122#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10123#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10124#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10125pub struct HiveSetLocation {
10126    pub has_set: bool,
10127    pub location: Ident,
10128}
10129
10130impl fmt::Display for HiveSetLocation {
10131    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10132        if self.has_set {
10133            write!(f, "SET ")?;
10134        }
10135        write!(f, "LOCATION {}", self.location)
10136    }
10137}
10138
10139/// MySQL `ALTER TABLE` only  [FIRST | AFTER column_name]
10140#[allow(clippy::large_enum_variant)]
10141#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10142#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10143#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10144pub enum MySQLColumnPosition {
10145    First,
10146    After(Ident),
10147}
10148
10149impl Display for MySQLColumnPosition {
10150    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10151        match self {
10152            MySQLColumnPosition::First => write!(f, "FIRST"),
10153            MySQLColumnPosition::After(ident) => {
10154                let column_name = &ident.value;
10155                write!(f, "AFTER {column_name}")
10156            }
10157        }
10158    }
10159}
10160
10161/// MySQL `CREATE VIEW` algorithm parameter: [ALGORITHM = {UNDEFINED | MERGE | TEMPTABLE}]
10162#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10163#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10164#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10165pub enum CreateViewAlgorithm {
10166    Undefined,
10167    Merge,
10168    TempTable,
10169}
10170
10171impl Display for CreateViewAlgorithm {
10172    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10173        match self {
10174            CreateViewAlgorithm::Undefined => write!(f, "UNDEFINED"),
10175            CreateViewAlgorithm::Merge => write!(f, "MERGE"),
10176            CreateViewAlgorithm::TempTable => write!(f, "TEMPTABLE"),
10177        }
10178    }
10179}
10180/// MySQL `CREATE VIEW` security parameter: [SQL SECURITY { DEFINER | INVOKER }]
10181#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10182#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10183#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10184pub enum CreateViewSecurity {
10185    Definer,
10186    Invoker,
10187}
10188
10189impl Display for CreateViewSecurity {
10190    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10191        match self {
10192            CreateViewSecurity::Definer => write!(f, "DEFINER"),
10193            CreateViewSecurity::Invoker => write!(f, "INVOKER"),
10194        }
10195    }
10196}
10197
10198/// [MySQL] `CREATE VIEW` additional parameters
10199///
10200/// [MySQL]: https://dev.mysql.com/doc/refman/9.1/en/create-view.html
10201#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10202#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10203#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10204pub struct CreateViewParams {
10205    pub algorithm: Option<CreateViewAlgorithm>,
10206    pub definer: Option<GranteeName>,
10207    pub security: Option<CreateViewSecurity>,
10208}
10209
10210impl Display for CreateViewParams {
10211    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10212        let CreateViewParams {
10213            algorithm,
10214            definer,
10215            security,
10216        } = self;
10217        if let Some(algorithm) = algorithm {
10218            write!(f, "ALGORITHM = {algorithm} ")?;
10219        }
10220        if let Some(definers) = definer {
10221            write!(f, "DEFINER = {definers} ")?;
10222        }
10223        if let Some(security) = security {
10224            write!(f, "SQL SECURITY {security} ")?;
10225        }
10226        Ok(())
10227    }
10228}
10229
10230#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10231#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10232#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10233/// Key/Value, where the value is a (optionally named) list of identifiers
10234///
10235/// ```sql
10236/// UNION = (tbl_name[,tbl_name]...)
10237/// ENGINE = ReplicatedMergeTree('/table_name','{replica}', ver)
10238/// ENGINE = SummingMergeTree([columns])
10239/// ```
10240pub struct NamedParenthesizedList {
10241    pub key: Ident,
10242    pub name: Option<Ident>,
10243    pub values: Vec<Ident>,
10244}
10245
10246/// Snowflake `WITH ROW ACCESS POLICY policy_name ON (identifier, ...)`
10247///
10248/// <https://docs.snowflake.com/en/sql-reference/sql/create-table>
10249/// <https://docs.snowflake.com/en/user-guide/security-row-intro>
10250#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10251#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10252#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10253pub struct RowAccessPolicy {
10254    pub policy: ObjectName,
10255    pub on: Vec<Ident>,
10256}
10257
10258impl RowAccessPolicy {
10259    pub fn new(policy: ObjectName, on: Vec<Ident>) -> Self {
10260        Self { policy, on }
10261    }
10262}
10263
10264impl Display for RowAccessPolicy {
10265    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10266        write!(
10267            f,
10268            "WITH ROW ACCESS POLICY {} ON ({})",
10269            self.policy,
10270            display_comma_separated(self.on.as_slice())
10271        )
10272    }
10273}
10274
10275/// Snowflake `WITH TAG ( tag_name = '<tag_value>', ...)`
10276///
10277/// <https://docs.snowflake.com/en/sql-reference/sql/create-table>
10278#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10279#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10280#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10281pub struct Tag {
10282    pub key: ObjectName,
10283    pub value: String,
10284}
10285
10286impl Tag {
10287    pub fn new(key: ObjectName, value: String) -> Self {
10288        Self { key, value }
10289    }
10290}
10291
10292impl Display for Tag {
10293    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10294        write!(f, "{}='{}'", self.key, self.value)
10295    }
10296}
10297
10298/// Snowflake `WITH CONTACT ( purpose = contact [ , purpose = contact ...] )`
10299///
10300/// <https://docs.snowflake.com/en/sql-reference/sql/create-database>
10301#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10302#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10303#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10304pub struct ContactEntry {
10305    pub purpose: String,
10306    pub contact: String,
10307}
10308
10309impl Display for ContactEntry {
10310    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10311        write!(f, "{} = {}", self.purpose, self.contact)
10312    }
10313}
10314
10315/// Helper to indicate if a comment includes the `=` in the display form
10316#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10317#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10318#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10319pub enum CommentDef {
10320    /// Includes `=` when printing the comment, as `COMMENT = 'comment'`
10321    /// Does not include `=` when printing the comment, as `COMMENT 'comment'`
10322    WithEq(String),
10323    WithoutEq(String),
10324}
10325
10326impl Display for CommentDef {
10327    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10328        match self {
10329            CommentDef::WithEq(comment) | CommentDef::WithoutEq(comment) => write!(f, "{comment}"),
10330        }
10331    }
10332}
10333
10334/// Helper to indicate if a collection should be wrapped by a symbol in the display form
10335///
10336/// [`Display`] is implemented for every [`Vec<T>`] where `T: Display`.
10337/// The string output is a comma separated list for the vec items
10338///
10339/// # Examples
10340/// ```
10341/// # use sqlparser::ast::WrappedCollection;
10342/// let items = WrappedCollection::Parentheses(vec!["one", "two", "three"]);
10343/// assert_eq!("(one, two, three)", items.to_string());
10344///
10345/// let items = WrappedCollection::NoWrapping(vec!["one", "two", "three"]);
10346/// assert_eq!("one, two, three", items.to_string());
10347/// ```
10348#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10349#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10350#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10351pub enum WrappedCollection<T> {
10352    /// Print the collection without wrapping symbols, as `item, item, item`
10353    NoWrapping(T),
10354    /// Wraps the collection in Parentheses, as `(item, item, item)`
10355    Parentheses(T),
10356}
10357
10358impl<T> Display for WrappedCollection<Vec<T>>
10359where
10360    T: Display,
10361{
10362    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10363        match self {
10364            WrappedCollection::NoWrapping(inner) => {
10365                write!(f, "{}", display_comma_separated(inner.as_slice()))
10366            }
10367            WrappedCollection::Parentheses(inner) => {
10368                write!(f, "({})", display_comma_separated(inner.as_slice()))
10369            }
10370        }
10371    }
10372}
10373
10374/// Represents a single PostgreSQL utility option.
10375///
10376/// A utility option is a key-value pair where the key is an identifier (IDENT) and the value
10377/// can be one of the following:
10378/// - A number with an optional sign (`+` or `-`). Example: `+10`, `-10.2`, `3`
10379/// - A non-keyword string. Example: `option1`, `'option2'`, `"option3"`
10380/// - keyword: `TRUE`, `FALSE`, `ON` (`off` is also accept).
10381/// - Empty. Example: `ANALYZE` (identifier only)
10382///
10383/// Utility options are used in various PostgreSQL DDL statements, including statements such as
10384/// `CLUSTER`, `EXPLAIN`, `VACUUM`, and `REINDEX`. These statements format options as `( option [, ...] )`.
10385///
10386/// [CLUSTER](https://www.postgresql.org/docs/current/sql-cluster.html)
10387/// [EXPLAIN](https://www.postgresql.org/docs/current/sql-explain.html)
10388/// [VACUUM](https://www.postgresql.org/docs/current/sql-vacuum.html)
10389/// [REINDEX](https://www.postgresql.org/docs/current/sql-reindex.html)
10390///
10391/// For example, the `EXPLAIN` AND `VACUUM` statements with options might look like this:
10392/// ```sql
10393/// EXPLAIN (ANALYZE, VERBOSE TRUE, FORMAT TEXT) SELECT * FROM my_table;
10394///
10395/// VACUUM (VERBOSE, ANALYZE ON, PARALLEL 10) my_table;
10396/// ```
10397#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10398#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10399#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10400pub struct UtilityOption {
10401    pub name: Ident,
10402    pub arg: Option<Expr>,
10403}
10404
10405impl Display for UtilityOption {
10406    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10407        if let Some(ref arg) = self.arg {
10408            write!(f, "{} {}", self.name, arg)
10409        } else {
10410            write!(f, "{}", self.name)
10411        }
10412    }
10413}
10414
10415/// Represents the different options available for `SHOW`
10416/// statements to filter the results. Example from Snowflake:
10417/// <https://docs.snowflake.com/en/sql-reference/sql/show-tables>
10418#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10419#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10420#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10421pub struct ShowStatementOptions {
10422    pub show_in: Option<ShowStatementIn>,
10423    pub starts_with: Option<Value>,
10424    pub limit: Option<Expr>,
10425    pub limit_from: Option<Value>,
10426    pub filter_position: Option<ShowStatementFilterPosition>,
10427}
10428
10429impl Display for ShowStatementOptions {
10430    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10431        let (like_in_infix, like_in_suffix) = match &self.filter_position {
10432            Some(ShowStatementFilterPosition::Infix(filter)) => {
10433                (format!(" {filter}"), "".to_string())
10434            }
10435            Some(ShowStatementFilterPosition::Suffix(filter)) => {
10436                ("".to_string(), format!(" {filter}"))
10437            }
10438            None => ("".to_string(), "".to_string()),
10439        };
10440        write!(
10441            f,
10442            "{like_in_infix}{show_in}{starts_with}{limit}{from}{like_in_suffix}",
10443            show_in = match &self.show_in {
10444                Some(i) => format!(" {i}"),
10445                None => String::new(),
10446            },
10447            starts_with = match &self.starts_with {
10448                Some(s) => format!(" STARTS WITH {s}"),
10449                None => String::new(),
10450            },
10451            limit = match &self.limit {
10452                Some(l) => format!(" LIMIT {l}"),
10453                None => String::new(),
10454            },
10455            from = match &self.limit_from {
10456                Some(f) => format!(" FROM {f}"),
10457                None => String::new(),
10458            }
10459        )?;
10460        Ok(())
10461    }
10462}
10463
10464#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10465#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10466#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10467pub enum ShowStatementFilterPosition {
10468    Infix(ShowStatementFilter), // For example: SHOW COLUMNS LIKE '%name%' IN TABLE tbl
10469    Suffix(ShowStatementFilter), // For example: SHOW COLUMNS IN tbl LIKE '%name%'
10470}
10471
10472#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10473#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10474#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10475pub enum ShowStatementInParentType {
10476    Account,
10477    Database,
10478    Schema,
10479    Table,
10480    View,
10481}
10482
10483impl fmt::Display for ShowStatementInParentType {
10484    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10485        match self {
10486            ShowStatementInParentType::Account => write!(f, "ACCOUNT"),
10487            ShowStatementInParentType::Database => write!(f, "DATABASE"),
10488            ShowStatementInParentType::Schema => write!(f, "SCHEMA"),
10489            ShowStatementInParentType::Table => write!(f, "TABLE"),
10490            ShowStatementInParentType::View => write!(f, "VIEW"),
10491        }
10492    }
10493}
10494
10495#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10496#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10497#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10498pub struct ShowStatementIn {
10499    pub clause: ShowStatementInClause,
10500    pub parent_type: Option<ShowStatementInParentType>,
10501    #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
10502    pub parent_name: Option<ObjectName>,
10503}
10504
10505impl fmt::Display for ShowStatementIn {
10506    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10507        write!(f, "{}", self.clause)?;
10508        if let Some(parent_type) = &self.parent_type {
10509            write!(f, " {parent_type}")?;
10510        }
10511        if let Some(parent_name) = &self.parent_name {
10512            write!(f, " {parent_name}")?;
10513        }
10514        Ok(())
10515    }
10516}
10517
10518/// A Show Charset statement
10519#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10520#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10521#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10522pub struct ShowCharset {
10523    /// The statement can be written as `SHOW CHARSET` or `SHOW CHARACTER SET`
10524    /// true means CHARSET was used and false means CHARACTER SET was used
10525    pub is_shorthand: bool,
10526    pub filter: Option<ShowStatementFilter>,
10527}
10528
10529impl fmt::Display for ShowCharset {
10530    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10531        write!(f, "SHOW")?;
10532        if self.is_shorthand {
10533            write!(f, " CHARSET")?;
10534        } else {
10535            write!(f, " CHARACTER SET")?;
10536        }
10537        if self.filter.is_some() {
10538            write!(f, " {}", self.filter.as_ref().unwrap())?;
10539        }
10540        Ok(())
10541    }
10542}
10543
10544#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10545#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10546#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10547pub struct ShowObjects {
10548    pub terse: bool,
10549    pub show_options: ShowStatementOptions,
10550}
10551
10552/// MSSQL's json null clause
10553///
10554/// ```plaintext
10555/// <json_null_clause> ::=
10556///       NULL ON NULL
10557///     | ABSENT ON NULL
10558/// ```
10559///
10560/// <https://learn.microsoft.com/en-us/sql/t-sql/functions/json-object-transact-sql?view=sql-server-ver16#json_null_clause>
10561#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10562#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10563#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10564pub enum JsonNullClause {
10565    NullOnNull,
10566    AbsentOnNull,
10567}
10568
10569impl Display for JsonNullClause {
10570    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10571        match self {
10572            JsonNullClause::NullOnNull => write!(f, "NULL ON NULL"),
10573            JsonNullClause::AbsentOnNull => write!(f, "ABSENT ON NULL"),
10574        }
10575    }
10576}
10577
10578/// PostgreSQL JSON function RETURNING clause
10579///
10580/// Example:
10581/// ```sql
10582/// JSON_OBJECT('a': 1 RETURNING jsonb)
10583/// ```
10584#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10585#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10586#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10587pub struct JsonReturningClause {
10588    pub data_type: DataType,
10589}
10590
10591impl Display for JsonReturningClause {
10592    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10593        write!(f, "RETURNING {}", self.data_type)
10594    }
10595}
10596
10597/// rename object definition
10598#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10599#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10600#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10601pub struct RenameTable {
10602    pub old_name: ObjectName,
10603    pub new_name: ObjectName,
10604}
10605
10606impl fmt::Display for RenameTable {
10607    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10608        write!(f, "{} TO {}", self.old_name, self.new_name)?;
10609        Ok(())
10610    }
10611}
10612
10613/// Represents the referenced table in an `INSERT INTO` statement
10614#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10615#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10616#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10617pub enum TableObject {
10618    /// Table specified by name.
10619    /// Example:
10620    /// ```sql
10621    /// INSERT INTO my_table
10622    /// ```
10623    TableName(#[cfg_attr(feature = "visitor", visit(with = "visit_relation"))] ObjectName),
10624
10625    /// Table specified as a function.
10626    /// Example:
10627    /// ```sql
10628    /// INSERT INTO TABLE FUNCTION remote('localhost', default.simple_table)
10629    /// ```
10630    /// [Clickhouse](https://clickhouse.com/docs/en/sql-reference/table-functions)
10631    TableFunction(Function),
10632}
10633
10634impl fmt::Display for TableObject {
10635    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10636        match self {
10637            Self::TableName(table_name) => write!(f, "{table_name}"),
10638            Self::TableFunction(func) => write!(f, "FUNCTION {func}"),
10639        }
10640    }
10641}
10642
10643#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10644#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10645#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10646pub enum SetSessionParamKind {
10647    Generic(SetSessionParamGeneric),
10648    IdentityInsert(SetSessionParamIdentityInsert),
10649    Offsets(SetSessionParamOffsets),
10650    Statistics(SetSessionParamStatistics),
10651}
10652
10653impl fmt::Display for SetSessionParamKind {
10654    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10655        match self {
10656            SetSessionParamKind::Generic(x) => write!(f, "{x}"),
10657            SetSessionParamKind::IdentityInsert(x) => write!(f, "{x}"),
10658            SetSessionParamKind::Offsets(x) => write!(f, "{x}"),
10659            SetSessionParamKind::Statistics(x) => write!(f, "{x}"),
10660        }
10661    }
10662}
10663
10664#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10665#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10666#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10667pub struct SetSessionParamGeneric {
10668    pub names: Vec<String>,
10669    pub value: String,
10670}
10671
10672impl fmt::Display for SetSessionParamGeneric {
10673    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10674        write!(f, "{} {}", display_comma_separated(&self.names), self.value)
10675    }
10676}
10677
10678#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10679#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10680#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10681pub struct SetSessionParamIdentityInsert {
10682    pub obj: ObjectName,
10683    pub value: SessionParamValue,
10684}
10685
10686impl fmt::Display for SetSessionParamIdentityInsert {
10687    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10688        write!(f, "IDENTITY_INSERT {} {}", self.obj, self.value)
10689    }
10690}
10691
10692#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10693#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10694#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10695pub struct SetSessionParamOffsets {
10696    pub keywords: Vec<String>,
10697    pub value: SessionParamValue,
10698}
10699
10700impl fmt::Display for SetSessionParamOffsets {
10701    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10702        write!(
10703            f,
10704            "OFFSETS {} {}",
10705            display_comma_separated(&self.keywords),
10706            self.value
10707        )
10708    }
10709}
10710
10711#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10712#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10713#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10714pub struct SetSessionParamStatistics {
10715    pub topic: SessionParamStatsTopic,
10716    pub value: SessionParamValue,
10717}
10718
10719impl fmt::Display for SetSessionParamStatistics {
10720    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10721        write!(f, "STATISTICS {} {}", self.topic, self.value)
10722    }
10723}
10724
10725#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10726#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10727#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10728pub enum SessionParamStatsTopic {
10729    IO,
10730    Profile,
10731    Time,
10732    Xml,
10733}
10734
10735impl fmt::Display for SessionParamStatsTopic {
10736    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10737        match self {
10738            SessionParamStatsTopic::IO => write!(f, "IO"),
10739            SessionParamStatsTopic::Profile => write!(f, "PROFILE"),
10740            SessionParamStatsTopic::Time => write!(f, "TIME"),
10741            SessionParamStatsTopic::Xml => write!(f, "XML"),
10742        }
10743    }
10744}
10745
10746#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10747#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10748#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10749pub enum SessionParamValue {
10750    On,
10751    Off,
10752}
10753
10754impl fmt::Display for SessionParamValue {
10755    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10756        match self {
10757            SessionParamValue::On => write!(f, "ON"),
10758            SessionParamValue::Off => write!(f, "OFF"),
10759        }
10760    }
10761}
10762
10763/// Snowflake StorageSerializationPolicy for Iceberg Tables
10764/// ```sql
10765/// [ STORAGE_SERIALIZATION_POLICY = { COMPATIBLE | OPTIMIZED } ]
10766/// ```
10767///
10768/// <https://docs.snowflake.com/en/sql-reference/sql/create-iceberg-table>
10769#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10770#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10771#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10772pub enum StorageSerializationPolicy {
10773    Compatible,
10774    Optimized,
10775}
10776
10777impl Display for StorageSerializationPolicy {
10778    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10779        match self {
10780            StorageSerializationPolicy::Compatible => write!(f, "COMPATIBLE"),
10781            StorageSerializationPolicy::Optimized => write!(f, "OPTIMIZED"),
10782        }
10783    }
10784}
10785
10786/// Snowflake CatalogSyncNamespaceMode
10787/// ```sql
10788/// [ CATALOG_SYNC_NAMESPACE_MODE = { NEST | FLATTEN } ]
10789/// ```
10790///
10791/// <https://docs.snowflake.com/en/sql-reference/sql/create-database>
10792#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10793#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10794#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10795pub enum CatalogSyncNamespaceMode {
10796    Nest,
10797    Flatten,
10798}
10799
10800impl Display for CatalogSyncNamespaceMode {
10801    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10802        match self {
10803            CatalogSyncNamespaceMode::Nest => write!(f, "NEST"),
10804            CatalogSyncNamespaceMode::Flatten => write!(f, "FLATTEN"),
10805        }
10806    }
10807}
10808
10809/// Variants of the Snowflake `COPY INTO` statement
10810#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10811#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10812#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10813pub enum CopyIntoSnowflakeKind {
10814    /// Loads data from files to a table
10815    /// See: <https://docs.snowflake.com/en/sql-reference/sql/copy-into-table>
10816    Table,
10817    /// Unloads data from a table or query to external files
10818    /// See: <https://docs.snowflake.com/en/sql-reference/sql/copy-into-location>
10819    Location,
10820}
10821
10822#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10823#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10824#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10825pub struct PrintStatement {
10826    pub message: Box<Expr>,
10827}
10828
10829impl fmt::Display for PrintStatement {
10830    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10831        write!(f, "PRINT {}", self.message)
10832    }
10833}
10834
10835/// Represents a `Return` statement.
10836///
10837/// [MsSql triggers](https://learn.microsoft.com/en-us/sql/t-sql/statements/create-trigger-transact-sql)
10838/// [MsSql functions](https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql)
10839#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10840#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10841#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10842pub struct ReturnStatement {
10843    pub value: Option<ReturnStatementValue>,
10844}
10845
10846impl fmt::Display for ReturnStatement {
10847    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10848        match &self.value {
10849            Some(ReturnStatementValue::Expr(expr)) => write!(f, "RETURN {expr}"),
10850            None => write!(f, "RETURN"),
10851        }
10852    }
10853}
10854
10855/// Variants of a `RETURN` statement
10856#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10857#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10858#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10859pub enum ReturnStatementValue {
10860    Expr(Expr),
10861}
10862
10863/// Represents an `OPEN` statement.
10864#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10865#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10866#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10867pub struct OpenStatement {
10868    /// Cursor name
10869    pub cursor_name: Ident,
10870}
10871
10872impl fmt::Display for OpenStatement {
10873    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10874        write!(f, "OPEN {}", self.cursor_name)
10875    }
10876}
10877
10878/// Specifies Include / Exclude NULL within UNPIVOT command.
10879/// For example
10880/// `UNPIVOT (column1 FOR new_column IN (col3, col4, col5, col6))`
10881#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10882#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10883#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10884pub enum NullInclusion {
10885    IncludeNulls,
10886    ExcludeNulls,
10887}
10888
10889impl fmt::Display for NullInclusion {
10890    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10891        match self {
10892            NullInclusion::IncludeNulls => write!(f, "INCLUDE NULLS"),
10893            NullInclusion::ExcludeNulls => write!(f, "EXCLUDE NULLS"),
10894        }
10895    }
10896}
10897
10898/// Checks membership of a value in a JSON array
10899///
10900/// Syntax:
10901/// ```sql
10902/// <value> MEMBER OF(<array>)
10903/// ```
10904/// [MySQL](https://dev.mysql.com/doc/refman/8.4/en/json-search-functions.html#operator_member-of)
10905#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10906#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10907#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10908pub struct MemberOf {
10909    pub value: Box<Expr>,
10910    pub array: Box<Expr>,
10911}
10912
10913impl fmt::Display for MemberOf {
10914    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10915        write!(f, "{} MEMBER OF({})", self.value, self.array)
10916    }
10917}
10918
10919#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10920#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10921#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10922pub struct ExportData {
10923    pub options: Vec<SqlOption>,
10924    pub query: Box<Query>,
10925    pub connection: Option<ObjectName>,
10926}
10927
10928impl fmt::Display for ExportData {
10929    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10930        if let Some(connection) = &self.connection {
10931            write!(
10932                f,
10933                "EXPORT DATA WITH CONNECTION {connection} OPTIONS({}) AS {}",
10934                display_comma_separated(&self.options),
10935                self.query
10936            )
10937        } else {
10938            write!(
10939                f,
10940                "EXPORT DATA OPTIONS({}) AS {}",
10941                display_comma_separated(&self.options),
10942                self.query
10943            )
10944        }
10945    }
10946}
10947/// Creates a user
10948///
10949/// Syntax:
10950/// ```sql
10951/// CREATE [OR REPLACE] USER [IF NOT EXISTS] <name> [OPTIONS]
10952/// ```
10953///
10954/// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-user)
10955#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10956#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10957#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10958pub struct CreateUser {
10959    pub or_replace: bool,
10960    pub if_not_exists: bool,
10961    pub name: Ident,
10962    pub options: KeyValueOptions,
10963    pub with_tags: bool,
10964    pub tags: KeyValueOptions,
10965}
10966
10967impl fmt::Display for CreateUser {
10968    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10969        write!(f, "CREATE")?;
10970        if self.or_replace {
10971            write!(f, " OR REPLACE")?;
10972        }
10973        write!(f, " USER")?;
10974        if self.if_not_exists {
10975            write!(f, " IF NOT EXISTS")?;
10976        }
10977        write!(f, " {}", self.name)?;
10978        if !self.options.options.is_empty() {
10979            write!(f, " {}", self.options)?;
10980        }
10981        if !self.tags.options.is_empty() {
10982            if self.with_tags {
10983                write!(f, " WITH")?;
10984            }
10985            write!(f, " TAG ({})", self.tags)?;
10986        }
10987        Ok(())
10988    }
10989}
10990
10991/// Specifies how to create a new table based on an existing table's schema.
10992/// '''sql
10993/// CREATE TABLE new LIKE old ...
10994/// '''
10995#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10996#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10997#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10998pub enum CreateTableLikeKind {
10999    /// '''sql
11000    /// CREATE TABLE new (LIKE old ...)
11001    /// '''
11002    /// [Redshift](https://docs.aws.amazon.com/redshift/latest/dg/r_CREATE_TABLE_NEW.html)
11003    Parenthesized(CreateTableLike),
11004    /// '''sql
11005    /// CREATE TABLE new LIKE old ...
11006    /// '''
11007    /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-table#label-create-table-like)
11008    /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_table_like)
11009    Plain(CreateTableLike),
11010}
11011
11012#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11013#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11014#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11015pub enum CreateTableLikeDefaults {
11016    Including,
11017    Excluding,
11018}
11019
11020impl fmt::Display for CreateTableLikeDefaults {
11021    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11022        match self {
11023            CreateTableLikeDefaults::Including => write!(f, "INCLUDING DEFAULTS"),
11024            CreateTableLikeDefaults::Excluding => write!(f, "EXCLUDING DEFAULTS"),
11025        }
11026    }
11027}
11028
11029#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11030#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11031#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11032pub struct CreateTableLike {
11033    pub name: ObjectName,
11034    pub defaults: Option<CreateTableLikeDefaults>,
11035}
11036
11037impl fmt::Display for CreateTableLike {
11038    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11039        write!(f, "LIKE {}", self.name)?;
11040        if let Some(defaults) = &self.defaults {
11041            write!(f, " {defaults}")?;
11042        }
11043        Ok(())
11044    }
11045}
11046
11047/// Specifies the refresh mode for the dynamic table.
11048///
11049/// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-dynamic-table)
11050#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11051#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11052#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11053pub enum RefreshModeKind {
11054    Auto,
11055    Full,
11056    Incremental,
11057}
11058
11059impl fmt::Display for RefreshModeKind {
11060    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11061        match self {
11062            RefreshModeKind::Auto => write!(f, "AUTO"),
11063            RefreshModeKind::Full => write!(f, "FULL"),
11064            RefreshModeKind::Incremental => write!(f, "INCREMENTAL"),
11065        }
11066    }
11067}
11068
11069/// Specifies the behavior of the initial refresh of the dynamic table.
11070///
11071/// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-dynamic-table)
11072#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11073#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11074#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11075pub enum InitializeKind {
11076    OnCreate,
11077    OnSchedule,
11078}
11079
11080impl fmt::Display for InitializeKind {
11081    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11082        match self {
11083            InitializeKind::OnCreate => write!(f, "ON_CREATE"),
11084            InitializeKind::OnSchedule => write!(f, "ON_SCHEDULE"),
11085        }
11086    }
11087}
11088
11089/// Re-sorts rows and reclaims space in either a specified table or all tables in the current database
11090///
11091/// '''sql
11092/// VACUUM [ FULL | SORT ONLY | DELETE ONLY | REINDEX | RECLUSTER ] [ \[ table_name \] [ TO threshold PERCENT ] \[ BOOST \] ]
11093/// '''
11094/// [Redshift](https://docs.aws.amazon.com/redshift/latest/dg/r_VACUUM_command.html)
11095#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11096#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11097#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11098pub struct VacuumStatement {
11099    pub full: bool,
11100    pub sort_only: bool,
11101    pub delete_only: bool,
11102    pub reindex: bool,
11103    pub recluster: bool,
11104    pub table_name: Option<ObjectName>,
11105    pub threshold: Option<Value>,
11106    pub boost: bool,
11107}
11108
11109impl fmt::Display for VacuumStatement {
11110    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11111        write!(
11112            f,
11113            "VACUUM{}{}{}{}{}",
11114            if self.full { " FULL" } else { "" },
11115            if self.sort_only { " SORT ONLY" } else { "" },
11116            if self.delete_only { " DELETE ONLY" } else { "" },
11117            if self.reindex { " REINDEX" } else { "" },
11118            if self.recluster { " RECLUSTER" } else { "" },
11119        )?;
11120        if let Some(table_name) = &self.table_name {
11121            write!(f, " {table_name}")?;
11122        }
11123        if let Some(threshold) = &self.threshold {
11124            write!(f, " TO {threshold} PERCENT")?;
11125        }
11126        if self.boost {
11127            write!(f, " BOOST")?;
11128        }
11129        Ok(())
11130    }
11131}
11132
11133impl From<Set> for Statement {
11134    fn from(s: Set) -> Self {
11135        Self::Set(s)
11136    }
11137}
11138
11139impl From<Query> for Statement {
11140    fn from(q: Query) -> Self {
11141        Box::new(q).into()
11142    }
11143}
11144
11145impl From<Box<Query>> for Statement {
11146    fn from(q: Box<Query>) -> Self {
11147        Self::Query(q)
11148    }
11149}
11150
11151impl From<Insert> for Statement {
11152    fn from(i: Insert) -> Self {
11153        Self::Insert(i)
11154    }
11155}
11156
11157impl From<CaseStatement> for Statement {
11158    fn from(c: CaseStatement) -> Self {
11159        Self::Case(c)
11160    }
11161}
11162
11163impl From<IfStatement> for Statement {
11164    fn from(i: IfStatement) -> Self {
11165        Self::If(i)
11166    }
11167}
11168
11169impl From<WhileStatement> for Statement {
11170    fn from(w: WhileStatement) -> Self {
11171        Self::While(w)
11172    }
11173}
11174
11175impl From<RaiseStatement> for Statement {
11176    fn from(r: RaiseStatement) -> Self {
11177        Self::Raise(r)
11178    }
11179}
11180
11181impl From<Function> for Statement {
11182    fn from(f: Function) -> Self {
11183        Self::Call(f)
11184    }
11185}
11186
11187impl From<OpenStatement> for Statement {
11188    fn from(o: OpenStatement) -> Self {
11189        Self::Open(o)
11190    }
11191}
11192
11193impl From<Delete> for Statement {
11194    fn from(d: Delete) -> Self {
11195        Self::Delete(d)
11196    }
11197}
11198
11199impl From<CreateTable> for Statement {
11200    fn from(c: CreateTable) -> Self {
11201        Self::CreateTable(c)
11202    }
11203}
11204
11205impl From<CreateIndex> for Statement {
11206    fn from(c: CreateIndex) -> Self {
11207        Self::CreateIndex(c)
11208    }
11209}
11210
11211impl From<CreateServerStatement> for Statement {
11212    fn from(c: CreateServerStatement) -> Self {
11213        Self::CreateServer(c)
11214    }
11215}
11216
11217impl From<CreateConnector> for Statement {
11218    fn from(c: CreateConnector) -> Self {
11219        Self::CreateConnector(c)
11220    }
11221}
11222
11223impl From<AlterSchema> for Statement {
11224    fn from(a: AlterSchema) -> Self {
11225        Self::AlterSchema(a)
11226    }
11227}
11228
11229impl From<AlterType> for Statement {
11230    fn from(a: AlterType) -> Self {
11231        Self::AlterType(a)
11232    }
11233}
11234
11235impl From<DropDomain> for Statement {
11236    fn from(d: DropDomain) -> Self {
11237        Self::DropDomain(d)
11238    }
11239}
11240
11241impl From<ShowCharset> for Statement {
11242    fn from(s: ShowCharset) -> Self {
11243        Self::ShowCharset(s)
11244    }
11245}
11246
11247impl From<ShowObjects> for Statement {
11248    fn from(s: ShowObjects) -> Self {
11249        Self::ShowObjects(s)
11250    }
11251}
11252
11253impl From<Use> for Statement {
11254    fn from(u: Use) -> Self {
11255        Self::Use(u)
11256    }
11257}
11258
11259impl From<CreateFunction> for Statement {
11260    fn from(c: CreateFunction) -> Self {
11261        Self::CreateFunction(c)
11262    }
11263}
11264
11265impl From<CreateTrigger> for Statement {
11266    fn from(c: CreateTrigger) -> Self {
11267        Self::CreateTrigger(c)
11268    }
11269}
11270
11271impl From<DropTrigger> for Statement {
11272    fn from(d: DropTrigger) -> Self {
11273        Self::DropTrigger(d)
11274    }
11275}
11276
11277impl From<DenyStatement> for Statement {
11278    fn from(d: DenyStatement) -> Self {
11279        Self::Deny(d)
11280    }
11281}
11282
11283impl From<CreateDomain> for Statement {
11284    fn from(c: CreateDomain) -> Self {
11285        Self::CreateDomain(c)
11286    }
11287}
11288
11289impl From<RenameTable> for Statement {
11290    fn from(r: RenameTable) -> Self {
11291        vec![r].into()
11292    }
11293}
11294
11295impl From<Vec<RenameTable>> for Statement {
11296    fn from(r: Vec<RenameTable>) -> Self {
11297        Self::RenameTable(r)
11298    }
11299}
11300
11301impl From<PrintStatement> for Statement {
11302    fn from(p: PrintStatement) -> Self {
11303        Self::Print(p)
11304    }
11305}
11306
11307impl From<ReturnStatement> for Statement {
11308    fn from(r: ReturnStatement) -> Self {
11309        Self::Return(r)
11310    }
11311}
11312
11313impl From<ExportData> for Statement {
11314    fn from(e: ExportData) -> Self {
11315        Self::ExportData(e)
11316    }
11317}
11318
11319impl From<CreateUser> for Statement {
11320    fn from(c: CreateUser) -> Self {
11321        Self::CreateUser(c)
11322    }
11323}
11324
11325impl From<VacuumStatement> for Statement {
11326    fn from(v: VacuumStatement) -> Self {
11327        Self::Vacuum(v)
11328    }
11329}
11330
11331#[cfg(test)]
11332mod tests {
11333    use crate::tokenizer::Location;
11334
11335    use super::*;
11336
11337    #[test]
11338    fn test_window_frame_default() {
11339        let window_frame = WindowFrame::default();
11340        assert_eq!(WindowFrameBound::Preceding(None), window_frame.start_bound);
11341    }
11342
11343    #[test]
11344    fn test_grouping_sets_display() {
11345        // a and b in different group
11346        let grouping_sets = Expr::GroupingSets(vec![
11347            vec![Expr::Identifier(Ident::new("a"))],
11348            vec![Expr::Identifier(Ident::new("b"))],
11349        ]);
11350        assert_eq!("GROUPING SETS ((a), (b))", format!("{grouping_sets}"));
11351
11352        // a and b in the same group
11353        let grouping_sets = Expr::GroupingSets(vec![vec![
11354            Expr::Identifier(Ident::new("a")),
11355            Expr::Identifier(Ident::new("b")),
11356        ]]);
11357        assert_eq!("GROUPING SETS ((a, b))", format!("{grouping_sets}"));
11358
11359        // (a, b) and (c, d) in different group
11360        let grouping_sets = Expr::GroupingSets(vec![
11361            vec![
11362                Expr::Identifier(Ident::new("a")),
11363                Expr::Identifier(Ident::new("b")),
11364            ],
11365            vec![
11366                Expr::Identifier(Ident::new("c")),
11367                Expr::Identifier(Ident::new("d")),
11368            ],
11369        ]);
11370        assert_eq!("GROUPING SETS ((a, b), (c, d))", format!("{grouping_sets}"));
11371    }
11372
11373    #[test]
11374    fn test_rollup_display() {
11375        let rollup = Expr::Rollup(vec![vec![Expr::Identifier(Ident::new("a"))]]);
11376        assert_eq!("ROLLUP (a)", format!("{rollup}"));
11377
11378        let rollup = Expr::Rollup(vec![vec![
11379            Expr::Identifier(Ident::new("a")),
11380            Expr::Identifier(Ident::new("b")),
11381        ]]);
11382        assert_eq!("ROLLUP ((a, b))", format!("{rollup}"));
11383
11384        let rollup = Expr::Rollup(vec![
11385            vec![Expr::Identifier(Ident::new("a"))],
11386            vec![Expr::Identifier(Ident::new("b"))],
11387        ]);
11388        assert_eq!("ROLLUP (a, b)", format!("{rollup}"));
11389
11390        let rollup = Expr::Rollup(vec![
11391            vec![Expr::Identifier(Ident::new("a"))],
11392            vec![
11393                Expr::Identifier(Ident::new("b")),
11394                Expr::Identifier(Ident::new("c")),
11395            ],
11396            vec![Expr::Identifier(Ident::new("d"))],
11397        ]);
11398        assert_eq!("ROLLUP (a, (b, c), d)", format!("{rollup}"));
11399    }
11400
11401    #[test]
11402    fn test_cube_display() {
11403        let cube = Expr::Cube(vec![vec![Expr::Identifier(Ident::new("a"))]]);
11404        assert_eq!("CUBE (a)", format!("{cube}"));
11405
11406        let cube = Expr::Cube(vec![vec![
11407            Expr::Identifier(Ident::new("a")),
11408            Expr::Identifier(Ident::new("b")),
11409        ]]);
11410        assert_eq!("CUBE ((a, b))", format!("{cube}"));
11411
11412        let cube = Expr::Cube(vec![
11413            vec![Expr::Identifier(Ident::new("a"))],
11414            vec![Expr::Identifier(Ident::new("b"))],
11415        ]);
11416        assert_eq!("CUBE (a, b)", format!("{cube}"));
11417
11418        let cube = Expr::Cube(vec![
11419            vec![Expr::Identifier(Ident::new("a"))],
11420            vec![
11421                Expr::Identifier(Ident::new("b")),
11422                Expr::Identifier(Ident::new("c")),
11423            ],
11424            vec![Expr::Identifier(Ident::new("d"))],
11425        ]);
11426        assert_eq!("CUBE (a, (b, c), d)", format!("{cube}"));
11427    }
11428
11429    #[test]
11430    fn test_interval_display() {
11431        let interval = Expr::Interval(Interval {
11432            value: Box::new(Expr::Value(
11433                Value::SingleQuotedString(String::from("123:45.67")).with_empty_span(),
11434            )),
11435            leading_field: Some(DateTimeField::Minute),
11436            leading_precision: Some(10),
11437            last_field: Some(DateTimeField::Second),
11438            fractional_seconds_precision: Some(9),
11439        });
11440        assert_eq!(
11441            "INTERVAL '123:45.67' MINUTE (10) TO SECOND (9)",
11442            format!("{interval}"),
11443        );
11444
11445        let interval = Expr::Interval(Interval {
11446            value: Box::new(Expr::Value(
11447                Value::SingleQuotedString(String::from("5")).with_empty_span(),
11448            )),
11449            leading_field: Some(DateTimeField::Second),
11450            leading_precision: Some(1),
11451            last_field: None,
11452            fractional_seconds_precision: Some(3),
11453        });
11454        assert_eq!("INTERVAL '5' SECOND (1, 3)", format!("{interval}"));
11455    }
11456
11457    #[test]
11458    fn test_one_or_many_with_parens_deref() {
11459        use core::ops::Index;
11460
11461        let one = OneOrManyWithParens::One("a");
11462
11463        assert_eq!(one.deref(), &["a"]);
11464        assert_eq!(<OneOrManyWithParens<_> as Deref>::deref(&one), &["a"]);
11465
11466        assert_eq!(one[0], "a");
11467        assert_eq!(one.index(0), &"a");
11468        assert_eq!(
11469            <<OneOrManyWithParens<_> as Deref>::Target as Index<usize>>::index(&one, 0),
11470            &"a"
11471        );
11472
11473        assert_eq!(one.len(), 1);
11474        assert_eq!(<OneOrManyWithParens<_> as Deref>::Target::len(&one), 1);
11475
11476        let many1 = OneOrManyWithParens::Many(vec!["b"]);
11477
11478        assert_eq!(many1.deref(), &["b"]);
11479        assert_eq!(<OneOrManyWithParens<_> as Deref>::deref(&many1), &["b"]);
11480
11481        assert_eq!(many1[0], "b");
11482        assert_eq!(many1.index(0), &"b");
11483        assert_eq!(
11484            <<OneOrManyWithParens<_> as Deref>::Target as Index<usize>>::index(&many1, 0),
11485            &"b"
11486        );
11487
11488        assert_eq!(many1.len(), 1);
11489        assert_eq!(<OneOrManyWithParens<_> as Deref>::Target::len(&many1), 1);
11490
11491        let many2 = OneOrManyWithParens::Many(vec!["c", "d"]);
11492
11493        assert_eq!(many2.deref(), &["c", "d"]);
11494        assert_eq!(
11495            <OneOrManyWithParens<_> as Deref>::deref(&many2),
11496            &["c", "d"]
11497        );
11498
11499        assert_eq!(many2[0], "c");
11500        assert_eq!(many2.index(0), &"c");
11501        assert_eq!(
11502            <<OneOrManyWithParens<_> as Deref>::Target as Index<usize>>::index(&many2, 0),
11503            &"c"
11504        );
11505
11506        assert_eq!(many2[1], "d");
11507        assert_eq!(many2.index(1), &"d");
11508        assert_eq!(
11509            <<OneOrManyWithParens<_> as Deref>::Target as Index<usize>>::index(&many2, 1),
11510            &"d"
11511        );
11512
11513        assert_eq!(many2.len(), 2);
11514        assert_eq!(<OneOrManyWithParens<_> as Deref>::Target::len(&many2), 2);
11515    }
11516
11517    #[test]
11518    fn test_one_or_many_with_parens_as_ref() {
11519        let one = OneOrManyWithParens::One("a");
11520
11521        assert_eq!(one.as_ref(), &["a"]);
11522        assert_eq!(<OneOrManyWithParens<_> as AsRef<_>>::as_ref(&one), &["a"]);
11523
11524        let many1 = OneOrManyWithParens::Many(vec!["b"]);
11525
11526        assert_eq!(many1.as_ref(), &["b"]);
11527        assert_eq!(<OneOrManyWithParens<_> as AsRef<_>>::as_ref(&many1), &["b"]);
11528
11529        let many2 = OneOrManyWithParens::Many(vec!["c", "d"]);
11530
11531        assert_eq!(many2.as_ref(), &["c", "d"]);
11532        assert_eq!(
11533            <OneOrManyWithParens<_> as AsRef<_>>::as_ref(&many2),
11534            &["c", "d"]
11535        );
11536    }
11537
11538    #[test]
11539    fn test_one_or_many_with_parens_ref_into_iter() {
11540        let one = OneOrManyWithParens::One("a");
11541
11542        assert_eq!(Vec::from_iter(&one), vec![&"a"]);
11543
11544        let many1 = OneOrManyWithParens::Many(vec!["b"]);
11545
11546        assert_eq!(Vec::from_iter(&many1), vec![&"b"]);
11547
11548        let many2 = OneOrManyWithParens::Many(vec!["c", "d"]);
11549
11550        assert_eq!(Vec::from_iter(&many2), vec![&"c", &"d"]);
11551    }
11552
11553    #[test]
11554    fn test_one_or_many_with_parens_value_into_iter() {
11555        use core::iter::once;
11556
11557        //tests that our iterator implemented methods behaves exactly as it's inner iterator, at every step up to n calls to next/next_back
11558        fn test_steps<I>(ours: OneOrManyWithParens<usize>, inner: I, n: usize)
11559        where
11560            I: IntoIterator<Item = usize, IntoIter: DoubleEndedIterator + Clone> + Clone,
11561        {
11562            fn checks<I>(ours: OneOrManyWithParensIntoIter<usize>, inner: I)
11563            where
11564                I: Iterator<Item = usize> + Clone + DoubleEndedIterator,
11565            {
11566                assert_eq!(ours.size_hint(), inner.size_hint());
11567                assert_eq!(ours.clone().count(), inner.clone().count());
11568
11569                assert_eq!(
11570                    ours.clone().fold(1, |a, v| a + v),
11571                    inner.clone().fold(1, |a, v| a + v)
11572                );
11573
11574                assert_eq!(Vec::from_iter(ours.clone()), Vec::from_iter(inner.clone()));
11575                assert_eq!(
11576                    Vec::from_iter(ours.clone().rev()),
11577                    Vec::from_iter(inner.clone().rev())
11578                );
11579            }
11580
11581            let mut ours_next = ours.clone().into_iter();
11582            let mut inner_next = inner.clone().into_iter();
11583
11584            for _ in 0..n {
11585                checks(ours_next.clone(), inner_next.clone());
11586
11587                assert_eq!(ours_next.next(), inner_next.next());
11588            }
11589
11590            let mut ours_next_back = ours.clone().into_iter();
11591            let mut inner_next_back = inner.clone().into_iter();
11592
11593            for _ in 0..n {
11594                checks(ours_next_back.clone(), inner_next_back.clone());
11595
11596                assert_eq!(ours_next_back.next_back(), inner_next_back.next_back());
11597            }
11598
11599            let mut ours_mixed = ours.clone().into_iter();
11600            let mut inner_mixed = inner.clone().into_iter();
11601
11602            for i in 0..n {
11603                checks(ours_mixed.clone(), inner_mixed.clone());
11604
11605                if i % 2 == 0 {
11606                    assert_eq!(ours_mixed.next_back(), inner_mixed.next_back());
11607                } else {
11608                    assert_eq!(ours_mixed.next(), inner_mixed.next());
11609                }
11610            }
11611
11612            let mut ours_mixed2 = ours.into_iter();
11613            let mut inner_mixed2 = inner.into_iter();
11614
11615            for i in 0..n {
11616                checks(ours_mixed2.clone(), inner_mixed2.clone());
11617
11618                if i % 2 == 0 {
11619                    assert_eq!(ours_mixed2.next(), inner_mixed2.next());
11620                } else {
11621                    assert_eq!(ours_mixed2.next_back(), inner_mixed2.next_back());
11622                }
11623            }
11624        }
11625
11626        test_steps(OneOrManyWithParens::One(1), once(1), 3);
11627        test_steps(OneOrManyWithParens::Many(vec![2]), vec![2], 3);
11628        test_steps(OneOrManyWithParens::Many(vec![3, 4]), vec![3, 4], 4);
11629    }
11630
11631    // Tests that the position in the code of an `Ident` does not affect its
11632    // ordering.
11633    #[test]
11634    fn test_ident_ord() {
11635        let mut a = Ident::with_span(Span::new(Location::new(1, 1), Location::new(1, 1)), "a");
11636        let mut b = Ident::with_span(Span::new(Location::new(2, 2), Location::new(2, 2)), "b");
11637
11638        assert!(a < b);
11639        std::mem::swap(&mut a.span, &mut b.span);
11640        assert!(a < b);
11641    }
11642}