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    FullTextOrSpatialKind, FunctionReturnType, GeneratedAs, GeneratedExpressionMode,
81    IdentityParameters, IdentityProperty, IdentityPropertyFormatKind, IdentityPropertyKind,
82    IdentityPropertyOrder, IndexColumn, IndexOption, IndexType, KeyOrIndexDisplay, Msck,
83    NullsDistinctOption, OperatorArgTypes, OperatorClassItem, OperatorFamilyDropItem,
84    OperatorFamilyItem, OperatorOption, OperatorPurpose, Owner, Partition, PartitionBoundValue,
85    ProcedureParam, ReferentialAction, RenameTableNameKind, ReplicaIdentity, TagsColumnOption,
86    TextSearchObjectType, TriggerObjectKind, Truncate, UserDefinedTypeCompositeAttributeDef,
87    UserDefinedTypeInternalLength, UserDefinedTypeRangeOption, UserDefinedTypeRepresentation,
88    UserDefinedTypeSqlDefinitionOption, 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 ] [ form ] NORMALIZED`
952    IsNormalized {
953        /// Expression being tested.
954        expr: Box<Expr>,
955        /// Optional normalization `form` (e.g., NFC, NFD).
956        form: Option<NormalizationForm>,
957        /// `true` when `NOT` is present.
958        negated: bool,
959    },
960    /// `[ NOT ] IN (val1, val2, ...)`
961    InList {
962        /// Left-hand expression to test for membership.
963        expr: Box<Expr>,
964        /// Literal list of expressions to check against.
965        list: Vec<Expr>,
966        /// `true` when the `NOT` modifier is present.
967        negated: bool,
968    },
969    /// `[ NOT ] IN (SELECT ...)`
970    InSubquery {
971        /// Left-hand expression to test for membership.
972        expr: Box<Expr>,
973        /// The subquery providing the candidate values.
974        subquery: Box<Query>,
975        /// `true` when the `NOT` modifier is present.
976        negated: bool,
977    },
978    /// `[ NOT ] IN UNNEST(array_expression)`
979    InUnnest {
980        /// Left-hand expression to test for membership.
981        expr: Box<Expr>,
982        /// Array expression being unnested.
983        array_expr: Box<Expr>,
984        /// `true` when the `NOT` modifier is present.
985        negated: bool,
986    },
987    /// `<expr> [ NOT ] BETWEEN <low> AND <high>`
988    Between {
989        /// Expression being compared.
990        expr: Box<Expr>,
991        /// `true` when the `NOT` modifier is present.
992        negated: bool,
993        /// Lower bound.
994        low: Box<Expr>,
995        /// Upper bound.
996        high: Box<Expr>,
997    },
998    /// Binary operation e.g. `1 + 1` or `foo > bar`
999    BinaryOp {
1000        /// Left operand.
1001        left: Box<Expr>,
1002        /// Operator between operands.
1003        op: BinaryOperator,
1004        /// Right operand.
1005        right: Box<Expr>,
1006    },
1007    /// `[NOT] LIKE <pattern> [ESCAPE <escape_character>]`
1008    Like {
1009        /// `true` when `NOT` is present.
1010        negated: bool,
1011        /// Snowflake supports the ANY keyword to match against a list of patterns
1012        /// <https://docs.snowflake.com/en/sql-reference/functions/like_any>
1013        any: bool,
1014        /// Expression to match.
1015        expr: Box<Expr>,
1016        /// Pattern expression.
1017        pattern: Box<Expr>,
1018        /// Optional escape character.
1019        escape_char: Option<ValueWithSpan>,
1020    },
1021    /// `ILIKE` (case-insensitive `LIKE`)
1022    ILike {
1023        /// `true` when `NOT` is present.
1024        negated: bool,
1025        /// Snowflake supports the ANY keyword to match against a list of patterns
1026        /// <https://docs.snowflake.com/en/sql-reference/functions/like_any>
1027        any: bool,
1028        /// Expression to match.
1029        expr: Box<Expr>,
1030        /// Pattern expression.
1031        pattern: Box<Expr>,
1032        /// Optional escape character.
1033        escape_char: Option<ValueWithSpan>,
1034    },
1035    /// `SIMILAR TO` regex
1036    SimilarTo {
1037        /// `true` when `NOT` is present.
1038        negated: bool,
1039        /// Expression to test.
1040        expr: Box<Expr>,
1041        /// Pattern expression.
1042        pattern: Box<Expr>,
1043        /// Optional escape character.
1044        escape_char: Option<ValueWithSpan>,
1045    },
1046    /// MySQL: `RLIKE` regex or `REGEXP` regex
1047    RLike {
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        /// true for REGEXP, false for RLIKE (no difference in semantics)
1055        regexp: bool,
1056    },
1057    /// `ANY` operation e.g. `foo > ANY(bar)`, comparison operator is one of `[=, >, <, =>, =<, !=]`
1058    /// <https://docs.snowflake.com/en/sql-reference/operators-subquery#all-any>
1059    AnyOp {
1060        /// Left operand.
1061        left: Box<Expr>,
1062        /// Comparison operator.
1063        compare_op: BinaryOperator,
1064        /// Right-hand subquery expression.
1065        right: Box<Expr>,
1066        /// ANY and SOME are synonymous: <https://docs.cloudera.com/cdw-runtime/cloud/using-hiveql/topics/hive_comparison_predicates.html>
1067        is_some: bool,
1068    },
1069    /// `ALL` operation e.g. `foo > ALL(bar)`, comparison operator is one of `[=, >, <, =>, =<, !=]`
1070    /// <https://docs.snowflake.com/en/sql-reference/operators-subquery#all-any>
1071    AllOp {
1072        /// Left operand.
1073        left: Box<Expr>,
1074        /// Comparison operator.
1075        compare_op: BinaryOperator,
1076        /// Right-hand subquery expression.
1077        right: Box<Expr>,
1078    },
1079
1080    /// Unary operation e.g. `NOT foo`
1081    UnaryOp {
1082        /// The unary operator (e.g., `NOT`, `-`).
1083        op: UnaryOperator,
1084        /// Operand expression.
1085        expr: Box<Expr>,
1086    },
1087    /// CONVERT a value to a different data type or character encoding. e.g. `CONVERT(foo USING utf8mb4)`
1088    Convert {
1089        /// CONVERT (false) or TRY_CONVERT (true)
1090        /// <https://learn.microsoft.com/en-us/sql/t-sql/functions/try-convert-transact-sql?view=sql-server-ver16>
1091        is_try: bool,
1092        /// The expression to convert.
1093        expr: Box<Expr>,
1094        /// The target data type, if provided.
1095        data_type: Option<DataType>,
1096        /// Optional target character encoding (e.g., `utf8mb4`).
1097        charset: Option<ObjectName>,
1098        /// `true` when target precedes the value (MSSQL syntax).
1099        target_before_value: bool,
1100        /// How to translate the expression.
1101        ///
1102        /// [MSSQL]: https://learn.microsoft.com/en-us/sql/t-sql/functions/cast-and-convert-transact-sql?view=sql-server-ver16#style
1103        styles: Vec<Expr>,
1104    },
1105    /// `CAST` an expression to a different data type e.g. `CAST(foo AS VARCHAR(123))`
1106    Cast {
1107        /// The cast kind (e.g., `CAST`, `TRY_CAST`).
1108        kind: CastKind,
1109        /// Expression being cast.
1110        expr: Box<Expr>,
1111        /// Target data type.
1112        data_type: DataType,
1113        /// [MySQL] allows CAST(... AS type ARRAY) in functional index definitions for InnoDB
1114        /// multi-valued indices. It's not really a datatype, and is only allowed in `CAST` in key
1115        /// specifications, so it's a flag here.
1116        ///
1117        /// [MySQL]: https://dev.mysql.com/doc/refman/8.4/en/cast-functions.html#function_cast
1118        array: bool,
1119        /// Optional CAST(string_expression AS type FORMAT format_string_expression) as used by [BigQuery]
1120        ///
1121        /// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/format-elements#formatting_syntax
1122        format: Option<CastFormat>,
1123    },
1124    /// AT a timestamp to a different timezone e.g. `FROM_UNIXTIME(0) AT TIME ZONE 'UTC-06:00'`
1125    AtTimeZone {
1126        /// Timestamp expression to shift.
1127        timestamp: Box<Expr>,
1128        /// Time zone expression to apply.
1129        time_zone: Box<Expr>,
1130    },
1131    /// Extract a field from a timestamp e.g. `EXTRACT(MONTH FROM foo)`
1132    /// Or `EXTRACT(MONTH, foo)`
1133    ///
1134    /// Syntax:
1135    /// ```sql
1136    /// EXTRACT(DateTimeField FROM <expr>) | EXTRACT(DateTimeField, <expr>)
1137    /// ```
1138    Extract {
1139        /// Which datetime field is being extracted.
1140        field: DateTimeField,
1141        /// Syntax variant used (`From` or `Comma`).
1142        syntax: ExtractSyntax,
1143        /// Expression to extract from.
1144        expr: Box<Expr>,
1145    },
1146    /// ```sql
1147    /// CEIL(<expr> [TO DateTimeField])
1148    /// ```
1149    /// ```sql
1150    /// CEIL( <input_expr> [, <scale_expr> ] )
1151    /// ```
1152    Ceil {
1153        /// Expression to ceil.
1154        expr: Box<Expr>,
1155        /// The CEIL/FLOOR kind (datetime field or scale).
1156        field: CeilFloorKind,
1157    },
1158    /// ```sql
1159    /// FLOOR(<expr> [TO DateTimeField])
1160    /// ```
1161    /// ```sql
1162    /// FLOOR( <input_expr> [, <scale_expr> ] )
1163    ///
1164    Floor {
1165        /// Expression to floor.
1166        expr: Box<Expr>,
1167        /// The CEIL/FLOOR kind (datetime field or scale).
1168        field: CeilFloorKind,
1169    },
1170    /// ```sql
1171    /// POSITION(<expr> in <expr>)
1172    /// ```
1173    Position {
1174        /// Expression to search for.
1175        expr: Box<Expr>,
1176        /// Expression to search in.
1177        r#in: Box<Expr>,
1178    },
1179    /// ```sql
1180    /// SUBSTRING(<expr> [FROM <expr>] [FOR <expr>])
1181    /// ```
1182    /// or
1183    /// ```sql
1184    /// SUBSTRING(<expr>, <expr>, <expr>)
1185    /// ```
1186    Substring {
1187        /// Source expression.
1188        expr: Box<Expr>,
1189        /// Optional `FROM` expression.
1190        substring_from: Option<Box<Expr>>,
1191        /// Optional `FOR` expression.
1192        substring_for: Option<Box<Expr>>,
1193
1194        /// false if the expression is represented using the `SUBSTRING(expr [FROM start] [FOR len])` syntax
1195        /// true if the expression is represented using the `SUBSTRING(expr, start, len)` syntax
1196        /// This flag is used for formatting.
1197        special: bool,
1198
1199        /// true if the expression is represented using the `SUBSTR` shorthand
1200        /// This flag is used for formatting.
1201        shorthand: bool,
1202    },
1203    /// ```sql
1204    /// TRIM([BOTH | LEADING | TRAILING] [<expr> FROM] <expr>)
1205    /// TRIM(<expr>)
1206    /// TRIM(<expr>, [, characters]) -- PostgreSQL, DuckDB, Snowflake, BigQuery, Generic
1207    /// ```
1208    Trim {
1209        /// Which side to trim: `BOTH`, `LEADING`, or `TRAILING`.
1210        trim_where: Option<TrimWhereField>,
1211        /// Optional expression specifying what to trim from the value `expr`.
1212        trim_what: Option<Box<Expr>>,
1213        /// The expression to trim from.
1214        expr: Box<Expr>,
1215        /// Optional list of characters to trim (dialect-specific).
1216        trim_characters: Option<Vec<Expr>>,
1217    },
1218    /// ```sql
1219    /// OVERLAY(<expr> PLACING <expr> FROM <expr>[ FOR <expr> ]
1220    /// ```
1221    Overlay {
1222        /// The target expression being overlayed.
1223        expr: Box<Expr>,
1224        /// The expression to place into the target.
1225        overlay_what: Box<Expr>,
1226        /// The `FROM` position expression indicating where to start overlay.
1227        overlay_from: Box<Expr>,
1228        /// Optional `FOR` length expression limiting the overlay span.
1229        overlay_for: Option<Box<Expr>>,
1230    },
1231    /// `expr COLLATE collation`
1232    Collate {
1233        /// The expression being collated.
1234        expr: Box<Expr>,
1235        /// The collation name to apply to the expression.
1236        collation: ObjectName,
1237    },
1238    /// Nested expression e.g. `(foo > bar)` or `(1)`
1239    Nested(Box<Expr>),
1240    /// A literal value, such as string, number, date or NULL
1241    Value(ValueWithSpan),
1242    /// Prefixed expression, e.g. introducer strings, projection prefix
1243    /// <https://dev.mysql.com/doc/refman/8.0/en/charset-introducer.html>
1244    /// <https://docs.snowflake.com/en/sql-reference/constructs/connect-by>
1245    Prefixed {
1246        /// The prefix identifier (introducer or projection prefix).
1247        prefix: Ident,
1248        /// The value expression being prefixed.
1249        /// Hint: you can unwrap the string value using `value.into_string()`.
1250        value: Box<Expr>,
1251    },
1252    /// A constant of form `<data_type> 'value'`.
1253    /// This can represent ANSI SQL `DATE`, `TIME`, and `TIMESTAMP` literals (such as `DATE '2020-01-01'`),
1254    /// as well as constants of other types (a non-standard PostgreSQL extension).
1255    TypedString(TypedString),
1256    /// Scalar function call e.g. `LEFT(foo, 5)`
1257    Function(Function),
1258    /// `CASE [<operand>] WHEN <condition> THEN <result> ... [ELSE <result>] END`
1259    ///
1260    /// Note we only recognize a complete single expression as `<condition>`,
1261    /// not `< 0` nor `1, 2, 3` as allowed in a `<simple when clause>` per
1262    /// <https://jakewheat.github.io/sql-overview/sql-2011-foundation-grammar.html#simple-when-clause>
1263    Case {
1264        /// The attached `CASE` token (keeps original spacing/comments).
1265        case_token: AttachedToken,
1266        /// The attached `END` token (keeps original spacing/comments).
1267        end_token: AttachedToken,
1268        /// Optional operand expression after `CASE` (for simple CASE).
1269        operand: Option<Box<Expr>>,
1270        /// The `WHEN ... THEN` conditions and results.
1271        conditions: Vec<CaseWhen>,
1272        /// Optional `ELSE` result expression.
1273        else_result: Option<Box<Expr>>,
1274    },
1275    /// An exists expression `[ NOT ] EXISTS(SELECT ...)`, used in expressions like
1276    /// `WHERE [ NOT ] EXISTS (SELECT ...)`.
1277    Exists {
1278        /// The subquery checked by `EXISTS`.
1279        subquery: Box<Query>,
1280        /// Whether the `EXISTS` is negated (`NOT EXISTS`).
1281        negated: bool,
1282    },
1283    /// A parenthesized subquery `(SELECT ...)`, used in expression like
1284    /// `SELECT (subquery) AS x` or `WHERE (subquery) = x`
1285    Subquery(Box<Query>),
1286    /// The `GROUPING SETS` expr.
1287    GroupingSets(Vec<Vec<Expr>>),
1288    /// The `CUBE` expr.
1289    Cube(Vec<Vec<Expr>>),
1290    /// The `ROLLUP` expr.
1291    Rollup(Vec<Vec<Expr>>),
1292    /// ROW / TUPLE a single value, such as `SELECT (1, 2)`
1293    Tuple(Vec<Expr>),
1294    /// `Struct` literal expression
1295    /// Syntax:
1296    /// ```sql
1297    /// STRUCT<[field_name] field_type, ...>( expr1 [, ... ])
1298    ///
1299    /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-types#struct_type)
1300    /// [Databricks](https://docs.databricks.com/en/sql/language-manual/functions/struct.html)
1301    /// ```
1302    Struct {
1303        /// Struct values.
1304        values: Vec<Expr>,
1305        /// Struct field definitions.
1306        fields: Vec<StructField>,
1307    },
1308    /// A named expression: `1 AS A`. Used in `BigQuery` typeless structs [1]
1309    /// and in aliased function arguments, e.g. `XMLFOREST(a AS x)` in
1310    /// PostgreSQL [2].
1311    ///
1312    /// [1]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-types#struct_type
1313    /// [2]: https://www.postgresql.org/docs/current/functions-xml.html#FUNCTIONS-PRODUCING-XML-XMLFOREST
1314    Named {
1315        /// The expression being named.
1316        expr: Box<Expr>,
1317        /// The assigned identifier name for the expression.
1318        name: Ident,
1319    },
1320    /// `DuckDB` specific `Struct` literal expression [1]
1321    ///
1322    /// Syntax:
1323    /// ```sql
1324    /// syntax: {'field_name': expr1[, ... ]}
1325    /// ```
1326    /// [1]: https://duckdb.org/docs/sql/data_types/struct#creating-structs
1327    Dictionary(Vec<DictionaryField>),
1328    /// `DuckDB` specific `Map` literal expression [1]
1329    ///
1330    /// Syntax:
1331    /// ```sql
1332    /// syntax: Map {key1: value1[, ... ]}
1333    /// ```
1334    /// [1]: https://duckdb.org/docs/sql/data_types/map#creating-maps
1335    Map(Map),
1336    /// An array expression e.g. `ARRAY[1, 2]`
1337    Array(Array),
1338    /// An interval expression e.g. `INTERVAL '1' YEAR`
1339    Interval(Interval),
1340    /// `MySQL` specific text search function [(1)].
1341    ///
1342    /// Syntax:
1343    /// ```sql
1344    /// MATCH (<col>, <col>, ...) AGAINST (<expr> [<search modifier>])
1345    ///
1346    /// <col> = CompoundIdentifier
1347    /// <expr> = String literal
1348    /// ```
1349    /// [(1)]: https://dev.mysql.com/doc/refman/8.0/en/fulltext-search.html#function_match
1350    MatchAgainst {
1351        /// `(<col>, <col>, ...)`.
1352        columns: Vec<ObjectName>,
1353        /// `<expr>`.
1354        match_value: ValueWithSpan,
1355        /// `<search modifier>`
1356        opt_search_modifier: Option<SearchModifier>,
1357    },
1358    /// An unqualified `*` wildcard token (e.g. `*`).
1359    Wildcard(AttachedToken),
1360    /// Qualified wildcard, e.g. `alias.*` or `schema.table.*`.
1361    /// (Same caveats apply to `QualifiedWildcard` as to `Wildcard`.)
1362    QualifiedWildcard(ObjectName, AttachedToken),
1363    /// Some dialects support an older syntax for outer joins where columns are
1364    /// marked with the `(+)` operator in the WHERE clause, for example:
1365    ///
1366    /// ```sql
1367    /// SELECT t1.c1, t2.c2 FROM t1, t2 WHERE t1.c1 = t2.c2 (+)
1368    /// ```
1369    ///
1370    /// which is equivalent to
1371    ///
1372    /// ```sql
1373    /// SELECT t1.c1, t2.c2 FROM t1 LEFT OUTER JOIN t2 ON t1.c1 = t2.c2
1374    /// ```
1375    ///
1376    /// See <https://docs.snowflake.com/en/sql-reference/constructs/where#joins-in-the-where-clause>.
1377    OuterJoin(Box<Expr>),
1378    /// A reference to the prior level in a CONNECT BY clause.
1379    Prior(Box<Expr>),
1380    /// A lambda function.
1381    ///
1382    /// Syntax:
1383    /// ```plaintext
1384    /// param -> expr | (param1, ...) -> expr
1385    /// ```
1386    ///
1387    /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/functions#higher-order-functions---operator-and-lambdaparams-expr-function)
1388    /// [Databricks](https://docs.databricks.com/en/sql/language-manual/sql-ref-lambda-functions.html)
1389    /// [DuckDB](https://duckdb.org/docs/stable/sql/functions/lambda)
1390    Lambda(LambdaFunction),
1391    /// Checks membership of a value in a JSON array
1392    MemberOf(MemberOf),
1393}
1394
1395impl Expr {
1396    /// Creates a new [`Expr::Value`]
1397    pub fn value(value: impl Into<ValueWithSpan>) -> Self {
1398        Expr::Value(value.into())
1399    }
1400}
1401
1402/// The contents inside the `[` and `]` in a subscript expression.
1403#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1404#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1405#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1406pub enum Subscript {
1407    /// Accesses the element of the array at the given index.
1408    Index {
1409        /// The index expression used to access the array element.
1410        index: Expr,
1411    },
1412
1413    /// Accesses a slice of an array on PostgreSQL, e.g.
1414    ///
1415    /// ```plaintext
1416    /// => select (array[1,2,3,4,5,6])[2:5];
1417    /// -----------
1418    /// {2,3,4,5}
1419    /// ```
1420    ///
1421    /// The lower and/or upper bound can be omitted to slice from the start or
1422    /// end of the array respectively.
1423    ///
1424    /// See <https://www.postgresql.org/docs/current/arrays.html#ARRAYS-ACCESSING>.
1425    ///
1426    /// Also supports an optional "stride" as the last element (this is not
1427    /// supported by postgres), e.g.
1428    ///
1429    /// ```plaintext
1430    /// => select (array[1,2,3,4,5,6])[1:6:2];
1431    /// -----------
1432    /// {1,3,5}
1433    /// ```
1434    Slice {
1435        /// Optional lower bound for the slice (inclusive).
1436        lower_bound: Option<Expr>,
1437        /// Optional upper bound for the slice (inclusive).
1438        upper_bound: Option<Expr>,
1439        /// Optional stride for the slice (step size).
1440        stride: Option<Expr>,
1441    },
1442}
1443
1444impl fmt::Display for Subscript {
1445    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1446        match self {
1447            Subscript::Index { index } => write!(f, "{index}"),
1448            Subscript::Slice {
1449                lower_bound,
1450                upper_bound,
1451                stride,
1452            } => {
1453                if let Some(lower) = lower_bound {
1454                    write!(f, "{lower}")?;
1455                }
1456                write!(f, ":")?;
1457                if let Some(upper) = upper_bound {
1458                    write!(f, "{upper}")?;
1459                }
1460                if let Some(stride) = stride {
1461                    write!(f, ":")?;
1462                    write!(f, "{stride}")?;
1463                }
1464                Ok(())
1465            }
1466        }
1467    }
1468}
1469
1470/// An element of a [`Expr::CompoundFieldAccess`].
1471/// It can be an expression or a subscript.
1472#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1473#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1474#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1475pub enum AccessExpr {
1476    /// Accesses a field using dot notation, e.g. `foo.bar.baz`.
1477    Dot(Expr),
1478    /// Accesses a field or array element using bracket notation, e.g. `foo['bar']`.
1479    Subscript(Subscript),
1480}
1481
1482impl fmt::Display for AccessExpr {
1483    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1484        match self {
1485            AccessExpr::Dot(expr) => write!(f, ".{expr}"),
1486            AccessExpr::Subscript(subscript) => write!(f, "[{subscript}]"),
1487        }
1488    }
1489}
1490
1491/// A lambda function.
1492#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1493#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1494#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1495pub struct LambdaFunction {
1496    /// The parameters to the lambda function.
1497    pub params: OneOrManyWithParens<LambdaFunctionParameter>,
1498    /// The body of the lambda function.
1499    pub body: Box<Expr>,
1500    /// The syntax style used to write the lambda function.
1501    pub syntax: LambdaSyntax,
1502}
1503
1504impl fmt::Display for LambdaFunction {
1505    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1506        match self.syntax {
1507            LambdaSyntax::Arrow => write!(f, "{} -> {}", self.params, self.body),
1508            LambdaSyntax::LambdaKeyword => {
1509                // For lambda keyword syntax, display params without parentheses
1510                // e.g., `lambda x, y : expr` not `lambda (x, y) : expr`
1511                write!(f, "lambda ")?;
1512                match &self.params {
1513                    OneOrManyWithParens::One(p) => write!(f, "{p}")?,
1514                    OneOrManyWithParens::Many(ps) => write!(f, "{}", display_comma_separated(ps))?,
1515                };
1516                write!(f, " : {}", self.body)
1517            }
1518        }
1519    }
1520}
1521
1522/// A parameter to a lambda function, optionally with a data type.
1523#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1524#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1525#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1526pub struct LambdaFunctionParameter {
1527    /// The name of the parameter
1528    pub name: Ident,
1529    /// The optional data type of the parameter
1530    /// [Snowflake Syntax](https://docs.snowflake.com/en/sql-reference/functions/filter#arguments)
1531    pub data_type: Option<DataType>,
1532}
1533
1534impl fmt::Display for LambdaFunctionParameter {
1535    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1536        match &self.data_type {
1537            Some(dt) => write!(f, "{} {}", self.name, dt),
1538            None => write!(f, "{}", self.name),
1539        }
1540    }
1541}
1542
1543/// The syntax style for a lambda function.
1544#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Copy)]
1545#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1546#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1547pub enum LambdaSyntax {
1548    /// Arrow syntax: `param -> expr` or `(param1, param2) -> expr`
1549    ///
1550    /// <https://docs.databricks.com/aws/en/sql/language-manual/sql-ref-lambda-functions>
1551    ///
1552    /// Supported, but deprecated in DuckDB:
1553    /// <https://duckdb.org/docs/stable/sql/functions/lambda>
1554    Arrow,
1555    /// Lambda keyword syntax: `lambda param : expr` or `lambda param1, param2 : expr`
1556    ///
1557    /// Recommended in DuckDB:
1558    /// <https://duckdb.org/docs/stable/sql/functions/lambda>
1559    LambdaKeyword,
1560}
1561
1562/// Encapsulates the common pattern in SQL where either one unparenthesized item
1563/// such as an identifier or expression is permitted, or multiple of the same
1564/// item in a parenthesized list. For accessing items regardless of the form,
1565/// `OneOrManyWithParens` implements `Deref<Target = [T]>` and `IntoIterator`,
1566/// so you can call slice methods on it and iterate over items
1567/// # Examples
1568/// Accessing as a slice:
1569/// ```
1570/// # use sqlparser::ast::OneOrManyWithParens;
1571/// let one = OneOrManyWithParens::One("a");
1572///
1573/// assert_eq!(one[0], "a");
1574/// assert_eq!(one.len(), 1);
1575/// ```
1576/// Iterating:
1577/// ```
1578/// # use sqlparser::ast::OneOrManyWithParens;
1579/// let one = OneOrManyWithParens::One("a");
1580/// let many = OneOrManyWithParens::Many(vec!["a", "b"]);
1581///
1582/// assert_eq!(one.into_iter().chain(many).collect::<Vec<_>>(), vec!["a", "a", "b"] );
1583/// ```
1584#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1585#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1586#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1587pub enum OneOrManyWithParens<T> {
1588    /// A single `T`, unparenthesized.
1589    One(T),
1590    /// One or more `T`s, parenthesized.
1591    Many(Vec<T>),
1592}
1593
1594impl<T> Deref for OneOrManyWithParens<T> {
1595    type Target = [T];
1596
1597    fn deref(&self) -> &[T] {
1598        match self {
1599            OneOrManyWithParens::One(one) => core::slice::from_ref(one),
1600            OneOrManyWithParens::Many(many) => many,
1601        }
1602    }
1603}
1604
1605impl<T> AsRef<[T]> for OneOrManyWithParens<T> {
1606    fn as_ref(&self) -> &[T] {
1607        self
1608    }
1609}
1610
1611impl<'a, T> IntoIterator for &'a OneOrManyWithParens<T> {
1612    type Item = &'a T;
1613    type IntoIter = core::slice::Iter<'a, T>;
1614
1615    fn into_iter(self) -> Self::IntoIter {
1616        self.iter()
1617    }
1618}
1619
1620/// Owned iterator implementation of `OneOrManyWithParens`
1621#[derive(Debug, Clone)]
1622pub struct OneOrManyWithParensIntoIter<T> {
1623    inner: OneOrManyWithParensIntoIterInner<T>,
1624}
1625
1626#[derive(Debug, Clone)]
1627enum OneOrManyWithParensIntoIterInner<T> {
1628    One(core::iter::Once<T>),
1629    Many(<Vec<T> as IntoIterator>::IntoIter),
1630}
1631
1632impl<T> core::iter::FusedIterator for OneOrManyWithParensIntoIter<T>
1633where
1634    core::iter::Once<T>: core::iter::FusedIterator,
1635    <Vec<T> as IntoIterator>::IntoIter: core::iter::FusedIterator,
1636{
1637}
1638
1639impl<T> core::iter::ExactSizeIterator for OneOrManyWithParensIntoIter<T>
1640where
1641    core::iter::Once<T>: core::iter::ExactSizeIterator,
1642    <Vec<T> as IntoIterator>::IntoIter: core::iter::ExactSizeIterator,
1643{
1644}
1645
1646impl<T> core::iter::Iterator for OneOrManyWithParensIntoIter<T> {
1647    type Item = T;
1648
1649    fn next(&mut self) -> Option<Self::Item> {
1650        match &mut self.inner {
1651            OneOrManyWithParensIntoIterInner::One(one) => one.next(),
1652            OneOrManyWithParensIntoIterInner::Many(many) => many.next(),
1653        }
1654    }
1655
1656    fn size_hint(&self) -> (usize, Option<usize>) {
1657        match &self.inner {
1658            OneOrManyWithParensIntoIterInner::One(one) => one.size_hint(),
1659            OneOrManyWithParensIntoIterInner::Many(many) => many.size_hint(),
1660        }
1661    }
1662
1663    fn count(self) -> usize
1664    where
1665        Self: Sized,
1666    {
1667        match self.inner {
1668            OneOrManyWithParensIntoIterInner::One(one) => one.count(),
1669            OneOrManyWithParensIntoIterInner::Many(many) => many.count(),
1670        }
1671    }
1672
1673    fn fold<B, F>(mut self, init: B, f: F) -> B
1674    where
1675        Self: Sized,
1676        F: FnMut(B, Self::Item) -> B,
1677    {
1678        match &mut self.inner {
1679            OneOrManyWithParensIntoIterInner::One(one) => one.fold(init, f),
1680            OneOrManyWithParensIntoIterInner::Many(many) => many.fold(init, f),
1681        }
1682    }
1683}
1684
1685impl<T> core::iter::DoubleEndedIterator for OneOrManyWithParensIntoIter<T> {
1686    fn next_back(&mut self) -> Option<Self::Item> {
1687        match &mut self.inner {
1688            OneOrManyWithParensIntoIterInner::One(one) => one.next_back(),
1689            OneOrManyWithParensIntoIterInner::Many(many) => many.next_back(),
1690        }
1691    }
1692}
1693
1694impl<T> IntoIterator for OneOrManyWithParens<T> {
1695    type Item = T;
1696
1697    type IntoIter = OneOrManyWithParensIntoIter<T>;
1698
1699    fn into_iter(self) -> Self::IntoIter {
1700        let inner = match self {
1701            OneOrManyWithParens::One(one) => {
1702                OneOrManyWithParensIntoIterInner::One(core::iter::once(one))
1703            }
1704            OneOrManyWithParens::Many(many) => {
1705                OneOrManyWithParensIntoIterInner::Many(many.into_iter())
1706            }
1707        };
1708
1709        OneOrManyWithParensIntoIter { inner }
1710    }
1711}
1712
1713impl<T> fmt::Display for OneOrManyWithParens<T>
1714where
1715    T: fmt::Display,
1716{
1717    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1718        match self {
1719            OneOrManyWithParens::One(value) => write!(f, "{value}"),
1720            OneOrManyWithParens::Many(values) => {
1721                write!(f, "({})", display_comma_separated(values))
1722            }
1723        }
1724    }
1725}
1726
1727impl fmt::Display for CastFormat {
1728    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1729        match self {
1730            CastFormat::Value(v) => write!(f, "{v}"),
1731            CastFormat::ValueAtTimeZone(v, tz) => write!(f, "{v} AT TIME ZONE {tz}"),
1732        }
1733    }
1734}
1735
1736impl fmt::Display for Expr {
1737    #[cfg_attr(feature = "recursive-protection", recursive::recursive)]
1738    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1739        match self {
1740            Expr::Identifier(s) => write!(f, "{s}"),
1741            Expr::Wildcard(_) => f.write_str("*"),
1742            Expr::QualifiedWildcard(prefix, _) => write!(f, "{prefix}.*"),
1743            Expr::CompoundIdentifier(s) => write!(f, "{}", display_separated(s, ".")),
1744            Expr::CompoundFieldAccess { root, access_chain } => {
1745                write!(f, "{root}")?;
1746                for field in access_chain {
1747                    write!(f, "{field}")?;
1748                }
1749                Ok(())
1750            }
1751            Expr::IsTrue(ast) => write!(f, "{ast} IS TRUE"),
1752            Expr::IsNotTrue(ast) => write!(f, "{ast} IS NOT TRUE"),
1753            Expr::IsFalse(ast) => write!(f, "{ast} IS FALSE"),
1754            Expr::IsNotFalse(ast) => write!(f, "{ast} IS NOT FALSE"),
1755            Expr::IsNull(ast) => write!(f, "{ast} IS NULL"),
1756            Expr::IsNotNull(ast) => write!(f, "{ast} IS NOT NULL"),
1757            Expr::IsUnknown(ast) => write!(f, "{ast} IS UNKNOWN"),
1758            Expr::IsNotUnknown(ast) => write!(f, "{ast} IS NOT UNKNOWN"),
1759            Expr::InList {
1760                expr,
1761                list,
1762                negated,
1763            } => write!(
1764                f,
1765                "{} {}IN ({})",
1766                expr,
1767                if *negated { "NOT " } else { "" },
1768                display_comma_separated(list)
1769            ),
1770            Expr::InSubquery {
1771                expr,
1772                subquery,
1773                negated,
1774            } => write!(
1775                f,
1776                "{} {}IN ({})",
1777                expr,
1778                if *negated { "NOT " } else { "" },
1779                subquery
1780            ),
1781            Expr::InUnnest {
1782                expr,
1783                array_expr,
1784                negated,
1785            } => write!(
1786                f,
1787                "{} {}IN UNNEST({})",
1788                expr,
1789                if *negated { "NOT " } else { "" },
1790                array_expr
1791            ),
1792            Expr::Between {
1793                expr,
1794                negated,
1795                low,
1796                high,
1797            } => write!(
1798                f,
1799                "{} {}BETWEEN {} AND {}",
1800                expr,
1801                if *negated { "NOT " } else { "" },
1802                low,
1803                high
1804            ),
1805            Expr::BinaryOp { left, op, right } => write!(f, "{left} {op} {right}"),
1806            Expr::Like {
1807                negated,
1808                expr,
1809                pattern,
1810                escape_char,
1811                any,
1812            } => match escape_char {
1813                Some(ch) => write!(
1814                    f,
1815                    "{} {}LIKE {}{} ESCAPE {}",
1816                    expr,
1817                    if *negated { "NOT " } else { "" },
1818                    if *any { "ANY " } else { "" },
1819                    pattern,
1820                    ch
1821                ),
1822                _ => write!(
1823                    f,
1824                    "{} {}LIKE {}{}",
1825                    expr,
1826                    if *negated { "NOT " } else { "" },
1827                    if *any { "ANY " } else { "" },
1828                    pattern
1829                ),
1830            },
1831            Expr::ILike {
1832                negated,
1833                expr,
1834                pattern,
1835                escape_char,
1836                any,
1837            } => match escape_char {
1838                Some(ch) => write!(
1839                    f,
1840                    "{} {}ILIKE {}{} ESCAPE {}",
1841                    expr,
1842                    if *negated { "NOT " } else { "" },
1843                    if *any { "ANY" } else { "" },
1844                    pattern,
1845                    ch
1846                ),
1847                _ => write!(
1848                    f,
1849                    "{} {}ILIKE {}{}",
1850                    expr,
1851                    if *negated { "NOT " } else { "" },
1852                    if *any { "ANY " } else { "" },
1853                    pattern
1854                ),
1855            },
1856            Expr::RLike {
1857                negated,
1858                expr,
1859                pattern,
1860                regexp,
1861            } => write!(
1862                f,
1863                "{} {}{} {}",
1864                expr,
1865                if *negated { "NOT " } else { "" },
1866                if *regexp { "REGEXP" } else { "RLIKE" },
1867                pattern
1868            ),
1869            Expr::IsNormalized {
1870                expr,
1871                form,
1872                negated,
1873            } => {
1874                let not_ = if *negated { "NOT " } else { "" };
1875                if let Some(form) = form {
1876                    write!(f, "{} IS {}{} NORMALIZED", expr, not_, form)
1877                } else {
1878                    write!(f, "{expr} IS {not_}NORMALIZED")
1879                }
1880            }
1881            Expr::SimilarTo {
1882                negated,
1883                expr,
1884                pattern,
1885                escape_char,
1886            } => match escape_char {
1887                Some(ch) => write!(
1888                    f,
1889                    "{} {}SIMILAR TO {} ESCAPE {}",
1890                    expr,
1891                    if *negated { "NOT " } else { "" },
1892                    pattern,
1893                    ch
1894                ),
1895                _ => write!(
1896                    f,
1897                    "{} {}SIMILAR TO {}",
1898                    expr,
1899                    if *negated { "NOT " } else { "" },
1900                    pattern
1901                ),
1902            },
1903            Expr::AnyOp {
1904                left,
1905                compare_op,
1906                right,
1907                is_some,
1908            } => {
1909                let add_parens = !matches!(right.as_ref(), Expr::Subquery(_));
1910                write!(
1911                    f,
1912                    "{left} {compare_op} {}{}{right}{}",
1913                    if *is_some { "SOME" } else { "ANY" },
1914                    if add_parens { "(" } else { "" },
1915                    if add_parens { ")" } else { "" },
1916                )
1917            }
1918            Expr::AllOp {
1919                left,
1920                compare_op,
1921                right,
1922            } => {
1923                let add_parens = !matches!(right.as_ref(), Expr::Subquery(_));
1924                write!(
1925                    f,
1926                    "{left} {compare_op} ALL{}{right}{}",
1927                    if add_parens { "(" } else { "" },
1928                    if add_parens { ")" } else { "" },
1929                )
1930            }
1931            Expr::UnaryOp { op, expr } => {
1932                if op == &UnaryOperator::PGPostfixFactorial {
1933                    write!(f, "{expr}{op}")
1934                } else if matches!(
1935                    op,
1936                    UnaryOperator::Not
1937                        | UnaryOperator::Hash
1938                        | UnaryOperator::AtDashAt
1939                        | UnaryOperator::DoubleAt
1940                        | UnaryOperator::QuestionDash
1941                        | UnaryOperator::QuestionPipe
1942                ) {
1943                    write!(f, "{op} {expr}")
1944                } else {
1945                    write!(f, "{op}{expr}")
1946                }
1947            }
1948            Expr::Convert {
1949                is_try,
1950                expr,
1951                target_before_value,
1952                data_type,
1953                charset,
1954                styles,
1955            } => {
1956                write!(f, "{}CONVERT(", if *is_try { "TRY_" } else { "" })?;
1957                if let Some(data_type) = data_type {
1958                    if let Some(charset) = charset {
1959                        write!(f, "{expr}, {data_type} CHARACTER SET {charset}")
1960                    } else if *target_before_value {
1961                        write!(f, "{data_type}, {expr}")
1962                    } else {
1963                        write!(f, "{expr}, {data_type}")
1964                    }
1965                } else if let Some(charset) = charset {
1966                    write!(f, "{expr} USING {charset}")
1967                } else {
1968                    write!(f, "{expr}") // This should never happen
1969                }?;
1970                if !styles.is_empty() {
1971                    write!(f, ", {}", display_comma_separated(styles))?;
1972                }
1973                write!(f, ")")
1974            }
1975            Expr::Cast {
1976                kind,
1977                expr,
1978                data_type,
1979                array,
1980                format,
1981            } => match kind {
1982                CastKind::Cast => {
1983                    write!(f, "CAST({expr} AS {data_type}")?;
1984                    if *array {
1985                        write!(f, " ARRAY")?;
1986                    }
1987                    if let Some(format) = format {
1988                        write!(f, " FORMAT {format}")?;
1989                    }
1990                    write!(f, ")")
1991                }
1992                CastKind::TryCast => {
1993                    if let Some(format) = format {
1994                        write!(f, "TRY_CAST({expr} AS {data_type} FORMAT {format})")
1995                    } else {
1996                        write!(f, "TRY_CAST({expr} AS {data_type})")
1997                    }
1998                }
1999                CastKind::SafeCast => {
2000                    if let Some(format) = format {
2001                        write!(f, "SAFE_CAST({expr} AS {data_type} FORMAT {format})")
2002                    } else {
2003                        write!(f, "SAFE_CAST({expr} AS {data_type})")
2004                    }
2005                }
2006                CastKind::DoubleColon => {
2007                    write!(f, "{expr}::{data_type}")
2008                }
2009            },
2010            Expr::Extract {
2011                field,
2012                syntax,
2013                expr,
2014            } => match syntax {
2015                ExtractSyntax::From => write!(f, "EXTRACT({field} FROM {expr})"),
2016                ExtractSyntax::Comma => write!(f, "EXTRACT({field}, {expr})"),
2017            },
2018            Expr::Ceil { expr, field } => match field {
2019                CeilFloorKind::DateTimeField(DateTimeField::NoDateTime) => {
2020                    write!(f, "CEIL({expr})")
2021                }
2022                CeilFloorKind::DateTimeField(dt_field) => write!(f, "CEIL({expr} TO {dt_field})"),
2023                CeilFloorKind::Scale(s) => write!(f, "CEIL({expr}, {s})"),
2024            },
2025            Expr::Floor { expr, field } => match field {
2026                CeilFloorKind::DateTimeField(DateTimeField::NoDateTime) => {
2027                    write!(f, "FLOOR({expr})")
2028                }
2029                CeilFloorKind::DateTimeField(dt_field) => write!(f, "FLOOR({expr} TO {dt_field})"),
2030                CeilFloorKind::Scale(s) => write!(f, "FLOOR({expr}, {s})"),
2031            },
2032            Expr::Position { expr, r#in } => write!(f, "POSITION({expr} IN {in})"),
2033            Expr::Collate { expr, collation } => write!(f, "{expr} COLLATE {collation}"),
2034            Expr::Nested(ast) => write!(f, "({ast})"),
2035            Expr::Value(v) => write!(f, "{v}"),
2036            Expr::Prefixed { prefix, value } => write!(f, "{prefix} {value}"),
2037            Expr::TypedString(ts) => ts.fmt(f),
2038            Expr::Function(fun) => fun.fmt(f),
2039            Expr::Case {
2040                case_token: _,
2041                end_token: _,
2042                operand,
2043                conditions,
2044                else_result,
2045            } => {
2046                f.write_str("CASE")?;
2047                if let Some(operand) = operand {
2048                    f.write_str(" ")?;
2049                    operand.fmt(f)?;
2050                }
2051                for when in conditions {
2052                    SpaceOrNewline.fmt(f)?;
2053                    Indent(when).fmt(f)?;
2054                }
2055                if let Some(else_result) = else_result {
2056                    SpaceOrNewline.fmt(f)?;
2057                    Indent("ELSE").fmt(f)?;
2058                    SpaceOrNewline.fmt(f)?;
2059                    Indent(Indent(else_result)).fmt(f)?;
2060                }
2061                SpaceOrNewline.fmt(f)?;
2062                f.write_str("END")
2063            }
2064            Expr::Exists { subquery, negated } => write!(
2065                f,
2066                "{}EXISTS ({})",
2067                if *negated { "NOT " } else { "" },
2068                subquery
2069            ),
2070            Expr::Subquery(s) => write!(f, "({s})"),
2071            Expr::GroupingSets(sets) => {
2072                write!(f, "GROUPING SETS (")?;
2073                let mut sep = "";
2074                for set in sets {
2075                    write!(f, "{sep}")?;
2076                    sep = ", ";
2077                    write!(f, "({})", display_comma_separated(set))?;
2078                }
2079                write!(f, ")")
2080            }
2081            Expr::Cube(sets) => {
2082                write!(f, "CUBE (")?;
2083                let mut sep = "";
2084                for set in sets {
2085                    write!(f, "{sep}")?;
2086                    sep = ", ";
2087                    if set.len() == 1 {
2088                        write!(f, "{}", set[0])?;
2089                    } else {
2090                        write!(f, "({})", display_comma_separated(set))?;
2091                    }
2092                }
2093                write!(f, ")")
2094            }
2095            Expr::Rollup(sets) => {
2096                write!(f, "ROLLUP (")?;
2097                let mut sep = "";
2098                for set in sets {
2099                    write!(f, "{sep}")?;
2100                    sep = ", ";
2101                    if set.len() == 1 {
2102                        write!(f, "{}", set[0])?;
2103                    } else {
2104                        write!(f, "({})", display_comma_separated(set))?;
2105                    }
2106                }
2107                write!(f, ")")
2108            }
2109            Expr::Substring {
2110                expr,
2111                substring_from,
2112                substring_for,
2113                special,
2114                shorthand,
2115            } => {
2116                f.write_str("SUBSTR")?;
2117                if !*shorthand {
2118                    f.write_str("ING")?;
2119                }
2120                write!(f, "({expr}")?;
2121                if let Some(from_part) = substring_from {
2122                    if *special {
2123                        write!(f, ", {from_part}")?;
2124                    } else {
2125                        write!(f, " FROM {from_part}")?;
2126                    }
2127                }
2128                if let Some(for_part) = substring_for {
2129                    if *special {
2130                        write!(f, ", {for_part}")?;
2131                    } else {
2132                        write!(f, " FOR {for_part}")?;
2133                    }
2134                }
2135
2136                write!(f, ")")
2137            }
2138            Expr::Overlay {
2139                expr,
2140                overlay_what,
2141                overlay_from,
2142                overlay_for,
2143            } => {
2144                write!(
2145                    f,
2146                    "OVERLAY({expr} PLACING {overlay_what} FROM {overlay_from}"
2147                )?;
2148                if let Some(for_part) = overlay_for {
2149                    write!(f, " FOR {for_part}")?;
2150                }
2151
2152                write!(f, ")")
2153            }
2154            Expr::IsDistinctFrom(a, b) => write!(f, "{a} IS DISTINCT FROM {b}"),
2155            Expr::IsNotDistinctFrom(a, b) => write!(f, "{a} IS NOT DISTINCT FROM {b}"),
2156            Expr::Trim {
2157                expr,
2158                trim_where,
2159                trim_what,
2160                trim_characters,
2161            } => {
2162                write!(f, "TRIM(")?;
2163                if let Some(ident) = trim_where {
2164                    write!(f, "{ident} ")?;
2165                }
2166                if let Some(trim_char) = trim_what {
2167                    write!(f, "{trim_char} FROM {expr}")?;
2168                } else {
2169                    write!(f, "{expr}")?;
2170                }
2171                if let Some(characters) = trim_characters {
2172                    write!(f, ", {}", display_comma_separated(characters))?;
2173                }
2174
2175                write!(f, ")")
2176            }
2177            Expr::Tuple(exprs) => {
2178                write!(f, "({})", display_comma_separated(exprs))
2179            }
2180            Expr::Struct { values, fields } => {
2181                if !fields.is_empty() {
2182                    write!(
2183                        f,
2184                        "STRUCT<{}>({})",
2185                        display_comma_separated(fields),
2186                        display_comma_separated(values)
2187                    )
2188                } else {
2189                    write!(f, "STRUCT({})", display_comma_separated(values))
2190                }
2191            }
2192            Expr::Named { expr, name } => {
2193                write!(f, "{expr} AS {name}")
2194            }
2195            Expr::Dictionary(fields) => {
2196                write!(f, "{{{}}}", display_comma_separated(fields))
2197            }
2198            Expr::Map(map) => {
2199                write!(f, "{map}")
2200            }
2201            Expr::Array(set) => {
2202                write!(f, "{set}")
2203            }
2204            Expr::JsonAccess { value, path } => {
2205                write!(f, "{value}{path}")
2206            }
2207            Expr::AtTimeZone {
2208                timestamp,
2209                time_zone,
2210            } => {
2211                write!(f, "{timestamp} AT TIME ZONE {time_zone}")
2212            }
2213            Expr::Interval(interval) => {
2214                write!(f, "{interval}")
2215            }
2216            Expr::MatchAgainst {
2217                columns,
2218                match_value: match_expr,
2219                opt_search_modifier,
2220            } => {
2221                write!(f, "MATCH ({}) AGAINST ", display_comma_separated(columns),)?;
2222
2223                if let Some(search_modifier) = opt_search_modifier {
2224                    write!(f, "({match_expr} {search_modifier})")?;
2225                } else {
2226                    write!(f, "({match_expr})")?;
2227                }
2228
2229                Ok(())
2230            }
2231            Expr::OuterJoin(expr) => {
2232                write!(f, "{expr} (+)")
2233            }
2234            Expr::Prior(expr) => write!(f, "PRIOR {expr}"),
2235            Expr::Lambda(lambda) => write!(f, "{lambda}"),
2236            Expr::MemberOf(member_of) => write!(f, "{member_of}"),
2237        }
2238    }
2239}
2240
2241/// The type of a window used in `OVER` clauses.
2242///
2243/// A window can be either an inline specification (`WindowSpec`) or a
2244/// reference to a previously defined named window.
2245///
2246/// - `WindowSpec(WindowSpec)`: An inline window specification, e.g.
2247///   `OVER (PARTITION BY ... ORDER BY ...)`.
2248/// - `NamedWindow(Ident)`: A reference to a named window declared elsewhere.
2249#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2250#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2251#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2252pub enum WindowType {
2253    /// An inline window specification.
2254    WindowSpec(WindowSpec),
2255    /// A reference to a previously defined named window.
2256    NamedWindow(Ident),
2257}
2258
2259impl Display for WindowType {
2260    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2261        match self {
2262            WindowType::WindowSpec(spec) => {
2263                f.write_str("(")?;
2264                NewLine.fmt(f)?;
2265                Indent(spec).fmt(f)?;
2266                NewLine.fmt(f)?;
2267                f.write_str(")")
2268            }
2269            WindowType::NamedWindow(name) => name.fmt(f),
2270        }
2271    }
2272}
2273
2274/// A window specification (i.e. `OVER ([window_name] PARTITION BY .. ORDER BY .. etc.)`)
2275#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2276#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2277#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2278pub struct WindowSpec {
2279    /// Optional window name.
2280    ///
2281    /// You can find it at least in [MySQL][1], [BigQuery][2], [PostgreSQL][3]
2282    ///
2283    /// [1]: https://dev.mysql.com/doc/refman/8.0/en/window-functions-named-windows.html
2284    /// [2]: https://cloud.google.com/bigquery/docs/reference/standard-sql/window-function-calls
2285    /// [3]: https://www.postgresql.org/docs/current/sql-expressions.html#SYNTAX-WINDOW-FUNCTIONS
2286    pub window_name: Option<Ident>,
2287    /// `OVER (PARTITION BY ...)`
2288    pub partition_by: Vec<Expr>,
2289    /// `OVER (ORDER BY ...)`
2290    pub order_by: Vec<OrderByExpr>,
2291    /// `OVER (window frame)`
2292    pub window_frame: Option<WindowFrame>,
2293}
2294
2295impl fmt::Display for WindowSpec {
2296    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2297        let mut is_first = true;
2298        if let Some(window_name) = &self.window_name {
2299            if !is_first {
2300                SpaceOrNewline.fmt(f)?;
2301            }
2302            is_first = false;
2303            write!(f, "{window_name}")?;
2304        }
2305        if !self.partition_by.is_empty() {
2306            if !is_first {
2307                SpaceOrNewline.fmt(f)?;
2308            }
2309            is_first = false;
2310            write!(
2311                f,
2312                "PARTITION BY {}",
2313                display_comma_separated(&self.partition_by)
2314            )?;
2315        }
2316        if !self.order_by.is_empty() {
2317            if !is_first {
2318                SpaceOrNewline.fmt(f)?;
2319            }
2320            is_first = false;
2321            write!(f, "ORDER BY {}", display_comma_separated(&self.order_by))?;
2322        }
2323        if let Some(window_frame) = &self.window_frame {
2324            if !is_first {
2325                SpaceOrNewline.fmt(f)?;
2326            }
2327            if let Some(end_bound) = &window_frame.end_bound {
2328                write!(
2329                    f,
2330                    "{} BETWEEN {} AND {}",
2331                    window_frame.units, window_frame.start_bound, end_bound
2332                )?;
2333            } else {
2334                write!(f, "{} {}", window_frame.units, window_frame.start_bound)?;
2335            }
2336        }
2337        Ok(())
2338    }
2339}
2340
2341/// Specifies the data processed by a window function, e.g.
2342/// `RANGE UNBOUNDED PRECEDING` or `ROWS BETWEEN 5 PRECEDING AND CURRENT ROW`.
2343///
2344/// Note: The parser does not validate the specified bounds; the caller should
2345/// reject invalid bounds like `ROWS UNBOUNDED FOLLOWING` before execution.
2346#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2347#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2348#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2349pub struct WindowFrame {
2350    /// Units for the frame (e.g. `ROWS`, `RANGE`, `GROUPS`).
2351    pub units: WindowFrameUnits,
2352    /// The start bound of the window frame.
2353    pub start_bound: WindowFrameBound,
2354    /// The right bound of the `BETWEEN .. AND` clause. The end bound of `None`
2355    /// indicates the shorthand form (e.g. `ROWS 1 PRECEDING`), which must
2356    /// behave the same as `end_bound = WindowFrameBound::CurrentRow`.
2357    pub end_bound: Option<WindowFrameBound>,
2358    // TBD: EXCLUDE
2359}
2360
2361impl Default for WindowFrame {
2362    /// Returns default value for window frame
2363    ///
2364    /// See [this page](https://www.sqlite.org/windowfunctions.html#frame_specifications) for more details.
2365    fn default() -> Self {
2366        Self {
2367            units: WindowFrameUnits::Range,
2368            start_bound: WindowFrameBound::Preceding(None),
2369            end_bound: None,
2370        }
2371    }
2372}
2373
2374#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2375#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2376#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2377/// Units used to describe the window frame scope.
2378pub enum WindowFrameUnits {
2379    /// `ROWS` unit.
2380    Rows,
2381    /// `RANGE` unit.
2382    Range,
2383    /// `GROUPS` unit.
2384    Groups,
2385}
2386
2387impl fmt::Display for WindowFrameUnits {
2388    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2389        f.write_str(match self {
2390            WindowFrameUnits::Rows => "ROWS",
2391            WindowFrameUnits::Range => "RANGE",
2392            WindowFrameUnits::Groups => "GROUPS",
2393        })
2394    }
2395}
2396
2397/// Specifies Ignore / Respect NULL within window functions.
2398/// For example
2399/// `FIRST_VALUE(column2) IGNORE NULLS OVER (PARTITION BY column1)`
2400#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2401#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2402#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2403/// How NULL values are treated in certain window functions.
2404pub enum NullTreatment {
2405    /// Ignore NULL values (e.g. `IGNORE NULLS`).
2406    IgnoreNulls,
2407    /// Respect NULL values (e.g. `RESPECT NULLS`).
2408    RespectNulls,
2409}
2410
2411impl fmt::Display for NullTreatment {
2412    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2413        f.write_str(match self {
2414            NullTreatment::IgnoreNulls => "IGNORE NULLS",
2415            NullTreatment::RespectNulls => "RESPECT NULLS",
2416        })
2417    }
2418}
2419
2420/// Specifies [WindowFrame]'s `start_bound` and `end_bound`
2421#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2422#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2423#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2424pub enum WindowFrameBound {
2425    /// `CURRENT ROW`
2426    CurrentRow,
2427    /// `<N> PRECEDING` or `UNBOUNDED PRECEDING`
2428    Preceding(Option<Box<Expr>>),
2429    /// `<N> FOLLOWING` or `UNBOUNDED FOLLOWING`.
2430    Following(Option<Box<Expr>>),
2431}
2432
2433impl fmt::Display for WindowFrameBound {
2434    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2435        match self {
2436            WindowFrameBound::CurrentRow => f.write_str("CURRENT ROW"),
2437            WindowFrameBound::Preceding(None) => f.write_str("UNBOUNDED PRECEDING"),
2438            WindowFrameBound::Following(None) => f.write_str("UNBOUNDED FOLLOWING"),
2439            WindowFrameBound::Preceding(Some(n)) => write!(f, "{n} PRECEDING"),
2440            WindowFrameBound::Following(Some(n)) => write!(f, "{n} FOLLOWING"),
2441        }
2442    }
2443}
2444
2445#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2446#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2447#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2448/// Indicates partition operation type for partition management statements.
2449pub enum AddDropSync {
2450    /// Add partitions.
2451    ADD,
2452    /// Drop partitions.
2453    DROP,
2454    /// Sync partitions.
2455    SYNC,
2456}
2457
2458impl fmt::Display for AddDropSync {
2459    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2460        match self {
2461            AddDropSync::SYNC => f.write_str("SYNC PARTITIONS"),
2462            AddDropSync::DROP => f.write_str("DROP PARTITIONS"),
2463            AddDropSync::ADD => f.write_str("ADD PARTITIONS"),
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/// Object kinds supported by `SHOW CREATE` statements.
2472pub enum ShowCreateObject {
2473    /// An event object for `SHOW CREATE EVENT`.
2474    Event,
2475    /// A function object for `SHOW CREATE FUNCTION`.
2476    Function,
2477    /// A procedure object for `SHOW CREATE PROCEDURE`.
2478    Procedure,
2479    /// A table object for `SHOW CREATE TABLE`.
2480    Table,
2481    /// A trigger object for `SHOW CREATE TRIGGER`.
2482    Trigger,
2483    /// A view object for `SHOW CREATE VIEW`.
2484    View,
2485}
2486
2487impl fmt::Display for ShowCreateObject {
2488    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2489        match self {
2490            ShowCreateObject::Event => f.write_str("EVENT"),
2491            ShowCreateObject::Function => f.write_str("FUNCTION"),
2492            ShowCreateObject::Procedure => f.write_str("PROCEDURE"),
2493            ShowCreateObject::Table => f.write_str("TABLE"),
2494            ShowCreateObject::Trigger => f.write_str("TRIGGER"),
2495            ShowCreateObject::View => f.write_str("VIEW"),
2496        }
2497    }
2498}
2499
2500#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2501#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2502#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2503/// Objects that can be targeted by a `COMMENT` statement.
2504pub enum CommentObject {
2505    /// A collation.
2506    Collation,
2507    /// A table column.
2508    Column,
2509    /// A database.
2510    Database,
2511    /// A domain.
2512    Domain,
2513    /// An extension.
2514    Extension,
2515    /// A function.
2516    Function,
2517    /// An index.
2518    Index,
2519    /// A materialized view.
2520    MaterializedView,
2521    /// A procedure.
2522    Procedure,
2523    /// A role.
2524    Role,
2525    /// A schema.
2526    Schema,
2527    /// A sequence.
2528    Sequence,
2529    /// A table.
2530    Table,
2531    /// A type.
2532    Type,
2533    /// A user.
2534    User,
2535    /// A view.
2536    View,
2537}
2538
2539impl fmt::Display for CommentObject {
2540    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2541        match self {
2542            CommentObject::Collation => f.write_str("COLLATION"),
2543            CommentObject::Column => f.write_str("COLUMN"),
2544            CommentObject::Database => f.write_str("DATABASE"),
2545            CommentObject::Domain => f.write_str("DOMAIN"),
2546            CommentObject::Extension => f.write_str("EXTENSION"),
2547            CommentObject::Function => f.write_str("FUNCTION"),
2548            CommentObject::Index => f.write_str("INDEX"),
2549            CommentObject::MaterializedView => f.write_str("MATERIALIZED VIEW"),
2550            CommentObject::Procedure => f.write_str("PROCEDURE"),
2551            CommentObject::Role => f.write_str("ROLE"),
2552            CommentObject::Schema => f.write_str("SCHEMA"),
2553            CommentObject::Sequence => f.write_str("SEQUENCE"),
2554            CommentObject::Table => f.write_str("TABLE"),
2555            CommentObject::Type => f.write_str("TYPE"),
2556            CommentObject::User => f.write_str("USER"),
2557            CommentObject::View => f.write_str("VIEW"),
2558        }
2559    }
2560}
2561
2562#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2563#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2564#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2565/// Password specification variants used in user-related statements.
2566pub enum Password {
2567    /// A concrete password expression.
2568    Password(Expr),
2569    /// Represents a `NULL` password.
2570    NullPassword,
2571}
2572
2573/// A `CASE` statement.
2574///
2575/// Examples:
2576/// ```sql
2577/// CASE
2578///     WHEN EXISTS(SELECT 1)
2579///         THEN SELECT 1 FROM T;
2580///     WHEN EXISTS(SELECT 2)
2581///         THEN SELECT 1 FROM U;
2582///     ELSE
2583///         SELECT 1 FROM V;
2584/// END CASE;
2585/// ```
2586///
2587/// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#case_search_expression)
2588/// [Snowflake](https://docs.snowflake.com/en/sql-reference/snowflake-scripting/case)
2589#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2590#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2591#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2592pub struct CaseStatement {
2593    /// The `CASE` token that starts the statement.
2594    pub case_token: AttachedToken,
2595    /// Optional expression to match against in `CASE ... WHEN`.
2596    pub match_expr: Option<Expr>,
2597    /// The `WHEN ... THEN` blocks of the `CASE` statement.
2598    pub when_blocks: Vec<ConditionalStatementBlock>,
2599    /// Optional `ELSE` block for the `CASE` statement.
2600    pub else_block: Option<ConditionalStatementBlock>,
2601    /// The last token of the statement (`END` or `CASE`).
2602    pub end_case_token: AttachedToken,
2603}
2604
2605impl fmt::Display for CaseStatement {
2606    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2607        let CaseStatement {
2608            case_token: _,
2609            match_expr,
2610            when_blocks,
2611            else_block,
2612            end_case_token: AttachedToken(end),
2613        } = self;
2614
2615        write!(f, "CASE")?;
2616
2617        if let Some(expr) = match_expr {
2618            write!(f, " {expr}")?;
2619        }
2620
2621        if !when_blocks.is_empty() {
2622            write!(f, " {}", display_separated(when_blocks, " "))?;
2623        }
2624
2625        if let Some(else_block) = else_block {
2626            write!(f, " {else_block}")?;
2627        }
2628
2629        write!(f, " END")?;
2630
2631        if let Token::Word(w) = &end.token {
2632            if w.keyword == Keyword::CASE {
2633                write!(f, " CASE")?;
2634            }
2635        }
2636
2637        Ok(())
2638    }
2639}
2640
2641/// An `IF` statement.
2642///
2643/// Example (BigQuery or Snowflake):
2644/// ```sql
2645/// IF TRUE THEN
2646///     SELECT 1;
2647///     SELECT 2;
2648/// ELSEIF TRUE THEN
2649///     SELECT 3;
2650/// ELSE
2651///     SELECT 4;
2652/// END IF
2653/// ```
2654/// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#if)
2655/// [Snowflake](https://docs.snowflake.com/en/sql-reference/snowflake-scripting/if)
2656///
2657/// Example (MSSQL):
2658/// ```sql
2659/// IF 1=1 SELECT 1 ELSE SELECT 2
2660/// ```
2661/// [MSSQL](https://learn.microsoft.com/en-us/sql/t-sql/language-elements/if-else-transact-sql?view=sql-server-ver16)
2662#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2663#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2664#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2665pub struct IfStatement {
2666    /// The initial `IF` block containing the condition and statements.
2667    pub if_block: ConditionalStatementBlock,
2668    /// Additional `ELSEIF` blocks.
2669    pub elseif_blocks: Vec<ConditionalStatementBlock>,
2670    /// Optional `ELSE` block.
2671    pub else_block: Option<ConditionalStatementBlock>,
2672    /// Optional trailing `END` token for the `IF` statement.
2673    pub end_token: Option<AttachedToken>,
2674}
2675
2676impl fmt::Display for IfStatement {
2677    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2678        let IfStatement {
2679            if_block,
2680            elseif_blocks,
2681            else_block,
2682            end_token,
2683        } = self;
2684
2685        write!(f, "{if_block}")?;
2686
2687        for elseif_block in elseif_blocks {
2688            write!(f, " {elseif_block}")?;
2689        }
2690
2691        if let Some(else_block) = else_block {
2692            write!(f, " {else_block}")?;
2693        }
2694
2695        if let Some(AttachedToken(end_token)) = end_token {
2696            write!(f, " END {end_token}")?;
2697        }
2698
2699        Ok(())
2700    }
2701}
2702
2703/// A `WHILE` statement.
2704///
2705/// Example:
2706/// ```sql
2707/// WHILE @@FETCH_STATUS = 0
2708/// BEGIN
2709///    FETCH NEXT FROM c1 INTO @var1, @var2;
2710/// END
2711/// ```
2712///
2713/// [MsSql](https://learn.microsoft.com/en-us/sql/t-sql/language-elements/while-transact-sql)
2714#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2715#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2716#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2717pub struct WhileStatement {
2718    /// Block executed while the condition holds.
2719    pub while_block: ConditionalStatementBlock,
2720}
2721
2722impl fmt::Display for WhileStatement {
2723    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2724        let WhileStatement { while_block } = self;
2725        write!(f, "{while_block}")?;
2726        Ok(())
2727    }
2728}
2729
2730/// A block within a [Statement::Case] or [Statement::If] or [Statement::While]-like statement
2731///
2732/// Example 1:
2733/// ```sql
2734/// WHEN EXISTS(SELECT 1) THEN SELECT 1;
2735/// ```
2736///
2737/// Example 2:
2738/// ```sql
2739/// IF TRUE THEN SELECT 1; SELECT 2;
2740/// ```
2741///
2742/// Example 3:
2743/// ```sql
2744/// ELSE SELECT 1; SELECT 2;
2745/// ```
2746///
2747/// Example 4:
2748/// ```sql
2749/// WHILE @@FETCH_STATUS = 0
2750/// BEGIN
2751///    FETCH NEXT FROM c1 INTO @var1, @var2;
2752/// END
2753/// ```
2754#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2755#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2756#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2757pub struct ConditionalStatementBlock {
2758    /// Token representing the start of the block (e.g., WHEN/IF/WHILE).
2759    pub start_token: AttachedToken,
2760    /// Optional condition expression for the block.
2761    pub condition: Option<Expr>,
2762    /// Optional token for the `THEN` keyword.
2763    pub then_token: Option<AttachedToken>,
2764    /// The statements contained in this conditional block.
2765    pub conditional_statements: ConditionalStatements,
2766}
2767
2768impl ConditionalStatementBlock {
2769    /// Get the statements in this conditional block.
2770    pub fn statements(&self) -> &Vec<Statement> {
2771        self.conditional_statements.statements()
2772    }
2773}
2774
2775impl fmt::Display for ConditionalStatementBlock {
2776    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2777        let ConditionalStatementBlock {
2778            start_token: AttachedToken(start_token),
2779            condition,
2780            then_token,
2781            conditional_statements,
2782        } = self;
2783
2784        write!(f, "{start_token}")?;
2785
2786        if let Some(condition) = condition {
2787            write!(f, " {condition}")?;
2788        }
2789
2790        if then_token.is_some() {
2791            write!(f, " THEN")?;
2792        }
2793
2794        if !conditional_statements.statements().is_empty() {
2795            write!(f, " {conditional_statements}")?;
2796        }
2797
2798        Ok(())
2799    }
2800}
2801
2802/// A list of statements in a [ConditionalStatementBlock].
2803#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2804#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2805#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2806/// Statements used inside conditional blocks (`IF`, `WHEN`, `WHILE`).
2807pub enum ConditionalStatements {
2808    /// Simple sequence of statements (no `BEGIN`/`END`).
2809    Sequence {
2810        /// The statements in the sequence.
2811        statements: Vec<Statement>,
2812    },
2813    /// Block enclosed by `BEGIN` and `END`.
2814    BeginEnd(BeginEndStatements),
2815}
2816
2817impl ConditionalStatements {
2818    /// Get the statements in this conditional statements block.
2819    pub fn statements(&self) -> &Vec<Statement> {
2820        match self {
2821            ConditionalStatements::Sequence { statements } => statements,
2822            ConditionalStatements::BeginEnd(bes) => &bes.statements,
2823        }
2824    }
2825}
2826
2827impl fmt::Display for ConditionalStatements {
2828    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2829        match self {
2830            ConditionalStatements::Sequence { statements } => {
2831                if !statements.is_empty() {
2832                    format_statement_list(f, statements)?;
2833                }
2834                Ok(())
2835            }
2836            ConditionalStatements::BeginEnd(bes) => write!(f, "{bes}"),
2837        }
2838    }
2839}
2840
2841/// Represents a list of statements enclosed within `BEGIN` and `END` keywords.
2842/// Example:
2843/// ```sql
2844/// BEGIN
2845///     SELECT 1;
2846///     SELECT 2;
2847/// END
2848/// ```
2849#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2850#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2851#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2852pub struct BeginEndStatements {
2853    /// Token representing the `BEGIN` keyword (may include span info).
2854    pub begin_token: AttachedToken,
2855    /// Statements contained within the block.
2856    pub statements: Vec<Statement>,
2857    /// Token representing the `END` keyword (may include span info).
2858    pub end_token: AttachedToken,
2859}
2860
2861impl fmt::Display for BeginEndStatements {
2862    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2863        let BeginEndStatements {
2864            begin_token: AttachedToken(begin_token),
2865            statements,
2866            end_token: AttachedToken(end_token),
2867        } = self;
2868
2869        if begin_token.token != Token::EOF {
2870            write!(f, "{begin_token} ")?;
2871        }
2872        if !statements.is_empty() {
2873            format_statement_list(f, statements)?;
2874        }
2875        if end_token.token != Token::EOF {
2876            write!(f, " {end_token}")?;
2877        }
2878        Ok(())
2879    }
2880}
2881
2882/// A `RAISE` statement.
2883///
2884/// Examples:
2885/// ```sql
2886/// RAISE USING MESSAGE = 'error';
2887///
2888/// RAISE myerror;
2889/// ```
2890///
2891/// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#raise)
2892/// [Snowflake](https://docs.snowflake.com/en/sql-reference/snowflake-scripting/raise)
2893#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2894#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2895#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2896pub struct RaiseStatement {
2897    /// Optional value provided to the RAISE statement.
2898    pub value: Option<RaiseStatementValue>,
2899}
2900
2901impl fmt::Display for RaiseStatement {
2902    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2903        let RaiseStatement { value } = self;
2904
2905        write!(f, "RAISE")?;
2906        if let Some(value) = value {
2907            write!(f, " {value}")?;
2908        }
2909
2910        Ok(())
2911    }
2912}
2913
2914/// Represents the error value of a [RaiseStatement].
2915#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2916#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2917#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2918pub enum RaiseStatementValue {
2919    /// `RAISE USING MESSAGE = 'error'`
2920    UsingMessage(Expr),
2921    /// `RAISE myerror`
2922    Expr(Expr),
2923}
2924
2925impl fmt::Display for RaiseStatementValue {
2926    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2927        match self {
2928            RaiseStatementValue::Expr(expr) => write!(f, "{expr}"),
2929            RaiseStatementValue::UsingMessage(expr) => write!(f, "USING MESSAGE = {expr}"),
2930        }
2931    }
2932}
2933
2934/// A MSSQL `THROW` statement.
2935///
2936/// ```sql
2937/// THROW [ error_number, message, state ]
2938/// ```
2939///
2940/// [MSSQL](https://learn.microsoft.com/en-us/sql/t-sql/language-elements/throw-transact-sql)
2941#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2942#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2943#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2944pub struct ThrowStatement {
2945    /// Error number expression.
2946    pub error_number: Option<Box<Expr>>,
2947    /// Error message expression.
2948    pub message: Option<Box<Expr>>,
2949    /// State expression.
2950    pub state: Option<Box<Expr>>,
2951}
2952
2953impl fmt::Display for ThrowStatement {
2954    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2955        let ThrowStatement {
2956            error_number,
2957            message,
2958            state,
2959        } = self;
2960
2961        write!(f, "THROW")?;
2962        if let (Some(error_number), Some(message), Some(state)) = (error_number, message, state) {
2963            write!(f, " {error_number}, {message}, {state}")?;
2964        }
2965        Ok(())
2966    }
2967}
2968
2969/// Represents an expression assignment within a variable `DECLARE` statement.
2970///
2971/// Examples:
2972/// ```sql
2973/// DECLARE variable_name := 42
2974/// DECLARE variable_name DEFAULT 42
2975/// ```
2976#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2977#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2978#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2979pub enum DeclareAssignment {
2980    /// Plain expression specified.
2981    Expr(Box<Expr>),
2982
2983    /// Expression assigned via the `DEFAULT` keyword
2984    Default(Box<Expr>),
2985
2986    /// Expression assigned via the `:=` syntax
2987    ///
2988    /// Example:
2989    /// ```sql
2990    /// DECLARE variable_name := 42;
2991    /// ```
2992    DuckAssignment(Box<Expr>),
2993
2994    /// Expression via the `FOR` keyword
2995    ///
2996    /// Example:
2997    /// ```sql
2998    /// DECLARE c1 CURSOR FOR res
2999    /// ```
3000    For(Box<Expr>),
3001
3002    /// Expression via the `=` syntax.
3003    ///
3004    /// Example:
3005    /// ```sql
3006    /// DECLARE @variable AS INT = 100
3007    /// ```
3008    MsSqlAssignment(Box<Expr>),
3009}
3010
3011impl fmt::Display for DeclareAssignment {
3012    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3013        match self {
3014            DeclareAssignment::Expr(expr) => {
3015                write!(f, "{expr}")
3016            }
3017            DeclareAssignment::Default(expr) => {
3018                write!(f, "DEFAULT {expr}")
3019            }
3020            DeclareAssignment::DuckAssignment(expr) => {
3021                write!(f, ":= {expr}")
3022            }
3023            DeclareAssignment::MsSqlAssignment(expr) => {
3024                write!(f, "= {expr}")
3025            }
3026            DeclareAssignment::For(expr) => {
3027                write!(f, "FOR {expr}")
3028            }
3029        }
3030    }
3031}
3032
3033/// Represents the type of a `DECLARE` statement.
3034#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3035#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3036#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3037pub enum DeclareType {
3038    /// Cursor variable type. e.g. [Snowflake] [PostgreSQL] [MsSql]
3039    ///
3040    /// [Snowflake]: https://docs.snowflake.com/en/developer-guide/snowflake-scripting/cursors#declaring-a-cursor
3041    /// [PostgreSQL]: https://www.postgresql.org/docs/current/plpgsql-cursors.html
3042    /// [MsSql]: https://learn.microsoft.com/en-us/sql/t-sql/language-elements/declare-cursor-transact-sql
3043    Cursor,
3044
3045    /// Result set variable type. [Snowflake]
3046    ///
3047    /// Syntax:
3048    /// ```text
3049    /// <resultset_name> RESULTSET [ { DEFAULT | := } ( <query> ) ] ;
3050    /// ```
3051    /// [Snowflake]: https://docs.snowflake.com/en/sql-reference/snowflake-scripting/declare#resultset-declaration-syntax
3052    ResultSet,
3053
3054    /// Exception declaration syntax. [Snowflake]
3055    ///
3056    /// Syntax:
3057    /// ```text
3058    /// <exception_name> EXCEPTION [ ( <exception_number> , '<exception_message>' ) ] ;
3059    /// ```
3060    /// [Snowflake]: https://docs.snowflake.com/en/sql-reference/snowflake-scripting/declare#exception-declaration-syntax
3061    Exception,
3062}
3063
3064impl fmt::Display for DeclareType {
3065    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3066        match self {
3067            DeclareType::Cursor => {
3068                write!(f, "CURSOR")
3069            }
3070            DeclareType::ResultSet => {
3071                write!(f, "RESULTSET")
3072            }
3073            DeclareType::Exception => {
3074                write!(f, "EXCEPTION")
3075            }
3076        }
3077    }
3078}
3079
3080/// A `DECLARE` statement.
3081/// [PostgreSQL] [Snowflake] [BigQuery]
3082///
3083/// Examples:
3084/// ```sql
3085/// DECLARE variable_name := 42
3086/// DECLARE liahona CURSOR FOR SELECT * FROM films;
3087/// ```
3088///
3089/// [PostgreSQL]: https://www.postgresql.org/docs/current/sql-declare.html
3090/// [Snowflake]: https://docs.snowflake.com/en/sql-reference/snowflake-scripting/declare
3091/// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#declare
3092#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3093#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3094#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3095pub struct Declare {
3096    /// The name(s) being declared.
3097    /// Example: `DECLARE a, b, c DEFAULT 42;
3098    pub names: Vec<Ident>,
3099    /// Data-type assigned to the declared variable.
3100    /// Example: `DECLARE x INT64 DEFAULT 42;
3101    pub data_type: Option<DataType>,
3102    /// Expression being assigned to the declared variable.
3103    pub assignment: Option<DeclareAssignment>,
3104    /// Represents the type of the declared variable.
3105    pub declare_type: Option<DeclareType>,
3106    /// Causes the cursor to return data in binary rather than in text format.
3107    pub binary: Option<bool>,
3108    /// None = Not specified
3109    /// Some(true) = INSENSITIVE
3110    /// Some(false) = ASENSITIVE
3111    pub sensitive: Option<bool>,
3112    /// None = Not specified
3113    /// Some(true) = SCROLL
3114    /// Some(false) = NO SCROLL
3115    pub scroll: Option<bool>,
3116    /// None = Not specified
3117    /// Some(true) = WITH HOLD, specifies that the cursor can continue to be used after the transaction that created it successfully commits
3118    /// Some(false) = WITHOUT HOLD, specifies that the cursor cannot be used outside of the transaction that created it
3119    pub hold: Option<bool>,
3120    /// `FOR <query>` clause in a CURSOR declaration.
3121    pub for_query: Option<Box<Query>>,
3122}
3123
3124impl fmt::Display for Declare {
3125    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3126        let Declare {
3127            names,
3128            data_type,
3129            assignment,
3130            declare_type,
3131            binary,
3132            sensitive,
3133            scroll,
3134            hold,
3135            for_query,
3136        } = self;
3137        write!(f, "{}", display_comma_separated(names))?;
3138
3139        if let Some(true) = binary {
3140            write!(f, " BINARY")?;
3141        }
3142
3143        if let Some(sensitive) = sensitive {
3144            if *sensitive {
3145                write!(f, " INSENSITIVE")?;
3146            } else {
3147                write!(f, " ASENSITIVE")?;
3148            }
3149        }
3150
3151        if let Some(scroll) = scroll {
3152            if *scroll {
3153                write!(f, " SCROLL")?;
3154            } else {
3155                write!(f, " NO SCROLL")?;
3156            }
3157        }
3158
3159        if let Some(declare_type) = declare_type {
3160            write!(f, " {declare_type}")?;
3161        }
3162
3163        if let Some(hold) = hold {
3164            if *hold {
3165                write!(f, " WITH HOLD")?;
3166            } else {
3167                write!(f, " WITHOUT HOLD")?;
3168            }
3169        }
3170
3171        if let Some(query) = for_query {
3172            write!(f, " FOR {query}")?;
3173        }
3174
3175        if let Some(data_type) = data_type {
3176            write!(f, " {data_type}")?;
3177        }
3178
3179        if let Some(expr) = assignment {
3180            write!(f, " {expr}")?;
3181        }
3182        Ok(())
3183    }
3184}
3185
3186/// Sql options of a `CREATE TABLE` statement.
3187#[derive(Debug, Default, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3188#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3189#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3190/// Options allowed within a `CREATE TABLE` statement.
3191pub enum CreateTableOptions {
3192    /// No options specified.
3193    #[default]
3194    None,
3195    /// Options specified using the `WITH` keyword, e.g. `WITH (k = v)`.
3196    With(Vec<SqlOption>),
3197    /// Options specified using the `OPTIONS(...)` clause.
3198    Options(Vec<SqlOption>),
3199    /// Plain space-separated options.
3200    Plain(Vec<SqlOption>),
3201    /// Table properties (e.g., TBLPROPERTIES / storage properties).
3202    TableProperties(Vec<SqlOption>),
3203}
3204
3205impl fmt::Display for CreateTableOptions {
3206    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3207        match self {
3208            CreateTableOptions::With(with_options) => {
3209                write!(f, "WITH ({})", display_comma_separated(with_options))
3210            }
3211            CreateTableOptions::Options(options) => {
3212                write!(f, "OPTIONS({})", display_comma_separated(options))
3213            }
3214            CreateTableOptions::TableProperties(options) => {
3215                write!(f, "TBLPROPERTIES ({})", display_comma_separated(options))
3216            }
3217            CreateTableOptions::Plain(options) => {
3218                write!(f, "{}", display_separated(options, " "))
3219            }
3220            CreateTableOptions::None => Ok(()),
3221        }
3222    }
3223}
3224
3225/// A `FROM` clause within a `DELETE` statement.
3226///
3227/// Syntax
3228/// ```sql
3229/// [FROM] table
3230/// ```
3231#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3232#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3233#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3234pub enum FromTable {
3235    /// An explicit `FROM` keyword was specified.
3236    WithFromKeyword(Vec<TableWithJoins>),
3237    /// BigQuery: `FROM` keyword was omitted.
3238    /// <https://cloud.google.com/bigquery/docs/reference/standard-sql/dml-syntax#delete_statement>
3239    WithoutKeyword(Vec<TableWithJoins>),
3240}
3241impl Display for FromTable {
3242    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3243        match self {
3244            FromTable::WithFromKeyword(tables) => {
3245                write!(f, "FROM {}", display_comma_separated(tables))
3246            }
3247            FromTable::WithoutKeyword(tables) => {
3248                write!(f, "{}", display_comma_separated(tables))
3249            }
3250        }
3251    }
3252}
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))]
3257/// Variants for the `SET` family of statements.
3258pub enum Set {
3259    /// SQL Standard-style
3260    /// SET a = 1;
3261    /// `SET var = value` (standard SQL-style assignment).
3262    SingleAssignment {
3263        /// Optional scope modifier (`SESSION` / `LOCAL`).
3264        scope: Option<ContextModifier>,
3265        /// Whether this is a Hive-style `HIVEVAR:` assignment.
3266        hivevar: bool,
3267        /// Variable name to assign.
3268        variable: ObjectName,
3269        /// Values assigned to the variable.
3270        values: Vec<Expr>,
3271    },
3272    /// Snowflake-style
3273    /// SET (a, b, ..) = (1, 2, ..);
3274    /// `SET (a, b) = (1, 2)` (tuple assignment syntax).
3275    ParenthesizedAssignments {
3276        /// Variables being assigned in tuple form.
3277        variables: Vec<ObjectName>,
3278        /// Corresponding values for the variables.
3279        values: Vec<Expr>,
3280    },
3281    /// MySQL-style
3282    /// SET a = 1, b = 2, ..;
3283    /// `SET a = 1, b = 2` (MySQL-style comma-separated assignments).
3284    MultipleAssignments {
3285        /// List of `SET` assignments (MySQL-style comma-separated).
3286        assignments: Vec<SetAssignment>,
3287    },
3288    /// Session authorization for Postgres/Redshift
3289    ///
3290    /// ```sql
3291    /// SET SESSION AUTHORIZATION { user_name | DEFAULT }
3292    /// ```
3293    ///
3294    /// See <https://www.postgresql.org/docs/current/sql-set-session-authorization.html>
3295    /// See <https://docs.aws.amazon.com/redshift/latest/dg/r_SET_SESSION_AUTHORIZATION.html>
3296    SetSessionAuthorization(SetSessionAuthorizationParam),
3297    /// MS-SQL session
3298    ///
3299    /// See <https://learn.microsoft.com/en-us/sql/t-sql/statements/set-statements-transact-sql>
3300    SetSessionParam(SetSessionParamKind),
3301    /// ```sql
3302    /// SET [ SESSION | LOCAL ] ROLE role_name
3303    /// ```
3304    ///
3305    /// Sets session state. Examples: [ANSI][1], [Postgresql][2], [MySQL][3], and [Oracle][4]
3306    ///
3307    /// [1]: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#set-role-statement
3308    /// [2]: https://www.postgresql.org/docs/14/sql-set-role.html
3309    /// [3]: https://dev.mysql.com/doc/refman/8.0/en/set-role.html
3310    /// [4]: https://docs.oracle.com/cd/B19306_01/server.102/b14200/statements_10004.htm
3311    SetRole {
3312        /// Non-ANSI optional identifier to inform if the role is defined inside the current session (`SESSION`) or transaction (`LOCAL`).
3313        context_modifier: Option<ContextModifier>,
3314        /// Role name. If NONE is specified, then the current role name is removed.
3315        role_name: Option<Ident>,
3316    },
3317    /// ```sql
3318    /// SET TIME ZONE <value>
3319    /// ```
3320    ///
3321    /// Note: this is a PostgreSQL-specific statements
3322    /// `SET TIME ZONE <value>` is an alias for `SET timezone TO <value>` in PostgreSQL
3323    /// However, we allow it for all dialects.
3324    /// `SET TIME ZONE` statement. `local` indicates the `LOCAL` keyword.
3325    /// `SET TIME ZONE <value>` statement.
3326    SetTimeZone {
3327        /// Whether the `LOCAL` keyword was specified.
3328        local: bool,
3329        /// Time zone expression value.
3330        value: Expr,
3331    },
3332    /// ```sql
3333    /// SET NAMES 'charset_name' [COLLATE 'collation_name']
3334    /// ```
3335    SetNames {
3336        /// Character set name to set.
3337        charset_name: Ident,
3338        /// Optional collation name.
3339        collation_name: Option<String>,
3340    },
3341    /// ```sql
3342    /// SET NAMES DEFAULT
3343    /// ```
3344    ///
3345    /// Note: this is a MySQL-specific statement.
3346    SetNamesDefault {},
3347    /// ```sql
3348    /// SET TRANSACTION ...
3349    /// ```
3350    SetTransaction {
3351        /// Transaction modes (e.g., ISOLATION LEVEL, READ ONLY).
3352        modes: Vec<TransactionMode>,
3353        /// Optional snapshot value for transaction snapshot control.
3354        snapshot: Option<ValueWithSpan>,
3355        /// `true` when the `SESSION` keyword was used.
3356        session: bool,
3357    },
3358}
3359
3360impl Display for Set {
3361    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3362        match self {
3363            Self::ParenthesizedAssignments { variables, values } => write!(
3364                f,
3365                "SET ({}) = ({})",
3366                display_comma_separated(variables),
3367                display_comma_separated(values)
3368            ),
3369            Self::MultipleAssignments { assignments } => {
3370                write!(f, "SET {}", display_comma_separated(assignments))
3371            }
3372            Self::SetRole {
3373                context_modifier,
3374                role_name,
3375            } => {
3376                let role_name = role_name.clone().unwrap_or_else(|| Ident::new("NONE"));
3377                write!(
3378                    f,
3379                    "SET {modifier}ROLE {role_name}",
3380                    modifier = context_modifier.map(|m| format!("{m}")).unwrap_or_default()
3381                )
3382            }
3383            Self::SetSessionAuthorization(kind) => write!(f, "SET SESSION AUTHORIZATION {kind}"),
3384            Self::SetSessionParam(kind) => write!(f, "SET {kind}"),
3385            Self::SetTransaction {
3386                modes,
3387                snapshot,
3388                session,
3389            } => {
3390                if *session {
3391                    write!(f, "SET SESSION CHARACTERISTICS AS TRANSACTION")?;
3392                } else {
3393                    write!(f, "SET TRANSACTION")?;
3394                }
3395                if !modes.is_empty() {
3396                    write!(f, " {}", display_comma_separated(modes))?;
3397                }
3398                if let Some(snapshot_id) = snapshot {
3399                    write!(f, " SNAPSHOT {snapshot_id}")?;
3400                }
3401                Ok(())
3402            }
3403            Self::SetTimeZone { local, value } => {
3404                f.write_str("SET ")?;
3405                if *local {
3406                    f.write_str("LOCAL ")?;
3407                }
3408                write!(f, "TIME ZONE {value}")
3409            }
3410            Self::SetNames {
3411                charset_name,
3412                collation_name,
3413            } => {
3414                write!(f, "SET NAMES {charset_name}")?;
3415
3416                if let Some(collation) = collation_name {
3417                    f.write_str(" COLLATE ")?;
3418                    f.write_str(collation)?;
3419                };
3420
3421                Ok(())
3422            }
3423            Self::SetNamesDefault {} => {
3424                f.write_str("SET NAMES DEFAULT")?;
3425
3426                Ok(())
3427            }
3428            Set::SingleAssignment {
3429                scope,
3430                hivevar,
3431                variable,
3432                values,
3433            } => {
3434                write!(
3435                    f,
3436                    "SET {}{}{} = {}",
3437                    scope.map(|s| format!("{s}")).unwrap_or_default(),
3438                    if *hivevar { "HIVEVAR:" } else { "" },
3439                    variable,
3440                    display_comma_separated(values)
3441                )
3442            }
3443        }
3444    }
3445}
3446
3447/// A representation of a `WHEN` arm with all the identifiers catched and the statements to execute
3448/// for the arm.
3449///
3450/// Snowflake: <https://docs.snowflake.com/en/sql-reference/snowflake-scripting/exception>
3451/// BigQuery: <https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#beginexceptionend>
3452#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3453#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3454#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3455pub struct ExceptionWhen {
3456    /// Identifiers that trigger this branch (error conditions).
3457    pub idents: Vec<Ident>,
3458    /// Statements to execute when the condition matches.
3459    pub statements: Vec<Statement>,
3460}
3461
3462impl Display for ExceptionWhen {
3463    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3464        write!(
3465            f,
3466            "WHEN {idents} THEN",
3467            idents = display_separated(&self.idents, " OR ")
3468        )?;
3469
3470        if !self.statements.is_empty() {
3471            write!(f, " ")?;
3472            format_statement_list(f, &self.statements)?;
3473        }
3474
3475        Ok(())
3476    }
3477}
3478
3479/// ANALYZE statement
3480///
3481/// Supported syntax varies by dialect:
3482/// - Hive: `ANALYZE TABLE t [PARTITION (...)] COMPUTE STATISTICS [NOSCAN] [FOR COLUMNS [col1, ...]] [CACHE METADATA]`
3483/// - PostgreSQL: `ANALYZE [VERBOSE] [t [(col1, ...)]]` See <https://www.postgresql.org/docs/current/sql-analyze.html>
3484/// - General: `ANALYZE [TABLE] t`
3485#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3486#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3487#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3488pub struct Analyze {
3489    #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
3490    /// Name of the table to analyze. `None` for bare `ANALYZE`.
3491    pub table_name: Option<ObjectName>,
3492    /// Optional partition expressions to restrict the analysis.
3493    pub partitions: Option<Vec<Expr>>,
3494    /// `true` when analyzing specific columns (Hive `FOR COLUMNS` syntax).
3495    pub for_columns: bool,
3496    /// Columns to analyze.
3497    pub columns: Vec<Ident>,
3498    /// Whether to cache metadata before analyzing.
3499    pub cache_metadata: bool,
3500    /// Whether to skip scanning the table.
3501    pub noscan: bool,
3502    /// Whether to compute statistics during analysis.
3503    pub compute_statistics: bool,
3504    /// Whether the `TABLE` keyword was present.
3505    pub has_table_keyword: bool,
3506}
3507
3508impl fmt::Display for Analyze {
3509    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3510        write!(f, "ANALYZE")?;
3511        if let Some(ref table_name) = self.table_name {
3512            if self.has_table_keyword {
3513                write!(f, " TABLE")?;
3514            }
3515            write!(f, " {table_name}")?;
3516        }
3517        if !self.for_columns && !self.columns.is_empty() {
3518            write!(f, " ({})", display_comma_separated(&self.columns))?;
3519        }
3520        if let Some(ref parts) = self.partitions {
3521            if !parts.is_empty() {
3522                write!(f, " PARTITION ({})", display_comma_separated(parts))?;
3523            }
3524        }
3525        if self.compute_statistics {
3526            write!(f, " COMPUTE STATISTICS")?;
3527        }
3528        if self.noscan {
3529            write!(f, " NOSCAN")?;
3530        }
3531        if self.cache_metadata {
3532            write!(f, " CACHE METADATA")?;
3533        }
3534        if self.for_columns {
3535            write!(f, " FOR COLUMNS")?;
3536            if !self.columns.is_empty() {
3537                write!(f, " {}", display_comma_separated(&self.columns))?;
3538            }
3539        }
3540        Ok(())
3541    }
3542}
3543
3544/// A top-level statement (SELECT, INSERT, CREATE, etc.)
3545#[allow(clippy::large_enum_variant)]
3546#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3547#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3548#[cfg_attr(
3549    feature = "visitor",
3550    derive(Visit, VisitMut),
3551    visit(with = "visit_statement")
3552)]
3553pub enum Statement {
3554    /// ```sql
3555    /// ANALYZE
3556    /// ```
3557    /// Analyze (Hive)
3558    Analyze(Analyze),
3559    /// `SET` statements (session, transaction, timezone, etc.).
3560    Set(Set),
3561    /// ```sql
3562    /// TRUNCATE
3563    /// ```
3564    /// Truncate (Hive)
3565    Truncate(Truncate),
3566    /// ```sql
3567    /// MSCK
3568    /// ```
3569    /// Msck (Hive)
3570    Msck(Msck),
3571    /// ```sql
3572    /// SELECT
3573    /// ```
3574    Query(Box<Query>),
3575    /// ```sql
3576    /// INSERT
3577    /// ```
3578    Insert(Insert),
3579    /// ```sql
3580    /// INSTALL
3581    /// ```
3582    Install {
3583        /// Only for DuckDB
3584        extension_name: Ident,
3585    },
3586    /// ```sql
3587    /// LOAD
3588    /// ```
3589    Load {
3590        /// Only for DuckDB
3591        extension_name: Ident,
3592    },
3593    // TODO: Support ROW FORMAT
3594    /// LOAD DATA from a directory or query source.
3595    Directory {
3596        /// Whether to overwrite existing files.
3597        overwrite: bool,
3598        /// Whether the directory is local to the server.
3599        local: bool,
3600        /// Path to the directory or files.
3601        path: String,
3602        /// Optional file format for the data.
3603        file_format: Option<FileFormat>,
3604        /// Source query providing data to load.
3605        source: Box<Query>,
3606    },
3607    /// A `CASE` statement.
3608    Case(CaseStatement),
3609    /// An `IF` statement.
3610    If(IfStatement),
3611    /// A `WHILE` statement.
3612    While(WhileStatement),
3613    /// A `RAISE` statement.
3614    Raise(RaiseStatement),
3615    /// ```sql
3616    /// CALL <function>
3617    /// ```
3618    Call(Function),
3619    /// ```sql
3620    /// COPY [TO | FROM] ...
3621    /// ```
3622    Copy {
3623        /// The source of 'COPY TO', or the target of 'COPY FROM'
3624        source: CopySource,
3625        /// If true, is a 'COPY TO' statement. If false is a 'COPY FROM'
3626        to: bool,
3627        /// The target of 'COPY TO', or the source of 'COPY FROM'
3628        target: CopyTarget,
3629        /// WITH options (from PostgreSQL version 9.0)
3630        options: Vec<CopyOption>,
3631        /// WITH options (before PostgreSQL version 9.0)
3632        legacy_options: Vec<CopyLegacyOption>,
3633        /// VALUES a vector of values to be copied
3634        values: Vec<Option<String>>,
3635    },
3636    /// ```sql
3637    /// COPY INTO <table> | <location>
3638    /// ```
3639    /// See:
3640    /// <https://docs.snowflake.com/en/sql-reference/sql/copy-into-table>
3641    /// <https://docs.snowflake.com/en/sql-reference/sql/copy-into-location>
3642    ///
3643    /// Copy Into syntax available for Snowflake is different than the one implemented in
3644    /// Postgres. Although they share common prefix, it is reasonable to implement them
3645    /// in different enums. This can be refactored later once custom dialects
3646    /// are allowed to have custom Statements.
3647    CopyIntoSnowflake {
3648        /// Kind of COPY INTO operation (table or location).
3649        kind: CopyIntoSnowflakeKind,
3650        /// Target object for the COPY INTO operation.
3651        into: ObjectName,
3652        /// Optional list of target columns.
3653        into_columns: Option<Vec<Ident>>,
3654        /// Optional source object name (staged data).
3655        from_obj: Option<ObjectName>,
3656        /// Optional alias for the source object.
3657        from_obj_alias: Option<Ident>,
3658        /// Stage-specific parameters (e.g., credentials, path).
3659        stage_params: StageParamsObject,
3660        /// Optional list of transformations applied when loading.
3661        from_transformations: Option<Vec<StageLoadSelectItemKind>>,
3662        /// Optional source query instead of a staged object.
3663        from_query: Option<Box<Query>>,
3664        /// Optional list of specific file names to load.
3665        files: Option<Vec<String>>,
3666        /// Optional filename matching pattern.
3667        pattern: Option<String>,
3668        /// File format options.
3669        file_format: KeyValueOptions,
3670        /// Additional copy options.
3671        copy_options: KeyValueOptions,
3672        /// Optional validation mode string.
3673        validation_mode: Option<String>,
3674        /// Optional partition expression for loading.
3675        partition: Option<Box<Expr>>,
3676    },
3677    /// ```sql
3678    /// OPEN cursor_name
3679    /// ```
3680    /// Opens a cursor.
3681    Open(OpenStatement),
3682    /// ```sql
3683    /// CLOSE
3684    /// ```
3685    /// Closes the portal underlying an open cursor.
3686    Close {
3687        /// Cursor name
3688        cursor: CloseCursor,
3689    },
3690    /// ```sql
3691    /// UPDATE
3692    /// ```
3693    Update(Update),
3694    /// ```sql
3695    /// DELETE
3696    /// ```
3697    Delete(Delete),
3698    /// ```sql
3699    /// CREATE VIEW
3700    /// ```
3701    CreateView(CreateView),
3702    /// ```sql
3703    /// CREATE TABLE
3704    /// ```
3705    CreateTable(CreateTable),
3706    /// ```sql
3707    /// CREATE VIRTUAL TABLE .. USING <module_name> (<module_args>)`
3708    /// ```
3709    /// Sqlite specific statement
3710    CreateVirtualTable {
3711        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
3712        /// Name of the virtual table module instance.
3713        name: ObjectName,
3714        /// `true` when `IF NOT EXISTS` was specified.
3715        if_not_exists: bool,
3716        /// Module name used by the virtual table.
3717        module_name: Ident,
3718        /// Arguments passed to the module.
3719        module_args: Vec<Ident>,
3720    },
3721    /// ```sql
3722    /// `CREATE INDEX`
3723    /// ```
3724    CreateIndex(CreateIndex),
3725    /// ```sql
3726    /// CREATE ROLE
3727    /// ```
3728    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createrole.html)
3729    CreateRole(CreateRole),
3730    /// ```sql
3731    /// CREATE SECRET
3732    /// ```
3733    /// See [DuckDB](https://duckdb.org/docs/sql/statements/create_secret.html)
3734    CreateSecret {
3735        /// `true` when `OR REPLACE` was specified.
3736        or_replace: bool,
3737        /// Optional `TEMPORARY` flag.
3738        temporary: Option<bool>,
3739        /// `true` when `IF NOT EXISTS` was present.
3740        if_not_exists: bool,
3741        /// Optional secret name.
3742        name: Option<Ident>,
3743        /// Optional storage specifier identifier.
3744        storage_specifier: Option<Ident>,
3745        /// The secret type identifier.
3746        secret_type: Ident,
3747        /// Additional secret options.
3748        options: Vec<SecretOption>,
3749    },
3750    /// A `CREATE SERVER` statement.
3751    CreateServer(CreateServerStatement),
3752    /// ```sql
3753    /// CREATE POLICY
3754    /// ```
3755    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createpolicy.html)
3756    CreatePolicy(CreatePolicy),
3757    /// ```sql
3758    /// CREATE CONNECTOR
3759    /// ```
3760    /// See [Hive](https://cwiki.apache.org/confluence/pages/viewpage.action?pageId=27362034#LanguageManualDDL-CreateDataConnectorCreateConnector)
3761    CreateConnector(CreateConnector),
3762    /// ```sql
3763    /// CREATE OPERATOR
3764    /// ```
3765    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createoperator.html)
3766    CreateOperator(CreateOperator),
3767    /// ```sql
3768    /// CREATE OPERATOR FAMILY
3769    /// ```
3770    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createopfamily.html)
3771    CreateOperatorFamily(CreateOperatorFamily),
3772    /// ```sql
3773    /// CREATE OPERATOR CLASS
3774    /// ```
3775    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createopclass.html)
3776    CreateOperatorClass(CreateOperatorClass),
3777    /// A `CREATE TEXT SEARCH` statement.
3778    ///
3779    /// See [PostgreSQL](https://www.postgresql.org/docs/current/textsearch-intro.html)
3780    CreateTextSearch(CreateTextSearch),
3781    /// ```sql
3782    /// ALTER TABLE
3783    /// ```
3784    AlterTable(AlterTable),
3785    /// ```sql
3786    /// ALTER SCHEMA
3787    /// ```
3788    /// See [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#alter_schema_collate_statement)
3789    AlterSchema(AlterSchema),
3790    /// ```sql
3791    /// ALTER INDEX
3792    /// ```
3793    AlterIndex {
3794        /// Name of the index to alter.
3795        name: ObjectName,
3796        /// The operation to perform on the index.
3797        operation: AlterIndexOperation,
3798    },
3799    /// ```sql
3800    /// ALTER VIEW
3801    /// ```
3802    AlterView {
3803        /// View name being altered.
3804        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
3805        name: ObjectName,
3806        /// Optional new column list for the view.
3807        columns: Vec<Ident>,
3808        /// Replacement query for the view definition.
3809        query: Box<Query>,
3810        /// Additional WITH options for the view.
3811        with_options: Vec<SqlOption>,
3812    },
3813    /// ```sql
3814    /// ALTER FUNCTION
3815    /// ALTER AGGREGATE
3816    /// ```
3817    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-alterfunction.html)
3818    /// and [PostgreSQL](https://www.postgresql.org/docs/current/sql-alteraggregate.html)
3819    AlterFunction(AlterFunction),
3820    /// ```sql
3821    /// ALTER TYPE
3822    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-altertype.html)
3823    /// ```
3824    AlterType(AlterType),
3825    /// ```sql
3826    /// ALTER COLLATION
3827    /// ```
3828    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-altercollation.html)
3829    AlterCollation(AlterCollation),
3830    /// ```sql
3831    /// ALTER OPERATOR
3832    /// ```
3833    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-alteroperator.html)
3834    AlterOperator(AlterOperator),
3835    /// ```sql
3836    /// ALTER OPERATOR FAMILY
3837    /// ```
3838    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-alteropfamily.html)
3839    AlterOperatorFamily(AlterOperatorFamily),
3840    /// ```sql
3841    /// ALTER OPERATOR CLASS
3842    /// ```
3843    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-alteropclass.html)
3844    AlterOperatorClass(AlterOperatorClass),
3845    /// An `ALTER TEXT SEARCH` statement.
3846    ///
3847    /// See [PostgreSQL](https://www.postgresql.org/docs/current/textsearch-configuration.html)
3848    AlterTextSearch(AlterTextSearch),
3849    /// ```sql
3850    /// ALTER ROLE
3851    /// ```
3852    AlterRole {
3853        /// Role name being altered.
3854        name: Ident,
3855        /// Operation to perform on the role.
3856        operation: AlterRoleOperation,
3857    },
3858    /// ```sql
3859    /// ALTER POLICY <NAME> ON <TABLE NAME> [<OPERATION>]
3860    /// ```
3861    /// (Postgresql-specific)
3862    AlterPolicy(AlterPolicy),
3863    /// ```sql
3864    /// ALTER CONNECTOR connector_name SET DCPROPERTIES(property_name=property_value, ...);
3865    /// or
3866    /// ALTER CONNECTOR connector_name SET URL new_url;
3867    /// or
3868    /// ALTER CONNECTOR connector_name SET OWNER [USER|ROLE] user_or_role;
3869    /// ```
3870    /// (Hive-specific)
3871    AlterConnector {
3872        /// Name of the connector to alter.
3873        name: Ident,
3874        /// Optional connector properties to set.
3875        properties: Option<Vec<SqlOption>>,
3876        /// Optional new URL for the connector.
3877        url: Option<String>,
3878        /// Optional new owner specification.
3879        owner: Option<ddl::AlterConnectorOwner>,
3880    },
3881    /// ```sql
3882    /// ALTER SESSION SET sessionParam
3883    /// ALTER SESSION UNSET <param_name> [ , <param_name> , ... ]
3884    /// ```
3885    /// See <https://docs.snowflake.com/en/sql-reference/sql/alter-session>
3886    AlterSession {
3887        /// true is to set for the session parameters, false is to unset
3888        set: bool,
3889        /// The session parameters to set or unset
3890        session_params: KeyValueOptions,
3891    },
3892    /// ```sql
3893    /// ATTACH DATABASE 'path/to/file' AS alias
3894    /// ```
3895    /// (SQLite-specific)
3896    AttachDatabase {
3897        /// The name to bind to the newly attached database
3898        schema_name: Ident,
3899        /// An expression that indicates the path to the database file
3900        database_file_name: Expr,
3901        /// true if the syntax is 'ATTACH DATABASE', false if it's just 'ATTACH'
3902        database: bool,
3903    },
3904    /// (DuckDB-specific)
3905    /// ```sql
3906    /// ATTACH 'sqlite_file.db' AS sqlite_db (READ_ONLY, TYPE SQLITE);
3907    /// ```
3908    /// See <https://duckdb.org/docs/sql/statements/attach.html>
3909    AttachDuckDBDatabase {
3910        /// `true` when `IF NOT EXISTS` was present.
3911        if_not_exists: bool,
3912        /// `true` if the syntax used `ATTACH DATABASE` rather than `ATTACH`.
3913        database: bool,
3914        /// The path identifier to the database file being attached.
3915        database_path: Ident,
3916        /// Optional alias assigned to the attached database.
3917        database_alias: Option<Ident>,
3918        /// Dialect-specific attach options (e.g., `READ_ONLY`).
3919        attach_options: Vec<AttachDuckDBDatabaseOption>,
3920    },
3921    /// (DuckDB-specific)
3922    /// ```sql
3923    /// DETACH db_alias;
3924    /// ```
3925    /// See <https://duckdb.org/docs/sql/statements/attach.html>
3926    DetachDuckDBDatabase {
3927        /// `true` when `IF EXISTS` was present.
3928        if_exists: bool,
3929        /// `true` if the syntax used `DETACH DATABASE` rather than `DETACH`.
3930        database: bool,
3931        /// Alias of the database to detach.
3932        database_alias: Ident,
3933    },
3934    /// ```sql
3935    /// DROP [TABLE, VIEW, ...]
3936    /// ```
3937    Drop {
3938        /// The type of the object to drop: TABLE, VIEW, etc.
3939        object_type: ObjectType,
3940        /// An optional `IF EXISTS` clause. (Non-standard.)
3941        if_exists: bool,
3942        /// One or more objects to drop. (ANSI SQL requires exactly one.)
3943        names: Vec<ObjectName>,
3944        /// Whether `CASCADE` was specified. This will be `false` when
3945        /// `RESTRICT` or no drop behavior at all was specified.
3946        cascade: bool,
3947        /// Whether `RESTRICT` was specified. This will be `false` when
3948        /// `CASCADE` or no drop behavior at all was specified.
3949        restrict: bool,
3950        /// Hive allows you specify whether the table's stored data will be
3951        /// deleted along with the dropped table
3952        purge: bool,
3953        /// MySQL-specific "TEMPORARY" keyword
3954        temporary: bool,
3955        /// MySQL-specific drop index syntax, which requires table specification
3956        /// See <https://dev.mysql.com/doc/refman/8.4/en/drop-index.html>
3957        table: Option<ObjectName>,
3958    },
3959    /// ```sql
3960    /// DROP FUNCTION
3961    /// ```
3962    DropFunction(DropFunction),
3963    /// ```sql
3964    /// DROP DOMAIN
3965    /// ```
3966    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-dropdomain.html)
3967    ///
3968    /// DROP DOMAIN [ IF EXISTS ] name [, ...] [ CASCADE | RESTRICT ]
3969    ///
3970    DropDomain(DropDomain),
3971    /// ```sql
3972    /// DROP PROCEDURE
3973    /// ```
3974    DropProcedure {
3975        /// `true` when `IF EXISTS` was present.
3976        if_exists: bool,
3977        /// One or more functions/procedures to drop.
3978        proc_desc: Vec<FunctionDesc>,
3979        /// Optional drop behavior (`CASCADE` or `RESTRICT`).
3980        drop_behavior: Option<DropBehavior>,
3981    },
3982    /// ```sql
3983    /// DROP SECRET
3984    /// ```
3985    DropSecret {
3986        /// `true` when `IF EXISTS` was present.
3987        if_exists: bool,
3988        /// Optional `TEMPORARY` marker.
3989        temporary: Option<bool>,
3990        /// Name of the secret to drop.
3991        name: Ident,
3992        /// Optional storage specifier identifier.
3993        storage_specifier: Option<Ident>,
3994    },
3995    ///```sql
3996    /// DROP POLICY
3997    /// ```
3998    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-droppolicy.html)
3999    DropPolicy(DropPolicy),
4000    /// ```sql
4001    /// DROP CONNECTOR
4002    /// ```
4003    /// See [Hive](https://cwiki.apache.org/confluence/pages/viewpage.action?pageId=27362034#LanguageManualDDL-DropConnector)
4004    DropConnector {
4005        /// `true` when `IF EXISTS` was present.
4006        if_exists: bool,
4007        /// Name of the connector to drop.
4008        name: Ident,
4009    },
4010    /// ```sql
4011    /// DECLARE
4012    /// ```
4013    /// Declare Cursor Variables
4014    ///
4015    /// Note: this is a PostgreSQL-specific statement,
4016    /// but may also compatible with other SQL.
4017    Declare {
4018        /// Cursor declaration statements collected by `DECLARE`.
4019        stmts: Vec<Declare>,
4020    },
4021    /// ```sql
4022    /// CREATE EXTENSION [ IF NOT EXISTS ] extension_name
4023    ///     [ WITH ] [ SCHEMA schema_name ]
4024    ///              [ VERSION version ]
4025    ///              [ CASCADE ]
4026    /// ```
4027    ///
4028    /// Note: this is a PostgreSQL-specific statement,
4029    CreateExtension(CreateExtension),
4030    /// ```sql
4031    /// CREATE COLLATION
4032    /// ```
4033    /// Note: this is a PostgreSQL-specific statement.
4034    /// <https://www.postgresql.org/docs/current/sql-createcollation.html>
4035    CreateCollation(CreateCollation),
4036    /// ```sql
4037    /// DROP EXTENSION [ IF EXISTS ] name [, ...] [ CASCADE | RESTRICT ]
4038    /// ```
4039    /// Note: this is a PostgreSQL-specific statement.
4040    /// <https://www.postgresql.org/docs/current/sql-dropextension.html>
4041    DropExtension(DropExtension),
4042    /// ```sql
4043    /// DROP OPERATOR [ IF EXISTS ] name ( { left_type | NONE } , right_type ) [, ...] [ CASCADE | RESTRICT ]
4044    /// ```
4045    /// Note: this is a PostgreSQL-specific statement.
4046    /// <https://www.postgresql.org/docs/current/sql-dropoperator.html>
4047    DropOperator(DropOperator),
4048    /// ```sql
4049    /// DROP OPERATOR FAMILY [ IF EXISTS ] name USING index_method [ CASCADE | RESTRICT ]
4050    /// ```
4051    /// Note: this is a PostgreSQL-specific statement.
4052    /// <https://www.postgresql.org/docs/current/sql-dropopfamily.html>
4053    DropOperatorFamily(DropOperatorFamily),
4054    /// ```sql
4055    /// DROP OPERATOR CLASS [ IF EXISTS ] name USING index_method [ CASCADE | RESTRICT ]
4056    /// ```
4057    /// Note: this is a PostgreSQL-specific statement.
4058    /// <https://www.postgresql.org/docs/current/sql-dropopclass.html>
4059    DropOperatorClass(DropOperatorClass),
4060    /// ```sql
4061    /// FETCH
4062    /// ```
4063    /// Retrieve rows from a query using a cursor
4064    ///
4065    /// Note: this is a PostgreSQL-specific statement,
4066    /// but may also compatible with other SQL.
4067    Fetch {
4068        /// Cursor name
4069        name: Ident,
4070        /// The fetch direction (e.g., `FORWARD`, `BACKWARD`).
4071        direction: FetchDirection,
4072        /// The fetch position (e.g., `ALL`, `NEXT`, `ABSOLUTE`).
4073        position: FetchPosition,
4074        /// Optional target table to fetch rows into.
4075        into: Option<ObjectName>,
4076    },
4077    /// ```sql
4078    /// FLUSH [NO_WRITE_TO_BINLOG | LOCAL] flush_option [, flush_option] ... | tables_option
4079    /// ```
4080    ///
4081    /// Note: this is a Mysql-specific statement,
4082    /// but may also compatible with other SQL.
4083    Flush {
4084        /// The specific flush option or object to flush.
4085        object_type: FlushType,
4086        /// Optional flush location (dialect-specific).
4087        location: Option<FlushLocation>,
4088        /// Optional channel name used for flush operations.
4089        channel: Option<String>,
4090        /// Whether a read lock was requested.
4091        read_lock: bool,
4092        /// Whether this is an export flush operation.
4093        export: bool,
4094        /// Optional list of tables involved in the flush.
4095        tables: Vec<ObjectName>,
4096    },
4097    /// ```sql
4098    /// DISCARD [ ALL | PLANS | SEQUENCES | TEMPORARY | TEMP ]
4099    /// ```
4100    ///
4101    /// Note: this is a PostgreSQL-specific statement,
4102    /// but may also compatible with other SQL.
4103    Discard {
4104        /// The kind of object(s) to discard (ALL, PLANS, etc.).
4105        object_type: DiscardObject,
4106    },
4107    /// `SHOW FUNCTIONS`
4108    ///
4109    /// Note: this is a Presto-specific statement.
4110    ShowFunctions {
4111        /// Optional filter for which functions to display.
4112        filter: Option<ShowStatementFilter>,
4113    },
4114    /// ```sql
4115    /// SHOW <variable>
4116    /// ```
4117    ///
4118    /// Note: this is a PostgreSQL-specific statement.
4119    ShowVariable {
4120        /// Variable name as one or more identifiers.
4121        variable: Vec<Ident>,
4122    },
4123    /// ```sql
4124    /// SHOW [GLOBAL | SESSION] STATUS [LIKE 'pattern' | WHERE expr]
4125    /// ```
4126    ///
4127    /// Note: this is a MySQL-specific statement.
4128    ShowStatus {
4129        /// Optional filter for which status entries to display.
4130        filter: Option<ShowStatementFilter>,
4131        /// `true` when `GLOBAL` scope was requested.
4132        global: bool,
4133        /// `true` when `SESSION` scope was requested.
4134        session: bool,
4135    },
4136    /// ```sql
4137    /// SHOW VARIABLES
4138    /// ```
4139    ///
4140    /// Note: this is a MySQL-specific statement.
4141    ShowVariables {
4142        /// Optional filter for which variables to display.
4143        filter: Option<ShowStatementFilter>,
4144        /// `true` when `GLOBAL` scope was requested.
4145        global: bool,
4146        /// `true` when `SESSION` scope was requested.
4147        session: bool,
4148    },
4149    /// ```sql
4150    /// SHOW CREATE TABLE
4151    /// ```
4152    ///
4153    /// Note: this is a MySQL-specific statement.
4154    ShowCreate {
4155        /// The kind of object being shown (TABLE, VIEW, etc.).
4156        obj_type: ShowCreateObject,
4157        /// The name of the object to show create statement for.
4158        obj_name: ObjectName,
4159    },
4160    /// ```sql
4161    /// SHOW COLUMNS
4162    /// ```
4163    ShowColumns {
4164        /// `true` when extended column information was requested.
4165        extended: bool,
4166        /// `true` when full column details were requested.
4167        full: bool,
4168        /// Additional options for `SHOW COLUMNS`.
4169        show_options: ShowStatementOptions,
4170    },
4171    /// ```sql
4172    /// SHOW CATALOGS
4173    /// ```
4174    ShowCatalogs {
4175        /// `true` when terse output format was requested.
4176        terse: bool,
4177        /// `true` when history information was requested.
4178        history: bool,
4179        /// Additional options for `SHOW CATALOGS`.
4180        show_options: ShowStatementOptions,
4181    },
4182    /// ```sql
4183    /// SHOW DATABASES
4184    /// ```
4185    ShowDatabases {
4186        /// `true` when terse output format was requested.
4187        terse: bool,
4188        /// `true` when history information was requested.
4189        history: bool,
4190        /// Additional options for `SHOW DATABASES`.
4191        show_options: ShowStatementOptions,
4192    },
4193    /// ```sql
4194    /// SHOW [FULL] PROCESSLIST
4195    /// ```
4196    ///
4197    /// Note: this is a MySQL-specific statement.
4198    ShowProcessList {
4199        /// `true` when full process information was requested.
4200        full: bool,
4201    },
4202    /// ```sql
4203    /// SHOW SCHEMAS
4204    /// ```
4205    ShowSchemas {
4206        /// `true` when terse (compact) output was requested.
4207        terse: bool,
4208        /// `true` when history information was requested.
4209        history: bool,
4210        /// Additional options for `SHOW SCHEMAS`.
4211        show_options: ShowStatementOptions,
4212    },
4213    // ```sql
4214    // SHOW {CHARACTER SET | CHARSET}
4215    // ```
4216    // [MySQL]:
4217    // <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>
4218    /// Show the available character sets (alias `CHARSET`).
4219    ShowCharset(ShowCharset),
4220    /// ```sql
4221    /// SHOW OBJECTS LIKE 'line%' IN mydb.public
4222    /// ```
4223    /// Snowflake-specific statement
4224    /// <https://docs.snowflake.com/en/sql-reference/sql/show-objects>
4225    ShowObjects(ShowObjects),
4226    /// ```sql
4227    /// SHOW TABLES
4228    /// ```
4229    ShowTables {
4230        /// `true` when terse output format was requested (compact listing).
4231        terse: bool,
4232        /// `true` when history rows are requested.
4233        history: bool,
4234        /// `true` when extended information should be shown.
4235        extended: bool,
4236        /// `true` when a full listing was requested.
4237        full: bool,
4238        /// `true` when external tables should be included.
4239        external: bool,
4240        /// Additional options for `SHOW` statements.
4241        show_options: ShowStatementOptions,
4242    },
4243    /// ```sql
4244    /// SHOW VIEWS
4245    /// ```
4246    ShowViews {
4247        /// `true` when terse output format was requested.
4248        terse: bool,
4249        /// `true` when materialized views should be included.
4250        materialized: bool,
4251        /// Additional options for `SHOW` statements.
4252        show_options: ShowStatementOptions,
4253    },
4254    /// ```sql
4255    /// SHOW COLLATION
4256    /// ```
4257    ///
4258    /// Note: this is a MySQL-specific statement.
4259    ShowCollation {
4260        /// Optional filter for which collations to display.
4261        filter: Option<ShowStatementFilter>,
4262    },
4263    /// ```sql
4264    /// `USE ...`
4265    /// ```
4266    Use(Use),
4267    /// ```sql
4268    /// START  [ TRANSACTION | WORK ] | START TRANSACTION } ...
4269    /// ```
4270    /// If `begin` is false.
4271    ///
4272    /// ```sql
4273    /// `BEGIN  [ TRANSACTION | WORK ] | START TRANSACTION } ...`
4274    /// ```
4275    /// If `begin` is true
4276    StartTransaction {
4277        /// Transaction modes such as `ISOLATION LEVEL` or `READ WRITE`.
4278        modes: Vec<TransactionMode>,
4279        /// `true` when this was parsed as `BEGIN` instead of `START`.
4280        begin: bool,
4281        /// Optional specific keyword used: `TRANSACTION` or `WORK`.
4282        transaction: Option<BeginTransactionKind>,
4283        /// Optional transaction modifier (e.g., `AND NO CHAIN`).
4284        modifier: Option<TransactionModifier>,
4285        /// List of statements belonging to the `BEGIN` block.
4286        /// Example:
4287        /// ```sql
4288        /// BEGIN
4289        ///     SELECT 1;
4290        ///     SELECT 2;
4291        /// END;
4292        /// ```
4293        statements: Vec<Statement>,
4294        /// Exception handling with exception clauses.
4295        /// Example:
4296        /// ```sql
4297        /// EXCEPTION
4298        ///     WHEN EXCEPTION_1 THEN
4299        ///         SELECT 2;
4300        ///     WHEN EXCEPTION_2 OR EXCEPTION_3 THEN
4301        ///         SELECT 3;
4302        ///     WHEN OTHER THEN
4303        ///         SELECT 4;
4304        /// ```
4305        /// <https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#beginexceptionend>
4306        /// <https://docs.snowflake.com/en/sql-reference/snowflake-scripting/exception>
4307        exception: Option<Vec<ExceptionWhen>>,
4308        /// TRUE if the statement has an `END` keyword.
4309        has_end_keyword: bool,
4310    },
4311    /// ```sql
4312    /// COMMENT ON ...
4313    /// ```
4314    ///
4315    /// Note: this is a PostgreSQL-specific statement.
4316    Comment {
4317        /// Type of object being commented (table, column, etc.).
4318        object_type: CommentObject,
4319        /// Name of the object the comment applies to.
4320        object_name: ObjectName,
4321        /// Optional comment text (None to remove comment).
4322        comment: Option<String>,
4323        /// An optional `IF EXISTS` clause. (Non-standard.)
4324        /// See <https://docs.snowflake.com/en/sql-reference/sql/comment>
4325        if_exists: bool,
4326    },
4327    /// ```sql
4328    /// COMMIT [ TRANSACTION | WORK ] [ AND [ NO ] CHAIN ]
4329    /// ```
4330    /// If `end` is false
4331    ///
4332    /// ```sql
4333    /// END [ TRY | CATCH ]
4334    /// ```
4335    /// If `end` is true
4336    Commit {
4337        /// `true` when `AND [ NO ] CHAIN` was present.
4338        chain: bool,
4339        /// `true` when this `COMMIT` was parsed as an `END` block terminator.
4340        end: bool,
4341        /// Optional transaction modifier for commit semantics.
4342        modifier: Option<TransactionModifier>,
4343    },
4344    /// ```sql
4345    /// ROLLBACK [ TRANSACTION | WORK ] [ AND [ NO ] CHAIN ] [ TO [ SAVEPOINT ] savepoint_name ]
4346    /// ```
4347    Rollback {
4348        /// `true` when `AND [ NO ] CHAIN` was present.
4349        chain: bool,
4350        /// Optional savepoint name to roll back to.
4351        savepoint: Option<Ident>,
4352    },
4353    /// ```sql
4354    /// CREATE SCHEMA
4355    /// ```
4356    CreateSchema {
4357        /// `<schema name> | AUTHORIZATION <schema authorization identifier>  | <schema name>  AUTHORIZATION <schema authorization identifier>`
4358        schema_name: SchemaName,
4359        /// `true` when `IF NOT EXISTS` was present.
4360        if_not_exists: bool,
4361        /// Schema properties.
4362        ///
4363        /// ```sql
4364        /// CREATE SCHEMA myschema WITH (key1='value1');
4365        /// ```
4366        ///
4367        /// [Trino](https://trino.io/docs/current/sql/create-schema.html)
4368        with: Option<Vec<SqlOption>>,
4369        /// Schema options.
4370        ///
4371        /// ```sql
4372        /// CREATE SCHEMA myschema OPTIONS(key1='value1');
4373        /// ```
4374        ///
4375        /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_schema_statement)
4376        options: Option<Vec<SqlOption>>,
4377        /// Default collation specification for the schema.
4378        ///
4379        /// ```sql
4380        /// CREATE SCHEMA myschema DEFAULT COLLATE 'und:ci';
4381        /// ```
4382        ///
4383        /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_schema_statement)
4384        default_collate_spec: Option<Expr>,
4385        /// Clones a schema
4386        ///
4387        /// ```sql
4388        /// CREATE SCHEMA myschema CLONE otherschema
4389        /// ```
4390        ///
4391        /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-clone#databases-schemas)
4392        clone: Option<ObjectName>,
4393    },
4394    /// ```sql
4395    /// CREATE DATABASE
4396    /// ```
4397    /// See:
4398    /// <https://docs.snowflake.com/en/sql-reference/sql/create-database>
4399    CreateDatabase {
4400        /// Database name.
4401        db_name: ObjectName,
4402        /// `IF NOT EXISTS` flag.
4403        if_not_exists: bool,
4404        /// Optional location URI.
4405        location: Option<String>,
4406        /// Optional managed location.
4407        managed_location: Option<String>,
4408        /// `OR REPLACE` flag.
4409        or_replace: bool,
4410        /// `TRANSIENT` flag.
4411        transient: bool,
4412        /// Optional clone source.
4413        clone: Option<ObjectName>,
4414        /// Optional data retention time in days.
4415        data_retention_time_in_days: Option<u64>,
4416        /// Optional maximum data extension time in days.
4417        max_data_extension_time_in_days: Option<u64>,
4418        /// Optional external volume identifier.
4419        external_volume: Option<String>,
4420        /// Optional catalog name.
4421        catalog: Option<String>,
4422        /// Whether to replace invalid characters.
4423        replace_invalid_characters: Option<bool>,
4424        /// Default DDL collation string.
4425        default_ddl_collation: Option<String>,
4426        /// Storage serialization policy.
4427        storage_serialization_policy: Option<StorageSerializationPolicy>,
4428        /// Optional comment.
4429        comment: Option<String>,
4430        /// Optional default character set (MySQL).
4431        default_charset: Option<String>,
4432        /// Optional default collation (MySQL).
4433        default_collation: Option<String>,
4434        /// Optional catalog sync identifier.
4435        catalog_sync: Option<String>,
4436        /// Catalog sync namespace mode.
4437        catalog_sync_namespace_mode: Option<CatalogSyncNamespaceMode>,
4438        /// Optional flatten delimiter for namespace sync.
4439        catalog_sync_namespace_flatten_delimiter: Option<String>,
4440        /// Optional tags for the database.
4441        with_tags: Option<Vec<Tag>>,
4442        /// Optional contact entries for the database.
4443        with_contacts: Option<Vec<ContactEntry>>,
4444    },
4445    /// ```sql
4446    /// CREATE FUNCTION
4447    /// ```
4448    ///
4449    /// Supported variants:
4450    /// 1. [Hive](https://cwiki.apache.org/confluence/display/hive/languagemanual+ddl#LanguageManualDDL-Create/Drop/ReloadFunction)
4451    /// 2. [PostgreSQL](https://www.postgresql.org/docs/15/sql-createfunction.html)
4452    /// 3. [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_function_statement)
4453    /// 4. [MsSql](https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql)
4454    CreateFunction(CreateFunction),
4455    /// CREATE TRIGGER statement. See struct [CreateTrigger] for details.
4456    CreateTrigger(CreateTrigger),
4457    /// DROP TRIGGER statement. See struct [DropTrigger] for details.
4458    DropTrigger(DropTrigger),
4459    /// ```sql
4460    /// CREATE PROCEDURE
4461    /// ```
4462    CreateProcedure {
4463        /// `OR ALTER` flag.
4464        or_alter: bool,
4465        /// Procedure name.
4466        name: ObjectName,
4467        /// Optional procedure parameters.
4468        params: Option<Vec<ProcedureParam>>,
4469        /// Optional language identifier.
4470        language: Option<Ident>,
4471        /// Procedure body statements.
4472        body: ConditionalStatements,
4473    },
4474    /// ```sql
4475    /// CREATE MACRO
4476    /// ```
4477    ///
4478    /// Supported variants:
4479    /// 1. [DuckDB](https://duckdb.org/docs/sql/statements/create_macro)
4480    CreateMacro {
4481        /// `OR REPLACE` flag.
4482        or_replace: bool,
4483        /// Whether macro is temporary.
4484        temporary: bool,
4485        /// Macro name.
4486        name: ObjectName,
4487        /// Optional macro arguments.
4488        args: Option<Vec<MacroArg>>,
4489        /// Macro definition body.
4490        definition: MacroDefinition,
4491    },
4492    /// ```sql
4493    /// CREATE STAGE
4494    /// ```
4495    /// See <https://docs.snowflake.com/en/sql-reference/sql/create-stage>
4496    CreateStage {
4497        /// `OR REPLACE` flag for stage.
4498        or_replace: bool,
4499        /// Whether stage is temporary.
4500        temporary: bool,
4501        /// `IF NOT EXISTS` flag.
4502        if_not_exists: bool,
4503        /// Stage name.
4504        name: ObjectName,
4505        /// Stage parameters.
4506        stage_params: StageParamsObject,
4507        /// Directory table parameters.
4508        directory_table_params: KeyValueOptions,
4509        /// File format options.
4510        file_format: KeyValueOptions,
4511        /// Copy options for stage.
4512        copy_options: KeyValueOptions,
4513        /// Optional comment.
4514        comment: Option<String>,
4515    },
4516    /// ```sql
4517    /// CREATE [ OR REPLACE ] [ { TEMP | TEMPORARY | VOLATILE } ] FILE FORMAT [ IF NOT EXISTS ] <name>
4518    ///   [ TYPE = { CSV | JSON | AVRO | ORC | PARQUET | XML } [ formatTypeOptions ] ]
4519    ///   [ COMMENT = '<string_literal>' ]
4520    /// ```
4521    /// See <https://docs.snowflake.com/en/sql-reference/sql/create-file-format>
4522    CreateFileFormat {
4523        /// `OR REPLACE` flag.
4524        or_replace: bool,
4525        /// Whether file format is temporary.
4526        temporary: bool,
4527        /// Whether file format is volatile.
4528        volatile: bool,
4529        /// `IF NOT EXISTS` flag.
4530        if_not_exists: bool,
4531        /// File format name.
4532        name: ObjectName,
4533        /// Format type options (e.g. `TYPE`, `FIELD_DELIMITER`, `COMPRESSION`, ...).
4534        options: KeyValueOptions,
4535        /// Optional comment.
4536        comment: Option<String>,
4537    },
4538    /// ```sql
4539    /// ASSERT <condition> [AS <message>]
4540    /// ```
4541    Assert {
4542        /// Assertion condition expression.
4543        condition: Expr,
4544        /// Optional message expression.
4545        message: Option<Expr>,
4546    },
4547    /// ```sql
4548    /// GRANT privileges ON objects TO grantees
4549    /// ```
4550    Grant(Grant),
4551    /// ```sql
4552    /// DENY privileges ON object TO grantees
4553    /// ```
4554    Deny(DenyStatement),
4555    /// ```sql
4556    /// REVOKE privileges ON objects FROM grantees
4557    /// ```
4558    Revoke(Revoke),
4559    /// ```sql
4560    /// DEALLOCATE [ PREPARE ] { name | ALL }
4561    /// ```
4562    ///
4563    /// Note: this is a PostgreSQL-specific statement.
4564    Deallocate {
4565        /// Name to deallocate (or `ALL`).
4566        name: Ident,
4567        /// Whether `PREPARE` keyword was present.
4568        prepare: bool,
4569    },
4570    /// ```sql
4571    /// An `EXECUTE` statement
4572    /// ```
4573    ///
4574    /// Postgres: <https://www.postgresql.org/docs/current/sql-execute.html>
4575    /// MSSQL: <https://learn.microsoft.com/en-us/sql/relational-databases/stored-procedures/execute-a-stored-procedure>
4576    /// BigQuery: <https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#execute_immediate>
4577    /// Snowflake: <https://docs.snowflake.com/en/sql-reference/sql/execute-immediate>
4578    Execute {
4579        /// Optional function/procedure name.
4580        name: Option<ObjectName>,
4581        /// Parameter expressions passed to execute.
4582        parameters: Vec<Expr>,
4583        /// Whether parentheses were present around `parameters`.
4584        has_parentheses: bool,
4585        /// Is this an `EXECUTE IMMEDIATE`.
4586        immediate: bool,
4587        /// Identifiers to capture results into.
4588        into: Vec<Ident>,
4589        /// `USING` expressions with optional aliases.
4590        using: Vec<ExprWithAlias>,
4591        /// Whether the last parameter is the return value of the procedure
4592        /// MSSQL: <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/execute-transact-sql?view=sql-server-ver17#output>
4593        output: bool,
4594        /// Whether to invoke the procedure with the default parameter values
4595        /// MSSQL: <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/execute-transact-sql?view=sql-server-ver17#default>
4596        default: bool,
4597    },
4598    /// ```sql
4599    /// PREPARE name [ ( data_type [, ...] ) ] AS statement
4600    /// ```
4601    ///
4602    /// Note: this is a PostgreSQL-specific statement.
4603    Prepare {
4604        /// Name of the prepared statement.
4605        name: Ident,
4606        /// Optional data types for parameters.
4607        data_types: Vec<DataType>,
4608        /// Statement being prepared.
4609        statement: Box<Statement>,
4610    },
4611    /// ```sql
4612    /// KILL [CONNECTION | QUERY | MUTATION]
4613    /// ```
4614    ///
4615    /// See <https://clickhouse.com/docs/en/sql-reference/statements/kill/>
4616    /// See <https://dev.mysql.com/doc/refman/8.0/en/kill.html>
4617    Kill {
4618        /// Optional kill modifier (CONNECTION, QUERY, MUTATION).
4619        modifier: Option<KillType>,
4620        // processlist_id
4621        /// The id of the process to kill.
4622        id: u64,
4623    },
4624    /// ```sql
4625    /// [EXPLAIN | DESC | DESCRIBE] TABLE
4626    /// ```
4627    /// Note: this is a MySQL-specific statement. See <https://dev.mysql.com/doc/refman/8.0/en/explain.html>
4628    ExplainTable {
4629        /// `EXPLAIN | DESC | DESCRIBE`
4630        describe_alias: DescribeAlias,
4631        /// Hive style `FORMATTED | EXTENDED`
4632        hive_format: Option<HiveDescribeFormat>,
4633        /// Snowflake and ClickHouse support `DESC|DESCRIBE TABLE <table_name>` syntax
4634        ///
4635        /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/desc-table.html)
4636        /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/describe-table)
4637        has_table_keyword: bool,
4638        /// Table name
4639        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
4640        table_name: ObjectName,
4641    },
4642    /// ```sql
4643    /// [EXPLAIN | DESC | DESCRIBE]  <statement>
4644    /// ```
4645    Explain {
4646        /// `EXPLAIN | DESC | DESCRIBE`
4647        describe_alias: DescribeAlias,
4648        /// Carry out the command and show actual run times and other statistics.
4649        analyze: bool,
4650        /// Display additional information regarding the plan.
4651        verbose: bool,
4652        /// `EXPLAIN QUERY PLAN`
4653        /// Display the query plan without running the query.
4654        ///
4655        /// [SQLite](https://sqlite.org/lang_explain.html)
4656        query_plan: bool,
4657        /// `EXPLAIN ESTIMATE`
4658        /// [Clickhouse](https://clickhouse.com/docs/en/sql-reference/statements/explain#explain-estimate)
4659        estimate: bool,
4660        /// A SQL query that specifies what to explain
4661        statement: Box<Statement>,
4662        /// Optional output format of explain
4663        format: Option<AnalyzeFormatKind>,
4664        /// Postgres style utility options, `(analyze, verbose true)`
4665        options: Option<Vec<UtilityOption>>,
4666    },
4667    /// ```sql
4668    /// SAVEPOINT
4669    /// ```
4670    /// Define a new savepoint within the current transaction
4671    Savepoint {
4672        /// Name of the savepoint being defined.
4673        name: Ident,
4674    },
4675    /// ```sql
4676    /// RELEASE [ SAVEPOINT ] savepoint_name
4677    /// ```
4678    ReleaseSavepoint {
4679        /// Name of the savepoint to release.
4680        name: Ident,
4681    },
4682    /// A `MERGE` statement.
4683    ///
4684    /// ```sql
4685    /// MERGE INTO <target_table> USING <source> ON <join_expr> { matchedClause | notMatchedClause } [ ... ]
4686    /// ```
4687    /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/merge)
4688    /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/dml-syntax#merge_statement)
4689    /// [MSSQL](https://learn.microsoft.com/en-us/sql/t-sql/statements/merge-transact-sql?view=sql-server-ver16)
4690    Merge(Merge),
4691    /// ```sql
4692    /// CACHE [ FLAG ] TABLE <table_name> [ OPTIONS('K1' = 'V1', 'K2' = V2) ] [ AS ] [ <query> ]
4693    /// ```
4694    ///
4695    /// See [Spark SQL docs] for more details.
4696    ///
4697    /// [Spark SQL docs]: https://docs.databricks.com/spark/latest/spark-sql/language-manual/sql-ref-syntax-aux-cache-cache-table.html
4698    Cache {
4699        /// Table flag
4700        table_flag: Option<ObjectName>,
4701        /// Table name
4702        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
4703        table_name: ObjectName,
4704        /// `true` if `AS` keyword was present before the query.
4705        has_as: bool,
4706        /// Table confs
4707        options: Vec<SqlOption>,
4708        /// Cache table as a Query
4709        query: Option<Box<Query>>,
4710    },
4711    /// ```sql
4712    /// UNCACHE TABLE [ IF EXISTS ]  <table_name>
4713    /// ```
4714    UNCache {
4715        /// Table name
4716        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
4717        table_name: ObjectName,
4718        /// `true` when `IF EXISTS` was present.
4719        if_exists: bool,
4720    },
4721    /// ```sql
4722    /// CREATE [ { TEMPORARY | TEMP } ] SEQUENCE [ IF NOT EXISTS ] <sequence_name>
4723    /// ```
4724    /// Define a new sequence:
4725    CreateSequence {
4726        /// Whether the sequence is temporary.
4727        temporary: bool,
4728        /// `IF NOT EXISTS` flag.
4729        if_not_exists: bool,
4730        /// Sequence name.
4731        name: ObjectName,
4732        /// Optional data type for the sequence.
4733        data_type: Option<DataType>,
4734        /// Sequence options (INCREMENT, MINVALUE, etc.).
4735        sequence_options: Vec<SequenceOptions>,
4736        /// Optional `OWNED BY` target.
4737        owned_by: Option<ObjectName>,
4738    },
4739    /// A `CREATE DOMAIN` statement.
4740    CreateDomain(CreateDomain),
4741    /// ```sql
4742    /// CREATE TYPE <name>
4743    /// ```
4744    CreateType {
4745        /// Type name to create.
4746        name: ObjectName,
4747        /// Optional type representation details.
4748        representation: Option<UserDefinedTypeRepresentation>,
4749    },
4750    /// ```sql
4751    /// PRAGMA <schema-name>.<pragma-name> = <pragma-value>
4752    /// ```
4753    Pragma {
4754        /// Pragma name (possibly qualified).
4755        name: ObjectName,
4756        /// Optional pragma value.
4757        value: Option<ValueWithSpan>,
4758        /// Whether the pragma used `=`.
4759        is_eq: bool,
4760    },
4761    /// ```sql
4762    /// LOCK [ TABLE ] [ ONLY ] name [ * ] [, ...] [ IN lockmode MODE ] [ NOWAIT ]
4763    /// ```
4764    ///
4765    /// See <https://www.postgresql.org/docs/current/sql-lock.html>
4766    Lock(Lock),
4767    /// ```sql
4768    /// LOCK TABLES <table_name> [READ [LOCAL] | [LOW_PRIORITY] WRITE]
4769    /// ```
4770    /// Note: this is a MySQL-specific statement. See <https://dev.mysql.com/doc/refman/8.0/en/lock-tables.html>
4771    LockTables {
4772        /// List of tables to lock with modes.
4773        tables: Vec<LockTable>,
4774    },
4775    /// ```sql
4776    /// UNLOCK TABLES
4777    /// ```
4778    /// Note: this is a MySQL-specific statement. See <https://dev.mysql.com/doc/refman/8.0/en/lock-tables.html>
4779    UnlockTables,
4780    /// Unloads the result of a query to file
4781    ///
4782    /// [Athena](https://docs.aws.amazon.com/athena/latest/ug/unload.html):
4783    /// ```sql
4784    /// UNLOAD(statement) TO <destination> [ WITH options ]
4785    /// ```
4786    ///
4787    /// [Redshift](https://docs.aws.amazon.com/redshift/latest/dg/r_UNLOAD.html):
4788    /// ```sql
4789    /// UNLOAD('statement') TO <destination> [ OPTIONS ]
4790    /// ```
4791    Unload {
4792        /// Optional query AST to unload.
4793        query: Option<Box<Query>>,
4794        /// Optional original query text.
4795        query_text: Option<String>,
4796        /// Destination identifier.
4797        to: Ident,
4798        /// Optional IAM role/auth information.
4799        auth: Option<IamRoleKind>,
4800        /// Additional `WITH` options.
4801        with: Vec<SqlOption>,
4802        /// Legacy copy-style options.
4803        options: Vec<CopyLegacyOption>,
4804    },
4805    /// ClickHouse:
4806    /// ```sql
4807    /// OPTIMIZE TABLE [db.]name [ON CLUSTER cluster] [PARTITION partition | PARTITION ID 'partition_id'] [FINAL] [DEDUPLICATE [BY expression]]
4808    /// ```
4809    /// See ClickHouse <https://clickhouse.com/docs/en/sql-reference/statements/optimize>
4810    ///
4811    /// Databricks:
4812    /// ```sql
4813    /// OPTIMIZE table_name [WHERE predicate] [ZORDER BY (col_name1 [, ...])]
4814    /// ```
4815    /// See Databricks <https://docs.databricks.com/en/sql/language-manual/delta-optimize.html>
4816    OptimizeTable {
4817        /// Table name to optimize.
4818        name: ObjectName,
4819        /// Whether the `TABLE` keyword was present (ClickHouse uses `OPTIMIZE TABLE`, Databricks uses `OPTIMIZE`).
4820        has_table_keyword: bool,
4821        /// Optional cluster identifier.
4822        /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/optimize)
4823        on_cluster: Option<Ident>,
4824        /// Optional partition spec.
4825        /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/optimize)
4826        partition: Option<Partition>,
4827        /// Whether `FINAL` was specified.
4828        /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/optimize)
4829        include_final: bool,
4830        /// Optional deduplication settings.
4831        /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/optimize)
4832        deduplicate: Option<Deduplicate>,
4833        /// Optional WHERE predicate.
4834        /// [Databricks](https://docs.databricks.com/en/sql/language-manual/delta-optimize.html)
4835        predicate: Option<Expr>,
4836        /// Optional ZORDER BY columns.
4837        /// [Databricks](https://docs.databricks.com/en/sql/language-manual/delta-optimize.html)
4838        zorder: Option<Vec<Expr>>,
4839    },
4840    /// ```sql
4841    /// LISTEN
4842    /// ```
4843    /// listen for a notification channel
4844    ///
4845    /// See Postgres <https://www.postgresql.org/docs/current/sql-listen.html>
4846    LISTEN {
4847        /// Notification channel identifier.
4848        channel: Ident,
4849    },
4850    /// ```sql
4851    /// UNLISTEN
4852    /// ```
4853    /// stop listening for a notification
4854    ///
4855    /// See Postgres <https://www.postgresql.org/docs/current/sql-unlisten.html>
4856    UNLISTEN {
4857        /// Notification channel identifier.
4858        channel: Ident,
4859    },
4860    /// ```sql
4861    /// NOTIFY channel [ , payload ]
4862    /// ```
4863    /// send a notification event together with an optional "payload" string to channel
4864    ///
4865    /// See Postgres <https://www.postgresql.org/docs/current/sql-notify.html>
4866    NOTIFY {
4867        /// Notification channel identifier.
4868        channel: Ident,
4869        /// Optional payload string.
4870        payload: Option<String>,
4871    },
4872    /// ```sql
4873    /// LOAD DATA [LOCAL] INPATH 'filepath' [OVERWRITE] INTO TABLE tablename
4874    /// [PARTITION (partcol1=val1, partcol2=val2 ...)]
4875    /// [INPUTFORMAT 'inputformat' SERDE 'serde']
4876    /// ```
4877    /// Loading files into tables
4878    ///
4879    /// See Hive <https://cwiki.apache.org/confluence/pages/viewpage.action?pageId=27362036#LanguageManualDML-Loadingfilesintotables>
4880    LoadData {
4881        /// Whether `LOCAL` is present.
4882        local: bool,
4883        /// Input path for files to load.
4884        inpath: String,
4885        /// Whether `OVERWRITE` was specified.
4886        overwrite: bool,
4887        /// Target table name to load into.
4888        table_name: ObjectName,
4889        /// Optional partition specification.
4890        partitioned: Option<Vec<Expr>>,
4891        /// Optional table format information.
4892        table_format: Option<HiveLoadDataFormat>,
4893    },
4894    /// ```sql
4895    /// Rename TABLE tbl_name TO new_tbl_name[, tbl_name2 TO new_tbl_name2] ...
4896    /// ```
4897    /// Renames one or more tables
4898    ///
4899    /// See Mysql <https://dev.mysql.com/doc/refman/9.1/en/rename-table.html>
4900    RenameTable(Vec<RenameTable>),
4901    /// Snowflake `LIST`
4902    /// See: <https://docs.snowflake.com/en/sql-reference/sql/list>
4903    List(FileStagingCommand),
4904    /// Snowflake `PUT`
4905    /// ```sql
4906    /// PUT 'file://<path>' <internalStage> [ <option> = <value> ... ]
4907    /// ```
4908    /// Options include `PARALLEL`, `AUTO_COMPRESS`, `SOURCE_COMPRESSION`, `OVERWRITE`.
4909    /// See: <https://docs.snowflake.com/en/sql-reference/sql/put>
4910    Put {
4911        /// Local source URI as written in the statement, e.g. `file:///tmp/data.csv`.
4912        source: String,
4913        /// Target internal stage (e.g. `@mystage`, `@~`, `@%table`).
4914        stage: ObjectName,
4915        /// Trailing options (`PARALLEL=4`, `AUTO_COMPRESS=TRUE`, ...).
4916        options: KeyValueOptions,
4917    },
4918    /// Snowflake `REMOVE`
4919    /// See: <https://docs.snowflake.com/en/sql-reference/sql/remove>
4920    Remove(FileStagingCommand),
4921    /// RaiseError (MSSQL)
4922    /// RAISERROR ( { msg_id | msg_str | @local_variable }
4923    /// { , severity , state }
4924    /// [ , argument [ , ...n ] ] )
4925    /// [ WITH option [ , ...n ] ]
4926    /// See <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/raiserror-transact-sql?view=sql-server-ver16>
4927    RaisError {
4928        /// Error message expression or identifier.
4929        message: Box<Expr>,
4930        /// Severity expression.
4931        severity: Box<Expr>,
4932        /// State expression.
4933        state: Box<Expr>,
4934        /// Substitution arguments for the message.
4935        arguments: Vec<Expr>,
4936        /// Additional `WITH` options for RAISERROR.
4937        options: Vec<RaisErrorOption>,
4938    },
4939    /// A MSSQL `THROW` statement.
4940    Throw(ThrowStatement),
4941    /// ```sql
4942    /// PRINT msg_str | @local_variable | string_expr
4943    /// ```
4944    ///
4945    /// See: <https://learn.microsoft.com/en-us/sql/t-sql/statements/print-transact-sql>
4946    Print(PrintStatement),
4947    /// MSSQL `WAITFOR` statement.
4948    ///
4949    /// See: <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/waitfor-transact-sql>
4950    WaitFor(WaitForStatement),
4951    /// ```sql
4952    /// RETURN [ expression ]
4953    /// ```
4954    ///
4955    /// See [ReturnStatement]
4956    Return(ReturnStatement),
4957    /// Export data statement
4958    ///
4959    /// Example:
4960    /// ```sql
4961    /// EXPORT DATA OPTIONS(uri='gs://bucket/folder/*', format='PARQUET', overwrite=true) AS
4962    /// SELECT field1, field2 FROM mydataset.table1 ORDER BY field1 LIMIT 10
4963    /// ```
4964    /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/export-statements)
4965    ExportData(ExportData),
4966    /// ```sql
4967    /// CREATE [OR REPLACE] USER <user> [IF NOT EXISTS]
4968    /// ```
4969    /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-user)
4970    CreateUser(CreateUser),
4971    /// ```sql
4972    /// ALTER USER \[ IF EXISTS \] \[ <name> \]
4973    /// ```
4974    /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/alter-user)
4975    AlterUser(AlterUser),
4976    /// Re-sorts rows and reclaims space in either a specified table or all tables in the current database
4977    ///
4978    /// ```sql
4979    /// VACUUM tbl
4980    /// ```
4981    /// [Redshift](https://docs.aws.amazon.com/redshift/latest/dg/r_VACUUM_command.html)
4982    Vacuum(VacuumStatement),
4983    /// Restore the value of a run-time parameter to the default value.
4984    ///
4985    /// ```sql
4986    /// RESET configuration_parameter;
4987    /// RESET ALL;
4988    /// ```
4989    /// [PostgreSQL](https://www.postgresql.org/docs/current/sql-reset.html)
4990    Reset(ResetStatement),
4991}
4992
4993impl From<Analyze> for Statement {
4994    fn from(analyze: Analyze) -> Self {
4995        Statement::Analyze(analyze)
4996    }
4997}
4998
4999impl From<ddl::Truncate> for Statement {
5000    fn from(truncate: ddl::Truncate) -> Self {
5001        Statement::Truncate(truncate)
5002    }
5003}
5004
5005impl From<Lock> for Statement {
5006    fn from(lock: Lock) -> Self {
5007        Statement::Lock(lock)
5008    }
5009}
5010
5011impl From<ddl::Msck> for Statement {
5012    fn from(msck: ddl::Msck) -> Self {
5013        Statement::Msck(msck)
5014    }
5015}
5016
5017/// ```sql
5018/// {COPY | REVOKE} CURRENT GRANTS
5019/// ```
5020///
5021/// - [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/grant-ownership#optional-parameters)
5022#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
5023#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
5024#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
5025pub enum CurrentGrantsKind {
5026    /// `COPY CURRENT GRANTS` (copy current grants to target).
5027    CopyCurrentGrants,
5028    /// `REVOKE CURRENT GRANTS` (revoke current grants from target).
5029    RevokeCurrentGrants,
5030}
5031
5032impl fmt::Display for CurrentGrantsKind {
5033    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
5034        match self {
5035            CurrentGrantsKind::CopyCurrentGrants => write!(f, "COPY CURRENT GRANTS"),
5036            CurrentGrantsKind::RevokeCurrentGrants => write!(f, "REVOKE CURRENT GRANTS"),
5037        }
5038    }
5039}
5040
5041#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
5042#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
5043#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
5044/// `RAISERROR` options
5045/// See <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/raiserror-transact-sql?view=sql-server-ver16#options>
5046pub enum RaisErrorOption {
5047    /// Log the error.
5048    Log,
5049    /// Do not wait for completion.
5050    NoWait,
5051    /// Set the error state.
5052    SetError,
5053}
5054
5055impl fmt::Display for RaisErrorOption {
5056    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
5057        match self {
5058            RaisErrorOption::Log => write!(f, "LOG"),
5059            RaisErrorOption::NoWait => write!(f, "NOWAIT"),
5060            RaisErrorOption::SetError => write!(f, "SETERROR"),
5061        }
5062    }
5063}
5064
5065impl fmt::Display for Statement {
5066    /// Formats a SQL statement with support for pretty printing.
5067    ///
5068    /// When using the alternate flag (`{:#}`), the statement will be formatted with proper
5069    /// indentation and line breaks. For example:
5070    ///
5071    /// ```
5072    /// # use sqlparser::dialect::GenericDialect;
5073    /// # use sqlparser::parser::Parser;
5074    /// let sql = "SELECT a, b FROM table_1";
5075    /// let ast = Parser::parse_sql(&GenericDialect, sql).unwrap();
5076    ///
5077    /// // Regular formatting
5078    /// assert_eq!(format!("{}", ast[0]), "SELECT a, b FROM table_1");
5079    ///
5080    /// // Pretty printing
5081    /// assert_eq!(format!("{:#}", ast[0]),
5082    /// r#"SELECT
5083    ///   a,
5084    ///   b
5085    /// FROM
5086    ///   table_1"#);
5087    /// ```
5088    // Clippy thinks this function is too complicated, but it is painful to
5089    // split up without extracting structs for each `Statement` variant.
5090    #[allow(clippy::cognitive_complexity)]
5091    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
5092        match self {
5093            Statement::Flush {
5094                object_type,
5095                location,
5096                channel,
5097                read_lock,
5098                export,
5099                tables,
5100            } => {
5101                write!(f, "FLUSH")?;
5102                if let Some(location) = location {
5103                    f.write_str(" ")?;
5104                    location.fmt(f)?;
5105                }
5106                write!(f, " {object_type}")?;
5107
5108                if let Some(channel) = channel {
5109                    write!(f, " FOR CHANNEL {channel}")?;
5110                }
5111
5112                write!(
5113                    f,
5114                    "{tables}{read}{export}",
5115                    tables = if !tables.is_empty() {
5116                        format!(" {}", display_comma_separated(tables))
5117                    } else {
5118                        String::new()
5119                    },
5120                    export = if *export { " FOR EXPORT" } else { "" },
5121                    read = if *read_lock { " WITH READ LOCK" } else { "" }
5122                )
5123            }
5124            Statement::Kill { modifier, id } => {
5125                write!(f, "KILL ")?;
5126
5127                if let Some(m) = modifier {
5128                    write!(f, "{m} ")?;
5129                }
5130
5131                write!(f, "{id}")
5132            }
5133            Statement::ExplainTable {
5134                describe_alias,
5135                hive_format,
5136                has_table_keyword,
5137                table_name,
5138            } => {
5139                write!(f, "{describe_alias} ")?;
5140
5141                if let Some(format) = hive_format {
5142                    write!(f, "{format} ")?;
5143                }
5144                if *has_table_keyword {
5145                    write!(f, "TABLE ")?;
5146                }
5147
5148                write!(f, "{table_name}")
5149            }
5150            Statement::Explain {
5151                describe_alias,
5152                verbose,
5153                analyze,
5154                query_plan,
5155                estimate,
5156                statement,
5157                format,
5158                options,
5159            } => {
5160                write!(f, "{describe_alias} ")?;
5161
5162                if *query_plan {
5163                    write!(f, "QUERY PLAN ")?;
5164                }
5165                if *analyze {
5166                    write!(f, "ANALYZE ")?;
5167                }
5168                if *estimate {
5169                    write!(f, "ESTIMATE ")?;
5170                }
5171
5172                if *verbose {
5173                    write!(f, "VERBOSE ")?;
5174                }
5175
5176                if let Some(format) = format {
5177                    write!(f, "{format} ")?;
5178                }
5179
5180                if let Some(options) = options {
5181                    write!(f, "({}) ", display_comma_separated(options))?;
5182                }
5183
5184                write!(f, "{statement}")
5185            }
5186            Statement::Query(s) => s.fmt(f),
5187            Statement::Declare { stmts } => {
5188                write!(f, "DECLARE ")?;
5189                write!(f, "{}", display_separated(stmts, "; "))
5190            }
5191            Statement::Fetch {
5192                name,
5193                direction,
5194                position,
5195                into,
5196            } => {
5197                write!(f, "FETCH {direction} {position} {name}")?;
5198
5199                if let Some(into) = into {
5200                    write!(f, " INTO {into}")?;
5201                }
5202
5203                Ok(())
5204            }
5205            Statement::Directory {
5206                overwrite,
5207                local,
5208                path,
5209                file_format,
5210                source,
5211            } => {
5212                write!(
5213                    f,
5214                    "INSERT{overwrite}{local} DIRECTORY '{path}'",
5215                    overwrite = if *overwrite { " OVERWRITE" } else { "" },
5216                    local = if *local { " LOCAL" } else { "" },
5217                    path = path
5218                )?;
5219                if let Some(ref ff) = file_format {
5220                    write!(f, " STORED AS {ff}")?
5221                }
5222                write!(f, " {source}")
5223            }
5224            Statement::Msck(msck) => msck.fmt(f),
5225            Statement::Truncate(truncate) => truncate.fmt(f),
5226            Statement::Case(stmt) => {
5227                write!(f, "{stmt}")
5228            }
5229            Statement::If(stmt) => {
5230                write!(f, "{stmt}")
5231            }
5232            Statement::While(stmt) => {
5233                write!(f, "{stmt}")
5234            }
5235            Statement::Raise(stmt) => {
5236                write!(f, "{stmt}")
5237            }
5238            Statement::AttachDatabase {
5239                schema_name,
5240                database_file_name,
5241                database,
5242            } => {
5243                let keyword = if *database { "DATABASE " } else { "" };
5244                write!(f, "ATTACH {keyword}{database_file_name} AS {schema_name}")
5245            }
5246            Statement::AttachDuckDBDatabase {
5247                if_not_exists,
5248                database,
5249                database_path,
5250                database_alias,
5251                attach_options,
5252            } => {
5253                write!(
5254                    f,
5255                    "ATTACH{database}{if_not_exists} {database_path}",
5256                    database = if *database { " DATABASE" } else { "" },
5257                    if_not_exists = if *if_not_exists { " IF NOT EXISTS" } else { "" },
5258                )?;
5259                if let Some(alias) = database_alias {
5260                    write!(f, " AS {alias}")?;
5261                }
5262                if !attach_options.is_empty() {
5263                    write!(f, " ({})", display_comma_separated(attach_options))?;
5264                }
5265                Ok(())
5266            }
5267            Statement::DetachDuckDBDatabase {
5268                if_exists,
5269                database,
5270                database_alias,
5271            } => {
5272                write!(
5273                    f,
5274                    "DETACH{database}{if_exists} {database_alias}",
5275                    database = if *database { " DATABASE" } else { "" },
5276                    if_exists = if *if_exists { " IF EXISTS" } else { "" },
5277                )?;
5278                Ok(())
5279            }
5280            Statement::Analyze(analyze) => analyze.fmt(f),
5281            Statement::Insert(insert) => insert.fmt(f),
5282            Statement::Install {
5283                extension_name: name,
5284            } => write!(f, "INSTALL {name}"),
5285
5286            Statement::Load {
5287                extension_name: name,
5288            } => write!(f, "LOAD {name}"),
5289
5290            Statement::Call(function) => write!(f, "CALL {function}"),
5291
5292            Statement::Copy {
5293                source,
5294                to,
5295                target,
5296                options,
5297                legacy_options,
5298                values,
5299            } => {
5300                write!(f, "COPY")?;
5301                match source {
5302                    CopySource::Query(query) => write!(f, " ({query})")?,
5303                    CopySource::Table {
5304                        table_name,
5305                        columns,
5306                    } => {
5307                        write!(f, " {table_name}")?;
5308                        if !columns.is_empty() {
5309                            write!(f, " ({})", display_comma_separated(columns))?;
5310                        }
5311                    }
5312                }
5313                write!(f, " {} {}", if *to { "TO" } else { "FROM" }, target)?;
5314                if !options.is_empty() {
5315                    write!(f, " ({})", display_comma_separated(options))?;
5316                }
5317                if !legacy_options.is_empty() {
5318                    write!(f, " {}", display_separated(legacy_options, " "))?;
5319                }
5320                if !values.is_empty() {
5321                    writeln!(f, ";")?;
5322                    let mut delim = "";
5323                    for v in values {
5324                        write!(f, "{delim}")?;
5325                        delim = "\t";
5326                        if let Some(v) = v {
5327                            write!(f, "{v}")?;
5328                        } else {
5329                            write!(f, "\\N")?;
5330                        }
5331                    }
5332                    write!(f, "\n\\.")?;
5333                }
5334                Ok(())
5335            }
5336            Statement::Update(update) => update.fmt(f),
5337            Statement::Delete(delete) => delete.fmt(f),
5338            Statement::Open(open) => open.fmt(f),
5339            Statement::Close { cursor } => {
5340                write!(f, "CLOSE {cursor}")?;
5341
5342                Ok(())
5343            }
5344            Statement::CreateDatabase {
5345                db_name,
5346                if_not_exists,
5347                location,
5348                managed_location,
5349                or_replace,
5350                transient,
5351                clone,
5352                data_retention_time_in_days,
5353                max_data_extension_time_in_days,
5354                external_volume,
5355                catalog,
5356                replace_invalid_characters,
5357                default_ddl_collation,
5358                storage_serialization_policy,
5359                comment,
5360                default_charset,
5361                default_collation,
5362                catalog_sync,
5363                catalog_sync_namespace_mode,
5364                catalog_sync_namespace_flatten_delimiter,
5365                with_tags,
5366                with_contacts,
5367            } => {
5368                write!(
5369                    f,
5370                    "CREATE {or_replace}{transient}DATABASE {if_not_exists}{name}",
5371                    or_replace = if *or_replace { "OR REPLACE " } else { "" },
5372                    transient = if *transient { "TRANSIENT " } else { "" },
5373                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
5374                    name = db_name,
5375                )?;
5376
5377                if let Some(l) = location {
5378                    write!(f, " LOCATION '{l}'")?;
5379                }
5380                if let Some(ml) = managed_location {
5381                    write!(f, " MANAGEDLOCATION '{ml}'")?;
5382                }
5383                if let Some(clone) = clone {
5384                    write!(f, " CLONE {clone}")?;
5385                }
5386
5387                if let Some(value) = data_retention_time_in_days {
5388                    write!(f, " DATA_RETENTION_TIME_IN_DAYS = {value}")?;
5389                }
5390
5391                if let Some(value) = max_data_extension_time_in_days {
5392                    write!(f, " MAX_DATA_EXTENSION_TIME_IN_DAYS = {value}")?;
5393                }
5394
5395                if let Some(vol) = external_volume {
5396                    write!(f, " EXTERNAL_VOLUME = '{vol}'")?;
5397                }
5398
5399                if let Some(cat) = catalog {
5400                    write!(f, " CATALOG = '{cat}'")?;
5401                }
5402
5403                if let Some(true) = replace_invalid_characters {
5404                    write!(f, " REPLACE_INVALID_CHARACTERS = TRUE")?;
5405                } else if let Some(false) = replace_invalid_characters {
5406                    write!(f, " REPLACE_INVALID_CHARACTERS = FALSE")?;
5407                }
5408
5409                if let Some(collation) = default_ddl_collation {
5410                    write!(f, " DEFAULT_DDL_COLLATION = '{collation}'")?;
5411                }
5412
5413                if let Some(policy) = storage_serialization_policy {
5414                    write!(f, " STORAGE_SERIALIZATION_POLICY = {policy}")?;
5415                }
5416
5417                if let Some(comment) = comment {
5418                    write!(f, " COMMENT = '{comment}'")?;
5419                }
5420
5421                if let Some(charset) = default_charset {
5422                    write!(f, " DEFAULT CHARACTER SET {charset}")?;
5423                }
5424
5425                if let Some(collation) = default_collation {
5426                    write!(f, " DEFAULT COLLATE {collation}")?;
5427                }
5428
5429                if let Some(sync) = catalog_sync {
5430                    write!(f, " CATALOG_SYNC = '{sync}'")?;
5431                }
5432
5433                if let Some(mode) = catalog_sync_namespace_mode {
5434                    write!(f, " CATALOG_SYNC_NAMESPACE_MODE = {mode}")?;
5435                }
5436
5437                if let Some(delim) = catalog_sync_namespace_flatten_delimiter {
5438                    write!(f, " CATALOG_SYNC_NAMESPACE_FLATTEN_DELIMITER = '{delim}'")?;
5439                }
5440
5441                if let Some(tags) = with_tags {
5442                    write!(f, " WITH TAG ({})", display_comma_separated(tags))?;
5443                }
5444
5445                if let Some(contacts) = with_contacts {
5446                    write!(f, " WITH CONTACT ({})", display_comma_separated(contacts))?;
5447                }
5448                Ok(())
5449            }
5450            Statement::CreateFunction(create_function) => create_function.fmt(f),
5451            Statement::CreateDomain(create_domain) => create_domain.fmt(f),
5452            Statement::CreateTrigger(create_trigger) => create_trigger.fmt(f),
5453            Statement::DropTrigger(drop_trigger) => drop_trigger.fmt(f),
5454            Statement::CreateProcedure {
5455                name,
5456                or_alter,
5457                params,
5458                language,
5459                body,
5460            } => {
5461                write!(
5462                    f,
5463                    "CREATE {or_alter}PROCEDURE {name}",
5464                    or_alter = if *or_alter { "OR ALTER " } else { "" },
5465                    name = name
5466                )?;
5467
5468                if let Some(p) = params {
5469                    if !p.is_empty() {
5470                        write!(f, " ({})", display_comma_separated(p))?;
5471                    }
5472                }
5473
5474                if let Some(language) = language {
5475                    write!(f, " LANGUAGE {language}")?;
5476                }
5477
5478                write!(f, " AS {body}")
5479            }
5480            Statement::CreateMacro {
5481                or_replace,
5482                temporary,
5483                name,
5484                args,
5485                definition,
5486            } => {
5487                write!(
5488                    f,
5489                    "CREATE {or_replace}{temp}MACRO {name}",
5490                    temp = if *temporary { "TEMPORARY " } else { "" },
5491                    or_replace = if *or_replace { "OR REPLACE " } else { "" },
5492                )?;
5493                if let Some(args) = args {
5494                    write!(f, "({})", display_comma_separated(args))?;
5495                }
5496                match definition {
5497                    MacroDefinition::Expr(expr) => write!(f, " AS {expr}")?,
5498                    MacroDefinition::Table(query) => write!(f, " AS TABLE {query}")?,
5499                }
5500                Ok(())
5501            }
5502            Statement::CreateView(create_view) => create_view.fmt(f),
5503            Statement::CreateTable(create_table) => create_table.fmt(f),
5504            Statement::LoadData {
5505                local,
5506                inpath,
5507                overwrite,
5508                table_name,
5509                partitioned,
5510                table_format,
5511            } => {
5512                write!(
5513                    f,
5514                    "LOAD DATA {local}INPATH '{inpath}' {overwrite}INTO TABLE {table_name}",
5515                    local = if *local { "LOCAL " } else { "" },
5516                    inpath = inpath,
5517                    overwrite = if *overwrite { "OVERWRITE " } else { "" },
5518                    table_name = table_name,
5519                )?;
5520                if let Some(ref parts) = &partitioned {
5521                    if !parts.is_empty() {
5522                        write!(f, " PARTITION ({})", display_comma_separated(parts))?;
5523                    }
5524                }
5525                if let Some(HiveLoadDataFormat {
5526                    serde,
5527                    input_format,
5528                }) = &table_format
5529                {
5530                    write!(f, " INPUTFORMAT {input_format} SERDE {serde}")?;
5531                }
5532                Ok(())
5533            }
5534            Statement::CreateVirtualTable {
5535                name,
5536                if_not_exists,
5537                module_name,
5538                module_args,
5539            } => {
5540                write!(
5541                    f,
5542                    "CREATE VIRTUAL TABLE {if_not_exists}{name} USING {module_name}",
5543                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
5544                    name = name,
5545                    module_name = module_name
5546                )?;
5547                if !module_args.is_empty() {
5548                    write!(f, " ({})", display_comma_separated(module_args))?;
5549                }
5550                Ok(())
5551            }
5552            Statement::CreateIndex(create_index) => create_index.fmt(f),
5553            Statement::CreateExtension(create_extension) => write!(f, "{create_extension}"),
5554            Statement::CreateCollation(create_collation) => write!(f, "{create_collation}"),
5555            Statement::DropExtension(drop_extension) => write!(f, "{drop_extension}"),
5556            Statement::DropOperator(drop_operator) => write!(f, "{drop_operator}"),
5557            Statement::DropOperatorFamily(drop_operator_family) => {
5558                write!(f, "{drop_operator_family}")
5559            }
5560            Statement::DropOperatorClass(drop_operator_class) => {
5561                write!(f, "{drop_operator_class}")
5562            }
5563            Statement::CreateRole(create_role) => write!(f, "{create_role}"),
5564            Statement::CreateSecret {
5565                or_replace,
5566                temporary,
5567                if_not_exists,
5568                name,
5569                storage_specifier,
5570                secret_type,
5571                options,
5572            } => {
5573                write!(
5574                    f,
5575                    "CREATE {or_replace}",
5576                    or_replace = if *or_replace { "OR REPLACE " } else { "" },
5577                )?;
5578                if let Some(t) = temporary {
5579                    write!(f, "{}", if *t { "TEMPORARY " } else { "PERSISTENT " })?;
5580                }
5581                write!(
5582                    f,
5583                    "SECRET {if_not_exists}",
5584                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
5585                )?;
5586                if let Some(n) = name {
5587                    write!(f, "{n} ")?;
5588                };
5589                if let Some(s) = storage_specifier {
5590                    write!(f, "IN {s} ")?;
5591                }
5592                write!(f, "( TYPE {secret_type}",)?;
5593                if !options.is_empty() {
5594                    write!(f, ", {o}", o = display_comma_separated(options))?;
5595                }
5596                write!(f, " )")?;
5597                Ok(())
5598            }
5599            Statement::CreateServer(stmt) => {
5600                write!(f, "{stmt}")
5601            }
5602            Statement::CreatePolicy(policy) => write!(f, "{policy}"),
5603            Statement::CreateConnector(create_connector) => create_connector.fmt(f),
5604            Statement::CreateOperator(create_operator) => create_operator.fmt(f),
5605            Statement::CreateOperatorFamily(create_operator_family) => {
5606                create_operator_family.fmt(f)
5607            }
5608            Statement::CreateOperatorClass(create_operator_class) => create_operator_class.fmt(f),
5609            Statement::CreateTextSearch(create_text_search) => create_text_search.fmt(f),
5610            Statement::AlterTable(alter_table) => write!(f, "{alter_table}"),
5611            Statement::AlterIndex { name, operation } => {
5612                write!(f, "ALTER INDEX {name} {operation}")
5613            }
5614            Statement::AlterView {
5615                name,
5616                columns,
5617                query,
5618                with_options,
5619            } => {
5620                write!(f, "ALTER VIEW {name}")?;
5621                if !with_options.is_empty() {
5622                    write!(f, " WITH ({})", display_comma_separated(with_options))?;
5623                }
5624                if !columns.is_empty() {
5625                    write!(f, " ({})", display_comma_separated(columns))?;
5626                }
5627                write!(f, " AS {query}")
5628            }
5629            Statement::AlterFunction(alter_function) => write!(f, "{alter_function}"),
5630            Statement::AlterType(AlterType { name, operation }) => {
5631                write!(f, "ALTER TYPE {name} {operation}")
5632            }
5633            Statement::AlterCollation(alter_collation) => write!(f, "{alter_collation}"),
5634            Statement::AlterOperator(alter_operator) => write!(f, "{alter_operator}"),
5635            Statement::AlterOperatorFamily(alter_operator_family) => {
5636                write!(f, "{alter_operator_family}")
5637            }
5638            Statement::AlterOperatorClass(alter_operator_class) => {
5639                write!(f, "{alter_operator_class}")
5640            }
5641            Statement::AlterTextSearch(alter_text_search) => write!(f, "{alter_text_search}"),
5642            Statement::AlterRole { name, operation } => {
5643                write!(f, "ALTER ROLE {name} {operation}")
5644            }
5645            Statement::AlterPolicy(alter_policy) => write!(f, "{alter_policy}"),
5646            Statement::AlterConnector {
5647                name,
5648                properties,
5649                url,
5650                owner,
5651            } => {
5652                write!(f, "ALTER CONNECTOR {name}")?;
5653                if let Some(properties) = properties {
5654                    write!(
5655                        f,
5656                        " SET DCPROPERTIES({})",
5657                        display_comma_separated(properties)
5658                    )?;
5659                }
5660                if let Some(url) = url {
5661                    write!(f, " SET URL '{url}'")?;
5662                }
5663                if let Some(owner) = owner {
5664                    write!(f, " SET OWNER {owner}")?;
5665                }
5666                Ok(())
5667            }
5668            Statement::AlterSession {
5669                set,
5670                session_params,
5671            } => {
5672                write!(
5673                    f,
5674                    "ALTER SESSION {set}",
5675                    set = if *set { "SET" } else { "UNSET" }
5676                )?;
5677                if !session_params.options.is_empty() {
5678                    if *set {
5679                        write!(f, " {session_params}")?;
5680                    } else {
5681                        let options = session_params
5682                            .options
5683                            .iter()
5684                            .map(|p| p.option_name.clone())
5685                            .collect::<Vec<_>>();
5686                        write!(f, " {}", display_separated(&options, ", "))?;
5687                    }
5688                }
5689                Ok(())
5690            }
5691            Statement::Drop {
5692                object_type,
5693                if_exists,
5694                names,
5695                cascade,
5696                restrict,
5697                purge,
5698                temporary,
5699                table,
5700            } => {
5701                write!(
5702                    f,
5703                    "DROP {}{}{} {}{}{}{}",
5704                    if *temporary { "TEMPORARY " } else { "" },
5705                    object_type,
5706                    if *if_exists { " IF EXISTS" } else { "" },
5707                    display_comma_separated(names),
5708                    if *cascade { " CASCADE" } else { "" },
5709                    if *restrict { " RESTRICT" } else { "" },
5710                    if *purge { " PURGE" } else { "" },
5711                )?;
5712                if let Some(table_name) = table.as_ref() {
5713                    write!(f, " ON {table_name}")?;
5714                };
5715                Ok(())
5716            }
5717            Statement::DropFunction(drop_function) => write!(f, "{drop_function}"),
5718            Statement::DropDomain(DropDomain {
5719                if_exists,
5720                name,
5721                drop_behavior,
5722            }) => {
5723                write!(
5724                    f,
5725                    "DROP DOMAIN{} {name}",
5726                    if *if_exists { " IF EXISTS" } else { "" },
5727                )?;
5728                if let Some(op) = drop_behavior {
5729                    write!(f, " {op}")?;
5730                }
5731                Ok(())
5732            }
5733            Statement::DropProcedure {
5734                if_exists,
5735                proc_desc,
5736                drop_behavior,
5737            } => {
5738                write!(
5739                    f,
5740                    "DROP PROCEDURE{} {}",
5741                    if *if_exists { " IF EXISTS" } else { "" },
5742                    display_comma_separated(proc_desc),
5743                )?;
5744                if let Some(op) = drop_behavior {
5745                    write!(f, " {op}")?;
5746                }
5747                Ok(())
5748            }
5749            Statement::DropSecret {
5750                if_exists,
5751                temporary,
5752                name,
5753                storage_specifier,
5754            } => {
5755                write!(f, "DROP ")?;
5756                if let Some(t) = temporary {
5757                    write!(f, "{}", if *t { "TEMPORARY " } else { "PERSISTENT " })?;
5758                }
5759                write!(
5760                    f,
5761                    "SECRET {if_exists}{name}",
5762                    if_exists = if *if_exists { "IF EXISTS " } else { "" },
5763                )?;
5764                if let Some(s) = storage_specifier {
5765                    write!(f, " FROM {s}")?;
5766                }
5767                Ok(())
5768            }
5769            Statement::DropPolicy(policy) => write!(f, "{policy}"),
5770            Statement::DropConnector { if_exists, name } => {
5771                write!(
5772                    f,
5773                    "DROP CONNECTOR {if_exists}{name}",
5774                    if_exists = if *if_exists { "IF EXISTS " } else { "" }
5775                )?;
5776                Ok(())
5777            }
5778            Statement::Discard { object_type } => {
5779                write!(f, "DISCARD {object_type}")?;
5780                Ok(())
5781            }
5782            Self::Set(set) => write!(f, "{set}"),
5783            Statement::ShowVariable { variable } => {
5784                write!(f, "SHOW")?;
5785                if !variable.is_empty() {
5786                    write!(f, " {}", display_separated(variable, " "))?;
5787                }
5788                Ok(())
5789            }
5790            Statement::ShowStatus {
5791                filter,
5792                global,
5793                session,
5794            } => {
5795                write!(f, "SHOW")?;
5796                if *global {
5797                    write!(f, " GLOBAL")?;
5798                }
5799                if *session {
5800                    write!(f, " SESSION")?;
5801                }
5802                write!(f, " STATUS")?;
5803                if let Some(filter) = filter {
5804                    write!(f, " {}", filter)?;
5805                }
5806                Ok(())
5807            }
5808            Statement::ShowVariables {
5809                filter,
5810                global,
5811                session,
5812            } => {
5813                write!(f, "SHOW")?;
5814                if *global {
5815                    write!(f, " GLOBAL")?;
5816                }
5817                if *session {
5818                    write!(f, " SESSION")?;
5819                }
5820                write!(f, " VARIABLES")?;
5821                if let Some(filter) = filter {
5822                    write!(f, " {}", filter)?;
5823                }
5824                Ok(())
5825            }
5826            Statement::ShowCreate { obj_type, obj_name } => {
5827                write!(f, "SHOW CREATE {obj_type} {obj_name}",)?;
5828                Ok(())
5829            }
5830            Statement::ShowColumns {
5831                extended,
5832                full,
5833                show_options,
5834            } => {
5835                write!(
5836                    f,
5837                    "SHOW {extended}{full}COLUMNS{show_options}",
5838                    extended = if *extended { "EXTENDED " } else { "" },
5839                    full = if *full { "FULL " } else { "" },
5840                )?;
5841                Ok(())
5842            }
5843            Statement::ShowDatabases {
5844                terse,
5845                history,
5846                show_options,
5847            } => {
5848                write!(
5849                    f,
5850                    "SHOW {terse}DATABASES{history}{show_options}",
5851                    terse = if *terse { "TERSE " } else { "" },
5852                    history = if *history { " HISTORY" } else { "" },
5853                )?;
5854                Ok(())
5855            }
5856            Statement::ShowCatalogs {
5857                terse,
5858                history,
5859                show_options,
5860            } => {
5861                write!(
5862                    f,
5863                    "SHOW {terse}CATALOGS{history}{show_options}",
5864                    terse = if *terse { "TERSE " } else { "" },
5865                    history = if *history { " HISTORY" } else { "" },
5866                )?;
5867                Ok(())
5868            }
5869            Statement::ShowProcessList { full } => {
5870                write!(
5871                    f,
5872                    "SHOW {full}PROCESSLIST",
5873                    full = if *full { "FULL " } else { "" },
5874                )?;
5875                Ok(())
5876            }
5877            Statement::ShowSchemas {
5878                terse,
5879                history,
5880                show_options,
5881            } => {
5882                write!(
5883                    f,
5884                    "SHOW {terse}SCHEMAS{history}{show_options}",
5885                    terse = if *terse { "TERSE " } else { "" },
5886                    history = if *history { " HISTORY" } else { "" },
5887                )?;
5888                Ok(())
5889            }
5890            Statement::ShowObjects(ShowObjects {
5891                terse,
5892                show_options,
5893            }) => {
5894                write!(
5895                    f,
5896                    "SHOW {terse}OBJECTS{show_options}",
5897                    terse = if *terse { "TERSE " } else { "" },
5898                )?;
5899                Ok(())
5900            }
5901            Statement::ShowTables {
5902                terse,
5903                history,
5904                extended,
5905                full,
5906                external,
5907                show_options,
5908            } => {
5909                write!(
5910                    f,
5911                    "SHOW {terse}{extended}{full}{external}TABLES{history}{show_options}",
5912                    terse = if *terse { "TERSE " } else { "" },
5913                    extended = if *extended { "EXTENDED " } else { "" },
5914                    full = if *full { "FULL " } else { "" },
5915                    external = if *external { "EXTERNAL " } else { "" },
5916                    history = if *history { " HISTORY" } else { "" },
5917                )?;
5918                Ok(())
5919            }
5920            Statement::ShowViews {
5921                terse,
5922                materialized,
5923                show_options,
5924            } => {
5925                write!(
5926                    f,
5927                    "SHOW {terse}{materialized}VIEWS{show_options}",
5928                    terse = if *terse { "TERSE " } else { "" },
5929                    materialized = if *materialized { "MATERIALIZED " } else { "" }
5930                )?;
5931                Ok(())
5932            }
5933            Statement::ShowFunctions { filter } => {
5934                write!(f, "SHOW FUNCTIONS")?;
5935                if let Some(filter) = filter {
5936                    write!(f, " {filter}")?;
5937                }
5938                Ok(())
5939            }
5940            Statement::Use(use_expr) => use_expr.fmt(f),
5941            Statement::ShowCollation { filter } => {
5942                write!(f, "SHOW COLLATION")?;
5943                if let Some(filter) = filter {
5944                    write!(f, " {filter}")?;
5945                }
5946                Ok(())
5947            }
5948            Statement::ShowCharset(show_stm) => show_stm.fmt(f),
5949            Statement::StartTransaction {
5950                modes,
5951                begin: syntax_begin,
5952                transaction,
5953                modifier,
5954                statements,
5955                exception,
5956                has_end_keyword,
5957            } => {
5958                if *syntax_begin {
5959                    if let Some(modifier) = *modifier {
5960                        write!(f, "BEGIN {modifier}")?;
5961                    } else {
5962                        write!(f, "BEGIN")?;
5963                    }
5964                } else {
5965                    write!(f, "START")?;
5966                }
5967                if let Some(transaction) = transaction {
5968                    write!(f, " {transaction}")?;
5969                }
5970                if !modes.is_empty() {
5971                    write!(f, " {}", display_comma_separated(modes))?;
5972                }
5973                if !statements.is_empty() {
5974                    write!(f, " ")?;
5975                    format_statement_list(f, statements)?;
5976                }
5977                if let Some(exception_when) = exception {
5978                    write!(f, " EXCEPTION")?;
5979                    for when in exception_when {
5980                        write!(f, " {when}")?;
5981                    }
5982                }
5983                if *has_end_keyword {
5984                    write!(f, " END")?;
5985                }
5986                Ok(())
5987            }
5988            Statement::Commit {
5989                chain,
5990                end: end_syntax,
5991                modifier,
5992            } => {
5993                if *end_syntax {
5994                    write!(f, "END")?;
5995                    if let Some(modifier) = *modifier {
5996                        write!(f, " {modifier}")?;
5997                    }
5998                    if *chain {
5999                        write!(f, " AND CHAIN")?;
6000                    }
6001                } else {
6002                    write!(f, "COMMIT{}", if *chain { " AND CHAIN" } else { "" })?;
6003                }
6004                Ok(())
6005            }
6006            Statement::Rollback { chain, savepoint } => {
6007                write!(f, "ROLLBACK")?;
6008
6009                if *chain {
6010                    write!(f, " AND CHAIN")?;
6011                }
6012
6013                if let Some(savepoint) = savepoint {
6014                    write!(f, " TO SAVEPOINT {savepoint}")?;
6015                }
6016
6017                Ok(())
6018            }
6019            Statement::CreateSchema {
6020                schema_name,
6021                if_not_exists,
6022                with,
6023                options,
6024                default_collate_spec,
6025                clone,
6026            } => {
6027                write!(
6028                    f,
6029                    "CREATE SCHEMA {if_not_exists}{name}",
6030                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
6031                    name = schema_name
6032                )?;
6033
6034                if let Some(collate) = default_collate_spec {
6035                    write!(f, " DEFAULT COLLATE {collate}")?;
6036                }
6037
6038                if let Some(with) = with {
6039                    write!(f, " WITH ({})", display_comma_separated(with))?;
6040                }
6041
6042                if let Some(options) = options {
6043                    write!(f, " OPTIONS({})", display_comma_separated(options))?;
6044                }
6045
6046                if let Some(clone) = clone {
6047                    write!(f, " CLONE {clone}")?;
6048                }
6049                Ok(())
6050            }
6051            Statement::Assert { condition, message } => {
6052                write!(f, "ASSERT {condition}")?;
6053                if let Some(m) = message {
6054                    write!(f, " AS {m}")?;
6055                }
6056                Ok(())
6057            }
6058            Statement::Grant(grant) => write!(f, "{grant}"),
6059            Statement::Deny(s) => write!(f, "{s}"),
6060            Statement::Revoke(revoke) => write!(f, "{revoke}"),
6061            Statement::Deallocate { name, prepare } => write!(
6062                f,
6063                "DEALLOCATE {prepare}{name}",
6064                prepare = if *prepare { "PREPARE " } else { "" },
6065                name = name,
6066            ),
6067            Statement::Execute {
6068                name,
6069                parameters,
6070                has_parentheses,
6071                immediate,
6072                into,
6073                using,
6074                output,
6075                default,
6076            } => {
6077                let (open, close) = if *has_parentheses {
6078                    // Space before `(` only when there is no name directly preceding it.
6079                    (if name.is_some() { "(" } else { " (" }, ")")
6080                } else {
6081                    (if parameters.is_empty() { "" } else { " " }, "")
6082                };
6083                write!(f, "EXECUTE")?;
6084                if *immediate {
6085                    write!(f, " IMMEDIATE")?;
6086                }
6087                if let Some(name) = name {
6088                    write!(f, " {name}")?;
6089                }
6090                write!(f, "{open}{}{close}", display_comma_separated(parameters),)?;
6091                if !into.is_empty() {
6092                    write!(f, " INTO {}", display_comma_separated(into))?;
6093                }
6094                if !using.is_empty() {
6095                    write!(f, " USING {}", display_comma_separated(using))?;
6096                };
6097                if *output {
6098                    write!(f, " OUTPUT")?;
6099                }
6100                if *default {
6101                    write!(f, " DEFAULT")?;
6102                }
6103                Ok(())
6104            }
6105            Statement::Prepare {
6106                name,
6107                data_types,
6108                statement,
6109            } => {
6110                write!(f, "PREPARE {name} ")?;
6111                if !data_types.is_empty() {
6112                    write!(f, "({}) ", display_comma_separated(data_types))?;
6113                }
6114                write!(f, "AS {statement}")
6115            }
6116            Statement::Comment {
6117                object_type,
6118                object_name,
6119                comment,
6120                if_exists,
6121            } => {
6122                write!(f, "COMMENT ")?;
6123                if *if_exists {
6124                    write!(f, "IF EXISTS ")?
6125                };
6126                write!(f, "ON {object_type} {object_name} IS ")?;
6127                if let Some(c) = comment {
6128                    write!(f, "'{c}'")
6129                } else {
6130                    write!(f, "NULL")
6131                }
6132            }
6133            Statement::Savepoint { name } => {
6134                write!(f, "SAVEPOINT ")?;
6135                write!(f, "{name}")
6136            }
6137            Statement::ReleaseSavepoint { name } => {
6138                write!(f, "RELEASE SAVEPOINT {name}")
6139            }
6140            Statement::Merge(merge) => merge.fmt(f),
6141            Statement::Cache {
6142                table_name,
6143                table_flag,
6144                has_as,
6145                options,
6146                query,
6147            } => {
6148                if let Some(table_flag) = table_flag {
6149                    write!(f, "CACHE {table_flag} TABLE {table_name}")?;
6150                } else {
6151                    write!(f, "CACHE TABLE {table_name}")?;
6152                }
6153
6154                if !options.is_empty() {
6155                    write!(f, " OPTIONS({})", display_comma_separated(options))?;
6156                }
6157
6158                match (*has_as, query) {
6159                    (true, Some(query)) => write!(f, " AS {query}"),
6160                    (true, None) => f.write_str(" AS"),
6161                    (false, Some(query)) => write!(f, " {query}"),
6162                    (false, None) => Ok(()),
6163                }
6164            }
6165            Statement::UNCache {
6166                table_name,
6167                if_exists,
6168            } => {
6169                if *if_exists {
6170                    write!(f, "UNCACHE TABLE IF EXISTS {table_name}")
6171                } else {
6172                    write!(f, "UNCACHE TABLE {table_name}")
6173                }
6174            }
6175            Statement::CreateSequence {
6176                temporary,
6177                if_not_exists,
6178                name,
6179                data_type,
6180                sequence_options,
6181                owned_by,
6182            } => {
6183                let as_type: String = if let Some(dt) = data_type.as_ref() {
6184                    //Cannot use format!(" AS {}", dt), due to format! is not available in --target thumbv6m-none-eabi
6185                    // " AS ".to_owned() + &dt.to_string()
6186                    [" AS ", &dt.to_string()].concat()
6187                } else {
6188                    "".to_string()
6189                };
6190                write!(
6191                    f,
6192                    "CREATE {temporary}SEQUENCE {if_not_exists}{name}{as_type}",
6193                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
6194                    temporary = if *temporary { "TEMPORARY " } else { "" },
6195                    name = name,
6196                    as_type = as_type
6197                )?;
6198                for sequence_option in sequence_options {
6199                    write!(f, "{sequence_option}")?;
6200                }
6201                if let Some(ob) = owned_by.as_ref() {
6202                    write!(f, " OWNED BY {ob}")?;
6203                }
6204                write!(f, "")
6205            }
6206            Statement::CreateStage {
6207                or_replace,
6208                temporary,
6209                if_not_exists,
6210                name,
6211                stage_params,
6212                directory_table_params,
6213                file_format,
6214                copy_options,
6215                comment,
6216                ..
6217            } => {
6218                write!(
6219                    f,
6220                    "CREATE {or_replace}{temp}STAGE {if_not_exists}{name}{stage_params}",
6221                    temp = if *temporary { "TEMPORARY " } else { "" },
6222                    or_replace = if *or_replace { "OR REPLACE " } else { "" },
6223                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
6224                )?;
6225                if !directory_table_params.options.is_empty() {
6226                    write!(f, " DIRECTORY=({directory_table_params})")?;
6227                }
6228                if !file_format.options.is_empty() {
6229                    write!(f, " FILE_FORMAT=({file_format})")?;
6230                }
6231                if !copy_options.options.is_empty() {
6232                    write!(f, " COPY_OPTIONS=({copy_options})")?;
6233                }
6234                if let Some(comment) = comment {
6235                    write!(f, " COMMENT='{}'", comment)?;
6236                }
6237                Ok(())
6238            }
6239            Statement::CreateFileFormat {
6240                or_replace,
6241                temporary,
6242                volatile,
6243                if_not_exists,
6244                name,
6245                options,
6246                comment,
6247            } => {
6248                write!(
6249                    f,
6250                    "CREATE {or_replace}{temp}{volatile}FILE FORMAT {if_not_exists}{name}",
6251                    or_replace = if *or_replace { "OR REPLACE " } else { "" },
6252                    temp = if *temporary { "TEMPORARY " } else { "" },
6253                    volatile = if *volatile { "VOLATILE " } else { "" },
6254                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
6255                )?;
6256                if !options.options.is_empty() {
6257                    write!(f, " {options}")?;
6258                }
6259                if let Some(comment) = comment {
6260                    write!(f, " COMMENT='{}'", comment)?;
6261                }
6262                Ok(())
6263            }
6264            Statement::CopyIntoSnowflake {
6265                kind,
6266                into,
6267                into_columns,
6268                from_obj,
6269                from_obj_alias,
6270                stage_params,
6271                from_transformations,
6272                from_query,
6273                files,
6274                pattern,
6275                file_format,
6276                copy_options,
6277                validation_mode,
6278                partition,
6279            } => {
6280                write!(f, "COPY INTO {into}")?;
6281                if let Some(into_columns) = into_columns {
6282                    write!(f, " ({})", display_comma_separated(into_columns))?;
6283                }
6284                if let Some(from_transformations) = from_transformations {
6285                    // Data load with transformation
6286                    if let Some(from_stage) = from_obj {
6287                        write!(
6288                            f,
6289                            " FROM (SELECT {} FROM {}{}",
6290                            display_separated(from_transformations, ", "),
6291                            from_stage,
6292                            stage_params
6293                        )?;
6294                    }
6295                    if let Some(from_obj_alias) = from_obj_alias {
6296                        write!(f, " AS {from_obj_alias}")?;
6297                    }
6298                    write!(f, ")")?;
6299                } else if let Some(from_obj) = from_obj {
6300                    // Standard data load
6301                    write!(f, " FROM {from_obj}{stage_params}")?;
6302                    if let Some(from_obj_alias) = from_obj_alias {
6303                        write!(f, " AS {from_obj_alias}")?;
6304                    }
6305                } else if let Some(from_query) = from_query {
6306                    // Data unload from query
6307                    write!(f, " FROM ({from_query})")?;
6308                }
6309
6310                if let Some(files) = files {
6311                    write!(f, " FILES = ('{}')", display_separated(files, "', '"))?;
6312                }
6313                if let Some(pattern) = pattern {
6314                    write!(f, " PATTERN = '{pattern}'")?;
6315                }
6316                if let Some(partition) = partition {
6317                    write!(f, " PARTITION BY {partition}")?;
6318                }
6319                if !file_format.options.is_empty() {
6320                    write!(f, " FILE_FORMAT=({file_format})")?;
6321                }
6322                if !copy_options.options.is_empty() {
6323                    match kind {
6324                        CopyIntoSnowflakeKind::Table => {
6325                            write!(f, " COPY_OPTIONS=({copy_options})")?
6326                        }
6327                        CopyIntoSnowflakeKind::Location => write!(f, " {copy_options}")?,
6328                    }
6329                }
6330                if let Some(validation_mode) = validation_mode {
6331                    write!(f, " VALIDATION_MODE = {validation_mode}")?;
6332                }
6333                Ok(())
6334            }
6335            Statement::CreateType {
6336                name,
6337                representation,
6338            } => {
6339                write!(f, "CREATE TYPE {name}")?;
6340                if let Some(repr) = representation {
6341                    write!(f, " {repr}")?;
6342                }
6343                Ok(())
6344            }
6345            Statement::Pragma { name, value, is_eq } => {
6346                write!(f, "PRAGMA {name}")?;
6347                if let Some(value) = value {
6348                    if *is_eq {
6349                        write!(f, " = {value}")?;
6350                    } else {
6351                        write!(f, "({value})")?;
6352                    }
6353                }
6354                Ok(())
6355            }
6356            Statement::Lock(lock) => lock.fmt(f),
6357            Statement::LockTables { tables } => {
6358                write!(f, "LOCK TABLES {}", display_comma_separated(tables))
6359            }
6360            Statement::UnlockTables => {
6361                write!(f, "UNLOCK TABLES")
6362            }
6363            Statement::Unload {
6364                query,
6365                query_text,
6366                to,
6367                auth,
6368                with,
6369                options,
6370            } => {
6371                write!(f, "UNLOAD(")?;
6372                if let Some(query) = query {
6373                    write!(f, "{query}")?;
6374                }
6375                if let Some(query_text) = query_text {
6376                    write!(f, "'{query_text}'")?;
6377                }
6378                write!(f, ") TO {to}")?;
6379                if let Some(auth) = auth {
6380                    write!(f, " IAM_ROLE {auth}")?;
6381                }
6382                if !with.is_empty() {
6383                    write!(f, " WITH ({})", display_comma_separated(with))?;
6384                }
6385                if !options.is_empty() {
6386                    write!(f, " {}", display_separated(options, " "))?;
6387                }
6388                Ok(())
6389            }
6390            Statement::OptimizeTable {
6391                name,
6392                has_table_keyword,
6393                on_cluster,
6394                partition,
6395                include_final,
6396                deduplicate,
6397                predicate,
6398                zorder,
6399            } => {
6400                write!(f, "OPTIMIZE")?;
6401                if *has_table_keyword {
6402                    write!(f, " TABLE")?;
6403                }
6404                write!(f, " {name}")?;
6405                if let Some(on_cluster) = on_cluster {
6406                    write!(f, " ON CLUSTER {on_cluster}")?;
6407                }
6408                if let Some(partition) = partition {
6409                    write!(f, " {partition}")?;
6410                }
6411                if *include_final {
6412                    write!(f, " FINAL")?;
6413                }
6414                if let Some(deduplicate) = deduplicate {
6415                    write!(f, " {deduplicate}")?;
6416                }
6417                if let Some(predicate) = predicate {
6418                    write!(f, " WHERE {predicate}")?;
6419                }
6420                if let Some(zorder) = zorder {
6421                    write!(f, " ZORDER BY ({})", display_comma_separated(zorder))?;
6422                }
6423                Ok(())
6424            }
6425            Statement::LISTEN { channel } => {
6426                write!(f, "LISTEN {channel}")?;
6427                Ok(())
6428            }
6429            Statement::UNLISTEN { channel } => {
6430                write!(f, "UNLISTEN {channel}")?;
6431                Ok(())
6432            }
6433            Statement::NOTIFY { channel, payload } => {
6434                write!(f, "NOTIFY {channel}")?;
6435                if let Some(payload) = payload {
6436                    write!(f, ", '{payload}'")?;
6437                }
6438                Ok(())
6439            }
6440            Statement::RenameTable(rename_tables) => {
6441                write!(f, "RENAME TABLE {}", display_comma_separated(rename_tables))
6442            }
6443            Statement::RaisError {
6444                message,
6445                severity,
6446                state,
6447                arguments,
6448                options,
6449            } => {
6450                write!(f, "RAISERROR({message}, {severity}, {state}")?;
6451                if !arguments.is_empty() {
6452                    write!(f, ", {}", display_comma_separated(arguments))?;
6453                }
6454                write!(f, ")")?;
6455                if !options.is_empty() {
6456                    write!(f, " WITH {}", display_comma_separated(options))?;
6457                }
6458                Ok(())
6459            }
6460            Statement::Throw(s) => write!(f, "{s}"),
6461            Statement::Print(s) => write!(f, "{s}"),
6462            Statement::WaitFor(s) => write!(f, "{s}"),
6463            Statement::Return(r) => write!(f, "{r}"),
6464            Statement::List(command) => write!(f, "LIST {command}"),
6465            Statement::Put {
6466                source,
6467                stage,
6468                options,
6469            } => {
6470                write!(f, "PUT '{source}' {stage}")?;
6471                if !options.options.is_empty() {
6472                    write!(f, " {options}")?;
6473                }
6474                Ok(())
6475            }
6476            Statement::Remove(command) => write!(f, "REMOVE {command}"),
6477            Statement::ExportData(e) => write!(f, "{e}"),
6478            Statement::CreateUser(s) => write!(f, "{s}"),
6479            Statement::AlterSchema(s) => write!(f, "{s}"),
6480            Statement::Vacuum(s) => write!(f, "{s}"),
6481            Statement::AlterUser(s) => write!(f, "{s}"),
6482            Statement::Reset(s) => write!(f, "{s}"),
6483        }
6484    }
6485}
6486
6487/// Can use to describe options in create sequence or table column type identity
6488/// ```sql
6489/// [ INCREMENT [ BY ] increment ]
6490///     [ MINVALUE minvalue | NO MINVALUE ] [ MAXVALUE maxvalue | NO MAXVALUE ]
6491///     [ START [ WITH ] start ] [ CACHE cache ] [ [ NO ] CYCLE ]
6492/// ```
6493#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6494#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6495#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6496pub enum SequenceOptions {
6497    /// `INCREMENT [BY] <expr>` option; second value indicates presence of `BY` keyword.
6498    IncrementBy(Expr, bool),
6499    /// `MINVALUE <expr>` or `NO MINVALUE`.
6500    MinValue(Option<Expr>),
6501    /// `MAXVALUE <expr>` or `NO MAXVALUE`.
6502    MaxValue(Option<Expr>),
6503    /// `START [WITH] <expr>`; second value indicates presence of `WITH`.
6504    StartWith(Expr, bool),
6505    /// `CACHE <expr>` option.
6506    Cache(Expr),
6507    /// `CYCLE` or `NO CYCLE` option.
6508    Cycle(bool),
6509}
6510
6511impl fmt::Display for SequenceOptions {
6512    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6513        match self {
6514            SequenceOptions::IncrementBy(increment, by) => {
6515                write!(
6516                    f,
6517                    " INCREMENT{by} {increment}",
6518                    by = if *by { " BY" } else { "" },
6519                    increment = increment
6520                )
6521            }
6522            SequenceOptions::MinValue(Some(expr)) => {
6523                write!(f, " MINVALUE {expr}")
6524            }
6525            SequenceOptions::MinValue(None) => {
6526                write!(f, " NO MINVALUE")
6527            }
6528            SequenceOptions::MaxValue(Some(expr)) => {
6529                write!(f, " MAXVALUE {expr}")
6530            }
6531            SequenceOptions::MaxValue(None) => {
6532                write!(f, " NO MAXVALUE")
6533            }
6534            SequenceOptions::StartWith(start, with) => {
6535                write!(
6536                    f,
6537                    " START{with} {start}",
6538                    with = if *with { " WITH" } else { "" },
6539                    start = start
6540                )
6541            }
6542            SequenceOptions::Cache(cache) => {
6543                write!(f, " CACHE {}", *cache)
6544            }
6545            SequenceOptions::Cycle(no) => {
6546                write!(f, " {}CYCLE", if *no { "NO " } else { "" })
6547            }
6548        }
6549    }
6550}
6551
6552/// Assignment for a `SET` statement (name [=|TO] value)
6553#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6554#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6555#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6556pub struct SetAssignment {
6557    /// Optional context scope (e.g., SESSION or LOCAL).
6558    pub scope: Option<ContextModifier>,
6559    /// Assignment target name.
6560    pub name: ObjectName,
6561    /// Assigned expression value.
6562    pub value: Expr,
6563}
6564
6565impl fmt::Display for SetAssignment {
6566    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6567        write!(
6568            f,
6569            "{}{} = {}",
6570            self.scope.map(|s| format!("{s}")).unwrap_or_default(),
6571            self.name,
6572            self.value
6573        )
6574    }
6575}
6576
6577/// Target of a `TRUNCATE TABLE` command
6578///
6579/// Note this is its own struct because `visit_relation` requires an `ObjectName` (not a `Vec<ObjectName>`)
6580#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6581#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6582#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6583pub struct TruncateTableTarget {
6584    /// name of the table being truncated
6585    #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
6586    pub name: ObjectName,
6587    /// Postgres-specific option: explicitly exclude descendants (also default without ONLY)
6588    /// ```sql
6589    /// TRUNCATE TABLE ONLY name
6590    /// ```
6591    /// <https://www.postgresql.org/docs/current/sql-truncate.html>
6592    pub only: bool,
6593    /// Postgres-specific option: asterisk after table name to explicitly indicate descendants
6594    /// ```sql
6595    /// TRUNCATE TABLE name [ * ]
6596    /// ```
6597    /// <https://www.postgresql.org/docs/current/sql-truncate.html>
6598    pub has_asterisk: bool,
6599}
6600
6601impl fmt::Display for TruncateTableTarget {
6602    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6603        if self.only {
6604            write!(f, "ONLY ")?;
6605        };
6606        write!(f, "{}", self.name)?;
6607        if self.has_asterisk {
6608            write!(f, " *")?;
6609        };
6610        Ok(())
6611    }
6612}
6613
6614/// A `LOCK` statement.
6615///
6616/// See <https://www.postgresql.org/docs/current/sql-lock.html>
6617#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6618#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6619#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6620pub struct Lock {
6621    /// List of tables to lock.
6622    pub tables: Vec<LockTableTarget>,
6623    /// Lock mode.
6624    pub lock_mode: Option<LockTableMode>,
6625    /// Whether `NOWAIT` was specified.
6626    pub nowait: bool,
6627}
6628
6629impl fmt::Display for Lock {
6630    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6631        write!(f, "LOCK TABLE {}", display_comma_separated(&self.tables))?;
6632        if let Some(lock_mode) = &self.lock_mode {
6633            write!(f, " IN {lock_mode} MODE")?;
6634        }
6635        if self.nowait {
6636            write!(f, " NOWAIT")?;
6637        }
6638        Ok(())
6639    }
6640}
6641
6642/// Target of a `LOCK TABLE` command
6643///
6644/// See <https://www.postgresql.org/docs/current/sql-lock.html>
6645#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6646#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6647#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6648pub struct LockTableTarget {
6649    /// Name of the table being locked.
6650    #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
6651    pub name: ObjectName,
6652    /// Whether `ONLY` was specified to exclude descendant tables.
6653    pub only: bool,
6654    /// Whether `*` was specified to explicitly include descendant tables.
6655    pub has_asterisk: bool,
6656}
6657
6658impl fmt::Display for LockTableTarget {
6659    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6660        if self.only {
6661            write!(f, "ONLY ")?;
6662        }
6663        write!(f, "{}", self.name)?;
6664        if self.has_asterisk {
6665            write!(f, " *")?;
6666        }
6667        Ok(())
6668    }
6669}
6670
6671/// PostgreSQL lock modes for `LOCK TABLE`.
6672///
6673/// See <https://www.postgresql.org/docs/current/sql-lock.html>
6674#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6675#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6676#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6677pub enum LockTableMode {
6678    /// `ACCESS SHARE`
6679    AccessShare,
6680    /// `ROW SHARE`
6681    RowShare,
6682    /// `ROW EXCLUSIVE`
6683    RowExclusive,
6684    /// `SHARE UPDATE EXCLUSIVE`
6685    ShareUpdateExclusive,
6686    /// `SHARE`
6687    Share,
6688    /// `SHARE ROW EXCLUSIVE`
6689    ShareRowExclusive,
6690    /// `EXCLUSIVE`
6691    Exclusive,
6692    /// `ACCESS EXCLUSIVE`
6693    AccessExclusive,
6694}
6695
6696impl fmt::Display for LockTableMode {
6697    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
6698        let text = match self {
6699            Self::AccessShare => "ACCESS SHARE",
6700            Self::RowShare => "ROW SHARE",
6701            Self::RowExclusive => "ROW EXCLUSIVE",
6702            Self::ShareUpdateExclusive => "SHARE UPDATE EXCLUSIVE",
6703            Self::Share => "SHARE",
6704            Self::ShareRowExclusive => "SHARE ROW EXCLUSIVE",
6705            Self::Exclusive => "EXCLUSIVE",
6706            Self::AccessExclusive => "ACCESS EXCLUSIVE",
6707        };
6708        write!(f, "{text}")
6709    }
6710}
6711
6712/// PostgreSQL identity option for TRUNCATE table
6713/// [ RESTART IDENTITY | CONTINUE IDENTITY ]
6714#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6715#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6716#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6717pub enum TruncateIdentityOption {
6718    /// Restart identity values (RESTART IDENTITY).
6719    Restart,
6720    /// Continue identity values (CONTINUE IDENTITY).
6721    Continue,
6722}
6723
6724/// Cascade/restrict option for Postgres TRUNCATE table, MySQL GRANT/REVOKE, etc.
6725/// [ CASCADE | RESTRICT ]
6726#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6727#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6728#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6729pub enum CascadeOption {
6730    /// Apply cascading action (e.g., CASCADE).
6731    Cascade,
6732    /// Restrict the action (e.g., RESTRICT).
6733    Restrict,
6734}
6735
6736impl Display for CascadeOption {
6737    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6738        match self {
6739            CascadeOption::Cascade => write!(f, "CASCADE"),
6740            CascadeOption::Restrict => write!(f, "RESTRICT"),
6741        }
6742    }
6743}
6744
6745/// Transaction started with [ TRANSACTION | WORK | TRAN ]
6746#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6747#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6748#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6749pub enum BeginTransactionKind {
6750    /// Standard `TRANSACTION` keyword.
6751    Transaction,
6752    /// Alternate `WORK` keyword.
6753    Work,
6754    /// MSSQL shorthand `TRAN` keyword.
6755    /// See <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/begin-transaction-transact-sql>
6756    Tran,
6757}
6758
6759impl Display for BeginTransactionKind {
6760    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6761        match self {
6762            BeginTransactionKind::Transaction => write!(f, "TRANSACTION"),
6763            BeginTransactionKind::Work => write!(f, "WORK"),
6764            BeginTransactionKind::Tran => write!(f, "TRAN"),
6765        }
6766    }
6767}
6768
6769/// Can use to describe options in  create sequence or table column type identity
6770/// [ MINVALUE minvalue | NO MINVALUE ] [ MAXVALUE maxvalue | NO MAXVALUE ]
6771#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6772#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6773#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6774pub enum MinMaxValue {
6775    /// Clause is not specified.
6776    Empty,
6777    /// NO MINVALUE / NO MAXVALUE.
6778    None,
6779    /// `MINVALUE <expr>` / `MAXVALUE <expr>`.
6780    Some(Expr),
6781}
6782
6783#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6784#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6785#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6786#[non_exhaustive]
6787/// Behavior to apply for `INSERT` when a conflict occurs.
6788pub enum OnInsert {
6789    /// ON DUPLICATE KEY UPDATE (MySQL when the key already exists, then execute an update instead)
6790    DuplicateKeyUpdate(Vec<Assignment>),
6791    /// ON CONFLICT is a PostgreSQL and Sqlite extension
6792    OnConflict(OnConflict),
6793}
6794
6795#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6796#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6797#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6798/// Optional aliases for `INSERT` targets: row alias and optional column aliases.
6799pub struct InsertAliases {
6800    /// Row alias (table-style alias) for the inserted values.
6801    pub row_alias: ObjectName,
6802    /// Optional list of column aliases for the inserted values.
6803    pub col_aliases: Option<Vec<Ident>>,
6804}
6805
6806#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6807#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6808#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6809/// Optional alias for an `INSERT` table; i.e. the table to be inserted into
6810pub struct TableAliasWithoutColumns {
6811    /// `true` if the aliases was explicitly introduced with the "AS" keyword
6812    pub explicit: bool,
6813    /// the alias name itself
6814    pub alias: Ident,
6815}
6816
6817#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6818#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6819#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6820/// `ON CONFLICT` clause representation.
6821pub struct OnConflict {
6822    /// Optional conflict target specifying columns or constraint.
6823    pub conflict_target: Option<ConflictTarget>,
6824    /// Action to take when a conflict occurs.
6825    pub action: OnConflictAction,
6826}
6827#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6828#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6829#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6830/// Target specification for an `ON CONFLICT` clause.
6831pub enum ConflictTarget {
6832    /// Target specified as a list of columns.
6833    Columns(Vec<Ident>),
6834    /// Target specified as a named constraint.
6835    OnConstraint(ObjectName),
6836}
6837#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6838#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6839#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6840/// Action to perform when an `ON CONFLICT` target is matched.
6841pub enum OnConflictAction {
6842    /// Do nothing on conflict.
6843    DoNothing,
6844    /// Perform an update on conflict.
6845    DoUpdate(DoUpdate),
6846}
6847
6848#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6849#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6850#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6851/// Details for `DO UPDATE` action of an `ON CONFLICT` clause.
6852pub struct DoUpdate {
6853    /// Column assignments to perform on update.
6854    pub assignments: Vec<Assignment>,
6855    /// Optional WHERE clause limiting the update.
6856    pub selection: Option<Expr>,
6857}
6858
6859impl fmt::Display for OnInsert {
6860    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6861        match self {
6862            Self::DuplicateKeyUpdate(expr) => write!(
6863                f,
6864                " ON DUPLICATE KEY UPDATE {}",
6865                display_comma_separated(expr)
6866            ),
6867            Self::OnConflict(o) => write!(f, "{o}"),
6868        }
6869    }
6870}
6871impl fmt::Display for OnConflict {
6872    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6873        write!(f, " ON CONFLICT")?;
6874        if let Some(target) = &self.conflict_target {
6875            write!(f, "{target}")?;
6876        }
6877        write!(f, " {}", self.action)
6878    }
6879}
6880impl fmt::Display for ConflictTarget {
6881    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6882        match self {
6883            ConflictTarget::Columns(cols) => write!(f, "({})", display_comma_separated(cols)),
6884            ConflictTarget::OnConstraint(name) => write!(f, " ON CONSTRAINT {name}"),
6885        }
6886    }
6887}
6888impl fmt::Display for OnConflictAction {
6889    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6890        match self {
6891            Self::DoNothing => write!(f, "DO NOTHING"),
6892            Self::DoUpdate(do_update) => {
6893                write!(f, "DO UPDATE")?;
6894                if !do_update.assignments.is_empty() {
6895                    write!(
6896                        f,
6897                        " SET {}",
6898                        display_comma_separated(&do_update.assignments)
6899                    )?;
6900                }
6901                if let Some(selection) = &do_update.selection {
6902                    write!(f, " WHERE {selection}")?;
6903                }
6904                Ok(())
6905            }
6906        }
6907    }
6908}
6909
6910/// Privileges granted in a GRANT statement or revoked in a REVOKE statement.
6911#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6912#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6913#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6914pub enum Privileges {
6915    /// All privileges applicable to the object type
6916    All {
6917        /// Optional keyword from the spec, ignored in practice
6918        with_privileges_keyword: bool,
6919    },
6920    /// Specific privileges (e.g. `SELECT`, `INSERT`)
6921    Actions(Vec<Action>),
6922}
6923
6924impl fmt::Display for Privileges {
6925    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6926        match self {
6927            Privileges::All {
6928                with_privileges_keyword,
6929            } => {
6930                write!(
6931                    f,
6932                    "ALL{}",
6933                    if *with_privileges_keyword {
6934                        " PRIVILEGES"
6935                    } else {
6936                        ""
6937                    }
6938                )
6939            }
6940            Privileges::Actions(actions) => {
6941                write!(f, "{}", display_comma_separated(actions))
6942            }
6943        }
6944    }
6945}
6946
6947/// Specific direction for FETCH statement
6948#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6949#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6950#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6951pub enum FetchDirection {
6952    /// Fetch a specific count of rows.
6953    Count {
6954        /// The limit value for the count.
6955        limit: ValueWithSpan,
6956    },
6957    /// Fetch the next row.
6958    Next,
6959    /// Fetch the prior row.
6960    Prior,
6961    /// Fetch the first row.
6962    First,
6963    /// Fetch the last row.
6964    Last,
6965    /// Fetch an absolute row by index.
6966    Absolute {
6967        /// The absolute index value.
6968        limit: ValueWithSpan,
6969    },
6970    /// Fetch a row relative to the current position.
6971    Relative {
6972        /// The relative offset value.
6973        limit: ValueWithSpan,
6974    },
6975    /// Fetch all rows.
6976    All,
6977    // FORWARD
6978    // FORWARD count
6979    /// Fetch forward by an optional limit.
6980    Forward {
6981        /// Optional forward limit.
6982        limit: Option<ValueWithSpan>,
6983    },
6984    /// Fetch all forward rows.
6985    ForwardAll,
6986    // BACKWARD
6987    // BACKWARD count
6988    /// Fetch backward by an optional limit.
6989    Backward {
6990        /// Optional backward limit.
6991        limit: Option<ValueWithSpan>,
6992    },
6993    /// Fetch all backward rows.
6994    BackwardAll,
6995}
6996
6997impl fmt::Display for FetchDirection {
6998    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6999        match self {
7000            FetchDirection::Count { limit } => f.write_str(&limit.to_string())?,
7001            FetchDirection::Next => f.write_str("NEXT")?,
7002            FetchDirection::Prior => f.write_str("PRIOR")?,
7003            FetchDirection::First => f.write_str("FIRST")?,
7004            FetchDirection::Last => f.write_str("LAST")?,
7005            FetchDirection::Absolute { limit } => {
7006                f.write_str("ABSOLUTE ")?;
7007                f.write_str(&limit.to_string())?;
7008            }
7009            FetchDirection::Relative { limit } => {
7010                f.write_str("RELATIVE ")?;
7011                f.write_str(&limit.to_string())?;
7012            }
7013            FetchDirection::All => f.write_str("ALL")?,
7014            FetchDirection::Forward { limit } => {
7015                f.write_str("FORWARD")?;
7016
7017                if let Some(l) = limit {
7018                    f.write_str(" ")?;
7019                    f.write_str(&l.to_string())?;
7020                }
7021            }
7022            FetchDirection::ForwardAll => f.write_str("FORWARD ALL")?,
7023            FetchDirection::Backward { limit } => {
7024                f.write_str("BACKWARD")?;
7025
7026                if let Some(l) = limit {
7027                    f.write_str(" ")?;
7028                    f.write_str(&l.to_string())?;
7029                }
7030            }
7031            FetchDirection::BackwardAll => f.write_str("BACKWARD ALL")?,
7032        };
7033
7034        Ok(())
7035    }
7036}
7037
7038/// The "position" for a FETCH statement.
7039///
7040/// [MsSql](https://learn.microsoft.com/en-us/sql/t-sql/language-elements/fetch-transact-sql)
7041#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7042#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7043#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7044pub enum FetchPosition {
7045    /// Use `FROM <pos>` position specifier.
7046    From,
7047    /// Use `IN <pos>` position specifier.
7048    In,
7049}
7050
7051impl fmt::Display for FetchPosition {
7052    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7053        match self {
7054            FetchPosition::From => f.write_str("FROM")?,
7055            FetchPosition::In => f.write_str("IN")?,
7056        };
7057
7058        Ok(())
7059    }
7060}
7061
7062/// A privilege on a database object (table, sequence, etc.).
7063#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7064#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7065#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7066pub enum Action {
7067    /// Add a search optimization.
7068    AddSearchOptimization,
7069    /// Apply an `APPLY` operation with a specific type.
7070    Apply {
7071        /// The type of apply operation.
7072        apply_type: ActionApplyType,
7073    },
7074    /// Apply a budget operation.
7075    ApplyBudget,
7076    /// Attach a listing.
7077    AttachListing,
7078    /// Attach a policy.
7079    AttachPolicy,
7080    /// Audit operation.
7081    Audit,
7082    /// Bind a service endpoint.
7083    BindServiceEndpoint,
7084    /// Connect permission.
7085    Connect,
7086    /// Create action, optionally specifying an object type.
7087    Create {
7088        /// Optional object type to create.
7089        obj_type: Option<ActionCreateObjectType>,
7090    },
7091    /// Actions related to database roles.
7092    DatabaseRole {
7093        /// The role name.
7094        role: ObjectName,
7095    },
7096    /// Delete permission.
7097    Delete,
7098    /// Drop permission.
7099    Drop,
7100    /// Evolve schema permission.
7101    EvolveSchema,
7102    /// Exec action (execute) with optional object type.
7103    Exec {
7104        /// Optional execute object type.
7105        obj_type: Option<ActionExecuteObjectType>,
7106    },
7107    /// Execute action with optional object type.
7108    Execute {
7109        /// Optional execute object type.
7110        obj_type: Option<ActionExecuteObjectType>,
7111    },
7112    /// Failover operation.
7113    Failover,
7114    /// Use imported privileges.
7115    ImportedPrivileges,
7116    /// Import a share.
7117    ImportShare,
7118    /// Insert rows with optional column list.
7119    Insert {
7120        /// Optional list of target columns for insert.
7121        columns: Option<Vec<Ident>>,
7122    },
7123    /// Manage operation with a specific manage type.
7124    Manage {
7125        /// The specific manage sub-type.
7126        manage_type: ActionManageType,
7127    },
7128    /// Manage releases.
7129    ManageReleases,
7130    /// Manage versions.
7131    ManageVersions,
7132    /// Modify operation with an optional modify type.
7133    Modify {
7134        /// The optional modify sub-type.
7135        modify_type: Option<ActionModifyType>,
7136    },
7137    /// Monitor operation with an optional monitor type.
7138    Monitor {
7139        /// The optional monitor sub-type.
7140        monitor_type: Option<ActionMonitorType>,
7141    },
7142    /// Operate permission.
7143    Operate,
7144    /// Override share restrictions.
7145    OverrideShareRestrictions,
7146    /// Ownership permission.
7147    Ownership,
7148    /// Purchase a data exchange listing.
7149    PurchaseDataExchangeListing,
7150
7151    /// Read access.
7152    Read,
7153    /// Read session-level access.
7154    ReadSession,
7155    /// References with optional column list.
7156    References {
7157        /// Optional list of referenced column identifiers.
7158        columns: Option<Vec<Ident>>,
7159    },
7160    /// Replication permission.
7161    Replicate,
7162    /// Resolve all references.
7163    ResolveAll,
7164    /// Role-related permission with target role name.
7165    Role {
7166        /// The target role name.
7167        role: ObjectName,
7168    },
7169    /// Select permission with optional column list.
7170    Select {
7171        /// Optional list of selected columns.
7172        columns: Option<Vec<Ident>>,
7173    },
7174    /// Temporary object permission.
7175    Temporary,
7176    /// Trigger-related permission.
7177    Trigger,
7178    /// Truncate permission.
7179    Truncate,
7180    /// Update permission with optional affected columns.
7181    Update {
7182        /// Optional list of columns affected by update.
7183        columns: Option<Vec<Ident>>,
7184    },
7185    /// Usage permission.
7186    Usage,
7187}
7188
7189impl fmt::Display for Action {
7190    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7191        match self {
7192            Action::AddSearchOptimization => f.write_str("ADD SEARCH OPTIMIZATION")?,
7193            Action::Apply { apply_type } => write!(f, "APPLY {apply_type}")?,
7194            Action::ApplyBudget => f.write_str("APPLYBUDGET")?,
7195            Action::AttachListing => f.write_str("ATTACH LISTING")?,
7196            Action::AttachPolicy => f.write_str("ATTACH POLICY")?,
7197            Action::Audit => f.write_str("AUDIT")?,
7198            Action::BindServiceEndpoint => f.write_str("BIND SERVICE ENDPOINT")?,
7199            Action::Connect => f.write_str("CONNECT")?,
7200            Action::Create { obj_type } => {
7201                f.write_str("CREATE")?;
7202                if let Some(obj_type) = obj_type {
7203                    write!(f, " {obj_type}")?
7204                }
7205            }
7206            Action::DatabaseRole { role } => write!(f, "DATABASE ROLE {role}")?,
7207            Action::Delete => f.write_str("DELETE")?,
7208            Action::Drop => f.write_str("DROP")?,
7209            Action::EvolveSchema => f.write_str("EVOLVE SCHEMA")?,
7210            Action::Exec { obj_type } => {
7211                f.write_str("EXEC")?;
7212                if let Some(obj_type) = obj_type {
7213                    write!(f, " {obj_type}")?
7214                }
7215            }
7216            Action::Execute { obj_type } => {
7217                f.write_str("EXECUTE")?;
7218                if let Some(obj_type) = obj_type {
7219                    write!(f, " {obj_type}")?
7220                }
7221            }
7222            Action::Failover => f.write_str("FAILOVER")?,
7223            Action::ImportedPrivileges => f.write_str("IMPORTED PRIVILEGES")?,
7224            Action::ImportShare => f.write_str("IMPORT SHARE")?,
7225            Action::Insert { .. } => f.write_str("INSERT")?,
7226            Action::Manage { manage_type } => write!(f, "MANAGE {manage_type}")?,
7227            Action::ManageReleases => f.write_str("MANAGE RELEASES")?,
7228            Action::ManageVersions => f.write_str("MANAGE VERSIONS")?,
7229            Action::Modify { modify_type } => {
7230                write!(f, "MODIFY")?;
7231                if let Some(modify_type) = modify_type {
7232                    write!(f, " {modify_type}")?;
7233                }
7234            }
7235            Action::Monitor { monitor_type } => {
7236                write!(f, "MONITOR")?;
7237                if let Some(monitor_type) = monitor_type {
7238                    write!(f, " {monitor_type}")?
7239                }
7240            }
7241            Action::Operate => f.write_str("OPERATE")?,
7242            Action::OverrideShareRestrictions => f.write_str("OVERRIDE SHARE RESTRICTIONS")?,
7243            Action::Ownership => f.write_str("OWNERSHIP")?,
7244            Action::PurchaseDataExchangeListing => f.write_str("PURCHASE DATA EXCHANGE LISTING")?,
7245            Action::Read => f.write_str("READ")?,
7246            Action::ReadSession => f.write_str("READ SESSION")?,
7247            Action::References { .. } => f.write_str("REFERENCES")?,
7248            Action::Replicate => f.write_str("REPLICATE")?,
7249            Action::ResolveAll => f.write_str("RESOLVE ALL")?,
7250            Action::Role { role } => write!(f, "ROLE {role}")?,
7251            Action::Select { .. } => f.write_str("SELECT")?,
7252            Action::Temporary => f.write_str("TEMPORARY")?,
7253            Action::Trigger => f.write_str("TRIGGER")?,
7254            Action::Truncate => f.write_str("TRUNCATE")?,
7255            Action::Update { .. } => f.write_str("UPDATE")?,
7256            Action::Usage => f.write_str("USAGE")?,
7257        };
7258        match self {
7259            Action::Insert { columns }
7260            | Action::References { columns }
7261            | Action::Select { columns }
7262            | Action::Update { columns } => {
7263                if let Some(columns) = columns {
7264                    write!(f, " ({})", display_comma_separated(columns))?;
7265                }
7266            }
7267            _ => (),
7268        };
7269        Ok(())
7270    }
7271}
7272
7273#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7274#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7275#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7276/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
7277/// under `globalPrivileges` in the `CREATE` privilege.
7278pub enum ActionCreateObjectType {
7279    /// An account-level object.
7280    Account,
7281    /// An application object.
7282    Application,
7283    /// An application package object.
7284    ApplicationPackage,
7285    /// A compute pool object.
7286    ComputePool,
7287    /// A data exchange listing.
7288    DataExchangeListing,
7289    /// A database object.
7290    Database,
7291    /// An external volume object.
7292    ExternalVolume,
7293    /// A failover group object.
7294    FailoverGroup,
7295    /// An integration object.
7296    Integration,
7297    /// A network policy object.
7298    NetworkPolicy,
7299    /// An organization listing.
7300    OrganiationListing,
7301    /// A replication group object.
7302    ReplicationGroup,
7303    /// A role object.
7304    Role,
7305    /// A schema object.
7306    Schema,
7307    /// A share object.
7308    Share,
7309    /// A user object.
7310    User,
7311    /// A warehouse object.
7312    Warehouse,
7313}
7314
7315impl fmt::Display for ActionCreateObjectType {
7316    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7317        match self {
7318            ActionCreateObjectType::Account => write!(f, "ACCOUNT"),
7319            ActionCreateObjectType::Application => write!(f, "APPLICATION"),
7320            ActionCreateObjectType::ApplicationPackage => write!(f, "APPLICATION PACKAGE"),
7321            ActionCreateObjectType::ComputePool => write!(f, "COMPUTE POOL"),
7322            ActionCreateObjectType::DataExchangeListing => write!(f, "DATA EXCHANGE LISTING"),
7323            ActionCreateObjectType::Database => write!(f, "DATABASE"),
7324            ActionCreateObjectType::ExternalVolume => write!(f, "EXTERNAL VOLUME"),
7325            ActionCreateObjectType::FailoverGroup => write!(f, "FAILOVER GROUP"),
7326            ActionCreateObjectType::Integration => write!(f, "INTEGRATION"),
7327            ActionCreateObjectType::NetworkPolicy => write!(f, "NETWORK POLICY"),
7328            ActionCreateObjectType::OrganiationListing => write!(f, "ORGANIZATION LISTING"),
7329            ActionCreateObjectType::ReplicationGroup => write!(f, "REPLICATION GROUP"),
7330            ActionCreateObjectType::Role => write!(f, "ROLE"),
7331            ActionCreateObjectType::Schema => write!(f, "SCHEMA"),
7332            ActionCreateObjectType::Share => write!(f, "SHARE"),
7333            ActionCreateObjectType::User => write!(f, "USER"),
7334            ActionCreateObjectType::Warehouse => write!(f, "WAREHOUSE"),
7335        }
7336    }
7337}
7338
7339#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7340#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7341#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7342/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
7343/// under `globalPrivileges` in the `APPLY` privilege.
7344pub enum ActionApplyType {
7345    /// Apply an aggregation policy.
7346    AggregationPolicy,
7347    /// Apply an authentication policy.
7348    AuthenticationPolicy,
7349    /// Apply a join policy.
7350    JoinPolicy,
7351    /// Apply a masking policy.
7352    MaskingPolicy,
7353    /// Apply a packages policy.
7354    PackagesPolicy,
7355    /// Apply a password policy.
7356    PasswordPolicy,
7357    /// Apply a projection policy.
7358    ProjectionPolicy,
7359    /// Apply a row access policy.
7360    RowAccessPolicy,
7361    /// Apply a session policy.
7362    SessionPolicy,
7363    /// Apply a tag.
7364    Tag,
7365}
7366
7367impl fmt::Display for ActionApplyType {
7368    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7369        match self {
7370            ActionApplyType::AggregationPolicy => write!(f, "AGGREGATION POLICY"),
7371            ActionApplyType::AuthenticationPolicy => write!(f, "AUTHENTICATION POLICY"),
7372            ActionApplyType::JoinPolicy => write!(f, "JOIN POLICY"),
7373            ActionApplyType::MaskingPolicy => write!(f, "MASKING POLICY"),
7374            ActionApplyType::PackagesPolicy => write!(f, "PACKAGES POLICY"),
7375            ActionApplyType::PasswordPolicy => write!(f, "PASSWORD POLICY"),
7376            ActionApplyType::ProjectionPolicy => write!(f, "PROJECTION POLICY"),
7377            ActionApplyType::RowAccessPolicy => write!(f, "ROW ACCESS POLICY"),
7378            ActionApplyType::SessionPolicy => write!(f, "SESSION POLICY"),
7379            ActionApplyType::Tag => write!(f, "TAG"),
7380        }
7381    }
7382}
7383
7384#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7385#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7386#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7387/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
7388/// under `globalPrivileges` in the `EXECUTE` privilege.
7389pub enum ActionExecuteObjectType {
7390    /// Alert object.
7391    Alert,
7392    /// Data metric function object.
7393    DataMetricFunction,
7394    /// Managed alert object.
7395    ManagedAlert,
7396    /// Managed task object.
7397    ManagedTask,
7398    /// Task object.
7399    Task,
7400}
7401
7402impl fmt::Display for ActionExecuteObjectType {
7403    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7404        match self {
7405            ActionExecuteObjectType::Alert => write!(f, "ALERT"),
7406            ActionExecuteObjectType::DataMetricFunction => write!(f, "DATA METRIC FUNCTION"),
7407            ActionExecuteObjectType::ManagedAlert => write!(f, "MANAGED ALERT"),
7408            ActionExecuteObjectType::ManagedTask => write!(f, "MANAGED TASK"),
7409            ActionExecuteObjectType::Task => write!(f, "TASK"),
7410        }
7411    }
7412}
7413
7414#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7415#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7416#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7417/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
7418/// under `globalPrivileges` in the `MANAGE` privilege.
7419pub enum ActionManageType {
7420    /// Account support cases management.
7421    AccountSupportCases,
7422    /// Event sharing management.
7423    EventSharing,
7424    /// Grants management.
7425    Grants,
7426    /// Listing auto-fulfillment management.
7427    ListingAutoFulfillment,
7428    /// Organization support cases management.
7429    OrganizationSupportCases,
7430    /// User support cases management.
7431    UserSupportCases,
7432    /// Warehouses management.
7433    Warehouses,
7434}
7435
7436impl fmt::Display for ActionManageType {
7437    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7438        match self {
7439            ActionManageType::AccountSupportCases => write!(f, "ACCOUNT SUPPORT CASES"),
7440            ActionManageType::EventSharing => write!(f, "EVENT SHARING"),
7441            ActionManageType::Grants => write!(f, "GRANTS"),
7442            ActionManageType::ListingAutoFulfillment => write!(f, "LISTING AUTO FULFILLMENT"),
7443            ActionManageType::OrganizationSupportCases => write!(f, "ORGANIZATION SUPPORT CASES"),
7444            ActionManageType::UserSupportCases => write!(f, "USER SUPPORT CASES"),
7445            ActionManageType::Warehouses => write!(f, "WAREHOUSES"),
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 `MODIFY` privilege.
7455pub enum ActionModifyType {
7456    /// Modify log level.
7457    LogLevel,
7458    /// Modify trace level.
7459    TraceLevel,
7460    /// Modify session log level.
7461    SessionLogLevel,
7462    /// Modify session trace level.
7463    SessionTraceLevel,
7464}
7465
7466impl fmt::Display for ActionModifyType {
7467    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7468        match self {
7469            ActionModifyType::LogLevel => write!(f, "LOG LEVEL"),
7470            ActionModifyType::TraceLevel => write!(f, "TRACE LEVEL"),
7471            ActionModifyType::SessionLogLevel => write!(f, "SESSION LOG LEVEL"),
7472            ActionModifyType::SessionTraceLevel => write!(f, "SESSION TRACE LEVEL"),
7473        }
7474    }
7475}
7476
7477#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7478#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7479#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7480/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
7481/// under `globalPrivileges` in the `MONITOR` privilege.
7482pub enum ActionMonitorType {
7483    /// Monitor execution.
7484    Execution,
7485    /// Monitor security.
7486    Security,
7487    /// Monitor usage.
7488    Usage,
7489}
7490
7491impl fmt::Display for ActionMonitorType {
7492    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7493        match self {
7494            ActionMonitorType::Execution => write!(f, "EXECUTION"),
7495            ActionMonitorType::Security => write!(f, "SECURITY"),
7496            ActionMonitorType::Usage => write!(f, "USAGE"),
7497        }
7498    }
7499}
7500
7501/// The principal that receives the privileges
7502#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7503#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7504#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7505pub struct Grantee {
7506    /// The category/type of grantee (role, user, share, etc.).
7507    pub grantee_type: GranteesType,
7508    /// Optional name of the grantee (identifier or user@host).
7509    pub name: Option<GranteeName>,
7510}
7511
7512impl fmt::Display for Grantee {
7513    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7514        match self.grantee_type {
7515            GranteesType::Role => {
7516                write!(f, "ROLE ")?;
7517            }
7518            GranteesType::Share => {
7519                write!(f, "SHARE ")?;
7520            }
7521            GranteesType::User => {
7522                write!(f, "USER ")?;
7523            }
7524            GranteesType::Group => {
7525                write!(f, "GROUP ")?;
7526            }
7527            GranteesType::Public => {
7528                write!(f, "PUBLIC ")?;
7529            }
7530            GranteesType::DatabaseRole => {
7531                write!(f, "DATABASE ROLE ")?;
7532            }
7533            GranteesType::Application => {
7534                write!(f, "APPLICATION ")?;
7535            }
7536            GranteesType::ApplicationRole => {
7537                write!(f, "APPLICATION ROLE ")?;
7538            }
7539            GranteesType::None => (),
7540        }
7541        if let Some(ref name) = self.name {
7542            name.fmt(f)?;
7543        }
7544        Ok(())
7545    }
7546}
7547
7548#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7549#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7550#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7551/// The kind of principal receiving privileges.
7552pub enum GranteesType {
7553    /// A role principal.
7554    Role,
7555    /// A share principal.
7556    Share,
7557    /// A user principal.
7558    User,
7559    /// A group principal.
7560    Group,
7561    /// The public principal.
7562    Public,
7563    /// A database role principal.
7564    DatabaseRole,
7565    /// An application principal.
7566    Application,
7567    /// An application role principal.
7568    ApplicationRole,
7569    /// No specific principal (e.g. `NONE`).
7570    None,
7571}
7572
7573/// Users/roles designated in a GRANT/REVOKE
7574#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7575#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7576#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7577pub enum GranteeName {
7578    /// A bare identifier
7579    ObjectName(ObjectName),
7580    /// A MySQL user/host pair such as 'root'@'%'
7581    UserHost {
7582        /// The user identifier portion.
7583        user: Ident,
7584        /// The host identifier portion.
7585        host: Ident,
7586    },
7587}
7588
7589impl fmt::Display for GranteeName {
7590    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7591        match self {
7592            GranteeName::ObjectName(name) => name.fmt(f),
7593            GranteeName::UserHost { user, host } => {
7594                write!(f, "{user}@{host}")
7595            }
7596        }
7597    }
7598}
7599
7600/// Objects on which privileges are granted in a GRANT statement.
7601#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7602#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7603#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7604pub enum GrantObjects {
7605    /// Grant privileges on `ALL SEQUENCES IN SCHEMA <schema_name> [, ...]`
7606    AllSequencesInSchema {
7607        /// The target schema names.
7608        schemas: Vec<ObjectName>,
7609    },
7610    /// Grant privileges on `ALL TABLES IN SCHEMA <schema_name> [, ...]`
7611    AllTablesInSchema {
7612        /// The target schema names.
7613        schemas: Vec<ObjectName>,
7614    },
7615    /// Grant privileges on `ALL VIEWS IN SCHEMA <schema_name> [, ...]`
7616    AllViewsInSchema {
7617        /// The target schema names.
7618        schemas: Vec<ObjectName>,
7619    },
7620    /// Grant privileges on `ALL MATERIALIZED VIEWS IN SCHEMA <schema_name> [, ...]`
7621    AllMaterializedViewsInSchema {
7622        /// The target schema names.
7623        schemas: Vec<ObjectName>,
7624    },
7625    /// Grant privileges on `ALL EXTERNAL TABLES IN SCHEMA <schema_name> [, ...]`
7626    AllExternalTablesInSchema {
7627        /// The target schema names.
7628        schemas: Vec<ObjectName>,
7629    },
7630    /// Grant privileges on `ALL FUNCTIONS IN SCHEMA <schema_name> [, ...]`
7631    AllFunctionsInSchema {
7632        /// The target schema names.
7633        schemas: Vec<ObjectName>,
7634    },
7635    /// Grant privileges on `FUTURE SCHEMAS IN DATABASE <database_name> [, ...]`
7636    FutureSchemasInDatabase {
7637        /// The target database names.
7638        databases: Vec<ObjectName>,
7639    },
7640    /// Grant privileges on `FUTURE TABLES IN SCHEMA <schema_name> [, ...]`
7641    FutureTablesInSchema {
7642        /// The target schema names.
7643        schemas: Vec<ObjectName>,
7644    },
7645    /// Grant privileges on `FUTURE VIEWS IN SCHEMA <schema_name> [, ...]`
7646    FutureViewsInSchema {
7647        /// The target schema names.
7648        schemas: Vec<ObjectName>,
7649    },
7650    /// Grant privileges on `FUTURE EXTERNAL TABLES IN SCHEMA <schema_name> [, ...]`
7651    FutureExternalTablesInSchema {
7652        /// The target schema names.
7653        schemas: Vec<ObjectName>,
7654    },
7655    /// Grant privileges on `FUTURE MATERIALIZED VIEWS IN SCHEMA <schema_name> [, ...]`
7656    FutureMaterializedViewsInSchema {
7657        /// The target schema names.
7658        schemas: Vec<ObjectName>,
7659    },
7660    /// Grant privileges on `FUTURE SEQUENCES IN SCHEMA <schema_name> [, ...]`
7661    FutureSequencesInSchema {
7662        /// The target schema names.
7663        schemas: Vec<ObjectName>,
7664    },
7665    /// Grant privileges on specific databases
7666    Databases(Vec<ObjectName>),
7667    /// Grant privileges on specific schemas
7668    Schemas(Vec<ObjectName>),
7669    /// Grant privileges on specific sequences
7670    Sequences(Vec<ObjectName>),
7671    /// Grant privileges on specific tables
7672    Tables(Vec<ObjectName>),
7673    /// Grant privileges on specific views
7674    Views(Vec<ObjectName>),
7675    /// Grant privileges on specific warehouses
7676    Warehouses(Vec<ObjectName>),
7677    /// Grant privileges on specific integrations
7678    Integrations(Vec<ObjectName>),
7679    /// Grant privileges on resource monitors
7680    ResourceMonitors(Vec<ObjectName>),
7681    /// Grant privileges on users
7682    Users(Vec<ObjectName>),
7683    /// Grant privileges on compute pools
7684    ComputePools(Vec<ObjectName>),
7685    /// Grant privileges on connections
7686    Connections(Vec<ObjectName>),
7687    /// Grant privileges on failover groups
7688    FailoverGroup(Vec<ObjectName>),
7689    /// Grant privileges on replication group
7690    ReplicationGroup(Vec<ObjectName>),
7691    /// Grant privileges on external volumes
7692    ExternalVolumes(Vec<ObjectName>),
7693    /// Grant privileges on a procedure. In dialects that
7694    /// support overloading, the argument types must be specified.
7695    ///
7696    /// For example:
7697    /// `GRANT USAGE ON PROCEDURE foo(varchar) TO ROLE role1`
7698    Procedure {
7699        /// The procedure name.
7700        name: ObjectName,
7701        /// Optional argument types for overloaded procedures.
7702        arg_types: Vec<DataType>,
7703    },
7704
7705    /// Grant privileges on a function. In dialects that
7706    /// support overloading, the argument types must be specified.
7707    ///
7708    /// For example:
7709    /// `GRANT USAGE ON FUNCTION foo(varchar) TO ROLE role1`
7710    Function {
7711        /// The function name.
7712        name: ObjectName,
7713        /// Optional argument types for overloaded functions.
7714        arg_types: Vec<DataType>,
7715    },
7716}
7717
7718impl fmt::Display for GrantObjects {
7719    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7720        match self {
7721            GrantObjects::Sequences(sequences) => {
7722                write!(f, "SEQUENCE {}", display_comma_separated(sequences))
7723            }
7724            GrantObjects::Databases(databases) => {
7725                write!(f, "DATABASE {}", display_comma_separated(databases))
7726            }
7727            GrantObjects::Schemas(schemas) => {
7728                write!(f, "SCHEMA {}", display_comma_separated(schemas))
7729            }
7730            GrantObjects::Tables(tables) => {
7731                write!(f, "{}", display_comma_separated(tables))
7732            }
7733            GrantObjects::Views(views) => {
7734                write!(f, "VIEW {}", display_comma_separated(views))
7735            }
7736            GrantObjects::Warehouses(warehouses) => {
7737                write!(f, "WAREHOUSE {}", display_comma_separated(warehouses))
7738            }
7739            GrantObjects::Integrations(integrations) => {
7740                write!(f, "INTEGRATION {}", display_comma_separated(integrations))
7741            }
7742            GrantObjects::AllSequencesInSchema { schemas } => {
7743                write!(
7744                    f,
7745                    "ALL SEQUENCES IN SCHEMA {}",
7746                    display_comma_separated(schemas)
7747                )
7748            }
7749            GrantObjects::AllTablesInSchema { schemas } => {
7750                write!(
7751                    f,
7752                    "ALL TABLES IN SCHEMA {}",
7753                    display_comma_separated(schemas)
7754                )
7755            }
7756            GrantObjects::AllExternalTablesInSchema { schemas } => {
7757                write!(
7758                    f,
7759                    "ALL EXTERNAL TABLES IN SCHEMA {}",
7760                    display_comma_separated(schemas)
7761                )
7762            }
7763            GrantObjects::AllViewsInSchema { schemas } => {
7764                write!(
7765                    f,
7766                    "ALL VIEWS IN SCHEMA {}",
7767                    display_comma_separated(schemas)
7768                )
7769            }
7770            GrantObjects::AllMaterializedViewsInSchema { schemas } => {
7771                write!(
7772                    f,
7773                    "ALL MATERIALIZED VIEWS IN SCHEMA {}",
7774                    display_comma_separated(schemas)
7775                )
7776            }
7777            GrantObjects::AllFunctionsInSchema { schemas } => {
7778                write!(
7779                    f,
7780                    "ALL FUNCTIONS IN SCHEMA {}",
7781                    display_comma_separated(schemas)
7782                )
7783            }
7784            GrantObjects::FutureSchemasInDatabase { databases } => {
7785                write!(
7786                    f,
7787                    "FUTURE SCHEMAS IN DATABASE {}",
7788                    display_comma_separated(databases)
7789                )
7790            }
7791            GrantObjects::FutureTablesInSchema { schemas } => {
7792                write!(
7793                    f,
7794                    "FUTURE TABLES IN SCHEMA {}",
7795                    display_comma_separated(schemas)
7796                )
7797            }
7798            GrantObjects::FutureExternalTablesInSchema { schemas } => {
7799                write!(
7800                    f,
7801                    "FUTURE EXTERNAL TABLES IN SCHEMA {}",
7802                    display_comma_separated(schemas)
7803                )
7804            }
7805            GrantObjects::FutureViewsInSchema { schemas } => {
7806                write!(
7807                    f,
7808                    "FUTURE VIEWS IN SCHEMA {}",
7809                    display_comma_separated(schemas)
7810                )
7811            }
7812            GrantObjects::FutureMaterializedViewsInSchema { schemas } => {
7813                write!(
7814                    f,
7815                    "FUTURE MATERIALIZED VIEWS IN SCHEMA {}",
7816                    display_comma_separated(schemas)
7817                )
7818            }
7819            GrantObjects::FutureSequencesInSchema { schemas } => {
7820                write!(
7821                    f,
7822                    "FUTURE SEQUENCES IN SCHEMA {}",
7823                    display_comma_separated(schemas)
7824                )
7825            }
7826            GrantObjects::ResourceMonitors(objects) => {
7827                write!(f, "RESOURCE MONITOR {}", display_comma_separated(objects))
7828            }
7829            GrantObjects::Users(objects) => {
7830                write!(f, "USER {}", display_comma_separated(objects))
7831            }
7832            GrantObjects::ComputePools(objects) => {
7833                write!(f, "COMPUTE POOL {}", display_comma_separated(objects))
7834            }
7835            GrantObjects::Connections(objects) => {
7836                write!(f, "CONNECTION {}", display_comma_separated(objects))
7837            }
7838            GrantObjects::FailoverGroup(objects) => {
7839                write!(f, "FAILOVER GROUP {}", display_comma_separated(objects))
7840            }
7841            GrantObjects::ReplicationGroup(objects) => {
7842                write!(f, "REPLICATION GROUP {}", display_comma_separated(objects))
7843            }
7844            GrantObjects::ExternalVolumes(objects) => {
7845                write!(f, "EXTERNAL VOLUME {}", display_comma_separated(objects))
7846            }
7847            GrantObjects::Procedure { name, arg_types } => {
7848                write!(f, "PROCEDURE {name}")?;
7849                if !arg_types.is_empty() {
7850                    write!(f, "({})", display_comma_separated(arg_types))?;
7851                }
7852                Ok(())
7853            }
7854            GrantObjects::Function { name, arg_types } => {
7855                write!(f, "FUNCTION {name}")?;
7856                if !arg_types.is_empty() {
7857                    write!(f, "({})", display_comma_separated(arg_types))?;
7858                }
7859                Ok(())
7860            }
7861        }
7862    }
7863}
7864
7865/// A `DENY` statement
7866///
7867/// [MsSql](https://learn.microsoft.com/en-us/sql/t-sql/statements/deny-transact-sql)
7868#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7869#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7870#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7871pub struct DenyStatement {
7872    /// The privileges to deny.
7873    pub privileges: Privileges,
7874    /// The objects the privileges apply to.
7875    pub objects: GrantObjects,
7876    /// The grantees (users/roles) to whom the denial applies.
7877    pub grantees: Vec<Grantee>,
7878    /// Optional identifier of the principal that performed the grant.
7879    pub granted_by: Option<Ident>,
7880    /// Optional cascade option controlling dependent objects.
7881    pub cascade: Option<CascadeOption>,
7882}
7883
7884impl fmt::Display for DenyStatement {
7885    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7886        write!(f, "DENY {}", self.privileges)?;
7887        write!(f, " ON {}", self.objects)?;
7888        if !self.grantees.is_empty() {
7889            write!(f, " TO {}", display_comma_separated(&self.grantees))?;
7890        }
7891        if let Some(cascade) = &self.cascade {
7892            write!(f, " {cascade}")?;
7893        }
7894        if let Some(granted_by) = &self.granted_by {
7895            write!(f, " AS {granted_by}")?;
7896        }
7897        Ok(())
7898    }
7899}
7900
7901/// SQL assignment `foo = expr` as used in SQLUpdate
7902#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7903#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7904#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7905pub struct Assignment {
7906    /// The left-hand side of the assignment.
7907    pub target: AssignmentTarget,
7908    /// The expression assigned to the target.
7909    pub value: Expr,
7910}
7911
7912impl fmt::Display for Assignment {
7913    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7914        write!(f, "{} = {}", self.target, self.value)
7915    }
7916}
7917
7918/// Left-hand side of an assignment in an UPDATE statement,
7919/// e.g. `foo` in `foo = 5` (ColumnName assignment) or
7920/// `(a, b)` in `(a, b) = (1, 2)` (Tuple assignment).
7921#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7922#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7923#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7924pub enum AssignmentTarget {
7925    /// A single column
7926    ColumnName(ObjectName),
7927    /// A tuple of columns
7928    Tuple(Vec<ObjectName>),
7929}
7930
7931impl fmt::Display for AssignmentTarget {
7932    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7933        match self {
7934            AssignmentTarget::ColumnName(column) => write!(f, "{column}"),
7935            AssignmentTarget::Tuple(columns) => write!(f, "({})", display_comma_separated(columns)),
7936        }
7937    }
7938}
7939
7940#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7941#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7942#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7943/// Expression forms allowed as a function argument.
7944pub enum FunctionArgExpr {
7945    /// A normal expression argument.
7946    Expr(Expr),
7947    /// Qualified wildcard, e.g. `alias.*` or `schema.table.*`.
7948    QualifiedWildcard(ObjectName),
7949    /// An unqualified `*` wildcard.
7950    Wildcard,
7951    /// An unqualified `*` wildcard with additional options, e.g. `* EXCLUDE(col)`.
7952    ///
7953    /// Used in Snowflake to support expressions like `HASH(* EXCLUDE(col))`.
7954    WildcardWithOptions(WildcardAdditionalOptions),
7955}
7956
7957impl From<Expr> for FunctionArgExpr {
7958    fn from(wildcard_expr: Expr) -> Self {
7959        match wildcard_expr {
7960            Expr::QualifiedWildcard(prefix, _) => Self::QualifiedWildcard(prefix),
7961            Expr::Wildcard(_) => Self::Wildcard,
7962            expr => Self::Expr(expr),
7963        }
7964    }
7965}
7966
7967impl fmt::Display for FunctionArgExpr {
7968    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7969        match self {
7970            FunctionArgExpr::Expr(expr) => write!(f, "{expr}"),
7971            FunctionArgExpr::QualifiedWildcard(prefix) => write!(f, "{prefix}.*"),
7972            FunctionArgExpr::Wildcard => f.write_str("*"),
7973            FunctionArgExpr::WildcardWithOptions(opts) => write!(f, "*{opts}"),
7974        }
7975    }
7976}
7977
7978#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7979#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7980#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7981/// Operator used to separate function arguments
7982pub enum FunctionArgOperator {
7983    /// function(arg1 = value1)
7984    Equals,
7985    /// function(arg1 => value1)
7986    RightArrow,
7987    /// function(arg1 := value1)
7988    Assignment,
7989    /// function(arg1 : value1)
7990    Colon,
7991    /// function(arg1 VALUE value1)
7992    Value,
7993}
7994
7995impl fmt::Display for FunctionArgOperator {
7996    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7997        match self {
7998            FunctionArgOperator::Equals => f.write_str("="),
7999            FunctionArgOperator::RightArrow => f.write_str("=>"),
8000            FunctionArgOperator::Assignment => f.write_str(":="),
8001            FunctionArgOperator::Colon => f.write_str(":"),
8002            FunctionArgOperator::Value => f.write_str("VALUE"),
8003        }
8004    }
8005}
8006
8007#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8008#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8009#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8010/// Forms of function arguments (named, expression-named, or positional).
8011pub enum FunctionArg {
8012    /// `name` is identifier
8013    ///
8014    /// Enabled when `Dialect::supports_named_fn_args_with_expr_name` returns 'false'
8015    Named {
8016        /// The identifier name of the argument.
8017        name: Ident,
8018        /// The argument expression or wildcard form.
8019        arg: FunctionArgExpr,
8020        /// The operator separating name and value.
8021        operator: FunctionArgOperator,
8022    },
8023    /// `name` is arbitrary expression
8024    ///
8025    /// Enabled when `Dialect::supports_named_fn_args_with_expr_name` returns 'true'
8026    ExprNamed {
8027        /// The expression used as the argument name.
8028        name: Expr,
8029        /// The argument expression or wildcard form.
8030        arg: FunctionArgExpr,
8031        /// The operator separating name and value.
8032        operator: FunctionArgOperator,
8033    },
8034    /// An unnamed argument (positional), given by expression or wildcard.
8035    Unnamed(FunctionArgExpr),
8036}
8037
8038impl fmt::Display for FunctionArg {
8039    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8040        match self {
8041            FunctionArg::Named {
8042                name,
8043                arg,
8044                operator,
8045            } => write!(f, "{name} {operator} {arg}"),
8046            FunctionArg::ExprNamed {
8047                name,
8048                arg,
8049                operator,
8050            } => write!(f, "{name} {operator} {arg}"),
8051            FunctionArg::Unnamed(unnamed_arg) => write!(f, "{unnamed_arg}"),
8052        }
8053    }
8054}
8055
8056#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8057#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8058#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8059/// Which cursor(s) to close.
8060pub enum CloseCursor {
8061    /// Close all cursors.
8062    All,
8063    /// Close a specific cursor by name.
8064    Specific {
8065        /// The name of the cursor to close.
8066        name: Ident,
8067    },
8068}
8069
8070impl fmt::Display for CloseCursor {
8071    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8072        match self {
8073            CloseCursor::All => write!(f, "ALL"),
8074            CloseCursor::Specific { name } => write!(f, "{name}"),
8075        }
8076    }
8077}
8078
8079/// A Drop Domain statement
8080#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8081#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8082#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8083pub struct DropDomain {
8084    /// Whether to drop the domain if it exists
8085    pub if_exists: bool,
8086    /// The name of the domain to drop
8087    pub name: ObjectName,
8088    /// The behavior to apply when dropping the domain
8089    pub drop_behavior: Option<DropBehavior>,
8090}
8091
8092/// A constant of form `<data_type> 'value'`.
8093/// This can represent ANSI SQL `DATE`, `TIME`, and `TIMESTAMP` literals (such as `DATE '2020-01-01'`),
8094/// as well as constants of other types (a non-standard PostgreSQL extension).
8095#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8096#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8097#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8098pub struct TypedString {
8099    /// The data type of the typed string (e.g. DATE, TIME, TIMESTAMP).
8100    pub data_type: DataType,
8101    /// The value of the constant.
8102    /// Hint: you can unwrap the string value using `value.into_string()`.
8103    pub value: ValueWithSpan,
8104    /// Flags whether this TypedString uses the [ODBC syntax].
8105    ///
8106    /// Example:
8107    /// ```sql
8108    /// -- An ODBC date literal:
8109    /// SELECT {d '2025-07-16'}
8110    /// -- This is equivalent to the standard ANSI SQL literal:
8111    /// SELECT DATE '2025-07-16'
8112    ///
8113    /// [ODBC syntax]: https://learn.microsoft.com/en-us/sql/odbc/reference/develop-app/date-time-and-timestamp-literals?view=sql-server-2017
8114    pub uses_odbc_syntax: bool,
8115}
8116
8117impl fmt::Display for TypedString {
8118    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8119        let data_type = &self.data_type;
8120        let value = &self.value;
8121        match self.uses_odbc_syntax {
8122            false => {
8123                write!(f, "{data_type}")?;
8124                write!(f, " {value}")
8125            }
8126            true => {
8127                let prefix = match data_type {
8128                    DataType::Date => "d",
8129                    DataType::Time(..) => "t",
8130                    DataType::Timestamp(..) => "ts",
8131                    _ => "?",
8132                };
8133                write!(f, "{{{prefix} {value}}}")
8134            }
8135        }
8136    }
8137}
8138
8139/// A function call
8140#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8141#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8142#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8143pub struct Function {
8144    /// The function name (may be qualified).
8145    pub name: ObjectName,
8146    /// Flags whether this function call uses the [ODBC syntax].
8147    ///
8148    /// Example:
8149    /// ```sql
8150    /// SELECT {fn CONCAT('foo', 'bar')}
8151    /// ```
8152    ///
8153    /// [ODBC syntax]: https://learn.microsoft.com/en-us/sql/odbc/reference/develop-app/scalar-function-calls?view=sql-server-2017
8154    pub uses_odbc_syntax: bool,
8155    /// The parameters to the function, including any options specified within the
8156    /// delimiting parentheses.
8157    ///
8158    /// Example:
8159    /// ```plaintext
8160    /// HISTOGRAM(0.5, 0.6)(x, y)
8161    /// ```
8162    ///
8163    /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/aggregate-functions/parametric-functions)
8164    pub parameters: FunctionArguments,
8165    /// The arguments to the function, including any options specified within the
8166    /// delimiting parentheses.
8167    pub args: FunctionArguments,
8168    /// e.g. `x > 5` in `COUNT(x) FILTER (WHERE x > 5)`
8169    pub filter: Option<Box<Expr>>,
8170    /// Indicates how `NULL`s should be handled in the calculation.
8171    ///
8172    /// Example:
8173    /// ```plaintext
8174    /// FIRST_VALUE( <expr> ) [ { IGNORE | RESPECT } NULLS ] OVER ...
8175    /// ```
8176    ///
8177    /// [Snowflake](https://docs.snowflake.com/en/sql-reference/functions/first_value)
8178    pub null_treatment: Option<NullTreatment>,
8179    /// The `OVER` clause, indicating a window function call.
8180    pub over: Option<WindowType>,
8181    /// A clause used with certain aggregate functions to control the ordering
8182    /// within grouped sets before the function is applied.
8183    ///
8184    /// Syntax:
8185    /// ```plaintext
8186    /// <aggregate_function>(expression) WITHIN GROUP (ORDER BY key [ASC | DESC], ...)
8187    /// ```
8188    pub within_group: Vec<OrderByExpr>,
8189}
8190
8191impl fmt::Display for Function {
8192    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8193        if self.uses_odbc_syntax {
8194            write!(f, "{{fn ")?;
8195        }
8196
8197        write!(f, "{}{}{}", self.name, self.parameters, self.args)?;
8198
8199        if !self.within_group.is_empty() {
8200            write!(
8201                f,
8202                " WITHIN GROUP (ORDER BY {})",
8203                display_comma_separated(&self.within_group)
8204            )?;
8205        }
8206
8207        if let Some(filter_cond) = &self.filter {
8208            write!(f, " FILTER (WHERE {filter_cond})")?;
8209        }
8210
8211        if let Some(null_treatment) = &self.null_treatment {
8212            write!(f, " {null_treatment}")?;
8213        }
8214
8215        if let Some(o) = &self.over {
8216            f.write_str(" OVER ")?;
8217            o.fmt(f)?;
8218        }
8219
8220        if self.uses_odbc_syntax {
8221            write!(f, "}}")?;
8222        }
8223
8224        Ok(())
8225    }
8226}
8227
8228/// The arguments passed to a function call.
8229#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8230#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8231#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8232pub enum FunctionArguments {
8233    /// Used for special functions like `CURRENT_TIMESTAMP` that are invoked
8234    /// without parentheses.
8235    None,
8236    /// On some dialects, a subquery can be passed without surrounding
8237    /// parentheses if it's the sole argument to the function.
8238    Subquery(Box<Query>),
8239    /// A normal function argument list, including any clauses within it such as
8240    /// `DISTINCT` or `ORDER BY`.
8241    List(FunctionArgumentList),
8242}
8243
8244impl fmt::Display for FunctionArguments {
8245    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8246        match self {
8247            FunctionArguments::None => Ok(()),
8248            FunctionArguments::Subquery(query) => write!(f, "({query})"),
8249            FunctionArguments::List(args) => write!(f, "({args})"),
8250        }
8251    }
8252}
8253
8254/// This represents everything inside the parentheses when calling a function.
8255#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8256#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8257#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8258pub struct FunctionArgumentList {
8259    /// `[ ALL | DISTINCT ]`
8260    pub duplicate_treatment: Option<DuplicateTreatment>,
8261    /// The function arguments.
8262    pub args: Vec<FunctionArg>,
8263    /// Additional clauses specified within the argument list.
8264    pub clauses: Vec<FunctionArgumentClause>,
8265}
8266
8267impl fmt::Display for FunctionArgumentList {
8268    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8269        if let Some(duplicate_treatment) = self.duplicate_treatment {
8270            write!(f, "{duplicate_treatment} ")?;
8271        }
8272        write!(f, "{}", display_comma_separated(&self.args))?;
8273        if !self.clauses.is_empty() {
8274            if !self.args.is_empty() {
8275                write!(f, " ")?;
8276            }
8277            write!(f, "{}", display_separated(&self.clauses, " "))?;
8278        }
8279        Ok(())
8280    }
8281}
8282
8283#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8284#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8285#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8286/// Clauses that can appear inside a function argument list.
8287pub enum FunctionArgumentClause {
8288    /// Indicates how `NULL`s should be handled in the calculation, e.g. in `FIRST_VALUE` on [BigQuery].
8289    ///
8290    /// Syntax:
8291    /// ```plaintext
8292    /// { IGNORE | RESPECT } NULLS ]
8293    /// ```
8294    ///
8295    /// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/navigation_functions#first_value
8296    IgnoreOrRespectNulls(NullTreatment),
8297    /// Specifies the the ordering for some ordered set aggregates, e.g. `ARRAY_AGG` on [BigQuery].
8298    ///
8299    /// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/aggregate_functions#array_agg
8300    OrderBy(Vec<OrderByExpr>),
8301    /// Specifies a limit for the `ARRAY_AGG` and `ARRAY_CONCAT_AGG` functions on BigQuery.
8302    Limit(Expr),
8303    /// Specifies the behavior on overflow of the `LISTAGG` function.
8304    ///
8305    /// See <https://trino.io/docs/current/functions/aggregate.html>.
8306    OnOverflow(ListAggOnOverflow),
8307    /// Specifies a minimum or maximum bound on the input to [`ANY_VALUE`] on BigQuery.
8308    ///
8309    /// Syntax:
8310    /// ```plaintext
8311    /// HAVING { MAX | MIN } expression
8312    /// ```
8313    ///
8314    /// [`ANY_VALUE`]: https://cloud.google.com/bigquery/docs/reference/standard-sql/aggregate_functions#any_value
8315    Having(HavingBound),
8316    /// The `SEPARATOR` clause to the [`GROUP_CONCAT`] function in MySQL.
8317    ///
8318    /// [`GROUP_CONCAT`]: https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html#function_group-concat
8319    Separator(ValueWithSpan),
8320    /// The `ON NULL` clause for some JSON functions.
8321    ///
8322    /// [MSSQL `JSON_ARRAY`](https://learn.microsoft.com/en-us/sql/t-sql/functions/json-array-transact-sql?view=sql-server-ver16)
8323    /// [MSSQL `JSON_OBJECT`](https://learn.microsoft.com/en-us/sql/t-sql/functions/json-object-transact-sql?view=sql-server-ver16>)
8324    /// [PostgreSQL JSON functions](https://www.postgresql.org/docs/current/functions-json.html#FUNCTIONS-JSON-PROCESSING)
8325    JsonNullClause(JsonNullClause),
8326    /// The `RETURNING` clause for some JSON functions in PostgreSQL
8327    ///
8328    /// [`JSON_OBJECT`](https://www.postgresql.org/docs/current/functions-json.html#:~:text=json_object)
8329    JsonReturningClause(JsonReturningClause),
8330}
8331
8332impl fmt::Display for FunctionArgumentClause {
8333    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8334        match self {
8335            FunctionArgumentClause::IgnoreOrRespectNulls(null_treatment) => {
8336                write!(f, "{null_treatment}")
8337            }
8338            FunctionArgumentClause::OrderBy(order_by) => {
8339                write!(f, "ORDER BY {}", display_comma_separated(order_by))
8340            }
8341            FunctionArgumentClause::Limit(limit) => write!(f, "LIMIT {limit}"),
8342            FunctionArgumentClause::OnOverflow(on_overflow) => write!(f, "{on_overflow}"),
8343            FunctionArgumentClause::Having(bound) => write!(f, "{bound}"),
8344            FunctionArgumentClause::Separator(sep) => write!(f, "SEPARATOR {sep}"),
8345            FunctionArgumentClause::JsonNullClause(null_clause) => write!(f, "{null_clause}"),
8346            FunctionArgumentClause::JsonReturningClause(returning_clause) => {
8347                write!(f, "{returning_clause}")
8348            }
8349        }
8350    }
8351}
8352
8353/// A method call
8354#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8355#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8356#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8357pub struct Method {
8358    /// The expression on which the method is invoked.
8359    pub expr: Box<Expr>,
8360    // always non-empty
8361    /// The sequence of chained method calls.
8362    pub method_chain: Vec<Function>,
8363}
8364
8365impl fmt::Display for Method {
8366    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8367        write!(
8368            f,
8369            "{}.{}",
8370            self.expr,
8371            display_separated(&self.method_chain, ".")
8372        )
8373    }
8374}
8375
8376#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8377#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8378#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8379/// How duplicate values are treated inside function argument lists.
8380pub enum DuplicateTreatment {
8381    /// Consider only unique values.
8382    Distinct,
8383    /// Retain all duplicate values (the default).
8384    All,
8385}
8386
8387impl fmt::Display for DuplicateTreatment {
8388    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8389        match self {
8390            DuplicateTreatment::Distinct => write!(f, "DISTINCT"),
8391            DuplicateTreatment::All => write!(f, "ALL"),
8392        }
8393    }
8394}
8395
8396#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8397#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8398#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8399/// How the `ANALYZE`/`EXPLAIN ANALYZE` format is specified.
8400pub enum AnalyzeFormatKind {
8401    /// Format provided as a keyword, e.g. `FORMAT JSON`.
8402    Keyword(AnalyzeFormat),
8403    /// Format provided as an assignment, e.g. `FORMAT=JSON`.
8404    Assignment(AnalyzeFormat),
8405}
8406
8407impl fmt::Display for AnalyzeFormatKind {
8408    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
8409        match self {
8410            AnalyzeFormatKind::Keyword(format) => write!(f, "FORMAT {format}"),
8411            AnalyzeFormatKind::Assignment(format) => write!(f, "FORMAT={format}"),
8412        }
8413    }
8414}
8415
8416#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8417#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8418#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8419/// Output formats supported for `ANALYZE`/`EXPLAIN ANALYZE`.
8420pub enum AnalyzeFormat {
8421    /// Plain text format.
8422    TEXT,
8423    /// Graphviz DOT format.
8424    GRAPHVIZ,
8425    /// JSON format.
8426    JSON,
8427    /// Traditional explain output.
8428    TRADITIONAL,
8429    /// Tree-style explain output.
8430    TREE,
8431}
8432
8433impl fmt::Display for AnalyzeFormat {
8434    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
8435        f.write_str(match self {
8436            AnalyzeFormat::TEXT => "TEXT",
8437            AnalyzeFormat::GRAPHVIZ => "GRAPHVIZ",
8438            AnalyzeFormat::JSON => "JSON",
8439            AnalyzeFormat::TRADITIONAL => "TRADITIONAL",
8440            AnalyzeFormat::TREE => "TREE",
8441        })
8442    }
8443}
8444
8445/// External table's available file format
8446#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8447#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8448#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8449pub enum FileFormat {
8450    /// Text file format.
8451    TEXTFILE,
8452    /// Sequence file format.
8453    SEQUENCEFILE,
8454    /// ORC file format.
8455    ORC,
8456    /// Parquet file format.
8457    PARQUET,
8458    /// Avro file format.
8459    AVRO,
8460    /// RCFile format.
8461    RCFILE,
8462    /// JSON file format.
8463    JSONFILE,
8464}
8465
8466impl fmt::Display for FileFormat {
8467    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8468        use self::FileFormat::*;
8469        f.write_str(match self {
8470            TEXTFILE => "TEXTFILE",
8471            SEQUENCEFILE => "SEQUENCEFILE",
8472            ORC => "ORC",
8473            PARQUET => "PARQUET",
8474            AVRO => "AVRO",
8475            RCFILE => "RCFILE",
8476            JSONFILE => "JSONFILE",
8477        })
8478    }
8479}
8480
8481/// The `ON OVERFLOW` clause of a LISTAGG invocation
8482#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8483#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8484#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8485pub enum ListAggOnOverflow {
8486    /// `ON OVERFLOW ERROR`
8487    Error,
8488
8489    /// `ON OVERFLOW TRUNCATE [ <filler> ] WITH[OUT] COUNT`
8490    Truncate {
8491        /// Optional filler expression used when truncating.
8492        filler: Option<Box<Expr>>,
8493        /// Whether to include a count when truncating.
8494        with_count: bool,
8495    },
8496}
8497
8498impl fmt::Display for ListAggOnOverflow {
8499    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8500        write!(f, "ON OVERFLOW")?;
8501        match self {
8502            ListAggOnOverflow::Error => write!(f, " ERROR"),
8503            ListAggOnOverflow::Truncate { filler, with_count } => {
8504                write!(f, " TRUNCATE")?;
8505                if let Some(filler) = filler {
8506                    write!(f, " {filler}")?;
8507                }
8508                if *with_count {
8509                    write!(f, " WITH")?;
8510                } else {
8511                    write!(f, " WITHOUT")?;
8512                }
8513                write!(f, " COUNT")
8514            }
8515        }
8516    }
8517}
8518
8519/// The `HAVING` clause in a call to `ANY_VALUE` on BigQuery.
8520#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8521#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8522#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8523pub struct HavingBound(pub HavingBoundKind, pub Expr);
8524
8525impl fmt::Display for HavingBound {
8526    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8527        write!(f, "HAVING {} {}", self.0, self.1)
8528    }
8529}
8530
8531#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8532#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8533#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8534/// Which bound is used in a HAVING clause for ANY_VALUE on BigQuery.
8535pub enum HavingBoundKind {
8536    /// The minimum bound.
8537    Min,
8538    /// The maximum bound.
8539    Max,
8540}
8541
8542impl fmt::Display for HavingBoundKind {
8543    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8544        match self {
8545            HavingBoundKind::Min => write!(f, "MIN"),
8546            HavingBoundKind::Max => write!(f, "MAX"),
8547        }
8548    }
8549}
8550
8551#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8552#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8553#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8554/// Types of database objects referenced by DDL statements.
8555pub enum ObjectType {
8556    /// A collation.
8557    Collation,
8558    /// A table.
8559    Table,
8560    /// A view.
8561    View,
8562    /// A materialized view.
8563    MaterializedView,
8564    /// An index.
8565    Index,
8566    /// A schema.
8567    Schema,
8568    /// A database.
8569    Database,
8570    /// A role.
8571    Role,
8572    /// A sequence.
8573    Sequence,
8574    /// A stage.
8575    Stage,
8576    /// A type definition.
8577    Type,
8578    /// A user.
8579    User,
8580    /// A stream.
8581    Stream,
8582}
8583
8584impl fmt::Display for ObjectType {
8585    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8586        f.write_str(match self {
8587            ObjectType::Collation => "COLLATION",
8588            ObjectType::Table => "TABLE",
8589            ObjectType::View => "VIEW",
8590            ObjectType::MaterializedView => "MATERIALIZED VIEW",
8591            ObjectType::Index => "INDEX",
8592            ObjectType::Schema => "SCHEMA",
8593            ObjectType::Database => "DATABASE",
8594            ObjectType::Role => "ROLE",
8595            ObjectType::Sequence => "SEQUENCE",
8596            ObjectType::Stage => "STAGE",
8597            ObjectType::Type => "TYPE",
8598            ObjectType::User => "USER",
8599            ObjectType::Stream => "STREAM",
8600        })
8601    }
8602}
8603
8604#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8605#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8606#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8607/// Types supported by `KILL` statements.
8608pub enum KillType {
8609    /// Kill a connection.
8610    Connection,
8611    /// Kill a running query.
8612    Query,
8613    /// Kill a mutation (ClickHouse).
8614    Mutation,
8615}
8616
8617impl fmt::Display for KillType {
8618    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8619        f.write_str(match self {
8620            // MySQL
8621            KillType::Connection => "CONNECTION",
8622            KillType::Query => "QUERY",
8623            // Clickhouse supports Mutation
8624            KillType::Mutation => "MUTATION",
8625        })
8626    }
8627}
8628
8629#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8630#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8631#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8632/// Distribution style options for Hive tables.
8633pub enum HiveDistributionStyle {
8634    /// Partitioned distribution with the given columns.
8635    PARTITIONED {
8636        /// Columns used for partitioning.
8637        columns: Vec<ColumnDef>,
8638    },
8639    /// Skewed distribution definition.
8640    SKEWED {
8641        /// Columns participating in the skew definition.
8642        columns: Vec<ColumnDef>,
8643        /// Columns listed in the `ON` clause for skewing.
8644        on: Vec<ColumnDef>,
8645        /// Whether skewed data is stored as directories.
8646        stored_as_directories: bool,
8647    },
8648    /// No distribution style specified.
8649    NONE,
8650}
8651
8652#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8653#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8654#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8655/// Row format specification for Hive tables (SERDE or DELIMITED).
8656pub enum HiveRowFormat {
8657    /// SerDe class specification with the implementing class name.
8658    SERDE {
8659        /// The SerDe implementation class name.
8660        class: String,
8661    },
8662    /// Delimited row format with one or more delimiter specifications.
8663    DELIMITED {
8664        /// The list of delimiters used for delimiting fields/lines.
8665        delimiters: Vec<HiveRowDelimiter>,
8666    },
8667}
8668
8669#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8670#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8671#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8672/// Format specification for `LOAD DATA` Hive operations.
8673pub struct HiveLoadDataFormat {
8674    /// SerDe expression used for the table.
8675    pub serde: Expr,
8676    /// Input format expression.
8677    pub input_format: Expr,
8678}
8679
8680#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8681#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8682#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8683/// A single row delimiter specification for Hive `ROW FORMAT`.
8684pub struct HiveRowDelimiter {
8685    /// The delimiter kind (fields/lines/etc.).
8686    pub delimiter: HiveDelimiter,
8687    /// The delimiter character identifier.
8688    pub char: Ident,
8689}
8690
8691impl fmt::Display for HiveRowDelimiter {
8692    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8693        write!(f, "{} ", self.delimiter)?;
8694        write!(f, "{}", self.char)
8695    }
8696}
8697
8698#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8699#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8700#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8701/// Kind of delimiter used in Hive `ROW FORMAT` definitions.
8702pub enum HiveDelimiter {
8703    /// Fields terminated by a delimiter.
8704    FieldsTerminatedBy,
8705    /// Fields escaped by a character.
8706    FieldsEscapedBy,
8707    /// Collection items terminated by a delimiter.
8708    CollectionItemsTerminatedBy,
8709    /// Map keys terminated by a delimiter.
8710    MapKeysTerminatedBy,
8711    /// Lines terminated by a delimiter.
8712    LinesTerminatedBy,
8713    /// Null represented by a specific token.
8714    NullDefinedAs,
8715}
8716
8717impl fmt::Display for HiveDelimiter {
8718    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8719        use HiveDelimiter::*;
8720        f.write_str(match self {
8721            FieldsTerminatedBy => "FIELDS TERMINATED BY",
8722            FieldsEscapedBy => "ESCAPED BY",
8723            CollectionItemsTerminatedBy => "COLLECTION ITEMS TERMINATED BY",
8724            MapKeysTerminatedBy => "MAP KEYS TERMINATED BY",
8725            LinesTerminatedBy => "LINES TERMINATED BY",
8726            NullDefinedAs => "NULL DEFINED AS",
8727        })
8728    }
8729}
8730
8731#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8732#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8733#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8734/// Describe output format options for Hive `DESCRIBE`/`EXPLAIN`.
8735pub enum HiveDescribeFormat {
8736    /// Extended describe output.
8737    Extended,
8738    /// Formatted describe output.
8739    Formatted,
8740}
8741
8742impl fmt::Display for HiveDescribeFormat {
8743    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8744        use HiveDescribeFormat::*;
8745        f.write_str(match self {
8746            Extended => "EXTENDED",
8747            Formatted => "FORMATTED",
8748        })
8749    }
8750}
8751
8752#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8753#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8754#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8755/// Aliases accepted for describe-style commands.
8756pub enum DescribeAlias {
8757    /// `DESCRIBE` alias.
8758    Describe,
8759    /// `EXPLAIN` alias.
8760    Explain,
8761    /// `DESC` alias.
8762    Desc,
8763}
8764
8765impl fmt::Display for DescribeAlias {
8766    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8767        use DescribeAlias::*;
8768        f.write_str(match self {
8769            Describe => "DESCRIBE",
8770            Explain => "EXPLAIN",
8771            Desc => "DESC",
8772        })
8773    }
8774}
8775
8776#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8777#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8778#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8779#[allow(clippy::large_enum_variant)]
8780/// Hive input/output format specification used in `CREATE TABLE`.
8781pub enum HiveIOFormat {
8782    /// Generic IO format with separate input and output expressions.
8783    IOF {
8784        /// Expression for the input format.
8785        input_format: Expr,
8786        /// Expression for the output format.
8787        output_format: Expr,
8788    },
8789    /// File format wrapper referencing a `FileFormat` variant.
8790    FileFormat {
8791        /// The file format used for storage.
8792        format: FileFormat,
8793    },
8794    /// `USING <format>` syntax used by Spark SQL.
8795    ///
8796    /// Example: `CREATE TABLE t (i INT) USING PARQUET`
8797    ///
8798    /// See <https://spark.apache.org/docs/latest/sql-ref-syntax-ddl-create-table-datasource.html>
8799    Using {
8800        /// The data source or format name, e.g. `parquet`, `delta`, `csv`.
8801        format: Ident,
8802    },
8803}
8804
8805#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Default)]
8806#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8807#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8808/// Hive table format and storage-related options.
8809pub struct HiveFormat {
8810    /// Optional row format specification.
8811    pub row_format: Option<HiveRowFormat>,
8812    /// Optional SerDe properties expressed as SQL options.
8813    pub serde_properties: Option<Vec<SqlOption>>,
8814    /// Optional input/output storage format details.
8815    pub storage: Option<HiveIOFormat>,
8816    /// Optional location (URI or path) for table data.
8817    pub location: Option<String>,
8818}
8819
8820#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8821#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8822#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8823/// A clustered index column specification.
8824pub struct ClusteredIndex {
8825    /// Column identifier for the clustered index entry.
8826    pub name: Ident,
8827    /// Optional sort direction: `Some(true)` for ASC, `Some(false)` for DESC, `None` for unspecified.
8828    pub asc: Option<bool>,
8829}
8830
8831impl fmt::Display for ClusteredIndex {
8832    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8833        write!(f, "{}", self.name)?;
8834        match self.asc {
8835            Some(true) => write!(f, " ASC"),
8836            Some(false) => write!(f, " DESC"),
8837            _ => Ok(()),
8838        }
8839    }
8840}
8841
8842#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8843#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8844#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8845/// Clustered options used for `CREATE TABLE` clustered/indexed storage.
8846pub enum TableOptionsClustered {
8847    /// Use a columnstore index.
8848    ColumnstoreIndex,
8849    /// Columnstore index with an explicit ordering of columns.
8850    ColumnstoreIndexOrder(Vec<Ident>),
8851    /// A named clustered index with one or more columns.
8852    Index(Vec<ClusteredIndex>),
8853}
8854
8855impl fmt::Display for TableOptionsClustered {
8856    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8857        match self {
8858            TableOptionsClustered::ColumnstoreIndex => {
8859                write!(f, "CLUSTERED COLUMNSTORE INDEX")
8860            }
8861            TableOptionsClustered::ColumnstoreIndexOrder(values) => {
8862                write!(
8863                    f,
8864                    "CLUSTERED COLUMNSTORE INDEX ORDER ({})",
8865                    display_comma_separated(values)
8866                )
8867            }
8868            TableOptionsClustered::Index(values) => {
8869                write!(f, "CLUSTERED INDEX ({})", display_comma_separated(values))
8870            }
8871        }
8872    }
8873}
8874
8875/// Specifies which partition the boundary values on table partitioning belongs to.
8876#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash)]
8877#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8878#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8879pub enum PartitionRangeDirection {
8880    /// LEFT range direction.
8881    Left,
8882    /// RIGHT range direction.
8883    Right,
8884}
8885
8886#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8887#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8888#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8889/// SQL option syntax used in table and server definitions.
8890pub enum SqlOption {
8891    /// Clustered represents the clustered version of table storage for MSSQL.
8892    ///
8893    /// <https://learn.microsoft.com/en-us/sql/t-sql/statements/create-table-azure-sql-data-warehouse?view=aps-pdw-2016-au7#TableOptions>
8894    Clustered(TableOptionsClustered),
8895    /// Single identifier options, e.g. `HEAP` for MSSQL.
8896    ///
8897    /// <https://learn.microsoft.com/en-us/sql/t-sql/statements/create-table-azure-sql-data-warehouse?view=aps-pdw-2016-au7#TableOptions>
8898    Ident(Ident),
8899    /// Any option that consists of a key value pair where the value is an expression. e.g.
8900    ///
8901    ///   WITH(DISTRIBUTION = ROUND_ROBIN)
8902    KeyValue {
8903        /// The option key identifier.
8904        key: Ident,
8905        /// The expression value for the option.
8906        value: Expr,
8907    },
8908    /// One or more table partitions and represents which partition the boundary values belong to,
8909    /// e.g.
8910    ///
8911    ///   PARTITION (id RANGE LEFT FOR VALUES (10, 20, 30, 40))
8912    ///
8913    /// <https://learn.microsoft.com/en-us/sql/t-sql/statements/create-table-azure-sql-data-warehouse?view=aps-pdw-2016-au7#TablePartitionOptions>
8914    Partition {
8915        /// The partition column name.
8916        column_name: Ident,
8917        /// Optional direction for the partition range (LEFT/RIGHT).
8918        range_direction: Option<PartitionRangeDirection>,
8919        /// Values that define the partition boundaries.
8920        for_values: Vec<Expr>,
8921    },
8922    /// Comment parameter (supports `=` and no `=` syntax)
8923    Comment(CommentDef),
8924    /// MySQL TableSpace option
8925    /// <https://dev.mysql.com/doc/refman/8.4/en/create-table.html>
8926    TableSpace(TablespaceOption),
8927    /// An option representing a key value pair, where the value is a parenthesized list and with an optional name
8928    /// e.g.
8929    ///
8930    ///   UNION  = (tbl_name\[,tbl_name\]...) <https://dev.mysql.com/doc/refman/8.4/en/create-table.html>
8931    ///   ENGINE = ReplicatedMergeTree('/table_name','{replica}', ver) <https://clickhouse.com/docs/engines/table-engines/mergetree-family/replication>
8932    ///   ENGINE = SummingMergeTree(\[columns\]) <https://clickhouse.com/docs/engines/table-engines/mergetree-family/summingmergetree>
8933    NamedParenthesizedList(NamedParenthesizedList),
8934}
8935
8936impl fmt::Display for SqlOption {
8937    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8938        match self {
8939            SqlOption::Clustered(c) => write!(f, "{c}"),
8940            SqlOption::Ident(ident) => {
8941                write!(f, "{ident}")
8942            }
8943            SqlOption::KeyValue { key: name, value } => {
8944                write!(f, "{name} = {value}")
8945            }
8946            SqlOption::Partition {
8947                column_name,
8948                range_direction,
8949                for_values,
8950            } => {
8951                let direction = match range_direction {
8952                    Some(PartitionRangeDirection::Left) => " LEFT",
8953                    Some(PartitionRangeDirection::Right) => " RIGHT",
8954                    None => "",
8955                };
8956
8957                write!(
8958                    f,
8959                    "PARTITION ({} RANGE{} FOR VALUES ({}))",
8960                    column_name,
8961                    direction,
8962                    display_comma_separated(for_values)
8963                )
8964            }
8965            SqlOption::TableSpace(tablespace_option) => {
8966                write!(f, "TABLESPACE {}", tablespace_option.name)?;
8967                match tablespace_option.storage {
8968                    Some(StorageType::Disk) => write!(f, " STORAGE DISK"),
8969                    Some(StorageType::Memory) => write!(f, " STORAGE MEMORY"),
8970                    None => Ok(()),
8971                }
8972            }
8973            SqlOption::Comment(comment) => match comment {
8974                CommentDef::WithEq(comment) => {
8975                    write!(f, "COMMENT = '{comment}'")
8976                }
8977                CommentDef::WithoutEq(comment) => {
8978                    write!(f, "COMMENT '{comment}'")
8979                }
8980            },
8981            SqlOption::NamedParenthesizedList(value) => {
8982                write!(f, "{} = ", value.key)?;
8983                if let Some(key) = &value.name {
8984                    write!(f, "{key}")?;
8985                }
8986                if !value.values.is_empty() {
8987                    write!(f, "({})", display_comma_separated(&value.values))?
8988                }
8989                Ok(())
8990            }
8991        }
8992    }
8993}
8994
8995#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
8996#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8997#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8998/// Storage type options for a tablespace.
8999pub enum StorageType {
9000    /// Store on disk.
9001    Disk,
9002    /// Store in memory.
9003    Memory,
9004}
9005
9006#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
9007#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9008#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9009/// MySql TableSpace option
9010/// <https://dev.mysql.com/doc/refman/8.4/en/create-table.html>
9011pub struct TablespaceOption {
9012    /// Name of the tablespace.
9013    pub name: String,
9014    /// Optional storage type for the tablespace.
9015    pub storage: Option<StorageType>,
9016}
9017
9018#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9019#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9020#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9021/// A key/value identifier pair used for secret or key-based options.
9022pub struct SecretOption {
9023    /// The option key identifier.
9024    pub key: Ident,
9025    /// The option value identifier.
9026    pub value: Ident,
9027}
9028
9029impl fmt::Display for SecretOption {
9030    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9031        write!(f, "{} {}", self.key, self.value)
9032    }
9033}
9034
9035/// A `CREATE SERVER` statement.
9036///
9037/// [PostgreSQL Documentation](https://www.postgresql.org/docs/current/sql-createserver.html)
9038#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9039#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9040#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9041pub struct CreateServerStatement {
9042    /// The server name.
9043    pub name: ObjectName,
9044    /// Whether `IF NOT EXISTS` was specified.
9045    pub if_not_exists: bool,
9046    /// Optional server type identifier.
9047    pub server_type: Option<Ident>,
9048    /// Optional server version identifier.
9049    pub version: Option<Ident>,
9050    /// Foreign-data wrapper object name.
9051    pub foreign_data_wrapper: ObjectName,
9052    /// Optional list of server options.
9053    pub options: Option<Vec<CreateServerOption>>,
9054}
9055
9056impl fmt::Display for CreateServerStatement {
9057    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
9058        let CreateServerStatement {
9059            name,
9060            if_not_exists,
9061            server_type,
9062            version,
9063            foreign_data_wrapper,
9064            options,
9065        } = self;
9066
9067        write!(
9068            f,
9069            "CREATE SERVER {if_not_exists}{name} ",
9070            if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
9071        )?;
9072
9073        if let Some(st) = server_type {
9074            write!(f, "TYPE {st} ")?;
9075        }
9076
9077        if let Some(v) = version {
9078            write!(f, "VERSION {v} ")?;
9079        }
9080
9081        write!(f, "FOREIGN DATA WRAPPER {foreign_data_wrapper}")?;
9082
9083        if let Some(o) = options {
9084            write!(f, " OPTIONS ({o})", o = display_comma_separated(o))?;
9085        }
9086
9087        Ok(())
9088    }
9089}
9090
9091/// A key/value option for `CREATE SERVER`.
9092#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9093#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9094#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9095pub struct CreateServerOption {
9096    /// Option key identifier.
9097    pub key: Ident,
9098    /// Option value identifier.
9099    pub value: Ident,
9100}
9101
9102impl fmt::Display for CreateServerOption {
9103    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9104        write!(f, "{} {}", self.key, self.value)
9105    }
9106}
9107
9108#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9109#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9110#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9111/// Options supported by DuckDB for `ATTACH DATABASE`.
9112pub enum AttachDuckDBDatabaseOption {
9113    /// READ_ONLY option, optional boolean value.
9114    ReadOnly(Option<bool>),
9115    /// TYPE option specifying a database type identifier.
9116    Type(Ident),
9117}
9118
9119impl fmt::Display for AttachDuckDBDatabaseOption {
9120    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9121        match self {
9122            AttachDuckDBDatabaseOption::ReadOnly(Some(true)) => write!(f, "READ_ONLY true"),
9123            AttachDuckDBDatabaseOption::ReadOnly(Some(false)) => write!(f, "READ_ONLY false"),
9124            AttachDuckDBDatabaseOption::ReadOnly(None) => write!(f, "READ_ONLY"),
9125            AttachDuckDBDatabaseOption::Type(t) => write!(f, "TYPE {t}"),
9126        }
9127    }
9128}
9129
9130#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9131#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9132#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9133/// Mode for transactions: access mode or isolation level.
9134pub enum TransactionMode {
9135    /// Access mode for a transaction (e.g. `READ ONLY` / `READ WRITE`).
9136    AccessMode(TransactionAccessMode),
9137    /// Isolation level for a transaction (e.g. `SERIALIZABLE`).
9138    IsolationLevel(TransactionIsolationLevel),
9139}
9140
9141impl fmt::Display for TransactionMode {
9142    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9143        use TransactionMode::*;
9144        match self {
9145            AccessMode(access_mode) => write!(f, "{access_mode}"),
9146            IsolationLevel(iso_level) => write!(f, "ISOLATION LEVEL {iso_level}"),
9147        }
9148    }
9149}
9150
9151#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9152#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9153#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9154/// Transaction access mode (READ ONLY / READ WRITE).
9155pub enum TransactionAccessMode {
9156    /// READ ONLY access mode.
9157    ReadOnly,
9158    /// READ WRITE access mode.
9159    ReadWrite,
9160}
9161
9162impl fmt::Display for TransactionAccessMode {
9163    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9164        use TransactionAccessMode::*;
9165        f.write_str(match self {
9166            ReadOnly => "READ ONLY",
9167            ReadWrite => "READ WRITE",
9168        })
9169    }
9170}
9171
9172#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9173#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9174#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9175/// Transaction isolation levels.
9176pub enum TransactionIsolationLevel {
9177    /// READ UNCOMMITTED isolation level.
9178    ReadUncommitted,
9179    /// READ COMMITTED isolation level.
9180    ReadCommitted,
9181    /// REPEATABLE READ isolation level.
9182    RepeatableRead,
9183    /// SERIALIZABLE isolation level.
9184    Serializable,
9185    /// SNAPSHOT isolation level.
9186    Snapshot,
9187}
9188
9189impl fmt::Display for TransactionIsolationLevel {
9190    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9191        use TransactionIsolationLevel::*;
9192        f.write_str(match self {
9193            ReadUncommitted => "READ UNCOMMITTED",
9194            ReadCommitted => "READ COMMITTED",
9195            RepeatableRead => "REPEATABLE READ",
9196            Serializable => "SERIALIZABLE",
9197            Snapshot => "SNAPSHOT",
9198        })
9199    }
9200}
9201
9202/// Modifier for the transaction in the `BEGIN` syntax
9203///
9204/// SQLite: <https://sqlite.org/lang_transaction.html>
9205/// MS-SQL: <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/try-catch-transact-sql>
9206#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9207#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9208#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9209pub enum TransactionModifier {
9210    /// DEFERRED transaction modifier.
9211    Deferred,
9212    /// IMMEDIATE transaction modifier.
9213    Immediate,
9214    /// EXCLUSIVE transaction modifier.
9215    Exclusive,
9216    /// TRY block modifier (MS-SQL style TRY/CATCH).
9217    Try,
9218    /// CATCH block modifier (MS-SQL style TRY/CATCH).
9219    Catch,
9220}
9221
9222impl fmt::Display for TransactionModifier {
9223    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9224        use TransactionModifier::*;
9225        f.write_str(match self {
9226            Deferred => "DEFERRED",
9227            Immediate => "IMMEDIATE",
9228            Exclusive => "EXCLUSIVE",
9229            Try => "TRY",
9230            Catch => "CATCH",
9231        })
9232    }
9233}
9234
9235#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9236#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9237#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9238/// Filter forms usable in SHOW statements.
9239pub enum ShowStatementFilter {
9240    /// Filter using LIKE pattern.
9241    Like(String),
9242    /// Filter using ILIKE pattern.
9243    ILike(String),
9244    /// Filter using a WHERE expression.
9245    Where(Expr),
9246    /// Filter provided without a keyword (raw string).
9247    NoKeyword(String),
9248}
9249
9250impl fmt::Display for ShowStatementFilter {
9251    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9252        use ShowStatementFilter::*;
9253        match self {
9254            Like(pattern) => write!(f, "LIKE '{}'", value::escape_single_quote_string(pattern)),
9255            ILike(pattern) => write!(f, "ILIKE {}", value::escape_single_quote_string(pattern)),
9256            Where(expr) => write!(f, "WHERE {expr}"),
9257            NoKeyword(pattern) => write!(f, "'{}'", value::escape_single_quote_string(pattern)),
9258        }
9259    }
9260}
9261
9262#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9263#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9264#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9265/// Clause types used with SHOW ... IN/FROM.
9266pub enum ShowStatementInClause {
9267    /// Use the `IN` clause.
9268    IN,
9269    /// Use the `FROM` clause.
9270    FROM,
9271}
9272
9273impl fmt::Display for ShowStatementInClause {
9274    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9275        use ShowStatementInClause::*;
9276        match self {
9277            FROM => write!(f, "FROM"),
9278            IN => write!(f, "IN"),
9279        }
9280    }
9281}
9282
9283/// Sqlite specific syntax
9284///
9285/// See [Sqlite documentation](https://sqlite.org/lang_conflict.html)
9286/// for more details.
9287#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9288#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9289#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9290pub enum SqliteOnConflict {
9291    /// Use ROLLBACK on conflict.
9292    Rollback,
9293    /// Use ABORT on conflict.
9294    Abort,
9295    /// Use FAIL on conflict.
9296    Fail,
9297    /// Use IGNORE on conflict.
9298    Ignore,
9299    /// Use REPLACE on conflict.
9300    Replace,
9301}
9302
9303impl fmt::Display for SqliteOnConflict {
9304    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9305        use SqliteOnConflict::*;
9306        match self {
9307            Rollback => write!(f, "OR ROLLBACK"),
9308            Abort => write!(f, "OR ABORT"),
9309            Fail => write!(f, "OR FAIL"),
9310            Ignore => write!(f, "OR IGNORE"),
9311            Replace => write!(f, "OR REPLACE"),
9312        }
9313    }
9314}
9315
9316/// Mysql specific syntax
9317///
9318/// See [Mysql documentation](https://dev.mysql.com/doc/refman/8.0/en/replace.html)
9319/// See [Mysql documentation](https://dev.mysql.com/doc/refman/8.0/en/insert.html)
9320/// for more details.
9321#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9322#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9323#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9324pub enum MysqlInsertPriority {
9325    /// LOW_PRIORITY modifier for INSERT/REPLACE.
9326    LowPriority,
9327    /// DELAYED modifier for INSERT/REPLACE.
9328    Delayed,
9329    /// HIGH_PRIORITY modifier for INSERT/REPLACE.
9330    HighPriority,
9331}
9332
9333impl fmt::Display for crate::ast::MysqlInsertPriority {
9334    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9335        use MysqlInsertPriority::*;
9336        match self {
9337            LowPriority => write!(f, "LOW_PRIORITY"),
9338            Delayed => write!(f, "DELAYED"),
9339            HighPriority => write!(f, "HIGH_PRIORITY"),
9340        }
9341    }
9342}
9343
9344#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9345#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9346#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9347/// Source for the `COPY` command: a table or a query.
9348pub enum CopySource {
9349    /// Copy from a table with optional column list.
9350    Table {
9351        /// The name of the table to copy from.
9352        table_name: ObjectName,
9353        /// A list of column names to copy. Empty list means that all columns
9354        /// are copied.
9355        columns: Vec<Ident>,
9356    },
9357    /// Copy from the results of a query.
9358    Query(Box<Query>),
9359}
9360
9361#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9362#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9363#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9364/// Target for the `COPY` command: STDIN, STDOUT, a file, or a program.
9365pub enum CopyTarget {
9366    /// Use standard input as the source.
9367    Stdin,
9368    /// Use standard output as the target.
9369    Stdout,
9370    /// Read from or write to a file.
9371    File {
9372        /// The path name of the input or output file.
9373        filename: String,
9374    },
9375    /// Use a program as the source or target (shell command).
9376    Program {
9377        /// A command to execute
9378        command: String,
9379    },
9380}
9381
9382impl fmt::Display for CopyTarget {
9383    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9384        use CopyTarget::*;
9385        match self {
9386            Stdin => write!(f, "STDIN"),
9387            Stdout => write!(f, "STDOUT"),
9388            File { filename } => write!(f, "'{}'", value::escape_single_quote_string(filename)),
9389            Program { command } => write!(
9390                f,
9391                "PROGRAM '{}'",
9392                value::escape_single_quote_string(command)
9393            ),
9394        }
9395    }
9396}
9397
9398#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9399#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9400#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9401/// Action to take `ON COMMIT` for temporary tables.
9402pub enum OnCommit {
9403    /// Delete rows on commit.
9404    DeleteRows,
9405    /// Preserve rows on commit.
9406    PreserveRows,
9407    /// Drop the table on commit.
9408    Drop,
9409}
9410
9411/// An option in `COPY` statement.
9412///
9413/// <https://www.postgresql.org/docs/14/sql-copy.html>
9414#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9415#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9416#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9417pub enum CopyOption {
9418    /// FORMAT format_name
9419    Format(Ident),
9420    /// FREEZE \[ boolean \]
9421    Freeze(bool),
9422    /// DELIMITER 'delimiter_character'
9423    Delimiter(char),
9424    /// NULL 'null_string'
9425    Null(String),
9426    /// HEADER \[ boolean \]
9427    Header(bool),
9428    /// QUOTE 'quote_character'
9429    Quote(char),
9430    /// ESCAPE 'escape_character'
9431    Escape(char),
9432    /// FORCE_QUOTE { ( column_name [, ...] ) | * }
9433    ForceQuote(Vec<Ident>),
9434    /// FORCE_NOT_NULL ( column_name [, ...] )
9435    ForceNotNull(Vec<Ident>),
9436    /// FORCE_NULL ( column_name [, ...] )
9437    ForceNull(Vec<Ident>),
9438    /// ENCODING 'encoding_name'
9439    Encoding(String),
9440}
9441
9442impl fmt::Display for CopyOption {
9443    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9444        use CopyOption::*;
9445        match self {
9446            Format(name) => write!(f, "FORMAT {name}"),
9447            Freeze(true) => write!(f, "FREEZE"),
9448            Freeze(false) => write!(f, "FREEZE FALSE"),
9449            Delimiter(char) => write!(f, "DELIMITER '{char}'"),
9450            Null(string) => write!(f, "NULL '{}'", value::escape_single_quote_string(string)),
9451            Header(true) => write!(f, "HEADER"),
9452            Header(false) => write!(f, "HEADER FALSE"),
9453            Quote(char) => write!(f, "QUOTE '{char}'"),
9454            Escape(char) => write!(f, "ESCAPE '{char}'"),
9455            ForceQuote(columns) => write!(f, "FORCE_QUOTE ({})", display_comma_separated(columns)),
9456            ForceNotNull(columns) => {
9457                write!(f, "FORCE_NOT_NULL ({})", display_comma_separated(columns))
9458            }
9459            ForceNull(columns) => write!(f, "FORCE_NULL ({})", display_comma_separated(columns)),
9460            Encoding(name) => write!(f, "ENCODING '{}'", value::escape_single_quote_string(name)),
9461        }
9462    }
9463}
9464
9465/// An option in `COPY` statement before PostgreSQL version 9.0.
9466///
9467/// [PostgreSQL](https://www.postgresql.org/docs/8.4/sql-copy.html)
9468/// [Redshift](https://docs.aws.amazon.com/redshift/latest/dg/r_COPY-alphabetical-parm-list.html)
9469#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9470#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9471#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9472pub enum CopyLegacyOption {
9473    /// ACCEPTANYDATE
9474    AcceptAnyDate,
9475    /// ACCEPTINVCHARS
9476    AcceptInvChars(Option<String>),
9477    /// ADDQUOTES
9478    AddQuotes,
9479    /// ALLOWOVERWRITE
9480    AllowOverwrite,
9481    /// BINARY
9482    Binary,
9483    /// BLANKSASNULL
9484    BlankAsNull,
9485    /// BZIP2
9486    Bzip2,
9487    /// CLEANPATH
9488    CleanPath,
9489    /// COMPUPDATE [ PRESET | { ON | TRUE } | { OFF | FALSE } ]
9490    CompUpdate {
9491        /// Whether the COMPUPDATE PRESET option was used.
9492        preset: bool,
9493        /// Optional enabled flag for COMPUPDATE.
9494        enabled: Option<bool>,
9495    },
9496    /// CSV ...
9497    Csv(Vec<CopyLegacyCsvOption>),
9498    /// DATEFORMAT \[ AS \] {'dateformat_string' | 'auto' }
9499    DateFormat(Option<String>),
9500    /// DELIMITER \[ AS \] 'delimiter_character'
9501    Delimiter(char),
9502    /// EMPTYASNULL
9503    EmptyAsNull,
9504    /// `ENCRYPTED \[ AUTO \]`
9505    Encrypted {
9506        /// Whether `AUTO` was specified for encryption.
9507        auto: bool,
9508    },
9509    /// ESCAPE
9510    Escape,
9511    /// EXTENSION 'extension-name'
9512    Extension(String),
9513    /// FIXEDWIDTH \[ AS \] 'fixedwidth-spec'
9514    FixedWidth(String),
9515    /// GZIP
9516    Gzip,
9517    /// HEADER
9518    Header,
9519    /// IAM_ROLE { DEFAULT | 'arn:aws:iam::123456789:role/role1' }
9520    IamRole(IamRoleKind),
9521    /// IGNOREHEADER \[ AS \] number_rows
9522    IgnoreHeader(u64),
9523    /// JSON \[ AS \] 'json_option'
9524    Json(Option<String>),
9525    /// MANIFEST \[ VERBOSE \]
9526    Manifest {
9527        /// Whether the MANIFEST is verbose.
9528        verbose: bool,
9529    },
9530    /// MAXFILESIZE \[ AS \] max-size \[ MB | GB \]
9531    MaxFileSize(FileSize),
9532    /// `NULL \[ AS \] 'null_string'`
9533    Null(String),
9534    /// `PARALLEL [ { ON | TRUE } | { OFF | FALSE } ]`
9535    Parallel(Option<bool>),
9536    /// PARQUET
9537    Parquet,
9538    /// PARTITION BY ( column_name [, ... ] ) \[ INCLUDE \]
9539    PartitionBy(UnloadPartitionBy),
9540    /// REGION \[ AS \] 'aws-region' }
9541    Region(String),
9542    /// REMOVEQUOTES
9543    RemoveQuotes,
9544    /// ROWGROUPSIZE \[ AS \] size \[ MB | GB \]
9545    RowGroupSize(FileSize),
9546    /// STATUPDATE [ { ON | TRUE } | { OFF | FALSE } ]
9547    StatUpdate(Option<bool>),
9548    /// TIMEFORMAT \[ AS \] {'timeformat_string' | 'auto' | 'epochsecs' | 'epochmillisecs' }
9549    TimeFormat(Option<String>),
9550    /// TRUNCATECOLUMNS
9551    TruncateColumns,
9552    /// ZSTD
9553    Zstd,
9554    /// Redshift `CREDENTIALS 'auth-args'`
9555    /// <https://docs.aws.amazon.com/redshift/latest/dg/copy-parameters-authorization.html>
9556    Credentials(String),
9557}
9558
9559impl fmt::Display for CopyLegacyOption {
9560    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9561        use CopyLegacyOption::*;
9562        match self {
9563            AcceptAnyDate => write!(f, "ACCEPTANYDATE"),
9564            AcceptInvChars(ch) => {
9565                write!(f, "ACCEPTINVCHARS")?;
9566                if let Some(ch) = ch {
9567                    write!(f, " '{}'", value::escape_single_quote_string(ch))?;
9568                }
9569                Ok(())
9570            }
9571            AddQuotes => write!(f, "ADDQUOTES"),
9572            AllowOverwrite => write!(f, "ALLOWOVERWRITE"),
9573            Binary => write!(f, "BINARY"),
9574            BlankAsNull => write!(f, "BLANKSASNULL"),
9575            Bzip2 => write!(f, "BZIP2"),
9576            CleanPath => write!(f, "CLEANPATH"),
9577            CompUpdate { preset, enabled } => {
9578                write!(f, "COMPUPDATE")?;
9579                if *preset {
9580                    write!(f, " PRESET")?;
9581                } else if let Some(enabled) = enabled {
9582                    write!(
9583                        f,
9584                        "{}",
9585                        match enabled {
9586                            true => " TRUE",
9587                            false => " FALSE",
9588                        }
9589                    )?;
9590                }
9591                Ok(())
9592            }
9593            Csv(opts) => {
9594                write!(f, "CSV")?;
9595                if !opts.is_empty() {
9596                    write!(f, " {}", display_separated(opts, " "))?;
9597                }
9598                Ok(())
9599            }
9600            DateFormat(fmt) => {
9601                write!(f, "DATEFORMAT")?;
9602                if let Some(fmt) = fmt {
9603                    write!(f, " '{}'", value::escape_single_quote_string(fmt))?;
9604                }
9605                Ok(())
9606            }
9607            Delimiter(char) => write!(f, "DELIMITER '{char}'"),
9608            EmptyAsNull => write!(f, "EMPTYASNULL"),
9609            Encrypted { auto } => write!(f, "ENCRYPTED{}", if *auto { " AUTO" } else { "" }),
9610            Escape => write!(f, "ESCAPE"),
9611            Extension(ext) => write!(f, "EXTENSION '{}'", value::escape_single_quote_string(ext)),
9612            FixedWidth(spec) => write!(
9613                f,
9614                "FIXEDWIDTH '{}'",
9615                value::escape_single_quote_string(spec)
9616            ),
9617            Gzip => write!(f, "GZIP"),
9618            Header => write!(f, "HEADER"),
9619            IamRole(role) => write!(f, "IAM_ROLE {role}"),
9620            IgnoreHeader(num_rows) => write!(f, "IGNOREHEADER {num_rows}"),
9621            Json(opt) => {
9622                write!(f, "JSON")?;
9623                if let Some(opt) = opt {
9624                    write!(f, " AS '{}'", value::escape_single_quote_string(opt))?;
9625                }
9626                Ok(())
9627            }
9628            Manifest { verbose } => write!(f, "MANIFEST{}", if *verbose { " VERBOSE" } else { "" }),
9629            MaxFileSize(file_size) => write!(f, "MAXFILESIZE {file_size}"),
9630            Null(string) => write!(f, "NULL '{}'", value::escape_single_quote_string(string)),
9631            Parallel(enabled) => {
9632                write!(
9633                    f,
9634                    "PARALLEL{}",
9635                    match enabled {
9636                        Some(true) => " TRUE",
9637                        Some(false) => " FALSE",
9638                        _ => "",
9639                    }
9640                )
9641            }
9642            Parquet => write!(f, "PARQUET"),
9643            PartitionBy(p) => write!(f, "{p}"),
9644            Region(region) => write!(f, "REGION '{}'", value::escape_single_quote_string(region)),
9645            RemoveQuotes => write!(f, "REMOVEQUOTES"),
9646            RowGroupSize(file_size) => write!(f, "ROWGROUPSIZE {file_size}"),
9647            StatUpdate(enabled) => {
9648                write!(
9649                    f,
9650                    "STATUPDATE{}",
9651                    match enabled {
9652                        Some(true) => " TRUE",
9653                        Some(false) => " FALSE",
9654                        _ => "",
9655                    }
9656                )
9657            }
9658            TimeFormat(fmt) => {
9659                write!(f, "TIMEFORMAT")?;
9660                if let Some(fmt) = fmt {
9661                    write!(f, " '{}'", value::escape_single_quote_string(fmt))?;
9662                }
9663                Ok(())
9664            }
9665            TruncateColumns => write!(f, "TRUNCATECOLUMNS"),
9666            Zstd => write!(f, "ZSTD"),
9667            Credentials(s) => write!(f, "CREDENTIALS '{}'", value::escape_single_quote_string(s)),
9668        }
9669    }
9670}
9671
9672/// ```sql
9673/// SIZE \[ MB | GB \]
9674/// ```
9675#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9676#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9677#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9678pub struct FileSize {
9679    /// Numeric size value.
9680    pub size: ValueWithSpan,
9681    /// Optional unit for the size (MB or GB).
9682    pub unit: Option<FileSizeUnit>,
9683}
9684
9685impl fmt::Display for FileSize {
9686    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9687        write!(f, "{}", self.size)?;
9688        if let Some(unit) = &self.unit {
9689            write!(f, " {unit}")?;
9690        }
9691        Ok(())
9692    }
9693}
9694
9695/// Units for `FileSize` (MB or GB).
9696#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9697#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9698#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9699pub enum FileSizeUnit {
9700    /// Megabytes.
9701    MB,
9702    /// Gigabytes.
9703    GB,
9704}
9705
9706impl fmt::Display for FileSizeUnit {
9707    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9708        match self {
9709            FileSizeUnit::MB => write!(f, "MB"),
9710            FileSizeUnit::GB => write!(f, "GB"),
9711        }
9712    }
9713}
9714
9715/// Specifies the partition keys for the unload operation
9716///
9717/// ```sql
9718/// PARTITION BY ( column_name [, ... ] ) [ INCLUDE ]
9719/// ```
9720#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9721#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9722#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9723pub struct UnloadPartitionBy {
9724    /// Columns used to partition the unload output.
9725    pub columns: Vec<Ident>,
9726    /// Whether to include the partition in the output.
9727    pub include: bool,
9728}
9729
9730impl fmt::Display for UnloadPartitionBy {
9731    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9732        write!(
9733            f,
9734            "PARTITION BY ({}){}",
9735            display_comma_separated(&self.columns),
9736            if self.include { " INCLUDE" } else { "" }
9737        )
9738    }
9739}
9740
9741/// An `IAM_ROLE` option in the AWS ecosystem
9742///
9743/// [Redshift COPY](https://docs.aws.amazon.com/redshift/latest/dg/copy-parameters-authorization.html#copy-iam-role)
9744#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9745#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9746#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9747pub enum IamRoleKind {
9748    /// Default role
9749    Default,
9750    /// Specific role ARN, for example: `arn:aws:iam::123456789:role/role1`
9751    Arn(String),
9752}
9753
9754impl fmt::Display for IamRoleKind {
9755    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9756        match self {
9757            IamRoleKind::Default => write!(f, "DEFAULT"),
9758            IamRoleKind::Arn(arn) => write!(f, "'{arn}'"),
9759        }
9760    }
9761}
9762
9763/// A `CSV` option in `COPY` statement before PostgreSQL version 9.0.
9764///
9765/// <https://www.postgresql.org/docs/8.4/sql-copy.html>
9766#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9767#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9768#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9769pub enum CopyLegacyCsvOption {
9770    /// HEADER
9771    Header,
9772    /// QUOTE \[ AS \] 'quote_character'
9773    Quote(char),
9774    /// ESCAPE \[ AS \] 'escape_character'
9775    Escape(char),
9776    /// FORCE QUOTE { column_name [, ...] | * }
9777    ForceQuote(Vec<Ident>),
9778    /// FORCE NOT NULL column_name [, ...]
9779    ForceNotNull(Vec<Ident>),
9780}
9781
9782impl fmt::Display for CopyLegacyCsvOption {
9783    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9784        use CopyLegacyCsvOption::*;
9785        match self {
9786            Header => write!(f, "HEADER"),
9787            Quote(char) => write!(f, "QUOTE '{char}'"),
9788            Escape(char) => write!(f, "ESCAPE '{char}'"),
9789            ForceQuote(columns) => write!(f, "FORCE QUOTE {}", display_comma_separated(columns)),
9790            ForceNotNull(columns) => {
9791                write!(f, "FORCE NOT NULL {}", display_comma_separated(columns))
9792            }
9793        }
9794    }
9795}
9796
9797/// Objects that can be discarded with `DISCARD`.
9798#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9799#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9800#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9801pub enum DiscardObject {
9802    /// Discard all session state.
9803    ALL,
9804    /// Discard cached plans.
9805    PLANS,
9806    /// Discard sequence values.
9807    SEQUENCES,
9808    /// Discard temporary objects.
9809    TEMP,
9810}
9811
9812impl fmt::Display for DiscardObject {
9813    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9814        match self {
9815            DiscardObject::ALL => f.write_str("ALL"),
9816            DiscardObject::PLANS => f.write_str("PLANS"),
9817            DiscardObject::SEQUENCES => f.write_str("SEQUENCES"),
9818            DiscardObject::TEMP => f.write_str("TEMP"),
9819        }
9820    }
9821}
9822
9823/// Types of flush operations supported by `FLUSH`.
9824#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9825#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9826#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9827pub enum FlushType {
9828    /// Flush binary logs.
9829    BinaryLogs,
9830    /// Flush engine logs.
9831    EngineLogs,
9832    /// Flush error logs.
9833    ErrorLogs,
9834    /// Flush general logs.
9835    GeneralLogs,
9836    /// Flush hosts information.
9837    Hosts,
9838    /// Flush logs.
9839    Logs,
9840    /// Flush privileges.
9841    Privileges,
9842    /// Flush optimizer costs.
9843    OptimizerCosts,
9844    /// Flush relay logs.
9845    RelayLogs,
9846    /// Flush slow logs.
9847    SlowLogs,
9848    /// Flush status.
9849    Status,
9850    /// Flush user resources.
9851    UserResources,
9852    /// Flush table data.
9853    Tables,
9854}
9855
9856impl fmt::Display for FlushType {
9857    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9858        match self {
9859            FlushType::BinaryLogs => f.write_str("BINARY LOGS"),
9860            FlushType::EngineLogs => f.write_str("ENGINE LOGS"),
9861            FlushType::ErrorLogs => f.write_str("ERROR LOGS"),
9862            FlushType::GeneralLogs => f.write_str("GENERAL LOGS"),
9863            FlushType::Hosts => f.write_str("HOSTS"),
9864            FlushType::Logs => f.write_str("LOGS"),
9865            FlushType::Privileges => f.write_str("PRIVILEGES"),
9866            FlushType::OptimizerCosts => f.write_str("OPTIMIZER_COSTS"),
9867            FlushType::RelayLogs => f.write_str("RELAY LOGS"),
9868            FlushType::SlowLogs => f.write_str("SLOW LOGS"),
9869            FlushType::Status => f.write_str("STATUS"),
9870            FlushType::UserResources => f.write_str("USER_RESOURCES"),
9871            FlushType::Tables => f.write_str("TABLES"),
9872        }
9873    }
9874}
9875
9876/// Location modifier for flush commands.
9877#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9878#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9879#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9880pub enum FlushLocation {
9881    /// Do not write changes to the binary log.
9882    NoWriteToBinlog,
9883    /// Apply flush locally.
9884    Local,
9885}
9886
9887impl fmt::Display for FlushLocation {
9888    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9889        match self {
9890            FlushLocation::NoWriteToBinlog => f.write_str("NO_WRITE_TO_BINLOG"),
9891            FlushLocation::Local => f.write_str("LOCAL"),
9892        }
9893    }
9894}
9895
9896/// Optional context modifier for statements that can be or `LOCAL`, `GLOBAL`, or `SESSION`.
9897#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9898#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9899#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9900pub enum ContextModifier {
9901    /// `LOCAL` identifier, usually related to transactional states.
9902    Local,
9903    /// `SESSION` identifier
9904    Session,
9905    /// `GLOBAL` identifier
9906    Global,
9907}
9908
9909impl fmt::Display for ContextModifier {
9910    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9911        match self {
9912            Self::Local => {
9913                write!(f, "LOCAL ")
9914            }
9915            Self::Session => {
9916                write!(f, "SESSION ")
9917            }
9918            Self::Global => {
9919                write!(f, "GLOBAL ")
9920            }
9921        }
9922    }
9923}
9924
9925/// Function describe in DROP FUNCTION.
9926#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9927#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9928pub enum DropFunctionOption {
9929    /// `RESTRICT` option for DROP FUNCTION.
9930    Restrict,
9931    /// `CASCADE` option for DROP FUNCTION.
9932    Cascade,
9933}
9934
9935impl fmt::Display for DropFunctionOption {
9936    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9937        match self {
9938            DropFunctionOption::Restrict => write!(f, "RESTRICT "),
9939            DropFunctionOption::Cascade => write!(f, "CASCADE  "),
9940        }
9941    }
9942}
9943
9944/// Generic function description for DROP FUNCTION and CREATE TRIGGER.
9945#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9946#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9947#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9948pub struct FunctionDesc {
9949    /// The function name.
9950    pub name: ObjectName,
9951    /// Optional list of function arguments.
9952    pub args: Option<Vec<OperateFunctionArg>>,
9953}
9954
9955impl fmt::Display for FunctionDesc {
9956    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9957        write!(f, "{}", self.name)?;
9958        if let Some(args) = &self.args {
9959            write!(f, "({})", display_comma_separated(args))?;
9960        }
9961        Ok(())
9962    }
9963}
9964
9965/// Function argument in CREATE OR DROP FUNCTION.
9966#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9967#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9968#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9969pub struct OperateFunctionArg {
9970    /// Optional argument mode (`IN`, `OUT`, `INOUT`).
9971    pub mode: Option<ArgMode>,
9972    /// Optional argument identifier/name.
9973    pub name: Option<Ident>,
9974    /// The data type of the argument.
9975    pub data_type: DataType,
9976    /// Optional default expression for the argument.
9977    pub default_expr: Option<Expr>,
9978}
9979
9980impl OperateFunctionArg {
9981    /// Returns an unnamed argument.
9982    pub fn unnamed(data_type: DataType) -> Self {
9983        Self {
9984            mode: None,
9985            name: None,
9986            data_type,
9987            default_expr: None,
9988        }
9989    }
9990
9991    /// Returns an argument with name.
9992    pub fn with_name(name: &str, data_type: DataType) -> Self {
9993        Self {
9994            mode: None,
9995            name: Some(name.into()),
9996            data_type,
9997            default_expr: None,
9998        }
9999    }
10000}
10001
10002impl fmt::Display for OperateFunctionArg {
10003    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10004        if let Some(mode) = &self.mode {
10005            write!(f, "{mode} ")?;
10006        }
10007        if let Some(name) = &self.name {
10008            write!(f, "{name} ")?;
10009        }
10010        write!(f, "{}", self.data_type)?;
10011        if let Some(default_expr) = &self.default_expr {
10012            write!(f, " = {default_expr}")?;
10013        }
10014        Ok(())
10015    }
10016}
10017
10018/// The mode of an argument in CREATE FUNCTION.
10019#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10020#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10021#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10022pub enum ArgMode {
10023    /// `IN` mode.
10024    In,
10025    /// `OUT` mode.
10026    Out,
10027    /// `INOUT` mode.
10028    InOut,
10029    /// `VARIADIC` mode.
10030    Variadic,
10031}
10032
10033impl fmt::Display for ArgMode {
10034    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10035        match self {
10036            ArgMode::In => write!(f, "IN"),
10037            ArgMode::Out => write!(f, "OUT"),
10038            ArgMode::InOut => write!(f, "INOUT"),
10039            ArgMode::Variadic => write!(f, "VARIADIC"),
10040        }
10041    }
10042}
10043
10044/// These attributes inform the query optimizer about the behavior of the function.
10045#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10046#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10047#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10048pub enum FunctionBehavior {
10049    /// Function is immutable.
10050    Immutable,
10051    /// Function is stable.
10052    Stable,
10053    /// Function is volatile.
10054    Volatile,
10055}
10056
10057impl fmt::Display for FunctionBehavior {
10058    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10059        match self {
10060            FunctionBehavior::Immutable => write!(f, "IMMUTABLE"),
10061            FunctionBehavior::Stable => write!(f, "STABLE"),
10062            FunctionBehavior::Volatile => write!(f, "VOLATILE"),
10063        }
10064    }
10065}
10066
10067/// Security attribute for functions: SECURITY DEFINER or SECURITY INVOKER.
10068///
10069/// [PostgreSQL](https://www.postgresql.org/docs/current/sql-createfunction.html)
10070#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10071#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10072#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10073pub enum FunctionSecurity {
10074    /// Execute the function with the privileges of the user who defined it.
10075    Definer,
10076    /// Execute the function with the privileges of the user who invokes it.
10077    Invoker,
10078}
10079
10080impl fmt::Display for FunctionSecurity {
10081    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10082        match self {
10083            FunctionSecurity::Definer => write!(f, "SECURITY DEFINER"),
10084            FunctionSecurity::Invoker => write!(f, "SECURITY INVOKER"),
10085        }
10086    }
10087}
10088
10089/// Value for a SET configuration parameter in a CREATE FUNCTION statement.
10090///
10091/// [PostgreSQL](https://www.postgresql.org/docs/current/sql-createfunction.html)
10092#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10093#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10094#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10095pub enum FunctionSetValue {
10096    /// SET param = DEFAULT / SET param TO DEFAULT
10097    Default,
10098    /// SET param = value1, value2, ...
10099    Values(Vec<Expr>),
10100    /// SET param FROM CURRENT
10101    FromCurrent,
10102}
10103
10104/// A SET configuration_parameter clause in a CREATE FUNCTION statement.
10105///
10106/// [PostgreSQL](https://www.postgresql.org/docs/current/sql-createfunction.html)
10107#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10108#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10109#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10110pub struct FunctionDefinitionSetParam {
10111    /// The name of the configuration parameter.
10112    pub name: ObjectName,
10113    /// The value to set for the parameter.
10114    pub value: FunctionSetValue,
10115}
10116
10117impl fmt::Display for FunctionDefinitionSetParam {
10118    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10119        write!(f, "SET {} ", self.name)?;
10120        match &self.value {
10121            FunctionSetValue::Default => write!(f, "= DEFAULT"),
10122            FunctionSetValue::Values(values) => {
10123                write!(f, "= {}", display_comma_separated(values))
10124            }
10125            FunctionSetValue::FromCurrent => write!(f, "FROM CURRENT"),
10126        }
10127    }
10128}
10129
10130/// These attributes describe the behavior of the function when called with a null argument.
10131#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10132#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10133#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10134pub enum FunctionCalledOnNull {
10135    /// Function is called even when inputs are null.
10136    CalledOnNullInput,
10137    /// Function returns null when any input is null.
10138    ReturnsNullOnNullInput,
10139    /// Function is strict about null inputs.
10140    Strict,
10141}
10142
10143impl fmt::Display for FunctionCalledOnNull {
10144    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10145        match self {
10146            FunctionCalledOnNull::CalledOnNullInput => write!(f, "CALLED ON NULL INPUT"),
10147            FunctionCalledOnNull::ReturnsNullOnNullInput => write!(f, "RETURNS NULL ON NULL INPUT"),
10148            FunctionCalledOnNull::Strict => write!(f, "STRICT"),
10149        }
10150    }
10151}
10152
10153/// If it is safe for PostgreSQL to call the function from multiple threads at once
10154#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10155#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10156#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10157pub enum FunctionParallel {
10158    /// The function is not safe to run in parallel.
10159    Unsafe,
10160    /// The function is restricted for parallel execution.
10161    Restricted,
10162    /// The function is safe to run in parallel.
10163    Safe,
10164}
10165
10166impl fmt::Display for FunctionParallel {
10167    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10168        match self {
10169            FunctionParallel::Unsafe => write!(f, "PARALLEL UNSAFE"),
10170            FunctionParallel::Restricted => write!(f, "PARALLEL RESTRICTED"),
10171            FunctionParallel::Safe => write!(f, "PARALLEL SAFE"),
10172        }
10173    }
10174}
10175
10176/// [BigQuery] Determinism specifier used in a UDF definition.
10177///
10178/// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#syntax_11
10179#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10180#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10181#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10182pub enum FunctionDeterminismSpecifier {
10183    /// Function is deterministic.
10184    Deterministic,
10185    /// Function is not deterministic.
10186    NotDeterministic,
10187}
10188
10189impl fmt::Display for FunctionDeterminismSpecifier {
10190    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10191        match self {
10192            FunctionDeterminismSpecifier::Deterministic => {
10193                write!(f, "DETERMINISTIC")
10194            }
10195            FunctionDeterminismSpecifier::NotDeterministic => {
10196                write!(f, "NOT DETERMINISTIC")
10197            }
10198        }
10199    }
10200}
10201
10202/// Represent the expression body of a `CREATE FUNCTION` statement as well as
10203/// where within the statement, the body shows up.
10204///
10205/// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#syntax_11
10206/// [PostgreSQL]: https://www.postgresql.org/docs/15/sql-createfunction.html
10207/// [MsSql]: https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql
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 enum CreateFunctionBody {
10212    /// A function body expression using the 'AS' keyword and shows up
10213    /// before any `OPTIONS` clause.
10214    ///
10215    /// Example:
10216    /// ```sql
10217    /// CREATE FUNCTION myfunc(x FLOAT64, y FLOAT64) RETURNS FLOAT64
10218    /// AS (x * y)
10219    /// OPTIONS(description="desc");
10220    /// ```
10221    ///
10222    /// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#syntax_11
10223    /// [PostgreSQL]: https://www.postgresql.org/docs/current/sql-createfunction.html
10224    AsBeforeOptions {
10225        /// The primary expression.
10226        body: Expr,
10227        /// Link symbol if the primary expression contains the name of shared library file.
10228        ///
10229        /// Example:
10230        /// ```sql
10231        /// CREATE FUNCTION cas_in(input cstring) RETURNS cas
10232        /// AS 'MODULE_PATHNAME', 'cas_in_wrapper'
10233        /// ```
10234        /// [PostgreSQL]: https://www.postgresql.org/docs/current/sql-createfunction.html
10235        link_symbol: Option<Expr>,
10236    },
10237    /// A function body expression using the 'AS' keyword and shows up
10238    /// after any `OPTIONS` clause.
10239    ///
10240    /// Example:
10241    /// ```sql
10242    /// CREATE FUNCTION myfunc(x FLOAT64, y FLOAT64) RETURNS FLOAT64
10243    /// OPTIONS(description="desc")
10244    /// AS (x * y);
10245    /// ```
10246    ///
10247    /// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#syntax_11
10248    AsAfterOptions(Expr),
10249    /// Function body with statements before the `RETURN` keyword.
10250    ///
10251    /// Example:
10252    /// ```sql
10253    /// CREATE FUNCTION my_scalar_udf(a INT, b INT)
10254    /// RETURNS INT
10255    /// AS
10256    /// BEGIN
10257    ///     DECLARE c INT;
10258    ///     SET c = a + b;
10259    ///     RETURN c;
10260    /// END
10261    /// ```
10262    ///
10263    /// [MsSql]: https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql
10264    AsBeginEnd(BeginEndStatements),
10265    /// Function body expression using the 'RETURN' keyword.
10266    ///
10267    /// Example:
10268    /// ```sql
10269    /// CREATE FUNCTION myfunc(a INTEGER, IN b INTEGER = 1) RETURNS INTEGER
10270    /// LANGUAGE SQL
10271    /// RETURN a + b;
10272    /// ```
10273    ///
10274    /// [PostgreSQL]: https://www.postgresql.org/docs/current/sql-createfunction.html
10275    Return(Expr),
10276
10277    /// Function body expression using the 'AS RETURN' keywords
10278    ///
10279    /// Example:
10280    /// ```sql
10281    /// CREATE FUNCTION myfunc(a INT, b INT)
10282    /// RETURNS TABLE
10283    /// AS RETURN (SELECT a + b AS sum);
10284    /// ```
10285    ///
10286    /// [MsSql]: https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql
10287    AsReturnExpr(Expr),
10288
10289    /// Function body expression using the 'AS RETURN' keywords, with an un-parenthesized SELECT query
10290    ///
10291    /// Example:
10292    /// ```sql
10293    /// CREATE FUNCTION myfunc(a INT, b INT)
10294    /// RETURNS TABLE
10295    /// AS RETURN SELECT a + b AS sum;
10296    /// ```
10297    ///
10298    /// [MsSql]: https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql?view=sql-server-ver16#select_stmt
10299    AsReturnSelect(Select),
10300}
10301
10302#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10303#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10304#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10305/// `USING` clause options for `CREATE FUNCTION` (e.g., JAR, FILE, ARCHIVE).
10306pub enum CreateFunctionUsing {
10307    /// Use a JAR file located at the given URI.
10308    Jar(String),
10309    /// Use a file located at the given URI.
10310    File(String),
10311    /// Use an archive located at the given URI.
10312    Archive(String),
10313}
10314
10315impl fmt::Display for CreateFunctionUsing {
10316    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10317        write!(f, "USING ")?;
10318        match self {
10319            CreateFunctionUsing::Jar(uri) => write!(f, "JAR '{uri}'"),
10320            CreateFunctionUsing::File(uri) => write!(f, "FILE '{uri}'"),
10321            CreateFunctionUsing::Archive(uri) => write!(f, "ARCHIVE '{uri}'"),
10322        }
10323    }
10324}
10325
10326/// `NAME = <EXPR>` arguments for DuckDB macros
10327///
10328/// See [Create Macro - DuckDB](https://duckdb.org/docs/sql/statements/create_macro)
10329/// for more details
10330#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10331#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10332#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10333pub struct MacroArg {
10334    /// The argument name.
10335    pub name: Ident,
10336    /// Optional default expression for the argument.
10337    pub default_expr: Option<Expr>,
10338}
10339
10340impl MacroArg {
10341    /// Returns an argument with name.
10342    pub fn new(name: &str) -> Self {
10343        Self {
10344            name: name.into(),
10345            default_expr: None,
10346        }
10347    }
10348}
10349
10350impl fmt::Display for MacroArg {
10351    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10352        write!(f, "{}", self.name)?;
10353        if let Some(default_expr) = &self.default_expr {
10354            write!(f, " := {default_expr}")?;
10355        }
10356        Ok(())
10357    }
10358}
10359
10360#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10361#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10362#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10363/// Definition for a DuckDB macro: either an expression or a table-producing query.
10364pub enum MacroDefinition {
10365    /// The macro is defined as an expression.
10366    Expr(Expr),
10367    /// The macro is defined as a table (query).
10368    Table(Box<Query>),
10369}
10370
10371impl fmt::Display for MacroDefinition {
10372    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10373        match self {
10374            MacroDefinition::Expr(expr) => write!(f, "{expr}")?,
10375            MacroDefinition::Table(query) => write!(f, "{query}")?,
10376        }
10377        Ok(())
10378    }
10379}
10380
10381/// Schema possible naming variants ([1]).
10382///
10383/// [1]: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#schema-definition
10384#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10385#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10386#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10387pub enum SchemaName {
10388    /// Only schema name specified: `<schema name>`.
10389    Simple(ObjectName),
10390    /// Only authorization identifier specified: `AUTHORIZATION <schema authorization identifier>`.
10391    UnnamedAuthorization(Ident),
10392    /// Both schema name and authorization identifier specified: `<schema name>  AUTHORIZATION <schema authorization identifier>`.
10393    NamedAuthorization(ObjectName, Ident),
10394}
10395
10396impl fmt::Display for SchemaName {
10397    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10398        match self {
10399            SchemaName::Simple(name) => {
10400                write!(f, "{name}")
10401            }
10402            SchemaName::UnnamedAuthorization(authorization) => {
10403                write!(f, "AUTHORIZATION {authorization}")
10404            }
10405            SchemaName::NamedAuthorization(name, authorization) => {
10406                write!(f, "{name} AUTHORIZATION {authorization}")
10407            }
10408        }
10409    }
10410}
10411
10412/// Fulltext search modifiers ([1]).
10413///
10414/// [1]: https://dev.mysql.com/doc/refman/8.0/en/fulltext-search.html#function_match
10415#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10416#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10417#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10418pub enum SearchModifier {
10419    /// `IN NATURAL LANGUAGE MODE`.
10420    InNaturalLanguageMode,
10421    /// `IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION`.
10422    InNaturalLanguageModeWithQueryExpansion,
10423    ///`IN BOOLEAN MODE`.
10424    InBooleanMode,
10425    ///`WITH QUERY EXPANSION`.
10426    WithQueryExpansion,
10427}
10428
10429impl fmt::Display for SearchModifier {
10430    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10431        match self {
10432            Self::InNaturalLanguageMode => {
10433                write!(f, "IN NATURAL LANGUAGE MODE")?;
10434            }
10435            Self::InNaturalLanguageModeWithQueryExpansion => {
10436                write!(f, "IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION")?;
10437            }
10438            Self::InBooleanMode => {
10439                write!(f, "IN BOOLEAN MODE")?;
10440            }
10441            Self::WithQueryExpansion => {
10442                write!(f, "WITH QUERY EXPANSION")?;
10443            }
10444        }
10445
10446        Ok(())
10447    }
10448}
10449
10450/// Represents a `LOCK TABLE` clause with optional alias and lock type.
10451#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10452#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10453#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10454pub struct LockTable {
10455    /// The table identifier to lock.
10456    pub table: Ident,
10457    /// Optional alias for the table.
10458    pub alias: Option<Ident>,
10459    /// The type of lock to apply to the table.
10460    pub lock_type: LockTableType,
10461}
10462
10463impl fmt::Display for LockTable {
10464    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10465        let Self {
10466            table: tbl_name,
10467            alias,
10468            lock_type,
10469        } = self;
10470
10471        write!(f, "{tbl_name} ")?;
10472        if let Some(alias) = alias {
10473            write!(f, "AS {alias} ")?;
10474        }
10475        write!(f, "{lock_type}")?;
10476        Ok(())
10477    }
10478}
10479
10480#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10481#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10482#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10483/// The type of lock used in `LOCK TABLE` statements.
10484pub enum LockTableType {
10485    /// Shared/read lock. If `local` is true, it's a local read lock.
10486    Read {
10487        /// Whether the read lock is local.
10488        local: bool,
10489    },
10490    /// Exclusive/write lock. If `low_priority` is true, the write is low priority.
10491    Write {
10492        /// Whether the write lock is low priority.
10493        low_priority: bool,
10494    },
10495}
10496
10497impl fmt::Display for LockTableType {
10498    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10499        match self {
10500            Self::Read { local } => {
10501                write!(f, "READ")?;
10502                if *local {
10503                    write!(f, " LOCAL")?;
10504                }
10505            }
10506            Self::Write { low_priority } => {
10507                if *low_priority {
10508                    write!(f, "LOW_PRIORITY ")?;
10509                }
10510                write!(f, "WRITE")?;
10511            }
10512        }
10513
10514        Ok(())
10515    }
10516}
10517
10518#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10519#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10520#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10521/// Hive-specific `SET LOCATION` helper used in some `LOAD DATA` statements.
10522pub struct HiveSetLocation {
10523    /// Whether the `SET` keyword was present.
10524    pub has_set: bool,
10525    /// The location identifier.
10526    pub location: Ident,
10527}
10528
10529impl fmt::Display for HiveSetLocation {
10530    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10531        if self.has_set {
10532            write!(f, "SET ")?;
10533        }
10534        write!(f, "LOCATION {}", self.location)
10535    }
10536}
10537
10538/// MySQL `ALTER TABLE` only  [FIRST | AFTER column_name]
10539#[allow(clippy::large_enum_variant)]
10540#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10541#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10542#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10543/// MySQL `ALTER TABLE` column position specifier: `FIRST` or `AFTER <column>`.
10544pub enum MySQLColumnPosition {
10545    /// Place the column first in the table.
10546    First,
10547    /// Place the column after the specified identifier.
10548    After(Ident),
10549}
10550
10551impl Display for MySQLColumnPosition {
10552    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10553        match self {
10554            MySQLColumnPosition::First => write!(f, "FIRST"),
10555            MySQLColumnPosition::After(ident) => {
10556                let column_name = &ident.value;
10557                write!(f, "AFTER {column_name}")
10558            }
10559        }
10560    }
10561}
10562
10563/// MySQL `CREATE VIEW` algorithm parameter: [ALGORITHM = {UNDEFINED | MERGE | TEMPTABLE}]
10564#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10565#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10566#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10567/// MySQL `CREATE VIEW` algorithm options.
10568pub enum CreateViewAlgorithm {
10569    /// `UNDEFINED` algorithm.
10570    Undefined,
10571    /// `MERGE` algorithm.
10572    Merge,
10573    /// `TEMPTABLE` algorithm.
10574    TempTable,
10575}
10576
10577impl Display for CreateViewAlgorithm {
10578    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10579        match self {
10580            CreateViewAlgorithm::Undefined => write!(f, "UNDEFINED"),
10581            CreateViewAlgorithm::Merge => write!(f, "MERGE"),
10582            CreateViewAlgorithm::TempTable => write!(f, "TEMPTABLE"),
10583        }
10584    }
10585}
10586/// MySQL `CREATE VIEW` security parameter: [SQL SECURITY { DEFINER | INVOKER }]
10587#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10588#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10589#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10590/// MySQL `CREATE VIEW` SQL SECURITY options.
10591pub enum CreateViewSecurity {
10592    /// The view runs with the privileges of the definer.
10593    Definer,
10594    /// The view runs with the privileges of the invoker.
10595    Invoker,
10596}
10597
10598impl Display for CreateViewSecurity {
10599    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10600        match self {
10601            CreateViewSecurity::Definer => write!(f, "DEFINER"),
10602            CreateViewSecurity::Invoker => write!(f, "INVOKER"),
10603        }
10604    }
10605}
10606
10607/// [MySQL] `CREATE VIEW` additional parameters
10608///
10609/// [MySQL]: https://dev.mysql.com/doc/refman/9.1/en/create-view.html
10610#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10611#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10612#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10613pub struct CreateViewParams {
10614    /// Optional view algorithm (e.g., MERGE, TEMPTABLE).
10615    pub algorithm: Option<CreateViewAlgorithm>,
10616    /// Optional definer (the security principal that will own the view).
10617    pub definer: Option<GranteeName>,
10618    /// Optional SQL SECURITY setting for the view.
10619    pub security: Option<CreateViewSecurity>,
10620}
10621
10622impl Display for CreateViewParams {
10623    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10624        let CreateViewParams {
10625            algorithm,
10626            definer,
10627            security,
10628        } = self;
10629        if let Some(algorithm) = algorithm {
10630            write!(f, "ALGORITHM = {algorithm} ")?;
10631        }
10632        if let Some(definers) = definer {
10633            write!(f, "DEFINER = {definers} ")?;
10634        }
10635        if let Some(security) = security {
10636            write!(f, "SQL SECURITY {security} ")?;
10637        }
10638        Ok(())
10639    }
10640}
10641
10642#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10643#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10644#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10645/// Key/Value, where the value is a (optionally named) list of identifiers
10646///
10647/// ```sql
10648/// UNION = (tbl_name[,tbl_name]...)
10649/// ENGINE = ReplicatedMergeTree('/table_name','{replica}', ver)
10650/// ENGINE = SummingMergeTree([columns])
10651/// ```
10652pub struct NamedParenthesizedList {
10653    /// The option key (identifier) for this named list.
10654    pub key: Ident,
10655    /// Optional secondary name associated with the key.
10656    pub name: Option<Ident>,
10657    /// The list of identifier values for the key.
10658    pub values: Vec<Ident>,
10659}
10660
10661/// Snowflake `WITH ROW ACCESS POLICY policy_name ON (identifier, ...)`
10662///
10663/// <https://docs.snowflake.com/en/sql-reference/sql/create-table>
10664/// <https://docs.snowflake.com/en/user-guide/security-row-intro>
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))]
10668pub struct RowAccessPolicy {
10669    /// The fully-qualified policy object name.
10670    pub policy: ObjectName,
10671    /// Identifiers for the columns or objects the policy applies to.
10672    pub on: Vec<Ident>,
10673}
10674
10675impl RowAccessPolicy {
10676    /// Create a new `RowAccessPolicy` for the given `policy` and `on` identifiers.
10677    pub fn new(policy: ObjectName, on: Vec<Ident>) -> Self {
10678        Self { policy, on }
10679    }
10680}
10681
10682impl Display for RowAccessPolicy {
10683    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10684        write!(
10685            f,
10686            "WITH ROW ACCESS POLICY {} ON ({})",
10687            self.policy,
10688            display_comma_separated(self.on.as_slice())
10689        )
10690    }
10691}
10692
10693/// Snowflake `[ WITH ] STORAGE LIFECYCLE POLICY <policy_name> ON ( <col_name> [ , ... ] )`
10694///
10695/// <https://docs.snowflake.com/en/sql-reference/sql/create-table>
10696#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10697#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10698#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10699pub struct StorageLifecyclePolicy {
10700    /// The fully-qualified policy object name.
10701    pub policy: ObjectName,
10702    /// Column names the policy applies to.
10703    pub on: Vec<Ident>,
10704}
10705
10706impl Display for StorageLifecyclePolicy {
10707    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10708        write!(
10709            f,
10710            "WITH STORAGE LIFECYCLE POLICY {} ON ({})",
10711            self.policy,
10712            display_comma_separated(self.on.as_slice())
10713        )
10714    }
10715}
10716
10717/// Snowflake `WITH TAG ( tag_name = '<tag_value>', ...)`
10718///
10719/// <https://docs.snowflake.com/en/sql-reference/sql/create-table>
10720#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10721#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10722#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10723pub struct Tag {
10724    /// The tag key (can be qualified).
10725    pub key: ObjectName,
10726    /// The tag value as a string.
10727    pub value: String,
10728}
10729
10730impl Tag {
10731    /// Create a new `Tag` with the given key and value.
10732    pub fn new(key: ObjectName, value: String) -> Self {
10733        Self { key, value }
10734    }
10735}
10736
10737impl Display for Tag {
10738    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10739        write!(f, "{}='{}'", self.key, self.value)
10740    }
10741}
10742
10743/// Snowflake `WITH CONTACT ( purpose = contact [ , purpose = contact ...] )`
10744///
10745/// <https://docs.snowflake.com/en/sql-reference/sql/create-database>
10746#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10747#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10748#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10749pub struct ContactEntry {
10750    /// The purpose label for the contact entry.
10751    pub purpose: String,
10752    /// The contact information associated with the purpose.
10753    pub contact: String,
10754}
10755
10756impl Display for ContactEntry {
10757    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10758        write!(f, "{} = {}", self.purpose, self.contact)
10759    }
10760}
10761
10762/// Helper to indicate if a comment includes the `=` in the display form
10763#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10764#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10765#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10766pub enum CommentDef {
10767    /// Includes `=` when printing the comment, as `COMMENT = 'comment'`
10768    /// Does not include `=` when printing the comment, as `COMMENT 'comment'`
10769    WithEq(String),
10770    /// Comment variant that omits the `=` when displayed.
10771    WithoutEq(String),
10772}
10773
10774impl Display for CommentDef {
10775    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10776        match self {
10777            CommentDef::WithEq(comment) | CommentDef::WithoutEq(comment) => write!(f, "{comment}"),
10778        }
10779    }
10780}
10781
10782/// Helper to indicate if a collection should be wrapped by a symbol in the display form
10783///
10784/// [`Display`] is implemented for every [`Vec<T>`] where `T: Display`.
10785/// The string output is a comma separated list for the vec items
10786///
10787/// # Examples
10788/// ```
10789/// # use sqlparser::ast::WrappedCollection;
10790/// let items = WrappedCollection::Parentheses(vec!["one", "two", "three"]);
10791/// assert_eq!("(one, two, three)", items.to_string());
10792///
10793/// let items = WrappedCollection::NoWrapping(vec!["one", "two", "three"]);
10794/// assert_eq!("one, two, three", items.to_string());
10795/// ```
10796#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10797#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10798#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10799pub enum WrappedCollection<T> {
10800    /// Print the collection without wrapping symbols, as `item, item, item`
10801    NoWrapping(T),
10802    /// Wraps the collection in Parentheses, as `(item, item, item)`
10803    Parentheses(T),
10804}
10805
10806impl<T> Display for WrappedCollection<Vec<T>>
10807where
10808    T: Display,
10809{
10810    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10811        match self {
10812            WrappedCollection::NoWrapping(inner) => {
10813                write!(f, "{}", display_comma_separated(inner.as_slice()))
10814            }
10815            WrappedCollection::Parentheses(inner) => {
10816                write!(f, "({})", display_comma_separated(inner.as_slice()))
10817            }
10818        }
10819    }
10820}
10821
10822/// Represents a single PostgreSQL utility option.
10823///
10824/// A utility option is a key-value pair where the key is an identifier (IDENT) and the value
10825/// can be one of the following:
10826/// - A number with an optional sign (`+` or `-`). Example: `+10`, `-10.2`, `3`
10827/// - A non-keyword string. Example: `option1`, `'option2'`, `"option3"`
10828/// - keyword: `TRUE`, `FALSE`, `ON` (`off` is also accept).
10829/// - Empty. Example: `ANALYZE` (identifier only)
10830///
10831/// Utility options are used in various PostgreSQL DDL statements, including statements such as
10832/// `CLUSTER`, `EXPLAIN`, `VACUUM`, and `REINDEX`. These statements format options as `( option [, ...] )`.
10833///
10834/// [CLUSTER](https://www.postgresql.org/docs/current/sql-cluster.html)
10835/// [EXPLAIN](https://www.postgresql.org/docs/current/sql-explain.html)
10836/// [VACUUM](https://www.postgresql.org/docs/current/sql-vacuum.html)
10837/// [REINDEX](https://www.postgresql.org/docs/current/sql-reindex.html)
10838///
10839/// For example, the `EXPLAIN` AND `VACUUM` statements with options might look like this:
10840/// ```sql
10841/// EXPLAIN (ANALYZE, VERBOSE TRUE, FORMAT TEXT) SELECT * FROM my_table;
10842///
10843/// VACUUM (VERBOSE, ANALYZE ON, PARALLEL 10) my_table;
10844/// ```
10845#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10846#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10847#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10848pub struct UtilityOption {
10849    /// The option name (identifier).
10850    pub name: Ident,
10851    /// Optional argument for the option (number, string, keyword, etc.).
10852    pub arg: Option<Expr>,
10853}
10854
10855impl Display for UtilityOption {
10856    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10857        if let Some(ref arg) = self.arg {
10858            write!(f, "{} {}", self.name, arg)
10859        } else {
10860            write!(f, "{}", self.name)
10861        }
10862    }
10863}
10864
10865/// Represents the different options available for `SHOW`
10866/// statements to filter the results. Example from Snowflake:
10867/// <https://docs.snowflake.com/en/sql-reference/sql/show-tables>
10868#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10869#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10870#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10871pub struct ShowStatementOptions {
10872    /// Optional scope to show in (for example: TABLE, SCHEMA).
10873    pub show_in: Option<ShowStatementIn>,
10874    /// Optional `STARTS WITH` filter value.
10875    pub starts_with: Option<ValueWithSpan>,
10876    /// Optional `LIMIT` expression.
10877    pub limit: Option<Expr>,
10878    /// Optional `FROM` value used with `LIMIT`.
10879    pub limit_from: Option<ValueWithSpan>,
10880    /// Optional filter position (infix or suffix) for `LIKE`/`FILTER`.
10881    pub filter_position: Option<ShowStatementFilterPosition>,
10882}
10883
10884impl Display for ShowStatementOptions {
10885    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10886        let (like_in_infix, like_in_suffix) = match &self.filter_position {
10887            Some(ShowStatementFilterPosition::Infix(filter)) => {
10888                (format!(" {filter}"), "".to_string())
10889            }
10890            Some(ShowStatementFilterPosition::Suffix(filter)) => {
10891                ("".to_string(), format!(" {filter}"))
10892            }
10893            None => ("".to_string(), "".to_string()),
10894        };
10895        write!(
10896            f,
10897            "{like_in_infix}{show_in}{starts_with}{limit}{from}{like_in_suffix}",
10898            show_in = match &self.show_in {
10899                Some(i) => format!(" {i}"),
10900                None => String::new(),
10901            },
10902            starts_with = match &self.starts_with {
10903                Some(s) => format!(" STARTS WITH {s}"),
10904                None => String::new(),
10905            },
10906            limit = match &self.limit {
10907                Some(l) => format!(" LIMIT {l}"),
10908                None => String::new(),
10909            },
10910            from = match &self.limit_from {
10911                Some(f) => format!(" FROM {f}"),
10912                None => String::new(),
10913            }
10914        )?;
10915        Ok(())
10916    }
10917}
10918
10919#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10920#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10921#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10922/// Where a `SHOW` filter appears relative to the main clause.
10923pub enum ShowStatementFilterPosition {
10924    /// Put the filter in an infix position (e.g. `SHOW COLUMNS LIKE '%name%' IN TABLE tbl`).
10925    Infix(ShowStatementFilter), // For example: SHOW COLUMNS LIKE '%name%' IN TABLE tbl
10926    /// Put the filter in a suffix position (e.g. `SHOW COLUMNS IN tbl LIKE '%name%'`).
10927    Suffix(ShowStatementFilter), // For example: SHOW COLUMNS IN tbl LIKE '%name%'
10928}
10929
10930#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10931#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10932#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10933/// Parent object types usable with `SHOW ... IN <parent>` clauses.
10934pub enum ShowStatementInParentType {
10935    /// ACCOUNT parent type for SHOW statements.
10936    Account,
10937    /// DATABASE parent type for SHOW statements.
10938    Database,
10939    /// SCHEMA parent type for SHOW statements.
10940    Schema,
10941    /// TABLE parent type for SHOW statements.
10942    Table,
10943    /// VIEW parent type for SHOW statements.
10944    View,
10945}
10946
10947impl fmt::Display for ShowStatementInParentType {
10948    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10949        match self {
10950            ShowStatementInParentType::Account => write!(f, "ACCOUNT"),
10951            ShowStatementInParentType::Database => write!(f, "DATABASE"),
10952            ShowStatementInParentType::Schema => write!(f, "SCHEMA"),
10953            ShowStatementInParentType::Table => write!(f, "TABLE"),
10954            ShowStatementInParentType::View => write!(f, "VIEW"),
10955        }
10956    }
10957}
10958
10959#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10960#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10961#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10962/// Represents a `SHOW ... IN` clause with optional parent qualifier and name.
10963pub struct ShowStatementIn {
10964    /// The clause that specifies what to show (e.g. COLUMNS, TABLES).
10965    pub clause: ShowStatementInClause,
10966    /// Optional parent type qualifier (ACCOUNT/DATABASE/...).
10967    pub parent_type: Option<ShowStatementInParentType>,
10968    /// Optional parent object name for the SHOW clause.
10969    #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
10970    pub parent_name: Option<ObjectName>,
10971}
10972
10973impl fmt::Display for ShowStatementIn {
10974    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10975        write!(f, "{}", self.clause)?;
10976        if let Some(parent_type) = &self.parent_type {
10977            write!(f, " {parent_type}")?;
10978        }
10979        if let Some(parent_name) = &self.parent_name {
10980            write!(f, " {parent_name}")?;
10981        }
10982        Ok(())
10983    }
10984}
10985
10986/// A Show Charset statement
10987#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10988#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10989#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10990pub struct ShowCharset {
10991    /// The statement can be written as `SHOW CHARSET` or `SHOW CHARACTER SET`
10992    /// true means CHARSET was used and false means CHARACTER SET was used
10993    pub is_shorthand: bool,
10994    /// Optional `LIKE`/`WHERE`-style filter for the statement.
10995    pub filter: Option<ShowStatementFilter>,
10996}
10997
10998impl fmt::Display for ShowCharset {
10999    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11000        write!(f, "SHOW")?;
11001        if self.is_shorthand {
11002            write!(f, " CHARSET")?;
11003        } else {
11004            write!(f, " CHARACTER SET")?;
11005        }
11006        if let Some(filter) = &self.filter {
11007            write!(f, " {filter}")?;
11008        }
11009        Ok(())
11010    }
11011}
11012
11013#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11014#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11015#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11016/// Options for a `SHOW OBJECTS` statement.
11017pub struct ShowObjects {
11018    /// Whether to show terse output.
11019    pub terse: bool,
11020    /// Additional options controlling the SHOW output.
11021    pub show_options: ShowStatementOptions,
11022}
11023
11024/// MSSQL's json null clause
11025///
11026/// ```plaintext
11027/// <json_null_clause> ::=
11028///       NULL ON NULL
11029///     | ABSENT ON NULL
11030/// ```
11031///
11032/// <https://learn.microsoft.com/en-us/sql/t-sql/functions/json-object-transact-sql?view=sql-server-ver16#json_null_clause>
11033#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11034#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11035#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11036pub enum JsonNullClause {
11037    /// `NULL ON NULL` behavior for JSON functions.
11038    NullOnNull,
11039    /// `ABSENT ON NULL` behavior for JSON functions.
11040    AbsentOnNull,
11041}
11042
11043impl Display for JsonNullClause {
11044    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
11045        match self {
11046            JsonNullClause::NullOnNull => write!(f, "NULL ON NULL"),
11047            JsonNullClause::AbsentOnNull => write!(f, "ABSENT ON NULL"),
11048        }
11049    }
11050}
11051
11052/// PostgreSQL JSON function RETURNING clause
11053///
11054/// Example:
11055/// ```sql
11056/// JSON_OBJECT('a': 1 RETURNING jsonb)
11057/// ```
11058#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11059#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11060#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11061pub struct JsonReturningClause {
11062    /// The data type to return from the JSON function (e.g. JSON/JSONB).
11063    pub data_type: DataType,
11064}
11065
11066impl Display for JsonReturningClause {
11067    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
11068        write!(f, "RETURNING {}", self.data_type)
11069    }
11070}
11071
11072/// rename object definition
11073#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11074#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11075#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11076pub struct RenameTable {
11077    /// The current name of the object to rename.
11078    pub old_name: ObjectName,
11079    /// The new name for the object.
11080    pub new_name: ObjectName,
11081}
11082
11083impl fmt::Display for RenameTable {
11084    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11085        write!(f, "{} TO {}", self.old_name, self.new_name)?;
11086        Ok(())
11087    }
11088}
11089
11090/// Represents the referenced table in an `INSERT INTO` statement
11091#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11092#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11093#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11094pub enum TableObject {
11095    /// Table specified by name.
11096    /// Example:
11097    /// ```sql
11098    /// INSERT INTO my_table
11099    /// ```
11100    TableName(#[cfg_attr(feature = "visitor", visit(with = "visit_relation"))] ObjectName),
11101
11102    /// Table specified as a function.
11103    /// Example:
11104    /// ```sql
11105    /// INSERT INTO TABLE FUNCTION remote('localhost', default.simple_table)
11106    /// ```
11107    /// [Clickhouse](https://clickhouse.com/docs/en/sql-reference/table-functions)
11108    TableFunction(Function),
11109
11110    /// Table specified through a sub-query
11111    /// Example:
11112    /// ```sql
11113    /// INSERT INTO
11114    /// (SELECT employee_id, last_name, email, hire_date, job_id,  salary, commission_pct FROM employees)
11115    /// VALUES (207, 'Gregory', 'pgregory@example.com', sysdate, 'PU_CLERK', 1.2E3, NULL);
11116    /// ```
11117    /// [Oracle](https://docs.oracle.com/en/database/oracle/oracle-database/21/sqlrf/INSERT.html#GUID-903F8043-0254-4EE9-ACC1-CB8AC0AF3423__I2126242)
11118    TableQuery(Box<Query>),
11119}
11120
11121impl fmt::Display for TableObject {
11122    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11123        match self {
11124            Self::TableName(table_name) => write!(f, "{table_name}"),
11125            Self::TableFunction(func) => write!(f, "FUNCTION {func}"),
11126            Self::TableQuery(table_query) => write!(f, "({table_query})"),
11127        }
11128    }
11129}
11130
11131/// Represents a SET SESSION AUTHORIZATION statement
11132#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11133#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11134#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11135pub struct SetSessionAuthorizationParam {
11136    /// The scope for the `SET SESSION AUTHORIZATION` (e.g., GLOBAL/SESSION).
11137    pub scope: ContextModifier,
11138    /// The specific authorization parameter kind.
11139    pub kind: SetSessionAuthorizationParamKind,
11140}
11141
11142impl fmt::Display for SetSessionAuthorizationParam {
11143    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11144        write!(f, "{}", self.kind)
11145    }
11146}
11147
11148/// Represents the parameter kind for SET SESSION AUTHORIZATION
11149#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11150#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11151#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11152pub enum SetSessionAuthorizationParamKind {
11153    /// Default authorization
11154    Default,
11155
11156    /// User name
11157    User(Ident),
11158}
11159
11160impl fmt::Display for SetSessionAuthorizationParamKind {
11161    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11162        match self {
11163            SetSessionAuthorizationParamKind::Default => write!(f, "DEFAULT"),
11164            SetSessionAuthorizationParamKind::User(name) => write!(f, "{}", name),
11165        }
11166    }
11167}
11168
11169#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11170#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11171#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11172/// Kind of session parameter being set by `SET SESSION`.
11173pub enum SetSessionParamKind {
11174    /// Generic session parameter (name/value pair).
11175    Generic(SetSessionParamGeneric),
11176    /// Identity insert related parameter.
11177    IdentityInsert(SetSessionParamIdentityInsert),
11178    /// Offsets-related parameter.
11179    Offsets(SetSessionParamOffsets),
11180    /// Statistics-related parameter.
11181    Statistics(SetSessionParamStatistics),
11182}
11183
11184impl fmt::Display for SetSessionParamKind {
11185    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11186        match self {
11187            SetSessionParamKind::Generic(x) => write!(f, "{x}"),
11188            SetSessionParamKind::IdentityInsert(x) => write!(f, "{x}"),
11189            SetSessionParamKind::Offsets(x) => write!(f, "{x}"),
11190            SetSessionParamKind::Statistics(x) => write!(f, "{x}"),
11191        }
11192    }
11193}
11194
11195#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11196#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11197#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11198/// Generic `SET SESSION` parameter represented as name(s) and value.
11199pub struct SetSessionParamGeneric {
11200    /// Names of the session parameters being set.
11201    pub names: Vec<String>,
11202    /// The value to assign to the parameter(s).
11203    pub value: String,
11204}
11205
11206impl fmt::Display for SetSessionParamGeneric {
11207    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11208        write!(f, "{} {}", display_comma_separated(&self.names), self.value)
11209    }
11210}
11211
11212#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11213#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11214#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11215/// `IDENTITY_INSERT` session parameter for a specific object.
11216pub struct SetSessionParamIdentityInsert {
11217    /// Object name targeted by `IDENTITY_INSERT`.
11218    pub obj: ObjectName,
11219    /// Value (ON/OFF) for the identity insert setting.
11220    pub value: SessionParamValue,
11221}
11222
11223impl fmt::Display for SetSessionParamIdentityInsert {
11224    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11225        write!(f, "IDENTITY_INSERT {} {}", self.obj, self.value)
11226    }
11227}
11228
11229#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11230#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11231#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11232/// Offsets-related session parameter with keywords and a value.
11233pub struct SetSessionParamOffsets {
11234    /// Keywords specifying which offsets to modify.
11235    pub keywords: Vec<String>,
11236    /// Value (ON/OFF) for the offsets setting.
11237    pub value: SessionParamValue,
11238}
11239
11240impl fmt::Display for SetSessionParamOffsets {
11241    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11242        write!(
11243            f,
11244            "OFFSETS {} {}",
11245            display_comma_separated(&self.keywords),
11246            self.value
11247        )
11248    }
11249}
11250
11251#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11252#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11253#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11254/// Statistics-related session parameter specifying topic and value.
11255pub struct SetSessionParamStatistics {
11256    /// Statistics topic to set (IO/PROFILE/TIME/XML).
11257    pub topic: SessionParamStatsTopic,
11258    /// Value (ON/OFF) for the statistics topic.
11259    pub value: SessionParamValue,
11260}
11261
11262impl fmt::Display for SetSessionParamStatistics {
11263    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11264        write!(f, "STATISTICS {} {}", self.topic, self.value)
11265    }
11266}
11267
11268#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11269#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11270#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11271/// Topics available for session statistics configuration.
11272pub enum SessionParamStatsTopic {
11273    /// Input/output statistics.
11274    IO,
11275    /// Profile statistics.
11276    Profile,
11277    /// Time statistics.
11278    Time,
11279    /// XML-related statistics.
11280    Xml,
11281}
11282
11283impl fmt::Display for SessionParamStatsTopic {
11284    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11285        match self {
11286            SessionParamStatsTopic::IO => write!(f, "IO"),
11287            SessionParamStatsTopic::Profile => write!(f, "PROFILE"),
11288            SessionParamStatsTopic::Time => write!(f, "TIME"),
11289            SessionParamStatsTopic::Xml => write!(f, "XML"),
11290        }
11291    }
11292}
11293
11294#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11295#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11296#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11297/// Value for a session boolean-like parameter (ON/OFF).
11298pub enum SessionParamValue {
11299    /// Session parameter enabled.
11300    On,
11301    /// Session parameter disabled.
11302    Off,
11303}
11304
11305impl fmt::Display for SessionParamValue {
11306    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11307        match self {
11308            SessionParamValue::On => write!(f, "ON"),
11309            SessionParamValue::Off => write!(f, "OFF"),
11310        }
11311    }
11312}
11313
11314/// Snowflake StorageSerializationPolicy for Iceberg Tables
11315/// ```sql
11316/// [ STORAGE_SERIALIZATION_POLICY = { COMPATIBLE | OPTIMIZED } ]
11317/// ```
11318///
11319/// <https://docs.snowflake.com/en/sql-reference/sql/create-iceberg-table>
11320#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11321#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11322#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11323pub enum StorageSerializationPolicy {
11324    /// Use compatible serialization mode.
11325    Compatible,
11326    /// Use optimized serialization mode.
11327    Optimized,
11328}
11329
11330impl Display for StorageSerializationPolicy {
11331    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
11332        match self {
11333            StorageSerializationPolicy::Compatible => write!(f, "COMPATIBLE"),
11334            StorageSerializationPolicy::Optimized => write!(f, "OPTIMIZED"),
11335        }
11336    }
11337}
11338
11339/// Snowflake CatalogSyncNamespaceMode
11340/// ```sql
11341/// [ CATALOG_SYNC_NAMESPACE_MODE = { NEST | FLATTEN } ]
11342/// ```
11343///
11344/// <https://docs.snowflake.com/en/sql-reference/sql/create-database>
11345#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11346#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11347#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11348pub enum CatalogSyncNamespaceMode {
11349    /// Nest namespaces when syncing catalog.
11350    Nest,
11351    /// Flatten namespaces when syncing catalog.
11352    Flatten,
11353}
11354
11355impl Display for CatalogSyncNamespaceMode {
11356    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
11357        match self {
11358            CatalogSyncNamespaceMode::Nest => write!(f, "NEST"),
11359            CatalogSyncNamespaceMode::Flatten => write!(f, "FLATTEN"),
11360        }
11361    }
11362}
11363
11364/// Variants of the Snowflake `COPY INTO` statement
11365#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11366#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11367#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11368pub enum CopyIntoSnowflakeKind {
11369    /// Loads data from files to a table
11370    /// See: <https://docs.snowflake.com/en/sql-reference/sql/copy-into-table>
11371    Table,
11372    /// Unloads data from a table or query to external files
11373    /// See: <https://docs.snowflake.com/en/sql-reference/sql/copy-into-location>
11374    Location,
11375}
11376
11377#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11378#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11379#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11380/// `PRINT` statement for producing debug/output messages.
11381pub struct PrintStatement {
11382    /// The expression producing the message to print.
11383    pub message: Box<Expr>,
11384}
11385
11386impl fmt::Display for PrintStatement {
11387    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11388        write!(f, "PRINT {}", self.message)
11389    }
11390}
11391
11392/// The type of `WAITFOR` statement (MSSQL).
11393///
11394/// See: <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/waitfor-transact-sql>
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))]
11398pub enum WaitForType {
11399    /// `WAITFOR DELAY 'time_to_pass'`
11400    Delay,
11401    /// `WAITFOR TIME 'time_to_execute'`
11402    Time,
11403}
11404
11405impl fmt::Display for WaitForType {
11406    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11407        match self {
11408            WaitForType::Delay => write!(f, "DELAY"),
11409            WaitForType::Time => write!(f, "TIME"),
11410        }
11411    }
11412}
11413
11414/// MSSQL `WAITFOR` statement.
11415///
11416/// See: <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/waitfor-transact-sql>
11417#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11418#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11419#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11420pub struct WaitForStatement {
11421    /// `DELAY` or `TIME`.
11422    pub wait_type: WaitForType,
11423    /// The time expression.
11424    pub expr: Expr,
11425}
11426
11427impl fmt::Display for WaitForStatement {
11428    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11429        write!(f, "WAITFOR {} {}", self.wait_type, self.expr)
11430    }
11431}
11432
11433/// Represents a `Return` statement.
11434///
11435/// [MsSql triggers](https://learn.microsoft.com/en-us/sql/t-sql/statements/create-trigger-transact-sql)
11436/// [MsSql functions](https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql)
11437#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11438#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11439#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11440pub struct ReturnStatement {
11441    /// Optional return value expression.
11442    pub value: Option<ReturnStatementValue>,
11443}
11444
11445impl fmt::Display for ReturnStatement {
11446    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11447        match &self.value {
11448            Some(ReturnStatementValue::Expr(expr)) => write!(f, "RETURN {expr}"),
11449            None => write!(f, "RETURN"),
11450        }
11451    }
11452}
11453
11454/// Variants of a `RETURN` statement
11455#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11456#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11457#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11458pub enum ReturnStatementValue {
11459    /// Return an expression from a function or trigger.
11460    Expr(Expr),
11461}
11462
11463/// Represents an `OPEN` statement.
11464#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11465#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11466#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11467pub struct OpenStatement {
11468    /// Cursor name
11469    pub cursor_name: Ident,
11470}
11471
11472impl fmt::Display for OpenStatement {
11473    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11474        write!(f, "OPEN {}", self.cursor_name)
11475    }
11476}
11477
11478/// Specifies Include / Exclude NULL within UNPIVOT command.
11479/// For example
11480/// `UNPIVOT (column1 FOR new_column IN (col3, col4, col5, col6))`
11481#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11482#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11483#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11484pub enum NullInclusion {
11485    /// Include NULL values in the UNPIVOT output.
11486    IncludeNulls,
11487    /// Exclude NULL values from the UNPIVOT output.
11488    ExcludeNulls,
11489}
11490
11491impl fmt::Display for NullInclusion {
11492    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11493        match self {
11494            NullInclusion::IncludeNulls => write!(f, "INCLUDE NULLS"),
11495            NullInclusion::ExcludeNulls => write!(f, "EXCLUDE NULLS"),
11496        }
11497    }
11498}
11499
11500/// Checks membership of a value in a JSON array
11501///
11502/// Syntax:
11503/// ```sql
11504/// <value> MEMBER OF(<array>)
11505/// ```
11506/// [MySQL](https://dev.mysql.com/doc/refman/8.4/en/json-search-functions.html#operator_member-of)
11507#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11508#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11509#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11510pub struct MemberOf {
11511    /// The value to check for membership.
11512    pub value: Box<Expr>,
11513    /// The JSON array expression to check against.
11514    pub array: Box<Expr>,
11515}
11516
11517impl fmt::Display for MemberOf {
11518    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11519        write!(f, "{} MEMBER OF({})", self.value, self.array)
11520    }
11521}
11522
11523#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11524#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11525#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11526/// Represents an `EXPORT DATA` statement.
11527pub struct ExportData {
11528    /// Options for the export operation.
11529    pub options: Vec<SqlOption>,
11530    /// The query producing the data to export.
11531    pub query: Box<Query>,
11532    /// Optional named connection to use for export.
11533    pub connection: Option<ObjectName>,
11534}
11535
11536impl fmt::Display for ExportData {
11537    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11538        if let Some(connection) = &self.connection {
11539            write!(
11540                f,
11541                "EXPORT DATA WITH CONNECTION {connection} OPTIONS({}) AS {}",
11542                display_comma_separated(&self.options),
11543                self.query
11544            )
11545        } else {
11546            write!(
11547                f,
11548                "EXPORT DATA OPTIONS({}) AS {}",
11549                display_comma_separated(&self.options),
11550                self.query
11551            )
11552        }
11553    }
11554}
11555/// Creates a user
11556///
11557/// Syntax:
11558/// ```sql
11559/// CREATE [OR REPLACE] USER [IF NOT EXISTS] <name> [OPTIONS]
11560/// ```
11561///
11562/// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-user)
11563#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11564#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11565#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11566pub struct CreateUser {
11567    /// Replace existing user if present.
11568    pub or_replace: bool,
11569    /// Only create the user if it does not already exist.
11570    pub if_not_exists: bool,
11571    /// The name of the user to create.
11572    pub name: Ident,
11573    /// Key/value options for user creation.
11574    pub options: KeyValueOptions,
11575    /// Whether tags are specified using `WITH TAG`.
11576    pub with_tags: bool,
11577    /// Tags for the user.
11578    pub tags: KeyValueOptions,
11579}
11580
11581impl fmt::Display for CreateUser {
11582    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11583        write!(f, "CREATE")?;
11584        if self.or_replace {
11585            write!(f, " OR REPLACE")?;
11586        }
11587        write!(f, " USER")?;
11588        if self.if_not_exists {
11589            write!(f, " IF NOT EXISTS")?;
11590        }
11591        write!(f, " {}", self.name)?;
11592        if !self.options.options.is_empty() {
11593            write!(f, " {}", self.options)?;
11594        }
11595        if !self.tags.options.is_empty() {
11596            if self.with_tags {
11597                write!(f, " WITH")?;
11598            }
11599            write!(f, " TAG ({})", self.tags)?;
11600        }
11601        Ok(())
11602    }
11603}
11604
11605/// Modifies the properties of a user
11606///
11607/// [Snowflake Syntax:](https://docs.snowflake.com/en/sql-reference/sql/alter-user)
11608/// ```sql
11609/// ALTER USER [ IF EXISTS ] [ <name> ] [ OPTIONS ]
11610/// ```
11611///
11612/// [PostgreSQL Syntax:](https://www.postgresql.org/docs/current/sql-alteruser.html)
11613/// ```sql
11614/// ALTER USER <role_specification> [ WITH ] option [ ... ]
11615/// ```
11616#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11617#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11618#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11619pub struct AlterUser {
11620    /// Whether to only alter the user if it exists.
11621    pub if_exists: bool,
11622    /// The name of the user to alter.
11623    pub name: Ident,
11624    /// Optional new name for the user (Snowflake-specific).
11625    /// See: <https://docs.snowflake.com/en/sql-reference/sql/alter-user#syntax>
11626    pub rename_to: Option<Ident>,
11627    /// Reset the user's password.
11628    pub reset_password: bool,
11629    /// Abort all running queries for the user.
11630    pub abort_all_queries: bool,
11631    /// Optionally add a delegated role authorization.
11632    pub add_role_delegation: Option<AlterUserAddRoleDelegation>,
11633    /// Optionally remove a delegated role authorization.
11634    pub remove_role_delegation: Option<AlterUserRemoveRoleDelegation>,
11635    /// Enroll the user in MFA.
11636    pub enroll_mfa: bool,
11637    /// Set the default MFA method for the user.
11638    pub set_default_mfa_method: Option<MfaMethodKind>,
11639    /// Remove the user's default MFA method.
11640    pub remove_mfa_method: Option<MfaMethodKind>,
11641    /// Modify an MFA method for the user.
11642    pub modify_mfa_method: Option<AlterUserModifyMfaMethod>,
11643    /// Add an MFA OTP method with optional count.
11644    pub add_mfa_method_otp: Option<AlterUserAddMfaMethodOtp>,
11645    /// Set a user policy.
11646    pub set_policy: Option<AlterUserSetPolicy>,
11647    /// Unset a user policy.
11648    pub unset_policy: Option<UserPolicyKind>,
11649    /// Key/value tag options to set on the user.
11650    pub set_tag: KeyValueOptions,
11651    /// Tags to unset on the user.
11652    pub unset_tag: Vec<String>,
11653    /// Key/value properties to set on the user.
11654    pub set_props: KeyValueOptions,
11655    /// Properties to unset on the user.
11656    pub unset_props: Vec<String>,
11657    /// The following options are PostgreSQL-specific: <https://www.postgresql.org/docs/current/sql-alteruser.html>
11658    pub password: Option<AlterUserPassword>,
11659}
11660
11661/// ```sql
11662/// ALTER USER [ IF EXISTS ] [ <name> ] ADD DELEGATED AUTHORIZATION OF ROLE <role_name> TO SECURITY INTEGRATION <integration_name>
11663/// ```
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 AlterUserAddRoleDelegation {
11668    /// Role name to delegate.
11669    pub role: Ident,
11670    /// Security integration receiving the delegation.
11671    pub integration: Ident,
11672}
11673
11674/// ```sql
11675/// ALTER USER [ IF EXISTS ] [ <name> ] REMOVE DELEGATED { AUTHORIZATION OF ROLE <role_name> | AUTHORIZATIONS } FROM SECURITY INTEGRATION <integration_name>
11676/// ```
11677#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11678#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11679#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11680pub struct AlterUserRemoveRoleDelegation {
11681    /// Optional role name to remove delegation for.
11682    pub role: Option<Ident>,
11683    /// Security integration from which to remove delegation.
11684    pub integration: Ident,
11685}
11686
11687/// ```sql
11688/// ADD MFA METHOD OTP [ COUNT = number ]
11689/// ```
11690#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11691#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11692#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11693pub struct AlterUserAddMfaMethodOtp {
11694    /// Optional OTP count parameter.
11695    pub count: Option<ValueWithSpan>,
11696}
11697
11698/// ```sql
11699/// ALTER USER [ IF EXISTS ] [ <name> ] MODIFY MFA METHOD <mfa_method> SET COMMENT = '<string>'
11700/// ```
11701#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11702#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11703#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11704pub struct AlterUserModifyMfaMethod {
11705    /// The MFA method being modified.
11706    pub method: MfaMethodKind,
11707    /// The new comment for the MFA method.
11708    pub comment: String,
11709}
11710
11711/// Types of MFA methods
11712#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11713#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11714#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11715pub enum MfaMethodKind {
11716    /// PassKey (hardware or platform passkey) MFA method.
11717    PassKey,
11718    /// Time-based One-Time Password (TOTP) MFA method.
11719    Totp,
11720    /// Duo Security MFA method.
11721    Duo,
11722}
11723
11724impl fmt::Display for MfaMethodKind {
11725    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11726        match self {
11727            MfaMethodKind::PassKey => write!(f, "PASSKEY"),
11728            MfaMethodKind::Totp => write!(f, "TOTP"),
11729            MfaMethodKind::Duo => write!(f, "DUO"),
11730        }
11731    }
11732}
11733
11734/// ```sql
11735/// ALTER USER [ IF EXISTS ] [ <name> ] SET { AUTHENTICATION | PASSWORD | SESSION } POLICY <policy_name>
11736/// ```
11737#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11738#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11739#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11740pub struct AlterUserSetPolicy {
11741    /// The kind of user policy being set (authentication/password/session).
11742    pub policy_kind: UserPolicyKind,
11743    /// The identifier of the policy to apply.
11744    pub policy: Ident,
11745}
11746
11747/// Types of user-based policies
11748#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11749#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11750#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11751pub enum UserPolicyKind {
11752    /// Authentication policy.
11753    Authentication,
11754    /// Password policy.
11755    Password,
11756    /// Session policy.
11757    Session,
11758}
11759
11760impl fmt::Display for UserPolicyKind {
11761    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11762        match self {
11763            UserPolicyKind::Authentication => write!(f, "AUTHENTICATION"),
11764            UserPolicyKind::Password => write!(f, "PASSWORD"),
11765            UserPolicyKind::Session => write!(f, "SESSION"),
11766        }
11767    }
11768}
11769
11770impl fmt::Display for AlterUser {
11771    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11772        write!(f, "ALTER")?;
11773        write!(f, " USER")?;
11774        if self.if_exists {
11775            write!(f, " IF EXISTS")?;
11776        }
11777        write!(f, " {}", self.name)?;
11778        if let Some(new_name) = &self.rename_to {
11779            write!(f, " RENAME TO {new_name}")?;
11780        }
11781        if self.reset_password {
11782            write!(f, " RESET PASSWORD")?;
11783        }
11784        if self.abort_all_queries {
11785            write!(f, " ABORT ALL QUERIES")?;
11786        }
11787        if let Some(role_delegation) = &self.add_role_delegation {
11788            let role = &role_delegation.role;
11789            let integration = &role_delegation.integration;
11790            write!(
11791                f,
11792                " ADD DELEGATED AUTHORIZATION OF ROLE {role} TO SECURITY INTEGRATION {integration}"
11793            )?;
11794        }
11795        if let Some(role_delegation) = &self.remove_role_delegation {
11796            write!(f, " REMOVE DELEGATED")?;
11797            match &role_delegation.role {
11798                Some(role) => write!(f, " AUTHORIZATION OF ROLE {role}")?,
11799                None => write!(f, " AUTHORIZATIONS")?,
11800            }
11801            let integration = &role_delegation.integration;
11802            write!(f, " FROM SECURITY INTEGRATION {integration}")?;
11803        }
11804        if self.enroll_mfa {
11805            write!(f, " ENROLL MFA")?;
11806        }
11807        if let Some(method) = &self.set_default_mfa_method {
11808            write!(f, " SET DEFAULT_MFA_METHOD {method}")?
11809        }
11810        if let Some(method) = &self.remove_mfa_method {
11811            write!(f, " REMOVE MFA METHOD {method}")?;
11812        }
11813        if let Some(modify) = &self.modify_mfa_method {
11814            let method = &modify.method;
11815            let comment = &modify.comment;
11816            write!(
11817                f,
11818                " MODIFY MFA METHOD {method} SET COMMENT '{}'",
11819                value::escape_single_quote_string(comment)
11820            )?;
11821        }
11822        if let Some(add_mfa_method_otp) = &self.add_mfa_method_otp {
11823            write!(f, " ADD MFA METHOD OTP")?;
11824            if let Some(count) = &add_mfa_method_otp.count {
11825                write!(f, " COUNT = {count}")?;
11826            }
11827        }
11828        if let Some(policy) = &self.set_policy {
11829            let policy_kind = &policy.policy_kind;
11830            let name = &policy.policy;
11831            write!(f, " SET {policy_kind} POLICY {name}")?;
11832        }
11833        if let Some(policy_kind) = &self.unset_policy {
11834            write!(f, " UNSET {policy_kind} POLICY")?;
11835        }
11836        if !self.set_tag.options.is_empty() {
11837            write!(f, " SET TAG {}", self.set_tag)?;
11838        }
11839        if !self.unset_tag.is_empty() {
11840            write!(f, " UNSET TAG {}", display_comma_separated(&self.unset_tag))?;
11841        }
11842        let has_props = !self.set_props.options.is_empty();
11843        if has_props {
11844            write!(f, " SET")?;
11845            write!(f, " {}", &self.set_props)?;
11846        }
11847        if !self.unset_props.is_empty() {
11848            write!(f, " UNSET {}", display_comma_separated(&self.unset_props))?;
11849        }
11850        if let Some(password) = &self.password {
11851            write!(f, " {}", password)?;
11852        }
11853        Ok(())
11854    }
11855}
11856
11857/// ```sql
11858/// ALTER USER <role_specification> [ WITH ] PASSWORD { 'password' | NULL }``
11859/// ```
11860#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11861#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11862#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11863pub struct AlterUserPassword {
11864    /// Whether the password is encrypted.
11865    pub encrypted: bool,
11866    /// The password string, or `None` for `NULL`.
11867    pub password: Option<String>,
11868}
11869
11870impl Display for AlterUserPassword {
11871    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11872        if self.encrypted {
11873            write!(f, "ENCRYPTED ")?;
11874        }
11875        write!(f, "PASSWORD")?;
11876        match &self.password {
11877            None => write!(f, " NULL")?,
11878            Some(password) => write!(f, " '{}'", value::escape_single_quote_string(password))?,
11879        }
11880        Ok(())
11881    }
11882}
11883
11884/// Specifies how to create a new table based on an existing table's schema.
11885/// '''sql
11886/// CREATE TABLE new LIKE old ...
11887/// '''
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 CreateTableLikeKind {
11892    /// '''sql
11893    /// CREATE TABLE new (LIKE old ...)
11894    /// '''
11895    /// [Redshift](https://docs.aws.amazon.com/redshift/latest/dg/r_CREATE_TABLE_NEW.html)
11896    Parenthesized(CreateTableLike),
11897    /// '''sql
11898    /// CREATE TABLE new LIKE old ...
11899    /// '''
11900    /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-table#label-create-table-like)
11901    /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_table_like)
11902    Plain(CreateTableLike),
11903}
11904
11905#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11906#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11907#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11908/// Controls whether defaults are included when creating a table FROM/LILE another.
11909pub enum CreateTableLikeDefaults {
11910    /// Include default values from the source table.
11911    Including,
11912    /// Exclude default values from the source table.
11913    Excluding,
11914}
11915
11916impl fmt::Display for CreateTableLikeDefaults {
11917    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11918        match self {
11919            CreateTableLikeDefaults::Including => write!(f, "INCLUDING DEFAULTS"),
11920            CreateTableLikeDefaults::Excluding => write!(f, "EXCLUDING DEFAULTS"),
11921        }
11922    }
11923}
11924
11925#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11926#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11927#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11928/// Represents the `LIKE` clause of a `CREATE TABLE` statement.
11929pub struct CreateTableLike {
11930    /// The source table name to copy the schema from.
11931    pub name: ObjectName,
11932    /// Optional behavior controlling whether defaults are copied.
11933    pub defaults: Option<CreateTableLikeDefaults>,
11934}
11935
11936impl fmt::Display for CreateTableLike {
11937    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11938        write!(f, "LIKE {}", self.name)?;
11939        if let Some(defaults) = &self.defaults {
11940            write!(f, " {defaults}")?;
11941        }
11942        Ok(())
11943    }
11944}
11945
11946/// Specifies the refresh mode for the dynamic table.
11947///
11948/// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-dynamic-table)
11949#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11950#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11951#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11952pub enum RefreshModeKind {
11953    /// Automatic refresh mode (`AUTO`).
11954    Auto,
11955    /// Full refresh mode (`FULL`).
11956    Full,
11957    /// Incremental refresh mode (`INCREMENTAL`).
11958    Incremental,
11959}
11960
11961impl fmt::Display for RefreshModeKind {
11962    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11963        match self {
11964            RefreshModeKind::Auto => write!(f, "AUTO"),
11965            RefreshModeKind::Full => write!(f, "FULL"),
11966            RefreshModeKind::Incremental => write!(f, "INCREMENTAL"),
11967        }
11968    }
11969}
11970
11971/// Specifies the behavior of the initial refresh of the dynamic table.
11972///
11973/// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-dynamic-table)
11974#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11975#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11976#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11977pub enum InitializeKind {
11978    /// Initialize on creation (`ON CREATE`).
11979    OnCreate,
11980    /// Initialize on schedule (`ON SCHEDULE`).
11981    OnSchedule,
11982}
11983
11984impl fmt::Display for InitializeKind {
11985    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11986        match self {
11987            InitializeKind::OnCreate => write!(f, "ON_CREATE"),
11988            InitializeKind::OnSchedule => write!(f, "ON_SCHEDULE"),
11989        }
11990    }
11991}
11992
11993/// Re-sorts rows and reclaims space in either a specified table or all tables in the current database
11994///
11995/// '''sql
11996/// VACUUM [ FULL | SORT ONLY | DELETE ONLY | REINDEX | RECLUSTER ] [ \[ table_name \] [ TO threshold PERCENT ] \[ BOOST \] ]
11997/// '''
11998/// [Redshift](https://docs.aws.amazon.com/redshift/latest/dg/r_VACUUM_command.html)
11999#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
12000#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
12001#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
12002pub struct VacuumStatement {
12003    /// Whether `FULL` was specified.
12004    pub full: bool,
12005    /// Whether `SORT ONLY` was specified.
12006    pub sort_only: bool,
12007    /// Whether `DELETE ONLY` was specified.
12008    pub delete_only: bool,
12009    /// Whether `REINDEX` was specified.
12010    pub reindex: bool,
12011    /// Whether `RECLUSTER` was specified.
12012    pub recluster: bool,
12013    /// Optional table to run `VACUUM` on.
12014    pub table_name: Option<ObjectName>,
12015    /// Optional threshold value (percent) for `TO threshold PERCENT`.
12016    pub threshold: Option<ValueWithSpan>,
12017    /// Whether `BOOST` was specified.
12018    pub boost: bool,
12019}
12020
12021impl fmt::Display for VacuumStatement {
12022    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
12023        write!(
12024            f,
12025            "VACUUM{}{}{}{}{}",
12026            if self.full { " FULL" } else { "" },
12027            if self.sort_only { " SORT ONLY" } else { "" },
12028            if self.delete_only { " DELETE ONLY" } else { "" },
12029            if self.reindex { " REINDEX" } else { "" },
12030            if self.recluster { " RECLUSTER" } else { "" },
12031        )?;
12032        if let Some(table_name) = &self.table_name {
12033            write!(f, " {table_name}")?;
12034        }
12035        if let Some(threshold) = &self.threshold {
12036            write!(f, " TO {threshold} PERCENT")?;
12037        }
12038        if self.boost {
12039            write!(f, " BOOST")?;
12040        }
12041        Ok(())
12042    }
12043}
12044
12045/// Variants of the RESET statement
12046#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
12047#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
12048#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
12049pub enum Reset {
12050    /// Resets all session parameters to their default values.
12051    ALL,
12052
12053    /// Resets a specific session parameter to its default value.
12054    ConfigurationParameter(ObjectName),
12055}
12056
12057/// Resets a session parameter to its default value.
12058/// ```sql
12059/// RESET { ALL | <configuration_parameter> }
12060/// ```
12061#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
12062#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
12063#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
12064pub struct ResetStatement {
12065    /// The reset action to perform (either `ALL` or a specific configuration parameter).
12066    pub reset: Reset,
12067}
12068
12069/// Query optimizer hints are optionally supported comments after the
12070/// `SELECT`, `INSERT`, `UPDATE`, `REPLACE`, `MERGE`, and `DELETE` keywords in
12071/// the corresponding statements.
12072///
12073/// See [Select::optimizer_hints]
12074#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
12075#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
12076#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
12077pub struct OptimizerHint {
12078    /// An optional prefix between the comment marker and `+`.
12079    ///
12080    /// Standard optimizer hints like `/*+ ... */` have an empty prefix,
12081    /// while system-specific hints like `/*abc+ ... */` have `prefix = "abc"`.
12082    /// The prefix is any sequence of ASCII alphanumeric characters
12083    /// immediately before the `+` marker.
12084    pub prefix: String,
12085    /// the raw text of the optimizer hint without its markers
12086    pub text: String,
12087    /// the style of the comment which `text` was extracted from,
12088    /// e.g. `/*+...*/` or `--+...`
12089    ///
12090    /// Not all dialects support all styles, though.
12091    pub style: OptimizerHintStyle,
12092}
12093
12094/// The commentary style of an [optimizer hint](OptimizerHint)
12095#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
12096#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
12097#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
12098pub enum OptimizerHintStyle {
12099    /// A hint corresponding to a single line comment,
12100    /// e.g. `--+ LEADING(v.e v.d t)`
12101    SingleLine {
12102        /// the comment prefix, e.g. `--`
12103        prefix: String,
12104    },
12105    /// A hint corresponding to a multi line comment,
12106    /// e.g. `/*+ LEADING(v.e v.d t) */`
12107    MultiLine,
12108}
12109
12110impl fmt::Display for OptimizerHint {
12111    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
12112        match &self.style {
12113            OptimizerHintStyle::SingleLine { prefix } => {
12114                f.write_str(prefix)?;
12115                f.write_str(&self.prefix)?;
12116                f.write_str("+")?;
12117                f.write_str(&self.text)?;
12118                f.write_str("\n")
12119            }
12120            OptimizerHintStyle::MultiLine => {
12121                f.write_str("/*")?;
12122                f.write_str(&self.prefix)?;
12123                f.write_str("+")?;
12124                f.write_str(&self.text)?;
12125                f.write_str("*/")
12126            }
12127        }
12128    }
12129}
12130
12131impl fmt::Display for ResetStatement {
12132    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
12133        match &self.reset {
12134            Reset::ALL => write!(f, "RESET ALL"),
12135            Reset::ConfigurationParameter(param) => write!(f, "RESET {}", param),
12136        }
12137    }
12138}
12139
12140impl From<Set> for Statement {
12141    fn from(s: Set) -> Self {
12142        Self::Set(s)
12143    }
12144}
12145
12146impl From<Query> for Statement {
12147    fn from(q: Query) -> Self {
12148        Box::new(q).into()
12149    }
12150}
12151
12152impl From<Box<Query>> for Statement {
12153    fn from(q: Box<Query>) -> Self {
12154        Self::Query(q)
12155    }
12156}
12157
12158impl From<Insert> for Statement {
12159    fn from(i: Insert) -> Self {
12160        Self::Insert(i)
12161    }
12162}
12163
12164impl From<Update> for Statement {
12165    fn from(u: Update) -> Self {
12166        Self::Update(u)
12167    }
12168}
12169
12170impl From<CreateView> for Statement {
12171    fn from(cv: CreateView) -> Self {
12172        Self::CreateView(cv)
12173    }
12174}
12175
12176impl From<CreateRole> for Statement {
12177    fn from(cr: CreateRole) -> Self {
12178        Self::CreateRole(cr)
12179    }
12180}
12181
12182impl From<AlterTable> for Statement {
12183    fn from(at: AlterTable) -> Self {
12184        Self::AlterTable(at)
12185    }
12186}
12187
12188impl From<DropFunction> for Statement {
12189    fn from(df: DropFunction) -> Self {
12190        Self::DropFunction(df)
12191    }
12192}
12193
12194impl From<CreateExtension> for Statement {
12195    fn from(ce: CreateExtension) -> Self {
12196        Self::CreateExtension(ce)
12197    }
12198}
12199
12200impl From<CreateCollation> for Statement {
12201    fn from(c: CreateCollation) -> Self {
12202        Self::CreateCollation(c)
12203    }
12204}
12205
12206impl From<DropExtension> for Statement {
12207    fn from(de: DropExtension) -> Self {
12208        Self::DropExtension(de)
12209    }
12210}
12211
12212impl From<CaseStatement> for Statement {
12213    fn from(c: CaseStatement) -> Self {
12214        Self::Case(c)
12215    }
12216}
12217
12218impl From<IfStatement> for Statement {
12219    fn from(i: IfStatement) -> Self {
12220        Self::If(i)
12221    }
12222}
12223
12224impl From<WhileStatement> for Statement {
12225    fn from(w: WhileStatement) -> Self {
12226        Self::While(w)
12227    }
12228}
12229
12230impl From<RaiseStatement> for Statement {
12231    fn from(r: RaiseStatement) -> Self {
12232        Self::Raise(r)
12233    }
12234}
12235
12236impl From<ThrowStatement> for Statement {
12237    fn from(t: ThrowStatement) -> Self {
12238        Self::Throw(t)
12239    }
12240}
12241
12242impl From<Function> for Statement {
12243    fn from(f: Function) -> Self {
12244        Self::Call(f)
12245    }
12246}
12247
12248impl From<OpenStatement> for Statement {
12249    fn from(o: OpenStatement) -> Self {
12250        Self::Open(o)
12251    }
12252}
12253
12254impl From<Delete> for Statement {
12255    fn from(d: Delete) -> Self {
12256        Self::Delete(d)
12257    }
12258}
12259
12260impl From<CreateTable> for Statement {
12261    fn from(c: CreateTable) -> Self {
12262        Self::CreateTable(c)
12263    }
12264}
12265
12266impl From<CreateIndex> for Statement {
12267    fn from(c: CreateIndex) -> Self {
12268        Self::CreateIndex(c)
12269    }
12270}
12271
12272impl From<CreateServerStatement> for Statement {
12273    fn from(c: CreateServerStatement) -> Self {
12274        Self::CreateServer(c)
12275    }
12276}
12277
12278impl From<CreateConnector> for Statement {
12279    fn from(c: CreateConnector) -> Self {
12280        Self::CreateConnector(c)
12281    }
12282}
12283
12284impl From<CreateOperator> for Statement {
12285    fn from(c: CreateOperator) -> Self {
12286        Self::CreateOperator(c)
12287    }
12288}
12289
12290impl From<CreateOperatorFamily> for Statement {
12291    fn from(c: CreateOperatorFamily) -> Self {
12292        Self::CreateOperatorFamily(c)
12293    }
12294}
12295
12296impl From<CreateOperatorClass> for Statement {
12297    fn from(c: CreateOperatorClass) -> Self {
12298        Self::CreateOperatorClass(c)
12299    }
12300}
12301
12302impl From<CreateTextSearch> for Statement {
12303    fn from(c: CreateTextSearch) -> Self {
12304        Self::CreateTextSearch(c)
12305    }
12306}
12307
12308impl From<AlterSchema> for Statement {
12309    fn from(a: AlterSchema) -> Self {
12310        Self::AlterSchema(a)
12311    }
12312}
12313
12314impl From<AlterFunction> for Statement {
12315    fn from(a: AlterFunction) -> Self {
12316        Self::AlterFunction(a)
12317    }
12318}
12319
12320impl From<AlterType> for Statement {
12321    fn from(a: AlterType) -> Self {
12322        Self::AlterType(a)
12323    }
12324}
12325
12326impl From<AlterCollation> for Statement {
12327    fn from(a: AlterCollation) -> Self {
12328        Self::AlterCollation(a)
12329    }
12330}
12331
12332impl From<AlterOperator> for Statement {
12333    fn from(a: AlterOperator) -> Self {
12334        Self::AlterOperator(a)
12335    }
12336}
12337
12338impl From<AlterOperatorFamily> for Statement {
12339    fn from(a: AlterOperatorFamily) -> Self {
12340        Self::AlterOperatorFamily(a)
12341    }
12342}
12343
12344impl From<AlterOperatorClass> for Statement {
12345    fn from(a: AlterOperatorClass) -> Self {
12346        Self::AlterOperatorClass(a)
12347    }
12348}
12349
12350impl From<AlterTextSearch> for Statement {
12351    fn from(a: AlterTextSearch) -> Self {
12352        Self::AlterTextSearch(a)
12353    }
12354}
12355
12356impl From<Merge> for Statement {
12357    fn from(m: Merge) -> Self {
12358        Self::Merge(m)
12359    }
12360}
12361
12362impl From<AlterUser> for Statement {
12363    fn from(a: AlterUser) -> Self {
12364        Self::AlterUser(a)
12365    }
12366}
12367
12368impl From<DropDomain> for Statement {
12369    fn from(d: DropDomain) -> Self {
12370        Self::DropDomain(d)
12371    }
12372}
12373
12374impl From<ShowCharset> for Statement {
12375    fn from(s: ShowCharset) -> Self {
12376        Self::ShowCharset(s)
12377    }
12378}
12379
12380impl From<ShowObjects> for Statement {
12381    fn from(s: ShowObjects) -> Self {
12382        Self::ShowObjects(s)
12383    }
12384}
12385
12386impl From<Use> for Statement {
12387    fn from(u: Use) -> Self {
12388        Self::Use(u)
12389    }
12390}
12391
12392impl From<CreateFunction> for Statement {
12393    fn from(c: CreateFunction) -> Self {
12394        Self::CreateFunction(c)
12395    }
12396}
12397
12398impl From<CreateTrigger> for Statement {
12399    fn from(c: CreateTrigger) -> Self {
12400        Self::CreateTrigger(c)
12401    }
12402}
12403
12404impl From<DropTrigger> for Statement {
12405    fn from(d: DropTrigger) -> Self {
12406        Self::DropTrigger(d)
12407    }
12408}
12409
12410impl From<DropOperator> for Statement {
12411    fn from(d: DropOperator) -> Self {
12412        Self::DropOperator(d)
12413    }
12414}
12415
12416impl From<DropOperatorFamily> for Statement {
12417    fn from(d: DropOperatorFamily) -> Self {
12418        Self::DropOperatorFamily(d)
12419    }
12420}
12421
12422impl From<DropOperatorClass> for Statement {
12423    fn from(d: DropOperatorClass) -> Self {
12424        Self::DropOperatorClass(d)
12425    }
12426}
12427
12428impl From<DenyStatement> for Statement {
12429    fn from(d: DenyStatement) -> Self {
12430        Self::Deny(d)
12431    }
12432}
12433
12434impl From<CreateDomain> for Statement {
12435    fn from(c: CreateDomain) -> Self {
12436        Self::CreateDomain(c)
12437    }
12438}
12439
12440impl From<RenameTable> for Statement {
12441    fn from(r: RenameTable) -> Self {
12442        vec![r].into()
12443    }
12444}
12445
12446impl From<Vec<RenameTable>> for Statement {
12447    fn from(r: Vec<RenameTable>) -> Self {
12448        Self::RenameTable(r)
12449    }
12450}
12451
12452impl From<PrintStatement> for Statement {
12453    fn from(p: PrintStatement) -> Self {
12454        Self::Print(p)
12455    }
12456}
12457
12458impl From<ReturnStatement> for Statement {
12459    fn from(r: ReturnStatement) -> Self {
12460        Self::Return(r)
12461    }
12462}
12463
12464impl From<ExportData> for Statement {
12465    fn from(e: ExportData) -> Self {
12466        Self::ExportData(e)
12467    }
12468}
12469
12470impl From<CreateUser> for Statement {
12471    fn from(c: CreateUser) -> Self {
12472        Self::CreateUser(c)
12473    }
12474}
12475
12476impl From<VacuumStatement> for Statement {
12477    fn from(v: VacuumStatement) -> Self {
12478        Self::Vacuum(v)
12479    }
12480}
12481
12482impl From<ResetStatement> for Statement {
12483    fn from(r: ResetStatement) -> Self {
12484        Self::Reset(r)
12485    }
12486}
12487
12488#[cfg(test)]
12489mod tests {
12490    use crate::tokenizer::Location;
12491
12492    use super::*;
12493
12494    #[test]
12495    fn test_window_frame_default() {
12496        let window_frame = WindowFrame::default();
12497        assert_eq!(WindowFrameBound::Preceding(None), window_frame.start_bound);
12498    }
12499
12500    #[test]
12501    fn test_grouping_sets_display() {
12502        // a and b in different group
12503        let grouping_sets = Expr::GroupingSets(vec![
12504            vec![Expr::Identifier(Ident::new("a"))],
12505            vec![Expr::Identifier(Ident::new("b"))],
12506        ]);
12507        assert_eq!("GROUPING SETS ((a), (b))", format!("{grouping_sets}"));
12508
12509        // a and b in the same group
12510        let grouping_sets = Expr::GroupingSets(vec![vec![
12511            Expr::Identifier(Ident::new("a")),
12512            Expr::Identifier(Ident::new("b")),
12513        ]]);
12514        assert_eq!("GROUPING SETS ((a, b))", format!("{grouping_sets}"));
12515
12516        // (a, b) and (c, d) in different group
12517        let grouping_sets = Expr::GroupingSets(vec![
12518            vec![
12519                Expr::Identifier(Ident::new("a")),
12520                Expr::Identifier(Ident::new("b")),
12521            ],
12522            vec![
12523                Expr::Identifier(Ident::new("c")),
12524                Expr::Identifier(Ident::new("d")),
12525            ],
12526        ]);
12527        assert_eq!("GROUPING SETS ((a, b), (c, d))", format!("{grouping_sets}"));
12528    }
12529
12530    #[test]
12531    fn test_rollup_display() {
12532        let rollup = Expr::Rollup(vec![vec![Expr::Identifier(Ident::new("a"))]]);
12533        assert_eq!("ROLLUP (a)", format!("{rollup}"));
12534
12535        let rollup = Expr::Rollup(vec![vec![
12536            Expr::Identifier(Ident::new("a")),
12537            Expr::Identifier(Ident::new("b")),
12538        ]]);
12539        assert_eq!("ROLLUP ((a, b))", format!("{rollup}"));
12540
12541        let rollup = Expr::Rollup(vec![
12542            vec![Expr::Identifier(Ident::new("a"))],
12543            vec![Expr::Identifier(Ident::new("b"))],
12544        ]);
12545        assert_eq!("ROLLUP (a, b)", format!("{rollup}"));
12546
12547        let rollup = Expr::Rollup(vec![
12548            vec![Expr::Identifier(Ident::new("a"))],
12549            vec![
12550                Expr::Identifier(Ident::new("b")),
12551                Expr::Identifier(Ident::new("c")),
12552            ],
12553            vec![Expr::Identifier(Ident::new("d"))],
12554        ]);
12555        assert_eq!("ROLLUP (a, (b, c), d)", format!("{rollup}"));
12556    }
12557
12558    #[test]
12559    fn test_cube_display() {
12560        let cube = Expr::Cube(vec![vec![Expr::Identifier(Ident::new("a"))]]);
12561        assert_eq!("CUBE (a)", format!("{cube}"));
12562
12563        let cube = Expr::Cube(vec![vec![
12564            Expr::Identifier(Ident::new("a")),
12565            Expr::Identifier(Ident::new("b")),
12566        ]]);
12567        assert_eq!("CUBE ((a, b))", format!("{cube}"));
12568
12569        let cube = Expr::Cube(vec![
12570            vec![Expr::Identifier(Ident::new("a"))],
12571            vec![Expr::Identifier(Ident::new("b"))],
12572        ]);
12573        assert_eq!("CUBE (a, b)", format!("{cube}"));
12574
12575        let cube = Expr::Cube(vec![
12576            vec![Expr::Identifier(Ident::new("a"))],
12577            vec![
12578                Expr::Identifier(Ident::new("b")),
12579                Expr::Identifier(Ident::new("c")),
12580            ],
12581            vec![Expr::Identifier(Ident::new("d"))],
12582        ]);
12583        assert_eq!("CUBE (a, (b, c), d)", format!("{cube}"));
12584    }
12585
12586    #[test]
12587    fn test_interval_display() {
12588        let interval = Expr::Interval(Interval {
12589            value: Box::new(Expr::Value(
12590                Value::SingleQuotedString(String::from("123:45.67")).with_empty_span(),
12591            )),
12592            leading_field: Some(DateTimeField::Minute),
12593            leading_precision: Some(10),
12594            last_field: Some(DateTimeField::Second),
12595            fractional_seconds_precision: Some(9),
12596        });
12597        assert_eq!(
12598            "INTERVAL '123:45.67' MINUTE (10) TO SECOND (9)",
12599            format!("{interval}"),
12600        );
12601
12602        let interval = Expr::Interval(Interval {
12603            value: Box::new(Expr::Value(
12604                Value::SingleQuotedString(String::from("5")).with_empty_span(),
12605            )),
12606            leading_field: Some(DateTimeField::Second),
12607            leading_precision: Some(1),
12608            last_field: None,
12609            fractional_seconds_precision: Some(3),
12610        });
12611        assert_eq!("INTERVAL '5' SECOND (1, 3)", format!("{interval}"));
12612    }
12613
12614    #[test]
12615    fn test_one_or_many_with_parens_deref() {
12616        use core::ops::Index;
12617
12618        let one = OneOrManyWithParens::One("a");
12619
12620        assert_eq!(one.deref(), &["a"]);
12621        assert_eq!(<OneOrManyWithParens<_> as Deref>::deref(&one), &["a"]);
12622
12623        assert_eq!(one[0], "a");
12624        assert_eq!(one.index(0), &"a");
12625        assert_eq!(
12626            <<OneOrManyWithParens<_> as Deref>::Target as Index<usize>>::index(&one, 0),
12627            &"a"
12628        );
12629
12630        assert_eq!(one.len(), 1);
12631        assert_eq!(<OneOrManyWithParens<_> as Deref>::Target::len(&one), 1);
12632
12633        let many1 = OneOrManyWithParens::Many(vec!["b"]);
12634
12635        assert_eq!(many1.deref(), &["b"]);
12636        assert_eq!(<OneOrManyWithParens<_> as Deref>::deref(&many1), &["b"]);
12637
12638        assert_eq!(many1[0], "b");
12639        assert_eq!(many1.index(0), &"b");
12640        assert_eq!(
12641            <<OneOrManyWithParens<_> as Deref>::Target as Index<usize>>::index(&many1, 0),
12642            &"b"
12643        );
12644
12645        assert_eq!(many1.len(), 1);
12646        assert_eq!(<OneOrManyWithParens<_> as Deref>::Target::len(&many1), 1);
12647
12648        let many2 = OneOrManyWithParens::Many(vec!["c", "d"]);
12649
12650        assert_eq!(many2.deref(), &["c", "d"]);
12651        assert_eq!(
12652            <OneOrManyWithParens<_> as Deref>::deref(&many2),
12653            &["c", "d"]
12654        );
12655
12656        assert_eq!(many2[0], "c");
12657        assert_eq!(many2.index(0), &"c");
12658        assert_eq!(
12659            <<OneOrManyWithParens<_> as Deref>::Target as Index<usize>>::index(&many2, 0),
12660            &"c"
12661        );
12662
12663        assert_eq!(many2[1], "d");
12664        assert_eq!(many2.index(1), &"d");
12665        assert_eq!(
12666            <<OneOrManyWithParens<_> as Deref>::Target as Index<usize>>::index(&many2, 1),
12667            &"d"
12668        );
12669
12670        assert_eq!(many2.len(), 2);
12671        assert_eq!(<OneOrManyWithParens<_> as Deref>::Target::len(&many2), 2);
12672    }
12673
12674    #[test]
12675    fn test_one_or_many_with_parens_as_ref() {
12676        let one = OneOrManyWithParens::One("a");
12677
12678        assert_eq!(one.as_ref(), &["a"]);
12679        assert_eq!(<OneOrManyWithParens<_> as AsRef<_>>::as_ref(&one), &["a"]);
12680
12681        let many1 = OneOrManyWithParens::Many(vec!["b"]);
12682
12683        assert_eq!(many1.as_ref(), &["b"]);
12684        assert_eq!(<OneOrManyWithParens<_> as AsRef<_>>::as_ref(&many1), &["b"]);
12685
12686        let many2 = OneOrManyWithParens::Many(vec!["c", "d"]);
12687
12688        assert_eq!(many2.as_ref(), &["c", "d"]);
12689        assert_eq!(
12690            <OneOrManyWithParens<_> as AsRef<_>>::as_ref(&many2),
12691            &["c", "d"]
12692        );
12693    }
12694
12695    #[test]
12696    fn test_one_or_many_with_parens_ref_into_iter() {
12697        let one = OneOrManyWithParens::One("a");
12698
12699        assert_eq!(Vec::from_iter(&one), vec![&"a"]);
12700
12701        let many1 = OneOrManyWithParens::Many(vec!["b"]);
12702
12703        assert_eq!(Vec::from_iter(&many1), vec![&"b"]);
12704
12705        let many2 = OneOrManyWithParens::Many(vec!["c", "d"]);
12706
12707        assert_eq!(Vec::from_iter(&many2), vec![&"c", &"d"]);
12708    }
12709
12710    #[test]
12711    fn test_one_or_many_with_parens_value_into_iter() {
12712        use core::iter::once;
12713
12714        //tests that our iterator implemented methods behaves exactly as it's inner iterator, at every step up to n calls to next/next_back
12715        fn test_steps<I>(ours: OneOrManyWithParens<usize>, inner: I, n: usize)
12716        where
12717            I: IntoIterator<Item = usize, IntoIter: DoubleEndedIterator + Clone> + Clone,
12718        {
12719            fn checks<I>(ours: OneOrManyWithParensIntoIter<usize>, inner: I)
12720            where
12721                I: Iterator<Item = usize> + Clone + DoubleEndedIterator,
12722            {
12723                assert_eq!(ours.size_hint(), inner.size_hint());
12724                assert_eq!(ours.clone().count(), inner.clone().count());
12725
12726                assert_eq!(
12727                    ours.clone().fold(1, |a, v| a + v),
12728                    inner.clone().fold(1, |a, v| a + v)
12729                );
12730
12731                assert_eq!(Vec::from_iter(ours.clone()), Vec::from_iter(inner.clone()));
12732                assert_eq!(
12733                    Vec::from_iter(ours.clone().rev()),
12734                    Vec::from_iter(inner.clone().rev())
12735                );
12736            }
12737
12738            let mut ours_next = ours.clone().into_iter();
12739            let mut inner_next = inner.clone().into_iter();
12740
12741            for _ in 0..n {
12742                checks(ours_next.clone(), inner_next.clone());
12743
12744                assert_eq!(ours_next.next(), inner_next.next());
12745            }
12746
12747            let mut ours_next_back = ours.clone().into_iter();
12748            let mut inner_next_back = inner.clone().into_iter();
12749
12750            for _ in 0..n {
12751                checks(ours_next_back.clone(), inner_next_back.clone());
12752
12753                assert_eq!(ours_next_back.next_back(), inner_next_back.next_back());
12754            }
12755
12756            let mut ours_mixed = ours.clone().into_iter();
12757            let mut inner_mixed = inner.clone().into_iter();
12758
12759            for i in 0..n {
12760                checks(ours_mixed.clone(), inner_mixed.clone());
12761
12762                if i % 2 == 0 {
12763                    assert_eq!(ours_mixed.next_back(), inner_mixed.next_back());
12764                } else {
12765                    assert_eq!(ours_mixed.next(), inner_mixed.next());
12766                }
12767            }
12768
12769            let mut ours_mixed2 = ours.into_iter();
12770            let mut inner_mixed2 = inner.into_iter();
12771
12772            for i in 0..n {
12773                checks(ours_mixed2.clone(), inner_mixed2.clone());
12774
12775                if i % 2 == 0 {
12776                    assert_eq!(ours_mixed2.next(), inner_mixed2.next());
12777                } else {
12778                    assert_eq!(ours_mixed2.next_back(), inner_mixed2.next_back());
12779                }
12780            }
12781        }
12782
12783        test_steps(OneOrManyWithParens::One(1), once(1), 3);
12784        test_steps(OneOrManyWithParens::Many(vec![2]), vec![2], 3);
12785        test_steps(OneOrManyWithParens::Many(vec![3, 4]), vec![3, 4], 4);
12786    }
12787
12788    // Tests that the position in the code of an `Ident` does not affect its
12789    // ordering.
12790    #[test]
12791    fn test_ident_ord() {
12792        let mut a = Ident::with_span(Span::new(Location::new(1, 1), Location::new(1, 1)), "a");
12793        let mut b = Ident::with_span(Span::new(Location::new(2, 2), Location::new(2, 2)), "b");
12794
12795        assert!(a < b);
12796        std::mem::swap(&mut a.span, &mut b.span);
12797        assert!(a < b);
12798    }
12799}