Skip to main content

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, DerefMut};
34use core::{
35    fmt::{self, Display},
36    hash,
37};
38
39#[cfg(feature = "serde")]
40use serde::{Deserialize, Serialize};
41
42#[cfg(feature = "visitor")]
43use sqlparser_derive::{Visit, VisitMut};
44
45use crate::{
46    display_utils::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, CreateRole, Grant, ResetConfig, Revoke, RoleOption, SecondaryRoles,
60    SetConfigValue, Use,
61};
62pub use self::ddl::{
63    Alignment, AlterCollation, AlterCollationOperation, AlterColumnOperation, AlterConnectorOwner,
64    AlterFunction, AlterFunctionAction, AlterFunctionKind, AlterFunctionOperation,
65    AlterIndexOperation, AlterOperator, AlterOperatorClass, AlterOperatorClassOperation,
66    AlterOperatorFamily, AlterOperatorFamilyOperation, AlterOperatorOperation, AlterPolicy,
67    AlterPolicyOperation, AlterSchema, AlterSchemaOperation, AlterTable, AlterTableAlgorithm,
68    AlterTableLock, AlterTableOperation, AlterTableType, AlterType, AlterTypeAddValue,
69    AlterTypeAddValuePosition, AlterTypeOperation, AlterTypeRename, AlterTypeRenameValue,
70    ClusteredBy, ColumnDef, ColumnOption, ColumnOptionDef, ColumnOptions, ColumnPolicy,
71    ColumnPolicyProperty, ConstraintCharacteristics, CreateCollation, CreateCollationDefinition,
72    CreateConnector, CreateDomain, CreateExtension, CreateFunction, CreateIndex, CreateOperator,
73    CreateOperatorClass, CreateOperatorFamily, CreatePolicy, CreatePolicyCommand, CreatePolicyType,
74    CreateTable, CreateTrigger, CreateView, Deduplicate, DeferrableInitial, DistStyle,
75    DropBehavior, DropExtension, DropFunction, DropOperator, DropOperatorClass, DropOperatorFamily,
76    DropOperatorSignature, DropPolicy, DropTrigger, ForValues, FunctionReturnType, GeneratedAs,
77    GeneratedExpressionMode, IdentityParameters, IdentityProperty, IdentityPropertyFormatKind,
78    IdentityPropertyKind, IdentityPropertyOrder, IndexColumn, IndexOption, IndexType,
79    KeyOrIndexDisplay, Msck, NullsDistinctOption, OperatorArgTypes, OperatorClassItem,
80    OperatorFamilyDropItem, OperatorFamilyItem, OperatorOption, OperatorPurpose, Owner, Partition,
81    PartitionBoundValue, ProcedureParam, ReferentialAction, RenameTableNameKind, ReplicaIdentity,
82    TagsColumnOption, TriggerObjectKind, Truncate, UserDefinedTypeCompositeAttributeDef,
83    UserDefinedTypeInternalLength, UserDefinedTypeRangeOption, UserDefinedTypeRepresentation,
84    UserDefinedTypeSqlDefinitionOption, UserDefinedTypeStorage, ViewColumnDef,
85};
86pub use self::dml::{
87    Delete, Insert, Merge, MergeAction, MergeClause, MergeClauseKind, MergeInsertExpr,
88    MergeInsertKind, MergeUpdateExpr, MultiTableInsertIntoClause, MultiTableInsertType,
89    MultiTableInsertValue, MultiTableInsertValues, MultiTableInsertWhenClause, OutputClause,
90    Update,
91};
92pub use self::operator::{BinaryOperator, UnaryOperator};
93pub use self::query::{
94    AfterMatchSkip, ConnectByKind, Cte, CteAsMaterialized, Distinct, EmptyMatchesMode,
95    ExceptSelectItem, ExcludeSelectItem, ExprWithAlias, ExprWithAliasAndOrderBy, Fetch, ForClause,
96    ForJson, ForXml, FormatClause, GroupByExpr, GroupByWithModifier, IdentWithAlias,
97    IlikeSelectItem, InputFormatClause, Interpolate, InterpolateExpr, Join, JoinConstraint,
98    JoinOperator, JsonTableColumn, JsonTableColumnErrorHandling, JsonTableNamedColumn,
99    JsonTableNestedColumn, LateralView, LimitClause, LockClause, LockType, MatchRecognizePattern,
100    MatchRecognizeSymbol, Measure, NamedWindowDefinition, NamedWindowExpr, NonBlock, Offset,
101    OffsetRows, OpenJsonTableColumn, OrderBy, OrderByExpr, OrderByKind, OrderByOptions,
102    PipeOperator, PivotValueSource, ProjectionSelect, Query, RenameSelectItem,
103    RepetitionQuantifier, ReplaceSelectElement, ReplaceSelectItem, RowsPerMatch, Select,
104    SelectFlavor, SelectInto, SelectItem, SelectItemQualifiedWildcardKind, SelectModifiers,
105    SetExpr, SetOperator, SetQuantifier, Setting, SymbolDefinition, Table, TableAlias,
106    TableAliasColumnDef, TableFactor, TableFunctionArgs, TableIndexHintForClause,
107    TableIndexHintType, TableIndexHints, TableIndexType, TableSample, TableSampleBucket,
108    TableSampleKind, TableSampleMethod, TableSampleModifier, TableSampleQuantity, TableSampleSeed,
109    TableSampleSeedModifier, TableSampleUnit, TableVersion, TableWithJoins, Top, TopQuantity,
110    UpdateTableFromKind, ValueTableMode, Values, WildcardAdditionalOptions, With, WithFill,
111    XmlNamespaceDefinition, XmlPassingArgument, XmlPassingClause, XmlTableColumn,
112    XmlTableColumnOption,
113};
114
115pub use self::trigger::{
116    TriggerEvent, TriggerExecBody, TriggerExecBodyType, TriggerObject, TriggerPeriod,
117    TriggerReferencing, TriggerReferencingType,
118};
119
120pub use self::value::{
121    escape_double_quote_string, escape_quoted_string, DateTimeField, DollarQuotedString,
122    NormalizationForm, QuoteDelimitedString, TrimWhereField, Value, ValueWithSpan,
123};
124
125use crate::ast::helpers::key_value_options::KeyValueOptions;
126use crate::ast::helpers::stmt_data_loading::StageParamsObject;
127
128#[cfg(feature = "visitor")]
129pub use visitor::*;
130
131pub use self::data_type::GeometricTypeKind;
132
133mod data_type;
134mod dcl;
135mod ddl;
136mod dml;
137/// Helper modules for building and manipulating AST nodes.
138pub mod helpers;
139pub mod table_constraints;
140pub use table_constraints::{
141    CheckConstraint, ConstraintUsingIndex, ForeignKeyConstraint, FullTextOrSpatialConstraint,
142    IndexConstraint, PrimaryKeyConstraint, TableConstraint, UniqueConstraint,
143};
144mod operator;
145mod query;
146mod spans;
147pub use spans::Spanned;
148
149pub mod comments;
150mod trigger;
151mod value;
152
153#[cfg(feature = "visitor")]
154mod visitor;
155
156/// Helper used to format a slice using a separator string (e.g., `", "`).
157pub struct DisplaySeparated<'a, T>
158where
159    T: fmt::Display,
160{
161    slice: &'a [T],
162    sep: &'static str,
163}
164
165impl<T> fmt::Display for DisplaySeparated<'_, T>
166where
167    T: fmt::Display,
168{
169    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
170        let mut delim = "";
171        for t in self.slice {
172            f.write_str(delim)?;
173            delim = self.sep;
174            t.fmt(f)?;
175        }
176        Ok(())
177    }
178}
179
180pub(crate) fn display_separated<'a, T>(slice: &'a [T], sep: &'static str) -> DisplaySeparated<'a, T>
181where
182    T: fmt::Display,
183{
184    DisplaySeparated { slice, sep }
185}
186
187pub(crate) fn display_comma_separated<T>(slice: &[T]) -> DisplaySeparated<'_, T>
188where
189    T: fmt::Display,
190{
191    DisplaySeparated { slice, sep: ", " }
192}
193
194/// Writes the given statements to the formatter, each ending with
195/// a semicolon and space separated.
196fn format_statement_list(f: &mut fmt::Formatter, statements: &[Statement]) -> fmt::Result {
197    write!(f, "{}", display_separated(statements, "; "))?;
198    // We manually insert semicolon for the last statement,
199    // since display_separated doesn't handle that case.
200    write!(f, ";")
201}
202
203/// A item `T` enclosed in a pair of parentheses
204#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
205#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
206#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
207pub struct Parens<T> {
208    /// the opening parenthesis token, i.e. `(`
209    pub opening_token: AttachedToken,
210    /// content enclosed in parentheses
211    pub content: T,
212    /// the closing parenthesis token, i.e. `)`
213    pub closing_token: AttachedToken,
214}
215
216impl<T> Parens<T> {
217    /// Constructor wrapping `content` into `Parens` with an empty span;
218    /// useful for testing purposes.
219    pub fn with_empty_span(content: T) -> Self {
220        Self {
221            opening_token: AttachedToken::empty(),
222            content,
223            closing_token: AttachedToken::empty(),
224        }
225    }
226}
227
228impl<T> Deref for Parens<T> {
229    type Target = T;
230
231    fn deref(&self) -> &Self::Target {
232        &self.content
233    }
234}
235
236impl<T> DerefMut for Parens<T> {
237    fn deref_mut(&mut self) -> &mut Self::Target {
238        &mut self.content
239    }
240}
241
242/// An identifier, decomposed into its value or character data and the quote style.
243#[derive(Debug, Clone)]
244#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
245#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
246pub struct Ident {
247    /// The value of the identifier without quotes.
248    pub value: String,
249    /// The starting quote if any. Valid quote characters are the single quote,
250    /// double quote, backtick, and opening square bracket.
251    pub quote_style: Option<char>,
252    /// The span of the identifier in the original SQL string.
253    pub span: Span,
254}
255
256impl PartialEq for Ident {
257    fn eq(&self, other: &Self) -> bool {
258        let Ident {
259            value,
260            quote_style,
261            // exhaustiveness check; we ignore spans in comparisons
262            span: _,
263        } = self;
264
265        value == &other.value && quote_style == &other.quote_style
266    }
267}
268
269impl core::hash::Hash for Ident {
270    fn hash<H: hash::Hasher>(&self, state: &mut H) {
271        let Ident {
272            value,
273            quote_style,
274            // exhaustiveness check; we ignore spans in hashes
275            span: _,
276        } = self;
277
278        value.hash(state);
279        quote_style.hash(state);
280    }
281}
282
283impl Eq for Ident {}
284
285impl PartialOrd for Ident {
286    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
287        Some(self.cmp(other))
288    }
289}
290
291impl Ord for Ident {
292    fn cmp(&self, other: &Self) -> Ordering {
293        let Ident {
294            value,
295            quote_style,
296            // exhaustiveness check; we ignore spans in ordering
297            span: _,
298        } = self;
299
300        let Ident {
301            value: other_value,
302            quote_style: other_quote_style,
303            // exhaustiveness check; we ignore spans in ordering
304            span: _,
305        } = other;
306
307        // First compare by value, then by quote_style
308        value
309            .cmp(other_value)
310            .then_with(|| quote_style.cmp(other_quote_style))
311    }
312}
313
314impl Ident {
315    /// Create a new identifier with the given value and no quotes and an empty span.
316    pub fn new<S>(value: S) -> Self
317    where
318        S: Into<String>,
319    {
320        Ident {
321            value: value.into(),
322            quote_style: None,
323            span: Span::empty(),
324        }
325    }
326
327    /// Create a new quoted identifier with the given quote and value. This function
328    /// panics if the given quote is not a valid quote character.
329    pub fn with_quote<S>(quote: char, value: S) -> Self
330    where
331        S: Into<String>,
332    {
333        assert!(quote == '\'' || quote == '"' || quote == '`' || quote == '[');
334        Ident {
335            value: value.into(),
336            quote_style: Some(quote),
337            span: Span::empty(),
338        }
339    }
340
341    /// Create an `Ident` with the given `span` and `value` (unquoted).
342    pub fn with_span<S>(span: Span, value: S) -> Self
343    where
344        S: Into<String>,
345    {
346        Ident {
347            value: value.into(),
348            quote_style: None,
349            span,
350        }
351    }
352
353    /// Create a quoted `Ident` with the given `quote` and `span`.
354    pub fn with_quote_and_span<S>(quote: char, span: Span, value: S) -> Self
355    where
356        S: Into<String>,
357    {
358        assert!(quote == '\'' || quote == '"' || quote == '`' || quote == '[');
359        Ident {
360            value: value.into(),
361            quote_style: Some(quote),
362            span,
363        }
364    }
365}
366
367impl From<&str> for Ident {
368    fn from(value: &str) -> Self {
369        Ident {
370            value: value.to_string(),
371            quote_style: None,
372            span: Span::empty(),
373        }
374    }
375}
376
377impl fmt::Display for Ident {
378    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
379        match self.quote_style {
380            Some(q) if q == '"' || q == '\'' || q == '`' => {
381                let escaped = value::escape_quoted_string(&self.value, q);
382                write!(f, "{q}{escaped}{q}")
383            }
384            Some('[') => write!(f, "[{}]", self.value),
385            None => f.write_str(&self.value),
386            _ => panic!("unexpected quote style"),
387        }
388    }
389}
390
391/// A name of a table, view, custom type, etc., possibly multi-part, i.e. db.schema.obj
392#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
393#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
394#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
395pub struct ObjectName(pub Vec<ObjectNamePart>);
396
397impl From<Vec<Ident>> for ObjectName {
398    fn from(idents: Vec<Ident>) -> Self {
399        ObjectName(idents.into_iter().map(ObjectNamePart::Identifier).collect())
400    }
401}
402
403impl From<Ident> for ObjectName {
404    fn from(ident: Ident) -> Self {
405        ObjectName(vec![ObjectNamePart::Identifier(ident)])
406    }
407}
408
409impl fmt::Display for ObjectName {
410    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
411        write!(f, "{}", display_separated(&self.0, "."))
412    }
413}
414
415/// A single part of an ObjectName
416#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
417#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
418#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
419pub enum ObjectNamePart {
420    /// A single identifier part, e.g. `schema` or `table`.
421    Identifier(Ident),
422    /// A function that returns an identifier (dialect-specific).
423    Function(ObjectNamePartFunction),
424}
425
426impl ObjectNamePart {
427    /// Return the identifier if this is an `Identifier` variant.
428    pub fn as_ident(&self) -> Option<&Ident> {
429        match self {
430            ObjectNamePart::Identifier(ident) => Some(ident),
431            ObjectNamePart::Function(_) => None,
432        }
433    }
434}
435
436impl fmt::Display for ObjectNamePart {
437    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
438        match self {
439            ObjectNamePart::Identifier(ident) => write!(f, "{ident}"),
440            ObjectNamePart::Function(func) => write!(f, "{func}"),
441        }
442    }
443}
444
445/// An object name part that consists of a function that dynamically
446/// constructs identifiers.
447///
448/// - [Snowflake](https://docs.snowflake.com/en/sql-reference/identifier-literal)
449#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
450#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
451#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
452pub struct ObjectNamePartFunction {
453    /// The function name that produces the object name part.
454    pub name: Ident,
455    /// Function arguments used to compute the identifier.
456    pub args: Vec<FunctionArg>,
457}
458
459impl fmt::Display for ObjectNamePartFunction {
460    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
461        write!(f, "{}(", self.name)?;
462        write!(f, "{})", display_comma_separated(&self.args))
463    }
464}
465
466/// Represents an Array Expression, either
467/// `ARRAY[..]`, or `[..]`
468#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
469#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
470#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
471pub struct Array {
472    /// The list of expressions between brackets
473    pub elem: Vec<Expr>,
474
475    /// `true` for  `ARRAY[..]`, `false` for `[..]`
476    pub named: bool,
477}
478
479impl fmt::Display for Array {
480    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
481        write!(
482            f,
483            "{}[{}]",
484            if self.named { "ARRAY" } else { "" },
485            display_comma_separated(&self.elem)
486        )
487    }
488}
489
490/// Represents an INTERVAL expression, roughly in the following format:
491/// `INTERVAL '<value>' [ <leading_field> [ (<leading_precision>) ] ]
492/// [ TO <last_field> [ (<fractional_seconds_precision>) ] ]`,
493/// e.g. `INTERVAL '123:45.67' MINUTE(3) TO SECOND(2)`.
494///
495/// The parser does not validate the `<value>`, nor does it ensure
496/// that the `<leading_field>` units >= the units in `<last_field>`,
497/// so the user will have to reject intervals like `HOUR TO YEAR`.
498#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
499#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
500#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
501pub struct Interval {
502    /// The interval value expression (commonly a string literal).
503    pub value: Box<Expr>,
504    /// Optional leading time unit (e.g., `HOUR`, `MINUTE`).
505    pub leading_field: Option<DateTimeField>,
506    /// Optional leading precision for the leading field.
507    pub leading_precision: Option<u64>,
508    /// Optional trailing time unit for a range (e.g., `SECOND`).
509    pub last_field: Option<DateTimeField>,
510    /// The fractional seconds precision, when specified.
511    ///
512    /// See SQL `SECOND(n)` or `SECOND(m, n)` forms.
513    pub fractional_seconds_precision: Option<u64>,
514}
515
516impl fmt::Display for Interval {
517    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
518        let value = self.value.as_ref();
519        match (
520            &self.leading_field,
521            self.leading_precision,
522            self.fractional_seconds_precision,
523        ) {
524            (
525                Some(DateTimeField::Second),
526                Some(leading_precision),
527                Some(fractional_seconds_precision),
528            ) => {
529                // When the leading field is SECOND, the parser guarantees that
530                // the last field is None.
531                assert!(self.last_field.is_none());
532                write!(
533                    f,
534                    "INTERVAL {value} SECOND ({leading_precision}, {fractional_seconds_precision})"
535                )
536            }
537            _ => {
538                write!(f, "INTERVAL {value}")?;
539                if let Some(leading_field) = &self.leading_field {
540                    write!(f, " {leading_field}")?;
541                }
542                if let Some(leading_precision) = self.leading_precision {
543                    write!(f, " ({leading_precision})")?;
544                }
545                if let Some(last_field) = &self.last_field {
546                    write!(f, " TO {last_field}")?;
547                }
548                if let Some(fractional_seconds_precision) = self.fractional_seconds_precision {
549                    write!(f, " ({fractional_seconds_precision})")?;
550                }
551                Ok(())
552            }
553        }
554    }
555}
556
557/// A field definition within a struct
558///
559/// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-types#struct_type
560#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
561#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
562#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
563pub struct StructField {
564    /// Optional name of the struct field.
565    pub field_name: Option<Ident>,
566    /// The field data type.
567    pub field_type: DataType,
568    /// Struct field options (e.g., `OPTIONS(...)` on BigQuery).
569    /// See [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#column_name_and_column_schema)
570    pub options: Option<Vec<SqlOption>>,
571}
572
573impl fmt::Display for StructField {
574    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
575        if let Some(name) = &self.field_name {
576            write!(f, "{name} {}", self.field_type)?;
577        } else {
578            write!(f, "{}", self.field_type)?;
579        }
580        if let Some(options) = &self.options {
581            write!(f, " OPTIONS({})", display_separated(options, ", "))
582        } else {
583            Ok(())
584        }
585    }
586}
587
588/// A field definition within a union
589///
590/// [DuckDB]: https://duckdb.org/docs/sql/data_types/union.html
591#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
592#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
593#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
594pub struct UnionField {
595    /// Name of the union field.
596    pub field_name: Ident,
597    /// Type of the union field.
598    pub field_type: DataType,
599}
600
601impl fmt::Display for UnionField {
602    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
603        write!(f, "{} {}", self.field_name, self.field_type)
604    }
605}
606
607/// A dictionary field within a dictionary.
608///
609/// [DuckDB]: https://duckdb.org/docs/sql/data_types/struct#creating-structs
610#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
611#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
612#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
613pub struct DictionaryField {
614    /// Dictionary key identifier.
615    pub key: Ident,
616    /// Value expression for the dictionary entry.
617    pub value: Box<Expr>,
618}
619
620impl fmt::Display for DictionaryField {
621    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
622        write!(f, "{}: {}", self.key, self.value)
623    }
624}
625
626/// Represents a Map expression.
627#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
628#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
629#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
630pub struct Map {
631    /// Entries of the map as key/value pairs.
632    pub entries: Vec<MapEntry>,
633}
634
635impl Display for Map {
636    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
637        write!(f, "MAP {{{}}}", display_comma_separated(&self.entries))
638    }
639}
640
641/// A map field within a map.
642///
643/// [DuckDB]: https://duckdb.org/docs/sql/data_types/map.html#creating-maps
644#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
645#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
646#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
647pub struct MapEntry {
648    /// Key expression of the map entry.
649    pub key: Box<Expr>,
650    /// Value expression of the map entry.
651    pub value: Box<Expr>,
652}
653
654impl fmt::Display for MapEntry {
655    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
656        write!(f, "{}: {}", self.key, self.value)
657    }
658}
659
660/// Options for `CAST` / `TRY_CAST`
661/// BigQuery: <https://cloud.google.com/bigquery/docs/reference/standard-sql/format-elements#formatting_syntax>
662#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
663#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
664#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
665pub enum CastFormat {
666    /// A simple cast format specified by a `Value`.
667    Value(ValueWithSpan),
668    /// A cast format with an explicit time zone: `(format, timezone)`.
669    ValueAtTimeZone(ValueWithSpan, ValueWithSpan),
670}
671
672/// An element of a JSON path.
673#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
674#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
675#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
676pub enum JsonPathElem {
677    /// Accesses an object field using dot notation, e.g. `obj:foo.bar.baz`.
678    ///
679    /// See <https://docs.snowflake.com/en/user-guide/querying-semistructured#dot-notation>.
680    Dot {
681        /// The object key text (without quotes).
682        key: String,
683        /// `true` when the key was quoted in the source.
684        quoted: bool,
685    },
686    /// Accesses an object field or array element using bracket notation,
687    /// e.g. `obj['foo']`.
688    ///
689    /// See <https://docs.snowflake.com/en/user-guide/querying-semistructured#bracket-notation>.
690    Bracket {
691        /// The expression used as the bracket key (string or numeric expression).
692        key: Expr,
693    },
694    /// Access an object field using colon bracket notation
695    /// e.g. `obj:['foo']`
696    ///
697    /// See <https://docs.databricks.com/en/sql/language-manual/functions/colonsign.html>
698    ColonBracket {
699        /// The expression used as the bracket key (string or numeric expression).
700        key: Expr,
701    },
702}
703
704/// A JSON path.
705///
706/// See <https://docs.snowflake.com/en/user-guide/querying-semistructured>.
707/// See <https://docs.databricks.com/en/sql/language-manual/sql-ref-json-path-expression.html>.
708#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
709#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
710#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
711pub struct JsonPath {
712    /// Sequence of path elements that form the JSON path.
713    pub path: Vec<JsonPathElem>,
714}
715
716impl fmt::Display for JsonPath {
717    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
718        for (i, elem) in self.path.iter().enumerate() {
719            match elem {
720                JsonPathElem::Dot { key, quoted } => {
721                    if i == 0 {
722                        write!(f, ":")?;
723                    } else {
724                        write!(f, ".")?;
725                    }
726
727                    if *quoted {
728                        write!(f, "\"{}\"", escape_double_quote_string(key))?;
729                    } else {
730                        write!(f, "{key}")?;
731                    }
732                }
733                JsonPathElem::Bracket { key } => {
734                    write!(f, "[{key}]")?;
735                }
736                JsonPathElem::ColonBracket { key } => {
737                    write!(f, ":[{key}]")?;
738                }
739            }
740        }
741        Ok(())
742    }
743}
744
745/// The syntax used for in a cast expression.
746#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
747#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
748#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
749pub enum CastKind {
750    /// The standard SQL cast syntax, e.g. `CAST(<expr> as <datatype>)`
751    Cast,
752    /// A cast that returns `NULL` on failure, e.g. `TRY_CAST(<expr> as <datatype>)`.
753    ///
754    /// See <https://docs.snowflake.com/en/sql-reference/functions/try_cast>.
755    /// See <https://learn.microsoft.com/en-us/sql/t-sql/functions/try-cast-transact-sql>.
756    TryCast,
757    /// A cast that returns `NULL` on failure, bigQuery-specific ,  e.g. `SAFE_CAST(<expr> as <datatype>)`.
758    ///
759    /// See <https://cloud.google.com/bigquery/docs/reference/standard-sql/functions-and-operators#safe_casting>.
760    SafeCast,
761    /// `<expr> :: <datatype>`
762    DoubleColon,
763}
764
765/// `MATCH` type for constraint references
766///
767/// See: <https://www.postgresql.org/docs/current/sql-createtable.html#SQL-CREATETABLE-PARMS-REFERENCES>
768#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
769#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
770#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
771pub enum ConstraintReferenceMatchKind {
772    /// `MATCH FULL`
773    Full,
774    /// `MATCH PARTIAL`
775    Partial,
776    /// `MATCH SIMPLE`
777    Simple,
778}
779
780impl fmt::Display for ConstraintReferenceMatchKind {
781    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
782        match self {
783            Self::Full => write!(f, "MATCH FULL"),
784            Self::Partial => write!(f, "MATCH PARTIAL"),
785            Self::Simple => write!(f, "MATCH SIMPLE"),
786        }
787    }
788}
789
790/// `EXTRACT` syntax variants.
791///
792/// In Snowflake dialect, the `EXTRACT` expression can support either the `from` syntax
793/// or the comma syntax.
794///
795/// See <https://docs.snowflake.com/en/sql-reference/functions/extract>
796#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
797#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
798#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
799pub enum ExtractSyntax {
800    /// `EXTRACT( <date_or_time_part> FROM <date_or_time_expr> )`
801    From,
802    /// `EXTRACT( <date_or_time_part> , <date_or_timestamp_expr> )`
803    Comma,
804}
805
806/// The syntax used in a CEIL or FLOOR expression.
807///
808/// The `CEIL/FLOOR(<datetime value expression> TO <time unit>)` is an Amazon Kinesis Data Analytics extension.
809/// See <https://docs.aws.amazon.com/kinesisanalytics/latest/sqlref/sql-reference-ceil.html> for
810/// details.
811///
812/// Other dialects either support `CEIL/FLOOR( <expr> [, <scale>])` format or just
813/// `CEIL/FLOOR(<expr>)`.
814#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
815#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
816#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
817pub enum CeilFloorKind {
818    /// `CEIL( <expr> TO <DateTimeField>)`
819    DateTimeField(DateTimeField),
820    /// `CEIL( <expr> [, <scale>])`
821    Scale(ValueWithSpan),
822}
823
824/// A WHEN clause in a CASE expression containing both
825/// the condition and its corresponding result
826#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
827#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
828#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
829pub struct CaseWhen {
830    /// The `WHEN` condition expression.
831    pub condition: Expr,
832    /// The expression returned when `condition` matches.
833    pub result: Expr,
834}
835
836impl fmt::Display for CaseWhen {
837    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
838        f.write_str("WHEN ")?;
839        self.condition.fmt(f)?;
840        f.write_str(" THEN")?;
841        SpaceOrNewline.fmt(f)?;
842        Indent(&self.result).fmt(f)?;
843        Ok(())
844    }
845}
846
847/// An SQL expression of any type.
848///
849/// # Semantics / Type Checking
850///
851/// The parser does not distinguish between expressions of different types
852/// (e.g. boolean vs string). The caller is responsible for detecting and
853/// validating types as necessary (for example  `WHERE 1` vs `SELECT 1=1`)
854/// See the [README.md] for more details.
855///
856/// [README.md]: https://github.com/apache/datafusion-sqlparser-rs/blob/main/README.md#syntax-vs-semantics
857///
858/// # Equality and Hashing Does not Include Source Locations
859///
860/// The `Expr` type implements `PartialEq` and `Eq` based on the semantic value
861/// of the expression (not bitwise comparison). This means that `Expr` instances
862/// that are semantically equivalent but have different spans (locations in the
863/// source tree) will compare as equal.
864#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
865#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
866#[cfg_attr(
867    feature = "visitor",
868    derive(Visit, VisitMut),
869    visit(with = "visit_expr")
870)]
871pub enum Expr {
872    /// Identifier e.g. table name or column name
873    Identifier(Ident),
874    /// Multi-part identifier, e.g. `table_alias.column` or `schema.table.col`
875    CompoundIdentifier(Vec<Ident>),
876    /// Multi-part expression access.
877    ///
878    /// This structure represents an access chain in structured / nested types
879    /// such as maps, arrays, and lists:
880    /// - Array
881    ///     - A 1-dim array `a[1]` will be represented like:
882    ///       `CompoundFieldAccess(Ident('a'), vec![Subscript(1)]`
883    ///     - A 2-dim array `a[1][2]` will be represented like:
884    ///       `CompoundFieldAccess(Ident('a'), vec![Subscript(1), Subscript(2)]`
885    /// - Map or Struct (Bracket-style)
886    ///     - A map `a['field1']` will be represented like:
887    ///       `CompoundFieldAccess(Ident('a'), vec![Subscript('field')]`
888    ///     - A 2-dim map `a['field1']['field2']` will be represented like:
889    ///       `CompoundFieldAccess(Ident('a'), vec![Subscript('field1'), Subscript('field2')]`
890    /// - Struct (Dot-style) (only effect when the chain contains both subscript and expr)
891    ///     - A struct access `a[field1].field2` will be represented like:
892    ///       `CompoundFieldAccess(Ident('a'), vec![Subscript('field1'), Ident('field2')]`
893    /// - If a struct access likes `a.field1.field2`, it will be represented by CompoundIdentifier([a, field1, field2])
894    CompoundFieldAccess {
895        /// The base expression being accessed.
896        root: Box<Expr>,
897        /// Sequence of access operations (subscript or identifier accesses).
898        access_chain: Vec<AccessExpr>,
899    },
900    /// Access data nested in a value containing semi-structured data, such as
901    /// the `VARIANT` type on Snowflake. for example `src:customer[0].name`.
902    ///
903    /// See <https://docs.snowflake.com/en/user-guide/querying-semistructured>.
904    /// See <https://docs.databricks.com/en/sql/language-manual/functions/colonsign.html>.
905    JsonAccess {
906        /// The value being queried.
907        value: Box<Expr>,
908        /// The path to the data to extract.
909        path: JsonPath,
910    },
911    /// `IS FALSE` operator
912    IsFalse(Box<Expr>),
913    /// `IS NOT FALSE` operator
914    IsNotFalse(Box<Expr>),
915    /// `IS TRUE` operator
916    IsTrue(Box<Expr>),
917    /// `IS NOT TRUE` operator
918    IsNotTrue(Box<Expr>),
919    /// `IS NULL` operator
920    IsNull(Box<Expr>),
921    /// `IS NOT NULL` operator
922    IsNotNull(Box<Expr>),
923    /// `IS UNKNOWN` operator
924    IsUnknown(Box<Expr>),
925    /// `IS NOT UNKNOWN` operator
926    IsNotUnknown(Box<Expr>),
927    /// `IS DISTINCT FROM` operator
928    IsDistinctFrom(Box<Expr>, Box<Expr>),
929    /// `IS NOT DISTINCT FROM` operator
930    IsNotDistinctFrom(Box<Expr>, Box<Expr>),
931    /// `<expr> IS [ NOT ] [ form ] NORMALIZED`
932    IsNormalized {
933        /// Expression being tested.
934        expr: Box<Expr>,
935        /// Optional normalization `form` (e.g., NFC, NFD).
936        form: Option<NormalizationForm>,
937        /// `true` when `NOT` is present.
938        negated: bool,
939    },
940    /// `[ NOT ] IN (val1, val2, ...)`
941    InList {
942        /// Left-hand expression to test for membership.
943        expr: Box<Expr>,
944        /// Literal list of expressions to check against.
945        list: Vec<Expr>,
946        /// `true` when the `NOT` modifier is present.
947        negated: bool,
948    },
949    /// `[ NOT ] IN (SELECT ...)`
950    InSubquery {
951        /// Left-hand expression to test for membership.
952        expr: Box<Expr>,
953        /// The subquery providing the candidate values.
954        subquery: Box<Query>,
955        /// `true` when the `NOT` modifier is present.
956        negated: bool,
957    },
958    /// `[ NOT ] IN UNNEST(array_expression)`
959    InUnnest {
960        /// Left-hand expression to test for membership.
961        expr: Box<Expr>,
962        /// Array expression being unnested.
963        array_expr: Box<Expr>,
964        /// `true` when the `NOT` modifier is present.
965        negated: bool,
966    },
967    /// `<expr> [ NOT ] BETWEEN <low> AND <high>`
968    Between {
969        /// Expression being compared.
970        expr: Box<Expr>,
971        /// `true` when the `NOT` modifier is present.
972        negated: bool,
973        /// Lower bound.
974        low: Box<Expr>,
975        /// Upper bound.
976        high: Box<Expr>,
977    },
978    /// Binary operation e.g. `1 + 1` or `foo > bar`
979    BinaryOp {
980        /// Left operand.
981        left: Box<Expr>,
982        /// Operator between operands.
983        op: BinaryOperator,
984        /// Right operand.
985        right: Box<Expr>,
986    },
987    /// `[NOT] LIKE <pattern> [ESCAPE <escape_character>]`
988    Like {
989        /// `true` when `NOT` is present.
990        negated: bool,
991        /// Snowflake supports the ANY keyword to match against a list of patterns
992        /// <https://docs.snowflake.com/en/sql-reference/functions/like_any>
993        any: bool,
994        /// Expression to match.
995        expr: Box<Expr>,
996        /// Pattern expression.
997        pattern: Box<Expr>,
998        /// Optional escape character.
999        escape_char: Option<ValueWithSpan>,
1000    },
1001    /// `ILIKE` (case-insensitive `LIKE`)
1002    ILike {
1003        /// `true` when `NOT` is present.
1004        negated: bool,
1005        /// Snowflake supports the ANY keyword to match against a list of patterns
1006        /// <https://docs.snowflake.com/en/sql-reference/functions/like_any>
1007        any: bool,
1008        /// Expression to match.
1009        expr: Box<Expr>,
1010        /// Pattern expression.
1011        pattern: Box<Expr>,
1012        /// Optional escape character.
1013        escape_char: Option<ValueWithSpan>,
1014    },
1015    /// `SIMILAR TO` regex
1016    SimilarTo {
1017        /// `true` when `NOT` is present.
1018        negated: bool,
1019        /// Expression to test.
1020        expr: Box<Expr>,
1021        /// Pattern expression.
1022        pattern: Box<Expr>,
1023        /// Optional escape character.
1024        escape_char: Option<ValueWithSpan>,
1025    },
1026    /// MySQL: `RLIKE` regex or `REGEXP` regex
1027    RLike {
1028        /// `true` when `NOT` is present.
1029        negated: bool,
1030        /// Expression to test.
1031        expr: Box<Expr>,
1032        /// Pattern expression.
1033        pattern: Box<Expr>,
1034        /// true for REGEXP, false for RLIKE (no difference in semantics)
1035        regexp: bool,
1036    },
1037    /// `ANY` operation e.g. `foo > ANY(bar)`, comparison operator is one of `[=, >, <, =>, =<, !=]`
1038    /// <https://docs.snowflake.com/en/sql-reference/operators-subquery#all-any>
1039    AnyOp {
1040        /// Left operand.
1041        left: Box<Expr>,
1042        /// Comparison operator.
1043        compare_op: BinaryOperator,
1044        /// Right-hand subquery expression.
1045        right: Box<Expr>,
1046        /// ANY and SOME are synonymous: <https://docs.cloudera.com/cdw-runtime/cloud/using-hiveql/topics/hive_comparison_predicates.html>
1047        is_some: bool,
1048    },
1049    /// `ALL` operation e.g. `foo > ALL(bar)`, comparison operator is one of `[=, >, <, =>, =<, !=]`
1050    /// <https://docs.snowflake.com/en/sql-reference/operators-subquery#all-any>
1051    AllOp {
1052        /// Left operand.
1053        left: Box<Expr>,
1054        /// Comparison operator.
1055        compare_op: BinaryOperator,
1056        /// Right-hand subquery expression.
1057        right: Box<Expr>,
1058    },
1059
1060    /// Unary operation e.g. `NOT foo`
1061    UnaryOp {
1062        /// The unary operator (e.g., `NOT`, `-`).
1063        op: UnaryOperator,
1064        /// Operand expression.
1065        expr: Box<Expr>,
1066    },
1067    /// CONVERT a value to a different data type or character encoding. e.g. `CONVERT(foo USING utf8mb4)`
1068    Convert {
1069        /// CONVERT (false) or TRY_CONVERT (true)
1070        /// <https://learn.microsoft.com/en-us/sql/t-sql/functions/try-convert-transact-sql?view=sql-server-ver16>
1071        is_try: bool,
1072        /// The expression to convert.
1073        expr: Box<Expr>,
1074        /// The target data type, if provided.
1075        data_type: Option<DataType>,
1076        /// Optional target character encoding (e.g., `utf8mb4`).
1077        charset: Option<ObjectName>,
1078        /// `true` when target precedes the value (MSSQL syntax).
1079        target_before_value: bool,
1080        /// How to translate the expression.
1081        ///
1082        /// [MSSQL]: https://learn.microsoft.com/en-us/sql/t-sql/functions/cast-and-convert-transact-sql?view=sql-server-ver16#style
1083        styles: Vec<Expr>,
1084    },
1085    /// `CAST` an expression to a different data type e.g. `CAST(foo AS VARCHAR(123))`
1086    Cast {
1087        /// The cast kind (e.g., `CAST`, `TRY_CAST`).
1088        kind: CastKind,
1089        /// Expression being cast.
1090        expr: Box<Expr>,
1091        /// Target data type.
1092        data_type: DataType,
1093        /// [MySQL] allows CAST(... AS type ARRAY) in functional index definitions for InnoDB
1094        /// multi-valued indices. It's not really a datatype, and is only allowed in `CAST` in key
1095        /// specifications, so it's a flag here.
1096        ///
1097        /// [MySQL]: https://dev.mysql.com/doc/refman/8.4/en/cast-functions.html#function_cast
1098        array: bool,
1099        /// Optional CAST(string_expression AS type FORMAT format_string_expression) as used by [BigQuery]
1100        ///
1101        /// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/format-elements#formatting_syntax
1102        format: Option<CastFormat>,
1103    },
1104    /// AT a timestamp to a different timezone e.g. `FROM_UNIXTIME(0) AT TIME ZONE 'UTC-06:00'`
1105    AtTimeZone {
1106        /// Timestamp expression to shift.
1107        timestamp: Box<Expr>,
1108        /// Time zone expression to apply.
1109        time_zone: Box<Expr>,
1110    },
1111    /// Extract a field from a timestamp e.g. `EXTRACT(MONTH FROM foo)`
1112    /// Or `EXTRACT(MONTH, foo)`
1113    ///
1114    /// Syntax:
1115    /// ```sql
1116    /// EXTRACT(DateTimeField FROM <expr>) | EXTRACT(DateTimeField, <expr>)
1117    /// ```
1118    Extract {
1119        /// Which datetime field is being extracted.
1120        field: DateTimeField,
1121        /// Syntax variant used (`From` or `Comma`).
1122        syntax: ExtractSyntax,
1123        /// Expression to extract from.
1124        expr: Box<Expr>,
1125    },
1126    /// ```sql
1127    /// CEIL(<expr> [TO DateTimeField])
1128    /// ```
1129    /// ```sql
1130    /// CEIL( <input_expr> [, <scale_expr> ] )
1131    /// ```
1132    Ceil {
1133        /// Expression to ceil.
1134        expr: Box<Expr>,
1135        /// The CEIL/FLOOR kind (datetime field or scale).
1136        field: CeilFloorKind,
1137    },
1138    /// ```sql
1139    /// FLOOR(<expr> [TO DateTimeField])
1140    /// ```
1141    /// ```sql
1142    /// FLOOR( <input_expr> [, <scale_expr> ] )
1143    ///
1144    Floor {
1145        /// Expression to floor.
1146        expr: Box<Expr>,
1147        /// The CEIL/FLOOR kind (datetime field or scale).
1148        field: CeilFloorKind,
1149    },
1150    /// ```sql
1151    /// POSITION(<expr> in <expr>)
1152    /// ```
1153    Position {
1154        /// Expression to search for.
1155        expr: Box<Expr>,
1156        /// Expression to search in.
1157        r#in: Box<Expr>,
1158    },
1159    /// ```sql
1160    /// SUBSTRING(<expr> [FROM <expr>] [FOR <expr>])
1161    /// ```
1162    /// or
1163    /// ```sql
1164    /// SUBSTRING(<expr>, <expr>, <expr>)
1165    /// ```
1166    Substring {
1167        /// Source expression.
1168        expr: Box<Expr>,
1169        /// Optional `FROM` expression.
1170        substring_from: Option<Box<Expr>>,
1171        /// Optional `FOR` expression.
1172        substring_for: Option<Box<Expr>>,
1173
1174        /// false if the expression is represented using the `SUBSTRING(expr [FROM start] [FOR len])` syntax
1175        /// true if the expression is represented using the `SUBSTRING(expr, start, len)` syntax
1176        /// This flag is used for formatting.
1177        special: bool,
1178
1179        /// true if the expression is represented using the `SUBSTR` shorthand
1180        /// This flag is used for formatting.
1181        shorthand: bool,
1182    },
1183    /// ```sql
1184    /// TRIM([BOTH | LEADING | TRAILING] [<expr> FROM] <expr>)
1185    /// TRIM(<expr>)
1186    /// TRIM(<expr>, [, characters]) -- PostgreSQL, DuckDB, Snowflake, BigQuery, Generic
1187    /// ```
1188    Trim {
1189        /// Which side to trim: `BOTH`, `LEADING`, or `TRAILING`.
1190        trim_where: Option<TrimWhereField>,
1191        /// Optional expression specifying what to trim from the value `expr`.
1192        trim_what: Option<Box<Expr>>,
1193        /// The expression to trim from.
1194        expr: Box<Expr>,
1195        /// Optional list of characters to trim (dialect-specific).
1196        trim_characters: Option<Vec<Expr>>,
1197    },
1198    /// ```sql
1199    /// OVERLAY(<expr> PLACING <expr> FROM <expr>[ FOR <expr> ]
1200    /// ```
1201    Overlay {
1202        /// The target expression being overlayed.
1203        expr: Box<Expr>,
1204        /// The expression to place into the target.
1205        overlay_what: Box<Expr>,
1206        /// The `FROM` position expression indicating where to start overlay.
1207        overlay_from: Box<Expr>,
1208        /// Optional `FOR` length expression limiting the overlay span.
1209        overlay_for: Option<Box<Expr>>,
1210    },
1211    /// `expr COLLATE collation`
1212    Collate {
1213        /// The expression being collated.
1214        expr: Box<Expr>,
1215        /// The collation name to apply to the expression.
1216        collation: ObjectName,
1217    },
1218    /// Nested expression e.g. `(foo > bar)` or `(1)`
1219    Nested(Box<Expr>),
1220    /// A literal value, such as string, number, date or NULL
1221    Value(ValueWithSpan),
1222    /// Prefixed expression, e.g. introducer strings, projection prefix
1223    /// <https://dev.mysql.com/doc/refman/8.0/en/charset-introducer.html>
1224    /// <https://docs.snowflake.com/en/sql-reference/constructs/connect-by>
1225    Prefixed {
1226        /// The prefix identifier (introducer or projection prefix).
1227        prefix: Ident,
1228        /// The value expression being prefixed.
1229        /// Hint: you can unwrap the string value using `value.into_string()`.
1230        value: Box<Expr>,
1231    },
1232    /// A constant of form `<data_type> 'value'`.
1233    /// This can represent ANSI SQL `DATE`, `TIME`, and `TIMESTAMP` literals (such as `DATE '2020-01-01'`),
1234    /// as well as constants of other types (a non-standard PostgreSQL extension).
1235    TypedString(TypedString),
1236    /// Scalar function call e.g. `LEFT(foo, 5)`
1237    Function(Function),
1238    /// `CASE [<operand>] WHEN <condition> THEN <result> ... [ELSE <result>] END`
1239    ///
1240    /// Note we only recognize a complete single expression as `<condition>`,
1241    /// not `< 0` nor `1, 2, 3` as allowed in a `<simple when clause>` per
1242    /// <https://jakewheat.github.io/sql-overview/sql-2011-foundation-grammar.html#simple-when-clause>
1243    Case {
1244        /// The attached `CASE` token (keeps original spacing/comments).
1245        case_token: AttachedToken,
1246        /// The attached `END` token (keeps original spacing/comments).
1247        end_token: AttachedToken,
1248        /// Optional operand expression after `CASE` (for simple CASE).
1249        operand: Option<Box<Expr>>,
1250        /// The `WHEN ... THEN` conditions and results.
1251        conditions: Vec<CaseWhen>,
1252        /// Optional `ELSE` result expression.
1253        else_result: Option<Box<Expr>>,
1254    },
1255    /// An exists expression `[ NOT ] EXISTS(SELECT ...)`, used in expressions like
1256    /// `WHERE [ NOT ] EXISTS (SELECT ...)`.
1257    Exists {
1258        /// The subquery checked by `EXISTS`.
1259        subquery: Box<Query>,
1260        /// Whether the `EXISTS` is negated (`NOT EXISTS`).
1261        negated: bool,
1262    },
1263    /// A parenthesized subquery `(SELECT ...)`, used in expression like
1264    /// `SELECT (subquery) AS x` or `WHERE (subquery) = x`
1265    Subquery(Box<Query>),
1266    /// The `GROUPING SETS` expr.
1267    GroupingSets(Vec<Vec<Expr>>),
1268    /// The `CUBE` expr.
1269    Cube(Vec<Vec<Expr>>),
1270    /// The `ROLLUP` expr.
1271    Rollup(Vec<Vec<Expr>>),
1272    /// ROW / TUPLE a single value, such as `SELECT (1, 2)`
1273    Tuple(Vec<Expr>),
1274    /// `Struct` literal expression
1275    /// Syntax:
1276    /// ```sql
1277    /// STRUCT<[field_name] field_type, ...>( expr1 [, ... ])
1278    ///
1279    /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-types#struct_type)
1280    /// [Databricks](https://docs.databricks.com/en/sql/language-manual/functions/struct.html)
1281    /// ```
1282    Struct {
1283        /// Struct values.
1284        values: Vec<Expr>,
1285        /// Struct field definitions.
1286        fields: Vec<StructField>,
1287    },
1288    /// `BigQuery` specific: An named expression in a typeless struct [1]
1289    ///
1290    /// Syntax
1291    /// ```sql
1292    /// 1 AS A
1293    /// ```
1294    /// [1]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-types#struct_type
1295    Named {
1296        /// The expression being named.
1297        expr: Box<Expr>,
1298        /// The assigned identifier name for the expression.
1299        name: Ident,
1300    },
1301    /// `DuckDB` specific `Struct` literal expression [1]
1302    ///
1303    /// Syntax:
1304    /// ```sql
1305    /// syntax: {'field_name': expr1[, ... ]}
1306    /// ```
1307    /// [1]: https://duckdb.org/docs/sql/data_types/struct#creating-structs
1308    Dictionary(Vec<DictionaryField>),
1309    /// `DuckDB` specific `Map` literal expression [1]
1310    ///
1311    /// Syntax:
1312    /// ```sql
1313    /// syntax: Map {key1: value1[, ... ]}
1314    /// ```
1315    /// [1]: https://duckdb.org/docs/sql/data_types/map#creating-maps
1316    Map(Map),
1317    /// An array expression e.g. `ARRAY[1, 2]`
1318    Array(Array),
1319    /// An interval expression e.g. `INTERVAL '1' YEAR`
1320    Interval(Interval),
1321    /// `MySQL` specific text search function [(1)].
1322    ///
1323    /// Syntax:
1324    /// ```sql
1325    /// MATCH (<col>, <col>, ...) AGAINST (<expr> [<search modifier>])
1326    ///
1327    /// <col> = CompoundIdentifier
1328    /// <expr> = String literal
1329    /// ```
1330    /// [(1)]: https://dev.mysql.com/doc/refman/8.0/en/fulltext-search.html#function_match
1331    MatchAgainst {
1332        /// `(<col>, <col>, ...)`.
1333        columns: Vec<ObjectName>,
1334        /// `<expr>`.
1335        match_value: ValueWithSpan,
1336        /// `<search modifier>`
1337        opt_search_modifier: Option<SearchModifier>,
1338    },
1339    /// An unqualified `*` wildcard token (e.g. `*`).
1340    Wildcard(AttachedToken),
1341    /// Qualified wildcard, e.g. `alias.*` or `schema.table.*`.
1342    /// (Same caveats apply to `QualifiedWildcard` as to `Wildcard`.)
1343    QualifiedWildcard(ObjectName, AttachedToken),
1344    /// Some dialects support an older syntax for outer joins where columns are
1345    /// marked with the `(+)` operator in the WHERE clause, for example:
1346    ///
1347    /// ```sql
1348    /// SELECT t1.c1, t2.c2 FROM t1, t2 WHERE t1.c1 = t2.c2 (+)
1349    /// ```
1350    ///
1351    /// which is equivalent to
1352    ///
1353    /// ```sql
1354    /// SELECT t1.c1, t2.c2 FROM t1 LEFT OUTER JOIN t2 ON t1.c1 = t2.c2
1355    /// ```
1356    ///
1357    /// See <https://docs.snowflake.com/en/sql-reference/constructs/where#joins-in-the-where-clause>.
1358    OuterJoin(Box<Expr>),
1359    /// A reference to the prior level in a CONNECT BY clause.
1360    Prior(Box<Expr>),
1361    /// A lambda function.
1362    ///
1363    /// Syntax:
1364    /// ```plaintext
1365    /// param -> expr | (param1, ...) -> expr
1366    /// ```
1367    ///
1368    /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/functions#higher-order-functions---operator-and-lambdaparams-expr-function)
1369    /// [Databricks](https://docs.databricks.com/en/sql/language-manual/sql-ref-lambda-functions.html)
1370    /// [DuckDB](https://duckdb.org/docs/stable/sql/functions/lambda)
1371    Lambda(LambdaFunction),
1372    /// Checks membership of a value in a JSON array
1373    MemberOf(MemberOf),
1374}
1375
1376impl Expr {
1377    /// Creates a new [`Expr::Value`]
1378    pub fn value(value: impl Into<ValueWithSpan>) -> Self {
1379        Expr::Value(value.into())
1380    }
1381}
1382
1383/// The contents inside the `[` and `]` in a subscript expression.
1384#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1385#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1386#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1387pub enum Subscript {
1388    /// Accesses the element of the array at the given index.
1389    Index {
1390        /// The index expression used to access the array element.
1391        index: Expr,
1392    },
1393
1394    /// Accesses a slice of an array on PostgreSQL, e.g.
1395    ///
1396    /// ```plaintext
1397    /// => select (array[1,2,3,4,5,6])[2:5];
1398    /// -----------
1399    /// {2,3,4,5}
1400    /// ```
1401    ///
1402    /// The lower and/or upper bound can be omitted to slice from the start or
1403    /// end of the array respectively.
1404    ///
1405    /// See <https://www.postgresql.org/docs/current/arrays.html#ARRAYS-ACCESSING>.
1406    ///
1407    /// Also supports an optional "stride" as the last element (this is not
1408    /// supported by postgres), e.g.
1409    ///
1410    /// ```plaintext
1411    /// => select (array[1,2,3,4,5,6])[1:6:2];
1412    /// -----------
1413    /// {1,3,5}
1414    /// ```
1415    Slice {
1416        /// Optional lower bound for the slice (inclusive).
1417        lower_bound: Option<Expr>,
1418        /// Optional upper bound for the slice (inclusive).
1419        upper_bound: Option<Expr>,
1420        /// Optional stride for the slice (step size).
1421        stride: Option<Expr>,
1422    },
1423}
1424
1425impl fmt::Display for Subscript {
1426    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1427        match self {
1428            Subscript::Index { index } => write!(f, "{index}"),
1429            Subscript::Slice {
1430                lower_bound,
1431                upper_bound,
1432                stride,
1433            } => {
1434                if let Some(lower) = lower_bound {
1435                    write!(f, "{lower}")?;
1436                }
1437                write!(f, ":")?;
1438                if let Some(upper) = upper_bound {
1439                    write!(f, "{upper}")?;
1440                }
1441                if let Some(stride) = stride {
1442                    write!(f, ":")?;
1443                    write!(f, "{stride}")?;
1444                }
1445                Ok(())
1446            }
1447        }
1448    }
1449}
1450
1451/// An element of a [`Expr::CompoundFieldAccess`].
1452/// It can be an expression or a subscript.
1453#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1454#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1455#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1456pub enum AccessExpr {
1457    /// Accesses a field using dot notation, e.g. `foo.bar.baz`.
1458    Dot(Expr),
1459    /// Accesses a field or array element using bracket notation, e.g. `foo['bar']`.
1460    Subscript(Subscript),
1461}
1462
1463impl fmt::Display for AccessExpr {
1464    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1465        match self {
1466            AccessExpr::Dot(expr) => write!(f, ".{expr}"),
1467            AccessExpr::Subscript(subscript) => write!(f, "[{subscript}]"),
1468        }
1469    }
1470}
1471
1472/// A lambda function.
1473#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1474#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1475#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1476pub struct LambdaFunction {
1477    /// The parameters to the lambda function.
1478    pub params: OneOrManyWithParens<LambdaFunctionParameter>,
1479    /// The body of the lambda function.
1480    pub body: Box<Expr>,
1481    /// The syntax style used to write the lambda function.
1482    pub syntax: LambdaSyntax,
1483}
1484
1485impl fmt::Display for LambdaFunction {
1486    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1487        match self.syntax {
1488            LambdaSyntax::Arrow => write!(f, "{} -> {}", self.params, self.body),
1489            LambdaSyntax::LambdaKeyword => {
1490                // For lambda keyword syntax, display params without parentheses
1491                // e.g., `lambda x, y : expr` not `lambda (x, y) : expr`
1492                write!(f, "lambda ")?;
1493                match &self.params {
1494                    OneOrManyWithParens::One(p) => write!(f, "{p}")?,
1495                    OneOrManyWithParens::Many(ps) => write!(f, "{}", display_comma_separated(ps))?,
1496                };
1497                write!(f, " : {}", self.body)
1498            }
1499        }
1500    }
1501}
1502
1503/// A parameter to a lambda function, optionally with a data type.
1504#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1505#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1506#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1507pub struct LambdaFunctionParameter {
1508    /// The name of the parameter
1509    pub name: Ident,
1510    /// The optional data type of the parameter
1511    /// [Snowflake Syntax](https://docs.snowflake.com/en/sql-reference/functions/filter#arguments)
1512    pub data_type: Option<DataType>,
1513}
1514
1515impl fmt::Display for LambdaFunctionParameter {
1516    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1517        match &self.data_type {
1518            Some(dt) => write!(f, "{} {}", self.name, dt),
1519            None => write!(f, "{}", self.name),
1520        }
1521    }
1522}
1523
1524/// The syntax style for a lambda function.
1525#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Copy)]
1526#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1527#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1528pub enum LambdaSyntax {
1529    /// Arrow syntax: `param -> expr` or `(param1, param2) -> expr`
1530    ///
1531    /// <https://docs.databricks.com/aws/en/sql/language-manual/sql-ref-lambda-functions>
1532    ///
1533    /// Supported, but deprecated in DuckDB:
1534    /// <https://duckdb.org/docs/stable/sql/functions/lambda>
1535    Arrow,
1536    /// Lambda keyword syntax: `lambda param : expr` or `lambda param1, param2 : expr`
1537    ///
1538    /// Recommended in DuckDB:
1539    /// <https://duckdb.org/docs/stable/sql/functions/lambda>
1540    LambdaKeyword,
1541}
1542
1543/// Encapsulates the common pattern in SQL where either one unparenthesized item
1544/// such as an identifier or expression is permitted, or multiple of the same
1545/// item in a parenthesized list. For accessing items regardless of the form,
1546/// `OneOrManyWithParens` implements `Deref<Target = [T]>` and `IntoIterator`,
1547/// so you can call slice methods on it and iterate over items
1548/// # Examples
1549/// Accessing as a slice:
1550/// ```
1551/// # use sqlparser::ast::OneOrManyWithParens;
1552/// let one = OneOrManyWithParens::One("a");
1553///
1554/// assert_eq!(one[0], "a");
1555/// assert_eq!(one.len(), 1);
1556/// ```
1557/// Iterating:
1558/// ```
1559/// # use sqlparser::ast::OneOrManyWithParens;
1560/// let one = OneOrManyWithParens::One("a");
1561/// let many = OneOrManyWithParens::Many(vec!["a", "b"]);
1562///
1563/// assert_eq!(one.into_iter().chain(many).collect::<Vec<_>>(), vec!["a", "a", "b"] );
1564/// ```
1565#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1566#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1567#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1568pub enum OneOrManyWithParens<T> {
1569    /// A single `T`, unparenthesized.
1570    One(T),
1571    /// One or more `T`s, parenthesized.
1572    Many(Vec<T>),
1573}
1574
1575impl<T> Deref for OneOrManyWithParens<T> {
1576    type Target = [T];
1577
1578    fn deref(&self) -> &[T] {
1579        match self {
1580            OneOrManyWithParens::One(one) => core::slice::from_ref(one),
1581            OneOrManyWithParens::Many(many) => many,
1582        }
1583    }
1584}
1585
1586impl<T> AsRef<[T]> for OneOrManyWithParens<T> {
1587    fn as_ref(&self) -> &[T] {
1588        self
1589    }
1590}
1591
1592impl<'a, T> IntoIterator for &'a OneOrManyWithParens<T> {
1593    type Item = &'a T;
1594    type IntoIter = core::slice::Iter<'a, T>;
1595
1596    fn into_iter(self) -> Self::IntoIter {
1597        self.iter()
1598    }
1599}
1600
1601/// Owned iterator implementation of `OneOrManyWithParens`
1602#[derive(Debug, Clone)]
1603pub struct OneOrManyWithParensIntoIter<T> {
1604    inner: OneOrManyWithParensIntoIterInner<T>,
1605}
1606
1607#[derive(Debug, Clone)]
1608enum OneOrManyWithParensIntoIterInner<T> {
1609    One(core::iter::Once<T>),
1610    Many(<Vec<T> as IntoIterator>::IntoIter),
1611}
1612
1613impl<T> core::iter::FusedIterator for OneOrManyWithParensIntoIter<T>
1614where
1615    core::iter::Once<T>: core::iter::FusedIterator,
1616    <Vec<T> as IntoIterator>::IntoIter: core::iter::FusedIterator,
1617{
1618}
1619
1620impl<T> core::iter::ExactSizeIterator for OneOrManyWithParensIntoIter<T>
1621where
1622    core::iter::Once<T>: core::iter::ExactSizeIterator,
1623    <Vec<T> as IntoIterator>::IntoIter: core::iter::ExactSizeIterator,
1624{
1625}
1626
1627impl<T> core::iter::Iterator for OneOrManyWithParensIntoIter<T> {
1628    type Item = T;
1629
1630    fn next(&mut self) -> Option<Self::Item> {
1631        match &mut self.inner {
1632            OneOrManyWithParensIntoIterInner::One(one) => one.next(),
1633            OneOrManyWithParensIntoIterInner::Many(many) => many.next(),
1634        }
1635    }
1636
1637    fn size_hint(&self) -> (usize, Option<usize>) {
1638        match &self.inner {
1639            OneOrManyWithParensIntoIterInner::One(one) => one.size_hint(),
1640            OneOrManyWithParensIntoIterInner::Many(many) => many.size_hint(),
1641        }
1642    }
1643
1644    fn count(self) -> usize
1645    where
1646        Self: Sized,
1647    {
1648        match self.inner {
1649            OneOrManyWithParensIntoIterInner::One(one) => one.count(),
1650            OneOrManyWithParensIntoIterInner::Many(many) => many.count(),
1651        }
1652    }
1653
1654    fn fold<B, F>(mut self, init: B, f: F) -> B
1655    where
1656        Self: Sized,
1657        F: FnMut(B, Self::Item) -> B,
1658    {
1659        match &mut self.inner {
1660            OneOrManyWithParensIntoIterInner::One(one) => one.fold(init, f),
1661            OneOrManyWithParensIntoIterInner::Many(many) => many.fold(init, f),
1662        }
1663    }
1664}
1665
1666impl<T> core::iter::DoubleEndedIterator for OneOrManyWithParensIntoIter<T> {
1667    fn next_back(&mut self) -> Option<Self::Item> {
1668        match &mut self.inner {
1669            OneOrManyWithParensIntoIterInner::One(one) => one.next_back(),
1670            OneOrManyWithParensIntoIterInner::Many(many) => many.next_back(),
1671        }
1672    }
1673}
1674
1675impl<T> IntoIterator for OneOrManyWithParens<T> {
1676    type Item = T;
1677
1678    type IntoIter = OneOrManyWithParensIntoIter<T>;
1679
1680    fn into_iter(self) -> Self::IntoIter {
1681        let inner = match self {
1682            OneOrManyWithParens::One(one) => {
1683                OneOrManyWithParensIntoIterInner::One(core::iter::once(one))
1684            }
1685            OneOrManyWithParens::Many(many) => {
1686                OneOrManyWithParensIntoIterInner::Many(many.into_iter())
1687            }
1688        };
1689
1690        OneOrManyWithParensIntoIter { inner }
1691    }
1692}
1693
1694impl<T> fmt::Display for OneOrManyWithParens<T>
1695where
1696    T: fmt::Display,
1697{
1698    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1699        match self {
1700            OneOrManyWithParens::One(value) => write!(f, "{value}"),
1701            OneOrManyWithParens::Many(values) => {
1702                write!(f, "({})", display_comma_separated(values))
1703            }
1704        }
1705    }
1706}
1707
1708impl fmt::Display for CastFormat {
1709    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1710        match self {
1711            CastFormat::Value(v) => write!(f, "{v}"),
1712            CastFormat::ValueAtTimeZone(v, tz) => write!(f, "{v} AT TIME ZONE {tz}"),
1713        }
1714    }
1715}
1716
1717impl fmt::Display for Expr {
1718    #[cfg_attr(feature = "recursive-protection", recursive::recursive)]
1719    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1720        match self {
1721            Expr::Identifier(s) => write!(f, "{s}"),
1722            Expr::Wildcard(_) => f.write_str("*"),
1723            Expr::QualifiedWildcard(prefix, _) => write!(f, "{prefix}.*"),
1724            Expr::CompoundIdentifier(s) => write!(f, "{}", display_separated(s, ".")),
1725            Expr::CompoundFieldAccess { root, access_chain } => {
1726                write!(f, "{root}")?;
1727                for field in access_chain {
1728                    write!(f, "{field}")?;
1729                }
1730                Ok(())
1731            }
1732            Expr::IsTrue(ast) => write!(f, "{ast} IS TRUE"),
1733            Expr::IsNotTrue(ast) => write!(f, "{ast} IS NOT TRUE"),
1734            Expr::IsFalse(ast) => write!(f, "{ast} IS FALSE"),
1735            Expr::IsNotFalse(ast) => write!(f, "{ast} IS NOT FALSE"),
1736            Expr::IsNull(ast) => write!(f, "{ast} IS NULL"),
1737            Expr::IsNotNull(ast) => write!(f, "{ast} IS NOT NULL"),
1738            Expr::IsUnknown(ast) => write!(f, "{ast} IS UNKNOWN"),
1739            Expr::IsNotUnknown(ast) => write!(f, "{ast} IS NOT UNKNOWN"),
1740            Expr::InList {
1741                expr,
1742                list,
1743                negated,
1744            } => write!(
1745                f,
1746                "{} {}IN ({})",
1747                expr,
1748                if *negated { "NOT " } else { "" },
1749                display_comma_separated(list)
1750            ),
1751            Expr::InSubquery {
1752                expr,
1753                subquery,
1754                negated,
1755            } => write!(
1756                f,
1757                "{} {}IN ({})",
1758                expr,
1759                if *negated { "NOT " } else { "" },
1760                subquery
1761            ),
1762            Expr::InUnnest {
1763                expr,
1764                array_expr,
1765                negated,
1766            } => write!(
1767                f,
1768                "{} {}IN UNNEST({})",
1769                expr,
1770                if *negated { "NOT " } else { "" },
1771                array_expr
1772            ),
1773            Expr::Between {
1774                expr,
1775                negated,
1776                low,
1777                high,
1778            } => write!(
1779                f,
1780                "{} {}BETWEEN {} AND {}",
1781                expr,
1782                if *negated { "NOT " } else { "" },
1783                low,
1784                high
1785            ),
1786            Expr::BinaryOp { left, op, right } => write!(f, "{left} {op} {right}"),
1787            Expr::Like {
1788                negated,
1789                expr,
1790                pattern,
1791                escape_char,
1792                any,
1793            } => match escape_char {
1794                Some(ch) => write!(
1795                    f,
1796                    "{} {}LIKE {}{} ESCAPE {}",
1797                    expr,
1798                    if *negated { "NOT " } else { "" },
1799                    if *any { "ANY " } else { "" },
1800                    pattern,
1801                    ch
1802                ),
1803                _ => write!(
1804                    f,
1805                    "{} {}LIKE {}{}",
1806                    expr,
1807                    if *negated { "NOT " } else { "" },
1808                    if *any { "ANY " } else { "" },
1809                    pattern
1810                ),
1811            },
1812            Expr::ILike {
1813                negated,
1814                expr,
1815                pattern,
1816                escape_char,
1817                any,
1818            } => match escape_char {
1819                Some(ch) => write!(
1820                    f,
1821                    "{} {}ILIKE {}{} ESCAPE {}",
1822                    expr,
1823                    if *negated { "NOT " } else { "" },
1824                    if *any { "ANY" } else { "" },
1825                    pattern,
1826                    ch
1827                ),
1828                _ => write!(
1829                    f,
1830                    "{} {}ILIKE {}{}",
1831                    expr,
1832                    if *negated { "NOT " } else { "" },
1833                    if *any { "ANY " } else { "" },
1834                    pattern
1835                ),
1836            },
1837            Expr::RLike {
1838                negated,
1839                expr,
1840                pattern,
1841                regexp,
1842            } => write!(
1843                f,
1844                "{} {}{} {}",
1845                expr,
1846                if *negated { "NOT " } else { "" },
1847                if *regexp { "REGEXP" } else { "RLIKE" },
1848                pattern
1849            ),
1850            Expr::IsNormalized {
1851                expr,
1852                form,
1853                negated,
1854            } => {
1855                let not_ = if *negated { "NOT " } else { "" };
1856                if form.is_none() {
1857                    write!(f, "{expr} IS {not_}NORMALIZED")
1858                } else {
1859                    write!(
1860                        f,
1861                        "{} IS {}{} NORMALIZED",
1862                        expr,
1863                        not_,
1864                        form.as_ref().unwrap()
1865                    )
1866                }
1867            }
1868            Expr::SimilarTo {
1869                negated,
1870                expr,
1871                pattern,
1872                escape_char,
1873            } => match escape_char {
1874                Some(ch) => write!(
1875                    f,
1876                    "{} {}SIMILAR TO {} ESCAPE {}",
1877                    expr,
1878                    if *negated { "NOT " } else { "" },
1879                    pattern,
1880                    ch
1881                ),
1882                _ => write!(
1883                    f,
1884                    "{} {}SIMILAR TO {}",
1885                    expr,
1886                    if *negated { "NOT " } else { "" },
1887                    pattern
1888                ),
1889            },
1890            Expr::AnyOp {
1891                left,
1892                compare_op,
1893                right,
1894                is_some,
1895            } => {
1896                let add_parens = !matches!(right.as_ref(), Expr::Subquery(_));
1897                write!(
1898                    f,
1899                    "{left} {compare_op} {}{}{right}{}",
1900                    if *is_some { "SOME" } else { "ANY" },
1901                    if add_parens { "(" } else { "" },
1902                    if add_parens { ")" } else { "" },
1903                )
1904            }
1905            Expr::AllOp {
1906                left,
1907                compare_op,
1908                right,
1909            } => {
1910                let add_parens = !matches!(right.as_ref(), Expr::Subquery(_));
1911                write!(
1912                    f,
1913                    "{left} {compare_op} ALL{}{right}{}",
1914                    if add_parens { "(" } else { "" },
1915                    if add_parens { ")" } else { "" },
1916                )
1917            }
1918            Expr::UnaryOp { op, expr } => {
1919                if op == &UnaryOperator::PGPostfixFactorial {
1920                    write!(f, "{expr}{op}")
1921                } else if matches!(
1922                    op,
1923                    UnaryOperator::Not
1924                        | UnaryOperator::Hash
1925                        | UnaryOperator::AtDashAt
1926                        | UnaryOperator::DoubleAt
1927                        | UnaryOperator::QuestionDash
1928                        | UnaryOperator::QuestionPipe
1929                ) {
1930                    write!(f, "{op} {expr}")
1931                } else {
1932                    write!(f, "{op}{expr}")
1933                }
1934            }
1935            Expr::Convert {
1936                is_try,
1937                expr,
1938                target_before_value,
1939                data_type,
1940                charset,
1941                styles,
1942            } => {
1943                write!(f, "{}CONVERT(", if *is_try { "TRY_" } else { "" })?;
1944                if let Some(data_type) = data_type {
1945                    if let Some(charset) = charset {
1946                        write!(f, "{expr}, {data_type} CHARACTER SET {charset}")
1947                    } else if *target_before_value {
1948                        write!(f, "{data_type}, {expr}")
1949                    } else {
1950                        write!(f, "{expr}, {data_type}")
1951                    }
1952                } else if let Some(charset) = charset {
1953                    write!(f, "{expr} USING {charset}")
1954                } else {
1955                    write!(f, "{expr}") // This should never happen
1956                }?;
1957                if !styles.is_empty() {
1958                    write!(f, ", {}", display_comma_separated(styles))?;
1959                }
1960                write!(f, ")")
1961            }
1962            Expr::Cast {
1963                kind,
1964                expr,
1965                data_type,
1966                array,
1967                format,
1968            } => match kind {
1969                CastKind::Cast => {
1970                    write!(f, "CAST({expr} AS {data_type}")?;
1971                    if *array {
1972                        write!(f, " ARRAY")?;
1973                    }
1974                    if let Some(format) = format {
1975                        write!(f, " FORMAT {format}")?;
1976                    }
1977                    write!(f, ")")
1978                }
1979                CastKind::TryCast => {
1980                    if let Some(format) = format {
1981                        write!(f, "TRY_CAST({expr} AS {data_type} FORMAT {format})")
1982                    } else {
1983                        write!(f, "TRY_CAST({expr} AS {data_type})")
1984                    }
1985                }
1986                CastKind::SafeCast => {
1987                    if let Some(format) = format {
1988                        write!(f, "SAFE_CAST({expr} AS {data_type} FORMAT {format})")
1989                    } else {
1990                        write!(f, "SAFE_CAST({expr} AS {data_type})")
1991                    }
1992                }
1993                CastKind::DoubleColon => {
1994                    write!(f, "{expr}::{data_type}")
1995                }
1996            },
1997            Expr::Extract {
1998                field,
1999                syntax,
2000                expr,
2001            } => match syntax {
2002                ExtractSyntax::From => write!(f, "EXTRACT({field} FROM {expr})"),
2003                ExtractSyntax::Comma => write!(f, "EXTRACT({field}, {expr})"),
2004            },
2005            Expr::Ceil { expr, field } => match field {
2006                CeilFloorKind::DateTimeField(DateTimeField::NoDateTime) => {
2007                    write!(f, "CEIL({expr})")
2008                }
2009                CeilFloorKind::DateTimeField(dt_field) => write!(f, "CEIL({expr} TO {dt_field})"),
2010                CeilFloorKind::Scale(s) => write!(f, "CEIL({expr}, {s})"),
2011            },
2012            Expr::Floor { expr, field } => match field {
2013                CeilFloorKind::DateTimeField(DateTimeField::NoDateTime) => {
2014                    write!(f, "FLOOR({expr})")
2015                }
2016                CeilFloorKind::DateTimeField(dt_field) => write!(f, "FLOOR({expr} TO {dt_field})"),
2017                CeilFloorKind::Scale(s) => write!(f, "FLOOR({expr}, {s})"),
2018            },
2019            Expr::Position { expr, r#in } => write!(f, "POSITION({expr} IN {in})"),
2020            Expr::Collate { expr, collation } => write!(f, "{expr} COLLATE {collation}"),
2021            Expr::Nested(ast) => write!(f, "({ast})"),
2022            Expr::Value(v) => write!(f, "{v}"),
2023            Expr::Prefixed { prefix, value } => write!(f, "{prefix} {value}"),
2024            Expr::TypedString(ts) => ts.fmt(f),
2025            Expr::Function(fun) => fun.fmt(f),
2026            Expr::Case {
2027                case_token: _,
2028                end_token: _,
2029                operand,
2030                conditions,
2031                else_result,
2032            } => {
2033                f.write_str("CASE")?;
2034                if let Some(operand) = operand {
2035                    f.write_str(" ")?;
2036                    operand.fmt(f)?;
2037                }
2038                for when in conditions {
2039                    SpaceOrNewline.fmt(f)?;
2040                    Indent(when).fmt(f)?;
2041                }
2042                if let Some(else_result) = else_result {
2043                    SpaceOrNewline.fmt(f)?;
2044                    Indent("ELSE").fmt(f)?;
2045                    SpaceOrNewline.fmt(f)?;
2046                    Indent(Indent(else_result)).fmt(f)?;
2047                }
2048                SpaceOrNewline.fmt(f)?;
2049                f.write_str("END")
2050            }
2051            Expr::Exists { subquery, negated } => write!(
2052                f,
2053                "{}EXISTS ({})",
2054                if *negated { "NOT " } else { "" },
2055                subquery
2056            ),
2057            Expr::Subquery(s) => write!(f, "({s})"),
2058            Expr::GroupingSets(sets) => {
2059                write!(f, "GROUPING SETS (")?;
2060                let mut sep = "";
2061                for set in sets {
2062                    write!(f, "{sep}")?;
2063                    sep = ", ";
2064                    write!(f, "({})", display_comma_separated(set))?;
2065                }
2066                write!(f, ")")
2067            }
2068            Expr::Cube(sets) => {
2069                write!(f, "CUBE (")?;
2070                let mut sep = "";
2071                for set in sets {
2072                    write!(f, "{sep}")?;
2073                    sep = ", ";
2074                    if set.len() == 1 {
2075                        write!(f, "{}", set[0])?;
2076                    } else {
2077                        write!(f, "({})", display_comma_separated(set))?;
2078                    }
2079                }
2080                write!(f, ")")
2081            }
2082            Expr::Rollup(sets) => {
2083                write!(f, "ROLLUP (")?;
2084                let mut sep = "";
2085                for set in sets {
2086                    write!(f, "{sep}")?;
2087                    sep = ", ";
2088                    if set.len() == 1 {
2089                        write!(f, "{}", set[0])?;
2090                    } else {
2091                        write!(f, "({})", display_comma_separated(set))?;
2092                    }
2093                }
2094                write!(f, ")")
2095            }
2096            Expr::Substring {
2097                expr,
2098                substring_from,
2099                substring_for,
2100                special,
2101                shorthand,
2102            } => {
2103                f.write_str("SUBSTR")?;
2104                if !*shorthand {
2105                    f.write_str("ING")?;
2106                }
2107                write!(f, "({expr}")?;
2108                if let Some(from_part) = substring_from {
2109                    if *special {
2110                        write!(f, ", {from_part}")?;
2111                    } else {
2112                        write!(f, " FROM {from_part}")?;
2113                    }
2114                }
2115                if let Some(for_part) = substring_for {
2116                    if *special {
2117                        write!(f, ", {for_part}")?;
2118                    } else {
2119                        write!(f, " FOR {for_part}")?;
2120                    }
2121                }
2122
2123                write!(f, ")")
2124            }
2125            Expr::Overlay {
2126                expr,
2127                overlay_what,
2128                overlay_from,
2129                overlay_for,
2130            } => {
2131                write!(
2132                    f,
2133                    "OVERLAY({expr} PLACING {overlay_what} FROM {overlay_from}"
2134                )?;
2135                if let Some(for_part) = overlay_for {
2136                    write!(f, " FOR {for_part}")?;
2137                }
2138
2139                write!(f, ")")
2140            }
2141            Expr::IsDistinctFrom(a, b) => write!(f, "{a} IS DISTINCT FROM {b}"),
2142            Expr::IsNotDistinctFrom(a, b) => write!(f, "{a} IS NOT DISTINCT FROM {b}"),
2143            Expr::Trim {
2144                expr,
2145                trim_where,
2146                trim_what,
2147                trim_characters,
2148            } => {
2149                write!(f, "TRIM(")?;
2150                if let Some(ident) = trim_where {
2151                    write!(f, "{ident} ")?;
2152                }
2153                if let Some(trim_char) = trim_what {
2154                    write!(f, "{trim_char} FROM {expr}")?;
2155                } else {
2156                    write!(f, "{expr}")?;
2157                }
2158                if let Some(characters) = trim_characters {
2159                    write!(f, ", {}", display_comma_separated(characters))?;
2160                }
2161
2162                write!(f, ")")
2163            }
2164            Expr::Tuple(exprs) => {
2165                write!(f, "({})", display_comma_separated(exprs))
2166            }
2167            Expr::Struct { values, fields } => {
2168                if !fields.is_empty() {
2169                    write!(
2170                        f,
2171                        "STRUCT<{}>({})",
2172                        display_comma_separated(fields),
2173                        display_comma_separated(values)
2174                    )
2175                } else {
2176                    write!(f, "STRUCT({})", display_comma_separated(values))
2177                }
2178            }
2179            Expr::Named { expr, name } => {
2180                write!(f, "{expr} AS {name}")
2181            }
2182            Expr::Dictionary(fields) => {
2183                write!(f, "{{{}}}", display_comma_separated(fields))
2184            }
2185            Expr::Map(map) => {
2186                write!(f, "{map}")
2187            }
2188            Expr::Array(set) => {
2189                write!(f, "{set}")
2190            }
2191            Expr::JsonAccess { value, path } => {
2192                write!(f, "{value}{path}")
2193            }
2194            Expr::AtTimeZone {
2195                timestamp,
2196                time_zone,
2197            } => {
2198                write!(f, "{timestamp} AT TIME ZONE {time_zone}")
2199            }
2200            Expr::Interval(interval) => {
2201                write!(f, "{interval}")
2202            }
2203            Expr::MatchAgainst {
2204                columns,
2205                match_value: match_expr,
2206                opt_search_modifier,
2207            } => {
2208                write!(f, "MATCH ({}) AGAINST ", display_comma_separated(columns),)?;
2209
2210                if let Some(search_modifier) = opt_search_modifier {
2211                    write!(f, "({match_expr} {search_modifier})")?;
2212                } else {
2213                    write!(f, "({match_expr})")?;
2214                }
2215
2216                Ok(())
2217            }
2218            Expr::OuterJoin(expr) => {
2219                write!(f, "{expr} (+)")
2220            }
2221            Expr::Prior(expr) => write!(f, "PRIOR {expr}"),
2222            Expr::Lambda(lambda) => write!(f, "{lambda}"),
2223            Expr::MemberOf(member_of) => write!(f, "{member_of}"),
2224        }
2225    }
2226}
2227
2228/// The type of a window used in `OVER` clauses.
2229///
2230/// A window can be either an inline specification (`WindowSpec`) or a
2231/// reference to a previously defined named window.
2232///
2233/// - `WindowSpec(WindowSpec)`: An inline window specification, e.g.
2234///   `OVER (PARTITION BY ... ORDER BY ...)`.
2235/// - `NamedWindow(Ident)`: A reference to a named window declared elsewhere.
2236#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2237#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2238#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2239pub enum WindowType {
2240    /// An inline window specification.
2241    WindowSpec(WindowSpec),
2242    /// A reference to a previously defined named window.
2243    NamedWindow(Ident),
2244}
2245
2246impl Display for WindowType {
2247    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2248        match self {
2249            WindowType::WindowSpec(spec) => {
2250                f.write_str("(")?;
2251                NewLine.fmt(f)?;
2252                Indent(spec).fmt(f)?;
2253                NewLine.fmt(f)?;
2254                f.write_str(")")
2255            }
2256            WindowType::NamedWindow(name) => name.fmt(f),
2257        }
2258    }
2259}
2260
2261/// A window specification (i.e. `OVER ([window_name] PARTITION BY .. ORDER BY .. etc.)`)
2262#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2263#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2264#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2265pub struct WindowSpec {
2266    /// Optional window name.
2267    ///
2268    /// You can find it at least in [MySQL][1], [BigQuery][2], [PostgreSQL][3]
2269    ///
2270    /// [1]: https://dev.mysql.com/doc/refman/8.0/en/window-functions-named-windows.html
2271    /// [2]: https://cloud.google.com/bigquery/docs/reference/standard-sql/window-function-calls
2272    /// [3]: https://www.postgresql.org/docs/current/sql-expressions.html#SYNTAX-WINDOW-FUNCTIONS
2273    pub window_name: Option<Ident>,
2274    /// `OVER (PARTITION BY ...)`
2275    pub partition_by: Vec<Expr>,
2276    /// `OVER (ORDER BY ...)`
2277    pub order_by: Vec<OrderByExpr>,
2278    /// `OVER (window frame)`
2279    pub window_frame: Option<WindowFrame>,
2280}
2281
2282impl fmt::Display for WindowSpec {
2283    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2284        let mut is_first = true;
2285        if let Some(window_name) = &self.window_name {
2286            if !is_first {
2287                SpaceOrNewline.fmt(f)?;
2288            }
2289            is_first = false;
2290            write!(f, "{window_name}")?;
2291        }
2292        if !self.partition_by.is_empty() {
2293            if !is_first {
2294                SpaceOrNewline.fmt(f)?;
2295            }
2296            is_first = false;
2297            write!(
2298                f,
2299                "PARTITION BY {}",
2300                display_comma_separated(&self.partition_by)
2301            )?;
2302        }
2303        if !self.order_by.is_empty() {
2304            if !is_first {
2305                SpaceOrNewline.fmt(f)?;
2306            }
2307            is_first = false;
2308            write!(f, "ORDER BY {}", display_comma_separated(&self.order_by))?;
2309        }
2310        if let Some(window_frame) = &self.window_frame {
2311            if !is_first {
2312                SpaceOrNewline.fmt(f)?;
2313            }
2314            if let Some(end_bound) = &window_frame.end_bound {
2315                write!(
2316                    f,
2317                    "{} BETWEEN {} AND {}",
2318                    window_frame.units, window_frame.start_bound, end_bound
2319                )?;
2320            } else {
2321                write!(f, "{} {}", window_frame.units, window_frame.start_bound)?;
2322            }
2323        }
2324        Ok(())
2325    }
2326}
2327
2328/// Specifies the data processed by a window function, e.g.
2329/// `RANGE UNBOUNDED PRECEDING` or `ROWS BETWEEN 5 PRECEDING AND CURRENT ROW`.
2330///
2331/// Note: The parser does not validate the specified bounds; the caller should
2332/// reject invalid bounds like `ROWS UNBOUNDED FOLLOWING` before execution.
2333#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2334#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2335#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2336pub struct WindowFrame {
2337    /// Units for the frame (e.g. `ROWS`, `RANGE`, `GROUPS`).
2338    pub units: WindowFrameUnits,
2339    /// The start bound of the window frame.
2340    pub start_bound: WindowFrameBound,
2341    /// The right bound of the `BETWEEN .. AND` clause. The end bound of `None`
2342    /// indicates the shorthand form (e.g. `ROWS 1 PRECEDING`), which must
2343    /// behave the same as `end_bound = WindowFrameBound::CurrentRow`.
2344    pub end_bound: Option<WindowFrameBound>,
2345    // TBD: EXCLUDE
2346}
2347
2348impl Default for WindowFrame {
2349    /// Returns default value for window frame
2350    ///
2351    /// See [this page](https://www.sqlite.org/windowfunctions.html#frame_specifications) for more details.
2352    fn default() -> Self {
2353        Self {
2354            units: WindowFrameUnits::Range,
2355            start_bound: WindowFrameBound::Preceding(None),
2356            end_bound: None,
2357        }
2358    }
2359}
2360
2361#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2362#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2363#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2364/// Units used to describe the window frame scope.
2365pub enum WindowFrameUnits {
2366    /// `ROWS` unit.
2367    Rows,
2368    /// `RANGE` unit.
2369    Range,
2370    /// `GROUPS` unit.
2371    Groups,
2372}
2373
2374impl fmt::Display for WindowFrameUnits {
2375    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2376        f.write_str(match self {
2377            WindowFrameUnits::Rows => "ROWS",
2378            WindowFrameUnits::Range => "RANGE",
2379            WindowFrameUnits::Groups => "GROUPS",
2380        })
2381    }
2382}
2383
2384/// Specifies Ignore / Respect NULL within window functions.
2385/// For example
2386/// `FIRST_VALUE(column2) IGNORE NULLS OVER (PARTITION BY column1)`
2387#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2388#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2389#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2390/// How NULL values are treated in certain window functions.
2391pub enum NullTreatment {
2392    /// Ignore NULL values (e.g. `IGNORE NULLS`).
2393    IgnoreNulls,
2394    /// Respect NULL values (e.g. `RESPECT NULLS`).
2395    RespectNulls,
2396}
2397
2398impl fmt::Display for NullTreatment {
2399    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2400        f.write_str(match self {
2401            NullTreatment::IgnoreNulls => "IGNORE NULLS",
2402            NullTreatment::RespectNulls => "RESPECT NULLS",
2403        })
2404    }
2405}
2406
2407/// Specifies [WindowFrame]'s `start_bound` and `end_bound`
2408#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2409#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2410#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2411pub enum WindowFrameBound {
2412    /// `CURRENT ROW`
2413    CurrentRow,
2414    /// `<N> PRECEDING` or `UNBOUNDED PRECEDING`
2415    Preceding(Option<Box<Expr>>),
2416    /// `<N> FOLLOWING` or `UNBOUNDED FOLLOWING`.
2417    Following(Option<Box<Expr>>),
2418}
2419
2420impl fmt::Display for WindowFrameBound {
2421    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2422        match self {
2423            WindowFrameBound::CurrentRow => f.write_str("CURRENT ROW"),
2424            WindowFrameBound::Preceding(None) => f.write_str("UNBOUNDED PRECEDING"),
2425            WindowFrameBound::Following(None) => f.write_str("UNBOUNDED FOLLOWING"),
2426            WindowFrameBound::Preceding(Some(n)) => write!(f, "{n} PRECEDING"),
2427            WindowFrameBound::Following(Some(n)) => write!(f, "{n} FOLLOWING"),
2428        }
2429    }
2430}
2431
2432#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2433#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2434#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2435/// Indicates partition operation type for partition management statements.
2436pub enum AddDropSync {
2437    /// Add partitions.
2438    ADD,
2439    /// Drop partitions.
2440    DROP,
2441    /// Sync partitions.
2442    SYNC,
2443}
2444
2445impl fmt::Display for AddDropSync {
2446    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2447        match self {
2448            AddDropSync::SYNC => f.write_str("SYNC PARTITIONS"),
2449            AddDropSync::DROP => f.write_str("DROP PARTITIONS"),
2450            AddDropSync::ADD => f.write_str("ADD PARTITIONS"),
2451        }
2452    }
2453}
2454
2455#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2456#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2457#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2458/// Object kinds supported by `SHOW CREATE` statements.
2459pub enum ShowCreateObject {
2460    /// An event object for `SHOW CREATE EVENT`.
2461    Event,
2462    /// A function object for `SHOW CREATE FUNCTION`.
2463    Function,
2464    /// A procedure object for `SHOW CREATE PROCEDURE`.
2465    Procedure,
2466    /// A table object for `SHOW CREATE TABLE`.
2467    Table,
2468    /// A trigger object for `SHOW CREATE TRIGGER`.
2469    Trigger,
2470    /// A view object for `SHOW CREATE VIEW`.
2471    View,
2472}
2473
2474impl fmt::Display for ShowCreateObject {
2475    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2476        match self {
2477            ShowCreateObject::Event => f.write_str("EVENT"),
2478            ShowCreateObject::Function => f.write_str("FUNCTION"),
2479            ShowCreateObject::Procedure => f.write_str("PROCEDURE"),
2480            ShowCreateObject::Table => f.write_str("TABLE"),
2481            ShowCreateObject::Trigger => f.write_str("TRIGGER"),
2482            ShowCreateObject::View => f.write_str("VIEW"),
2483        }
2484    }
2485}
2486
2487#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2488#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2489#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2490/// Objects that can be targeted by a `COMMENT` statement.
2491pub enum CommentObject {
2492    /// A collation.
2493    Collation,
2494    /// A table column.
2495    Column,
2496    /// A database.
2497    Database,
2498    /// A domain.
2499    Domain,
2500    /// An extension.
2501    Extension,
2502    /// A function.
2503    Function,
2504    /// An index.
2505    Index,
2506    /// A materialized view.
2507    MaterializedView,
2508    /// A procedure.
2509    Procedure,
2510    /// A role.
2511    Role,
2512    /// A schema.
2513    Schema,
2514    /// A sequence.
2515    Sequence,
2516    /// A table.
2517    Table,
2518    /// A type.
2519    Type,
2520    /// A user.
2521    User,
2522    /// A view.
2523    View,
2524}
2525
2526impl fmt::Display for CommentObject {
2527    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2528        match self {
2529            CommentObject::Collation => f.write_str("COLLATION"),
2530            CommentObject::Column => f.write_str("COLUMN"),
2531            CommentObject::Database => f.write_str("DATABASE"),
2532            CommentObject::Domain => f.write_str("DOMAIN"),
2533            CommentObject::Extension => f.write_str("EXTENSION"),
2534            CommentObject::Function => f.write_str("FUNCTION"),
2535            CommentObject::Index => f.write_str("INDEX"),
2536            CommentObject::MaterializedView => f.write_str("MATERIALIZED VIEW"),
2537            CommentObject::Procedure => f.write_str("PROCEDURE"),
2538            CommentObject::Role => f.write_str("ROLE"),
2539            CommentObject::Schema => f.write_str("SCHEMA"),
2540            CommentObject::Sequence => f.write_str("SEQUENCE"),
2541            CommentObject::Table => f.write_str("TABLE"),
2542            CommentObject::Type => f.write_str("TYPE"),
2543            CommentObject::User => f.write_str("USER"),
2544            CommentObject::View => f.write_str("VIEW"),
2545        }
2546    }
2547}
2548
2549#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2550#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2551#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2552/// Password specification variants used in user-related statements.
2553pub enum Password {
2554    /// A concrete password expression.
2555    Password(Expr),
2556    /// Represents a `NULL` password.
2557    NullPassword,
2558}
2559
2560/// A `CASE` statement.
2561///
2562/// Examples:
2563/// ```sql
2564/// CASE
2565///     WHEN EXISTS(SELECT 1)
2566///         THEN SELECT 1 FROM T;
2567///     WHEN EXISTS(SELECT 2)
2568///         THEN SELECT 1 FROM U;
2569///     ELSE
2570///         SELECT 1 FROM V;
2571/// END CASE;
2572/// ```
2573///
2574/// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#case_search_expression)
2575/// [Snowflake](https://docs.snowflake.com/en/sql-reference/snowflake-scripting/case)
2576#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2577#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2578#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2579pub struct CaseStatement {
2580    /// The `CASE` token that starts the statement.
2581    pub case_token: AttachedToken,
2582    /// Optional expression to match against in `CASE ... WHEN`.
2583    pub match_expr: Option<Expr>,
2584    /// The `WHEN ... THEN` blocks of the `CASE` statement.
2585    pub when_blocks: Vec<ConditionalStatementBlock>,
2586    /// Optional `ELSE` block for the `CASE` statement.
2587    pub else_block: Option<ConditionalStatementBlock>,
2588    /// The last token of the statement (`END` or `CASE`).
2589    pub end_case_token: AttachedToken,
2590}
2591
2592impl fmt::Display for CaseStatement {
2593    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2594        let CaseStatement {
2595            case_token: _,
2596            match_expr,
2597            when_blocks,
2598            else_block,
2599            end_case_token: AttachedToken(end),
2600        } = self;
2601
2602        write!(f, "CASE")?;
2603
2604        if let Some(expr) = match_expr {
2605            write!(f, " {expr}")?;
2606        }
2607
2608        if !when_blocks.is_empty() {
2609            write!(f, " {}", display_separated(when_blocks, " "))?;
2610        }
2611
2612        if let Some(else_block) = else_block {
2613            write!(f, " {else_block}")?;
2614        }
2615
2616        write!(f, " END")?;
2617
2618        if let Token::Word(w) = &end.token {
2619            if w.keyword == Keyword::CASE {
2620                write!(f, " CASE")?;
2621            }
2622        }
2623
2624        Ok(())
2625    }
2626}
2627
2628/// An `IF` statement.
2629///
2630/// Example (BigQuery or Snowflake):
2631/// ```sql
2632/// IF TRUE THEN
2633///     SELECT 1;
2634///     SELECT 2;
2635/// ELSEIF TRUE THEN
2636///     SELECT 3;
2637/// ELSE
2638///     SELECT 4;
2639/// END IF
2640/// ```
2641/// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#if)
2642/// [Snowflake](https://docs.snowflake.com/en/sql-reference/snowflake-scripting/if)
2643///
2644/// Example (MSSQL):
2645/// ```sql
2646/// IF 1=1 SELECT 1 ELSE SELECT 2
2647/// ```
2648/// [MSSQL](https://learn.microsoft.com/en-us/sql/t-sql/language-elements/if-else-transact-sql?view=sql-server-ver16)
2649#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2650#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2651#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2652pub struct IfStatement {
2653    /// The initial `IF` block containing the condition and statements.
2654    pub if_block: ConditionalStatementBlock,
2655    /// Additional `ELSEIF` blocks.
2656    pub elseif_blocks: Vec<ConditionalStatementBlock>,
2657    /// Optional `ELSE` block.
2658    pub else_block: Option<ConditionalStatementBlock>,
2659    /// Optional trailing `END` token for the `IF` statement.
2660    pub end_token: Option<AttachedToken>,
2661}
2662
2663impl fmt::Display for IfStatement {
2664    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2665        let IfStatement {
2666            if_block,
2667            elseif_blocks,
2668            else_block,
2669            end_token,
2670        } = self;
2671
2672        write!(f, "{if_block}")?;
2673
2674        for elseif_block in elseif_blocks {
2675            write!(f, " {elseif_block}")?;
2676        }
2677
2678        if let Some(else_block) = else_block {
2679            write!(f, " {else_block}")?;
2680        }
2681
2682        if let Some(AttachedToken(end_token)) = end_token {
2683            write!(f, " END {end_token}")?;
2684        }
2685
2686        Ok(())
2687    }
2688}
2689
2690/// A `WHILE` statement.
2691///
2692/// Example:
2693/// ```sql
2694/// WHILE @@FETCH_STATUS = 0
2695/// BEGIN
2696///    FETCH NEXT FROM c1 INTO @var1, @var2;
2697/// END
2698/// ```
2699///
2700/// [MsSql](https://learn.microsoft.com/en-us/sql/t-sql/language-elements/while-transact-sql)
2701#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2702#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2703#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2704pub struct WhileStatement {
2705    /// Block executed while the condition holds.
2706    pub while_block: ConditionalStatementBlock,
2707}
2708
2709impl fmt::Display for WhileStatement {
2710    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2711        let WhileStatement { while_block } = self;
2712        write!(f, "{while_block}")?;
2713        Ok(())
2714    }
2715}
2716
2717/// A block within a [Statement::Case] or [Statement::If] or [Statement::While]-like statement
2718///
2719/// Example 1:
2720/// ```sql
2721/// WHEN EXISTS(SELECT 1) THEN SELECT 1;
2722/// ```
2723///
2724/// Example 2:
2725/// ```sql
2726/// IF TRUE THEN SELECT 1; SELECT 2;
2727/// ```
2728///
2729/// Example 3:
2730/// ```sql
2731/// ELSE SELECT 1; SELECT 2;
2732/// ```
2733///
2734/// Example 4:
2735/// ```sql
2736/// WHILE @@FETCH_STATUS = 0
2737/// BEGIN
2738///    FETCH NEXT FROM c1 INTO @var1, @var2;
2739/// END
2740/// ```
2741#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2742#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2743#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2744pub struct ConditionalStatementBlock {
2745    /// Token representing the start of the block (e.g., WHEN/IF/WHILE).
2746    pub start_token: AttachedToken,
2747    /// Optional condition expression for the block.
2748    pub condition: Option<Expr>,
2749    /// Optional token for the `THEN` keyword.
2750    pub then_token: Option<AttachedToken>,
2751    /// The statements contained in this conditional block.
2752    pub conditional_statements: ConditionalStatements,
2753}
2754
2755impl ConditionalStatementBlock {
2756    /// Get the statements in this conditional block.
2757    pub fn statements(&self) -> &Vec<Statement> {
2758        self.conditional_statements.statements()
2759    }
2760}
2761
2762impl fmt::Display for ConditionalStatementBlock {
2763    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2764        let ConditionalStatementBlock {
2765            start_token: AttachedToken(start_token),
2766            condition,
2767            then_token,
2768            conditional_statements,
2769        } = self;
2770
2771        write!(f, "{start_token}")?;
2772
2773        if let Some(condition) = condition {
2774            write!(f, " {condition}")?;
2775        }
2776
2777        if then_token.is_some() {
2778            write!(f, " THEN")?;
2779        }
2780
2781        if !conditional_statements.statements().is_empty() {
2782            write!(f, " {conditional_statements}")?;
2783        }
2784
2785        Ok(())
2786    }
2787}
2788
2789/// A list of statements in a [ConditionalStatementBlock].
2790#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2791#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2792#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2793/// Statements used inside conditional blocks (`IF`, `WHEN`, `WHILE`).
2794pub enum ConditionalStatements {
2795    /// Simple sequence of statements (no `BEGIN`/`END`).
2796    Sequence {
2797        /// The statements in the sequence.
2798        statements: Vec<Statement>,
2799    },
2800    /// Block enclosed by `BEGIN` and `END`.
2801    BeginEnd(BeginEndStatements),
2802}
2803
2804impl ConditionalStatements {
2805    /// Get the statements in this conditional statements block.
2806    pub fn statements(&self) -> &Vec<Statement> {
2807        match self {
2808            ConditionalStatements::Sequence { statements } => statements,
2809            ConditionalStatements::BeginEnd(bes) => &bes.statements,
2810        }
2811    }
2812}
2813
2814impl fmt::Display for ConditionalStatements {
2815    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2816        match self {
2817            ConditionalStatements::Sequence { statements } => {
2818                if !statements.is_empty() {
2819                    format_statement_list(f, statements)?;
2820                }
2821                Ok(())
2822            }
2823            ConditionalStatements::BeginEnd(bes) => write!(f, "{bes}"),
2824        }
2825    }
2826}
2827
2828/// Represents a list of statements enclosed within `BEGIN` and `END` keywords.
2829/// Example:
2830/// ```sql
2831/// BEGIN
2832///     SELECT 1;
2833///     SELECT 2;
2834/// END
2835/// ```
2836#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2837#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2838#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2839pub struct BeginEndStatements {
2840    /// Token representing the `BEGIN` keyword (may include span info).
2841    pub begin_token: AttachedToken,
2842    /// Statements contained within the block.
2843    pub statements: Vec<Statement>,
2844    /// Token representing the `END` keyword (may include span info).
2845    pub end_token: AttachedToken,
2846}
2847
2848impl fmt::Display for BeginEndStatements {
2849    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2850        let BeginEndStatements {
2851            begin_token: AttachedToken(begin_token),
2852            statements,
2853            end_token: AttachedToken(end_token),
2854        } = self;
2855
2856        if begin_token.token != Token::EOF {
2857            write!(f, "{begin_token} ")?;
2858        }
2859        if !statements.is_empty() {
2860            format_statement_list(f, statements)?;
2861        }
2862        if end_token.token != Token::EOF {
2863            write!(f, " {end_token}")?;
2864        }
2865        Ok(())
2866    }
2867}
2868
2869/// A `RAISE` statement.
2870///
2871/// Examples:
2872/// ```sql
2873/// RAISE USING MESSAGE = 'error';
2874///
2875/// RAISE myerror;
2876/// ```
2877///
2878/// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#raise)
2879/// [Snowflake](https://docs.snowflake.com/en/sql-reference/snowflake-scripting/raise)
2880#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2881#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2882#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2883pub struct RaiseStatement {
2884    /// Optional value provided to the RAISE statement.
2885    pub value: Option<RaiseStatementValue>,
2886}
2887
2888impl fmt::Display for RaiseStatement {
2889    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2890        let RaiseStatement { value } = self;
2891
2892        write!(f, "RAISE")?;
2893        if let Some(value) = value {
2894            write!(f, " {value}")?;
2895        }
2896
2897        Ok(())
2898    }
2899}
2900
2901/// Represents the error value of a [RaiseStatement].
2902#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2903#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2904#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2905pub enum RaiseStatementValue {
2906    /// `RAISE USING MESSAGE = 'error'`
2907    UsingMessage(Expr),
2908    /// `RAISE myerror`
2909    Expr(Expr),
2910}
2911
2912impl fmt::Display for RaiseStatementValue {
2913    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2914        match self {
2915            RaiseStatementValue::Expr(expr) => write!(f, "{expr}"),
2916            RaiseStatementValue::UsingMessage(expr) => write!(f, "USING MESSAGE = {expr}"),
2917        }
2918    }
2919}
2920
2921/// A MSSQL `THROW` statement.
2922///
2923/// ```sql
2924/// THROW [ error_number, message, state ]
2925/// ```
2926///
2927/// [MSSQL](https://learn.microsoft.com/en-us/sql/t-sql/language-elements/throw-transact-sql)
2928#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2929#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2930#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2931pub struct ThrowStatement {
2932    /// Error number expression.
2933    pub error_number: Option<Box<Expr>>,
2934    /// Error message expression.
2935    pub message: Option<Box<Expr>>,
2936    /// State expression.
2937    pub state: Option<Box<Expr>>,
2938}
2939
2940impl fmt::Display for ThrowStatement {
2941    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2942        let ThrowStatement {
2943            error_number,
2944            message,
2945            state,
2946        } = self;
2947
2948        write!(f, "THROW")?;
2949        if let (Some(error_number), Some(message), Some(state)) = (error_number, message, state) {
2950            write!(f, " {error_number}, {message}, {state}")?;
2951        }
2952        Ok(())
2953    }
2954}
2955
2956/// Represents an expression assignment within a variable `DECLARE` statement.
2957///
2958/// Examples:
2959/// ```sql
2960/// DECLARE variable_name := 42
2961/// DECLARE variable_name DEFAULT 42
2962/// ```
2963#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2964#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2965#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2966pub enum DeclareAssignment {
2967    /// Plain expression specified.
2968    Expr(Box<Expr>),
2969
2970    /// Expression assigned via the `DEFAULT` keyword
2971    Default(Box<Expr>),
2972
2973    /// Expression assigned via the `:=` syntax
2974    ///
2975    /// Example:
2976    /// ```sql
2977    /// DECLARE variable_name := 42;
2978    /// ```
2979    DuckAssignment(Box<Expr>),
2980
2981    /// Expression via the `FOR` keyword
2982    ///
2983    /// Example:
2984    /// ```sql
2985    /// DECLARE c1 CURSOR FOR res
2986    /// ```
2987    For(Box<Expr>),
2988
2989    /// Expression via the `=` syntax.
2990    ///
2991    /// Example:
2992    /// ```sql
2993    /// DECLARE @variable AS INT = 100
2994    /// ```
2995    MsSqlAssignment(Box<Expr>),
2996}
2997
2998impl fmt::Display for DeclareAssignment {
2999    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3000        match self {
3001            DeclareAssignment::Expr(expr) => {
3002                write!(f, "{expr}")
3003            }
3004            DeclareAssignment::Default(expr) => {
3005                write!(f, "DEFAULT {expr}")
3006            }
3007            DeclareAssignment::DuckAssignment(expr) => {
3008                write!(f, ":= {expr}")
3009            }
3010            DeclareAssignment::MsSqlAssignment(expr) => {
3011                write!(f, "= {expr}")
3012            }
3013            DeclareAssignment::For(expr) => {
3014                write!(f, "FOR {expr}")
3015            }
3016        }
3017    }
3018}
3019
3020/// Represents the type of a `DECLARE` statement.
3021#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3022#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3023#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3024pub enum DeclareType {
3025    /// Cursor variable type. e.g. [Snowflake] [PostgreSQL] [MsSql]
3026    ///
3027    /// [Snowflake]: https://docs.snowflake.com/en/developer-guide/snowflake-scripting/cursors#declaring-a-cursor
3028    /// [PostgreSQL]: https://www.postgresql.org/docs/current/plpgsql-cursors.html
3029    /// [MsSql]: https://learn.microsoft.com/en-us/sql/t-sql/language-elements/declare-cursor-transact-sql
3030    Cursor,
3031
3032    /// Result set variable type. [Snowflake]
3033    ///
3034    /// Syntax:
3035    /// ```text
3036    /// <resultset_name> RESULTSET [ { DEFAULT | := } ( <query> ) ] ;
3037    /// ```
3038    /// [Snowflake]: https://docs.snowflake.com/en/sql-reference/snowflake-scripting/declare#resultset-declaration-syntax
3039    ResultSet,
3040
3041    /// Exception declaration syntax. [Snowflake]
3042    ///
3043    /// Syntax:
3044    /// ```text
3045    /// <exception_name> EXCEPTION [ ( <exception_number> , '<exception_message>' ) ] ;
3046    /// ```
3047    /// [Snowflake]: https://docs.snowflake.com/en/sql-reference/snowflake-scripting/declare#exception-declaration-syntax
3048    Exception,
3049}
3050
3051impl fmt::Display for DeclareType {
3052    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3053        match self {
3054            DeclareType::Cursor => {
3055                write!(f, "CURSOR")
3056            }
3057            DeclareType::ResultSet => {
3058                write!(f, "RESULTSET")
3059            }
3060            DeclareType::Exception => {
3061                write!(f, "EXCEPTION")
3062            }
3063        }
3064    }
3065}
3066
3067/// A `DECLARE` statement.
3068/// [PostgreSQL] [Snowflake] [BigQuery]
3069///
3070/// Examples:
3071/// ```sql
3072/// DECLARE variable_name := 42
3073/// DECLARE liahona CURSOR FOR SELECT * FROM films;
3074/// ```
3075///
3076/// [PostgreSQL]: https://www.postgresql.org/docs/current/sql-declare.html
3077/// [Snowflake]: https://docs.snowflake.com/en/sql-reference/snowflake-scripting/declare
3078/// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#declare
3079#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3080#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3081#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3082pub struct Declare {
3083    /// The name(s) being declared.
3084    /// Example: `DECLARE a, b, c DEFAULT 42;
3085    pub names: Vec<Ident>,
3086    /// Data-type assigned to the declared variable.
3087    /// Example: `DECLARE x INT64 DEFAULT 42;
3088    pub data_type: Option<DataType>,
3089    /// Expression being assigned to the declared variable.
3090    pub assignment: Option<DeclareAssignment>,
3091    /// Represents the type of the declared variable.
3092    pub declare_type: Option<DeclareType>,
3093    /// Causes the cursor to return data in binary rather than in text format.
3094    pub binary: Option<bool>,
3095    /// None = Not specified
3096    /// Some(true) = INSENSITIVE
3097    /// Some(false) = ASENSITIVE
3098    pub sensitive: Option<bool>,
3099    /// None = Not specified
3100    /// Some(true) = SCROLL
3101    /// Some(false) = NO SCROLL
3102    pub scroll: Option<bool>,
3103    /// None = Not specified
3104    /// Some(true) = WITH HOLD, specifies that the cursor can continue to be used after the transaction that created it successfully commits
3105    /// Some(false) = WITHOUT HOLD, specifies that the cursor cannot be used outside of the transaction that created it
3106    pub hold: Option<bool>,
3107    /// `FOR <query>` clause in a CURSOR declaration.
3108    pub for_query: Option<Box<Query>>,
3109}
3110
3111impl fmt::Display for Declare {
3112    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3113        let Declare {
3114            names,
3115            data_type,
3116            assignment,
3117            declare_type,
3118            binary,
3119            sensitive,
3120            scroll,
3121            hold,
3122            for_query,
3123        } = self;
3124        write!(f, "{}", display_comma_separated(names))?;
3125
3126        if let Some(true) = binary {
3127            write!(f, " BINARY")?;
3128        }
3129
3130        if let Some(sensitive) = sensitive {
3131            if *sensitive {
3132                write!(f, " INSENSITIVE")?;
3133            } else {
3134                write!(f, " ASENSITIVE")?;
3135            }
3136        }
3137
3138        if let Some(scroll) = scroll {
3139            if *scroll {
3140                write!(f, " SCROLL")?;
3141            } else {
3142                write!(f, " NO SCROLL")?;
3143            }
3144        }
3145
3146        if let Some(declare_type) = declare_type {
3147            write!(f, " {declare_type}")?;
3148        }
3149
3150        if let Some(hold) = hold {
3151            if *hold {
3152                write!(f, " WITH HOLD")?;
3153            } else {
3154                write!(f, " WITHOUT HOLD")?;
3155            }
3156        }
3157
3158        if let Some(query) = for_query {
3159            write!(f, " FOR {query}")?;
3160        }
3161
3162        if let Some(data_type) = data_type {
3163            write!(f, " {data_type}")?;
3164        }
3165
3166        if let Some(expr) = assignment {
3167            write!(f, " {expr}")?;
3168        }
3169        Ok(())
3170    }
3171}
3172
3173/// Sql options of a `CREATE TABLE` statement.
3174#[derive(Debug, Default, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3175#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3176#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3177/// Options allowed within a `CREATE TABLE` statement.
3178pub enum CreateTableOptions {
3179    /// No options specified.
3180    #[default]
3181    None,
3182    /// Options specified using the `WITH` keyword, e.g. `WITH (k = v)`.
3183    With(Vec<SqlOption>),
3184    /// Options specified using the `OPTIONS(...)` clause.
3185    Options(Vec<SqlOption>),
3186    /// Plain space-separated options.
3187    Plain(Vec<SqlOption>),
3188    /// Table properties (e.g., TBLPROPERTIES / storage properties).
3189    TableProperties(Vec<SqlOption>),
3190}
3191
3192impl fmt::Display for CreateTableOptions {
3193    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3194        match self {
3195            CreateTableOptions::With(with_options) => {
3196                write!(f, "WITH ({})", display_comma_separated(with_options))
3197            }
3198            CreateTableOptions::Options(options) => {
3199                write!(f, "OPTIONS({})", display_comma_separated(options))
3200            }
3201            CreateTableOptions::TableProperties(options) => {
3202                write!(f, "TBLPROPERTIES ({})", display_comma_separated(options))
3203            }
3204            CreateTableOptions::Plain(options) => {
3205                write!(f, "{}", display_separated(options, " "))
3206            }
3207            CreateTableOptions::None => Ok(()),
3208        }
3209    }
3210}
3211
3212/// A `FROM` clause within a `DELETE` statement.
3213///
3214/// Syntax
3215/// ```sql
3216/// [FROM] table
3217/// ```
3218#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3219#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3220#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3221pub enum FromTable {
3222    /// An explicit `FROM` keyword was specified.
3223    WithFromKeyword(Vec<TableWithJoins>),
3224    /// BigQuery: `FROM` keyword was omitted.
3225    /// <https://cloud.google.com/bigquery/docs/reference/standard-sql/dml-syntax#delete_statement>
3226    WithoutKeyword(Vec<TableWithJoins>),
3227}
3228impl Display for FromTable {
3229    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3230        match self {
3231            FromTable::WithFromKeyword(tables) => {
3232                write!(f, "FROM {}", display_comma_separated(tables))
3233            }
3234            FromTable::WithoutKeyword(tables) => {
3235                write!(f, "{}", display_comma_separated(tables))
3236            }
3237        }
3238    }
3239}
3240
3241#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3242#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3243#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3244/// Variants for the `SET` family of statements.
3245pub enum Set {
3246    /// SQL Standard-style
3247    /// SET a = 1;
3248    /// `SET var = value` (standard SQL-style assignment).
3249    SingleAssignment {
3250        /// Optional scope modifier (`SESSION` / `LOCAL`).
3251        scope: Option<ContextModifier>,
3252        /// Whether this is a Hive-style `HIVEVAR:` assignment.
3253        hivevar: bool,
3254        /// Variable name to assign.
3255        variable: ObjectName,
3256        /// Values assigned to the variable.
3257        values: Vec<Expr>,
3258    },
3259    /// Snowflake-style
3260    /// SET (a, b, ..) = (1, 2, ..);
3261    /// `SET (a, b) = (1, 2)` (tuple assignment syntax).
3262    ParenthesizedAssignments {
3263        /// Variables being assigned in tuple form.
3264        variables: Vec<ObjectName>,
3265        /// Corresponding values for the variables.
3266        values: Vec<Expr>,
3267    },
3268    /// MySQL-style
3269    /// SET a = 1, b = 2, ..;
3270    /// `SET a = 1, b = 2` (MySQL-style comma-separated assignments).
3271    MultipleAssignments {
3272        /// List of `SET` assignments (MySQL-style comma-separated).
3273        assignments: Vec<SetAssignment>,
3274    },
3275    /// Session authorization for Postgres/Redshift
3276    ///
3277    /// ```sql
3278    /// SET SESSION AUTHORIZATION { user_name | DEFAULT }
3279    /// ```
3280    ///
3281    /// See <https://www.postgresql.org/docs/current/sql-set-session-authorization.html>
3282    /// See <https://docs.aws.amazon.com/redshift/latest/dg/r_SET_SESSION_AUTHORIZATION.html>
3283    SetSessionAuthorization(SetSessionAuthorizationParam),
3284    /// MS-SQL session
3285    ///
3286    /// See <https://learn.microsoft.com/en-us/sql/t-sql/statements/set-statements-transact-sql>
3287    SetSessionParam(SetSessionParamKind),
3288    /// ```sql
3289    /// SET [ SESSION | LOCAL ] ROLE role_name
3290    /// ```
3291    ///
3292    /// Sets session state. Examples: [ANSI][1], [Postgresql][2], [MySQL][3], and [Oracle][4]
3293    ///
3294    /// [1]: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#set-role-statement
3295    /// [2]: https://www.postgresql.org/docs/14/sql-set-role.html
3296    /// [3]: https://dev.mysql.com/doc/refman/8.0/en/set-role.html
3297    /// [4]: https://docs.oracle.com/cd/B19306_01/server.102/b14200/statements_10004.htm
3298    SetRole {
3299        /// Non-ANSI optional identifier to inform if the role is defined inside the current session (`SESSION`) or transaction (`LOCAL`).
3300        context_modifier: Option<ContextModifier>,
3301        /// Role name. If NONE is specified, then the current role name is removed.
3302        role_name: Option<Ident>,
3303    },
3304    /// ```sql
3305    /// SET TIME ZONE <value>
3306    /// ```
3307    ///
3308    /// Note: this is a PostgreSQL-specific statements
3309    /// `SET TIME ZONE <value>` is an alias for `SET timezone TO <value>` in PostgreSQL
3310    /// However, we allow it for all dialects.
3311    /// `SET TIME ZONE` statement. `local` indicates the `LOCAL` keyword.
3312    /// `SET TIME ZONE <value>` statement.
3313    SetTimeZone {
3314        /// Whether the `LOCAL` keyword was specified.
3315        local: bool,
3316        /// Time zone expression value.
3317        value: Expr,
3318    },
3319    /// ```sql
3320    /// SET NAMES 'charset_name' [COLLATE 'collation_name']
3321    /// ```
3322    SetNames {
3323        /// Character set name to set.
3324        charset_name: Ident,
3325        /// Optional collation name.
3326        collation_name: Option<String>,
3327    },
3328    /// ```sql
3329    /// SET NAMES DEFAULT
3330    /// ```
3331    ///
3332    /// Note: this is a MySQL-specific statement.
3333    SetNamesDefault {},
3334    /// ```sql
3335    /// SET TRANSACTION ...
3336    /// ```
3337    SetTransaction {
3338        /// Transaction modes (e.g., ISOLATION LEVEL, READ ONLY).
3339        modes: Vec<TransactionMode>,
3340        /// Optional snapshot value for transaction snapshot control.
3341        snapshot: Option<ValueWithSpan>,
3342        /// `true` when the `SESSION` keyword was used.
3343        session: bool,
3344    },
3345}
3346
3347impl Display for Set {
3348    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3349        match self {
3350            Self::ParenthesizedAssignments { variables, values } => write!(
3351                f,
3352                "SET ({}) = ({})",
3353                display_comma_separated(variables),
3354                display_comma_separated(values)
3355            ),
3356            Self::MultipleAssignments { assignments } => {
3357                write!(f, "SET {}", display_comma_separated(assignments))
3358            }
3359            Self::SetRole {
3360                context_modifier,
3361                role_name,
3362            } => {
3363                let role_name = role_name.clone().unwrap_or_else(|| Ident::new("NONE"));
3364                write!(
3365                    f,
3366                    "SET {modifier}ROLE {role_name}",
3367                    modifier = context_modifier.map(|m| format!("{m}")).unwrap_or_default()
3368                )
3369            }
3370            Self::SetSessionAuthorization(kind) => write!(f, "SET SESSION AUTHORIZATION {kind}"),
3371            Self::SetSessionParam(kind) => write!(f, "SET {kind}"),
3372            Self::SetTransaction {
3373                modes,
3374                snapshot,
3375                session,
3376            } => {
3377                if *session {
3378                    write!(f, "SET SESSION CHARACTERISTICS AS TRANSACTION")?;
3379                } else {
3380                    write!(f, "SET TRANSACTION")?;
3381                }
3382                if !modes.is_empty() {
3383                    write!(f, " {}", display_comma_separated(modes))?;
3384                }
3385                if let Some(snapshot_id) = snapshot {
3386                    write!(f, " SNAPSHOT {snapshot_id}")?;
3387                }
3388                Ok(())
3389            }
3390            Self::SetTimeZone { local, value } => {
3391                f.write_str("SET ")?;
3392                if *local {
3393                    f.write_str("LOCAL ")?;
3394                }
3395                write!(f, "TIME ZONE {value}")
3396            }
3397            Self::SetNames {
3398                charset_name,
3399                collation_name,
3400            } => {
3401                write!(f, "SET NAMES {charset_name}")?;
3402
3403                if let Some(collation) = collation_name {
3404                    f.write_str(" COLLATE ")?;
3405                    f.write_str(collation)?;
3406                };
3407
3408                Ok(())
3409            }
3410            Self::SetNamesDefault {} => {
3411                f.write_str("SET NAMES DEFAULT")?;
3412
3413                Ok(())
3414            }
3415            Set::SingleAssignment {
3416                scope,
3417                hivevar,
3418                variable,
3419                values,
3420            } => {
3421                write!(
3422                    f,
3423                    "SET {}{}{} = {}",
3424                    scope.map(|s| format!("{s}")).unwrap_or_default(),
3425                    if *hivevar { "HIVEVAR:" } else { "" },
3426                    variable,
3427                    display_comma_separated(values)
3428                )
3429            }
3430        }
3431    }
3432}
3433
3434/// A representation of a `WHEN` arm with all the identifiers catched and the statements to execute
3435/// for the arm.
3436///
3437/// Snowflake: <https://docs.snowflake.com/en/sql-reference/snowflake-scripting/exception>
3438/// BigQuery: <https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#beginexceptionend>
3439#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3440#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3441#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3442pub struct ExceptionWhen {
3443    /// Identifiers that trigger this branch (error conditions).
3444    pub idents: Vec<Ident>,
3445    /// Statements to execute when the condition matches.
3446    pub statements: Vec<Statement>,
3447}
3448
3449impl Display for ExceptionWhen {
3450    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3451        write!(
3452            f,
3453            "WHEN {idents} THEN",
3454            idents = display_separated(&self.idents, " OR ")
3455        )?;
3456
3457        if !self.statements.is_empty() {
3458            write!(f, " ")?;
3459            format_statement_list(f, &self.statements)?;
3460        }
3461
3462        Ok(())
3463    }
3464}
3465
3466/// ANALYZE statement
3467///
3468/// Supported syntax varies by dialect:
3469/// - Hive: `ANALYZE TABLE t [PARTITION (...)] COMPUTE STATISTICS [NOSCAN] [FOR COLUMNS [col1, ...]] [CACHE METADATA]`
3470/// - PostgreSQL: `ANALYZE [VERBOSE] [t [(col1, ...)]]` See <https://www.postgresql.org/docs/current/sql-analyze.html>
3471/// - General: `ANALYZE [TABLE] t`
3472#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3473#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3474#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3475pub struct Analyze {
3476    #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
3477    /// Name of the table to analyze. `None` for bare `ANALYZE`.
3478    pub table_name: Option<ObjectName>,
3479    /// Optional partition expressions to restrict the analysis.
3480    pub partitions: Option<Vec<Expr>>,
3481    /// `true` when analyzing specific columns (Hive `FOR COLUMNS` syntax).
3482    pub for_columns: bool,
3483    /// Columns to analyze.
3484    pub columns: Vec<Ident>,
3485    /// Whether to cache metadata before analyzing.
3486    pub cache_metadata: bool,
3487    /// Whether to skip scanning the table.
3488    pub noscan: bool,
3489    /// Whether to compute statistics during analysis.
3490    pub compute_statistics: bool,
3491    /// Whether the `TABLE` keyword was present.
3492    pub has_table_keyword: bool,
3493}
3494
3495impl fmt::Display for Analyze {
3496    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3497        write!(f, "ANALYZE")?;
3498        if let Some(ref table_name) = self.table_name {
3499            if self.has_table_keyword {
3500                write!(f, " TABLE")?;
3501            }
3502            write!(f, " {table_name}")?;
3503        }
3504        if !self.for_columns && !self.columns.is_empty() {
3505            write!(f, " ({})", display_comma_separated(&self.columns))?;
3506        }
3507        if let Some(ref parts) = self.partitions {
3508            if !parts.is_empty() {
3509                write!(f, " PARTITION ({})", display_comma_separated(parts))?;
3510            }
3511        }
3512        if self.compute_statistics {
3513            write!(f, " COMPUTE STATISTICS")?;
3514        }
3515        if self.noscan {
3516            write!(f, " NOSCAN")?;
3517        }
3518        if self.cache_metadata {
3519            write!(f, " CACHE METADATA")?;
3520        }
3521        if self.for_columns {
3522            write!(f, " FOR COLUMNS")?;
3523            if !self.columns.is_empty() {
3524                write!(f, " {}", display_comma_separated(&self.columns))?;
3525            }
3526        }
3527        Ok(())
3528    }
3529}
3530
3531/// A top-level statement (SELECT, INSERT, CREATE, etc.)
3532#[allow(clippy::large_enum_variant)]
3533#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3534#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3535#[cfg_attr(
3536    feature = "visitor",
3537    derive(Visit, VisitMut),
3538    visit(with = "visit_statement")
3539)]
3540pub enum Statement {
3541    /// ```sql
3542    /// ANALYZE
3543    /// ```
3544    /// Analyze (Hive)
3545    Analyze(Analyze),
3546    /// `SET` statements (session, transaction, timezone, etc.).
3547    Set(Set),
3548    /// ```sql
3549    /// TRUNCATE
3550    /// ```
3551    /// Truncate (Hive)
3552    Truncate(Truncate),
3553    /// ```sql
3554    /// MSCK
3555    /// ```
3556    /// Msck (Hive)
3557    Msck(Msck),
3558    /// ```sql
3559    /// SELECT
3560    /// ```
3561    Query(Box<Query>),
3562    /// ```sql
3563    /// INSERT
3564    /// ```
3565    Insert(Insert),
3566    /// ```sql
3567    /// INSTALL
3568    /// ```
3569    Install {
3570        /// Only for DuckDB
3571        extension_name: Ident,
3572    },
3573    /// ```sql
3574    /// LOAD
3575    /// ```
3576    Load {
3577        /// Only for DuckDB
3578        extension_name: Ident,
3579    },
3580    // TODO: Support ROW FORMAT
3581    /// LOAD DATA from a directory or query source.
3582    Directory {
3583        /// Whether to overwrite existing files.
3584        overwrite: bool,
3585        /// Whether the directory is local to the server.
3586        local: bool,
3587        /// Path to the directory or files.
3588        path: String,
3589        /// Optional file format for the data.
3590        file_format: Option<FileFormat>,
3591        /// Source query providing data to load.
3592        source: Box<Query>,
3593    },
3594    /// A `CASE` statement.
3595    Case(CaseStatement),
3596    /// An `IF` statement.
3597    If(IfStatement),
3598    /// A `WHILE` statement.
3599    While(WhileStatement),
3600    /// A `RAISE` statement.
3601    Raise(RaiseStatement),
3602    /// ```sql
3603    /// CALL <function>
3604    /// ```
3605    Call(Function),
3606    /// ```sql
3607    /// COPY [TO | FROM] ...
3608    /// ```
3609    Copy {
3610        /// The source of 'COPY TO', or the target of 'COPY FROM'
3611        source: CopySource,
3612        /// If true, is a 'COPY TO' statement. If false is a 'COPY FROM'
3613        to: bool,
3614        /// The target of 'COPY TO', or the source of 'COPY FROM'
3615        target: CopyTarget,
3616        /// WITH options (from PostgreSQL version 9.0)
3617        options: Vec<CopyOption>,
3618        /// WITH options (before PostgreSQL version 9.0)
3619        legacy_options: Vec<CopyLegacyOption>,
3620        /// VALUES a vector of values to be copied
3621        values: Vec<Option<String>>,
3622    },
3623    /// ```sql
3624    /// COPY INTO <table> | <location>
3625    /// ```
3626    /// See:
3627    /// <https://docs.snowflake.com/en/sql-reference/sql/copy-into-table>
3628    /// <https://docs.snowflake.com/en/sql-reference/sql/copy-into-location>
3629    ///
3630    /// Copy Into syntax available for Snowflake is different than the one implemented in
3631    /// Postgres. Although they share common prefix, it is reasonable to implement them
3632    /// in different enums. This can be refactored later once custom dialects
3633    /// are allowed to have custom Statements.
3634    CopyIntoSnowflake {
3635        /// Kind of COPY INTO operation (table or location).
3636        kind: CopyIntoSnowflakeKind,
3637        /// Target object for the COPY INTO operation.
3638        into: ObjectName,
3639        /// Optional list of target columns.
3640        into_columns: Option<Vec<Ident>>,
3641        /// Optional source object name (staged data).
3642        from_obj: Option<ObjectName>,
3643        /// Optional alias for the source object.
3644        from_obj_alias: Option<Ident>,
3645        /// Stage-specific parameters (e.g., credentials, path).
3646        stage_params: StageParamsObject,
3647        /// Optional list of transformations applied when loading.
3648        from_transformations: Option<Vec<StageLoadSelectItemKind>>,
3649        /// Optional source query instead of a staged object.
3650        from_query: Option<Box<Query>>,
3651        /// Optional list of specific file names to load.
3652        files: Option<Vec<String>>,
3653        /// Optional filename matching pattern.
3654        pattern: Option<String>,
3655        /// File format options.
3656        file_format: KeyValueOptions,
3657        /// Additional copy options.
3658        copy_options: KeyValueOptions,
3659        /// Optional validation mode string.
3660        validation_mode: Option<String>,
3661        /// Optional partition expression for loading.
3662        partition: Option<Box<Expr>>,
3663    },
3664    /// ```sql
3665    /// OPEN cursor_name
3666    /// ```
3667    /// Opens a cursor.
3668    Open(OpenStatement),
3669    /// ```sql
3670    /// CLOSE
3671    /// ```
3672    /// Closes the portal underlying an open cursor.
3673    Close {
3674        /// Cursor name
3675        cursor: CloseCursor,
3676    },
3677    /// ```sql
3678    /// UPDATE
3679    /// ```
3680    Update(Update),
3681    /// ```sql
3682    /// DELETE
3683    /// ```
3684    Delete(Delete),
3685    /// ```sql
3686    /// CREATE VIEW
3687    /// ```
3688    CreateView(CreateView),
3689    /// ```sql
3690    /// CREATE TABLE
3691    /// ```
3692    CreateTable(CreateTable),
3693    /// ```sql
3694    /// CREATE VIRTUAL TABLE .. USING <module_name> (<module_args>)`
3695    /// ```
3696    /// Sqlite specific statement
3697    CreateVirtualTable {
3698        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
3699        /// Name of the virtual table module instance.
3700        name: ObjectName,
3701        /// `true` when `IF NOT EXISTS` was specified.
3702        if_not_exists: bool,
3703        /// Module name used by the virtual table.
3704        module_name: Ident,
3705        /// Arguments passed to the module.
3706        module_args: Vec<Ident>,
3707    },
3708    /// ```sql
3709    /// `CREATE INDEX`
3710    /// ```
3711    CreateIndex(CreateIndex),
3712    /// ```sql
3713    /// CREATE ROLE
3714    /// ```
3715    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createrole.html)
3716    CreateRole(CreateRole),
3717    /// ```sql
3718    /// CREATE SECRET
3719    /// ```
3720    /// See [DuckDB](https://duckdb.org/docs/sql/statements/create_secret.html)
3721    CreateSecret {
3722        /// `true` when `OR REPLACE` was specified.
3723        or_replace: bool,
3724        /// Optional `TEMPORARY` flag.
3725        temporary: Option<bool>,
3726        /// `true` when `IF NOT EXISTS` was present.
3727        if_not_exists: bool,
3728        /// Optional secret name.
3729        name: Option<Ident>,
3730        /// Optional storage specifier identifier.
3731        storage_specifier: Option<Ident>,
3732        /// The secret type identifier.
3733        secret_type: Ident,
3734        /// Additional secret options.
3735        options: Vec<SecretOption>,
3736    },
3737    /// A `CREATE SERVER` statement.
3738    CreateServer(CreateServerStatement),
3739    /// ```sql
3740    /// CREATE POLICY
3741    /// ```
3742    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createpolicy.html)
3743    CreatePolicy(CreatePolicy),
3744    /// ```sql
3745    /// CREATE CONNECTOR
3746    /// ```
3747    /// See [Hive](https://cwiki.apache.org/confluence/pages/viewpage.action?pageId=27362034#LanguageManualDDL-CreateDataConnectorCreateConnector)
3748    CreateConnector(CreateConnector),
3749    /// ```sql
3750    /// CREATE OPERATOR
3751    /// ```
3752    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createoperator.html)
3753    CreateOperator(CreateOperator),
3754    /// ```sql
3755    /// CREATE OPERATOR FAMILY
3756    /// ```
3757    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createopfamily.html)
3758    CreateOperatorFamily(CreateOperatorFamily),
3759    /// ```sql
3760    /// CREATE OPERATOR CLASS
3761    /// ```
3762    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createopclass.html)
3763    CreateOperatorClass(CreateOperatorClass),
3764    /// ```sql
3765    /// ALTER TABLE
3766    /// ```
3767    AlterTable(AlterTable),
3768    /// ```sql
3769    /// ALTER SCHEMA
3770    /// ```
3771    /// See [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#alter_schema_collate_statement)
3772    AlterSchema(AlterSchema),
3773    /// ```sql
3774    /// ALTER INDEX
3775    /// ```
3776    AlterIndex {
3777        /// Name of the index to alter.
3778        name: ObjectName,
3779        /// The operation to perform on the index.
3780        operation: AlterIndexOperation,
3781    },
3782    /// ```sql
3783    /// ALTER VIEW
3784    /// ```
3785    AlterView {
3786        /// View name being altered.
3787        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
3788        name: ObjectName,
3789        /// Optional new column list for the view.
3790        columns: Vec<Ident>,
3791        /// Replacement query for the view definition.
3792        query: Box<Query>,
3793        /// Additional WITH options for the view.
3794        with_options: Vec<SqlOption>,
3795    },
3796    /// ```sql
3797    /// ALTER FUNCTION
3798    /// ALTER AGGREGATE
3799    /// ```
3800    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-alterfunction.html)
3801    /// and [PostgreSQL](https://www.postgresql.org/docs/current/sql-alteraggregate.html)
3802    AlterFunction(AlterFunction),
3803    /// ```sql
3804    /// ALTER TYPE
3805    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-altertype.html)
3806    /// ```
3807    AlterType(AlterType),
3808    /// ```sql
3809    /// ALTER COLLATION
3810    /// ```
3811    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-altercollation.html)
3812    AlterCollation(AlterCollation),
3813    /// ```sql
3814    /// ALTER OPERATOR
3815    /// ```
3816    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-alteroperator.html)
3817    AlterOperator(AlterOperator),
3818    /// ```sql
3819    /// ALTER OPERATOR FAMILY
3820    /// ```
3821    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-alteropfamily.html)
3822    AlterOperatorFamily(AlterOperatorFamily),
3823    /// ```sql
3824    /// ALTER OPERATOR CLASS
3825    /// ```
3826    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-alteropclass.html)
3827    AlterOperatorClass(AlterOperatorClass),
3828    /// ```sql
3829    /// ALTER ROLE
3830    /// ```
3831    AlterRole {
3832        /// Role name being altered.
3833        name: Ident,
3834        /// Operation to perform on the role.
3835        operation: AlterRoleOperation,
3836    },
3837    /// ```sql
3838    /// ALTER POLICY <NAME> ON <TABLE NAME> [<OPERATION>]
3839    /// ```
3840    /// (Postgresql-specific)
3841    AlterPolicy(AlterPolicy),
3842    /// ```sql
3843    /// ALTER CONNECTOR connector_name SET DCPROPERTIES(property_name=property_value, ...);
3844    /// or
3845    /// ALTER CONNECTOR connector_name SET URL new_url;
3846    /// or
3847    /// ALTER CONNECTOR connector_name SET OWNER [USER|ROLE] user_or_role;
3848    /// ```
3849    /// (Hive-specific)
3850    AlterConnector {
3851        /// Name of the connector to alter.
3852        name: Ident,
3853        /// Optional connector properties to set.
3854        properties: Option<Vec<SqlOption>>,
3855        /// Optional new URL for the connector.
3856        url: Option<String>,
3857        /// Optional new owner specification.
3858        owner: Option<ddl::AlterConnectorOwner>,
3859    },
3860    /// ```sql
3861    /// ALTER SESSION SET sessionParam
3862    /// ALTER SESSION UNSET <param_name> [ , <param_name> , ... ]
3863    /// ```
3864    /// See <https://docs.snowflake.com/en/sql-reference/sql/alter-session>
3865    AlterSession {
3866        /// true is to set for the session parameters, false is to unset
3867        set: bool,
3868        /// The session parameters to set or unset
3869        session_params: KeyValueOptions,
3870    },
3871    /// ```sql
3872    /// ATTACH DATABASE 'path/to/file' AS alias
3873    /// ```
3874    /// (SQLite-specific)
3875    AttachDatabase {
3876        /// The name to bind to the newly attached database
3877        schema_name: Ident,
3878        /// An expression that indicates the path to the database file
3879        database_file_name: Expr,
3880        /// true if the syntax is 'ATTACH DATABASE', false if it's just 'ATTACH'
3881        database: bool,
3882    },
3883    /// (DuckDB-specific)
3884    /// ```sql
3885    /// ATTACH 'sqlite_file.db' AS sqlite_db (READ_ONLY, TYPE SQLITE);
3886    /// ```
3887    /// See <https://duckdb.org/docs/sql/statements/attach.html>
3888    AttachDuckDBDatabase {
3889        /// `true` when `IF NOT EXISTS` was present.
3890        if_not_exists: bool,
3891        /// `true` if the syntax used `ATTACH DATABASE` rather than `ATTACH`.
3892        database: bool,
3893        /// The path identifier to the database file being attached.
3894        database_path: Ident,
3895        /// Optional alias assigned to the attached database.
3896        database_alias: Option<Ident>,
3897        /// Dialect-specific attach options (e.g., `READ_ONLY`).
3898        attach_options: Vec<AttachDuckDBDatabaseOption>,
3899    },
3900    /// (DuckDB-specific)
3901    /// ```sql
3902    /// DETACH db_alias;
3903    /// ```
3904    /// See <https://duckdb.org/docs/sql/statements/attach.html>
3905    DetachDuckDBDatabase {
3906        /// `true` when `IF EXISTS` was present.
3907        if_exists: bool,
3908        /// `true` if the syntax used `DETACH DATABASE` rather than `DETACH`.
3909        database: bool,
3910        /// Alias of the database to detach.
3911        database_alias: Ident,
3912    },
3913    /// ```sql
3914    /// DROP [TABLE, VIEW, ...]
3915    /// ```
3916    Drop {
3917        /// The type of the object to drop: TABLE, VIEW, etc.
3918        object_type: ObjectType,
3919        /// An optional `IF EXISTS` clause. (Non-standard.)
3920        if_exists: bool,
3921        /// One or more objects to drop. (ANSI SQL requires exactly one.)
3922        names: Vec<ObjectName>,
3923        /// Whether `CASCADE` was specified. This will be `false` when
3924        /// `RESTRICT` or no drop behavior at all was specified.
3925        cascade: bool,
3926        /// Whether `RESTRICT` was specified. This will be `false` when
3927        /// `CASCADE` or no drop behavior at all was specified.
3928        restrict: bool,
3929        /// Hive allows you specify whether the table's stored data will be
3930        /// deleted along with the dropped table
3931        purge: bool,
3932        /// MySQL-specific "TEMPORARY" keyword
3933        temporary: bool,
3934        /// MySQL-specific drop index syntax, which requires table specification
3935        /// See <https://dev.mysql.com/doc/refman/8.4/en/drop-index.html>
3936        table: Option<ObjectName>,
3937    },
3938    /// ```sql
3939    /// DROP FUNCTION
3940    /// ```
3941    DropFunction(DropFunction),
3942    /// ```sql
3943    /// DROP DOMAIN
3944    /// ```
3945    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-dropdomain.html)
3946    ///
3947    /// DROP DOMAIN [ IF EXISTS ] name [, ...] [ CASCADE | RESTRICT ]
3948    ///
3949    DropDomain(DropDomain),
3950    /// ```sql
3951    /// DROP PROCEDURE
3952    /// ```
3953    DropProcedure {
3954        /// `true` when `IF EXISTS` was present.
3955        if_exists: bool,
3956        /// One or more functions/procedures to drop.
3957        proc_desc: Vec<FunctionDesc>,
3958        /// Optional drop behavior (`CASCADE` or `RESTRICT`).
3959        drop_behavior: Option<DropBehavior>,
3960    },
3961    /// ```sql
3962    /// DROP SECRET
3963    /// ```
3964    DropSecret {
3965        /// `true` when `IF EXISTS` was present.
3966        if_exists: bool,
3967        /// Optional `TEMPORARY` marker.
3968        temporary: Option<bool>,
3969        /// Name of the secret to drop.
3970        name: Ident,
3971        /// Optional storage specifier identifier.
3972        storage_specifier: Option<Ident>,
3973    },
3974    ///```sql
3975    /// DROP POLICY
3976    /// ```
3977    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-droppolicy.html)
3978    DropPolicy(DropPolicy),
3979    /// ```sql
3980    /// DROP CONNECTOR
3981    /// ```
3982    /// See [Hive](https://cwiki.apache.org/confluence/pages/viewpage.action?pageId=27362034#LanguageManualDDL-DropConnector)
3983    DropConnector {
3984        /// `true` when `IF EXISTS` was present.
3985        if_exists: bool,
3986        /// Name of the connector to drop.
3987        name: Ident,
3988    },
3989    /// ```sql
3990    /// DECLARE
3991    /// ```
3992    /// Declare Cursor Variables
3993    ///
3994    /// Note: this is a PostgreSQL-specific statement,
3995    /// but may also compatible with other SQL.
3996    Declare {
3997        /// Cursor declaration statements collected by `DECLARE`.
3998        stmts: Vec<Declare>,
3999    },
4000    /// ```sql
4001    /// CREATE EXTENSION [ IF NOT EXISTS ] extension_name
4002    ///     [ WITH ] [ SCHEMA schema_name ]
4003    ///              [ VERSION version ]
4004    ///              [ CASCADE ]
4005    /// ```
4006    ///
4007    /// Note: this is a PostgreSQL-specific statement,
4008    CreateExtension(CreateExtension),
4009    /// ```sql
4010    /// CREATE COLLATION
4011    /// ```
4012    /// Note: this is a PostgreSQL-specific statement.
4013    /// <https://www.postgresql.org/docs/current/sql-createcollation.html>
4014    CreateCollation(CreateCollation),
4015    /// ```sql
4016    /// DROP EXTENSION [ IF EXISTS ] name [, ...] [ CASCADE | RESTRICT ]
4017    /// ```
4018    /// Note: this is a PostgreSQL-specific statement.
4019    /// <https://www.postgresql.org/docs/current/sql-dropextension.html>
4020    DropExtension(DropExtension),
4021    /// ```sql
4022    /// DROP OPERATOR [ IF EXISTS ] name ( { left_type | NONE } , right_type ) [, ...] [ CASCADE | RESTRICT ]
4023    /// ```
4024    /// Note: this is a PostgreSQL-specific statement.
4025    /// <https://www.postgresql.org/docs/current/sql-dropoperator.html>
4026    DropOperator(DropOperator),
4027    /// ```sql
4028    /// DROP OPERATOR FAMILY [ IF EXISTS ] name USING index_method [ CASCADE | RESTRICT ]
4029    /// ```
4030    /// Note: this is a PostgreSQL-specific statement.
4031    /// <https://www.postgresql.org/docs/current/sql-dropopfamily.html>
4032    DropOperatorFamily(DropOperatorFamily),
4033    /// ```sql
4034    /// DROP OPERATOR CLASS [ IF EXISTS ] name USING index_method [ CASCADE | RESTRICT ]
4035    /// ```
4036    /// Note: this is a PostgreSQL-specific statement.
4037    /// <https://www.postgresql.org/docs/current/sql-dropopclass.html>
4038    DropOperatorClass(DropOperatorClass),
4039    /// ```sql
4040    /// FETCH
4041    /// ```
4042    /// Retrieve rows from a query using a cursor
4043    ///
4044    /// Note: this is a PostgreSQL-specific statement,
4045    /// but may also compatible with other SQL.
4046    Fetch {
4047        /// Cursor name
4048        name: Ident,
4049        /// The fetch direction (e.g., `FORWARD`, `BACKWARD`).
4050        direction: FetchDirection,
4051        /// The fetch position (e.g., `ALL`, `NEXT`, `ABSOLUTE`).
4052        position: FetchPosition,
4053        /// Optional target table to fetch rows into.
4054        into: Option<ObjectName>,
4055    },
4056    /// ```sql
4057    /// FLUSH [NO_WRITE_TO_BINLOG | LOCAL] flush_option [, flush_option] ... | tables_option
4058    /// ```
4059    ///
4060    /// Note: this is a Mysql-specific statement,
4061    /// but may also compatible with other SQL.
4062    Flush {
4063        /// The specific flush option or object to flush.
4064        object_type: FlushType,
4065        /// Optional flush location (dialect-specific).
4066        location: Option<FlushLocation>,
4067        /// Optional channel name used for flush operations.
4068        channel: Option<String>,
4069        /// Whether a read lock was requested.
4070        read_lock: bool,
4071        /// Whether this is an export flush operation.
4072        export: bool,
4073        /// Optional list of tables involved in the flush.
4074        tables: Vec<ObjectName>,
4075    },
4076    /// ```sql
4077    /// DISCARD [ ALL | PLANS | SEQUENCES | TEMPORARY | TEMP ]
4078    /// ```
4079    ///
4080    /// Note: this is a PostgreSQL-specific statement,
4081    /// but may also compatible with other SQL.
4082    Discard {
4083        /// The kind of object(s) to discard (ALL, PLANS, etc.).
4084        object_type: DiscardObject,
4085    },
4086    /// `SHOW FUNCTIONS`
4087    ///
4088    /// Note: this is a Presto-specific statement.
4089    ShowFunctions {
4090        /// Optional filter for which functions to display.
4091        filter: Option<ShowStatementFilter>,
4092    },
4093    /// ```sql
4094    /// SHOW <variable>
4095    /// ```
4096    ///
4097    /// Note: this is a PostgreSQL-specific statement.
4098    ShowVariable {
4099        /// Variable name as one or more identifiers.
4100        variable: Vec<Ident>,
4101    },
4102    /// ```sql
4103    /// SHOW [GLOBAL | SESSION] STATUS [LIKE 'pattern' | WHERE expr]
4104    /// ```
4105    ///
4106    /// Note: this is a MySQL-specific statement.
4107    ShowStatus {
4108        /// Optional filter for which status entries to display.
4109        filter: Option<ShowStatementFilter>,
4110        /// `true` when `GLOBAL` scope was requested.
4111        global: bool,
4112        /// `true` when `SESSION` scope was requested.
4113        session: bool,
4114    },
4115    /// ```sql
4116    /// SHOW VARIABLES
4117    /// ```
4118    ///
4119    /// Note: this is a MySQL-specific statement.
4120    ShowVariables {
4121        /// Optional filter for which variables to display.
4122        filter: Option<ShowStatementFilter>,
4123        /// `true` when `GLOBAL` scope was requested.
4124        global: bool,
4125        /// `true` when `SESSION` scope was requested.
4126        session: bool,
4127    },
4128    /// ```sql
4129    /// SHOW CREATE TABLE
4130    /// ```
4131    ///
4132    /// Note: this is a MySQL-specific statement.
4133    ShowCreate {
4134        /// The kind of object being shown (TABLE, VIEW, etc.).
4135        obj_type: ShowCreateObject,
4136        /// The name of the object to show create statement for.
4137        obj_name: ObjectName,
4138    },
4139    /// ```sql
4140    /// SHOW COLUMNS
4141    /// ```
4142    ShowColumns {
4143        /// `true` when extended column information was requested.
4144        extended: bool,
4145        /// `true` when full column details were requested.
4146        full: bool,
4147        /// Additional options for `SHOW COLUMNS`.
4148        show_options: ShowStatementOptions,
4149    },
4150    /// ```sql
4151    /// SHOW CATALOGS
4152    /// ```
4153    ShowCatalogs {
4154        /// `true` when terse output format was requested.
4155        terse: bool,
4156        /// `true` when history information was requested.
4157        history: bool,
4158        /// Additional options for `SHOW CATALOGS`.
4159        show_options: ShowStatementOptions,
4160    },
4161    /// ```sql
4162    /// SHOW DATABASES
4163    /// ```
4164    ShowDatabases {
4165        /// `true` when terse output format was requested.
4166        terse: bool,
4167        /// `true` when history information was requested.
4168        history: bool,
4169        /// Additional options for `SHOW DATABASES`.
4170        show_options: ShowStatementOptions,
4171    },
4172    /// ```sql
4173    /// SHOW [FULL] PROCESSLIST
4174    /// ```
4175    ///
4176    /// Note: this is a MySQL-specific statement.
4177    ShowProcessList {
4178        /// `true` when full process information was requested.
4179        full: bool,
4180    },
4181    /// ```sql
4182    /// SHOW SCHEMAS
4183    /// ```
4184    ShowSchemas {
4185        /// `true` when terse (compact) output was requested.
4186        terse: bool,
4187        /// `true` when history information was requested.
4188        history: bool,
4189        /// Additional options for `SHOW SCHEMAS`.
4190        show_options: ShowStatementOptions,
4191    },
4192    // ```sql
4193    // SHOW {CHARACTER SET | CHARSET}
4194    // ```
4195    // [MySQL]:
4196    // <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>
4197    /// Show the available character sets (alias `CHARSET`).
4198    ShowCharset(ShowCharset),
4199    /// ```sql
4200    /// SHOW OBJECTS LIKE 'line%' IN mydb.public
4201    /// ```
4202    /// Snowflake-specific statement
4203    /// <https://docs.snowflake.com/en/sql-reference/sql/show-objects>
4204    ShowObjects(ShowObjects),
4205    /// ```sql
4206    /// SHOW TABLES
4207    /// ```
4208    ShowTables {
4209        /// `true` when terse output format was requested (compact listing).
4210        terse: bool,
4211        /// `true` when history rows are requested.
4212        history: bool,
4213        /// `true` when extended information should be shown.
4214        extended: bool,
4215        /// `true` when a full listing was requested.
4216        full: bool,
4217        /// `true` when external tables should be included.
4218        external: bool,
4219        /// Additional options for `SHOW` statements.
4220        show_options: ShowStatementOptions,
4221    },
4222    /// ```sql
4223    /// SHOW VIEWS
4224    /// ```
4225    ShowViews {
4226        /// `true` when terse output format was requested.
4227        terse: bool,
4228        /// `true` when materialized views should be included.
4229        materialized: bool,
4230        /// Additional options for `SHOW` statements.
4231        show_options: ShowStatementOptions,
4232    },
4233    /// ```sql
4234    /// SHOW COLLATION
4235    /// ```
4236    ///
4237    /// Note: this is a MySQL-specific statement.
4238    ShowCollation {
4239        /// Optional filter for which collations to display.
4240        filter: Option<ShowStatementFilter>,
4241    },
4242    /// ```sql
4243    /// `USE ...`
4244    /// ```
4245    Use(Use),
4246    /// ```sql
4247    /// START  [ TRANSACTION | WORK ] | START TRANSACTION } ...
4248    /// ```
4249    /// If `begin` is false.
4250    ///
4251    /// ```sql
4252    /// `BEGIN  [ TRANSACTION | WORK ] | START TRANSACTION } ...`
4253    /// ```
4254    /// If `begin` is true
4255    StartTransaction {
4256        /// Transaction modes such as `ISOLATION LEVEL` or `READ WRITE`.
4257        modes: Vec<TransactionMode>,
4258        /// `true` when this was parsed as `BEGIN` instead of `START`.
4259        begin: bool,
4260        /// Optional specific keyword used: `TRANSACTION` or `WORK`.
4261        transaction: Option<BeginTransactionKind>,
4262        /// Optional transaction modifier (e.g., `AND NO CHAIN`).
4263        modifier: Option<TransactionModifier>,
4264        /// List of statements belonging to the `BEGIN` block.
4265        /// Example:
4266        /// ```sql
4267        /// BEGIN
4268        ///     SELECT 1;
4269        ///     SELECT 2;
4270        /// END;
4271        /// ```
4272        statements: Vec<Statement>,
4273        /// Exception handling with exception clauses.
4274        /// Example:
4275        /// ```sql
4276        /// EXCEPTION
4277        ///     WHEN EXCEPTION_1 THEN
4278        ///         SELECT 2;
4279        ///     WHEN EXCEPTION_2 OR EXCEPTION_3 THEN
4280        ///         SELECT 3;
4281        ///     WHEN OTHER THEN
4282        ///         SELECT 4;
4283        /// ```
4284        /// <https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#beginexceptionend>
4285        /// <https://docs.snowflake.com/en/sql-reference/snowflake-scripting/exception>
4286        exception: Option<Vec<ExceptionWhen>>,
4287        /// TRUE if the statement has an `END` keyword.
4288        has_end_keyword: bool,
4289    },
4290    /// ```sql
4291    /// COMMENT ON ...
4292    /// ```
4293    ///
4294    /// Note: this is a PostgreSQL-specific statement.
4295    Comment {
4296        /// Type of object being commented (table, column, etc.).
4297        object_type: CommentObject,
4298        /// Name of the object the comment applies to.
4299        object_name: ObjectName,
4300        /// Optional comment text (None to remove comment).
4301        comment: Option<String>,
4302        /// An optional `IF EXISTS` clause. (Non-standard.)
4303        /// See <https://docs.snowflake.com/en/sql-reference/sql/comment>
4304        if_exists: bool,
4305    },
4306    /// ```sql
4307    /// COMMIT [ TRANSACTION | WORK ] [ AND [ NO ] CHAIN ]
4308    /// ```
4309    /// If `end` is false
4310    ///
4311    /// ```sql
4312    /// END [ TRY | CATCH ]
4313    /// ```
4314    /// If `end` is true
4315    Commit {
4316        /// `true` when `AND [ NO ] CHAIN` was present.
4317        chain: bool,
4318        /// `true` when this `COMMIT` was parsed as an `END` block terminator.
4319        end: bool,
4320        /// Optional transaction modifier for commit semantics.
4321        modifier: Option<TransactionModifier>,
4322    },
4323    /// ```sql
4324    /// ROLLBACK [ TRANSACTION | WORK ] [ AND [ NO ] CHAIN ] [ TO [ SAVEPOINT ] savepoint_name ]
4325    /// ```
4326    Rollback {
4327        /// `true` when `AND [ NO ] CHAIN` was present.
4328        chain: bool,
4329        /// Optional savepoint name to roll back to.
4330        savepoint: Option<Ident>,
4331    },
4332    /// ```sql
4333    /// CREATE SCHEMA
4334    /// ```
4335    CreateSchema {
4336        /// `<schema name> | AUTHORIZATION <schema authorization identifier>  | <schema name>  AUTHORIZATION <schema authorization identifier>`
4337        schema_name: SchemaName,
4338        /// `true` when `IF NOT EXISTS` was present.
4339        if_not_exists: bool,
4340        /// Schema properties.
4341        ///
4342        /// ```sql
4343        /// CREATE SCHEMA myschema WITH (key1='value1');
4344        /// ```
4345        ///
4346        /// [Trino](https://trino.io/docs/current/sql/create-schema.html)
4347        with: Option<Vec<SqlOption>>,
4348        /// Schema options.
4349        ///
4350        /// ```sql
4351        /// CREATE SCHEMA myschema OPTIONS(key1='value1');
4352        /// ```
4353        ///
4354        /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_schema_statement)
4355        options: Option<Vec<SqlOption>>,
4356        /// Default collation specification for the schema.
4357        ///
4358        /// ```sql
4359        /// CREATE SCHEMA myschema DEFAULT COLLATE 'und:ci';
4360        /// ```
4361        ///
4362        /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_schema_statement)
4363        default_collate_spec: Option<Expr>,
4364        /// Clones a schema
4365        ///
4366        /// ```sql
4367        /// CREATE SCHEMA myschema CLONE otherschema
4368        /// ```
4369        ///
4370        /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-clone#databases-schemas)
4371        clone: Option<ObjectName>,
4372    },
4373    /// ```sql
4374    /// CREATE DATABASE
4375    /// ```
4376    /// See:
4377    /// <https://docs.snowflake.com/en/sql-reference/sql/create-database>
4378    CreateDatabase {
4379        /// Database name.
4380        db_name: ObjectName,
4381        /// `IF NOT EXISTS` flag.
4382        if_not_exists: bool,
4383        /// Optional location URI.
4384        location: Option<String>,
4385        /// Optional managed location.
4386        managed_location: Option<String>,
4387        /// `OR REPLACE` flag.
4388        or_replace: bool,
4389        /// `TRANSIENT` flag.
4390        transient: bool,
4391        /// Optional clone source.
4392        clone: Option<ObjectName>,
4393        /// Optional data retention time in days.
4394        data_retention_time_in_days: Option<u64>,
4395        /// Optional maximum data extension time in days.
4396        max_data_extension_time_in_days: Option<u64>,
4397        /// Optional external volume identifier.
4398        external_volume: Option<String>,
4399        /// Optional catalog name.
4400        catalog: Option<String>,
4401        /// Whether to replace invalid characters.
4402        replace_invalid_characters: Option<bool>,
4403        /// Default DDL collation string.
4404        default_ddl_collation: Option<String>,
4405        /// Storage serialization policy.
4406        storage_serialization_policy: Option<StorageSerializationPolicy>,
4407        /// Optional comment.
4408        comment: Option<String>,
4409        /// Optional default character set (MySQL).
4410        default_charset: Option<String>,
4411        /// Optional default collation (MySQL).
4412        default_collation: Option<String>,
4413        /// Optional catalog sync identifier.
4414        catalog_sync: Option<String>,
4415        /// Catalog sync namespace mode.
4416        catalog_sync_namespace_mode: Option<CatalogSyncNamespaceMode>,
4417        /// Optional flatten delimiter for namespace sync.
4418        catalog_sync_namespace_flatten_delimiter: Option<String>,
4419        /// Optional tags for the database.
4420        with_tags: Option<Vec<Tag>>,
4421        /// Optional contact entries for the database.
4422        with_contacts: Option<Vec<ContactEntry>>,
4423    },
4424    /// ```sql
4425    /// CREATE FUNCTION
4426    /// ```
4427    ///
4428    /// Supported variants:
4429    /// 1. [Hive](https://cwiki.apache.org/confluence/display/hive/languagemanual+ddl#LanguageManualDDL-Create/Drop/ReloadFunction)
4430    /// 2. [PostgreSQL](https://www.postgresql.org/docs/15/sql-createfunction.html)
4431    /// 3. [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_function_statement)
4432    /// 4. [MsSql](https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql)
4433    CreateFunction(CreateFunction),
4434    /// CREATE TRIGGER statement. See struct [CreateTrigger] for details.
4435    CreateTrigger(CreateTrigger),
4436    /// DROP TRIGGER statement. See struct [DropTrigger] for details.
4437    DropTrigger(DropTrigger),
4438    /// ```sql
4439    /// CREATE PROCEDURE
4440    /// ```
4441    CreateProcedure {
4442        /// `OR ALTER` flag.
4443        or_alter: bool,
4444        /// Procedure name.
4445        name: ObjectName,
4446        /// Optional procedure parameters.
4447        params: Option<Vec<ProcedureParam>>,
4448        /// Optional language identifier.
4449        language: Option<Ident>,
4450        /// Procedure body statements.
4451        body: ConditionalStatements,
4452    },
4453    /// ```sql
4454    /// CREATE MACRO
4455    /// ```
4456    ///
4457    /// Supported variants:
4458    /// 1. [DuckDB](https://duckdb.org/docs/sql/statements/create_macro)
4459    CreateMacro {
4460        /// `OR REPLACE` flag.
4461        or_replace: bool,
4462        /// Whether macro is temporary.
4463        temporary: bool,
4464        /// Macro name.
4465        name: ObjectName,
4466        /// Optional macro arguments.
4467        args: Option<Vec<MacroArg>>,
4468        /// Macro definition body.
4469        definition: MacroDefinition,
4470    },
4471    /// ```sql
4472    /// CREATE STAGE
4473    /// ```
4474    /// See <https://docs.snowflake.com/en/sql-reference/sql/create-stage>
4475    CreateStage {
4476        /// `OR REPLACE` flag for stage.
4477        or_replace: bool,
4478        /// Whether stage is temporary.
4479        temporary: bool,
4480        /// `IF NOT EXISTS` flag.
4481        if_not_exists: bool,
4482        /// Stage name.
4483        name: ObjectName,
4484        /// Stage parameters.
4485        stage_params: StageParamsObject,
4486        /// Directory table parameters.
4487        directory_table_params: KeyValueOptions,
4488        /// File format options.
4489        file_format: KeyValueOptions,
4490        /// Copy options for stage.
4491        copy_options: KeyValueOptions,
4492        /// Optional comment.
4493        comment: Option<String>,
4494    },
4495    /// ```sql
4496    /// ASSERT <condition> [AS <message>]
4497    /// ```
4498    Assert {
4499        /// Assertion condition expression.
4500        condition: Expr,
4501        /// Optional message expression.
4502        message: Option<Expr>,
4503    },
4504    /// ```sql
4505    /// GRANT privileges ON objects TO grantees
4506    /// ```
4507    Grant(Grant),
4508    /// ```sql
4509    /// DENY privileges ON object TO grantees
4510    /// ```
4511    Deny(DenyStatement),
4512    /// ```sql
4513    /// REVOKE privileges ON objects FROM grantees
4514    /// ```
4515    Revoke(Revoke),
4516    /// ```sql
4517    /// DEALLOCATE [ PREPARE ] { name | ALL }
4518    /// ```
4519    ///
4520    /// Note: this is a PostgreSQL-specific statement.
4521    Deallocate {
4522        /// Name to deallocate (or `ALL`).
4523        name: Ident,
4524        /// Whether `PREPARE` keyword was present.
4525        prepare: bool,
4526    },
4527    /// ```sql
4528    /// An `EXECUTE` statement
4529    /// ```
4530    ///
4531    /// Postgres: <https://www.postgresql.org/docs/current/sql-execute.html>
4532    /// MSSQL: <https://learn.microsoft.com/en-us/sql/relational-databases/stored-procedures/execute-a-stored-procedure>
4533    /// BigQuery: <https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#execute_immediate>
4534    /// Snowflake: <https://docs.snowflake.com/en/sql-reference/sql/execute-immediate>
4535    Execute {
4536        /// Optional function/procedure name.
4537        name: Option<ObjectName>,
4538        /// Parameter expressions passed to execute.
4539        parameters: Vec<Expr>,
4540        /// Whether parentheses were present around `parameters`.
4541        has_parentheses: bool,
4542        /// Is this an `EXECUTE IMMEDIATE`.
4543        immediate: bool,
4544        /// Identifiers to capture results into.
4545        into: Vec<Ident>,
4546        /// `USING` expressions with optional aliases.
4547        using: Vec<ExprWithAlias>,
4548        /// Whether the last parameter is the return value of the procedure
4549        /// MSSQL: <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/execute-transact-sql?view=sql-server-ver17#output>
4550        output: bool,
4551        /// Whether to invoke the procedure with the default parameter values
4552        /// MSSQL: <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/execute-transact-sql?view=sql-server-ver17#default>
4553        default: bool,
4554    },
4555    /// ```sql
4556    /// PREPARE name [ ( data_type [, ...] ) ] AS statement
4557    /// ```
4558    ///
4559    /// Note: this is a PostgreSQL-specific statement.
4560    Prepare {
4561        /// Name of the prepared statement.
4562        name: Ident,
4563        /// Optional data types for parameters.
4564        data_types: Vec<DataType>,
4565        /// Statement being prepared.
4566        statement: Box<Statement>,
4567    },
4568    /// ```sql
4569    /// KILL [CONNECTION | QUERY | MUTATION]
4570    /// ```
4571    ///
4572    /// See <https://clickhouse.com/docs/en/sql-reference/statements/kill/>
4573    /// See <https://dev.mysql.com/doc/refman/8.0/en/kill.html>
4574    Kill {
4575        /// Optional kill modifier (CONNECTION, QUERY, MUTATION).
4576        modifier: Option<KillType>,
4577        // processlist_id
4578        /// The id of the process to kill.
4579        id: u64,
4580    },
4581    /// ```sql
4582    /// [EXPLAIN | DESC | DESCRIBE] TABLE
4583    /// ```
4584    /// Note: this is a MySQL-specific statement. See <https://dev.mysql.com/doc/refman/8.0/en/explain.html>
4585    ExplainTable {
4586        /// `EXPLAIN | DESC | DESCRIBE`
4587        describe_alias: DescribeAlias,
4588        /// Hive style `FORMATTED | EXTENDED`
4589        hive_format: Option<HiveDescribeFormat>,
4590        /// Snowflake and ClickHouse support `DESC|DESCRIBE TABLE <table_name>` syntax
4591        ///
4592        /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/desc-table.html)
4593        /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/describe-table)
4594        has_table_keyword: bool,
4595        /// Table name
4596        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
4597        table_name: ObjectName,
4598    },
4599    /// ```sql
4600    /// [EXPLAIN | DESC | DESCRIBE]  <statement>
4601    /// ```
4602    Explain {
4603        /// `EXPLAIN | DESC | DESCRIBE`
4604        describe_alias: DescribeAlias,
4605        /// Carry out the command and show actual run times and other statistics.
4606        analyze: bool,
4607        /// Display additional information regarding the plan.
4608        verbose: bool,
4609        /// `EXPLAIN QUERY PLAN`
4610        /// Display the query plan without running the query.
4611        ///
4612        /// [SQLite](https://sqlite.org/lang_explain.html)
4613        query_plan: bool,
4614        /// `EXPLAIN ESTIMATE`
4615        /// [Clickhouse](https://clickhouse.com/docs/en/sql-reference/statements/explain#explain-estimate)
4616        estimate: bool,
4617        /// A SQL query that specifies what to explain
4618        statement: Box<Statement>,
4619        /// Optional output format of explain
4620        format: Option<AnalyzeFormatKind>,
4621        /// Postgres style utility options, `(analyze, verbose true)`
4622        options: Option<Vec<UtilityOption>>,
4623    },
4624    /// ```sql
4625    /// SAVEPOINT
4626    /// ```
4627    /// Define a new savepoint within the current transaction
4628    Savepoint {
4629        /// Name of the savepoint being defined.
4630        name: Ident,
4631    },
4632    /// ```sql
4633    /// RELEASE [ SAVEPOINT ] savepoint_name
4634    /// ```
4635    ReleaseSavepoint {
4636        /// Name of the savepoint to release.
4637        name: Ident,
4638    },
4639    /// A `MERGE` statement.
4640    ///
4641    /// ```sql
4642    /// MERGE INTO <target_table> USING <source> ON <join_expr> { matchedClause | notMatchedClause } [ ... ]
4643    /// ```
4644    /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/merge)
4645    /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/dml-syntax#merge_statement)
4646    /// [MSSQL](https://learn.microsoft.com/en-us/sql/t-sql/statements/merge-transact-sql?view=sql-server-ver16)
4647    Merge(Merge),
4648    /// ```sql
4649    /// CACHE [ FLAG ] TABLE <table_name> [ OPTIONS('K1' = 'V1', 'K2' = V2) ] [ AS ] [ <query> ]
4650    /// ```
4651    ///
4652    /// See [Spark SQL docs] for more details.
4653    ///
4654    /// [Spark SQL docs]: https://docs.databricks.com/spark/latest/spark-sql/language-manual/sql-ref-syntax-aux-cache-cache-table.html
4655    Cache {
4656        /// Table flag
4657        table_flag: Option<ObjectName>,
4658        /// Table name
4659        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
4660        table_name: ObjectName,
4661        /// `true` if `AS` keyword was present before the query.
4662        has_as: bool,
4663        /// Table confs
4664        options: Vec<SqlOption>,
4665        /// Cache table as a Query
4666        query: Option<Box<Query>>,
4667    },
4668    /// ```sql
4669    /// UNCACHE TABLE [ IF EXISTS ]  <table_name>
4670    /// ```
4671    UNCache {
4672        /// Table name
4673        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
4674        table_name: ObjectName,
4675        /// `true` when `IF EXISTS` was present.
4676        if_exists: bool,
4677    },
4678    /// ```sql
4679    /// CREATE [ { TEMPORARY | TEMP } ] SEQUENCE [ IF NOT EXISTS ] <sequence_name>
4680    /// ```
4681    /// Define a new sequence:
4682    CreateSequence {
4683        /// Whether the sequence is temporary.
4684        temporary: bool,
4685        /// `IF NOT EXISTS` flag.
4686        if_not_exists: bool,
4687        /// Sequence name.
4688        name: ObjectName,
4689        /// Optional data type for the sequence.
4690        data_type: Option<DataType>,
4691        /// Sequence options (INCREMENT, MINVALUE, etc.).
4692        sequence_options: Vec<SequenceOptions>,
4693        /// Optional `OWNED BY` target.
4694        owned_by: Option<ObjectName>,
4695    },
4696    /// A `CREATE DOMAIN` statement.
4697    CreateDomain(CreateDomain),
4698    /// ```sql
4699    /// CREATE TYPE <name>
4700    /// ```
4701    CreateType {
4702        /// Type name to create.
4703        name: ObjectName,
4704        /// Optional type representation details.
4705        representation: Option<UserDefinedTypeRepresentation>,
4706    },
4707    /// ```sql
4708    /// PRAGMA <schema-name>.<pragma-name> = <pragma-value>
4709    /// ```
4710    Pragma {
4711        /// Pragma name (possibly qualified).
4712        name: ObjectName,
4713        /// Optional pragma value.
4714        value: Option<ValueWithSpan>,
4715        /// Whether the pragma used `=`.
4716        is_eq: bool,
4717    },
4718    /// ```sql
4719    /// LOCK [ TABLE ] [ ONLY ] name [ * ] [, ...] [ IN lockmode MODE ] [ NOWAIT ]
4720    /// ```
4721    ///
4722    /// See <https://www.postgresql.org/docs/current/sql-lock.html>
4723    Lock(Lock),
4724    /// ```sql
4725    /// LOCK TABLES <table_name> [READ [LOCAL] | [LOW_PRIORITY] WRITE]
4726    /// ```
4727    /// Note: this is a MySQL-specific statement. See <https://dev.mysql.com/doc/refman/8.0/en/lock-tables.html>
4728    LockTables {
4729        /// List of tables to lock with modes.
4730        tables: Vec<LockTable>,
4731    },
4732    /// ```sql
4733    /// UNLOCK TABLES
4734    /// ```
4735    /// Note: this is a MySQL-specific statement. See <https://dev.mysql.com/doc/refman/8.0/en/lock-tables.html>
4736    UnlockTables,
4737    /// Unloads the result of a query to file
4738    ///
4739    /// [Athena](https://docs.aws.amazon.com/athena/latest/ug/unload.html):
4740    /// ```sql
4741    /// UNLOAD(statement) TO <destination> [ WITH options ]
4742    /// ```
4743    ///
4744    /// [Redshift](https://docs.aws.amazon.com/redshift/latest/dg/r_UNLOAD.html):
4745    /// ```sql
4746    /// UNLOAD('statement') TO <destination> [ OPTIONS ]
4747    /// ```
4748    Unload {
4749        /// Optional query AST to unload.
4750        query: Option<Box<Query>>,
4751        /// Optional original query text.
4752        query_text: Option<String>,
4753        /// Destination identifier.
4754        to: Ident,
4755        /// Optional IAM role/auth information.
4756        auth: Option<IamRoleKind>,
4757        /// Additional `WITH` options.
4758        with: Vec<SqlOption>,
4759        /// Legacy copy-style options.
4760        options: Vec<CopyLegacyOption>,
4761    },
4762    /// ClickHouse:
4763    /// ```sql
4764    /// OPTIMIZE TABLE [db.]name [ON CLUSTER cluster] [PARTITION partition | PARTITION ID 'partition_id'] [FINAL] [DEDUPLICATE [BY expression]]
4765    /// ```
4766    /// See ClickHouse <https://clickhouse.com/docs/en/sql-reference/statements/optimize>
4767    ///
4768    /// Databricks:
4769    /// ```sql
4770    /// OPTIMIZE table_name [WHERE predicate] [ZORDER BY (col_name1 [, ...])]
4771    /// ```
4772    /// See Databricks <https://docs.databricks.com/en/sql/language-manual/delta-optimize.html>
4773    OptimizeTable {
4774        /// Table name to optimize.
4775        name: ObjectName,
4776        /// Whether the `TABLE` keyword was present (ClickHouse uses `OPTIMIZE TABLE`, Databricks uses `OPTIMIZE`).
4777        has_table_keyword: bool,
4778        /// Optional cluster identifier.
4779        /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/optimize)
4780        on_cluster: Option<Ident>,
4781        /// Optional partition spec.
4782        /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/optimize)
4783        partition: Option<Partition>,
4784        /// Whether `FINAL` was specified.
4785        /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/optimize)
4786        include_final: bool,
4787        /// Optional deduplication settings.
4788        /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/optimize)
4789        deduplicate: Option<Deduplicate>,
4790        /// Optional WHERE predicate.
4791        /// [Databricks](https://docs.databricks.com/en/sql/language-manual/delta-optimize.html)
4792        predicate: Option<Expr>,
4793        /// Optional ZORDER BY columns.
4794        /// [Databricks](https://docs.databricks.com/en/sql/language-manual/delta-optimize.html)
4795        zorder: Option<Vec<Expr>>,
4796    },
4797    /// ```sql
4798    /// LISTEN
4799    /// ```
4800    /// listen for a notification channel
4801    ///
4802    /// See Postgres <https://www.postgresql.org/docs/current/sql-listen.html>
4803    LISTEN {
4804        /// Notification channel identifier.
4805        channel: Ident,
4806    },
4807    /// ```sql
4808    /// UNLISTEN
4809    /// ```
4810    /// stop listening for a notification
4811    ///
4812    /// See Postgres <https://www.postgresql.org/docs/current/sql-unlisten.html>
4813    UNLISTEN {
4814        /// Notification channel identifier.
4815        channel: Ident,
4816    },
4817    /// ```sql
4818    /// NOTIFY channel [ , payload ]
4819    /// ```
4820    /// send a notification event together with an optional "payload" string to channel
4821    ///
4822    /// See Postgres <https://www.postgresql.org/docs/current/sql-notify.html>
4823    NOTIFY {
4824        /// Notification channel identifier.
4825        channel: Ident,
4826        /// Optional payload string.
4827        payload: Option<String>,
4828    },
4829    /// ```sql
4830    /// LOAD DATA [LOCAL] INPATH 'filepath' [OVERWRITE] INTO TABLE tablename
4831    /// [PARTITION (partcol1=val1, partcol2=val2 ...)]
4832    /// [INPUTFORMAT 'inputformat' SERDE 'serde']
4833    /// ```
4834    /// Loading files into tables
4835    ///
4836    /// See Hive <https://cwiki.apache.org/confluence/pages/viewpage.action?pageId=27362036#LanguageManualDML-Loadingfilesintotables>
4837    LoadData {
4838        /// Whether `LOCAL` is present.
4839        local: bool,
4840        /// Input path for files to load.
4841        inpath: String,
4842        /// Whether `OVERWRITE` was specified.
4843        overwrite: bool,
4844        /// Target table name to load into.
4845        table_name: ObjectName,
4846        /// Optional partition specification.
4847        partitioned: Option<Vec<Expr>>,
4848        /// Optional table format information.
4849        table_format: Option<HiveLoadDataFormat>,
4850    },
4851    /// ```sql
4852    /// Rename TABLE tbl_name TO new_tbl_name[, tbl_name2 TO new_tbl_name2] ...
4853    /// ```
4854    /// Renames one or more tables
4855    ///
4856    /// See Mysql <https://dev.mysql.com/doc/refman/9.1/en/rename-table.html>
4857    RenameTable(Vec<RenameTable>),
4858    /// Snowflake `LIST`
4859    /// See: <https://docs.snowflake.com/en/sql-reference/sql/list>
4860    List(FileStagingCommand),
4861    /// Snowflake `REMOVE`
4862    /// See: <https://docs.snowflake.com/en/sql-reference/sql/remove>
4863    Remove(FileStagingCommand),
4864    /// RaiseError (MSSQL)
4865    /// RAISERROR ( { msg_id | msg_str | @local_variable }
4866    /// { , severity , state }
4867    /// [ , argument [ , ...n ] ] )
4868    /// [ WITH option [ , ...n ] ]
4869    /// See <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/raiserror-transact-sql?view=sql-server-ver16>
4870    RaisError {
4871        /// Error message expression or identifier.
4872        message: Box<Expr>,
4873        /// Severity expression.
4874        severity: Box<Expr>,
4875        /// State expression.
4876        state: Box<Expr>,
4877        /// Substitution arguments for the message.
4878        arguments: Vec<Expr>,
4879        /// Additional `WITH` options for RAISERROR.
4880        options: Vec<RaisErrorOption>,
4881    },
4882    /// A MSSQL `THROW` statement.
4883    Throw(ThrowStatement),
4884    /// ```sql
4885    /// PRINT msg_str | @local_variable | string_expr
4886    /// ```
4887    ///
4888    /// See: <https://learn.microsoft.com/en-us/sql/t-sql/statements/print-transact-sql>
4889    Print(PrintStatement),
4890    /// MSSQL `WAITFOR` statement.
4891    ///
4892    /// See: <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/waitfor-transact-sql>
4893    WaitFor(WaitForStatement),
4894    /// ```sql
4895    /// RETURN [ expression ]
4896    /// ```
4897    ///
4898    /// See [ReturnStatement]
4899    Return(ReturnStatement),
4900    /// Export data statement
4901    ///
4902    /// Example:
4903    /// ```sql
4904    /// EXPORT DATA OPTIONS(uri='gs://bucket/folder/*', format='PARQUET', overwrite=true) AS
4905    /// SELECT field1, field2 FROM mydataset.table1 ORDER BY field1 LIMIT 10
4906    /// ```
4907    /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/export-statements)
4908    ExportData(ExportData),
4909    /// ```sql
4910    /// CREATE [OR REPLACE] USER <user> [IF NOT EXISTS]
4911    /// ```
4912    /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-user)
4913    CreateUser(CreateUser),
4914    /// ```sql
4915    /// ALTER USER \[ IF EXISTS \] \[ <name> \]
4916    /// ```
4917    /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/alter-user)
4918    AlterUser(AlterUser),
4919    /// Re-sorts rows and reclaims space in either a specified table or all tables in the current database
4920    ///
4921    /// ```sql
4922    /// VACUUM tbl
4923    /// ```
4924    /// [Redshift](https://docs.aws.amazon.com/redshift/latest/dg/r_VACUUM_command.html)
4925    Vacuum(VacuumStatement),
4926    /// Restore the value of a run-time parameter to the default value.
4927    ///
4928    /// ```sql
4929    /// RESET configuration_parameter;
4930    /// RESET ALL;
4931    /// ```
4932    /// [PostgreSQL](https://www.postgresql.org/docs/current/sql-reset.html)
4933    Reset(ResetStatement),
4934}
4935
4936impl From<Analyze> for Statement {
4937    fn from(analyze: Analyze) -> Self {
4938        Statement::Analyze(analyze)
4939    }
4940}
4941
4942impl From<ddl::Truncate> for Statement {
4943    fn from(truncate: ddl::Truncate) -> Self {
4944        Statement::Truncate(truncate)
4945    }
4946}
4947
4948impl From<Lock> for Statement {
4949    fn from(lock: Lock) -> Self {
4950        Statement::Lock(lock)
4951    }
4952}
4953
4954impl From<ddl::Msck> for Statement {
4955    fn from(msck: ddl::Msck) -> Self {
4956        Statement::Msck(msck)
4957    }
4958}
4959
4960/// ```sql
4961/// {COPY | REVOKE} CURRENT GRANTS
4962/// ```
4963///
4964/// - [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/grant-ownership#optional-parameters)
4965#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
4966#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4967#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
4968pub enum CurrentGrantsKind {
4969    /// `COPY CURRENT GRANTS` (copy current grants to target).
4970    CopyCurrentGrants,
4971    /// `REVOKE CURRENT GRANTS` (revoke current grants from target).
4972    RevokeCurrentGrants,
4973}
4974
4975impl fmt::Display for CurrentGrantsKind {
4976    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
4977        match self {
4978            CurrentGrantsKind::CopyCurrentGrants => write!(f, "COPY CURRENT GRANTS"),
4979            CurrentGrantsKind::RevokeCurrentGrants => write!(f, "REVOKE CURRENT GRANTS"),
4980        }
4981    }
4982}
4983
4984#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
4985#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4986#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
4987/// `RAISERROR` options
4988/// See <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/raiserror-transact-sql?view=sql-server-ver16#options>
4989pub enum RaisErrorOption {
4990    /// Log the error.
4991    Log,
4992    /// Do not wait for completion.
4993    NoWait,
4994    /// Set the error state.
4995    SetError,
4996}
4997
4998impl fmt::Display for RaisErrorOption {
4999    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
5000        match self {
5001            RaisErrorOption::Log => write!(f, "LOG"),
5002            RaisErrorOption::NoWait => write!(f, "NOWAIT"),
5003            RaisErrorOption::SetError => write!(f, "SETERROR"),
5004        }
5005    }
5006}
5007
5008impl fmt::Display for Statement {
5009    /// Formats a SQL statement with support for pretty printing.
5010    ///
5011    /// When using the alternate flag (`{:#}`), the statement will be formatted with proper
5012    /// indentation and line breaks. For example:
5013    ///
5014    /// ```
5015    /// # use sqlparser::dialect::GenericDialect;
5016    /// # use sqlparser::parser::Parser;
5017    /// let sql = "SELECT a, b FROM table_1";
5018    /// let ast = Parser::parse_sql(&GenericDialect, sql).unwrap();
5019    ///
5020    /// // Regular formatting
5021    /// assert_eq!(format!("{}", ast[0]), "SELECT a, b FROM table_1");
5022    ///
5023    /// // Pretty printing
5024    /// assert_eq!(format!("{:#}", ast[0]),
5025    /// r#"SELECT
5026    ///   a,
5027    ///   b
5028    /// FROM
5029    ///   table_1"#);
5030    /// ```
5031    // Clippy thinks this function is too complicated, but it is painful to
5032    // split up without extracting structs for each `Statement` variant.
5033    #[allow(clippy::cognitive_complexity)]
5034    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
5035        match self {
5036            Statement::Flush {
5037                object_type,
5038                location,
5039                channel,
5040                read_lock,
5041                export,
5042                tables,
5043            } => {
5044                write!(f, "FLUSH")?;
5045                if let Some(location) = location {
5046                    f.write_str(" ")?;
5047                    location.fmt(f)?;
5048                }
5049                write!(f, " {object_type}")?;
5050
5051                if let Some(channel) = channel {
5052                    write!(f, " FOR CHANNEL {channel}")?;
5053                }
5054
5055                write!(
5056                    f,
5057                    "{tables}{read}{export}",
5058                    tables = if !tables.is_empty() {
5059                        format!(" {}", display_comma_separated(tables))
5060                    } else {
5061                        String::new()
5062                    },
5063                    export = if *export { " FOR EXPORT" } else { "" },
5064                    read = if *read_lock { " WITH READ LOCK" } else { "" }
5065                )
5066            }
5067            Statement::Kill { modifier, id } => {
5068                write!(f, "KILL ")?;
5069
5070                if let Some(m) = modifier {
5071                    write!(f, "{m} ")?;
5072                }
5073
5074                write!(f, "{id}")
5075            }
5076            Statement::ExplainTable {
5077                describe_alias,
5078                hive_format,
5079                has_table_keyword,
5080                table_name,
5081            } => {
5082                write!(f, "{describe_alias} ")?;
5083
5084                if let Some(format) = hive_format {
5085                    write!(f, "{format} ")?;
5086                }
5087                if *has_table_keyword {
5088                    write!(f, "TABLE ")?;
5089                }
5090
5091                write!(f, "{table_name}")
5092            }
5093            Statement::Explain {
5094                describe_alias,
5095                verbose,
5096                analyze,
5097                query_plan,
5098                estimate,
5099                statement,
5100                format,
5101                options,
5102            } => {
5103                write!(f, "{describe_alias} ")?;
5104
5105                if *query_plan {
5106                    write!(f, "QUERY PLAN ")?;
5107                }
5108                if *analyze {
5109                    write!(f, "ANALYZE ")?;
5110                }
5111                if *estimate {
5112                    write!(f, "ESTIMATE ")?;
5113                }
5114
5115                if *verbose {
5116                    write!(f, "VERBOSE ")?;
5117                }
5118
5119                if let Some(format) = format {
5120                    write!(f, "{format} ")?;
5121                }
5122
5123                if let Some(options) = options {
5124                    write!(f, "({}) ", display_comma_separated(options))?;
5125                }
5126
5127                write!(f, "{statement}")
5128            }
5129            Statement::Query(s) => s.fmt(f),
5130            Statement::Declare { stmts } => {
5131                write!(f, "DECLARE ")?;
5132                write!(f, "{}", display_separated(stmts, "; "))
5133            }
5134            Statement::Fetch {
5135                name,
5136                direction,
5137                position,
5138                into,
5139            } => {
5140                write!(f, "FETCH {direction} {position} {name}")?;
5141
5142                if let Some(into) = into {
5143                    write!(f, " INTO {into}")?;
5144                }
5145
5146                Ok(())
5147            }
5148            Statement::Directory {
5149                overwrite,
5150                local,
5151                path,
5152                file_format,
5153                source,
5154            } => {
5155                write!(
5156                    f,
5157                    "INSERT{overwrite}{local} DIRECTORY '{path}'",
5158                    overwrite = if *overwrite { " OVERWRITE" } else { "" },
5159                    local = if *local { " LOCAL" } else { "" },
5160                    path = path
5161                )?;
5162                if let Some(ref ff) = file_format {
5163                    write!(f, " STORED AS {ff}")?
5164                }
5165                write!(f, " {source}")
5166            }
5167            Statement::Msck(msck) => msck.fmt(f),
5168            Statement::Truncate(truncate) => truncate.fmt(f),
5169            Statement::Case(stmt) => {
5170                write!(f, "{stmt}")
5171            }
5172            Statement::If(stmt) => {
5173                write!(f, "{stmt}")
5174            }
5175            Statement::While(stmt) => {
5176                write!(f, "{stmt}")
5177            }
5178            Statement::Raise(stmt) => {
5179                write!(f, "{stmt}")
5180            }
5181            Statement::AttachDatabase {
5182                schema_name,
5183                database_file_name,
5184                database,
5185            } => {
5186                let keyword = if *database { "DATABASE " } else { "" };
5187                write!(f, "ATTACH {keyword}{database_file_name} AS {schema_name}")
5188            }
5189            Statement::AttachDuckDBDatabase {
5190                if_not_exists,
5191                database,
5192                database_path,
5193                database_alias,
5194                attach_options,
5195            } => {
5196                write!(
5197                    f,
5198                    "ATTACH{database}{if_not_exists} {database_path}",
5199                    database = if *database { " DATABASE" } else { "" },
5200                    if_not_exists = if *if_not_exists { " IF NOT EXISTS" } else { "" },
5201                )?;
5202                if let Some(alias) = database_alias {
5203                    write!(f, " AS {alias}")?;
5204                }
5205                if !attach_options.is_empty() {
5206                    write!(f, " ({})", display_comma_separated(attach_options))?;
5207                }
5208                Ok(())
5209            }
5210            Statement::DetachDuckDBDatabase {
5211                if_exists,
5212                database,
5213                database_alias,
5214            } => {
5215                write!(
5216                    f,
5217                    "DETACH{database}{if_exists} {database_alias}",
5218                    database = if *database { " DATABASE" } else { "" },
5219                    if_exists = if *if_exists { " IF EXISTS" } else { "" },
5220                )?;
5221                Ok(())
5222            }
5223            Statement::Analyze(analyze) => analyze.fmt(f),
5224            Statement::Insert(insert) => insert.fmt(f),
5225            Statement::Install {
5226                extension_name: name,
5227            } => write!(f, "INSTALL {name}"),
5228
5229            Statement::Load {
5230                extension_name: name,
5231            } => write!(f, "LOAD {name}"),
5232
5233            Statement::Call(function) => write!(f, "CALL {function}"),
5234
5235            Statement::Copy {
5236                source,
5237                to,
5238                target,
5239                options,
5240                legacy_options,
5241                values,
5242            } => {
5243                write!(f, "COPY")?;
5244                match source {
5245                    CopySource::Query(query) => write!(f, " ({query})")?,
5246                    CopySource::Table {
5247                        table_name,
5248                        columns,
5249                    } => {
5250                        write!(f, " {table_name}")?;
5251                        if !columns.is_empty() {
5252                            write!(f, " ({})", display_comma_separated(columns))?;
5253                        }
5254                    }
5255                }
5256                write!(f, " {} {}", if *to { "TO" } else { "FROM" }, target)?;
5257                if !options.is_empty() {
5258                    write!(f, " ({})", display_comma_separated(options))?;
5259                }
5260                if !legacy_options.is_empty() {
5261                    write!(f, " {}", display_separated(legacy_options, " "))?;
5262                }
5263                if !values.is_empty() {
5264                    writeln!(f, ";")?;
5265                    let mut delim = "";
5266                    for v in values {
5267                        write!(f, "{delim}")?;
5268                        delim = "\t";
5269                        if let Some(v) = v {
5270                            write!(f, "{v}")?;
5271                        } else {
5272                            write!(f, "\\N")?;
5273                        }
5274                    }
5275                    write!(f, "\n\\.")?;
5276                }
5277                Ok(())
5278            }
5279            Statement::Update(update) => update.fmt(f),
5280            Statement::Delete(delete) => delete.fmt(f),
5281            Statement::Open(open) => open.fmt(f),
5282            Statement::Close { cursor } => {
5283                write!(f, "CLOSE {cursor}")?;
5284
5285                Ok(())
5286            }
5287            Statement::CreateDatabase {
5288                db_name,
5289                if_not_exists,
5290                location,
5291                managed_location,
5292                or_replace,
5293                transient,
5294                clone,
5295                data_retention_time_in_days,
5296                max_data_extension_time_in_days,
5297                external_volume,
5298                catalog,
5299                replace_invalid_characters,
5300                default_ddl_collation,
5301                storage_serialization_policy,
5302                comment,
5303                default_charset,
5304                default_collation,
5305                catalog_sync,
5306                catalog_sync_namespace_mode,
5307                catalog_sync_namespace_flatten_delimiter,
5308                with_tags,
5309                with_contacts,
5310            } => {
5311                write!(
5312                    f,
5313                    "CREATE {or_replace}{transient}DATABASE {if_not_exists}{name}",
5314                    or_replace = if *or_replace { "OR REPLACE " } else { "" },
5315                    transient = if *transient { "TRANSIENT " } else { "" },
5316                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
5317                    name = db_name,
5318                )?;
5319
5320                if let Some(l) = location {
5321                    write!(f, " LOCATION '{l}'")?;
5322                }
5323                if let Some(ml) = managed_location {
5324                    write!(f, " MANAGEDLOCATION '{ml}'")?;
5325                }
5326                if let Some(clone) = clone {
5327                    write!(f, " CLONE {clone}")?;
5328                }
5329
5330                if let Some(value) = data_retention_time_in_days {
5331                    write!(f, " DATA_RETENTION_TIME_IN_DAYS = {value}")?;
5332                }
5333
5334                if let Some(value) = max_data_extension_time_in_days {
5335                    write!(f, " MAX_DATA_EXTENSION_TIME_IN_DAYS = {value}")?;
5336                }
5337
5338                if let Some(vol) = external_volume {
5339                    write!(f, " EXTERNAL_VOLUME = '{vol}'")?;
5340                }
5341
5342                if let Some(cat) = catalog {
5343                    write!(f, " CATALOG = '{cat}'")?;
5344                }
5345
5346                if let Some(true) = replace_invalid_characters {
5347                    write!(f, " REPLACE_INVALID_CHARACTERS = TRUE")?;
5348                } else if let Some(false) = replace_invalid_characters {
5349                    write!(f, " REPLACE_INVALID_CHARACTERS = FALSE")?;
5350                }
5351
5352                if let Some(collation) = default_ddl_collation {
5353                    write!(f, " DEFAULT_DDL_COLLATION = '{collation}'")?;
5354                }
5355
5356                if let Some(policy) = storage_serialization_policy {
5357                    write!(f, " STORAGE_SERIALIZATION_POLICY = {policy}")?;
5358                }
5359
5360                if let Some(comment) = comment {
5361                    write!(f, " COMMENT = '{comment}'")?;
5362                }
5363
5364                if let Some(charset) = default_charset {
5365                    write!(f, " DEFAULT CHARACTER SET {charset}")?;
5366                }
5367
5368                if let Some(collation) = default_collation {
5369                    write!(f, " DEFAULT COLLATE {collation}")?;
5370                }
5371
5372                if let Some(sync) = catalog_sync {
5373                    write!(f, " CATALOG_SYNC = '{sync}'")?;
5374                }
5375
5376                if let Some(mode) = catalog_sync_namespace_mode {
5377                    write!(f, " CATALOG_SYNC_NAMESPACE_MODE = {mode}")?;
5378                }
5379
5380                if let Some(delim) = catalog_sync_namespace_flatten_delimiter {
5381                    write!(f, " CATALOG_SYNC_NAMESPACE_FLATTEN_DELIMITER = '{delim}'")?;
5382                }
5383
5384                if let Some(tags) = with_tags {
5385                    write!(f, " WITH TAG ({})", display_comma_separated(tags))?;
5386                }
5387
5388                if let Some(contacts) = with_contacts {
5389                    write!(f, " WITH CONTACT ({})", display_comma_separated(contacts))?;
5390                }
5391                Ok(())
5392            }
5393            Statement::CreateFunction(create_function) => create_function.fmt(f),
5394            Statement::CreateDomain(create_domain) => create_domain.fmt(f),
5395            Statement::CreateTrigger(create_trigger) => create_trigger.fmt(f),
5396            Statement::DropTrigger(drop_trigger) => drop_trigger.fmt(f),
5397            Statement::CreateProcedure {
5398                name,
5399                or_alter,
5400                params,
5401                language,
5402                body,
5403            } => {
5404                write!(
5405                    f,
5406                    "CREATE {or_alter}PROCEDURE {name}",
5407                    or_alter = if *or_alter { "OR ALTER " } else { "" },
5408                    name = name
5409                )?;
5410
5411                if let Some(p) = params {
5412                    if !p.is_empty() {
5413                        write!(f, " ({})", display_comma_separated(p))?;
5414                    }
5415                }
5416
5417                if let Some(language) = language {
5418                    write!(f, " LANGUAGE {language}")?;
5419                }
5420
5421                write!(f, " AS {body}")
5422            }
5423            Statement::CreateMacro {
5424                or_replace,
5425                temporary,
5426                name,
5427                args,
5428                definition,
5429            } => {
5430                write!(
5431                    f,
5432                    "CREATE {or_replace}{temp}MACRO {name}",
5433                    temp = if *temporary { "TEMPORARY " } else { "" },
5434                    or_replace = if *or_replace { "OR REPLACE " } else { "" },
5435                )?;
5436                if let Some(args) = args {
5437                    write!(f, "({})", display_comma_separated(args))?;
5438                }
5439                match definition {
5440                    MacroDefinition::Expr(expr) => write!(f, " AS {expr}")?,
5441                    MacroDefinition::Table(query) => write!(f, " AS TABLE {query}")?,
5442                }
5443                Ok(())
5444            }
5445            Statement::CreateView(create_view) => create_view.fmt(f),
5446            Statement::CreateTable(create_table) => create_table.fmt(f),
5447            Statement::LoadData {
5448                local,
5449                inpath,
5450                overwrite,
5451                table_name,
5452                partitioned,
5453                table_format,
5454            } => {
5455                write!(
5456                    f,
5457                    "LOAD DATA {local}INPATH '{inpath}' {overwrite}INTO TABLE {table_name}",
5458                    local = if *local { "LOCAL " } else { "" },
5459                    inpath = inpath,
5460                    overwrite = if *overwrite { "OVERWRITE " } else { "" },
5461                    table_name = table_name,
5462                )?;
5463                if let Some(ref parts) = &partitioned {
5464                    if !parts.is_empty() {
5465                        write!(f, " PARTITION ({})", display_comma_separated(parts))?;
5466                    }
5467                }
5468                if let Some(HiveLoadDataFormat {
5469                    serde,
5470                    input_format,
5471                }) = &table_format
5472                {
5473                    write!(f, " INPUTFORMAT {input_format} SERDE {serde}")?;
5474                }
5475                Ok(())
5476            }
5477            Statement::CreateVirtualTable {
5478                name,
5479                if_not_exists,
5480                module_name,
5481                module_args,
5482            } => {
5483                write!(
5484                    f,
5485                    "CREATE VIRTUAL TABLE {if_not_exists}{name} USING {module_name}",
5486                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
5487                    name = name,
5488                    module_name = module_name
5489                )?;
5490                if !module_args.is_empty() {
5491                    write!(f, " ({})", display_comma_separated(module_args))?;
5492                }
5493                Ok(())
5494            }
5495            Statement::CreateIndex(create_index) => create_index.fmt(f),
5496            Statement::CreateExtension(create_extension) => write!(f, "{create_extension}"),
5497            Statement::CreateCollation(create_collation) => write!(f, "{create_collation}"),
5498            Statement::DropExtension(drop_extension) => write!(f, "{drop_extension}"),
5499            Statement::DropOperator(drop_operator) => write!(f, "{drop_operator}"),
5500            Statement::DropOperatorFamily(drop_operator_family) => {
5501                write!(f, "{drop_operator_family}")
5502            }
5503            Statement::DropOperatorClass(drop_operator_class) => {
5504                write!(f, "{drop_operator_class}")
5505            }
5506            Statement::CreateRole(create_role) => write!(f, "{create_role}"),
5507            Statement::CreateSecret {
5508                or_replace,
5509                temporary,
5510                if_not_exists,
5511                name,
5512                storage_specifier,
5513                secret_type,
5514                options,
5515            } => {
5516                write!(
5517                    f,
5518                    "CREATE {or_replace}",
5519                    or_replace = if *or_replace { "OR REPLACE " } else { "" },
5520                )?;
5521                if let Some(t) = temporary {
5522                    write!(f, "{}", if *t { "TEMPORARY " } else { "PERSISTENT " })?;
5523                }
5524                write!(
5525                    f,
5526                    "SECRET {if_not_exists}",
5527                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
5528                )?;
5529                if let Some(n) = name {
5530                    write!(f, "{n} ")?;
5531                };
5532                if let Some(s) = storage_specifier {
5533                    write!(f, "IN {s} ")?;
5534                }
5535                write!(f, "( TYPE {secret_type}",)?;
5536                if !options.is_empty() {
5537                    write!(f, ", {o}", o = display_comma_separated(options))?;
5538                }
5539                write!(f, " )")?;
5540                Ok(())
5541            }
5542            Statement::CreateServer(stmt) => {
5543                write!(f, "{stmt}")
5544            }
5545            Statement::CreatePolicy(policy) => write!(f, "{policy}"),
5546            Statement::CreateConnector(create_connector) => create_connector.fmt(f),
5547            Statement::CreateOperator(create_operator) => create_operator.fmt(f),
5548            Statement::CreateOperatorFamily(create_operator_family) => {
5549                create_operator_family.fmt(f)
5550            }
5551            Statement::CreateOperatorClass(create_operator_class) => create_operator_class.fmt(f),
5552            Statement::AlterTable(alter_table) => write!(f, "{alter_table}"),
5553            Statement::AlterIndex { name, operation } => {
5554                write!(f, "ALTER INDEX {name} {operation}")
5555            }
5556            Statement::AlterView {
5557                name,
5558                columns,
5559                query,
5560                with_options,
5561            } => {
5562                write!(f, "ALTER VIEW {name}")?;
5563                if !with_options.is_empty() {
5564                    write!(f, " WITH ({})", display_comma_separated(with_options))?;
5565                }
5566                if !columns.is_empty() {
5567                    write!(f, " ({})", display_comma_separated(columns))?;
5568                }
5569                write!(f, " AS {query}")
5570            }
5571            Statement::AlterFunction(alter_function) => write!(f, "{alter_function}"),
5572            Statement::AlterType(AlterType { name, operation }) => {
5573                write!(f, "ALTER TYPE {name} {operation}")
5574            }
5575            Statement::AlterCollation(alter_collation) => write!(f, "{alter_collation}"),
5576            Statement::AlterOperator(alter_operator) => write!(f, "{alter_operator}"),
5577            Statement::AlterOperatorFamily(alter_operator_family) => {
5578                write!(f, "{alter_operator_family}")
5579            }
5580            Statement::AlterOperatorClass(alter_operator_class) => {
5581                write!(f, "{alter_operator_class}")
5582            }
5583            Statement::AlterRole { name, operation } => {
5584                write!(f, "ALTER ROLE {name} {operation}")
5585            }
5586            Statement::AlterPolicy(alter_policy) => write!(f, "{alter_policy}"),
5587            Statement::AlterConnector {
5588                name,
5589                properties,
5590                url,
5591                owner,
5592            } => {
5593                write!(f, "ALTER CONNECTOR {name}")?;
5594                if let Some(properties) = properties {
5595                    write!(
5596                        f,
5597                        " SET DCPROPERTIES({})",
5598                        display_comma_separated(properties)
5599                    )?;
5600                }
5601                if let Some(url) = url {
5602                    write!(f, " SET URL '{url}'")?;
5603                }
5604                if let Some(owner) = owner {
5605                    write!(f, " SET OWNER {owner}")?;
5606                }
5607                Ok(())
5608            }
5609            Statement::AlterSession {
5610                set,
5611                session_params,
5612            } => {
5613                write!(
5614                    f,
5615                    "ALTER SESSION {set}",
5616                    set = if *set { "SET" } else { "UNSET" }
5617                )?;
5618                if !session_params.options.is_empty() {
5619                    if *set {
5620                        write!(f, " {session_params}")?;
5621                    } else {
5622                        let options = session_params
5623                            .options
5624                            .iter()
5625                            .map(|p| p.option_name.clone())
5626                            .collect::<Vec<_>>();
5627                        write!(f, " {}", display_separated(&options, ", "))?;
5628                    }
5629                }
5630                Ok(())
5631            }
5632            Statement::Drop {
5633                object_type,
5634                if_exists,
5635                names,
5636                cascade,
5637                restrict,
5638                purge,
5639                temporary,
5640                table,
5641            } => {
5642                write!(
5643                    f,
5644                    "DROP {}{}{} {}{}{}{}",
5645                    if *temporary { "TEMPORARY " } else { "" },
5646                    object_type,
5647                    if *if_exists { " IF EXISTS" } else { "" },
5648                    display_comma_separated(names),
5649                    if *cascade { " CASCADE" } else { "" },
5650                    if *restrict { " RESTRICT" } else { "" },
5651                    if *purge { " PURGE" } else { "" },
5652                )?;
5653                if let Some(table_name) = table.as_ref() {
5654                    write!(f, " ON {table_name}")?;
5655                };
5656                Ok(())
5657            }
5658            Statement::DropFunction(drop_function) => write!(f, "{drop_function}"),
5659            Statement::DropDomain(DropDomain {
5660                if_exists,
5661                name,
5662                drop_behavior,
5663            }) => {
5664                write!(
5665                    f,
5666                    "DROP DOMAIN{} {name}",
5667                    if *if_exists { " IF EXISTS" } else { "" },
5668                )?;
5669                if let Some(op) = drop_behavior {
5670                    write!(f, " {op}")?;
5671                }
5672                Ok(())
5673            }
5674            Statement::DropProcedure {
5675                if_exists,
5676                proc_desc,
5677                drop_behavior,
5678            } => {
5679                write!(
5680                    f,
5681                    "DROP PROCEDURE{} {}",
5682                    if *if_exists { " IF EXISTS" } else { "" },
5683                    display_comma_separated(proc_desc),
5684                )?;
5685                if let Some(op) = drop_behavior {
5686                    write!(f, " {op}")?;
5687                }
5688                Ok(())
5689            }
5690            Statement::DropSecret {
5691                if_exists,
5692                temporary,
5693                name,
5694                storage_specifier,
5695            } => {
5696                write!(f, "DROP ")?;
5697                if let Some(t) = temporary {
5698                    write!(f, "{}", if *t { "TEMPORARY " } else { "PERSISTENT " })?;
5699                }
5700                write!(
5701                    f,
5702                    "SECRET {if_exists}{name}",
5703                    if_exists = if *if_exists { "IF EXISTS " } else { "" },
5704                )?;
5705                if let Some(s) = storage_specifier {
5706                    write!(f, " FROM {s}")?;
5707                }
5708                Ok(())
5709            }
5710            Statement::DropPolicy(policy) => write!(f, "{policy}"),
5711            Statement::DropConnector { if_exists, name } => {
5712                write!(
5713                    f,
5714                    "DROP CONNECTOR {if_exists}{name}",
5715                    if_exists = if *if_exists { "IF EXISTS " } else { "" }
5716                )?;
5717                Ok(())
5718            }
5719            Statement::Discard { object_type } => {
5720                write!(f, "DISCARD {object_type}")?;
5721                Ok(())
5722            }
5723            Self::Set(set) => write!(f, "{set}"),
5724            Statement::ShowVariable { variable } => {
5725                write!(f, "SHOW")?;
5726                if !variable.is_empty() {
5727                    write!(f, " {}", display_separated(variable, " "))?;
5728                }
5729                Ok(())
5730            }
5731            Statement::ShowStatus {
5732                filter,
5733                global,
5734                session,
5735            } => {
5736                write!(f, "SHOW")?;
5737                if *global {
5738                    write!(f, " GLOBAL")?;
5739                }
5740                if *session {
5741                    write!(f, " SESSION")?;
5742                }
5743                write!(f, " STATUS")?;
5744                if filter.is_some() {
5745                    write!(f, " {}", filter.as_ref().unwrap())?;
5746                }
5747                Ok(())
5748            }
5749            Statement::ShowVariables {
5750                filter,
5751                global,
5752                session,
5753            } => {
5754                write!(f, "SHOW")?;
5755                if *global {
5756                    write!(f, " GLOBAL")?;
5757                }
5758                if *session {
5759                    write!(f, " SESSION")?;
5760                }
5761                write!(f, " VARIABLES")?;
5762                if filter.is_some() {
5763                    write!(f, " {}", filter.as_ref().unwrap())?;
5764                }
5765                Ok(())
5766            }
5767            Statement::ShowCreate { obj_type, obj_name } => {
5768                write!(f, "SHOW CREATE {obj_type} {obj_name}",)?;
5769                Ok(())
5770            }
5771            Statement::ShowColumns {
5772                extended,
5773                full,
5774                show_options,
5775            } => {
5776                write!(
5777                    f,
5778                    "SHOW {extended}{full}COLUMNS{show_options}",
5779                    extended = if *extended { "EXTENDED " } else { "" },
5780                    full = if *full { "FULL " } else { "" },
5781                )?;
5782                Ok(())
5783            }
5784            Statement::ShowDatabases {
5785                terse,
5786                history,
5787                show_options,
5788            } => {
5789                write!(
5790                    f,
5791                    "SHOW {terse}DATABASES{history}{show_options}",
5792                    terse = if *terse { "TERSE " } else { "" },
5793                    history = if *history { " HISTORY" } else { "" },
5794                )?;
5795                Ok(())
5796            }
5797            Statement::ShowCatalogs {
5798                terse,
5799                history,
5800                show_options,
5801            } => {
5802                write!(
5803                    f,
5804                    "SHOW {terse}CATALOGS{history}{show_options}",
5805                    terse = if *terse { "TERSE " } else { "" },
5806                    history = if *history { " HISTORY" } else { "" },
5807                )?;
5808                Ok(())
5809            }
5810            Statement::ShowProcessList { full } => {
5811                write!(
5812                    f,
5813                    "SHOW {full}PROCESSLIST",
5814                    full = if *full { "FULL " } else { "" },
5815                )?;
5816                Ok(())
5817            }
5818            Statement::ShowSchemas {
5819                terse,
5820                history,
5821                show_options,
5822            } => {
5823                write!(
5824                    f,
5825                    "SHOW {terse}SCHEMAS{history}{show_options}",
5826                    terse = if *terse { "TERSE " } else { "" },
5827                    history = if *history { " HISTORY" } else { "" },
5828                )?;
5829                Ok(())
5830            }
5831            Statement::ShowObjects(ShowObjects {
5832                terse,
5833                show_options,
5834            }) => {
5835                write!(
5836                    f,
5837                    "SHOW {terse}OBJECTS{show_options}",
5838                    terse = if *terse { "TERSE " } else { "" },
5839                )?;
5840                Ok(())
5841            }
5842            Statement::ShowTables {
5843                terse,
5844                history,
5845                extended,
5846                full,
5847                external,
5848                show_options,
5849            } => {
5850                write!(
5851                    f,
5852                    "SHOW {terse}{extended}{full}{external}TABLES{history}{show_options}",
5853                    terse = if *terse { "TERSE " } else { "" },
5854                    extended = if *extended { "EXTENDED " } else { "" },
5855                    full = if *full { "FULL " } else { "" },
5856                    external = if *external { "EXTERNAL " } else { "" },
5857                    history = if *history { " HISTORY" } else { "" },
5858                )?;
5859                Ok(())
5860            }
5861            Statement::ShowViews {
5862                terse,
5863                materialized,
5864                show_options,
5865            } => {
5866                write!(
5867                    f,
5868                    "SHOW {terse}{materialized}VIEWS{show_options}",
5869                    terse = if *terse { "TERSE " } else { "" },
5870                    materialized = if *materialized { "MATERIALIZED " } else { "" }
5871                )?;
5872                Ok(())
5873            }
5874            Statement::ShowFunctions { filter } => {
5875                write!(f, "SHOW FUNCTIONS")?;
5876                if let Some(filter) = filter {
5877                    write!(f, " {filter}")?;
5878                }
5879                Ok(())
5880            }
5881            Statement::Use(use_expr) => use_expr.fmt(f),
5882            Statement::ShowCollation { filter } => {
5883                write!(f, "SHOW COLLATION")?;
5884                if let Some(filter) = filter {
5885                    write!(f, " {filter}")?;
5886                }
5887                Ok(())
5888            }
5889            Statement::ShowCharset(show_stm) => show_stm.fmt(f),
5890            Statement::StartTransaction {
5891                modes,
5892                begin: syntax_begin,
5893                transaction,
5894                modifier,
5895                statements,
5896                exception,
5897                has_end_keyword,
5898            } => {
5899                if *syntax_begin {
5900                    if let Some(modifier) = *modifier {
5901                        write!(f, "BEGIN {modifier}")?;
5902                    } else {
5903                        write!(f, "BEGIN")?;
5904                    }
5905                } else {
5906                    write!(f, "START")?;
5907                }
5908                if let Some(transaction) = transaction {
5909                    write!(f, " {transaction}")?;
5910                }
5911                if !modes.is_empty() {
5912                    write!(f, " {}", display_comma_separated(modes))?;
5913                }
5914                if !statements.is_empty() {
5915                    write!(f, " ")?;
5916                    format_statement_list(f, statements)?;
5917                }
5918                if let Some(exception_when) = exception {
5919                    write!(f, " EXCEPTION")?;
5920                    for when in exception_when {
5921                        write!(f, " {when}")?;
5922                    }
5923                }
5924                if *has_end_keyword {
5925                    write!(f, " END")?;
5926                }
5927                Ok(())
5928            }
5929            Statement::Commit {
5930                chain,
5931                end: end_syntax,
5932                modifier,
5933            } => {
5934                if *end_syntax {
5935                    write!(f, "END")?;
5936                    if let Some(modifier) = *modifier {
5937                        write!(f, " {modifier}")?;
5938                    }
5939                    if *chain {
5940                        write!(f, " AND CHAIN")?;
5941                    }
5942                } else {
5943                    write!(f, "COMMIT{}", if *chain { " AND CHAIN" } else { "" })?;
5944                }
5945                Ok(())
5946            }
5947            Statement::Rollback { chain, savepoint } => {
5948                write!(f, "ROLLBACK")?;
5949
5950                if *chain {
5951                    write!(f, " AND CHAIN")?;
5952                }
5953
5954                if let Some(savepoint) = savepoint {
5955                    write!(f, " TO SAVEPOINT {savepoint}")?;
5956                }
5957
5958                Ok(())
5959            }
5960            Statement::CreateSchema {
5961                schema_name,
5962                if_not_exists,
5963                with,
5964                options,
5965                default_collate_spec,
5966                clone,
5967            } => {
5968                write!(
5969                    f,
5970                    "CREATE SCHEMA {if_not_exists}{name}",
5971                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
5972                    name = schema_name
5973                )?;
5974
5975                if let Some(collate) = default_collate_spec {
5976                    write!(f, " DEFAULT COLLATE {collate}")?;
5977                }
5978
5979                if let Some(with) = with {
5980                    write!(f, " WITH ({})", display_comma_separated(with))?;
5981                }
5982
5983                if let Some(options) = options {
5984                    write!(f, " OPTIONS({})", display_comma_separated(options))?;
5985                }
5986
5987                if let Some(clone) = clone {
5988                    write!(f, " CLONE {clone}")?;
5989                }
5990                Ok(())
5991            }
5992            Statement::Assert { condition, message } => {
5993                write!(f, "ASSERT {condition}")?;
5994                if let Some(m) = message {
5995                    write!(f, " AS {m}")?;
5996                }
5997                Ok(())
5998            }
5999            Statement::Grant(grant) => write!(f, "{grant}"),
6000            Statement::Deny(s) => write!(f, "{s}"),
6001            Statement::Revoke(revoke) => write!(f, "{revoke}"),
6002            Statement::Deallocate { name, prepare } => write!(
6003                f,
6004                "DEALLOCATE {prepare}{name}",
6005                prepare = if *prepare { "PREPARE " } else { "" },
6006                name = name,
6007            ),
6008            Statement::Execute {
6009                name,
6010                parameters,
6011                has_parentheses,
6012                immediate,
6013                into,
6014                using,
6015                output,
6016                default,
6017            } => {
6018                let (open, close) = if *has_parentheses {
6019                    // Space before `(` only when there is no name directly preceding it.
6020                    (if name.is_some() { "(" } else { " (" }, ")")
6021                } else {
6022                    (if parameters.is_empty() { "" } else { " " }, "")
6023                };
6024                write!(f, "EXECUTE")?;
6025                if *immediate {
6026                    write!(f, " IMMEDIATE")?;
6027                }
6028                if let Some(name) = name {
6029                    write!(f, " {name}")?;
6030                }
6031                write!(f, "{open}{}{close}", display_comma_separated(parameters),)?;
6032                if !into.is_empty() {
6033                    write!(f, " INTO {}", display_comma_separated(into))?;
6034                }
6035                if !using.is_empty() {
6036                    write!(f, " USING {}", display_comma_separated(using))?;
6037                };
6038                if *output {
6039                    write!(f, " OUTPUT")?;
6040                }
6041                if *default {
6042                    write!(f, " DEFAULT")?;
6043                }
6044                Ok(())
6045            }
6046            Statement::Prepare {
6047                name,
6048                data_types,
6049                statement,
6050            } => {
6051                write!(f, "PREPARE {name} ")?;
6052                if !data_types.is_empty() {
6053                    write!(f, "({}) ", display_comma_separated(data_types))?;
6054                }
6055                write!(f, "AS {statement}")
6056            }
6057            Statement::Comment {
6058                object_type,
6059                object_name,
6060                comment,
6061                if_exists,
6062            } => {
6063                write!(f, "COMMENT ")?;
6064                if *if_exists {
6065                    write!(f, "IF EXISTS ")?
6066                };
6067                write!(f, "ON {object_type} {object_name} IS ")?;
6068                if let Some(c) = comment {
6069                    write!(f, "'{c}'")
6070                } else {
6071                    write!(f, "NULL")
6072                }
6073            }
6074            Statement::Savepoint { name } => {
6075                write!(f, "SAVEPOINT ")?;
6076                write!(f, "{name}")
6077            }
6078            Statement::ReleaseSavepoint { name } => {
6079                write!(f, "RELEASE SAVEPOINT {name}")
6080            }
6081            Statement::Merge(merge) => merge.fmt(f),
6082            Statement::Cache {
6083                table_name,
6084                table_flag,
6085                has_as,
6086                options,
6087                query,
6088            } => {
6089                if let Some(table_flag) = table_flag {
6090                    write!(f, "CACHE {table_flag} TABLE {table_name}")?;
6091                } else {
6092                    write!(f, "CACHE TABLE {table_name}")?;
6093                }
6094
6095                if !options.is_empty() {
6096                    write!(f, " OPTIONS({})", display_comma_separated(options))?;
6097                }
6098
6099                match (*has_as, query) {
6100                    (true, Some(query)) => write!(f, " AS {query}"),
6101                    (true, None) => f.write_str(" AS"),
6102                    (false, Some(query)) => write!(f, " {query}"),
6103                    (false, None) => Ok(()),
6104                }
6105            }
6106            Statement::UNCache {
6107                table_name,
6108                if_exists,
6109            } => {
6110                if *if_exists {
6111                    write!(f, "UNCACHE TABLE IF EXISTS {table_name}")
6112                } else {
6113                    write!(f, "UNCACHE TABLE {table_name}")
6114                }
6115            }
6116            Statement::CreateSequence {
6117                temporary,
6118                if_not_exists,
6119                name,
6120                data_type,
6121                sequence_options,
6122                owned_by,
6123            } => {
6124                let as_type: String = if let Some(dt) = data_type.as_ref() {
6125                    //Cannot use format!(" AS {}", dt), due to format! is not available in --target thumbv6m-none-eabi
6126                    // " AS ".to_owned() + &dt.to_string()
6127                    [" AS ", &dt.to_string()].concat()
6128                } else {
6129                    "".to_string()
6130                };
6131                write!(
6132                    f,
6133                    "CREATE {temporary}SEQUENCE {if_not_exists}{name}{as_type}",
6134                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
6135                    temporary = if *temporary { "TEMPORARY " } else { "" },
6136                    name = name,
6137                    as_type = as_type
6138                )?;
6139                for sequence_option in sequence_options {
6140                    write!(f, "{sequence_option}")?;
6141                }
6142                if let Some(ob) = owned_by.as_ref() {
6143                    write!(f, " OWNED BY {ob}")?;
6144                }
6145                write!(f, "")
6146            }
6147            Statement::CreateStage {
6148                or_replace,
6149                temporary,
6150                if_not_exists,
6151                name,
6152                stage_params,
6153                directory_table_params,
6154                file_format,
6155                copy_options,
6156                comment,
6157                ..
6158            } => {
6159                write!(
6160                    f,
6161                    "CREATE {or_replace}{temp}STAGE {if_not_exists}{name}{stage_params}",
6162                    temp = if *temporary { "TEMPORARY " } else { "" },
6163                    or_replace = if *or_replace { "OR REPLACE " } else { "" },
6164                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
6165                )?;
6166                if !directory_table_params.options.is_empty() {
6167                    write!(f, " DIRECTORY=({directory_table_params})")?;
6168                }
6169                if !file_format.options.is_empty() {
6170                    write!(f, " FILE_FORMAT=({file_format})")?;
6171                }
6172                if !copy_options.options.is_empty() {
6173                    write!(f, " COPY_OPTIONS=({copy_options})")?;
6174                }
6175                if comment.is_some() {
6176                    write!(f, " COMMENT='{}'", comment.as_ref().unwrap())?;
6177                }
6178                Ok(())
6179            }
6180            Statement::CopyIntoSnowflake {
6181                kind,
6182                into,
6183                into_columns,
6184                from_obj,
6185                from_obj_alias,
6186                stage_params,
6187                from_transformations,
6188                from_query,
6189                files,
6190                pattern,
6191                file_format,
6192                copy_options,
6193                validation_mode,
6194                partition,
6195            } => {
6196                write!(f, "COPY INTO {into}")?;
6197                if let Some(into_columns) = into_columns {
6198                    write!(f, " ({})", display_comma_separated(into_columns))?;
6199                }
6200                if let Some(from_transformations) = from_transformations {
6201                    // Data load with transformation
6202                    if let Some(from_stage) = from_obj {
6203                        write!(
6204                            f,
6205                            " FROM (SELECT {} FROM {}{}",
6206                            display_separated(from_transformations, ", "),
6207                            from_stage,
6208                            stage_params
6209                        )?;
6210                    }
6211                    if let Some(from_obj_alias) = from_obj_alias {
6212                        write!(f, " AS {from_obj_alias}")?;
6213                    }
6214                    write!(f, ")")?;
6215                } else if let Some(from_obj) = from_obj {
6216                    // Standard data load
6217                    write!(f, " FROM {from_obj}{stage_params}")?;
6218                    if let Some(from_obj_alias) = from_obj_alias {
6219                        write!(f, " AS {from_obj_alias}")?;
6220                    }
6221                } else if let Some(from_query) = from_query {
6222                    // Data unload from query
6223                    write!(f, " FROM ({from_query})")?;
6224                }
6225
6226                if let Some(files) = files {
6227                    write!(f, " FILES = ('{}')", display_separated(files, "', '"))?;
6228                }
6229                if let Some(pattern) = pattern {
6230                    write!(f, " PATTERN = '{pattern}'")?;
6231                }
6232                if let Some(partition) = partition {
6233                    write!(f, " PARTITION BY {partition}")?;
6234                }
6235                if !file_format.options.is_empty() {
6236                    write!(f, " FILE_FORMAT=({file_format})")?;
6237                }
6238                if !copy_options.options.is_empty() {
6239                    match kind {
6240                        CopyIntoSnowflakeKind::Table => {
6241                            write!(f, " COPY_OPTIONS=({copy_options})")?
6242                        }
6243                        CopyIntoSnowflakeKind::Location => write!(f, " {copy_options}")?,
6244                    }
6245                }
6246                if let Some(validation_mode) = validation_mode {
6247                    write!(f, " VALIDATION_MODE = {validation_mode}")?;
6248                }
6249                Ok(())
6250            }
6251            Statement::CreateType {
6252                name,
6253                representation,
6254            } => {
6255                write!(f, "CREATE TYPE {name}")?;
6256                if let Some(repr) = representation {
6257                    write!(f, " {repr}")?;
6258                }
6259                Ok(())
6260            }
6261            Statement::Pragma { name, value, is_eq } => {
6262                write!(f, "PRAGMA {name}")?;
6263                if value.is_some() {
6264                    let val = value.as_ref().unwrap();
6265                    if *is_eq {
6266                        write!(f, " = {val}")?;
6267                    } else {
6268                        write!(f, "({val})")?;
6269                    }
6270                }
6271                Ok(())
6272            }
6273            Statement::Lock(lock) => lock.fmt(f),
6274            Statement::LockTables { tables } => {
6275                write!(f, "LOCK TABLES {}", display_comma_separated(tables))
6276            }
6277            Statement::UnlockTables => {
6278                write!(f, "UNLOCK TABLES")
6279            }
6280            Statement::Unload {
6281                query,
6282                query_text,
6283                to,
6284                auth,
6285                with,
6286                options,
6287            } => {
6288                write!(f, "UNLOAD(")?;
6289                if let Some(query) = query {
6290                    write!(f, "{query}")?;
6291                }
6292                if let Some(query_text) = query_text {
6293                    write!(f, "'{query_text}'")?;
6294                }
6295                write!(f, ") TO {to}")?;
6296                if let Some(auth) = auth {
6297                    write!(f, " IAM_ROLE {auth}")?;
6298                }
6299                if !with.is_empty() {
6300                    write!(f, " WITH ({})", display_comma_separated(with))?;
6301                }
6302                if !options.is_empty() {
6303                    write!(f, " {}", display_separated(options, " "))?;
6304                }
6305                Ok(())
6306            }
6307            Statement::OptimizeTable {
6308                name,
6309                has_table_keyword,
6310                on_cluster,
6311                partition,
6312                include_final,
6313                deduplicate,
6314                predicate,
6315                zorder,
6316            } => {
6317                write!(f, "OPTIMIZE")?;
6318                if *has_table_keyword {
6319                    write!(f, " TABLE")?;
6320                }
6321                write!(f, " {name}")?;
6322                if let Some(on_cluster) = on_cluster {
6323                    write!(f, " ON CLUSTER {on_cluster}")?;
6324                }
6325                if let Some(partition) = partition {
6326                    write!(f, " {partition}")?;
6327                }
6328                if *include_final {
6329                    write!(f, " FINAL")?;
6330                }
6331                if let Some(deduplicate) = deduplicate {
6332                    write!(f, " {deduplicate}")?;
6333                }
6334                if let Some(predicate) = predicate {
6335                    write!(f, " WHERE {predicate}")?;
6336                }
6337                if let Some(zorder) = zorder {
6338                    write!(f, " ZORDER BY ({})", display_comma_separated(zorder))?;
6339                }
6340                Ok(())
6341            }
6342            Statement::LISTEN { channel } => {
6343                write!(f, "LISTEN {channel}")?;
6344                Ok(())
6345            }
6346            Statement::UNLISTEN { channel } => {
6347                write!(f, "UNLISTEN {channel}")?;
6348                Ok(())
6349            }
6350            Statement::NOTIFY { channel, payload } => {
6351                write!(f, "NOTIFY {channel}")?;
6352                if let Some(payload) = payload {
6353                    write!(f, ", '{payload}'")?;
6354                }
6355                Ok(())
6356            }
6357            Statement::RenameTable(rename_tables) => {
6358                write!(f, "RENAME TABLE {}", display_comma_separated(rename_tables))
6359            }
6360            Statement::RaisError {
6361                message,
6362                severity,
6363                state,
6364                arguments,
6365                options,
6366            } => {
6367                write!(f, "RAISERROR({message}, {severity}, {state}")?;
6368                if !arguments.is_empty() {
6369                    write!(f, ", {}", display_comma_separated(arguments))?;
6370                }
6371                write!(f, ")")?;
6372                if !options.is_empty() {
6373                    write!(f, " WITH {}", display_comma_separated(options))?;
6374                }
6375                Ok(())
6376            }
6377            Statement::Throw(s) => write!(f, "{s}"),
6378            Statement::Print(s) => write!(f, "{s}"),
6379            Statement::WaitFor(s) => write!(f, "{s}"),
6380            Statement::Return(r) => write!(f, "{r}"),
6381            Statement::List(command) => write!(f, "LIST {command}"),
6382            Statement::Remove(command) => write!(f, "REMOVE {command}"),
6383            Statement::ExportData(e) => write!(f, "{e}"),
6384            Statement::CreateUser(s) => write!(f, "{s}"),
6385            Statement::AlterSchema(s) => write!(f, "{s}"),
6386            Statement::Vacuum(s) => write!(f, "{s}"),
6387            Statement::AlterUser(s) => write!(f, "{s}"),
6388            Statement::Reset(s) => write!(f, "{s}"),
6389        }
6390    }
6391}
6392
6393/// Can use to describe options in create sequence or table column type identity
6394/// ```sql
6395/// [ INCREMENT [ BY ] increment ]
6396///     [ MINVALUE minvalue | NO MINVALUE ] [ MAXVALUE maxvalue | NO MAXVALUE ]
6397///     [ START [ WITH ] start ] [ CACHE cache ] [ [ NO ] CYCLE ]
6398/// ```
6399#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6400#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6401#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6402pub enum SequenceOptions {
6403    /// `INCREMENT [BY] <expr>` option; second value indicates presence of `BY` keyword.
6404    IncrementBy(Expr, bool),
6405    /// `MINVALUE <expr>` or `NO MINVALUE`.
6406    MinValue(Option<Expr>),
6407    /// `MAXVALUE <expr>` or `NO MAXVALUE`.
6408    MaxValue(Option<Expr>),
6409    /// `START [WITH] <expr>`; second value indicates presence of `WITH`.
6410    StartWith(Expr, bool),
6411    /// `CACHE <expr>` option.
6412    Cache(Expr),
6413    /// `CYCLE` or `NO CYCLE` option.
6414    Cycle(bool),
6415}
6416
6417impl fmt::Display for SequenceOptions {
6418    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6419        match self {
6420            SequenceOptions::IncrementBy(increment, by) => {
6421                write!(
6422                    f,
6423                    " INCREMENT{by} {increment}",
6424                    by = if *by { " BY" } else { "" },
6425                    increment = increment
6426                )
6427            }
6428            SequenceOptions::MinValue(Some(expr)) => {
6429                write!(f, " MINVALUE {expr}")
6430            }
6431            SequenceOptions::MinValue(None) => {
6432                write!(f, " NO MINVALUE")
6433            }
6434            SequenceOptions::MaxValue(Some(expr)) => {
6435                write!(f, " MAXVALUE {expr}")
6436            }
6437            SequenceOptions::MaxValue(None) => {
6438                write!(f, " NO MAXVALUE")
6439            }
6440            SequenceOptions::StartWith(start, with) => {
6441                write!(
6442                    f,
6443                    " START{with} {start}",
6444                    with = if *with { " WITH" } else { "" },
6445                    start = start
6446                )
6447            }
6448            SequenceOptions::Cache(cache) => {
6449                write!(f, " CACHE {}", *cache)
6450            }
6451            SequenceOptions::Cycle(no) => {
6452                write!(f, " {}CYCLE", if *no { "NO " } else { "" })
6453            }
6454        }
6455    }
6456}
6457
6458/// Assignment for a `SET` statement (name [=|TO] value)
6459#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6460#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6461#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6462pub struct SetAssignment {
6463    /// Optional context scope (e.g., SESSION or LOCAL).
6464    pub scope: Option<ContextModifier>,
6465    /// Assignment target name.
6466    pub name: ObjectName,
6467    /// Assigned expression value.
6468    pub value: Expr,
6469}
6470
6471impl fmt::Display for SetAssignment {
6472    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6473        write!(
6474            f,
6475            "{}{} = {}",
6476            self.scope.map(|s| format!("{s}")).unwrap_or_default(),
6477            self.name,
6478            self.value
6479        )
6480    }
6481}
6482
6483/// Target of a `TRUNCATE TABLE` command
6484///
6485/// Note this is its own struct because `visit_relation` requires an `ObjectName` (not a `Vec<ObjectName>`)
6486#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6487#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6488#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6489pub struct TruncateTableTarget {
6490    /// name of the table being truncated
6491    #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
6492    pub name: ObjectName,
6493    /// Postgres-specific option: explicitly exclude descendants (also default without ONLY)
6494    /// ```sql
6495    /// TRUNCATE TABLE ONLY name
6496    /// ```
6497    /// <https://www.postgresql.org/docs/current/sql-truncate.html>
6498    pub only: bool,
6499    /// Postgres-specific option: asterisk after table name to explicitly indicate descendants
6500    /// ```sql
6501    /// TRUNCATE TABLE name [ * ]
6502    /// ```
6503    /// <https://www.postgresql.org/docs/current/sql-truncate.html>
6504    pub has_asterisk: bool,
6505}
6506
6507impl fmt::Display for TruncateTableTarget {
6508    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6509        if self.only {
6510            write!(f, "ONLY ")?;
6511        };
6512        write!(f, "{}", self.name)?;
6513        if self.has_asterisk {
6514            write!(f, " *")?;
6515        };
6516        Ok(())
6517    }
6518}
6519
6520/// A `LOCK` statement.
6521///
6522/// See <https://www.postgresql.org/docs/current/sql-lock.html>
6523#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6524#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6525#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6526pub struct Lock {
6527    /// List of tables to lock.
6528    pub tables: Vec<LockTableTarget>,
6529    /// Lock mode.
6530    pub lock_mode: Option<LockTableMode>,
6531    /// Whether `NOWAIT` was specified.
6532    pub nowait: bool,
6533}
6534
6535impl fmt::Display for Lock {
6536    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6537        write!(f, "LOCK TABLE {}", display_comma_separated(&self.tables))?;
6538        if let Some(lock_mode) = &self.lock_mode {
6539            write!(f, " IN {lock_mode} MODE")?;
6540        }
6541        if self.nowait {
6542            write!(f, " NOWAIT")?;
6543        }
6544        Ok(())
6545    }
6546}
6547
6548/// Target of a `LOCK TABLE` command
6549///
6550/// See <https://www.postgresql.org/docs/current/sql-lock.html>
6551#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6552#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6553#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6554pub struct LockTableTarget {
6555    /// Name of the table being locked.
6556    #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
6557    pub name: ObjectName,
6558    /// Whether `ONLY` was specified to exclude descendant tables.
6559    pub only: bool,
6560    /// Whether `*` was specified to explicitly include descendant tables.
6561    pub has_asterisk: bool,
6562}
6563
6564impl fmt::Display for LockTableTarget {
6565    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6566        if self.only {
6567            write!(f, "ONLY ")?;
6568        }
6569        write!(f, "{}", self.name)?;
6570        if self.has_asterisk {
6571            write!(f, " *")?;
6572        }
6573        Ok(())
6574    }
6575}
6576
6577/// PostgreSQL lock modes for `LOCK TABLE`.
6578///
6579/// See <https://www.postgresql.org/docs/current/sql-lock.html>
6580#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6581#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6582#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6583pub enum LockTableMode {
6584    /// `ACCESS SHARE`
6585    AccessShare,
6586    /// `ROW SHARE`
6587    RowShare,
6588    /// `ROW EXCLUSIVE`
6589    RowExclusive,
6590    /// `SHARE UPDATE EXCLUSIVE`
6591    ShareUpdateExclusive,
6592    /// `SHARE`
6593    Share,
6594    /// `SHARE ROW EXCLUSIVE`
6595    ShareRowExclusive,
6596    /// `EXCLUSIVE`
6597    Exclusive,
6598    /// `ACCESS EXCLUSIVE`
6599    AccessExclusive,
6600}
6601
6602impl fmt::Display for LockTableMode {
6603    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
6604        let text = match self {
6605            Self::AccessShare => "ACCESS SHARE",
6606            Self::RowShare => "ROW SHARE",
6607            Self::RowExclusive => "ROW EXCLUSIVE",
6608            Self::ShareUpdateExclusive => "SHARE UPDATE EXCLUSIVE",
6609            Self::Share => "SHARE",
6610            Self::ShareRowExclusive => "SHARE ROW EXCLUSIVE",
6611            Self::Exclusive => "EXCLUSIVE",
6612            Self::AccessExclusive => "ACCESS EXCLUSIVE",
6613        };
6614        write!(f, "{text}")
6615    }
6616}
6617
6618/// PostgreSQL identity option for TRUNCATE table
6619/// [ RESTART IDENTITY | CONTINUE IDENTITY ]
6620#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6621#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6622#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6623pub enum TruncateIdentityOption {
6624    /// Restart identity values (RESTART IDENTITY).
6625    Restart,
6626    /// Continue identity values (CONTINUE IDENTITY).
6627    Continue,
6628}
6629
6630/// Cascade/restrict option for Postgres TRUNCATE table, MySQL GRANT/REVOKE, etc.
6631/// [ CASCADE | RESTRICT ]
6632#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6633#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6634#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6635pub enum CascadeOption {
6636    /// Apply cascading action (e.g., CASCADE).
6637    Cascade,
6638    /// Restrict the action (e.g., RESTRICT).
6639    Restrict,
6640}
6641
6642impl Display for CascadeOption {
6643    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6644        match self {
6645            CascadeOption::Cascade => write!(f, "CASCADE"),
6646            CascadeOption::Restrict => write!(f, "RESTRICT"),
6647        }
6648    }
6649}
6650
6651/// Transaction started with [ TRANSACTION | WORK | TRAN ]
6652#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6653#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6654#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6655pub enum BeginTransactionKind {
6656    /// Standard `TRANSACTION` keyword.
6657    Transaction,
6658    /// Alternate `WORK` keyword.
6659    Work,
6660    /// MSSQL shorthand `TRAN` keyword.
6661    /// See <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/begin-transaction-transact-sql>
6662    Tran,
6663}
6664
6665impl Display for BeginTransactionKind {
6666    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6667        match self {
6668            BeginTransactionKind::Transaction => write!(f, "TRANSACTION"),
6669            BeginTransactionKind::Work => write!(f, "WORK"),
6670            BeginTransactionKind::Tran => write!(f, "TRAN"),
6671        }
6672    }
6673}
6674
6675/// Can use to describe options in  create sequence or table column type identity
6676/// [ MINVALUE minvalue | NO MINVALUE ] [ MAXVALUE maxvalue | NO MAXVALUE ]
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 enum MinMaxValue {
6681    /// Clause is not specified.
6682    Empty,
6683    /// NO MINVALUE / NO MAXVALUE.
6684    None,
6685    /// `MINVALUE <expr>` / `MAXVALUE <expr>`.
6686    Some(Expr),
6687}
6688
6689#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6690#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6691#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6692#[non_exhaustive]
6693/// Behavior to apply for `INSERT` when a conflict occurs.
6694pub enum OnInsert {
6695    /// ON DUPLICATE KEY UPDATE (MySQL when the key already exists, then execute an update instead)
6696    DuplicateKeyUpdate(Vec<Assignment>),
6697    /// ON CONFLICT is a PostgreSQL and Sqlite extension
6698    OnConflict(OnConflict),
6699}
6700
6701#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6702#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6703#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6704/// Optional aliases for `INSERT` targets: row alias and optional column aliases.
6705pub struct InsertAliases {
6706    /// Row alias (table-style alias) for the inserted values.
6707    pub row_alias: ObjectName,
6708    /// Optional list of column aliases for the inserted values.
6709    pub col_aliases: Option<Vec<Ident>>,
6710}
6711
6712#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6713#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6714#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6715/// Optional alias for an `INSERT` table; i.e. the table to be inserted into
6716pub struct TableAliasWithoutColumns {
6717    /// `true` if the aliases was explicitly introduced with the "AS" keyword
6718    pub explicit: bool,
6719    /// the alias name itself
6720    pub alias: Ident,
6721}
6722
6723#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6724#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6725#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6726/// `ON CONFLICT` clause representation.
6727pub struct OnConflict {
6728    /// Optional conflict target specifying columns or constraint.
6729    pub conflict_target: Option<ConflictTarget>,
6730    /// Action to take when a conflict occurs.
6731    pub action: OnConflictAction,
6732}
6733#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6734#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6735#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6736/// Target specification for an `ON CONFLICT` clause.
6737pub enum ConflictTarget {
6738    /// Target specified as a list of columns.
6739    Columns(Vec<Ident>),
6740    /// Target specified as a named constraint.
6741    OnConstraint(ObjectName),
6742}
6743#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6744#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6745#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6746/// Action to perform when an `ON CONFLICT` target is matched.
6747pub enum OnConflictAction {
6748    /// Do nothing on conflict.
6749    DoNothing,
6750    /// Perform an update on conflict.
6751    DoUpdate(DoUpdate),
6752}
6753
6754#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6755#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6756#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6757/// Details for `DO UPDATE` action of an `ON CONFLICT` clause.
6758pub struct DoUpdate {
6759    /// Column assignments to perform on update.
6760    pub assignments: Vec<Assignment>,
6761    /// Optional WHERE clause limiting the update.
6762    pub selection: Option<Expr>,
6763}
6764
6765impl fmt::Display for OnInsert {
6766    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6767        match self {
6768            Self::DuplicateKeyUpdate(expr) => write!(
6769                f,
6770                " ON DUPLICATE KEY UPDATE {}",
6771                display_comma_separated(expr)
6772            ),
6773            Self::OnConflict(o) => write!(f, "{o}"),
6774        }
6775    }
6776}
6777impl fmt::Display for OnConflict {
6778    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6779        write!(f, " ON CONFLICT")?;
6780        if let Some(target) = &self.conflict_target {
6781            write!(f, "{target}")?;
6782        }
6783        write!(f, " {}", self.action)
6784    }
6785}
6786impl fmt::Display for ConflictTarget {
6787    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6788        match self {
6789            ConflictTarget::Columns(cols) => write!(f, "({})", display_comma_separated(cols)),
6790            ConflictTarget::OnConstraint(name) => write!(f, " ON CONSTRAINT {name}"),
6791        }
6792    }
6793}
6794impl fmt::Display for OnConflictAction {
6795    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6796        match self {
6797            Self::DoNothing => write!(f, "DO NOTHING"),
6798            Self::DoUpdate(do_update) => {
6799                write!(f, "DO UPDATE")?;
6800                if !do_update.assignments.is_empty() {
6801                    write!(
6802                        f,
6803                        " SET {}",
6804                        display_comma_separated(&do_update.assignments)
6805                    )?;
6806                }
6807                if let Some(selection) = &do_update.selection {
6808                    write!(f, " WHERE {selection}")?;
6809                }
6810                Ok(())
6811            }
6812        }
6813    }
6814}
6815
6816/// Privileges granted in a GRANT statement or revoked in a REVOKE statement.
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 Privileges {
6821    /// All privileges applicable to the object type
6822    All {
6823        /// Optional keyword from the spec, ignored in practice
6824        with_privileges_keyword: bool,
6825    },
6826    /// Specific privileges (e.g. `SELECT`, `INSERT`)
6827    Actions(Vec<Action>),
6828}
6829
6830impl fmt::Display for Privileges {
6831    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6832        match self {
6833            Privileges::All {
6834                with_privileges_keyword,
6835            } => {
6836                write!(
6837                    f,
6838                    "ALL{}",
6839                    if *with_privileges_keyword {
6840                        " PRIVILEGES"
6841                    } else {
6842                        ""
6843                    }
6844                )
6845            }
6846            Privileges::Actions(actions) => {
6847                write!(f, "{}", display_comma_separated(actions))
6848            }
6849        }
6850    }
6851}
6852
6853/// Specific direction for FETCH statement
6854#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6855#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6856#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6857pub enum FetchDirection {
6858    /// Fetch a specific count of rows.
6859    Count {
6860        /// The limit value for the count.
6861        limit: ValueWithSpan,
6862    },
6863    /// Fetch the next row.
6864    Next,
6865    /// Fetch the prior row.
6866    Prior,
6867    /// Fetch the first row.
6868    First,
6869    /// Fetch the last row.
6870    Last,
6871    /// Fetch an absolute row by index.
6872    Absolute {
6873        /// The absolute index value.
6874        limit: ValueWithSpan,
6875    },
6876    /// Fetch a row relative to the current position.
6877    Relative {
6878        /// The relative offset value.
6879        limit: ValueWithSpan,
6880    },
6881    /// Fetch all rows.
6882    All,
6883    // FORWARD
6884    // FORWARD count
6885    /// Fetch forward by an optional limit.
6886    Forward {
6887        /// Optional forward limit.
6888        limit: Option<ValueWithSpan>,
6889    },
6890    /// Fetch all forward rows.
6891    ForwardAll,
6892    // BACKWARD
6893    // BACKWARD count
6894    /// Fetch backward by an optional limit.
6895    Backward {
6896        /// Optional backward limit.
6897        limit: Option<ValueWithSpan>,
6898    },
6899    /// Fetch all backward rows.
6900    BackwardAll,
6901}
6902
6903impl fmt::Display for FetchDirection {
6904    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6905        match self {
6906            FetchDirection::Count { limit } => f.write_str(&limit.to_string())?,
6907            FetchDirection::Next => f.write_str("NEXT")?,
6908            FetchDirection::Prior => f.write_str("PRIOR")?,
6909            FetchDirection::First => f.write_str("FIRST")?,
6910            FetchDirection::Last => f.write_str("LAST")?,
6911            FetchDirection::Absolute { limit } => {
6912                f.write_str("ABSOLUTE ")?;
6913                f.write_str(&limit.to_string())?;
6914            }
6915            FetchDirection::Relative { limit } => {
6916                f.write_str("RELATIVE ")?;
6917                f.write_str(&limit.to_string())?;
6918            }
6919            FetchDirection::All => f.write_str("ALL")?,
6920            FetchDirection::Forward { limit } => {
6921                f.write_str("FORWARD")?;
6922
6923                if let Some(l) = limit {
6924                    f.write_str(" ")?;
6925                    f.write_str(&l.to_string())?;
6926                }
6927            }
6928            FetchDirection::ForwardAll => f.write_str("FORWARD ALL")?,
6929            FetchDirection::Backward { limit } => {
6930                f.write_str("BACKWARD")?;
6931
6932                if let Some(l) = limit {
6933                    f.write_str(" ")?;
6934                    f.write_str(&l.to_string())?;
6935                }
6936            }
6937            FetchDirection::BackwardAll => f.write_str("BACKWARD ALL")?,
6938        };
6939
6940        Ok(())
6941    }
6942}
6943
6944/// The "position" for a FETCH statement.
6945///
6946/// [MsSql](https://learn.microsoft.com/en-us/sql/t-sql/language-elements/fetch-transact-sql)
6947#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6948#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6949#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6950pub enum FetchPosition {
6951    /// Use `FROM <pos>` position specifier.
6952    From,
6953    /// Use `IN <pos>` position specifier.
6954    In,
6955}
6956
6957impl fmt::Display for FetchPosition {
6958    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6959        match self {
6960            FetchPosition::From => f.write_str("FROM")?,
6961            FetchPosition::In => f.write_str("IN")?,
6962        };
6963
6964        Ok(())
6965    }
6966}
6967
6968/// A privilege on a database object (table, sequence, etc.).
6969#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6970#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6971#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6972pub enum Action {
6973    /// Add a search optimization.
6974    AddSearchOptimization,
6975    /// Apply an `APPLY` operation with a specific type.
6976    Apply {
6977        /// The type of apply operation.
6978        apply_type: ActionApplyType,
6979    },
6980    /// Apply a budget operation.
6981    ApplyBudget,
6982    /// Attach a listing.
6983    AttachListing,
6984    /// Attach a policy.
6985    AttachPolicy,
6986    /// Audit operation.
6987    Audit,
6988    /// Bind a service endpoint.
6989    BindServiceEndpoint,
6990    /// Connect permission.
6991    Connect,
6992    /// Create action, optionally specifying an object type.
6993    Create {
6994        /// Optional object type to create.
6995        obj_type: Option<ActionCreateObjectType>,
6996    },
6997    /// Actions related to database roles.
6998    DatabaseRole {
6999        /// The role name.
7000        role: ObjectName,
7001    },
7002    /// Delete permission.
7003    Delete,
7004    /// Drop permission.
7005    Drop,
7006    /// Evolve schema permission.
7007    EvolveSchema,
7008    /// Exec action (execute) with optional object type.
7009    Exec {
7010        /// Optional execute object type.
7011        obj_type: Option<ActionExecuteObjectType>,
7012    },
7013    /// Execute action with optional object type.
7014    Execute {
7015        /// Optional execute object type.
7016        obj_type: Option<ActionExecuteObjectType>,
7017    },
7018    /// Failover operation.
7019    Failover,
7020    /// Use imported privileges.
7021    ImportedPrivileges,
7022    /// Import a share.
7023    ImportShare,
7024    /// Insert rows with optional column list.
7025    Insert {
7026        /// Optional list of target columns for insert.
7027        columns: Option<Vec<Ident>>,
7028    },
7029    /// Manage operation with a specific manage type.
7030    Manage {
7031        /// The specific manage sub-type.
7032        manage_type: ActionManageType,
7033    },
7034    /// Manage releases.
7035    ManageReleases,
7036    /// Manage versions.
7037    ManageVersions,
7038    /// Modify operation with an optional modify type.
7039    Modify {
7040        /// The optional modify sub-type.
7041        modify_type: Option<ActionModifyType>,
7042    },
7043    /// Monitor operation with an optional monitor type.
7044    Monitor {
7045        /// The optional monitor sub-type.
7046        monitor_type: Option<ActionMonitorType>,
7047    },
7048    /// Operate permission.
7049    Operate,
7050    /// Override share restrictions.
7051    OverrideShareRestrictions,
7052    /// Ownership permission.
7053    Ownership,
7054    /// Purchase a data exchange listing.
7055    PurchaseDataExchangeListing,
7056
7057    /// Read access.
7058    Read,
7059    /// Read session-level access.
7060    ReadSession,
7061    /// References with optional column list.
7062    References {
7063        /// Optional list of referenced column identifiers.
7064        columns: Option<Vec<Ident>>,
7065    },
7066    /// Replication permission.
7067    Replicate,
7068    /// Resolve all references.
7069    ResolveAll,
7070    /// Role-related permission with target role name.
7071    Role {
7072        /// The target role name.
7073        role: ObjectName,
7074    },
7075    /// Select permission with optional column list.
7076    Select {
7077        /// Optional list of selected columns.
7078        columns: Option<Vec<Ident>>,
7079    },
7080    /// Temporary object permission.
7081    Temporary,
7082    /// Trigger-related permission.
7083    Trigger,
7084    /// Truncate permission.
7085    Truncate,
7086    /// Update permission with optional affected columns.
7087    Update {
7088        /// Optional list of columns affected by update.
7089        columns: Option<Vec<Ident>>,
7090    },
7091    /// Usage permission.
7092    Usage,
7093}
7094
7095impl fmt::Display for Action {
7096    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7097        match self {
7098            Action::AddSearchOptimization => f.write_str("ADD SEARCH OPTIMIZATION")?,
7099            Action::Apply { apply_type } => write!(f, "APPLY {apply_type}")?,
7100            Action::ApplyBudget => f.write_str("APPLYBUDGET")?,
7101            Action::AttachListing => f.write_str("ATTACH LISTING")?,
7102            Action::AttachPolicy => f.write_str("ATTACH POLICY")?,
7103            Action::Audit => f.write_str("AUDIT")?,
7104            Action::BindServiceEndpoint => f.write_str("BIND SERVICE ENDPOINT")?,
7105            Action::Connect => f.write_str("CONNECT")?,
7106            Action::Create { obj_type } => {
7107                f.write_str("CREATE")?;
7108                if let Some(obj_type) = obj_type {
7109                    write!(f, " {obj_type}")?
7110                }
7111            }
7112            Action::DatabaseRole { role } => write!(f, "DATABASE ROLE {role}")?,
7113            Action::Delete => f.write_str("DELETE")?,
7114            Action::Drop => f.write_str("DROP")?,
7115            Action::EvolveSchema => f.write_str("EVOLVE SCHEMA")?,
7116            Action::Exec { obj_type } => {
7117                f.write_str("EXEC")?;
7118                if let Some(obj_type) = obj_type {
7119                    write!(f, " {obj_type}")?
7120                }
7121            }
7122            Action::Execute { obj_type } => {
7123                f.write_str("EXECUTE")?;
7124                if let Some(obj_type) = obj_type {
7125                    write!(f, " {obj_type}")?
7126                }
7127            }
7128            Action::Failover => f.write_str("FAILOVER")?,
7129            Action::ImportedPrivileges => f.write_str("IMPORTED PRIVILEGES")?,
7130            Action::ImportShare => f.write_str("IMPORT SHARE")?,
7131            Action::Insert { .. } => f.write_str("INSERT")?,
7132            Action::Manage { manage_type } => write!(f, "MANAGE {manage_type}")?,
7133            Action::ManageReleases => f.write_str("MANAGE RELEASES")?,
7134            Action::ManageVersions => f.write_str("MANAGE VERSIONS")?,
7135            Action::Modify { modify_type } => {
7136                write!(f, "MODIFY")?;
7137                if let Some(modify_type) = modify_type {
7138                    write!(f, " {modify_type}")?;
7139                }
7140            }
7141            Action::Monitor { monitor_type } => {
7142                write!(f, "MONITOR")?;
7143                if let Some(monitor_type) = monitor_type {
7144                    write!(f, " {monitor_type}")?
7145                }
7146            }
7147            Action::Operate => f.write_str("OPERATE")?,
7148            Action::OverrideShareRestrictions => f.write_str("OVERRIDE SHARE RESTRICTIONS")?,
7149            Action::Ownership => f.write_str("OWNERSHIP")?,
7150            Action::PurchaseDataExchangeListing => f.write_str("PURCHASE DATA EXCHANGE LISTING")?,
7151            Action::Read => f.write_str("READ")?,
7152            Action::ReadSession => f.write_str("READ SESSION")?,
7153            Action::References { .. } => f.write_str("REFERENCES")?,
7154            Action::Replicate => f.write_str("REPLICATE")?,
7155            Action::ResolveAll => f.write_str("RESOLVE ALL")?,
7156            Action::Role { role } => write!(f, "ROLE {role}")?,
7157            Action::Select { .. } => f.write_str("SELECT")?,
7158            Action::Temporary => f.write_str("TEMPORARY")?,
7159            Action::Trigger => f.write_str("TRIGGER")?,
7160            Action::Truncate => f.write_str("TRUNCATE")?,
7161            Action::Update { .. } => f.write_str("UPDATE")?,
7162            Action::Usage => f.write_str("USAGE")?,
7163        };
7164        match self {
7165            Action::Insert { columns }
7166            | Action::References { columns }
7167            | Action::Select { columns }
7168            | Action::Update { columns } => {
7169                if let Some(columns) = columns {
7170                    write!(f, " ({})", display_comma_separated(columns))?;
7171                }
7172            }
7173            _ => (),
7174        };
7175        Ok(())
7176    }
7177}
7178
7179#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7180#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7181#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7182/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
7183/// under `globalPrivileges` in the `CREATE` privilege.
7184pub enum ActionCreateObjectType {
7185    /// An account-level object.
7186    Account,
7187    /// An application object.
7188    Application,
7189    /// An application package object.
7190    ApplicationPackage,
7191    /// A compute pool object.
7192    ComputePool,
7193    /// A data exchange listing.
7194    DataExchangeListing,
7195    /// A database object.
7196    Database,
7197    /// An external volume object.
7198    ExternalVolume,
7199    /// A failover group object.
7200    FailoverGroup,
7201    /// An integration object.
7202    Integration,
7203    /// A network policy object.
7204    NetworkPolicy,
7205    /// An organization listing.
7206    OrganiationListing,
7207    /// A replication group object.
7208    ReplicationGroup,
7209    /// A role object.
7210    Role,
7211    /// A schema object.
7212    Schema,
7213    /// A share object.
7214    Share,
7215    /// A user object.
7216    User,
7217    /// A warehouse object.
7218    Warehouse,
7219}
7220
7221impl fmt::Display for ActionCreateObjectType {
7222    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7223        match self {
7224            ActionCreateObjectType::Account => write!(f, "ACCOUNT"),
7225            ActionCreateObjectType::Application => write!(f, "APPLICATION"),
7226            ActionCreateObjectType::ApplicationPackage => write!(f, "APPLICATION PACKAGE"),
7227            ActionCreateObjectType::ComputePool => write!(f, "COMPUTE POOL"),
7228            ActionCreateObjectType::DataExchangeListing => write!(f, "DATA EXCHANGE LISTING"),
7229            ActionCreateObjectType::Database => write!(f, "DATABASE"),
7230            ActionCreateObjectType::ExternalVolume => write!(f, "EXTERNAL VOLUME"),
7231            ActionCreateObjectType::FailoverGroup => write!(f, "FAILOVER GROUP"),
7232            ActionCreateObjectType::Integration => write!(f, "INTEGRATION"),
7233            ActionCreateObjectType::NetworkPolicy => write!(f, "NETWORK POLICY"),
7234            ActionCreateObjectType::OrganiationListing => write!(f, "ORGANIZATION LISTING"),
7235            ActionCreateObjectType::ReplicationGroup => write!(f, "REPLICATION GROUP"),
7236            ActionCreateObjectType::Role => write!(f, "ROLE"),
7237            ActionCreateObjectType::Schema => write!(f, "SCHEMA"),
7238            ActionCreateObjectType::Share => write!(f, "SHARE"),
7239            ActionCreateObjectType::User => write!(f, "USER"),
7240            ActionCreateObjectType::Warehouse => write!(f, "WAREHOUSE"),
7241        }
7242    }
7243}
7244
7245#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7246#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7247#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7248/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
7249/// under `globalPrivileges` in the `APPLY` privilege.
7250pub enum ActionApplyType {
7251    /// Apply an aggregation policy.
7252    AggregationPolicy,
7253    /// Apply an authentication policy.
7254    AuthenticationPolicy,
7255    /// Apply a join policy.
7256    JoinPolicy,
7257    /// Apply a masking policy.
7258    MaskingPolicy,
7259    /// Apply a packages policy.
7260    PackagesPolicy,
7261    /// Apply a password policy.
7262    PasswordPolicy,
7263    /// Apply a projection policy.
7264    ProjectionPolicy,
7265    /// Apply a row access policy.
7266    RowAccessPolicy,
7267    /// Apply a session policy.
7268    SessionPolicy,
7269    /// Apply a tag.
7270    Tag,
7271}
7272
7273impl fmt::Display for ActionApplyType {
7274    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7275        match self {
7276            ActionApplyType::AggregationPolicy => write!(f, "AGGREGATION POLICY"),
7277            ActionApplyType::AuthenticationPolicy => write!(f, "AUTHENTICATION POLICY"),
7278            ActionApplyType::JoinPolicy => write!(f, "JOIN POLICY"),
7279            ActionApplyType::MaskingPolicy => write!(f, "MASKING POLICY"),
7280            ActionApplyType::PackagesPolicy => write!(f, "PACKAGES POLICY"),
7281            ActionApplyType::PasswordPolicy => write!(f, "PASSWORD POLICY"),
7282            ActionApplyType::ProjectionPolicy => write!(f, "PROJECTION POLICY"),
7283            ActionApplyType::RowAccessPolicy => write!(f, "ROW ACCESS POLICY"),
7284            ActionApplyType::SessionPolicy => write!(f, "SESSION POLICY"),
7285            ActionApplyType::Tag => write!(f, "TAG"),
7286        }
7287    }
7288}
7289
7290#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7291#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7292#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7293/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
7294/// under `globalPrivileges` in the `EXECUTE` privilege.
7295pub enum ActionExecuteObjectType {
7296    /// Alert object.
7297    Alert,
7298    /// Data metric function object.
7299    DataMetricFunction,
7300    /// Managed alert object.
7301    ManagedAlert,
7302    /// Managed task object.
7303    ManagedTask,
7304    /// Task object.
7305    Task,
7306}
7307
7308impl fmt::Display for ActionExecuteObjectType {
7309    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7310        match self {
7311            ActionExecuteObjectType::Alert => write!(f, "ALERT"),
7312            ActionExecuteObjectType::DataMetricFunction => write!(f, "DATA METRIC FUNCTION"),
7313            ActionExecuteObjectType::ManagedAlert => write!(f, "MANAGED ALERT"),
7314            ActionExecuteObjectType::ManagedTask => write!(f, "MANAGED TASK"),
7315            ActionExecuteObjectType::Task => write!(f, "TASK"),
7316        }
7317    }
7318}
7319
7320#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7321#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7322#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7323/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
7324/// under `globalPrivileges` in the `MANAGE` privilege.
7325pub enum ActionManageType {
7326    /// Account support cases management.
7327    AccountSupportCases,
7328    /// Event sharing management.
7329    EventSharing,
7330    /// Grants management.
7331    Grants,
7332    /// Listing auto-fulfillment management.
7333    ListingAutoFulfillment,
7334    /// Organization support cases management.
7335    OrganizationSupportCases,
7336    /// User support cases management.
7337    UserSupportCases,
7338    /// Warehouses management.
7339    Warehouses,
7340}
7341
7342impl fmt::Display for ActionManageType {
7343    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7344        match self {
7345            ActionManageType::AccountSupportCases => write!(f, "ACCOUNT SUPPORT CASES"),
7346            ActionManageType::EventSharing => write!(f, "EVENT SHARING"),
7347            ActionManageType::Grants => write!(f, "GRANTS"),
7348            ActionManageType::ListingAutoFulfillment => write!(f, "LISTING AUTO FULFILLMENT"),
7349            ActionManageType::OrganizationSupportCases => write!(f, "ORGANIZATION SUPPORT CASES"),
7350            ActionManageType::UserSupportCases => write!(f, "USER SUPPORT CASES"),
7351            ActionManageType::Warehouses => write!(f, "WAREHOUSES"),
7352        }
7353    }
7354}
7355
7356#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7357#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7358#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7359/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
7360/// under `globalPrivileges` in the `MODIFY` privilege.
7361pub enum ActionModifyType {
7362    /// Modify log level.
7363    LogLevel,
7364    /// Modify trace level.
7365    TraceLevel,
7366    /// Modify session log level.
7367    SessionLogLevel,
7368    /// Modify session trace level.
7369    SessionTraceLevel,
7370}
7371
7372impl fmt::Display for ActionModifyType {
7373    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7374        match self {
7375            ActionModifyType::LogLevel => write!(f, "LOG LEVEL"),
7376            ActionModifyType::TraceLevel => write!(f, "TRACE LEVEL"),
7377            ActionModifyType::SessionLogLevel => write!(f, "SESSION LOG LEVEL"),
7378            ActionModifyType::SessionTraceLevel => write!(f, "SESSION TRACE LEVEL"),
7379        }
7380    }
7381}
7382
7383#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7384#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7385#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7386/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
7387/// under `globalPrivileges` in the `MONITOR` privilege.
7388pub enum ActionMonitorType {
7389    /// Monitor execution.
7390    Execution,
7391    /// Monitor security.
7392    Security,
7393    /// Monitor usage.
7394    Usage,
7395}
7396
7397impl fmt::Display for ActionMonitorType {
7398    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7399        match self {
7400            ActionMonitorType::Execution => write!(f, "EXECUTION"),
7401            ActionMonitorType::Security => write!(f, "SECURITY"),
7402            ActionMonitorType::Usage => write!(f, "USAGE"),
7403        }
7404    }
7405}
7406
7407/// The principal that receives the privileges
7408#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7409#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7410#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7411pub struct Grantee {
7412    /// The category/type of grantee (role, user, share, etc.).
7413    pub grantee_type: GranteesType,
7414    /// Optional name of the grantee (identifier or user@host).
7415    pub name: Option<GranteeName>,
7416}
7417
7418impl fmt::Display for Grantee {
7419    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7420        match self.grantee_type {
7421            GranteesType::Role => {
7422                write!(f, "ROLE ")?;
7423            }
7424            GranteesType::Share => {
7425                write!(f, "SHARE ")?;
7426            }
7427            GranteesType::User => {
7428                write!(f, "USER ")?;
7429            }
7430            GranteesType::Group => {
7431                write!(f, "GROUP ")?;
7432            }
7433            GranteesType::Public => {
7434                write!(f, "PUBLIC ")?;
7435            }
7436            GranteesType::DatabaseRole => {
7437                write!(f, "DATABASE ROLE ")?;
7438            }
7439            GranteesType::Application => {
7440                write!(f, "APPLICATION ")?;
7441            }
7442            GranteesType::ApplicationRole => {
7443                write!(f, "APPLICATION ROLE ")?;
7444            }
7445            GranteesType::None => (),
7446        }
7447        if let Some(ref name) = self.name {
7448            name.fmt(f)?;
7449        }
7450        Ok(())
7451    }
7452}
7453
7454#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7455#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7456#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7457/// The kind of principal receiving privileges.
7458pub enum GranteesType {
7459    /// A role principal.
7460    Role,
7461    /// A share principal.
7462    Share,
7463    /// A user principal.
7464    User,
7465    /// A group principal.
7466    Group,
7467    /// The public principal.
7468    Public,
7469    /// A database role principal.
7470    DatabaseRole,
7471    /// An application principal.
7472    Application,
7473    /// An application role principal.
7474    ApplicationRole,
7475    /// No specific principal (e.g. `NONE`).
7476    None,
7477}
7478
7479/// Users/roles designated in a GRANT/REVOKE
7480#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7481#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7482#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7483pub enum GranteeName {
7484    /// A bare identifier
7485    ObjectName(ObjectName),
7486    /// A MySQL user/host pair such as 'root'@'%'
7487    UserHost {
7488        /// The user identifier portion.
7489        user: Ident,
7490        /// The host identifier portion.
7491        host: Ident,
7492    },
7493}
7494
7495impl fmt::Display for GranteeName {
7496    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7497        match self {
7498            GranteeName::ObjectName(name) => name.fmt(f),
7499            GranteeName::UserHost { user, host } => {
7500                write!(f, "{user}@{host}")
7501            }
7502        }
7503    }
7504}
7505
7506/// Objects on which privileges are granted in a GRANT statement.
7507#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7508#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7509#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7510pub enum GrantObjects {
7511    /// Grant privileges on `ALL SEQUENCES IN SCHEMA <schema_name> [, ...]`
7512    AllSequencesInSchema {
7513        /// The target schema names.
7514        schemas: Vec<ObjectName>,
7515    },
7516    /// Grant privileges on `ALL TABLES IN SCHEMA <schema_name> [, ...]`
7517    AllTablesInSchema {
7518        /// The target schema names.
7519        schemas: Vec<ObjectName>,
7520    },
7521    /// Grant privileges on `ALL VIEWS IN SCHEMA <schema_name> [, ...]`
7522    AllViewsInSchema {
7523        /// The target schema names.
7524        schemas: Vec<ObjectName>,
7525    },
7526    /// Grant privileges on `ALL MATERIALIZED VIEWS IN SCHEMA <schema_name> [, ...]`
7527    AllMaterializedViewsInSchema {
7528        /// The target schema names.
7529        schemas: Vec<ObjectName>,
7530    },
7531    /// Grant privileges on `ALL EXTERNAL TABLES IN SCHEMA <schema_name> [, ...]`
7532    AllExternalTablesInSchema {
7533        /// The target schema names.
7534        schemas: Vec<ObjectName>,
7535    },
7536    /// Grant privileges on `ALL FUNCTIONS IN SCHEMA <schema_name> [, ...]`
7537    AllFunctionsInSchema {
7538        /// The target schema names.
7539        schemas: Vec<ObjectName>,
7540    },
7541    /// Grant privileges on `FUTURE SCHEMAS IN DATABASE <database_name> [, ...]`
7542    FutureSchemasInDatabase {
7543        /// The target database names.
7544        databases: Vec<ObjectName>,
7545    },
7546    /// Grant privileges on `FUTURE TABLES IN SCHEMA <schema_name> [, ...]`
7547    FutureTablesInSchema {
7548        /// The target schema names.
7549        schemas: Vec<ObjectName>,
7550    },
7551    /// Grant privileges on `FUTURE VIEWS IN SCHEMA <schema_name> [, ...]`
7552    FutureViewsInSchema {
7553        /// The target schema names.
7554        schemas: Vec<ObjectName>,
7555    },
7556    /// Grant privileges on `FUTURE EXTERNAL TABLES IN SCHEMA <schema_name> [, ...]`
7557    FutureExternalTablesInSchema {
7558        /// The target schema names.
7559        schemas: Vec<ObjectName>,
7560    },
7561    /// Grant privileges on `FUTURE MATERIALIZED VIEWS IN SCHEMA <schema_name> [, ...]`
7562    FutureMaterializedViewsInSchema {
7563        /// The target schema names.
7564        schemas: Vec<ObjectName>,
7565    },
7566    /// Grant privileges on `FUTURE SEQUENCES IN SCHEMA <schema_name> [, ...]`
7567    FutureSequencesInSchema {
7568        /// The target schema names.
7569        schemas: Vec<ObjectName>,
7570    },
7571    /// Grant privileges on specific databases
7572    Databases(Vec<ObjectName>),
7573    /// Grant privileges on specific schemas
7574    Schemas(Vec<ObjectName>),
7575    /// Grant privileges on specific sequences
7576    Sequences(Vec<ObjectName>),
7577    /// Grant privileges on specific tables
7578    Tables(Vec<ObjectName>),
7579    /// Grant privileges on specific views
7580    Views(Vec<ObjectName>),
7581    /// Grant privileges on specific warehouses
7582    Warehouses(Vec<ObjectName>),
7583    /// Grant privileges on specific integrations
7584    Integrations(Vec<ObjectName>),
7585    /// Grant privileges on resource monitors
7586    ResourceMonitors(Vec<ObjectName>),
7587    /// Grant privileges on users
7588    Users(Vec<ObjectName>),
7589    /// Grant privileges on compute pools
7590    ComputePools(Vec<ObjectName>),
7591    /// Grant privileges on connections
7592    Connections(Vec<ObjectName>),
7593    /// Grant privileges on failover groups
7594    FailoverGroup(Vec<ObjectName>),
7595    /// Grant privileges on replication group
7596    ReplicationGroup(Vec<ObjectName>),
7597    /// Grant privileges on external volumes
7598    ExternalVolumes(Vec<ObjectName>),
7599    /// Grant privileges on a procedure. In dialects that
7600    /// support overloading, the argument types must be specified.
7601    ///
7602    /// For example:
7603    /// `GRANT USAGE ON PROCEDURE foo(varchar) TO ROLE role1`
7604    Procedure {
7605        /// The procedure name.
7606        name: ObjectName,
7607        /// Optional argument types for overloaded procedures.
7608        arg_types: Vec<DataType>,
7609    },
7610
7611    /// Grant privileges on a function. In dialects that
7612    /// support overloading, the argument types must be specified.
7613    ///
7614    /// For example:
7615    /// `GRANT USAGE ON FUNCTION foo(varchar) TO ROLE role1`
7616    Function {
7617        /// The function name.
7618        name: ObjectName,
7619        /// Optional argument types for overloaded functions.
7620        arg_types: Vec<DataType>,
7621    },
7622}
7623
7624impl fmt::Display for GrantObjects {
7625    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7626        match self {
7627            GrantObjects::Sequences(sequences) => {
7628                write!(f, "SEQUENCE {}", display_comma_separated(sequences))
7629            }
7630            GrantObjects::Databases(databases) => {
7631                write!(f, "DATABASE {}", display_comma_separated(databases))
7632            }
7633            GrantObjects::Schemas(schemas) => {
7634                write!(f, "SCHEMA {}", display_comma_separated(schemas))
7635            }
7636            GrantObjects::Tables(tables) => {
7637                write!(f, "{}", display_comma_separated(tables))
7638            }
7639            GrantObjects::Views(views) => {
7640                write!(f, "VIEW {}", display_comma_separated(views))
7641            }
7642            GrantObjects::Warehouses(warehouses) => {
7643                write!(f, "WAREHOUSE {}", display_comma_separated(warehouses))
7644            }
7645            GrantObjects::Integrations(integrations) => {
7646                write!(f, "INTEGRATION {}", display_comma_separated(integrations))
7647            }
7648            GrantObjects::AllSequencesInSchema { schemas } => {
7649                write!(
7650                    f,
7651                    "ALL SEQUENCES IN SCHEMA {}",
7652                    display_comma_separated(schemas)
7653                )
7654            }
7655            GrantObjects::AllTablesInSchema { schemas } => {
7656                write!(
7657                    f,
7658                    "ALL TABLES IN SCHEMA {}",
7659                    display_comma_separated(schemas)
7660                )
7661            }
7662            GrantObjects::AllExternalTablesInSchema { schemas } => {
7663                write!(
7664                    f,
7665                    "ALL EXTERNAL TABLES IN SCHEMA {}",
7666                    display_comma_separated(schemas)
7667                )
7668            }
7669            GrantObjects::AllViewsInSchema { schemas } => {
7670                write!(
7671                    f,
7672                    "ALL VIEWS IN SCHEMA {}",
7673                    display_comma_separated(schemas)
7674                )
7675            }
7676            GrantObjects::AllMaterializedViewsInSchema { schemas } => {
7677                write!(
7678                    f,
7679                    "ALL MATERIALIZED VIEWS IN SCHEMA {}",
7680                    display_comma_separated(schemas)
7681                )
7682            }
7683            GrantObjects::AllFunctionsInSchema { schemas } => {
7684                write!(
7685                    f,
7686                    "ALL FUNCTIONS IN SCHEMA {}",
7687                    display_comma_separated(schemas)
7688                )
7689            }
7690            GrantObjects::FutureSchemasInDatabase { databases } => {
7691                write!(
7692                    f,
7693                    "FUTURE SCHEMAS IN DATABASE {}",
7694                    display_comma_separated(databases)
7695                )
7696            }
7697            GrantObjects::FutureTablesInSchema { schemas } => {
7698                write!(
7699                    f,
7700                    "FUTURE TABLES IN SCHEMA {}",
7701                    display_comma_separated(schemas)
7702                )
7703            }
7704            GrantObjects::FutureExternalTablesInSchema { schemas } => {
7705                write!(
7706                    f,
7707                    "FUTURE EXTERNAL TABLES IN SCHEMA {}",
7708                    display_comma_separated(schemas)
7709                )
7710            }
7711            GrantObjects::FutureViewsInSchema { schemas } => {
7712                write!(
7713                    f,
7714                    "FUTURE VIEWS IN SCHEMA {}",
7715                    display_comma_separated(schemas)
7716                )
7717            }
7718            GrantObjects::FutureMaterializedViewsInSchema { schemas } => {
7719                write!(
7720                    f,
7721                    "FUTURE MATERIALIZED VIEWS IN SCHEMA {}",
7722                    display_comma_separated(schemas)
7723                )
7724            }
7725            GrantObjects::FutureSequencesInSchema { schemas } => {
7726                write!(
7727                    f,
7728                    "FUTURE SEQUENCES IN SCHEMA {}",
7729                    display_comma_separated(schemas)
7730                )
7731            }
7732            GrantObjects::ResourceMonitors(objects) => {
7733                write!(f, "RESOURCE MONITOR {}", display_comma_separated(objects))
7734            }
7735            GrantObjects::Users(objects) => {
7736                write!(f, "USER {}", display_comma_separated(objects))
7737            }
7738            GrantObjects::ComputePools(objects) => {
7739                write!(f, "COMPUTE POOL {}", display_comma_separated(objects))
7740            }
7741            GrantObjects::Connections(objects) => {
7742                write!(f, "CONNECTION {}", display_comma_separated(objects))
7743            }
7744            GrantObjects::FailoverGroup(objects) => {
7745                write!(f, "FAILOVER GROUP {}", display_comma_separated(objects))
7746            }
7747            GrantObjects::ReplicationGroup(objects) => {
7748                write!(f, "REPLICATION GROUP {}", display_comma_separated(objects))
7749            }
7750            GrantObjects::ExternalVolumes(objects) => {
7751                write!(f, "EXTERNAL VOLUME {}", display_comma_separated(objects))
7752            }
7753            GrantObjects::Procedure { name, arg_types } => {
7754                write!(f, "PROCEDURE {name}")?;
7755                if !arg_types.is_empty() {
7756                    write!(f, "({})", display_comma_separated(arg_types))?;
7757                }
7758                Ok(())
7759            }
7760            GrantObjects::Function { name, arg_types } => {
7761                write!(f, "FUNCTION {name}")?;
7762                if !arg_types.is_empty() {
7763                    write!(f, "({})", display_comma_separated(arg_types))?;
7764                }
7765                Ok(())
7766            }
7767        }
7768    }
7769}
7770
7771/// A `DENY` statement
7772///
7773/// [MsSql](https://learn.microsoft.com/en-us/sql/t-sql/statements/deny-transact-sql)
7774#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7775#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7776#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7777pub struct DenyStatement {
7778    /// The privileges to deny.
7779    pub privileges: Privileges,
7780    /// The objects the privileges apply to.
7781    pub objects: GrantObjects,
7782    /// The grantees (users/roles) to whom the denial applies.
7783    pub grantees: Vec<Grantee>,
7784    /// Optional identifier of the principal that performed the grant.
7785    pub granted_by: Option<Ident>,
7786    /// Optional cascade option controlling dependent objects.
7787    pub cascade: Option<CascadeOption>,
7788}
7789
7790impl fmt::Display for DenyStatement {
7791    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7792        write!(f, "DENY {}", self.privileges)?;
7793        write!(f, " ON {}", self.objects)?;
7794        if !self.grantees.is_empty() {
7795            write!(f, " TO {}", display_comma_separated(&self.grantees))?;
7796        }
7797        if let Some(cascade) = &self.cascade {
7798            write!(f, " {cascade}")?;
7799        }
7800        if let Some(granted_by) = &self.granted_by {
7801            write!(f, " AS {granted_by}")?;
7802        }
7803        Ok(())
7804    }
7805}
7806
7807/// SQL assignment `foo = expr` as used in SQLUpdate
7808#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7809#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7810#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7811pub struct Assignment {
7812    /// The left-hand side of the assignment.
7813    pub target: AssignmentTarget,
7814    /// The expression assigned to the target.
7815    pub value: Expr,
7816}
7817
7818impl fmt::Display for Assignment {
7819    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7820        write!(f, "{} = {}", self.target, self.value)
7821    }
7822}
7823
7824/// Left-hand side of an assignment in an UPDATE statement,
7825/// e.g. `foo` in `foo = 5` (ColumnName assignment) or
7826/// `(a, b)` in `(a, b) = (1, 2)` (Tuple assignment).
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 AssignmentTarget {
7831    /// A single column
7832    ColumnName(ObjectName),
7833    /// A tuple of columns
7834    Tuple(Vec<ObjectName>),
7835}
7836
7837impl fmt::Display for AssignmentTarget {
7838    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7839        match self {
7840            AssignmentTarget::ColumnName(column) => write!(f, "{column}"),
7841            AssignmentTarget::Tuple(columns) => write!(f, "({})", display_comma_separated(columns)),
7842        }
7843    }
7844}
7845
7846#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7847#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7848#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7849/// Expression forms allowed as a function argument.
7850pub enum FunctionArgExpr {
7851    /// A normal expression argument.
7852    Expr(Expr),
7853    /// Qualified wildcard, e.g. `alias.*` or `schema.table.*`.
7854    QualifiedWildcard(ObjectName),
7855    /// An unqualified `*` wildcard.
7856    Wildcard,
7857    /// An unqualified `*` wildcard with additional options, e.g. `* EXCLUDE(col)`.
7858    ///
7859    /// Used in Snowflake to support expressions like `HASH(* EXCLUDE(col))`.
7860    WildcardWithOptions(WildcardAdditionalOptions),
7861}
7862
7863impl From<Expr> for FunctionArgExpr {
7864    fn from(wildcard_expr: Expr) -> Self {
7865        match wildcard_expr {
7866            Expr::QualifiedWildcard(prefix, _) => Self::QualifiedWildcard(prefix),
7867            Expr::Wildcard(_) => Self::Wildcard,
7868            expr => Self::Expr(expr),
7869        }
7870    }
7871}
7872
7873impl fmt::Display for FunctionArgExpr {
7874    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7875        match self {
7876            FunctionArgExpr::Expr(expr) => write!(f, "{expr}"),
7877            FunctionArgExpr::QualifiedWildcard(prefix) => write!(f, "{prefix}.*"),
7878            FunctionArgExpr::Wildcard => f.write_str("*"),
7879            FunctionArgExpr::WildcardWithOptions(opts) => write!(f, "*{opts}"),
7880        }
7881    }
7882}
7883
7884#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7885#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7886#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7887/// Operator used to separate function arguments
7888pub enum FunctionArgOperator {
7889    /// function(arg1 = value1)
7890    Equals,
7891    /// function(arg1 => value1)
7892    RightArrow,
7893    /// function(arg1 := value1)
7894    Assignment,
7895    /// function(arg1 : value1)
7896    Colon,
7897    /// function(arg1 VALUE value1)
7898    Value,
7899}
7900
7901impl fmt::Display for FunctionArgOperator {
7902    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7903        match self {
7904            FunctionArgOperator::Equals => f.write_str("="),
7905            FunctionArgOperator::RightArrow => f.write_str("=>"),
7906            FunctionArgOperator::Assignment => f.write_str(":="),
7907            FunctionArgOperator::Colon => f.write_str(":"),
7908            FunctionArgOperator::Value => f.write_str("VALUE"),
7909        }
7910    }
7911}
7912
7913#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7914#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7915#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7916/// Forms of function arguments (named, expression-named, or positional).
7917pub enum FunctionArg {
7918    /// `name` is identifier
7919    ///
7920    /// Enabled when `Dialect::supports_named_fn_args_with_expr_name` returns 'false'
7921    Named {
7922        /// The identifier name of the argument.
7923        name: Ident,
7924        /// The argument expression or wildcard form.
7925        arg: FunctionArgExpr,
7926        /// The operator separating name and value.
7927        operator: FunctionArgOperator,
7928    },
7929    /// `name` is arbitrary expression
7930    ///
7931    /// Enabled when `Dialect::supports_named_fn_args_with_expr_name` returns 'true'
7932    ExprNamed {
7933        /// The expression used as the argument name.
7934        name: Expr,
7935        /// The argument expression or wildcard form.
7936        arg: FunctionArgExpr,
7937        /// The operator separating name and value.
7938        operator: FunctionArgOperator,
7939    },
7940    /// An unnamed argument (positional), given by expression or wildcard.
7941    Unnamed(FunctionArgExpr),
7942}
7943
7944impl fmt::Display for FunctionArg {
7945    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7946        match self {
7947            FunctionArg::Named {
7948                name,
7949                arg,
7950                operator,
7951            } => write!(f, "{name} {operator} {arg}"),
7952            FunctionArg::ExprNamed {
7953                name,
7954                arg,
7955                operator,
7956            } => write!(f, "{name} {operator} {arg}"),
7957            FunctionArg::Unnamed(unnamed_arg) => write!(f, "{unnamed_arg}"),
7958        }
7959    }
7960}
7961
7962#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7963#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7964#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7965/// Which cursor(s) to close.
7966pub enum CloseCursor {
7967    /// Close all cursors.
7968    All,
7969    /// Close a specific cursor by name.
7970    Specific {
7971        /// The name of the cursor to close.
7972        name: Ident,
7973    },
7974}
7975
7976impl fmt::Display for CloseCursor {
7977    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7978        match self {
7979            CloseCursor::All => write!(f, "ALL"),
7980            CloseCursor::Specific { name } => write!(f, "{name}"),
7981        }
7982    }
7983}
7984
7985/// A Drop Domain statement
7986#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7987#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7988#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7989pub struct DropDomain {
7990    /// Whether to drop the domain if it exists
7991    pub if_exists: bool,
7992    /// The name of the domain to drop
7993    pub name: ObjectName,
7994    /// The behavior to apply when dropping the domain
7995    pub drop_behavior: Option<DropBehavior>,
7996}
7997
7998/// A constant of form `<data_type> 'value'`.
7999/// This can represent ANSI SQL `DATE`, `TIME`, and `TIMESTAMP` literals (such as `DATE '2020-01-01'`),
8000/// as well as constants of other types (a non-standard PostgreSQL extension).
8001#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8002#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8003#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8004pub struct TypedString {
8005    /// The data type of the typed string (e.g. DATE, TIME, TIMESTAMP).
8006    pub data_type: DataType,
8007    /// The value of the constant.
8008    /// Hint: you can unwrap the string value using `value.into_string()`.
8009    pub value: ValueWithSpan,
8010    /// Flags whether this TypedString uses the [ODBC syntax].
8011    ///
8012    /// Example:
8013    /// ```sql
8014    /// -- An ODBC date literal:
8015    /// SELECT {d '2025-07-16'}
8016    /// -- This is equivalent to the standard ANSI SQL literal:
8017    /// SELECT DATE '2025-07-16'
8018    ///
8019    /// [ODBC syntax]: https://learn.microsoft.com/en-us/sql/odbc/reference/develop-app/date-time-and-timestamp-literals?view=sql-server-2017
8020    pub uses_odbc_syntax: bool,
8021}
8022
8023impl fmt::Display for TypedString {
8024    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8025        let data_type = &self.data_type;
8026        let value = &self.value;
8027        match self.uses_odbc_syntax {
8028            false => {
8029                write!(f, "{data_type}")?;
8030                write!(f, " {value}")
8031            }
8032            true => {
8033                let prefix = match data_type {
8034                    DataType::Date => "d",
8035                    DataType::Time(..) => "t",
8036                    DataType::Timestamp(..) => "ts",
8037                    _ => "?",
8038                };
8039                write!(f, "{{{prefix} {value}}}")
8040            }
8041        }
8042    }
8043}
8044
8045/// A function call
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 struct Function {
8050    /// The function name (may be qualified).
8051    pub name: ObjectName,
8052    /// Flags whether this function call uses the [ODBC syntax].
8053    ///
8054    /// Example:
8055    /// ```sql
8056    /// SELECT {fn CONCAT('foo', 'bar')}
8057    /// ```
8058    ///
8059    /// [ODBC syntax]: https://learn.microsoft.com/en-us/sql/odbc/reference/develop-app/scalar-function-calls?view=sql-server-2017
8060    pub uses_odbc_syntax: bool,
8061    /// The parameters to the function, including any options specified within the
8062    /// delimiting parentheses.
8063    ///
8064    /// Example:
8065    /// ```plaintext
8066    /// HISTOGRAM(0.5, 0.6)(x, y)
8067    /// ```
8068    ///
8069    /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/aggregate-functions/parametric-functions)
8070    pub parameters: FunctionArguments,
8071    /// The arguments to the function, including any options specified within the
8072    /// delimiting parentheses.
8073    pub args: FunctionArguments,
8074    /// e.g. `x > 5` in `COUNT(x) FILTER (WHERE x > 5)`
8075    pub filter: Option<Box<Expr>>,
8076    /// Indicates how `NULL`s should be handled in the calculation.
8077    ///
8078    /// Example:
8079    /// ```plaintext
8080    /// FIRST_VALUE( <expr> ) [ { IGNORE | RESPECT } NULLS ] OVER ...
8081    /// ```
8082    ///
8083    /// [Snowflake](https://docs.snowflake.com/en/sql-reference/functions/first_value)
8084    pub null_treatment: Option<NullTreatment>,
8085    /// The `OVER` clause, indicating a window function call.
8086    pub over: Option<WindowType>,
8087    /// A clause used with certain aggregate functions to control the ordering
8088    /// within grouped sets before the function is applied.
8089    ///
8090    /// Syntax:
8091    /// ```plaintext
8092    /// <aggregate_function>(expression) WITHIN GROUP (ORDER BY key [ASC | DESC], ...)
8093    /// ```
8094    pub within_group: Vec<OrderByExpr>,
8095}
8096
8097impl fmt::Display for Function {
8098    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8099        if self.uses_odbc_syntax {
8100            write!(f, "{{fn ")?;
8101        }
8102
8103        write!(f, "{}{}{}", self.name, self.parameters, self.args)?;
8104
8105        if !self.within_group.is_empty() {
8106            write!(
8107                f,
8108                " WITHIN GROUP (ORDER BY {})",
8109                display_comma_separated(&self.within_group)
8110            )?;
8111        }
8112
8113        if let Some(filter_cond) = &self.filter {
8114            write!(f, " FILTER (WHERE {filter_cond})")?;
8115        }
8116
8117        if let Some(null_treatment) = &self.null_treatment {
8118            write!(f, " {null_treatment}")?;
8119        }
8120
8121        if let Some(o) = &self.over {
8122            f.write_str(" OVER ")?;
8123            o.fmt(f)?;
8124        }
8125
8126        if self.uses_odbc_syntax {
8127            write!(f, "}}")?;
8128        }
8129
8130        Ok(())
8131    }
8132}
8133
8134/// The arguments passed to a function call.
8135#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8136#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8137#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8138pub enum FunctionArguments {
8139    /// Used for special functions like `CURRENT_TIMESTAMP` that are invoked
8140    /// without parentheses.
8141    None,
8142    /// On some dialects, a subquery can be passed without surrounding
8143    /// parentheses if it's the sole argument to the function.
8144    Subquery(Box<Query>),
8145    /// A normal function argument list, including any clauses within it such as
8146    /// `DISTINCT` or `ORDER BY`.
8147    List(FunctionArgumentList),
8148}
8149
8150impl fmt::Display for FunctionArguments {
8151    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8152        match self {
8153            FunctionArguments::None => Ok(()),
8154            FunctionArguments::Subquery(query) => write!(f, "({query})"),
8155            FunctionArguments::List(args) => write!(f, "({args})"),
8156        }
8157    }
8158}
8159
8160/// This represents everything inside the parentheses when calling a function.
8161#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8162#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8163#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8164pub struct FunctionArgumentList {
8165    /// `[ ALL | DISTINCT ]`
8166    pub duplicate_treatment: Option<DuplicateTreatment>,
8167    /// The function arguments.
8168    pub args: Vec<FunctionArg>,
8169    /// Additional clauses specified within the argument list.
8170    pub clauses: Vec<FunctionArgumentClause>,
8171}
8172
8173impl fmt::Display for FunctionArgumentList {
8174    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8175        if let Some(duplicate_treatment) = self.duplicate_treatment {
8176            write!(f, "{duplicate_treatment} ")?;
8177        }
8178        write!(f, "{}", display_comma_separated(&self.args))?;
8179        if !self.clauses.is_empty() {
8180            if !self.args.is_empty() {
8181                write!(f, " ")?;
8182            }
8183            write!(f, "{}", display_separated(&self.clauses, " "))?;
8184        }
8185        Ok(())
8186    }
8187}
8188
8189#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8190#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8191#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8192/// Clauses that can appear inside a function argument list.
8193pub enum FunctionArgumentClause {
8194    /// Indicates how `NULL`s should be handled in the calculation, e.g. in `FIRST_VALUE` on [BigQuery].
8195    ///
8196    /// Syntax:
8197    /// ```plaintext
8198    /// { IGNORE | RESPECT } NULLS ]
8199    /// ```
8200    ///
8201    /// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/navigation_functions#first_value
8202    IgnoreOrRespectNulls(NullTreatment),
8203    /// Specifies the the ordering for some ordered set aggregates, e.g. `ARRAY_AGG` on [BigQuery].
8204    ///
8205    /// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/aggregate_functions#array_agg
8206    OrderBy(Vec<OrderByExpr>),
8207    /// Specifies a limit for the `ARRAY_AGG` and `ARRAY_CONCAT_AGG` functions on BigQuery.
8208    Limit(Expr),
8209    /// Specifies the behavior on overflow of the `LISTAGG` function.
8210    ///
8211    /// See <https://trino.io/docs/current/functions/aggregate.html>.
8212    OnOverflow(ListAggOnOverflow),
8213    /// Specifies a minimum or maximum bound on the input to [`ANY_VALUE`] on BigQuery.
8214    ///
8215    /// Syntax:
8216    /// ```plaintext
8217    /// HAVING { MAX | MIN } expression
8218    /// ```
8219    ///
8220    /// [`ANY_VALUE`]: https://cloud.google.com/bigquery/docs/reference/standard-sql/aggregate_functions#any_value
8221    Having(HavingBound),
8222    /// The `SEPARATOR` clause to the [`GROUP_CONCAT`] function in MySQL.
8223    ///
8224    /// [`GROUP_CONCAT`]: https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html#function_group-concat
8225    Separator(ValueWithSpan),
8226    /// The `ON NULL` clause for some JSON functions.
8227    ///
8228    /// [MSSQL `JSON_ARRAY`](https://learn.microsoft.com/en-us/sql/t-sql/functions/json-array-transact-sql?view=sql-server-ver16)
8229    /// [MSSQL `JSON_OBJECT`](https://learn.microsoft.com/en-us/sql/t-sql/functions/json-object-transact-sql?view=sql-server-ver16>)
8230    /// [PostgreSQL JSON functions](https://www.postgresql.org/docs/current/functions-json.html#FUNCTIONS-JSON-PROCESSING)
8231    JsonNullClause(JsonNullClause),
8232    /// The `RETURNING` clause for some JSON functions in PostgreSQL
8233    ///
8234    /// [`JSON_OBJECT`](https://www.postgresql.org/docs/current/functions-json.html#:~:text=json_object)
8235    JsonReturningClause(JsonReturningClause),
8236}
8237
8238impl fmt::Display for FunctionArgumentClause {
8239    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8240        match self {
8241            FunctionArgumentClause::IgnoreOrRespectNulls(null_treatment) => {
8242                write!(f, "{null_treatment}")
8243            }
8244            FunctionArgumentClause::OrderBy(order_by) => {
8245                write!(f, "ORDER BY {}", display_comma_separated(order_by))
8246            }
8247            FunctionArgumentClause::Limit(limit) => write!(f, "LIMIT {limit}"),
8248            FunctionArgumentClause::OnOverflow(on_overflow) => write!(f, "{on_overflow}"),
8249            FunctionArgumentClause::Having(bound) => write!(f, "{bound}"),
8250            FunctionArgumentClause::Separator(sep) => write!(f, "SEPARATOR {sep}"),
8251            FunctionArgumentClause::JsonNullClause(null_clause) => write!(f, "{null_clause}"),
8252            FunctionArgumentClause::JsonReturningClause(returning_clause) => {
8253                write!(f, "{returning_clause}")
8254            }
8255        }
8256    }
8257}
8258
8259/// A method call
8260#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8261#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8262#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8263pub struct Method {
8264    /// The expression on which the method is invoked.
8265    pub expr: Box<Expr>,
8266    // always non-empty
8267    /// The sequence of chained method calls.
8268    pub method_chain: Vec<Function>,
8269}
8270
8271impl fmt::Display for Method {
8272    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8273        write!(
8274            f,
8275            "{}.{}",
8276            self.expr,
8277            display_separated(&self.method_chain, ".")
8278        )
8279    }
8280}
8281
8282#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8283#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8284#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8285/// How duplicate values are treated inside function argument lists.
8286pub enum DuplicateTreatment {
8287    /// Consider only unique values.
8288    Distinct,
8289    /// Retain all duplicate values (the default).
8290    All,
8291}
8292
8293impl fmt::Display for DuplicateTreatment {
8294    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8295        match self {
8296            DuplicateTreatment::Distinct => write!(f, "DISTINCT"),
8297            DuplicateTreatment::All => write!(f, "ALL"),
8298        }
8299    }
8300}
8301
8302#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8303#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8304#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8305/// How the `ANALYZE`/`EXPLAIN ANALYZE` format is specified.
8306pub enum AnalyzeFormatKind {
8307    /// Format provided as a keyword, e.g. `FORMAT JSON`.
8308    Keyword(AnalyzeFormat),
8309    /// Format provided as an assignment, e.g. `FORMAT=JSON`.
8310    Assignment(AnalyzeFormat),
8311}
8312
8313impl fmt::Display for AnalyzeFormatKind {
8314    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
8315        match self {
8316            AnalyzeFormatKind::Keyword(format) => write!(f, "FORMAT {format}"),
8317            AnalyzeFormatKind::Assignment(format) => write!(f, "FORMAT={format}"),
8318        }
8319    }
8320}
8321
8322#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8323#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8324#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8325/// Output formats supported for `ANALYZE`/`EXPLAIN ANALYZE`.
8326pub enum AnalyzeFormat {
8327    /// Plain text format.
8328    TEXT,
8329    /// Graphviz DOT format.
8330    GRAPHVIZ,
8331    /// JSON format.
8332    JSON,
8333    /// Traditional explain output.
8334    TRADITIONAL,
8335    /// Tree-style explain output.
8336    TREE,
8337}
8338
8339impl fmt::Display for AnalyzeFormat {
8340    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
8341        f.write_str(match self {
8342            AnalyzeFormat::TEXT => "TEXT",
8343            AnalyzeFormat::GRAPHVIZ => "GRAPHVIZ",
8344            AnalyzeFormat::JSON => "JSON",
8345            AnalyzeFormat::TRADITIONAL => "TRADITIONAL",
8346            AnalyzeFormat::TREE => "TREE",
8347        })
8348    }
8349}
8350
8351/// External table's available file format
8352#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8353#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8354#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8355pub enum FileFormat {
8356    /// Text file format.
8357    TEXTFILE,
8358    /// Sequence file format.
8359    SEQUENCEFILE,
8360    /// ORC file format.
8361    ORC,
8362    /// Parquet file format.
8363    PARQUET,
8364    /// Avro file format.
8365    AVRO,
8366    /// RCFile format.
8367    RCFILE,
8368    /// JSON file format.
8369    JSONFILE,
8370}
8371
8372impl fmt::Display for FileFormat {
8373    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8374        use self::FileFormat::*;
8375        f.write_str(match self {
8376            TEXTFILE => "TEXTFILE",
8377            SEQUENCEFILE => "SEQUENCEFILE",
8378            ORC => "ORC",
8379            PARQUET => "PARQUET",
8380            AVRO => "AVRO",
8381            RCFILE => "RCFILE",
8382            JSONFILE => "JSONFILE",
8383        })
8384    }
8385}
8386
8387/// The `ON OVERFLOW` clause of a LISTAGG invocation
8388#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8389#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8390#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8391pub enum ListAggOnOverflow {
8392    /// `ON OVERFLOW ERROR`
8393    Error,
8394
8395    /// `ON OVERFLOW TRUNCATE [ <filler> ] WITH[OUT] COUNT`
8396    Truncate {
8397        /// Optional filler expression used when truncating.
8398        filler: Option<Box<Expr>>,
8399        /// Whether to include a count when truncating.
8400        with_count: bool,
8401    },
8402}
8403
8404impl fmt::Display for ListAggOnOverflow {
8405    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8406        write!(f, "ON OVERFLOW")?;
8407        match self {
8408            ListAggOnOverflow::Error => write!(f, " ERROR"),
8409            ListAggOnOverflow::Truncate { filler, with_count } => {
8410                write!(f, " TRUNCATE")?;
8411                if let Some(filler) = filler {
8412                    write!(f, " {filler}")?;
8413                }
8414                if *with_count {
8415                    write!(f, " WITH")?;
8416                } else {
8417                    write!(f, " WITHOUT")?;
8418                }
8419                write!(f, " COUNT")
8420            }
8421        }
8422    }
8423}
8424
8425/// The `HAVING` clause in a call to `ANY_VALUE` on BigQuery.
8426#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8427#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8428#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8429pub struct HavingBound(pub HavingBoundKind, pub Expr);
8430
8431impl fmt::Display for HavingBound {
8432    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8433        write!(f, "HAVING {} {}", self.0, self.1)
8434    }
8435}
8436
8437#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8438#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8439#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8440/// Which bound is used in a HAVING clause for ANY_VALUE on BigQuery.
8441pub enum HavingBoundKind {
8442    /// The minimum bound.
8443    Min,
8444    /// The maximum bound.
8445    Max,
8446}
8447
8448impl fmt::Display for HavingBoundKind {
8449    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8450        match self {
8451            HavingBoundKind::Min => write!(f, "MIN"),
8452            HavingBoundKind::Max => write!(f, "MAX"),
8453        }
8454    }
8455}
8456
8457#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8458#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8459#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8460/// Types of database objects referenced by DDL statements.
8461pub enum ObjectType {
8462    /// A collation.
8463    Collation,
8464    /// A table.
8465    Table,
8466    /// A view.
8467    View,
8468    /// A materialized view.
8469    MaterializedView,
8470    /// An index.
8471    Index,
8472    /// A schema.
8473    Schema,
8474    /// A database.
8475    Database,
8476    /// A role.
8477    Role,
8478    /// A sequence.
8479    Sequence,
8480    /// A stage.
8481    Stage,
8482    /// A type definition.
8483    Type,
8484    /// A user.
8485    User,
8486    /// A stream.
8487    Stream,
8488}
8489
8490impl fmt::Display for ObjectType {
8491    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8492        f.write_str(match self {
8493            ObjectType::Collation => "COLLATION",
8494            ObjectType::Table => "TABLE",
8495            ObjectType::View => "VIEW",
8496            ObjectType::MaterializedView => "MATERIALIZED VIEW",
8497            ObjectType::Index => "INDEX",
8498            ObjectType::Schema => "SCHEMA",
8499            ObjectType::Database => "DATABASE",
8500            ObjectType::Role => "ROLE",
8501            ObjectType::Sequence => "SEQUENCE",
8502            ObjectType::Stage => "STAGE",
8503            ObjectType::Type => "TYPE",
8504            ObjectType::User => "USER",
8505            ObjectType::Stream => "STREAM",
8506        })
8507    }
8508}
8509
8510#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8511#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8512#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8513/// Types supported by `KILL` statements.
8514pub enum KillType {
8515    /// Kill a connection.
8516    Connection,
8517    /// Kill a running query.
8518    Query,
8519    /// Kill a mutation (ClickHouse).
8520    Mutation,
8521}
8522
8523impl fmt::Display for KillType {
8524    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8525        f.write_str(match self {
8526            // MySQL
8527            KillType::Connection => "CONNECTION",
8528            KillType::Query => "QUERY",
8529            // Clickhouse supports Mutation
8530            KillType::Mutation => "MUTATION",
8531        })
8532    }
8533}
8534
8535#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8536#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8537#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8538/// Distribution style options for Hive tables.
8539pub enum HiveDistributionStyle {
8540    /// Partitioned distribution with the given columns.
8541    PARTITIONED {
8542        /// Columns used for partitioning.
8543        columns: Vec<ColumnDef>,
8544    },
8545    /// Skewed distribution definition.
8546    SKEWED {
8547        /// Columns participating in the skew definition.
8548        columns: Vec<ColumnDef>,
8549        /// Columns listed in the `ON` clause for skewing.
8550        on: Vec<ColumnDef>,
8551        /// Whether skewed data is stored as directories.
8552        stored_as_directories: bool,
8553    },
8554    /// No distribution style specified.
8555    NONE,
8556}
8557
8558#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8559#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8560#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8561/// Row format specification for Hive tables (SERDE or DELIMITED).
8562pub enum HiveRowFormat {
8563    /// SerDe class specification with the implementing class name.
8564    SERDE {
8565        /// The SerDe implementation class name.
8566        class: String,
8567    },
8568    /// Delimited row format with one or more delimiter specifications.
8569    DELIMITED {
8570        /// The list of delimiters used for delimiting fields/lines.
8571        delimiters: Vec<HiveRowDelimiter>,
8572    },
8573}
8574
8575#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8576#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8577#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8578/// Format specification for `LOAD DATA` Hive operations.
8579pub struct HiveLoadDataFormat {
8580    /// SerDe expression used for the table.
8581    pub serde: Expr,
8582    /// Input format expression.
8583    pub input_format: Expr,
8584}
8585
8586#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8587#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8588#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8589/// A single row delimiter specification for Hive `ROW FORMAT`.
8590pub struct HiveRowDelimiter {
8591    /// The delimiter kind (fields/lines/etc.).
8592    pub delimiter: HiveDelimiter,
8593    /// The delimiter character identifier.
8594    pub char: Ident,
8595}
8596
8597impl fmt::Display for HiveRowDelimiter {
8598    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8599        write!(f, "{} ", self.delimiter)?;
8600        write!(f, "{}", self.char)
8601    }
8602}
8603
8604#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8605#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8606#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8607/// Kind of delimiter used in Hive `ROW FORMAT` definitions.
8608pub enum HiveDelimiter {
8609    /// Fields terminated by a delimiter.
8610    FieldsTerminatedBy,
8611    /// Fields escaped by a character.
8612    FieldsEscapedBy,
8613    /// Collection items terminated by a delimiter.
8614    CollectionItemsTerminatedBy,
8615    /// Map keys terminated by a delimiter.
8616    MapKeysTerminatedBy,
8617    /// Lines terminated by a delimiter.
8618    LinesTerminatedBy,
8619    /// Null represented by a specific token.
8620    NullDefinedAs,
8621}
8622
8623impl fmt::Display for HiveDelimiter {
8624    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8625        use HiveDelimiter::*;
8626        f.write_str(match self {
8627            FieldsTerminatedBy => "FIELDS TERMINATED BY",
8628            FieldsEscapedBy => "ESCAPED BY",
8629            CollectionItemsTerminatedBy => "COLLECTION ITEMS TERMINATED BY",
8630            MapKeysTerminatedBy => "MAP KEYS TERMINATED BY",
8631            LinesTerminatedBy => "LINES TERMINATED BY",
8632            NullDefinedAs => "NULL DEFINED AS",
8633        })
8634    }
8635}
8636
8637#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8638#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8639#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8640/// Describe output format options for Hive `DESCRIBE`/`EXPLAIN`.
8641pub enum HiveDescribeFormat {
8642    /// Extended describe output.
8643    Extended,
8644    /// Formatted describe output.
8645    Formatted,
8646}
8647
8648impl fmt::Display for HiveDescribeFormat {
8649    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8650        use HiveDescribeFormat::*;
8651        f.write_str(match self {
8652            Extended => "EXTENDED",
8653            Formatted => "FORMATTED",
8654        })
8655    }
8656}
8657
8658#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8659#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8660#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8661/// Aliases accepted for describe-style commands.
8662pub enum DescribeAlias {
8663    /// `DESCRIBE` alias.
8664    Describe,
8665    /// `EXPLAIN` alias.
8666    Explain,
8667    /// `DESC` alias.
8668    Desc,
8669}
8670
8671impl fmt::Display for DescribeAlias {
8672    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8673        use DescribeAlias::*;
8674        f.write_str(match self {
8675            Describe => "DESCRIBE",
8676            Explain => "EXPLAIN",
8677            Desc => "DESC",
8678        })
8679    }
8680}
8681
8682#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8683#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8684#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8685#[allow(clippy::large_enum_variant)]
8686/// Hive input/output format specification used in `CREATE TABLE`.
8687pub enum HiveIOFormat {
8688    /// Generic IO format with separate input and output expressions.
8689    IOF {
8690        /// Expression for the input format.
8691        input_format: Expr,
8692        /// Expression for the output format.
8693        output_format: Expr,
8694    },
8695    /// File format wrapper referencing a `FileFormat` variant.
8696    FileFormat {
8697        /// The file format used for storage.
8698        format: FileFormat,
8699    },
8700    /// `USING <format>` syntax used by Spark SQL.
8701    ///
8702    /// Example: `CREATE TABLE t (i INT) USING PARQUET`
8703    ///
8704    /// See <https://spark.apache.org/docs/latest/sql-ref-syntax-ddl-create-table-datasource.html>
8705    Using {
8706        /// The data source or format name, e.g. `parquet`, `delta`, `csv`.
8707        format: Ident,
8708    },
8709}
8710
8711#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Default)]
8712#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8713#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8714/// Hive table format and storage-related options.
8715pub struct HiveFormat {
8716    /// Optional row format specification.
8717    pub row_format: Option<HiveRowFormat>,
8718    /// Optional SerDe properties expressed as SQL options.
8719    pub serde_properties: Option<Vec<SqlOption>>,
8720    /// Optional input/output storage format details.
8721    pub storage: Option<HiveIOFormat>,
8722    /// Optional location (URI or path) for table data.
8723    pub location: Option<String>,
8724}
8725
8726#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8727#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8728#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8729/// A clustered index column specification.
8730pub struct ClusteredIndex {
8731    /// Column identifier for the clustered index entry.
8732    pub name: Ident,
8733    /// Optional sort direction: `Some(true)` for ASC, `Some(false)` for DESC, `None` for unspecified.
8734    pub asc: Option<bool>,
8735}
8736
8737impl fmt::Display for ClusteredIndex {
8738    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8739        write!(f, "{}", self.name)?;
8740        match self.asc {
8741            Some(true) => write!(f, " ASC"),
8742            Some(false) => write!(f, " DESC"),
8743            _ => Ok(()),
8744        }
8745    }
8746}
8747
8748#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8749#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8750#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8751/// Clustered options used for `CREATE TABLE` clustered/indexed storage.
8752pub enum TableOptionsClustered {
8753    /// Use a columnstore index.
8754    ColumnstoreIndex,
8755    /// Columnstore index with an explicit ordering of columns.
8756    ColumnstoreIndexOrder(Vec<Ident>),
8757    /// A named clustered index with one or more columns.
8758    Index(Vec<ClusteredIndex>),
8759}
8760
8761impl fmt::Display for TableOptionsClustered {
8762    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8763        match self {
8764            TableOptionsClustered::ColumnstoreIndex => {
8765                write!(f, "CLUSTERED COLUMNSTORE INDEX")
8766            }
8767            TableOptionsClustered::ColumnstoreIndexOrder(values) => {
8768                write!(
8769                    f,
8770                    "CLUSTERED COLUMNSTORE INDEX ORDER ({})",
8771                    display_comma_separated(values)
8772                )
8773            }
8774            TableOptionsClustered::Index(values) => {
8775                write!(f, "CLUSTERED INDEX ({})", display_comma_separated(values))
8776            }
8777        }
8778    }
8779}
8780
8781/// Specifies which partition the boundary values on table partitioning belongs to.
8782#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash)]
8783#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8784#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8785pub enum PartitionRangeDirection {
8786    /// LEFT range direction.
8787    Left,
8788    /// RIGHT range direction.
8789    Right,
8790}
8791
8792#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8793#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8794#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8795/// SQL option syntax used in table and server definitions.
8796pub enum SqlOption {
8797    /// Clustered represents the clustered version of table storage for MSSQL.
8798    ///
8799    /// <https://learn.microsoft.com/en-us/sql/t-sql/statements/create-table-azure-sql-data-warehouse?view=aps-pdw-2016-au7#TableOptions>
8800    Clustered(TableOptionsClustered),
8801    /// Single identifier options, e.g. `HEAP` for MSSQL.
8802    ///
8803    /// <https://learn.microsoft.com/en-us/sql/t-sql/statements/create-table-azure-sql-data-warehouse?view=aps-pdw-2016-au7#TableOptions>
8804    Ident(Ident),
8805    /// Any option that consists of a key value pair where the value is an expression. e.g.
8806    ///
8807    ///   WITH(DISTRIBUTION = ROUND_ROBIN)
8808    KeyValue {
8809        /// The option key identifier.
8810        key: Ident,
8811        /// The expression value for the option.
8812        value: Expr,
8813    },
8814    /// One or more table partitions and represents which partition the boundary values belong to,
8815    /// e.g.
8816    ///
8817    ///   PARTITION (id RANGE LEFT FOR VALUES (10, 20, 30, 40))
8818    ///
8819    /// <https://learn.microsoft.com/en-us/sql/t-sql/statements/create-table-azure-sql-data-warehouse?view=aps-pdw-2016-au7#TablePartitionOptions>
8820    Partition {
8821        /// The partition column name.
8822        column_name: Ident,
8823        /// Optional direction for the partition range (LEFT/RIGHT).
8824        range_direction: Option<PartitionRangeDirection>,
8825        /// Values that define the partition boundaries.
8826        for_values: Vec<Expr>,
8827    },
8828    /// Comment parameter (supports `=` and no `=` syntax)
8829    Comment(CommentDef),
8830    /// MySQL TableSpace option
8831    /// <https://dev.mysql.com/doc/refman/8.4/en/create-table.html>
8832    TableSpace(TablespaceOption),
8833    /// An option representing a key value pair, where the value is a parenthesized list and with an optional name
8834    /// e.g.
8835    ///
8836    ///   UNION  = (tbl_name\[,tbl_name\]...) <https://dev.mysql.com/doc/refman/8.4/en/create-table.html>
8837    ///   ENGINE = ReplicatedMergeTree('/table_name','{replica}', ver) <https://clickhouse.com/docs/engines/table-engines/mergetree-family/replication>
8838    ///   ENGINE = SummingMergeTree(\[columns\]) <https://clickhouse.com/docs/engines/table-engines/mergetree-family/summingmergetree>
8839    NamedParenthesizedList(NamedParenthesizedList),
8840}
8841
8842impl fmt::Display for SqlOption {
8843    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8844        match self {
8845            SqlOption::Clustered(c) => write!(f, "{c}"),
8846            SqlOption::Ident(ident) => {
8847                write!(f, "{ident}")
8848            }
8849            SqlOption::KeyValue { key: name, value } => {
8850                write!(f, "{name} = {value}")
8851            }
8852            SqlOption::Partition {
8853                column_name,
8854                range_direction,
8855                for_values,
8856            } => {
8857                let direction = match range_direction {
8858                    Some(PartitionRangeDirection::Left) => " LEFT",
8859                    Some(PartitionRangeDirection::Right) => " RIGHT",
8860                    None => "",
8861                };
8862
8863                write!(
8864                    f,
8865                    "PARTITION ({} RANGE{} FOR VALUES ({}))",
8866                    column_name,
8867                    direction,
8868                    display_comma_separated(for_values)
8869                )
8870            }
8871            SqlOption::TableSpace(tablespace_option) => {
8872                write!(f, "TABLESPACE {}", tablespace_option.name)?;
8873                match tablespace_option.storage {
8874                    Some(StorageType::Disk) => write!(f, " STORAGE DISK"),
8875                    Some(StorageType::Memory) => write!(f, " STORAGE MEMORY"),
8876                    None => Ok(()),
8877                }
8878            }
8879            SqlOption::Comment(comment) => match comment {
8880                CommentDef::WithEq(comment) => {
8881                    write!(f, "COMMENT = '{comment}'")
8882                }
8883                CommentDef::WithoutEq(comment) => {
8884                    write!(f, "COMMENT '{comment}'")
8885                }
8886            },
8887            SqlOption::NamedParenthesizedList(value) => {
8888                write!(f, "{} = ", value.key)?;
8889                if let Some(key) = &value.name {
8890                    write!(f, "{key}")?;
8891                }
8892                if !value.values.is_empty() {
8893                    write!(f, "({})", display_comma_separated(&value.values))?
8894                }
8895                Ok(())
8896            }
8897        }
8898    }
8899}
8900
8901#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
8902#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8903#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8904/// Storage type options for a tablespace.
8905pub enum StorageType {
8906    /// Store on disk.
8907    Disk,
8908    /// Store in memory.
8909    Memory,
8910}
8911
8912#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
8913#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8914#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8915/// MySql TableSpace option
8916/// <https://dev.mysql.com/doc/refman/8.4/en/create-table.html>
8917pub struct TablespaceOption {
8918    /// Name of the tablespace.
8919    pub name: String,
8920    /// Optional storage type for the tablespace.
8921    pub storage: Option<StorageType>,
8922}
8923
8924#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8925#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8926#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8927/// A key/value identifier pair used for secret or key-based options.
8928pub struct SecretOption {
8929    /// The option key identifier.
8930    pub key: Ident,
8931    /// The option value identifier.
8932    pub value: Ident,
8933}
8934
8935impl fmt::Display for SecretOption {
8936    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8937        write!(f, "{} {}", self.key, self.value)
8938    }
8939}
8940
8941/// A `CREATE SERVER` statement.
8942///
8943/// [PostgreSQL Documentation](https://www.postgresql.org/docs/current/sql-createserver.html)
8944#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8945#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8946#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8947pub struct CreateServerStatement {
8948    /// The server name.
8949    pub name: ObjectName,
8950    /// Whether `IF NOT EXISTS` was specified.
8951    pub if_not_exists: bool,
8952    /// Optional server type identifier.
8953    pub server_type: Option<Ident>,
8954    /// Optional server version identifier.
8955    pub version: Option<Ident>,
8956    /// Foreign-data wrapper object name.
8957    pub foreign_data_wrapper: ObjectName,
8958    /// Optional list of server options.
8959    pub options: Option<Vec<CreateServerOption>>,
8960}
8961
8962impl fmt::Display for CreateServerStatement {
8963    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8964        let CreateServerStatement {
8965            name,
8966            if_not_exists,
8967            server_type,
8968            version,
8969            foreign_data_wrapper,
8970            options,
8971        } = self;
8972
8973        write!(
8974            f,
8975            "CREATE SERVER {if_not_exists}{name} ",
8976            if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
8977        )?;
8978
8979        if let Some(st) = server_type {
8980            write!(f, "TYPE {st} ")?;
8981        }
8982
8983        if let Some(v) = version {
8984            write!(f, "VERSION {v} ")?;
8985        }
8986
8987        write!(f, "FOREIGN DATA WRAPPER {foreign_data_wrapper}")?;
8988
8989        if let Some(o) = options {
8990            write!(f, " OPTIONS ({o})", o = display_comma_separated(o))?;
8991        }
8992
8993        Ok(())
8994    }
8995}
8996
8997/// A key/value option for `CREATE SERVER`.
8998#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8999#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9000#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9001pub struct CreateServerOption {
9002    /// Option key identifier.
9003    pub key: Ident,
9004    /// Option value identifier.
9005    pub value: Ident,
9006}
9007
9008impl fmt::Display for CreateServerOption {
9009    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9010        write!(f, "{} {}", self.key, self.value)
9011    }
9012}
9013
9014#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9015#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9016#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9017/// Options supported by DuckDB for `ATTACH DATABASE`.
9018pub enum AttachDuckDBDatabaseOption {
9019    /// READ_ONLY option, optional boolean value.
9020    ReadOnly(Option<bool>),
9021    /// TYPE option specifying a database type identifier.
9022    Type(Ident),
9023}
9024
9025impl fmt::Display for AttachDuckDBDatabaseOption {
9026    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9027        match self {
9028            AttachDuckDBDatabaseOption::ReadOnly(Some(true)) => write!(f, "READ_ONLY true"),
9029            AttachDuckDBDatabaseOption::ReadOnly(Some(false)) => write!(f, "READ_ONLY false"),
9030            AttachDuckDBDatabaseOption::ReadOnly(None) => write!(f, "READ_ONLY"),
9031            AttachDuckDBDatabaseOption::Type(t) => write!(f, "TYPE {t}"),
9032        }
9033    }
9034}
9035
9036#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9037#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9038#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9039/// Mode for transactions: access mode or isolation level.
9040pub enum TransactionMode {
9041    /// Access mode for a transaction (e.g. `READ ONLY` / `READ WRITE`).
9042    AccessMode(TransactionAccessMode),
9043    /// Isolation level for a transaction (e.g. `SERIALIZABLE`).
9044    IsolationLevel(TransactionIsolationLevel),
9045}
9046
9047impl fmt::Display for TransactionMode {
9048    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9049        use TransactionMode::*;
9050        match self {
9051            AccessMode(access_mode) => write!(f, "{access_mode}"),
9052            IsolationLevel(iso_level) => write!(f, "ISOLATION LEVEL {iso_level}"),
9053        }
9054    }
9055}
9056
9057#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9058#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9059#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9060/// Transaction access mode (READ ONLY / READ WRITE).
9061pub enum TransactionAccessMode {
9062    /// READ ONLY access mode.
9063    ReadOnly,
9064    /// READ WRITE access mode.
9065    ReadWrite,
9066}
9067
9068impl fmt::Display for TransactionAccessMode {
9069    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9070        use TransactionAccessMode::*;
9071        f.write_str(match self {
9072            ReadOnly => "READ ONLY",
9073            ReadWrite => "READ WRITE",
9074        })
9075    }
9076}
9077
9078#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9079#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9080#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9081/// Transaction isolation levels.
9082pub enum TransactionIsolationLevel {
9083    /// READ UNCOMMITTED isolation level.
9084    ReadUncommitted,
9085    /// READ COMMITTED isolation level.
9086    ReadCommitted,
9087    /// REPEATABLE READ isolation level.
9088    RepeatableRead,
9089    /// SERIALIZABLE isolation level.
9090    Serializable,
9091    /// SNAPSHOT isolation level.
9092    Snapshot,
9093}
9094
9095impl fmt::Display for TransactionIsolationLevel {
9096    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9097        use TransactionIsolationLevel::*;
9098        f.write_str(match self {
9099            ReadUncommitted => "READ UNCOMMITTED",
9100            ReadCommitted => "READ COMMITTED",
9101            RepeatableRead => "REPEATABLE READ",
9102            Serializable => "SERIALIZABLE",
9103            Snapshot => "SNAPSHOT",
9104        })
9105    }
9106}
9107
9108/// Modifier for the transaction in the `BEGIN` syntax
9109///
9110/// SQLite: <https://sqlite.org/lang_transaction.html>
9111/// MS-SQL: <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/try-catch-transact-sql>
9112#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9113#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9114#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9115pub enum TransactionModifier {
9116    /// DEFERRED transaction modifier.
9117    Deferred,
9118    /// IMMEDIATE transaction modifier.
9119    Immediate,
9120    /// EXCLUSIVE transaction modifier.
9121    Exclusive,
9122    /// TRY block modifier (MS-SQL style TRY/CATCH).
9123    Try,
9124    /// CATCH block modifier (MS-SQL style TRY/CATCH).
9125    Catch,
9126}
9127
9128impl fmt::Display for TransactionModifier {
9129    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9130        use TransactionModifier::*;
9131        f.write_str(match self {
9132            Deferred => "DEFERRED",
9133            Immediate => "IMMEDIATE",
9134            Exclusive => "EXCLUSIVE",
9135            Try => "TRY",
9136            Catch => "CATCH",
9137        })
9138    }
9139}
9140
9141#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9142#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9143#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9144/// Filter forms usable in SHOW statements.
9145pub enum ShowStatementFilter {
9146    /// Filter using LIKE pattern.
9147    Like(String),
9148    /// Filter using ILIKE pattern.
9149    ILike(String),
9150    /// Filter using a WHERE expression.
9151    Where(Expr),
9152    /// Filter provided without a keyword (raw string).
9153    NoKeyword(String),
9154}
9155
9156impl fmt::Display for ShowStatementFilter {
9157    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9158        use ShowStatementFilter::*;
9159        match self {
9160            Like(pattern) => write!(f, "LIKE '{}'", value::escape_single_quote_string(pattern)),
9161            ILike(pattern) => write!(f, "ILIKE {}", value::escape_single_quote_string(pattern)),
9162            Where(expr) => write!(f, "WHERE {expr}"),
9163            NoKeyword(pattern) => write!(f, "'{}'", value::escape_single_quote_string(pattern)),
9164        }
9165    }
9166}
9167
9168#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9169#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9170#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9171/// Clause types used with SHOW ... IN/FROM.
9172pub enum ShowStatementInClause {
9173    /// Use the `IN` clause.
9174    IN,
9175    /// Use the `FROM` clause.
9176    FROM,
9177}
9178
9179impl fmt::Display for ShowStatementInClause {
9180    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9181        use ShowStatementInClause::*;
9182        match self {
9183            FROM => write!(f, "FROM"),
9184            IN => write!(f, "IN"),
9185        }
9186    }
9187}
9188
9189/// Sqlite specific syntax
9190///
9191/// See [Sqlite documentation](https://sqlite.org/lang_conflict.html)
9192/// for more details.
9193#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9194#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9195#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9196pub enum SqliteOnConflict {
9197    /// Use ROLLBACK on conflict.
9198    Rollback,
9199    /// Use ABORT on conflict.
9200    Abort,
9201    /// Use FAIL on conflict.
9202    Fail,
9203    /// Use IGNORE on conflict.
9204    Ignore,
9205    /// Use REPLACE on conflict.
9206    Replace,
9207}
9208
9209impl fmt::Display for SqliteOnConflict {
9210    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9211        use SqliteOnConflict::*;
9212        match self {
9213            Rollback => write!(f, "OR ROLLBACK"),
9214            Abort => write!(f, "OR ABORT"),
9215            Fail => write!(f, "OR FAIL"),
9216            Ignore => write!(f, "OR IGNORE"),
9217            Replace => write!(f, "OR REPLACE"),
9218        }
9219    }
9220}
9221
9222/// Mysql specific syntax
9223///
9224/// See [Mysql documentation](https://dev.mysql.com/doc/refman/8.0/en/replace.html)
9225/// See [Mysql documentation](https://dev.mysql.com/doc/refman/8.0/en/insert.html)
9226/// for more details.
9227#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9228#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9229#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9230pub enum MysqlInsertPriority {
9231    /// LOW_PRIORITY modifier for INSERT/REPLACE.
9232    LowPriority,
9233    /// DELAYED modifier for INSERT/REPLACE.
9234    Delayed,
9235    /// HIGH_PRIORITY modifier for INSERT/REPLACE.
9236    HighPriority,
9237}
9238
9239impl fmt::Display for crate::ast::MysqlInsertPriority {
9240    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9241        use MysqlInsertPriority::*;
9242        match self {
9243            LowPriority => write!(f, "LOW_PRIORITY"),
9244            Delayed => write!(f, "DELAYED"),
9245            HighPriority => write!(f, "HIGH_PRIORITY"),
9246        }
9247    }
9248}
9249
9250#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9251#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9252#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9253/// Source for the `COPY` command: a table or a query.
9254pub enum CopySource {
9255    /// Copy from a table with optional column list.
9256    Table {
9257        /// The name of the table to copy from.
9258        table_name: ObjectName,
9259        /// A list of column names to copy. Empty list means that all columns
9260        /// are copied.
9261        columns: Vec<Ident>,
9262    },
9263    /// Copy from the results of a query.
9264    Query(Box<Query>),
9265}
9266
9267#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9268#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9269#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9270/// Target for the `COPY` command: STDIN, STDOUT, a file, or a program.
9271pub enum CopyTarget {
9272    /// Use standard input as the source.
9273    Stdin,
9274    /// Use standard output as the target.
9275    Stdout,
9276    /// Read from or write to a file.
9277    File {
9278        /// The path name of the input or output file.
9279        filename: String,
9280    },
9281    /// Use a program as the source or target (shell command).
9282    Program {
9283        /// A command to execute
9284        command: String,
9285    },
9286}
9287
9288impl fmt::Display for CopyTarget {
9289    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9290        use CopyTarget::*;
9291        match self {
9292            Stdin => write!(f, "STDIN"),
9293            Stdout => write!(f, "STDOUT"),
9294            File { filename } => write!(f, "'{}'", value::escape_single_quote_string(filename)),
9295            Program { command } => write!(
9296                f,
9297                "PROGRAM '{}'",
9298                value::escape_single_quote_string(command)
9299            ),
9300        }
9301    }
9302}
9303
9304#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9305#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9306#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9307/// Action to take `ON COMMIT` for temporary tables.
9308pub enum OnCommit {
9309    /// Delete rows on commit.
9310    DeleteRows,
9311    /// Preserve rows on commit.
9312    PreserveRows,
9313    /// Drop the table on commit.
9314    Drop,
9315}
9316
9317/// An option in `COPY` statement.
9318///
9319/// <https://www.postgresql.org/docs/14/sql-copy.html>
9320#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9321#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9322#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9323pub enum CopyOption {
9324    /// FORMAT format_name
9325    Format(Ident),
9326    /// FREEZE \[ boolean \]
9327    Freeze(bool),
9328    /// DELIMITER 'delimiter_character'
9329    Delimiter(char),
9330    /// NULL 'null_string'
9331    Null(String),
9332    /// HEADER \[ boolean \]
9333    Header(bool),
9334    /// QUOTE 'quote_character'
9335    Quote(char),
9336    /// ESCAPE 'escape_character'
9337    Escape(char),
9338    /// FORCE_QUOTE { ( column_name [, ...] ) | * }
9339    ForceQuote(Vec<Ident>),
9340    /// FORCE_NOT_NULL ( column_name [, ...] )
9341    ForceNotNull(Vec<Ident>),
9342    /// FORCE_NULL ( column_name [, ...] )
9343    ForceNull(Vec<Ident>),
9344    /// ENCODING 'encoding_name'
9345    Encoding(String),
9346}
9347
9348impl fmt::Display for CopyOption {
9349    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9350        use CopyOption::*;
9351        match self {
9352            Format(name) => write!(f, "FORMAT {name}"),
9353            Freeze(true) => write!(f, "FREEZE"),
9354            Freeze(false) => write!(f, "FREEZE FALSE"),
9355            Delimiter(char) => write!(f, "DELIMITER '{char}'"),
9356            Null(string) => write!(f, "NULL '{}'", value::escape_single_quote_string(string)),
9357            Header(true) => write!(f, "HEADER"),
9358            Header(false) => write!(f, "HEADER FALSE"),
9359            Quote(char) => write!(f, "QUOTE '{char}'"),
9360            Escape(char) => write!(f, "ESCAPE '{char}'"),
9361            ForceQuote(columns) => write!(f, "FORCE_QUOTE ({})", display_comma_separated(columns)),
9362            ForceNotNull(columns) => {
9363                write!(f, "FORCE_NOT_NULL ({})", display_comma_separated(columns))
9364            }
9365            ForceNull(columns) => write!(f, "FORCE_NULL ({})", display_comma_separated(columns)),
9366            Encoding(name) => write!(f, "ENCODING '{}'", value::escape_single_quote_string(name)),
9367        }
9368    }
9369}
9370
9371/// An option in `COPY` statement before PostgreSQL version 9.0.
9372///
9373/// [PostgreSQL](https://www.postgresql.org/docs/8.4/sql-copy.html)
9374/// [Redshift](https://docs.aws.amazon.com/redshift/latest/dg/r_COPY-alphabetical-parm-list.html)
9375#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9376#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9377#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9378pub enum CopyLegacyOption {
9379    /// ACCEPTANYDATE
9380    AcceptAnyDate,
9381    /// ACCEPTINVCHARS
9382    AcceptInvChars(Option<String>),
9383    /// ADDQUOTES
9384    AddQuotes,
9385    /// ALLOWOVERWRITE
9386    AllowOverwrite,
9387    /// BINARY
9388    Binary,
9389    /// BLANKSASNULL
9390    BlankAsNull,
9391    /// BZIP2
9392    Bzip2,
9393    /// CLEANPATH
9394    CleanPath,
9395    /// COMPUPDATE [ PRESET | { ON | TRUE } | { OFF | FALSE } ]
9396    CompUpdate {
9397        /// Whether the COMPUPDATE PRESET option was used.
9398        preset: bool,
9399        /// Optional enabled flag for COMPUPDATE.
9400        enabled: Option<bool>,
9401    },
9402    /// CSV ...
9403    Csv(Vec<CopyLegacyCsvOption>),
9404    /// DATEFORMAT \[ AS \] {'dateformat_string' | 'auto' }
9405    DateFormat(Option<String>),
9406    /// DELIMITER \[ AS \] 'delimiter_character'
9407    Delimiter(char),
9408    /// EMPTYASNULL
9409    EmptyAsNull,
9410    /// `ENCRYPTED \[ AUTO \]`
9411    Encrypted {
9412        /// Whether `AUTO` was specified for encryption.
9413        auto: bool,
9414    },
9415    /// ESCAPE
9416    Escape,
9417    /// EXTENSION 'extension-name'
9418    Extension(String),
9419    /// FIXEDWIDTH \[ AS \] 'fixedwidth-spec'
9420    FixedWidth(String),
9421    /// GZIP
9422    Gzip,
9423    /// HEADER
9424    Header,
9425    /// IAM_ROLE { DEFAULT | 'arn:aws:iam::123456789:role/role1' }
9426    IamRole(IamRoleKind),
9427    /// IGNOREHEADER \[ AS \] number_rows
9428    IgnoreHeader(u64),
9429    /// JSON \[ AS \] 'json_option'
9430    Json(Option<String>),
9431    /// MANIFEST \[ VERBOSE \]
9432    Manifest {
9433        /// Whether the MANIFEST is verbose.
9434        verbose: bool,
9435    },
9436    /// MAXFILESIZE \[ AS \] max-size \[ MB | GB \]
9437    MaxFileSize(FileSize),
9438    /// `NULL \[ AS \] 'null_string'`
9439    Null(String),
9440    /// `PARALLEL [ { ON | TRUE } | { OFF | FALSE } ]`
9441    Parallel(Option<bool>),
9442    /// PARQUET
9443    Parquet,
9444    /// PARTITION BY ( column_name [, ... ] ) \[ INCLUDE \]
9445    PartitionBy(UnloadPartitionBy),
9446    /// REGION \[ AS \] 'aws-region' }
9447    Region(String),
9448    /// REMOVEQUOTES
9449    RemoveQuotes,
9450    /// ROWGROUPSIZE \[ AS \] size \[ MB | GB \]
9451    RowGroupSize(FileSize),
9452    /// STATUPDATE [ { ON | TRUE } | { OFF | FALSE } ]
9453    StatUpdate(Option<bool>),
9454    /// TIMEFORMAT \[ AS \] {'timeformat_string' | 'auto' | 'epochsecs' | 'epochmillisecs' }
9455    TimeFormat(Option<String>),
9456    /// TRUNCATECOLUMNS
9457    TruncateColumns,
9458    /// ZSTD
9459    Zstd,
9460    /// Redshift `CREDENTIALS 'auth-args'`
9461    /// <https://docs.aws.amazon.com/redshift/latest/dg/copy-parameters-authorization.html>
9462    Credentials(String),
9463}
9464
9465impl fmt::Display for CopyLegacyOption {
9466    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9467        use CopyLegacyOption::*;
9468        match self {
9469            AcceptAnyDate => write!(f, "ACCEPTANYDATE"),
9470            AcceptInvChars(ch) => {
9471                write!(f, "ACCEPTINVCHARS")?;
9472                if let Some(ch) = ch {
9473                    write!(f, " '{}'", value::escape_single_quote_string(ch))?;
9474                }
9475                Ok(())
9476            }
9477            AddQuotes => write!(f, "ADDQUOTES"),
9478            AllowOverwrite => write!(f, "ALLOWOVERWRITE"),
9479            Binary => write!(f, "BINARY"),
9480            BlankAsNull => write!(f, "BLANKSASNULL"),
9481            Bzip2 => write!(f, "BZIP2"),
9482            CleanPath => write!(f, "CLEANPATH"),
9483            CompUpdate { preset, enabled } => {
9484                write!(f, "COMPUPDATE")?;
9485                if *preset {
9486                    write!(f, " PRESET")?;
9487                } else if let Some(enabled) = enabled {
9488                    write!(
9489                        f,
9490                        "{}",
9491                        match enabled {
9492                            true => " TRUE",
9493                            false => " FALSE",
9494                        }
9495                    )?;
9496                }
9497                Ok(())
9498            }
9499            Csv(opts) => {
9500                write!(f, "CSV")?;
9501                if !opts.is_empty() {
9502                    write!(f, " {}", display_separated(opts, " "))?;
9503                }
9504                Ok(())
9505            }
9506            DateFormat(fmt) => {
9507                write!(f, "DATEFORMAT")?;
9508                if let Some(fmt) = fmt {
9509                    write!(f, " '{}'", value::escape_single_quote_string(fmt))?;
9510                }
9511                Ok(())
9512            }
9513            Delimiter(char) => write!(f, "DELIMITER '{char}'"),
9514            EmptyAsNull => write!(f, "EMPTYASNULL"),
9515            Encrypted { auto } => write!(f, "ENCRYPTED{}", if *auto { " AUTO" } else { "" }),
9516            Escape => write!(f, "ESCAPE"),
9517            Extension(ext) => write!(f, "EXTENSION '{}'", value::escape_single_quote_string(ext)),
9518            FixedWidth(spec) => write!(
9519                f,
9520                "FIXEDWIDTH '{}'",
9521                value::escape_single_quote_string(spec)
9522            ),
9523            Gzip => write!(f, "GZIP"),
9524            Header => write!(f, "HEADER"),
9525            IamRole(role) => write!(f, "IAM_ROLE {role}"),
9526            IgnoreHeader(num_rows) => write!(f, "IGNOREHEADER {num_rows}"),
9527            Json(opt) => {
9528                write!(f, "JSON")?;
9529                if let Some(opt) = opt {
9530                    write!(f, " AS '{}'", value::escape_single_quote_string(opt))?;
9531                }
9532                Ok(())
9533            }
9534            Manifest { verbose } => write!(f, "MANIFEST{}", if *verbose { " VERBOSE" } else { "" }),
9535            MaxFileSize(file_size) => write!(f, "MAXFILESIZE {file_size}"),
9536            Null(string) => write!(f, "NULL '{}'", value::escape_single_quote_string(string)),
9537            Parallel(enabled) => {
9538                write!(
9539                    f,
9540                    "PARALLEL{}",
9541                    match enabled {
9542                        Some(true) => " TRUE",
9543                        Some(false) => " FALSE",
9544                        _ => "",
9545                    }
9546                )
9547            }
9548            Parquet => write!(f, "PARQUET"),
9549            PartitionBy(p) => write!(f, "{p}"),
9550            Region(region) => write!(f, "REGION '{}'", value::escape_single_quote_string(region)),
9551            RemoveQuotes => write!(f, "REMOVEQUOTES"),
9552            RowGroupSize(file_size) => write!(f, "ROWGROUPSIZE {file_size}"),
9553            StatUpdate(enabled) => {
9554                write!(
9555                    f,
9556                    "STATUPDATE{}",
9557                    match enabled {
9558                        Some(true) => " TRUE",
9559                        Some(false) => " FALSE",
9560                        _ => "",
9561                    }
9562                )
9563            }
9564            TimeFormat(fmt) => {
9565                write!(f, "TIMEFORMAT")?;
9566                if let Some(fmt) = fmt {
9567                    write!(f, " '{}'", value::escape_single_quote_string(fmt))?;
9568                }
9569                Ok(())
9570            }
9571            TruncateColumns => write!(f, "TRUNCATECOLUMNS"),
9572            Zstd => write!(f, "ZSTD"),
9573            Credentials(s) => write!(f, "CREDENTIALS '{}'", value::escape_single_quote_string(s)),
9574        }
9575    }
9576}
9577
9578/// ```sql
9579/// SIZE \[ MB | GB \]
9580/// ```
9581#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9582#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9583#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9584pub struct FileSize {
9585    /// Numeric size value.
9586    pub size: ValueWithSpan,
9587    /// Optional unit for the size (MB or GB).
9588    pub unit: Option<FileSizeUnit>,
9589}
9590
9591impl fmt::Display for FileSize {
9592    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9593        write!(f, "{}", self.size)?;
9594        if let Some(unit) = &self.unit {
9595            write!(f, " {unit}")?;
9596        }
9597        Ok(())
9598    }
9599}
9600
9601/// Units for `FileSize` (MB or GB).
9602#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9603#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9604#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9605pub enum FileSizeUnit {
9606    /// Megabytes.
9607    MB,
9608    /// Gigabytes.
9609    GB,
9610}
9611
9612impl fmt::Display for FileSizeUnit {
9613    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9614        match self {
9615            FileSizeUnit::MB => write!(f, "MB"),
9616            FileSizeUnit::GB => write!(f, "GB"),
9617        }
9618    }
9619}
9620
9621/// Specifies the partition keys for the unload operation
9622///
9623/// ```sql
9624/// PARTITION BY ( column_name [, ... ] ) [ INCLUDE ]
9625/// ```
9626#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9627#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9628#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9629pub struct UnloadPartitionBy {
9630    /// Columns used to partition the unload output.
9631    pub columns: Vec<Ident>,
9632    /// Whether to include the partition in the output.
9633    pub include: bool,
9634}
9635
9636impl fmt::Display for UnloadPartitionBy {
9637    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9638        write!(
9639            f,
9640            "PARTITION BY ({}){}",
9641            display_comma_separated(&self.columns),
9642            if self.include { " INCLUDE" } else { "" }
9643        )
9644    }
9645}
9646
9647/// An `IAM_ROLE` option in the AWS ecosystem
9648///
9649/// [Redshift COPY](https://docs.aws.amazon.com/redshift/latest/dg/copy-parameters-authorization.html#copy-iam-role)
9650#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9651#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9652#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9653pub enum IamRoleKind {
9654    /// Default role
9655    Default,
9656    /// Specific role ARN, for example: `arn:aws:iam::123456789:role/role1`
9657    Arn(String),
9658}
9659
9660impl fmt::Display for IamRoleKind {
9661    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9662        match self {
9663            IamRoleKind::Default => write!(f, "DEFAULT"),
9664            IamRoleKind::Arn(arn) => write!(f, "'{arn}'"),
9665        }
9666    }
9667}
9668
9669/// A `CSV` option in `COPY` statement before PostgreSQL version 9.0.
9670///
9671/// <https://www.postgresql.org/docs/8.4/sql-copy.html>
9672#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9673#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9674#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9675pub enum CopyLegacyCsvOption {
9676    /// HEADER
9677    Header,
9678    /// QUOTE \[ AS \] 'quote_character'
9679    Quote(char),
9680    /// ESCAPE \[ AS \] 'escape_character'
9681    Escape(char),
9682    /// FORCE QUOTE { column_name [, ...] | * }
9683    ForceQuote(Vec<Ident>),
9684    /// FORCE NOT NULL column_name [, ...]
9685    ForceNotNull(Vec<Ident>),
9686}
9687
9688impl fmt::Display for CopyLegacyCsvOption {
9689    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9690        use CopyLegacyCsvOption::*;
9691        match self {
9692            Header => write!(f, "HEADER"),
9693            Quote(char) => write!(f, "QUOTE '{char}'"),
9694            Escape(char) => write!(f, "ESCAPE '{char}'"),
9695            ForceQuote(columns) => write!(f, "FORCE QUOTE {}", display_comma_separated(columns)),
9696            ForceNotNull(columns) => {
9697                write!(f, "FORCE NOT NULL {}", display_comma_separated(columns))
9698            }
9699        }
9700    }
9701}
9702
9703/// Objects that can be discarded with `DISCARD`.
9704#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9705#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9706#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9707pub enum DiscardObject {
9708    /// Discard all session state.
9709    ALL,
9710    /// Discard cached plans.
9711    PLANS,
9712    /// Discard sequence values.
9713    SEQUENCES,
9714    /// Discard temporary objects.
9715    TEMP,
9716}
9717
9718impl fmt::Display for DiscardObject {
9719    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9720        match self {
9721            DiscardObject::ALL => f.write_str("ALL"),
9722            DiscardObject::PLANS => f.write_str("PLANS"),
9723            DiscardObject::SEQUENCES => f.write_str("SEQUENCES"),
9724            DiscardObject::TEMP => f.write_str("TEMP"),
9725        }
9726    }
9727}
9728
9729/// Types of flush operations supported by `FLUSH`.
9730#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9731#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9732#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9733pub enum FlushType {
9734    /// Flush binary logs.
9735    BinaryLogs,
9736    /// Flush engine logs.
9737    EngineLogs,
9738    /// Flush error logs.
9739    ErrorLogs,
9740    /// Flush general logs.
9741    GeneralLogs,
9742    /// Flush hosts information.
9743    Hosts,
9744    /// Flush logs.
9745    Logs,
9746    /// Flush privileges.
9747    Privileges,
9748    /// Flush optimizer costs.
9749    OptimizerCosts,
9750    /// Flush relay logs.
9751    RelayLogs,
9752    /// Flush slow logs.
9753    SlowLogs,
9754    /// Flush status.
9755    Status,
9756    /// Flush user resources.
9757    UserResources,
9758    /// Flush table data.
9759    Tables,
9760}
9761
9762impl fmt::Display for FlushType {
9763    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9764        match self {
9765            FlushType::BinaryLogs => f.write_str("BINARY LOGS"),
9766            FlushType::EngineLogs => f.write_str("ENGINE LOGS"),
9767            FlushType::ErrorLogs => f.write_str("ERROR LOGS"),
9768            FlushType::GeneralLogs => f.write_str("GENERAL LOGS"),
9769            FlushType::Hosts => f.write_str("HOSTS"),
9770            FlushType::Logs => f.write_str("LOGS"),
9771            FlushType::Privileges => f.write_str("PRIVILEGES"),
9772            FlushType::OptimizerCosts => f.write_str("OPTIMIZER_COSTS"),
9773            FlushType::RelayLogs => f.write_str("RELAY LOGS"),
9774            FlushType::SlowLogs => f.write_str("SLOW LOGS"),
9775            FlushType::Status => f.write_str("STATUS"),
9776            FlushType::UserResources => f.write_str("USER_RESOURCES"),
9777            FlushType::Tables => f.write_str("TABLES"),
9778        }
9779    }
9780}
9781
9782/// Location modifier for flush commands.
9783#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9784#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9785#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9786pub enum FlushLocation {
9787    /// Do not write changes to the binary log.
9788    NoWriteToBinlog,
9789    /// Apply flush locally.
9790    Local,
9791}
9792
9793impl fmt::Display for FlushLocation {
9794    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9795        match self {
9796            FlushLocation::NoWriteToBinlog => f.write_str("NO_WRITE_TO_BINLOG"),
9797            FlushLocation::Local => f.write_str("LOCAL"),
9798        }
9799    }
9800}
9801
9802/// Optional context modifier for statements that can be or `LOCAL`, `GLOBAL`, or `SESSION`.
9803#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9804#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9805#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9806pub enum ContextModifier {
9807    /// `LOCAL` identifier, usually related to transactional states.
9808    Local,
9809    /// `SESSION` identifier
9810    Session,
9811    /// `GLOBAL` identifier
9812    Global,
9813}
9814
9815impl fmt::Display for ContextModifier {
9816    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9817        match self {
9818            Self::Local => {
9819                write!(f, "LOCAL ")
9820            }
9821            Self::Session => {
9822                write!(f, "SESSION ")
9823            }
9824            Self::Global => {
9825                write!(f, "GLOBAL ")
9826            }
9827        }
9828    }
9829}
9830
9831/// Function describe in DROP FUNCTION.
9832#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9833#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9834pub enum DropFunctionOption {
9835    /// `RESTRICT` option for DROP FUNCTION.
9836    Restrict,
9837    /// `CASCADE` option for DROP FUNCTION.
9838    Cascade,
9839}
9840
9841impl fmt::Display for DropFunctionOption {
9842    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9843        match self {
9844            DropFunctionOption::Restrict => write!(f, "RESTRICT "),
9845            DropFunctionOption::Cascade => write!(f, "CASCADE  "),
9846        }
9847    }
9848}
9849
9850/// Generic function description for DROP FUNCTION and CREATE TRIGGER.
9851#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9852#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9853#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9854pub struct FunctionDesc {
9855    /// The function name.
9856    pub name: ObjectName,
9857    /// Optional list of function arguments.
9858    pub args: Option<Vec<OperateFunctionArg>>,
9859}
9860
9861impl fmt::Display for FunctionDesc {
9862    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9863        write!(f, "{}", self.name)?;
9864        if let Some(args) = &self.args {
9865            write!(f, "({})", display_comma_separated(args))?;
9866        }
9867        Ok(())
9868    }
9869}
9870
9871/// Function argument in CREATE OR DROP FUNCTION.
9872#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9873#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9874#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9875pub struct OperateFunctionArg {
9876    /// Optional argument mode (`IN`, `OUT`, `INOUT`).
9877    pub mode: Option<ArgMode>,
9878    /// Optional argument identifier/name.
9879    pub name: Option<Ident>,
9880    /// The data type of the argument.
9881    pub data_type: DataType,
9882    /// Optional default expression for the argument.
9883    pub default_expr: Option<Expr>,
9884}
9885
9886impl OperateFunctionArg {
9887    /// Returns an unnamed argument.
9888    pub fn unnamed(data_type: DataType) -> Self {
9889        Self {
9890            mode: None,
9891            name: None,
9892            data_type,
9893            default_expr: None,
9894        }
9895    }
9896
9897    /// Returns an argument with name.
9898    pub fn with_name(name: &str, data_type: DataType) -> Self {
9899        Self {
9900            mode: None,
9901            name: Some(name.into()),
9902            data_type,
9903            default_expr: None,
9904        }
9905    }
9906}
9907
9908impl fmt::Display for OperateFunctionArg {
9909    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9910        if let Some(mode) = &self.mode {
9911            write!(f, "{mode} ")?;
9912        }
9913        if let Some(name) = &self.name {
9914            write!(f, "{name} ")?;
9915        }
9916        write!(f, "{}", self.data_type)?;
9917        if let Some(default_expr) = &self.default_expr {
9918            write!(f, " = {default_expr}")?;
9919        }
9920        Ok(())
9921    }
9922}
9923
9924/// The mode of an argument in CREATE FUNCTION.
9925#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9926#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9927#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9928pub enum ArgMode {
9929    /// `IN` mode.
9930    In,
9931    /// `OUT` mode.
9932    Out,
9933    /// `INOUT` mode.
9934    InOut,
9935    /// `VARIADIC` mode.
9936    Variadic,
9937}
9938
9939impl fmt::Display for ArgMode {
9940    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9941        match self {
9942            ArgMode::In => write!(f, "IN"),
9943            ArgMode::Out => write!(f, "OUT"),
9944            ArgMode::InOut => write!(f, "INOUT"),
9945            ArgMode::Variadic => write!(f, "VARIADIC"),
9946        }
9947    }
9948}
9949
9950/// These attributes inform the query optimizer about the behavior of the function.
9951#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9952#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9953#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9954pub enum FunctionBehavior {
9955    /// Function is immutable.
9956    Immutable,
9957    /// Function is stable.
9958    Stable,
9959    /// Function is volatile.
9960    Volatile,
9961}
9962
9963impl fmt::Display for FunctionBehavior {
9964    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9965        match self {
9966            FunctionBehavior::Immutable => write!(f, "IMMUTABLE"),
9967            FunctionBehavior::Stable => write!(f, "STABLE"),
9968            FunctionBehavior::Volatile => write!(f, "VOLATILE"),
9969        }
9970    }
9971}
9972
9973/// Security attribute for functions: SECURITY DEFINER or SECURITY INVOKER.
9974///
9975/// [PostgreSQL](https://www.postgresql.org/docs/current/sql-createfunction.html)
9976#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9977#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9978#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9979pub enum FunctionSecurity {
9980    /// Execute the function with the privileges of the user who defined it.
9981    Definer,
9982    /// Execute the function with the privileges of the user who invokes it.
9983    Invoker,
9984}
9985
9986impl fmt::Display for FunctionSecurity {
9987    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9988        match self {
9989            FunctionSecurity::Definer => write!(f, "SECURITY DEFINER"),
9990            FunctionSecurity::Invoker => write!(f, "SECURITY INVOKER"),
9991        }
9992    }
9993}
9994
9995/// Value for a SET configuration parameter in a CREATE FUNCTION statement.
9996///
9997/// [PostgreSQL](https://www.postgresql.org/docs/current/sql-createfunction.html)
9998#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9999#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10000#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10001pub enum FunctionSetValue {
10002    /// SET param = DEFAULT / SET param TO DEFAULT
10003    Default,
10004    /// SET param = value1, value2, ...
10005    Values(Vec<Expr>),
10006    /// SET param FROM CURRENT
10007    FromCurrent,
10008}
10009
10010/// A SET configuration_parameter clause in a CREATE FUNCTION statement.
10011///
10012/// [PostgreSQL](https://www.postgresql.org/docs/current/sql-createfunction.html)
10013#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10014#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10015#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10016pub struct FunctionDefinitionSetParam {
10017    /// The name of the configuration parameter.
10018    pub name: ObjectName,
10019    /// The value to set for the parameter.
10020    pub value: FunctionSetValue,
10021}
10022
10023impl fmt::Display for FunctionDefinitionSetParam {
10024    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10025        write!(f, "SET {} ", self.name)?;
10026        match &self.value {
10027            FunctionSetValue::Default => write!(f, "= DEFAULT"),
10028            FunctionSetValue::Values(values) => {
10029                write!(f, "= {}", display_comma_separated(values))
10030            }
10031            FunctionSetValue::FromCurrent => write!(f, "FROM CURRENT"),
10032        }
10033    }
10034}
10035
10036/// These attributes describe the behavior of the function when called with a null argument.
10037#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10038#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10039#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10040pub enum FunctionCalledOnNull {
10041    /// Function is called even when inputs are null.
10042    CalledOnNullInput,
10043    /// Function returns null when any input is null.
10044    ReturnsNullOnNullInput,
10045    /// Function is strict about null inputs.
10046    Strict,
10047}
10048
10049impl fmt::Display for FunctionCalledOnNull {
10050    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10051        match self {
10052            FunctionCalledOnNull::CalledOnNullInput => write!(f, "CALLED ON NULL INPUT"),
10053            FunctionCalledOnNull::ReturnsNullOnNullInput => write!(f, "RETURNS NULL ON NULL INPUT"),
10054            FunctionCalledOnNull::Strict => write!(f, "STRICT"),
10055        }
10056    }
10057}
10058
10059/// If it is safe for PostgreSQL to call the function from multiple threads at once
10060#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10061#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10062#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10063pub enum FunctionParallel {
10064    /// The function is not safe to run in parallel.
10065    Unsafe,
10066    /// The function is restricted for parallel execution.
10067    Restricted,
10068    /// The function is safe to run in parallel.
10069    Safe,
10070}
10071
10072impl fmt::Display for FunctionParallel {
10073    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10074        match self {
10075            FunctionParallel::Unsafe => write!(f, "PARALLEL UNSAFE"),
10076            FunctionParallel::Restricted => write!(f, "PARALLEL RESTRICTED"),
10077            FunctionParallel::Safe => write!(f, "PARALLEL SAFE"),
10078        }
10079    }
10080}
10081
10082/// [BigQuery] Determinism specifier used in a UDF definition.
10083///
10084/// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#syntax_11
10085#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10086#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10087#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10088pub enum FunctionDeterminismSpecifier {
10089    /// Function is deterministic.
10090    Deterministic,
10091    /// Function is not deterministic.
10092    NotDeterministic,
10093}
10094
10095impl fmt::Display for FunctionDeterminismSpecifier {
10096    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10097        match self {
10098            FunctionDeterminismSpecifier::Deterministic => {
10099                write!(f, "DETERMINISTIC")
10100            }
10101            FunctionDeterminismSpecifier::NotDeterministic => {
10102                write!(f, "NOT DETERMINISTIC")
10103            }
10104        }
10105    }
10106}
10107
10108/// Represent the expression body of a `CREATE FUNCTION` statement as well as
10109/// where within the statement, the body shows up.
10110///
10111/// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#syntax_11
10112/// [PostgreSQL]: https://www.postgresql.org/docs/15/sql-createfunction.html
10113/// [MsSql]: https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql
10114#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10115#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10116#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10117pub enum CreateFunctionBody {
10118    /// A function body expression using the 'AS' keyword and shows up
10119    /// before any `OPTIONS` clause.
10120    ///
10121    /// Example:
10122    /// ```sql
10123    /// CREATE FUNCTION myfunc(x FLOAT64, y FLOAT64) RETURNS FLOAT64
10124    /// AS (x * y)
10125    /// OPTIONS(description="desc");
10126    /// ```
10127    ///
10128    /// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#syntax_11
10129    /// [PostgreSQL]: https://www.postgresql.org/docs/current/sql-createfunction.html
10130    AsBeforeOptions {
10131        /// The primary expression.
10132        body: Expr,
10133        /// Link symbol if the primary expression contains the name of shared library file.
10134        ///
10135        /// Example:
10136        /// ```sql
10137        /// CREATE FUNCTION cas_in(input cstring) RETURNS cas
10138        /// AS 'MODULE_PATHNAME', 'cas_in_wrapper'
10139        /// ```
10140        /// [PostgreSQL]: https://www.postgresql.org/docs/current/sql-createfunction.html
10141        link_symbol: Option<Expr>,
10142    },
10143    /// A function body expression using the 'AS' keyword and shows up
10144    /// after any `OPTIONS` clause.
10145    ///
10146    /// Example:
10147    /// ```sql
10148    /// CREATE FUNCTION myfunc(x FLOAT64, y FLOAT64) RETURNS FLOAT64
10149    /// OPTIONS(description="desc")
10150    /// AS (x * y);
10151    /// ```
10152    ///
10153    /// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#syntax_11
10154    AsAfterOptions(Expr),
10155    /// Function body with statements before the `RETURN` keyword.
10156    ///
10157    /// Example:
10158    /// ```sql
10159    /// CREATE FUNCTION my_scalar_udf(a INT, b INT)
10160    /// RETURNS INT
10161    /// AS
10162    /// BEGIN
10163    ///     DECLARE c INT;
10164    ///     SET c = a + b;
10165    ///     RETURN c;
10166    /// END
10167    /// ```
10168    ///
10169    /// [MsSql]: https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql
10170    AsBeginEnd(BeginEndStatements),
10171    /// Function body expression using the 'RETURN' keyword.
10172    ///
10173    /// Example:
10174    /// ```sql
10175    /// CREATE FUNCTION myfunc(a INTEGER, IN b INTEGER = 1) RETURNS INTEGER
10176    /// LANGUAGE SQL
10177    /// RETURN a + b;
10178    /// ```
10179    ///
10180    /// [PostgreSQL]: https://www.postgresql.org/docs/current/sql-createfunction.html
10181    Return(Expr),
10182
10183    /// Function body expression using the 'AS RETURN' keywords
10184    ///
10185    /// Example:
10186    /// ```sql
10187    /// CREATE FUNCTION myfunc(a INT, b INT)
10188    /// RETURNS TABLE
10189    /// AS RETURN (SELECT a + b AS sum);
10190    /// ```
10191    ///
10192    /// [MsSql]: https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql
10193    AsReturnExpr(Expr),
10194
10195    /// Function body expression using the 'AS RETURN' keywords, with an un-parenthesized SELECT query
10196    ///
10197    /// Example:
10198    /// ```sql
10199    /// CREATE FUNCTION myfunc(a INT, b INT)
10200    /// RETURNS TABLE
10201    /// AS RETURN SELECT a + b AS sum;
10202    /// ```
10203    ///
10204    /// [MsSql]: https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql?view=sql-server-ver16#select_stmt
10205    AsReturnSelect(Select),
10206}
10207
10208#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10209#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10210#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10211/// `USING` clause options for `CREATE FUNCTION` (e.g., JAR, FILE, ARCHIVE).
10212pub enum CreateFunctionUsing {
10213    /// Use a JAR file located at the given URI.
10214    Jar(String),
10215    /// Use a file located at the given URI.
10216    File(String),
10217    /// Use an archive located at the given URI.
10218    Archive(String),
10219}
10220
10221impl fmt::Display for CreateFunctionUsing {
10222    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10223        write!(f, "USING ")?;
10224        match self {
10225            CreateFunctionUsing::Jar(uri) => write!(f, "JAR '{uri}'"),
10226            CreateFunctionUsing::File(uri) => write!(f, "FILE '{uri}'"),
10227            CreateFunctionUsing::Archive(uri) => write!(f, "ARCHIVE '{uri}'"),
10228        }
10229    }
10230}
10231
10232/// `NAME = <EXPR>` arguments for DuckDB macros
10233///
10234/// See [Create Macro - DuckDB](https://duckdb.org/docs/sql/statements/create_macro)
10235/// for more details
10236#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10237#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10238#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10239pub struct MacroArg {
10240    /// The argument name.
10241    pub name: Ident,
10242    /// Optional default expression for the argument.
10243    pub default_expr: Option<Expr>,
10244}
10245
10246impl MacroArg {
10247    /// Returns an argument with name.
10248    pub fn new(name: &str) -> Self {
10249        Self {
10250            name: name.into(),
10251            default_expr: None,
10252        }
10253    }
10254}
10255
10256impl fmt::Display for MacroArg {
10257    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10258        write!(f, "{}", self.name)?;
10259        if let Some(default_expr) = &self.default_expr {
10260            write!(f, " := {default_expr}")?;
10261        }
10262        Ok(())
10263    }
10264}
10265
10266#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10267#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10268#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10269/// Definition for a DuckDB macro: either an expression or a table-producing query.
10270pub enum MacroDefinition {
10271    /// The macro is defined as an expression.
10272    Expr(Expr),
10273    /// The macro is defined as a table (query).
10274    Table(Box<Query>),
10275}
10276
10277impl fmt::Display for MacroDefinition {
10278    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10279        match self {
10280            MacroDefinition::Expr(expr) => write!(f, "{expr}")?,
10281            MacroDefinition::Table(query) => write!(f, "{query}")?,
10282        }
10283        Ok(())
10284    }
10285}
10286
10287/// Schema possible naming variants ([1]).
10288///
10289/// [1]: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#schema-definition
10290#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10291#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10292#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10293pub enum SchemaName {
10294    /// Only schema name specified: `<schema name>`.
10295    Simple(ObjectName),
10296    /// Only authorization identifier specified: `AUTHORIZATION <schema authorization identifier>`.
10297    UnnamedAuthorization(Ident),
10298    /// Both schema name and authorization identifier specified: `<schema name>  AUTHORIZATION <schema authorization identifier>`.
10299    NamedAuthorization(ObjectName, Ident),
10300}
10301
10302impl fmt::Display for SchemaName {
10303    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10304        match self {
10305            SchemaName::Simple(name) => {
10306                write!(f, "{name}")
10307            }
10308            SchemaName::UnnamedAuthorization(authorization) => {
10309                write!(f, "AUTHORIZATION {authorization}")
10310            }
10311            SchemaName::NamedAuthorization(name, authorization) => {
10312                write!(f, "{name} AUTHORIZATION {authorization}")
10313            }
10314        }
10315    }
10316}
10317
10318/// Fulltext search modifiers ([1]).
10319///
10320/// [1]: https://dev.mysql.com/doc/refman/8.0/en/fulltext-search.html#function_match
10321#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10322#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10323#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10324pub enum SearchModifier {
10325    /// `IN NATURAL LANGUAGE MODE`.
10326    InNaturalLanguageMode,
10327    /// `IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION`.
10328    InNaturalLanguageModeWithQueryExpansion,
10329    ///`IN BOOLEAN MODE`.
10330    InBooleanMode,
10331    ///`WITH QUERY EXPANSION`.
10332    WithQueryExpansion,
10333}
10334
10335impl fmt::Display for SearchModifier {
10336    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10337        match self {
10338            Self::InNaturalLanguageMode => {
10339                write!(f, "IN NATURAL LANGUAGE MODE")?;
10340            }
10341            Self::InNaturalLanguageModeWithQueryExpansion => {
10342                write!(f, "IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION")?;
10343            }
10344            Self::InBooleanMode => {
10345                write!(f, "IN BOOLEAN MODE")?;
10346            }
10347            Self::WithQueryExpansion => {
10348                write!(f, "WITH QUERY EXPANSION")?;
10349            }
10350        }
10351
10352        Ok(())
10353    }
10354}
10355
10356/// Represents a `LOCK TABLE` clause with optional alias and lock type.
10357#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10358#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10359#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10360pub struct LockTable {
10361    /// The table identifier to lock.
10362    pub table: Ident,
10363    /// Optional alias for the table.
10364    pub alias: Option<Ident>,
10365    /// The type of lock to apply to the table.
10366    pub lock_type: LockTableType,
10367}
10368
10369impl fmt::Display for LockTable {
10370    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10371        let Self {
10372            table: tbl_name,
10373            alias,
10374            lock_type,
10375        } = self;
10376
10377        write!(f, "{tbl_name} ")?;
10378        if let Some(alias) = alias {
10379            write!(f, "AS {alias} ")?;
10380        }
10381        write!(f, "{lock_type}")?;
10382        Ok(())
10383    }
10384}
10385
10386#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10387#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10388#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10389/// The type of lock used in `LOCK TABLE` statements.
10390pub enum LockTableType {
10391    /// Shared/read lock. If `local` is true, it's a local read lock.
10392    Read {
10393        /// Whether the read lock is local.
10394        local: bool,
10395    },
10396    /// Exclusive/write lock. If `low_priority` is true, the write is low priority.
10397    Write {
10398        /// Whether the write lock is low priority.
10399        low_priority: bool,
10400    },
10401}
10402
10403impl fmt::Display for LockTableType {
10404    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10405        match self {
10406            Self::Read { local } => {
10407                write!(f, "READ")?;
10408                if *local {
10409                    write!(f, " LOCAL")?;
10410                }
10411            }
10412            Self::Write { low_priority } => {
10413                if *low_priority {
10414                    write!(f, "LOW_PRIORITY ")?;
10415                }
10416                write!(f, "WRITE")?;
10417            }
10418        }
10419
10420        Ok(())
10421    }
10422}
10423
10424#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10425#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10426#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10427/// Hive-specific `SET LOCATION` helper used in some `LOAD DATA` statements.
10428pub struct HiveSetLocation {
10429    /// Whether the `SET` keyword was present.
10430    pub has_set: bool,
10431    /// The location identifier.
10432    pub location: Ident,
10433}
10434
10435impl fmt::Display for HiveSetLocation {
10436    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10437        if self.has_set {
10438            write!(f, "SET ")?;
10439        }
10440        write!(f, "LOCATION {}", self.location)
10441    }
10442}
10443
10444/// MySQL `ALTER TABLE` only  [FIRST | AFTER column_name]
10445#[allow(clippy::large_enum_variant)]
10446#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10447#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10448#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10449/// MySQL `ALTER TABLE` column position specifier: `FIRST` or `AFTER <column>`.
10450pub enum MySQLColumnPosition {
10451    /// Place the column first in the table.
10452    First,
10453    /// Place the column after the specified identifier.
10454    After(Ident),
10455}
10456
10457impl Display for MySQLColumnPosition {
10458    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10459        match self {
10460            MySQLColumnPosition::First => write!(f, "FIRST"),
10461            MySQLColumnPosition::After(ident) => {
10462                let column_name = &ident.value;
10463                write!(f, "AFTER {column_name}")
10464            }
10465        }
10466    }
10467}
10468
10469/// MySQL `CREATE VIEW` algorithm parameter: [ALGORITHM = {UNDEFINED | MERGE | TEMPTABLE}]
10470#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10471#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10472#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10473/// MySQL `CREATE VIEW` algorithm options.
10474pub enum CreateViewAlgorithm {
10475    /// `UNDEFINED` algorithm.
10476    Undefined,
10477    /// `MERGE` algorithm.
10478    Merge,
10479    /// `TEMPTABLE` algorithm.
10480    TempTable,
10481}
10482
10483impl Display for CreateViewAlgorithm {
10484    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10485        match self {
10486            CreateViewAlgorithm::Undefined => write!(f, "UNDEFINED"),
10487            CreateViewAlgorithm::Merge => write!(f, "MERGE"),
10488            CreateViewAlgorithm::TempTable => write!(f, "TEMPTABLE"),
10489        }
10490    }
10491}
10492/// MySQL `CREATE VIEW` security parameter: [SQL SECURITY { DEFINER | INVOKER }]
10493#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10494#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10495#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10496/// MySQL `CREATE VIEW` SQL SECURITY options.
10497pub enum CreateViewSecurity {
10498    /// The view runs with the privileges of the definer.
10499    Definer,
10500    /// The view runs with the privileges of the invoker.
10501    Invoker,
10502}
10503
10504impl Display for CreateViewSecurity {
10505    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10506        match self {
10507            CreateViewSecurity::Definer => write!(f, "DEFINER"),
10508            CreateViewSecurity::Invoker => write!(f, "INVOKER"),
10509        }
10510    }
10511}
10512
10513/// [MySQL] `CREATE VIEW` additional parameters
10514///
10515/// [MySQL]: https://dev.mysql.com/doc/refman/9.1/en/create-view.html
10516#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10517#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10518#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10519pub struct CreateViewParams {
10520    /// Optional view algorithm (e.g., MERGE, TEMPTABLE).
10521    pub algorithm: Option<CreateViewAlgorithm>,
10522    /// Optional definer (the security principal that will own the view).
10523    pub definer: Option<GranteeName>,
10524    /// Optional SQL SECURITY setting for the view.
10525    pub security: Option<CreateViewSecurity>,
10526}
10527
10528impl Display for CreateViewParams {
10529    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10530        let CreateViewParams {
10531            algorithm,
10532            definer,
10533            security,
10534        } = self;
10535        if let Some(algorithm) = algorithm {
10536            write!(f, "ALGORITHM = {algorithm} ")?;
10537        }
10538        if let Some(definers) = definer {
10539            write!(f, "DEFINER = {definers} ")?;
10540        }
10541        if let Some(security) = security {
10542            write!(f, "SQL SECURITY {security} ")?;
10543        }
10544        Ok(())
10545    }
10546}
10547
10548#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10549#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10550#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10551/// Key/Value, where the value is a (optionally named) list of identifiers
10552///
10553/// ```sql
10554/// UNION = (tbl_name[,tbl_name]...)
10555/// ENGINE = ReplicatedMergeTree('/table_name','{replica}', ver)
10556/// ENGINE = SummingMergeTree([columns])
10557/// ```
10558pub struct NamedParenthesizedList {
10559    /// The option key (identifier) for this named list.
10560    pub key: Ident,
10561    /// Optional secondary name associated with the key.
10562    pub name: Option<Ident>,
10563    /// The list of identifier values for the key.
10564    pub values: Vec<Ident>,
10565}
10566
10567/// Snowflake `WITH ROW ACCESS POLICY policy_name ON (identifier, ...)`
10568///
10569/// <https://docs.snowflake.com/en/sql-reference/sql/create-table>
10570/// <https://docs.snowflake.com/en/user-guide/security-row-intro>
10571#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10572#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10573#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10574pub struct RowAccessPolicy {
10575    /// The fully-qualified policy object name.
10576    pub policy: ObjectName,
10577    /// Identifiers for the columns or objects the policy applies to.
10578    pub on: Vec<Ident>,
10579}
10580
10581impl RowAccessPolicy {
10582    /// Create a new `RowAccessPolicy` for the given `policy` and `on` identifiers.
10583    pub fn new(policy: ObjectName, on: Vec<Ident>) -> Self {
10584        Self { policy, on }
10585    }
10586}
10587
10588impl Display for RowAccessPolicy {
10589    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10590        write!(
10591            f,
10592            "WITH ROW ACCESS POLICY {} ON ({})",
10593            self.policy,
10594            display_comma_separated(self.on.as_slice())
10595        )
10596    }
10597}
10598
10599/// Snowflake `[ WITH ] STORAGE LIFECYCLE POLICY <policy_name> ON ( <col_name> [ , ... ] )`
10600///
10601/// <https://docs.snowflake.com/en/sql-reference/sql/create-table>
10602#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10603#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10604#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10605pub struct StorageLifecyclePolicy {
10606    /// The fully-qualified policy object name.
10607    pub policy: ObjectName,
10608    /// Column names the policy applies to.
10609    pub on: Vec<Ident>,
10610}
10611
10612impl Display for StorageLifecyclePolicy {
10613    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10614        write!(
10615            f,
10616            "WITH STORAGE LIFECYCLE POLICY {} ON ({})",
10617            self.policy,
10618            display_comma_separated(self.on.as_slice())
10619        )
10620    }
10621}
10622
10623/// Snowflake `WITH TAG ( tag_name = '<tag_value>', ...)`
10624///
10625/// <https://docs.snowflake.com/en/sql-reference/sql/create-table>
10626#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10627#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10628#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10629pub struct Tag {
10630    /// The tag key (can be qualified).
10631    pub key: ObjectName,
10632    /// The tag value as a string.
10633    pub value: String,
10634}
10635
10636impl Tag {
10637    /// Create a new `Tag` with the given key and value.
10638    pub fn new(key: ObjectName, value: String) -> Self {
10639        Self { key, value }
10640    }
10641}
10642
10643impl Display for Tag {
10644    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10645        write!(f, "{}='{}'", self.key, self.value)
10646    }
10647}
10648
10649/// Snowflake `WITH CONTACT ( purpose = contact [ , purpose = contact ...] )`
10650///
10651/// <https://docs.snowflake.com/en/sql-reference/sql/create-database>
10652#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10653#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10654#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10655pub struct ContactEntry {
10656    /// The purpose label for the contact entry.
10657    pub purpose: String,
10658    /// The contact information associated with the purpose.
10659    pub contact: String,
10660}
10661
10662impl Display for ContactEntry {
10663    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10664        write!(f, "{} = {}", self.purpose, self.contact)
10665    }
10666}
10667
10668/// Helper to indicate if a comment includes the `=` in the display form
10669#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10670#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10671#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10672pub enum CommentDef {
10673    /// Includes `=` when printing the comment, as `COMMENT = 'comment'`
10674    /// Does not include `=` when printing the comment, as `COMMENT 'comment'`
10675    WithEq(String),
10676    /// Comment variant that omits the `=` when displayed.
10677    WithoutEq(String),
10678}
10679
10680impl Display for CommentDef {
10681    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10682        match self {
10683            CommentDef::WithEq(comment) | CommentDef::WithoutEq(comment) => write!(f, "{comment}"),
10684        }
10685    }
10686}
10687
10688/// Helper to indicate if a collection should be wrapped by a symbol in the display form
10689///
10690/// [`Display`] is implemented for every [`Vec<T>`] where `T: Display`.
10691/// The string output is a comma separated list for the vec items
10692///
10693/// # Examples
10694/// ```
10695/// # use sqlparser::ast::WrappedCollection;
10696/// let items = WrappedCollection::Parentheses(vec!["one", "two", "three"]);
10697/// assert_eq!("(one, two, three)", items.to_string());
10698///
10699/// let items = WrappedCollection::NoWrapping(vec!["one", "two", "three"]);
10700/// assert_eq!("one, two, three", items.to_string());
10701/// ```
10702#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10703#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10704#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10705pub enum WrappedCollection<T> {
10706    /// Print the collection without wrapping symbols, as `item, item, item`
10707    NoWrapping(T),
10708    /// Wraps the collection in Parentheses, as `(item, item, item)`
10709    Parentheses(T),
10710}
10711
10712impl<T> Display for WrappedCollection<Vec<T>>
10713where
10714    T: Display,
10715{
10716    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10717        match self {
10718            WrappedCollection::NoWrapping(inner) => {
10719                write!(f, "{}", display_comma_separated(inner.as_slice()))
10720            }
10721            WrappedCollection::Parentheses(inner) => {
10722                write!(f, "({})", display_comma_separated(inner.as_slice()))
10723            }
10724        }
10725    }
10726}
10727
10728/// Represents a single PostgreSQL utility option.
10729///
10730/// A utility option is a key-value pair where the key is an identifier (IDENT) and the value
10731/// can be one of the following:
10732/// - A number with an optional sign (`+` or `-`). Example: `+10`, `-10.2`, `3`
10733/// - A non-keyword string. Example: `option1`, `'option2'`, `"option3"`
10734/// - keyword: `TRUE`, `FALSE`, `ON` (`off` is also accept).
10735/// - Empty. Example: `ANALYZE` (identifier only)
10736///
10737/// Utility options are used in various PostgreSQL DDL statements, including statements such as
10738/// `CLUSTER`, `EXPLAIN`, `VACUUM`, and `REINDEX`. These statements format options as `( option [, ...] )`.
10739///
10740/// [CLUSTER](https://www.postgresql.org/docs/current/sql-cluster.html)
10741/// [EXPLAIN](https://www.postgresql.org/docs/current/sql-explain.html)
10742/// [VACUUM](https://www.postgresql.org/docs/current/sql-vacuum.html)
10743/// [REINDEX](https://www.postgresql.org/docs/current/sql-reindex.html)
10744///
10745/// For example, the `EXPLAIN` AND `VACUUM` statements with options might look like this:
10746/// ```sql
10747/// EXPLAIN (ANALYZE, VERBOSE TRUE, FORMAT TEXT) SELECT * FROM my_table;
10748///
10749/// VACUUM (VERBOSE, ANALYZE ON, PARALLEL 10) my_table;
10750/// ```
10751#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10752#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10753#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10754pub struct UtilityOption {
10755    /// The option name (identifier).
10756    pub name: Ident,
10757    /// Optional argument for the option (number, string, keyword, etc.).
10758    pub arg: Option<Expr>,
10759}
10760
10761impl Display for UtilityOption {
10762    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10763        if let Some(ref arg) = self.arg {
10764            write!(f, "{} {}", self.name, arg)
10765        } else {
10766            write!(f, "{}", self.name)
10767        }
10768    }
10769}
10770
10771/// Represents the different options available for `SHOW`
10772/// statements to filter the results. Example from Snowflake:
10773/// <https://docs.snowflake.com/en/sql-reference/sql/show-tables>
10774#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10775#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10776#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10777pub struct ShowStatementOptions {
10778    /// Optional scope to show in (for example: TABLE, SCHEMA).
10779    pub show_in: Option<ShowStatementIn>,
10780    /// Optional `STARTS WITH` filter value.
10781    pub starts_with: Option<ValueWithSpan>,
10782    /// Optional `LIMIT` expression.
10783    pub limit: Option<Expr>,
10784    /// Optional `FROM` value used with `LIMIT`.
10785    pub limit_from: Option<ValueWithSpan>,
10786    /// Optional filter position (infix or suffix) for `LIKE`/`FILTER`.
10787    pub filter_position: Option<ShowStatementFilterPosition>,
10788}
10789
10790impl Display for ShowStatementOptions {
10791    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10792        let (like_in_infix, like_in_suffix) = match &self.filter_position {
10793            Some(ShowStatementFilterPosition::Infix(filter)) => {
10794                (format!(" {filter}"), "".to_string())
10795            }
10796            Some(ShowStatementFilterPosition::Suffix(filter)) => {
10797                ("".to_string(), format!(" {filter}"))
10798            }
10799            None => ("".to_string(), "".to_string()),
10800        };
10801        write!(
10802            f,
10803            "{like_in_infix}{show_in}{starts_with}{limit}{from}{like_in_suffix}",
10804            show_in = match &self.show_in {
10805                Some(i) => format!(" {i}"),
10806                None => String::new(),
10807            },
10808            starts_with = match &self.starts_with {
10809                Some(s) => format!(" STARTS WITH {s}"),
10810                None => String::new(),
10811            },
10812            limit = match &self.limit {
10813                Some(l) => format!(" LIMIT {l}"),
10814                None => String::new(),
10815            },
10816            from = match &self.limit_from {
10817                Some(f) => format!(" FROM {f}"),
10818                None => String::new(),
10819            }
10820        )?;
10821        Ok(())
10822    }
10823}
10824
10825#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10826#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10827#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10828/// Where a `SHOW` filter appears relative to the main clause.
10829pub enum ShowStatementFilterPosition {
10830    /// Put the filter in an infix position (e.g. `SHOW COLUMNS LIKE '%name%' IN TABLE tbl`).
10831    Infix(ShowStatementFilter), // For example: SHOW COLUMNS LIKE '%name%' IN TABLE tbl
10832    /// Put the filter in a suffix position (e.g. `SHOW COLUMNS IN tbl LIKE '%name%'`).
10833    Suffix(ShowStatementFilter), // For example: SHOW COLUMNS IN tbl LIKE '%name%'
10834}
10835
10836#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10837#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10838#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10839/// Parent object types usable with `SHOW ... IN <parent>` clauses.
10840pub enum ShowStatementInParentType {
10841    /// ACCOUNT parent type for SHOW statements.
10842    Account,
10843    /// DATABASE parent type for SHOW statements.
10844    Database,
10845    /// SCHEMA parent type for SHOW statements.
10846    Schema,
10847    /// TABLE parent type for SHOW statements.
10848    Table,
10849    /// VIEW parent type for SHOW statements.
10850    View,
10851}
10852
10853impl fmt::Display for ShowStatementInParentType {
10854    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10855        match self {
10856            ShowStatementInParentType::Account => write!(f, "ACCOUNT"),
10857            ShowStatementInParentType::Database => write!(f, "DATABASE"),
10858            ShowStatementInParentType::Schema => write!(f, "SCHEMA"),
10859            ShowStatementInParentType::Table => write!(f, "TABLE"),
10860            ShowStatementInParentType::View => write!(f, "VIEW"),
10861        }
10862    }
10863}
10864
10865#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10866#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10867#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10868/// Represents a `SHOW ... IN` clause with optional parent qualifier and name.
10869pub struct ShowStatementIn {
10870    /// The clause that specifies what to show (e.g. COLUMNS, TABLES).
10871    pub clause: ShowStatementInClause,
10872    /// Optional parent type qualifier (ACCOUNT/DATABASE/...).
10873    pub parent_type: Option<ShowStatementInParentType>,
10874    /// Optional parent object name for the SHOW clause.
10875    #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
10876    pub parent_name: Option<ObjectName>,
10877}
10878
10879impl fmt::Display for ShowStatementIn {
10880    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10881        write!(f, "{}", self.clause)?;
10882        if let Some(parent_type) = &self.parent_type {
10883            write!(f, " {parent_type}")?;
10884        }
10885        if let Some(parent_name) = &self.parent_name {
10886            write!(f, " {parent_name}")?;
10887        }
10888        Ok(())
10889    }
10890}
10891
10892/// A Show Charset statement
10893#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10894#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10895#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10896pub struct ShowCharset {
10897    /// The statement can be written as `SHOW CHARSET` or `SHOW CHARACTER SET`
10898    /// true means CHARSET was used and false means CHARACTER SET was used
10899    pub is_shorthand: bool,
10900    /// Optional `LIKE`/`WHERE`-style filter for the statement.
10901    pub filter: Option<ShowStatementFilter>,
10902}
10903
10904impl fmt::Display for ShowCharset {
10905    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10906        write!(f, "SHOW")?;
10907        if self.is_shorthand {
10908            write!(f, " CHARSET")?;
10909        } else {
10910            write!(f, " CHARACTER SET")?;
10911        }
10912        if let Some(filter) = &self.filter {
10913            write!(f, " {filter}")?;
10914        }
10915        Ok(())
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))]
10922/// Options for a `SHOW OBJECTS` statement.
10923pub struct ShowObjects {
10924    /// Whether to show terse output.
10925    pub terse: bool,
10926    /// Additional options controlling the SHOW output.
10927    pub show_options: ShowStatementOptions,
10928}
10929
10930/// MSSQL's json null clause
10931///
10932/// ```plaintext
10933/// <json_null_clause> ::=
10934///       NULL ON NULL
10935///     | ABSENT ON NULL
10936/// ```
10937///
10938/// <https://learn.microsoft.com/en-us/sql/t-sql/functions/json-object-transact-sql?view=sql-server-ver16#json_null_clause>
10939#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10940#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10941#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10942pub enum JsonNullClause {
10943    /// `NULL ON NULL` behavior for JSON functions.
10944    NullOnNull,
10945    /// `ABSENT ON NULL` behavior for JSON functions.
10946    AbsentOnNull,
10947}
10948
10949impl Display for JsonNullClause {
10950    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10951        match self {
10952            JsonNullClause::NullOnNull => write!(f, "NULL ON NULL"),
10953            JsonNullClause::AbsentOnNull => write!(f, "ABSENT ON NULL"),
10954        }
10955    }
10956}
10957
10958/// PostgreSQL JSON function RETURNING clause
10959///
10960/// Example:
10961/// ```sql
10962/// JSON_OBJECT('a': 1 RETURNING jsonb)
10963/// ```
10964#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10965#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10966#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10967pub struct JsonReturningClause {
10968    /// The data type to return from the JSON function (e.g. JSON/JSONB).
10969    pub data_type: DataType,
10970}
10971
10972impl Display for JsonReturningClause {
10973    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10974        write!(f, "RETURNING {}", self.data_type)
10975    }
10976}
10977
10978/// rename object definition
10979#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10980#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10981#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10982pub struct RenameTable {
10983    /// The current name of the object to rename.
10984    pub old_name: ObjectName,
10985    /// The new name for the object.
10986    pub new_name: ObjectName,
10987}
10988
10989impl fmt::Display for RenameTable {
10990    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10991        write!(f, "{} TO {}", self.old_name, self.new_name)?;
10992        Ok(())
10993    }
10994}
10995
10996/// Represents the referenced table in an `INSERT INTO` statement
10997#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10998#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10999#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11000pub enum TableObject {
11001    /// Table specified by name.
11002    /// Example:
11003    /// ```sql
11004    /// INSERT INTO my_table
11005    /// ```
11006    TableName(#[cfg_attr(feature = "visitor", visit(with = "visit_relation"))] ObjectName),
11007
11008    /// Table specified as a function.
11009    /// Example:
11010    /// ```sql
11011    /// INSERT INTO TABLE FUNCTION remote('localhost', default.simple_table)
11012    /// ```
11013    /// [Clickhouse](https://clickhouse.com/docs/en/sql-reference/table-functions)
11014    TableFunction(Function),
11015
11016    /// Table specified through a sub-query
11017    /// Example:
11018    /// ```sql
11019    /// INSERT INTO
11020    /// (SELECT employee_id, last_name, email, hire_date, job_id,  salary, commission_pct FROM employees)
11021    /// VALUES (207, 'Gregory', 'pgregory@example.com', sysdate, 'PU_CLERK', 1.2E3, NULL);
11022    /// ```
11023    /// [Oracle](https://docs.oracle.com/en/database/oracle/oracle-database/21/sqlrf/INSERT.html#GUID-903F8043-0254-4EE9-ACC1-CB8AC0AF3423__I2126242)
11024    TableQuery(Box<Query>),
11025}
11026
11027impl fmt::Display for TableObject {
11028    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11029        match self {
11030            Self::TableName(table_name) => write!(f, "{table_name}"),
11031            Self::TableFunction(func) => write!(f, "FUNCTION {func}"),
11032            Self::TableQuery(table_query) => write!(f, "({table_query})"),
11033        }
11034    }
11035}
11036
11037/// Represents a SET SESSION AUTHORIZATION statement
11038#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11039#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11040#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11041pub struct SetSessionAuthorizationParam {
11042    /// The scope for the `SET SESSION AUTHORIZATION` (e.g., GLOBAL/SESSION).
11043    pub scope: ContextModifier,
11044    /// The specific authorization parameter kind.
11045    pub kind: SetSessionAuthorizationParamKind,
11046}
11047
11048impl fmt::Display for SetSessionAuthorizationParam {
11049    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11050        write!(f, "{}", self.kind)
11051    }
11052}
11053
11054/// Represents the parameter kind for SET SESSION AUTHORIZATION
11055#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11056#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11057#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11058pub enum SetSessionAuthorizationParamKind {
11059    /// Default authorization
11060    Default,
11061
11062    /// User name
11063    User(Ident),
11064}
11065
11066impl fmt::Display for SetSessionAuthorizationParamKind {
11067    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11068        match self {
11069            SetSessionAuthorizationParamKind::Default => write!(f, "DEFAULT"),
11070            SetSessionAuthorizationParamKind::User(name) => write!(f, "{}", name),
11071        }
11072    }
11073}
11074
11075#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11076#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11077#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11078/// Kind of session parameter being set by `SET SESSION`.
11079pub enum SetSessionParamKind {
11080    /// Generic session parameter (name/value pair).
11081    Generic(SetSessionParamGeneric),
11082    /// Identity insert related parameter.
11083    IdentityInsert(SetSessionParamIdentityInsert),
11084    /// Offsets-related parameter.
11085    Offsets(SetSessionParamOffsets),
11086    /// Statistics-related parameter.
11087    Statistics(SetSessionParamStatistics),
11088}
11089
11090impl fmt::Display for SetSessionParamKind {
11091    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11092        match self {
11093            SetSessionParamKind::Generic(x) => write!(f, "{x}"),
11094            SetSessionParamKind::IdentityInsert(x) => write!(f, "{x}"),
11095            SetSessionParamKind::Offsets(x) => write!(f, "{x}"),
11096            SetSessionParamKind::Statistics(x) => write!(f, "{x}"),
11097        }
11098    }
11099}
11100
11101#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11102#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11103#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11104/// Generic `SET SESSION` parameter represented as name(s) and value.
11105pub struct SetSessionParamGeneric {
11106    /// Names of the session parameters being set.
11107    pub names: Vec<String>,
11108    /// The value to assign to the parameter(s).
11109    pub value: String,
11110}
11111
11112impl fmt::Display for SetSessionParamGeneric {
11113    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11114        write!(f, "{} {}", display_comma_separated(&self.names), self.value)
11115    }
11116}
11117
11118#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11119#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11120#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11121/// `IDENTITY_INSERT` session parameter for a specific object.
11122pub struct SetSessionParamIdentityInsert {
11123    /// Object name targeted by `IDENTITY_INSERT`.
11124    pub obj: ObjectName,
11125    /// Value (ON/OFF) for the identity insert setting.
11126    pub value: SessionParamValue,
11127}
11128
11129impl fmt::Display for SetSessionParamIdentityInsert {
11130    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11131        write!(f, "IDENTITY_INSERT {} {}", self.obj, self.value)
11132    }
11133}
11134
11135#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11136#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11137#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11138/// Offsets-related session parameter with keywords and a value.
11139pub struct SetSessionParamOffsets {
11140    /// Keywords specifying which offsets to modify.
11141    pub keywords: Vec<String>,
11142    /// Value (ON/OFF) for the offsets setting.
11143    pub value: SessionParamValue,
11144}
11145
11146impl fmt::Display for SetSessionParamOffsets {
11147    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11148        write!(
11149            f,
11150            "OFFSETS {} {}",
11151            display_comma_separated(&self.keywords),
11152            self.value
11153        )
11154    }
11155}
11156
11157#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11158#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11159#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11160/// Statistics-related session parameter specifying topic and value.
11161pub struct SetSessionParamStatistics {
11162    /// Statistics topic to set (IO/PROFILE/TIME/XML).
11163    pub topic: SessionParamStatsTopic,
11164    /// Value (ON/OFF) for the statistics topic.
11165    pub value: SessionParamValue,
11166}
11167
11168impl fmt::Display for SetSessionParamStatistics {
11169    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11170        write!(f, "STATISTICS {} {}", self.topic, self.value)
11171    }
11172}
11173
11174#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11175#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11176#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11177/// Topics available for session statistics configuration.
11178pub enum SessionParamStatsTopic {
11179    /// Input/output statistics.
11180    IO,
11181    /// Profile statistics.
11182    Profile,
11183    /// Time statistics.
11184    Time,
11185    /// XML-related statistics.
11186    Xml,
11187}
11188
11189impl fmt::Display for SessionParamStatsTopic {
11190    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11191        match self {
11192            SessionParamStatsTopic::IO => write!(f, "IO"),
11193            SessionParamStatsTopic::Profile => write!(f, "PROFILE"),
11194            SessionParamStatsTopic::Time => write!(f, "TIME"),
11195            SessionParamStatsTopic::Xml => write!(f, "XML"),
11196        }
11197    }
11198}
11199
11200#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11201#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11202#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11203/// Value for a session boolean-like parameter (ON/OFF).
11204pub enum SessionParamValue {
11205    /// Session parameter enabled.
11206    On,
11207    /// Session parameter disabled.
11208    Off,
11209}
11210
11211impl fmt::Display for SessionParamValue {
11212    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11213        match self {
11214            SessionParamValue::On => write!(f, "ON"),
11215            SessionParamValue::Off => write!(f, "OFF"),
11216        }
11217    }
11218}
11219
11220/// Snowflake StorageSerializationPolicy for Iceberg Tables
11221/// ```sql
11222/// [ STORAGE_SERIALIZATION_POLICY = { COMPATIBLE | OPTIMIZED } ]
11223/// ```
11224///
11225/// <https://docs.snowflake.com/en/sql-reference/sql/create-iceberg-table>
11226#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11227#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11228#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11229pub enum StorageSerializationPolicy {
11230    /// Use compatible serialization mode.
11231    Compatible,
11232    /// Use optimized serialization mode.
11233    Optimized,
11234}
11235
11236impl Display for StorageSerializationPolicy {
11237    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
11238        match self {
11239            StorageSerializationPolicy::Compatible => write!(f, "COMPATIBLE"),
11240            StorageSerializationPolicy::Optimized => write!(f, "OPTIMIZED"),
11241        }
11242    }
11243}
11244
11245/// Snowflake CatalogSyncNamespaceMode
11246/// ```sql
11247/// [ CATALOG_SYNC_NAMESPACE_MODE = { NEST | FLATTEN } ]
11248/// ```
11249///
11250/// <https://docs.snowflake.com/en/sql-reference/sql/create-database>
11251#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11252#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11253#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11254pub enum CatalogSyncNamespaceMode {
11255    /// Nest namespaces when syncing catalog.
11256    Nest,
11257    /// Flatten namespaces when syncing catalog.
11258    Flatten,
11259}
11260
11261impl Display for CatalogSyncNamespaceMode {
11262    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
11263        match self {
11264            CatalogSyncNamespaceMode::Nest => write!(f, "NEST"),
11265            CatalogSyncNamespaceMode::Flatten => write!(f, "FLATTEN"),
11266        }
11267    }
11268}
11269
11270/// Variants of the Snowflake `COPY INTO` statement
11271#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11272#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11273#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11274pub enum CopyIntoSnowflakeKind {
11275    /// Loads data from files to a table
11276    /// See: <https://docs.snowflake.com/en/sql-reference/sql/copy-into-table>
11277    Table,
11278    /// Unloads data from a table or query to external files
11279    /// See: <https://docs.snowflake.com/en/sql-reference/sql/copy-into-location>
11280    Location,
11281}
11282
11283#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11284#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11285#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11286/// `PRINT` statement for producing debug/output messages.
11287pub struct PrintStatement {
11288    /// The expression producing the message to print.
11289    pub message: Box<Expr>,
11290}
11291
11292impl fmt::Display for PrintStatement {
11293    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11294        write!(f, "PRINT {}", self.message)
11295    }
11296}
11297
11298/// The type of `WAITFOR` statement (MSSQL).
11299///
11300/// See: <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/waitfor-transact-sql>
11301#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11302#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11303#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11304pub enum WaitForType {
11305    /// `WAITFOR DELAY 'time_to_pass'`
11306    Delay,
11307    /// `WAITFOR TIME 'time_to_execute'`
11308    Time,
11309}
11310
11311impl fmt::Display for WaitForType {
11312    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11313        match self {
11314            WaitForType::Delay => write!(f, "DELAY"),
11315            WaitForType::Time => write!(f, "TIME"),
11316        }
11317    }
11318}
11319
11320/// MSSQL `WAITFOR` statement.
11321///
11322/// See: <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/waitfor-transact-sql>
11323#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11324#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11325#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11326pub struct WaitForStatement {
11327    /// `DELAY` or `TIME`.
11328    pub wait_type: WaitForType,
11329    /// The time expression.
11330    pub expr: Expr,
11331}
11332
11333impl fmt::Display for WaitForStatement {
11334    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11335        write!(f, "WAITFOR {} {}", self.wait_type, self.expr)
11336    }
11337}
11338
11339/// Represents a `Return` statement.
11340///
11341/// [MsSql triggers](https://learn.microsoft.com/en-us/sql/t-sql/statements/create-trigger-transact-sql)
11342/// [MsSql functions](https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql)
11343#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11344#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11345#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11346pub struct ReturnStatement {
11347    /// Optional return value expression.
11348    pub value: Option<ReturnStatementValue>,
11349}
11350
11351impl fmt::Display for ReturnStatement {
11352    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11353        match &self.value {
11354            Some(ReturnStatementValue::Expr(expr)) => write!(f, "RETURN {expr}"),
11355            None => write!(f, "RETURN"),
11356        }
11357    }
11358}
11359
11360/// Variants of a `RETURN` statement
11361#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11362#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11363#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11364pub enum ReturnStatementValue {
11365    /// Return an expression from a function or trigger.
11366    Expr(Expr),
11367}
11368
11369/// Represents an `OPEN` statement.
11370#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11371#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11372#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11373pub struct OpenStatement {
11374    /// Cursor name
11375    pub cursor_name: Ident,
11376}
11377
11378impl fmt::Display for OpenStatement {
11379    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11380        write!(f, "OPEN {}", self.cursor_name)
11381    }
11382}
11383
11384/// Specifies Include / Exclude NULL within UNPIVOT command.
11385/// For example
11386/// `UNPIVOT (column1 FOR new_column IN (col3, col4, col5, col6))`
11387#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11388#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11389#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11390pub enum NullInclusion {
11391    /// Include NULL values in the UNPIVOT output.
11392    IncludeNulls,
11393    /// Exclude NULL values from the UNPIVOT output.
11394    ExcludeNulls,
11395}
11396
11397impl fmt::Display for NullInclusion {
11398    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11399        match self {
11400            NullInclusion::IncludeNulls => write!(f, "INCLUDE NULLS"),
11401            NullInclusion::ExcludeNulls => write!(f, "EXCLUDE NULLS"),
11402        }
11403    }
11404}
11405
11406/// Checks membership of a value in a JSON array
11407///
11408/// Syntax:
11409/// ```sql
11410/// <value> MEMBER OF(<array>)
11411/// ```
11412/// [MySQL](https://dev.mysql.com/doc/refman/8.4/en/json-search-functions.html#operator_member-of)
11413#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11414#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11415#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11416pub struct MemberOf {
11417    /// The value to check for membership.
11418    pub value: Box<Expr>,
11419    /// The JSON array expression to check against.
11420    pub array: Box<Expr>,
11421}
11422
11423impl fmt::Display for MemberOf {
11424    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11425        write!(f, "{} MEMBER OF({})", self.value, self.array)
11426    }
11427}
11428
11429#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11430#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11431#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11432/// Represents an `EXPORT DATA` statement.
11433pub struct ExportData {
11434    /// Options for the export operation.
11435    pub options: Vec<SqlOption>,
11436    /// The query producing the data to export.
11437    pub query: Box<Query>,
11438    /// Optional named connection to use for export.
11439    pub connection: Option<ObjectName>,
11440}
11441
11442impl fmt::Display for ExportData {
11443    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11444        if let Some(connection) = &self.connection {
11445            write!(
11446                f,
11447                "EXPORT DATA WITH CONNECTION {connection} OPTIONS({}) AS {}",
11448                display_comma_separated(&self.options),
11449                self.query
11450            )
11451        } else {
11452            write!(
11453                f,
11454                "EXPORT DATA OPTIONS({}) AS {}",
11455                display_comma_separated(&self.options),
11456                self.query
11457            )
11458        }
11459    }
11460}
11461/// Creates a user
11462///
11463/// Syntax:
11464/// ```sql
11465/// CREATE [OR REPLACE] USER [IF NOT EXISTS] <name> [OPTIONS]
11466/// ```
11467///
11468/// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-user)
11469#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11470#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11471#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11472pub struct CreateUser {
11473    /// Replace existing user if present.
11474    pub or_replace: bool,
11475    /// Only create the user if it does not already exist.
11476    pub if_not_exists: bool,
11477    /// The name of the user to create.
11478    pub name: Ident,
11479    /// Key/value options for user creation.
11480    pub options: KeyValueOptions,
11481    /// Whether tags are specified using `WITH TAG`.
11482    pub with_tags: bool,
11483    /// Tags for the user.
11484    pub tags: KeyValueOptions,
11485}
11486
11487impl fmt::Display for CreateUser {
11488    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11489        write!(f, "CREATE")?;
11490        if self.or_replace {
11491            write!(f, " OR REPLACE")?;
11492        }
11493        write!(f, " USER")?;
11494        if self.if_not_exists {
11495            write!(f, " IF NOT EXISTS")?;
11496        }
11497        write!(f, " {}", self.name)?;
11498        if !self.options.options.is_empty() {
11499            write!(f, " {}", self.options)?;
11500        }
11501        if !self.tags.options.is_empty() {
11502            if self.with_tags {
11503                write!(f, " WITH")?;
11504            }
11505            write!(f, " TAG ({})", self.tags)?;
11506        }
11507        Ok(())
11508    }
11509}
11510
11511/// Modifies the properties of a user
11512///
11513/// [Snowflake Syntax:](https://docs.snowflake.com/en/sql-reference/sql/alter-user)
11514/// ```sql
11515/// ALTER USER [ IF EXISTS ] [ <name> ] [ OPTIONS ]
11516/// ```
11517///
11518/// [PostgreSQL Syntax:](https://www.postgresql.org/docs/current/sql-alteruser.html)
11519/// ```sql
11520/// ALTER USER <role_specification> [ WITH ] option [ ... ]
11521/// ```
11522#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11523#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11524#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11525pub struct AlterUser {
11526    /// Whether to only alter the user if it exists.
11527    pub if_exists: bool,
11528    /// The name of the user to alter.
11529    pub name: Ident,
11530    /// Optional new name for the user (Snowflake-specific).
11531    /// See: <https://docs.snowflake.com/en/sql-reference/sql/alter-user#syntax>
11532    pub rename_to: Option<Ident>,
11533    /// Reset the user's password.
11534    pub reset_password: bool,
11535    /// Abort all running queries for the user.
11536    pub abort_all_queries: bool,
11537    /// Optionally add a delegated role authorization.
11538    pub add_role_delegation: Option<AlterUserAddRoleDelegation>,
11539    /// Optionally remove a delegated role authorization.
11540    pub remove_role_delegation: Option<AlterUserRemoveRoleDelegation>,
11541    /// Enroll the user in MFA.
11542    pub enroll_mfa: bool,
11543    /// Set the default MFA method for the user.
11544    pub set_default_mfa_method: Option<MfaMethodKind>,
11545    /// Remove the user's default MFA method.
11546    pub remove_mfa_method: Option<MfaMethodKind>,
11547    /// Modify an MFA method for the user.
11548    pub modify_mfa_method: Option<AlterUserModifyMfaMethod>,
11549    /// Add an MFA OTP method with optional count.
11550    pub add_mfa_method_otp: Option<AlterUserAddMfaMethodOtp>,
11551    /// Set a user policy.
11552    pub set_policy: Option<AlterUserSetPolicy>,
11553    /// Unset a user policy.
11554    pub unset_policy: Option<UserPolicyKind>,
11555    /// Key/value tag options to set on the user.
11556    pub set_tag: KeyValueOptions,
11557    /// Tags to unset on the user.
11558    pub unset_tag: Vec<String>,
11559    /// Key/value properties to set on the user.
11560    pub set_props: KeyValueOptions,
11561    /// Properties to unset on the user.
11562    pub unset_props: Vec<String>,
11563    /// The following options are PostgreSQL-specific: <https://www.postgresql.org/docs/current/sql-alteruser.html>
11564    pub password: Option<AlterUserPassword>,
11565}
11566
11567/// ```sql
11568/// ALTER USER [ IF EXISTS ] [ <name> ] ADD DELEGATED AUTHORIZATION OF ROLE <role_name> TO SECURITY INTEGRATION <integration_name>
11569/// ```
11570#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11571#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11572#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11573pub struct AlterUserAddRoleDelegation {
11574    /// Role name to delegate.
11575    pub role: Ident,
11576    /// Security integration receiving the delegation.
11577    pub integration: Ident,
11578}
11579
11580/// ```sql
11581/// ALTER USER [ IF EXISTS ] [ <name> ] REMOVE DELEGATED { AUTHORIZATION OF ROLE <role_name> | AUTHORIZATIONS } FROM SECURITY INTEGRATION <integration_name>
11582/// ```
11583#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11584#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11585#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11586pub struct AlterUserRemoveRoleDelegation {
11587    /// Optional role name to remove delegation for.
11588    pub role: Option<Ident>,
11589    /// Security integration from which to remove delegation.
11590    pub integration: Ident,
11591}
11592
11593/// ```sql
11594/// ADD MFA METHOD OTP [ COUNT = number ]
11595/// ```
11596#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11597#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11598#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11599pub struct AlterUserAddMfaMethodOtp {
11600    /// Optional OTP count parameter.
11601    pub count: Option<ValueWithSpan>,
11602}
11603
11604/// ```sql
11605/// ALTER USER [ IF EXISTS ] [ <name> ] MODIFY MFA METHOD <mfa_method> SET COMMENT = '<string>'
11606/// ```
11607#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11608#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11609#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11610pub struct AlterUserModifyMfaMethod {
11611    /// The MFA method being modified.
11612    pub method: MfaMethodKind,
11613    /// The new comment for the MFA method.
11614    pub comment: String,
11615}
11616
11617/// Types of MFA methods
11618#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11619#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11620#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11621pub enum MfaMethodKind {
11622    /// PassKey (hardware or platform passkey) MFA method.
11623    PassKey,
11624    /// Time-based One-Time Password (TOTP) MFA method.
11625    Totp,
11626    /// Duo Security MFA method.
11627    Duo,
11628}
11629
11630impl fmt::Display for MfaMethodKind {
11631    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11632        match self {
11633            MfaMethodKind::PassKey => write!(f, "PASSKEY"),
11634            MfaMethodKind::Totp => write!(f, "TOTP"),
11635            MfaMethodKind::Duo => write!(f, "DUO"),
11636        }
11637    }
11638}
11639
11640/// ```sql
11641/// ALTER USER [ IF EXISTS ] [ <name> ] SET { AUTHENTICATION | PASSWORD | SESSION } POLICY <policy_name>
11642/// ```
11643#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11644#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11645#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11646pub struct AlterUserSetPolicy {
11647    /// The kind of user policy being set (authentication/password/session).
11648    pub policy_kind: UserPolicyKind,
11649    /// The identifier of the policy to apply.
11650    pub policy: Ident,
11651}
11652
11653/// Types of user-based policies
11654#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11655#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11656#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11657pub enum UserPolicyKind {
11658    /// Authentication policy.
11659    Authentication,
11660    /// Password policy.
11661    Password,
11662    /// Session policy.
11663    Session,
11664}
11665
11666impl fmt::Display for UserPolicyKind {
11667    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11668        match self {
11669            UserPolicyKind::Authentication => write!(f, "AUTHENTICATION"),
11670            UserPolicyKind::Password => write!(f, "PASSWORD"),
11671            UserPolicyKind::Session => write!(f, "SESSION"),
11672        }
11673    }
11674}
11675
11676impl fmt::Display for AlterUser {
11677    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11678        write!(f, "ALTER")?;
11679        write!(f, " USER")?;
11680        if self.if_exists {
11681            write!(f, " IF EXISTS")?;
11682        }
11683        write!(f, " {}", self.name)?;
11684        if let Some(new_name) = &self.rename_to {
11685            write!(f, " RENAME TO {new_name}")?;
11686        }
11687        if self.reset_password {
11688            write!(f, " RESET PASSWORD")?;
11689        }
11690        if self.abort_all_queries {
11691            write!(f, " ABORT ALL QUERIES")?;
11692        }
11693        if let Some(role_delegation) = &self.add_role_delegation {
11694            let role = &role_delegation.role;
11695            let integration = &role_delegation.integration;
11696            write!(
11697                f,
11698                " ADD DELEGATED AUTHORIZATION OF ROLE {role} TO SECURITY INTEGRATION {integration}"
11699            )?;
11700        }
11701        if let Some(role_delegation) = &self.remove_role_delegation {
11702            write!(f, " REMOVE DELEGATED")?;
11703            match &role_delegation.role {
11704                Some(role) => write!(f, " AUTHORIZATION OF ROLE {role}")?,
11705                None => write!(f, " AUTHORIZATIONS")?,
11706            }
11707            let integration = &role_delegation.integration;
11708            write!(f, " FROM SECURITY INTEGRATION {integration}")?;
11709        }
11710        if self.enroll_mfa {
11711            write!(f, " ENROLL MFA")?;
11712        }
11713        if let Some(method) = &self.set_default_mfa_method {
11714            write!(f, " SET DEFAULT_MFA_METHOD {method}")?
11715        }
11716        if let Some(method) = &self.remove_mfa_method {
11717            write!(f, " REMOVE MFA METHOD {method}")?;
11718        }
11719        if let Some(modify) = &self.modify_mfa_method {
11720            let method = &modify.method;
11721            let comment = &modify.comment;
11722            write!(
11723                f,
11724                " MODIFY MFA METHOD {method} SET COMMENT '{}'",
11725                value::escape_single_quote_string(comment)
11726            )?;
11727        }
11728        if let Some(add_mfa_method_otp) = &self.add_mfa_method_otp {
11729            write!(f, " ADD MFA METHOD OTP")?;
11730            if let Some(count) = &add_mfa_method_otp.count {
11731                write!(f, " COUNT = {count}")?;
11732            }
11733        }
11734        if let Some(policy) = &self.set_policy {
11735            let policy_kind = &policy.policy_kind;
11736            let name = &policy.policy;
11737            write!(f, " SET {policy_kind} POLICY {name}")?;
11738        }
11739        if let Some(policy_kind) = &self.unset_policy {
11740            write!(f, " UNSET {policy_kind} POLICY")?;
11741        }
11742        if !self.set_tag.options.is_empty() {
11743            write!(f, " SET TAG {}", self.set_tag)?;
11744        }
11745        if !self.unset_tag.is_empty() {
11746            write!(f, " UNSET TAG {}", display_comma_separated(&self.unset_tag))?;
11747        }
11748        let has_props = !self.set_props.options.is_empty();
11749        if has_props {
11750            write!(f, " SET")?;
11751            write!(f, " {}", &self.set_props)?;
11752        }
11753        if !self.unset_props.is_empty() {
11754            write!(f, " UNSET {}", display_comma_separated(&self.unset_props))?;
11755        }
11756        if let Some(password) = &self.password {
11757            write!(f, " {}", password)?;
11758        }
11759        Ok(())
11760    }
11761}
11762
11763/// ```sql
11764/// ALTER USER <role_specification> [ WITH ] PASSWORD { 'password' | NULL }``
11765/// ```
11766#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11767#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11768#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11769pub struct AlterUserPassword {
11770    /// Whether the password is encrypted.
11771    pub encrypted: bool,
11772    /// The password string, or `None` for `NULL`.
11773    pub password: Option<String>,
11774}
11775
11776impl Display for AlterUserPassword {
11777    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11778        if self.encrypted {
11779            write!(f, "ENCRYPTED ")?;
11780        }
11781        write!(f, "PASSWORD")?;
11782        match &self.password {
11783            None => write!(f, " NULL")?,
11784            Some(password) => write!(f, " '{}'", value::escape_single_quote_string(password))?,
11785        }
11786        Ok(())
11787    }
11788}
11789
11790/// Specifies how to create a new table based on an existing table's schema.
11791/// '''sql
11792/// CREATE TABLE new LIKE old ...
11793/// '''
11794#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11795#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11796#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11797pub enum CreateTableLikeKind {
11798    /// '''sql
11799    /// CREATE TABLE new (LIKE old ...)
11800    /// '''
11801    /// [Redshift](https://docs.aws.amazon.com/redshift/latest/dg/r_CREATE_TABLE_NEW.html)
11802    Parenthesized(CreateTableLike),
11803    /// '''sql
11804    /// CREATE TABLE new LIKE old ...
11805    /// '''
11806    /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-table#label-create-table-like)
11807    /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_table_like)
11808    Plain(CreateTableLike),
11809}
11810
11811#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11812#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11813#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11814/// Controls whether defaults are included when creating a table FROM/LILE another.
11815pub enum CreateTableLikeDefaults {
11816    /// Include default values from the source table.
11817    Including,
11818    /// Exclude default values from the source table.
11819    Excluding,
11820}
11821
11822impl fmt::Display for CreateTableLikeDefaults {
11823    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11824        match self {
11825            CreateTableLikeDefaults::Including => write!(f, "INCLUDING DEFAULTS"),
11826            CreateTableLikeDefaults::Excluding => write!(f, "EXCLUDING DEFAULTS"),
11827        }
11828    }
11829}
11830
11831#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11832#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11833#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11834/// Represents the `LIKE` clause of a `CREATE TABLE` statement.
11835pub struct CreateTableLike {
11836    /// The source table name to copy the schema from.
11837    pub name: ObjectName,
11838    /// Optional behavior controlling whether defaults are copied.
11839    pub defaults: Option<CreateTableLikeDefaults>,
11840}
11841
11842impl fmt::Display for CreateTableLike {
11843    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11844        write!(f, "LIKE {}", self.name)?;
11845        if let Some(defaults) = &self.defaults {
11846            write!(f, " {defaults}")?;
11847        }
11848        Ok(())
11849    }
11850}
11851
11852/// Specifies the refresh mode for the dynamic table.
11853///
11854/// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-dynamic-table)
11855#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11856#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11857#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11858pub enum RefreshModeKind {
11859    /// Automatic refresh mode (`AUTO`).
11860    Auto,
11861    /// Full refresh mode (`FULL`).
11862    Full,
11863    /// Incremental refresh mode (`INCREMENTAL`).
11864    Incremental,
11865}
11866
11867impl fmt::Display for RefreshModeKind {
11868    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11869        match self {
11870            RefreshModeKind::Auto => write!(f, "AUTO"),
11871            RefreshModeKind::Full => write!(f, "FULL"),
11872            RefreshModeKind::Incremental => write!(f, "INCREMENTAL"),
11873        }
11874    }
11875}
11876
11877/// Specifies the behavior of the initial refresh of the dynamic table.
11878///
11879/// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-dynamic-table)
11880#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11881#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11882#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11883pub enum InitializeKind {
11884    /// Initialize on creation (`ON CREATE`).
11885    OnCreate,
11886    /// Initialize on schedule (`ON SCHEDULE`).
11887    OnSchedule,
11888}
11889
11890impl fmt::Display for InitializeKind {
11891    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11892        match self {
11893            InitializeKind::OnCreate => write!(f, "ON_CREATE"),
11894            InitializeKind::OnSchedule => write!(f, "ON_SCHEDULE"),
11895        }
11896    }
11897}
11898
11899/// Re-sorts rows and reclaims space in either a specified table or all tables in the current database
11900///
11901/// '''sql
11902/// VACUUM [ FULL | SORT ONLY | DELETE ONLY | REINDEX | RECLUSTER ] [ \[ table_name \] [ TO threshold PERCENT ] \[ BOOST \] ]
11903/// '''
11904/// [Redshift](https://docs.aws.amazon.com/redshift/latest/dg/r_VACUUM_command.html)
11905#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11906#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11907#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11908pub struct VacuumStatement {
11909    /// Whether `FULL` was specified.
11910    pub full: bool,
11911    /// Whether `SORT ONLY` was specified.
11912    pub sort_only: bool,
11913    /// Whether `DELETE ONLY` was specified.
11914    pub delete_only: bool,
11915    /// Whether `REINDEX` was specified.
11916    pub reindex: bool,
11917    /// Whether `RECLUSTER` was specified.
11918    pub recluster: bool,
11919    /// Optional table to run `VACUUM` on.
11920    pub table_name: Option<ObjectName>,
11921    /// Optional threshold value (percent) for `TO threshold PERCENT`.
11922    pub threshold: Option<ValueWithSpan>,
11923    /// Whether `BOOST` was specified.
11924    pub boost: bool,
11925}
11926
11927impl fmt::Display for VacuumStatement {
11928    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11929        write!(
11930            f,
11931            "VACUUM{}{}{}{}{}",
11932            if self.full { " FULL" } else { "" },
11933            if self.sort_only { " SORT ONLY" } else { "" },
11934            if self.delete_only { " DELETE ONLY" } else { "" },
11935            if self.reindex { " REINDEX" } else { "" },
11936            if self.recluster { " RECLUSTER" } else { "" },
11937        )?;
11938        if let Some(table_name) = &self.table_name {
11939            write!(f, " {table_name}")?;
11940        }
11941        if let Some(threshold) = &self.threshold {
11942            write!(f, " TO {threshold} PERCENT")?;
11943        }
11944        if self.boost {
11945            write!(f, " BOOST")?;
11946        }
11947        Ok(())
11948    }
11949}
11950
11951/// Variants of the RESET statement
11952#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11953#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11954#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11955pub enum Reset {
11956    /// Resets all session parameters to their default values.
11957    ALL,
11958
11959    /// Resets a specific session parameter to its default value.
11960    ConfigurationParameter(ObjectName),
11961}
11962
11963/// Resets a session parameter to its default value.
11964/// ```sql
11965/// RESET { ALL | <configuration_parameter> }
11966/// ```
11967#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11968#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11969#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11970pub struct ResetStatement {
11971    /// The reset action to perform (either `ALL` or a specific configuration parameter).
11972    pub reset: Reset,
11973}
11974
11975/// Query optimizer hints are optionally supported comments after the
11976/// `SELECT`, `INSERT`, `UPDATE`, `REPLACE`, `MERGE`, and `DELETE` keywords in
11977/// the corresponding statements.
11978///
11979/// See [Select::optimizer_hints]
11980#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11981#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11982#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11983pub struct OptimizerHint {
11984    /// An optional prefix between the comment marker and `+`.
11985    ///
11986    /// Standard optimizer hints like `/*+ ... */` have an empty prefix,
11987    /// while system-specific hints like `/*abc+ ... */` have `prefix = "abc"`.
11988    /// The prefix is any sequence of ASCII alphanumeric characters
11989    /// immediately before the `+` marker.
11990    pub prefix: String,
11991    /// the raw text of the optimizer hint without its markers
11992    pub text: String,
11993    /// the style of the comment which `text` was extracted from,
11994    /// e.g. `/*+...*/` or `--+...`
11995    ///
11996    /// Not all dialects support all styles, though.
11997    pub style: OptimizerHintStyle,
11998}
11999
12000/// The commentary style of an [optimizer hint](OptimizerHint)
12001#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
12002#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
12003#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
12004pub enum OptimizerHintStyle {
12005    /// A hint corresponding to a single line comment,
12006    /// e.g. `--+ LEADING(v.e v.d t)`
12007    SingleLine {
12008        /// the comment prefix, e.g. `--`
12009        prefix: String,
12010    },
12011    /// A hint corresponding to a multi line comment,
12012    /// e.g. `/*+ LEADING(v.e v.d t) */`
12013    MultiLine,
12014}
12015
12016impl fmt::Display for OptimizerHint {
12017    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
12018        match &self.style {
12019            OptimizerHintStyle::SingleLine { prefix } => {
12020                f.write_str(prefix)?;
12021                f.write_str(&self.prefix)?;
12022                f.write_str("+")?;
12023                f.write_str(&self.text)
12024            }
12025            OptimizerHintStyle::MultiLine => {
12026                f.write_str("/*")?;
12027                f.write_str(&self.prefix)?;
12028                f.write_str("+")?;
12029                f.write_str(&self.text)?;
12030                f.write_str("*/")
12031            }
12032        }
12033    }
12034}
12035
12036impl fmt::Display for ResetStatement {
12037    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
12038        match &self.reset {
12039            Reset::ALL => write!(f, "RESET ALL"),
12040            Reset::ConfigurationParameter(param) => write!(f, "RESET {}", param),
12041        }
12042    }
12043}
12044
12045impl From<Set> for Statement {
12046    fn from(s: Set) -> Self {
12047        Self::Set(s)
12048    }
12049}
12050
12051impl From<Query> for Statement {
12052    fn from(q: Query) -> Self {
12053        Box::new(q).into()
12054    }
12055}
12056
12057impl From<Box<Query>> for Statement {
12058    fn from(q: Box<Query>) -> Self {
12059        Self::Query(q)
12060    }
12061}
12062
12063impl From<Insert> for Statement {
12064    fn from(i: Insert) -> Self {
12065        Self::Insert(i)
12066    }
12067}
12068
12069impl From<Update> for Statement {
12070    fn from(u: Update) -> Self {
12071        Self::Update(u)
12072    }
12073}
12074
12075impl From<CreateView> for Statement {
12076    fn from(cv: CreateView) -> Self {
12077        Self::CreateView(cv)
12078    }
12079}
12080
12081impl From<CreateRole> for Statement {
12082    fn from(cr: CreateRole) -> Self {
12083        Self::CreateRole(cr)
12084    }
12085}
12086
12087impl From<AlterTable> for Statement {
12088    fn from(at: AlterTable) -> Self {
12089        Self::AlterTable(at)
12090    }
12091}
12092
12093impl From<DropFunction> for Statement {
12094    fn from(df: DropFunction) -> Self {
12095        Self::DropFunction(df)
12096    }
12097}
12098
12099impl From<CreateExtension> for Statement {
12100    fn from(ce: CreateExtension) -> Self {
12101        Self::CreateExtension(ce)
12102    }
12103}
12104
12105impl From<CreateCollation> for Statement {
12106    fn from(c: CreateCollation) -> Self {
12107        Self::CreateCollation(c)
12108    }
12109}
12110
12111impl From<DropExtension> for Statement {
12112    fn from(de: DropExtension) -> Self {
12113        Self::DropExtension(de)
12114    }
12115}
12116
12117impl From<CaseStatement> for Statement {
12118    fn from(c: CaseStatement) -> Self {
12119        Self::Case(c)
12120    }
12121}
12122
12123impl From<IfStatement> for Statement {
12124    fn from(i: IfStatement) -> Self {
12125        Self::If(i)
12126    }
12127}
12128
12129impl From<WhileStatement> for Statement {
12130    fn from(w: WhileStatement) -> Self {
12131        Self::While(w)
12132    }
12133}
12134
12135impl From<RaiseStatement> for Statement {
12136    fn from(r: RaiseStatement) -> Self {
12137        Self::Raise(r)
12138    }
12139}
12140
12141impl From<ThrowStatement> for Statement {
12142    fn from(t: ThrowStatement) -> Self {
12143        Self::Throw(t)
12144    }
12145}
12146
12147impl From<Function> for Statement {
12148    fn from(f: Function) -> Self {
12149        Self::Call(f)
12150    }
12151}
12152
12153impl From<OpenStatement> for Statement {
12154    fn from(o: OpenStatement) -> Self {
12155        Self::Open(o)
12156    }
12157}
12158
12159impl From<Delete> for Statement {
12160    fn from(d: Delete) -> Self {
12161        Self::Delete(d)
12162    }
12163}
12164
12165impl From<CreateTable> for Statement {
12166    fn from(c: CreateTable) -> Self {
12167        Self::CreateTable(c)
12168    }
12169}
12170
12171impl From<CreateIndex> for Statement {
12172    fn from(c: CreateIndex) -> Self {
12173        Self::CreateIndex(c)
12174    }
12175}
12176
12177impl From<CreateServerStatement> for Statement {
12178    fn from(c: CreateServerStatement) -> Self {
12179        Self::CreateServer(c)
12180    }
12181}
12182
12183impl From<CreateConnector> for Statement {
12184    fn from(c: CreateConnector) -> Self {
12185        Self::CreateConnector(c)
12186    }
12187}
12188
12189impl From<CreateOperator> for Statement {
12190    fn from(c: CreateOperator) -> Self {
12191        Self::CreateOperator(c)
12192    }
12193}
12194
12195impl From<CreateOperatorFamily> for Statement {
12196    fn from(c: CreateOperatorFamily) -> Self {
12197        Self::CreateOperatorFamily(c)
12198    }
12199}
12200
12201impl From<CreateOperatorClass> for Statement {
12202    fn from(c: CreateOperatorClass) -> Self {
12203        Self::CreateOperatorClass(c)
12204    }
12205}
12206
12207impl From<AlterSchema> for Statement {
12208    fn from(a: AlterSchema) -> Self {
12209        Self::AlterSchema(a)
12210    }
12211}
12212
12213impl From<AlterFunction> for Statement {
12214    fn from(a: AlterFunction) -> Self {
12215        Self::AlterFunction(a)
12216    }
12217}
12218
12219impl From<AlterType> for Statement {
12220    fn from(a: AlterType) -> Self {
12221        Self::AlterType(a)
12222    }
12223}
12224
12225impl From<AlterCollation> for Statement {
12226    fn from(a: AlterCollation) -> Self {
12227        Self::AlterCollation(a)
12228    }
12229}
12230
12231impl From<AlterOperator> for Statement {
12232    fn from(a: AlterOperator) -> Self {
12233        Self::AlterOperator(a)
12234    }
12235}
12236
12237impl From<AlterOperatorFamily> for Statement {
12238    fn from(a: AlterOperatorFamily) -> Self {
12239        Self::AlterOperatorFamily(a)
12240    }
12241}
12242
12243impl From<AlterOperatorClass> for Statement {
12244    fn from(a: AlterOperatorClass) -> Self {
12245        Self::AlterOperatorClass(a)
12246    }
12247}
12248
12249impl From<Merge> for Statement {
12250    fn from(m: Merge) -> Self {
12251        Self::Merge(m)
12252    }
12253}
12254
12255impl From<AlterUser> for Statement {
12256    fn from(a: AlterUser) -> Self {
12257        Self::AlterUser(a)
12258    }
12259}
12260
12261impl From<DropDomain> for Statement {
12262    fn from(d: DropDomain) -> Self {
12263        Self::DropDomain(d)
12264    }
12265}
12266
12267impl From<ShowCharset> for Statement {
12268    fn from(s: ShowCharset) -> Self {
12269        Self::ShowCharset(s)
12270    }
12271}
12272
12273impl From<ShowObjects> for Statement {
12274    fn from(s: ShowObjects) -> Self {
12275        Self::ShowObjects(s)
12276    }
12277}
12278
12279impl From<Use> for Statement {
12280    fn from(u: Use) -> Self {
12281        Self::Use(u)
12282    }
12283}
12284
12285impl From<CreateFunction> for Statement {
12286    fn from(c: CreateFunction) -> Self {
12287        Self::CreateFunction(c)
12288    }
12289}
12290
12291impl From<CreateTrigger> for Statement {
12292    fn from(c: CreateTrigger) -> Self {
12293        Self::CreateTrigger(c)
12294    }
12295}
12296
12297impl From<DropTrigger> for Statement {
12298    fn from(d: DropTrigger) -> Self {
12299        Self::DropTrigger(d)
12300    }
12301}
12302
12303impl From<DropOperator> for Statement {
12304    fn from(d: DropOperator) -> Self {
12305        Self::DropOperator(d)
12306    }
12307}
12308
12309impl From<DropOperatorFamily> for Statement {
12310    fn from(d: DropOperatorFamily) -> Self {
12311        Self::DropOperatorFamily(d)
12312    }
12313}
12314
12315impl From<DropOperatorClass> for Statement {
12316    fn from(d: DropOperatorClass) -> Self {
12317        Self::DropOperatorClass(d)
12318    }
12319}
12320
12321impl From<DenyStatement> for Statement {
12322    fn from(d: DenyStatement) -> Self {
12323        Self::Deny(d)
12324    }
12325}
12326
12327impl From<CreateDomain> for Statement {
12328    fn from(c: CreateDomain) -> Self {
12329        Self::CreateDomain(c)
12330    }
12331}
12332
12333impl From<RenameTable> for Statement {
12334    fn from(r: RenameTable) -> Self {
12335        vec![r].into()
12336    }
12337}
12338
12339impl From<Vec<RenameTable>> for Statement {
12340    fn from(r: Vec<RenameTable>) -> Self {
12341        Self::RenameTable(r)
12342    }
12343}
12344
12345impl From<PrintStatement> for Statement {
12346    fn from(p: PrintStatement) -> Self {
12347        Self::Print(p)
12348    }
12349}
12350
12351impl From<ReturnStatement> for Statement {
12352    fn from(r: ReturnStatement) -> Self {
12353        Self::Return(r)
12354    }
12355}
12356
12357impl From<ExportData> for Statement {
12358    fn from(e: ExportData) -> Self {
12359        Self::ExportData(e)
12360    }
12361}
12362
12363impl From<CreateUser> for Statement {
12364    fn from(c: CreateUser) -> Self {
12365        Self::CreateUser(c)
12366    }
12367}
12368
12369impl From<VacuumStatement> for Statement {
12370    fn from(v: VacuumStatement) -> Self {
12371        Self::Vacuum(v)
12372    }
12373}
12374
12375impl From<ResetStatement> for Statement {
12376    fn from(r: ResetStatement) -> Self {
12377        Self::Reset(r)
12378    }
12379}
12380
12381#[cfg(test)]
12382mod tests {
12383    use crate::tokenizer::Location;
12384
12385    use super::*;
12386
12387    #[test]
12388    fn test_window_frame_default() {
12389        let window_frame = WindowFrame::default();
12390        assert_eq!(WindowFrameBound::Preceding(None), window_frame.start_bound);
12391    }
12392
12393    #[test]
12394    fn test_grouping_sets_display() {
12395        // a and b in different group
12396        let grouping_sets = Expr::GroupingSets(vec![
12397            vec![Expr::Identifier(Ident::new("a"))],
12398            vec![Expr::Identifier(Ident::new("b"))],
12399        ]);
12400        assert_eq!("GROUPING SETS ((a), (b))", format!("{grouping_sets}"));
12401
12402        // a and b in the same group
12403        let grouping_sets = Expr::GroupingSets(vec![vec![
12404            Expr::Identifier(Ident::new("a")),
12405            Expr::Identifier(Ident::new("b")),
12406        ]]);
12407        assert_eq!("GROUPING SETS ((a, b))", format!("{grouping_sets}"));
12408
12409        // (a, b) and (c, d) in different group
12410        let grouping_sets = Expr::GroupingSets(vec![
12411            vec![
12412                Expr::Identifier(Ident::new("a")),
12413                Expr::Identifier(Ident::new("b")),
12414            ],
12415            vec![
12416                Expr::Identifier(Ident::new("c")),
12417                Expr::Identifier(Ident::new("d")),
12418            ],
12419        ]);
12420        assert_eq!("GROUPING SETS ((a, b), (c, d))", format!("{grouping_sets}"));
12421    }
12422
12423    #[test]
12424    fn test_rollup_display() {
12425        let rollup = Expr::Rollup(vec![vec![Expr::Identifier(Ident::new("a"))]]);
12426        assert_eq!("ROLLUP (a)", format!("{rollup}"));
12427
12428        let rollup = Expr::Rollup(vec![vec![
12429            Expr::Identifier(Ident::new("a")),
12430            Expr::Identifier(Ident::new("b")),
12431        ]]);
12432        assert_eq!("ROLLUP ((a, b))", format!("{rollup}"));
12433
12434        let rollup = Expr::Rollup(vec![
12435            vec![Expr::Identifier(Ident::new("a"))],
12436            vec![Expr::Identifier(Ident::new("b"))],
12437        ]);
12438        assert_eq!("ROLLUP (a, b)", format!("{rollup}"));
12439
12440        let rollup = Expr::Rollup(vec![
12441            vec![Expr::Identifier(Ident::new("a"))],
12442            vec![
12443                Expr::Identifier(Ident::new("b")),
12444                Expr::Identifier(Ident::new("c")),
12445            ],
12446            vec![Expr::Identifier(Ident::new("d"))],
12447        ]);
12448        assert_eq!("ROLLUP (a, (b, c), d)", format!("{rollup}"));
12449    }
12450
12451    #[test]
12452    fn test_cube_display() {
12453        let cube = Expr::Cube(vec![vec![Expr::Identifier(Ident::new("a"))]]);
12454        assert_eq!("CUBE (a)", format!("{cube}"));
12455
12456        let cube = Expr::Cube(vec![vec![
12457            Expr::Identifier(Ident::new("a")),
12458            Expr::Identifier(Ident::new("b")),
12459        ]]);
12460        assert_eq!("CUBE ((a, b))", format!("{cube}"));
12461
12462        let cube = Expr::Cube(vec![
12463            vec![Expr::Identifier(Ident::new("a"))],
12464            vec![Expr::Identifier(Ident::new("b"))],
12465        ]);
12466        assert_eq!("CUBE (a, b)", format!("{cube}"));
12467
12468        let cube = Expr::Cube(vec![
12469            vec![Expr::Identifier(Ident::new("a"))],
12470            vec![
12471                Expr::Identifier(Ident::new("b")),
12472                Expr::Identifier(Ident::new("c")),
12473            ],
12474            vec![Expr::Identifier(Ident::new("d"))],
12475        ]);
12476        assert_eq!("CUBE (a, (b, c), d)", format!("{cube}"));
12477    }
12478
12479    #[test]
12480    fn test_interval_display() {
12481        let interval = Expr::Interval(Interval {
12482            value: Box::new(Expr::Value(
12483                Value::SingleQuotedString(String::from("123:45.67")).with_empty_span(),
12484            )),
12485            leading_field: Some(DateTimeField::Minute),
12486            leading_precision: Some(10),
12487            last_field: Some(DateTimeField::Second),
12488            fractional_seconds_precision: Some(9),
12489        });
12490        assert_eq!(
12491            "INTERVAL '123:45.67' MINUTE (10) TO SECOND (9)",
12492            format!("{interval}"),
12493        );
12494
12495        let interval = Expr::Interval(Interval {
12496            value: Box::new(Expr::Value(
12497                Value::SingleQuotedString(String::from("5")).with_empty_span(),
12498            )),
12499            leading_field: Some(DateTimeField::Second),
12500            leading_precision: Some(1),
12501            last_field: None,
12502            fractional_seconds_precision: Some(3),
12503        });
12504        assert_eq!("INTERVAL '5' SECOND (1, 3)", format!("{interval}"));
12505    }
12506
12507    #[test]
12508    fn test_one_or_many_with_parens_deref() {
12509        use core::ops::Index;
12510
12511        let one = OneOrManyWithParens::One("a");
12512
12513        assert_eq!(one.deref(), &["a"]);
12514        assert_eq!(<OneOrManyWithParens<_> as Deref>::deref(&one), &["a"]);
12515
12516        assert_eq!(one[0], "a");
12517        assert_eq!(one.index(0), &"a");
12518        assert_eq!(
12519            <<OneOrManyWithParens<_> as Deref>::Target as Index<usize>>::index(&one, 0),
12520            &"a"
12521        );
12522
12523        assert_eq!(one.len(), 1);
12524        assert_eq!(<OneOrManyWithParens<_> as Deref>::Target::len(&one), 1);
12525
12526        let many1 = OneOrManyWithParens::Many(vec!["b"]);
12527
12528        assert_eq!(many1.deref(), &["b"]);
12529        assert_eq!(<OneOrManyWithParens<_> as Deref>::deref(&many1), &["b"]);
12530
12531        assert_eq!(many1[0], "b");
12532        assert_eq!(many1.index(0), &"b");
12533        assert_eq!(
12534            <<OneOrManyWithParens<_> as Deref>::Target as Index<usize>>::index(&many1, 0),
12535            &"b"
12536        );
12537
12538        assert_eq!(many1.len(), 1);
12539        assert_eq!(<OneOrManyWithParens<_> as Deref>::Target::len(&many1), 1);
12540
12541        let many2 = OneOrManyWithParens::Many(vec!["c", "d"]);
12542
12543        assert_eq!(many2.deref(), &["c", "d"]);
12544        assert_eq!(
12545            <OneOrManyWithParens<_> as Deref>::deref(&many2),
12546            &["c", "d"]
12547        );
12548
12549        assert_eq!(many2[0], "c");
12550        assert_eq!(many2.index(0), &"c");
12551        assert_eq!(
12552            <<OneOrManyWithParens<_> as Deref>::Target as Index<usize>>::index(&many2, 0),
12553            &"c"
12554        );
12555
12556        assert_eq!(many2[1], "d");
12557        assert_eq!(many2.index(1), &"d");
12558        assert_eq!(
12559            <<OneOrManyWithParens<_> as Deref>::Target as Index<usize>>::index(&many2, 1),
12560            &"d"
12561        );
12562
12563        assert_eq!(many2.len(), 2);
12564        assert_eq!(<OneOrManyWithParens<_> as Deref>::Target::len(&many2), 2);
12565    }
12566
12567    #[test]
12568    fn test_one_or_many_with_parens_as_ref() {
12569        let one = OneOrManyWithParens::One("a");
12570
12571        assert_eq!(one.as_ref(), &["a"]);
12572        assert_eq!(<OneOrManyWithParens<_> as AsRef<_>>::as_ref(&one), &["a"]);
12573
12574        let many1 = OneOrManyWithParens::Many(vec!["b"]);
12575
12576        assert_eq!(many1.as_ref(), &["b"]);
12577        assert_eq!(<OneOrManyWithParens<_> as AsRef<_>>::as_ref(&many1), &["b"]);
12578
12579        let many2 = OneOrManyWithParens::Many(vec!["c", "d"]);
12580
12581        assert_eq!(many2.as_ref(), &["c", "d"]);
12582        assert_eq!(
12583            <OneOrManyWithParens<_> as AsRef<_>>::as_ref(&many2),
12584            &["c", "d"]
12585        );
12586    }
12587
12588    #[test]
12589    fn test_one_or_many_with_parens_ref_into_iter() {
12590        let one = OneOrManyWithParens::One("a");
12591
12592        assert_eq!(Vec::from_iter(&one), vec![&"a"]);
12593
12594        let many1 = OneOrManyWithParens::Many(vec!["b"]);
12595
12596        assert_eq!(Vec::from_iter(&many1), vec![&"b"]);
12597
12598        let many2 = OneOrManyWithParens::Many(vec!["c", "d"]);
12599
12600        assert_eq!(Vec::from_iter(&many2), vec![&"c", &"d"]);
12601    }
12602
12603    #[test]
12604    fn test_one_or_many_with_parens_value_into_iter() {
12605        use core::iter::once;
12606
12607        //tests that our iterator implemented methods behaves exactly as it's inner iterator, at every step up to n calls to next/next_back
12608        fn test_steps<I>(ours: OneOrManyWithParens<usize>, inner: I, n: usize)
12609        where
12610            I: IntoIterator<Item = usize, IntoIter: DoubleEndedIterator + Clone> + Clone,
12611        {
12612            fn checks<I>(ours: OneOrManyWithParensIntoIter<usize>, inner: I)
12613            where
12614                I: Iterator<Item = usize> + Clone + DoubleEndedIterator,
12615            {
12616                assert_eq!(ours.size_hint(), inner.size_hint());
12617                assert_eq!(ours.clone().count(), inner.clone().count());
12618
12619                assert_eq!(
12620                    ours.clone().fold(1, |a, v| a + v),
12621                    inner.clone().fold(1, |a, v| a + v)
12622                );
12623
12624                assert_eq!(Vec::from_iter(ours.clone()), Vec::from_iter(inner.clone()));
12625                assert_eq!(
12626                    Vec::from_iter(ours.clone().rev()),
12627                    Vec::from_iter(inner.clone().rev())
12628                );
12629            }
12630
12631            let mut ours_next = ours.clone().into_iter();
12632            let mut inner_next = inner.clone().into_iter();
12633
12634            for _ in 0..n {
12635                checks(ours_next.clone(), inner_next.clone());
12636
12637                assert_eq!(ours_next.next(), inner_next.next());
12638            }
12639
12640            let mut ours_next_back = ours.clone().into_iter();
12641            let mut inner_next_back = inner.clone().into_iter();
12642
12643            for _ in 0..n {
12644                checks(ours_next_back.clone(), inner_next_back.clone());
12645
12646                assert_eq!(ours_next_back.next_back(), inner_next_back.next_back());
12647            }
12648
12649            let mut ours_mixed = ours.clone().into_iter();
12650            let mut inner_mixed = inner.clone().into_iter();
12651
12652            for i in 0..n {
12653                checks(ours_mixed.clone(), inner_mixed.clone());
12654
12655                if i % 2 == 0 {
12656                    assert_eq!(ours_mixed.next_back(), inner_mixed.next_back());
12657                } else {
12658                    assert_eq!(ours_mixed.next(), inner_mixed.next());
12659                }
12660            }
12661
12662            let mut ours_mixed2 = ours.into_iter();
12663            let mut inner_mixed2 = inner.into_iter();
12664
12665            for i in 0..n {
12666                checks(ours_mixed2.clone(), inner_mixed2.clone());
12667
12668                if i % 2 == 0 {
12669                    assert_eq!(ours_mixed2.next(), inner_mixed2.next());
12670                } else {
12671                    assert_eq!(ours_mixed2.next_back(), inner_mixed2.next_back());
12672                }
12673            }
12674        }
12675
12676        test_steps(OneOrManyWithParens::One(1), once(1), 3);
12677        test_steps(OneOrManyWithParens::Many(vec![2]), vec![2], 3);
12678        test_steps(OneOrManyWithParens::Many(vec![3, 4]), vec![3, 4], 4);
12679    }
12680
12681    // Tests that the position in the code of an `Ident` does not affect its
12682    // ordering.
12683    #[test]
12684    fn test_ident_ord() {
12685        let mut a = Ident::with_span(Span::new(Location::new(1, 1), Location::new(1, 1)), "a");
12686        let mut b = Ident::with_span(Span::new(Location::new(2, 2), Location::new(2, 2)), "b");
12687
12688        assert!(a < b);
12689        std::mem::swap(&mut a.span, &mut b.span);
12690        assert!(a < b);
12691    }
12692}