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 core::ops::ControlFlow;
44#[cfg(feature = "visitor")]
45use sqlparser_derive::{Visit, VisitMut};
46
47use crate::{
48    display_utils::SpaceOrNewline,
49    tokenizer::{Span, Token},
50};
51use crate::{
52    display_utils::{Indent, NewLine},
53    keywords::Keyword,
54};
55
56pub use self::data_type::{
57    ArrayElemTypeDef, BinaryLength, CharLengthUnits, CharacterLength, DataType, EnumMember,
58    ExactNumberInfo, IntervalFields, MapBracketKind, StructBracketKind, TimezoneInfo,
59};
60pub use self::dcl::{
61    AlterRoleOperation, CreateRole, Grant, ResetConfig, Revoke, RoleOption, SecondaryRoles,
62    SetConfigValue, Use,
63};
64pub use self::ddl::{
65    Alignment, AlterCollation, AlterCollationOperation, AlterColumnOperation, AlterConnectorOwner,
66    AlterFunction, AlterFunctionAction, AlterFunctionKind, AlterFunctionOperation,
67    AlterIndexOperation, AlterOperator, AlterOperatorClass, AlterOperatorClassOperation,
68    AlterOperatorFamily, AlterOperatorFamilyOperation, AlterOperatorOperation, AlterPolicy,
69    AlterPolicyOperation, AlterSchema, AlterSchemaOperation, AlterTable, AlterTableAlgorithm,
70    AlterTableLock, AlterTableOperation, AlterTableType, AlterTextSearch, AlterTextSearchOperation,
71    AlterTextSearchOption, AlterType, AlterTypeAddValue, AlterTypeAddValuePosition,
72    AlterTypeOperation, AlterTypeRename, AlterTypeRenameValue, ClusteredBy, ColumnDef,
73    ColumnOption, ColumnOptionDef, ColumnOptions, ColumnPolicy, ColumnPolicyProperty,
74    ConstraintCharacteristics, CreateCollation, CreateCollationDefinition, CreateConnector,
75    CreateDomain, CreateExtension, CreateFunction, CreateIndex, CreateOperator,
76    CreateOperatorClass, CreateOperatorFamily, CreatePolicy, CreatePolicyCommand, CreatePolicyType,
77    CreateTable, CreateTextSearch, CreateTrigger, CreateView, Deduplicate, DeferrableInitial,
78    DistStyle, DropBehavior, DropExtension, DropFunction, DropOperator, DropOperatorClass,
79    DropOperatorFamily, DropOperatorSignature, DropPolicy, DropTrigger, ForValues,
80    FunctionReturnType, GeneratedAs, GeneratedExpressionMode, IdentityParameters, IdentityProperty,
81    IdentityPropertyFormatKind, IdentityPropertyKind, IdentityPropertyOrder, IndexColumn,
82    IndexOption, IndexType, KeyOrIndexDisplay, Msck, NullsDistinctOption, OperatorArgTypes,
83    OperatorClassItem, OperatorFamilyDropItem, OperatorFamilyItem, OperatorOption, OperatorPurpose,
84    Owner, Partition, PartitionBoundValue, ProcedureParam, ReferentialAction, RenameTableNameKind,
85    ReplicaIdentity, TagsColumnOption, TextSearchObjectType, TriggerObjectKind, Truncate,
86    UserDefinedTypeCompositeAttributeDef, UserDefinedTypeInternalLength,
87    UserDefinedTypeRangeOption, UserDefinedTypeRepresentation, UserDefinedTypeSqlDefinitionOption,
88    UserDefinedTypeStorage, ViewColumnDef, WithData,
89};
90pub use self::dml::{
91    Delete, Insert, Merge, MergeAction, MergeClause, MergeClauseKind, MergeInsertExpr,
92    MergeInsertKind, MergeUpdateExpr, MergeUpdateKind, MultiTableInsertIntoClause,
93    MultiTableInsertType, MultiTableInsertValue, MultiTableInsertValues,
94    MultiTableInsertWhenClause, OutputClause, Update,
95};
96pub use self::operator::{BinaryOperator, UnaryOperator};
97pub use self::query::{
98    AfterMatchSkip, ConnectByKind, Cte, CteAsMaterialized, Distinct, EmptyMatchesMode,
99    ExceptSelectItem, ExcludeSelectItem, ExprWithAlias, ExprWithAliasAndOrderBy, Fetch, ForClause,
100    ForJson, ForXml, FormatClause, GroupByExpr, GroupByWithModifier, IdentWithAlias,
101    IlikeSelectItem, InputFormatClause, Interpolate, InterpolateExpr, Join, JoinConstraint,
102    JoinOperator, JsonTableColumn, JsonTableColumnErrorHandling, JsonTableNamedColumn,
103    JsonTableNestedColumn, LateralView, LimitClause, LockClause, LockType, MatchRecognizePattern,
104    MatchRecognizeSymbol, Measure, NamedWindowDefinition, NamedWindowExpr, NonBlock, Offset,
105    OffsetRows, OpenJsonTableColumn, OrderBy, OrderByExpr, OrderByKind, OrderByOptions,
106    OrderBySort, PipeOperator, PivotValueSource, ProjectionSelect, Query, RenameSelectItem,
107    RepetitionQuantifier, ReplaceSelectElement, ReplaceSelectItem, RowsPerMatch, Select,
108    SelectFlavor, SelectInto, SelectItem, SelectItemQualifiedWildcardKind, SelectModifiers,
109    SetExpr, SetOperator, SetQuantifier, Setting, SymbolDefinition, Table, TableAlias,
110    TableAliasColumnDef, TableFactor, TableFunctionArgs, TableIndexHintForClause,
111    TableIndexHintType, TableIndexHints, TableIndexType, TableSample, TableSampleBucket,
112    TableSampleKind, TableSampleMethod, TableSampleModifier, TableSampleQuantity, TableSampleSeed,
113    TableSampleSeedModifier, TableSampleUnit, TableVersion, TableWithJoins, Top, TopQuantity,
114    UpdateTableFromKind, ValueTableMode, Values, WildcardAdditionalOptions, With, WithFill,
115    XmlNamespaceDefinition, XmlPassingArgument, XmlPassingClause, XmlTableColumn,
116    XmlTableColumnOption,
117};
118
119pub use self::trigger::{
120    TriggerEvent, TriggerExecBody, TriggerExecBodyType, TriggerObject, TriggerPeriod,
121    TriggerReferencing, TriggerReferencingType,
122};
123
124pub use self::value::{
125    escape_double_quote_string, escape_quoted_string, DateTimeField, DollarQuotedString,
126    NormalizationForm, QuoteDelimitedString, TrimWhereField, Value, ValueWithSpan,
127};
128
129use crate::ast::helpers::key_value_options::KeyValueOptions;
130use crate::ast::helpers::stmt_data_loading::StageParamsObject;
131
132#[cfg(feature = "visitor")]
133pub use visitor::*;
134
135pub use self::data_type::GeometricTypeKind;
136
137mod data_type;
138mod dcl;
139mod ddl;
140mod dml;
141/// Helper modules for building and manipulating AST nodes.
142pub mod helpers;
143pub mod table_constraints;
144pub use table_constraints::{
145    CheckConstraint, ConstraintUsingIndex, ExcludeConstraint, ExcludeConstraintElement,
146    ExcludeConstraintOperator, ForeignKeyConstraint, FullTextOrSpatialConstraint, IndexConstraint,
147    PrimaryKeyConstraint, TableConstraint, UniqueConstraint,
148};
149mod operator;
150mod query;
151mod spans;
152pub use spans::Spanned;
153
154pub mod comments;
155mod trigger;
156mod value;
157
158#[cfg(feature = "visitor")]
159mod visitor;
160
161/// Helper used to format a slice using a separator string (e.g., `", "`).
162pub struct DisplaySeparated<'a, T>
163where
164    T: fmt::Display,
165{
166    slice: &'a [T],
167    sep: &'static str,
168}
169
170impl<T> fmt::Display for DisplaySeparated<'_, T>
171where
172    T: fmt::Display,
173{
174    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
175        let mut delim = "";
176        for t in self.slice {
177            f.write_str(delim)?;
178            delim = self.sep;
179            t.fmt(f)?;
180        }
181        Ok(())
182    }
183}
184
185pub(crate) fn display_separated<'a, T>(slice: &'a [T], sep: &'static str) -> DisplaySeparated<'a, T>
186where
187    T: fmt::Display,
188{
189    DisplaySeparated { slice, sep }
190}
191
192pub(crate) fn display_comma_separated<T>(slice: &[T]) -> DisplaySeparated<'_, T>
193where
194    T: fmt::Display,
195{
196    DisplaySeparated { slice, sep: ", " }
197}
198
199/// Writes the given statements to the formatter, each ending with
200/// a semicolon and space separated.
201fn format_statement_list(f: &mut fmt::Formatter, statements: &[Statement]) -> fmt::Result {
202    write!(f, "{}", display_separated(statements, "; "))?;
203    // We manually insert semicolon for the last statement,
204    // since display_separated doesn't handle that case.
205    write!(f, ";")
206}
207
208/// A item `T` enclosed in a pair of parentheses
209#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
210#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
211#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
212pub struct Parens<T> {
213    /// the opening parenthesis token, i.e. `(`
214    pub opening_token: AttachedToken,
215    /// content enclosed in parentheses
216    pub content: T,
217    /// the closing parenthesis token, i.e. `)`
218    pub closing_token: AttachedToken,
219}
220
221impl<T> Parens<T> {
222    /// Constructor wrapping `content` into `Parens` with an empty span;
223    /// useful for testing purposes.
224    pub fn with_empty_span(content: T) -> Self {
225        Self {
226            opening_token: AttachedToken::empty(),
227            content,
228            closing_token: AttachedToken::empty(),
229        }
230    }
231}
232
233impl<T> Deref for Parens<T> {
234    type Target = T;
235
236    fn deref(&self) -> &Self::Target {
237        &self.content
238    }
239}
240
241impl<T> DerefMut for Parens<T> {
242    fn deref_mut(&mut self) -> &mut Self::Target {
243        &mut self.content
244    }
245}
246
247/// An identifier, decomposed into its value or character data and the quote style.
248#[derive(Debug, Clone)]
249#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
250pub struct Ident {
251    /// The value of the identifier without quotes.
252    pub value: String,
253    /// The starting quote if any. Valid quote characters are the single quote,
254    /// double quote, backtick, and opening square bracket.
255    pub quote_style: Option<char>,
256    /// The span of the identifier in the original SQL string.
257    pub span: Span,
258}
259
260impl PartialEq for Ident {
261    fn eq(&self, other: &Self) -> bool {
262        let Ident {
263            value,
264            quote_style,
265            // exhaustiveness check; we ignore spans in comparisons
266            span: _,
267        } = self;
268
269        value == &other.value && quote_style == &other.quote_style
270    }
271}
272
273impl core::hash::Hash for Ident {
274    fn hash<H: hash::Hasher>(&self, state: &mut H) {
275        let Ident {
276            value,
277            quote_style,
278            // exhaustiveness check; we ignore spans in hashes
279            span: _,
280        } = self;
281
282        value.hash(state);
283        quote_style.hash(state);
284    }
285}
286
287impl Eq for Ident {}
288
289impl PartialOrd for Ident {
290    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
291        Some(self.cmp(other))
292    }
293}
294
295impl Ord for Ident {
296    fn cmp(&self, other: &Self) -> Ordering {
297        let Ident {
298            value,
299            quote_style,
300            // exhaustiveness check; we ignore spans in ordering
301            span: _,
302        } = self;
303
304        let Ident {
305            value: other_value,
306            quote_style: other_quote_style,
307            // exhaustiveness check; we ignore spans in ordering
308            span: _,
309        } = other;
310
311        // First compare by value, then by quote_style
312        value
313            .cmp(other_value)
314            .then_with(|| quote_style.cmp(other_quote_style))
315    }
316}
317
318impl Ident {
319    /// Create a new identifier with the given value and no quotes and an empty span.
320    pub fn new<S>(value: S) -> Self
321    where
322        S: Into<String>,
323    {
324        Ident {
325            value: value.into(),
326            quote_style: None,
327            span: Span::empty(),
328        }
329    }
330
331    /// Create a new quoted identifier with the given quote and value. This function
332    /// panics if the given quote is not a valid quote character.
333    pub fn with_quote<S>(quote: char, value: S) -> Self
334    where
335        S: Into<String>,
336    {
337        assert!(quote == '\'' || quote == '"' || quote == '`' || quote == '[');
338        Ident {
339            value: value.into(),
340            quote_style: Some(quote),
341            span: Span::empty(),
342        }
343    }
344
345    /// Create an `Ident` with the given `span` and `value` (unquoted).
346    pub fn with_span<S>(span: Span, value: S) -> Self
347    where
348        S: Into<String>,
349    {
350        Ident {
351            value: value.into(),
352            quote_style: None,
353            span,
354        }
355    }
356
357    /// Create a quoted `Ident` with the given `quote` and `span`.
358    pub fn with_quote_and_span<S>(quote: char, span: Span, value: S) -> Self
359    where
360        S: Into<String>,
361    {
362        assert!(quote == '\'' || quote == '"' || quote == '`' || quote == '[');
363        Ident {
364            value: value.into(),
365            quote_style: Some(quote),
366            span,
367        }
368    }
369}
370
371impl From<&str> for Ident {
372    fn from(value: &str) -> Self {
373        Ident {
374            value: value.to_string(),
375            quote_style: None,
376            span: Span::empty(),
377        }
378    }
379}
380
381impl fmt::Display for Ident {
382    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
383        match self.quote_style {
384            Some(q) if q == '"' || q == '\'' || q == '`' => {
385                let escaped = value::escape_quoted_string(&self.value, q);
386                write!(f, "{q}{escaped}{q}")
387            }
388            Some('[') => write!(f, "[{}]", self.value),
389            None => f.write_str(&self.value),
390            _ => panic!("unexpected quote style"),
391        }
392    }
393}
394
395#[cfg(feature = "visitor")]
396impl Visit for Ident {
397    fn visit<V: Visitor>(&self, visitor: &mut V) -> ControlFlow<V::Break> {
398        visitor.pre_visit_ident(self)?;
399        visitor.post_visit_ident(self)
400    }
401}
402
403#[cfg(feature = "visitor")]
404impl VisitMut for Ident {
405    fn visit<V: VisitorMut>(&mut self, visitor: &mut V) -> ControlFlow<V::Break> {
406        visitor.pre_visit_ident(self)?;
407        visitor.post_visit_ident(self)
408    }
409}
410
411/// A name of a table, view, custom type, etc., possibly multi-part, i.e. db.schema.obj
412#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
413#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
414#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
415pub struct ObjectName(pub Vec<ObjectNamePart>);
416
417impl From<Vec<Ident>> for ObjectName {
418    fn from(idents: Vec<Ident>) -> Self {
419        ObjectName(idents.into_iter().map(ObjectNamePart::Identifier).collect())
420    }
421}
422
423impl From<Ident> for ObjectName {
424    fn from(ident: Ident) -> Self {
425        ObjectName(vec![ObjectNamePart::Identifier(ident)])
426    }
427}
428
429impl fmt::Display for ObjectName {
430    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
431        write!(f, "{}", display_separated(&self.0, "."))
432    }
433}
434
435/// A single part of an ObjectName
436#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
437#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
438#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
439pub enum ObjectNamePart {
440    /// A single identifier part, e.g. `schema` or `table`.
441    Identifier(Ident),
442    /// A function that returns an identifier (dialect-specific).
443    Function(ObjectNamePartFunction),
444}
445
446impl ObjectNamePart {
447    /// Return the identifier if this is an `Identifier` variant.
448    pub fn as_ident(&self) -> Option<&Ident> {
449        match self {
450            ObjectNamePart::Identifier(ident) => Some(ident),
451            ObjectNamePart::Function(_) => None,
452        }
453    }
454}
455
456impl fmt::Display for ObjectNamePart {
457    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
458        match self {
459            ObjectNamePart::Identifier(ident) => write!(f, "{ident}"),
460            ObjectNamePart::Function(func) => write!(f, "{func}"),
461        }
462    }
463}
464
465/// An object name part that consists of a function that dynamically
466/// constructs identifiers.
467///
468/// - [Snowflake](https://docs.snowflake.com/en/sql-reference/identifier-literal)
469#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
470#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
471#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
472pub struct ObjectNamePartFunction {
473    /// The function name that produces the object name part.
474    pub name: Ident,
475    /// Function arguments used to compute the identifier.
476    pub args: Vec<FunctionArg>,
477}
478
479impl fmt::Display for ObjectNamePartFunction {
480    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
481        write!(f, "{}(", self.name)?;
482        write!(f, "{})", display_comma_separated(&self.args))
483    }
484}
485
486/// Represents an Array Expression, either
487/// `ARRAY[..]`, or `[..]`
488#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
489#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
490#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
491pub struct Array {
492    /// The list of expressions between brackets
493    pub elem: Vec<Expr>,
494
495    /// `true` for  `ARRAY[..]`, `false` for `[..]`
496    pub named: bool,
497}
498
499impl fmt::Display for Array {
500    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
501        write!(
502            f,
503            "{}[{}]",
504            if self.named { "ARRAY" } else { "" },
505            display_comma_separated(&self.elem)
506        )
507    }
508}
509
510/// Represents an INTERVAL expression, roughly in the following format:
511/// `INTERVAL '<value>' [ <leading_field> [ (<leading_precision>) ] ]
512/// [ TO <last_field> [ (<fractional_seconds_precision>) ] ]`,
513/// e.g. `INTERVAL '123:45.67' MINUTE(3) TO SECOND(2)`.
514///
515/// The parser does not validate the `<value>`, nor does it ensure
516/// that the `<leading_field>` units >= the units in `<last_field>`,
517/// so the user will have to reject intervals like `HOUR TO YEAR`.
518#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
519#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
520#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
521pub struct Interval {
522    /// The interval value expression (commonly a string literal).
523    pub value: Box<Expr>,
524    /// Optional leading time unit (e.g., `HOUR`, `MINUTE`).
525    pub leading_field: Option<DateTimeField>,
526    /// Optional leading precision for the leading field.
527    pub leading_precision: Option<u64>,
528    /// Optional trailing time unit for a range (e.g., `SECOND`).
529    pub last_field: Option<DateTimeField>,
530    /// The fractional seconds precision, when specified.
531    ///
532    /// See SQL `SECOND(n)` or `SECOND(m, n)` forms.
533    pub fractional_seconds_precision: Option<u64>,
534}
535
536impl fmt::Display for Interval {
537    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
538        let value = self.value.as_ref();
539        match (
540            &self.leading_field,
541            self.leading_precision,
542            self.fractional_seconds_precision,
543        ) {
544            (
545                Some(DateTimeField::Second),
546                Some(leading_precision),
547                Some(fractional_seconds_precision),
548            ) => {
549                // When the leading field is SECOND, the parser guarantees that
550                // the last field is None.
551                assert!(self.last_field.is_none());
552                write!(
553                    f,
554                    "INTERVAL {value} SECOND ({leading_precision}, {fractional_seconds_precision})"
555                )
556            }
557            _ => {
558                write!(f, "INTERVAL {value}")?;
559                if let Some(leading_field) = &self.leading_field {
560                    write!(f, " {leading_field}")?;
561                }
562                if let Some(leading_precision) = self.leading_precision {
563                    write!(f, " ({leading_precision})")?;
564                }
565                if let Some(last_field) = &self.last_field {
566                    write!(f, " TO {last_field}")?;
567                }
568                if let Some(fractional_seconds_precision) = self.fractional_seconds_precision {
569                    write!(f, " ({fractional_seconds_precision})")?;
570                }
571                Ok(())
572            }
573        }
574    }
575}
576
577/// A field definition within a struct
578///
579/// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-types#struct_type
580#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
581#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
582#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
583pub struct StructField {
584    /// Optional name of the struct field.
585    pub field_name: Option<Ident>,
586    /// The field data type.
587    pub field_type: DataType,
588    /// Struct field options (e.g., `OPTIONS(...)` on BigQuery).
589    /// See [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#column_name_and_column_schema)
590    pub options: Option<Vec<SqlOption>>,
591}
592
593impl fmt::Display for StructField {
594    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
595        if let Some(name) = &self.field_name {
596            write!(f, "{name} {}", self.field_type)?;
597        } else {
598            write!(f, "{}", self.field_type)?;
599        }
600        if let Some(options) = &self.options {
601            write!(f, " OPTIONS({})", display_separated(options, ", "))
602        } else {
603            Ok(())
604        }
605    }
606}
607
608/// A field definition within a union
609///
610/// [DuckDB]: https://duckdb.org/docs/sql/data_types/union.html
611#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
612#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
613#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
614pub struct UnionField {
615    /// Name of the union field.
616    pub field_name: Ident,
617    /// Type of the union field.
618    pub field_type: DataType,
619}
620
621impl fmt::Display for UnionField {
622    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
623        write!(f, "{} {}", self.field_name, self.field_type)
624    }
625}
626
627/// A dictionary field within a dictionary.
628///
629/// [DuckDB]: https://duckdb.org/docs/sql/data_types/struct#creating-structs
630#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
631#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
632#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
633pub struct DictionaryField {
634    /// Dictionary key identifier.
635    pub key: Ident,
636    /// Value expression for the dictionary entry.
637    pub value: Box<Expr>,
638}
639
640impl fmt::Display for DictionaryField {
641    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
642        write!(f, "{}: {}", self.key, self.value)
643    }
644}
645
646/// Represents a Map expression.
647#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
648#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
649#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
650pub struct Map {
651    /// Entries of the map as key/value pairs.
652    pub entries: Vec<MapEntry>,
653}
654
655impl Display for Map {
656    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
657        write!(f, "MAP {{{}}}", display_comma_separated(&self.entries))
658    }
659}
660
661/// A map field within a map.
662///
663/// [DuckDB]: https://duckdb.org/docs/sql/data_types/map.html#creating-maps
664#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
665#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
666#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
667pub struct MapEntry {
668    /// Key expression of the map entry.
669    pub key: Box<Expr>,
670    /// Value expression of the map entry.
671    pub value: Box<Expr>,
672}
673
674impl fmt::Display for MapEntry {
675    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
676        write!(f, "{}: {}", self.key, self.value)
677    }
678}
679
680/// Options for `CAST` / `TRY_CAST`
681/// BigQuery: <https://cloud.google.com/bigquery/docs/reference/standard-sql/format-elements#formatting_syntax>
682#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
683#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
684#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
685pub enum CastFormat {
686    /// A simple cast format specified by a `Value`.
687    Value(ValueWithSpan),
688    /// A cast format with an explicit time zone: `(format, timezone)`.
689    ValueAtTimeZone(ValueWithSpan, ValueWithSpan),
690}
691
692/// An element of a JSON path.
693#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
694#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
695#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
696pub enum JsonPathElem {
697    /// Accesses an object field using dot notation, e.g. `obj:foo.bar.baz`.
698    ///
699    /// See <https://docs.snowflake.com/en/user-guide/querying-semistructured#dot-notation>.
700    Dot {
701        /// The object key text (without quotes).
702        key: String,
703        /// `true` when the key was quoted in the source.
704        quoted: bool,
705    },
706    /// Accesses an object field or array element using bracket notation,
707    /// e.g. `obj['foo']`.
708    ///
709    /// See <https://docs.snowflake.com/en/user-guide/querying-semistructured#bracket-notation>.
710    Bracket {
711        /// The expression used as the bracket key (string or numeric expression).
712        key: Expr,
713    },
714    /// Access an object field using colon bracket notation
715    /// e.g. `obj:['foo']`
716    ///
717    /// See <https://docs.databricks.com/en/sql/language-manual/functions/colonsign.html>
718    ColonBracket {
719        /// The expression used as the bracket key (string or numeric expression).
720        key: Expr,
721    },
722}
723
724/// A JSON path.
725///
726/// See <https://docs.snowflake.com/en/user-guide/querying-semistructured>.
727/// See <https://docs.databricks.com/en/sql/language-manual/sql-ref-json-path-expression.html>.
728#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
729#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
730#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
731pub struct JsonPath {
732    /// Sequence of path elements that form the JSON path.
733    pub path: Vec<JsonPathElem>,
734}
735
736impl fmt::Display for JsonPath {
737    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
738        for (i, elem) in self.path.iter().enumerate() {
739            match elem {
740                JsonPathElem::Dot { key, quoted } => {
741                    if i == 0 {
742                        write!(f, ":")?;
743                    } else {
744                        write!(f, ".")?;
745                    }
746
747                    if *quoted {
748                        write!(f, "\"{}\"", escape_double_quote_string(key))?;
749                    } else {
750                        write!(f, "{key}")?;
751                    }
752                }
753                JsonPathElem::Bracket { key } => {
754                    write!(f, "[{key}]")?;
755                }
756                JsonPathElem::ColonBracket { key } => {
757                    write!(f, ":[{key}]")?;
758                }
759            }
760        }
761        Ok(())
762    }
763}
764
765/// The syntax used for in a cast expression.
766#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
767#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
768#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
769pub enum CastKind {
770    /// The standard SQL cast syntax, e.g. `CAST(<expr> as <datatype>)`
771    Cast,
772    /// A cast that returns `NULL` on failure, e.g. `TRY_CAST(<expr> as <datatype>)`.
773    ///
774    /// See <https://docs.snowflake.com/en/sql-reference/functions/try_cast>.
775    /// See <https://learn.microsoft.com/en-us/sql/t-sql/functions/try-cast-transact-sql>.
776    TryCast,
777    /// A cast that returns `NULL` on failure, bigQuery-specific ,  e.g. `SAFE_CAST(<expr> as <datatype>)`.
778    ///
779    /// See <https://cloud.google.com/bigquery/docs/reference/standard-sql/functions-and-operators#safe_casting>.
780    SafeCast,
781    /// `<expr> :: <datatype>`
782    DoubleColon,
783}
784
785/// `MATCH` type for constraint references
786///
787/// See: <https://www.postgresql.org/docs/current/sql-createtable.html#SQL-CREATETABLE-PARMS-REFERENCES>
788#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
789#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
790#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
791pub enum ConstraintReferenceMatchKind {
792    /// `MATCH FULL`
793    Full,
794    /// `MATCH PARTIAL`
795    Partial,
796    /// `MATCH SIMPLE`
797    Simple,
798}
799
800impl fmt::Display for ConstraintReferenceMatchKind {
801    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
802        match self {
803            Self::Full => write!(f, "MATCH FULL"),
804            Self::Partial => write!(f, "MATCH PARTIAL"),
805            Self::Simple => write!(f, "MATCH SIMPLE"),
806        }
807    }
808}
809
810/// `EXTRACT` syntax variants.
811///
812/// In Snowflake dialect, the `EXTRACT` expression can support either the `from` syntax
813/// or the comma syntax.
814///
815/// See <https://docs.snowflake.com/en/sql-reference/functions/extract>
816#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
817#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
818#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
819pub enum ExtractSyntax {
820    /// `EXTRACT( <date_or_time_part> FROM <date_or_time_expr> )`
821    From,
822    /// `EXTRACT( <date_or_time_part> , <date_or_timestamp_expr> )`
823    Comma,
824}
825
826/// The syntax used in a CEIL or FLOOR expression.
827///
828/// The `CEIL/FLOOR(<datetime value expression> TO <time unit>)` is an Amazon Kinesis Data Analytics extension.
829/// See <https://docs.aws.amazon.com/kinesisanalytics/latest/sqlref/sql-reference-ceil.html> for
830/// details.
831///
832/// Other dialects either support `CEIL/FLOOR( <expr> [, <scale>])` format or just
833/// `CEIL/FLOOR(<expr>)`.
834#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
835#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
836#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
837pub enum CeilFloorKind {
838    /// `CEIL( <expr> TO <DateTimeField>)`
839    DateTimeField(DateTimeField),
840    /// `CEIL( <expr> [, <scale>])`
841    Scale(ValueWithSpan),
842}
843
844/// A WHEN clause in a CASE expression containing both
845/// the condition and its corresponding result
846#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
847#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
848#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
849pub struct CaseWhen {
850    /// The `WHEN` condition expression.
851    pub condition: Expr,
852    /// The expression returned when `condition` matches.
853    pub result: Expr,
854}
855
856impl fmt::Display for CaseWhen {
857    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
858        f.write_str("WHEN ")?;
859        self.condition.fmt(f)?;
860        f.write_str(" THEN")?;
861        SpaceOrNewline.fmt(f)?;
862        Indent(&self.result).fmt(f)?;
863        Ok(())
864    }
865}
866
867/// An SQL expression of any type.
868///
869/// # Semantics / Type Checking
870///
871/// The parser does not distinguish between expressions of different types
872/// (e.g. boolean vs string). The caller is responsible for detecting and
873/// validating types as necessary (for example  `WHERE 1` vs `SELECT 1=1`)
874/// See the [README.md] for more details.
875///
876/// [README.md]: https://github.com/apache/datafusion-sqlparser-rs/blob/main/README.md#syntax-vs-semantics
877///
878/// # Equality and Hashing Does not Include Source Locations
879///
880/// The `Expr` type implements `PartialEq` and `Eq` based on the semantic value
881/// of the expression (not bitwise comparison). This means that `Expr` instances
882/// that are semantically equivalent but have different spans (locations in the
883/// source tree) will compare as equal.
884#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
885#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
886#[cfg_attr(
887    feature = "visitor",
888    derive(Visit, VisitMut),
889    visit(with = "visit_expr")
890)]
891pub enum Expr {
892    /// Identifier e.g. table name or column name
893    Identifier(Ident),
894    /// Multi-part identifier, e.g. `table_alias.column` or `schema.table.col`
895    CompoundIdentifier(Vec<Ident>),
896    /// Multi-part expression access.
897    ///
898    /// This structure represents an access chain in structured / nested types
899    /// such as maps, arrays, and lists:
900    /// - Array
901    ///     - A 1-dim array `a[1]` will be represented like:
902    ///       `CompoundFieldAccess(Ident('a'), vec![Subscript(1)]`
903    ///     - A 2-dim array `a[1][2]` will be represented like:
904    ///       `CompoundFieldAccess(Ident('a'), vec![Subscript(1), Subscript(2)]`
905    /// - Map or Struct (Bracket-style)
906    ///     - A map `a['field1']` will be represented like:
907    ///       `CompoundFieldAccess(Ident('a'), vec![Subscript('field')]`
908    ///     - A 2-dim map `a['field1']['field2']` will be represented like:
909    ///       `CompoundFieldAccess(Ident('a'), vec![Subscript('field1'), Subscript('field2')]`
910    /// - Struct (Dot-style) (only effect when the chain contains both subscript and expr)
911    ///     - A struct access `a[field1].field2` will be represented like:
912    ///       `CompoundFieldAccess(Ident('a'), vec![Subscript('field1'), Ident('field2')]`
913    /// - If a struct access likes `a.field1.field2`, it will be represented by CompoundIdentifier([a, field1, field2])
914    CompoundFieldAccess {
915        /// The base expression being accessed.
916        root: Box<Expr>,
917        /// Sequence of access operations (subscript or identifier accesses).
918        access_chain: Vec<AccessExpr>,
919    },
920    /// Access data nested in a value containing semi-structured data, such as
921    /// the `VARIANT` type on Snowflake. for example `src:customer[0].name`.
922    ///
923    /// See <https://docs.snowflake.com/en/user-guide/querying-semistructured>.
924    /// See <https://docs.databricks.com/en/sql/language-manual/functions/colonsign.html>.
925    JsonAccess {
926        /// The value being queried.
927        value: Box<Expr>,
928        /// The path to the data to extract.
929        path: JsonPath,
930    },
931    /// `IS FALSE` operator
932    IsFalse(Box<Expr>),
933    /// `IS NOT FALSE` operator
934    IsNotFalse(Box<Expr>),
935    /// `IS TRUE` operator
936    IsTrue(Box<Expr>),
937    /// `IS NOT TRUE` operator
938    IsNotTrue(Box<Expr>),
939    /// `IS NULL` operator
940    IsNull(Box<Expr>),
941    /// `IS NOT NULL` operator
942    IsNotNull(Box<Expr>),
943    /// `IS UNKNOWN` operator
944    IsUnknown(Box<Expr>),
945    /// `IS NOT UNKNOWN` operator
946    IsNotUnknown(Box<Expr>),
947    /// `IS DISTINCT FROM` operator
948    IsDistinctFrom(Box<Expr>, Box<Expr>),
949    /// `IS NOT DISTINCT FROM` operator
950    IsNotDistinctFrom(Box<Expr>, Box<Expr>),
951    /// `<expr> IS [NOT] JSON [VALUE|SCALAR|ARRAY|OBJECT] [WITH|WITHOUT UNIQUE [KEYS]]`
952    IsJson {
953        /// Expression being tested.
954        expr: Box<Expr>,
955        /// Optional JSON shape constraint.
956        kind: Option<JsonPredicateType>,
957        /// Optional duplicate-key handling constraint for JSON objects.
958        unique_keys: Option<JsonKeyUniqueness>,
959        /// `true` when `NOT` is present.
960        negated: bool,
961    },
962    /// `<expr> IS [ NOT ] [ form ] NORMALIZED`
963    IsNormalized {
964        /// Expression being tested.
965        expr: Box<Expr>,
966        /// Optional normalization `form` (e.g., NFC, NFD).
967        form: Option<NormalizationForm>,
968        /// `true` when `NOT` is present.
969        negated: bool,
970    },
971    /// `[ NOT ] IN (val1, val2, ...)`
972    InList {
973        /// Left-hand expression to test for membership.
974        expr: Box<Expr>,
975        /// Literal list of expressions to check against.
976        list: Vec<Expr>,
977        /// `true` when the `NOT` modifier is present.
978        negated: bool,
979    },
980    /// `[ NOT ] IN (SELECT ...)`
981    InSubquery {
982        /// Left-hand expression to test for membership.
983        expr: Box<Expr>,
984        /// The subquery providing the candidate values.
985        subquery: Box<Query>,
986        /// `true` when the `NOT` modifier is present.
987        negated: bool,
988    },
989    /// `[ NOT ] IN UNNEST(array_expression)`
990    InUnnest {
991        /// Left-hand expression to test for membership.
992        expr: Box<Expr>,
993        /// Array expression being unnested.
994        array_expr: Box<Expr>,
995        /// `true` when the `NOT` modifier is present.
996        negated: bool,
997    },
998    /// `<expr> [ NOT ] BETWEEN <low> AND <high>`
999    Between {
1000        /// Expression being compared.
1001        expr: Box<Expr>,
1002        /// `true` when the `NOT` modifier is present.
1003        negated: bool,
1004        /// Lower bound.
1005        low: Box<Expr>,
1006        /// Upper bound.
1007        high: Box<Expr>,
1008    },
1009    /// Binary operation e.g. `1 + 1` or `foo > bar`
1010    BinaryOp {
1011        /// Left operand.
1012        left: Box<Expr>,
1013        /// Operator between operands.
1014        op: BinaryOperator,
1015        /// Right operand.
1016        right: Box<Expr>,
1017    },
1018    /// `[NOT] LIKE <pattern> [ESCAPE <escape_character>]`
1019    Like {
1020        /// `true` when `NOT` is present.
1021        negated: bool,
1022        /// Snowflake supports the ANY keyword to match against a list of patterns
1023        /// <https://docs.snowflake.com/en/sql-reference/functions/like_any>
1024        any: bool,
1025        /// Expression to match.
1026        expr: Box<Expr>,
1027        /// Pattern expression.
1028        pattern: Box<Expr>,
1029        /// Optional escape character.
1030        escape_char: Option<Box<Expr>>,
1031    },
1032    /// `ILIKE` (case-insensitive `LIKE`)
1033    ILike {
1034        /// `true` when `NOT` is present.
1035        negated: bool,
1036        /// Snowflake supports the ANY keyword to match against a list of patterns
1037        /// <https://docs.snowflake.com/en/sql-reference/functions/like_any>
1038        any: bool,
1039        /// Expression to match.
1040        expr: Box<Expr>,
1041        /// Pattern expression.
1042        pattern: Box<Expr>,
1043        /// Optional escape character.
1044        escape_char: Option<Box<Expr>>,
1045    },
1046    /// `SIMILAR TO` regex
1047    SimilarTo {
1048        /// `true` when `NOT` is present.
1049        negated: bool,
1050        /// Expression to test.
1051        expr: Box<Expr>,
1052        /// Pattern expression.
1053        pattern: Box<Expr>,
1054        /// Optional escape character.
1055        escape_char: Option<Box<Expr>>,
1056    },
1057    /// MySQL: `RLIKE` regex or `REGEXP` regex
1058    RLike {
1059        /// `true` when `NOT` is present.
1060        negated: bool,
1061        /// Expression to test.
1062        expr: Box<Expr>,
1063        /// Pattern expression.
1064        pattern: Box<Expr>,
1065        /// true for REGEXP, false for RLIKE (no difference in semantics)
1066        regexp: bool,
1067    },
1068    /// `ANY` operation e.g. `foo > ANY(bar)`, comparison operator is one of `[=, >, <, =>, =<, !=]`
1069    /// <https://docs.snowflake.com/en/sql-reference/operators-subquery#all-any>
1070    AnyOp {
1071        /// Left operand.
1072        left: Box<Expr>,
1073        /// Comparison operator.
1074        compare_op: BinaryOperator,
1075        /// Right-hand subquery expression.
1076        right: Box<Expr>,
1077        /// ANY and SOME are synonymous: <https://docs.cloudera.com/cdw-runtime/cloud/using-hiveql/topics/hive_comparison_predicates.html>
1078        is_some: bool,
1079    },
1080    /// `ALL` operation e.g. `foo > ALL(bar)`, comparison operator is one of `[=, >, <, =>, =<, !=]`
1081    /// <https://docs.snowflake.com/en/sql-reference/operators-subquery#all-any>
1082    AllOp {
1083        /// Left operand.
1084        left: Box<Expr>,
1085        /// Comparison operator.
1086        compare_op: BinaryOperator,
1087        /// Right-hand subquery expression.
1088        right: Box<Expr>,
1089    },
1090
1091    /// Unary operation e.g. `NOT foo`
1092    UnaryOp {
1093        /// The unary operator (e.g., `NOT`, `-`).
1094        op: UnaryOperator,
1095        /// Operand expression.
1096        expr: Box<Expr>,
1097    },
1098    /// CONVERT a value to a different data type or character encoding. e.g. `CONVERT(foo USING utf8mb4)`
1099    Convert {
1100        /// CONVERT (false) or TRY_CONVERT (true)
1101        /// <https://learn.microsoft.com/en-us/sql/t-sql/functions/try-convert-transact-sql?view=sql-server-ver16>
1102        is_try: bool,
1103        /// The expression to convert.
1104        expr: Box<Expr>,
1105        /// The target data type, if provided.
1106        data_type: Option<DataType>,
1107        /// Optional target character encoding (e.g., `utf8mb4`).
1108        charset: Option<ObjectName>,
1109        /// `true` when target precedes the value (MSSQL syntax).
1110        target_before_value: bool,
1111        /// How to translate the expression.
1112        ///
1113        /// [MSSQL]: https://learn.microsoft.com/en-us/sql/t-sql/functions/cast-and-convert-transact-sql?view=sql-server-ver16#style
1114        styles: Vec<Expr>,
1115    },
1116    /// `CAST` an expression to a different data type e.g. `CAST(foo AS VARCHAR(123))`
1117    Cast {
1118        /// The cast kind (e.g., `CAST`, `TRY_CAST`).
1119        kind: CastKind,
1120        /// Expression being cast.
1121        expr: Box<Expr>,
1122        /// Target data type.
1123        data_type: DataType,
1124        /// Optional CAST(string_expression AS type FORMAT format_string_expression) as used by [BigQuery]
1125        ///
1126        /// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/format-elements#formatting_syntax
1127        format: Option<CastFormat>,
1128    },
1129    /// AT a timestamp to a different timezone e.g. `FROM_UNIXTIME(0) AT TIME ZONE 'UTC-06:00'`
1130    AtTimeZone {
1131        /// Timestamp expression to shift.
1132        timestamp: Box<Expr>,
1133        /// Time zone expression to apply.
1134        time_zone: Box<Expr>,
1135    },
1136    /// Extract a field from a timestamp e.g. `EXTRACT(MONTH FROM foo)`
1137    /// Or `EXTRACT(MONTH, foo)`
1138    ///
1139    /// Syntax:
1140    /// ```sql
1141    /// EXTRACT(DateTimeField FROM <expr>) | EXTRACT(DateTimeField, <expr>)
1142    /// ```
1143    Extract {
1144        /// Which datetime field is being extracted.
1145        field: DateTimeField,
1146        /// Syntax variant used (`From` or `Comma`).
1147        syntax: ExtractSyntax,
1148        /// Expression to extract from.
1149        expr: Box<Expr>,
1150    },
1151    /// ```sql
1152    /// CEIL(<expr> [TO DateTimeField])
1153    /// ```
1154    /// ```sql
1155    /// CEIL( <input_expr> [, <scale_expr> ] )
1156    /// ```
1157    Ceil {
1158        /// Expression to ceil.
1159        expr: Box<Expr>,
1160        /// The CEIL/FLOOR kind (datetime field or scale).
1161        field: CeilFloorKind,
1162    },
1163    /// ```sql
1164    /// FLOOR(<expr> [TO DateTimeField])
1165    /// ```
1166    /// ```sql
1167    /// FLOOR( <input_expr> [, <scale_expr> ] )
1168    ///
1169    Floor {
1170        /// Expression to floor.
1171        expr: Box<Expr>,
1172        /// The CEIL/FLOOR kind (datetime field or scale).
1173        field: CeilFloorKind,
1174    },
1175    /// ```sql
1176    /// POSITION(<expr> in <expr>)
1177    /// ```
1178    Position {
1179        /// Expression to search for.
1180        expr: Box<Expr>,
1181        /// Expression to search in.
1182        r#in: Box<Expr>,
1183    },
1184    /// ```sql
1185    /// SUBSTRING(<expr> [FROM <expr>] [FOR <expr>])
1186    /// ```
1187    /// or
1188    /// ```sql
1189    /// SUBSTRING(<expr>, <expr>, <expr>)
1190    /// ```
1191    Substring {
1192        /// Source expression.
1193        expr: Box<Expr>,
1194        /// Optional `FROM` expression.
1195        substring_from: Option<Box<Expr>>,
1196        /// Optional `FOR` expression.
1197        substring_for: Option<Box<Expr>>,
1198
1199        /// false if the expression is represented using the `SUBSTRING(expr [FROM start] [FOR len])` syntax
1200        /// true if the expression is represented using the `SUBSTRING(expr, start, len)` syntax
1201        /// This flag is used for formatting.
1202        special: bool,
1203
1204        /// true if the expression is represented using the `SUBSTR` shorthand
1205        /// This flag is used for formatting.
1206        shorthand: bool,
1207    },
1208    /// ```sql
1209    /// TRIM([BOTH | LEADING | TRAILING] [<expr> FROM] <expr>)
1210    /// TRIM(<expr>)
1211    /// TRIM(<expr>, [, characters]) -- PostgreSQL, DuckDB, Snowflake, BigQuery, Generic
1212    /// ```
1213    Trim {
1214        /// Which side to trim: `BOTH`, `LEADING`, or `TRAILING`.
1215        trim_where: Option<TrimWhereField>,
1216        /// Optional expression specifying what to trim from the value `expr`.
1217        trim_what: Option<Box<Expr>>,
1218        /// The expression to trim from.
1219        expr: Box<Expr>,
1220        /// Optional list of characters to trim (dialect-specific).
1221        trim_characters: Option<Vec<Expr>>,
1222    },
1223    /// ```sql
1224    /// OVERLAY(<expr> PLACING <expr> FROM <expr>[ FOR <expr> ]
1225    /// ```
1226    Overlay {
1227        /// The target expression being overlayed.
1228        expr: Box<Expr>,
1229        /// The expression to place into the target.
1230        overlay_what: Box<Expr>,
1231        /// The `FROM` position expression indicating where to start overlay.
1232        overlay_from: Box<Expr>,
1233        /// Optional `FOR` length expression limiting the overlay span.
1234        overlay_for: Option<Box<Expr>>,
1235    },
1236    /// `expr COLLATE collation`
1237    Collate {
1238        /// The expression being collated.
1239        expr: Box<Expr>,
1240        /// The collation name to apply to the expression.
1241        collation: ObjectName,
1242    },
1243    /// Nested expression e.g. `(foo > bar)` or `(1)`
1244    Nested(Box<Expr>),
1245    /// A literal value, such as string, number, date or NULL
1246    Value(ValueWithSpan),
1247    /// Prefixed expression, e.g. introducer strings, projection prefix
1248    /// <https://dev.mysql.com/doc/refman/8.0/en/charset-introducer.html>
1249    /// <https://docs.snowflake.com/en/sql-reference/constructs/connect-by>
1250    Prefixed {
1251        /// The prefix identifier (introducer or projection prefix).
1252        prefix: Ident,
1253        /// The value expression being prefixed.
1254        /// Hint: you can unwrap the string value using `value.into_string()`.
1255        value: Box<Expr>,
1256    },
1257    /// A constant of form `<data_type> 'value'`.
1258    /// This can represent ANSI SQL `DATE`, `TIME`, and `TIMESTAMP` literals (such as `DATE '2020-01-01'`),
1259    /// as well as constants of other types (a non-standard PostgreSQL extension).
1260    TypedString(TypedString),
1261    /// Scalar function call e.g. `LEFT(foo, 5)`
1262    Function(Function),
1263    /// `CASE [<operand>] WHEN <condition> THEN <result> ... [ELSE <result>] END`
1264    ///
1265    /// Note we only recognize a complete single expression as `<condition>`,
1266    /// not `< 0` nor `1, 2, 3` as allowed in a `<simple when clause>` per
1267    /// <https://jakewheat.github.io/sql-overview/sql-2011-foundation-grammar.html#simple-when-clause>
1268    Case {
1269        /// The attached `CASE` token (keeps original spacing/comments).
1270        case_token: AttachedToken,
1271        /// The attached `END` token (keeps original spacing/comments).
1272        end_token: AttachedToken,
1273        /// Optional operand expression after `CASE` (for simple CASE).
1274        operand: Option<Box<Expr>>,
1275        /// The `WHEN ... THEN` conditions and results.
1276        conditions: Vec<CaseWhen>,
1277        /// Optional `ELSE` result expression.
1278        else_result: Option<Box<Expr>>,
1279    },
1280    /// An exists expression `[ NOT ] EXISTS(SELECT ...)`, used in expressions like
1281    /// `WHERE [ NOT ] EXISTS (SELECT ...)`.
1282    Exists {
1283        /// The subquery checked by `EXISTS`.
1284        subquery: Box<Query>,
1285        /// Whether the `EXISTS` is negated (`NOT EXISTS`).
1286        negated: bool,
1287    },
1288    /// A parenthesized subquery `(SELECT ...)`, used in expression like
1289    /// `SELECT (subquery) AS x` or `WHERE (subquery) = x`
1290    Subquery(Box<Query>),
1291    /// The `GROUPING SETS` expr.
1292    GroupingSets(Vec<Vec<Expr>>),
1293    /// The `CUBE` expr.
1294    Cube(Vec<Vec<Expr>>),
1295    /// The `ROLLUP` expr.
1296    Rollup(Vec<Vec<Expr>>),
1297    /// ROW / TUPLE a single value, such as `SELECT (1, 2)`
1298    Tuple(Vec<Expr>),
1299    /// `Struct` literal expression
1300    /// Syntax:
1301    /// ```sql
1302    /// STRUCT<[field_name] field_type, ...>( expr1 [, ... ])
1303    ///
1304    /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-types#struct_type)
1305    /// [Databricks](https://docs.databricks.com/en/sql/language-manual/functions/struct.html)
1306    /// ```
1307    Struct {
1308        /// Struct values.
1309        values: Vec<Expr>,
1310        /// Struct field definitions.
1311        fields: Vec<StructField>,
1312    },
1313    /// A named expression: `1 AS A`. Used in `BigQuery` typeless structs [1]
1314    /// and in aliased function arguments, e.g. `XMLFOREST(a AS x)` in
1315    /// PostgreSQL [2].
1316    ///
1317    /// [1]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-types#struct_type
1318    /// [2]: https://www.postgresql.org/docs/current/functions-xml.html#FUNCTIONS-PRODUCING-XML-XMLFOREST
1319    Named {
1320        /// The expression being named.
1321        expr: Box<Expr>,
1322        /// The assigned identifier name for the expression.
1323        name: Ident,
1324    },
1325    /// `DuckDB` specific `Struct` literal expression [1]
1326    ///
1327    /// Syntax:
1328    /// ```sql
1329    /// syntax: {'field_name': expr1[, ... ]}
1330    /// ```
1331    /// [1]: https://duckdb.org/docs/sql/data_types/struct#creating-structs
1332    Dictionary(Vec<DictionaryField>),
1333    /// `DuckDB` specific `Map` literal expression [1]
1334    ///
1335    /// Syntax:
1336    /// ```sql
1337    /// syntax: Map {key1: value1[, ... ]}
1338    /// ```
1339    /// [1]: https://duckdb.org/docs/sql/data_types/map#creating-maps
1340    Map(Map),
1341    /// An array expression e.g. `ARRAY[1, 2]`
1342    Array(Array),
1343    /// An interval expression e.g. `INTERVAL '1' YEAR`
1344    Interval(Interval),
1345    /// `MySQL` specific text search function [(1)].
1346    ///
1347    /// Syntax:
1348    /// ```sql
1349    /// MATCH (<col>, <col>, ...) AGAINST (<expr> [<search modifier>])
1350    ///
1351    /// <col> = CompoundIdentifier
1352    /// <expr> = String literal
1353    /// ```
1354    /// [(1)]: https://dev.mysql.com/doc/refman/8.0/en/fulltext-search.html#function_match
1355    MatchAgainst {
1356        /// `(<col>, <col>, ...)`.
1357        columns: Vec<ObjectName>,
1358        /// `<expr>`.
1359        match_value: ValueWithSpan,
1360        /// `<search modifier>`
1361        opt_search_modifier: Option<SearchModifier>,
1362    },
1363    /// An unqualified `*` wildcard token (e.g. `*`).
1364    Wildcard(AttachedToken),
1365    /// Qualified wildcard, e.g. `alias.*` or `schema.table.*`.
1366    /// (Same caveats apply to `QualifiedWildcard` as to `Wildcard`.)
1367    QualifiedWildcard(ObjectName, AttachedToken),
1368    /// Some dialects support an older syntax for outer joins where columns are
1369    /// marked with the `(+)` operator in the WHERE clause, for example:
1370    ///
1371    /// ```sql
1372    /// SELECT t1.c1, t2.c2 FROM t1, t2 WHERE t1.c1 = t2.c2 (+)
1373    /// ```
1374    ///
1375    /// which is equivalent to
1376    ///
1377    /// ```sql
1378    /// SELECT t1.c1, t2.c2 FROM t1 LEFT OUTER JOIN t2 ON t1.c1 = t2.c2
1379    /// ```
1380    ///
1381    /// See <https://docs.snowflake.com/en/sql-reference/constructs/where#joins-in-the-where-clause>.
1382    OuterJoin(Box<Expr>),
1383    /// A reference to the prior level in a CONNECT BY clause.
1384    Prior(Box<Expr>),
1385    /// A lambda function.
1386    ///
1387    /// Syntax:
1388    /// ```plaintext
1389    /// param -> expr | (param1, ...) -> expr
1390    /// ```
1391    ///
1392    /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/functions#higher-order-functions---operator-and-lambdaparams-expr-function)
1393    /// [Databricks](https://docs.databricks.com/en/sql/language-manual/sql-ref-lambda-functions.html)
1394    /// [DuckDB](https://duckdb.org/docs/stable/sql/functions/lambda)
1395    Lambda(LambdaFunction),
1396    /// Checks membership of a value in a JSON array
1397    MemberOf(MemberOf),
1398}
1399
1400impl Expr {
1401    /// Creates a new [`Expr::Value`]
1402    pub fn value(value: impl Into<ValueWithSpan>) -> Self {
1403        Expr::Value(value.into())
1404    }
1405}
1406
1407/// The contents inside the `[` and `]` in a subscript expression.
1408#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1409#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1410#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1411pub enum Subscript {
1412    /// Accesses the element of the array at the given index.
1413    Index {
1414        /// The index expression used to access the array element.
1415        index: Expr,
1416    },
1417
1418    /// Accesses a slice of an array on PostgreSQL, e.g.
1419    ///
1420    /// ```plaintext
1421    /// => select (array[1,2,3,4,5,6])[2:5];
1422    /// -----------
1423    /// {2,3,4,5}
1424    /// ```
1425    ///
1426    /// The lower and/or upper bound can be omitted to slice from the start or
1427    /// end of the array respectively.
1428    ///
1429    /// See <https://www.postgresql.org/docs/current/arrays.html#ARRAYS-ACCESSING>.
1430    ///
1431    /// Also supports an optional "stride" as the last element (this is not
1432    /// supported by postgres), e.g.
1433    ///
1434    /// ```plaintext
1435    /// => select (array[1,2,3,4,5,6])[1:6:2];
1436    /// -----------
1437    /// {1,3,5}
1438    /// ```
1439    Slice {
1440        /// Optional lower bound for the slice (inclusive).
1441        lower_bound: Option<Expr>,
1442        /// Optional upper bound for the slice (inclusive).
1443        upper_bound: Option<Expr>,
1444        /// Optional stride for the slice (step size).
1445        stride: Option<Expr>,
1446    },
1447}
1448
1449impl fmt::Display for Subscript {
1450    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1451        match self {
1452            Subscript::Index { index } => write!(f, "{index}"),
1453            Subscript::Slice {
1454                lower_bound,
1455                upper_bound,
1456                stride,
1457            } => {
1458                if let Some(lower) = lower_bound {
1459                    write!(f, "{lower}")?;
1460                }
1461                write!(f, ":")?;
1462                if let Some(upper) = upper_bound {
1463                    write!(f, "{upper}")?;
1464                }
1465                if let Some(stride) = stride {
1466                    write!(f, ":")?;
1467                    write!(f, "{stride}")?;
1468                }
1469                Ok(())
1470            }
1471        }
1472    }
1473}
1474
1475/// An element of a [`Expr::CompoundFieldAccess`].
1476/// It can be an expression or a subscript.
1477#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1478#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1479#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1480pub enum AccessExpr {
1481    /// Accesses a field using dot notation, e.g. `foo.bar.baz`.
1482    Dot(Expr),
1483    /// Accesses a field or array element using bracket notation, e.g. `foo['bar']`.
1484    Subscript(Subscript),
1485}
1486
1487impl fmt::Display for AccessExpr {
1488    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1489        match self {
1490            AccessExpr::Dot(Expr::Value(value)) if matches!(value.value, Value::Number(_, _)) => {
1491                write!(f, " . {value}")
1492            }
1493            AccessExpr::Dot(expr) => write!(f, ".{expr}"),
1494            AccessExpr::Subscript(subscript) => write!(f, "[{subscript}]"),
1495        }
1496    }
1497}
1498
1499/// A lambda function.
1500#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1501#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1502#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1503pub struct LambdaFunction {
1504    /// The parameters to the lambda function.
1505    pub params: OneOrManyWithParens<LambdaFunctionParameter>,
1506    /// The body of the lambda function.
1507    pub body: Box<Expr>,
1508    /// The syntax style used to write the lambda function.
1509    pub syntax: LambdaSyntax,
1510}
1511
1512impl fmt::Display for LambdaFunction {
1513    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1514        match self.syntax {
1515            LambdaSyntax::Arrow => write!(f, "{} -> {}", self.params, self.body),
1516            LambdaSyntax::LambdaKeyword => {
1517                // For lambda keyword syntax, display params without parentheses
1518                // e.g., `lambda x, y : expr` not `lambda (x, y) : expr`
1519                write!(f, "lambda ")?;
1520                match &self.params {
1521                    OneOrManyWithParens::One(p) => write!(f, "{p}")?,
1522                    OneOrManyWithParens::Many(ps) => write!(f, "{}", display_comma_separated(ps))?,
1523                };
1524                write!(f, " : {}", self.body)
1525            }
1526        }
1527    }
1528}
1529
1530/// A parameter to a lambda function, optionally with a data type.
1531#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1532#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1533#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1534pub struct LambdaFunctionParameter {
1535    /// The name of the parameter
1536    pub name: Ident,
1537    /// The optional data type of the parameter
1538    /// [Snowflake Syntax](https://docs.snowflake.com/en/sql-reference/functions/filter#arguments)
1539    pub data_type: Option<DataType>,
1540}
1541
1542impl fmt::Display for LambdaFunctionParameter {
1543    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1544        match &self.data_type {
1545            Some(dt) => write!(f, "{} {}", self.name, dt),
1546            None => write!(f, "{}", self.name),
1547        }
1548    }
1549}
1550
1551/// The syntax style for a lambda function.
1552#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Copy)]
1553#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1554#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1555pub enum LambdaSyntax {
1556    /// Arrow syntax: `param -> expr` or `(param1, param2) -> expr`
1557    ///
1558    /// <https://docs.databricks.com/aws/en/sql/language-manual/sql-ref-lambda-functions>
1559    ///
1560    /// Supported, but deprecated in DuckDB:
1561    /// <https://duckdb.org/docs/stable/sql/functions/lambda>
1562    Arrow,
1563    /// Lambda keyword syntax: `lambda param : expr` or `lambda param1, param2 : expr`
1564    ///
1565    /// Recommended in DuckDB:
1566    /// <https://duckdb.org/docs/stable/sql/functions/lambda>
1567    LambdaKeyword,
1568}
1569
1570/// Encapsulates the common pattern in SQL where either one unparenthesized item
1571/// such as an identifier or expression is permitted, or multiple of the same
1572/// item in a parenthesized list. For accessing items regardless of the form,
1573/// `OneOrManyWithParens` implements `Deref<Target = [T]>` and `IntoIterator`,
1574/// so you can call slice methods on it and iterate over items
1575/// # Examples
1576/// Accessing as a slice:
1577/// ```
1578/// # use sqlparser::ast::OneOrManyWithParens;
1579/// let one = OneOrManyWithParens::One("a");
1580///
1581/// assert_eq!(one[0], "a");
1582/// assert_eq!(one.len(), 1);
1583/// ```
1584/// Iterating:
1585/// ```
1586/// # use sqlparser::ast::OneOrManyWithParens;
1587/// let one = OneOrManyWithParens::One("a");
1588/// let many = OneOrManyWithParens::Many(vec!["a", "b"]);
1589///
1590/// assert_eq!(one.into_iter().chain(many).collect::<Vec<_>>(), vec!["a", "a", "b"] );
1591/// ```
1592#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1593#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1594#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1595pub enum OneOrManyWithParens<T> {
1596    /// A single `T`, unparenthesized.
1597    One(T),
1598    /// One or more `T`s, parenthesized.
1599    Many(Vec<T>),
1600}
1601
1602impl<T> Deref for OneOrManyWithParens<T> {
1603    type Target = [T];
1604
1605    fn deref(&self) -> &[T] {
1606        match self {
1607            OneOrManyWithParens::One(one) => core::slice::from_ref(one),
1608            OneOrManyWithParens::Many(many) => many,
1609        }
1610    }
1611}
1612
1613impl<T> AsRef<[T]> for OneOrManyWithParens<T> {
1614    fn as_ref(&self) -> &[T] {
1615        self
1616    }
1617}
1618
1619impl<'a, T> IntoIterator for &'a OneOrManyWithParens<T> {
1620    type Item = &'a T;
1621    type IntoIter = core::slice::Iter<'a, T>;
1622
1623    fn into_iter(self) -> Self::IntoIter {
1624        self.iter()
1625    }
1626}
1627
1628/// Owned iterator implementation of `OneOrManyWithParens`
1629#[derive(Debug, Clone)]
1630pub struct OneOrManyWithParensIntoIter<T> {
1631    inner: OneOrManyWithParensIntoIterInner<T>,
1632}
1633
1634#[derive(Debug, Clone)]
1635enum OneOrManyWithParensIntoIterInner<T> {
1636    One(core::iter::Once<T>),
1637    Many(<Vec<T> as IntoIterator>::IntoIter),
1638}
1639
1640impl<T> core::iter::FusedIterator for OneOrManyWithParensIntoIter<T>
1641where
1642    core::iter::Once<T>: core::iter::FusedIterator,
1643    <Vec<T> as IntoIterator>::IntoIter: core::iter::FusedIterator,
1644{
1645}
1646
1647impl<T> core::iter::ExactSizeIterator for OneOrManyWithParensIntoIter<T>
1648where
1649    core::iter::Once<T>: core::iter::ExactSizeIterator,
1650    <Vec<T> as IntoIterator>::IntoIter: core::iter::ExactSizeIterator,
1651{
1652}
1653
1654impl<T> core::iter::Iterator for OneOrManyWithParensIntoIter<T> {
1655    type Item = T;
1656
1657    fn next(&mut self) -> Option<Self::Item> {
1658        match &mut self.inner {
1659            OneOrManyWithParensIntoIterInner::One(one) => one.next(),
1660            OneOrManyWithParensIntoIterInner::Many(many) => many.next(),
1661        }
1662    }
1663
1664    fn size_hint(&self) -> (usize, Option<usize>) {
1665        match &self.inner {
1666            OneOrManyWithParensIntoIterInner::One(one) => one.size_hint(),
1667            OneOrManyWithParensIntoIterInner::Many(many) => many.size_hint(),
1668        }
1669    }
1670
1671    fn count(self) -> usize
1672    where
1673        Self: Sized,
1674    {
1675        match self.inner {
1676            OneOrManyWithParensIntoIterInner::One(one) => one.count(),
1677            OneOrManyWithParensIntoIterInner::Many(many) => many.count(),
1678        }
1679    }
1680
1681    fn fold<B, F>(mut self, init: B, f: F) -> B
1682    where
1683        Self: Sized,
1684        F: FnMut(B, Self::Item) -> B,
1685    {
1686        match &mut self.inner {
1687            OneOrManyWithParensIntoIterInner::One(one) => one.fold(init, f),
1688            OneOrManyWithParensIntoIterInner::Many(many) => many.fold(init, f),
1689        }
1690    }
1691}
1692
1693impl<T> core::iter::DoubleEndedIterator for OneOrManyWithParensIntoIter<T> {
1694    fn next_back(&mut self) -> Option<Self::Item> {
1695        match &mut self.inner {
1696            OneOrManyWithParensIntoIterInner::One(one) => one.next_back(),
1697            OneOrManyWithParensIntoIterInner::Many(many) => many.next_back(),
1698        }
1699    }
1700}
1701
1702impl<T> IntoIterator for OneOrManyWithParens<T> {
1703    type Item = T;
1704
1705    type IntoIter = OneOrManyWithParensIntoIter<T>;
1706
1707    fn into_iter(self) -> Self::IntoIter {
1708        let inner = match self {
1709            OneOrManyWithParens::One(one) => {
1710                OneOrManyWithParensIntoIterInner::One(core::iter::once(one))
1711            }
1712            OneOrManyWithParens::Many(many) => {
1713                OneOrManyWithParensIntoIterInner::Many(many.into_iter())
1714            }
1715        };
1716
1717        OneOrManyWithParensIntoIter { inner }
1718    }
1719}
1720
1721impl<T> fmt::Display for OneOrManyWithParens<T>
1722where
1723    T: fmt::Display,
1724{
1725    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1726        match self {
1727            OneOrManyWithParens::One(value) => write!(f, "{value}"),
1728            OneOrManyWithParens::Many(values) => {
1729                write!(f, "({})", display_comma_separated(values))
1730            }
1731        }
1732    }
1733}
1734
1735impl fmt::Display for CastFormat {
1736    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1737        match self {
1738            CastFormat::Value(v) => write!(f, "{v}"),
1739            CastFormat::ValueAtTimeZone(v, tz) => write!(f, "{v} AT TIME ZONE {tz}"),
1740        }
1741    }
1742}
1743
1744impl fmt::Display for Expr {
1745    #[cfg_attr(feature = "recursive-protection", recursive::recursive)]
1746    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1747        match self {
1748            Expr::Identifier(s) => write!(f, "{s}"),
1749            Expr::Wildcard(_) => f.write_str("*"),
1750            Expr::QualifiedWildcard(prefix, _) => write!(f, "{prefix}.*"),
1751            Expr::CompoundIdentifier(s) => write!(f, "{}", display_separated(s, ".")),
1752            Expr::CompoundFieldAccess { root, access_chain } => {
1753                write!(f, "{root}")?;
1754                for field in access_chain {
1755                    write!(f, "{field}")?;
1756                }
1757                Ok(())
1758            }
1759            Expr::IsTrue(ast) => write!(f, "{ast} IS TRUE"),
1760            Expr::IsNotTrue(ast) => write!(f, "{ast} IS NOT TRUE"),
1761            Expr::IsFalse(ast) => write!(f, "{ast} IS FALSE"),
1762            Expr::IsNotFalse(ast) => write!(f, "{ast} IS NOT FALSE"),
1763            Expr::IsNull(ast) => write!(f, "{ast} IS NULL"),
1764            Expr::IsNotNull(ast) => write!(f, "{ast} IS NOT NULL"),
1765            Expr::IsUnknown(ast) => write!(f, "{ast} IS UNKNOWN"),
1766            Expr::IsNotUnknown(ast) => write!(f, "{ast} IS NOT UNKNOWN"),
1767            Expr::IsJson {
1768                expr,
1769                kind,
1770                unique_keys,
1771                negated,
1772            } => {
1773                write!(f, "{expr} IS ")?;
1774                if *negated {
1775                    write!(f, "NOT ")?;
1776                }
1777                write!(f, "JSON")?;
1778                if let Some(kind) = kind {
1779                    write!(f, " {kind}")?;
1780                }
1781                if let Some(unique_keys) = unique_keys {
1782                    write!(f, " {unique_keys}")?;
1783                }
1784                Ok(())
1785            }
1786            Expr::InList {
1787                expr,
1788                list,
1789                negated,
1790            } => write!(
1791                f,
1792                "{} {}IN ({})",
1793                expr,
1794                if *negated { "NOT " } else { "" },
1795                display_comma_separated(list)
1796            ),
1797            Expr::InSubquery {
1798                expr,
1799                subquery,
1800                negated,
1801            } => write!(
1802                f,
1803                "{} {}IN ({})",
1804                expr,
1805                if *negated { "NOT " } else { "" },
1806                subquery
1807            ),
1808            Expr::InUnnest {
1809                expr,
1810                array_expr,
1811                negated,
1812            } => write!(
1813                f,
1814                "{} {}IN UNNEST({})",
1815                expr,
1816                if *negated { "NOT " } else { "" },
1817                array_expr
1818            ),
1819            Expr::Between {
1820                expr,
1821                negated,
1822                low,
1823                high,
1824            } => write!(
1825                f,
1826                "{} {}BETWEEN {} AND {}",
1827                expr,
1828                if *negated { "NOT " } else { "" },
1829                low,
1830                high
1831            ),
1832            Expr::BinaryOp { left, op, right } => write!(f, "{left} {op} {right}"),
1833            Expr::Like {
1834                negated,
1835                expr,
1836                pattern,
1837                escape_char,
1838                any,
1839            } => match escape_char {
1840                Some(ch) => write!(
1841                    f,
1842                    "{} {}LIKE {}{} ESCAPE {}",
1843                    expr,
1844                    if *negated { "NOT " } else { "" },
1845                    if *any { "ANY " } else { "" },
1846                    pattern,
1847                    ch
1848                ),
1849                _ => write!(
1850                    f,
1851                    "{} {}LIKE {}{}",
1852                    expr,
1853                    if *negated { "NOT " } else { "" },
1854                    if *any { "ANY " } else { "" },
1855                    pattern
1856                ),
1857            },
1858            Expr::ILike {
1859                negated,
1860                expr,
1861                pattern,
1862                escape_char,
1863                any,
1864            } => match escape_char {
1865                Some(ch) => write!(
1866                    f,
1867                    "{} {}ILIKE {}{} ESCAPE {}",
1868                    expr,
1869                    if *negated { "NOT " } else { "" },
1870                    if *any { "ANY" } else { "" },
1871                    pattern,
1872                    ch
1873                ),
1874                _ => write!(
1875                    f,
1876                    "{} {}ILIKE {}{}",
1877                    expr,
1878                    if *negated { "NOT " } else { "" },
1879                    if *any { "ANY " } else { "" },
1880                    pattern
1881                ),
1882            },
1883            Expr::RLike {
1884                negated,
1885                expr,
1886                pattern,
1887                regexp,
1888            } => write!(
1889                f,
1890                "{} {}{} {}",
1891                expr,
1892                if *negated { "NOT " } else { "" },
1893                if *regexp { "REGEXP" } else { "RLIKE" },
1894                pattern
1895            ),
1896            Expr::IsNormalized {
1897                expr,
1898                form,
1899                negated,
1900            } => {
1901                let not_ = if *negated { "NOT " } else { "" };
1902                if let Some(form) = form {
1903                    write!(f, "{} IS {}{} NORMALIZED", expr, not_, form)
1904                } else {
1905                    write!(f, "{expr} IS {not_}NORMALIZED")
1906                }
1907            }
1908            Expr::SimilarTo {
1909                negated,
1910                expr,
1911                pattern,
1912                escape_char,
1913            } => match escape_char {
1914                Some(ch) => write!(
1915                    f,
1916                    "{} {}SIMILAR TO {} ESCAPE {}",
1917                    expr,
1918                    if *negated { "NOT " } else { "" },
1919                    pattern,
1920                    ch
1921                ),
1922                _ => write!(
1923                    f,
1924                    "{} {}SIMILAR TO {}",
1925                    expr,
1926                    if *negated { "NOT " } else { "" },
1927                    pattern
1928                ),
1929            },
1930            Expr::AnyOp {
1931                left,
1932                compare_op,
1933                right,
1934                is_some,
1935            } => {
1936                let add_parens = !matches!(right.as_ref(), Expr::Subquery(_));
1937                write!(
1938                    f,
1939                    "{left} {compare_op} {}{}{right}{}",
1940                    if *is_some { "SOME" } else { "ANY" },
1941                    if add_parens { "(" } else { "" },
1942                    if add_parens { ")" } else { "" },
1943                )
1944            }
1945            Expr::AllOp {
1946                left,
1947                compare_op,
1948                right,
1949            } => {
1950                let add_parens = !matches!(right.as_ref(), Expr::Subquery(_));
1951                write!(
1952                    f,
1953                    "{left} {compare_op} ALL{}{right}{}",
1954                    if add_parens { "(" } else { "" },
1955                    if add_parens { ")" } else { "" },
1956                )
1957            }
1958            Expr::UnaryOp { op, expr } => {
1959                if op == &UnaryOperator::PGPostfixFactorial {
1960                    write!(f, "{expr}{op}")
1961                } else if matches!(
1962                    op,
1963                    UnaryOperator::Not
1964                        | UnaryOperator::Hash
1965                        | UnaryOperator::AtDashAt
1966                        | UnaryOperator::DoubleAt
1967                        | UnaryOperator::QuestionDash
1968                        | UnaryOperator::QuestionPipe
1969                ) {
1970                    write!(f, "{op} {expr}")
1971                } else {
1972                    write!(f, "{op}{expr}")
1973                }
1974            }
1975            Expr::Convert {
1976                is_try,
1977                expr,
1978                target_before_value,
1979                data_type,
1980                charset,
1981                styles,
1982            } => {
1983                write!(f, "{}CONVERT(", if *is_try { "TRY_" } else { "" })?;
1984                if let Some(data_type) = data_type {
1985                    if let Some(charset) = charset {
1986                        write!(f, "{expr}, {data_type} CHARACTER SET {charset}")
1987                    } else if *target_before_value {
1988                        write!(f, "{data_type}, {expr}")
1989                    } else {
1990                        write!(f, "{expr}, {data_type}")
1991                    }
1992                } else if let Some(charset) = charset {
1993                    write!(f, "{expr} USING {charset}")
1994                } else {
1995                    write!(f, "{expr}") // This should never happen
1996                }?;
1997                if !styles.is_empty() {
1998                    write!(f, ", {}", display_comma_separated(styles))?;
1999                }
2000                write!(f, ")")
2001            }
2002            Expr::Cast {
2003                kind,
2004                expr,
2005                data_type,
2006                format,
2007            } => match kind {
2008                CastKind::Cast => {
2009                    write!(f, "CAST({expr} AS {data_type}")?;
2010                    if let Some(format) = format {
2011                        write!(f, " FORMAT {format}")?;
2012                    }
2013                    write!(f, ")")
2014                }
2015                CastKind::TryCast => {
2016                    if let Some(format) = format {
2017                        write!(f, "TRY_CAST({expr} AS {data_type} FORMAT {format})")
2018                    } else {
2019                        write!(f, "TRY_CAST({expr} AS {data_type})")
2020                    }
2021                }
2022                CastKind::SafeCast => {
2023                    if let Some(format) = format {
2024                        write!(f, "SAFE_CAST({expr} AS {data_type} FORMAT {format})")
2025                    } else {
2026                        write!(f, "SAFE_CAST({expr} AS {data_type})")
2027                    }
2028                }
2029                CastKind::DoubleColon => {
2030                    write!(f, "{expr}::{data_type}")
2031                }
2032            },
2033            Expr::Extract {
2034                field,
2035                syntax,
2036                expr,
2037            } => match syntax {
2038                ExtractSyntax::From => write!(f, "EXTRACT({field} FROM {expr})"),
2039                ExtractSyntax::Comma => write!(f, "EXTRACT({field}, {expr})"),
2040            },
2041            Expr::Ceil { expr, field } => match field {
2042                CeilFloorKind::DateTimeField(DateTimeField::NoDateTime) => {
2043                    write!(f, "CEIL({expr})")
2044                }
2045                CeilFloorKind::DateTimeField(dt_field) => write!(f, "CEIL({expr} TO {dt_field})"),
2046                CeilFloorKind::Scale(s) => write!(f, "CEIL({expr}, {s})"),
2047            },
2048            Expr::Floor { expr, field } => match field {
2049                CeilFloorKind::DateTimeField(DateTimeField::NoDateTime) => {
2050                    write!(f, "FLOOR({expr})")
2051                }
2052                CeilFloorKind::DateTimeField(dt_field) => write!(f, "FLOOR({expr} TO {dt_field})"),
2053                CeilFloorKind::Scale(s) => write!(f, "FLOOR({expr}, {s})"),
2054            },
2055            Expr::Position { expr, r#in } => write!(f, "POSITION({expr} IN {in})"),
2056            Expr::Collate { expr, collation } => write!(f, "{expr} COLLATE {collation}"),
2057            Expr::Nested(ast) => write!(f, "({ast})"),
2058            Expr::Value(v) => write!(f, "{v}"),
2059            Expr::Prefixed { prefix, value } => write!(f, "{prefix} {value}"),
2060            Expr::TypedString(ts) => ts.fmt(f),
2061            Expr::Function(fun) => fun.fmt(f),
2062            Expr::Case {
2063                case_token: _,
2064                end_token: _,
2065                operand,
2066                conditions,
2067                else_result,
2068            } => {
2069                f.write_str("CASE")?;
2070                if let Some(operand) = operand {
2071                    f.write_str(" ")?;
2072                    operand.fmt(f)?;
2073                }
2074                for when in conditions {
2075                    SpaceOrNewline.fmt(f)?;
2076                    Indent(when).fmt(f)?;
2077                }
2078                if let Some(else_result) = else_result {
2079                    SpaceOrNewline.fmt(f)?;
2080                    Indent("ELSE").fmt(f)?;
2081                    SpaceOrNewline.fmt(f)?;
2082                    Indent(Indent(else_result)).fmt(f)?;
2083                }
2084                SpaceOrNewline.fmt(f)?;
2085                f.write_str("END")
2086            }
2087            Expr::Exists { subquery, negated } => write!(
2088                f,
2089                "{}EXISTS ({})",
2090                if *negated { "NOT " } else { "" },
2091                subquery
2092            ),
2093            Expr::Subquery(s) => write!(f, "({s})"),
2094            Expr::GroupingSets(sets) => {
2095                write!(f, "GROUPING SETS (")?;
2096                let mut sep = "";
2097                for set in sets {
2098                    write!(f, "{sep}")?;
2099                    sep = ", ";
2100                    write!(f, "({})", display_comma_separated(set))?;
2101                }
2102                write!(f, ")")
2103            }
2104            Expr::Cube(sets) => {
2105                write!(f, "CUBE (")?;
2106                let mut sep = "";
2107                for set in sets {
2108                    write!(f, "{sep}")?;
2109                    sep = ", ";
2110                    if set.len() == 1 {
2111                        write!(f, "{}", set[0])?;
2112                    } else {
2113                        write!(f, "({})", display_comma_separated(set))?;
2114                    }
2115                }
2116                write!(f, ")")
2117            }
2118            Expr::Rollup(sets) => {
2119                write!(f, "ROLLUP (")?;
2120                let mut sep = "";
2121                for set in sets {
2122                    write!(f, "{sep}")?;
2123                    sep = ", ";
2124                    if set.len() == 1 {
2125                        write!(f, "{}", set[0])?;
2126                    } else {
2127                        write!(f, "({})", display_comma_separated(set))?;
2128                    }
2129                }
2130                write!(f, ")")
2131            }
2132            Expr::Substring {
2133                expr,
2134                substring_from,
2135                substring_for,
2136                special,
2137                shorthand,
2138            } => {
2139                f.write_str("SUBSTR")?;
2140                if !*shorthand {
2141                    f.write_str("ING")?;
2142                }
2143                write!(f, "({expr}")?;
2144                if let Some(from_part) = substring_from {
2145                    if *special {
2146                        write!(f, ", {from_part}")?;
2147                    } else {
2148                        write!(f, " FROM {from_part}")?;
2149                    }
2150                }
2151                if let Some(for_part) = substring_for {
2152                    if *special {
2153                        write!(f, ", {for_part}")?;
2154                    } else {
2155                        write!(f, " FOR {for_part}")?;
2156                    }
2157                }
2158
2159                write!(f, ")")
2160            }
2161            Expr::Overlay {
2162                expr,
2163                overlay_what,
2164                overlay_from,
2165                overlay_for,
2166            } => {
2167                write!(
2168                    f,
2169                    "OVERLAY({expr} PLACING {overlay_what} FROM {overlay_from}"
2170                )?;
2171                if let Some(for_part) = overlay_for {
2172                    write!(f, " FOR {for_part}")?;
2173                }
2174
2175                write!(f, ")")
2176            }
2177            Expr::IsDistinctFrom(a, b) => write!(f, "{a} IS DISTINCT FROM {b}"),
2178            Expr::IsNotDistinctFrom(a, b) => write!(f, "{a} IS NOT DISTINCT FROM {b}"),
2179            Expr::Trim {
2180                expr,
2181                trim_where,
2182                trim_what,
2183                trim_characters,
2184            } => {
2185                write!(f, "TRIM(")?;
2186                if let Some(ident) = trim_where {
2187                    write!(f, "{ident} ")?;
2188                }
2189                if let Some(trim_char) = trim_what {
2190                    write!(f, "{trim_char} FROM {expr}")?;
2191                } else {
2192                    write!(f, "{expr}")?;
2193                }
2194                if let Some(characters) = trim_characters {
2195                    write!(f, ", {}", display_comma_separated(characters))?;
2196                }
2197
2198                write!(f, ")")
2199            }
2200            Expr::Tuple(exprs) => {
2201                write!(f, "({})", display_comma_separated(exprs))
2202            }
2203            Expr::Struct { values, fields } => {
2204                if !fields.is_empty() {
2205                    write!(
2206                        f,
2207                        "STRUCT<{}>({})",
2208                        display_comma_separated(fields),
2209                        display_comma_separated(values)
2210                    )
2211                } else {
2212                    write!(f, "STRUCT({})", display_comma_separated(values))
2213                }
2214            }
2215            Expr::Named { expr, name } => {
2216                write!(f, "{expr} AS {name}")
2217            }
2218            Expr::Dictionary(fields) => {
2219                write!(f, "{{{}}}", display_comma_separated(fields))
2220            }
2221            Expr::Map(map) => {
2222                write!(f, "{map}")
2223            }
2224            Expr::Array(set) => {
2225                write!(f, "{set}")
2226            }
2227            Expr::JsonAccess { value, path } => {
2228                write!(f, "{value}{path}")
2229            }
2230            Expr::AtTimeZone {
2231                timestamp,
2232                time_zone,
2233            } => {
2234                write!(f, "{timestamp} AT TIME ZONE {time_zone}")
2235            }
2236            Expr::Interval(interval) => {
2237                write!(f, "{interval}")
2238            }
2239            Expr::MatchAgainst {
2240                columns,
2241                match_value: match_expr,
2242                opt_search_modifier,
2243            } => {
2244                write!(f, "MATCH ({}) AGAINST ", display_comma_separated(columns),)?;
2245
2246                if let Some(search_modifier) = opt_search_modifier {
2247                    write!(f, "({match_expr} {search_modifier})")?;
2248                } else {
2249                    write!(f, "({match_expr})")?;
2250                }
2251
2252                Ok(())
2253            }
2254            Expr::OuterJoin(expr) => {
2255                write!(f, "{expr} (+)")
2256            }
2257            Expr::Prior(expr) => write!(f, "PRIOR {expr}"),
2258            Expr::Lambda(lambda) => write!(f, "{lambda}"),
2259            Expr::MemberOf(member_of) => write!(f, "{member_of}"),
2260        }
2261    }
2262}
2263
2264/// The type of a window used in `OVER` clauses.
2265///
2266/// A window can be either an inline specification (`WindowSpec`) or a
2267/// reference to a previously defined named window.
2268///
2269/// - `WindowSpec(WindowSpec)`: An inline window specification, e.g.
2270///   `OVER (PARTITION BY ... ORDER BY ...)`.
2271/// - `NamedWindow(Ident)`: A reference to a named window declared elsewhere.
2272#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2273#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2274#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2275pub enum WindowType {
2276    /// An inline window specification.
2277    WindowSpec(WindowSpec),
2278    /// A reference to a previously defined named window.
2279    NamedWindow(Ident),
2280}
2281
2282impl Display for WindowType {
2283    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2284        match self {
2285            WindowType::WindowSpec(spec) => {
2286                f.write_str("(")?;
2287                NewLine.fmt(f)?;
2288                Indent(spec).fmt(f)?;
2289                NewLine.fmt(f)?;
2290                f.write_str(")")
2291            }
2292            WindowType::NamedWindow(name) => name.fmt(f),
2293        }
2294    }
2295}
2296
2297/// A window specification (i.e. `OVER ([window_name] PARTITION BY .. ORDER BY .. etc.)`)
2298#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2299#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2300#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2301pub struct WindowSpec {
2302    /// Optional window name.
2303    ///
2304    /// You can find it at least in [MySQL][1], [BigQuery][2], [PostgreSQL][3]
2305    ///
2306    /// [1]: https://dev.mysql.com/doc/refman/8.0/en/window-functions-named-windows.html
2307    /// [2]: https://cloud.google.com/bigquery/docs/reference/standard-sql/window-function-calls
2308    /// [3]: https://www.postgresql.org/docs/current/sql-expressions.html#SYNTAX-WINDOW-FUNCTIONS
2309    pub window_name: Option<Ident>,
2310    /// `OVER (PARTITION BY ...)`
2311    pub partition_by: Vec<Expr>,
2312    /// `OVER (ORDER BY ...)`
2313    pub order_by: Vec<OrderByExpr>,
2314    /// `OVER (window frame)`
2315    pub window_frame: Option<WindowFrame>,
2316}
2317
2318impl fmt::Display for WindowSpec {
2319    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2320        let mut is_first = true;
2321        if let Some(window_name) = &self.window_name {
2322            if !is_first {
2323                SpaceOrNewline.fmt(f)?;
2324            }
2325            is_first = false;
2326            write!(f, "{window_name}")?;
2327        }
2328        if !self.partition_by.is_empty() {
2329            if !is_first {
2330                SpaceOrNewline.fmt(f)?;
2331            }
2332            is_first = false;
2333            write!(
2334                f,
2335                "PARTITION BY {}",
2336                display_comma_separated(&self.partition_by)
2337            )?;
2338        }
2339        if !self.order_by.is_empty() {
2340            if !is_first {
2341                SpaceOrNewline.fmt(f)?;
2342            }
2343            is_first = false;
2344            write!(f, "ORDER BY {}", display_comma_separated(&self.order_by))?;
2345        }
2346        if let Some(window_frame) = &self.window_frame {
2347            if !is_first {
2348                SpaceOrNewline.fmt(f)?;
2349            }
2350            if let Some(end_bound) = &window_frame.end_bound {
2351                write!(
2352                    f,
2353                    "{} BETWEEN {} AND {}",
2354                    window_frame.units, window_frame.start_bound, end_bound
2355                )?;
2356            } else {
2357                write!(f, "{} {}", window_frame.units, window_frame.start_bound)?;
2358            }
2359        }
2360        Ok(())
2361    }
2362}
2363
2364/// Specifies the data processed by a window function, e.g.
2365/// `RANGE UNBOUNDED PRECEDING` or `ROWS BETWEEN 5 PRECEDING AND CURRENT ROW`.
2366///
2367/// Note: The parser does not validate the specified bounds; the caller should
2368/// reject invalid bounds like `ROWS UNBOUNDED FOLLOWING` before execution.
2369#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2370#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2371#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2372pub struct WindowFrame {
2373    /// Units for the frame (e.g. `ROWS`, `RANGE`, `GROUPS`).
2374    pub units: WindowFrameUnits,
2375    /// The start bound of the window frame.
2376    pub start_bound: WindowFrameBound,
2377    /// The right bound of the `BETWEEN .. AND` clause. The end bound of `None`
2378    /// indicates the shorthand form (e.g. `ROWS 1 PRECEDING`), which must
2379    /// behave the same as `end_bound = WindowFrameBound::CurrentRow`.
2380    pub end_bound: Option<WindowFrameBound>,
2381    // TBD: EXCLUDE
2382}
2383
2384impl Default for WindowFrame {
2385    /// Returns default value for window frame
2386    ///
2387    /// See [this page](https://www.sqlite.org/windowfunctions.html#frame_specifications) for more details.
2388    fn default() -> Self {
2389        Self {
2390            units: WindowFrameUnits::Range,
2391            start_bound: WindowFrameBound::Preceding(None),
2392            end_bound: None,
2393        }
2394    }
2395}
2396
2397#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2398#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2399#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2400/// Units used to describe the window frame scope.
2401pub enum WindowFrameUnits {
2402    /// `ROWS` unit.
2403    Rows,
2404    /// `RANGE` unit.
2405    Range,
2406    /// `GROUPS` unit.
2407    Groups,
2408}
2409
2410impl fmt::Display for WindowFrameUnits {
2411    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2412        f.write_str(match self {
2413            WindowFrameUnits::Rows => "ROWS",
2414            WindowFrameUnits::Range => "RANGE",
2415            WindowFrameUnits::Groups => "GROUPS",
2416        })
2417    }
2418}
2419
2420/// Specifies Ignore / Respect NULL within window functions.
2421/// For example
2422/// `FIRST_VALUE(column2) IGNORE NULLS OVER (PARTITION BY column1)`
2423#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2424#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2425#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2426/// How NULL values are treated in certain window functions.
2427pub enum NullTreatment {
2428    /// Ignore NULL values (e.g. `IGNORE NULLS`).
2429    IgnoreNulls,
2430    /// Respect NULL values (e.g. `RESPECT NULLS`).
2431    RespectNulls,
2432}
2433
2434impl fmt::Display for NullTreatment {
2435    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2436        f.write_str(match self {
2437            NullTreatment::IgnoreNulls => "IGNORE NULLS",
2438            NullTreatment::RespectNulls => "RESPECT NULLS",
2439        })
2440    }
2441}
2442
2443/// Specifies [WindowFrame]'s `start_bound` and `end_bound`
2444#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2445#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2446#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2447pub enum WindowFrameBound {
2448    /// `CURRENT ROW`
2449    CurrentRow,
2450    /// `<N> PRECEDING` or `UNBOUNDED PRECEDING`
2451    Preceding(Option<Box<Expr>>),
2452    /// `<N> FOLLOWING` or `UNBOUNDED FOLLOWING`.
2453    Following(Option<Box<Expr>>),
2454}
2455
2456impl fmt::Display for WindowFrameBound {
2457    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2458        match self {
2459            WindowFrameBound::CurrentRow => f.write_str("CURRENT ROW"),
2460            WindowFrameBound::Preceding(None) => f.write_str("UNBOUNDED PRECEDING"),
2461            WindowFrameBound::Following(None) => f.write_str("UNBOUNDED FOLLOWING"),
2462            WindowFrameBound::Preceding(Some(n)) => write!(f, "{n} PRECEDING"),
2463            WindowFrameBound::Following(Some(n)) => write!(f, "{n} FOLLOWING"),
2464        }
2465    }
2466}
2467
2468#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2469#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2470#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2471/// Indicates partition operation type for partition management statements.
2472pub enum AddDropSync {
2473    /// Add partitions.
2474    ADD,
2475    /// Drop partitions.
2476    DROP,
2477    /// Sync partitions.
2478    SYNC,
2479}
2480
2481impl fmt::Display for AddDropSync {
2482    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2483        match self {
2484            AddDropSync::SYNC => f.write_str("SYNC PARTITIONS"),
2485            AddDropSync::DROP => f.write_str("DROP PARTITIONS"),
2486            AddDropSync::ADD => f.write_str("ADD PARTITIONS"),
2487        }
2488    }
2489}
2490
2491#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2492#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2493#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2494/// Object kinds supported by `SHOW CREATE` statements.
2495pub enum ShowCreateObject {
2496    /// An event object for `SHOW CREATE EVENT`.
2497    Event,
2498    /// A function object for `SHOW CREATE FUNCTION`.
2499    Function,
2500    /// A procedure object for `SHOW CREATE PROCEDURE`.
2501    Procedure,
2502    /// A table object for `SHOW CREATE TABLE`.
2503    Table,
2504    /// A trigger object for `SHOW CREATE TRIGGER`.
2505    Trigger,
2506    /// A view object for `SHOW CREATE VIEW`.
2507    View,
2508}
2509
2510impl fmt::Display for ShowCreateObject {
2511    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2512        match self {
2513            ShowCreateObject::Event => f.write_str("EVENT"),
2514            ShowCreateObject::Function => f.write_str("FUNCTION"),
2515            ShowCreateObject::Procedure => f.write_str("PROCEDURE"),
2516            ShowCreateObject::Table => f.write_str("TABLE"),
2517            ShowCreateObject::Trigger => f.write_str("TRIGGER"),
2518            ShowCreateObject::View => f.write_str("VIEW"),
2519        }
2520    }
2521}
2522
2523#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2524#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2525#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2526/// Objects that can be targeted by a `COMMENT` statement.
2527pub enum CommentObject {
2528    /// A collation.
2529    Collation,
2530    /// A table column.
2531    Column,
2532    /// A database.
2533    Database,
2534    /// A domain.
2535    Domain,
2536    /// An extension.
2537    Extension,
2538    /// A function.
2539    Function,
2540    /// An index.
2541    Index,
2542    /// A materialized view.
2543    MaterializedView,
2544    /// A procedure.
2545    Procedure,
2546    /// A role.
2547    Role,
2548    /// A schema.
2549    Schema,
2550    /// A sequence.
2551    Sequence,
2552    /// A table.
2553    Table,
2554    /// A type.
2555    Type,
2556    /// A user.
2557    User,
2558    /// A view.
2559    View,
2560}
2561
2562impl fmt::Display for CommentObject {
2563    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2564        match self {
2565            CommentObject::Collation => f.write_str("COLLATION"),
2566            CommentObject::Column => f.write_str("COLUMN"),
2567            CommentObject::Database => f.write_str("DATABASE"),
2568            CommentObject::Domain => f.write_str("DOMAIN"),
2569            CommentObject::Extension => f.write_str("EXTENSION"),
2570            CommentObject::Function => f.write_str("FUNCTION"),
2571            CommentObject::Index => f.write_str("INDEX"),
2572            CommentObject::MaterializedView => f.write_str("MATERIALIZED VIEW"),
2573            CommentObject::Procedure => f.write_str("PROCEDURE"),
2574            CommentObject::Role => f.write_str("ROLE"),
2575            CommentObject::Schema => f.write_str("SCHEMA"),
2576            CommentObject::Sequence => f.write_str("SEQUENCE"),
2577            CommentObject::Table => f.write_str("TABLE"),
2578            CommentObject::Type => f.write_str("TYPE"),
2579            CommentObject::User => f.write_str("USER"),
2580            CommentObject::View => f.write_str("VIEW"),
2581        }
2582    }
2583}
2584
2585#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2586#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2587#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2588/// Password specification variants used in user-related statements.
2589pub enum Password {
2590    /// A concrete password expression.
2591    Password(Expr),
2592    /// Represents a `NULL` password.
2593    NullPassword,
2594}
2595
2596/// A `CASE` statement.
2597///
2598/// Examples:
2599/// ```sql
2600/// CASE
2601///     WHEN EXISTS(SELECT 1)
2602///         THEN SELECT 1 FROM T;
2603///     WHEN EXISTS(SELECT 2)
2604///         THEN SELECT 1 FROM U;
2605///     ELSE
2606///         SELECT 1 FROM V;
2607/// END CASE;
2608/// ```
2609///
2610/// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#case_search_expression)
2611/// [Snowflake](https://docs.snowflake.com/en/sql-reference/snowflake-scripting/case)
2612#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2613#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2614#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2615pub struct CaseStatement {
2616    /// The `CASE` token that starts the statement.
2617    pub case_token: AttachedToken,
2618    /// Optional expression to match against in `CASE ... WHEN`.
2619    pub match_expr: Option<Expr>,
2620    /// The `WHEN ... THEN` blocks of the `CASE` statement.
2621    pub when_blocks: Vec<ConditionalStatementBlock>,
2622    /// Optional `ELSE` block for the `CASE` statement.
2623    pub else_block: Option<ConditionalStatementBlock>,
2624    /// The last token of the statement (`END` or `CASE`).
2625    pub end_case_token: AttachedToken,
2626}
2627
2628impl fmt::Display for CaseStatement {
2629    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2630        let CaseStatement {
2631            case_token: _,
2632            match_expr,
2633            when_blocks,
2634            else_block,
2635            end_case_token: AttachedToken(end),
2636        } = self;
2637
2638        write!(f, "CASE")?;
2639
2640        if let Some(expr) = match_expr {
2641            write!(f, " {expr}")?;
2642        }
2643
2644        if !when_blocks.is_empty() {
2645            write!(f, " {}", display_separated(when_blocks, " "))?;
2646        }
2647
2648        if let Some(else_block) = else_block {
2649            write!(f, " {else_block}")?;
2650        }
2651
2652        write!(f, " END")?;
2653
2654        if let Token::Word(w) = &end.token {
2655            if w.keyword == Keyword::CASE {
2656                write!(f, " CASE")?;
2657            }
2658        }
2659
2660        Ok(())
2661    }
2662}
2663
2664/// An `IF` statement.
2665///
2666/// Example (BigQuery or Snowflake):
2667/// ```sql
2668/// IF TRUE THEN
2669///     SELECT 1;
2670///     SELECT 2;
2671/// ELSEIF TRUE THEN
2672///     SELECT 3;
2673/// ELSE
2674///     SELECT 4;
2675/// END IF
2676/// ```
2677/// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#if)
2678/// [Snowflake](https://docs.snowflake.com/en/sql-reference/snowflake-scripting/if)
2679///
2680/// Example (MSSQL):
2681/// ```sql
2682/// IF 1=1 SELECT 1 ELSE SELECT 2
2683/// ```
2684/// [MSSQL](https://learn.microsoft.com/en-us/sql/t-sql/language-elements/if-else-transact-sql?view=sql-server-ver16)
2685#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2686#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2687#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2688pub struct IfStatement {
2689    /// The initial `IF` block containing the condition and statements.
2690    pub if_block: ConditionalStatementBlock,
2691    /// Additional `ELSEIF` blocks.
2692    pub elseif_blocks: Vec<ConditionalStatementBlock>,
2693    /// Optional `ELSE` block.
2694    pub else_block: Option<ConditionalStatementBlock>,
2695    /// Optional trailing `END` token for the `IF` statement.
2696    pub end_token: Option<AttachedToken>,
2697}
2698
2699impl fmt::Display for IfStatement {
2700    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2701        let IfStatement {
2702            if_block,
2703            elseif_blocks,
2704            else_block,
2705            end_token,
2706        } = self;
2707
2708        write!(f, "{if_block}")?;
2709
2710        for elseif_block in elseif_blocks {
2711            write!(f, " {elseif_block}")?;
2712        }
2713
2714        if let Some(else_block) = else_block {
2715            write!(f, " {else_block}")?;
2716        }
2717
2718        if let Some(AttachedToken(end_token)) = end_token {
2719            write!(f, " END {end_token}")?;
2720        }
2721
2722        Ok(())
2723    }
2724}
2725
2726/// A `WHILE` statement.
2727///
2728/// Example:
2729/// ```sql
2730/// WHILE @@FETCH_STATUS = 0
2731/// BEGIN
2732///    FETCH NEXT FROM c1 INTO @var1, @var2;
2733/// END
2734/// ```
2735///
2736/// [MsSql](https://learn.microsoft.com/en-us/sql/t-sql/language-elements/while-transact-sql)
2737#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2738#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2739#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2740pub struct WhileStatement {
2741    /// Block executed while the condition holds.
2742    pub while_block: ConditionalStatementBlock,
2743}
2744
2745impl fmt::Display for WhileStatement {
2746    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2747        let WhileStatement { while_block } = self;
2748        write!(f, "{while_block}")?;
2749        Ok(())
2750    }
2751}
2752
2753/// A block within a [Statement::Case] or [Statement::If] or [Statement::While]-like statement
2754///
2755/// Example 1:
2756/// ```sql
2757/// WHEN EXISTS(SELECT 1) THEN SELECT 1;
2758/// ```
2759///
2760/// Example 2:
2761/// ```sql
2762/// IF TRUE THEN SELECT 1; SELECT 2;
2763/// ```
2764///
2765/// Example 3:
2766/// ```sql
2767/// ELSE SELECT 1; SELECT 2;
2768/// ```
2769///
2770/// Example 4:
2771/// ```sql
2772/// WHILE @@FETCH_STATUS = 0
2773/// BEGIN
2774///    FETCH NEXT FROM c1 INTO @var1, @var2;
2775/// END
2776/// ```
2777#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2778#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2779#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2780pub struct ConditionalStatementBlock {
2781    /// Token representing the start of the block (e.g., WHEN/IF/WHILE).
2782    pub start_token: AttachedToken,
2783    /// Optional condition expression for the block.
2784    pub condition: Option<Expr>,
2785    /// Optional token for the `THEN` keyword.
2786    pub then_token: Option<AttachedToken>,
2787    /// The statements contained in this conditional block.
2788    pub conditional_statements: ConditionalStatements,
2789}
2790
2791impl ConditionalStatementBlock {
2792    /// Get the statements in this conditional block.
2793    pub fn statements(&self) -> &Vec<Statement> {
2794        self.conditional_statements.statements()
2795    }
2796}
2797
2798impl fmt::Display for ConditionalStatementBlock {
2799    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2800        let ConditionalStatementBlock {
2801            start_token: AttachedToken(start_token),
2802            condition,
2803            then_token,
2804            conditional_statements,
2805        } = self;
2806
2807        write!(f, "{start_token}")?;
2808
2809        if let Some(condition) = condition {
2810            write!(f, " {condition}")?;
2811        }
2812
2813        if then_token.is_some() {
2814            write!(f, " THEN")?;
2815        }
2816
2817        if !conditional_statements.statements().is_empty() {
2818            write!(f, " {conditional_statements}")?;
2819        }
2820
2821        Ok(())
2822    }
2823}
2824
2825/// A list of statements in a [ConditionalStatementBlock].
2826#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2827#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2828#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2829/// Statements used inside conditional blocks (`IF`, `WHEN`, `WHILE`).
2830pub enum ConditionalStatements {
2831    /// Simple sequence of statements (no `BEGIN`/`END`).
2832    Sequence {
2833        /// The statements in the sequence.
2834        statements: Vec<Statement>,
2835    },
2836    /// Block enclosed by `BEGIN` and `END`.
2837    BeginEnd(BeginEndStatements),
2838}
2839
2840impl ConditionalStatements {
2841    /// Get the statements in this conditional statements block.
2842    pub fn statements(&self) -> &Vec<Statement> {
2843        match self {
2844            ConditionalStatements::Sequence { statements } => statements,
2845            ConditionalStatements::BeginEnd(bes) => &bes.statements,
2846        }
2847    }
2848}
2849
2850impl fmt::Display for ConditionalStatements {
2851    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2852        match self {
2853            ConditionalStatements::Sequence { statements } => {
2854                if !statements.is_empty() {
2855                    format_statement_list(f, statements)?;
2856                }
2857                Ok(())
2858            }
2859            ConditionalStatements::BeginEnd(bes) => write!(f, "{bes}"),
2860        }
2861    }
2862}
2863
2864/// Represents a list of statements enclosed within `BEGIN` and `END` keywords.
2865/// Example:
2866/// ```sql
2867/// BEGIN
2868///     SELECT 1;
2869///     SELECT 2;
2870/// END
2871/// ```
2872#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2873#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2874#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2875pub struct BeginEndStatements {
2876    /// Token representing the `BEGIN` keyword (may include span info).
2877    pub begin_token: AttachedToken,
2878    /// Statements contained within the block.
2879    pub statements: Vec<Statement>,
2880    /// Token representing the `END` keyword (may include span info).
2881    pub end_token: AttachedToken,
2882}
2883
2884impl fmt::Display for BeginEndStatements {
2885    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2886        let BeginEndStatements {
2887            begin_token: AttachedToken(begin_token),
2888            statements,
2889            end_token: AttachedToken(end_token),
2890        } = self;
2891
2892        if begin_token.token != Token::EOF {
2893            write!(f, "{begin_token} ")?;
2894        }
2895        if !statements.is_empty() {
2896            format_statement_list(f, statements)?;
2897        }
2898        if end_token.token != Token::EOF {
2899            write!(f, " {end_token}")?;
2900        }
2901        Ok(())
2902    }
2903}
2904
2905/// A `RAISE` statement.
2906///
2907/// Examples:
2908/// ```sql
2909/// RAISE USING MESSAGE = 'error';
2910///
2911/// RAISE myerror;
2912/// ```
2913///
2914/// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#raise)
2915/// [Snowflake](https://docs.snowflake.com/en/sql-reference/snowflake-scripting/raise)
2916#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2917#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2918#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2919pub struct RaiseStatement {
2920    /// Optional value provided to the RAISE statement.
2921    pub value: Option<RaiseStatementValue>,
2922}
2923
2924impl fmt::Display for RaiseStatement {
2925    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2926        let RaiseStatement { value } = self;
2927
2928        write!(f, "RAISE")?;
2929        if let Some(value) = value {
2930            write!(f, " {value}")?;
2931        }
2932
2933        Ok(())
2934    }
2935}
2936
2937/// Represents the error value of a [RaiseStatement].
2938#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2939#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2940#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2941pub enum RaiseStatementValue {
2942    /// `RAISE USING MESSAGE = 'error'`
2943    UsingMessage(Expr),
2944    /// `RAISE myerror`
2945    Expr(Expr),
2946}
2947
2948impl fmt::Display for RaiseStatementValue {
2949    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2950        match self {
2951            RaiseStatementValue::Expr(expr) => write!(f, "{expr}"),
2952            RaiseStatementValue::UsingMessage(expr) => write!(f, "USING MESSAGE = {expr}"),
2953        }
2954    }
2955}
2956
2957/// A MSSQL `THROW` statement.
2958///
2959/// ```sql
2960/// THROW [ error_number, message, state ]
2961/// ```
2962///
2963/// [MSSQL](https://learn.microsoft.com/en-us/sql/t-sql/language-elements/throw-transact-sql)
2964#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2965#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2966#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2967pub struct ThrowStatement {
2968    /// Error number expression.
2969    pub error_number: Option<Box<Expr>>,
2970    /// Error message expression.
2971    pub message: Option<Box<Expr>>,
2972    /// State expression.
2973    pub state: Option<Box<Expr>>,
2974}
2975
2976impl fmt::Display for ThrowStatement {
2977    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2978        let ThrowStatement {
2979            error_number,
2980            message,
2981            state,
2982        } = self;
2983
2984        write!(f, "THROW")?;
2985        if let (Some(error_number), Some(message), Some(state)) = (error_number, message, state) {
2986            write!(f, " {error_number}, {message}, {state}")?;
2987        }
2988        Ok(())
2989    }
2990}
2991
2992/// Represents an expression assignment within a variable `DECLARE` statement.
2993///
2994/// Examples:
2995/// ```sql
2996/// DECLARE variable_name := 42
2997/// DECLARE variable_name DEFAULT 42
2998/// ```
2999#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3000#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3001#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3002pub enum DeclareAssignment {
3003    /// Plain expression specified.
3004    Expr(Box<Expr>),
3005
3006    /// Expression assigned via the `DEFAULT` keyword
3007    Default(Box<Expr>),
3008
3009    /// Expression assigned via the `:=` syntax
3010    ///
3011    /// Example:
3012    /// ```sql
3013    /// DECLARE variable_name := 42;
3014    /// ```
3015    DuckAssignment(Box<Expr>),
3016
3017    /// Expression via the `FOR` keyword
3018    ///
3019    /// Example:
3020    /// ```sql
3021    /// DECLARE c1 CURSOR FOR res
3022    /// ```
3023    For(Box<Expr>),
3024
3025    /// Expression via the `=` syntax.
3026    ///
3027    /// Example:
3028    /// ```sql
3029    /// DECLARE @variable AS INT = 100
3030    /// ```
3031    MsSqlAssignment(Box<Expr>),
3032}
3033
3034impl fmt::Display for DeclareAssignment {
3035    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3036        match self {
3037            DeclareAssignment::Expr(expr) => {
3038                write!(f, "{expr}")
3039            }
3040            DeclareAssignment::Default(expr) => {
3041                write!(f, "DEFAULT {expr}")
3042            }
3043            DeclareAssignment::DuckAssignment(expr) => {
3044                write!(f, ":= {expr}")
3045            }
3046            DeclareAssignment::MsSqlAssignment(expr) => {
3047                write!(f, "= {expr}")
3048            }
3049            DeclareAssignment::For(expr) => {
3050                write!(f, "FOR {expr}")
3051            }
3052        }
3053    }
3054}
3055
3056/// Represents the type of a `DECLARE` statement.
3057#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3058#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3059#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3060pub enum DeclareType {
3061    /// Cursor variable type. e.g. [Snowflake] [PostgreSQL] [MsSql]
3062    ///
3063    /// [Snowflake]: https://docs.snowflake.com/en/developer-guide/snowflake-scripting/cursors#declaring-a-cursor
3064    /// [PostgreSQL]: https://www.postgresql.org/docs/current/plpgsql-cursors.html
3065    /// [MsSql]: https://learn.microsoft.com/en-us/sql/t-sql/language-elements/declare-cursor-transact-sql
3066    Cursor,
3067
3068    /// Result set variable type. [Snowflake]
3069    ///
3070    /// Syntax:
3071    /// ```text
3072    /// <resultset_name> RESULTSET [ { DEFAULT | := } ( <query> ) ] ;
3073    /// ```
3074    /// [Snowflake]: https://docs.snowflake.com/en/sql-reference/snowflake-scripting/declare#resultset-declaration-syntax
3075    ResultSet,
3076
3077    /// Exception declaration syntax. [Snowflake]
3078    ///
3079    /// Syntax:
3080    /// ```text
3081    /// <exception_name> EXCEPTION [ ( <exception_number> , '<exception_message>' ) ] ;
3082    /// ```
3083    /// [Snowflake]: https://docs.snowflake.com/en/sql-reference/snowflake-scripting/declare#exception-declaration-syntax
3084    Exception,
3085}
3086
3087impl fmt::Display for DeclareType {
3088    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3089        match self {
3090            DeclareType::Cursor => {
3091                write!(f, "CURSOR")
3092            }
3093            DeclareType::ResultSet => {
3094                write!(f, "RESULTSET")
3095            }
3096            DeclareType::Exception => {
3097                write!(f, "EXCEPTION")
3098            }
3099        }
3100    }
3101}
3102
3103/// A `DECLARE` statement.
3104/// [PostgreSQL] [Snowflake] [BigQuery]
3105///
3106/// Examples:
3107/// ```sql
3108/// DECLARE variable_name := 42
3109/// DECLARE liahona CURSOR FOR SELECT * FROM films;
3110/// ```
3111///
3112/// [PostgreSQL]: https://www.postgresql.org/docs/current/sql-declare.html
3113/// [Snowflake]: https://docs.snowflake.com/en/sql-reference/snowflake-scripting/declare
3114/// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#declare
3115#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3116#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3117#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3118pub struct Declare {
3119    /// The name(s) being declared.
3120    /// Example: `DECLARE a, b, c DEFAULT 42;
3121    pub names: Vec<Ident>,
3122    /// Data-type assigned to the declared variable.
3123    /// Example: `DECLARE x INT64 DEFAULT 42;
3124    pub data_type: Option<DataType>,
3125    /// Expression being assigned to the declared variable.
3126    pub assignment: Option<DeclareAssignment>,
3127    /// Represents the type of the declared variable.
3128    pub declare_type: Option<DeclareType>,
3129    /// Causes the cursor to return data in binary rather than in text format.
3130    pub binary: Option<bool>,
3131    /// None = Not specified
3132    /// Some(true) = INSENSITIVE
3133    /// Some(false) = ASENSITIVE
3134    pub sensitive: Option<bool>,
3135    /// None = Not specified
3136    /// Some(true) = SCROLL
3137    /// Some(false) = NO SCROLL
3138    pub scroll: Option<bool>,
3139    /// None = Not specified
3140    /// Some(true) = WITH HOLD, specifies that the cursor can continue to be used after the transaction that created it successfully commits
3141    /// Some(false) = WITHOUT HOLD, specifies that the cursor cannot be used outside of the transaction that created it
3142    pub hold: Option<bool>,
3143    /// `FOR <query>` clause in a CURSOR declaration.
3144    pub for_query: Option<Box<Query>>,
3145}
3146
3147impl fmt::Display for Declare {
3148    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3149        let Declare {
3150            names,
3151            data_type,
3152            assignment,
3153            declare_type,
3154            binary,
3155            sensitive,
3156            scroll,
3157            hold,
3158            for_query,
3159        } = self;
3160        write!(f, "{}", display_comma_separated(names))?;
3161
3162        if let Some(true) = binary {
3163            write!(f, " BINARY")?;
3164        }
3165
3166        if let Some(sensitive) = sensitive {
3167            if *sensitive {
3168                write!(f, " INSENSITIVE")?;
3169            } else {
3170                write!(f, " ASENSITIVE")?;
3171            }
3172        }
3173
3174        if let Some(scroll) = scroll {
3175            if *scroll {
3176                write!(f, " SCROLL")?;
3177            } else {
3178                write!(f, " NO SCROLL")?;
3179            }
3180        }
3181
3182        if let Some(declare_type) = declare_type {
3183            write!(f, " {declare_type}")?;
3184        }
3185
3186        if let Some(hold) = hold {
3187            if *hold {
3188                write!(f, " WITH HOLD")?;
3189            } else {
3190                write!(f, " WITHOUT HOLD")?;
3191            }
3192        }
3193
3194        if let Some(query) = for_query {
3195            write!(f, " FOR {query}")?;
3196        }
3197
3198        if let Some(data_type) = data_type {
3199            write!(f, " {data_type}")?;
3200        }
3201
3202        if let Some(expr) = assignment {
3203            write!(f, " {expr}")?;
3204        }
3205        Ok(())
3206    }
3207}
3208
3209/// Sql options of a `CREATE TABLE` statement.
3210#[derive(Debug, Default, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3211#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3212#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3213/// Options allowed within a `CREATE TABLE` statement.
3214pub enum CreateTableOptions {
3215    /// No options specified.
3216    #[default]
3217    None,
3218    /// Options specified using the `WITH` keyword, e.g. `WITH (k = v)`.
3219    With(Vec<SqlOption>),
3220    /// Options specified using the `OPTIONS(...)` clause.
3221    Options(Vec<SqlOption>),
3222    /// Plain space-separated options.
3223    Plain(Vec<SqlOption>),
3224    /// Table properties (e.g., TBLPROPERTIES / storage properties).
3225    TableProperties(Vec<SqlOption>),
3226}
3227
3228impl fmt::Display for CreateTableOptions {
3229    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3230        match self {
3231            CreateTableOptions::With(with_options) => {
3232                write!(f, "WITH ({})", display_comma_separated(with_options))
3233            }
3234            CreateTableOptions::Options(options) => {
3235                write!(f, "OPTIONS({})", display_comma_separated(options))
3236            }
3237            CreateTableOptions::TableProperties(options) => {
3238                write!(f, "TBLPROPERTIES ({})", display_comma_separated(options))
3239            }
3240            CreateTableOptions::Plain(options) => {
3241                write!(f, "{}", display_separated(options, " "))
3242            }
3243            CreateTableOptions::None => Ok(()),
3244        }
3245    }
3246}
3247
3248/// A `FROM` clause within a `DELETE` statement.
3249///
3250/// Syntax
3251/// ```sql
3252/// [FROM] table
3253/// ```
3254#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3255#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3256#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3257pub enum FromTable {
3258    /// An explicit `FROM` keyword was specified.
3259    WithFromKeyword(Vec<TableWithJoins>),
3260    /// BigQuery: `FROM` keyword was omitted.
3261    /// <https://cloud.google.com/bigquery/docs/reference/standard-sql/dml-syntax#delete_statement>
3262    WithoutKeyword(Vec<TableWithJoins>),
3263}
3264impl Display for FromTable {
3265    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3266        match self {
3267            FromTable::WithFromKeyword(tables) => {
3268                write!(f, "FROM {}", display_comma_separated(tables))
3269            }
3270            FromTable::WithoutKeyword(tables) => {
3271                write!(f, "{}", display_comma_separated(tables))
3272            }
3273        }
3274    }
3275}
3276
3277#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3278#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3279#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3280/// Variants for the `SET` family of statements.
3281pub enum Set {
3282    /// SQL Standard-style
3283    /// SET a = 1;
3284    /// `SET var = value` (standard SQL-style assignment).
3285    SingleAssignment {
3286        /// Optional scope modifier (`SESSION` / `LOCAL`).
3287        scope: Option<ContextModifier>,
3288        /// Whether this is a Hive-style `HIVEVAR:` assignment.
3289        hivevar: bool,
3290        /// Variable name to assign.
3291        variable: ObjectName,
3292        /// Values assigned to the variable.
3293        values: Vec<Expr>,
3294    },
3295    /// Snowflake-style
3296    /// SET (a, b, ..) = (1, 2, ..);
3297    /// `SET (a, b) = (1, 2)` (tuple assignment syntax).
3298    ParenthesizedAssignments {
3299        /// Variables being assigned in tuple form.
3300        variables: Vec<ObjectName>,
3301        /// Corresponding values for the variables.
3302        values: Vec<Expr>,
3303    },
3304    /// MySQL-style
3305    /// SET a = 1, b = 2, ..;
3306    /// `SET a = 1, b = 2` (MySQL-style comma-separated assignments).
3307    MultipleAssignments {
3308        /// List of `SET` assignments (MySQL-style comma-separated).
3309        assignments: Vec<SetAssignment>,
3310    },
3311    /// Session authorization for Postgres/Redshift
3312    ///
3313    /// ```sql
3314    /// SET SESSION AUTHORIZATION { user_name | DEFAULT }
3315    /// ```
3316    ///
3317    /// See <https://www.postgresql.org/docs/current/sql-set-session-authorization.html>
3318    /// See <https://docs.aws.amazon.com/redshift/latest/dg/r_SET_SESSION_AUTHORIZATION.html>
3319    SetSessionAuthorization(SetSessionAuthorizationParam),
3320    /// MS-SQL session
3321    ///
3322    /// See <https://learn.microsoft.com/en-us/sql/t-sql/statements/set-statements-transact-sql>
3323    SetSessionParam(SetSessionParamKind),
3324    /// ```sql
3325    /// SET [ SESSION | LOCAL ] ROLE role_name
3326    /// ```
3327    ///
3328    /// Sets session state. Examples: [ANSI][1], [Postgresql][2], [MySQL][3], and [Oracle][4]
3329    ///
3330    /// [1]: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#set-role-statement
3331    /// [2]: https://www.postgresql.org/docs/14/sql-set-role.html
3332    /// [3]: https://dev.mysql.com/doc/refman/8.0/en/set-role.html
3333    /// [4]: https://docs.oracle.com/cd/B19306_01/server.102/b14200/statements_10004.htm
3334    SetRole {
3335        /// Non-ANSI optional identifier to inform if the role is defined inside the current session (`SESSION`) or transaction (`LOCAL`).
3336        context_modifier: Option<ContextModifier>,
3337        /// Role name. If NONE is specified, then the current role name is removed.
3338        role_name: Option<Ident>,
3339    },
3340    /// ```sql
3341    /// SET TIME ZONE <value>
3342    /// ```
3343    ///
3344    /// Note: this is a PostgreSQL-specific statements
3345    /// `SET TIME ZONE <value>` is an alias for `SET timezone TO <value>` in PostgreSQL
3346    /// However, we allow it for all dialects.
3347    /// `SET TIME ZONE` statement. `local` indicates the `LOCAL` keyword.
3348    /// `SET TIME ZONE <value>` statement.
3349    SetTimeZone {
3350        /// Whether the `LOCAL` keyword was specified.
3351        local: bool,
3352        /// Time zone expression value.
3353        value: Expr,
3354    },
3355    /// ```sql
3356    /// SET NAMES 'charset_name' [COLLATE 'collation_name']
3357    /// ```
3358    SetNames {
3359        /// Character set name to set.
3360        charset_name: Ident,
3361        /// Optional collation name.
3362        collation_name: Option<String>,
3363    },
3364    /// ```sql
3365    /// SET NAMES DEFAULT
3366    /// ```
3367    ///
3368    /// Note: this is a MySQL-specific statement.
3369    SetNamesDefault {},
3370    /// ```sql
3371    /// SET TRANSACTION ...
3372    /// ```
3373    SetTransaction {
3374        /// Transaction modes (e.g., ISOLATION LEVEL, READ ONLY).
3375        modes: Vec<TransactionMode>,
3376        /// Optional snapshot value for transaction snapshot control.
3377        snapshot: Option<ValueWithSpan>,
3378        /// `true` when the `SESSION` keyword was used.
3379        session: bool,
3380    },
3381}
3382
3383impl Display for Set {
3384    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3385        match self {
3386            Self::ParenthesizedAssignments { variables, values } => write!(
3387                f,
3388                "SET ({}) = ({})",
3389                display_comma_separated(variables),
3390                display_comma_separated(values)
3391            ),
3392            Self::MultipleAssignments { assignments } => {
3393                write!(f, "SET {}", display_comma_separated(assignments))
3394            }
3395            Self::SetRole {
3396                context_modifier,
3397                role_name,
3398            } => {
3399                let role_name = role_name.clone().unwrap_or_else(|| Ident::new("NONE"));
3400                write!(
3401                    f,
3402                    "SET {modifier}ROLE {role_name}",
3403                    modifier = context_modifier.map(|m| format!("{m}")).unwrap_or_default()
3404                )
3405            }
3406            Self::SetSessionAuthorization(kind) => write!(f, "SET SESSION AUTHORIZATION {kind}"),
3407            Self::SetSessionParam(kind) => write!(f, "SET {kind}"),
3408            Self::SetTransaction {
3409                modes,
3410                snapshot,
3411                session,
3412            } => {
3413                if *session {
3414                    write!(f, "SET SESSION CHARACTERISTICS AS TRANSACTION")?;
3415                } else {
3416                    write!(f, "SET TRANSACTION")?;
3417                }
3418                if !modes.is_empty() {
3419                    write!(f, " {}", display_comma_separated(modes))?;
3420                }
3421                if let Some(snapshot_id) = snapshot {
3422                    write!(f, " SNAPSHOT {snapshot_id}")?;
3423                }
3424                Ok(())
3425            }
3426            Self::SetTimeZone { local, value } => {
3427                f.write_str("SET ")?;
3428                if *local {
3429                    f.write_str("LOCAL ")?;
3430                }
3431                write!(f, "TIME ZONE {value}")
3432            }
3433            Self::SetNames {
3434                charset_name,
3435                collation_name,
3436            } => {
3437                write!(f, "SET NAMES {charset_name}")?;
3438
3439                if let Some(collation) = collation_name {
3440                    f.write_str(" COLLATE ")?;
3441                    f.write_str(collation)?;
3442                };
3443
3444                Ok(())
3445            }
3446            Self::SetNamesDefault {} => {
3447                f.write_str("SET NAMES DEFAULT")?;
3448
3449                Ok(())
3450            }
3451            Set::SingleAssignment {
3452                scope,
3453                hivevar,
3454                variable,
3455                values,
3456            } => {
3457                write!(
3458                    f,
3459                    "SET {}{}{} = {}",
3460                    scope.map(|s| format!("{s}")).unwrap_or_default(),
3461                    if *hivevar { "HIVEVAR:" } else { "" },
3462                    variable,
3463                    display_comma_separated(values)
3464                )
3465            }
3466        }
3467    }
3468}
3469
3470/// A representation of a `WHEN` arm with all the identifiers catched and the statements to execute
3471/// for the arm.
3472///
3473/// Snowflake: <https://docs.snowflake.com/en/sql-reference/snowflake-scripting/exception>
3474/// BigQuery: <https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#beginexceptionend>
3475#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3476#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3477#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3478pub struct ExceptionWhen {
3479    /// Identifiers that trigger this branch (error conditions).
3480    pub idents: Vec<Ident>,
3481    /// Statements to execute when the condition matches.
3482    pub statements: Vec<Statement>,
3483}
3484
3485impl Display for ExceptionWhen {
3486    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3487        write!(
3488            f,
3489            "WHEN {idents} THEN",
3490            idents = display_separated(&self.idents, " OR ")
3491        )?;
3492
3493        if !self.statements.is_empty() {
3494            write!(f, " ")?;
3495            format_statement_list(f, &self.statements)?;
3496        }
3497
3498        Ok(())
3499    }
3500}
3501
3502/// ANALYZE statement
3503///
3504/// Supported syntax varies by dialect:
3505/// - Hive: `ANALYZE TABLE t [PARTITION (...)] COMPUTE STATISTICS [NOSCAN] [FOR COLUMNS [col1, ...]] [CACHE METADATA]`
3506/// - PostgreSQL: `ANALYZE [VERBOSE] [t [(col1, ...)]]` See <https://www.postgresql.org/docs/current/sql-analyze.html>
3507/// - General: `ANALYZE [TABLE] t`
3508#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3509#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3510#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3511pub struct Analyze {
3512    #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
3513    /// Name of the table to analyze. `None` for bare `ANALYZE`.
3514    pub table_name: Option<ObjectName>,
3515    /// Optional partition expressions to restrict the analysis.
3516    pub partitions: Option<Vec<Expr>>,
3517    /// `true` when analyzing specific columns (Hive `FOR COLUMNS` syntax).
3518    pub for_columns: bool,
3519    /// Columns to analyze.
3520    pub columns: Vec<Ident>,
3521    /// Whether to cache metadata before analyzing.
3522    pub cache_metadata: bool,
3523    /// Whether to skip scanning the table.
3524    pub noscan: bool,
3525    /// Whether to compute statistics during analysis.
3526    pub compute_statistics: bool,
3527    /// Whether the `TABLE` keyword was present.
3528    pub has_table_keyword: bool,
3529}
3530
3531impl fmt::Display for Analyze {
3532    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3533        write!(f, "ANALYZE")?;
3534        if let Some(ref table_name) = self.table_name {
3535            if self.has_table_keyword {
3536                write!(f, " TABLE")?;
3537            }
3538            write!(f, " {table_name}")?;
3539        }
3540        if !self.for_columns && !self.columns.is_empty() {
3541            write!(f, " ({})", display_comma_separated(&self.columns))?;
3542        }
3543        if let Some(ref parts) = self.partitions {
3544            if !parts.is_empty() {
3545                write!(f, " PARTITION ({})", display_comma_separated(parts))?;
3546            }
3547        }
3548        if self.compute_statistics {
3549            write!(f, " COMPUTE STATISTICS")?;
3550        }
3551        if self.noscan {
3552            write!(f, " NOSCAN")?;
3553        }
3554        if self.cache_metadata {
3555            write!(f, " CACHE METADATA")?;
3556        }
3557        if self.for_columns {
3558            write!(f, " FOR COLUMNS")?;
3559            if !self.columns.is_empty() {
3560                write!(f, " {}", display_comma_separated(&self.columns))?;
3561            }
3562        }
3563        Ok(())
3564    }
3565}
3566
3567/// A top-level statement (SELECT, INSERT, CREATE, etc.)
3568#[allow(clippy::large_enum_variant)]
3569#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3570#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3571#[cfg_attr(
3572    feature = "visitor",
3573    derive(Visit, VisitMut),
3574    visit(with = "visit_statement")
3575)]
3576pub enum Statement {
3577    /// ```sql
3578    /// ANALYZE
3579    /// ```
3580    /// Analyze (Hive)
3581    Analyze(Analyze),
3582    /// `SET` statements (session, transaction, timezone, etc.).
3583    Set(Set),
3584    /// ```sql
3585    /// TRUNCATE
3586    /// ```
3587    /// Truncate (Hive)
3588    Truncate(Truncate),
3589    /// ```sql
3590    /// MSCK
3591    /// ```
3592    /// Msck (Hive)
3593    Msck(Msck),
3594    /// ```sql
3595    /// SELECT
3596    /// ```
3597    Query(Box<Query>),
3598    /// ```sql
3599    /// INSERT
3600    /// ```
3601    Insert(Insert),
3602    /// ```sql
3603    /// INSTALL
3604    /// ```
3605    Install {
3606        /// Only for DuckDB
3607        extension_name: Ident,
3608    },
3609    /// ```sql
3610    /// LOAD
3611    /// ```
3612    Load {
3613        /// Only for DuckDB
3614        extension_name: Ident,
3615    },
3616    // TODO: Support ROW FORMAT
3617    /// LOAD DATA from a directory or query source.
3618    Directory {
3619        /// Whether to overwrite existing files.
3620        overwrite: bool,
3621        /// Whether the directory is local to the server.
3622        local: bool,
3623        /// Path to the directory or files.
3624        path: String,
3625        /// Optional file format for the data.
3626        file_format: Option<FileFormat>,
3627        /// Source query providing data to load.
3628        source: Box<Query>,
3629    },
3630    /// A `CASE` statement.
3631    Case(CaseStatement),
3632    /// An `IF` statement.
3633    If(IfStatement),
3634    /// A `WHILE` statement.
3635    While(WhileStatement),
3636    /// A `RAISE` statement.
3637    Raise(RaiseStatement),
3638    /// ```sql
3639    /// CALL <function>
3640    /// ```
3641    Call(Function),
3642    /// ```sql
3643    /// COPY [TO | FROM] ...
3644    /// ```
3645    Copy {
3646        /// The source of 'COPY TO', or the target of 'COPY FROM'
3647        source: CopySource,
3648        /// If true, is a 'COPY TO' statement. If false is a 'COPY FROM'
3649        to: bool,
3650        /// The target of 'COPY TO', or the source of 'COPY FROM'
3651        target: CopyTarget,
3652        /// WITH options (from PostgreSQL version 9.0)
3653        options: Vec<CopyOption>,
3654        /// WITH options (before PostgreSQL version 9.0)
3655        legacy_options: Vec<CopyLegacyOption>,
3656        /// VALUES a vector of values to be copied
3657        values: Vec<Option<String>>,
3658    },
3659    /// ```sql
3660    /// COPY INTO <table> | <location>
3661    /// ```
3662    /// See:
3663    /// <https://docs.snowflake.com/en/sql-reference/sql/copy-into-table>
3664    /// <https://docs.snowflake.com/en/sql-reference/sql/copy-into-location>
3665    ///
3666    /// Copy Into syntax available for Snowflake is different than the one implemented in
3667    /// Postgres. Although they share common prefix, it is reasonable to implement them
3668    /// in different enums. This can be refactored later once custom dialects
3669    /// are allowed to have custom Statements.
3670    CopyIntoSnowflake {
3671        /// Kind of COPY INTO operation (table or location).
3672        kind: CopyIntoSnowflakeKind,
3673        /// Target object for the COPY INTO operation.
3674        into: ObjectName,
3675        /// Optional list of target columns.
3676        into_columns: Option<Vec<Ident>>,
3677        /// Optional source object name (staged data).
3678        from_obj: Option<ObjectName>,
3679        /// Optional alias for the source object.
3680        from_obj_alias: Option<Ident>,
3681        /// Stage-specific parameters (e.g., credentials, path).
3682        stage_params: StageParamsObject,
3683        /// Optional list of transformations applied when loading.
3684        from_transformations: Option<Vec<StageLoadSelectItemKind>>,
3685        /// Optional source query instead of a staged object.
3686        from_query: Option<Box<Query>>,
3687        /// Optional list of specific file names to load.
3688        files: Option<Vec<String>>,
3689        /// Optional filename matching pattern.
3690        pattern: Option<String>,
3691        /// File format options.
3692        file_format: KeyValueOptions,
3693        /// Additional copy options.
3694        copy_options: KeyValueOptions,
3695        /// Optional validation mode string.
3696        validation_mode: Option<String>,
3697        /// Optional partition expression for loading.
3698        partition: Option<Box<Expr>>,
3699    },
3700    /// ```sql
3701    /// OPEN cursor_name
3702    /// ```
3703    /// Opens a cursor.
3704    Open(OpenStatement),
3705    /// ```sql
3706    /// CLOSE
3707    /// ```
3708    /// Closes the portal underlying an open cursor.
3709    Close {
3710        /// Cursor name
3711        cursor: CloseCursor,
3712    },
3713    /// ```sql
3714    /// UPDATE
3715    /// ```
3716    Update(Update),
3717    /// ```sql
3718    /// DELETE
3719    /// ```
3720    Delete(Delete),
3721    /// ```sql
3722    /// CREATE VIEW
3723    /// ```
3724    CreateView(CreateView),
3725    /// ```sql
3726    /// CREATE TABLE
3727    /// ```
3728    CreateTable(CreateTable),
3729    /// ```sql
3730    /// CREATE VIRTUAL TABLE .. USING <module_name> (<module_args>)`
3731    /// ```
3732    /// Sqlite specific statement
3733    CreateVirtualTable {
3734        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
3735        /// Name of the virtual table module instance.
3736        name: ObjectName,
3737        /// `true` when `IF NOT EXISTS` was specified.
3738        if_not_exists: bool,
3739        /// Module name used by the virtual table.
3740        module_name: Ident,
3741        /// Arguments passed to the module.
3742        module_args: Vec<Ident>,
3743    },
3744    /// ```sql
3745    /// `CREATE INDEX`
3746    /// ```
3747    CreateIndex(CreateIndex),
3748    /// ```sql
3749    /// CREATE ROLE
3750    /// ```
3751    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createrole.html)
3752    CreateRole(CreateRole),
3753    /// ```sql
3754    /// CREATE SECRET
3755    /// ```
3756    /// See [DuckDB](https://duckdb.org/docs/sql/statements/create_secret.html)
3757    CreateSecret {
3758        /// `true` when `OR REPLACE` was specified.
3759        or_replace: bool,
3760        /// Optional `TEMPORARY` flag.
3761        temporary: Option<bool>,
3762        /// `true` when `IF NOT EXISTS` was present.
3763        if_not_exists: bool,
3764        /// Optional secret name.
3765        name: Option<Ident>,
3766        /// Optional storage specifier identifier.
3767        storage_specifier: Option<Ident>,
3768        /// The secret type identifier.
3769        secret_type: Ident,
3770        /// Additional secret options.
3771        options: Vec<SecretOption>,
3772    },
3773    /// A `CREATE SERVER` statement.
3774    CreateServer(CreateServerStatement),
3775    /// ```sql
3776    /// CREATE POLICY
3777    /// ```
3778    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createpolicy.html)
3779    CreatePolicy(CreatePolicy),
3780    /// ```sql
3781    /// CREATE CONNECTOR
3782    /// ```
3783    /// See [Hive](https://cwiki.apache.org/confluence/pages/viewpage.action?pageId=27362034#LanguageManualDDL-CreateDataConnectorCreateConnector)
3784    CreateConnector(CreateConnector),
3785    /// ```sql
3786    /// CREATE OPERATOR
3787    /// ```
3788    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createoperator.html)
3789    CreateOperator(CreateOperator),
3790    /// ```sql
3791    /// CREATE OPERATOR FAMILY
3792    /// ```
3793    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createopfamily.html)
3794    CreateOperatorFamily(CreateOperatorFamily),
3795    /// ```sql
3796    /// CREATE OPERATOR CLASS
3797    /// ```
3798    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createopclass.html)
3799    CreateOperatorClass(CreateOperatorClass),
3800    /// A `CREATE TEXT SEARCH` statement.
3801    ///
3802    /// See [PostgreSQL](https://www.postgresql.org/docs/current/textsearch-intro.html)
3803    CreateTextSearch(CreateTextSearch),
3804    /// ```sql
3805    /// ALTER TABLE
3806    /// ```
3807    AlterTable(AlterTable),
3808    /// ```sql
3809    /// ALTER SCHEMA
3810    /// ```
3811    /// See [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#alter_schema_collate_statement)
3812    AlterSchema(AlterSchema),
3813    /// ```sql
3814    /// ALTER INDEX
3815    /// ```
3816    AlterIndex {
3817        /// Name of the index to alter.
3818        name: ObjectName,
3819        /// The operation to perform on the index.
3820        operation: AlterIndexOperation,
3821    },
3822    /// ```sql
3823    /// ALTER VIEW
3824    /// ```
3825    AlterView {
3826        /// View name being altered.
3827        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
3828        name: ObjectName,
3829        /// Optional new column list for the view.
3830        columns: Vec<Ident>,
3831        /// Replacement query for the view definition.
3832        query: Box<Query>,
3833        /// Additional WITH options for the view.
3834        with_options: Vec<SqlOption>,
3835    },
3836    /// ```sql
3837    /// ALTER FUNCTION
3838    /// ALTER AGGREGATE
3839    /// ```
3840    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-alterfunction.html)
3841    /// and [PostgreSQL](https://www.postgresql.org/docs/current/sql-alteraggregate.html)
3842    AlterFunction(AlterFunction),
3843    /// ```sql
3844    /// ALTER TYPE
3845    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-altertype.html)
3846    /// ```
3847    AlterType(AlterType),
3848    /// ```sql
3849    /// ALTER COLLATION
3850    /// ```
3851    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-altercollation.html)
3852    AlterCollation(AlterCollation),
3853    /// ```sql
3854    /// ALTER OPERATOR
3855    /// ```
3856    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-alteroperator.html)
3857    AlterOperator(AlterOperator),
3858    /// ```sql
3859    /// ALTER OPERATOR FAMILY
3860    /// ```
3861    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-alteropfamily.html)
3862    AlterOperatorFamily(AlterOperatorFamily),
3863    /// ```sql
3864    /// ALTER OPERATOR CLASS
3865    /// ```
3866    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-alteropclass.html)
3867    AlterOperatorClass(AlterOperatorClass),
3868    /// An `ALTER TEXT SEARCH` statement.
3869    ///
3870    /// See [PostgreSQL](https://www.postgresql.org/docs/current/textsearch-configuration.html)
3871    AlterTextSearch(AlterTextSearch),
3872    /// ```sql
3873    /// ALTER ROLE
3874    /// ```
3875    AlterRole {
3876        /// Role name being altered.
3877        name: Ident,
3878        /// Operation to perform on the role.
3879        operation: AlterRoleOperation,
3880    },
3881    /// ```sql
3882    /// ALTER POLICY <NAME> ON <TABLE NAME> [<OPERATION>]
3883    /// ```
3884    /// (Postgresql-specific)
3885    AlterPolicy(AlterPolicy),
3886    /// ```sql
3887    /// ALTER CONNECTOR connector_name SET DCPROPERTIES(property_name=property_value, ...);
3888    /// or
3889    /// ALTER CONNECTOR connector_name SET URL new_url;
3890    /// or
3891    /// ALTER CONNECTOR connector_name SET OWNER [USER|ROLE] user_or_role;
3892    /// ```
3893    /// (Hive-specific)
3894    AlterConnector {
3895        /// Name of the connector to alter.
3896        name: Ident,
3897        /// Optional connector properties to set.
3898        properties: Option<Vec<SqlOption>>,
3899        /// Optional new URL for the connector.
3900        url: Option<String>,
3901        /// Optional new owner specification.
3902        owner: Option<ddl::AlterConnectorOwner>,
3903    },
3904    /// ```sql
3905    /// ALTER SESSION SET sessionParam
3906    /// ALTER SESSION UNSET <param_name> [ , <param_name> , ... ]
3907    /// ```
3908    /// See <https://docs.snowflake.com/en/sql-reference/sql/alter-session>
3909    AlterSession {
3910        /// true is to set for the session parameters, false is to unset
3911        set: bool,
3912        /// The session parameters to set or unset
3913        session_params: KeyValueOptions,
3914    },
3915    /// ```sql
3916    /// ATTACH DATABASE 'path/to/file' AS alias
3917    /// ```
3918    /// (SQLite-specific)
3919    AttachDatabase {
3920        /// The name to bind to the newly attached database
3921        schema_name: Ident,
3922        /// An expression that indicates the path to the database file
3923        database_file_name: Expr,
3924        /// true if the syntax is 'ATTACH DATABASE', false if it's just 'ATTACH'
3925        database: bool,
3926    },
3927    /// (DuckDB-specific)
3928    /// ```sql
3929    /// ATTACH 'sqlite_file.db' AS sqlite_db (READ_ONLY, TYPE SQLITE);
3930    /// ```
3931    /// See <https://duckdb.org/docs/sql/statements/attach.html>
3932    AttachDuckDBDatabase {
3933        /// `true` when `IF NOT EXISTS` was present.
3934        if_not_exists: bool,
3935        /// `true` if the syntax used `ATTACH DATABASE` rather than `ATTACH`.
3936        database: bool,
3937        /// The path identifier to the database file being attached.
3938        database_path: Ident,
3939        /// Optional alias assigned to the attached database.
3940        database_alias: Option<Ident>,
3941        /// Dialect-specific attach options (e.g., `READ_ONLY`).
3942        attach_options: Vec<AttachDuckDBDatabaseOption>,
3943    },
3944    /// (DuckDB-specific)
3945    /// ```sql
3946    /// DETACH db_alias;
3947    /// ```
3948    /// See <https://duckdb.org/docs/sql/statements/attach.html>
3949    DetachDuckDBDatabase {
3950        /// `true` when `IF EXISTS` was present.
3951        if_exists: bool,
3952        /// `true` if the syntax used `DETACH DATABASE` rather than `DETACH`.
3953        database: bool,
3954        /// Alias of the database to detach.
3955        database_alias: Ident,
3956    },
3957    /// ```sql
3958    /// DROP [TABLE, VIEW, ...]
3959    /// ```
3960    Drop {
3961        /// The type of the object to drop: TABLE, VIEW, etc.
3962        object_type: ObjectType,
3963        /// An optional `IF EXISTS` clause. (Non-standard.)
3964        if_exists: bool,
3965        /// One or more objects to drop. (ANSI SQL requires exactly one.)
3966        names: Vec<ObjectName>,
3967        /// Whether `CASCADE` was specified. This will be `false` when
3968        /// `RESTRICT` or no drop behavior at all was specified.
3969        cascade: bool,
3970        /// Whether `RESTRICT` was specified. This will be `false` when
3971        /// `CASCADE` or no drop behavior at all was specified.
3972        restrict: bool,
3973        /// Hive allows you specify whether the table's stored data will be
3974        /// deleted along with the dropped table
3975        purge: bool,
3976        /// MySQL-specific "TEMPORARY" keyword
3977        temporary: bool,
3978        /// MySQL-specific drop index syntax, which requires table specification
3979        /// See <https://dev.mysql.com/doc/refman/8.4/en/drop-index.html>
3980        table: Option<ObjectName>,
3981    },
3982    /// ```sql
3983    /// DROP FUNCTION
3984    /// ```
3985    DropFunction(DropFunction),
3986    /// ```sql
3987    /// DROP DOMAIN
3988    /// ```
3989    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-dropdomain.html)
3990    ///
3991    /// DROP DOMAIN [ IF EXISTS ] name [, ...] [ CASCADE | RESTRICT ]
3992    ///
3993    DropDomain(DropDomain),
3994    /// ```sql
3995    /// DROP PROCEDURE
3996    /// ```
3997    DropProcedure {
3998        /// `true` when `IF EXISTS` was present.
3999        if_exists: bool,
4000        /// One or more functions/procedures to drop.
4001        proc_desc: Vec<FunctionDesc>,
4002        /// Optional drop behavior (`CASCADE` or `RESTRICT`).
4003        drop_behavior: Option<DropBehavior>,
4004    },
4005    /// ```sql
4006    /// DROP SECRET
4007    /// ```
4008    DropSecret {
4009        /// `true` when `IF EXISTS` was present.
4010        if_exists: bool,
4011        /// Optional `TEMPORARY` marker.
4012        temporary: Option<bool>,
4013        /// Name of the secret to drop.
4014        name: Ident,
4015        /// Optional storage specifier identifier.
4016        storage_specifier: Option<Ident>,
4017    },
4018    ///```sql
4019    /// DROP POLICY
4020    /// ```
4021    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-droppolicy.html)
4022    DropPolicy(DropPolicy),
4023    /// ```sql
4024    /// DROP CONNECTOR
4025    /// ```
4026    /// See [Hive](https://cwiki.apache.org/confluence/pages/viewpage.action?pageId=27362034#LanguageManualDDL-DropConnector)
4027    DropConnector {
4028        /// `true` when `IF EXISTS` was present.
4029        if_exists: bool,
4030        /// Name of the connector to drop.
4031        name: Ident,
4032    },
4033    /// ```sql
4034    /// DECLARE
4035    /// ```
4036    /// Declare Cursor Variables
4037    ///
4038    /// Note: this is a PostgreSQL-specific statement,
4039    /// but may also compatible with other SQL.
4040    Declare {
4041        /// Cursor declaration statements collected by `DECLARE`.
4042        stmts: Vec<Declare>,
4043    },
4044    /// ```sql
4045    /// CREATE EXTENSION [ IF NOT EXISTS ] extension_name
4046    ///     [ WITH ] [ SCHEMA schema_name ]
4047    ///              [ VERSION version ]
4048    ///              [ CASCADE ]
4049    /// ```
4050    ///
4051    /// Note: this is a PostgreSQL-specific statement,
4052    CreateExtension(CreateExtension),
4053    /// ```sql
4054    /// CREATE COLLATION
4055    /// ```
4056    /// Note: this is a PostgreSQL-specific statement.
4057    /// <https://www.postgresql.org/docs/current/sql-createcollation.html>
4058    CreateCollation(CreateCollation),
4059    /// ```sql
4060    /// DROP EXTENSION [ IF EXISTS ] name [, ...] [ CASCADE | RESTRICT ]
4061    /// ```
4062    /// Note: this is a PostgreSQL-specific statement.
4063    /// <https://www.postgresql.org/docs/current/sql-dropextension.html>
4064    DropExtension(DropExtension),
4065    /// ```sql
4066    /// DROP OPERATOR [ IF EXISTS ] name ( { left_type | NONE } , right_type ) [, ...] [ CASCADE | RESTRICT ]
4067    /// ```
4068    /// Note: this is a PostgreSQL-specific statement.
4069    /// <https://www.postgresql.org/docs/current/sql-dropoperator.html>
4070    DropOperator(DropOperator),
4071    /// ```sql
4072    /// DROP OPERATOR FAMILY [ IF EXISTS ] name USING index_method [ CASCADE | RESTRICT ]
4073    /// ```
4074    /// Note: this is a PostgreSQL-specific statement.
4075    /// <https://www.postgresql.org/docs/current/sql-dropopfamily.html>
4076    DropOperatorFamily(DropOperatorFamily),
4077    /// ```sql
4078    /// DROP OPERATOR CLASS [ IF EXISTS ] name USING index_method [ CASCADE | RESTRICT ]
4079    /// ```
4080    /// Note: this is a PostgreSQL-specific statement.
4081    /// <https://www.postgresql.org/docs/current/sql-dropopclass.html>
4082    DropOperatorClass(DropOperatorClass),
4083    /// ```sql
4084    /// FETCH
4085    /// ```
4086    /// Retrieve rows from a query using a cursor
4087    ///
4088    /// Note: this is a PostgreSQL-specific statement,
4089    /// but may also compatible with other SQL.
4090    Fetch {
4091        /// Cursor name
4092        name: Ident,
4093        /// The fetch direction (e.g., `FORWARD`, `BACKWARD`).
4094        direction: FetchDirection,
4095        /// The fetch position (e.g., `ALL`, `NEXT`, `ABSOLUTE`).
4096        position: FetchPosition,
4097        /// Optional target table to fetch rows into.
4098        into: Option<ObjectName>,
4099    },
4100    /// ```sql
4101    /// FLUSH [NO_WRITE_TO_BINLOG | LOCAL] flush_option [, flush_option] ... | tables_option
4102    /// ```
4103    ///
4104    /// Note: this is a Mysql-specific statement,
4105    /// but may also compatible with other SQL.
4106    Flush {
4107        /// The specific flush option or object to flush.
4108        object_type: FlushType,
4109        /// Optional flush location (dialect-specific).
4110        location: Option<FlushLocation>,
4111        /// Optional channel name used for flush operations.
4112        channel: Option<String>,
4113        /// Whether a read lock was requested.
4114        read_lock: bool,
4115        /// Whether this is an export flush operation.
4116        export: bool,
4117        /// Optional list of tables involved in the flush.
4118        tables: Vec<ObjectName>,
4119    },
4120    /// ```sql
4121    /// DISCARD [ ALL | PLANS | SEQUENCES | TEMPORARY | TEMP ]
4122    /// ```
4123    ///
4124    /// Note: this is a PostgreSQL-specific statement,
4125    /// but may also compatible with other SQL.
4126    Discard {
4127        /// The kind of object(s) to discard (ALL, PLANS, etc.).
4128        object_type: DiscardObject,
4129    },
4130    /// `SHOW FUNCTIONS`
4131    ///
4132    /// Note: this is a Presto-specific statement.
4133    ShowFunctions {
4134        /// Optional filter for which functions to display.
4135        filter: Option<ShowStatementFilter>,
4136    },
4137    /// ```sql
4138    /// SHOW <variable>
4139    /// ```
4140    ///
4141    /// Note: this is a PostgreSQL-specific statement.
4142    ShowVariable {
4143        /// Variable name as one or more identifiers.
4144        variable: Vec<Ident>,
4145    },
4146    /// ```sql
4147    /// SHOW [GLOBAL | SESSION] STATUS [LIKE 'pattern' | WHERE expr]
4148    /// ```
4149    ///
4150    /// Note: this is a MySQL-specific statement.
4151    ShowStatus {
4152        /// Optional filter for which status entries to display.
4153        filter: Option<ShowStatementFilter>,
4154        /// `true` when `GLOBAL` scope was requested.
4155        global: bool,
4156        /// `true` when `SESSION` scope was requested.
4157        session: bool,
4158    },
4159    /// ```sql
4160    /// SHOW VARIABLES
4161    /// ```
4162    ///
4163    /// Note: this is a MySQL-specific statement.
4164    ShowVariables {
4165        /// Optional filter for which variables to display.
4166        filter: Option<ShowStatementFilter>,
4167        /// `true` when `GLOBAL` scope was requested.
4168        global: bool,
4169        /// `true` when `SESSION` scope was requested.
4170        session: bool,
4171    },
4172    /// ```sql
4173    /// SHOW CREATE TABLE
4174    /// ```
4175    ///
4176    /// Note: this is a MySQL-specific statement.
4177    ShowCreate {
4178        /// The kind of object being shown (TABLE, VIEW, etc.).
4179        obj_type: ShowCreateObject,
4180        /// The name of the object to show create statement for.
4181        obj_name: ObjectName,
4182    },
4183    /// ```sql
4184    /// SHOW COLUMNS
4185    /// ```
4186    ShowColumns {
4187        /// `true` when extended column information was requested.
4188        extended: bool,
4189        /// `true` when full column details were requested.
4190        full: bool,
4191        /// Additional options for `SHOW COLUMNS`.
4192        show_options: ShowStatementOptions,
4193    },
4194    /// ```sql
4195    /// SHOW CATALOGS
4196    /// ```
4197    ShowCatalogs {
4198        /// `true` when terse output format was requested.
4199        terse: bool,
4200        /// `true` when history information was requested.
4201        history: bool,
4202        /// Additional options for `SHOW CATALOGS`.
4203        show_options: ShowStatementOptions,
4204    },
4205    /// ```sql
4206    /// SHOW DATABASES
4207    /// ```
4208    ShowDatabases {
4209        /// `true` when terse output format was requested.
4210        terse: bool,
4211        /// `true` when history information was requested.
4212        history: bool,
4213        /// Additional options for `SHOW DATABASES`.
4214        show_options: ShowStatementOptions,
4215    },
4216    /// ```sql
4217    /// SHOW [FULL] PROCESSLIST
4218    /// ```
4219    ///
4220    /// Note: this is a MySQL-specific statement.
4221    ShowProcessList {
4222        /// `true` when full process information was requested.
4223        full: bool,
4224    },
4225    /// ```sql
4226    /// SHOW SCHEMAS
4227    /// ```
4228    ShowSchemas {
4229        /// `true` when terse (compact) output was requested.
4230        terse: bool,
4231        /// `true` when history information was requested.
4232        history: bool,
4233        /// Additional options for `SHOW SCHEMAS`.
4234        show_options: ShowStatementOptions,
4235    },
4236    // ```sql
4237    // SHOW {CHARACTER SET | CHARSET}
4238    // ```
4239    // [MySQL]:
4240    // <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>
4241    /// Show the available character sets (alias `CHARSET`).
4242    ShowCharset(ShowCharset),
4243    /// ```sql
4244    /// SHOW OBJECTS LIKE 'line%' IN mydb.public
4245    /// ```
4246    /// Snowflake-specific statement
4247    /// <https://docs.snowflake.com/en/sql-reference/sql/show-objects>
4248    ShowObjects(ShowObjects),
4249    /// ```sql
4250    /// SHOW TABLES
4251    /// ```
4252    ShowTables {
4253        /// `true` when terse output format was requested (compact listing).
4254        terse: bool,
4255        /// `true` when history rows are requested.
4256        history: bool,
4257        /// `true` when extended information should be shown.
4258        extended: bool,
4259        /// `true` when a full listing was requested.
4260        full: bool,
4261        /// `true` when external tables should be included.
4262        external: bool,
4263        /// Additional options for `SHOW` statements.
4264        show_options: ShowStatementOptions,
4265    },
4266    /// ```sql
4267    /// SHOW VIEWS
4268    /// ```
4269    ShowViews {
4270        /// `true` when terse output format was requested.
4271        terse: bool,
4272        /// `true` when materialized views should be included.
4273        materialized: bool,
4274        /// Additional options for `SHOW` statements.
4275        show_options: ShowStatementOptions,
4276    },
4277    /// ```sql
4278    /// SHOW COLLATION
4279    /// ```
4280    ///
4281    /// Note: this is a MySQL-specific statement.
4282    ShowCollation {
4283        /// Optional filter for which collations to display.
4284        filter: Option<ShowStatementFilter>,
4285    },
4286    /// ```sql
4287    /// `USE ...`
4288    /// ```
4289    Use(Use),
4290    /// ```sql
4291    /// START  [ TRANSACTION | WORK ] | START TRANSACTION } ...
4292    /// ```
4293    /// If `begin` is false.
4294    ///
4295    /// ```sql
4296    /// `BEGIN  [ TRANSACTION | WORK ] | START TRANSACTION } ...`
4297    /// ```
4298    /// If `begin` is true
4299    StartTransaction {
4300        /// Transaction modes such as `ISOLATION LEVEL` or `READ WRITE`.
4301        modes: Vec<TransactionMode>,
4302        /// `true` when this was parsed as `BEGIN` instead of `START`.
4303        begin: bool,
4304        /// Optional specific keyword used: `TRANSACTION` or `WORK`.
4305        transaction: Option<BeginTransactionKind>,
4306        /// Optional transaction modifier (e.g., `AND NO CHAIN`).
4307        modifier: Option<TransactionModifier>,
4308        /// List of statements belonging to the `BEGIN` block.
4309        /// Example:
4310        /// ```sql
4311        /// BEGIN
4312        ///     SELECT 1;
4313        ///     SELECT 2;
4314        /// END;
4315        /// ```
4316        statements: Vec<Statement>,
4317        /// Exception handling with exception clauses.
4318        /// Example:
4319        /// ```sql
4320        /// EXCEPTION
4321        ///     WHEN EXCEPTION_1 THEN
4322        ///         SELECT 2;
4323        ///     WHEN EXCEPTION_2 OR EXCEPTION_3 THEN
4324        ///         SELECT 3;
4325        ///     WHEN OTHER THEN
4326        ///         SELECT 4;
4327        /// ```
4328        /// <https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#beginexceptionend>
4329        /// <https://docs.snowflake.com/en/sql-reference/snowflake-scripting/exception>
4330        exception: Option<Vec<ExceptionWhen>>,
4331        /// TRUE if the statement has an `END` keyword.
4332        has_end_keyword: bool,
4333    },
4334    /// ```sql
4335    /// COMMENT ON ...
4336    /// ```
4337    ///
4338    /// Note: this is a PostgreSQL-specific statement.
4339    Comment {
4340        /// Type of object being commented (table, column, etc.).
4341        object_type: CommentObject,
4342        /// Name of the object the comment applies to.
4343        object_name: ObjectName,
4344        /// Optional comment text (None to remove comment).
4345        comment: Option<String>,
4346        /// An optional `IF EXISTS` clause. (Non-standard.)
4347        /// See <https://docs.snowflake.com/en/sql-reference/sql/comment>
4348        if_exists: bool,
4349    },
4350    /// ```sql
4351    /// COMMIT [ TRANSACTION | WORK ] [ AND [ NO ] CHAIN ]
4352    /// ```
4353    /// If `end` is false
4354    ///
4355    /// ```sql
4356    /// END [ TRY | CATCH ]
4357    /// ```
4358    /// If `end` is true
4359    Commit {
4360        /// `true` when `AND [ NO ] CHAIN` was present.
4361        chain: bool,
4362        /// `true` when this `COMMIT` was parsed as an `END` block terminator.
4363        end: bool,
4364        /// Optional transaction modifier for commit semantics.
4365        modifier: Option<TransactionModifier>,
4366    },
4367    /// ```sql
4368    /// ROLLBACK [ TRANSACTION | WORK ] [ AND [ NO ] CHAIN ] [ TO [ SAVEPOINT ] savepoint_name ]
4369    /// ```
4370    Rollback {
4371        /// `true` when `AND [ NO ] CHAIN` was present.
4372        chain: bool,
4373        /// Optional savepoint name to roll back to.
4374        savepoint: Option<Ident>,
4375    },
4376    /// ```sql
4377    /// CREATE SCHEMA
4378    /// ```
4379    CreateSchema {
4380        /// `<schema name> | AUTHORIZATION <schema authorization identifier>  | <schema name>  AUTHORIZATION <schema authorization identifier>`
4381        schema_name: SchemaName,
4382        /// `true` when `OR REPLACE` was present.
4383        or_replace: bool,
4384        /// `true` when `IF NOT EXISTS` was present.
4385        if_not_exists: bool,
4386        /// Schema properties.
4387        ///
4388        /// ```sql
4389        /// CREATE SCHEMA myschema WITH (key1='value1');
4390        /// ```
4391        ///
4392        /// [Trino](https://trino.io/docs/current/sql/create-schema.html)
4393        with: Option<Vec<SqlOption>>,
4394        /// Schema options.
4395        ///
4396        /// ```sql
4397        /// CREATE SCHEMA myschema OPTIONS(key1='value1');
4398        /// ```
4399        ///
4400        /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_schema_statement)
4401        options: Option<Vec<SqlOption>>,
4402        /// Default collation specification for the schema.
4403        ///
4404        /// ```sql
4405        /// CREATE SCHEMA myschema DEFAULT COLLATE 'und:ci';
4406        /// ```
4407        ///
4408        /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_schema_statement)
4409        default_collate_spec: Option<Expr>,
4410        /// Clones a schema
4411        ///
4412        /// ```sql
4413        /// CREATE SCHEMA myschema CLONE otherschema
4414        /// ```
4415        ///
4416        /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-clone#databases-schemas)
4417        clone: Option<ObjectName>,
4418    },
4419    /// ```sql
4420    /// CREATE DATABASE
4421    /// ```
4422    /// See:
4423    /// <https://docs.snowflake.com/en/sql-reference/sql/create-database>
4424    CreateDatabase {
4425        /// Database name.
4426        db_name: ObjectName,
4427        /// `IF NOT EXISTS` flag.
4428        if_not_exists: bool,
4429        /// Optional location URI.
4430        location: Option<String>,
4431        /// Optional managed location.
4432        managed_location: Option<String>,
4433        /// `OR REPLACE` flag.
4434        or_replace: bool,
4435        /// `TRANSIENT` flag.
4436        transient: bool,
4437        /// Optional clone source.
4438        clone: Option<ObjectName>,
4439        /// Optional data retention time in days.
4440        data_retention_time_in_days: Option<u64>,
4441        /// Optional maximum data extension time in days.
4442        max_data_extension_time_in_days: Option<u64>,
4443        /// Optional external volume identifier.
4444        external_volume: Option<String>,
4445        /// Optional catalog name.
4446        catalog: Option<String>,
4447        /// Whether to replace invalid characters.
4448        replace_invalid_characters: Option<bool>,
4449        /// Default DDL collation string.
4450        default_ddl_collation: Option<String>,
4451        /// Storage serialization policy.
4452        storage_serialization_policy: Option<StorageSerializationPolicy>,
4453        /// Optional comment.
4454        comment: Option<String>,
4455        /// Optional default character set (MySQL).
4456        default_charset: Option<String>,
4457        /// Optional default collation (MySQL).
4458        default_collation: Option<String>,
4459        /// Optional catalog sync identifier.
4460        catalog_sync: Option<String>,
4461        /// Catalog sync namespace mode.
4462        catalog_sync_namespace_mode: Option<CatalogSyncNamespaceMode>,
4463        /// Optional flatten delimiter for namespace sync.
4464        catalog_sync_namespace_flatten_delimiter: Option<String>,
4465        /// Optional tags for the database.
4466        with_tags: Option<Vec<Tag>>,
4467        /// Optional contact entries for the database.
4468        with_contacts: Option<Vec<ContactEntry>>,
4469    },
4470    /// ```sql
4471    /// CREATE FUNCTION
4472    /// ```
4473    ///
4474    /// Supported variants:
4475    /// 1. [Hive](https://cwiki.apache.org/confluence/display/hive/languagemanual+ddl#LanguageManualDDL-Create/Drop/ReloadFunction)
4476    /// 2. [PostgreSQL](https://www.postgresql.org/docs/15/sql-createfunction.html)
4477    /// 3. [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_function_statement)
4478    /// 4. [MsSql](https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql)
4479    CreateFunction(CreateFunction),
4480    /// CREATE TRIGGER statement. See struct [CreateTrigger] for details.
4481    CreateTrigger(CreateTrigger),
4482    /// DROP TRIGGER statement. See struct [DropTrigger] for details.
4483    DropTrigger(DropTrigger),
4484    /// ```sql
4485    /// CREATE PROCEDURE
4486    /// ```
4487    CreateProcedure {
4488        /// `OR ALTER` flag.
4489        or_alter: bool,
4490        /// Procedure name.
4491        name: ObjectName,
4492        /// Optional procedure parameters.
4493        params: Option<Vec<ProcedureParam>>,
4494        /// Optional language identifier.
4495        language: Option<Ident>,
4496        /// Procedure body statements.
4497        body: ConditionalStatements,
4498    },
4499    /// ```sql
4500    /// CREATE MACRO
4501    /// ```
4502    ///
4503    /// Supported variants:
4504    /// 1. [DuckDB](https://duckdb.org/docs/sql/statements/create_macro)
4505    CreateMacro {
4506        /// `OR REPLACE` flag.
4507        or_replace: bool,
4508        /// Whether macro is temporary.
4509        temporary: bool,
4510        /// Macro name.
4511        name: ObjectName,
4512        /// Optional macro arguments.
4513        args: Option<Vec<MacroArg>>,
4514        /// Macro definition body.
4515        definition: MacroDefinition,
4516    },
4517    /// ```sql
4518    /// CREATE STAGE
4519    /// ```
4520    /// See <https://docs.snowflake.com/en/sql-reference/sql/create-stage>
4521    CreateStage {
4522        /// `OR REPLACE` flag for stage.
4523        or_replace: bool,
4524        /// Whether stage is temporary.
4525        temporary: bool,
4526        /// `IF NOT EXISTS` flag.
4527        if_not_exists: bool,
4528        /// Stage name.
4529        name: ObjectName,
4530        /// Stage parameters.
4531        stage_params: StageParamsObject,
4532        /// Directory table parameters.
4533        directory_table_params: KeyValueOptions,
4534        /// File format options.
4535        file_format: KeyValueOptions,
4536        /// Copy options for stage.
4537        copy_options: KeyValueOptions,
4538        /// Optional comment.
4539        comment: Option<String>,
4540    },
4541    /// ```sql
4542    /// CREATE [ OR REPLACE ] [ { TEMP | TEMPORARY | VOLATILE } ] FILE FORMAT [ IF NOT EXISTS ] <name>
4543    ///   [ TYPE = { CSV | JSON | AVRO | ORC | PARQUET | XML } [ formatTypeOptions ] ]
4544    ///   [ COMMENT = '<string_literal>' ]
4545    /// ```
4546    /// See <https://docs.snowflake.com/en/sql-reference/sql/create-file-format>
4547    CreateFileFormat {
4548        /// `OR REPLACE` flag.
4549        or_replace: bool,
4550        /// Whether file format is temporary.
4551        temporary: bool,
4552        /// Whether file format is volatile.
4553        volatile: bool,
4554        /// `IF NOT EXISTS` flag.
4555        if_not_exists: bool,
4556        /// File format name.
4557        name: ObjectName,
4558        /// Format type options (e.g. `TYPE`, `FIELD_DELIMITER`, `COMPRESSION`, ...).
4559        options: KeyValueOptions,
4560        /// Optional comment.
4561        comment: Option<String>,
4562    },
4563    /// ```sql
4564    /// CREATE [ OR REPLACE ] WAREHOUSE [ IF NOT EXISTS ] <name>
4565    ///   [ [ WITH ] <property> = <value> [ ... ] ]
4566    /// ```
4567    /// Snowflake-specific statement to create a virtual warehouse.
4568    ///
4569    /// See <https://docs.snowflake.com/en/sql-reference/sql/create-warehouse>
4570    CreateWarehouse(CreateWarehouse),
4571    /// ```sql
4572    /// ASSERT <condition> [AS <message>]
4573    /// ```
4574    Assert {
4575        /// Assertion condition expression.
4576        condition: Expr,
4577        /// Optional message expression.
4578        message: Option<Expr>,
4579    },
4580    /// ```sql
4581    /// GRANT privileges ON objects TO grantees
4582    /// ```
4583    Grant(Grant),
4584    /// ```sql
4585    /// DENY privileges ON object TO grantees
4586    /// ```
4587    Deny(DenyStatement),
4588    /// ```sql
4589    /// REVOKE privileges ON objects FROM grantees
4590    /// ```
4591    Revoke(Revoke),
4592    /// ```sql
4593    /// DEALLOCATE [ PREPARE ] { name | ALL }
4594    /// ```
4595    ///
4596    /// Note: this is a PostgreSQL-specific statement.
4597    Deallocate {
4598        /// Name to deallocate (or `ALL`).
4599        name: Ident,
4600        /// Whether `PREPARE` keyword was present.
4601        prepare: bool,
4602    },
4603    /// ```sql
4604    /// An `EXECUTE` statement
4605    /// ```
4606    ///
4607    /// Postgres: <https://www.postgresql.org/docs/current/sql-execute.html>
4608    /// MSSQL: <https://learn.microsoft.com/en-us/sql/relational-databases/stored-procedures/execute-a-stored-procedure>
4609    /// BigQuery: <https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#execute_immediate>
4610    /// Snowflake: <https://docs.snowflake.com/en/sql-reference/sql/execute-immediate>
4611    Execute {
4612        /// Optional function/procedure name.
4613        name: Option<ObjectName>,
4614        /// Parameter expressions passed to execute.
4615        parameters: Vec<Expr>,
4616        /// Whether parentheses were present around `parameters`.
4617        has_parentheses: bool,
4618        /// Is this an `EXECUTE IMMEDIATE`.
4619        immediate: bool,
4620        /// Identifiers to capture results into.
4621        into: Vec<Ident>,
4622        /// `USING` expressions with optional aliases.
4623        using: Vec<ExprWithAlias>,
4624        /// Whether the last parameter is the return value of the procedure
4625        /// MSSQL: <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/execute-transact-sql?view=sql-server-ver17#output>
4626        output: bool,
4627        /// Whether to invoke the procedure with the default parameter values
4628        /// MSSQL: <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/execute-transact-sql?view=sql-server-ver17#default>
4629        default: bool,
4630    },
4631    /// ```sql
4632    /// PREPARE name [ ( data_type [, ...] ) ] AS statement
4633    /// ```
4634    ///
4635    /// Note: this is a PostgreSQL-specific statement.
4636    Prepare {
4637        /// Name of the prepared statement.
4638        name: Ident,
4639        /// Optional data types for parameters.
4640        data_types: Vec<DataType>,
4641        /// Statement being prepared.
4642        statement: Box<Statement>,
4643    },
4644    /// ```sql
4645    /// KILL [CONNECTION | QUERY | MUTATION]
4646    /// ```
4647    ///
4648    /// See <https://clickhouse.com/docs/en/sql-reference/statements/kill/>
4649    /// See <https://dev.mysql.com/doc/refman/8.0/en/kill.html>
4650    Kill {
4651        /// Optional kill modifier (CONNECTION, QUERY, MUTATION).
4652        modifier: Option<KillType>,
4653        // processlist_id
4654        /// The id of the process to kill.
4655        id: u64,
4656    },
4657    /// ```sql
4658    /// [EXPLAIN | DESC | DESCRIBE] TABLE
4659    /// ```
4660    /// Note: this is a MySQL-specific statement. See <https://dev.mysql.com/doc/refman/8.0/en/explain.html>
4661    ExplainTable {
4662        /// `EXPLAIN | DESC | DESCRIBE`
4663        describe_alias: DescribeAlias,
4664        /// Hive style `FORMATTED | EXTENDED`
4665        hive_format: Option<HiveDescribeFormat>,
4666        /// Snowflake and ClickHouse support `DESC|DESCRIBE TABLE <table_name>` syntax
4667        ///
4668        /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/desc-table.html)
4669        /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/describe-table)
4670        has_table_keyword: bool,
4671        /// Table name
4672        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
4673        table_name: ObjectName,
4674    },
4675    /// ```sql
4676    /// [EXPLAIN | DESC | DESCRIBE]  <statement>
4677    /// ```
4678    Explain {
4679        /// `EXPLAIN | DESC | DESCRIBE`
4680        describe_alias: DescribeAlias,
4681        /// Carry out the command and show actual run times and other statistics.
4682        analyze: bool,
4683        /// Display additional information regarding the plan.
4684        verbose: bool,
4685        /// `EXPLAIN QUERY PLAN`
4686        /// Display the query plan without running the query.
4687        ///
4688        /// [SQLite](https://sqlite.org/lang_explain.html)
4689        query_plan: bool,
4690        /// `EXPLAIN ESTIMATE`
4691        /// [Clickhouse](https://clickhouse.com/docs/en/sql-reference/statements/explain#explain-estimate)
4692        estimate: bool,
4693        /// A SQL query that specifies what to explain
4694        statement: Box<Statement>,
4695        /// Optional output format of explain
4696        format: Option<AnalyzeFormatKind>,
4697        /// Postgres style utility options, `(analyze, verbose true)`
4698        options: Option<Vec<UtilityOption>>,
4699    },
4700    /// ```sql
4701    /// SAVEPOINT
4702    /// ```
4703    /// Define a new savepoint within the current transaction
4704    Savepoint {
4705        /// Name of the savepoint being defined.
4706        name: Ident,
4707    },
4708    /// ```sql
4709    /// RELEASE [ SAVEPOINT ] savepoint_name
4710    /// ```
4711    ReleaseSavepoint {
4712        /// Name of the savepoint to release.
4713        name: Ident,
4714    },
4715    /// A `MERGE` statement.
4716    ///
4717    /// ```sql
4718    /// MERGE INTO <target_table> USING <source> ON <join_expr> { matchedClause | notMatchedClause } [ ... ]
4719    /// ```
4720    /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/merge)
4721    /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/dml-syntax#merge_statement)
4722    /// [MSSQL](https://learn.microsoft.com/en-us/sql/t-sql/statements/merge-transact-sql?view=sql-server-ver16)
4723    Merge(Merge),
4724    /// ```sql
4725    /// CACHE [ FLAG ] TABLE <table_name> [ OPTIONS('K1' = 'V1', 'K2' = V2) ] [ AS ] [ <query> ]
4726    /// ```
4727    ///
4728    /// See [Spark SQL docs] for more details.
4729    ///
4730    /// [Spark SQL docs]: https://docs.databricks.com/spark/latest/spark-sql/language-manual/sql-ref-syntax-aux-cache-cache-table.html
4731    Cache {
4732        /// Table flag
4733        table_flag: Option<ObjectName>,
4734        /// Table name
4735        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
4736        table_name: ObjectName,
4737        /// `true` if `AS` keyword was present before the query.
4738        has_as: bool,
4739        /// Table confs
4740        options: Vec<SqlOption>,
4741        /// Cache table as a Query
4742        query: Option<Box<Query>>,
4743    },
4744    /// ```sql
4745    /// UNCACHE TABLE [ IF EXISTS ]  <table_name>
4746    /// ```
4747    UNCache {
4748        /// Table name
4749        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
4750        table_name: ObjectName,
4751        /// `true` when `IF EXISTS` was present.
4752        if_exists: bool,
4753    },
4754    /// ```sql
4755    /// CREATE [ { TEMPORARY | TEMP } ] SEQUENCE [ IF NOT EXISTS ] <sequence_name>
4756    /// ```
4757    /// Define a new sequence:
4758    CreateSequence {
4759        /// Whether the sequence is temporary.
4760        temporary: bool,
4761        /// `IF NOT EXISTS` flag.
4762        if_not_exists: bool,
4763        /// Sequence name.
4764        name: ObjectName,
4765        /// Optional data type for the sequence.
4766        data_type: Option<DataType>,
4767        /// Sequence options (INCREMENT, MINVALUE, etc.).
4768        sequence_options: Vec<SequenceOptions>,
4769        /// Optional `OWNED BY` target.
4770        owned_by: Option<ObjectName>,
4771    },
4772    /// A `CREATE DOMAIN` statement.
4773    CreateDomain(CreateDomain),
4774    /// ```sql
4775    /// CREATE TYPE <name>
4776    /// ```
4777    CreateType {
4778        /// Type name to create.
4779        name: ObjectName,
4780        /// Optional type representation details.
4781        representation: Option<UserDefinedTypeRepresentation>,
4782    },
4783    /// ```sql
4784    /// PRAGMA <schema-name>.<pragma-name> = <pragma-value>
4785    /// ```
4786    Pragma {
4787        /// Pragma name (possibly qualified).
4788        name: ObjectName,
4789        /// Optional pragma value.
4790        value: Option<ValueWithSpan>,
4791        /// Whether the pragma used `=`.
4792        is_eq: bool,
4793    },
4794    /// ```sql
4795    /// LOCK [ TABLE ] [ ONLY ] name [ * ] [, ...] [ IN lockmode MODE ] [ NOWAIT ]
4796    /// ```
4797    ///
4798    /// See <https://www.postgresql.org/docs/current/sql-lock.html>
4799    Lock(Lock),
4800    /// ```sql
4801    /// LOCK TABLES <table_name> [READ [LOCAL] | [LOW_PRIORITY] WRITE]
4802    /// ```
4803    /// Note: this is a MySQL-specific statement. See <https://dev.mysql.com/doc/refman/8.0/en/lock-tables.html>
4804    LockTables {
4805        /// List of tables to lock with modes.
4806        tables: Vec<LockTable>,
4807    },
4808    /// ```sql
4809    /// UNLOCK TABLES
4810    /// ```
4811    /// Note: this is a MySQL-specific statement. See <https://dev.mysql.com/doc/refman/8.0/en/lock-tables.html>
4812    UnlockTables,
4813    /// Unloads the result of a query to file
4814    ///
4815    /// [Athena](https://docs.aws.amazon.com/athena/latest/ug/unload.html):
4816    /// ```sql
4817    /// UNLOAD(statement) TO <destination> [ WITH options ]
4818    /// ```
4819    ///
4820    /// [Redshift](https://docs.aws.amazon.com/redshift/latest/dg/r_UNLOAD.html):
4821    /// ```sql
4822    /// UNLOAD('statement') TO <destination> [ OPTIONS ]
4823    /// ```
4824    Unload {
4825        /// Optional query AST to unload.
4826        query: Option<Box<Query>>,
4827        /// Optional original query text.
4828        query_text: Option<String>,
4829        /// Destination identifier.
4830        to: Ident,
4831        /// Optional IAM role/auth information.
4832        auth: Option<IamRoleKind>,
4833        /// Additional `WITH` options.
4834        with: Vec<SqlOption>,
4835        /// Legacy copy-style options.
4836        options: Vec<CopyLegacyOption>,
4837    },
4838    /// ClickHouse:
4839    /// ```sql
4840    /// OPTIMIZE TABLE [db.]name [ON CLUSTER cluster] [PARTITION partition | PARTITION ID 'partition_id'] [FINAL] [DEDUPLICATE [BY expression]]
4841    /// ```
4842    /// See ClickHouse <https://clickhouse.com/docs/en/sql-reference/statements/optimize>
4843    ///
4844    /// Databricks:
4845    /// ```sql
4846    /// OPTIMIZE table_name [WHERE predicate] [ZORDER BY (col_name1 [, ...])]
4847    /// ```
4848    /// See Databricks <https://docs.databricks.com/en/sql/language-manual/delta-optimize.html>
4849    OptimizeTable {
4850        /// Table name to optimize.
4851        name: ObjectName,
4852        /// Whether the `TABLE` keyword was present (ClickHouse uses `OPTIMIZE TABLE`, Databricks uses `OPTIMIZE`).
4853        has_table_keyword: bool,
4854        /// Optional cluster identifier.
4855        /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/optimize)
4856        on_cluster: Option<Ident>,
4857        /// Optional partition spec.
4858        /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/optimize)
4859        partition: Option<Partition>,
4860        /// Whether `FINAL` was specified.
4861        /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/optimize)
4862        include_final: bool,
4863        /// Optional deduplication settings.
4864        /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/optimize)
4865        deduplicate: Option<Deduplicate>,
4866        /// Optional WHERE predicate.
4867        /// [Databricks](https://docs.databricks.com/en/sql/language-manual/delta-optimize.html)
4868        predicate: Option<Expr>,
4869        /// Optional ZORDER BY columns.
4870        /// [Databricks](https://docs.databricks.com/en/sql/language-manual/delta-optimize.html)
4871        zorder: Option<Vec<Expr>>,
4872    },
4873    /// ```sql
4874    /// LISTEN
4875    /// ```
4876    /// listen for a notification channel
4877    ///
4878    /// See Postgres <https://www.postgresql.org/docs/current/sql-listen.html>
4879    LISTEN {
4880        /// Notification channel identifier.
4881        channel: Ident,
4882    },
4883    /// ```sql
4884    /// UNLISTEN
4885    /// ```
4886    /// stop listening for a notification
4887    ///
4888    /// See Postgres <https://www.postgresql.org/docs/current/sql-unlisten.html>
4889    UNLISTEN {
4890        /// Notification channel identifier.
4891        channel: Ident,
4892    },
4893    /// ```sql
4894    /// NOTIFY channel [ , payload ]
4895    /// ```
4896    /// send a notification event together with an optional "payload" string to channel
4897    ///
4898    /// See Postgres <https://www.postgresql.org/docs/current/sql-notify.html>
4899    NOTIFY {
4900        /// Notification channel identifier.
4901        channel: Ident,
4902        /// Optional payload string.
4903        payload: Option<String>,
4904    },
4905    /// ```sql
4906    /// LOAD DATA [LOCAL] INPATH 'filepath' [OVERWRITE] INTO TABLE tablename
4907    /// [PARTITION (partcol1=val1, partcol2=val2 ...)]
4908    /// [INPUTFORMAT 'inputformat' SERDE 'serde']
4909    /// ```
4910    /// Loading files into tables
4911    ///
4912    /// See Hive <https://cwiki.apache.org/confluence/pages/viewpage.action?pageId=27362036#LanguageManualDML-Loadingfilesintotables>
4913    LoadData {
4914        /// Whether `LOCAL` is present.
4915        local: bool,
4916        /// Input path for files to load.
4917        inpath: String,
4918        /// Whether `OVERWRITE` was specified.
4919        overwrite: bool,
4920        /// Target table name to load into.
4921        table_name: ObjectName,
4922        /// Optional partition specification.
4923        partitioned: Option<Vec<Expr>>,
4924        /// Optional table format information.
4925        table_format: Option<HiveLoadDataFormat>,
4926    },
4927    /// ```sql
4928    /// Rename TABLE tbl_name TO new_tbl_name[, tbl_name2 TO new_tbl_name2] ...
4929    /// ```
4930    /// Renames one or more tables
4931    ///
4932    /// See Mysql <https://dev.mysql.com/doc/refman/9.1/en/rename-table.html>
4933    RenameTable(Vec<RenameTable>),
4934    /// Snowflake `LIST`
4935    /// See: <https://docs.snowflake.com/en/sql-reference/sql/list>
4936    List(FileStagingCommand),
4937    /// Snowflake `PUT`
4938    /// ```sql
4939    /// PUT 'file://<path>' <internalStage> [ <option> = <value> ... ]
4940    /// ```
4941    /// Options include `PARALLEL`, `AUTO_COMPRESS`, `SOURCE_COMPRESSION`, `OVERWRITE`.
4942    /// See: <https://docs.snowflake.com/en/sql-reference/sql/put>
4943    Put {
4944        /// Local source URI as written in the statement, e.g. `file:///tmp/data.csv`.
4945        source: String,
4946        /// Target internal stage (e.g. `@mystage`, `@~`, `@%table`).
4947        stage: ObjectName,
4948        /// Trailing options (`PARALLEL=4`, `AUTO_COMPRESS=TRUE`, ...).
4949        options: KeyValueOptions,
4950    },
4951    /// Snowflake `REMOVE`
4952    /// See: <https://docs.snowflake.com/en/sql-reference/sql/remove>
4953    Remove(FileStagingCommand),
4954    /// RaiseError (MSSQL)
4955    /// RAISERROR ( { msg_id | msg_str | @local_variable }
4956    /// { , severity , state }
4957    /// [ , argument [ , ...n ] ] )
4958    /// [ WITH option [ , ...n ] ]
4959    /// See <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/raiserror-transact-sql?view=sql-server-ver16>
4960    RaisError {
4961        /// Error message expression or identifier.
4962        message: Box<Expr>,
4963        /// Severity expression.
4964        severity: Box<Expr>,
4965        /// State expression.
4966        state: Box<Expr>,
4967        /// Substitution arguments for the message.
4968        arguments: Vec<Expr>,
4969        /// Additional `WITH` options for RAISERROR.
4970        options: Vec<RaisErrorOption>,
4971    },
4972    /// A MSSQL `THROW` statement.
4973    Throw(ThrowStatement),
4974    /// ```sql
4975    /// PRINT msg_str | @local_variable | string_expr
4976    /// ```
4977    ///
4978    /// See: <https://learn.microsoft.com/en-us/sql/t-sql/statements/print-transact-sql>
4979    Print(PrintStatement),
4980    /// MSSQL `WAITFOR` statement.
4981    ///
4982    /// See: <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/waitfor-transact-sql>
4983    WaitFor(WaitForStatement),
4984    /// ```sql
4985    /// RETURN [ expression ]
4986    /// ```
4987    ///
4988    /// See [ReturnStatement]
4989    Return(ReturnStatement),
4990    /// Export data statement
4991    ///
4992    /// Example:
4993    /// ```sql
4994    /// EXPORT DATA OPTIONS(uri='gs://bucket/folder/*', format='PARQUET', overwrite=true) AS
4995    /// SELECT field1, field2 FROM mydataset.table1 ORDER BY field1 LIMIT 10
4996    /// ```
4997    /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/export-statements)
4998    ExportData(ExportData),
4999    /// ```sql
5000    /// CREATE [OR REPLACE] USER <user> [IF NOT EXISTS]
5001    /// ```
5002    /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-user)
5003    CreateUser(CreateUser),
5004    /// ```sql
5005    /// ALTER USER \[ IF EXISTS \] \[ <name> \]
5006    /// ```
5007    /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/alter-user)
5008    AlterUser(AlterUser),
5009    /// Re-sorts rows and reclaims space in either a specified table or all tables in the current database
5010    ///
5011    /// ```sql
5012    /// VACUUM tbl
5013    /// ```
5014    /// [Redshift](https://docs.aws.amazon.com/redshift/latest/dg/r_VACUUM_command.html)
5015    Vacuum(VacuumStatement),
5016    /// Restore the value of a run-time parameter to the default value.
5017    ///
5018    /// ```sql
5019    /// RESET configuration_parameter;
5020    /// RESET ALL;
5021    /// ```
5022    /// [PostgreSQL](https://www.postgresql.org/docs/current/sql-reset.html)
5023    Reset(ResetStatement),
5024}
5025
5026impl From<Analyze> for Statement {
5027    fn from(analyze: Analyze) -> Self {
5028        Statement::Analyze(analyze)
5029    }
5030}
5031
5032impl From<ddl::Truncate> for Statement {
5033    fn from(truncate: ddl::Truncate) -> Self {
5034        Statement::Truncate(truncate)
5035    }
5036}
5037
5038impl From<Lock> for Statement {
5039    fn from(lock: Lock) -> Self {
5040        Statement::Lock(lock)
5041    }
5042}
5043
5044impl From<ddl::Msck> for Statement {
5045    fn from(msck: ddl::Msck) -> Self {
5046        Statement::Msck(msck)
5047    }
5048}
5049
5050/// ```sql
5051/// {COPY | REVOKE} CURRENT GRANTS
5052/// ```
5053///
5054/// - [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/grant-ownership#optional-parameters)
5055#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
5056#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
5057#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
5058pub enum CurrentGrantsKind {
5059    /// `COPY CURRENT GRANTS` (copy current grants to target).
5060    CopyCurrentGrants,
5061    /// `REVOKE CURRENT GRANTS` (revoke current grants from target).
5062    RevokeCurrentGrants,
5063}
5064
5065impl fmt::Display for CurrentGrantsKind {
5066    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
5067        match self {
5068            CurrentGrantsKind::CopyCurrentGrants => write!(f, "COPY CURRENT GRANTS"),
5069            CurrentGrantsKind::RevokeCurrentGrants => write!(f, "REVOKE CURRENT GRANTS"),
5070        }
5071    }
5072}
5073
5074#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
5075#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
5076#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
5077/// `RAISERROR` options
5078/// See <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/raiserror-transact-sql?view=sql-server-ver16#options>
5079pub enum RaisErrorOption {
5080    /// Log the error.
5081    Log,
5082    /// Do not wait for completion.
5083    NoWait,
5084    /// Set the error state.
5085    SetError,
5086}
5087
5088impl fmt::Display for RaisErrorOption {
5089    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
5090        match self {
5091            RaisErrorOption::Log => write!(f, "LOG"),
5092            RaisErrorOption::NoWait => write!(f, "NOWAIT"),
5093            RaisErrorOption::SetError => write!(f, "SETERROR"),
5094        }
5095    }
5096}
5097
5098impl fmt::Display for Statement {
5099    /// Formats a SQL statement with support for pretty printing.
5100    ///
5101    /// When using the alternate flag (`{:#}`), the statement will be formatted with proper
5102    /// indentation and line breaks. For example:
5103    ///
5104    /// ```
5105    /// # use sqlparser::dialect::GenericDialect;
5106    /// # use sqlparser::parser::Parser;
5107    /// let sql = "SELECT a, b FROM table_1";
5108    /// let ast = Parser::parse_sql(&GenericDialect, sql).unwrap();
5109    ///
5110    /// // Regular formatting
5111    /// assert_eq!(format!("{}", ast[0]), "SELECT a, b FROM table_1");
5112    ///
5113    /// // Pretty printing
5114    /// assert_eq!(format!("{:#}", ast[0]),
5115    /// r#"SELECT
5116    ///   a,
5117    ///   b
5118    /// FROM
5119    ///   table_1"#);
5120    /// ```
5121    // Clippy thinks this function is too complicated, but it is painful to
5122    // split up without extracting structs for each `Statement` variant.
5123    #[allow(clippy::cognitive_complexity)]
5124    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
5125        match self {
5126            Statement::Flush {
5127                object_type,
5128                location,
5129                channel,
5130                read_lock,
5131                export,
5132                tables,
5133            } => {
5134                write!(f, "FLUSH")?;
5135                if let Some(location) = location {
5136                    f.write_str(" ")?;
5137                    location.fmt(f)?;
5138                }
5139                write!(f, " {object_type}")?;
5140
5141                if let Some(channel) = channel {
5142                    write!(f, " FOR CHANNEL {channel}")?;
5143                }
5144
5145                write!(
5146                    f,
5147                    "{tables}{read}{export}",
5148                    tables = if !tables.is_empty() {
5149                        format!(" {}", display_comma_separated(tables))
5150                    } else {
5151                        String::new()
5152                    },
5153                    export = if *export { " FOR EXPORT" } else { "" },
5154                    read = if *read_lock { " WITH READ LOCK" } else { "" }
5155                )
5156            }
5157            Statement::Kill { modifier, id } => {
5158                write!(f, "KILL ")?;
5159
5160                if let Some(m) = modifier {
5161                    write!(f, "{m} ")?;
5162                }
5163
5164                write!(f, "{id}")
5165            }
5166            Statement::ExplainTable {
5167                describe_alias,
5168                hive_format,
5169                has_table_keyword,
5170                table_name,
5171            } => {
5172                write!(f, "{describe_alias} ")?;
5173
5174                if let Some(format) = hive_format {
5175                    write!(f, "{format} ")?;
5176                }
5177                if *has_table_keyword {
5178                    write!(f, "TABLE ")?;
5179                }
5180
5181                write!(f, "{table_name}")
5182            }
5183            Statement::Explain {
5184                describe_alias,
5185                verbose,
5186                analyze,
5187                query_plan,
5188                estimate,
5189                statement,
5190                format,
5191                options,
5192            } => {
5193                write!(f, "{describe_alias} ")?;
5194
5195                if *query_plan {
5196                    write!(f, "QUERY PLAN ")?;
5197                }
5198                if *analyze {
5199                    write!(f, "ANALYZE ")?;
5200                }
5201                if *estimate {
5202                    write!(f, "ESTIMATE ")?;
5203                }
5204
5205                if *verbose {
5206                    write!(f, "VERBOSE ")?;
5207                }
5208
5209                if let Some(format) = format {
5210                    write!(f, "{format} ")?;
5211                }
5212
5213                if let Some(options) = options {
5214                    write!(f, "({}) ", display_comma_separated(options))?;
5215                }
5216
5217                write!(f, "{statement}")
5218            }
5219            Statement::Query(s) => s.fmt(f),
5220            Statement::Declare { stmts } => {
5221                write!(f, "DECLARE ")?;
5222                write!(f, "{}", display_separated(stmts, "; "))
5223            }
5224            Statement::Fetch {
5225                name,
5226                direction,
5227                position,
5228                into,
5229            } => {
5230                write!(f, "FETCH {direction} {position} {name}")?;
5231
5232                if let Some(into) = into {
5233                    write!(f, " INTO {into}")?;
5234                }
5235
5236                Ok(())
5237            }
5238            Statement::Directory {
5239                overwrite,
5240                local,
5241                path,
5242                file_format,
5243                source,
5244            } => {
5245                write!(
5246                    f,
5247                    "INSERT{overwrite}{local} DIRECTORY '{path}'",
5248                    overwrite = if *overwrite { " OVERWRITE" } else { "" },
5249                    local = if *local { " LOCAL" } else { "" },
5250                    path = path
5251                )?;
5252                if let Some(ref ff) = file_format {
5253                    write!(f, " STORED AS {ff}")?
5254                }
5255                write!(f, " {source}")
5256            }
5257            Statement::Msck(msck) => msck.fmt(f),
5258            Statement::Truncate(truncate) => truncate.fmt(f),
5259            Statement::Case(stmt) => {
5260                write!(f, "{stmt}")
5261            }
5262            Statement::If(stmt) => {
5263                write!(f, "{stmt}")
5264            }
5265            Statement::While(stmt) => {
5266                write!(f, "{stmt}")
5267            }
5268            Statement::Raise(stmt) => {
5269                write!(f, "{stmt}")
5270            }
5271            Statement::AttachDatabase {
5272                schema_name,
5273                database_file_name,
5274                database,
5275            } => {
5276                let keyword = if *database { "DATABASE " } else { "" };
5277                write!(f, "ATTACH {keyword}{database_file_name} AS {schema_name}")
5278            }
5279            Statement::AttachDuckDBDatabase {
5280                if_not_exists,
5281                database,
5282                database_path,
5283                database_alias,
5284                attach_options,
5285            } => {
5286                write!(
5287                    f,
5288                    "ATTACH{database}{if_not_exists} {database_path}",
5289                    database = if *database { " DATABASE" } else { "" },
5290                    if_not_exists = if *if_not_exists { " IF NOT EXISTS" } else { "" },
5291                )?;
5292                if let Some(alias) = database_alias {
5293                    write!(f, " AS {alias}")?;
5294                }
5295                if !attach_options.is_empty() {
5296                    write!(f, " ({})", display_comma_separated(attach_options))?;
5297                }
5298                Ok(())
5299            }
5300            Statement::DetachDuckDBDatabase {
5301                if_exists,
5302                database,
5303                database_alias,
5304            } => {
5305                write!(
5306                    f,
5307                    "DETACH{database}{if_exists} {database_alias}",
5308                    database = if *database { " DATABASE" } else { "" },
5309                    if_exists = if *if_exists { " IF EXISTS" } else { "" },
5310                )?;
5311                Ok(())
5312            }
5313            Statement::Analyze(analyze) => analyze.fmt(f),
5314            Statement::Insert(insert) => insert.fmt(f),
5315            Statement::Install {
5316                extension_name: name,
5317            } => write!(f, "INSTALL {name}"),
5318
5319            Statement::Load {
5320                extension_name: name,
5321            } => write!(f, "LOAD {name}"),
5322
5323            Statement::Call(function) => write!(f, "CALL {function}"),
5324
5325            Statement::Copy {
5326                source,
5327                to,
5328                target,
5329                options,
5330                legacy_options,
5331                values,
5332            } => {
5333                write!(f, "COPY")?;
5334                match source {
5335                    CopySource::Query(query) => write!(f, " ({query})")?,
5336                    CopySource::Table {
5337                        table_name,
5338                        columns,
5339                    } => {
5340                        write!(f, " {table_name}")?;
5341                        if !columns.is_empty() {
5342                            write!(f, " ({})", display_comma_separated(columns))?;
5343                        }
5344                    }
5345                }
5346                write!(f, " {} {}", if *to { "TO" } else { "FROM" }, target)?;
5347                if !options.is_empty() {
5348                    write!(f, " ({})", display_comma_separated(options))?;
5349                }
5350                if !legacy_options.is_empty() {
5351                    write!(f, " {}", display_separated(legacy_options, " "))?;
5352                }
5353                if !values.is_empty() {
5354                    writeln!(f, ";")?;
5355                    let mut delim = "";
5356                    for v in values {
5357                        write!(f, "{delim}")?;
5358                        delim = "\t";
5359                        if let Some(v) = v {
5360                            write!(f, "{v}")?;
5361                        } else {
5362                            write!(f, "\\N")?;
5363                        }
5364                    }
5365                    write!(f, "\n\\.")?;
5366                }
5367                Ok(())
5368            }
5369            Statement::Update(update) => update.fmt(f),
5370            Statement::Delete(delete) => delete.fmt(f),
5371            Statement::Open(open) => open.fmt(f),
5372            Statement::Close { cursor } => {
5373                write!(f, "CLOSE {cursor}")?;
5374
5375                Ok(())
5376            }
5377            Statement::CreateDatabase {
5378                db_name,
5379                if_not_exists,
5380                location,
5381                managed_location,
5382                or_replace,
5383                transient,
5384                clone,
5385                data_retention_time_in_days,
5386                max_data_extension_time_in_days,
5387                external_volume,
5388                catalog,
5389                replace_invalid_characters,
5390                default_ddl_collation,
5391                storage_serialization_policy,
5392                comment,
5393                default_charset,
5394                default_collation,
5395                catalog_sync,
5396                catalog_sync_namespace_mode,
5397                catalog_sync_namespace_flatten_delimiter,
5398                with_tags,
5399                with_contacts,
5400            } => {
5401                write!(
5402                    f,
5403                    "CREATE {or_replace}{transient}DATABASE {if_not_exists}{name}",
5404                    or_replace = if *or_replace { "OR REPLACE " } else { "" },
5405                    transient = if *transient { "TRANSIENT " } else { "" },
5406                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
5407                    name = db_name,
5408                )?;
5409
5410                if let Some(l) = location {
5411                    write!(f, " LOCATION '{l}'")?;
5412                }
5413                if let Some(ml) = managed_location {
5414                    write!(f, " MANAGEDLOCATION '{ml}'")?;
5415                }
5416                if let Some(clone) = clone {
5417                    write!(f, " CLONE {clone}")?;
5418                }
5419
5420                if let Some(value) = data_retention_time_in_days {
5421                    write!(f, " DATA_RETENTION_TIME_IN_DAYS = {value}")?;
5422                }
5423
5424                if let Some(value) = max_data_extension_time_in_days {
5425                    write!(f, " MAX_DATA_EXTENSION_TIME_IN_DAYS = {value}")?;
5426                }
5427
5428                if let Some(vol) = external_volume {
5429                    write!(f, " EXTERNAL_VOLUME = '{vol}'")?;
5430                }
5431
5432                if let Some(cat) = catalog {
5433                    write!(f, " CATALOG = '{cat}'")?;
5434                }
5435
5436                if let Some(true) = replace_invalid_characters {
5437                    write!(f, " REPLACE_INVALID_CHARACTERS = TRUE")?;
5438                } else if let Some(false) = replace_invalid_characters {
5439                    write!(f, " REPLACE_INVALID_CHARACTERS = FALSE")?;
5440                }
5441
5442                if let Some(collation) = default_ddl_collation {
5443                    write!(f, " DEFAULT_DDL_COLLATION = '{collation}'")?;
5444                }
5445
5446                if let Some(policy) = storage_serialization_policy {
5447                    write!(f, " STORAGE_SERIALIZATION_POLICY = {policy}")?;
5448                }
5449
5450                if let Some(comment) = comment {
5451                    write!(f, " COMMENT = '{comment}'")?;
5452                }
5453
5454                if let Some(charset) = default_charset {
5455                    write!(f, " DEFAULT CHARACTER SET {charset}")?;
5456                }
5457
5458                if let Some(collation) = default_collation {
5459                    write!(f, " DEFAULT COLLATE {collation}")?;
5460                }
5461
5462                if let Some(sync) = catalog_sync {
5463                    write!(f, " CATALOG_SYNC = '{sync}'")?;
5464                }
5465
5466                if let Some(mode) = catalog_sync_namespace_mode {
5467                    write!(f, " CATALOG_SYNC_NAMESPACE_MODE = {mode}")?;
5468                }
5469
5470                if let Some(delim) = catalog_sync_namespace_flatten_delimiter {
5471                    write!(f, " CATALOG_SYNC_NAMESPACE_FLATTEN_DELIMITER = '{delim}'")?;
5472                }
5473
5474                if let Some(tags) = with_tags {
5475                    write!(f, " WITH TAG ({})", display_comma_separated(tags))?;
5476                }
5477
5478                if let Some(contacts) = with_contacts {
5479                    write!(f, " WITH CONTACT ({})", display_comma_separated(contacts))?;
5480                }
5481                Ok(())
5482            }
5483            Statement::CreateFunction(create_function) => create_function.fmt(f),
5484            Statement::CreateDomain(create_domain) => create_domain.fmt(f),
5485            Statement::CreateTrigger(create_trigger) => create_trigger.fmt(f),
5486            Statement::DropTrigger(drop_trigger) => drop_trigger.fmt(f),
5487            Statement::CreateProcedure {
5488                name,
5489                or_alter,
5490                params,
5491                language,
5492                body,
5493            } => {
5494                write!(
5495                    f,
5496                    "CREATE {or_alter}PROCEDURE {name}",
5497                    or_alter = if *or_alter { "OR ALTER " } else { "" },
5498                    name = name
5499                )?;
5500
5501                if let Some(p) = params {
5502                    if !p.is_empty() {
5503                        write!(f, " ({})", display_comma_separated(p))?;
5504                    }
5505                }
5506
5507                if let Some(language) = language {
5508                    write!(f, " LANGUAGE {language}")?;
5509                }
5510
5511                write!(f, " AS {body}")
5512            }
5513            Statement::CreateMacro {
5514                or_replace,
5515                temporary,
5516                name,
5517                args,
5518                definition,
5519            } => {
5520                write!(
5521                    f,
5522                    "CREATE {or_replace}{temp}MACRO {name}",
5523                    temp = if *temporary { "TEMPORARY " } else { "" },
5524                    or_replace = if *or_replace { "OR REPLACE " } else { "" },
5525                )?;
5526                if let Some(args) = args {
5527                    write!(f, "({})", display_comma_separated(args))?;
5528                }
5529                match definition {
5530                    MacroDefinition::Expr(expr) => write!(f, " AS {expr}")?,
5531                    MacroDefinition::Table(query) => write!(f, " AS TABLE {query}")?,
5532                }
5533                Ok(())
5534            }
5535            Statement::CreateView(create_view) => create_view.fmt(f),
5536            Statement::CreateTable(create_table) => create_table.fmt(f),
5537            Statement::LoadData {
5538                local,
5539                inpath,
5540                overwrite,
5541                table_name,
5542                partitioned,
5543                table_format,
5544            } => {
5545                write!(
5546                    f,
5547                    "LOAD DATA {local}INPATH '{inpath}' {overwrite}INTO TABLE {table_name}",
5548                    local = if *local { "LOCAL " } else { "" },
5549                    inpath = inpath,
5550                    overwrite = if *overwrite { "OVERWRITE " } else { "" },
5551                    table_name = table_name,
5552                )?;
5553                if let Some(ref parts) = &partitioned {
5554                    if !parts.is_empty() {
5555                        write!(f, " PARTITION ({})", display_comma_separated(parts))?;
5556                    }
5557                }
5558                if let Some(HiveLoadDataFormat {
5559                    serde,
5560                    input_format,
5561                }) = &table_format
5562                {
5563                    write!(f, " INPUTFORMAT {input_format} SERDE {serde}")?;
5564                }
5565                Ok(())
5566            }
5567            Statement::CreateVirtualTable {
5568                name,
5569                if_not_exists,
5570                module_name,
5571                module_args,
5572            } => {
5573                write!(
5574                    f,
5575                    "CREATE VIRTUAL TABLE {if_not_exists}{name} USING {module_name}",
5576                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
5577                    name = name,
5578                    module_name = module_name
5579                )?;
5580                if !module_args.is_empty() {
5581                    write!(f, " ({})", display_comma_separated(module_args))?;
5582                }
5583                Ok(())
5584            }
5585            Statement::CreateIndex(create_index) => create_index.fmt(f),
5586            Statement::CreateExtension(create_extension) => write!(f, "{create_extension}"),
5587            Statement::CreateCollation(create_collation) => write!(f, "{create_collation}"),
5588            Statement::DropExtension(drop_extension) => write!(f, "{drop_extension}"),
5589            Statement::DropOperator(drop_operator) => write!(f, "{drop_operator}"),
5590            Statement::DropOperatorFamily(drop_operator_family) => {
5591                write!(f, "{drop_operator_family}")
5592            }
5593            Statement::DropOperatorClass(drop_operator_class) => {
5594                write!(f, "{drop_operator_class}")
5595            }
5596            Statement::CreateRole(create_role) => write!(f, "{create_role}"),
5597            Statement::CreateSecret {
5598                or_replace,
5599                temporary,
5600                if_not_exists,
5601                name,
5602                storage_specifier,
5603                secret_type,
5604                options,
5605            } => {
5606                write!(
5607                    f,
5608                    "CREATE {or_replace}",
5609                    or_replace = if *or_replace { "OR REPLACE " } else { "" },
5610                )?;
5611                if let Some(t) = temporary {
5612                    write!(f, "{}", if *t { "TEMPORARY " } else { "PERSISTENT " })?;
5613                }
5614                write!(
5615                    f,
5616                    "SECRET {if_not_exists}",
5617                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
5618                )?;
5619                if let Some(n) = name {
5620                    write!(f, "{n} ")?;
5621                };
5622                if let Some(s) = storage_specifier {
5623                    write!(f, "IN {s} ")?;
5624                }
5625                write!(f, "( TYPE {secret_type}",)?;
5626                if !options.is_empty() {
5627                    write!(f, ", {o}", o = display_comma_separated(options))?;
5628                }
5629                write!(f, " )")?;
5630                Ok(())
5631            }
5632            Statement::CreateServer(stmt) => {
5633                write!(f, "{stmt}")
5634            }
5635            Statement::CreatePolicy(policy) => write!(f, "{policy}"),
5636            Statement::CreateConnector(create_connector) => create_connector.fmt(f),
5637            Statement::CreateOperator(create_operator) => create_operator.fmt(f),
5638            Statement::CreateOperatorFamily(create_operator_family) => {
5639                create_operator_family.fmt(f)
5640            }
5641            Statement::CreateOperatorClass(create_operator_class) => create_operator_class.fmt(f),
5642            Statement::CreateTextSearch(create_text_search) => create_text_search.fmt(f),
5643            Statement::AlterTable(alter_table) => write!(f, "{alter_table}"),
5644            Statement::AlterIndex { name, operation } => {
5645                write!(f, "ALTER INDEX {name} {operation}")
5646            }
5647            Statement::AlterView {
5648                name,
5649                columns,
5650                query,
5651                with_options,
5652            } => {
5653                write!(f, "ALTER VIEW {name}")?;
5654                if !with_options.is_empty() {
5655                    write!(f, " WITH ({})", display_comma_separated(with_options))?;
5656                }
5657                if !columns.is_empty() {
5658                    write!(f, " ({})", display_comma_separated(columns))?;
5659                }
5660                write!(f, " AS {query}")
5661            }
5662            Statement::AlterFunction(alter_function) => write!(f, "{alter_function}"),
5663            Statement::AlterType(AlterType { name, operation }) => {
5664                write!(f, "ALTER TYPE {name} {operation}")
5665            }
5666            Statement::AlterCollation(alter_collation) => write!(f, "{alter_collation}"),
5667            Statement::AlterOperator(alter_operator) => write!(f, "{alter_operator}"),
5668            Statement::AlterOperatorFamily(alter_operator_family) => {
5669                write!(f, "{alter_operator_family}")
5670            }
5671            Statement::AlterOperatorClass(alter_operator_class) => {
5672                write!(f, "{alter_operator_class}")
5673            }
5674            Statement::AlterTextSearch(alter_text_search) => write!(f, "{alter_text_search}"),
5675            Statement::AlterRole { name, operation } => {
5676                write!(f, "ALTER ROLE {name} {operation}")
5677            }
5678            Statement::AlterPolicy(alter_policy) => write!(f, "{alter_policy}"),
5679            Statement::AlterConnector {
5680                name,
5681                properties,
5682                url,
5683                owner,
5684            } => {
5685                write!(f, "ALTER CONNECTOR {name}")?;
5686                if let Some(properties) = properties {
5687                    write!(
5688                        f,
5689                        " SET DCPROPERTIES({})",
5690                        display_comma_separated(properties)
5691                    )?;
5692                }
5693                if let Some(url) = url {
5694                    write!(f, " SET URL '{url}'")?;
5695                }
5696                if let Some(owner) = owner {
5697                    write!(f, " SET OWNER {owner}")?;
5698                }
5699                Ok(())
5700            }
5701            Statement::AlterSession {
5702                set,
5703                session_params,
5704            } => {
5705                write!(
5706                    f,
5707                    "ALTER SESSION {set}",
5708                    set = if *set { "SET" } else { "UNSET" }
5709                )?;
5710                if !session_params.options.is_empty() {
5711                    if *set {
5712                        write!(f, " {session_params}")?;
5713                    } else {
5714                        let options = session_params
5715                            .options
5716                            .iter()
5717                            .map(|p| p.option_name.clone())
5718                            .collect::<Vec<_>>();
5719                        write!(f, " {}", display_separated(&options, ", "))?;
5720                    }
5721                }
5722                Ok(())
5723            }
5724            Statement::Drop {
5725                object_type,
5726                if_exists,
5727                names,
5728                cascade,
5729                restrict,
5730                purge,
5731                temporary,
5732                table,
5733            } => {
5734                write!(
5735                    f,
5736                    "DROP {}{}{} {}{}{}{}",
5737                    if *temporary { "TEMPORARY " } else { "" },
5738                    object_type,
5739                    if *if_exists { " IF EXISTS" } else { "" },
5740                    display_comma_separated(names),
5741                    if *cascade { " CASCADE" } else { "" },
5742                    if *restrict { " RESTRICT" } else { "" },
5743                    if *purge { " PURGE" } else { "" },
5744                )?;
5745                if let Some(table_name) = table.as_ref() {
5746                    write!(f, " ON {table_name}")?;
5747                };
5748                Ok(())
5749            }
5750            Statement::DropFunction(drop_function) => write!(f, "{drop_function}"),
5751            Statement::DropDomain(DropDomain {
5752                if_exists,
5753                name,
5754                drop_behavior,
5755            }) => {
5756                write!(
5757                    f,
5758                    "DROP DOMAIN{} {name}",
5759                    if *if_exists { " IF EXISTS" } else { "" },
5760                )?;
5761                if let Some(op) = drop_behavior {
5762                    write!(f, " {op}")?;
5763                }
5764                Ok(())
5765            }
5766            Statement::DropProcedure {
5767                if_exists,
5768                proc_desc,
5769                drop_behavior,
5770            } => {
5771                write!(
5772                    f,
5773                    "DROP PROCEDURE{} {}",
5774                    if *if_exists { " IF EXISTS" } else { "" },
5775                    display_comma_separated(proc_desc),
5776                )?;
5777                if let Some(op) = drop_behavior {
5778                    write!(f, " {op}")?;
5779                }
5780                Ok(())
5781            }
5782            Statement::DropSecret {
5783                if_exists,
5784                temporary,
5785                name,
5786                storage_specifier,
5787            } => {
5788                write!(f, "DROP ")?;
5789                if let Some(t) = temporary {
5790                    write!(f, "{}", if *t { "TEMPORARY " } else { "PERSISTENT " })?;
5791                }
5792                write!(
5793                    f,
5794                    "SECRET {if_exists}{name}",
5795                    if_exists = if *if_exists { "IF EXISTS " } else { "" },
5796                )?;
5797                if let Some(s) = storage_specifier {
5798                    write!(f, " FROM {s}")?;
5799                }
5800                Ok(())
5801            }
5802            Statement::DropPolicy(policy) => write!(f, "{policy}"),
5803            Statement::DropConnector { if_exists, name } => {
5804                write!(
5805                    f,
5806                    "DROP CONNECTOR {if_exists}{name}",
5807                    if_exists = if *if_exists { "IF EXISTS " } else { "" }
5808                )?;
5809                Ok(())
5810            }
5811            Statement::Discard { object_type } => {
5812                write!(f, "DISCARD {object_type}")?;
5813                Ok(())
5814            }
5815            Self::Set(set) => write!(f, "{set}"),
5816            Statement::ShowVariable { variable } => {
5817                write!(f, "SHOW")?;
5818                if !variable.is_empty() {
5819                    write!(f, " {}", display_separated(variable, " "))?;
5820                }
5821                Ok(())
5822            }
5823            Statement::ShowStatus {
5824                filter,
5825                global,
5826                session,
5827            } => {
5828                write!(f, "SHOW")?;
5829                if *global {
5830                    write!(f, " GLOBAL")?;
5831                }
5832                if *session {
5833                    write!(f, " SESSION")?;
5834                }
5835                write!(f, " STATUS")?;
5836                if let Some(filter) = filter {
5837                    write!(f, " {}", filter)?;
5838                }
5839                Ok(())
5840            }
5841            Statement::ShowVariables {
5842                filter,
5843                global,
5844                session,
5845            } => {
5846                write!(f, "SHOW")?;
5847                if *global {
5848                    write!(f, " GLOBAL")?;
5849                }
5850                if *session {
5851                    write!(f, " SESSION")?;
5852                }
5853                write!(f, " VARIABLES")?;
5854                if let Some(filter) = filter {
5855                    write!(f, " {}", filter)?;
5856                }
5857                Ok(())
5858            }
5859            Statement::ShowCreate { obj_type, obj_name } => {
5860                write!(f, "SHOW CREATE {obj_type} {obj_name}",)?;
5861                Ok(())
5862            }
5863            Statement::ShowColumns {
5864                extended,
5865                full,
5866                show_options,
5867            } => {
5868                write!(
5869                    f,
5870                    "SHOW {extended}{full}COLUMNS{show_options}",
5871                    extended = if *extended { "EXTENDED " } else { "" },
5872                    full = if *full { "FULL " } else { "" },
5873                )?;
5874                Ok(())
5875            }
5876            Statement::ShowDatabases {
5877                terse,
5878                history,
5879                show_options,
5880            } => {
5881                write!(
5882                    f,
5883                    "SHOW {terse}DATABASES{history}{show_options}",
5884                    terse = if *terse { "TERSE " } else { "" },
5885                    history = if *history { " HISTORY" } else { "" },
5886                )?;
5887                Ok(())
5888            }
5889            Statement::ShowCatalogs {
5890                terse,
5891                history,
5892                show_options,
5893            } => {
5894                write!(
5895                    f,
5896                    "SHOW {terse}CATALOGS{history}{show_options}",
5897                    terse = if *terse { "TERSE " } else { "" },
5898                    history = if *history { " HISTORY" } else { "" },
5899                )?;
5900                Ok(())
5901            }
5902            Statement::ShowProcessList { full } => {
5903                write!(
5904                    f,
5905                    "SHOW {full}PROCESSLIST",
5906                    full = if *full { "FULL " } else { "" },
5907                )?;
5908                Ok(())
5909            }
5910            Statement::ShowSchemas {
5911                terse,
5912                history,
5913                show_options,
5914            } => {
5915                write!(
5916                    f,
5917                    "SHOW {terse}SCHEMAS{history}{show_options}",
5918                    terse = if *terse { "TERSE " } else { "" },
5919                    history = if *history { " HISTORY" } else { "" },
5920                )?;
5921                Ok(())
5922            }
5923            Statement::ShowObjects(ShowObjects {
5924                terse,
5925                show_options,
5926            }) => {
5927                write!(
5928                    f,
5929                    "SHOW {terse}OBJECTS{show_options}",
5930                    terse = if *terse { "TERSE " } else { "" },
5931                )?;
5932                Ok(())
5933            }
5934            Statement::ShowTables {
5935                terse,
5936                history,
5937                extended,
5938                full,
5939                external,
5940                show_options,
5941            } => {
5942                write!(
5943                    f,
5944                    "SHOW {terse}{extended}{full}{external}TABLES{history}{show_options}",
5945                    terse = if *terse { "TERSE " } else { "" },
5946                    extended = if *extended { "EXTENDED " } else { "" },
5947                    full = if *full { "FULL " } else { "" },
5948                    external = if *external { "EXTERNAL " } else { "" },
5949                    history = if *history { " HISTORY" } else { "" },
5950                )?;
5951                Ok(())
5952            }
5953            Statement::ShowViews {
5954                terse,
5955                materialized,
5956                show_options,
5957            } => {
5958                write!(
5959                    f,
5960                    "SHOW {terse}{materialized}VIEWS{show_options}",
5961                    terse = if *terse { "TERSE " } else { "" },
5962                    materialized = if *materialized { "MATERIALIZED " } else { "" }
5963                )?;
5964                Ok(())
5965            }
5966            Statement::ShowFunctions { filter } => {
5967                write!(f, "SHOW FUNCTIONS")?;
5968                if let Some(filter) = filter {
5969                    write!(f, " {filter}")?;
5970                }
5971                Ok(())
5972            }
5973            Statement::Use(use_expr) => use_expr.fmt(f),
5974            Statement::ShowCollation { filter } => {
5975                write!(f, "SHOW COLLATION")?;
5976                if let Some(filter) = filter {
5977                    write!(f, " {filter}")?;
5978                }
5979                Ok(())
5980            }
5981            Statement::ShowCharset(show_stm) => show_stm.fmt(f),
5982            Statement::StartTransaction {
5983                modes,
5984                begin: syntax_begin,
5985                transaction,
5986                modifier,
5987                statements,
5988                exception,
5989                has_end_keyword,
5990            } => {
5991                if *syntax_begin {
5992                    if let Some(modifier) = *modifier {
5993                        write!(f, "BEGIN {modifier}")?;
5994                    } else {
5995                        write!(f, "BEGIN")?;
5996                    }
5997                } else {
5998                    write!(f, "START")?;
5999                }
6000                if let Some(transaction) = transaction {
6001                    write!(f, " {transaction}")?;
6002                }
6003                if !modes.is_empty() {
6004                    write!(f, " {}", display_comma_separated(modes))?;
6005                }
6006                if !statements.is_empty() {
6007                    write!(f, " ")?;
6008                    format_statement_list(f, statements)?;
6009                }
6010                if let Some(exception_when) = exception {
6011                    write!(f, " EXCEPTION")?;
6012                    for when in exception_when {
6013                        write!(f, " {when}")?;
6014                    }
6015                }
6016                if *has_end_keyword {
6017                    write!(f, " END")?;
6018                }
6019                Ok(())
6020            }
6021            Statement::Commit {
6022                chain,
6023                end: end_syntax,
6024                modifier,
6025            } => {
6026                if *end_syntax {
6027                    write!(f, "END")?;
6028                    if let Some(modifier) = *modifier {
6029                        write!(f, " {modifier}")?;
6030                    }
6031                    if *chain {
6032                        write!(f, " AND CHAIN")?;
6033                    }
6034                } else {
6035                    write!(f, "COMMIT{}", if *chain { " AND CHAIN" } else { "" })?;
6036                }
6037                Ok(())
6038            }
6039            Statement::Rollback { chain, savepoint } => {
6040                write!(f, "ROLLBACK")?;
6041
6042                if *chain {
6043                    write!(f, " AND CHAIN")?;
6044                }
6045
6046                if let Some(savepoint) = savepoint {
6047                    write!(f, " TO SAVEPOINT {savepoint}")?;
6048                }
6049
6050                Ok(())
6051            }
6052            Statement::CreateSchema {
6053                schema_name,
6054                or_replace,
6055                if_not_exists,
6056                with,
6057                options,
6058                default_collate_spec,
6059                clone,
6060            } => {
6061                write!(
6062                    f,
6063                    "CREATE {or_replace}SCHEMA {if_not_exists}{name}",
6064                    or_replace = if *or_replace { "OR REPLACE " } else { "" },
6065                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
6066                    name = schema_name
6067                )?;
6068
6069                if let Some(collate) = default_collate_spec {
6070                    write!(f, " DEFAULT COLLATE {collate}")?;
6071                }
6072
6073                if let Some(with) = with {
6074                    write!(f, " WITH ({})", display_comma_separated(with))?;
6075                }
6076
6077                if let Some(options) = options {
6078                    write!(f, " OPTIONS({})", display_comma_separated(options))?;
6079                }
6080
6081                if let Some(clone) = clone {
6082                    write!(f, " CLONE {clone}")?;
6083                }
6084                Ok(())
6085            }
6086            Statement::Assert { condition, message } => {
6087                write!(f, "ASSERT {condition}")?;
6088                if let Some(m) = message {
6089                    write!(f, " AS {m}")?;
6090                }
6091                Ok(())
6092            }
6093            Statement::Grant(grant) => write!(f, "{grant}"),
6094            Statement::Deny(s) => write!(f, "{s}"),
6095            Statement::Revoke(revoke) => write!(f, "{revoke}"),
6096            Statement::Deallocate { name, prepare } => write!(
6097                f,
6098                "DEALLOCATE {prepare}{name}",
6099                prepare = if *prepare { "PREPARE " } else { "" },
6100                name = name,
6101            ),
6102            Statement::Execute {
6103                name,
6104                parameters,
6105                has_parentheses,
6106                immediate,
6107                into,
6108                using,
6109                output,
6110                default,
6111            } => {
6112                let (open, close) = if *has_parentheses {
6113                    // Space before `(` only when there is no name directly preceding it.
6114                    (if name.is_some() { "(" } else { " (" }, ")")
6115                } else {
6116                    (if parameters.is_empty() { "" } else { " " }, "")
6117                };
6118                write!(f, "EXECUTE")?;
6119                if *immediate {
6120                    write!(f, " IMMEDIATE")?;
6121                }
6122                if let Some(name) = name {
6123                    write!(f, " {name}")?;
6124                }
6125                write!(f, "{open}{}{close}", display_comma_separated(parameters),)?;
6126                if !into.is_empty() {
6127                    write!(f, " INTO {}", display_comma_separated(into))?;
6128                }
6129                if !using.is_empty() {
6130                    write!(f, " USING {}", display_comma_separated(using))?;
6131                };
6132                if *output {
6133                    write!(f, " OUTPUT")?;
6134                }
6135                if *default {
6136                    write!(f, " DEFAULT")?;
6137                }
6138                Ok(())
6139            }
6140            Statement::Prepare {
6141                name,
6142                data_types,
6143                statement,
6144            } => {
6145                write!(f, "PREPARE {name} ")?;
6146                if !data_types.is_empty() {
6147                    write!(f, "({}) ", display_comma_separated(data_types))?;
6148                }
6149                write!(f, "AS {statement}")
6150            }
6151            Statement::Comment {
6152                object_type,
6153                object_name,
6154                comment,
6155                if_exists,
6156            } => {
6157                write!(f, "COMMENT ")?;
6158                if *if_exists {
6159                    write!(f, "IF EXISTS ")?
6160                };
6161                write!(f, "ON {object_type} {object_name} IS ")?;
6162                if let Some(c) = comment {
6163                    write!(f, "'{c}'")
6164                } else {
6165                    write!(f, "NULL")
6166                }
6167            }
6168            Statement::Savepoint { name } => {
6169                write!(f, "SAVEPOINT ")?;
6170                write!(f, "{name}")
6171            }
6172            Statement::ReleaseSavepoint { name } => {
6173                write!(f, "RELEASE SAVEPOINT {name}")
6174            }
6175            Statement::Merge(merge) => merge.fmt(f),
6176            Statement::Cache {
6177                table_name,
6178                table_flag,
6179                has_as,
6180                options,
6181                query,
6182            } => {
6183                if let Some(table_flag) = table_flag {
6184                    write!(f, "CACHE {table_flag} TABLE {table_name}")?;
6185                } else {
6186                    write!(f, "CACHE TABLE {table_name}")?;
6187                }
6188
6189                if !options.is_empty() {
6190                    write!(f, " OPTIONS({})", display_comma_separated(options))?;
6191                }
6192
6193                match (*has_as, query) {
6194                    (true, Some(query)) => write!(f, " AS {query}"),
6195                    (true, None) => f.write_str(" AS"),
6196                    (false, Some(query)) => write!(f, " {query}"),
6197                    (false, None) => Ok(()),
6198                }
6199            }
6200            Statement::UNCache {
6201                table_name,
6202                if_exists,
6203            } => {
6204                if *if_exists {
6205                    write!(f, "UNCACHE TABLE IF EXISTS {table_name}")
6206                } else {
6207                    write!(f, "UNCACHE TABLE {table_name}")
6208                }
6209            }
6210            Statement::CreateSequence {
6211                temporary,
6212                if_not_exists,
6213                name,
6214                data_type,
6215                sequence_options,
6216                owned_by,
6217            } => {
6218                let as_type: String = if let Some(dt) = data_type.as_ref() {
6219                    //Cannot use format!(" AS {}", dt), due to format! is not available in --target thumbv6m-none-eabi
6220                    // " AS ".to_owned() + &dt.to_string()
6221                    [" AS ", &dt.to_string()].concat()
6222                } else {
6223                    "".to_string()
6224                };
6225                write!(
6226                    f,
6227                    "CREATE {temporary}SEQUENCE {if_not_exists}{name}{as_type}",
6228                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
6229                    temporary = if *temporary { "TEMPORARY " } else { "" },
6230                    name = name,
6231                    as_type = as_type
6232                )?;
6233                for sequence_option in sequence_options {
6234                    write!(f, "{sequence_option}")?;
6235                }
6236                if let Some(ob) = owned_by.as_ref() {
6237                    write!(f, " OWNED BY {ob}")?;
6238                }
6239                write!(f, "")
6240            }
6241            Statement::CreateStage {
6242                or_replace,
6243                temporary,
6244                if_not_exists,
6245                name,
6246                stage_params,
6247                directory_table_params,
6248                file_format,
6249                copy_options,
6250                comment,
6251                ..
6252            } => {
6253                write!(
6254                    f,
6255                    "CREATE {or_replace}{temp}STAGE {if_not_exists}{name}{stage_params}",
6256                    temp = if *temporary { "TEMPORARY " } else { "" },
6257                    or_replace = if *or_replace { "OR REPLACE " } else { "" },
6258                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
6259                )?;
6260                if !directory_table_params.options.is_empty() {
6261                    write!(f, " DIRECTORY=({directory_table_params})")?;
6262                }
6263                if !file_format.options.is_empty() {
6264                    write!(f, " FILE_FORMAT=({file_format})")?;
6265                }
6266                if !copy_options.options.is_empty() {
6267                    write!(f, " COPY_OPTIONS=({copy_options})")?;
6268                }
6269                if let Some(comment) = comment {
6270                    write!(f, " COMMENT='{}'", comment)?;
6271                }
6272                Ok(())
6273            }
6274            Statement::CreateFileFormat {
6275                or_replace,
6276                temporary,
6277                volatile,
6278                if_not_exists,
6279                name,
6280                options,
6281                comment,
6282            } => {
6283                write!(
6284                    f,
6285                    "CREATE {or_replace}{temp}{volatile}FILE FORMAT {if_not_exists}{name}",
6286                    or_replace = if *or_replace { "OR REPLACE " } else { "" },
6287                    temp = if *temporary { "TEMPORARY " } else { "" },
6288                    volatile = if *volatile { "VOLATILE " } else { "" },
6289                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
6290                )?;
6291                if !options.options.is_empty() {
6292                    write!(f, " {options}")?;
6293                }
6294                if let Some(comment) = comment {
6295                    write!(f, " COMMENT='{}'", comment)?;
6296                }
6297                Ok(())
6298            }
6299            Statement::CreateWarehouse(s) => write!(f, "{s}"),
6300            Statement::CopyIntoSnowflake {
6301                kind,
6302                into,
6303                into_columns,
6304                from_obj,
6305                from_obj_alias,
6306                stage_params,
6307                from_transformations,
6308                from_query,
6309                files,
6310                pattern,
6311                file_format,
6312                copy_options,
6313                validation_mode,
6314                partition,
6315            } => {
6316                write!(f, "COPY INTO {into}")?;
6317                if let Some(into_columns) = into_columns {
6318                    write!(f, " ({})", display_comma_separated(into_columns))?;
6319                }
6320                if let Some(from_transformations) = from_transformations {
6321                    // Data load with transformation
6322                    if let Some(from_stage) = from_obj {
6323                        write!(
6324                            f,
6325                            " FROM (SELECT {} FROM {}{}",
6326                            display_separated(from_transformations, ", "),
6327                            from_stage,
6328                            stage_params
6329                        )?;
6330                    }
6331                    if let Some(from_obj_alias) = from_obj_alias {
6332                        write!(f, " AS {from_obj_alias}")?;
6333                    }
6334                    write!(f, ")")?;
6335                } else if let Some(from_obj) = from_obj {
6336                    // Standard data load
6337                    write!(f, " FROM {from_obj}{stage_params}")?;
6338                    if let Some(from_obj_alias) = from_obj_alias {
6339                        write!(f, " AS {from_obj_alias}")?;
6340                    }
6341                } else if let Some(from_query) = from_query {
6342                    // Data unload from query
6343                    write!(f, " FROM ({from_query})")?;
6344                }
6345
6346                if let Some(files) = files {
6347                    write!(f, " FILES = ('{}')", display_separated(files, "', '"))?;
6348                }
6349                if let Some(pattern) = pattern {
6350                    write!(f, " PATTERN = '{pattern}'")?;
6351                }
6352                if let Some(partition) = partition {
6353                    write!(f, " PARTITION BY {partition}")?;
6354                }
6355                if !file_format.options.is_empty() {
6356                    write!(f, " FILE_FORMAT=({file_format})")?;
6357                }
6358                if !copy_options.options.is_empty() {
6359                    match kind {
6360                        CopyIntoSnowflakeKind::Table => {
6361                            write!(f, " COPY_OPTIONS=({copy_options})")?
6362                        }
6363                        CopyIntoSnowflakeKind::Location => write!(f, " {copy_options}")?,
6364                    }
6365                }
6366                if let Some(validation_mode) = validation_mode {
6367                    write!(f, " VALIDATION_MODE = {validation_mode}")?;
6368                }
6369                Ok(())
6370            }
6371            Statement::CreateType {
6372                name,
6373                representation,
6374            } => {
6375                write!(f, "CREATE TYPE {name}")?;
6376                if let Some(repr) = representation {
6377                    write!(f, " {repr}")?;
6378                }
6379                Ok(())
6380            }
6381            Statement::Pragma { name, value, is_eq } => {
6382                write!(f, "PRAGMA {name}")?;
6383                if let Some(value) = value {
6384                    if *is_eq {
6385                        write!(f, " = {value}")?;
6386                    } else {
6387                        write!(f, "({value})")?;
6388                    }
6389                }
6390                Ok(())
6391            }
6392            Statement::Lock(lock) => lock.fmt(f),
6393            Statement::LockTables { tables } => {
6394                write!(f, "LOCK TABLES {}", display_comma_separated(tables))
6395            }
6396            Statement::UnlockTables => {
6397                write!(f, "UNLOCK TABLES")
6398            }
6399            Statement::Unload {
6400                query,
6401                query_text,
6402                to,
6403                auth,
6404                with,
6405                options,
6406            } => {
6407                write!(f, "UNLOAD(")?;
6408                if let Some(query) = query {
6409                    write!(f, "{query}")?;
6410                }
6411                if let Some(query_text) = query_text {
6412                    write!(f, "'{query_text}'")?;
6413                }
6414                write!(f, ") TO {to}")?;
6415                if let Some(auth) = auth {
6416                    write!(f, " IAM_ROLE {auth}")?;
6417                }
6418                if !with.is_empty() {
6419                    write!(f, " WITH ({})", display_comma_separated(with))?;
6420                }
6421                if !options.is_empty() {
6422                    write!(f, " {}", display_separated(options, " "))?;
6423                }
6424                Ok(())
6425            }
6426            Statement::OptimizeTable {
6427                name,
6428                has_table_keyword,
6429                on_cluster,
6430                partition,
6431                include_final,
6432                deduplicate,
6433                predicate,
6434                zorder,
6435            } => {
6436                write!(f, "OPTIMIZE")?;
6437                if *has_table_keyword {
6438                    write!(f, " TABLE")?;
6439                }
6440                write!(f, " {name}")?;
6441                if let Some(on_cluster) = on_cluster {
6442                    write!(f, " ON CLUSTER {on_cluster}")?;
6443                }
6444                if let Some(partition) = partition {
6445                    write!(f, " {partition}")?;
6446                }
6447                if *include_final {
6448                    write!(f, " FINAL")?;
6449                }
6450                if let Some(deduplicate) = deduplicate {
6451                    write!(f, " {deduplicate}")?;
6452                }
6453                if let Some(predicate) = predicate {
6454                    write!(f, " WHERE {predicate}")?;
6455                }
6456                if let Some(zorder) = zorder {
6457                    write!(f, " ZORDER BY ({})", display_comma_separated(zorder))?;
6458                }
6459                Ok(())
6460            }
6461            Statement::LISTEN { channel } => {
6462                write!(f, "LISTEN {channel}")?;
6463                Ok(())
6464            }
6465            Statement::UNLISTEN { channel } => {
6466                write!(f, "UNLISTEN {channel}")?;
6467                Ok(())
6468            }
6469            Statement::NOTIFY { channel, payload } => {
6470                write!(f, "NOTIFY {channel}")?;
6471                if let Some(payload) = payload {
6472                    write!(f, ", '{payload}'")?;
6473                }
6474                Ok(())
6475            }
6476            Statement::RenameTable(rename_tables) => {
6477                write!(f, "RENAME TABLE {}", display_comma_separated(rename_tables))
6478            }
6479            Statement::RaisError {
6480                message,
6481                severity,
6482                state,
6483                arguments,
6484                options,
6485            } => {
6486                write!(f, "RAISERROR({message}, {severity}, {state}")?;
6487                if !arguments.is_empty() {
6488                    write!(f, ", {}", display_comma_separated(arguments))?;
6489                }
6490                write!(f, ")")?;
6491                if !options.is_empty() {
6492                    write!(f, " WITH {}", display_comma_separated(options))?;
6493                }
6494                Ok(())
6495            }
6496            Statement::Throw(s) => write!(f, "{s}"),
6497            Statement::Print(s) => write!(f, "{s}"),
6498            Statement::WaitFor(s) => write!(f, "{s}"),
6499            Statement::Return(r) => write!(f, "{r}"),
6500            Statement::List(command) => write!(f, "LIST {command}"),
6501            Statement::Put {
6502                source,
6503                stage,
6504                options,
6505            } => {
6506                write!(f, "PUT '{source}' {stage}")?;
6507                if !options.options.is_empty() {
6508                    write!(f, " {options}")?;
6509                }
6510                Ok(())
6511            }
6512            Statement::Remove(command) => write!(f, "REMOVE {command}"),
6513            Statement::ExportData(e) => write!(f, "{e}"),
6514            Statement::CreateUser(s) => write!(f, "{s}"),
6515            Statement::AlterSchema(s) => write!(f, "{s}"),
6516            Statement::Vacuum(s) => write!(f, "{s}"),
6517            Statement::AlterUser(s) => write!(f, "{s}"),
6518            Statement::Reset(s) => write!(f, "{s}"),
6519        }
6520    }
6521}
6522
6523/// Can use to describe options in create sequence or table column type identity
6524/// ```sql
6525/// [ INCREMENT [ BY ] increment ]
6526///     [ MINVALUE minvalue | NO MINVALUE ] [ MAXVALUE maxvalue | NO MAXVALUE ]
6527///     [ START [ WITH ] start ] [ CACHE cache ] [ [ NO ] CYCLE ]
6528/// ```
6529#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6530#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6531#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6532pub enum SequenceOptions {
6533    /// `INCREMENT [BY] <expr>` option; second value indicates presence of `BY` keyword.
6534    IncrementBy(Expr, bool),
6535    /// `MINVALUE <expr>` or `NO MINVALUE`.
6536    MinValue(Option<Expr>),
6537    /// `MAXVALUE <expr>` or `NO MAXVALUE`.
6538    MaxValue(Option<Expr>),
6539    /// `START [WITH] <expr>`; second value indicates presence of `WITH`.
6540    StartWith(Expr, bool),
6541    /// `CACHE <expr>` option.
6542    Cache(Expr),
6543    /// `CYCLE` or `NO CYCLE` option.
6544    Cycle(bool),
6545}
6546
6547impl fmt::Display for SequenceOptions {
6548    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6549        match self {
6550            SequenceOptions::IncrementBy(increment, by) => {
6551                write!(
6552                    f,
6553                    " INCREMENT{by} {increment}",
6554                    by = if *by { " BY" } else { "" },
6555                    increment = increment
6556                )
6557            }
6558            SequenceOptions::MinValue(Some(expr)) => {
6559                write!(f, " MINVALUE {expr}")
6560            }
6561            SequenceOptions::MinValue(None) => {
6562                write!(f, " NO MINVALUE")
6563            }
6564            SequenceOptions::MaxValue(Some(expr)) => {
6565                write!(f, " MAXVALUE {expr}")
6566            }
6567            SequenceOptions::MaxValue(None) => {
6568                write!(f, " NO MAXVALUE")
6569            }
6570            SequenceOptions::StartWith(start, with) => {
6571                write!(
6572                    f,
6573                    " START{with} {start}",
6574                    with = if *with { " WITH" } else { "" },
6575                    start = start
6576                )
6577            }
6578            SequenceOptions::Cache(cache) => {
6579                write!(f, " CACHE {}", *cache)
6580            }
6581            SequenceOptions::Cycle(no) => {
6582                write!(f, " {}CYCLE", if *no { "NO " } else { "" })
6583            }
6584        }
6585    }
6586}
6587
6588/// Assignment for a `SET` statement (name [=|TO] value)
6589#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6590#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6591#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6592pub struct SetAssignment {
6593    /// Optional context scope (e.g., SESSION or LOCAL).
6594    pub scope: Option<ContextModifier>,
6595    /// Assignment target name.
6596    pub name: ObjectName,
6597    /// Assigned expression value.
6598    pub value: Expr,
6599}
6600
6601impl fmt::Display for SetAssignment {
6602    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6603        write!(
6604            f,
6605            "{}{} = {}",
6606            self.scope.map(|s| format!("{s}")).unwrap_or_default(),
6607            self.name,
6608            self.value
6609        )
6610    }
6611}
6612
6613/// Target of a `TRUNCATE TABLE` command
6614///
6615/// Note this is its own struct because `visit_relation` requires an `ObjectName` (not a `Vec<ObjectName>`)
6616#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6617#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6618#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6619pub struct TruncateTableTarget {
6620    /// name of the table being truncated
6621    #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
6622    pub name: ObjectName,
6623    /// Postgres-specific option: explicitly exclude descendants (also default without ONLY)
6624    /// ```sql
6625    /// TRUNCATE TABLE ONLY name
6626    /// ```
6627    /// <https://www.postgresql.org/docs/current/sql-truncate.html>
6628    pub only: bool,
6629    /// Postgres-specific option: asterisk after table name to explicitly indicate descendants
6630    /// ```sql
6631    /// TRUNCATE TABLE name [ * ]
6632    /// ```
6633    /// <https://www.postgresql.org/docs/current/sql-truncate.html>
6634    pub has_asterisk: bool,
6635}
6636
6637impl fmt::Display for TruncateTableTarget {
6638    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6639        if self.only {
6640            write!(f, "ONLY ")?;
6641        };
6642        write!(f, "{}", self.name)?;
6643        if self.has_asterisk {
6644            write!(f, " *")?;
6645        };
6646        Ok(())
6647    }
6648}
6649
6650/// A `LOCK` statement.
6651///
6652/// See <https://www.postgresql.org/docs/current/sql-lock.html>
6653#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6654#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6655#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6656pub struct Lock {
6657    /// List of tables to lock.
6658    pub tables: Vec<LockTableTarget>,
6659    /// Lock mode.
6660    pub lock_mode: Option<LockTableMode>,
6661    /// Whether `NOWAIT` was specified.
6662    pub nowait: bool,
6663}
6664
6665impl fmt::Display for Lock {
6666    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6667        write!(f, "LOCK TABLE {}", display_comma_separated(&self.tables))?;
6668        if let Some(lock_mode) = &self.lock_mode {
6669            write!(f, " IN {lock_mode} MODE")?;
6670        }
6671        if self.nowait {
6672            write!(f, " NOWAIT")?;
6673        }
6674        Ok(())
6675    }
6676}
6677
6678/// Target of a `LOCK TABLE` command
6679///
6680/// See <https://www.postgresql.org/docs/current/sql-lock.html>
6681#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6682#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6683#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6684pub struct LockTableTarget {
6685    /// Name of the table being locked.
6686    #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
6687    pub name: ObjectName,
6688    /// Whether `ONLY` was specified to exclude descendant tables.
6689    pub only: bool,
6690    /// Whether `*` was specified to explicitly include descendant tables.
6691    pub has_asterisk: bool,
6692}
6693
6694impl fmt::Display for LockTableTarget {
6695    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6696        if self.only {
6697            write!(f, "ONLY ")?;
6698        }
6699        write!(f, "{}", self.name)?;
6700        if self.has_asterisk {
6701            write!(f, " *")?;
6702        }
6703        Ok(())
6704    }
6705}
6706
6707/// PostgreSQL lock modes for `LOCK TABLE`.
6708///
6709/// See <https://www.postgresql.org/docs/current/sql-lock.html>
6710#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6711#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6712#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6713pub enum LockTableMode {
6714    /// `ACCESS SHARE`
6715    AccessShare,
6716    /// `ROW SHARE`
6717    RowShare,
6718    /// `ROW EXCLUSIVE`
6719    RowExclusive,
6720    /// `SHARE UPDATE EXCLUSIVE`
6721    ShareUpdateExclusive,
6722    /// `SHARE`
6723    Share,
6724    /// `SHARE ROW EXCLUSIVE`
6725    ShareRowExclusive,
6726    /// `EXCLUSIVE`
6727    Exclusive,
6728    /// `ACCESS EXCLUSIVE`
6729    AccessExclusive,
6730}
6731
6732impl fmt::Display for LockTableMode {
6733    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
6734        let text = match self {
6735            Self::AccessShare => "ACCESS SHARE",
6736            Self::RowShare => "ROW SHARE",
6737            Self::RowExclusive => "ROW EXCLUSIVE",
6738            Self::ShareUpdateExclusive => "SHARE UPDATE EXCLUSIVE",
6739            Self::Share => "SHARE",
6740            Self::ShareRowExclusive => "SHARE ROW EXCLUSIVE",
6741            Self::Exclusive => "EXCLUSIVE",
6742            Self::AccessExclusive => "ACCESS EXCLUSIVE",
6743        };
6744        write!(f, "{text}")
6745    }
6746}
6747
6748/// PostgreSQL identity option for TRUNCATE table
6749/// [ RESTART IDENTITY | CONTINUE IDENTITY ]
6750#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6751#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6752#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6753pub enum TruncateIdentityOption {
6754    /// Restart identity values (RESTART IDENTITY).
6755    Restart,
6756    /// Continue identity values (CONTINUE IDENTITY).
6757    Continue,
6758}
6759
6760/// Cascade/restrict option for Postgres TRUNCATE table, MySQL GRANT/REVOKE, etc.
6761/// [ CASCADE | RESTRICT ]
6762#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6763#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6764#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6765pub enum CascadeOption {
6766    /// Apply cascading action (e.g., CASCADE).
6767    Cascade,
6768    /// Restrict the action (e.g., RESTRICT).
6769    Restrict,
6770}
6771
6772impl Display for CascadeOption {
6773    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6774        match self {
6775            CascadeOption::Cascade => write!(f, "CASCADE"),
6776            CascadeOption::Restrict => write!(f, "RESTRICT"),
6777        }
6778    }
6779}
6780
6781/// Transaction started with [ TRANSACTION | WORK | TRAN ]
6782#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6783#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6784#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6785pub enum BeginTransactionKind {
6786    /// Standard `TRANSACTION` keyword.
6787    Transaction,
6788    /// Alternate `WORK` keyword.
6789    Work,
6790    /// MSSQL shorthand `TRAN` keyword.
6791    /// See <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/begin-transaction-transact-sql>
6792    Tran,
6793}
6794
6795impl Display for BeginTransactionKind {
6796    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6797        match self {
6798            BeginTransactionKind::Transaction => write!(f, "TRANSACTION"),
6799            BeginTransactionKind::Work => write!(f, "WORK"),
6800            BeginTransactionKind::Tran => write!(f, "TRAN"),
6801        }
6802    }
6803}
6804
6805/// Can use to describe options in  create sequence or table column type identity
6806/// [ MINVALUE minvalue | NO MINVALUE ] [ MAXVALUE maxvalue | NO MAXVALUE ]
6807#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6808#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6809#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6810pub enum MinMaxValue {
6811    /// Clause is not specified.
6812    Empty,
6813    /// NO MINVALUE / NO MAXVALUE.
6814    None,
6815    /// `MINVALUE <expr>` / `MAXVALUE <expr>`.
6816    Some(Expr),
6817}
6818
6819#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6820#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6821#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6822#[non_exhaustive]
6823/// Behavior to apply for `INSERT` when a conflict occurs.
6824pub enum OnInsert {
6825    /// ON DUPLICATE KEY UPDATE (MySQL when the key already exists, then execute an update instead)
6826    DuplicateKeyUpdate(Vec<Assignment>),
6827    /// ON CONFLICT is a PostgreSQL and Sqlite extension
6828    OnConflict(OnConflict),
6829}
6830
6831#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6832#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6833#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6834/// Optional aliases for `INSERT` targets: row alias and optional column aliases.
6835pub struct InsertAliases {
6836    /// Row alias (table-style alias) for the inserted values.
6837    pub row_alias: ObjectName,
6838    /// Optional list of column aliases for the inserted values.
6839    pub col_aliases: Option<Vec<Ident>>,
6840}
6841
6842#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6843#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6844#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6845/// Optional alias for an `INSERT` table; i.e. the table to be inserted into
6846pub struct TableAliasWithoutColumns {
6847    /// `true` if the aliases was explicitly introduced with the "AS" keyword
6848    pub explicit: bool,
6849    /// the alias name itself
6850    pub alias: Ident,
6851}
6852
6853#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6854#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6855#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6856/// `ON CONFLICT` clause representation.
6857pub struct OnConflict {
6858    /// Optional conflict target specifying columns or constraint.
6859    pub conflict_target: Option<ConflictTarget>,
6860    /// Action to take when a conflict occurs.
6861    pub action: OnConflictAction,
6862}
6863#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6864#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6865#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6866/// Target specification for an `ON CONFLICT` clause.
6867pub enum ConflictTarget {
6868    /// Target specified as a list of columns.
6869    Columns(Vec<Ident>),
6870    /// Target specified as a named constraint.
6871    OnConstraint(ObjectName),
6872}
6873#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6874#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6875#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6876/// Action to perform when an `ON CONFLICT` target is matched.
6877pub enum OnConflictAction {
6878    /// Do nothing on conflict.
6879    DoNothing,
6880    /// Perform an update on conflict.
6881    DoUpdate(DoUpdate),
6882}
6883
6884#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6885#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6886#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6887/// Details for `DO UPDATE` action of an `ON CONFLICT` clause.
6888pub struct DoUpdate {
6889    /// Column assignments to perform on update.
6890    pub assignments: Vec<Assignment>,
6891    /// Optional WHERE clause limiting the update.
6892    pub selection: Option<Expr>,
6893}
6894
6895impl fmt::Display for OnInsert {
6896    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6897        match self {
6898            Self::DuplicateKeyUpdate(expr) => write!(
6899                f,
6900                " ON DUPLICATE KEY UPDATE {}",
6901                display_comma_separated(expr)
6902            ),
6903            Self::OnConflict(o) => write!(f, "{o}"),
6904        }
6905    }
6906}
6907impl fmt::Display for OnConflict {
6908    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6909        write!(f, " ON CONFLICT")?;
6910        if let Some(target) = &self.conflict_target {
6911            write!(f, "{target}")?;
6912        }
6913        write!(f, " {}", self.action)
6914    }
6915}
6916impl fmt::Display for ConflictTarget {
6917    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6918        match self {
6919            ConflictTarget::Columns(cols) => write!(f, "({})", display_comma_separated(cols)),
6920            ConflictTarget::OnConstraint(name) => write!(f, " ON CONSTRAINT {name}"),
6921        }
6922    }
6923}
6924impl fmt::Display for OnConflictAction {
6925    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6926        match self {
6927            Self::DoNothing => write!(f, "DO NOTHING"),
6928            Self::DoUpdate(do_update) => {
6929                write!(f, "DO UPDATE")?;
6930                if !do_update.assignments.is_empty() {
6931                    write!(
6932                        f,
6933                        " SET {}",
6934                        display_comma_separated(&do_update.assignments)
6935                    )?;
6936                }
6937                if let Some(selection) = &do_update.selection {
6938                    write!(f, " WHERE {selection}")?;
6939                }
6940                Ok(())
6941            }
6942        }
6943    }
6944}
6945
6946/// Privileges granted in a GRANT statement or revoked in a REVOKE statement.
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 Privileges {
6951    /// All privileges applicable to the object type
6952    All {
6953        /// Optional keyword from the spec, ignored in practice
6954        with_privileges_keyword: bool,
6955    },
6956    /// Specific privileges (e.g. `SELECT`, `INSERT`)
6957    Actions(Vec<Action>),
6958}
6959
6960impl fmt::Display for Privileges {
6961    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6962        match self {
6963            Privileges::All {
6964                with_privileges_keyword,
6965            } => {
6966                write!(
6967                    f,
6968                    "ALL{}",
6969                    if *with_privileges_keyword {
6970                        " PRIVILEGES"
6971                    } else {
6972                        ""
6973                    }
6974                )
6975            }
6976            Privileges::Actions(actions) => {
6977                write!(f, "{}", display_comma_separated(actions))
6978            }
6979        }
6980    }
6981}
6982
6983/// Specific direction for FETCH statement
6984#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6985#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6986#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6987pub enum FetchDirection {
6988    /// Fetch a specific count of rows.
6989    Count {
6990        /// The limit value for the count.
6991        limit: ValueWithSpan,
6992    },
6993    /// Fetch the next row.
6994    Next,
6995    /// Fetch the prior row.
6996    Prior,
6997    /// Fetch the first row.
6998    First,
6999    /// Fetch the last row.
7000    Last,
7001    /// Fetch an absolute row by index.
7002    Absolute {
7003        /// The absolute index value.
7004        limit: ValueWithSpan,
7005    },
7006    /// Fetch a row relative to the current position.
7007    Relative {
7008        /// The relative offset value.
7009        limit: ValueWithSpan,
7010    },
7011    /// Fetch all rows.
7012    All,
7013    // FORWARD
7014    // FORWARD count
7015    /// Fetch forward by an optional limit.
7016    Forward {
7017        /// Optional forward limit.
7018        limit: Option<ValueWithSpan>,
7019    },
7020    /// Fetch all forward rows.
7021    ForwardAll,
7022    // BACKWARD
7023    // BACKWARD count
7024    /// Fetch backward by an optional limit.
7025    Backward {
7026        /// Optional backward limit.
7027        limit: Option<ValueWithSpan>,
7028    },
7029    /// Fetch all backward rows.
7030    BackwardAll,
7031}
7032
7033impl fmt::Display for FetchDirection {
7034    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7035        match self {
7036            FetchDirection::Count { limit } => f.write_str(&limit.to_string())?,
7037            FetchDirection::Next => f.write_str("NEXT")?,
7038            FetchDirection::Prior => f.write_str("PRIOR")?,
7039            FetchDirection::First => f.write_str("FIRST")?,
7040            FetchDirection::Last => f.write_str("LAST")?,
7041            FetchDirection::Absolute { limit } => {
7042                f.write_str("ABSOLUTE ")?;
7043                f.write_str(&limit.to_string())?;
7044            }
7045            FetchDirection::Relative { limit } => {
7046                f.write_str("RELATIVE ")?;
7047                f.write_str(&limit.to_string())?;
7048            }
7049            FetchDirection::All => f.write_str("ALL")?,
7050            FetchDirection::Forward { limit } => {
7051                f.write_str("FORWARD")?;
7052
7053                if let Some(l) = limit {
7054                    f.write_str(" ")?;
7055                    f.write_str(&l.to_string())?;
7056                }
7057            }
7058            FetchDirection::ForwardAll => f.write_str("FORWARD ALL")?,
7059            FetchDirection::Backward { limit } => {
7060                f.write_str("BACKWARD")?;
7061
7062                if let Some(l) = limit {
7063                    f.write_str(" ")?;
7064                    f.write_str(&l.to_string())?;
7065                }
7066            }
7067            FetchDirection::BackwardAll => f.write_str("BACKWARD ALL")?,
7068        };
7069
7070        Ok(())
7071    }
7072}
7073
7074/// The "position" for a FETCH statement.
7075///
7076/// [MsSql](https://learn.microsoft.com/en-us/sql/t-sql/language-elements/fetch-transact-sql)
7077#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7078#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7079#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7080pub enum FetchPosition {
7081    /// Use `FROM <pos>` position specifier.
7082    From,
7083    /// Use `IN <pos>` position specifier.
7084    In,
7085}
7086
7087impl fmt::Display for FetchPosition {
7088    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7089        match self {
7090            FetchPosition::From => f.write_str("FROM")?,
7091            FetchPosition::In => f.write_str("IN")?,
7092        };
7093
7094        Ok(())
7095    }
7096}
7097
7098/// A privilege on a database object (table, sequence, etc.).
7099#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7100#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7101#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7102pub enum Action {
7103    /// Add a search optimization.
7104    AddSearchOptimization,
7105    /// Apply an `APPLY` operation with a specific type.
7106    Apply {
7107        /// The type of apply operation.
7108        apply_type: ActionApplyType,
7109    },
7110    /// Apply a budget operation.
7111    ApplyBudget,
7112    /// Attach a listing.
7113    AttachListing,
7114    /// Attach a policy.
7115    AttachPolicy,
7116    /// Audit operation.
7117    Audit,
7118    /// Bind a service endpoint.
7119    BindServiceEndpoint,
7120    /// Connect permission.
7121    Connect,
7122    /// Create action, optionally specifying an object type.
7123    Create {
7124        /// Optional object type to create.
7125        obj_type: Option<ActionCreateObjectType>,
7126    },
7127    /// Actions related to database roles.
7128    DatabaseRole {
7129        /// The role name.
7130        role: ObjectName,
7131    },
7132    /// Delete permission.
7133    Delete,
7134    /// Drop permission.
7135    Drop,
7136    /// Evolve schema permission.
7137    EvolveSchema,
7138    /// Exec action (execute) with optional object type.
7139    Exec {
7140        /// Optional execute object type.
7141        obj_type: Option<ActionExecuteObjectType>,
7142    },
7143    /// Execute action with optional object type.
7144    Execute {
7145        /// Optional execute object type.
7146        obj_type: Option<ActionExecuteObjectType>,
7147    },
7148    /// Failover operation.
7149    Failover,
7150    /// Use imported privileges.
7151    ImportedPrivileges,
7152    /// Import a share.
7153    ImportShare,
7154    /// Insert rows with optional column list.
7155    Insert {
7156        /// Optional list of target columns for insert.
7157        columns: Option<Vec<Ident>>,
7158    },
7159    /// Manage operation with a specific manage type.
7160    Manage {
7161        /// The specific manage sub-type.
7162        manage_type: ActionManageType,
7163    },
7164    /// Manage releases.
7165    ManageReleases,
7166    /// Manage versions.
7167    ManageVersions,
7168    /// Modify operation with an optional modify type.
7169    Modify {
7170        /// The optional modify sub-type.
7171        modify_type: Option<ActionModifyType>,
7172    },
7173    /// Monitor operation with an optional monitor type.
7174    Monitor {
7175        /// The optional monitor sub-type.
7176        monitor_type: Option<ActionMonitorType>,
7177    },
7178    /// Operate permission.
7179    Operate,
7180    /// Override share restrictions.
7181    OverrideShareRestrictions,
7182    /// Ownership permission.
7183    Ownership,
7184    /// Purchase a data exchange listing.
7185    PurchaseDataExchangeListing,
7186
7187    /// Read access.
7188    Read,
7189    /// Read session-level access.
7190    ReadSession,
7191    /// References with optional column list.
7192    References {
7193        /// Optional list of referenced column identifiers.
7194        columns: Option<Vec<Ident>>,
7195    },
7196    /// Replication permission.
7197    Replicate,
7198    /// Resolve all references.
7199    ResolveAll,
7200    /// Role-related permission with target role name.
7201    Role {
7202        /// The target role name.
7203        role: ObjectName,
7204    },
7205    /// Select permission with optional column list.
7206    Select {
7207        /// Optional list of selected columns.
7208        columns: Option<Vec<Ident>>,
7209    },
7210    /// Temporary object permission.
7211    Temporary,
7212    /// Trigger-related permission.
7213    Trigger,
7214    /// Truncate permission.
7215    Truncate,
7216    /// Update permission with optional affected columns.
7217    Update {
7218        /// Optional list of columns affected by update.
7219        columns: Option<Vec<Ident>>,
7220    },
7221    /// Usage permission.
7222    Usage,
7223}
7224
7225impl fmt::Display for Action {
7226    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7227        match self {
7228            Action::AddSearchOptimization => f.write_str("ADD SEARCH OPTIMIZATION")?,
7229            Action::Apply { apply_type } => write!(f, "APPLY {apply_type}")?,
7230            Action::ApplyBudget => f.write_str("APPLYBUDGET")?,
7231            Action::AttachListing => f.write_str("ATTACH LISTING")?,
7232            Action::AttachPolicy => f.write_str("ATTACH POLICY")?,
7233            Action::Audit => f.write_str("AUDIT")?,
7234            Action::BindServiceEndpoint => f.write_str("BIND SERVICE ENDPOINT")?,
7235            Action::Connect => f.write_str("CONNECT")?,
7236            Action::Create { obj_type } => {
7237                f.write_str("CREATE")?;
7238                if let Some(obj_type) = obj_type {
7239                    write!(f, " {obj_type}")?
7240                }
7241            }
7242            Action::DatabaseRole { role } => write!(f, "DATABASE ROLE {role}")?,
7243            Action::Delete => f.write_str("DELETE")?,
7244            Action::Drop => f.write_str("DROP")?,
7245            Action::EvolveSchema => f.write_str("EVOLVE SCHEMA")?,
7246            Action::Exec { obj_type } => {
7247                f.write_str("EXEC")?;
7248                if let Some(obj_type) = obj_type {
7249                    write!(f, " {obj_type}")?
7250                }
7251            }
7252            Action::Execute { obj_type } => {
7253                f.write_str("EXECUTE")?;
7254                if let Some(obj_type) = obj_type {
7255                    write!(f, " {obj_type}")?
7256                }
7257            }
7258            Action::Failover => f.write_str("FAILOVER")?,
7259            Action::ImportedPrivileges => f.write_str("IMPORTED PRIVILEGES")?,
7260            Action::ImportShare => f.write_str("IMPORT SHARE")?,
7261            Action::Insert { .. } => f.write_str("INSERT")?,
7262            Action::Manage { manage_type } => write!(f, "MANAGE {manage_type}")?,
7263            Action::ManageReleases => f.write_str("MANAGE RELEASES")?,
7264            Action::ManageVersions => f.write_str("MANAGE VERSIONS")?,
7265            Action::Modify { modify_type } => {
7266                write!(f, "MODIFY")?;
7267                if let Some(modify_type) = modify_type {
7268                    write!(f, " {modify_type}")?;
7269                }
7270            }
7271            Action::Monitor { monitor_type } => {
7272                write!(f, "MONITOR")?;
7273                if let Some(monitor_type) = monitor_type {
7274                    write!(f, " {monitor_type}")?
7275                }
7276            }
7277            Action::Operate => f.write_str("OPERATE")?,
7278            Action::OverrideShareRestrictions => f.write_str("OVERRIDE SHARE RESTRICTIONS")?,
7279            Action::Ownership => f.write_str("OWNERSHIP")?,
7280            Action::PurchaseDataExchangeListing => f.write_str("PURCHASE DATA EXCHANGE LISTING")?,
7281            Action::Read => f.write_str("READ")?,
7282            Action::ReadSession => f.write_str("READ SESSION")?,
7283            Action::References { .. } => f.write_str("REFERENCES")?,
7284            Action::Replicate => f.write_str("REPLICATE")?,
7285            Action::ResolveAll => f.write_str("RESOLVE ALL")?,
7286            Action::Role { role } => write!(f, "ROLE {role}")?,
7287            Action::Select { .. } => f.write_str("SELECT")?,
7288            Action::Temporary => f.write_str("TEMPORARY")?,
7289            Action::Trigger => f.write_str("TRIGGER")?,
7290            Action::Truncate => f.write_str("TRUNCATE")?,
7291            Action::Update { .. } => f.write_str("UPDATE")?,
7292            Action::Usage => f.write_str("USAGE")?,
7293        };
7294        match self {
7295            Action::Insert { columns }
7296            | Action::References { columns }
7297            | Action::Select { columns }
7298            | Action::Update { columns } => {
7299                if let Some(columns) = columns {
7300                    write!(f, " ({})", display_comma_separated(columns))?;
7301                }
7302            }
7303            _ => (),
7304        };
7305        Ok(())
7306    }
7307}
7308
7309#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7310#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7311#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7312/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
7313/// under `globalPrivileges` in the `CREATE` privilege.
7314pub enum ActionCreateObjectType {
7315    /// An account-level object.
7316    Account,
7317    /// An application object.
7318    Application,
7319    /// An application package object.
7320    ApplicationPackage,
7321    /// A compute pool object.
7322    ComputePool,
7323    /// A data exchange listing.
7324    DataExchangeListing,
7325    /// A database object.
7326    Database,
7327    /// An external volume object.
7328    ExternalVolume,
7329    /// A failover group object.
7330    FailoverGroup,
7331    /// An integration object.
7332    Integration,
7333    /// A network policy object.
7334    NetworkPolicy,
7335    /// An organization listing.
7336    OrganiationListing,
7337    /// A replication group object.
7338    ReplicationGroup,
7339    /// A role object.
7340    Role,
7341    /// A schema object.
7342    Schema,
7343    /// A share object.
7344    Share,
7345    /// A user object.
7346    User,
7347    /// A warehouse object.
7348    Warehouse,
7349}
7350
7351impl fmt::Display for ActionCreateObjectType {
7352    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7353        match self {
7354            ActionCreateObjectType::Account => write!(f, "ACCOUNT"),
7355            ActionCreateObjectType::Application => write!(f, "APPLICATION"),
7356            ActionCreateObjectType::ApplicationPackage => write!(f, "APPLICATION PACKAGE"),
7357            ActionCreateObjectType::ComputePool => write!(f, "COMPUTE POOL"),
7358            ActionCreateObjectType::DataExchangeListing => write!(f, "DATA EXCHANGE LISTING"),
7359            ActionCreateObjectType::Database => write!(f, "DATABASE"),
7360            ActionCreateObjectType::ExternalVolume => write!(f, "EXTERNAL VOLUME"),
7361            ActionCreateObjectType::FailoverGroup => write!(f, "FAILOVER GROUP"),
7362            ActionCreateObjectType::Integration => write!(f, "INTEGRATION"),
7363            ActionCreateObjectType::NetworkPolicy => write!(f, "NETWORK POLICY"),
7364            ActionCreateObjectType::OrganiationListing => write!(f, "ORGANIZATION LISTING"),
7365            ActionCreateObjectType::ReplicationGroup => write!(f, "REPLICATION GROUP"),
7366            ActionCreateObjectType::Role => write!(f, "ROLE"),
7367            ActionCreateObjectType::Schema => write!(f, "SCHEMA"),
7368            ActionCreateObjectType::Share => write!(f, "SHARE"),
7369            ActionCreateObjectType::User => write!(f, "USER"),
7370            ActionCreateObjectType::Warehouse => write!(f, "WAREHOUSE"),
7371        }
7372    }
7373}
7374
7375#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7376#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7377#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7378/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
7379/// under `globalPrivileges` in the `APPLY` privilege.
7380pub enum ActionApplyType {
7381    /// Apply an aggregation policy.
7382    AggregationPolicy,
7383    /// Apply an authentication policy.
7384    AuthenticationPolicy,
7385    /// Apply a join policy.
7386    JoinPolicy,
7387    /// Apply a masking policy.
7388    MaskingPolicy,
7389    /// Apply a packages policy.
7390    PackagesPolicy,
7391    /// Apply a password policy.
7392    PasswordPolicy,
7393    /// Apply a projection policy.
7394    ProjectionPolicy,
7395    /// Apply a row access policy.
7396    RowAccessPolicy,
7397    /// Apply a session policy.
7398    SessionPolicy,
7399    /// Apply a tag.
7400    Tag,
7401}
7402
7403impl fmt::Display for ActionApplyType {
7404    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7405        match self {
7406            ActionApplyType::AggregationPolicy => write!(f, "AGGREGATION POLICY"),
7407            ActionApplyType::AuthenticationPolicy => write!(f, "AUTHENTICATION POLICY"),
7408            ActionApplyType::JoinPolicy => write!(f, "JOIN POLICY"),
7409            ActionApplyType::MaskingPolicy => write!(f, "MASKING POLICY"),
7410            ActionApplyType::PackagesPolicy => write!(f, "PACKAGES POLICY"),
7411            ActionApplyType::PasswordPolicy => write!(f, "PASSWORD POLICY"),
7412            ActionApplyType::ProjectionPolicy => write!(f, "PROJECTION POLICY"),
7413            ActionApplyType::RowAccessPolicy => write!(f, "ROW ACCESS POLICY"),
7414            ActionApplyType::SessionPolicy => write!(f, "SESSION POLICY"),
7415            ActionApplyType::Tag => write!(f, "TAG"),
7416        }
7417    }
7418}
7419
7420#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7421#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7422#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7423/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
7424/// under `globalPrivileges` in the `EXECUTE` privilege.
7425pub enum ActionExecuteObjectType {
7426    /// Alert object.
7427    Alert,
7428    /// Data metric function object.
7429    DataMetricFunction,
7430    /// Managed alert object.
7431    ManagedAlert,
7432    /// Managed task object.
7433    ManagedTask,
7434    /// Task object.
7435    Task,
7436}
7437
7438impl fmt::Display for ActionExecuteObjectType {
7439    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7440        match self {
7441            ActionExecuteObjectType::Alert => write!(f, "ALERT"),
7442            ActionExecuteObjectType::DataMetricFunction => write!(f, "DATA METRIC FUNCTION"),
7443            ActionExecuteObjectType::ManagedAlert => write!(f, "MANAGED ALERT"),
7444            ActionExecuteObjectType::ManagedTask => write!(f, "MANAGED TASK"),
7445            ActionExecuteObjectType::Task => write!(f, "TASK"),
7446        }
7447    }
7448}
7449
7450#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7451#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7452#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7453/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
7454/// under `globalPrivileges` in the `MANAGE` privilege.
7455pub enum ActionManageType {
7456    /// Account support cases management.
7457    AccountSupportCases,
7458    /// Event sharing management.
7459    EventSharing,
7460    /// Grants management.
7461    Grants,
7462    /// Listing auto-fulfillment management.
7463    ListingAutoFulfillment,
7464    /// Organization support cases management.
7465    OrganizationSupportCases,
7466    /// User support cases management.
7467    UserSupportCases,
7468    /// Warehouses management.
7469    Warehouses,
7470}
7471
7472impl fmt::Display for ActionManageType {
7473    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7474        match self {
7475            ActionManageType::AccountSupportCases => write!(f, "ACCOUNT SUPPORT CASES"),
7476            ActionManageType::EventSharing => write!(f, "EVENT SHARING"),
7477            ActionManageType::Grants => write!(f, "GRANTS"),
7478            ActionManageType::ListingAutoFulfillment => write!(f, "LISTING AUTO FULFILLMENT"),
7479            ActionManageType::OrganizationSupportCases => write!(f, "ORGANIZATION SUPPORT CASES"),
7480            ActionManageType::UserSupportCases => write!(f, "USER SUPPORT CASES"),
7481            ActionManageType::Warehouses => write!(f, "WAREHOUSES"),
7482        }
7483    }
7484}
7485
7486#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7487#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7488#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7489/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
7490/// under `globalPrivileges` in the `MODIFY` privilege.
7491pub enum ActionModifyType {
7492    /// Modify log level.
7493    LogLevel,
7494    /// Modify trace level.
7495    TraceLevel,
7496    /// Modify session log level.
7497    SessionLogLevel,
7498    /// Modify session trace level.
7499    SessionTraceLevel,
7500}
7501
7502impl fmt::Display for ActionModifyType {
7503    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7504        match self {
7505            ActionModifyType::LogLevel => write!(f, "LOG LEVEL"),
7506            ActionModifyType::TraceLevel => write!(f, "TRACE LEVEL"),
7507            ActionModifyType::SessionLogLevel => write!(f, "SESSION LOG LEVEL"),
7508            ActionModifyType::SessionTraceLevel => write!(f, "SESSION TRACE LEVEL"),
7509        }
7510    }
7511}
7512
7513#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7514#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7515#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7516/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
7517/// under `globalPrivileges` in the `MONITOR` privilege.
7518pub enum ActionMonitorType {
7519    /// Monitor execution.
7520    Execution,
7521    /// Monitor security.
7522    Security,
7523    /// Monitor usage.
7524    Usage,
7525}
7526
7527impl fmt::Display for ActionMonitorType {
7528    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7529        match self {
7530            ActionMonitorType::Execution => write!(f, "EXECUTION"),
7531            ActionMonitorType::Security => write!(f, "SECURITY"),
7532            ActionMonitorType::Usage => write!(f, "USAGE"),
7533        }
7534    }
7535}
7536
7537/// The principal that receives the privileges
7538#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7539#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7540#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7541pub struct Grantee {
7542    /// The category/type of grantee (role, user, share, etc.).
7543    pub grantee_type: GranteesType,
7544    /// Optional name of the grantee (identifier or user@host).
7545    pub name: Option<GranteeName>,
7546}
7547
7548impl fmt::Display for Grantee {
7549    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7550        let keyword = match self.grantee_type {
7551            GranteesType::Role => "ROLE",
7552            GranteesType::Share => "SHARE",
7553            GranteesType::User => "USER",
7554            GranteesType::Group => "GROUP",
7555            GranteesType::Public => "PUBLIC",
7556            GranteesType::DatabaseRole => "DATABASE ROLE",
7557            GranteesType::Application => "APPLICATION",
7558            GranteesType::ApplicationRole => "APPLICATION ROLE",
7559            GranteesType::None => "",
7560        };
7561        f.write_str(keyword)?;
7562        if let Some(name) = &self.name {
7563            if !keyword.is_empty() {
7564                f.write_str(" ")?;
7565            }
7566            name.fmt(f)?;
7567        }
7568        Ok(())
7569    }
7570}
7571
7572#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7573#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7574#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7575/// The kind of principal receiving privileges.
7576pub enum GranteesType {
7577    /// A role principal.
7578    Role,
7579    /// A share principal.
7580    Share,
7581    /// A user principal.
7582    User,
7583    /// A group principal.
7584    Group,
7585    /// The public principal.
7586    Public,
7587    /// A database role principal.
7588    DatabaseRole,
7589    /// An application principal.
7590    Application,
7591    /// An application role principal.
7592    ApplicationRole,
7593    /// No specific principal (e.g. `NONE`).
7594    None,
7595}
7596
7597/// Users/roles designated in a GRANT/REVOKE
7598#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7599#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7600#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7601pub enum GranteeName {
7602    /// A bare identifier
7603    ObjectName(ObjectName),
7604    /// A MySQL user/host pair such as 'root'@'%'
7605    UserHost {
7606        /// The user identifier portion.
7607        user: Ident,
7608        /// The host identifier portion.
7609        host: Ident,
7610    },
7611}
7612
7613impl fmt::Display for GranteeName {
7614    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7615        match self {
7616            GranteeName::ObjectName(name) => name.fmt(f),
7617            GranteeName::UserHost { user, host } => {
7618                write!(f, "{user}@{host}")
7619            }
7620        }
7621    }
7622}
7623
7624/// Objects on which privileges are granted in a GRANT statement.
7625#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7626#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7627#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7628pub enum GrantObjects {
7629    /// Grant privileges on `ALL SEQUENCES IN SCHEMA <schema_name> [, ...]`
7630    AllSequencesInSchema {
7631        /// The target schema names.
7632        schemas: Vec<ObjectName>,
7633    },
7634    /// Grant privileges on `ALL TABLES IN SCHEMA <schema_name> [, ...]`
7635    AllTablesInSchema {
7636        /// The target schema names.
7637        schemas: Vec<ObjectName>,
7638    },
7639    /// Grant privileges on `ALL VIEWS IN SCHEMA <schema_name> [, ...]`
7640    AllViewsInSchema {
7641        /// The target schema names.
7642        schemas: Vec<ObjectName>,
7643    },
7644    /// Grant privileges on `ALL MATERIALIZED VIEWS IN SCHEMA <schema_name> [, ...]`
7645    AllMaterializedViewsInSchema {
7646        /// The target schema names.
7647        schemas: Vec<ObjectName>,
7648    },
7649    /// Grant privileges on `ALL EXTERNAL TABLES IN SCHEMA <schema_name> [, ...]`
7650    AllExternalTablesInSchema {
7651        /// The target schema names.
7652        schemas: Vec<ObjectName>,
7653    },
7654    /// Grant privileges on `ALL FUNCTIONS IN SCHEMA <schema_name> [, ...]`
7655    AllFunctionsInSchema {
7656        /// The target schema names.
7657        schemas: Vec<ObjectName>,
7658    },
7659    /// Grant privileges on `FUTURE SCHEMAS IN DATABASE <database_name> [, ...]`
7660    FutureSchemasInDatabase {
7661        /// The target database names.
7662        databases: Vec<ObjectName>,
7663    },
7664    /// Grant privileges on `FUTURE TABLES IN SCHEMA <schema_name> [, ...]`
7665    FutureTablesInSchema {
7666        /// The target schema names.
7667        schemas: Vec<ObjectName>,
7668    },
7669    /// Grant privileges on `FUTURE VIEWS IN SCHEMA <schema_name> [, ...]`
7670    FutureViewsInSchema {
7671        /// The target schema names.
7672        schemas: Vec<ObjectName>,
7673    },
7674    /// Grant privileges on `FUTURE EXTERNAL TABLES IN SCHEMA <schema_name> [, ...]`
7675    FutureExternalTablesInSchema {
7676        /// The target schema names.
7677        schemas: Vec<ObjectName>,
7678    },
7679    /// Grant privileges on `FUTURE MATERIALIZED VIEWS IN SCHEMA <schema_name> [, ...]`
7680    FutureMaterializedViewsInSchema {
7681        /// The target schema names.
7682        schemas: Vec<ObjectName>,
7683    },
7684    /// Grant privileges on `FUTURE SEQUENCES IN SCHEMA <schema_name> [, ...]`
7685    FutureSequencesInSchema {
7686        /// The target schema names.
7687        schemas: Vec<ObjectName>,
7688    },
7689    /// Grant privileges on specific databases
7690    Databases(Vec<ObjectName>),
7691    /// Grant privileges on specific schemas
7692    Schemas(Vec<ObjectName>),
7693    /// Grant privileges on specific sequences
7694    Sequences(Vec<ObjectName>),
7695    /// Grant privileges on specific tables
7696    Tables(Vec<ObjectName>),
7697    /// Grant privileges on specific views
7698    Views(Vec<ObjectName>),
7699    /// Grant privileges on specific warehouses
7700    Warehouses(Vec<ObjectName>),
7701    /// Grant privileges on specific integrations
7702    Integrations(Vec<ObjectName>),
7703    /// Grant privileges on resource monitors
7704    ResourceMonitors(Vec<ObjectName>),
7705    /// Grant privileges on users
7706    Users(Vec<ObjectName>),
7707    /// Grant privileges on compute pools
7708    ComputePools(Vec<ObjectName>),
7709    /// Grant privileges on connections
7710    Connections(Vec<ObjectName>),
7711    /// Grant privileges on failover groups
7712    FailoverGroup(Vec<ObjectName>),
7713    /// Grant privileges on replication group
7714    ReplicationGroup(Vec<ObjectName>),
7715    /// Grant privileges on external volumes
7716    ExternalVolumes(Vec<ObjectName>),
7717    /// Grant privileges on a procedure. In dialects that
7718    /// support overloading, the argument types must be specified.
7719    ///
7720    /// For example:
7721    /// `GRANT USAGE ON PROCEDURE foo(varchar) TO ROLE role1`
7722    Procedure {
7723        /// The procedure name.
7724        name: ObjectName,
7725        /// Optional argument types for overloaded procedures.
7726        arg_types: Vec<DataType>,
7727    },
7728
7729    /// Grant privileges on a function. In dialects that
7730    /// support overloading, the argument types must be specified.
7731    ///
7732    /// For example:
7733    /// `GRANT USAGE ON FUNCTION foo(varchar) TO ROLE role1`
7734    Function {
7735        /// The function name.
7736        name: ObjectName,
7737        /// Optional argument types for overloaded functions.
7738        arg_types: Vec<DataType>,
7739    },
7740}
7741
7742impl fmt::Display for GrantObjects {
7743    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7744        match self {
7745            GrantObjects::Sequences(sequences) => {
7746                write!(f, "SEQUENCE {}", display_comma_separated(sequences))
7747            }
7748            GrantObjects::Databases(databases) => {
7749                write!(f, "DATABASE {}", display_comma_separated(databases))
7750            }
7751            GrantObjects::Schemas(schemas) => {
7752                write!(f, "SCHEMA {}", display_comma_separated(schemas))
7753            }
7754            GrantObjects::Tables(tables) => {
7755                write!(f, "{}", display_comma_separated(tables))
7756            }
7757            GrantObjects::Views(views) => {
7758                write!(f, "VIEW {}", display_comma_separated(views))
7759            }
7760            GrantObjects::Warehouses(warehouses) => {
7761                write!(f, "WAREHOUSE {}", display_comma_separated(warehouses))
7762            }
7763            GrantObjects::Integrations(integrations) => {
7764                write!(f, "INTEGRATION {}", display_comma_separated(integrations))
7765            }
7766            GrantObjects::AllSequencesInSchema { schemas } => {
7767                write!(
7768                    f,
7769                    "ALL SEQUENCES IN SCHEMA {}",
7770                    display_comma_separated(schemas)
7771                )
7772            }
7773            GrantObjects::AllTablesInSchema { schemas } => {
7774                write!(
7775                    f,
7776                    "ALL TABLES IN SCHEMA {}",
7777                    display_comma_separated(schemas)
7778                )
7779            }
7780            GrantObjects::AllExternalTablesInSchema { schemas } => {
7781                write!(
7782                    f,
7783                    "ALL EXTERNAL TABLES IN SCHEMA {}",
7784                    display_comma_separated(schemas)
7785                )
7786            }
7787            GrantObjects::AllViewsInSchema { schemas } => {
7788                write!(
7789                    f,
7790                    "ALL VIEWS IN SCHEMA {}",
7791                    display_comma_separated(schemas)
7792                )
7793            }
7794            GrantObjects::AllMaterializedViewsInSchema { schemas } => {
7795                write!(
7796                    f,
7797                    "ALL MATERIALIZED VIEWS IN SCHEMA {}",
7798                    display_comma_separated(schemas)
7799                )
7800            }
7801            GrantObjects::AllFunctionsInSchema { schemas } => {
7802                write!(
7803                    f,
7804                    "ALL FUNCTIONS IN SCHEMA {}",
7805                    display_comma_separated(schemas)
7806                )
7807            }
7808            GrantObjects::FutureSchemasInDatabase { databases } => {
7809                write!(
7810                    f,
7811                    "FUTURE SCHEMAS IN DATABASE {}",
7812                    display_comma_separated(databases)
7813                )
7814            }
7815            GrantObjects::FutureTablesInSchema { schemas } => {
7816                write!(
7817                    f,
7818                    "FUTURE TABLES IN SCHEMA {}",
7819                    display_comma_separated(schemas)
7820                )
7821            }
7822            GrantObjects::FutureExternalTablesInSchema { schemas } => {
7823                write!(
7824                    f,
7825                    "FUTURE EXTERNAL TABLES IN SCHEMA {}",
7826                    display_comma_separated(schemas)
7827                )
7828            }
7829            GrantObjects::FutureViewsInSchema { schemas } => {
7830                write!(
7831                    f,
7832                    "FUTURE VIEWS IN SCHEMA {}",
7833                    display_comma_separated(schemas)
7834                )
7835            }
7836            GrantObjects::FutureMaterializedViewsInSchema { schemas } => {
7837                write!(
7838                    f,
7839                    "FUTURE MATERIALIZED VIEWS IN SCHEMA {}",
7840                    display_comma_separated(schemas)
7841                )
7842            }
7843            GrantObjects::FutureSequencesInSchema { schemas } => {
7844                write!(
7845                    f,
7846                    "FUTURE SEQUENCES IN SCHEMA {}",
7847                    display_comma_separated(schemas)
7848                )
7849            }
7850            GrantObjects::ResourceMonitors(objects) => {
7851                write!(f, "RESOURCE MONITOR {}", display_comma_separated(objects))
7852            }
7853            GrantObjects::Users(objects) => {
7854                write!(f, "USER {}", display_comma_separated(objects))
7855            }
7856            GrantObjects::ComputePools(objects) => {
7857                write!(f, "COMPUTE POOL {}", display_comma_separated(objects))
7858            }
7859            GrantObjects::Connections(objects) => {
7860                write!(f, "CONNECTION {}", display_comma_separated(objects))
7861            }
7862            GrantObjects::FailoverGroup(objects) => {
7863                write!(f, "FAILOVER GROUP {}", display_comma_separated(objects))
7864            }
7865            GrantObjects::ReplicationGroup(objects) => {
7866                write!(f, "REPLICATION GROUP {}", display_comma_separated(objects))
7867            }
7868            GrantObjects::ExternalVolumes(objects) => {
7869                write!(f, "EXTERNAL VOLUME {}", display_comma_separated(objects))
7870            }
7871            GrantObjects::Procedure { name, arg_types } => {
7872                write!(f, "PROCEDURE {name}")?;
7873                if !arg_types.is_empty() {
7874                    write!(f, "({})", display_comma_separated(arg_types))?;
7875                }
7876                Ok(())
7877            }
7878            GrantObjects::Function { name, arg_types } => {
7879                write!(f, "FUNCTION {name}")?;
7880                if !arg_types.is_empty() {
7881                    write!(f, "({})", display_comma_separated(arg_types))?;
7882                }
7883                Ok(())
7884            }
7885        }
7886    }
7887}
7888
7889/// A `DENY` statement
7890///
7891/// [MsSql](https://learn.microsoft.com/en-us/sql/t-sql/statements/deny-transact-sql)
7892#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7893#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7894#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7895pub struct DenyStatement {
7896    /// The privileges to deny.
7897    pub privileges: Privileges,
7898    /// The objects the privileges apply to.
7899    pub objects: GrantObjects,
7900    /// The grantees (users/roles) to whom the denial applies.
7901    pub grantees: Vec<Grantee>,
7902    /// Optional identifier of the principal that performed the grant.
7903    pub granted_by: Option<Ident>,
7904    /// Optional cascade option controlling dependent objects.
7905    pub cascade: Option<CascadeOption>,
7906}
7907
7908impl fmt::Display for DenyStatement {
7909    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7910        write!(f, "DENY {}", self.privileges)?;
7911        write!(f, " ON {}", self.objects)?;
7912        if !self.grantees.is_empty() {
7913            write!(f, " TO {}", display_comma_separated(&self.grantees))?;
7914        }
7915        if let Some(cascade) = &self.cascade {
7916            write!(f, " {cascade}")?;
7917        }
7918        if let Some(granted_by) = &self.granted_by {
7919            write!(f, " AS {granted_by}")?;
7920        }
7921        Ok(())
7922    }
7923}
7924
7925/// SQL assignment `foo = expr` as used in SQLUpdate
7926#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7927#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7928#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7929pub struct Assignment {
7930    /// The left-hand side of the assignment.
7931    pub target: AssignmentTarget,
7932    /// The expression assigned to the target.
7933    pub value: Expr,
7934}
7935
7936impl fmt::Display for Assignment {
7937    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7938        write!(f, "{} = {}", self.target, self.value)
7939    }
7940}
7941
7942/// Left-hand side of an assignment in an UPDATE statement,
7943/// e.g. `foo` in `foo = 5` (ColumnName assignment) or
7944/// `(a, b)` in `(a, b) = (1, 2)` (Tuple assignment).
7945#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7946#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7947#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7948pub enum AssignmentTarget {
7949    /// A single column
7950    ColumnName(ObjectName),
7951    /// A tuple of columns
7952    Tuple(Vec<ObjectName>),
7953}
7954
7955impl fmt::Display for AssignmentTarget {
7956    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7957        match self {
7958            AssignmentTarget::ColumnName(column) => write!(f, "{column}"),
7959            AssignmentTarget::Tuple(columns) => write!(f, "({})", display_comma_separated(columns)),
7960        }
7961    }
7962}
7963
7964#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7965#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7966#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7967/// Expression forms allowed as a function argument.
7968pub enum FunctionArgExpr {
7969    /// A normal expression argument.
7970    Expr(Expr),
7971    /// Qualified wildcard, e.g. `alias.*` or `schema.table.*`.
7972    QualifiedWildcard(ObjectName),
7973    /// An unqualified `*` wildcard.
7974    Wildcard,
7975    /// An unqualified `*` wildcard with additional options, e.g. `* EXCLUDE(col)`.
7976    ///
7977    /// Used in Snowflake to support expressions like `HASH(* EXCLUDE(col))`.
7978    WildcardWithOptions(WildcardAdditionalOptions),
7979}
7980
7981impl From<Expr> for FunctionArgExpr {
7982    fn from(wildcard_expr: Expr) -> Self {
7983        match wildcard_expr {
7984            Expr::QualifiedWildcard(prefix, _) => Self::QualifiedWildcard(prefix),
7985            Expr::Wildcard(_) => Self::Wildcard,
7986            expr => Self::Expr(expr),
7987        }
7988    }
7989}
7990
7991impl fmt::Display for FunctionArgExpr {
7992    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7993        match self {
7994            FunctionArgExpr::Expr(expr) => write!(f, "{expr}"),
7995            FunctionArgExpr::QualifiedWildcard(prefix) => write!(f, "{prefix}.*"),
7996            FunctionArgExpr::Wildcard => f.write_str("*"),
7997            FunctionArgExpr::WildcardWithOptions(opts) => write!(f, "*{opts}"),
7998        }
7999    }
8000}
8001
8002#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8003#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8004#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8005/// Operator used to separate function arguments
8006pub enum FunctionArgOperator {
8007    /// function(arg1 = value1)
8008    Equals,
8009    /// function(arg1 => value1)
8010    RightArrow,
8011    /// function(arg1 := value1)
8012    Assignment,
8013    /// function(arg1 : value1)
8014    Colon,
8015    /// function(arg1 VALUE value1)
8016    Value,
8017    /// function(arg1 value1), with no operator between the name and the value,
8018    /// as in PostgreSQL `XMLPARSE(DOCUMENT value)`
8019    ///
8020    /// [PostgreSQL](https://www.postgresql.org/docs/current/datatype-xml.html#DATATYPE-XML-CREATING)
8021    Space,
8022}
8023
8024impl fmt::Display for FunctionArgOperator {
8025    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8026        match self {
8027            FunctionArgOperator::Equals => f.write_str("="),
8028            FunctionArgOperator::RightArrow => f.write_str("=>"),
8029            FunctionArgOperator::Assignment => f.write_str(":="),
8030            FunctionArgOperator::Colon => f.write_str(":"),
8031            FunctionArgOperator::Value => f.write_str("VALUE"),
8032            FunctionArgOperator::Space => Ok(()),
8033        }
8034    }
8035}
8036
8037#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8038#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8039#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8040/// Forms of function arguments (named, expression-named, or positional).
8041pub enum FunctionArg {
8042    /// `name` is identifier
8043    ///
8044    /// Enabled when `Dialect::supports_named_fn_args_with_expr_name` returns 'false'
8045    Named {
8046        /// The identifier name of the argument.
8047        name: Ident,
8048        /// The argument expression or wildcard form.
8049        arg: FunctionArgExpr,
8050        /// The operator separating name and value.
8051        operator: FunctionArgOperator,
8052    },
8053    /// `name` is arbitrary expression
8054    ///
8055    /// Enabled when `Dialect::supports_named_fn_args_with_expr_name` returns 'true'
8056    ExprNamed {
8057        /// The expression used as the argument name.
8058        name: Expr,
8059        /// The argument expression or wildcard form.
8060        arg: FunctionArgExpr,
8061        /// The operator separating name and value.
8062        operator: FunctionArgOperator,
8063    },
8064    /// An unnamed argument (positional), given by expression or wildcard.
8065    Unnamed(FunctionArgExpr),
8066}
8067
8068impl fmt::Display for FunctionArg {
8069    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8070        match self {
8071            FunctionArg::Named {
8072                name,
8073                arg,
8074                operator,
8075            } => fmt_named_function_arg(f, name, operator, arg),
8076            FunctionArg::ExprNamed {
8077                name,
8078                arg,
8079                operator,
8080            } => fmt_named_function_arg(f, name, operator, arg),
8081            FunctionArg::Unnamed(unnamed_arg) => write!(f, "{unnamed_arg}"),
8082        }
8083    }
8084}
8085
8086/// `FunctionArgOperator::Space` has no token of its own, so the name and the
8087/// value are separated by a single space instead.
8088fn fmt_named_function_arg(
8089    f: &mut fmt::Formatter,
8090    name: &impl fmt::Display,
8091    operator: &FunctionArgOperator,
8092    arg: &FunctionArgExpr,
8093) -> fmt::Result {
8094    match operator {
8095        FunctionArgOperator::Space => write!(f, "{name} {arg}"),
8096        _ => write!(f, "{name} {operator} {arg}"),
8097    }
8098}
8099
8100#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8101#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8102#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8103/// Which cursor(s) to close.
8104pub enum CloseCursor {
8105    /// Close all cursors.
8106    All,
8107    /// Close a specific cursor by name.
8108    Specific {
8109        /// The name of the cursor to close.
8110        name: Ident,
8111    },
8112}
8113
8114impl fmt::Display for CloseCursor {
8115    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8116        match self {
8117            CloseCursor::All => write!(f, "ALL"),
8118            CloseCursor::Specific { name } => write!(f, "{name}"),
8119        }
8120    }
8121}
8122
8123/// A Drop Domain statement
8124#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8125#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8126#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8127pub struct DropDomain {
8128    /// Whether to drop the domain if it exists
8129    pub if_exists: bool,
8130    /// The name of the domain to drop
8131    pub name: ObjectName,
8132    /// The behavior to apply when dropping the domain
8133    pub drop_behavior: Option<DropBehavior>,
8134}
8135
8136/// A constant of form `<data_type> 'value'`.
8137/// This can represent ANSI SQL `DATE`, `TIME`, and `TIMESTAMP` literals (such as `DATE '2020-01-01'`),
8138/// as well as constants of other types (a non-standard PostgreSQL extension).
8139#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8140#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8141#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8142pub struct TypedString {
8143    /// The data type of the typed string (e.g. DATE, TIME, TIMESTAMP).
8144    pub data_type: DataType,
8145    /// The value of the constant.
8146    /// Hint: you can unwrap the string value using `value.into_string()`.
8147    pub value: ValueWithSpan,
8148    /// Flags whether this TypedString uses the [ODBC syntax].
8149    ///
8150    /// Example:
8151    /// ```sql
8152    /// -- An ODBC date literal:
8153    /// SELECT {d '2025-07-16'}
8154    /// -- This is equivalent to the standard ANSI SQL literal:
8155    /// SELECT DATE '2025-07-16'
8156    ///
8157    /// [ODBC syntax]: https://learn.microsoft.com/en-us/sql/odbc/reference/develop-app/date-time-and-timestamp-literals?view=sql-server-2017
8158    pub uses_odbc_syntax: bool,
8159}
8160
8161impl fmt::Display for TypedString {
8162    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8163        let data_type = &self.data_type;
8164        let value = &self.value;
8165        match self.uses_odbc_syntax {
8166            false => {
8167                write!(f, "{data_type}")?;
8168                write!(f, " {value}")
8169            }
8170            true => {
8171                let prefix = match data_type {
8172                    DataType::Date => "d",
8173                    DataType::Time(..) => "t",
8174                    DataType::Timestamp(..) => "ts",
8175                    _ => "?",
8176                };
8177                write!(f, "{{{prefix} {value}}}")
8178            }
8179        }
8180    }
8181}
8182
8183/// A function call
8184#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8185#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8186#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8187pub struct Function {
8188    /// The function name (may be qualified).
8189    pub name: ObjectName,
8190    /// Flags whether this function call uses the [ODBC syntax].
8191    ///
8192    /// Example:
8193    /// ```sql
8194    /// SELECT {fn CONCAT('foo', 'bar')}
8195    /// ```
8196    ///
8197    /// [ODBC syntax]: https://learn.microsoft.com/en-us/sql/odbc/reference/develop-app/scalar-function-calls?view=sql-server-2017
8198    pub uses_odbc_syntax: bool,
8199    /// The parameters to the function, including any options specified within the
8200    /// delimiting parentheses.
8201    ///
8202    /// Example:
8203    /// ```plaintext
8204    /// HISTOGRAM(0.5, 0.6)(x, y)
8205    /// ```
8206    ///
8207    /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/aggregate-functions/parametric-functions)
8208    pub parameters: FunctionArguments,
8209    /// The arguments to the function, including any options specified within the
8210    /// delimiting parentheses.
8211    pub args: FunctionArguments,
8212    /// A clause used with certain aggregate functions to control the ordering
8213    /// within grouped sets before the function is applied.
8214    ///
8215    /// Syntax:
8216    /// ```plaintext
8217    /// <aggregate_function>(expression) WITHIN GROUP (ORDER BY key [ASC | DESC], ...)
8218    /// ```
8219    pub within_group: Vec<OrderByExpr>,
8220    /// e.g. `x > 5` in `COUNT(x) FILTER (WHERE x > 5)`
8221    pub filter: Option<Box<Expr>>,
8222    /// Indicates how `NULL`s should be handled in the calculation.
8223    ///
8224    /// Example:
8225    /// ```plaintext
8226    /// FIRST_VALUE( <expr> ) [ { IGNORE | RESPECT } NULLS ] OVER ...
8227    /// ```
8228    ///
8229    /// [Snowflake](https://docs.snowflake.com/en/sql-reference/functions/first_value)
8230    pub null_treatment: Option<NullTreatment>,
8231    /// The `OVER` clause, indicating a window function call.
8232    pub over: Option<WindowType>,
8233}
8234
8235impl fmt::Display for Function {
8236    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8237        if self.uses_odbc_syntax {
8238            write!(f, "{{fn ")?;
8239        }
8240
8241        write!(f, "{}{}{}", self.name, self.parameters, self.args)?;
8242
8243        if !self.within_group.is_empty() {
8244            write!(
8245                f,
8246                " WITHIN GROUP (ORDER BY {})",
8247                display_comma_separated(&self.within_group)
8248            )?;
8249        }
8250
8251        if let Some(filter_cond) = &self.filter {
8252            write!(f, " FILTER (WHERE {filter_cond})")?;
8253        }
8254
8255        if let Some(null_treatment) = &self.null_treatment {
8256            write!(f, " {null_treatment}")?;
8257        }
8258
8259        if let Some(o) = &self.over {
8260            f.write_str(" OVER ")?;
8261            o.fmt(f)?;
8262        }
8263
8264        if self.uses_odbc_syntax {
8265            write!(f, "}}")?;
8266        }
8267
8268        Ok(())
8269    }
8270}
8271
8272/// The arguments passed to a function call.
8273#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8274#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8275#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8276pub enum FunctionArguments {
8277    /// Used for special functions like `CURRENT_TIMESTAMP` that are invoked
8278    /// without parentheses.
8279    None,
8280    /// On some dialects, a subquery can be passed without surrounding
8281    /// parentheses if it's the sole argument to the function.
8282    Subquery(Box<Query>),
8283    /// A normal function argument list, including any clauses within it such as
8284    /// `DISTINCT` or `ORDER BY`.
8285    List(FunctionArgumentList),
8286}
8287
8288impl fmt::Display for FunctionArguments {
8289    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8290        match self {
8291            FunctionArguments::None => Ok(()),
8292            FunctionArguments::Subquery(query) => write!(f, "({query})"),
8293            FunctionArguments::List(args) => write!(f, "({args})"),
8294        }
8295    }
8296}
8297
8298/// This represents everything inside the parentheses when calling a function.
8299#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8300#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8301#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8302pub struct FunctionArgumentList {
8303    /// `[ ALL | DISTINCT ]`
8304    pub duplicate_treatment: Option<DuplicateTreatment>,
8305    /// The function arguments.
8306    pub args: Vec<FunctionArg>,
8307    /// Additional clauses specified within the argument list.
8308    pub clauses: Vec<FunctionArgumentClause>,
8309}
8310
8311impl fmt::Display for FunctionArgumentList {
8312    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8313        if let Some(duplicate_treatment) = self.duplicate_treatment {
8314            write!(f, "{duplicate_treatment} ")?;
8315        }
8316        write!(f, "{}", display_comma_separated(&self.args))?;
8317        if !self.clauses.is_empty() {
8318            if !self.args.is_empty() {
8319                write!(f, " ")?;
8320            }
8321            write!(f, "{}", display_separated(&self.clauses, " "))?;
8322        }
8323        Ok(())
8324    }
8325}
8326
8327#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8328#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8329#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8330/// Clauses that can appear inside a function argument list.
8331pub enum FunctionArgumentClause {
8332    /// Indicates how `NULL`s should be handled in the calculation, e.g. in `FIRST_VALUE` on [BigQuery].
8333    ///
8334    /// Syntax:
8335    /// ```plaintext
8336    /// { IGNORE | RESPECT } NULLS ]
8337    /// ```
8338    ///
8339    /// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/navigation_functions#first_value
8340    IgnoreOrRespectNulls(NullTreatment),
8341    /// The inline `WHERE` filter clause on an aggregate call, e.g.
8342    /// `COUNT(* WHERE cond)` / `SUM(x WHERE cond)` / `ARRAY_AGG(x WHERE cond ORDER BY ..)`.
8343    /// Popularized by [GoogleSQL]; equivalent to the standard `AGG(x) FILTER (WHERE cond)`.
8344    /// Accepted for all dialects since `WHERE` cannot otherwise begin a function argument.
8345    ///
8346    /// [GoogleSQL]: https://cloud.google.com/bigquery/docs/reference/standard-sql/aggregate_functions#grouping_and_filtering
8347    Where(Expr),
8348    /// Specifies the the ordering for some ordered set aggregates, e.g. `ARRAY_AGG` on [BigQuery].
8349    ///
8350    /// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/aggregate_functions#array_agg
8351    OrderBy(Vec<OrderByExpr>),
8352    /// Specifies a limit for the `ARRAY_AGG` and `ARRAY_CONCAT_AGG` functions on BigQuery.
8353    Limit(Expr),
8354    /// Specifies the behavior on overflow of the `LISTAGG` function.
8355    ///
8356    /// See <https://trino.io/docs/current/functions/aggregate.html>.
8357    OnOverflow(ListAggOnOverflow),
8358    /// Specifies a minimum or maximum bound on the input to [`ANY_VALUE`] on BigQuery.
8359    ///
8360    /// Syntax:
8361    /// ```plaintext
8362    /// HAVING { MAX | MIN } expression
8363    /// ```
8364    ///
8365    /// [`ANY_VALUE`]: https://cloud.google.com/bigquery/docs/reference/standard-sql/aggregate_functions#any_value
8366    Having(HavingBound),
8367    /// The `SEPARATOR` clause to the [`GROUP_CONCAT`] function in MySQL.
8368    ///
8369    /// [`GROUP_CONCAT`]: https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html#function_group-concat
8370    Separator(ValueWithSpan),
8371    /// The `ON NULL` clause for some JSON functions.
8372    ///
8373    /// [MSSQL `JSON_ARRAY`](https://learn.microsoft.com/en-us/sql/t-sql/functions/json-array-transact-sql?view=sql-server-ver16)
8374    /// [MSSQL `JSON_OBJECT`](https://learn.microsoft.com/en-us/sql/t-sql/functions/json-object-transact-sql?view=sql-server-ver16>)
8375    /// [PostgreSQL JSON functions](https://www.postgresql.org/docs/current/functions-json.html#FUNCTIONS-JSON-PROCESSING)
8376    JsonNullClause(JsonNullClause),
8377    /// The `RETURNING` clause for some JSON functions in PostgreSQL
8378    ///
8379    /// [`JSON_OBJECT`](https://www.postgresql.org/docs/current/functions-json.html#:~:text=json_object)
8380    JsonReturningClause(JsonReturningClause),
8381}
8382
8383impl fmt::Display for FunctionArgumentClause {
8384    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8385        match self {
8386            FunctionArgumentClause::IgnoreOrRespectNulls(null_treatment) => {
8387                write!(f, "{null_treatment}")
8388            }
8389            FunctionArgumentClause::Where(expr) => write!(f, "WHERE {expr}"),
8390            FunctionArgumentClause::OrderBy(order_by) => {
8391                write!(f, "ORDER BY {}", display_comma_separated(order_by))
8392            }
8393            FunctionArgumentClause::Limit(limit) => write!(f, "LIMIT {limit}"),
8394            FunctionArgumentClause::OnOverflow(on_overflow) => write!(f, "{on_overflow}"),
8395            FunctionArgumentClause::Having(bound) => write!(f, "{bound}"),
8396            FunctionArgumentClause::Separator(sep) => write!(f, "SEPARATOR {sep}"),
8397            FunctionArgumentClause::JsonNullClause(null_clause) => write!(f, "{null_clause}"),
8398            FunctionArgumentClause::JsonReturningClause(returning_clause) => {
8399                write!(f, "{returning_clause}")
8400            }
8401        }
8402    }
8403}
8404
8405/// A method call
8406#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8407#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8408#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8409pub struct Method {
8410    /// The expression on which the method is invoked.
8411    pub expr: Box<Expr>,
8412    // always non-empty
8413    /// The sequence of chained method calls.
8414    pub method_chain: Vec<Function>,
8415}
8416
8417impl fmt::Display for Method {
8418    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8419        write!(
8420            f,
8421            "{}.{}",
8422            self.expr,
8423            display_separated(&self.method_chain, ".")
8424        )
8425    }
8426}
8427
8428#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8429#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8430#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8431/// How duplicate values are treated inside function argument lists.
8432pub enum DuplicateTreatment {
8433    /// Consider only unique values.
8434    Distinct,
8435    /// Retain all duplicate values (the default).
8436    All,
8437}
8438
8439impl fmt::Display for DuplicateTreatment {
8440    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8441        match self {
8442            DuplicateTreatment::Distinct => write!(f, "DISTINCT"),
8443            DuplicateTreatment::All => write!(f, "ALL"),
8444        }
8445    }
8446}
8447
8448#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8449#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8450#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8451/// How the `ANALYZE`/`EXPLAIN ANALYZE` format is specified.
8452pub enum AnalyzeFormatKind {
8453    /// Format provided as a keyword, e.g. `FORMAT JSON`.
8454    Keyword(AnalyzeFormat),
8455    /// Format provided as an assignment, e.g. `FORMAT=JSON`.
8456    Assignment(AnalyzeFormat),
8457}
8458
8459impl fmt::Display for AnalyzeFormatKind {
8460    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
8461        match self {
8462            AnalyzeFormatKind::Keyword(format) => write!(f, "FORMAT {format}"),
8463            AnalyzeFormatKind::Assignment(format) => write!(f, "FORMAT={format}"),
8464        }
8465    }
8466}
8467
8468#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8469#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8470#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8471/// Output formats supported for `ANALYZE`/`EXPLAIN ANALYZE`.
8472pub enum AnalyzeFormat {
8473    /// Plain text format.
8474    TEXT,
8475    /// Graphviz DOT format.
8476    GRAPHVIZ,
8477    /// JSON format.
8478    JSON,
8479    /// Traditional explain output.
8480    TRADITIONAL,
8481    /// Tree-style explain output.
8482    TREE,
8483}
8484
8485/// Optional type constraint for `IS JSON`.
8486#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash)]
8487#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8488#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8489pub enum JsonPredicateType {
8490    /// `VALUE` form.
8491    Value,
8492    /// `SCALAR` form.
8493    Scalar,
8494    /// `ARRAY` form.
8495    Array,
8496    /// `OBJECT` form.
8497    Object,
8498}
8499
8500impl fmt::Display for JsonPredicateType {
8501    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8502        match self {
8503            JsonPredicateType::Value => write!(f, "VALUE"),
8504            JsonPredicateType::Scalar => write!(f, "SCALAR"),
8505            JsonPredicateType::Array => write!(f, "ARRAY"),
8506            JsonPredicateType::Object => write!(f, "OBJECT"),
8507        }
8508    }
8509}
8510
8511/// Optional duplicate-key handling for `IS JSON`.
8512#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash)]
8513#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8514#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8515pub enum JsonKeyUniqueness {
8516    /// `WITH UNIQUE KEYS` form.
8517    WithUniqueKeys,
8518    /// `WITHOUT UNIQUE KEYS` form.
8519    WithoutUniqueKeys,
8520}
8521
8522impl fmt::Display for JsonKeyUniqueness {
8523    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8524        match self {
8525            JsonKeyUniqueness::WithUniqueKeys => write!(f, "WITH UNIQUE KEYS"),
8526            JsonKeyUniqueness::WithoutUniqueKeys => write!(f, "WITHOUT UNIQUE KEYS"),
8527        }
8528    }
8529}
8530
8531impl fmt::Display for AnalyzeFormat {
8532    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
8533        f.write_str(match self {
8534            AnalyzeFormat::TEXT => "TEXT",
8535            AnalyzeFormat::GRAPHVIZ => "GRAPHVIZ",
8536            AnalyzeFormat::JSON => "JSON",
8537            AnalyzeFormat::TRADITIONAL => "TRADITIONAL",
8538            AnalyzeFormat::TREE => "TREE",
8539        })
8540    }
8541}
8542
8543/// External table's available file format
8544#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8545#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8546#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8547pub enum FileFormat {
8548    /// Text file format.
8549    TEXTFILE,
8550    /// Sequence file format.
8551    SEQUENCEFILE,
8552    /// ORC file format.
8553    ORC,
8554    /// Parquet file format.
8555    PARQUET,
8556    /// Avro file format.
8557    AVRO,
8558    /// RCFile format.
8559    RCFILE,
8560    /// JSON file format.
8561    JSONFILE,
8562}
8563
8564impl fmt::Display for FileFormat {
8565    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8566        use self::FileFormat::*;
8567        f.write_str(match self {
8568            TEXTFILE => "TEXTFILE",
8569            SEQUENCEFILE => "SEQUENCEFILE",
8570            ORC => "ORC",
8571            PARQUET => "PARQUET",
8572            AVRO => "AVRO",
8573            RCFILE => "RCFILE",
8574            JSONFILE => "JSONFILE",
8575        })
8576    }
8577}
8578
8579/// The `ON OVERFLOW` clause of a LISTAGG invocation
8580#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8581#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8582#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8583pub enum ListAggOnOverflow {
8584    /// `ON OVERFLOW ERROR`
8585    Error,
8586
8587    /// `ON OVERFLOW TRUNCATE [ <filler> ] WITH[OUT] COUNT`
8588    Truncate {
8589        /// Optional filler expression used when truncating.
8590        filler: Option<Box<Expr>>,
8591        /// Whether to include a count when truncating.
8592        with_count: bool,
8593    },
8594}
8595
8596impl fmt::Display for ListAggOnOverflow {
8597    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8598        write!(f, "ON OVERFLOW")?;
8599        match self {
8600            ListAggOnOverflow::Error => write!(f, " ERROR"),
8601            ListAggOnOverflow::Truncate { filler, with_count } => {
8602                write!(f, " TRUNCATE")?;
8603                if let Some(filler) = filler {
8604                    write!(f, " {filler}")?;
8605                }
8606                if *with_count {
8607                    write!(f, " WITH")?;
8608                } else {
8609                    write!(f, " WITHOUT")?;
8610                }
8611                write!(f, " COUNT")
8612            }
8613        }
8614    }
8615}
8616
8617/// The `HAVING` clause in a call to `ANY_VALUE` on BigQuery.
8618#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8619#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8620#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8621pub struct HavingBound(pub HavingBoundKind, pub Expr);
8622
8623impl fmt::Display for HavingBound {
8624    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8625        write!(f, "HAVING {} {}", self.0, self.1)
8626    }
8627}
8628
8629#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8630#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8631#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8632/// Which bound is used in a HAVING clause for ANY_VALUE on BigQuery.
8633pub enum HavingBoundKind {
8634    /// The minimum bound.
8635    Min,
8636    /// The maximum bound.
8637    Max,
8638}
8639
8640impl fmt::Display for HavingBoundKind {
8641    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8642        match self {
8643            HavingBoundKind::Min => write!(f, "MIN"),
8644            HavingBoundKind::Max => write!(f, "MAX"),
8645        }
8646    }
8647}
8648
8649#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8650#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8651#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8652/// Types of database objects referenced by DDL statements.
8653pub enum ObjectType {
8654    /// A collation.
8655    Collation,
8656    /// A table.
8657    Table,
8658    /// A view.
8659    View,
8660    /// A materialized view.
8661    MaterializedView,
8662    /// An index.
8663    Index,
8664    /// A schema.
8665    Schema,
8666    /// A database.
8667    Database,
8668    /// A role.
8669    Role,
8670    /// A sequence.
8671    Sequence,
8672    /// A stage.
8673    Stage,
8674    /// A type definition.
8675    Type,
8676    /// A user.
8677    User,
8678    /// A stream.
8679    Stream,
8680    /// A warehouse.
8681    Warehouse,
8682}
8683
8684impl fmt::Display for ObjectType {
8685    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8686        f.write_str(match self {
8687            ObjectType::Collation => "COLLATION",
8688            ObjectType::Table => "TABLE",
8689            ObjectType::View => "VIEW",
8690            ObjectType::MaterializedView => "MATERIALIZED VIEW",
8691            ObjectType::Index => "INDEX",
8692            ObjectType::Schema => "SCHEMA",
8693            ObjectType::Database => "DATABASE",
8694            ObjectType::Role => "ROLE",
8695            ObjectType::Sequence => "SEQUENCE",
8696            ObjectType::Stage => "STAGE",
8697            ObjectType::Type => "TYPE",
8698            ObjectType::User => "USER",
8699            ObjectType::Stream => "STREAM",
8700            ObjectType::Warehouse => "WAREHOUSE",
8701        })
8702    }
8703}
8704
8705#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8706#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8707#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8708/// Types supported by `KILL` statements.
8709pub enum KillType {
8710    /// Kill a connection.
8711    Connection,
8712    /// Kill a running query.
8713    Query,
8714    /// Kill a mutation (ClickHouse).
8715    Mutation,
8716}
8717
8718impl fmt::Display for KillType {
8719    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8720        f.write_str(match self {
8721            // MySQL
8722            KillType::Connection => "CONNECTION",
8723            KillType::Query => "QUERY",
8724            // Clickhouse supports Mutation
8725            KillType::Mutation => "MUTATION",
8726        })
8727    }
8728}
8729
8730#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8731#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8732#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8733/// Distribution style options for Hive tables.
8734pub enum HiveDistributionStyle {
8735    /// Partitioned distribution with the given columns.
8736    PARTITIONED {
8737        /// Columns used for partitioning.
8738        columns: Vec<ColumnDef>,
8739    },
8740    /// Skewed distribution definition.
8741    SKEWED {
8742        /// Columns participating in the skew definition.
8743        columns: Vec<ColumnDef>,
8744        /// Columns listed in the `ON` clause for skewing.
8745        on: Vec<ColumnDef>,
8746        /// Whether skewed data is stored as directories.
8747        stored_as_directories: bool,
8748    },
8749    /// No distribution style specified.
8750    NONE,
8751}
8752
8753#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8754#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8755#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8756/// Row format specification for Hive tables (SERDE or DELIMITED).
8757pub enum HiveRowFormat {
8758    /// SerDe class specification with the implementing class name.
8759    SERDE {
8760        /// The SerDe implementation class name.
8761        class: String,
8762    },
8763    /// Delimited row format with one or more delimiter specifications.
8764    DELIMITED {
8765        /// The list of delimiters used for delimiting fields/lines.
8766        delimiters: Vec<HiveRowDelimiter>,
8767    },
8768}
8769
8770#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8771#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8772#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8773/// Format specification for `LOAD DATA` Hive operations.
8774pub struct HiveLoadDataFormat {
8775    /// SerDe expression used for the table.
8776    pub serde: Expr,
8777    /// Input format expression.
8778    pub input_format: Expr,
8779}
8780
8781#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8782#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8783#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8784/// A single row delimiter specification for Hive `ROW FORMAT`.
8785pub struct HiveRowDelimiter {
8786    /// The delimiter kind (fields/lines/etc.).
8787    pub delimiter: HiveDelimiter,
8788    /// The delimiter character identifier.
8789    pub char: Ident,
8790}
8791
8792impl fmt::Display for HiveRowDelimiter {
8793    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8794        write!(f, "{} ", self.delimiter)?;
8795        write!(f, "{}", self.char)
8796    }
8797}
8798
8799#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8800#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8801#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8802/// Kind of delimiter used in Hive `ROW FORMAT` definitions.
8803pub enum HiveDelimiter {
8804    /// Fields terminated by a delimiter.
8805    FieldsTerminatedBy,
8806    /// Fields escaped by a character.
8807    FieldsEscapedBy,
8808    /// Collection items terminated by a delimiter.
8809    CollectionItemsTerminatedBy,
8810    /// Map keys terminated by a delimiter.
8811    MapKeysTerminatedBy,
8812    /// Lines terminated by a delimiter.
8813    LinesTerminatedBy,
8814    /// Null represented by a specific token.
8815    NullDefinedAs,
8816}
8817
8818impl fmt::Display for HiveDelimiter {
8819    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8820        use HiveDelimiter::*;
8821        f.write_str(match self {
8822            FieldsTerminatedBy => "FIELDS TERMINATED BY",
8823            FieldsEscapedBy => "ESCAPED BY",
8824            CollectionItemsTerminatedBy => "COLLECTION ITEMS TERMINATED BY",
8825            MapKeysTerminatedBy => "MAP KEYS TERMINATED BY",
8826            LinesTerminatedBy => "LINES TERMINATED BY",
8827            NullDefinedAs => "NULL DEFINED AS",
8828        })
8829    }
8830}
8831
8832#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8833#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8834#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8835/// Describe output format options for Hive `DESCRIBE`/`EXPLAIN`.
8836pub enum HiveDescribeFormat {
8837    /// Extended describe output.
8838    Extended,
8839    /// Formatted describe output.
8840    Formatted,
8841}
8842
8843impl fmt::Display for HiveDescribeFormat {
8844    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8845        use HiveDescribeFormat::*;
8846        f.write_str(match self {
8847            Extended => "EXTENDED",
8848            Formatted => "FORMATTED",
8849        })
8850    }
8851}
8852
8853#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8854#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8855#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8856/// Aliases accepted for describe-style commands.
8857pub enum DescribeAlias {
8858    /// `DESCRIBE` alias.
8859    Describe,
8860    /// `EXPLAIN` alias.
8861    Explain,
8862    /// `DESC` alias.
8863    Desc,
8864}
8865
8866impl fmt::Display for DescribeAlias {
8867    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8868        use DescribeAlias::*;
8869        f.write_str(match self {
8870            Describe => "DESCRIBE",
8871            Explain => "EXPLAIN",
8872            Desc => "DESC",
8873        })
8874    }
8875}
8876
8877#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8878#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8879#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8880#[allow(clippy::large_enum_variant)]
8881/// Hive input/output format specification used in `CREATE TABLE`.
8882pub enum HiveIOFormat {
8883    /// Generic IO format with separate input and output expressions.
8884    IOF {
8885        /// Expression for the input format.
8886        input_format: Expr,
8887        /// Expression for the output format.
8888        output_format: Expr,
8889    },
8890    /// File format wrapper referencing a `FileFormat` variant.
8891    FileFormat {
8892        /// The file format used for storage.
8893        format: FileFormat,
8894    },
8895    /// `USING <format>` syntax used by Spark SQL.
8896    ///
8897    /// Example: `CREATE TABLE t (i INT) USING PARQUET`
8898    ///
8899    /// See <https://spark.apache.org/docs/latest/sql-ref-syntax-ddl-create-table-datasource.html>
8900    Using {
8901        /// The data source or format name, e.g. `parquet`, `delta`, `csv`.
8902        format: Ident,
8903    },
8904}
8905
8906#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Default)]
8907#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8908#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8909/// Hive table format and storage-related options.
8910pub struct HiveFormat {
8911    /// Optional row format specification.
8912    pub row_format: Option<HiveRowFormat>,
8913    /// Optional SerDe properties expressed as SQL options.
8914    pub serde_properties: Option<Vec<SqlOption>>,
8915    /// Optional input/output storage format details.
8916    pub storage: Option<HiveIOFormat>,
8917    /// Optional location (URI or path) for table data.
8918    pub location: Option<String>,
8919}
8920
8921#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8922#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8923#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8924/// A clustered index column specification.
8925pub struct ClusteredIndex {
8926    /// Column identifier for the clustered index entry.
8927    pub name: Ident,
8928    /// Optional sort direction: `Some(true)` for ASC, `Some(false)` for DESC, `None` for unspecified.
8929    pub asc: Option<bool>,
8930}
8931
8932impl fmt::Display for ClusteredIndex {
8933    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8934        write!(f, "{}", self.name)?;
8935        match self.asc {
8936            Some(true) => write!(f, " ASC"),
8937            Some(false) => write!(f, " DESC"),
8938            _ => Ok(()),
8939        }
8940    }
8941}
8942
8943#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8944#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8945#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8946/// Clustered options used for `CREATE TABLE` clustered/indexed storage.
8947pub enum TableOptionsClustered {
8948    /// Use a columnstore index.
8949    ColumnstoreIndex,
8950    /// Columnstore index with an explicit ordering of columns.
8951    ColumnstoreIndexOrder(Vec<Ident>),
8952    /// A named clustered index with one or more columns.
8953    Index(Vec<ClusteredIndex>),
8954}
8955
8956impl fmt::Display for TableOptionsClustered {
8957    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8958        match self {
8959            TableOptionsClustered::ColumnstoreIndex => {
8960                write!(f, "CLUSTERED COLUMNSTORE INDEX")
8961            }
8962            TableOptionsClustered::ColumnstoreIndexOrder(values) => {
8963                write!(
8964                    f,
8965                    "CLUSTERED COLUMNSTORE INDEX ORDER ({})",
8966                    display_comma_separated(values)
8967                )
8968            }
8969            TableOptionsClustered::Index(values) => {
8970                write!(f, "CLUSTERED INDEX ({})", display_comma_separated(values))
8971            }
8972        }
8973    }
8974}
8975
8976/// Specifies which partition the boundary values on table partitioning belongs to.
8977#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash)]
8978#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8979#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8980pub enum PartitionRangeDirection {
8981    /// LEFT range direction.
8982    Left,
8983    /// RIGHT range direction.
8984    Right,
8985}
8986
8987#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8988#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8989#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8990/// SQL option syntax used in table and server definitions.
8991pub enum SqlOption {
8992    /// Clustered represents the clustered version of table storage for MSSQL.
8993    ///
8994    /// <https://learn.microsoft.com/en-us/sql/t-sql/statements/create-table-azure-sql-data-warehouse?view=aps-pdw-2016-au7#TableOptions>
8995    Clustered(TableOptionsClustered),
8996    /// Single identifier options, e.g. `HEAP` for MSSQL.
8997    ///
8998    /// <https://learn.microsoft.com/en-us/sql/t-sql/statements/create-table-azure-sql-data-warehouse?view=aps-pdw-2016-au7#TableOptions>
8999    Ident(Ident),
9000    /// Any option that consists of a key value pair where the value is an expression. e.g.
9001    ///
9002    ///   WITH(DISTRIBUTION = ROUND_ROBIN)
9003    KeyValue {
9004        /// The option key identifier.
9005        key: Ident,
9006        /// The expression value for the option.
9007        value: Expr,
9008    },
9009    /// One or more table partitions and represents which partition the boundary values belong to,
9010    /// e.g.
9011    ///
9012    ///   PARTITION (id RANGE LEFT FOR VALUES (10, 20, 30, 40))
9013    ///
9014    /// <https://learn.microsoft.com/en-us/sql/t-sql/statements/create-table-azure-sql-data-warehouse?view=aps-pdw-2016-au7#TablePartitionOptions>
9015    Partition {
9016        /// The partition column name.
9017        column_name: Ident,
9018        /// Optional direction for the partition range (LEFT/RIGHT).
9019        range_direction: Option<PartitionRangeDirection>,
9020        /// Values that define the partition boundaries.
9021        for_values: Vec<Expr>,
9022    },
9023    /// Comment parameter (supports `=` and no `=` syntax)
9024    Comment(CommentDef),
9025    /// MySQL TableSpace option
9026    /// <https://dev.mysql.com/doc/refman/8.4/en/create-table.html>
9027    TableSpace(TablespaceOption),
9028    /// An option representing a key value pair, where the value is a parenthesized list and with an optional name
9029    /// e.g.
9030    ///
9031    ///   UNION  = (tbl_name\[,tbl_name\]...) <https://dev.mysql.com/doc/refman/8.4/en/create-table.html>
9032    ///   ENGINE = ReplicatedMergeTree('/table_name','{replica}', ver) <https://clickhouse.com/docs/engines/table-engines/mergetree-family/replication>
9033    ///   ENGINE = SummingMergeTree(\[columns\]) <https://clickhouse.com/docs/engines/table-engines/mergetree-family/summingmergetree>
9034    NamedParenthesizedList(NamedParenthesizedList),
9035}
9036
9037impl fmt::Display for SqlOption {
9038    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9039        match self {
9040            SqlOption::Clustered(c) => write!(f, "{c}"),
9041            SqlOption::Ident(ident) => {
9042                write!(f, "{ident}")
9043            }
9044            SqlOption::KeyValue { key: name, value } => {
9045                write!(f, "{name} = {value}")
9046            }
9047            SqlOption::Partition {
9048                column_name,
9049                range_direction,
9050                for_values,
9051            } => {
9052                let direction = match range_direction {
9053                    Some(PartitionRangeDirection::Left) => " LEFT",
9054                    Some(PartitionRangeDirection::Right) => " RIGHT",
9055                    None => "",
9056                };
9057
9058                write!(
9059                    f,
9060                    "PARTITION ({} RANGE{} FOR VALUES ({}))",
9061                    column_name,
9062                    direction,
9063                    display_comma_separated(for_values)
9064                )
9065            }
9066            SqlOption::TableSpace(tablespace_option) => {
9067                write!(f, "TABLESPACE {}", tablespace_option.name)?;
9068                match tablespace_option.storage {
9069                    Some(StorageType::Disk) => write!(f, " STORAGE DISK"),
9070                    Some(StorageType::Memory) => write!(f, " STORAGE MEMORY"),
9071                    None => Ok(()),
9072                }
9073            }
9074            SqlOption::Comment(comment) => match comment {
9075                CommentDef::WithEq(comment) => {
9076                    write!(f, "COMMENT = '{comment}'")
9077                }
9078                CommentDef::WithoutEq(comment) => {
9079                    write!(f, "COMMENT '{comment}'")
9080                }
9081            },
9082            SqlOption::NamedParenthesizedList(value) => {
9083                write!(f, "{} = ", value.key)?;
9084                if let Some(key) = &value.name {
9085                    write!(f, "{key}")?;
9086                }
9087                if !value.values.is_empty() {
9088                    write!(f, "({})", display_comma_separated(&value.values))?
9089                }
9090                Ok(())
9091            }
9092        }
9093    }
9094}
9095
9096#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
9097#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9098#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9099/// Storage type options for a tablespace.
9100pub enum StorageType {
9101    /// Store on disk.
9102    Disk,
9103    /// Store in memory.
9104    Memory,
9105}
9106
9107#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
9108#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9109#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9110/// MySql TableSpace option
9111/// <https://dev.mysql.com/doc/refman/8.4/en/create-table.html>
9112pub struct TablespaceOption {
9113    /// Name of the tablespace.
9114    pub name: String,
9115    /// Optional storage type for the tablespace.
9116    pub storage: Option<StorageType>,
9117}
9118
9119#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9120#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9121#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9122/// A key/value identifier pair used for secret or key-based options.
9123pub struct SecretOption {
9124    /// The option key identifier.
9125    pub key: Ident,
9126    /// The option value identifier.
9127    pub value: Ident,
9128}
9129
9130impl fmt::Display for SecretOption {
9131    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9132        write!(f, "{} {}", self.key, self.value)
9133    }
9134}
9135
9136/// A `CREATE SERVER` statement.
9137///
9138/// [PostgreSQL Documentation](https://www.postgresql.org/docs/current/sql-createserver.html)
9139#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9140#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9141#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9142pub struct CreateServerStatement {
9143    /// The server name.
9144    pub name: ObjectName,
9145    /// Whether `IF NOT EXISTS` was specified.
9146    pub if_not_exists: bool,
9147    /// Optional server type identifier.
9148    pub server_type: Option<Ident>,
9149    /// Optional server version identifier.
9150    pub version: Option<Ident>,
9151    /// Foreign-data wrapper object name.
9152    pub foreign_data_wrapper: ObjectName,
9153    /// Optional list of server options.
9154    pub options: Option<Vec<CreateServerOption>>,
9155}
9156
9157impl fmt::Display for CreateServerStatement {
9158    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
9159        let CreateServerStatement {
9160            name,
9161            if_not_exists,
9162            server_type,
9163            version,
9164            foreign_data_wrapper,
9165            options,
9166        } = self;
9167
9168        write!(
9169            f,
9170            "CREATE SERVER {if_not_exists}{name} ",
9171            if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
9172        )?;
9173
9174        if let Some(st) = server_type {
9175            write!(f, "TYPE {st} ")?;
9176        }
9177
9178        if let Some(v) = version {
9179            write!(f, "VERSION {v} ")?;
9180        }
9181
9182        write!(f, "FOREIGN DATA WRAPPER {foreign_data_wrapper}")?;
9183
9184        if let Some(o) = options {
9185            write!(f, " OPTIONS ({o})", o = display_comma_separated(o))?;
9186        }
9187
9188        Ok(())
9189    }
9190}
9191
9192/// A key/value option for `CREATE SERVER`.
9193#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9194#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9195#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9196pub struct CreateServerOption {
9197    /// Option key identifier.
9198    pub key: Ident,
9199    /// Option value identifier.
9200    pub value: Ident,
9201}
9202
9203impl fmt::Display for CreateServerOption {
9204    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9205        write!(f, "{} {}", self.key, self.value)
9206    }
9207}
9208
9209#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9210#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9211#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9212/// Options supported by DuckDB for `ATTACH DATABASE`.
9213pub enum AttachDuckDBDatabaseOption {
9214    /// READ_ONLY option, optional boolean value.
9215    ReadOnly(Option<bool>),
9216    /// TYPE option specifying a database type identifier.
9217    Type(Ident),
9218}
9219
9220impl fmt::Display for AttachDuckDBDatabaseOption {
9221    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9222        match self {
9223            AttachDuckDBDatabaseOption::ReadOnly(Some(true)) => write!(f, "READ_ONLY true"),
9224            AttachDuckDBDatabaseOption::ReadOnly(Some(false)) => write!(f, "READ_ONLY false"),
9225            AttachDuckDBDatabaseOption::ReadOnly(None) => write!(f, "READ_ONLY"),
9226            AttachDuckDBDatabaseOption::Type(t) => write!(f, "TYPE {t}"),
9227        }
9228    }
9229}
9230
9231#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9232#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9233#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9234/// Mode for transactions: access mode or isolation level.
9235pub enum TransactionMode {
9236    /// Access mode for a transaction (e.g. `READ ONLY` / `READ WRITE`).
9237    AccessMode(TransactionAccessMode),
9238    /// Isolation level for a transaction (e.g. `SERIALIZABLE`).
9239    IsolationLevel(TransactionIsolationLevel),
9240}
9241
9242impl fmt::Display for TransactionMode {
9243    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9244        use TransactionMode::*;
9245        match self {
9246            AccessMode(access_mode) => write!(f, "{access_mode}"),
9247            IsolationLevel(iso_level) => write!(f, "ISOLATION LEVEL {iso_level}"),
9248        }
9249    }
9250}
9251
9252#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9253#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9254#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9255/// Transaction access mode (READ ONLY / READ WRITE).
9256pub enum TransactionAccessMode {
9257    /// READ ONLY access mode.
9258    ReadOnly,
9259    /// READ WRITE access mode.
9260    ReadWrite,
9261}
9262
9263impl fmt::Display for TransactionAccessMode {
9264    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9265        use TransactionAccessMode::*;
9266        f.write_str(match self {
9267            ReadOnly => "READ ONLY",
9268            ReadWrite => "READ WRITE",
9269        })
9270    }
9271}
9272
9273#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9274#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9275#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9276/// Transaction isolation levels.
9277pub enum TransactionIsolationLevel {
9278    /// READ UNCOMMITTED isolation level.
9279    ReadUncommitted,
9280    /// READ COMMITTED isolation level.
9281    ReadCommitted,
9282    /// REPEATABLE READ isolation level.
9283    RepeatableRead,
9284    /// SERIALIZABLE isolation level.
9285    Serializable,
9286    /// SNAPSHOT isolation level.
9287    Snapshot,
9288}
9289
9290impl fmt::Display for TransactionIsolationLevel {
9291    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9292        use TransactionIsolationLevel::*;
9293        f.write_str(match self {
9294            ReadUncommitted => "READ UNCOMMITTED",
9295            ReadCommitted => "READ COMMITTED",
9296            RepeatableRead => "REPEATABLE READ",
9297            Serializable => "SERIALIZABLE",
9298            Snapshot => "SNAPSHOT",
9299        })
9300    }
9301}
9302
9303/// Modifier for the transaction in the `BEGIN` syntax
9304///
9305/// SQLite: <https://sqlite.org/lang_transaction.html>
9306/// MS-SQL: <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/try-catch-transact-sql>
9307#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9308#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9309#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9310pub enum TransactionModifier {
9311    /// DEFERRED transaction modifier.
9312    Deferred,
9313    /// IMMEDIATE transaction modifier.
9314    Immediate,
9315    /// EXCLUSIVE transaction modifier.
9316    Exclusive,
9317    /// TRY block modifier (MS-SQL style TRY/CATCH).
9318    Try,
9319    /// CATCH block modifier (MS-SQL style TRY/CATCH).
9320    Catch,
9321}
9322
9323impl fmt::Display for TransactionModifier {
9324    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9325        use TransactionModifier::*;
9326        f.write_str(match self {
9327            Deferred => "DEFERRED",
9328            Immediate => "IMMEDIATE",
9329            Exclusive => "EXCLUSIVE",
9330            Try => "TRY",
9331            Catch => "CATCH",
9332        })
9333    }
9334}
9335
9336#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9337#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9338#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9339/// Filter forms usable in SHOW statements.
9340pub enum ShowStatementFilter {
9341    /// Filter using LIKE pattern.
9342    Like(String),
9343    /// Filter using ILIKE pattern.
9344    ILike(String),
9345    /// Filter using a WHERE expression.
9346    Where(Expr),
9347    /// Filter provided without a keyword (raw string).
9348    NoKeyword(String),
9349}
9350
9351impl fmt::Display for ShowStatementFilter {
9352    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9353        use ShowStatementFilter::*;
9354        match self {
9355            Like(pattern) => write!(f, "LIKE '{}'", value::escape_single_quote_string(pattern)),
9356            ILike(pattern) => write!(f, "ILIKE {}", value::escape_single_quote_string(pattern)),
9357            Where(expr) => write!(f, "WHERE {expr}"),
9358            NoKeyword(pattern) => write!(f, "'{}'", value::escape_single_quote_string(pattern)),
9359        }
9360    }
9361}
9362
9363#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9364#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9365#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9366/// Clause types used with SHOW ... IN/FROM.
9367pub enum ShowStatementInClause {
9368    /// Use the `IN` clause.
9369    IN,
9370    /// Use the `FROM` clause.
9371    FROM,
9372}
9373
9374impl fmt::Display for ShowStatementInClause {
9375    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9376        use ShowStatementInClause::*;
9377        match self {
9378            FROM => write!(f, "FROM"),
9379            IN => write!(f, "IN"),
9380        }
9381    }
9382}
9383
9384/// Sqlite specific syntax
9385///
9386/// See [Sqlite documentation](https://sqlite.org/lang_conflict.html)
9387/// for more details.
9388#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9389#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9390#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9391pub enum SqliteOnConflict {
9392    /// Use ROLLBACK on conflict.
9393    Rollback,
9394    /// Use ABORT on conflict.
9395    Abort,
9396    /// Use FAIL on conflict.
9397    Fail,
9398    /// Use IGNORE on conflict.
9399    Ignore,
9400    /// Use REPLACE on conflict.
9401    Replace,
9402}
9403
9404impl fmt::Display for SqliteOnConflict {
9405    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9406        use SqliteOnConflict::*;
9407        match self {
9408            Rollback => write!(f, "OR ROLLBACK"),
9409            Abort => write!(f, "OR ABORT"),
9410            Fail => write!(f, "OR FAIL"),
9411            Ignore => write!(f, "OR IGNORE"),
9412            Replace => write!(f, "OR REPLACE"),
9413        }
9414    }
9415}
9416
9417/// Mysql specific syntax
9418///
9419/// See [Mysql documentation](https://dev.mysql.com/doc/refman/8.0/en/replace.html)
9420/// See [Mysql documentation](https://dev.mysql.com/doc/refman/8.0/en/insert.html)
9421/// for more details.
9422#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9423#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9424#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9425pub enum MysqlInsertPriority {
9426    /// LOW_PRIORITY modifier for INSERT/REPLACE.
9427    LowPriority,
9428    /// DELAYED modifier for INSERT/REPLACE.
9429    Delayed,
9430    /// HIGH_PRIORITY modifier for INSERT/REPLACE.
9431    HighPriority,
9432}
9433
9434impl fmt::Display for crate::ast::MysqlInsertPriority {
9435    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9436        use MysqlInsertPriority::*;
9437        match self {
9438            LowPriority => write!(f, "LOW_PRIORITY"),
9439            Delayed => write!(f, "DELAYED"),
9440            HighPriority => write!(f, "HIGH_PRIORITY"),
9441        }
9442    }
9443}
9444
9445#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9446#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9447#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9448/// Source for the `COPY` command: a table or a query.
9449pub enum CopySource {
9450    /// Copy from a table with optional column list.
9451    Table {
9452        /// The name of the table to copy from.
9453        table_name: ObjectName,
9454        /// A list of column names to copy. Empty list means that all columns
9455        /// are copied.
9456        columns: Vec<Ident>,
9457    },
9458    /// Copy from the results of a query.
9459    Query(Box<Query>),
9460}
9461
9462#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9463#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9464#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9465/// Target for the `COPY` command: STDIN, STDOUT, a file, or a program.
9466pub enum CopyTarget {
9467    /// Use standard input as the source.
9468    Stdin,
9469    /// Use standard output as the target.
9470    Stdout,
9471    /// Read from or write to a file.
9472    File {
9473        /// The path name of the input or output file.
9474        filename: String,
9475    },
9476    /// Use a program as the source or target (shell command).
9477    Program {
9478        /// A command to execute
9479        command: String,
9480    },
9481}
9482
9483impl fmt::Display for CopyTarget {
9484    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9485        use CopyTarget::*;
9486        match self {
9487            Stdin => write!(f, "STDIN"),
9488            Stdout => write!(f, "STDOUT"),
9489            File { filename } => write!(f, "'{}'", value::escape_single_quote_string(filename)),
9490            Program { command } => write!(
9491                f,
9492                "PROGRAM '{}'",
9493                value::escape_single_quote_string(command)
9494            ),
9495        }
9496    }
9497}
9498
9499#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9500#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9501#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9502/// Action to take `ON COMMIT` for temporary tables.
9503pub enum OnCommit {
9504    /// Delete rows on commit.
9505    DeleteRows,
9506    /// Preserve rows on commit.
9507    PreserveRows,
9508    /// Drop the table on commit.
9509    Drop,
9510}
9511
9512/// An option in `COPY` statement.
9513///
9514/// <https://www.postgresql.org/docs/14/sql-copy.html>
9515#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9516#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9517#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9518pub enum CopyOption {
9519    /// FORMAT format_name
9520    Format(Ident),
9521    /// FREEZE \[ boolean \]
9522    Freeze(bool),
9523    /// DELIMITER 'delimiter_character'
9524    Delimiter(char),
9525    /// NULL 'null_string'
9526    Null(String),
9527    /// HEADER \[ boolean \]
9528    Header(bool),
9529    /// QUOTE 'quote_character'
9530    Quote(char),
9531    /// ESCAPE 'escape_character'
9532    Escape(char),
9533    /// FORCE_QUOTE { ( column_name [, ...] ) | * }
9534    ForceQuote(Vec<Ident>),
9535    /// FORCE_NOT_NULL ( column_name [, ...] )
9536    ForceNotNull(Vec<Ident>),
9537    /// FORCE_NULL ( column_name [, ...] )
9538    ForceNull(Vec<Ident>),
9539    /// ENCODING 'encoding_name'
9540    Encoding(String),
9541}
9542
9543impl fmt::Display for CopyOption {
9544    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9545        use CopyOption::*;
9546        match self {
9547            Format(name) => write!(f, "FORMAT {name}"),
9548            Freeze(true) => write!(f, "FREEZE"),
9549            Freeze(false) => write!(f, "FREEZE FALSE"),
9550            Delimiter(char) => write!(f, "DELIMITER '{char}'"),
9551            Null(string) => write!(f, "NULL '{}'", value::escape_single_quote_string(string)),
9552            Header(true) => write!(f, "HEADER"),
9553            Header(false) => write!(f, "HEADER FALSE"),
9554            Quote(char) => write!(f, "QUOTE '{char}'"),
9555            Escape(char) => write!(f, "ESCAPE '{char}'"),
9556            ForceQuote(columns) => write!(f, "FORCE_QUOTE ({})", display_comma_separated(columns)),
9557            ForceNotNull(columns) => {
9558                write!(f, "FORCE_NOT_NULL ({})", display_comma_separated(columns))
9559            }
9560            ForceNull(columns) => write!(f, "FORCE_NULL ({})", display_comma_separated(columns)),
9561            Encoding(name) => write!(f, "ENCODING '{}'", value::escape_single_quote_string(name)),
9562        }
9563    }
9564}
9565
9566/// An option in `COPY` statement before PostgreSQL version 9.0.
9567///
9568/// [PostgreSQL](https://www.postgresql.org/docs/8.4/sql-copy.html)
9569/// [Redshift](https://docs.aws.amazon.com/redshift/latest/dg/r_COPY-alphabetical-parm-list.html)
9570#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9571#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9572#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9573pub enum CopyLegacyOption {
9574    /// ACCEPTANYDATE
9575    AcceptAnyDate,
9576    /// ACCEPTINVCHARS
9577    AcceptInvChars(Option<String>),
9578    /// ADDQUOTES
9579    AddQuotes,
9580    /// ALLOWOVERWRITE
9581    AllowOverwrite,
9582    /// BINARY
9583    Binary,
9584    /// BLANKSASNULL
9585    BlankAsNull,
9586    /// BZIP2
9587    Bzip2,
9588    /// CLEANPATH
9589    CleanPath,
9590    /// COMPUPDATE [ PRESET | { ON | TRUE } | { OFF | FALSE } ]
9591    CompUpdate {
9592        /// Whether the COMPUPDATE PRESET option was used.
9593        preset: bool,
9594        /// Optional enabled flag for COMPUPDATE.
9595        enabled: Option<bool>,
9596    },
9597    /// CSV ...
9598    Csv(Vec<CopyLegacyCsvOption>),
9599    /// DATEFORMAT \[ AS \] {'dateformat_string' | 'auto' }
9600    DateFormat(Option<String>),
9601    /// DELIMITER \[ AS \] 'delimiter_character'
9602    Delimiter(char),
9603    /// EMPTYASNULL
9604    EmptyAsNull,
9605    /// `ENCRYPTED \[ AUTO \]`
9606    Encrypted {
9607        /// Whether `AUTO` was specified for encryption.
9608        auto: bool,
9609    },
9610    /// ESCAPE
9611    Escape,
9612    /// EXTENSION 'extension-name'
9613    Extension(String),
9614    /// FIXEDWIDTH \[ AS \] 'fixedwidth-spec'
9615    FixedWidth(String),
9616    /// GZIP
9617    Gzip,
9618    /// HEADER
9619    Header,
9620    /// IAM_ROLE { DEFAULT | 'arn:aws:iam::123456789:role/role1' }
9621    IamRole(IamRoleKind),
9622    /// IGNOREHEADER \[ AS \] number_rows
9623    IgnoreHeader(u64),
9624    /// JSON \[ AS \] 'json_option'
9625    Json(Option<String>),
9626    /// MANIFEST \[ VERBOSE \]
9627    Manifest {
9628        /// Whether the MANIFEST is verbose.
9629        verbose: bool,
9630    },
9631    /// MAXFILESIZE \[ AS \] max-size \[ MB | GB \]
9632    MaxFileSize(FileSize),
9633    /// `NULL \[ AS \] 'null_string'`
9634    Null(String),
9635    /// `PARALLEL [ { ON | TRUE } | { OFF | FALSE } ]`
9636    Parallel(Option<bool>),
9637    /// PARQUET
9638    Parquet,
9639    /// PARTITION BY ( column_name [, ... ] ) \[ INCLUDE \]
9640    PartitionBy(UnloadPartitionBy),
9641    /// REGION \[ AS \] 'aws-region' }
9642    Region(String),
9643    /// REMOVEQUOTES
9644    RemoveQuotes,
9645    /// ROWGROUPSIZE \[ AS \] size \[ MB | GB \]
9646    RowGroupSize(FileSize),
9647    /// STATUPDATE [ { ON | TRUE } | { OFF | FALSE } ]
9648    StatUpdate(Option<bool>),
9649    /// TIMEFORMAT \[ AS \] {'timeformat_string' | 'auto' | 'epochsecs' | 'epochmillisecs' }
9650    TimeFormat(Option<String>),
9651    /// TRUNCATECOLUMNS
9652    TruncateColumns,
9653    /// ZSTD
9654    Zstd,
9655    /// Redshift `CREDENTIALS 'auth-args'`
9656    /// <https://docs.aws.amazon.com/redshift/latest/dg/copy-parameters-authorization.html>
9657    Credentials(String),
9658}
9659
9660impl fmt::Display for CopyLegacyOption {
9661    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9662        use CopyLegacyOption::*;
9663        match self {
9664            AcceptAnyDate => write!(f, "ACCEPTANYDATE"),
9665            AcceptInvChars(ch) => {
9666                write!(f, "ACCEPTINVCHARS")?;
9667                if let Some(ch) = ch {
9668                    write!(f, " '{}'", value::escape_single_quote_string(ch))?;
9669                }
9670                Ok(())
9671            }
9672            AddQuotes => write!(f, "ADDQUOTES"),
9673            AllowOverwrite => write!(f, "ALLOWOVERWRITE"),
9674            Binary => write!(f, "BINARY"),
9675            BlankAsNull => write!(f, "BLANKSASNULL"),
9676            Bzip2 => write!(f, "BZIP2"),
9677            CleanPath => write!(f, "CLEANPATH"),
9678            CompUpdate { preset, enabled } => {
9679                write!(f, "COMPUPDATE")?;
9680                if *preset {
9681                    write!(f, " PRESET")?;
9682                } else if let Some(enabled) = enabled {
9683                    write!(
9684                        f,
9685                        "{}",
9686                        match enabled {
9687                            true => " TRUE",
9688                            false => " FALSE",
9689                        }
9690                    )?;
9691                }
9692                Ok(())
9693            }
9694            Csv(opts) => {
9695                write!(f, "CSV")?;
9696                if !opts.is_empty() {
9697                    write!(f, " {}", display_separated(opts, " "))?;
9698                }
9699                Ok(())
9700            }
9701            DateFormat(fmt) => {
9702                write!(f, "DATEFORMAT")?;
9703                if let Some(fmt) = fmt {
9704                    write!(f, " '{}'", value::escape_single_quote_string(fmt))?;
9705                }
9706                Ok(())
9707            }
9708            Delimiter(char) => write!(f, "DELIMITER '{char}'"),
9709            EmptyAsNull => write!(f, "EMPTYASNULL"),
9710            Encrypted { auto } => write!(f, "ENCRYPTED{}", if *auto { " AUTO" } else { "" }),
9711            Escape => write!(f, "ESCAPE"),
9712            Extension(ext) => write!(f, "EXTENSION '{}'", value::escape_single_quote_string(ext)),
9713            FixedWidth(spec) => write!(
9714                f,
9715                "FIXEDWIDTH '{}'",
9716                value::escape_single_quote_string(spec)
9717            ),
9718            Gzip => write!(f, "GZIP"),
9719            Header => write!(f, "HEADER"),
9720            IamRole(role) => write!(f, "IAM_ROLE {role}"),
9721            IgnoreHeader(num_rows) => write!(f, "IGNOREHEADER {num_rows}"),
9722            Json(opt) => {
9723                write!(f, "JSON")?;
9724                if let Some(opt) = opt {
9725                    write!(f, " AS '{}'", value::escape_single_quote_string(opt))?;
9726                }
9727                Ok(())
9728            }
9729            Manifest { verbose } => write!(f, "MANIFEST{}", if *verbose { " VERBOSE" } else { "" }),
9730            MaxFileSize(file_size) => write!(f, "MAXFILESIZE {file_size}"),
9731            Null(string) => write!(f, "NULL '{}'", value::escape_single_quote_string(string)),
9732            Parallel(enabled) => {
9733                write!(
9734                    f,
9735                    "PARALLEL{}",
9736                    match enabled {
9737                        Some(true) => " TRUE",
9738                        Some(false) => " FALSE",
9739                        _ => "",
9740                    }
9741                )
9742            }
9743            Parquet => write!(f, "PARQUET"),
9744            PartitionBy(p) => write!(f, "{p}"),
9745            Region(region) => write!(f, "REGION '{}'", value::escape_single_quote_string(region)),
9746            RemoveQuotes => write!(f, "REMOVEQUOTES"),
9747            RowGroupSize(file_size) => write!(f, "ROWGROUPSIZE {file_size}"),
9748            StatUpdate(enabled) => {
9749                write!(
9750                    f,
9751                    "STATUPDATE{}",
9752                    match enabled {
9753                        Some(true) => " TRUE",
9754                        Some(false) => " FALSE",
9755                        _ => "",
9756                    }
9757                )
9758            }
9759            TimeFormat(fmt) => {
9760                write!(f, "TIMEFORMAT")?;
9761                if let Some(fmt) = fmt {
9762                    write!(f, " '{}'", value::escape_single_quote_string(fmt))?;
9763                }
9764                Ok(())
9765            }
9766            TruncateColumns => write!(f, "TRUNCATECOLUMNS"),
9767            Zstd => write!(f, "ZSTD"),
9768            Credentials(s) => write!(f, "CREDENTIALS '{}'", value::escape_single_quote_string(s)),
9769        }
9770    }
9771}
9772
9773/// ```sql
9774/// SIZE \[ MB | GB \]
9775/// ```
9776#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9777#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9778#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9779pub struct FileSize {
9780    /// Numeric size value.
9781    pub size: ValueWithSpan,
9782    /// Optional unit for the size (MB or GB).
9783    pub unit: Option<FileSizeUnit>,
9784}
9785
9786impl fmt::Display for FileSize {
9787    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9788        write!(f, "{}", self.size)?;
9789        if let Some(unit) = &self.unit {
9790            write!(f, " {unit}")?;
9791        }
9792        Ok(())
9793    }
9794}
9795
9796/// Units for `FileSize` (MB or GB).
9797#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9798#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9799#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9800pub enum FileSizeUnit {
9801    /// Megabytes.
9802    MB,
9803    /// Gigabytes.
9804    GB,
9805}
9806
9807impl fmt::Display for FileSizeUnit {
9808    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9809        match self {
9810            FileSizeUnit::MB => write!(f, "MB"),
9811            FileSizeUnit::GB => write!(f, "GB"),
9812        }
9813    }
9814}
9815
9816/// Specifies the partition keys for the unload operation
9817///
9818/// ```sql
9819/// PARTITION BY ( column_name [, ... ] ) [ INCLUDE ]
9820/// ```
9821#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9822#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9823#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9824pub struct UnloadPartitionBy {
9825    /// Columns used to partition the unload output.
9826    pub columns: Vec<Ident>,
9827    /// Whether to include the partition in the output.
9828    pub include: bool,
9829}
9830
9831impl fmt::Display for UnloadPartitionBy {
9832    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9833        write!(
9834            f,
9835            "PARTITION BY ({}){}",
9836            display_comma_separated(&self.columns),
9837            if self.include { " INCLUDE" } else { "" }
9838        )
9839    }
9840}
9841
9842/// An `IAM_ROLE` option in the AWS ecosystem
9843///
9844/// [Redshift COPY](https://docs.aws.amazon.com/redshift/latest/dg/copy-parameters-authorization.html#copy-iam-role)
9845#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9846#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9847#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9848pub enum IamRoleKind {
9849    /// Default role
9850    Default,
9851    /// Specific role ARN, for example: `arn:aws:iam::123456789:role/role1`
9852    Arn(String),
9853}
9854
9855impl fmt::Display for IamRoleKind {
9856    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9857        match self {
9858            IamRoleKind::Default => write!(f, "DEFAULT"),
9859            IamRoleKind::Arn(arn) => write!(f, "'{arn}'"),
9860        }
9861    }
9862}
9863
9864/// A `CSV` option in `COPY` statement before PostgreSQL version 9.0.
9865///
9866/// <https://www.postgresql.org/docs/8.4/sql-copy.html>
9867#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9868#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9869#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9870pub enum CopyLegacyCsvOption {
9871    /// HEADER
9872    Header,
9873    /// QUOTE \[ AS \] 'quote_character'
9874    Quote(char),
9875    /// ESCAPE \[ AS \] 'escape_character'
9876    Escape(char),
9877    /// FORCE QUOTE { column_name [, ...] | * }
9878    ForceQuote(Vec<Ident>),
9879    /// FORCE NOT NULL column_name [, ...]
9880    ForceNotNull(Vec<Ident>),
9881}
9882
9883impl fmt::Display for CopyLegacyCsvOption {
9884    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9885        use CopyLegacyCsvOption::*;
9886        match self {
9887            Header => write!(f, "HEADER"),
9888            Quote(char) => write!(f, "QUOTE '{char}'"),
9889            Escape(char) => write!(f, "ESCAPE '{char}'"),
9890            ForceQuote(columns) => write!(f, "FORCE QUOTE {}", display_comma_separated(columns)),
9891            ForceNotNull(columns) => {
9892                write!(f, "FORCE NOT NULL {}", display_comma_separated(columns))
9893            }
9894        }
9895    }
9896}
9897
9898/// Objects that can be discarded with `DISCARD`.
9899#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9900#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9901#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9902pub enum DiscardObject {
9903    /// Discard all session state.
9904    ALL,
9905    /// Discard cached plans.
9906    PLANS,
9907    /// Discard sequence values.
9908    SEQUENCES,
9909    /// Discard temporary objects.
9910    TEMP,
9911}
9912
9913impl fmt::Display for DiscardObject {
9914    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9915        match self {
9916            DiscardObject::ALL => f.write_str("ALL"),
9917            DiscardObject::PLANS => f.write_str("PLANS"),
9918            DiscardObject::SEQUENCES => f.write_str("SEQUENCES"),
9919            DiscardObject::TEMP => f.write_str("TEMP"),
9920        }
9921    }
9922}
9923
9924/// Types of flush operations supported by `FLUSH`.
9925#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9926#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9927#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9928pub enum FlushType {
9929    /// Flush binary logs.
9930    BinaryLogs,
9931    /// Flush engine logs.
9932    EngineLogs,
9933    /// Flush error logs.
9934    ErrorLogs,
9935    /// Flush general logs.
9936    GeneralLogs,
9937    /// Flush hosts information.
9938    Hosts,
9939    /// Flush logs.
9940    Logs,
9941    /// Flush privileges.
9942    Privileges,
9943    /// Flush optimizer costs.
9944    OptimizerCosts,
9945    /// Flush relay logs.
9946    RelayLogs,
9947    /// Flush slow logs.
9948    SlowLogs,
9949    /// Flush status.
9950    Status,
9951    /// Flush user resources.
9952    UserResources,
9953    /// Flush table data.
9954    Tables,
9955}
9956
9957impl fmt::Display for FlushType {
9958    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9959        match self {
9960            FlushType::BinaryLogs => f.write_str("BINARY LOGS"),
9961            FlushType::EngineLogs => f.write_str("ENGINE LOGS"),
9962            FlushType::ErrorLogs => f.write_str("ERROR LOGS"),
9963            FlushType::GeneralLogs => f.write_str("GENERAL LOGS"),
9964            FlushType::Hosts => f.write_str("HOSTS"),
9965            FlushType::Logs => f.write_str("LOGS"),
9966            FlushType::Privileges => f.write_str("PRIVILEGES"),
9967            FlushType::OptimizerCosts => f.write_str("OPTIMIZER_COSTS"),
9968            FlushType::RelayLogs => f.write_str("RELAY LOGS"),
9969            FlushType::SlowLogs => f.write_str("SLOW LOGS"),
9970            FlushType::Status => f.write_str("STATUS"),
9971            FlushType::UserResources => f.write_str("USER_RESOURCES"),
9972            FlushType::Tables => f.write_str("TABLES"),
9973        }
9974    }
9975}
9976
9977/// Location modifier for flush commands.
9978#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9979#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9980#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9981pub enum FlushLocation {
9982    /// Do not write changes to the binary log.
9983    NoWriteToBinlog,
9984    /// Apply flush locally.
9985    Local,
9986}
9987
9988impl fmt::Display for FlushLocation {
9989    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9990        match self {
9991            FlushLocation::NoWriteToBinlog => f.write_str("NO_WRITE_TO_BINLOG"),
9992            FlushLocation::Local => f.write_str("LOCAL"),
9993        }
9994    }
9995}
9996
9997/// Optional context modifier for statements that can be or `LOCAL`, `GLOBAL`, or `SESSION`.
9998#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9999#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10000#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10001pub enum ContextModifier {
10002    /// `LOCAL` identifier, usually related to transactional states.
10003    Local,
10004    /// `SESSION` identifier
10005    Session,
10006    /// `GLOBAL` identifier
10007    Global,
10008}
10009
10010impl fmt::Display for ContextModifier {
10011    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10012        match self {
10013            Self::Local => {
10014                write!(f, "LOCAL ")
10015            }
10016            Self::Session => {
10017                write!(f, "SESSION ")
10018            }
10019            Self::Global => {
10020                write!(f, "GLOBAL ")
10021            }
10022        }
10023    }
10024}
10025
10026/// Function describe in DROP FUNCTION.
10027#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10028#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10029pub enum DropFunctionOption {
10030    /// `RESTRICT` option for DROP FUNCTION.
10031    Restrict,
10032    /// `CASCADE` option for DROP FUNCTION.
10033    Cascade,
10034}
10035
10036impl fmt::Display for DropFunctionOption {
10037    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10038        match self {
10039            DropFunctionOption::Restrict => write!(f, "RESTRICT "),
10040            DropFunctionOption::Cascade => write!(f, "CASCADE  "),
10041        }
10042    }
10043}
10044
10045/// Generic function description for DROP FUNCTION and CREATE TRIGGER.
10046#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10047#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10048#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10049pub struct FunctionDesc {
10050    /// The function name.
10051    pub name: ObjectName,
10052    /// Optional list of function arguments.
10053    pub args: Option<Vec<OperateFunctionArg>>,
10054}
10055
10056impl fmt::Display for FunctionDesc {
10057    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10058        write!(f, "{}", self.name)?;
10059        if let Some(args) = &self.args {
10060            write!(f, "({})", display_comma_separated(args))?;
10061        }
10062        Ok(())
10063    }
10064}
10065
10066/// Function argument in CREATE OR DROP FUNCTION.
10067#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10068#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10069#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10070pub struct OperateFunctionArg {
10071    /// Optional argument mode (`IN`, `OUT`, `INOUT`).
10072    pub mode: Option<ArgMode>,
10073    /// Optional argument identifier/name.
10074    pub name: Option<Ident>,
10075    /// The data type of the argument.
10076    pub data_type: DataType,
10077    /// Optional default expression for the argument.
10078    pub default_expr: Option<Expr>,
10079}
10080
10081impl OperateFunctionArg {
10082    /// Returns an unnamed argument.
10083    pub fn unnamed(data_type: DataType) -> Self {
10084        Self {
10085            mode: None,
10086            name: None,
10087            data_type,
10088            default_expr: None,
10089        }
10090    }
10091
10092    /// Returns an argument with name.
10093    pub fn with_name(name: &str, data_type: DataType) -> Self {
10094        Self {
10095            mode: None,
10096            name: Some(name.into()),
10097            data_type,
10098            default_expr: None,
10099        }
10100    }
10101}
10102
10103impl fmt::Display for OperateFunctionArg {
10104    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10105        if let Some(mode) = &self.mode {
10106            write!(f, "{mode} ")?;
10107        }
10108        if let Some(name) = &self.name {
10109            write!(f, "{name} ")?;
10110        }
10111        write!(f, "{}", self.data_type)?;
10112        if let Some(default_expr) = &self.default_expr {
10113            write!(f, " = {default_expr}")?;
10114        }
10115        Ok(())
10116    }
10117}
10118
10119/// The mode of an argument in CREATE FUNCTION.
10120#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10121#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10122#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10123pub enum ArgMode {
10124    /// `IN` mode.
10125    In,
10126    /// `OUT` mode.
10127    Out,
10128    /// `INOUT` mode.
10129    InOut,
10130    /// `VARIADIC` mode.
10131    Variadic,
10132}
10133
10134impl fmt::Display for ArgMode {
10135    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10136        match self {
10137            ArgMode::In => write!(f, "IN"),
10138            ArgMode::Out => write!(f, "OUT"),
10139            ArgMode::InOut => write!(f, "INOUT"),
10140            ArgMode::Variadic => write!(f, "VARIADIC"),
10141        }
10142    }
10143}
10144
10145/// These attributes inform the query optimizer about the behavior of the function.
10146#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10147#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10148#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10149pub enum FunctionBehavior {
10150    /// Function is immutable.
10151    Immutable,
10152    /// Function is stable.
10153    Stable,
10154    /// Function is volatile.
10155    Volatile,
10156}
10157
10158impl fmt::Display for FunctionBehavior {
10159    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10160        match self {
10161            FunctionBehavior::Immutable => write!(f, "IMMUTABLE"),
10162            FunctionBehavior::Stable => write!(f, "STABLE"),
10163            FunctionBehavior::Volatile => write!(f, "VOLATILE"),
10164        }
10165    }
10166}
10167
10168/// Security attribute for functions: SECURITY DEFINER or SECURITY INVOKER.
10169///
10170/// [PostgreSQL](https://www.postgresql.org/docs/current/sql-createfunction.html)
10171#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10172#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10173#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10174pub enum FunctionSecurity {
10175    /// Execute the function with the privileges of the user who defined it.
10176    Definer,
10177    /// Execute the function with the privileges of the user who invokes it.
10178    Invoker,
10179}
10180
10181impl fmt::Display for FunctionSecurity {
10182    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10183        match self {
10184            FunctionSecurity::Definer => write!(f, "SECURITY DEFINER"),
10185            FunctionSecurity::Invoker => write!(f, "SECURITY INVOKER"),
10186        }
10187    }
10188}
10189
10190/// Value for a SET configuration parameter in a CREATE FUNCTION statement.
10191///
10192/// [PostgreSQL](https://www.postgresql.org/docs/current/sql-createfunction.html)
10193#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10194#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10195#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10196pub enum FunctionSetValue {
10197    /// SET param = DEFAULT / SET param TO DEFAULT
10198    Default,
10199    /// SET param = value1, value2, ...
10200    Values(Vec<Expr>),
10201    /// SET param FROM CURRENT
10202    FromCurrent,
10203}
10204
10205/// A SET configuration_parameter clause in a CREATE FUNCTION statement.
10206///
10207/// [PostgreSQL](https://www.postgresql.org/docs/current/sql-createfunction.html)
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))]
10211pub struct FunctionDefinitionSetParam {
10212    /// The name of the configuration parameter.
10213    pub name: ObjectName,
10214    /// The value to set for the parameter.
10215    pub value: FunctionSetValue,
10216}
10217
10218impl fmt::Display for FunctionDefinitionSetParam {
10219    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10220        write!(f, "SET {} ", self.name)?;
10221        match &self.value {
10222            FunctionSetValue::Default => write!(f, "= DEFAULT"),
10223            FunctionSetValue::Values(values) => {
10224                write!(f, "= {}", display_comma_separated(values))
10225            }
10226            FunctionSetValue::FromCurrent => write!(f, "FROM CURRENT"),
10227        }
10228    }
10229}
10230
10231/// These attributes describe the behavior of the function when called with a null argument.
10232#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10233#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10234#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10235pub enum FunctionCalledOnNull {
10236    /// Function is called even when inputs are null.
10237    CalledOnNullInput,
10238    /// Function returns null when any input is null.
10239    ReturnsNullOnNullInput,
10240    /// Function is strict about null inputs.
10241    Strict,
10242}
10243
10244impl fmt::Display for FunctionCalledOnNull {
10245    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10246        match self {
10247            FunctionCalledOnNull::CalledOnNullInput => write!(f, "CALLED ON NULL INPUT"),
10248            FunctionCalledOnNull::ReturnsNullOnNullInput => write!(f, "RETURNS NULL ON NULL INPUT"),
10249            FunctionCalledOnNull::Strict => write!(f, "STRICT"),
10250        }
10251    }
10252}
10253
10254/// If it is safe for PostgreSQL to call the function from multiple threads at once
10255#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10256#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10257#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10258pub enum FunctionParallel {
10259    /// The function is not safe to run in parallel.
10260    Unsafe,
10261    /// The function is restricted for parallel execution.
10262    Restricted,
10263    /// The function is safe to run in parallel.
10264    Safe,
10265}
10266
10267impl fmt::Display for FunctionParallel {
10268    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10269        match self {
10270            FunctionParallel::Unsafe => write!(f, "PARALLEL UNSAFE"),
10271            FunctionParallel::Restricted => write!(f, "PARALLEL RESTRICTED"),
10272            FunctionParallel::Safe => write!(f, "PARALLEL SAFE"),
10273        }
10274    }
10275}
10276
10277/// [BigQuery] Determinism specifier used in a UDF definition.
10278///
10279/// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#syntax_11
10280#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10281#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10282#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10283pub enum FunctionDeterminismSpecifier {
10284    /// Function is deterministic.
10285    Deterministic,
10286    /// Function is not deterministic.
10287    NotDeterministic,
10288}
10289
10290impl fmt::Display for FunctionDeterminismSpecifier {
10291    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10292        match self {
10293            FunctionDeterminismSpecifier::Deterministic => {
10294                write!(f, "DETERMINISTIC")
10295            }
10296            FunctionDeterminismSpecifier::NotDeterministic => {
10297                write!(f, "NOT DETERMINISTIC")
10298            }
10299        }
10300    }
10301}
10302
10303/// Represent the expression body of a `CREATE FUNCTION` statement as well as
10304/// where within the statement, the body shows up.
10305///
10306/// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#syntax_11
10307/// [PostgreSQL]: https://www.postgresql.org/docs/15/sql-createfunction.html
10308/// [MsSql]: https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql
10309#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10310#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10311#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10312pub enum CreateFunctionBody {
10313    /// A function body expression using the 'AS' keyword and shows up
10314    /// before any `OPTIONS` clause.
10315    ///
10316    /// Example:
10317    /// ```sql
10318    /// CREATE FUNCTION myfunc(x FLOAT64, y FLOAT64) RETURNS FLOAT64
10319    /// AS (x * y)
10320    /// OPTIONS(description="desc");
10321    /// ```
10322    ///
10323    /// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#syntax_11
10324    /// [PostgreSQL]: https://www.postgresql.org/docs/current/sql-createfunction.html
10325    AsBeforeOptions {
10326        /// The primary expression.
10327        body: Expr,
10328        /// Link symbol if the primary expression contains the name of shared library file.
10329        ///
10330        /// Example:
10331        /// ```sql
10332        /// CREATE FUNCTION cas_in(input cstring) RETURNS cas
10333        /// AS 'MODULE_PATHNAME', 'cas_in_wrapper'
10334        /// ```
10335        /// [PostgreSQL]: https://www.postgresql.org/docs/current/sql-createfunction.html
10336        link_symbol: Option<Expr>,
10337    },
10338    /// A function body expression using the 'AS' keyword and shows up
10339    /// after any `OPTIONS` clause.
10340    ///
10341    /// Example:
10342    /// ```sql
10343    /// CREATE FUNCTION myfunc(x FLOAT64, y FLOAT64) RETURNS FLOAT64
10344    /// OPTIONS(description="desc")
10345    /// AS (x * y);
10346    /// ```
10347    ///
10348    /// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#syntax_11
10349    AsAfterOptions(Expr),
10350    /// Function body with statements before the `RETURN` keyword.
10351    ///
10352    /// Example:
10353    /// ```sql
10354    /// CREATE FUNCTION my_scalar_udf(a INT, b INT)
10355    /// RETURNS INT
10356    /// AS
10357    /// BEGIN
10358    ///     DECLARE c INT;
10359    ///     SET c = a + b;
10360    ///     RETURN c;
10361    /// END
10362    /// ```
10363    ///
10364    /// [MsSql]: https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql
10365    AsBeginEnd(BeginEndStatements),
10366    /// Function body expression using the 'RETURN' keyword.
10367    ///
10368    /// Example:
10369    /// ```sql
10370    /// CREATE FUNCTION myfunc(a INTEGER, IN b INTEGER = 1) RETURNS INTEGER
10371    /// LANGUAGE SQL
10372    /// RETURN a + b;
10373    /// ```
10374    ///
10375    /// [PostgreSQL]: https://www.postgresql.org/docs/current/sql-createfunction.html
10376    Return(Expr),
10377
10378    /// Function body expression using the 'AS RETURN' keywords
10379    ///
10380    /// Example:
10381    /// ```sql
10382    /// CREATE FUNCTION myfunc(a INT, b INT)
10383    /// RETURNS TABLE
10384    /// AS RETURN (SELECT a + b AS sum);
10385    /// ```
10386    ///
10387    /// [MsSql]: https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql
10388    AsReturnExpr(Expr),
10389
10390    /// Function body expression using the 'AS RETURN' keywords, with an un-parenthesized SELECT query
10391    ///
10392    /// Example:
10393    /// ```sql
10394    /// CREATE FUNCTION myfunc(a INT, b INT)
10395    /// RETURNS TABLE
10396    /// AS RETURN SELECT a + b AS sum;
10397    /// ```
10398    ///
10399    /// [MsSql]: https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql?view=sql-server-ver16#select_stmt
10400    AsReturnSelect(Select),
10401}
10402
10403#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10404#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10405#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10406/// `USING` clause options for `CREATE FUNCTION` (e.g., JAR, FILE, ARCHIVE).
10407pub enum CreateFunctionUsing {
10408    /// Use a JAR file located at the given URI.
10409    Jar(String),
10410    /// Use a file located at the given URI.
10411    File(String),
10412    /// Use an archive located at the given URI.
10413    Archive(String),
10414}
10415
10416impl fmt::Display for CreateFunctionUsing {
10417    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10418        write!(f, "USING ")?;
10419        match self {
10420            CreateFunctionUsing::Jar(uri) => write!(f, "JAR '{uri}'"),
10421            CreateFunctionUsing::File(uri) => write!(f, "FILE '{uri}'"),
10422            CreateFunctionUsing::Archive(uri) => write!(f, "ARCHIVE '{uri}'"),
10423        }
10424    }
10425}
10426
10427/// `NAME = <EXPR>` arguments for DuckDB macros
10428///
10429/// See [Create Macro - DuckDB](https://duckdb.org/docs/sql/statements/create_macro)
10430/// for more details
10431#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10432#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10433#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10434pub struct MacroArg {
10435    /// The argument name.
10436    pub name: Ident,
10437    /// Optional default expression for the argument.
10438    pub default_expr: Option<Expr>,
10439}
10440
10441impl MacroArg {
10442    /// Returns an argument with name.
10443    pub fn new(name: &str) -> Self {
10444        Self {
10445            name: name.into(),
10446            default_expr: None,
10447        }
10448    }
10449}
10450
10451impl fmt::Display for MacroArg {
10452    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10453        write!(f, "{}", self.name)?;
10454        if let Some(default_expr) = &self.default_expr {
10455            write!(f, " := {default_expr}")?;
10456        }
10457        Ok(())
10458    }
10459}
10460
10461#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10462#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10463#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10464/// Definition for a DuckDB macro: either an expression or a table-producing query.
10465pub enum MacroDefinition {
10466    /// The macro is defined as an expression.
10467    Expr(Expr),
10468    /// The macro is defined as a table (query).
10469    Table(Box<Query>),
10470}
10471
10472impl fmt::Display for MacroDefinition {
10473    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10474        match self {
10475            MacroDefinition::Expr(expr) => write!(f, "{expr}")?,
10476            MacroDefinition::Table(query) => write!(f, "{query}")?,
10477        }
10478        Ok(())
10479    }
10480}
10481
10482/// Schema possible naming variants ([1]).
10483///
10484/// [1]: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#schema-definition
10485#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10486#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10487#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10488pub enum SchemaName {
10489    /// Only schema name specified: `<schema name>`.
10490    Simple(ObjectName),
10491    /// Only authorization identifier specified: `AUTHORIZATION <schema authorization identifier>`.
10492    UnnamedAuthorization(Ident),
10493    /// Both schema name and authorization identifier specified: `<schema name>  AUTHORIZATION <schema authorization identifier>`.
10494    NamedAuthorization(ObjectName, Ident),
10495}
10496
10497impl fmt::Display for SchemaName {
10498    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10499        match self {
10500            SchemaName::Simple(name) => {
10501                write!(f, "{name}")
10502            }
10503            SchemaName::UnnamedAuthorization(authorization) => {
10504                write!(f, "AUTHORIZATION {authorization}")
10505            }
10506            SchemaName::NamedAuthorization(name, authorization) => {
10507                write!(f, "{name} AUTHORIZATION {authorization}")
10508            }
10509        }
10510    }
10511}
10512
10513/// Fulltext search modifiers ([1]).
10514///
10515/// [1]: https://dev.mysql.com/doc/refman/8.0/en/fulltext-search.html#function_match
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 enum SearchModifier {
10520    /// `IN NATURAL LANGUAGE MODE`.
10521    InNaturalLanguageMode,
10522    /// `IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION`.
10523    InNaturalLanguageModeWithQueryExpansion,
10524    ///`IN BOOLEAN MODE`.
10525    InBooleanMode,
10526    ///`WITH QUERY EXPANSION`.
10527    WithQueryExpansion,
10528}
10529
10530impl fmt::Display for SearchModifier {
10531    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10532        match self {
10533            Self::InNaturalLanguageMode => {
10534                write!(f, "IN NATURAL LANGUAGE MODE")?;
10535            }
10536            Self::InNaturalLanguageModeWithQueryExpansion => {
10537                write!(f, "IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION")?;
10538            }
10539            Self::InBooleanMode => {
10540                write!(f, "IN BOOLEAN MODE")?;
10541            }
10542            Self::WithQueryExpansion => {
10543                write!(f, "WITH QUERY EXPANSION")?;
10544            }
10545        }
10546
10547        Ok(())
10548    }
10549}
10550
10551/// Represents a `LOCK TABLE` clause with optional alias and lock type.
10552#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10553#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10554#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10555pub struct LockTable {
10556    /// The table identifier to lock.
10557    pub table: Ident,
10558    /// Optional alias for the table.
10559    pub alias: Option<Ident>,
10560    /// The type of lock to apply to the table.
10561    pub lock_type: LockTableType,
10562}
10563
10564impl fmt::Display for LockTable {
10565    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10566        let Self {
10567            table: tbl_name,
10568            alias,
10569            lock_type,
10570        } = self;
10571
10572        write!(f, "{tbl_name} ")?;
10573        if let Some(alias) = alias {
10574            write!(f, "AS {alias} ")?;
10575        }
10576        write!(f, "{lock_type}")?;
10577        Ok(())
10578    }
10579}
10580
10581#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10582#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10583#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10584/// The type of lock used in `LOCK TABLE` statements.
10585pub enum LockTableType {
10586    /// Shared/read lock. If `local` is true, it's a local read lock.
10587    Read {
10588        /// Whether the read lock is local.
10589        local: bool,
10590    },
10591    /// Exclusive/write lock. If `low_priority` is true, the write is low priority.
10592    Write {
10593        /// Whether the write lock is low priority.
10594        low_priority: bool,
10595    },
10596}
10597
10598impl fmt::Display for LockTableType {
10599    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10600        match self {
10601            Self::Read { local } => {
10602                write!(f, "READ")?;
10603                if *local {
10604                    write!(f, " LOCAL")?;
10605                }
10606            }
10607            Self::Write { low_priority } => {
10608                if *low_priority {
10609                    write!(f, "LOW_PRIORITY ")?;
10610                }
10611                write!(f, "WRITE")?;
10612            }
10613        }
10614
10615        Ok(())
10616    }
10617}
10618
10619#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10620#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10621#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10622/// Hive-specific `SET LOCATION` helper used in some `LOAD DATA` statements.
10623pub struct HiveSetLocation {
10624    /// Whether the `SET` keyword was present.
10625    pub has_set: bool,
10626    /// The location identifier.
10627    pub location: Ident,
10628}
10629
10630impl fmt::Display for HiveSetLocation {
10631    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10632        if self.has_set {
10633            write!(f, "SET ")?;
10634        }
10635        write!(f, "LOCATION {}", self.location)
10636    }
10637}
10638
10639/// MySQL `ALTER TABLE` only  [FIRST | AFTER column_name]
10640#[allow(clippy::large_enum_variant)]
10641#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10642#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10643#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10644/// MySQL `ALTER TABLE` column position specifier: `FIRST` or `AFTER <column>`.
10645pub enum MySQLColumnPosition {
10646    /// Place the column first in the table.
10647    First,
10648    /// Place the column after the specified identifier.
10649    After(Ident),
10650}
10651
10652impl Display for MySQLColumnPosition {
10653    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10654        match self {
10655            MySQLColumnPosition::First => write!(f, "FIRST"),
10656            MySQLColumnPosition::After(ident) => {
10657                let column_name = &ident.value;
10658                write!(f, "AFTER {column_name}")
10659            }
10660        }
10661    }
10662}
10663
10664/// MySQL `CREATE VIEW` algorithm parameter: [ALGORITHM = {UNDEFINED | MERGE | TEMPTABLE}]
10665#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10666#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10667#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10668/// MySQL `CREATE VIEW` algorithm options.
10669pub enum CreateViewAlgorithm {
10670    /// `UNDEFINED` algorithm.
10671    Undefined,
10672    /// `MERGE` algorithm.
10673    Merge,
10674    /// `TEMPTABLE` algorithm.
10675    TempTable,
10676}
10677
10678impl Display for CreateViewAlgorithm {
10679    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10680        match self {
10681            CreateViewAlgorithm::Undefined => write!(f, "UNDEFINED"),
10682            CreateViewAlgorithm::Merge => write!(f, "MERGE"),
10683            CreateViewAlgorithm::TempTable => write!(f, "TEMPTABLE"),
10684        }
10685    }
10686}
10687/// MySQL `CREATE VIEW` security parameter: [SQL SECURITY { DEFINER | INVOKER }]
10688#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10689#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10690#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10691/// MySQL `CREATE VIEW` SQL SECURITY options.
10692pub enum CreateViewSecurity {
10693    /// The view runs with the privileges of the definer.
10694    Definer,
10695    /// The view runs with the privileges of the invoker.
10696    Invoker,
10697}
10698
10699impl Display for CreateViewSecurity {
10700    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10701        match self {
10702            CreateViewSecurity::Definer => write!(f, "DEFINER"),
10703            CreateViewSecurity::Invoker => write!(f, "INVOKER"),
10704        }
10705    }
10706}
10707
10708/// [MySQL] `CREATE VIEW` additional parameters
10709///
10710/// [MySQL]: https://dev.mysql.com/doc/refman/9.1/en/create-view.html
10711#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10712#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10713#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10714pub struct CreateViewParams {
10715    /// Optional view algorithm (e.g., MERGE, TEMPTABLE).
10716    pub algorithm: Option<CreateViewAlgorithm>,
10717    /// Optional definer (the security principal that will own the view).
10718    pub definer: Option<GranteeName>,
10719    /// Optional SQL SECURITY setting for the view.
10720    pub security: Option<CreateViewSecurity>,
10721}
10722
10723impl Display for CreateViewParams {
10724    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10725        let CreateViewParams {
10726            algorithm,
10727            definer,
10728            security,
10729        } = self;
10730        if let Some(algorithm) = algorithm {
10731            write!(f, "ALGORITHM = {algorithm} ")?;
10732        }
10733        if let Some(definers) = definer {
10734            write!(f, "DEFINER = {definers} ")?;
10735        }
10736        if let Some(security) = security {
10737            write!(f, "SQL SECURITY {security} ")?;
10738        }
10739        Ok(())
10740    }
10741}
10742
10743#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10744#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10745#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10746/// Key/Value, where the value is a (optionally named) list of identifiers
10747///
10748/// ```sql
10749/// UNION = (tbl_name[,tbl_name]...)
10750/// ENGINE = ReplicatedMergeTree('/table_name','{replica}', ver)
10751/// ENGINE = SummingMergeTree([columns])
10752/// ```
10753pub struct NamedParenthesizedList {
10754    /// The option key (identifier) for this named list.
10755    pub key: Ident,
10756    /// Optional secondary name associated with the key.
10757    pub name: Option<Ident>,
10758    /// The list of identifier values for the key.
10759    pub values: Vec<Ident>,
10760}
10761
10762/// Snowflake `WITH ROW ACCESS POLICY policy_name ON (identifier, ...)`
10763///
10764/// <https://docs.snowflake.com/en/sql-reference/sql/create-table>
10765/// <https://docs.snowflake.com/en/user-guide/security-row-intro>
10766#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10767#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10768#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10769pub struct RowAccessPolicy {
10770    /// The fully-qualified policy object name.
10771    pub policy: ObjectName,
10772    /// Identifiers for the columns or objects the policy applies to.
10773    pub on: Vec<Ident>,
10774}
10775
10776impl RowAccessPolicy {
10777    /// Create a new `RowAccessPolicy` for the given `policy` and `on` identifiers.
10778    pub fn new(policy: ObjectName, on: Vec<Ident>) -> Self {
10779        Self { policy, on }
10780    }
10781}
10782
10783impl Display for RowAccessPolicy {
10784    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10785        write!(
10786            f,
10787            "WITH ROW ACCESS POLICY {} ON ({})",
10788            self.policy,
10789            display_comma_separated(self.on.as_slice())
10790        )
10791    }
10792}
10793
10794/// Snowflake `[ WITH ] STORAGE LIFECYCLE POLICY <policy_name> ON ( <col_name> [ , ... ] )`
10795///
10796/// <https://docs.snowflake.com/en/sql-reference/sql/create-table>
10797#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10798#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10799#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10800pub struct StorageLifecyclePolicy {
10801    /// The fully-qualified policy object name.
10802    pub policy: ObjectName,
10803    /// Column names the policy applies to.
10804    pub on: Vec<Ident>,
10805}
10806
10807impl Display for StorageLifecyclePolicy {
10808    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10809        write!(
10810            f,
10811            "WITH STORAGE LIFECYCLE POLICY {} ON ({})",
10812            self.policy,
10813            display_comma_separated(self.on.as_slice())
10814        )
10815    }
10816}
10817
10818/// Snowflake `WITH TAG ( tag_name = '<tag_value>', ...)`
10819///
10820/// <https://docs.snowflake.com/en/sql-reference/sql/create-table>
10821#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10822#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10823#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10824pub struct Tag {
10825    /// The tag key (can be qualified).
10826    pub key: ObjectName,
10827    /// The tag value as a string.
10828    pub value: String,
10829}
10830
10831impl Tag {
10832    /// Create a new `Tag` with the given key and value.
10833    pub fn new(key: ObjectName, value: String) -> Self {
10834        Self { key, value }
10835    }
10836}
10837
10838impl Display for Tag {
10839    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10840        write!(f, "{}='{}'", self.key, self.value)
10841    }
10842}
10843
10844/// Snowflake `WITH CONTACT ( purpose = contact [ , purpose = contact ...] )`
10845///
10846/// <https://docs.snowflake.com/en/sql-reference/sql/create-database>
10847#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10848#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10849#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10850pub struct ContactEntry {
10851    /// The purpose label for the contact entry.
10852    pub purpose: String,
10853    /// The contact information associated with the purpose.
10854    pub contact: String,
10855}
10856
10857impl Display for ContactEntry {
10858    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10859        write!(f, "{} = {}", self.purpose, self.contact)
10860    }
10861}
10862
10863/// Helper to indicate if a comment includes the `=` in the display form
10864#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10865#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10866#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10867pub enum CommentDef {
10868    /// Includes `=` when printing the comment, as `COMMENT = 'comment'`
10869    /// Does not include `=` when printing the comment, as `COMMENT 'comment'`
10870    WithEq(String),
10871    /// Comment variant that omits the `=` when displayed.
10872    WithoutEq(String),
10873}
10874
10875impl Display for CommentDef {
10876    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10877        match self {
10878            CommentDef::WithEq(comment) | CommentDef::WithoutEq(comment) => write!(f, "{comment}"),
10879        }
10880    }
10881}
10882
10883/// Helper to indicate if a collection should be wrapped by a symbol in the display form
10884///
10885/// [`Display`] is implemented for every [`Vec<T>`] where `T: Display`.
10886/// The string output is a comma separated list for the vec items
10887///
10888/// # Examples
10889/// ```
10890/// # use sqlparser::ast::WrappedCollection;
10891/// let items = WrappedCollection::Parentheses(vec!["one", "two", "three"]);
10892/// assert_eq!("(one, two, three)", items.to_string());
10893///
10894/// let items = WrappedCollection::NoWrapping(vec!["one", "two", "three"]);
10895/// assert_eq!("one, two, three", items.to_string());
10896/// ```
10897#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10898#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10899#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10900pub enum WrappedCollection<T> {
10901    /// Print the collection without wrapping symbols, as `item, item, item`
10902    NoWrapping(T),
10903    /// Wraps the collection in Parentheses, as `(item, item, item)`
10904    Parentheses(T),
10905}
10906
10907impl<T> Display for WrappedCollection<Vec<T>>
10908where
10909    T: Display,
10910{
10911    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10912        match self {
10913            WrappedCollection::NoWrapping(inner) => {
10914                write!(f, "{}", display_comma_separated(inner.as_slice()))
10915            }
10916            WrappedCollection::Parentheses(inner) => {
10917                write!(f, "({})", display_comma_separated(inner.as_slice()))
10918            }
10919        }
10920    }
10921}
10922
10923/// Represents a single PostgreSQL utility option.
10924///
10925/// A utility option is a key-value pair where the key is an identifier (IDENT) and the value
10926/// can be one of the following:
10927/// - A number with an optional sign (`+` or `-`). Example: `+10`, `-10.2`, `3`
10928/// - A non-keyword string. Example: `option1`, `'option2'`, `"option3"`
10929/// - keyword: `TRUE`, `FALSE`, `ON` (`off` is also accept).
10930/// - Empty. Example: `ANALYZE` (identifier only)
10931///
10932/// Utility options are used in various PostgreSQL DDL statements, including statements such as
10933/// `CLUSTER`, `EXPLAIN`, `VACUUM`, and `REINDEX`. These statements format options as `( option [, ...] )`.
10934///
10935/// [CLUSTER](https://www.postgresql.org/docs/current/sql-cluster.html)
10936/// [EXPLAIN](https://www.postgresql.org/docs/current/sql-explain.html)
10937/// [VACUUM](https://www.postgresql.org/docs/current/sql-vacuum.html)
10938/// [REINDEX](https://www.postgresql.org/docs/current/sql-reindex.html)
10939///
10940/// For example, the `EXPLAIN` AND `VACUUM` statements with options might look like this:
10941/// ```sql
10942/// EXPLAIN (ANALYZE, VERBOSE TRUE, FORMAT TEXT) SELECT * FROM my_table;
10943///
10944/// VACUUM (VERBOSE, ANALYZE ON, PARALLEL 10) my_table;
10945/// ```
10946#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10947#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10948#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10949pub struct UtilityOption {
10950    /// The option name (identifier).
10951    pub name: Ident,
10952    /// Optional argument for the option (number, string, keyword, etc.).
10953    pub arg: Option<Expr>,
10954}
10955
10956impl Display for UtilityOption {
10957    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10958        if let Some(ref arg) = self.arg {
10959            write!(f, "{} {}", self.name, arg)
10960        } else {
10961            write!(f, "{}", self.name)
10962        }
10963    }
10964}
10965
10966/// Represents the different options available for `SHOW`
10967/// statements to filter the results. Example from Snowflake:
10968/// <https://docs.snowflake.com/en/sql-reference/sql/show-tables>
10969#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10970#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10971#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10972pub struct ShowStatementOptions {
10973    /// Optional scope to show in (for example: TABLE, SCHEMA).
10974    pub show_in: Option<ShowStatementIn>,
10975    /// Optional `STARTS WITH` filter value.
10976    pub starts_with: Option<ValueWithSpan>,
10977    /// Optional `LIMIT` expression.
10978    pub limit: Option<Expr>,
10979    /// Optional `FROM` value used with `LIMIT`.
10980    pub limit_from: Option<ValueWithSpan>,
10981    /// Optional filter position (infix or suffix) for `LIKE`/`FILTER`.
10982    pub filter_position: Option<ShowStatementFilterPosition>,
10983}
10984
10985impl Display for ShowStatementOptions {
10986    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10987        let (like_in_infix, like_in_suffix) = match &self.filter_position {
10988            Some(ShowStatementFilterPosition::Infix(filter)) => {
10989                (format!(" {filter}"), "".to_string())
10990            }
10991            Some(ShowStatementFilterPosition::Suffix(filter)) => {
10992                ("".to_string(), format!(" {filter}"))
10993            }
10994            None => ("".to_string(), "".to_string()),
10995        };
10996        write!(
10997            f,
10998            "{like_in_infix}{show_in}{starts_with}{limit}{from}{like_in_suffix}",
10999            show_in = match &self.show_in {
11000                Some(i) => format!(" {i}"),
11001                None => String::new(),
11002            },
11003            starts_with = match &self.starts_with {
11004                Some(s) => format!(" STARTS WITH {s}"),
11005                None => String::new(),
11006            },
11007            limit = match &self.limit {
11008                Some(l) => format!(" LIMIT {l}"),
11009                None => String::new(),
11010            },
11011            from = match &self.limit_from {
11012                Some(f) => format!(" FROM {f}"),
11013                None => String::new(),
11014            }
11015        )?;
11016        Ok(())
11017    }
11018}
11019
11020#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11021#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11022#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11023/// Where a `SHOW` filter appears relative to the main clause.
11024pub enum ShowStatementFilterPosition {
11025    /// Put the filter in an infix position (e.g. `SHOW COLUMNS LIKE '%name%' IN TABLE tbl`).
11026    Infix(ShowStatementFilter), // For example: SHOW COLUMNS LIKE '%name%' IN TABLE tbl
11027    /// Put the filter in a suffix position (e.g. `SHOW COLUMNS IN tbl LIKE '%name%'`).
11028    Suffix(ShowStatementFilter), // For example: SHOW COLUMNS IN tbl LIKE '%name%'
11029}
11030
11031#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11032#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11033#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11034/// Parent object types usable with `SHOW ... IN <parent>` clauses.
11035pub enum ShowStatementInParentType {
11036    /// ACCOUNT parent type for SHOW statements.
11037    Account,
11038    /// DATABASE parent type for SHOW statements.
11039    Database,
11040    /// SCHEMA parent type for SHOW statements.
11041    Schema,
11042    /// TABLE parent type for SHOW statements.
11043    Table,
11044    /// VIEW parent type for SHOW statements.
11045    View,
11046}
11047
11048impl fmt::Display for ShowStatementInParentType {
11049    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11050        match self {
11051            ShowStatementInParentType::Account => write!(f, "ACCOUNT"),
11052            ShowStatementInParentType::Database => write!(f, "DATABASE"),
11053            ShowStatementInParentType::Schema => write!(f, "SCHEMA"),
11054            ShowStatementInParentType::Table => write!(f, "TABLE"),
11055            ShowStatementInParentType::View => write!(f, "VIEW"),
11056        }
11057    }
11058}
11059
11060#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11061#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11062#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11063/// Represents a `SHOW ... IN` clause with optional parent qualifier and name.
11064pub struct ShowStatementIn {
11065    /// The clause that specifies what to show (e.g. COLUMNS, TABLES).
11066    pub clause: ShowStatementInClause,
11067    /// Optional parent type qualifier (ACCOUNT/DATABASE/...).
11068    pub parent_type: Option<ShowStatementInParentType>,
11069    /// Optional parent object name for the SHOW clause.
11070    #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
11071    pub parent_name: Option<ObjectName>,
11072}
11073
11074impl fmt::Display for ShowStatementIn {
11075    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11076        write!(f, "{}", self.clause)?;
11077        if let Some(parent_type) = &self.parent_type {
11078            write!(f, " {parent_type}")?;
11079        }
11080        if let Some(parent_name) = &self.parent_name {
11081            write!(f, " {parent_name}")?;
11082        }
11083        Ok(())
11084    }
11085}
11086
11087/// A Show Charset statement
11088#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11089#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11090#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11091pub struct ShowCharset {
11092    /// The statement can be written as `SHOW CHARSET` or `SHOW CHARACTER SET`
11093    /// true means CHARSET was used and false means CHARACTER SET was used
11094    pub is_shorthand: bool,
11095    /// Optional `LIKE`/`WHERE`-style filter for the statement.
11096    pub filter: Option<ShowStatementFilter>,
11097}
11098
11099impl fmt::Display for ShowCharset {
11100    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11101        write!(f, "SHOW")?;
11102        if self.is_shorthand {
11103            write!(f, " CHARSET")?;
11104        } else {
11105            write!(f, " CHARACTER SET")?;
11106        }
11107        if let Some(filter) = &self.filter {
11108            write!(f, " {filter}")?;
11109        }
11110        Ok(())
11111    }
11112}
11113
11114#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11115#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11116#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11117/// Options for a `SHOW OBJECTS` statement.
11118pub struct ShowObjects {
11119    /// Whether to show terse output.
11120    pub terse: bool,
11121    /// Additional options controlling the SHOW output.
11122    pub show_options: ShowStatementOptions,
11123}
11124
11125/// MSSQL's json null clause
11126///
11127/// ```plaintext
11128/// <json_null_clause> ::=
11129///       NULL ON NULL
11130///     | ABSENT ON NULL
11131/// ```
11132///
11133/// <https://learn.microsoft.com/en-us/sql/t-sql/functions/json-object-transact-sql?view=sql-server-ver16#json_null_clause>
11134#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11135#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11136#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11137pub enum JsonNullClause {
11138    /// `NULL ON NULL` behavior for JSON functions.
11139    NullOnNull,
11140    /// `ABSENT ON NULL` behavior for JSON functions.
11141    AbsentOnNull,
11142}
11143
11144impl Display for JsonNullClause {
11145    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
11146        match self {
11147            JsonNullClause::NullOnNull => write!(f, "NULL ON NULL"),
11148            JsonNullClause::AbsentOnNull => write!(f, "ABSENT ON NULL"),
11149        }
11150    }
11151}
11152
11153/// PostgreSQL JSON function RETURNING clause
11154///
11155/// Example:
11156/// ```sql
11157/// JSON_OBJECT('a': 1 RETURNING jsonb)
11158/// ```
11159#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11160#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11161#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11162pub struct JsonReturningClause {
11163    /// The data type to return from the JSON function (e.g. JSON/JSONB).
11164    pub data_type: DataType,
11165}
11166
11167impl Display for JsonReturningClause {
11168    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
11169        write!(f, "RETURNING {}", self.data_type)
11170    }
11171}
11172
11173/// rename object definition
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))]
11177pub struct RenameTable {
11178    /// The current name of the object to rename.
11179    pub old_name: ObjectName,
11180    /// The new name for the object.
11181    pub new_name: ObjectName,
11182}
11183
11184impl fmt::Display for RenameTable {
11185    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11186        write!(f, "{} TO {}", self.old_name, self.new_name)?;
11187        Ok(())
11188    }
11189}
11190
11191/// Represents the referenced table in an `INSERT INTO` statement
11192#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11193#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11194#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11195pub enum TableObject {
11196    /// Table specified by name.
11197    /// Example:
11198    /// ```sql
11199    /// INSERT INTO my_table
11200    /// ```
11201    TableName(#[cfg_attr(feature = "visitor", visit(with = "visit_relation"))] ObjectName),
11202
11203    /// Table specified as a function.
11204    /// Example:
11205    /// ```sql
11206    /// INSERT INTO TABLE FUNCTION remote('localhost', default.simple_table)
11207    /// ```
11208    /// [Clickhouse](https://clickhouse.com/docs/en/sql-reference/table-functions)
11209    TableFunction(Function),
11210
11211    /// Table specified through a sub-query
11212    /// Example:
11213    /// ```sql
11214    /// INSERT INTO
11215    /// (SELECT employee_id, last_name, email, hire_date, job_id,  salary, commission_pct FROM employees)
11216    /// VALUES (207, 'Gregory', 'pgregory@example.com', sysdate, 'PU_CLERK', 1.2E3, NULL);
11217    /// ```
11218    /// [Oracle](https://docs.oracle.com/en/database/oracle/oracle-database/21/sqlrf/INSERT.html#GUID-903F8043-0254-4EE9-ACC1-CB8AC0AF3423__I2126242)
11219    TableQuery(Box<Query>),
11220}
11221
11222impl fmt::Display for TableObject {
11223    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11224        match self {
11225            Self::TableName(table_name) => write!(f, "{table_name}"),
11226            Self::TableFunction(func) => write!(f, "FUNCTION {func}"),
11227            Self::TableQuery(table_query) => write!(f, "({table_query})"),
11228        }
11229    }
11230}
11231
11232/// Represents a SET SESSION AUTHORIZATION statement
11233#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11234#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11235#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11236pub struct SetSessionAuthorizationParam {
11237    /// The scope for the `SET SESSION AUTHORIZATION` (e.g., GLOBAL/SESSION).
11238    pub scope: ContextModifier,
11239    /// The specific authorization parameter kind.
11240    pub kind: SetSessionAuthorizationParamKind,
11241}
11242
11243impl fmt::Display for SetSessionAuthorizationParam {
11244    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11245        write!(f, "{}", self.kind)
11246    }
11247}
11248
11249/// Represents the parameter kind for SET SESSION AUTHORIZATION
11250#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11251#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11252#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11253pub enum SetSessionAuthorizationParamKind {
11254    /// Default authorization
11255    Default,
11256
11257    /// User name
11258    User(Ident),
11259}
11260
11261impl fmt::Display for SetSessionAuthorizationParamKind {
11262    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11263        match self {
11264            SetSessionAuthorizationParamKind::Default => write!(f, "DEFAULT"),
11265            SetSessionAuthorizationParamKind::User(name) => write!(f, "{}", name),
11266        }
11267    }
11268}
11269
11270#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11271#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11272#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11273/// Kind of session parameter being set by `SET SESSION`.
11274pub enum SetSessionParamKind {
11275    /// Generic session parameter (name/value pair).
11276    Generic(SetSessionParamGeneric),
11277    /// Identity insert related parameter.
11278    IdentityInsert(SetSessionParamIdentityInsert),
11279    /// Offsets-related parameter.
11280    Offsets(SetSessionParamOffsets),
11281    /// Statistics-related parameter.
11282    Statistics(SetSessionParamStatistics),
11283}
11284
11285impl fmt::Display for SetSessionParamKind {
11286    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11287        match self {
11288            SetSessionParamKind::Generic(x) => write!(f, "{x}"),
11289            SetSessionParamKind::IdentityInsert(x) => write!(f, "{x}"),
11290            SetSessionParamKind::Offsets(x) => write!(f, "{x}"),
11291            SetSessionParamKind::Statistics(x) => write!(f, "{x}"),
11292        }
11293    }
11294}
11295
11296#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11297#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11298#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11299/// Generic `SET SESSION` parameter represented as name(s) and value.
11300pub struct SetSessionParamGeneric {
11301    /// Names of the session parameters being set.
11302    pub names: Vec<String>,
11303    /// The value to assign to the parameter(s).
11304    pub value: String,
11305}
11306
11307impl fmt::Display for SetSessionParamGeneric {
11308    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11309        write!(f, "{} {}", display_comma_separated(&self.names), self.value)
11310    }
11311}
11312
11313#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11314#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11315#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11316/// `IDENTITY_INSERT` session parameter for a specific object.
11317pub struct SetSessionParamIdentityInsert {
11318    /// Object name targeted by `IDENTITY_INSERT`.
11319    pub obj: ObjectName,
11320    /// Value (ON/OFF) for the identity insert setting.
11321    pub value: SessionParamValue,
11322}
11323
11324impl fmt::Display for SetSessionParamIdentityInsert {
11325    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11326        write!(f, "IDENTITY_INSERT {} {}", self.obj, self.value)
11327    }
11328}
11329
11330#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11331#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11332#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11333/// Offsets-related session parameter with keywords and a value.
11334pub struct SetSessionParamOffsets {
11335    /// Keywords specifying which offsets to modify.
11336    pub keywords: Vec<String>,
11337    /// Value (ON/OFF) for the offsets setting.
11338    pub value: SessionParamValue,
11339}
11340
11341impl fmt::Display for SetSessionParamOffsets {
11342    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11343        write!(
11344            f,
11345            "OFFSETS {} {}",
11346            display_comma_separated(&self.keywords),
11347            self.value
11348        )
11349    }
11350}
11351
11352#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11353#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11354#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11355/// Statistics-related session parameter specifying topic and value.
11356pub struct SetSessionParamStatistics {
11357    /// Statistics topic to set (IO/PROFILE/TIME/XML).
11358    pub topic: SessionParamStatsTopic,
11359    /// Value (ON/OFF) for the statistics topic.
11360    pub value: SessionParamValue,
11361}
11362
11363impl fmt::Display for SetSessionParamStatistics {
11364    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11365        write!(f, "STATISTICS {} {}", self.topic, self.value)
11366    }
11367}
11368
11369#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11370#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11371#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11372/// Topics available for session statistics configuration.
11373pub enum SessionParamStatsTopic {
11374    /// Input/output statistics.
11375    IO,
11376    /// Profile statistics.
11377    Profile,
11378    /// Time statistics.
11379    Time,
11380    /// XML-related statistics.
11381    Xml,
11382}
11383
11384impl fmt::Display for SessionParamStatsTopic {
11385    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11386        match self {
11387            SessionParamStatsTopic::IO => write!(f, "IO"),
11388            SessionParamStatsTopic::Profile => write!(f, "PROFILE"),
11389            SessionParamStatsTopic::Time => write!(f, "TIME"),
11390            SessionParamStatsTopic::Xml => write!(f, "XML"),
11391        }
11392    }
11393}
11394
11395#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11396#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11397#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11398/// Value for a session boolean-like parameter (ON/OFF).
11399pub enum SessionParamValue {
11400    /// Session parameter enabled.
11401    On,
11402    /// Session parameter disabled.
11403    Off,
11404}
11405
11406impl fmt::Display for SessionParamValue {
11407    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11408        match self {
11409            SessionParamValue::On => write!(f, "ON"),
11410            SessionParamValue::Off => write!(f, "OFF"),
11411        }
11412    }
11413}
11414
11415/// Snowflake StorageSerializationPolicy for Iceberg Tables
11416/// ```sql
11417/// [ STORAGE_SERIALIZATION_POLICY = { COMPATIBLE | OPTIMIZED } ]
11418/// ```
11419///
11420/// <https://docs.snowflake.com/en/sql-reference/sql/create-iceberg-table>
11421#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11422#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11423#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11424pub enum StorageSerializationPolicy {
11425    /// Use compatible serialization mode.
11426    Compatible,
11427    /// Use optimized serialization mode.
11428    Optimized,
11429}
11430
11431impl Display for StorageSerializationPolicy {
11432    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
11433        match self {
11434            StorageSerializationPolicy::Compatible => write!(f, "COMPATIBLE"),
11435            StorageSerializationPolicy::Optimized => write!(f, "OPTIMIZED"),
11436        }
11437    }
11438}
11439
11440/// Snowflake CatalogSyncNamespaceMode
11441/// ```sql
11442/// [ CATALOG_SYNC_NAMESPACE_MODE = { NEST | FLATTEN } ]
11443/// ```
11444///
11445/// <https://docs.snowflake.com/en/sql-reference/sql/create-database>
11446#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11447#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11448#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11449pub enum CatalogSyncNamespaceMode {
11450    /// Nest namespaces when syncing catalog.
11451    Nest,
11452    /// Flatten namespaces when syncing catalog.
11453    Flatten,
11454}
11455
11456impl Display for CatalogSyncNamespaceMode {
11457    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
11458        match self {
11459            CatalogSyncNamespaceMode::Nest => write!(f, "NEST"),
11460            CatalogSyncNamespaceMode::Flatten => write!(f, "FLATTEN"),
11461        }
11462    }
11463}
11464
11465/// Variants of the Snowflake `COPY INTO` statement
11466#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11467#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11468#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11469pub enum CopyIntoSnowflakeKind {
11470    /// Loads data from files to a table
11471    /// See: <https://docs.snowflake.com/en/sql-reference/sql/copy-into-table>
11472    Table,
11473    /// Unloads data from a table or query to external files
11474    /// See: <https://docs.snowflake.com/en/sql-reference/sql/copy-into-location>
11475    Location,
11476}
11477
11478#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11479#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11480#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11481/// `PRINT` statement for producing debug/output messages.
11482pub struct PrintStatement {
11483    /// The expression producing the message to print.
11484    pub message: Box<Expr>,
11485}
11486
11487impl fmt::Display for PrintStatement {
11488    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11489        write!(f, "PRINT {}", self.message)
11490    }
11491}
11492
11493/// The type of `WAITFOR` statement (MSSQL).
11494///
11495/// See: <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/waitfor-transact-sql>
11496#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11497#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11498#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11499pub enum WaitForType {
11500    /// `WAITFOR DELAY 'time_to_pass'`
11501    Delay,
11502    /// `WAITFOR TIME 'time_to_execute'`
11503    Time,
11504}
11505
11506impl fmt::Display for WaitForType {
11507    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11508        match self {
11509            WaitForType::Delay => write!(f, "DELAY"),
11510            WaitForType::Time => write!(f, "TIME"),
11511        }
11512    }
11513}
11514
11515/// MSSQL `WAITFOR` statement.
11516///
11517/// See: <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/waitfor-transact-sql>
11518#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11519#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11520#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11521pub struct WaitForStatement {
11522    /// `DELAY` or `TIME`.
11523    pub wait_type: WaitForType,
11524    /// The time expression.
11525    pub expr: Expr,
11526}
11527
11528impl fmt::Display for WaitForStatement {
11529    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11530        write!(f, "WAITFOR {} {}", self.wait_type, self.expr)
11531    }
11532}
11533
11534/// Represents a `Return` statement.
11535///
11536/// [MsSql triggers](https://learn.microsoft.com/en-us/sql/t-sql/statements/create-trigger-transact-sql)
11537/// [MsSql functions](https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql)
11538#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11539#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11540#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11541pub struct ReturnStatement {
11542    /// Optional return value expression.
11543    pub value: Option<ReturnStatementValue>,
11544}
11545
11546impl fmt::Display for ReturnStatement {
11547    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11548        match &self.value {
11549            Some(ReturnStatementValue::Expr(expr)) => write!(f, "RETURN {expr}"),
11550            None => write!(f, "RETURN"),
11551        }
11552    }
11553}
11554
11555/// Variants of a `RETURN` statement
11556#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11557#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11558#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11559pub enum ReturnStatementValue {
11560    /// Return an expression from a function or trigger.
11561    Expr(Expr),
11562}
11563
11564/// Represents an `OPEN` statement.
11565#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11566#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11567#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11568pub struct OpenStatement {
11569    /// Cursor name
11570    pub cursor_name: Ident,
11571}
11572
11573impl fmt::Display for OpenStatement {
11574    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11575        write!(f, "OPEN {}", self.cursor_name)
11576    }
11577}
11578
11579/// Specifies Include / Exclude NULL within UNPIVOT command.
11580/// For example
11581/// `UNPIVOT (column1 FOR new_column IN (col3, col4, col5, col6))`
11582#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11583#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11584#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11585pub enum NullInclusion {
11586    /// Include NULL values in the UNPIVOT output.
11587    IncludeNulls,
11588    /// Exclude NULL values from the UNPIVOT output.
11589    ExcludeNulls,
11590}
11591
11592impl fmt::Display for NullInclusion {
11593    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11594        match self {
11595            NullInclusion::IncludeNulls => write!(f, "INCLUDE NULLS"),
11596            NullInclusion::ExcludeNulls => write!(f, "EXCLUDE NULLS"),
11597        }
11598    }
11599}
11600
11601/// Checks membership of a value in a JSON array
11602///
11603/// Syntax:
11604/// ```sql
11605/// <value> MEMBER OF(<array>)
11606/// ```
11607/// [MySQL](https://dev.mysql.com/doc/refman/8.4/en/json-search-functions.html#operator_member-of)
11608#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11609#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11610#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11611pub struct MemberOf {
11612    /// The value to check for membership.
11613    pub value: Box<Expr>,
11614    /// The JSON array expression to check against.
11615    pub array: Box<Expr>,
11616}
11617
11618impl fmt::Display for MemberOf {
11619    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11620        write!(f, "{} MEMBER OF({})", self.value, self.array)
11621    }
11622}
11623
11624#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11625#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11626#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11627/// Represents an `EXPORT DATA` statement.
11628pub struct ExportData {
11629    /// Options for the export operation.
11630    pub options: Vec<SqlOption>,
11631    /// The query producing the data to export.
11632    pub query: Box<Query>,
11633    /// Optional named connection to use for export.
11634    pub connection: Option<ObjectName>,
11635}
11636
11637impl fmt::Display for ExportData {
11638    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11639        if let Some(connection) = &self.connection {
11640            write!(
11641                f,
11642                "EXPORT DATA WITH CONNECTION {connection} OPTIONS({}) AS {}",
11643                display_comma_separated(&self.options),
11644                self.query
11645            )
11646        } else {
11647            write!(
11648                f,
11649                "EXPORT DATA OPTIONS({}) AS {}",
11650                display_comma_separated(&self.options),
11651                self.query
11652            )
11653        }
11654    }
11655}
11656/// Creates a user
11657///
11658/// Syntax:
11659/// ```sql
11660/// CREATE [OR REPLACE] USER [IF NOT EXISTS] <name> [OPTIONS]
11661/// ```
11662///
11663/// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-user)
11664#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11665#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11666#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11667pub struct CreateUser {
11668    /// Replace existing user if present.
11669    pub or_replace: bool,
11670    /// Only create the user if it does not already exist.
11671    pub if_not_exists: bool,
11672    /// The name of the user to create.
11673    pub name: Ident,
11674    /// Key/value options for user creation.
11675    pub options: KeyValueOptions,
11676    /// Whether tags are specified using `WITH TAG`.
11677    pub with_tags: bool,
11678    /// Tags for the user.
11679    pub tags: KeyValueOptions,
11680}
11681
11682impl fmt::Display for CreateUser {
11683    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11684        write!(f, "CREATE")?;
11685        if self.or_replace {
11686            write!(f, " OR REPLACE")?;
11687        }
11688        write!(f, " USER")?;
11689        if self.if_not_exists {
11690            write!(f, " IF NOT EXISTS")?;
11691        }
11692        write!(f, " {}", self.name)?;
11693        if !self.options.options.is_empty() {
11694            write!(f, " {}", self.options)?;
11695        }
11696        if !self.tags.options.is_empty() {
11697            if self.with_tags {
11698                write!(f, " WITH")?;
11699            }
11700            write!(f, " TAG ({})", self.tags)?;
11701        }
11702        Ok(())
11703    }
11704}
11705
11706/// ```sql
11707/// CREATE [ OR REPLACE ] WAREHOUSE [ IF NOT EXISTS ] <name>
11708///   [ [ WITH ] <property> = <value> [ ... ] ]
11709/// ```
11710/// Snowflake-specific statement to create a virtual warehouse.
11711///
11712/// See <https://docs.snowflake.com/en/sql-reference/sql/create-warehouse>
11713#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11714#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11715#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11716pub struct CreateWarehouse {
11717    /// `OR REPLACE` flag.
11718    pub or_replace: bool,
11719    /// `IF NOT EXISTS` flag.
11720    pub if_not_exists: bool,
11721    /// Warehouse name.
11722    pub name: ObjectName,
11723    /// Warehouse properties and parameters (e.g. `WAREHOUSE_SIZE = 'XSMALL'`).
11724    pub options: KeyValueOptions,
11725}
11726
11727impl fmt::Display for CreateWarehouse {
11728    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11729        write!(f, "CREATE")?;
11730        if self.or_replace {
11731            write!(f, " OR REPLACE")?;
11732        }
11733        write!(f, " WAREHOUSE")?;
11734        if self.if_not_exists {
11735            write!(f, " IF NOT EXISTS")?;
11736        }
11737        write!(f, " {}", self.name)?;
11738        if !self.options.options.is_empty() {
11739            write!(f, " {}", self.options)?;
11740        }
11741        Ok(())
11742    }
11743}
11744
11745/// Modifies the properties of a user
11746///
11747/// [Snowflake Syntax:](https://docs.snowflake.com/en/sql-reference/sql/alter-user)
11748/// ```sql
11749/// ALTER USER [ IF EXISTS ] [ <name> ] [ OPTIONS ]
11750/// ```
11751///
11752/// [PostgreSQL Syntax:](https://www.postgresql.org/docs/current/sql-alteruser.html)
11753/// ```sql
11754/// ALTER USER <role_specification> [ WITH ] option [ ... ]
11755/// ```
11756#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11757#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11758#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11759pub struct AlterUser {
11760    /// Whether to only alter the user if it exists.
11761    pub if_exists: bool,
11762    /// The name of the user to alter.
11763    pub name: Ident,
11764    /// Optional new name for the user (Snowflake-specific).
11765    /// See: <https://docs.snowflake.com/en/sql-reference/sql/alter-user#syntax>
11766    pub rename_to: Option<Ident>,
11767    /// Reset the user's password.
11768    pub reset_password: bool,
11769    /// Abort all running queries for the user.
11770    pub abort_all_queries: bool,
11771    /// Optionally add a delegated role authorization.
11772    pub add_role_delegation: Option<AlterUserAddRoleDelegation>,
11773    /// Optionally remove a delegated role authorization.
11774    pub remove_role_delegation: Option<AlterUserRemoveRoleDelegation>,
11775    /// Enroll the user in MFA.
11776    pub enroll_mfa: bool,
11777    /// Set the default MFA method for the user.
11778    pub set_default_mfa_method: Option<MfaMethodKind>,
11779    /// Remove the user's default MFA method.
11780    pub remove_mfa_method: Option<MfaMethodKind>,
11781    /// Modify an MFA method for the user.
11782    pub modify_mfa_method: Option<AlterUserModifyMfaMethod>,
11783    /// Add an MFA OTP method with optional count.
11784    pub add_mfa_method_otp: Option<AlterUserAddMfaMethodOtp>,
11785    /// Set a user policy.
11786    pub set_policy: Option<AlterUserSetPolicy>,
11787    /// Unset a user policy.
11788    pub unset_policy: Option<UserPolicyKind>,
11789    /// Key/value tag options to set on the user.
11790    pub set_tag: KeyValueOptions,
11791    /// Tags to unset on the user.
11792    pub unset_tag: Vec<String>,
11793    /// Key/value properties to set on the user.
11794    pub set_props: KeyValueOptions,
11795    /// Properties to unset on the user.
11796    pub unset_props: Vec<String>,
11797    /// The following options are PostgreSQL-specific: <https://www.postgresql.org/docs/current/sql-alteruser.html>
11798    pub password: Option<AlterUserPassword>,
11799}
11800
11801/// ```sql
11802/// ALTER USER [ IF EXISTS ] [ <name> ] ADD DELEGATED AUTHORIZATION OF ROLE <role_name> TO SECURITY INTEGRATION <integration_name>
11803/// ```
11804#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11805#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11806#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11807pub struct AlterUserAddRoleDelegation {
11808    /// Role name to delegate.
11809    pub role: Ident,
11810    /// Security integration receiving the delegation.
11811    pub integration: Ident,
11812}
11813
11814/// ```sql
11815/// ALTER USER [ IF EXISTS ] [ <name> ] REMOVE DELEGATED { AUTHORIZATION OF ROLE <role_name> | AUTHORIZATIONS } FROM SECURITY INTEGRATION <integration_name>
11816/// ```
11817#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11818#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11819#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11820pub struct AlterUserRemoveRoleDelegation {
11821    /// Optional role name to remove delegation for.
11822    pub role: Option<Ident>,
11823    /// Security integration from which to remove delegation.
11824    pub integration: Ident,
11825}
11826
11827/// ```sql
11828/// ADD MFA METHOD OTP [ COUNT = number ]
11829/// ```
11830#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11831#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11832#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11833pub struct AlterUserAddMfaMethodOtp {
11834    /// Optional OTP count parameter.
11835    pub count: Option<ValueWithSpan>,
11836}
11837
11838/// ```sql
11839/// ALTER USER [ IF EXISTS ] [ <name> ] MODIFY MFA METHOD <mfa_method> SET COMMENT = '<string>'
11840/// ```
11841#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11842#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11843#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11844pub struct AlterUserModifyMfaMethod {
11845    /// The MFA method being modified.
11846    pub method: MfaMethodKind,
11847    /// The new comment for the MFA method.
11848    pub comment: String,
11849}
11850
11851/// Types of MFA methods
11852#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11853#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11854#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11855pub enum MfaMethodKind {
11856    /// PassKey (hardware or platform passkey) MFA method.
11857    PassKey,
11858    /// Time-based One-Time Password (TOTP) MFA method.
11859    Totp,
11860    /// Duo Security MFA method.
11861    Duo,
11862}
11863
11864impl fmt::Display for MfaMethodKind {
11865    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11866        match self {
11867            MfaMethodKind::PassKey => write!(f, "PASSKEY"),
11868            MfaMethodKind::Totp => write!(f, "TOTP"),
11869            MfaMethodKind::Duo => write!(f, "DUO"),
11870        }
11871    }
11872}
11873
11874/// ```sql
11875/// ALTER USER [ IF EXISTS ] [ <name> ] SET { AUTHENTICATION | PASSWORD | SESSION } POLICY <policy_name>
11876/// ```
11877#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11878#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11879#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11880pub struct AlterUserSetPolicy {
11881    /// The kind of user policy being set (authentication/password/session).
11882    pub policy_kind: UserPolicyKind,
11883    /// The identifier of the policy to apply.
11884    pub policy: Ident,
11885}
11886
11887/// Types of user-based policies
11888#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11889#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11890#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11891pub enum UserPolicyKind {
11892    /// Authentication policy.
11893    Authentication,
11894    /// Password policy.
11895    Password,
11896    /// Session policy.
11897    Session,
11898}
11899
11900impl fmt::Display for UserPolicyKind {
11901    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11902        match self {
11903            UserPolicyKind::Authentication => write!(f, "AUTHENTICATION"),
11904            UserPolicyKind::Password => write!(f, "PASSWORD"),
11905            UserPolicyKind::Session => write!(f, "SESSION"),
11906        }
11907    }
11908}
11909
11910impl fmt::Display for AlterUser {
11911    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11912        write!(f, "ALTER")?;
11913        write!(f, " USER")?;
11914        if self.if_exists {
11915            write!(f, " IF EXISTS")?;
11916        }
11917        write!(f, " {}", self.name)?;
11918        if let Some(new_name) = &self.rename_to {
11919            write!(f, " RENAME TO {new_name}")?;
11920        }
11921        if self.reset_password {
11922            write!(f, " RESET PASSWORD")?;
11923        }
11924        if self.abort_all_queries {
11925            write!(f, " ABORT ALL QUERIES")?;
11926        }
11927        if let Some(role_delegation) = &self.add_role_delegation {
11928            let role = &role_delegation.role;
11929            let integration = &role_delegation.integration;
11930            write!(
11931                f,
11932                " ADD DELEGATED AUTHORIZATION OF ROLE {role} TO SECURITY INTEGRATION {integration}"
11933            )?;
11934        }
11935        if let Some(role_delegation) = &self.remove_role_delegation {
11936            write!(f, " REMOVE DELEGATED")?;
11937            match &role_delegation.role {
11938                Some(role) => write!(f, " AUTHORIZATION OF ROLE {role}")?,
11939                None => write!(f, " AUTHORIZATIONS")?,
11940            }
11941            let integration = &role_delegation.integration;
11942            write!(f, " FROM SECURITY INTEGRATION {integration}")?;
11943        }
11944        if self.enroll_mfa {
11945            write!(f, " ENROLL MFA")?;
11946        }
11947        if let Some(method) = &self.set_default_mfa_method {
11948            write!(f, " SET DEFAULT_MFA_METHOD {method}")?
11949        }
11950        if let Some(method) = &self.remove_mfa_method {
11951            write!(f, " REMOVE MFA METHOD {method}")?;
11952        }
11953        if let Some(modify) = &self.modify_mfa_method {
11954            let method = &modify.method;
11955            let comment = &modify.comment;
11956            write!(
11957                f,
11958                " MODIFY MFA METHOD {method} SET COMMENT '{}'",
11959                value::escape_single_quote_string(comment)
11960            )?;
11961        }
11962        if let Some(add_mfa_method_otp) = &self.add_mfa_method_otp {
11963            write!(f, " ADD MFA METHOD OTP")?;
11964            if let Some(count) = &add_mfa_method_otp.count {
11965                write!(f, " COUNT = {count}")?;
11966            }
11967        }
11968        if let Some(policy) = &self.set_policy {
11969            let policy_kind = &policy.policy_kind;
11970            let name = &policy.policy;
11971            write!(f, " SET {policy_kind} POLICY {name}")?;
11972        }
11973        if let Some(policy_kind) = &self.unset_policy {
11974            write!(f, " UNSET {policy_kind} POLICY")?;
11975        }
11976        if !self.set_tag.options.is_empty() {
11977            write!(f, " SET TAG {}", self.set_tag)?;
11978        }
11979        if !self.unset_tag.is_empty() {
11980            write!(f, " UNSET TAG {}", display_comma_separated(&self.unset_tag))?;
11981        }
11982        let has_props = !self.set_props.options.is_empty();
11983        if has_props {
11984            write!(f, " SET")?;
11985            write!(f, " {}", self.set_props)?;
11986        }
11987        if !self.unset_props.is_empty() {
11988            write!(f, " UNSET {}", display_comma_separated(&self.unset_props))?;
11989        }
11990        if let Some(password) = &self.password {
11991            write!(f, " {}", password)?;
11992        }
11993        Ok(())
11994    }
11995}
11996
11997/// ```sql
11998/// ALTER USER <role_specification> [ WITH ] PASSWORD { 'password' | NULL }``
11999/// ```
12000#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
12001#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
12002#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
12003pub struct AlterUserPassword {
12004    /// Whether the password is encrypted.
12005    pub encrypted: bool,
12006    /// The password string, or `None` for `NULL`.
12007    pub password: Option<String>,
12008}
12009
12010impl Display for AlterUserPassword {
12011    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
12012        if self.encrypted {
12013            write!(f, "ENCRYPTED ")?;
12014        }
12015        write!(f, "PASSWORD")?;
12016        match &self.password {
12017            None => write!(f, " NULL")?,
12018            Some(password) => write!(f, " '{}'", value::escape_single_quote_string(password))?,
12019        }
12020        Ok(())
12021    }
12022}
12023
12024/// Specifies how to create a new table based on an existing table's schema.
12025/// '''sql
12026/// CREATE TABLE new LIKE old ...
12027/// '''
12028#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
12029#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
12030#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
12031pub enum CreateTableLikeKind {
12032    /// '''sql
12033    /// CREATE TABLE new (LIKE old ...)
12034    /// '''
12035    /// [Redshift](https://docs.aws.amazon.com/redshift/latest/dg/r_CREATE_TABLE_NEW.html)
12036    Parenthesized(CreateTableLike),
12037    /// '''sql
12038    /// CREATE TABLE new LIKE old ...
12039    /// '''
12040    /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-table#label-create-table-like)
12041    /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_table_like)
12042    Plain(CreateTableLike),
12043}
12044
12045#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
12046#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
12047#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
12048/// Controls whether defaults are included when creating a table FROM/LILE another.
12049pub enum CreateTableLikeDefaults {
12050    /// Include default values from the source table.
12051    Including,
12052    /// Exclude default values from the source table.
12053    Excluding,
12054}
12055
12056impl fmt::Display for CreateTableLikeDefaults {
12057    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
12058        match self {
12059            CreateTableLikeDefaults::Including => write!(f, "INCLUDING DEFAULTS"),
12060            CreateTableLikeDefaults::Excluding => write!(f, "EXCLUDING DEFAULTS"),
12061        }
12062    }
12063}
12064
12065#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
12066#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
12067#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
12068/// Represents the `LIKE` clause of a `CREATE TABLE` statement.
12069pub struct CreateTableLike {
12070    /// The source table name to copy the schema from.
12071    pub name: ObjectName,
12072    /// Optional behavior controlling whether defaults are copied.
12073    pub defaults: Option<CreateTableLikeDefaults>,
12074}
12075
12076impl fmt::Display for CreateTableLike {
12077    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
12078        write!(f, "LIKE {}", self.name)?;
12079        if let Some(defaults) = &self.defaults {
12080            write!(f, " {defaults}")?;
12081        }
12082        Ok(())
12083    }
12084}
12085
12086/// Specifies the refresh mode for the dynamic table.
12087///
12088/// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-dynamic-table)
12089#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
12090#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
12091#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
12092pub enum RefreshModeKind {
12093    /// Automatic refresh mode (`AUTO`).
12094    Auto,
12095    /// Full refresh mode (`FULL`).
12096    Full,
12097    /// Incremental refresh mode (`INCREMENTAL`).
12098    Incremental,
12099}
12100
12101impl fmt::Display for RefreshModeKind {
12102    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
12103        match self {
12104            RefreshModeKind::Auto => write!(f, "AUTO"),
12105            RefreshModeKind::Full => write!(f, "FULL"),
12106            RefreshModeKind::Incremental => write!(f, "INCREMENTAL"),
12107        }
12108    }
12109}
12110
12111/// Specifies the behavior of the initial refresh of the dynamic table.
12112///
12113/// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-dynamic-table)
12114#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
12115#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
12116#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
12117pub enum InitializeKind {
12118    /// Initialize on creation (`ON CREATE`).
12119    OnCreate,
12120    /// Initialize on schedule (`ON SCHEDULE`).
12121    OnSchedule,
12122}
12123
12124impl fmt::Display for InitializeKind {
12125    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
12126        match self {
12127            InitializeKind::OnCreate => write!(f, "ON_CREATE"),
12128            InitializeKind::OnSchedule => write!(f, "ON_SCHEDULE"),
12129        }
12130    }
12131}
12132
12133/// Re-sorts rows and reclaims space in either a specified table or all tables in the current database
12134///
12135/// '''sql
12136/// VACUUM [ FULL | SORT ONLY | DELETE ONLY | REINDEX | RECLUSTER ] [ \[ table_name \] [ TO threshold PERCENT ] \[ BOOST \] ]
12137/// '''
12138/// [Redshift](https://docs.aws.amazon.com/redshift/latest/dg/r_VACUUM_command.html)
12139#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
12140#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
12141#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
12142pub struct VacuumStatement {
12143    /// Whether `FULL` was specified.
12144    pub full: bool,
12145    /// Whether `SORT ONLY` was specified.
12146    pub sort_only: bool,
12147    /// Whether `DELETE ONLY` was specified.
12148    pub delete_only: bool,
12149    /// Whether `REINDEX` was specified.
12150    pub reindex: bool,
12151    /// Whether `RECLUSTER` was specified.
12152    pub recluster: bool,
12153    /// Optional table to run `VACUUM` on.
12154    pub table_name: Option<ObjectName>,
12155    /// Optional threshold value (percent) for `TO threshold PERCENT`.
12156    pub threshold: Option<ValueWithSpan>,
12157    /// Whether `BOOST` was specified.
12158    pub boost: bool,
12159}
12160
12161impl fmt::Display for VacuumStatement {
12162    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
12163        write!(
12164            f,
12165            "VACUUM{}{}{}{}{}",
12166            if self.full { " FULL" } else { "" },
12167            if self.sort_only { " SORT ONLY" } else { "" },
12168            if self.delete_only { " DELETE ONLY" } else { "" },
12169            if self.reindex { " REINDEX" } else { "" },
12170            if self.recluster { " RECLUSTER" } else { "" },
12171        )?;
12172        if let Some(table_name) = &self.table_name {
12173            write!(f, " {table_name}")?;
12174        }
12175        if let Some(threshold) = &self.threshold {
12176            write!(f, " TO {threshold} PERCENT")?;
12177        }
12178        if self.boost {
12179            write!(f, " BOOST")?;
12180        }
12181        Ok(())
12182    }
12183}
12184
12185/// Variants of the RESET statement
12186#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
12187#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
12188#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
12189pub enum Reset {
12190    /// Resets all session parameters to their default values.
12191    ALL,
12192
12193    /// Resets session authorization to the session user.
12194    SessionAuthorization,
12195
12196    /// Resets a specific session parameter to its default value.
12197    ConfigurationParameter(ObjectName),
12198}
12199
12200/// Resets a session parameter to its default value.
12201/// ```sql
12202/// RESET { ALL | SESSION AUTHORIZATION | <configuration_parameter> }
12203/// ```
12204#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
12205#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
12206#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
12207pub struct ResetStatement {
12208    /// The reset action to perform (either `ALL` or a specific configuration parameter).
12209    pub reset: Reset,
12210}
12211
12212/// Query optimizer hints are optionally supported comments after the
12213/// `SELECT`, `INSERT`, `UPDATE`, `REPLACE`, `MERGE`, and `DELETE` keywords in
12214/// the corresponding statements.
12215///
12216/// See [Select::optimizer_hints]
12217#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
12218#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
12219#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
12220pub struct OptimizerHint {
12221    /// An optional prefix between the comment marker and `+`.
12222    ///
12223    /// Standard optimizer hints like `/*+ ... */` have an empty prefix,
12224    /// while system-specific hints like `/*abc+ ... */` have `prefix = "abc"`.
12225    /// The prefix is any sequence of ASCII alphanumeric characters
12226    /// immediately before the `+` marker.
12227    pub prefix: String,
12228    /// the raw text of the optimizer hint without its markers
12229    pub text: String,
12230    /// the style of the comment which `text` was extracted from,
12231    /// e.g. `/*+...*/` or `--+...`
12232    ///
12233    /// Not all dialects support all styles, though.
12234    pub style: OptimizerHintStyle,
12235}
12236
12237/// The commentary style of an [optimizer hint](OptimizerHint)
12238#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
12239#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
12240#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
12241pub enum OptimizerHintStyle {
12242    /// A hint corresponding to a single line comment,
12243    /// e.g. `--+ LEADING(v.e v.d t)`
12244    SingleLine {
12245        /// the comment prefix, e.g. `--`
12246        prefix: String,
12247    },
12248    /// A hint corresponding to a multi line comment,
12249    /// e.g. `/*+ LEADING(v.e v.d t) */`
12250    MultiLine,
12251}
12252
12253impl fmt::Display for OptimizerHint {
12254    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
12255        match &self.style {
12256            OptimizerHintStyle::SingleLine { prefix } => {
12257                f.write_str(prefix)?;
12258                f.write_str(&self.prefix)?;
12259                f.write_str("+")?;
12260                f.write_str(&self.text)?;
12261                f.write_str("\n")
12262            }
12263            OptimizerHintStyle::MultiLine => {
12264                f.write_str("/*")?;
12265                f.write_str(&self.prefix)?;
12266                f.write_str("+")?;
12267                f.write_str(&self.text)?;
12268                f.write_str("*/")
12269            }
12270        }
12271    }
12272}
12273
12274impl fmt::Display for ResetStatement {
12275    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
12276        match &self.reset {
12277            Reset::ALL => write!(f, "RESET ALL"),
12278            Reset::SessionAuthorization => write!(f, "RESET SESSION AUTHORIZATION"),
12279            Reset::ConfigurationParameter(param) => write!(f, "RESET {}", param),
12280        }
12281    }
12282}
12283
12284impl From<Set> for Statement {
12285    fn from(s: Set) -> Self {
12286        Self::Set(s)
12287    }
12288}
12289
12290impl From<Query> for Statement {
12291    fn from(q: Query) -> Self {
12292        Box::new(q).into()
12293    }
12294}
12295
12296impl From<Box<Query>> for Statement {
12297    fn from(q: Box<Query>) -> Self {
12298        Self::Query(q)
12299    }
12300}
12301
12302impl From<Insert> for Statement {
12303    fn from(i: Insert) -> Self {
12304        Self::Insert(i)
12305    }
12306}
12307
12308impl From<Update> for Statement {
12309    fn from(u: Update) -> Self {
12310        Self::Update(u)
12311    }
12312}
12313
12314impl From<CreateView> for Statement {
12315    fn from(cv: CreateView) -> Self {
12316        Self::CreateView(cv)
12317    }
12318}
12319
12320impl From<CreateRole> for Statement {
12321    fn from(cr: CreateRole) -> Self {
12322        Self::CreateRole(cr)
12323    }
12324}
12325
12326impl From<AlterTable> for Statement {
12327    fn from(at: AlterTable) -> Self {
12328        Self::AlterTable(at)
12329    }
12330}
12331
12332impl From<DropFunction> for Statement {
12333    fn from(df: DropFunction) -> Self {
12334        Self::DropFunction(df)
12335    }
12336}
12337
12338impl From<CreateExtension> for Statement {
12339    fn from(ce: CreateExtension) -> Self {
12340        Self::CreateExtension(ce)
12341    }
12342}
12343
12344impl From<CreateCollation> for Statement {
12345    fn from(c: CreateCollation) -> Self {
12346        Self::CreateCollation(c)
12347    }
12348}
12349
12350impl From<DropExtension> for Statement {
12351    fn from(de: DropExtension) -> Self {
12352        Self::DropExtension(de)
12353    }
12354}
12355
12356impl From<CaseStatement> for Statement {
12357    fn from(c: CaseStatement) -> Self {
12358        Self::Case(c)
12359    }
12360}
12361
12362impl From<IfStatement> for Statement {
12363    fn from(i: IfStatement) -> Self {
12364        Self::If(i)
12365    }
12366}
12367
12368impl From<WhileStatement> for Statement {
12369    fn from(w: WhileStatement) -> Self {
12370        Self::While(w)
12371    }
12372}
12373
12374impl From<RaiseStatement> for Statement {
12375    fn from(r: RaiseStatement) -> Self {
12376        Self::Raise(r)
12377    }
12378}
12379
12380impl From<ThrowStatement> for Statement {
12381    fn from(t: ThrowStatement) -> Self {
12382        Self::Throw(t)
12383    }
12384}
12385
12386impl From<Function> for Statement {
12387    fn from(f: Function) -> Self {
12388        Self::Call(f)
12389    }
12390}
12391
12392impl From<OpenStatement> for Statement {
12393    fn from(o: OpenStatement) -> Self {
12394        Self::Open(o)
12395    }
12396}
12397
12398impl From<Delete> for Statement {
12399    fn from(d: Delete) -> Self {
12400        Self::Delete(d)
12401    }
12402}
12403
12404impl From<CreateTable> for Statement {
12405    fn from(c: CreateTable) -> Self {
12406        Self::CreateTable(c)
12407    }
12408}
12409
12410impl From<CreateIndex> for Statement {
12411    fn from(c: CreateIndex) -> Self {
12412        Self::CreateIndex(c)
12413    }
12414}
12415
12416impl From<CreateServerStatement> for Statement {
12417    fn from(c: CreateServerStatement) -> Self {
12418        Self::CreateServer(c)
12419    }
12420}
12421
12422impl From<CreateConnector> for Statement {
12423    fn from(c: CreateConnector) -> Self {
12424        Self::CreateConnector(c)
12425    }
12426}
12427
12428impl From<CreateOperator> for Statement {
12429    fn from(c: CreateOperator) -> Self {
12430        Self::CreateOperator(c)
12431    }
12432}
12433
12434impl From<CreateOperatorFamily> for Statement {
12435    fn from(c: CreateOperatorFamily) -> Self {
12436        Self::CreateOperatorFamily(c)
12437    }
12438}
12439
12440impl From<CreateOperatorClass> for Statement {
12441    fn from(c: CreateOperatorClass) -> Self {
12442        Self::CreateOperatorClass(c)
12443    }
12444}
12445
12446impl From<CreateTextSearch> for Statement {
12447    fn from(c: CreateTextSearch) -> Self {
12448        Self::CreateTextSearch(c)
12449    }
12450}
12451
12452impl From<AlterSchema> for Statement {
12453    fn from(a: AlterSchema) -> Self {
12454        Self::AlterSchema(a)
12455    }
12456}
12457
12458impl From<AlterFunction> for Statement {
12459    fn from(a: AlterFunction) -> Self {
12460        Self::AlterFunction(a)
12461    }
12462}
12463
12464impl From<AlterType> for Statement {
12465    fn from(a: AlterType) -> Self {
12466        Self::AlterType(a)
12467    }
12468}
12469
12470impl From<AlterCollation> for Statement {
12471    fn from(a: AlterCollation) -> Self {
12472        Self::AlterCollation(a)
12473    }
12474}
12475
12476impl From<AlterOperator> for Statement {
12477    fn from(a: AlterOperator) -> Self {
12478        Self::AlterOperator(a)
12479    }
12480}
12481
12482impl From<AlterOperatorFamily> for Statement {
12483    fn from(a: AlterOperatorFamily) -> Self {
12484        Self::AlterOperatorFamily(a)
12485    }
12486}
12487
12488impl From<AlterOperatorClass> for Statement {
12489    fn from(a: AlterOperatorClass) -> Self {
12490        Self::AlterOperatorClass(a)
12491    }
12492}
12493
12494impl From<AlterTextSearch> for Statement {
12495    fn from(a: AlterTextSearch) -> Self {
12496        Self::AlterTextSearch(a)
12497    }
12498}
12499
12500impl From<Merge> for Statement {
12501    fn from(m: Merge) -> Self {
12502        Self::Merge(m)
12503    }
12504}
12505
12506impl From<AlterUser> for Statement {
12507    fn from(a: AlterUser) -> Self {
12508        Self::AlterUser(a)
12509    }
12510}
12511
12512impl From<DropDomain> for Statement {
12513    fn from(d: DropDomain) -> Self {
12514        Self::DropDomain(d)
12515    }
12516}
12517
12518impl From<ShowCharset> for Statement {
12519    fn from(s: ShowCharset) -> Self {
12520        Self::ShowCharset(s)
12521    }
12522}
12523
12524impl From<ShowObjects> for Statement {
12525    fn from(s: ShowObjects) -> Self {
12526        Self::ShowObjects(s)
12527    }
12528}
12529
12530impl From<Use> for Statement {
12531    fn from(u: Use) -> Self {
12532        Self::Use(u)
12533    }
12534}
12535
12536impl From<CreateFunction> for Statement {
12537    fn from(c: CreateFunction) -> Self {
12538        Self::CreateFunction(c)
12539    }
12540}
12541
12542impl From<CreateTrigger> for Statement {
12543    fn from(c: CreateTrigger) -> Self {
12544        Self::CreateTrigger(c)
12545    }
12546}
12547
12548impl From<DropTrigger> for Statement {
12549    fn from(d: DropTrigger) -> Self {
12550        Self::DropTrigger(d)
12551    }
12552}
12553
12554impl From<DropOperator> for Statement {
12555    fn from(d: DropOperator) -> Self {
12556        Self::DropOperator(d)
12557    }
12558}
12559
12560impl From<DropOperatorFamily> for Statement {
12561    fn from(d: DropOperatorFamily) -> Self {
12562        Self::DropOperatorFamily(d)
12563    }
12564}
12565
12566impl From<DropOperatorClass> for Statement {
12567    fn from(d: DropOperatorClass) -> Self {
12568        Self::DropOperatorClass(d)
12569    }
12570}
12571
12572impl From<DenyStatement> for Statement {
12573    fn from(d: DenyStatement) -> Self {
12574        Self::Deny(d)
12575    }
12576}
12577
12578impl From<CreateDomain> for Statement {
12579    fn from(c: CreateDomain) -> Self {
12580        Self::CreateDomain(c)
12581    }
12582}
12583
12584impl From<RenameTable> for Statement {
12585    fn from(r: RenameTable) -> Self {
12586        vec![r].into()
12587    }
12588}
12589
12590impl From<Vec<RenameTable>> for Statement {
12591    fn from(r: Vec<RenameTable>) -> Self {
12592        Self::RenameTable(r)
12593    }
12594}
12595
12596impl From<PrintStatement> for Statement {
12597    fn from(p: PrintStatement) -> Self {
12598        Self::Print(p)
12599    }
12600}
12601
12602impl From<ReturnStatement> for Statement {
12603    fn from(r: ReturnStatement) -> Self {
12604        Self::Return(r)
12605    }
12606}
12607
12608impl From<ExportData> for Statement {
12609    fn from(e: ExportData) -> Self {
12610        Self::ExportData(e)
12611    }
12612}
12613
12614impl From<CreateUser> for Statement {
12615    fn from(c: CreateUser) -> Self {
12616        Self::CreateUser(c)
12617    }
12618}
12619
12620impl From<CreateWarehouse> for Statement {
12621    fn from(c: CreateWarehouse) -> Self {
12622        Self::CreateWarehouse(c)
12623    }
12624}
12625
12626impl From<VacuumStatement> for Statement {
12627    fn from(v: VacuumStatement) -> Self {
12628        Self::Vacuum(v)
12629    }
12630}
12631
12632impl From<ResetStatement> for Statement {
12633    fn from(r: ResetStatement) -> Self {
12634        Self::Reset(r)
12635    }
12636}
12637
12638#[cfg(test)]
12639mod tests {
12640    use crate::tokenizer::Location;
12641
12642    use super::*;
12643
12644    #[test]
12645    fn test_window_frame_default() {
12646        let window_frame = WindowFrame::default();
12647        assert_eq!(WindowFrameBound::Preceding(None), window_frame.start_bound);
12648    }
12649
12650    #[test]
12651    fn test_grouping_sets_display() {
12652        // a and b in different group
12653        let grouping_sets = Expr::GroupingSets(vec![
12654            vec![Expr::Identifier(Ident::new("a"))],
12655            vec![Expr::Identifier(Ident::new("b"))],
12656        ]);
12657        assert_eq!("GROUPING SETS ((a), (b))", format!("{grouping_sets}"));
12658
12659        // a and b in the same group
12660        let grouping_sets = Expr::GroupingSets(vec![vec![
12661            Expr::Identifier(Ident::new("a")),
12662            Expr::Identifier(Ident::new("b")),
12663        ]]);
12664        assert_eq!("GROUPING SETS ((a, b))", format!("{grouping_sets}"));
12665
12666        // (a, b) and (c, d) in different group
12667        let grouping_sets = Expr::GroupingSets(vec![
12668            vec![
12669                Expr::Identifier(Ident::new("a")),
12670                Expr::Identifier(Ident::new("b")),
12671            ],
12672            vec![
12673                Expr::Identifier(Ident::new("c")),
12674                Expr::Identifier(Ident::new("d")),
12675            ],
12676        ]);
12677        assert_eq!("GROUPING SETS ((a, b), (c, d))", format!("{grouping_sets}"));
12678    }
12679
12680    #[test]
12681    fn test_rollup_display() {
12682        let rollup = Expr::Rollup(vec![vec![Expr::Identifier(Ident::new("a"))]]);
12683        assert_eq!("ROLLUP (a)", format!("{rollup}"));
12684
12685        let rollup = Expr::Rollup(vec![vec![
12686            Expr::Identifier(Ident::new("a")),
12687            Expr::Identifier(Ident::new("b")),
12688        ]]);
12689        assert_eq!("ROLLUP ((a, b))", format!("{rollup}"));
12690
12691        let rollup = Expr::Rollup(vec![
12692            vec![Expr::Identifier(Ident::new("a"))],
12693            vec![Expr::Identifier(Ident::new("b"))],
12694        ]);
12695        assert_eq!("ROLLUP (a, b)", format!("{rollup}"));
12696
12697        let rollup = Expr::Rollup(vec![
12698            vec![Expr::Identifier(Ident::new("a"))],
12699            vec![
12700                Expr::Identifier(Ident::new("b")),
12701                Expr::Identifier(Ident::new("c")),
12702            ],
12703            vec![Expr::Identifier(Ident::new("d"))],
12704        ]);
12705        assert_eq!("ROLLUP (a, (b, c), d)", format!("{rollup}"));
12706    }
12707
12708    #[test]
12709    fn test_cube_display() {
12710        let cube = Expr::Cube(vec![vec![Expr::Identifier(Ident::new("a"))]]);
12711        assert_eq!("CUBE (a)", format!("{cube}"));
12712
12713        let cube = Expr::Cube(vec![vec![
12714            Expr::Identifier(Ident::new("a")),
12715            Expr::Identifier(Ident::new("b")),
12716        ]]);
12717        assert_eq!("CUBE ((a, b))", format!("{cube}"));
12718
12719        let cube = Expr::Cube(vec![
12720            vec![Expr::Identifier(Ident::new("a"))],
12721            vec![Expr::Identifier(Ident::new("b"))],
12722        ]);
12723        assert_eq!("CUBE (a, b)", format!("{cube}"));
12724
12725        let cube = Expr::Cube(vec![
12726            vec![Expr::Identifier(Ident::new("a"))],
12727            vec![
12728                Expr::Identifier(Ident::new("b")),
12729                Expr::Identifier(Ident::new("c")),
12730            ],
12731            vec![Expr::Identifier(Ident::new("d"))],
12732        ]);
12733        assert_eq!("CUBE (a, (b, c), d)", format!("{cube}"));
12734    }
12735
12736    #[test]
12737    fn test_interval_display() {
12738        let interval = Expr::Interval(Interval {
12739            value: Box::new(Expr::Value(
12740                Value::SingleQuotedString(String::from("123:45.67")).with_empty_span(),
12741            )),
12742            leading_field: Some(DateTimeField::Minute),
12743            leading_precision: Some(10),
12744            last_field: Some(DateTimeField::Second),
12745            fractional_seconds_precision: Some(9),
12746        });
12747        assert_eq!(
12748            "INTERVAL '123:45.67' MINUTE (10) TO SECOND (9)",
12749            format!("{interval}"),
12750        );
12751
12752        let interval = Expr::Interval(Interval {
12753            value: Box::new(Expr::Value(
12754                Value::SingleQuotedString(String::from("5")).with_empty_span(),
12755            )),
12756            leading_field: Some(DateTimeField::Second),
12757            leading_precision: Some(1),
12758            last_field: None,
12759            fractional_seconds_precision: Some(3),
12760        });
12761        assert_eq!("INTERVAL '5' SECOND (1, 3)", format!("{interval}"));
12762    }
12763
12764    #[test]
12765    fn test_one_or_many_with_parens_deref() {
12766        use core::ops::Index;
12767
12768        let one = OneOrManyWithParens::One("a");
12769
12770        assert_eq!(one.deref(), &["a"]);
12771        assert_eq!(<OneOrManyWithParens<_> as Deref>::deref(&one), &["a"]);
12772
12773        assert_eq!(one[0], "a");
12774        assert_eq!(one.index(0), &"a");
12775        assert_eq!(
12776            <<OneOrManyWithParens<_> as Deref>::Target as Index<usize>>::index(&one, 0),
12777            &"a"
12778        );
12779
12780        assert_eq!(one.len(), 1);
12781        assert_eq!(<OneOrManyWithParens<_> as Deref>::Target::len(&one), 1);
12782
12783        let many1 = OneOrManyWithParens::Many(vec!["b"]);
12784
12785        assert_eq!(many1.deref(), &["b"]);
12786        assert_eq!(<OneOrManyWithParens<_> as Deref>::deref(&many1), &["b"]);
12787
12788        assert_eq!(many1[0], "b");
12789        assert_eq!(many1.index(0), &"b");
12790        assert_eq!(
12791            <<OneOrManyWithParens<_> as Deref>::Target as Index<usize>>::index(&many1, 0),
12792            &"b"
12793        );
12794
12795        assert_eq!(many1.len(), 1);
12796        assert_eq!(<OneOrManyWithParens<_> as Deref>::Target::len(&many1), 1);
12797
12798        let many2 = OneOrManyWithParens::Many(vec!["c", "d"]);
12799
12800        assert_eq!(many2.deref(), &["c", "d"]);
12801        assert_eq!(
12802            <OneOrManyWithParens<_> as Deref>::deref(&many2),
12803            &["c", "d"]
12804        );
12805
12806        assert_eq!(many2[0], "c");
12807        assert_eq!(many2.index(0), &"c");
12808        assert_eq!(
12809            <<OneOrManyWithParens<_> as Deref>::Target as Index<usize>>::index(&many2, 0),
12810            &"c"
12811        );
12812
12813        assert_eq!(many2[1], "d");
12814        assert_eq!(many2.index(1), &"d");
12815        assert_eq!(
12816            <<OneOrManyWithParens<_> as Deref>::Target as Index<usize>>::index(&many2, 1),
12817            &"d"
12818        );
12819
12820        assert_eq!(many2.len(), 2);
12821        assert_eq!(<OneOrManyWithParens<_> as Deref>::Target::len(&many2), 2);
12822    }
12823
12824    #[test]
12825    fn test_one_or_many_with_parens_as_ref() {
12826        let one = OneOrManyWithParens::One("a");
12827
12828        assert_eq!(one.as_ref(), &["a"]);
12829        assert_eq!(<OneOrManyWithParens<_> as AsRef<_>>::as_ref(&one), &["a"]);
12830
12831        let many1 = OneOrManyWithParens::Many(vec!["b"]);
12832
12833        assert_eq!(many1.as_ref(), &["b"]);
12834        assert_eq!(<OneOrManyWithParens<_> as AsRef<_>>::as_ref(&many1), &["b"]);
12835
12836        let many2 = OneOrManyWithParens::Many(vec!["c", "d"]);
12837
12838        assert_eq!(many2.as_ref(), &["c", "d"]);
12839        assert_eq!(
12840            <OneOrManyWithParens<_> as AsRef<_>>::as_ref(&many2),
12841            &["c", "d"]
12842        );
12843    }
12844
12845    #[test]
12846    fn test_one_or_many_with_parens_ref_into_iter() {
12847        let one = OneOrManyWithParens::One("a");
12848
12849        assert_eq!(Vec::from_iter(&one), vec![&"a"]);
12850
12851        let many1 = OneOrManyWithParens::Many(vec!["b"]);
12852
12853        assert_eq!(Vec::from_iter(&many1), vec![&"b"]);
12854
12855        let many2 = OneOrManyWithParens::Many(vec!["c", "d"]);
12856
12857        assert_eq!(Vec::from_iter(&many2), vec![&"c", &"d"]);
12858    }
12859
12860    #[test]
12861    fn test_one_or_many_with_parens_value_into_iter() {
12862        use core::iter::once;
12863
12864        //tests that our iterator implemented methods behaves exactly as it's inner iterator, at every step up to n calls to next/next_back
12865        fn test_steps<I>(ours: OneOrManyWithParens<usize>, inner: I, n: usize)
12866        where
12867            I: IntoIterator<Item = usize, IntoIter: DoubleEndedIterator + Clone> + Clone,
12868        {
12869            fn checks<I>(ours: OneOrManyWithParensIntoIter<usize>, inner: I)
12870            where
12871                I: Iterator<Item = usize> + Clone + DoubleEndedIterator,
12872            {
12873                assert_eq!(ours.size_hint(), inner.size_hint());
12874                assert_eq!(ours.clone().count(), inner.clone().count());
12875
12876                assert_eq!(
12877                    ours.clone().fold(1, |a, v| a + v),
12878                    inner.clone().fold(1, |a, v| a + v)
12879                );
12880
12881                assert_eq!(Vec::from_iter(ours.clone()), Vec::from_iter(inner.clone()));
12882                assert_eq!(
12883                    Vec::from_iter(ours.clone().rev()),
12884                    Vec::from_iter(inner.clone().rev())
12885                );
12886            }
12887
12888            let mut ours_next = ours.clone().into_iter();
12889            let mut inner_next = inner.clone().into_iter();
12890
12891            for _ in 0..n {
12892                checks(ours_next.clone(), inner_next.clone());
12893
12894                assert_eq!(ours_next.next(), inner_next.next());
12895            }
12896
12897            let mut ours_next_back = ours.clone().into_iter();
12898            let mut inner_next_back = inner.clone().into_iter();
12899
12900            for _ in 0..n {
12901                checks(ours_next_back.clone(), inner_next_back.clone());
12902
12903                assert_eq!(ours_next_back.next_back(), inner_next_back.next_back());
12904            }
12905
12906            let mut ours_mixed = ours.clone().into_iter();
12907            let mut inner_mixed = inner.clone().into_iter();
12908
12909            for i in 0..n {
12910                checks(ours_mixed.clone(), inner_mixed.clone());
12911
12912                if i % 2 == 0 {
12913                    assert_eq!(ours_mixed.next_back(), inner_mixed.next_back());
12914                } else {
12915                    assert_eq!(ours_mixed.next(), inner_mixed.next());
12916                }
12917            }
12918
12919            let mut ours_mixed2 = ours.into_iter();
12920            let mut inner_mixed2 = inner.into_iter();
12921
12922            for i in 0..n {
12923                checks(ours_mixed2.clone(), inner_mixed2.clone());
12924
12925                if i % 2 == 0 {
12926                    assert_eq!(ours_mixed2.next(), inner_mixed2.next());
12927                } else {
12928                    assert_eq!(ours_mixed2.next_back(), inner_mixed2.next_back());
12929                }
12930            }
12931        }
12932
12933        test_steps(OneOrManyWithParens::One(1), once(1), 3);
12934        test_steps(OneOrManyWithParens::Many(vec![2]), vec![2], 3);
12935        test_steps(OneOrManyWithParens::Many(vec![3, 4]), vec![3, 4], 4);
12936    }
12937
12938    // Tests that the position in the code of an `Ident` does not affect its
12939    // ordering.
12940    #[test]
12941    fn test_ident_ord() {
12942        let mut a = Ident::with_span(Span::new(Location::new(1, 1), Location::new(1, 1)), "a");
12943        let mut b = Ident::with_span(Span::new(Location::new(2, 2), Location::new(2, 2)), "b");
12944
12945        assert!(a < b);
12946        std::mem::swap(&mut a.span, &mut b.span);
12947        assert!(a < b);
12948    }
12949}