Skip to main content

sqlparser/ast/
mod.rs

1// Licensed to the Apache Software Foundation (ASF) under one
2// or more contributor license agreements.  See the NOTICE file
3// distributed with this work for additional information
4// regarding copyright ownership.  The ASF licenses this file
5// to you under the Apache License, Version 2.0 (the
6// "License"); you may not use this file except in compliance
7// with the License.  You may obtain a copy of the License at
8//
9//   http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing,
12// software distributed under the License is distributed on an
13// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14// KIND, either express or implied.  See the License for the
15// specific language governing permissions and limitations
16// under the License.
17
18//! SQL Abstract Syntax Tree (AST) types
19#[cfg(not(feature = "std"))]
20use alloc::{
21    boxed::Box,
22    format,
23    string::{String, ToString},
24    vec,
25    vec::Vec,
26};
27use helpers::{
28    attached_token::AttachedToken,
29    stmt_data_loading::{FileStagingCommand, StageLoadSelectItemKind},
30};
31
32use core::cmp::Ordering;
33use core::ops::{Deref, DerefMut};
34use core::{
35    fmt::{self, Display},
36    hash,
37};
38
39#[cfg(feature = "serde")]
40use serde::{Deserialize, Serialize};
41
42#[cfg(feature = "visitor")]
43use sqlparser_derive::{Visit, VisitMut};
44
45use crate::{
46    display_utils::SpaceOrNewline,
47    tokenizer::{Span, Token},
48};
49use crate::{
50    display_utils::{Indent, NewLine},
51    keywords::Keyword,
52};
53
54pub use self::data_type::{
55    ArrayElemTypeDef, BinaryLength, CharLengthUnits, CharacterLength, DataType, EnumMember,
56    ExactNumberInfo, IntervalFields, StructBracketKind, TimezoneInfo,
57};
58pub use self::dcl::{
59    AlterRoleOperation, CreateRole, Grant, ResetConfig, Revoke, RoleOption, SecondaryRoles,
60    SetConfigValue, Use,
61};
62pub use self::ddl::{
63    Alignment, AlterCollation, AlterCollationOperation, AlterColumnOperation, AlterConnectorOwner,
64    AlterFunction, AlterFunctionAction, AlterFunctionKind, AlterFunctionOperation,
65    AlterIndexOperation, AlterOperator, AlterOperatorClass, AlterOperatorClassOperation,
66    AlterOperatorFamily, AlterOperatorFamilyOperation, AlterOperatorOperation, AlterPolicy,
67    AlterPolicyOperation, AlterSchema, AlterSchemaOperation, AlterTable, AlterTableAlgorithm,
68    AlterTableLock, AlterTableOperation, AlterTableType, AlterType, AlterTypeAddValue,
69    AlterTypeAddValuePosition, AlterTypeOperation, AlterTypeRename, AlterTypeRenameValue,
70    ClusteredBy, ColumnDef, ColumnOption, ColumnOptionDef, ColumnOptions, ColumnPolicy,
71    ColumnPolicyProperty, ConstraintCharacteristics, CreateCollation, CreateCollationDefinition,
72    CreateConnector, CreateDomain, CreateExtension, CreateFunction, CreateIndex, CreateOperator,
73    CreateOperatorClass, CreateOperatorFamily, CreatePolicy, CreatePolicyCommand, CreatePolicyType,
74    CreateTable, CreateTrigger, CreateView, Deduplicate, DeferrableInitial, DistStyle,
75    DropBehavior, DropExtension, DropFunction, DropOperator, DropOperatorClass, DropOperatorFamily,
76    DropOperatorSignature, DropPolicy, DropTrigger, ForValues, FunctionReturnType, GeneratedAs,
77    GeneratedExpressionMode, IdentityParameters, IdentityProperty, IdentityPropertyFormatKind,
78    IdentityPropertyKind, IdentityPropertyOrder, IndexColumn, IndexOption, IndexType,
79    KeyOrIndexDisplay, Msck, NullsDistinctOption, OperatorArgTypes, OperatorClassItem,
80    OperatorFamilyDropItem, OperatorFamilyItem, OperatorOption, OperatorPurpose, Owner, Partition,
81    PartitionBoundValue, ProcedureParam, ReferentialAction, RenameTableNameKind, ReplicaIdentity,
82    TagsColumnOption, TriggerObjectKind, Truncate, UserDefinedTypeCompositeAttributeDef,
83    UserDefinedTypeInternalLength, UserDefinedTypeRangeOption, UserDefinedTypeRepresentation,
84    UserDefinedTypeSqlDefinitionOption, UserDefinedTypeStorage, ViewColumnDef, WithData,
85};
86pub use self::dml::{
87    Delete, Insert, Merge, MergeAction, MergeClause, MergeClauseKind, MergeInsertExpr,
88    MergeInsertKind, MergeUpdateExpr, MergeUpdateKind, MultiTableInsertIntoClause,
89    MultiTableInsertType, MultiTableInsertValue, MultiTableInsertValues,
90    MultiTableInsertWhenClause, OutputClause, Update,
91};
92pub use self::operator::{BinaryOperator, UnaryOperator};
93pub use self::query::{
94    AfterMatchSkip, ConnectByKind, Cte, CteAsMaterialized, Distinct, EmptyMatchesMode,
95    ExceptSelectItem, ExcludeSelectItem, ExprWithAlias, ExprWithAliasAndOrderBy, Fetch, ForClause,
96    ForJson, ForXml, FormatClause, GroupByExpr, GroupByWithModifier, IdentWithAlias,
97    IlikeSelectItem, InputFormatClause, Interpolate, InterpolateExpr, Join, JoinConstraint,
98    JoinOperator, JsonTableColumn, JsonTableColumnErrorHandling, JsonTableNamedColumn,
99    JsonTableNestedColumn, LateralView, LimitClause, LockClause, LockType, MatchRecognizePattern,
100    MatchRecognizeSymbol, Measure, NamedWindowDefinition, NamedWindowExpr, NonBlock, Offset,
101    OffsetRows, OpenJsonTableColumn, OrderBy, OrderByExpr, OrderByKind, OrderByOptions,
102    OrderBySort, PipeOperator, PivotValueSource, ProjectionSelect, Query, RenameSelectItem,
103    RepetitionQuantifier, ReplaceSelectElement, ReplaceSelectItem, RowsPerMatch, Select,
104    SelectFlavor, SelectInto, SelectItem, SelectItemQualifiedWildcardKind, SelectModifiers,
105    SetExpr, SetOperator, SetQuantifier, Setting, SymbolDefinition, Table, TableAlias,
106    TableAliasColumnDef, TableFactor, TableFunctionArgs, TableIndexHintForClause,
107    TableIndexHintType, TableIndexHints, TableIndexType, TableSample, TableSampleBucket,
108    TableSampleKind, TableSampleMethod, TableSampleModifier, TableSampleQuantity, TableSampleSeed,
109    TableSampleSeedModifier, TableSampleUnit, TableVersion, TableWithJoins, Top, TopQuantity,
110    UpdateTableFromKind, ValueTableMode, Values, WildcardAdditionalOptions, With, WithFill,
111    XmlNamespaceDefinition, XmlPassingArgument, XmlPassingClause, XmlTableColumn,
112    XmlTableColumnOption,
113};
114
115pub use self::trigger::{
116    TriggerEvent, TriggerExecBody, TriggerExecBodyType, TriggerObject, TriggerPeriod,
117    TriggerReferencing, TriggerReferencingType,
118};
119
120pub use self::value::{
121    escape_double_quote_string, escape_quoted_string, DateTimeField, DollarQuotedString,
122    NormalizationForm, QuoteDelimitedString, TrimWhereField, Value, ValueWithSpan,
123};
124
125use crate::ast::helpers::key_value_options::KeyValueOptions;
126use crate::ast::helpers::stmt_data_loading::StageParamsObject;
127
128#[cfg(feature = "visitor")]
129pub use visitor::*;
130
131pub use self::data_type::GeometricTypeKind;
132
133mod data_type;
134mod dcl;
135mod ddl;
136mod dml;
137/// Helper modules for building and manipulating AST nodes.
138pub mod helpers;
139pub mod table_constraints;
140pub use table_constraints::{
141    CheckConstraint, ConstraintUsingIndex, ForeignKeyConstraint, FullTextOrSpatialConstraint,
142    IndexConstraint, PrimaryKeyConstraint, TableConstraint, UniqueConstraint,
143};
144mod operator;
145mod query;
146mod spans;
147pub use spans::Spanned;
148
149pub mod comments;
150mod trigger;
151mod value;
152
153#[cfg(feature = "visitor")]
154mod visitor;
155
156/// Helper used to format a slice using a separator string (e.g., `", "`).
157pub struct DisplaySeparated<'a, T>
158where
159    T: fmt::Display,
160{
161    slice: &'a [T],
162    sep: &'static str,
163}
164
165impl<T> fmt::Display for DisplaySeparated<'_, T>
166where
167    T: fmt::Display,
168{
169    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
170        let mut delim = "";
171        for t in self.slice {
172            f.write_str(delim)?;
173            delim = self.sep;
174            t.fmt(f)?;
175        }
176        Ok(())
177    }
178}
179
180pub(crate) fn display_separated<'a, T>(slice: &'a [T], sep: &'static str) -> DisplaySeparated<'a, T>
181where
182    T: fmt::Display,
183{
184    DisplaySeparated { slice, sep }
185}
186
187pub(crate) fn display_comma_separated<T>(slice: &[T]) -> DisplaySeparated<'_, T>
188where
189    T: fmt::Display,
190{
191    DisplaySeparated { slice, sep: ", " }
192}
193
194/// Writes the given statements to the formatter, each ending with
195/// a semicolon and space separated.
196fn format_statement_list(f: &mut fmt::Formatter, statements: &[Statement]) -> fmt::Result {
197    write!(f, "{}", display_separated(statements, "; "))?;
198    // We manually insert semicolon for the last statement,
199    // since display_separated doesn't handle that case.
200    write!(f, ";")
201}
202
203/// A item `T` enclosed in a pair of parentheses
204#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
205#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
206#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
207pub struct Parens<T> {
208    /// the opening parenthesis token, i.e. `(`
209    pub opening_token: AttachedToken,
210    /// content enclosed in parentheses
211    pub content: T,
212    /// the closing parenthesis token, i.e. `)`
213    pub closing_token: AttachedToken,
214}
215
216impl<T> Parens<T> {
217    /// Constructor wrapping `content` into `Parens` with an empty span;
218    /// useful for testing purposes.
219    pub fn with_empty_span(content: T) -> Self {
220        Self {
221            opening_token: AttachedToken::empty(),
222            content,
223            closing_token: AttachedToken::empty(),
224        }
225    }
226}
227
228impl<T> Deref for Parens<T> {
229    type Target = T;
230
231    fn deref(&self) -> &Self::Target {
232        &self.content
233    }
234}
235
236impl<T> DerefMut for Parens<T> {
237    fn deref_mut(&mut self) -> &mut Self::Target {
238        &mut self.content
239    }
240}
241
242/// An identifier, decomposed into its value or character data and the quote style.
243#[derive(Debug, Clone)]
244#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
245#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
246pub struct Ident {
247    /// The value of the identifier without quotes.
248    pub value: String,
249    /// The starting quote if any. Valid quote characters are the single quote,
250    /// double quote, backtick, and opening square bracket.
251    pub quote_style: Option<char>,
252    /// The span of the identifier in the original SQL string.
253    pub span: Span,
254}
255
256impl PartialEq for Ident {
257    fn eq(&self, other: &Self) -> bool {
258        let Ident {
259            value,
260            quote_style,
261            // exhaustiveness check; we ignore spans in comparisons
262            span: _,
263        } = self;
264
265        value == &other.value && quote_style == &other.quote_style
266    }
267}
268
269impl core::hash::Hash for Ident {
270    fn hash<H: hash::Hasher>(&self, state: &mut H) {
271        let Ident {
272            value,
273            quote_style,
274            // exhaustiveness check; we ignore spans in hashes
275            span: _,
276        } = self;
277
278        value.hash(state);
279        quote_style.hash(state);
280    }
281}
282
283impl Eq for Ident {}
284
285impl PartialOrd for Ident {
286    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
287        Some(self.cmp(other))
288    }
289}
290
291impl Ord for Ident {
292    fn cmp(&self, other: &Self) -> Ordering {
293        let Ident {
294            value,
295            quote_style,
296            // exhaustiveness check; we ignore spans in ordering
297            span: _,
298        } = self;
299
300        let Ident {
301            value: other_value,
302            quote_style: other_quote_style,
303            // exhaustiveness check; we ignore spans in ordering
304            span: _,
305        } = other;
306
307        // First compare by value, then by quote_style
308        value
309            .cmp(other_value)
310            .then_with(|| quote_style.cmp(other_quote_style))
311    }
312}
313
314impl Ident {
315    /// Create a new identifier with the given value and no quotes and an empty span.
316    pub fn new<S>(value: S) -> Self
317    where
318        S: Into<String>,
319    {
320        Ident {
321            value: value.into(),
322            quote_style: None,
323            span: Span::empty(),
324        }
325    }
326
327    /// Create a new quoted identifier with the given quote and value. This function
328    /// panics if the given quote is not a valid quote character.
329    pub fn with_quote<S>(quote: char, value: S) -> Self
330    where
331        S: Into<String>,
332    {
333        assert!(quote == '\'' || quote == '"' || quote == '`' || quote == '[');
334        Ident {
335            value: value.into(),
336            quote_style: Some(quote),
337            span: Span::empty(),
338        }
339    }
340
341    /// Create an `Ident` with the given `span` and `value` (unquoted).
342    pub fn with_span<S>(span: Span, value: S) -> Self
343    where
344        S: Into<String>,
345    {
346        Ident {
347            value: value.into(),
348            quote_style: None,
349            span,
350        }
351    }
352
353    /// Create a quoted `Ident` with the given `quote` and `span`.
354    pub fn with_quote_and_span<S>(quote: char, span: Span, value: S) -> Self
355    where
356        S: Into<String>,
357    {
358        assert!(quote == '\'' || quote == '"' || quote == '`' || quote == '[');
359        Ident {
360            value: value.into(),
361            quote_style: Some(quote),
362            span,
363        }
364    }
365}
366
367impl From<&str> for Ident {
368    fn from(value: &str) -> Self {
369        Ident {
370            value: value.to_string(),
371            quote_style: None,
372            span: Span::empty(),
373        }
374    }
375}
376
377impl fmt::Display for Ident {
378    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
379        match self.quote_style {
380            Some(q) if q == '"' || q == '\'' || q == '`' => {
381                let escaped = value::escape_quoted_string(&self.value, q);
382                write!(f, "{q}{escaped}{q}")
383            }
384            Some('[') => write!(f, "[{}]", self.value),
385            None => f.write_str(&self.value),
386            _ => panic!("unexpected quote style"),
387        }
388    }
389}
390
391/// A name of a table, view, custom type, etc., possibly multi-part, i.e. db.schema.obj
392#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
393#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
394#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
395pub struct ObjectName(pub Vec<ObjectNamePart>);
396
397impl From<Vec<Ident>> for ObjectName {
398    fn from(idents: Vec<Ident>) -> Self {
399        ObjectName(idents.into_iter().map(ObjectNamePart::Identifier).collect())
400    }
401}
402
403impl From<Ident> for ObjectName {
404    fn from(ident: Ident) -> Self {
405        ObjectName(vec![ObjectNamePart::Identifier(ident)])
406    }
407}
408
409impl fmt::Display for ObjectName {
410    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
411        write!(f, "{}", display_separated(&self.0, "."))
412    }
413}
414
415/// A single part of an ObjectName
416#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
417#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
418#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
419pub enum ObjectNamePart {
420    /// A single identifier part, e.g. `schema` or `table`.
421    Identifier(Ident),
422    /// A function that returns an identifier (dialect-specific).
423    Function(ObjectNamePartFunction),
424}
425
426impl ObjectNamePart {
427    /// Return the identifier if this is an `Identifier` variant.
428    pub fn as_ident(&self) -> Option<&Ident> {
429        match self {
430            ObjectNamePart::Identifier(ident) => Some(ident),
431            ObjectNamePart::Function(_) => None,
432        }
433    }
434}
435
436impl fmt::Display for ObjectNamePart {
437    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
438        match self {
439            ObjectNamePart::Identifier(ident) => write!(f, "{ident}"),
440            ObjectNamePart::Function(func) => write!(f, "{func}"),
441        }
442    }
443}
444
445/// An object name part that consists of a function that dynamically
446/// constructs identifiers.
447///
448/// - [Snowflake](https://docs.snowflake.com/en/sql-reference/identifier-literal)
449#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
450#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
451#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
452pub struct ObjectNamePartFunction {
453    /// The function name that produces the object name part.
454    pub name: Ident,
455    /// Function arguments used to compute the identifier.
456    pub args: Vec<FunctionArg>,
457}
458
459impl fmt::Display for ObjectNamePartFunction {
460    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
461        write!(f, "{}(", self.name)?;
462        write!(f, "{})", display_comma_separated(&self.args))
463    }
464}
465
466/// Represents an Array Expression, either
467/// `ARRAY[..]`, or `[..]`
468#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
469#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
470#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
471pub struct Array {
472    /// The list of expressions between brackets
473    pub elem: Vec<Expr>,
474
475    /// `true` for  `ARRAY[..]`, `false` for `[..]`
476    pub named: bool,
477}
478
479impl fmt::Display for Array {
480    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
481        write!(
482            f,
483            "{}[{}]",
484            if self.named { "ARRAY" } else { "" },
485            display_comma_separated(&self.elem)
486        )
487    }
488}
489
490/// Represents an INTERVAL expression, roughly in the following format:
491/// `INTERVAL '<value>' [ <leading_field> [ (<leading_precision>) ] ]
492/// [ TO <last_field> [ (<fractional_seconds_precision>) ] ]`,
493/// e.g. `INTERVAL '123:45.67' MINUTE(3) TO SECOND(2)`.
494///
495/// The parser does not validate the `<value>`, nor does it ensure
496/// that the `<leading_field>` units >= the units in `<last_field>`,
497/// so the user will have to reject intervals like `HOUR TO YEAR`.
498#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
499#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
500#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
501pub struct Interval {
502    /// The interval value expression (commonly a string literal).
503    pub value: Box<Expr>,
504    /// Optional leading time unit (e.g., `HOUR`, `MINUTE`).
505    pub leading_field: Option<DateTimeField>,
506    /// Optional leading precision for the leading field.
507    pub leading_precision: Option<u64>,
508    /// Optional trailing time unit for a range (e.g., `SECOND`).
509    pub last_field: Option<DateTimeField>,
510    /// The fractional seconds precision, when specified.
511    ///
512    /// See SQL `SECOND(n)` or `SECOND(m, n)` forms.
513    pub fractional_seconds_precision: Option<u64>,
514}
515
516impl fmt::Display for Interval {
517    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
518        let value = self.value.as_ref();
519        match (
520            &self.leading_field,
521            self.leading_precision,
522            self.fractional_seconds_precision,
523        ) {
524            (
525                Some(DateTimeField::Second),
526                Some(leading_precision),
527                Some(fractional_seconds_precision),
528            ) => {
529                // When the leading field is SECOND, the parser guarantees that
530                // the last field is None.
531                assert!(self.last_field.is_none());
532                write!(
533                    f,
534                    "INTERVAL {value} SECOND ({leading_precision}, {fractional_seconds_precision})"
535                )
536            }
537            _ => {
538                write!(f, "INTERVAL {value}")?;
539                if let Some(leading_field) = &self.leading_field {
540                    write!(f, " {leading_field}")?;
541                }
542                if let Some(leading_precision) = self.leading_precision {
543                    write!(f, " ({leading_precision})")?;
544                }
545                if let Some(last_field) = &self.last_field {
546                    write!(f, " TO {last_field}")?;
547                }
548                if let Some(fractional_seconds_precision) = self.fractional_seconds_precision {
549                    write!(f, " ({fractional_seconds_precision})")?;
550                }
551                Ok(())
552            }
553        }
554    }
555}
556
557/// A field definition within a struct
558///
559/// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-types#struct_type
560#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
561#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
562#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
563pub struct StructField {
564    /// Optional name of the struct field.
565    pub field_name: Option<Ident>,
566    /// The field data type.
567    pub field_type: DataType,
568    /// Struct field options (e.g., `OPTIONS(...)` on BigQuery).
569    /// See [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#column_name_and_column_schema)
570    pub options: Option<Vec<SqlOption>>,
571}
572
573impl fmt::Display for StructField {
574    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
575        if let Some(name) = &self.field_name {
576            write!(f, "{name} {}", self.field_type)?;
577        } else {
578            write!(f, "{}", self.field_type)?;
579        }
580        if let Some(options) = &self.options {
581            write!(f, " OPTIONS({})", display_separated(options, ", "))
582        } else {
583            Ok(())
584        }
585    }
586}
587
588/// A field definition within a union
589///
590/// [DuckDB]: https://duckdb.org/docs/sql/data_types/union.html
591#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
592#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
593#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
594pub struct UnionField {
595    /// Name of the union field.
596    pub field_name: Ident,
597    /// Type of the union field.
598    pub field_type: DataType,
599}
600
601impl fmt::Display for UnionField {
602    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
603        write!(f, "{} {}", self.field_name, self.field_type)
604    }
605}
606
607/// A dictionary field within a dictionary.
608///
609/// [DuckDB]: https://duckdb.org/docs/sql/data_types/struct#creating-structs
610#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
611#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
612#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
613pub struct DictionaryField {
614    /// Dictionary key identifier.
615    pub key: Ident,
616    /// Value expression for the dictionary entry.
617    pub value: Box<Expr>,
618}
619
620impl fmt::Display for DictionaryField {
621    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
622        write!(f, "{}: {}", self.key, self.value)
623    }
624}
625
626/// Represents a Map expression.
627#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
628#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
629#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
630pub struct Map {
631    /// Entries of the map as key/value pairs.
632    pub entries: Vec<MapEntry>,
633}
634
635impl Display for Map {
636    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
637        write!(f, "MAP {{{}}}", display_comma_separated(&self.entries))
638    }
639}
640
641/// A map field within a map.
642///
643/// [DuckDB]: https://duckdb.org/docs/sql/data_types/map.html#creating-maps
644#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
645#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
646#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
647pub struct MapEntry {
648    /// Key expression of the map entry.
649    pub key: Box<Expr>,
650    /// Value expression of the map entry.
651    pub value: Box<Expr>,
652}
653
654impl fmt::Display for MapEntry {
655    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
656        write!(f, "{}: {}", self.key, self.value)
657    }
658}
659
660/// Options for `CAST` / `TRY_CAST`
661/// BigQuery: <https://cloud.google.com/bigquery/docs/reference/standard-sql/format-elements#formatting_syntax>
662#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
663#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
664#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
665pub enum CastFormat {
666    /// A simple cast format specified by a `Value`.
667    Value(ValueWithSpan),
668    /// A cast format with an explicit time zone: `(format, timezone)`.
669    ValueAtTimeZone(ValueWithSpan, ValueWithSpan),
670}
671
672/// An element of a JSON path.
673#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
674#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
675#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
676pub enum JsonPathElem {
677    /// Accesses an object field using dot notation, e.g. `obj:foo.bar.baz`.
678    ///
679    /// See <https://docs.snowflake.com/en/user-guide/querying-semistructured#dot-notation>.
680    Dot {
681        /// The object key text (without quotes).
682        key: String,
683        /// `true` when the key was quoted in the source.
684        quoted: bool,
685    },
686    /// Accesses an object field or array element using bracket notation,
687    /// e.g. `obj['foo']`.
688    ///
689    /// See <https://docs.snowflake.com/en/user-guide/querying-semistructured#bracket-notation>.
690    Bracket {
691        /// The expression used as the bracket key (string or numeric expression).
692        key: Expr,
693    },
694    /// Access an object field using colon bracket notation
695    /// e.g. `obj:['foo']`
696    ///
697    /// See <https://docs.databricks.com/en/sql/language-manual/functions/colonsign.html>
698    ColonBracket {
699        /// The expression used as the bracket key (string or numeric expression).
700        key: Expr,
701    },
702}
703
704/// A JSON path.
705///
706/// See <https://docs.snowflake.com/en/user-guide/querying-semistructured>.
707/// See <https://docs.databricks.com/en/sql/language-manual/sql-ref-json-path-expression.html>.
708#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
709#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
710#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
711pub struct JsonPath {
712    /// Sequence of path elements that form the JSON path.
713    pub path: Vec<JsonPathElem>,
714}
715
716impl fmt::Display for JsonPath {
717    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
718        for (i, elem) in self.path.iter().enumerate() {
719            match elem {
720                JsonPathElem::Dot { key, quoted } => {
721                    if i == 0 {
722                        write!(f, ":")?;
723                    } else {
724                        write!(f, ".")?;
725                    }
726
727                    if *quoted {
728                        write!(f, "\"{}\"", escape_double_quote_string(key))?;
729                    } else {
730                        write!(f, "{key}")?;
731                    }
732                }
733                JsonPathElem::Bracket { key } => {
734                    write!(f, "[{key}]")?;
735                }
736                JsonPathElem::ColonBracket { key } => {
737                    write!(f, ":[{key}]")?;
738                }
739            }
740        }
741        Ok(())
742    }
743}
744
745/// The syntax used for in a cast expression.
746#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
747#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
748#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
749pub enum CastKind {
750    /// The standard SQL cast syntax, e.g. `CAST(<expr> as <datatype>)`
751    Cast,
752    /// A cast that returns `NULL` on failure, e.g. `TRY_CAST(<expr> as <datatype>)`.
753    ///
754    /// See <https://docs.snowflake.com/en/sql-reference/functions/try_cast>.
755    /// See <https://learn.microsoft.com/en-us/sql/t-sql/functions/try-cast-transact-sql>.
756    TryCast,
757    /// A cast that returns `NULL` on failure, bigQuery-specific ,  e.g. `SAFE_CAST(<expr> as <datatype>)`.
758    ///
759    /// See <https://cloud.google.com/bigquery/docs/reference/standard-sql/functions-and-operators#safe_casting>.
760    SafeCast,
761    /// `<expr> :: <datatype>`
762    DoubleColon,
763}
764
765/// `MATCH` type for constraint references
766///
767/// See: <https://www.postgresql.org/docs/current/sql-createtable.html#SQL-CREATETABLE-PARMS-REFERENCES>
768#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
769#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
770#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
771pub enum ConstraintReferenceMatchKind {
772    /// `MATCH FULL`
773    Full,
774    /// `MATCH PARTIAL`
775    Partial,
776    /// `MATCH SIMPLE`
777    Simple,
778}
779
780impl fmt::Display for ConstraintReferenceMatchKind {
781    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
782        match self {
783            Self::Full => write!(f, "MATCH FULL"),
784            Self::Partial => write!(f, "MATCH PARTIAL"),
785            Self::Simple => write!(f, "MATCH SIMPLE"),
786        }
787    }
788}
789
790/// `EXTRACT` syntax variants.
791///
792/// In Snowflake dialect, the `EXTRACT` expression can support either the `from` syntax
793/// or the comma syntax.
794///
795/// See <https://docs.snowflake.com/en/sql-reference/functions/extract>
796#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
797#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
798#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
799pub enum ExtractSyntax {
800    /// `EXTRACT( <date_or_time_part> FROM <date_or_time_expr> )`
801    From,
802    /// `EXTRACT( <date_or_time_part> , <date_or_timestamp_expr> )`
803    Comma,
804}
805
806/// The syntax used in a CEIL or FLOOR expression.
807///
808/// The `CEIL/FLOOR(<datetime value expression> TO <time unit>)` is an Amazon Kinesis Data Analytics extension.
809/// See <https://docs.aws.amazon.com/kinesisanalytics/latest/sqlref/sql-reference-ceil.html> for
810/// details.
811///
812/// Other dialects either support `CEIL/FLOOR( <expr> [, <scale>])` format or just
813/// `CEIL/FLOOR(<expr>)`.
814#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
815#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
816#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
817pub enum CeilFloorKind {
818    /// `CEIL( <expr> TO <DateTimeField>)`
819    DateTimeField(DateTimeField),
820    /// `CEIL( <expr> [, <scale>])`
821    Scale(ValueWithSpan),
822}
823
824/// A WHEN clause in a CASE expression containing both
825/// the condition and its corresponding result
826#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
827#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
828#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
829pub struct CaseWhen {
830    /// The `WHEN` condition expression.
831    pub condition: Expr,
832    /// The expression returned when `condition` matches.
833    pub result: Expr,
834}
835
836impl fmt::Display for CaseWhen {
837    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
838        f.write_str("WHEN ")?;
839        self.condition.fmt(f)?;
840        f.write_str(" THEN")?;
841        SpaceOrNewline.fmt(f)?;
842        Indent(&self.result).fmt(f)?;
843        Ok(())
844    }
845}
846
847/// An SQL expression of any type.
848///
849/// # Semantics / Type Checking
850///
851/// The parser does not distinguish between expressions of different types
852/// (e.g. boolean vs string). The caller is responsible for detecting and
853/// validating types as necessary (for example  `WHERE 1` vs `SELECT 1=1`)
854/// See the [README.md] for more details.
855///
856/// [README.md]: https://github.com/apache/datafusion-sqlparser-rs/blob/main/README.md#syntax-vs-semantics
857///
858/// # Equality and Hashing Does not Include Source Locations
859///
860/// The `Expr` type implements `PartialEq` and `Eq` based on the semantic value
861/// of the expression (not bitwise comparison). This means that `Expr` instances
862/// that are semantically equivalent but have different spans (locations in the
863/// source tree) will compare as equal.
864#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
865#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
866#[cfg_attr(
867    feature = "visitor",
868    derive(Visit, VisitMut),
869    visit(with = "visit_expr")
870)]
871pub enum Expr {
872    /// Identifier e.g. table name or column name
873    Identifier(Ident),
874    /// Multi-part identifier, e.g. `table_alias.column` or `schema.table.col`
875    CompoundIdentifier(Vec<Ident>),
876    /// Multi-part expression access.
877    ///
878    /// This structure represents an access chain in structured / nested types
879    /// such as maps, arrays, and lists:
880    /// - Array
881    ///     - A 1-dim array `a[1]` will be represented like:
882    ///       `CompoundFieldAccess(Ident('a'), vec![Subscript(1)]`
883    ///     - A 2-dim array `a[1][2]` will be represented like:
884    ///       `CompoundFieldAccess(Ident('a'), vec![Subscript(1), Subscript(2)]`
885    /// - Map or Struct (Bracket-style)
886    ///     - A map `a['field1']` will be represented like:
887    ///       `CompoundFieldAccess(Ident('a'), vec![Subscript('field')]`
888    ///     - A 2-dim map `a['field1']['field2']` will be represented like:
889    ///       `CompoundFieldAccess(Ident('a'), vec![Subscript('field1'), Subscript('field2')]`
890    /// - Struct (Dot-style) (only effect when the chain contains both subscript and expr)
891    ///     - A struct access `a[field1].field2` will be represented like:
892    ///       `CompoundFieldAccess(Ident('a'), vec![Subscript('field1'), Ident('field2')]`
893    /// - If a struct access likes `a.field1.field2`, it will be represented by CompoundIdentifier([a, field1, field2])
894    CompoundFieldAccess {
895        /// The base expression being accessed.
896        root: Box<Expr>,
897        /// Sequence of access operations (subscript or identifier accesses).
898        access_chain: Vec<AccessExpr>,
899    },
900    /// Access data nested in a value containing semi-structured data, such as
901    /// the `VARIANT` type on Snowflake. for example `src:customer[0].name`.
902    ///
903    /// See <https://docs.snowflake.com/en/user-guide/querying-semistructured>.
904    /// See <https://docs.databricks.com/en/sql/language-manual/functions/colonsign.html>.
905    JsonAccess {
906        /// The value being queried.
907        value: Box<Expr>,
908        /// The path to the data to extract.
909        path: JsonPath,
910    },
911    /// `IS FALSE` operator
912    IsFalse(Box<Expr>),
913    /// `IS NOT FALSE` operator
914    IsNotFalse(Box<Expr>),
915    /// `IS TRUE` operator
916    IsTrue(Box<Expr>),
917    /// `IS NOT TRUE` operator
918    IsNotTrue(Box<Expr>),
919    /// `IS NULL` operator
920    IsNull(Box<Expr>),
921    /// `IS NOT NULL` operator
922    IsNotNull(Box<Expr>),
923    /// `IS UNKNOWN` operator
924    IsUnknown(Box<Expr>),
925    /// `IS NOT UNKNOWN` operator
926    IsNotUnknown(Box<Expr>),
927    /// `IS DISTINCT FROM` operator
928    IsDistinctFrom(Box<Expr>, Box<Expr>),
929    /// `IS NOT DISTINCT FROM` operator
930    IsNotDistinctFrom(Box<Expr>, Box<Expr>),
931    /// `<expr> IS [ NOT ] [ form ] NORMALIZED`
932    IsNormalized {
933        /// Expression being tested.
934        expr: Box<Expr>,
935        /// Optional normalization `form` (e.g., NFC, NFD).
936        form: Option<NormalizationForm>,
937        /// `true` when `NOT` is present.
938        negated: bool,
939    },
940    /// `[ NOT ] IN (val1, val2, ...)`
941    InList {
942        /// Left-hand expression to test for membership.
943        expr: Box<Expr>,
944        /// Literal list of expressions to check against.
945        list: Vec<Expr>,
946        /// `true` when the `NOT` modifier is present.
947        negated: bool,
948    },
949    /// `[ NOT ] IN (SELECT ...)`
950    InSubquery {
951        /// Left-hand expression to test for membership.
952        expr: Box<Expr>,
953        /// The subquery providing the candidate values.
954        subquery: Box<Query>,
955        /// `true` when the `NOT` modifier is present.
956        negated: bool,
957    },
958    /// `[ NOT ] IN UNNEST(array_expression)`
959    InUnnest {
960        /// Left-hand expression to test for membership.
961        expr: Box<Expr>,
962        /// Array expression being unnested.
963        array_expr: Box<Expr>,
964        /// `true` when the `NOT` modifier is present.
965        negated: bool,
966    },
967    /// `<expr> [ NOT ] BETWEEN <low> AND <high>`
968    Between {
969        /// Expression being compared.
970        expr: Box<Expr>,
971        /// `true` when the `NOT` modifier is present.
972        negated: bool,
973        /// Lower bound.
974        low: Box<Expr>,
975        /// Upper bound.
976        high: Box<Expr>,
977    },
978    /// Binary operation e.g. `1 + 1` or `foo > bar`
979    BinaryOp {
980        /// Left operand.
981        left: Box<Expr>,
982        /// Operator between operands.
983        op: BinaryOperator,
984        /// Right operand.
985        right: Box<Expr>,
986    },
987    /// `[NOT] LIKE <pattern> [ESCAPE <escape_character>]`
988    Like {
989        /// `true` when `NOT` is present.
990        negated: bool,
991        /// Snowflake supports the ANY keyword to match against a list of patterns
992        /// <https://docs.snowflake.com/en/sql-reference/functions/like_any>
993        any: bool,
994        /// Expression to match.
995        expr: Box<Expr>,
996        /// Pattern expression.
997        pattern: Box<Expr>,
998        /// Optional escape character.
999        escape_char: Option<ValueWithSpan>,
1000    },
1001    /// `ILIKE` (case-insensitive `LIKE`)
1002    ILike {
1003        /// `true` when `NOT` is present.
1004        negated: bool,
1005        /// Snowflake supports the ANY keyword to match against a list of patterns
1006        /// <https://docs.snowflake.com/en/sql-reference/functions/like_any>
1007        any: bool,
1008        /// Expression to match.
1009        expr: Box<Expr>,
1010        /// Pattern expression.
1011        pattern: Box<Expr>,
1012        /// Optional escape character.
1013        escape_char: Option<ValueWithSpan>,
1014    },
1015    /// `SIMILAR TO` regex
1016    SimilarTo {
1017        /// `true` when `NOT` is present.
1018        negated: bool,
1019        /// Expression to test.
1020        expr: Box<Expr>,
1021        /// Pattern expression.
1022        pattern: Box<Expr>,
1023        /// Optional escape character.
1024        escape_char: Option<ValueWithSpan>,
1025    },
1026    /// MySQL: `RLIKE` regex or `REGEXP` regex
1027    RLike {
1028        /// `true` when `NOT` is present.
1029        negated: bool,
1030        /// Expression to test.
1031        expr: Box<Expr>,
1032        /// Pattern expression.
1033        pattern: Box<Expr>,
1034        /// true for REGEXP, false for RLIKE (no difference in semantics)
1035        regexp: bool,
1036    },
1037    /// `ANY` operation e.g. `foo > ANY(bar)`, comparison operator is one of `[=, >, <, =>, =<, !=]`
1038    /// <https://docs.snowflake.com/en/sql-reference/operators-subquery#all-any>
1039    AnyOp {
1040        /// Left operand.
1041        left: Box<Expr>,
1042        /// Comparison operator.
1043        compare_op: BinaryOperator,
1044        /// Right-hand subquery expression.
1045        right: Box<Expr>,
1046        /// ANY and SOME are synonymous: <https://docs.cloudera.com/cdw-runtime/cloud/using-hiveql/topics/hive_comparison_predicates.html>
1047        is_some: bool,
1048    },
1049    /// `ALL` operation e.g. `foo > ALL(bar)`, comparison operator is one of `[=, >, <, =>, =<, !=]`
1050    /// <https://docs.snowflake.com/en/sql-reference/operators-subquery#all-any>
1051    AllOp {
1052        /// Left operand.
1053        left: Box<Expr>,
1054        /// Comparison operator.
1055        compare_op: BinaryOperator,
1056        /// Right-hand subquery expression.
1057        right: Box<Expr>,
1058    },
1059
1060    /// Unary operation e.g. `NOT foo`
1061    UnaryOp {
1062        /// The unary operator (e.g., `NOT`, `-`).
1063        op: UnaryOperator,
1064        /// Operand expression.
1065        expr: Box<Expr>,
1066    },
1067    /// CONVERT a value to a different data type or character encoding. e.g. `CONVERT(foo USING utf8mb4)`
1068    Convert {
1069        /// CONVERT (false) or TRY_CONVERT (true)
1070        /// <https://learn.microsoft.com/en-us/sql/t-sql/functions/try-convert-transact-sql?view=sql-server-ver16>
1071        is_try: bool,
1072        /// The expression to convert.
1073        expr: Box<Expr>,
1074        /// The target data type, if provided.
1075        data_type: Option<DataType>,
1076        /// Optional target character encoding (e.g., `utf8mb4`).
1077        charset: Option<ObjectName>,
1078        /// `true` when target precedes the value (MSSQL syntax).
1079        target_before_value: bool,
1080        /// How to translate the expression.
1081        ///
1082        /// [MSSQL]: https://learn.microsoft.com/en-us/sql/t-sql/functions/cast-and-convert-transact-sql?view=sql-server-ver16#style
1083        styles: Vec<Expr>,
1084    },
1085    /// `CAST` an expression to a different data type e.g. `CAST(foo AS VARCHAR(123))`
1086    Cast {
1087        /// The cast kind (e.g., `CAST`, `TRY_CAST`).
1088        kind: CastKind,
1089        /// Expression being cast.
1090        expr: Box<Expr>,
1091        /// Target data type.
1092        data_type: DataType,
1093        /// [MySQL] allows CAST(... AS type ARRAY) in functional index definitions for InnoDB
1094        /// multi-valued indices. It's not really a datatype, and is only allowed in `CAST` in key
1095        /// specifications, so it's a flag here.
1096        ///
1097        /// [MySQL]: https://dev.mysql.com/doc/refman/8.4/en/cast-functions.html#function_cast
1098        array: bool,
1099        /// Optional CAST(string_expression AS type FORMAT format_string_expression) as used by [BigQuery]
1100        ///
1101        /// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/format-elements#formatting_syntax
1102        format: Option<CastFormat>,
1103    },
1104    /// AT a timestamp to a different timezone e.g. `FROM_UNIXTIME(0) AT TIME ZONE 'UTC-06:00'`
1105    AtTimeZone {
1106        /// Timestamp expression to shift.
1107        timestamp: Box<Expr>,
1108        /// Time zone expression to apply.
1109        time_zone: Box<Expr>,
1110    },
1111    /// Extract a field from a timestamp e.g. `EXTRACT(MONTH FROM foo)`
1112    /// Or `EXTRACT(MONTH, foo)`
1113    ///
1114    /// Syntax:
1115    /// ```sql
1116    /// EXTRACT(DateTimeField FROM <expr>) | EXTRACT(DateTimeField, <expr>)
1117    /// ```
1118    Extract {
1119        /// Which datetime field is being extracted.
1120        field: DateTimeField,
1121        /// Syntax variant used (`From` or `Comma`).
1122        syntax: ExtractSyntax,
1123        /// Expression to extract from.
1124        expr: Box<Expr>,
1125    },
1126    /// ```sql
1127    /// CEIL(<expr> [TO DateTimeField])
1128    /// ```
1129    /// ```sql
1130    /// CEIL( <input_expr> [, <scale_expr> ] )
1131    /// ```
1132    Ceil {
1133        /// Expression to ceil.
1134        expr: Box<Expr>,
1135        /// The CEIL/FLOOR kind (datetime field or scale).
1136        field: CeilFloorKind,
1137    },
1138    /// ```sql
1139    /// FLOOR(<expr> [TO DateTimeField])
1140    /// ```
1141    /// ```sql
1142    /// FLOOR( <input_expr> [, <scale_expr> ] )
1143    ///
1144    Floor {
1145        /// Expression to floor.
1146        expr: Box<Expr>,
1147        /// The CEIL/FLOOR kind (datetime field or scale).
1148        field: CeilFloorKind,
1149    },
1150    /// ```sql
1151    /// POSITION(<expr> in <expr>)
1152    /// ```
1153    Position {
1154        /// Expression to search for.
1155        expr: Box<Expr>,
1156        /// Expression to search in.
1157        r#in: Box<Expr>,
1158    },
1159    /// ```sql
1160    /// SUBSTRING(<expr> [FROM <expr>] [FOR <expr>])
1161    /// ```
1162    /// or
1163    /// ```sql
1164    /// SUBSTRING(<expr>, <expr>, <expr>)
1165    /// ```
1166    Substring {
1167        /// Source expression.
1168        expr: Box<Expr>,
1169        /// Optional `FROM` expression.
1170        substring_from: Option<Box<Expr>>,
1171        /// Optional `FOR` expression.
1172        substring_for: Option<Box<Expr>>,
1173
1174        /// false if the expression is represented using the `SUBSTRING(expr [FROM start] [FOR len])` syntax
1175        /// true if the expression is represented using the `SUBSTRING(expr, start, len)` syntax
1176        /// This flag is used for formatting.
1177        special: bool,
1178
1179        /// true if the expression is represented using the `SUBSTR` shorthand
1180        /// This flag is used for formatting.
1181        shorthand: bool,
1182    },
1183    /// ```sql
1184    /// TRIM([BOTH | LEADING | TRAILING] [<expr> FROM] <expr>)
1185    /// TRIM(<expr>)
1186    /// TRIM(<expr>, [, characters]) -- PostgreSQL, DuckDB, Snowflake, BigQuery, Generic
1187    /// ```
1188    Trim {
1189        /// Which side to trim: `BOTH`, `LEADING`, or `TRAILING`.
1190        trim_where: Option<TrimWhereField>,
1191        /// Optional expression specifying what to trim from the value `expr`.
1192        trim_what: Option<Box<Expr>>,
1193        /// The expression to trim from.
1194        expr: Box<Expr>,
1195        /// Optional list of characters to trim (dialect-specific).
1196        trim_characters: Option<Vec<Expr>>,
1197    },
1198    /// ```sql
1199    /// OVERLAY(<expr> PLACING <expr> FROM <expr>[ FOR <expr> ]
1200    /// ```
1201    Overlay {
1202        /// The target expression being overlayed.
1203        expr: Box<Expr>,
1204        /// The expression to place into the target.
1205        overlay_what: Box<Expr>,
1206        /// The `FROM` position expression indicating where to start overlay.
1207        overlay_from: Box<Expr>,
1208        /// Optional `FOR` length expression limiting the overlay span.
1209        overlay_for: Option<Box<Expr>>,
1210    },
1211    /// `expr COLLATE collation`
1212    Collate {
1213        /// The expression being collated.
1214        expr: Box<Expr>,
1215        /// The collation name to apply to the expression.
1216        collation: ObjectName,
1217    },
1218    /// Nested expression e.g. `(foo > bar)` or `(1)`
1219    Nested(Box<Expr>),
1220    /// A literal value, such as string, number, date or NULL
1221    Value(ValueWithSpan),
1222    /// Prefixed expression, e.g. introducer strings, projection prefix
1223    /// <https://dev.mysql.com/doc/refman/8.0/en/charset-introducer.html>
1224    /// <https://docs.snowflake.com/en/sql-reference/constructs/connect-by>
1225    Prefixed {
1226        /// The prefix identifier (introducer or projection prefix).
1227        prefix: Ident,
1228        /// The value expression being prefixed.
1229        /// Hint: you can unwrap the string value using `value.into_string()`.
1230        value: Box<Expr>,
1231    },
1232    /// A constant of form `<data_type> 'value'`.
1233    /// This can represent ANSI SQL `DATE`, `TIME`, and `TIMESTAMP` literals (such as `DATE '2020-01-01'`),
1234    /// as well as constants of other types (a non-standard PostgreSQL extension).
1235    TypedString(TypedString),
1236    /// Scalar function call e.g. `LEFT(foo, 5)`
1237    Function(Function),
1238    /// `CASE [<operand>] WHEN <condition> THEN <result> ... [ELSE <result>] END`
1239    ///
1240    /// Note we only recognize a complete single expression as `<condition>`,
1241    /// not `< 0` nor `1, 2, 3` as allowed in a `<simple when clause>` per
1242    /// <https://jakewheat.github.io/sql-overview/sql-2011-foundation-grammar.html#simple-when-clause>
1243    Case {
1244        /// The attached `CASE` token (keeps original spacing/comments).
1245        case_token: AttachedToken,
1246        /// The attached `END` token (keeps original spacing/comments).
1247        end_token: AttachedToken,
1248        /// Optional operand expression after `CASE` (for simple CASE).
1249        operand: Option<Box<Expr>>,
1250        /// The `WHEN ... THEN` conditions and results.
1251        conditions: Vec<CaseWhen>,
1252        /// Optional `ELSE` result expression.
1253        else_result: Option<Box<Expr>>,
1254    },
1255    /// An exists expression `[ NOT ] EXISTS(SELECT ...)`, used in expressions like
1256    /// `WHERE [ NOT ] EXISTS (SELECT ...)`.
1257    Exists {
1258        /// The subquery checked by `EXISTS`.
1259        subquery: Box<Query>,
1260        /// Whether the `EXISTS` is negated (`NOT EXISTS`).
1261        negated: bool,
1262    },
1263    /// A parenthesized subquery `(SELECT ...)`, used in expression like
1264    /// `SELECT (subquery) AS x` or `WHERE (subquery) = x`
1265    Subquery(Box<Query>),
1266    /// The `GROUPING SETS` expr.
1267    GroupingSets(Vec<Vec<Expr>>),
1268    /// The `CUBE` expr.
1269    Cube(Vec<Vec<Expr>>),
1270    /// The `ROLLUP` expr.
1271    Rollup(Vec<Vec<Expr>>),
1272    /// ROW / TUPLE a single value, such as `SELECT (1, 2)`
1273    Tuple(Vec<Expr>),
1274    /// `Struct` literal expression
1275    /// Syntax:
1276    /// ```sql
1277    /// STRUCT<[field_name] field_type, ...>( expr1 [, ... ])
1278    ///
1279    /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-types#struct_type)
1280    /// [Databricks](https://docs.databricks.com/en/sql/language-manual/functions/struct.html)
1281    /// ```
1282    Struct {
1283        /// Struct values.
1284        values: Vec<Expr>,
1285        /// Struct field definitions.
1286        fields: Vec<StructField>,
1287    },
1288    /// `BigQuery` specific: An named expression in a typeless struct [1]
1289    ///
1290    /// Syntax
1291    /// ```sql
1292    /// 1 AS A
1293    /// ```
1294    /// [1]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-types#struct_type
1295    Named {
1296        /// The expression being named.
1297        expr: Box<Expr>,
1298        /// The assigned identifier name for the expression.
1299        name: Ident,
1300    },
1301    /// `DuckDB` specific `Struct` literal expression [1]
1302    ///
1303    /// Syntax:
1304    /// ```sql
1305    /// syntax: {'field_name': expr1[, ... ]}
1306    /// ```
1307    /// [1]: https://duckdb.org/docs/sql/data_types/struct#creating-structs
1308    Dictionary(Vec<DictionaryField>),
1309    /// `DuckDB` specific `Map` literal expression [1]
1310    ///
1311    /// Syntax:
1312    /// ```sql
1313    /// syntax: Map {key1: value1[, ... ]}
1314    /// ```
1315    /// [1]: https://duckdb.org/docs/sql/data_types/map#creating-maps
1316    Map(Map),
1317    /// An array expression e.g. `ARRAY[1, 2]`
1318    Array(Array),
1319    /// An interval expression e.g. `INTERVAL '1' YEAR`
1320    Interval(Interval),
1321    /// `MySQL` specific text search function [(1)].
1322    ///
1323    /// Syntax:
1324    /// ```sql
1325    /// MATCH (<col>, <col>, ...) AGAINST (<expr> [<search modifier>])
1326    ///
1327    /// <col> = CompoundIdentifier
1328    /// <expr> = String literal
1329    /// ```
1330    /// [(1)]: https://dev.mysql.com/doc/refman/8.0/en/fulltext-search.html#function_match
1331    MatchAgainst {
1332        /// `(<col>, <col>, ...)`.
1333        columns: Vec<ObjectName>,
1334        /// `<expr>`.
1335        match_value: ValueWithSpan,
1336        /// `<search modifier>`
1337        opt_search_modifier: Option<SearchModifier>,
1338    },
1339    /// An unqualified `*` wildcard token (e.g. `*`).
1340    Wildcard(AttachedToken),
1341    /// Qualified wildcard, e.g. `alias.*` or `schema.table.*`.
1342    /// (Same caveats apply to `QualifiedWildcard` as to `Wildcard`.)
1343    QualifiedWildcard(ObjectName, AttachedToken),
1344    /// Some dialects support an older syntax for outer joins where columns are
1345    /// marked with the `(+)` operator in the WHERE clause, for example:
1346    ///
1347    /// ```sql
1348    /// SELECT t1.c1, t2.c2 FROM t1, t2 WHERE t1.c1 = t2.c2 (+)
1349    /// ```
1350    ///
1351    /// which is equivalent to
1352    ///
1353    /// ```sql
1354    /// SELECT t1.c1, t2.c2 FROM t1 LEFT OUTER JOIN t2 ON t1.c1 = t2.c2
1355    /// ```
1356    ///
1357    /// See <https://docs.snowflake.com/en/sql-reference/constructs/where#joins-in-the-where-clause>.
1358    OuterJoin(Box<Expr>),
1359    /// A reference to the prior level in a CONNECT BY clause.
1360    Prior(Box<Expr>),
1361    /// A lambda function.
1362    ///
1363    /// Syntax:
1364    /// ```plaintext
1365    /// param -> expr | (param1, ...) -> expr
1366    /// ```
1367    ///
1368    /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/functions#higher-order-functions---operator-and-lambdaparams-expr-function)
1369    /// [Databricks](https://docs.databricks.com/en/sql/language-manual/sql-ref-lambda-functions.html)
1370    /// [DuckDB](https://duckdb.org/docs/stable/sql/functions/lambda)
1371    Lambda(LambdaFunction),
1372    /// Checks membership of a value in a JSON array
1373    MemberOf(MemberOf),
1374}
1375
1376impl Expr {
1377    /// Creates a new [`Expr::Value`]
1378    pub fn value(value: impl Into<ValueWithSpan>) -> Self {
1379        Expr::Value(value.into())
1380    }
1381}
1382
1383/// The contents inside the `[` and `]` in a subscript expression.
1384#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1385#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1386#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1387pub enum Subscript {
1388    /// Accesses the element of the array at the given index.
1389    Index {
1390        /// The index expression used to access the array element.
1391        index: Expr,
1392    },
1393
1394    /// Accesses a slice of an array on PostgreSQL, e.g.
1395    ///
1396    /// ```plaintext
1397    /// => select (array[1,2,3,4,5,6])[2:5];
1398    /// -----------
1399    /// {2,3,4,5}
1400    /// ```
1401    ///
1402    /// The lower and/or upper bound can be omitted to slice from the start or
1403    /// end of the array respectively.
1404    ///
1405    /// See <https://www.postgresql.org/docs/current/arrays.html#ARRAYS-ACCESSING>.
1406    ///
1407    /// Also supports an optional "stride" as the last element (this is not
1408    /// supported by postgres), e.g.
1409    ///
1410    /// ```plaintext
1411    /// => select (array[1,2,3,4,5,6])[1:6:2];
1412    /// -----------
1413    /// {1,3,5}
1414    /// ```
1415    Slice {
1416        /// Optional lower bound for the slice (inclusive).
1417        lower_bound: Option<Expr>,
1418        /// Optional upper bound for the slice (inclusive).
1419        upper_bound: Option<Expr>,
1420        /// Optional stride for the slice (step size).
1421        stride: Option<Expr>,
1422    },
1423}
1424
1425impl fmt::Display for Subscript {
1426    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1427        match self {
1428            Subscript::Index { index } => write!(f, "{index}"),
1429            Subscript::Slice {
1430                lower_bound,
1431                upper_bound,
1432                stride,
1433            } => {
1434                if let Some(lower) = lower_bound {
1435                    write!(f, "{lower}")?;
1436                }
1437                write!(f, ":")?;
1438                if let Some(upper) = upper_bound {
1439                    write!(f, "{upper}")?;
1440                }
1441                if let Some(stride) = stride {
1442                    write!(f, ":")?;
1443                    write!(f, "{stride}")?;
1444                }
1445                Ok(())
1446            }
1447        }
1448    }
1449}
1450
1451/// An element of a [`Expr::CompoundFieldAccess`].
1452/// It can be an expression or a subscript.
1453#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1454#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1455#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1456pub enum AccessExpr {
1457    /// Accesses a field using dot notation, e.g. `foo.bar.baz`.
1458    Dot(Expr),
1459    /// Accesses a field or array element using bracket notation, e.g. `foo['bar']`.
1460    Subscript(Subscript),
1461}
1462
1463impl fmt::Display for AccessExpr {
1464    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1465        match self {
1466            AccessExpr::Dot(expr) => write!(f, ".{expr}"),
1467            AccessExpr::Subscript(subscript) => write!(f, "[{subscript}]"),
1468        }
1469    }
1470}
1471
1472/// A lambda function.
1473#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1474#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1475#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1476pub struct LambdaFunction {
1477    /// The parameters to the lambda function.
1478    pub params: OneOrManyWithParens<LambdaFunctionParameter>,
1479    /// The body of the lambda function.
1480    pub body: Box<Expr>,
1481    /// The syntax style used to write the lambda function.
1482    pub syntax: LambdaSyntax,
1483}
1484
1485impl fmt::Display for LambdaFunction {
1486    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1487        match self.syntax {
1488            LambdaSyntax::Arrow => write!(f, "{} -> {}", self.params, self.body),
1489            LambdaSyntax::LambdaKeyword => {
1490                // For lambda keyword syntax, display params without parentheses
1491                // e.g., `lambda x, y : expr` not `lambda (x, y) : expr`
1492                write!(f, "lambda ")?;
1493                match &self.params {
1494                    OneOrManyWithParens::One(p) => write!(f, "{p}")?,
1495                    OneOrManyWithParens::Many(ps) => write!(f, "{}", display_comma_separated(ps))?,
1496                };
1497                write!(f, " : {}", self.body)
1498            }
1499        }
1500    }
1501}
1502
1503/// A parameter to a lambda function, optionally with a data type.
1504#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1505#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1506#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1507pub struct LambdaFunctionParameter {
1508    /// The name of the parameter
1509    pub name: Ident,
1510    /// The optional data type of the parameter
1511    /// [Snowflake Syntax](https://docs.snowflake.com/en/sql-reference/functions/filter#arguments)
1512    pub data_type: Option<DataType>,
1513}
1514
1515impl fmt::Display for LambdaFunctionParameter {
1516    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1517        match &self.data_type {
1518            Some(dt) => write!(f, "{} {}", self.name, dt),
1519            None => write!(f, "{}", self.name),
1520        }
1521    }
1522}
1523
1524/// The syntax style for a lambda function.
1525#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Copy)]
1526#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1527#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1528pub enum LambdaSyntax {
1529    /// Arrow syntax: `param -> expr` or `(param1, param2) -> expr`
1530    ///
1531    /// <https://docs.databricks.com/aws/en/sql/language-manual/sql-ref-lambda-functions>
1532    ///
1533    /// Supported, but deprecated in DuckDB:
1534    /// <https://duckdb.org/docs/stable/sql/functions/lambda>
1535    Arrow,
1536    /// Lambda keyword syntax: `lambda param : expr` or `lambda param1, param2 : expr`
1537    ///
1538    /// Recommended in DuckDB:
1539    /// <https://duckdb.org/docs/stable/sql/functions/lambda>
1540    LambdaKeyword,
1541}
1542
1543/// Encapsulates the common pattern in SQL where either one unparenthesized item
1544/// such as an identifier or expression is permitted, or multiple of the same
1545/// item in a parenthesized list. For accessing items regardless of the form,
1546/// `OneOrManyWithParens` implements `Deref<Target = [T]>` and `IntoIterator`,
1547/// so you can call slice methods on it and iterate over items
1548/// # Examples
1549/// Accessing as a slice:
1550/// ```
1551/// # use sqlparser::ast::OneOrManyWithParens;
1552/// let one = OneOrManyWithParens::One("a");
1553///
1554/// assert_eq!(one[0], "a");
1555/// assert_eq!(one.len(), 1);
1556/// ```
1557/// Iterating:
1558/// ```
1559/// # use sqlparser::ast::OneOrManyWithParens;
1560/// let one = OneOrManyWithParens::One("a");
1561/// let many = OneOrManyWithParens::Many(vec!["a", "b"]);
1562///
1563/// assert_eq!(one.into_iter().chain(many).collect::<Vec<_>>(), vec!["a", "a", "b"] );
1564/// ```
1565#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1566#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1567#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1568pub enum OneOrManyWithParens<T> {
1569    /// A single `T`, unparenthesized.
1570    One(T),
1571    /// One or more `T`s, parenthesized.
1572    Many(Vec<T>),
1573}
1574
1575impl<T> Deref for OneOrManyWithParens<T> {
1576    type Target = [T];
1577
1578    fn deref(&self) -> &[T] {
1579        match self {
1580            OneOrManyWithParens::One(one) => core::slice::from_ref(one),
1581            OneOrManyWithParens::Many(many) => many,
1582        }
1583    }
1584}
1585
1586impl<T> AsRef<[T]> for OneOrManyWithParens<T> {
1587    fn as_ref(&self) -> &[T] {
1588        self
1589    }
1590}
1591
1592impl<'a, T> IntoIterator for &'a OneOrManyWithParens<T> {
1593    type Item = &'a T;
1594    type IntoIter = core::slice::Iter<'a, T>;
1595
1596    fn into_iter(self) -> Self::IntoIter {
1597        self.iter()
1598    }
1599}
1600
1601/// Owned iterator implementation of `OneOrManyWithParens`
1602#[derive(Debug, Clone)]
1603pub struct OneOrManyWithParensIntoIter<T> {
1604    inner: OneOrManyWithParensIntoIterInner<T>,
1605}
1606
1607#[derive(Debug, Clone)]
1608enum OneOrManyWithParensIntoIterInner<T> {
1609    One(core::iter::Once<T>),
1610    Many(<Vec<T> as IntoIterator>::IntoIter),
1611}
1612
1613impl<T> core::iter::FusedIterator for OneOrManyWithParensIntoIter<T>
1614where
1615    core::iter::Once<T>: core::iter::FusedIterator,
1616    <Vec<T> as IntoIterator>::IntoIter: core::iter::FusedIterator,
1617{
1618}
1619
1620impl<T> core::iter::ExactSizeIterator for OneOrManyWithParensIntoIter<T>
1621where
1622    core::iter::Once<T>: core::iter::ExactSizeIterator,
1623    <Vec<T> as IntoIterator>::IntoIter: core::iter::ExactSizeIterator,
1624{
1625}
1626
1627impl<T> core::iter::Iterator for OneOrManyWithParensIntoIter<T> {
1628    type Item = T;
1629
1630    fn next(&mut self) -> Option<Self::Item> {
1631        match &mut self.inner {
1632            OneOrManyWithParensIntoIterInner::One(one) => one.next(),
1633            OneOrManyWithParensIntoIterInner::Many(many) => many.next(),
1634        }
1635    }
1636
1637    fn size_hint(&self) -> (usize, Option<usize>) {
1638        match &self.inner {
1639            OneOrManyWithParensIntoIterInner::One(one) => one.size_hint(),
1640            OneOrManyWithParensIntoIterInner::Many(many) => many.size_hint(),
1641        }
1642    }
1643
1644    fn count(self) -> usize
1645    where
1646        Self: Sized,
1647    {
1648        match self.inner {
1649            OneOrManyWithParensIntoIterInner::One(one) => one.count(),
1650            OneOrManyWithParensIntoIterInner::Many(many) => many.count(),
1651        }
1652    }
1653
1654    fn fold<B, F>(mut self, init: B, f: F) -> B
1655    where
1656        Self: Sized,
1657        F: FnMut(B, Self::Item) -> B,
1658    {
1659        match &mut self.inner {
1660            OneOrManyWithParensIntoIterInner::One(one) => one.fold(init, f),
1661            OneOrManyWithParensIntoIterInner::Many(many) => many.fold(init, f),
1662        }
1663    }
1664}
1665
1666impl<T> core::iter::DoubleEndedIterator for OneOrManyWithParensIntoIter<T> {
1667    fn next_back(&mut self) -> Option<Self::Item> {
1668        match &mut self.inner {
1669            OneOrManyWithParensIntoIterInner::One(one) => one.next_back(),
1670            OneOrManyWithParensIntoIterInner::Many(many) => many.next_back(),
1671        }
1672    }
1673}
1674
1675impl<T> IntoIterator for OneOrManyWithParens<T> {
1676    type Item = T;
1677
1678    type IntoIter = OneOrManyWithParensIntoIter<T>;
1679
1680    fn into_iter(self) -> Self::IntoIter {
1681        let inner = match self {
1682            OneOrManyWithParens::One(one) => {
1683                OneOrManyWithParensIntoIterInner::One(core::iter::once(one))
1684            }
1685            OneOrManyWithParens::Many(many) => {
1686                OneOrManyWithParensIntoIterInner::Many(many.into_iter())
1687            }
1688        };
1689
1690        OneOrManyWithParensIntoIter { inner }
1691    }
1692}
1693
1694impl<T> fmt::Display for OneOrManyWithParens<T>
1695where
1696    T: fmt::Display,
1697{
1698    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1699        match self {
1700            OneOrManyWithParens::One(value) => write!(f, "{value}"),
1701            OneOrManyWithParens::Many(values) => {
1702                write!(f, "({})", display_comma_separated(values))
1703            }
1704        }
1705    }
1706}
1707
1708impl fmt::Display for CastFormat {
1709    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1710        match self {
1711            CastFormat::Value(v) => write!(f, "{v}"),
1712            CastFormat::ValueAtTimeZone(v, tz) => write!(f, "{v} AT TIME ZONE {tz}"),
1713        }
1714    }
1715}
1716
1717impl fmt::Display for Expr {
1718    #[cfg_attr(feature = "recursive-protection", recursive::recursive)]
1719    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1720        match self {
1721            Expr::Identifier(s) => write!(f, "{s}"),
1722            Expr::Wildcard(_) => f.write_str("*"),
1723            Expr::QualifiedWildcard(prefix, _) => write!(f, "{prefix}.*"),
1724            Expr::CompoundIdentifier(s) => write!(f, "{}", display_separated(s, ".")),
1725            Expr::CompoundFieldAccess { root, access_chain } => {
1726                write!(f, "{root}")?;
1727                for field in access_chain {
1728                    write!(f, "{field}")?;
1729                }
1730                Ok(())
1731            }
1732            Expr::IsTrue(ast) => write!(f, "{ast} IS TRUE"),
1733            Expr::IsNotTrue(ast) => write!(f, "{ast} IS NOT TRUE"),
1734            Expr::IsFalse(ast) => write!(f, "{ast} IS FALSE"),
1735            Expr::IsNotFalse(ast) => write!(f, "{ast} IS NOT FALSE"),
1736            Expr::IsNull(ast) => write!(f, "{ast} IS NULL"),
1737            Expr::IsNotNull(ast) => write!(f, "{ast} IS NOT NULL"),
1738            Expr::IsUnknown(ast) => write!(f, "{ast} IS UNKNOWN"),
1739            Expr::IsNotUnknown(ast) => write!(f, "{ast} IS NOT UNKNOWN"),
1740            Expr::InList {
1741                expr,
1742                list,
1743                negated,
1744            } => write!(
1745                f,
1746                "{} {}IN ({})",
1747                expr,
1748                if *negated { "NOT " } else { "" },
1749                display_comma_separated(list)
1750            ),
1751            Expr::InSubquery {
1752                expr,
1753                subquery,
1754                negated,
1755            } => write!(
1756                f,
1757                "{} {}IN ({})",
1758                expr,
1759                if *negated { "NOT " } else { "" },
1760                subquery
1761            ),
1762            Expr::InUnnest {
1763                expr,
1764                array_expr,
1765                negated,
1766            } => write!(
1767                f,
1768                "{} {}IN UNNEST({})",
1769                expr,
1770                if *negated { "NOT " } else { "" },
1771                array_expr
1772            ),
1773            Expr::Between {
1774                expr,
1775                negated,
1776                low,
1777                high,
1778            } => write!(
1779                f,
1780                "{} {}BETWEEN {} AND {}",
1781                expr,
1782                if *negated { "NOT " } else { "" },
1783                low,
1784                high
1785            ),
1786            Expr::BinaryOp { left, op, right } => write!(f, "{left} {op} {right}"),
1787            Expr::Like {
1788                negated,
1789                expr,
1790                pattern,
1791                escape_char,
1792                any,
1793            } => match escape_char {
1794                Some(ch) => write!(
1795                    f,
1796                    "{} {}LIKE {}{} ESCAPE {}",
1797                    expr,
1798                    if *negated { "NOT " } else { "" },
1799                    if *any { "ANY " } else { "" },
1800                    pattern,
1801                    ch
1802                ),
1803                _ => write!(
1804                    f,
1805                    "{} {}LIKE {}{}",
1806                    expr,
1807                    if *negated { "NOT " } else { "" },
1808                    if *any { "ANY " } else { "" },
1809                    pattern
1810                ),
1811            },
1812            Expr::ILike {
1813                negated,
1814                expr,
1815                pattern,
1816                escape_char,
1817                any,
1818            } => match escape_char {
1819                Some(ch) => write!(
1820                    f,
1821                    "{} {}ILIKE {}{} ESCAPE {}",
1822                    expr,
1823                    if *negated { "NOT " } else { "" },
1824                    if *any { "ANY" } else { "" },
1825                    pattern,
1826                    ch
1827                ),
1828                _ => write!(
1829                    f,
1830                    "{} {}ILIKE {}{}",
1831                    expr,
1832                    if *negated { "NOT " } else { "" },
1833                    if *any { "ANY " } else { "" },
1834                    pattern
1835                ),
1836            },
1837            Expr::RLike {
1838                negated,
1839                expr,
1840                pattern,
1841                regexp,
1842            } => write!(
1843                f,
1844                "{} {}{} {}",
1845                expr,
1846                if *negated { "NOT " } else { "" },
1847                if *regexp { "REGEXP" } else { "RLIKE" },
1848                pattern
1849            ),
1850            Expr::IsNormalized {
1851                expr,
1852                form,
1853                negated,
1854            } => {
1855                let not_ = if *negated { "NOT " } else { "" };
1856                if let Some(form) = form {
1857                    write!(f, "{} IS {}{} NORMALIZED", expr, not_, form)
1858                } else {
1859                    write!(f, "{expr} IS {not_}NORMALIZED")
1860                }
1861            }
1862            Expr::SimilarTo {
1863                negated,
1864                expr,
1865                pattern,
1866                escape_char,
1867            } => match escape_char {
1868                Some(ch) => write!(
1869                    f,
1870                    "{} {}SIMILAR TO {} ESCAPE {}",
1871                    expr,
1872                    if *negated { "NOT " } else { "" },
1873                    pattern,
1874                    ch
1875                ),
1876                _ => write!(
1877                    f,
1878                    "{} {}SIMILAR TO {}",
1879                    expr,
1880                    if *negated { "NOT " } else { "" },
1881                    pattern
1882                ),
1883            },
1884            Expr::AnyOp {
1885                left,
1886                compare_op,
1887                right,
1888                is_some,
1889            } => {
1890                let add_parens = !matches!(right.as_ref(), Expr::Subquery(_));
1891                write!(
1892                    f,
1893                    "{left} {compare_op} {}{}{right}{}",
1894                    if *is_some { "SOME" } else { "ANY" },
1895                    if add_parens { "(" } else { "" },
1896                    if add_parens { ")" } else { "" },
1897                )
1898            }
1899            Expr::AllOp {
1900                left,
1901                compare_op,
1902                right,
1903            } => {
1904                let add_parens = !matches!(right.as_ref(), Expr::Subquery(_));
1905                write!(
1906                    f,
1907                    "{left} {compare_op} ALL{}{right}{}",
1908                    if add_parens { "(" } else { "" },
1909                    if add_parens { ")" } else { "" },
1910                )
1911            }
1912            Expr::UnaryOp { op, expr } => {
1913                if op == &UnaryOperator::PGPostfixFactorial {
1914                    write!(f, "{expr}{op}")
1915                } else if matches!(
1916                    op,
1917                    UnaryOperator::Not
1918                        | UnaryOperator::Hash
1919                        | UnaryOperator::AtDashAt
1920                        | UnaryOperator::DoubleAt
1921                        | UnaryOperator::QuestionDash
1922                        | UnaryOperator::QuestionPipe
1923                ) {
1924                    write!(f, "{op} {expr}")
1925                } else {
1926                    write!(f, "{op}{expr}")
1927                }
1928            }
1929            Expr::Convert {
1930                is_try,
1931                expr,
1932                target_before_value,
1933                data_type,
1934                charset,
1935                styles,
1936            } => {
1937                write!(f, "{}CONVERT(", if *is_try { "TRY_" } else { "" })?;
1938                if let Some(data_type) = data_type {
1939                    if let Some(charset) = charset {
1940                        write!(f, "{expr}, {data_type} CHARACTER SET {charset}")
1941                    } else if *target_before_value {
1942                        write!(f, "{data_type}, {expr}")
1943                    } else {
1944                        write!(f, "{expr}, {data_type}")
1945                    }
1946                } else if let Some(charset) = charset {
1947                    write!(f, "{expr} USING {charset}")
1948                } else {
1949                    write!(f, "{expr}") // This should never happen
1950                }?;
1951                if !styles.is_empty() {
1952                    write!(f, ", {}", display_comma_separated(styles))?;
1953                }
1954                write!(f, ")")
1955            }
1956            Expr::Cast {
1957                kind,
1958                expr,
1959                data_type,
1960                array,
1961                format,
1962            } => match kind {
1963                CastKind::Cast => {
1964                    write!(f, "CAST({expr} AS {data_type}")?;
1965                    if *array {
1966                        write!(f, " ARRAY")?;
1967                    }
1968                    if let Some(format) = format {
1969                        write!(f, " FORMAT {format}")?;
1970                    }
1971                    write!(f, ")")
1972                }
1973                CastKind::TryCast => {
1974                    if let Some(format) = format {
1975                        write!(f, "TRY_CAST({expr} AS {data_type} FORMAT {format})")
1976                    } else {
1977                        write!(f, "TRY_CAST({expr} AS {data_type})")
1978                    }
1979                }
1980                CastKind::SafeCast => {
1981                    if let Some(format) = format {
1982                        write!(f, "SAFE_CAST({expr} AS {data_type} FORMAT {format})")
1983                    } else {
1984                        write!(f, "SAFE_CAST({expr} AS {data_type})")
1985                    }
1986                }
1987                CastKind::DoubleColon => {
1988                    write!(f, "{expr}::{data_type}")
1989                }
1990            },
1991            Expr::Extract {
1992                field,
1993                syntax,
1994                expr,
1995            } => match syntax {
1996                ExtractSyntax::From => write!(f, "EXTRACT({field} FROM {expr})"),
1997                ExtractSyntax::Comma => write!(f, "EXTRACT({field}, {expr})"),
1998            },
1999            Expr::Ceil { expr, field } => match field {
2000                CeilFloorKind::DateTimeField(DateTimeField::NoDateTime) => {
2001                    write!(f, "CEIL({expr})")
2002                }
2003                CeilFloorKind::DateTimeField(dt_field) => write!(f, "CEIL({expr} TO {dt_field})"),
2004                CeilFloorKind::Scale(s) => write!(f, "CEIL({expr}, {s})"),
2005            },
2006            Expr::Floor { expr, field } => match field {
2007                CeilFloorKind::DateTimeField(DateTimeField::NoDateTime) => {
2008                    write!(f, "FLOOR({expr})")
2009                }
2010                CeilFloorKind::DateTimeField(dt_field) => write!(f, "FLOOR({expr} TO {dt_field})"),
2011                CeilFloorKind::Scale(s) => write!(f, "FLOOR({expr}, {s})"),
2012            },
2013            Expr::Position { expr, r#in } => write!(f, "POSITION({expr} IN {in})"),
2014            Expr::Collate { expr, collation } => write!(f, "{expr} COLLATE {collation}"),
2015            Expr::Nested(ast) => write!(f, "({ast})"),
2016            Expr::Value(v) => write!(f, "{v}"),
2017            Expr::Prefixed { prefix, value } => write!(f, "{prefix} {value}"),
2018            Expr::TypedString(ts) => ts.fmt(f),
2019            Expr::Function(fun) => fun.fmt(f),
2020            Expr::Case {
2021                case_token: _,
2022                end_token: _,
2023                operand,
2024                conditions,
2025                else_result,
2026            } => {
2027                f.write_str("CASE")?;
2028                if let Some(operand) = operand {
2029                    f.write_str(" ")?;
2030                    operand.fmt(f)?;
2031                }
2032                for when in conditions {
2033                    SpaceOrNewline.fmt(f)?;
2034                    Indent(when).fmt(f)?;
2035                }
2036                if let Some(else_result) = else_result {
2037                    SpaceOrNewline.fmt(f)?;
2038                    Indent("ELSE").fmt(f)?;
2039                    SpaceOrNewline.fmt(f)?;
2040                    Indent(Indent(else_result)).fmt(f)?;
2041                }
2042                SpaceOrNewline.fmt(f)?;
2043                f.write_str("END")
2044            }
2045            Expr::Exists { subquery, negated } => write!(
2046                f,
2047                "{}EXISTS ({})",
2048                if *negated { "NOT " } else { "" },
2049                subquery
2050            ),
2051            Expr::Subquery(s) => write!(f, "({s})"),
2052            Expr::GroupingSets(sets) => {
2053                write!(f, "GROUPING SETS (")?;
2054                let mut sep = "";
2055                for set in sets {
2056                    write!(f, "{sep}")?;
2057                    sep = ", ";
2058                    write!(f, "({})", display_comma_separated(set))?;
2059                }
2060                write!(f, ")")
2061            }
2062            Expr::Cube(sets) => {
2063                write!(f, "CUBE (")?;
2064                let mut sep = "";
2065                for set in sets {
2066                    write!(f, "{sep}")?;
2067                    sep = ", ";
2068                    if set.len() == 1 {
2069                        write!(f, "{}", set[0])?;
2070                    } else {
2071                        write!(f, "({})", display_comma_separated(set))?;
2072                    }
2073                }
2074                write!(f, ")")
2075            }
2076            Expr::Rollup(sets) => {
2077                write!(f, "ROLLUP (")?;
2078                let mut sep = "";
2079                for set in sets {
2080                    write!(f, "{sep}")?;
2081                    sep = ", ";
2082                    if set.len() == 1 {
2083                        write!(f, "{}", set[0])?;
2084                    } else {
2085                        write!(f, "({})", display_comma_separated(set))?;
2086                    }
2087                }
2088                write!(f, ")")
2089            }
2090            Expr::Substring {
2091                expr,
2092                substring_from,
2093                substring_for,
2094                special,
2095                shorthand,
2096            } => {
2097                f.write_str("SUBSTR")?;
2098                if !*shorthand {
2099                    f.write_str("ING")?;
2100                }
2101                write!(f, "({expr}")?;
2102                if let Some(from_part) = substring_from {
2103                    if *special {
2104                        write!(f, ", {from_part}")?;
2105                    } else {
2106                        write!(f, " FROM {from_part}")?;
2107                    }
2108                }
2109                if let Some(for_part) = substring_for {
2110                    if *special {
2111                        write!(f, ", {for_part}")?;
2112                    } else {
2113                        write!(f, " FOR {for_part}")?;
2114                    }
2115                }
2116
2117                write!(f, ")")
2118            }
2119            Expr::Overlay {
2120                expr,
2121                overlay_what,
2122                overlay_from,
2123                overlay_for,
2124            } => {
2125                write!(
2126                    f,
2127                    "OVERLAY({expr} PLACING {overlay_what} FROM {overlay_from}"
2128                )?;
2129                if let Some(for_part) = overlay_for {
2130                    write!(f, " FOR {for_part}")?;
2131                }
2132
2133                write!(f, ")")
2134            }
2135            Expr::IsDistinctFrom(a, b) => write!(f, "{a} IS DISTINCT FROM {b}"),
2136            Expr::IsNotDistinctFrom(a, b) => write!(f, "{a} IS NOT DISTINCT FROM {b}"),
2137            Expr::Trim {
2138                expr,
2139                trim_where,
2140                trim_what,
2141                trim_characters,
2142            } => {
2143                write!(f, "TRIM(")?;
2144                if let Some(ident) = trim_where {
2145                    write!(f, "{ident} ")?;
2146                }
2147                if let Some(trim_char) = trim_what {
2148                    write!(f, "{trim_char} FROM {expr}")?;
2149                } else {
2150                    write!(f, "{expr}")?;
2151                }
2152                if let Some(characters) = trim_characters {
2153                    write!(f, ", {}", display_comma_separated(characters))?;
2154                }
2155
2156                write!(f, ")")
2157            }
2158            Expr::Tuple(exprs) => {
2159                write!(f, "({})", display_comma_separated(exprs))
2160            }
2161            Expr::Struct { values, fields } => {
2162                if !fields.is_empty() {
2163                    write!(
2164                        f,
2165                        "STRUCT<{}>({})",
2166                        display_comma_separated(fields),
2167                        display_comma_separated(values)
2168                    )
2169                } else {
2170                    write!(f, "STRUCT({})", display_comma_separated(values))
2171                }
2172            }
2173            Expr::Named { expr, name } => {
2174                write!(f, "{expr} AS {name}")
2175            }
2176            Expr::Dictionary(fields) => {
2177                write!(f, "{{{}}}", display_comma_separated(fields))
2178            }
2179            Expr::Map(map) => {
2180                write!(f, "{map}")
2181            }
2182            Expr::Array(set) => {
2183                write!(f, "{set}")
2184            }
2185            Expr::JsonAccess { value, path } => {
2186                write!(f, "{value}{path}")
2187            }
2188            Expr::AtTimeZone {
2189                timestamp,
2190                time_zone,
2191            } => {
2192                write!(f, "{timestamp} AT TIME ZONE {time_zone}")
2193            }
2194            Expr::Interval(interval) => {
2195                write!(f, "{interval}")
2196            }
2197            Expr::MatchAgainst {
2198                columns,
2199                match_value: match_expr,
2200                opt_search_modifier,
2201            } => {
2202                write!(f, "MATCH ({}) AGAINST ", display_comma_separated(columns),)?;
2203
2204                if let Some(search_modifier) = opt_search_modifier {
2205                    write!(f, "({match_expr} {search_modifier})")?;
2206                } else {
2207                    write!(f, "({match_expr})")?;
2208                }
2209
2210                Ok(())
2211            }
2212            Expr::OuterJoin(expr) => {
2213                write!(f, "{expr} (+)")
2214            }
2215            Expr::Prior(expr) => write!(f, "PRIOR {expr}"),
2216            Expr::Lambda(lambda) => write!(f, "{lambda}"),
2217            Expr::MemberOf(member_of) => write!(f, "{member_of}"),
2218        }
2219    }
2220}
2221
2222/// The type of a window used in `OVER` clauses.
2223///
2224/// A window can be either an inline specification (`WindowSpec`) or a
2225/// reference to a previously defined named window.
2226///
2227/// - `WindowSpec(WindowSpec)`: An inline window specification, e.g.
2228///   `OVER (PARTITION BY ... ORDER BY ...)`.
2229/// - `NamedWindow(Ident)`: A reference to a named window declared elsewhere.
2230#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2231#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2232#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2233pub enum WindowType {
2234    /// An inline window specification.
2235    WindowSpec(WindowSpec),
2236    /// A reference to a previously defined named window.
2237    NamedWindow(Ident),
2238}
2239
2240impl Display for WindowType {
2241    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2242        match self {
2243            WindowType::WindowSpec(spec) => {
2244                f.write_str("(")?;
2245                NewLine.fmt(f)?;
2246                Indent(spec).fmt(f)?;
2247                NewLine.fmt(f)?;
2248                f.write_str(")")
2249            }
2250            WindowType::NamedWindow(name) => name.fmt(f),
2251        }
2252    }
2253}
2254
2255/// A window specification (i.e. `OVER ([window_name] PARTITION BY .. ORDER BY .. etc.)`)
2256#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2257#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2258#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2259pub struct WindowSpec {
2260    /// Optional window name.
2261    ///
2262    /// You can find it at least in [MySQL][1], [BigQuery][2], [PostgreSQL][3]
2263    ///
2264    /// [1]: https://dev.mysql.com/doc/refman/8.0/en/window-functions-named-windows.html
2265    /// [2]: https://cloud.google.com/bigquery/docs/reference/standard-sql/window-function-calls
2266    /// [3]: https://www.postgresql.org/docs/current/sql-expressions.html#SYNTAX-WINDOW-FUNCTIONS
2267    pub window_name: Option<Ident>,
2268    /// `OVER (PARTITION BY ...)`
2269    pub partition_by: Vec<Expr>,
2270    /// `OVER (ORDER BY ...)`
2271    pub order_by: Vec<OrderByExpr>,
2272    /// `OVER (window frame)`
2273    pub window_frame: Option<WindowFrame>,
2274}
2275
2276impl fmt::Display for WindowSpec {
2277    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2278        let mut is_first = true;
2279        if let Some(window_name) = &self.window_name {
2280            if !is_first {
2281                SpaceOrNewline.fmt(f)?;
2282            }
2283            is_first = false;
2284            write!(f, "{window_name}")?;
2285        }
2286        if !self.partition_by.is_empty() {
2287            if !is_first {
2288                SpaceOrNewline.fmt(f)?;
2289            }
2290            is_first = false;
2291            write!(
2292                f,
2293                "PARTITION BY {}",
2294                display_comma_separated(&self.partition_by)
2295            )?;
2296        }
2297        if !self.order_by.is_empty() {
2298            if !is_first {
2299                SpaceOrNewline.fmt(f)?;
2300            }
2301            is_first = false;
2302            write!(f, "ORDER BY {}", display_comma_separated(&self.order_by))?;
2303        }
2304        if let Some(window_frame) = &self.window_frame {
2305            if !is_first {
2306                SpaceOrNewline.fmt(f)?;
2307            }
2308            if let Some(end_bound) = &window_frame.end_bound {
2309                write!(
2310                    f,
2311                    "{} BETWEEN {} AND {}",
2312                    window_frame.units, window_frame.start_bound, end_bound
2313                )?;
2314            } else {
2315                write!(f, "{} {}", window_frame.units, window_frame.start_bound)?;
2316            }
2317        }
2318        Ok(())
2319    }
2320}
2321
2322/// Specifies the data processed by a window function, e.g.
2323/// `RANGE UNBOUNDED PRECEDING` or `ROWS BETWEEN 5 PRECEDING AND CURRENT ROW`.
2324///
2325/// Note: The parser does not validate the specified bounds; the caller should
2326/// reject invalid bounds like `ROWS UNBOUNDED FOLLOWING` before execution.
2327#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2328#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2329#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2330pub struct WindowFrame {
2331    /// Units for the frame (e.g. `ROWS`, `RANGE`, `GROUPS`).
2332    pub units: WindowFrameUnits,
2333    /// The start bound of the window frame.
2334    pub start_bound: WindowFrameBound,
2335    /// The right bound of the `BETWEEN .. AND` clause. The end bound of `None`
2336    /// indicates the shorthand form (e.g. `ROWS 1 PRECEDING`), which must
2337    /// behave the same as `end_bound = WindowFrameBound::CurrentRow`.
2338    pub end_bound: Option<WindowFrameBound>,
2339    // TBD: EXCLUDE
2340}
2341
2342impl Default for WindowFrame {
2343    /// Returns default value for window frame
2344    ///
2345    /// See [this page](https://www.sqlite.org/windowfunctions.html#frame_specifications) for more details.
2346    fn default() -> Self {
2347        Self {
2348            units: WindowFrameUnits::Range,
2349            start_bound: WindowFrameBound::Preceding(None),
2350            end_bound: None,
2351        }
2352    }
2353}
2354
2355#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2356#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2357#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2358/// Units used to describe the window frame scope.
2359pub enum WindowFrameUnits {
2360    /// `ROWS` unit.
2361    Rows,
2362    /// `RANGE` unit.
2363    Range,
2364    /// `GROUPS` unit.
2365    Groups,
2366}
2367
2368impl fmt::Display for WindowFrameUnits {
2369    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2370        f.write_str(match self {
2371            WindowFrameUnits::Rows => "ROWS",
2372            WindowFrameUnits::Range => "RANGE",
2373            WindowFrameUnits::Groups => "GROUPS",
2374        })
2375    }
2376}
2377
2378/// Specifies Ignore / Respect NULL within window functions.
2379/// For example
2380/// `FIRST_VALUE(column2) IGNORE NULLS OVER (PARTITION BY column1)`
2381#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2382#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2383#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2384/// How NULL values are treated in certain window functions.
2385pub enum NullTreatment {
2386    /// Ignore NULL values (e.g. `IGNORE NULLS`).
2387    IgnoreNulls,
2388    /// Respect NULL values (e.g. `RESPECT NULLS`).
2389    RespectNulls,
2390}
2391
2392impl fmt::Display for NullTreatment {
2393    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2394        f.write_str(match self {
2395            NullTreatment::IgnoreNulls => "IGNORE NULLS",
2396            NullTreatment::RespectNulls => "RESPECT NULLS",
2397        })
2398    }
2399}
2400
2401/// Specifies [WindowFrame]'s `start_bound` and `end_bound`
2402#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2403#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2404#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2405pub enum WindowFrameBound {
2406    /// `CURRENT ROW`
2407    CurrentRow,
2408    /// `<N> PRECEDING` or `UNBOUNDED PRECEDING`
2409    Preceding(Option<Box<Expr>>),
2410    /// `<N> FOLLOWING` or `UNBOUNDED FOLLOWING`.
2411    Following(Option<Box<Expr>>),
2412}
2413
2414impl fmt::Display for WindowFrameBound {
2415    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2416        match self {
2417            WindowFrameBound::CurrentRow => f.write_str("CURRENT ROW"),
2418            WindowFrameBound::Preceding(None) => f.write_str("UNBOUNDED PRECEDING"),
2419            WindowFrameBound::Following(None) => f.write_str("UNBOUNDED FOLLOWING"),
2420            WindowFrameBound::Preceding(Some(n)) => write!(f, "{n} PRECEDING"),
2421            WindowFrameBound::Following(Some(n)) => write!(f, "{n} FOLLOWING"),
2422        }
2423    }
2424}
2425
2426#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2427#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2428#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2429/// Indicates partition operation type for partition management statements.
2430pub enum AddDropSync {
2431    /// Add partitions.
2432    ADD,
2433    /// Drop partitions.
2434    DROP,
2435    /// Sync partitions.
2436    SYNC,
2437}
2438
2439impl fmt::Display for AddDropSync {
2440    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2441        match self {
2442            AddDropSync::SYNC => f.write_str("SYNC PARTITIONS"),
2443            AddDropSync::DROP => f.write_str("DROP PARTITIONS"),
2444            AddDropSync::ADD => f.write_str("ADD PARTITIONS"),
2445        }
2446    }
2447}
2448
2449#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2450#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2451#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2452/// Object kinds supported by `SHOW CREATE` statements.
2453pub enum ShowCreateObject {
2454    /// An event object for `SHOW CREATE EVENT`.
2455    Event,
2456    /// A function object for `SHOW CREATE FUNCTION`.
2457    Function,
2458    /// A procedure object for `SHOW CREATE PROCEDURE`.
2459    Procedure,
2460    /// A table object for `SHOW CREATE TABLE`.
2461    Table,
2462    /// A trigger object for `SHOW CREATE TRIGGER`.
2463    Trigger,
2464    /// A view object for `SHOW CREATE VIEW`.
2465    View,
2466}
2467
2468impl fmt::Display for ShowCreateObject {
2469    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2470        match self {
2471            ShowCreateObject::Event => f.write_str("EVENT"),
2472            ShowCreateObject::Function => f.write_str("FUNCTION"),
2473            ShowCreateObject::Procedure => f.write_str("PROCEDURE"),
2474            ShowCreateObject::Table => f.write_str("TABLE"),
2475            ShowCreateObject::Trigger => f.write_str("TRIGGER"),
2476            ShowCreateObject::View => f.write_str("VIEW"),
2477        }
2478    }
2479}
2480
2481#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2482#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2483#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2484/// Objects that can be targeted by a `COMMENT` statement.
2485pub enum CommentObject {
2486    /// A collation.
2487    Collation,
2488    /// A table column.
2489    Column,
2490    /// A database.
2491    Database,
2492    /// A domain.
2493    Domain,
2494    /// An extension.
2495    Extension,
2496    /// A function.
2497    Function,
2498    /// An index.
2499    Index,
2500    /// A materialized view.
2501    MaterializedView,
2502    /// A procedure.
2503    Procedure,
2504    /// A role.
2505    Role,
2506    /// A schema.
2507    Schema,
2508    /// A sequence.
2509    Sequence,
2510    /// A table.
2511    Table,
2512    /// A type.
2513    Type,
2514    /// A user.
2515    User,
2516    /// A view.
2517    View,
2518}
2519
2520impl fmt::Display for CommentObject {
2521    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2522        match self {
2523            CommentObject::Collation => f.write_str("COLLATION"),
2524            CommentObject::Column => f.write_str("COLUMN"),
2525            CommentObject::Database => f.write_str("DATABASE"),
2526            CommentObject::Domain => f.write_str("DOMAIN"),
2527            CommentObject::Extension => f.write_str("EXTENSION"),
2528            CommentObject::Function => f.write_str("FUNCTION"),
2529            CommentObject::Index => f.write_str("INDEX"),
2530            CommentObject::MaterializedView => f.write_str("MATERIALIZED VIEW"),
2531            CommentObject::Procedure => f.write_str("PROCEDURE"),
2532            CommentObject::Role => f.write_str("ROLE"),
2533            CommentObject::Schema => f.write_str("SCHEMA"),
2534            CommentObject::Sequence => f.write_str("SEQUENCE"),
2535            CommentObject::Table => f.write_str("TABLE"),
2536            CommentObject::Type => f.write_str("TYPE"),
2537            CommentObject::User => f.write_str("USER"),
2538            CommentObject::View => f.write_str("VIEW"),
2539        }
2540    }
2541}
2542
2543#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2544#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2545#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2546/// Password specification variants used in user-related statements.
2547pub enum Password {
2548    /// A concrete password expression.
2549    Password(Expr),
2550    /// Represents a `NULL` password.
2551    NullPassword,
2552}
2553
2554/// A `CASE` statement.
2555///
2556/// Examples:
2557/// ```sql
2558/// CASE
2559///     WHEN EXISTS(SELECT 1)
2560///         THEN SELECT 1 FROM T;
2561///     WHEN EXISTS(SELECT 2)
2562///         THEN SELECT 1 FROM U;
2563///     ELSE
2564///         SELECT 1 FROM V;
2565/// END CASE;
2566/// ```
2567///
2568/// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#case_search_expression)
2569/// [Snowflake](https://docs.snowflake.com/en/sql-reference/snowflake-scripting/case)
2570#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2571#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2572#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2573pub struct CaseStatement {
2574    /// The `CASE` token that starts the statement.
2575    pub case_token: AttachedToken,
2576    /// Optional expression to match against in `CASE ... WHEN`.
2577    pub match_expr: Option<Expr>,
2578    /// The `WHEN ... THEN` blocks of the `CASE` statement.
2579    pub when_blocks: Vec<ConditionalStatementBlock>,
2580    /// Optional `ELSE` block for the `CASE` statement.
2581    pub else_block: Option<ConditionalStatementBlock>,
2582    /// The last token of the statement (`END` or `CASE`).
2583    pub end_case_token: AttachedToken,
2584}
2585
2586impl fmt::Display for CaseStatement {
2587    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2588        let CaseStatement {
2589            case_token: _,
2590            match_expr,
2591            when_blocks,
2592            else_block,
2593            end_case_token: AttachedToken(end),
2594        } = self;
2595
2596        write!(f, "CASE")?;
2597
2598        if let Some(expr) = match_expr {
2599            write!(f, " {expr}")?;
2600        }
2601
2602        if !when_blocks.is_empty() {
2603            write!(f, " {}", display_separated(when_blocks, " "))?;
2604        }
2605
2606        if let Some(else_block) = else_block {
2607            write!(f, " {else_block}")?;
2608        }
2609
2610        write!(f, " END")?;
2611
2612        if let Token::Word(w) = &end.token {
2613            if w.keyword == Keyword::CASE {
2614                write!(f, " CASE")?;
2615            }
2616        }
2617
2618        Ok(())
2619    }
2620}
2621
2622/// An `IF` statement.
2623///
2624/// Example (BigQuery or Snowflake):
2625/// ```sql
2626/// IF TRUE THEN
2627///     SELECT 1;
2628///     SELECT 2;
2629/// ELSEIF TRUE THEN
2630///     SELECT 3;
2631/// ELSE
2632///     SELECT 4;
2633/// END IF
2634/// ```
2635/// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#if)
2636/// [Snowflake](https://docs.snowflake.com/en/sql-reference/snowflake-scripting/if)
2637///
2638/// Example (MSSQL):
2639/// ```sql
2640/// IF 1=1 SELECT 1 ELSE SELECT 2
2641/// ```
2642/// [MSSQL](https://learn.microsoft.com/en-us/sql/t-sql/language-elements/if-else-transact-sql?view=sql-server-ver16)
2643#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2644#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2645#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2646pub struct IfStatement {
2647    /// The initial `IF` block containing the condition and statements.
2648    pub if_block: ConditionalStatementBlock,
2649    /// Additional `ELSEIF` blocks.
2650    pub elseif_blocks: Vec<ConditionalStatementBlock>,
2651    /// Optional `ELSE` block.
2652    pub else_block: Option<ConditionalStatementBlock>,
2653    /// Optional trailing `END` token for the `IF` statement.
2654    pub end_token: Option<AttachedToken>,
2655}
2656
2657impl fmt::Display for IfStatement {
2658    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2659        let IfStatement {
2660            if_block,
2661            elseif_blocks,
2662            else_block,
2663            end_token,
2664        } = self;
2665
2666        write!(f, "{if_block}")?;
2667
2668        for elseif_block in elseif_blocks {
2669            write!(f, " {elseif_block}")?;
2670        }
2671
2672        if let Some(else_block) = else_block {
2673            write!(f, " {else_block}")?;
2674        }
2675
2676        if let Some(AttachedToken(end_token)) = end_token {
2677            write!(f, " END {end_token}")?;
2678        }
2679
2680        Ok(())
2681    }
2682}
2683
2684/// A `WHILE` statement.
2685///
2686/// Example:
2687/// ```sql
2688/// WHILE @@FETCH_STATUS = 0
2689/// BEGIN
2690///    FETCH NEXT FROM c1 INTO @var1, @var2;
2691/// END
2692/// ```
2693///
2694/// [MsSql](https://learn.microsoft.com/en-us/sql/t-sql/language-elements/while-transact-sql)
2695#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2696#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2697#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2698pub struct WhileStatement {
2699    /// Block executed while the condition holds.
2700    pub while_block: ConditionalStatementBlock,
2701}
2702
2703impl fmt::Display for WhileStatement {
2704    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2705        let WhileStatement { while_block } = self;
2706        write!(f, "{while_block}")?;
2707        Ok(())
2708    }
2709}
2710
2711/// A block within a [Statement::Case] or [Statement::If] or [Statement::While]-like statement
2712///
2713/// Example 1:
2714/// ```sql
2715/// WHEN EXISTS(SELECT 1) THEN SELECT 1;
2716/// ```
2717///
2718/// Example 2:
2719/// ```sql
2720/// IF TRUE THEN SELECT 1; SELECT 2;
2721/// ```
2722///
2723/// Example 3:
2724/// ```sql
2725/// ELSE SELECT 1; SELECT 2;
2726/// ```
2727///
2728/// Example 4:
2729/// ```sql
2730/// WHILE @@FETCH_STATUS = 0
2731/// BEGIN
2732///    FETCH NEXT FROM c1 INTO @var1, @var2;
2733/// END
2734/// ```
2735#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2736#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2737#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2738pub struct ConditionalStatementBlock {
2739    /// Token representing the start of the block (e.g., WHEN/IF/WHILE).
2740    pub start_token: AttachedToken,
2741    /// Optional condition expression for the block.
2742    pub condition: Option<Expr>,
2743    /// Optional token for the `THEN` keyword.
2744    pub then_token: Option<AttachedToken>,
2745    /// The statements contained in this conditional block.
2746    pub conditional_statements: ConditionalStatements,
2747}
2748
2749impl ConditionalStatementBlock {
2750    /// Get the statements in this conditional block.
2751    pub fn statements(&self) -> &Vec<Statement> {
2752        self.conditional_statements.statements()
2753    }
2754}
2755
2756impl fmt::Display for ConditionalStatementBlock {
2757    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2758        let ConditionalStatementBlock {
2759            start_token: AttachedToken(start_token),
2760            condition,
2761            then_token,
2762            conditional_statements,
2763        } = self;
2764
2765        write!(f, "{start_token}")?;
2766
2767        if let Some(condition) = condition {
2768            write!(f, " {condition}")?;
2769        }
2770
2771        if then_token.is_some() {
2772            write!(f, " THEN")?;
2773        }
2774
2775        if !conditional_statements.statements().is_empty() {
2776            write!(f, " {conditional_statements}")?;
2777        }
2778
2779        Ok(())
2780    }
2781}
2782
2783/// A list of statements in a [ConditionalStatementBlock].
2784#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2785#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2786#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2787/// Statements used inside conditional blocks (`IF`, `WHEN`, `WHILE`).
2788pub enum ConditionalStatements {
2789    /// Simple sequence of statements (no `BEGIN`/`END`).
2790    Sequence {
2791        /// The statements in the sequence.
2792        statements: Vec<Statement>,
2793    },
2794    /// Block enclosed by `BEGIN` and `END`.
2795    BeginEnd(BeginEndStatements),
2796}
2797
2798impl ConditionalStatements {
2799    /// Get the statements in this conditional statements block.
2800    pub fn statements(&self) -> &Vec<Statement> {
2801        match self {
2802            ConditionalStatements::Sequence { statements } => statements,
2803            ConditionalStatements::BeginEnd(bes) => &bes.statements,
2804        }
2805    }
2806}
2807
2808impl fmt::Display for ConditionalStatements {
2809    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2810        match self {
2811            ConditionalStatements::Sequence { statements } => {
2812                if !statements.is_empty() {
2813                    format_statement_list(f, statements)?;
2814                }
2815                Ok(())
2816            }
2817            ConditionalStatements::BeginEnd(bes) => write!(f, "{bes}"),
2818        }
2819    }
2820}
2821
2822/// Represents a list of statements enclosed within `BEGIN` and `END` keywords.
2823/// Example:
2824/// ```sql
2825/// BEGIN
2826///     SELECT 1;
2827///     SELECT 2;
2828/// END
2829/// ```
2830#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2831#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2832#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2833pub struct BeginEndStatements {
2834    /// Token representing the `BEGIN` keyword (may include span info).
2835    pub begin_token: AttachedToken,
2836    /// Statements contained within the block.
2837    pub statements: Vec<Statement>,
2838    /// Token representing the `END` keyword (may include span info).
2839    pub end_token: AttachedToken,
2840}
2841
2842impl fmt::Display for BeginEndStatements {
2843    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2844        let BeginEndStatements {
2845            begin_token: AttachedToken(begin_token),
2846            statements,
2847            end_token: AttachedToken(end_token),
2848        } = self;
2849
2850        if begin_token.token != Token::EOF {
2851            write!(f, "{begin_token} ")?;
2852        }
2853        if !statements.is_empty() {
2854            format_statement_list(f, statements)?;
2855        }
2856        if end_token.token != Token::EOF {
2857            write!(f, " {end_token}")?;
2858        }
2859        Ok(())
2860    }
2861}
2862
2863/// A `RAISE` statement.
2864///
2865/// Examples:
2866/// ```sql
2867/// RAISE USING MESSAGE = 'error';
2868///
2869/// RAISE myerror;
2870/// ```
2871///
2872/// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#raise)
2873/// [Snowflake](https://docs.snowflake.com/en/sql-reference/snowflake-scripting/raise)
2874#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2875#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2876#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2877pub struct RaiseStatement {
2878    /// Optional value provided to the RAISE statement.
2879    pub value: Option<RaiseStatementValue>,
2880}
2881
2882impl fmt::Display for RaiseStatement {
2883    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2884        let RaiseStatement { value } = self;
2885
2886        write!(f, "RAISE")?;
2887        if let Some(value) = value {
2888            write!(f, " {value}")?;
2889        }
2890
2891        Ok(())
2892    }
2893}
2894
2895/// Represents the error value of a [RaiseStatement].
2896#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2897#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2898#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2899pub enum RaiseStatementValue {
2900    /// `RAISE USING MESSAGE = 'error'`
2901    UsingMessage(Expr),
2902    /// `RAISE myerror`
2903    Expr(Expr),
2904}
2905
2906impl fmt::Display for RaiseStatementValue {
2907    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2908        match self {
2909            RaiseStatementValue::Expr(expr) => write!(f, "{expr}"),
2910            RaiseStatementValue::UsingMessage(expr) => write!(f, "USING MESSAGE = {expr}"),
2911        }
2912    }
2913}
2914
2915/// A MSSQL `THROW` statement.
2916///
2917/// ```sql
2918/// THROW [ error_number, message, state ]
2919/// ```
2920///
2921/// [MSSQL](https://learn.microsoft.com/en-us/sql/t-sql/language-elements/throw-transact-sql)
2922#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2923#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2924#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2925pub struct ThrowStatement {
2926    /// Error number expression.
2927    pub error_number: Option<Box<Expr>>,
2928    /// Error message expression.
2929    pub message: Option<Box<Expr>>,
2930    /// State expression.
2931    pub state: Option<Box<Expr>>,
2932}
2933
2934impl fmt::Display for ThrowStatement {
2935    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2936        let ThrowStatement {
2937            error_number,
2938            message,
2939            state,
2940        } = self;
2941
2942        write!(f, "THROW")?;
2943        if let (Some(error_number), Some(message), Some(state)) = (error_number, message, state) {
2944            write!(f, " {error_number}, {message}, {state}")?;
2945        }
2946        Ok(())
2947    }
2948}
2949
2950/// Represents an expression assignment within a variable `DECLARE` statement.
2951///
2952/// Examples:
2953/// ```sql
2954/// DECLARE variable_name := 42
2955/// DECLARE variable_name DEFAULT 42
2956/// ```
2957#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2958#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2959#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2960pub enum DeclareAssignment {
2961    /// Plain expression specified.
2962    Expr(Box<Expr>),
2963
2964    /// Expression assigned via the `DEFAULT` keyword
2965    Default(Box<Expr>),
2966
2967    /// Expression assigned via the `:=` syntax
2968    ///
2969    /// Example:
2970    /// ```sql
2971    /// DECLARE variable_name := 42;
2972    /// ```
2973    DuckAssignment(Box<Expr>),
2974
2975    /// Expression via the `FOR` keyword
2976    ///
2977    /// Example:
2978    /// ```sql
2979    /// DECLARE c1 CURSOR FOR res
2980    /// ```
2981    For(Box<Expr>),
2982
2983    /// Expression via the `=` syntax.
2984    ///
2985    /// Example:
2986    /// ```sql
2987    /// DECLARE @variable AS INT = 100
2988    /// ```
2989    MsSqlAssignment(Box<Expr>),
2990}
2991
2992impl fmt::Display for DeclareAssignment {
2993    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2994        match self {
2995            DeclareAssignment::Expr(expr) => {
2996                write!(f, "{expr}")
2997            }
2998            DeclareAssignment::Default(expr) => {
2999                write!(f, "DEFAULT {expr}")
3000            }
3001            DeclareAssignment::DuckAssignment(expr) => {
3002                write!(f, ":= {expr}")
3003            }
3004            DeclareAssignment::MsSqlAssignment(expr) => {
3005                write!(f, "= {expr}")
3006            }
3007            DeclareAssignment::For(expr) => {
3008                write!(f, "FOR {expr}")
3009            }
3010        }
3011    }
3012}
3013
3014/// Represents the type of a `DECLARE` statement.
3015#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3016#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3017#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3018pub enum DeclareType {
3019    /// Cursor variable type. e.g. [Snowflake] [PostgreSQL] [MsSql]
3020    ///
3021    /// [Snowflake]: https://docs.snowflake.com/en/developer-guide/snowflake-scripting/cursors#declaring-a-cursor
3022    /// [PostgreSQL]: https://www.postgresql.org/docs/current/plpgsql-cursors.html
3023    /// [MsSql]: https://learn.microsoft.com/en-us/sql/t-sql/language-elements/declare-cursor-transact-sql
3024    Cursor,
3025
3026    /// Result set variable type. [Snowflake]
3027    ///
3028    /// Syntax:
3029    /// ```text
3030    /// <resultset_name> RESULTSET [ { DEFAULT | := } ( <query> ) ] ;
3031    /// ```
3032    /// [Snowflake]: https://docs.snowflake.com/en/sql-reference/snowflake-scripting/declare#resultset-declaration-syntax
3033    ResultSet,
3034
3035    /// Exception declaration syntax. [Snowflake]
3036    ///
3037    /// Syntax:
3038    /// ```text
3039    /// <exception_name> EXCEPTION [ ( <exception_number> , '<exception_message>' ) ] ;
3040    /// ```
3041    /// [Snowflake]: https://docs.snowflake.com/en/sql-reference/snowflake-scripting/declare#exception-declaration-syntax
3042    Exception,
3043}
3044
3045impl fmt::Display for DeclareType {
3046    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3047        match self {
3048            DeclareType::Cursor => {
3049                write!(f, "CURSOR")
3050            }
3051            DeclareType::ResultSet => {
3052                write!(f, "RESULTSET")
3053            }
3054            DeclareType::Exception => {
3055                write!(f, "EXCEPTION")
3056            }
3057        }
3058    }
3059}
3060
3061/// A `DECLARE` statement.
3062/// [PostgreSQL] [Snowflake] [BigQuery]
3063///
3064/// Examples:
3065/// ```sql
3066/// DECLARE variable_name := 42
3067/// DECLARE liahona CURSOR FOR SELECT * FROM films;
3068/// ```
3069///
3070/// [PostgreSQL]: https://www.postgresql.org/docs/current/sql-declare.html
3071/// [Snowflake]: https://docs.snowflake.com/en/sql-reference/snowflake-scripting/declare
3072/// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#declare
3073#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3074#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3075#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3076pub struct Declare {
3077    /// The name(s) being declared.
3078    /// Example: `DECLARE a, b, c DEFAULT 42;
3079    pub names: Vec<Ident>,
3080    /// Data-type assigned to the declared variable.
3081    /// Example: `DECLARE x INT64 DEFAULT 42;
3082    pub data_type: Option<DataType>,
3083    /// Expression being assigned to the declared variable.
3084    pub assignment: Option<DeclareAssignment>,
3085    /// Represents the type of the declared variable.
3086    pub declare_type: Option<DeclareType>,
3087    /// Causes the cursor to return data in binary rather than in text format.
3088    pub binary: Option<bool>,
3089    /// None = Not specified
3090    /// Some(true) = INSENSITIVE
3091    /// Some(false) = ASENSITIVE
3092    pub sensitive: Option<bool>,
3093    /// None = Not specified
3094    /// Some(true) = SCROLL
3095    /// Some(false) = NO SCROLL
3096    pub scroll: Option<bool>,
3097    /// None = Not specified
3098    /// Some(true) = WITH HOLD, specifies that the cursor can continue to be used after the transaction that created it successfully commits
3099    /// Some(false) = WITHOUT HOLD, specifies that the cursor cannot be used outside of the transaction that created it
3100    pub hold: Option<bool>,
3101    /// `FOR <query>` clause in a CURSOR declaration.
3102    pub for_query: Option<Box<Query>>,
3103}
3104
3105impl fmt::Display for Declare {
3106    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3107        let Declare {
3108            names,
3109            data_type,
3110            assignment,
3111            declare_type,
3112            binary,
3113            sensitive,
3114            scroll,
3115            hold,
3116            for_query,
3117        } = self;
3118        write!(f, "{}", display_comma_separated(names))?;
3119
3120        if let Some(true) = binary {
3121            write!(f, " BINARY")?;
3122        }
3123
3124        if let Some(sensitive) = sensitive {
3125            if *sensitive {
3126                write!(f, " INSENSITIVE")?;
3127            } else {
3128                write!(f, " ASENSITIVE")?;
3129            }
3130        }
3131
3132        if let Some(scroll) = scroll {
3133            if *scroll {
3134                write!(f, " SCROLL")?;
3135            } else {
3136                write!(f, " NO SCROLL")?;
3137            }
3138        }
3139
3140        if let Some(declare_type) = declare_type {
3141            write!(f, " {declare_type}")?;
3142        }
3143
3144        if let Some(hold) = hold {
3145            if *hold {
3146                write!(f, " WITH HOLD")?;
3147            } else {
3148                write!(f, " WITHOUT HOLD")?;
3149            }
3150        }
3151
3152        if let Some(query) = for_query {
3153            write!(f, " FOR {query}")?;
3154        }
3155
3156        if let Some(data_type) = data_type {
3157            write!(f, " {data_type}")?;
3158        }
3159
3160        if let Some(expr) = assignment {
3161            write!(f, " {expr}")?;
3162        }
3163        Ok(())
3164    }
3165}
3166
3167/// Sql options of a `CREATE TABLE` statement.
3168#[derive(Debug, Default, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3169#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3170#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3171/// Options allowed within a `CREATE TABLE` statement.
3172pub enum CreateTableOptions {
3173    /// No options specified.
3174    #[default]
3175    None,
3176    /// Options specified using the `WITH` keyword, e.g. `WITH (k = v)`.
3177    With(Vec<SqlOption>),
3178    /// Options specified using the `OPTIONS(...)` clause.
3179    Options(Vec<SqlOption>),
3180    /// Plain space-separated options.
3181    Plain(Vec<SqlOption>),
3182    /// Table properties (e.g., TBLPROPERTIES / storage properties).
3183    TableProperties(Vec<SqlOption>),
3184}
3185
3186impl fmt::Display for CreateTableOptions {
3187    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3188        match self {
3189            CreateTableOptions::With(with_options) => {
3190                write!(f, "WITH ({})", display_comma_separated(with_options))
3191            }
3192            CreateTableOptions::Options(options) => {
3193                write!(f, "OPTIONS({})", display_comma_separated(options))
3194            }
3195            CreateTableOptions::TableProperties(options) => {
3196                write!(f, "TBLPROPERTIES ({})", display_comma_separated(options))
3197            }
3198            CreateTableOptions::Plain(options) => {
3199                write!(f, "{}", display_separated(options, " "))
3200            }
3201            CreateTableOptions::None => Ok(()),
3202        }
3203    }
3204}
3205
3206/// A `FROM` clause within a `DELETE` statement.
3207///
3208/// Syntax
3209/// ```sql
3210/// [FROM] table
3211/// ```
3212#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3213#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3214#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3215pub enum FromTable {
3216    /// An explicit `FROM` keyword was specified.
3217    WithFromKeyword(Vec<TableWithJoins>),
3218    /// BigQuery: `FROM` keyword was omitted.
3219    /// <https://cloud.google.com/bigquery/docs/reference/standard-sql/dml-syntax#delete_statement>
3220    WithoutKeyword(Vec<TableWithJoins>),
3221}
3222impl Display for FromTable {
3223    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3224        match self {
3225            FromTable::WithFromKeyword(tables) => {
3226                write!(f, "FROM {}", display_comma_separated(tables))
3227            }
3228            FromTable::WithoutKeyword(tables) => {
3229                write!(f, "{}", display_comma_separated(tables))
3230            }
3231        }
3232    }
3233}
3234
3235#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3236#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3237#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3238/// Variants for the `SET` family of statements.
3239pub enum Set {
3240    /// SQL Standard-style
3241    /// SET a = 1;
3242    /// `SET var = value` (standard SQL-style assignment).
3243    SingleAssignment {
3244        /// Optional scope modifier (`SESSION` / `LOCAL`).
3245        scope: Option<ContextModifier>,
3246        /// Whether this is a Hive-style `HIVEVAR:` assignment.
3247        hivevar: bool,
3248        /// Variable name to assign.
3249        variable: ObjectName,
3250        /// Values assigned to the variable.
3251        values: Vec<Expr>,
3252    },
3253    /// Snowflake-style
3254    /// SET (a, b, ..) = (1, 2, ..);
3255    /// `SET (a, b) = (1, 2)` (tuple assignment syntax).
3256    ParenthesizedAssignments {
3257        /// Variables being assigned in tuple form.
3258        variables: Vec<ObjectName>,
3259        /// Corresponding values for the variables.
3260        values: Vec<Expr>,
3261    },
3262    /// MySQL-style
3263    /// SET a = 1, b = 2, ..;
3264    /// `SET a = 1, b = 2` (MySQL-style comma-separated assignments).
3265    MultipleAssignments {
3266        /// List of `SET` assignments (MySQL-style comma-separated).
3267        assignments: Vec<SetAssignment>,
3268    },
3269    /// Session authorization for Postgres/Redshift
3270    ///
3271    /// ```sql
3272    /// SET SESSION AUTHORIZATION { user_name | DEFAULT }
3273    /// ```
3274    ///
3275    /// See <https://www.postgresql.org/docs/current/sql-set-session-authorization.html>
3276    /// See <https://docs.aws.amazon.com/redshift/latest/dg/r_SET_SESSION_AUTHORIZATION.html>
3277    SetSessionAuthorization(SetSessionAuthorizationParam),
3278    /// MS-SQL session
3279    ///
3280    /// See <https://learn.microsoft.com/en-us/sql/t-sql/statements/set-statements-transact-sql>
3281    SetSessionParam(SetSessionParamKind),
3282    /// ```sql
3283    /// SET [ SESSION | LOCAL ] ROLE role_name
3284    /// ```
3285    ///
3286    /// Sets session state. Examples: [ANSI][1], [Postgresql][2], [MySQL][3], and [Oracle][4]
3287    ///
3288    /// [1]: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#set-role-statement
3289    /// [2]: https://www.postgresql.org/docs/14/sql-set-role.html
3290    /// [3]: https://dev.mysql.com/doc/refman/8.0/en/set-role.html
3291    /// [4]: https://docs.oracle.com/cd/B19306_01/server.102/b14200/statements_10004.htm
3292    SetRole {
3293        /// Non-ANSI optional identifier to inform if the role is defined inside the current session (`SESSION`) or transaction (`LOCAL`).
3294        context_modifier: Option<ContextModifier>,
3295        /// Role name. If NONE is specified, then the current role name is removed.
3296        role_name: Option<Ident>,
3297    },
3298    /// ```sql
3299    /// SET TIME ZONE <value>
3300    /// ```
3301    ///
3302    /// Note: this is a PostgreSQL-specific statements
3303    /// `SET TIME ZONE <value>` is an alias for `SET timezone TO <value>` in PostgreSQL
3304    /// However, we allow it for all dialects.
3305    /// `SET TIME ZONE` statement. `local` indicates the `LOCAL` keyword.
3306    /// `SET TIME ZONE <value>` statement.
3307    SetTimeZone {
3308        /// Whether the `LOCAL` keyword was specified.
3309        local: bool,
3310        /// Time zone expression value.
3311        value: Expr,
3312    },
3313    /// ```sql
3314    /// SET NAMES 'charset_name' [COLLATE 'collation_name']
3315    /// ```
3316    SetNames {
3317        /// Character set name to set.
3318        charset_name: Ident,
3319        /// Optional collation name.
3320        collation_name: Option<String>,
3321    },
3322    /// ```sql
3323    /// SET NAMES DEFAULT
3324    /// ```
3325    ///
3326    /// Note: this is a MySQL-specific statement.
3327    SetNamesDefault {},
3328    /// ```sql
3329    /// SET TRANSACTION ...
3330    /// ```
3331    SetTransaction {
3332        /// Transaction modes (e.g., ISOLATION LEVEL, READ ONLY).
3333        modes: Vec<TransactionMode>,
3334        /// Optional snapshot value for transaction snapshot control.
3335        snapshot: Option<ValueWithSpan>,
3336        /// `true` when the `SESSION` keyword was used.
3337        session: bool,
3338    },
3339}
3340
3341impl Display for Set {
3342    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3343        match self {
3344            Self::ParenthesizedAssignments { variables, values } => write!(
3345                f,
3346                "SET ({}) = ({})",
3347                display_comma_separated(variables),
3348                display_comma_separated(values)
3349            ),
3350            Self::MultipleAssignments { assignments } => {
3351                write!(f, "SET {}", display_comma_separated(assignments))
3352            }
3353            Self::SetRole {
3354                context_modifier,
3355                role_name,
3356            } => {
3357                let role_name = role_name.clone().unwrap_or_else(|| Ident::new("NONE"));
3358                write!(
3359                    f,
3360                    "SET {modifier}ROLE {role_name}",
3361                    modifier = context_modifier.map(|m| format!("{m}")).unwrap_or_default()
3362                )
3363            }
3364            Self::SetSessionAuthorization(kind) => write!(f, "SET SESSION AUTHORIZATION {kind}"),
3365            Self::SetSessionParam(kind) => write!(f, "SET {kind}"),
3366            Self::SetTransaction {
3367                modes,
3368                snapshot,
3369                session,
3370            } => {
3371                if *session {
3372                    write!(f, "SET SESSION CHARACTERISTICS AS TRANSACTION")?;
3373                } else {
3374                    write!(f, "SET TRANSACTION")?;
3375                }
3376                if !modes.is_empty() {
3377                    write!(f, " {}", display_comma_separated(modes))?;
3378                }
3379                if let Some(snapshot_id) = snapshot {
3380                    write!(f, " SNAPSHOT {snapshot_id}")?;
3381                }
3382                Ok(())
3383            }
3384            Self::SetTimeZone { local, value } => {
3385                f.write_str("SET ")?;
3386                if *local {
3387                    f.write_str("LOCAL ")?;
3388                }
3389                write!(f, "TIME ZONE {value}")
3390            }
3391            Self::SetNames {
3392                charset_name,
3393                collation_name,
3394            } => {
3395                write!(f, "SET NAMES {charset_name}")?;
3396
3397                if let Some(collation) = collation_name {
3398                    f.write_str(" COLLATE ")?;
3399                    f.write_str(collation)?;
3400                };
3401
3402                Ok(())
3403            }
3404            Self::SetNamesDefault {} => {
3405                f.write_str("SET NAMES DEFAULT")?;
3406
3407                Ok(())
3408            }
3409            Set::SingleAssignment {
3410                scope,
3411                hivevar,
3412                variable,
3413                values,
3414            } => {
3415                write!(
3416                    f,
3417                    "SET {}{}{} = {}",
3418                    scope.map(|s| format!("{s}")).unwrap_or_default(),
3419                    if *hivevar { "HIVEVAR:" } else { "" },
3420                    variable,
3421                    display_comma_separated(values)
3422                )
3423            }
3424        }
3425    }
3426}
3427
3428/// A representation of a `WHEN` arm with all the identifiers catched and the statements to execute
3429/// for the arm.
3430///
3431/// Snowflake: <https://docs.snowflake.com/en/sql-reference/snowflake-scripting/exception>
3432/// BigQuery: <https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#beginexceptionend>
3433#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3434#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3435#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3436pub struct ExceptionWhen {
3437    /// Identifiers that trigger this branch (error conditions).
3438    pub idents: Vec<Ident>,
3439    /// Statements to execute when the condition matches.
3440    pub statements: Vec<Statement>,
3441}
3442
3443impl Display for ExceptionWhen {
3444    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3445        write!(
3446            f,
3447            "WHEN {idents} THEN",
3448            idents = display_separated(&self.idents, " OR ")
3449        )?;
3450
3451        if !self.statements.is_empty() {
3452            write!(f, " ")?;
3453            format_statement_list(f, &self.statements)?;
3454        }
3455
3456        Ok(())
3457    }
3458}
3459
3460/// ANALYZE statement
3461///
3462/// Supported syntax varies by dialect:
3463/// - Hive: `ANALYZE TABLE t [PARTITION (...)] COMPUTE STATISTICS [NOSCAN] [FOR COLUMNS [col1, ...]] [CACHE METADATA]`
3464/// - PostgreSQL: `ANALYZE [VERBOSE] [t [(col1, ...)]]` See <https://www.postgresql.org/docs/current/sql-analyze.html>
3465/// - General: `ANALYZE [TABLE] t`
3466#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3467#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3468#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3469pub struct Analyze {
3470    #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
3471    /// Name of the table to analyze. `None` for bare `ANALYZE`.
3472    pub table_name: Option<ObjectName>,
3473    /// Optional partition expressions to restrict the analysis.
3474    pub partitions: Option<Vec<Expr>>,
3475    /// `true` when analyzing specific columns (Hive `FOR COLUMNS` syntax).
3476    pub for_columns: bool,
3477    /// Columns to analyze.
3478    pub columns: Vec<Ident>,
3479    /// Whether to cache metadata before analyzing.
3480    pub cache_metadata: bool,
3481    /// Whether to skip scanning the table.
3482    pub noscan: bool,
3483    /// Whether to compute statistics during analysis.
3484    pub compute_statistics: bool,
3485    /// Whether the `TABLE` keyword was present.
3486    pub has_table_keyword: bool,
3487}
3488
3489impl fmt::Display for Analyze {
3490    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3491        write!(f, "ANALYZE")?;
3492        if let Some(ref table_name) = self.table_name {
3493            if self.has_table_keyword {
3494                write!(f, " TABLE")?;
3495            }
3496            write!(f, " {table_name}")?;
3497        }
3498        if !self.for_columns && !self.columns.is_empty() {
3499            write!(f, " ({})", display_comma_separated(&self.columns))?;
3500        }
3501        if let Some(ref parts) = self.partitions {
3502            if !parts.is_empty() {
3503                write!(f, " PARTITION ({})", display_comma_separated(parts))?;
3504            }
3505        }
3506        if self.compute_statistics {
3507            write!(f, " COMPUTE STATISTICS")?;
3508        }
3509        if self.noscan {
3510            write!(f, " NOSCAN")?;
3511        }
3512        if self.cache_metadata {
3513            write!(f, " CACHE METADATA")?;
3514        }
3515        if self.for_columns {
3516            write!(f, " FOR COLUMNS")?;
3517            if !self.columns.is_empty() {
3518                write!(f, " {}", display_comma_separated(&self.columns))?;
3519            }
3520        }
3521        Ok(())
3522    }
3523}
3524
3525/// A top-level statement (SELECT, INSERT, CREATE, etc.)
3526#[allow(clippy::large_enum_variant)]
3527#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3528#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3529#[cfg_attr(
3530    feature = "visitor",
3531    derive(Visit, VisitMut),
3532    visit(with = "visit_statement")
3533)]
3534pub enum Statement {
3535    /// ```sql
3536    /// ANALYZE
3537    /// ```
3538    /// Analyze (Hive)
3539    Analyze(Analyze),
3540    /// `SET` statements (session, transaction, timezone, etc.).
3541    Set(Set),
3542    /// ```sql
3543    /// TRUNCATE
3544    /// ```
3545    /// Truncate (Hive)
3546    Truncate(Truncate),
3547    /// ```sql
3548    /// MSCK
3549    /// ```
3550    /// Msck (Hive)
3551    Msck(Msck),
3552    /// ```sql
3553    /// SELECT
3554    /// ```
3555    Query(Box<Query>),
3556    /// ```sql
3557    /// INSERT
3558    /// ```
3559    Insert(Insert),
3560    /// ```sql
3561    /// INSTALL
3562    /// ```
3563    Install {
3564        /// Only for DuckDB
3565        extension_name: Ident,
3566    },
3567    /// ```sql
3568    /// LOAD
3569    /// ```
3570    Load {
3571        /// Only for DuckDB
3572        extension_name: Ident,
3573    },
3574    // TODO: Support ROW FORMAT
3575    /// LOAD DATA from a directory or query source.
3576    Directory {
3577        /// Whether to overwrite existing files.
3578        overwrite: bool,
3579        /// Whether the directory is local to the server.
3580        local: bool,
3581        /// Path to the directory or files.
3582        path: String,
3583        /// Optional file format for the data.
3584        file_format: Option<FileFormat>,
3585        /// Source query providing data to load.
3586        source: Box<Query>,
3587    },
3588    /// A `CASE` statement.
3589    Case(CaseStatement),
3590    /// An `IF` statement.
3591    If(IfStatement),
3592    /// A `WHILE` statement.
3593    While(WhileStatement),
3594    /// A `RAISE` statement.
3595    Raise(RaiseStatement),
3596    /// ```sql
3597    /// CALL <function>
3598    /// ```
3599    Call(Function),
3600    /// ```sql
3601    /// COPY [TO | FROM] ...
3602    /// ```
3603    Copy {
3604        /// The source of 'COPY TO', or the target of 'COPY FROM'
3605        source: CopySource,
3606        /// If true, is a 'COPY TO' statement. If false is a 'COPY FROM'
3607        to: bool,
3608        /// The target of 'COPY TO', or the source of 'COPY FROM'
3609        target: CopyTarget,
3610        /// WITH options (from PostgreSQL version 9.0)
3611        options: Vec<CopyOption>,
3612        /// WITH options (before PostgreSQL version 9.0)
3613        legacy_options: Vec<CopyLegacyOption>,
3614        /// VALUES a vector of values to be copied
3615        values: Vec<Option<String>>,
3616    },
3617    /// ```sql
3618    /// COPY INTO <table> | <location>
3619    /// ```
3620    /// See:
3621    /// <https://docs.snowflake.com/en/sql-reference/sql/copy-into-table>
3622    /// <https://docs.snowflake.com/en/sql-reference/sql/copy-into-location>
3623    ///
3624    /// Copy Into syntax available for Snowflake is different than the one implemented in
3625    /// Postgres. Although they share common prefix, it is reasonable to implement them
3626    /// in different enums. This can be refactored later once custom dialects
3627    /// are allowed to have custom Statements.
3628    CopyIntoSnowflake {
3629        /// Kind of COPY INTO operation (table or location).
3630        kind: CopyIntoSnowflakeKind,
3631        /// Target object for the COPY INTO operation.
3632        into: ObjectName,
3633        /// Optional list of target columns.
3634        into_columns: Option<Vec<Ident>>,
3635        /// Optional source object name (staged data).
3636        from_obj: Option<ObjectName>,
3637        /// Optional alias for the source object.
3638        from_obj_alias: Option<Ident>,
3639        /// Stage-specific parameters (e.g., credentials, path).
3640        stage_params: StageParamsObject,
3641        /// Optional list of transformations applied when loading.
3642        from_transformations: Option<Vec<StageLoadSelectItemKind>>,
3643        /// Optional source query instead of a staged object.
3644        from_query: Option<Box<Query>>,
3645        /// Optional list of specific file names to load.
3646        files: Option<Vec<String>>,
3647        /// Optional filename matching pattern.
3648        pattern: Option<String>,
3649        /// File format options.
3650        file_format: KeyValueOptions,
3651        /// Additional copy options.
3652        copy_options: KeyValueOptions,
3653        /// Optional validation mode string.
3654        validation_mode: Option<String>,
3655        /// Optional partition expression for loading.
3656        partition: Option<Box<Expr>>,
3657    },
3658    /// ```sql
3659    /// OPEN cursor_name
3660    /// ```
3661    /// Opens a cursor.
3662    Open(OpenStatement),
3663    /// ```sql
3664    /// CLOSE
3665    /// ```
3666    /// Closes the portal underlying an open cursor.
3667    Close {
3668        /// Cursor name
3669        cursor: CloseCursor,
3670    },
3671    /// ```sql
3672    /// UPDATE
3673    /// ```
3674    Update(Update),
3675    /// ```sql
3676    /// DELETE
3677    /// ```
3678    Delete(Delete),
3679    /// ```sql
3680    /// CREATE VIEW
3681    /// ```
3682    CreateView(CreateView),
3683    /// ```sql
3684    /// CREATE TABLE
3685    /// ```
3686    CreateTable(CreateTable),
3687    /// ```sql
3688    /// CREATE VIRTUAL TABLE .. USING <module_name> (<module_args>)`
3689    /// ```
3690    /// Sqlite specific statement
3691    CreateVirtualTable {
3692        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
3693        /// Name of the virtual table module instance.
3694        name: ObjectName,
3695        /// `true` when `IF NOT EXISTS` was specified.
3696        if_not_exists: bool,
3697        /// Module name used by the virtual table.
3698        module_name: Ident,
3699        /// Arguments passed to the module.
3700        module_args: Vec<Ident>,
3701    },
3702    /// ```sql
3703    /// `CREATE INDEX`
3704    /// ```
3705    CreateIndex(CreateIndex),
3706    /// ```sql
3707    /// CREATE ROLE
3708    /// ```
3709    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createrole.html)
3710    CreateRole(CreateRole),
3711    /// ```sql
3712    /// CREATE SECRET
3713    /// ```
3714    /// See [DuckDB](https://duckdb.org/docs/sql/statements/create_secret.html)
3715    CreateSecret {
3716        /// `true` when `OR REPLACE` was specified.
3717        or_replace: bool,
3718        /// Optional `TEMPORARY` flag.
3719        temporary: Option<bool>,
3720        /// `true` when `IF NOT EXISTS` was present.
3721        if_not_exists: bool,
3722        /// Optional secret name.
3723        name: Option<Ident>,
3724        /// Optional storage specifier identifier.
3725        storage_specifier: Option<Ident>,
3726        /// The secret type identifier.
3727        secret_type: Ident,
3728        /// Additional secret options.
3729        options: Vec<SecretOption>,
3730    },
3731    /// A `CREATE SERVER` statement.
3732    CreateServer(CreateServerStatement),
3733    /// ```sql
3734    /// CREATE POLICY
3735    /// ```
3736    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createpolicy.html)
3737    CreatePolicy(CreatePolicy),
3738    /// ```sql
3739    /// CREATE CONNECTOR
3740    /// ```
3741    /// See [Hive](https://cwiki.apache.org/confluence/pages/viewpage.action?pageId=27362034#LanguageManualDDL-CreateDataConnectorCreateConnector)
3742    CreateConnector(CreateConnector),
3743    /// ```sql
3744    /// CREATE OPERATOR
3745    /// ```
3746    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createoperator.html)
3747    CreateOperator(CreateOperator),
3748    /// ```sql
3749    /// CREATE OPERATOR FAMILY
3750    /// ```
3751    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createopfamily.html)
3752    CreateOperatorFamily(CreateOperatorFamily),
3753    /// ```sql
3754    /// CREATE OPERATOR CLASS
3755    /// ```
3756    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createopclass.html)
3757    CreateOperatorClass(CreateOperatorClass),
3758    /// ```sql
3759    /// ALTER TABLE
3760    /// ```
3761    AlterTable(AlterTable),
3762    /// ```sql
3763    /// ALTER SCHEMA
3764    /// ```
3765    /// See [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#alter_schema_collate_statement)
3766    AlterSchema(AlterSchema),
3767    /// ```sql
3768    /// ALTER INDEX
3769    /// ```
3770    AlterIndex {
3771        /// Name of the index to alter.
3772        name: ObjectName,
3773        /// The operation to perform on the index.
3774        operation: AlterIndexOperation,
3775    },
3776    /// ```sql
3777    /// ALTER VIEW
3778    /// ```
3779    AlterView {
3780        /// View name being altered.
3781        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
3782        name: ObjectName,
3783        /// Optional new column list for the view.
3784        columns: Vec<Ident>,
3785        /// Replacement query for the view definition.
3786        query: Box<Query>,
3787        /// Additional WITH options for the view.
3788        with_options: Vec<SqlOption>,
3789    },
3790    /// ```sql
3791    /// ALTER FUNCTION
3792    /// ALTER AGGREGATE
3793    /// ```
3794    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-alterfunction.html)
3795    /// and [PostgreSQL](https://www.postgresql.org/docs/current/sql-alteraggregate.html)
3796    AlterFunction(AlterFunction),
3797    /// ```sql
3798    /// ALTER TYPE
3799    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-altertype.html)
3800    /// ```
3801    AlterType(AlterType),
3802    /// ```sql
3803    /// ALTER COLLATION
3804    /// ```
3805    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-altercollation.html)
3806    AlterCollation(AlterCollation),
3807    /// ```sql
3808    /// ALTER OPERATOR
3809    /// ```
3810    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-alteroperator.html)
3811    AlterOperator(AlterOperator),
3812    /// ```sql
3813    /// ALTER OPERATOR FAMILY
3814    /// ```
3815    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-alteropfamily.html)
3816    AlterOperatorFamily(AlterOperatorFamily),
3817    /// ```sql
3818    /// ALTER OPERATOR CLASS
3819    /// ```
3820    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-alteropclass.html)
3821    AlterOperatorClass(AlterOperatorClass),
3822    /// ```sql
3823    /// ALTER ROLE
3824    /// ```
3825    AlterRole {
3826        /// Role name being altered.
3827        name: Ident,
3828        /// Operation to perform on the role.
3829        operation: AlterRoleOperation,
3830    },
3831    /// ```sql
3832    /// ALTER POLICY <NAME> ON <TABLE NAME> [<OPERATION>]
3833    /// ```
3834    /// (Postgresql-specific)
3835    AlterPolicy(AlterPolicy),
3836    /// ```sql
3837    /// ALTER CONNECTOR connector_name SET DCPROPERTIES(property_name=property_value, ...);
3838    /// or
3839    /// ALTER CONNECTOR connector_name SET URL new_url;
3840    /// or
3841    /// ALTER CONNECTOR connector_name SET OWNER [USER|ROLE] user_or_role;
3842    /// ```
3843    /// (Hive-specific)
3844    AlterConnector {
3845        /// Name of the connector to alter.
3846        name: Ident,
3847        /// Optional connector properties to set.
3848        properties: Option<Vec<SqlOption>>,
3849        /// Optional new URL for the connector.
3850        url: Option<String>,
3851        /// Optional new owner specification.
3852        owner: Option<ddl::AlterConnectorOwner>,
3853    },
3854    /// ```sql
3855    /// ALTER SESSION SET sessionParam
3856    /// ALTER SESSION UNSET <param_name> [ , <param_name> , ... ]
3857    /// ```
3858    /// See <https://docs.snowflake.com/en/sql-reference/sql/alter-session>
3859    AlterSession {
3860        /// true is to set for the session parameters, false is to unset
3861        set: bool,
3862        /// The session parameters to set or unset
3863        session_params: KeyValueOptions,
3864    },
3865    /// ```sql
3866    /// ATTACH DATABASE 'path/to/file' AS alias
3867    /// ```
3868    /// (SQLite-specific)
3869    AttachDatabase {
3870        /// The name to bind to the newly attached database
3871        schema_name: Ident,
3872        /// An expression that indicates the path to the database file
3873        database_file_name: Expr,
3874        /// true if the syntax is 'ATTACH DATABASE', false if it's just 'ATTACH'
3875        database: bool,
3876    },
3877    /// (DuckDB-specific)
3878    /// ```sql
3879    /// ATTACH 'sqlite_file.db' AS sqlite_db (READ_ONLY, TYPE SQLITE);
3880    /// ```
3881    /// See <https://duckdb.org/docs/sql/statements/attach.html>
3882    AttachDuckDBDatabase {
3883        /// `true` when `IF NOT EXISTS` was present.
3884        if_not_exists: bool,
3885        /// `true` if the syntax used `ATTACH DATABASE` rather than `ATTACH`.
3886        database: bool,
3887        /// The path identifier to the database file being attached.
3888        database_path: Ident,
3889        /// Optional alias assigned to the attached database.
3890        database_alias: Option<Ident>,
3891        /// Dialect-specific attach options (e.g., `READ_ONLY`).
3892        attach_options: Vec<AttachDuckDBDatabaseOption>,
3893    },
3894    /// (DuckDB-specific)
3895    /// ```sql
3896    /// DETACH db_alias;
3897    /// ```
3898    /// See <https://duckdb.org/docs/sql/statements/attach.html>
3899    DetachDuckDBDatabase {
3900        /// `true` when `IF EXISTS` was present.
3901        if_exists: bool,
3902        /// `true` if the syntax used `DETACH DATABASE` rather than `DETACH`.
3903        database: bool,
3904        /// Alias of the database to detach.
3905        database_alias: Ident,
3906    },
3907    /// ```sql
3908    /// DROP [TABLE, VIEW, ...]
3909    /// ```
3910    Drop {
3911        /// The type of the object to drop: TABLE, VIEW, etc.
3912        object_type: ObjectType,
3913        /// An optional `IF EXISTS` clause. (Non-standard.)
3914        if_exists: bool,
3915        /// One or more objects to drop. (ANSI SQL requires exactly one.)
3916        names: Vec<ObjectName>,
3917        /// Whether `CASCADE` was specified. This will be `false` when
3918        /// `RESTRICT` or no drop behavior at all was specified.
3919        cascade: bool,
3920        /// Whether `RESTRICT` was specified. This will be `false` when
3921        /// `CASCADE` or no drop behavior at all was specified.
3922        restrict: bool,
3923        /// Hive allows you specify whether the table's stored data will be
3924        /// deleted along with the dropped table
3925        purge: bool,
3926        /// MySQL-specific "TEMPORARY" keyword
3927        temporary: bool,
3928        /// MySQL-specific drop index syntax, which requires table specification
3929        /// See <https://dev.mysql.com/doc/refman/8.4/en/drop-index.html>
3930        table: Option<ObjectName>,
3931    },
3932    /// ```sql
3933    /// DROP FUNCTION
3934    /// ```
3935    DropFunction(DropFunction),
3936    /// ```sql
3937    /// DROP DOMAIN
3938    /// ```
3939    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-dropdomain.html)
3940    ///
3941    /// DROP DOMAIN [ IF EXISTS ] name [, ...] [ CASCADE | RESTRICT ]
3942    ///
3943    DropDomain(DropDomain),
3944    /// ```sql
3945    /// DROP PROCEDURE
3946    /// ```
3947    DropProcedure {
3948        /// `true` when `IF EXISTS` was present.
3949        if_exists: bool,
3950        /// One or more functions/procedures to drop.
3951        proc_desc: Vec<FunctionDesc>,
3952        /// Optional drop behavior (`CASCADE` or `RESTRICT`).
3953        drop_behavior: Option<DropBehavior>,
3954    },
3955    /// ```sql
3956    /// DROP SECRET
3957    /// ```
3958    DropSecret {
3959        /// `true` when `IF EXISTS` was present.
3960        if_exists: bool,
3961        /// Optional `TEMPORARY` marker.
3962        temporary: Option<bool>,
3963        /// Name of the secret to drop.
3964        name: Ident,
3965        /// Optional storage specifier identifier.
3966        storage_specifier: Option<Ident>,
3967    },
3968    ///```sql
3969    /// DROP POLICY
3970    /// ```
3971    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-droppolicy.html)
3972    DropPolicy(DropPolicy),
3973    /// ```sql
3974    /// DROP CONNECTOR
3975    /// ```
3976    /// See [Hive](https://cwiki.apache.org/confluence/pages/viewpage.action?pageId=27362034#LanguageManualDDL-DropConnector)
3977    DropConnector {
3978        /// `true` when `IF EXISTS` was present.
3979        if_exists: bool,
3980        /// Name of the connector to drop.
3981        name: Ident,
3982    },
3983    /// ```sql
3984    /// DECLARE
3985    /// ```
3986    /// Declare Cursor Variables
3987    ///
3988    /// Note: this is a PostgreSQL-specific statement,
3989    /// but may also compatible with other SQL.
3990    Declare {
3991        /// Cursor declaration statements collected by `DECLARE`.
3992        stmts: Vec<Declare>,
3993    },
3994    /// ```sql
3995    /// CREATE EXTENSION [ IF NOT EXISTS ] extension_name
3996    ///     [ WITH ] [ SCHEMA schema_name ]
3997    ///              [ VERSION version ]
3998    ///              [ CASCADE ]
3999    /// ```
4000    ///
4001    /// Note: this is a PostgreSQL-specific statement,
4002    CreateExtension(CreateExtension),
4003    /// ```sql
4004    /// CREATE COLLATION
4005    /// ```
4006    /// Note: this is a PostgreSQL-specific statement.
4007    /// <https://www.postgresql.org/docs/current/sql-createcollation.html>
4008    CreateCollation(CreateCollation),
4009    /// ```sql
4010    /// DROP EXTENSION [ IF EXISTS ] name [, ...] [ CASCADE | RESTRICT ]
4011    /// ```
4012    /// Note: this is a PostgreSQL-specific statement.
4013    /// <https://www.postgresql.org/docs/current/sql-dropextension.html>
4014    DropExtension(DropExtension),
4015    /// ```sql
4016    /// DROP OPERATOR [ IF EXISTS ] name ( { left_type | NONE } , right_type ) [, ...] [ CASCADE | RESTRICT ]
4017    /// ```
4018    /// Note: this is a PostgreSQL-specific statement.
4019    /// <https://www.postgresql.org/docs/current/sql-dropoperator.html>
4020    DropOperator(DropOperator),
4021    /// ```sql
4022    /// DROP OPERATOR FAMILY [ IF EXISTS ] name USING index_method [ CASCADE | RESTRICT ]
4023    /// ```
4024    /// Note: this is a PostgreSQL-specific statement.
4025    /// <https://www.postgresql.org/docs/current/sql-dropopfamily.html>
4026    DropOperatorFamily(DropOperatorFamily),
4027    /// ```sql
4028    /// DROP OPERATOR CLASS [ IF EXISTS ] name USING index_method [ CASCADE | RESTRICT ]
4029    /// ```
4030    /// Note: this is a PostgreSQL-specific statement.
4031    /// <https://www.postgresql.org/docs/current/sql-dropopclass.html>
4032    DropOperatorClass(DropOperatorClass),
4033    /// ```sql
4034    /// FETCH
4035    /// ```
4036    /// Retrieve rows from a query using a cursor
4037    ///
4038    /// Note: this is a PostgreSQL-specific statement,
4039    /// but may also compatible with other SQL.
4040    Fetch {
4041        /// Cursor name
4042        name: Ident,
4043        /// The fetch direction (e.g., `FORWARD`, `BACKWARD`).
4044        direction: FetchDirection,
4045        /// The fetch position (e.g., `ALL`, `NEXT`, `ABSOLUTE`).
4046        position: FetchPosition,
4047        /// Optional target table to fetch rows into.
4048        into: Option<ObjectName>,
4049    },
4050    /// ```sql
4051    /// FLUSH [NO_WRITE_TO_BINLOG | LOCAL] flush_option [, flush_option] ... | tables_option
4052    /// ```
4053    ///
4054    /// Note: this is a Mysql-specific statement,
4055    /// but may also compatible with other SQL.
4056    Flush {
4057        /// The specific flush option or object to flush.
4058        object_type: FlushType,
4059        /// Optional flush location (dialect-specific).
4060        location: Option<FlushLocation>,
4061        /// Optional channel name used for flush operations.
4062        channel: Option<String>,
4063        /// Whether a read lock was requested.
4064        read_lock: bool,
4065        /// Whether this is an export flush operation.
4066        export: bool,
4067        /// Optional list of tables involved in the flush.
4068        tables: Vec<ObjectName>,
4069    },
4070    /// ```sql
4071    /// DISCARD [ ALL | PLANS | SEQUENCES | TEMPORARY | TEMP ]
4072    /// ```
4073    ///
4074    /// Note: this is a PostgreSQL-specific statement,
4075    /// but may also compatible with other SQL.
4076    Discard {
4077        /// The kind of object(s) to discard (ALL, PLANS, etc.).
4078        object_type: DiscardObject,
4079    },
4080    /// `SHOW FUNCTIONS`
4081    ///
4082    /// Note: this is a Presto-specific statement.
4083    ShowFunctions {
4084        /// Optional filter for which functions to display.
4085        filter: Option<ShowStatementFilter>,
4086    },
4087    /// ```sql
4088    /// SHOW <variable>
4089    /// ```
4090    ///
4091    /// Note: this is a PostgreSQL-specific statement.
4092    ShowVariable {
4093        /// Variable name as one or more identifiers.
4094        variable: Vec<Ident>,
4095    },
4096    /// ```sql
4097    /// SHOW [GLOBAL | SESSION] STATUS [LIKE 'pattern' | WHERE expr]
4098    /// ```
4099    ///
4100    /// Note: this is a MySQL-specific statement.
4101    ShowStatus {
4102        /// Optional filter for which status entries to display.
4103        filter: Option<ShowStatementFilter>,
4104        /// `true` when `GLOBAL` scope was requested.
4105        global: bool,
4106        /// `true` when `SESSION` scope was requested.
4107        session: bool,
4108    },
4109    /// ```sql
4110    /// SHOW VARIABLES
4111    /// ```
4112    ///
4113    /// Note: this is a MySQL-specific statement.
4114    ShowVariables {
4115        /// Optional filter for which variables to display.
4116        filter: Option<ShowStatementFilter>,
4117        /// `true` when `GLOBAL` scope was requested.
4118        global: bool,
4119        /// `true` when `SESSION` scope was requested.
4120        session: bool,
4121    },
4122    /// ```sql
4123    /// SHOW CREATE TABLE
4124    /// ```
4125    ///
4126    /// Note: this is a MySQL-specific statement.
4127    ShowCreate {
4128        /// The kind of object being shown (TABLE, VIEW, etc.).
4129        obj_type: ShowCreateObject,
4130        /// The name of the object to show create statement for.
4131        obj_name: ObjectName,
4132    },
4133    /// ```sql
4134    /// SHOW COLUMNS
4135    /// ```
4136    ShowColumns {
4137        /// `true` when extended column information was requested.
4138        extended: bool,
4139        /// `true` when full column details were requested.
4140        full: bool,
4141        /// Additional options for `SHOW COLUMNS`.
4142        show_options: ShowStatementOptions,
4143    },
4144    /// ```sql
4145    /// SHOW CATALOGS
4146    /// ```
4147    ShowCatalogs {
4148        /// `true` when terse output format was requested.
4149        terse: bool,
4150        /// `true` when history information was requested.
4151        history: bool,
4152        /// Additional options for `SHOW CATALOGS`.
4153        show_options: ShowStatementOptions,
4154    },
4155    /// ```sql
4156    /// SHOW DATABASES
4157    /// ```
4158    ShowDatabases {
4159        /// `true` when terse output format was requested.
4160        terse: bool,
4161        /// `true` when history information was requested.
4162        history: bool,
4163        /// Additional options for `SHOW DATABASES`.
4164        show_options: ShowStatementOptions,
4165    },
4166    /// ```sql
4167    /// SHOW [FULL] PROCESSLIST
4168    /// ```
4169    ///
4170    /// Note: this is a MySQL-specific statement.
4171    ShowProcessList {
4172        /// `true` when full process information was requested.
4173        full: bool,
4174    },
4175    /// ```sql
4176    /// SHOW SCHEMAS
4177    /// ```
4178    ShowSchemas {
4179        /// `true` when terse (compact) output was requested.
4180        terse: bool,
4181        /// `true` when history information was requested.
4182        history: bool,
4183        /// Additional options for `SHOW SCHEMAS`.
4184        show_options: ShowStatementOptions,
4185    },
4186    // ```sql
4187    // SHOW {CHARACTER SET | CHARSET}
4188    // ```
4189    // [MySQL]:
4190    // <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>
4191    /// Show the available character sets (alias `CHARSET`).
4192    ShowCharset(ShowCharset),
4193    /// ```sql
4194    /// SHOW OBJECTS LIKE 'line%' IN mydb.public
4195    /// ```
4196    /// Snowflake-specific statement
4197    /// <https://docs.snowflake.com/en/sql-reference/sql/show-objects>
4198    ShowObjects(ShowObjects),
4199    /// ```sql
4200    /// SHOW TABLES
4201    /// ```
4202    ShowTables {
4203        /// `true` when terse output format was requested (compact listing).
4204        terse: bool,
4205        /// `true` when history rows are requested.
4206        history: bool,
4207        /// `true` when extended information should be shown.
4208        extended: bool,
4209        /// `true` when a full listing was requested.
4210        full: bool,
4211        /// `true` when external tables should be included.
4212        external: bool,
4213        /// Additional options for `SHOW` statements.
4214        show_options: ShowStatementOptions,
4215    },
4216    /// ```sql
4217    /// SHOW VIEWS
4218    /// ```
4219    ShowViews {
4220        /// `true` when terse output format was requested.
4221        terse: bool,
4222        /// `true` when materialized views should be included.
4223        materialized: bool,
4224        /// Additional options for `SHOW` statements.
4225        show_options: ShowStatementOptions,
4226    },
4227    /// ```sql
4228    /// SHOW COLLATION
4229    /// ```
4230    ///
4231    /// Note: this is a MySQL-specific statement.
4232    ShowCollation {
4233        /// Optional filter for which collations to display.
4234        filter: Option<ShowStatementFilter>,
4235    },
4236    /// ```sql
4237    /// `USE ...`
4238    /// ```
4239    Use(Use),
4240    /// ```sql
4241    /// START  [ TRANSACTION | WORK ] | START TRANSACTION } ...
4242    /// ```
4243    /// If `begin` is false.
4244    ///
4245    /// ```sql
4246    /// `BEGIN  [ TRANSACTION | WORK ] | START TRANSACTION } ...`
4247    /// ```
4248    /// If `begin` is true
4249    StartTransaction {
4250        /// Transaction modes such as `ISOLATION LEVEL` or `READ WRITE`.
4251        modes: Vec<TransactionMode>,
4252        /// `true` when this was parsed as `BEGIN` instead of `START`.
4253        begin: bool,
4254        /// Optional specific keyword used: `TRANSACTION` or `WORK`.
4255        transaction: Option<BeginTransactionKind>,
4256        /// Optional transaction modifier (e.g., `AND NO CHAIN`).
4257        modifier: Option<TransactionModifier>,
4258        /// List of statements belonging to the `BEGIN` block.
4259        /// Example:
4260        /// ```sql
4261        /// BEGIN
4262        ///     SELECT 1;
4263        ///     SELECT 2;
4264        /// END;
4265        /// ```
4266        statements: Vec<Statement>,
4267        /// Exception handling with exception clauses.
4268        /// Example:
4269        /// ```sql
4270        /// EXCEPTION
4271        ///     WHEN EXCEPTION_1 THEN
4272        ///         SELECT 2;
4273        ///     WHEN EXCEPTION_2 OR EXCEPTION_3 THEN
4274        ///         SELECT 3;
4275        ///     WHEN OTHER THEN
4276        ///         SELECT 4;
4277        /// ```
4278        /// <https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#beginexceptionend>
4279        /// <https://docs.snowflake.com/en/sql-reference/snowflake-scripting/exception>
4280        exception: Option<Vec<ExceptionWhen>>,
4281        /// TRUE if the statement has an `END` keyword.
4282        has_end_keyword: bool,
4283    },
4284    /// ```sql
4285    /// COMMENT ON ...
4286    /// ```
4287    ///
4288    /// Note: this is a PostgreSQL-specific statement.
4289    Comment {
4290        /// Type of object being commented (table, column, etc.).
4291        object_type: CommentObject,
4292        /// Name of the object the comment applies to.
4293        object_name: ObjectName,
4294        /// Optional comment text (None to remove comment).
4295        comment: Option<String>,
4296        /// An optional `IF EXISTS` clause. (Non-standard.)
4297        /// See <https://docs.snowflake.com/en/sql-reference/sql/comment>
4298        if_exists: bool,
4299    },
4300    /// ```sql
4301    /// COMMIT [ TRANSACTION | WORK ] [ AND [ NO ] CHAIN ]
4302    /// ```
4303    /// If `end` is false
4304    ///
4305    /// ```sql
4306    /// END [ TRY | CATCH ]
4307    /// ```
4308    /// If `end` is true
4309    Commit {
4310        /// `true` when `AND [ NO ] CHAIN` was present.
4311        chain: bool,
4312        /// `true` when this `COMMIT` was parsed as an `END` block terminator.
4313        end: bool,
4314        /// Optional transaction modifier for commit semantics.
4315        modifier: Option<TransactionModifier>,
4316    },
4317    /// ```sql
4318    /// ROLLBACK [ TRANSACTION | WORK ] [ AND [ NO ] CHAIN ] [ TO [ SAVEPOINT ] savepoint_name ]
4319    /// ```
4320    Rollback {
4321        /// `true` when `AND [ NO ] CHAIN` was present.
4322        chain: bool,
4323        /// Optional savepoint name to roll back to.
4324        savepoint: Option<Ident>,
4325    },
4326    /// ```sql
4327    /// CREATE SCHEMA
4328    /// ```
4329    CreateSchema {
4330        /// `<schema name> | AUTHORIZATION <schema authorization identifier>  | <schema name>  AUTHORIZATION <schema authorization identifier>`
4331        schema_name: SchemaName,
4332        /// `true` when `IF NOT EXISTS` was present.
4333        if_not_exists: bool,
4334        /// Schema properties.
4335        ///
4336        /// ```sql
4337        /// CREATE SCHEMA myschema WITH (key1='value1');
4338        /// ```
4339        ///
4340        /// [Trino](https://trino.io/docs/current/sql/create-schema.html)
4341        with: Option<Vec<SqlOption>>,
4342        /// Schema options.
4343        ///
4344        /// ```sql
4345        /// CREATE SCHEMA myschema OPTIONS(key1='value1');
4346        /// ```
4347        ///
4348        /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_schema_statement)
4349        options: Option<Vec<SqlOption>>,
4350        /// Default collation specification for the schema.
4351        ///
4352        /// ```sql
4353        /// CREATE SCHEMA myschema DEFAULT COLLATE 'und:ci';
4354        /// ```
4355        ///
4356        /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_schema_statement)
4357        default_collate_spec: Option<Expr>,
4358        /// Clones a schema
4359        ///
4360        /// ```sql
4361        /// CREATE SCHEMA myschema CLONE otherschema
4362        /// ```
4363        ///
4364        /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-clone#databases-schemas)
4365        clone: Option<ObjectName>,
4366    },
4367    /// ```sql
4368    /// CREATE DATABASE
4369    /// ```
4370    /// See:
4371    /// <https://docs.snowflake.com/en/sql-reference/sql/create-database>
4372    CreateDatabase {
4373        /// Database name.
4374        db_name: ObjectName,
4375        /// `IF NOT EXISTS` flag.
4376        if_not_exists: bool,
4377        /// Optional location URI.
4378        location: Option<String>,
4379        /// Optional managed location.
4380        managed_location: Option<String>,
4381        /// `OR REPLACE` flag.
4382        or_replace: bool,
4383        /// `TRANSIENT` flag.
4384        transient: bool,
4385        /// Optional clone source.
4386        clone: Option<ObjectName>,
4387        /// Optional data retention time in days.
4388        data_retention_time_in_days: Option<u64>,
4389        /// Optional maximum data extension time in days.
4390        max_data_extension_time_in_days: Option<u64>,
4391        /// Optional external volume identifier.
4392        external_volume: Option<String>,
4393        /// Optional catalog name.
4394        catalog: Option<String>,
4395        /// Whether to replace invalid characters.
4396        replace_invalid_characters: Option<bool>,
4397        /// Default DDL collation string.
4398        default_ddl_collation: Option<String>,
4399        /// Storage serialization policy.
4400        storage_serialization_policy: Option<StorageSerializationPolicy>,
4401        /// Optional comment.
4402        comment: Option<String>,
4403        /// Optional default character set (MySQL).
4404        default_charset: Option<String>,
4405        /// Optional default collation (MySQL).
4406        default_collation: Option<String>,
4407        /// Optional catalog sync identifier.
4408        catalog_sync: Option<String>,
4409        /// Catalog sync namespace mode.
4410        catalog_sync_namespace_mode: Option<CatalogSyncNamespaceMode>,
4411        /// Optional flatten delimiter for namespace sync.
4412        catalog_sync_namespace_flatten_delimiter: Option<String>,
4413        /// Optional tags for the database.
4414        with_tags: Option<Vec<Tag>>,
4415        /// Optional contact entries for the database.
4416        with_contacts: Option<Vec<ContactEntry>>,
4417    },
4418    /// ```sql
4419    /// CREATE FUNCTION
4420    /// ```
4421    ///
4422    /// Supported variants:
4423    /// 1. [Hive](https://cwiki.apache.org/confluence/display/hive/languagemanual+ddl#LanguageManualDDL-Create/Drop/ReloadFunction)
4424    /// 2. [PostgreSQL](https://www.postgresql.org/docs/15/sql-createfunction.html)
4425    /// 3. [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_function_statement)
4426    /// 4. [MsSql](https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql)
4427    CreateFunction(CreateFunction),
4428    /// CREATE TRIGGER statement. See struct [CreateTrigger] for details.
4429    CreateTrigger(CreateTrigger),
4430    /// DROP TRIGGER statement. See struct [DropTrigger] for details.
4431    DropTrigger(DropTrigger),
4432    /// ```sql
4433    /// CREATE PROCEDURE
4434    /// ```
4435    CreateProcedure {
4436        /// `OR ALTER` flag.
4437        or_alter: bool,
4438        /// Procedure name.
4439        name: ObjectName,
4440        /// Optional procedure parameters.
4441        params: Option<Vec<ProcedureParam>>,
4442        /// Optional language identifier.
4443        language: Option<Ident>,
4444        /// Procedure body statements.
4445        body: ConditionalStatements,
4446    },
4447    /// ```sql
4448    /// CREATE MACRO
4449    /// ```
4450    ///
4451    /// Supported variants:
4452    /// 1. [DuckDB](https://duckdb.org/docs/sql/statements/create_macro)
4453    CreateMacro {
4454        /// `OR REPLACE` flag.
4455        or_replace: bool,
4456        /// Whether macro is temporary.
4457        temporary: bool,
4458        /// Macro name.
4459        name: ObjectName,
4460        /// Optional macro arguments.
4461        args: Option<Vec<MacroArg>>,
4462        /// Macro definition body.
4463        definition: MacroDefinition,
4464    },
4465    /// ```sql
4466    /// CREATE STAGE
4467    /// ```
4468    /// See <https://docs.snowflake.com/en/sql-reference/sql/create-stage>
4469    CreateStage {
4470        /// `OR REPLACE` flag for stage.
4471        or_replace: bool,
4472        /// Whether stage is temporary.
4473        temporary: bool,
4474        /// `IF NOT EXISTS` flag.
4475        if_not_exists: bool,
4476        /// Stage name.
4477        name: ObjectName,
4478        /// Stage parameters.
4479        stage_params: StageParamsObject,
4480        /// Directory table parameters.
4481        directory_table_params: KeyValueOptions,
4482        /// File format options.
4483        file_format: KeyValueOptions,
4484        /// Copy options for stage.
4485        copy_options: KeyValueOptions,
4486        /// Optional comment.
4487        comment: Option<String>,
4488    },
4489    /// ```sql
4490    /// ASSERT <condition> [AS <message>]
4491    /// ```
4492    Assert {
4493        /// Assertion condition expression.
4494        condition: Expr,
4495        /// Optional message expression.
4496        message: Option<Expr>,
4497    },
4498    /// ```sql
4499    /// GRANT privileges ON objects TO grantees
4500    /// ```
4501    Grant(Grant),
4502    /// ```sql
4503    /// DENY privileges ON object TO grantees
4504    /// ```
4505    Deny(DenyStatement),
4506    /// ```sql
4507    /// REVOKE privileges ON objects FROM grantees
4508    /// ```
4509    Revoke(Revoke),
4510    /// ```sql
4511    /// DEALLOCATE [ PREPARE ] { name | ALL }
4512    /// ```
4513    ///
4514    /// Note: this is a PostgreSQL-specific statement.
4515    Deallocate {
4516        /// Name to deallocate (or `ALL`).
4517        name: Ident,
4518        /// Whether `PREPARE` keyword was present.
4519        prepare: bool,
4520    },
4521    /// ```sql
4522    /// An `EXECUTE` statement
4523    /// ```
4524    ///
4525    /// Postgres: <https://www.postgresql.org/docs/current/sql-execute.html>
4526    /// MSSQL: <https://learn.microsoft.com/en-us/sql/relational-databases/stored-procedures/execute-a-stored-procedure>
4527    /// BigQuery: <https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#execute_immediate>
4528    /// Snowflake: <https://docs.snowflake.com/en/sql-reference/sql/execute-immediate>
4529    Execute {
4530        /// Optional function/procedure name.
4531        name: Option<ObjectName>,
4532        /// Parameter expressions passed to execute.
4533        parameters: Vec<Expr>,
4534        /// Whether parentheses were present around `parameters`.
4535        has_parentheses: bool,
4536        /// Is this an `EXECUTE IMMEDIATE`.
4537        immediate: bool,
4538        /// Identifiers to capture results into.
4539        into: Vec<Ident>,
4540        /// `USING` expressions with optional aliases.
4541        using: Vec<ExprWithAlias>,
4542        /// Whether the last parameter is the return value of the procedure
4543        /// MSSQL: <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/execute-transact-sql?view=sql-server-ver17#output>
4544        output: bool,
4545        /// Whether to invoke the procedure with the default parameter values
4546        /// MSSQL: <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/execute-transact-sql?view=sql-server-ver17#default>
4547        default: bool,
4548    },
4549    /// ```sql
4550    /// PREPARE name [ ( data_type [, ...] ) ] AS statement
4551    /// ```
4552    ///
4553    /// Note: this is a PostgreSQL-specific statement.
4554    Prepare {
4555        /// Name of the prepared statement.
4556        name: Ident,
4557        /// Optional data types for parameters.
4558        data_types: Vec<DataType>,
4559        /// Statement being prepared.
4560        statement: Box<Statement>,
4561    },
4562    /// ```sql
4563    /// KILL [CONNECTION | QUERY | MUTATION]
4564    /// ```
4565    ///
4566    /// See <https://clickhouse.com/docs/en/sql-reference/statements/kill/>
4567    /// See <https://dev.mysql.com/doc/refman/8.0/en/kill.html>
4568    Kill {
4569        /// Optional kill modifier (CONNECTION, QUERY, MUTATION).
4570        modifier: Option<KillType>,
4571        // processlist_id
4572        /// The id of the process to kill.
4573        id: u64,
4574    },
4575    /// ```sql
4576    /// [EXPLAIN | DESC | DESCRIBE] TABLE
4577    /// ```
4578    /// Note: this is a MySQL-specific statement. See <https://dev.mysql.com/doc/refman/8.0/en/explain.html>
4579    ExplainTable {
4580        /// `EXPLAIN | DESC | DESCRIBE`
4581        describe_alias: DescribeAlias,
4582        /// Hive style `FORMATTED | EXTENDED`
4583        hive_format: Option<HiveDescribeFormat>,
4584        /// Snowflake and ClickHouse support `DESC|DESCRIBE TABLE <table_name>` syntax
4585        ///
4586        /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/desc-table.html)
4587        /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/describe-table)
4588        has_table_keyword: bool,
4589        /// Table name
4590        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
4591        table_name: ObjectName,
4592    },
4593    /// ```sql
4594    /// [EXPLAIN | DESC | DESCRIBE]  <statement>
4595    /// ```
4596    Explain {
4597        /// `EXPLAIN | DESC | DESCRIBE`
4598        describe_alias: DescribeAlias,
4599        /// Carry out the command and show actual run times and other statistics.
4600        analyze: bool,
4601        /// Display additional information regarding the plan.
4602        verbose: bool,
4603        /// `EXPLAIN QUERY PLAN`
4604        /// Display the query plan without running the query.
4605        ///
4606        /// [SQLite](https://sqlite.org/lang_explain.html)
4607        query_plan: bool,
4608        /// `EXPLAIN ESTIMATE`
4609        /// [Clickhouse](https://clickhouse.com/docs/en/sql-reference/statements/explain#explain-estimate)
4610        estimate: bool,
4611        /// A SQL query that specifies what to explain
4612        statement: Box<Statement>,
4613        /// Optional output format of explain
4614        format: Option<AnalyzeFormatKind>,
4615        /// Postgres style utility options, `(analyze, verbose true)`
4616        options: Option<Vec<UtilityOption>>,
4617    },
4618    /// ```sql
4619    /// SAVEPOINT
4620    /// ```
4621    /// Define a new savepoint within the current transaction
4622    Savepoint {
4623        /// Name of the savepoint being defined.
4624        name: Ident,
4625    },
4626    /// ```sql
4627    /// RELEASE [ SAVEPOINT ] savepoint_name
4628    /// ```
4629    ReleaseSavepoint {
4630        /// Name of the savepoint to release.
4631        name: Ident,
4632    },
4633    /// A `MERGE` statement.
4634    ///
4635    /// ```sql
4636    /// MERGE INTO <target_table> USING <source> ON <join_expr> { matchedClause | notMatchedClause } [ ... ]
4637    /// ```
4638    /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/merge)
4639    /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/dml-syntax#merge_statement)
4640    /// [MSSQL](https://learn.microsoft.com/en-us/sql/t-sql/statements/merge-transact-sql?view=sql-server-ver16)
4641    Merge(Merge),
4642    /// ```sql
4643    /// CACHE [ FLAG ] TABLE <table_name> [ OPTIONS('K1' = 'V1', 'K2' = V2) ] [ AS ] [ <query> ]
4644    /// ```
4645    ///
4646    /// See [Spark SQL docs] for more details.
4647    ///
4648    /// [Spark SQL docs]: https://docs.databricks.com/spark/latest/spark-sql/language-manual/sql-ref-syntax-aux-cache-cache-table.html
4649    Cache {
4650        /// Table flag
4651        table_flag: Option<ObjectName>,
4652        /// Table name
4653        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
4654        table_name: ObjectName,
4655        /// `true` if `AS` keyword was present before the query.
4656        has_as: bool,
4657        /// Table confs
4658        options: Vec<SqlOption>,
4659        /// Cache table as a Query
4660        query: Option<Box<Query>>,
4661    },
4662    /// ```sql
4663    /// UNCACHE TABLE [ IF EXISTS ]  <table_name>
4664    /// ```
4665    UNCache {
4666        /// Table name
4667        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
4668        table_name: ObjectName,
4669        /// `true` when `IF EXISTS` was present.
4670        if_exists: bool,
4671    },
4672    /// ```sql
4673    /// CREATE [ { TEMPORARY | TEMP } ] SEQUENCE [ IF NOT EXISTS ] <sequence_name>
4674    /// ```
4675    /// Define a new sequence:
4676    ///
4677    /// Note: PostgreSQL allows the option clauses (`INCREMENT`, `MINVALUE`,
4678    /// `START`, etc.) to appear in any order.
4679    /// See <https://www.postgresql.org/docs/current/sql-createsequence.html>
4680    CreateSequence {
4681        /// Whether the sequence is temporary.
4682        temporary: bool,
4683        /// `IF NOT EXISTS` flag.
4684        if_not_exists: bool,
4685        /// Sequence name.
4686        name: ObjectName,
4687        /// Optional data type for the sequence.
4688        data_type: Option<DataType>,
4689        /// Sequence options (INCREMENT, MINVALUE, etc.).
4690        sequence_options: Vec<SequenceOptions>,
4691        /// Optional `OWNED BY` target.
4692        owned_by: Option<ObjectName>,
4693    },
4694    /// A `CREATE DOMAIN` statement.
4695    CreateDomain(CreateDomain),
4696    /// ```sql
4697    /// CREATE TYPE <name>
4698    /// ```
4699    CreateType {
4700        /// Type name to create.
4701        name: ObjectName,
4702        /// Optional type representation details.
4703        representation: Option<UserDefinedTypeRepresentation>,
4704    },
4705    /// ```sql
4706    /// PRAGMA <schema-name>.<pragma-name> = <pragma-value>
4707    /// ```
4708    Pragma {
4709        /// Pragma name (possibly qualified).
4710        name: ObjectName,
4711        /// Optional pragma value.
4712        value: Option<ValueWithSpan>,
4713        /// Whether the pragma used `=`.
4714        is_eq: bool,
4715    },
4716    /// ```sql
4717    /// LOCK [ TABLE ] [ ONLY ] name [ * ] [, ...] [ IN lockmode MODE ] [ NOWAIT ]
4718    /// ```
4719    ///
4720    /// See <https://www.postgresql.org/docs/current/sql-lock.html>
4721    Lock(Lock),
4722    /// ```sql
4723    /// LOCK TABLES <table_name> [READ [LOCAL] | [LOW_PRIORITY] WRITE]
4724    /// ```
4725    /// Note: this is a MySQL-specific statement. See <https://dev.mysql.com/doc/refman/8.0/en/lock-tables.html>
4726    LockTables {
4727        /// List of tables to lock with modes.
4728        tables: Vec<LockTable>,
4729    },
4730    /// ```sql
4731    /// UNLOCK TABLES
4732    /// ```
4733    /// Note: this is a MySQL-specific statement. See <https://dev.mysql.com/doc/refman/8.0/en/lock-tables.html>
4734    UnlockTables,
4735    /// Unloads the result of a query to file
4736    ///
4737    /// [Athena](https://docs.aws.amazon.com/athena/latest/ug/unload.html):
4738    /// ```sql
4739    /// UNLOAD(statement) TO <destination> [ WITH options ]
4740    /// ```
4741    ///
4742    /// [Redshift](https://docs.aws.amazon.com/redshift/latest/dg/r_UNLOAD.html):
4743    /// ```sql
4744    /// UNLOAD('statement') TO <destination> [ OPTIONS ]
4745    /// ```
4746    Unload {
4747        /// Optional query AST to unload.
4748        query: Option<Box<Query>>,
4749        /// Optional original query text.
4750        query_text: Option<String>,
4751        /// Destination identifier.
4752        to: Ident,
4753        /// Optional IAM role/auth information.
4754        auth: Option<IamRoleKind>,
4755        /// Additional `WITH` options.
4756        with: Vec<SqlOption>,
4757        /// Legacy copy-style options.
4758        options: Vec<CopyLegacyOption>,
4759    },
4760    /// ClickHouse:
4761    /// ```sql
4762    /// OPTIMIZE TABLE [db.]name [ON CLUSTER cluster] [PARTITION partition | PARTITION ID 'partition_id'] [FINAL] [DEDUPLICATE [BY expression]]
4763    /// ```
4764    /// See ClickHouse <https://clickhouse.com/docs/en/sql-reference/statements/optimize>
4765    ///
4766    /// Databricks:
4767    /// ```sql
4768    /// OPTIMIZE table_name [WHERE predicate] [ZORDER BY (col_name1 [, ...])]
4769    /// ```
4770    /// See Databricks <https://docs.databricks.com/en/sql/language-manual/delta-optimize.html>
4771    OptimizeTable {
4772        /// Table name to optimize.
4773        name: ObjectName,
4774        /// Whether the `TABLE` keyword was present (ClickHouse uses `OPTIMIZE TABLE`, Databricks uses `OPTIMIZE`).
4775        has_table_keyword: bool,
4776        /// Optional cluster identifier.
4777        /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/optimize)
4778        on_cluster: Option<Ident>,
4779        /// Optional partition spec.
4780        /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/optimize)
4781        partition: Option<Partition>,
4782        /// Whether `FINAL` was specified.
4783        /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/optimize)
4784        include_final: bool,
4785        /// Optional deduplication settings.
4786        /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/optimize)
4787        deduplicate: Option<Deduplicate>,
4788        /// Optional WHERE predicate.
4789        /// [Databricks](https://docs.databricks.com/en/sql/language-manual/delta-optimize.html)
4790        predicate: Option<Expr>,
4791        /// Optional ZORDER BY columns.
4792        /// [Databricks](https://docs.databricks.com/en/sql/language-manual/delta-optimize.html)
4793        zorder: Option<Vec<Expr>>,
4794    },
4795    /// ```sql
4796    /// LISTEN
4797    /// ```
4798    /// listen for a notification channel
4799    ///
4800    /// See Postgres <https://www.postgresql.org/docs/current/sql-listen.html>
4801    LISTEN {
4802        /// Notification channel identifier.
4803        channel: Ident,
4804    },
4805    /// ```sql
4806    /// UNLISTEN
4807    /// ```
4808    /// stop listening for a notification
4809    ///
4810    /// See Postgres <https://www.postgresql.org/docs/current/sql-unlisten.html>
4811    UNLISTEN {
4812        /// Notification channel identifier.
4813        channel: Ident,
4814    },
4815    /// ```sql
4816    /// NOTIFY channel [ , payload ]
4817    /// ```
4818    /// send a notification event together with an optional "payload" string to channel
4819    ///
4820    /// See Postgres <https://www.postgresql.org/docs/current/sql-notify.html>
4821    NOTIFY {
4822        /// Notification channel identifier.
4823        channel: Ident,
4824        /// Optional payload string.
4825        payload: Option<String>,
4826    },
4827    /// ```sql
4828    /// LOAD DATA [LOCAL] INPATH 'filepath' [OVERWRITE] INTO TABLE tablename
4829    /// [PARTITION (partcol1=val1, partcol2=val2 ...)]
4830    /// [INPUTFORMAT 'inputformat' SERDE 'serde']
4831    /// ```
4832    /// Loading files into tables
4833    ///
4834    /// See Hive <https://cwiki.apache.org/confluence/pages/viewpage.action?pageId=27362036#LanguageManualDML-Loadingfilesintotables>
4835    LoadData {
4836        /// Whether `LOCAL` is present.
4837        local: bool,
4838        /// Input path for files to load.
4839        inpath: String,
4840        /// Whether `OVERWRITE` was specified.
4841        overwrite: bool,
4842        /// Target table name to load into.
4843        table_name: ObjectName,
4844        /// Optional partition specification.
4845        partitioned: Option<Vec<Expr>>,
4846        /// Optional table format information.
4847        table_format: Option<HiveLoadDataFormat>,
4848    },
4849    /// ```sql
4850    /// Rename TABLE tbl_name TO new_tbl_name[, tbl_name2 TO new_tbl_name2] ...
4851    /// ```
4852    /// Renames one or more tables
4853    ///
4854    /// See Mysql <https://dev.mysql.com/doc/refman/9.1/en/rename-table.html>
4855    RenameTable(Vec<RenameTable>),
4856    /// Snowflake `LIST`
4857    /// See: <https://docs.snowflake.com/en/sql-reference/sql/list>
4858    List(FileStagingCommand),
4859    /// Snowflake `REMOVE`
4860    /// See: <https://docs.snowflake.com/en/sql-reference/sql/remove>
4861    Remove(FileStagingCommand),
4862    /// RaiseError (MSSQL)
4863    /// RAISERROR ( { msg_id | msg_str | @local_variable }
4864    /// { , severity , state }
4865    /// [ , argument [ , ...n ] ] )
4866    /// [ WITH option [ , ...n ] ]
4867    /// See <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/raiserror-transact-sql?view=sql-server-ver16>
4868    RaisError {
4869        /// Error message expression or identifier.
4870        message: Box<Expr>,
4871        /// Severity expression.
4872        severity: Box<Expr>,
4873        /// State expression.
4874        state: Box<Expr>,
4875        /// Substitution arguments for the message.
4876        arguments: Vec<Expr>,
4877        /// Additional `WITH` options for RAISERROR.
4878        options: Vec<RaisErrorOption>,
4879    },
4880    /// A MSSQL `THROW` statement.
4881    Throw(ThrowStatement),
4882    /// ```sql
4883    /// PRINT msg_str | @local_variable | string_expr
4884    /// ```
4885    ///
4886    /// See: <https://learn.microsoft.com/en-us/sql/t-sql/statements/print-transact-sql>
4887    Print(PrintStatement),
4888    /// MSSQL `WAITFOR` statement.
4889    ///
4890    /// See: <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/waitfor-transact-sql>
4891    WaitFor(WaitForStatement),
4892    /// ```sql
4893    /// RETURN [ expression ]
4894    /// ```
4895    ///
4896    /// See [ReturnStatement]
4897    Return(ReturnStatement),
4898    /// Export data statement
4899    ///
4900    /// Example:
4901    /// ```sql
4902    /// EXPORT DATA OPTIONS(uri='gs://bucket/folder/*', format='PARQUET', overwrite=true) AS
4903    /// SELECT field1, field2 FROM mydataset.table1 ORDER BY field1 LIMIT 10
4904    /// ```
4905    /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/export-statements)
4906    ExportData(ExportData),
4907    /// ```sql
4908    /// CREATE [OR REPLACE] USER <user> [IF NOT EXISTS]
4909    /// ```
4910    /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-user)
4911    CreateUser(CreateUser),
4912    /// ```sql
4913    /// ALTER USER \[ IF EXISTS \] \[ <name> \]
4914    /// ```
4915    /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/alter-user)
4916    AlterUser(AlterUser),
4917    /// Re-sorts rows and reclaims space in either a specified table or all tables in the current database
4918    ///
4919    /// ```sql
4920    /// VACUUM tbl
4921    /// ```
4922    /// [Redshift](https://docs.aws.amazon.com/redshift/latest/dg/r_VACUUM_command.html)
4923    Vacuum(VacuumStatement),
4924    /// Restore the value of a run-time parameter to the default value.
4925    ///
4926    /// ```sql
4927    /// RESET configuration_parameter;
4928    /// RESET ALL;
4929    /// ```
4930    /// [PostgreSQL](https://www.postgresql.org/docs/current/sql-reset.html)
4931    Reset(ResetStatement),
4932}
4933
4934impl From<Analyze> for Statement {
4935    fn from(analyze: Analyze) -> Self {
4936        Statement::Analyze(analyze)
4937    }
4938}
4939
4940impl From<ddl::Truncate> for Statement {
4941    fn from(truncate: ddl::Truncate) -> Self {
4942        Statement::Truncate(truncate)
4943    }
4944}
4945
4946impl From<Lock> for Statement {
4947    fn from(lock: Lock) -> Self {
4948        Statement::Lock(lock)
4949    }
4950}
4951
4952impl From<ddl::Msck> for Statement {
4953    fn from(msck: ddl::Msck) -> Self {
4954        Statement::Msck(msck)
4955    }
4956}
4957
4958/// ```sql
4959/// {COPY | REVOKE} CURRENT GRANTS
4960/// ```
4961///
4962/// - [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/grant-ownership#optional-parameters)
4963#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
4964#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4965#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
4966pub enum CurrentGrantsKind {
4967    /// `COPY CURRENT GRANTS` (copy current grants to target).
4968    CopyCurrentGrants,
4969    /// `REVOKE CURRENT GRANTS` (revoke current grants from target).
4970    RevokeCurrentGrants,
4971}
4972
4973impl fmt::Display for CurrentGrantsKind {
4974    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
4975        match self {
4976            CurrentGrantsKind::CopyCurrentGrants => write!(f, "COPY CURRENT GRANTS"),
4977            CurrentGrantsKind::RevokeCurrentGrants => write!(f, "REVOKE CURRENT GRANTS"),
4978        }
4979    }
4980}
4981
4982#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
4983#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4984#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
4985/// `RAISERROR` options
4986/// See <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/raiserror-transact-sql?view=sql-server-ver16#options>
4987pub enum RaisErrorOption {
4988    /// Log the error.
4989    Log,
4990    /// Do not wait for completion.
4991    NoWait,
4992    /// Set the error state.
4993    SetError,
4994}
4995
4996impl fmt::Display for RaisErrorOption {
4997    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
4998        match self {
4999            RaisErrorOption::Log => write!(f, "LOG"),
5000            RaisErrorOption::NoWait => write!(f, "NOWAIT"),
5001            RaisErrorOption::SetError => write!(f, "SETERROR"),
5002        }
5003    }
5004}
5005
5006impl fmt::Display for Statement {
5007    /// Formats a SQL statement with support for pretty printing.
5008    ///
5009    /// When using the alternate flag (`{:#}`), the statement will be formatted with proper
5010    /// indentation and line breaks. For example:
5011    ///
5012    /// ```
5013    /// # use sqlparser::dialect::GenericDialect;
5014    /// # use sqlparser::parser::Parser;
5015    /// let sql = "SELECT a, b FROM table_1";
5016    /// let ast = Parser::parse_sql(&GenericDialect, sql).unwrap();
5017    ///
5018    /// // Regular formatting
5019    /// assert_eq!(format!("{}", ast[0]), "SELECT a, b FROM table_1");
5020    ///
5021    /// // Pretty printing
5022    /// assert_eq!(format!("{:#}", ast[0]),
5023    /// r#"SELECT
5024    ///   a,
5025    ///   b
5026    /// FROM
5027    ///   table_1"#);
5028    /// ```
5029    // Clippy thinks this function is too complicated, but it is painful to
5030    // split up without extracting structs for each `Statement` variant.
5031    #[allow(clippy::cognitive_complexity)]
5032    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
5033        match self {
5034            Statement::Flush {
5035                object_type,
5036                location,
5037                channel,
5038                read_lock,
5039                export,
5040                tables,
5041            } => {
5042                write!(f, "FLUSH")?;
5043                if let Some(location) = location {
5044                    f.write_str(" ")?;
5045                    location.fmt(f)?;
5046                }
5047                write!(f, " {object_type}")?;
5048
5049                if let Some(channel) = channel {
5050                    write!(f, " FOR CHANNEL {channel}")?;
5051                }
5052
5053                write!(
5054                    f,
5055                    "{tables}{read}{export}",
5056                    tables = if !tables.is_empty() {
5057                        format!(" {}", display_comma_separated(tables))
5058                    } else {
5059                        String::new()
5060                    },
5061                    export = if *export { " FOR EXPORT" } else { "" },
5062                    read = if *read_lock { " WITH READ LOCK" } else { "" }
5063                )
5064            }
5065            Statement::Kill { modifier, id } => {
5066                write!(f, "KILL ")?;
5067
5068                if let Some(m) = modifier {
5069                    write!(f, "{m} ")?;
5070                }
5071
5072                write!(f, "{id}")
5073            }
5074            Statement::ExplainTable {
5075                describe_alias,
5076                hive_format,
5077                has_table_keyword,
5078                table_name,
5079            } => {
5080                write!(f, "{describe_alias} ")?;
5081
5082                if let Some(format) = hive_format {
5083                    write!(f, "{format} ")?;
5084                }
5085                if *has_table_keyword {
5086                    write!(f, "TABLE ")?;
5087                }
5088
5089                write!(f, "{table_name}")
5090            }
5091            Statement::Explain {
5092                describe_alias,
5093                verbose,
5094                analyze,
5095                query_plan,
5096                estimate,
5097                statement,
5098                format,
5099                options,
5100            } => {
5101                write!(f, "{describe_alias} ")?;
5102
5103                if *query_plan {
5104                    write!(f, "QUERY PLAN ")?;
5105                }
5106                if *analyze {
5107                    write!(f, "ANALYZE ")?;
5108                }
5109                if *estimate {
5110                    write!(f, "ESTIMATE ")?;
5111                }
5112
5113                if *verbose {
5114                    write!(f, "VERBOSE ")?;
5115                }
5116
5117                if let Some(format) = format {
5118                    write!(f, "{format} ")?;
5119                }
5120
5121                if let Some(options) = options {
5122                    write!(f, "({}) ", display_comma_separated(options))?;
5123                }
5124
5125                write!(f, "{statement}")
5126            }
5127            Statement::Query(s) => s.fmt(f),
5128            Statement::Declare { stmts } => {
5129                write!(f, "DECLARE ")?;
5130                write!(f, "{}", display_separated(stmts, "; "))
5131            }
5132            Statement::Fetch {
5133                name,
5134                direction,
5135                position,
5136                into,
5137            } => {
5138                write!(f, "FETCH {direction} {position} {name}")?;
5139
5140                if let Some(into) = into {
5141                    write!(f, " INTO {into}")?;
5142                }
5143
5144                Ok(())
5145            }
5146            Statement::Directory {
5147                overwrite,
5148                local,
5149                path,
5150                file_format,
5151                source,
5152            } => {
5153                write!(
5154                    f,
5155                    "INSERT{overwrite}{local} DIRECTORY '{path}'",
5156                    overwrite = if *overwrite { " OVERWRITE" } else { "" },
5157                    local = if *local { " LOCAL" } else { "" },
5158                    path = path
5159                )?;
5160                if let Some(ref ff) = file_format {
5161                    write!(f, " STORED AS {ff}")?
5162                }
5163                write!(f, " {source}")
5164            }
5165            Statement::Msck(msck) => msck.fmt(f),
5166            Statement::Truncate(truncate) => truncate.fmt(f),
5167            Statement::Case(stmt) => {
5168                write!(f, "{stmt}")
5169            }
5170            Statement::If(stmt) => {
5171                write!(f, "{stmt}")
5172            }
5173            Statement::While(stmt) => {
5174                write!(f, "{stmt}")
5175            }
5176            Statement::Raise(stmt) => {
5177                write!(f, "{stmt}")
5178            }
5179            Statement::AttachDatabase {
5180                schema_name,
5181                database_file_name,
5182                database,
5183            } => {
5184                let keyword = if *database { "DATABASE " } else { "" };
5185                write!(f, "ATTACH {keyword}{database_file_name} AS {schema_name}")
5186            }
5187            Statement::AttachDuckDBDatabase {
5188                if_not_exists,
5189                database,
5190                database_path,
5191                database_alias,
5192                attach_options,
5193            } => {
5194                write!(
5195                    f,
5196                    "ATTACH{database}{if_not_exists} {database_path}",
5197                    database = if *database { " DATABASE" } else { "" },
5198                    if_not_exists = if *if_not_exists { " IF NOT EXISTS" } else { "" },
5199                )?;
5200                if let Some(alias) = database_alias {
5201                    write!(f, " AS {alias}")?;
5202                }
5203                if !attach_options.is_empty() {
5204                    write!(f, " ({})", display_comma_separated(attach_options))?;
5205                }
5206                Ok(())
5207            }
5208            Statement::DetachDuckDBDatabase {
5209                if_exists,
5210                database,
5211                database_alias,
5212            } => {
5213                write!(
5214                    f,
5215                    "DETACH{database}{if_exists} {database_alias}",
5216                    database = if *database { " DATABASE" } else { "" },
5217                    if_exists = if *if_exists { " IF EXISTS" } else { "" },
5218                )?;
5219                Ok(())
5220            }
5221            Statement::Analyze(analyze) => analyze.fmt(f),
5222            Statement::Insert(insert) => insert.fmt(f),
5223            Statement::Install {
5224                extension_name: name,
5225            } => write!(f, "INSTALL {name}"),
5226
5227            Statement::Load {
5228                extension_name: name,
5229            } => write!(f, "LOAD {name}"),
5230
5231            Statement::Call(function) => write!(f, "CALL {function}"),
5232
5233            Statement::Copy {
5234                source,
5235                to,
5236                target,
5237                options,
5238                legacy_options,
5239                values,
5240            } => {
5241                write!(f, "COPY")?;
5242                match source {
5243                    CopySource::Query(query) => write!(f, " ({query})")?,
5244                    CopySource::Table {
5245                        table_name,
5246                        columns,
5247                    } => {
5248                        write!(f, " {table_name}")?;
5249                        if !columns.is_empty() {
5250                            write!(f, " ({})", display_comma_separated(columns))?;
5251                        }
5252                    }
5253                }
5254                write!(f, " {} {}", if *to { "TO" } else { "FROM" }, target)?;
5255                if !options.is_empty() {
5256                    write!(f, " ({})", display_comma_separated(options))?;
5257                }
5258                if !legacy_options.is_empty() {
5259                    write!(f, " {}", display_separated(legacy_options, " "))?;
5260                }
5261                if !values.is_empty() {
5262                    writeln!(f, ";")?;
5263                    let mut delim = "";
5264                    for v in values {
5265                        write!(f, "{delim}")?;
5266                        delim = "\t";
5267                        if let Some(v) = v {
5268                            write!(f, "{v}")?;
5269                        } else {
5270                            write!(f, "\\N")?;
5271                        }
5272                    }
5273                    write!(f, "\n\\.")?;
5274                }
5275                Ok(())
5276            }
5277            Statement::Update(update) => update.fmt(f),
5278            Statement::Delete(delete) => delete.fmt(f),
5279            Statement::Open(open) => open.fmt(f),
5280            Statement::Close { cursor } => {
5281                write!(f, "CLOSE {cursor}")?;
5282
5283                Ok(())
5284            }
5285            Statement::CreateDatabase {
5286                db_name,
5287                if_not_exists,
5288                location,
5289                managed_location,
5290                or_replace,
5291                transient,
5292                clone,
5293                data_retention_time_in_days,
5294                max_data_extension_time_in_days,
5295                external_volume,
5296                catalog,
5297                replace_invalid_characters,
5298                default_ddl_collation,
5299                storage_serialization_policy,
5300                comment,
5301                default_charset,
5302                default_collation,
5303                catalog_sync,
5304                catalog_sync_namespace_mode,
5305                catalog_sync_namespace_flatten_delimiter,
5306                with_tags,
5307                with_contacts,
5308            } => {
5309                write!(
5310                    f,
5311                    "CREATE {or_replace}{transient}DATABASE {if_not_exists}{name}",
5312                    or_replace = if *or_replace { "OR REPLACE " } else { "" },
5313                    transient = if *transient { "TRANSIENT " } else { "" },
5314                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
5315                    name = db_name,
5316                )?;
5317
5318                if let Some(l) = location {
5319                    write!(f, " LOCATION '{l}'")?;
5320                }
5321                if let Some(ml) = managed_location {
5322                    write!(f, " MANAGEDLOCATION '{ml}'")?;
5323                }
5324                if let Some(clone) = clone {
5325                    write!(f, " CLONE {clone}")?;
5326                }
5327
5328                if let Some(value) = data_retention_time_in_days {
5329                    write!(f, " DATA_RETENTION_TIME_IN_DAYS = {value}")?;
5330                }
5331
5332                if let Some(value) = max_data_extension_time_in_days {
5333                    write!(f, " MAX_DATA_EXTENSION_TIME_IN_DAYS = {value}")?;
5334                }
5335
5336                if let Some(vol) = external_volume {
5337                    write!(f, " EXTERNAL_VOLUME = '{vol}'")?;
5338                }
5339
5340                if let Some(cat) = catalog {
5341                    write!(f, " CATALOG = '{cat}'")?;
5342                }
5343
5344                if let Some(true) = replace_invalid_characters {
5345                    write!(f, " REPLACE_INVALID_CHARACTERS = TRUE")?;
5346                } else if let Some(false) = replace_invalid_characters {
5347                    write!(f, " REPLACE_INVALID_CHARACTERS = FALSE")?;
5348                }
5349
5350                if let Some(collation) = default_ddl_collation {
5351                    write!(f, " DEFAULT_DDL_COLLATION = '{collation}'")?;
5352                }
5353
5354                if let Some(policy) = storage_serialization_policy {
5355                    write!(f, " STORAGE_SERIALIZATION_POLICY = {policy}")?;
5356                }
5357
5358                if let Some(comment) = comment {
5359                    write!(f, " COMMENT = '{comment}'")?;
5360                }
5361
5362                if let Some(charset) = default_charset {
5363                    write!(f, " DEFAULT CHARACTER SET {charset}")?;
5364                }
5365
5366                if let Some(collation) = default_collation {
5367                    write!(f, " DEFAULT COLLATE {collation}")?;
5368                }
5369
5370                if let Some(sync) = catalog_sync {
5371                    write!(f, " CATALOG_SYNC = '{sync}'")?;
5372                }
5373
5374                if let Some(mode) = catalog_sync_namespace_mode {
5375                    write!(f, " CATALOG_SYNC_NAMESPACE_MODE = {mode}")?;
5376                }
5377
5378                if let Some(delim) = catalog_sync_namespace_flatten_delimiter {
5379                    write!(f, " CATALOG_SYNC_NAMESPACE_FLATTEN_DELIMITER = '{delim}'")?;
5380                }
5381
5382                if let Some(tags) = with_tags {
5383                    write!(f, " WITH TAG ({})", display_comma_separated(tags))?;
5384                }
5385
5386                if let Some(contacts) = with_contacts {
5387                    write!(f, " WITH CONTACT ({})", display_comma_separated(contacts))?;
5388                }
5389                Ok(())
5390            }
5391            Statement::CreateFunction(create_function) => create_function.fmt(f),
5392            Statement::CreateDomain(create_domain) => create_domain.fmt(f),
5393            Statement::CreateTrigger(create_trigger) => create_trigger.fmt(f),
5394            Statement::DropTrigger(drop_trigger) => drop_trigger.fmt(f),
5395            Statement::CreateProcedure {
5396                name,
5397                or_alter,
5398                params,
5399                language,
5400                body,
5401            } => {
5402                write!(
5403                    f,
5404                    "CREATE {or_alter}PROCEDURE {name}",
5405                    or_alter = if *or_alter { "OR ALTER " } else { "" },
5406                    name = name
5407                )?;
5408
5409                if let Some(p) = params {
5410                    if !p.is_empty() {
5411                        write!(f, " ({})", display_comma_separated(p))?;
5412                    }
5413                }
5414
5415                if let Some(language) = language {
5416                    write!(f, " LANGUAGE {language}")?;
5417                }
5418
5419                write!(f, " AS {body}")
5420            }
5421            Statement::CreateMacro {
5422                or_replace,
5423                temporary,
5424                name,
5425                args,
5426                definition,
5427            } => {
5428                write!(
5429                    f,
5430                    "CREATE {or_replace}{temp}MACRO {name}",
5431                    temp = if *temporary { "TEMPORARY " } else { "" },
5432                    or_replace = if *or_replace { "OR REPLACE " } else { "" },
5433                )?;
5434                if let Some(args) = args {
5435                    write!(f, "({})", display_comma_separated(args))?;
5436                }
5437                match definition {
5438                    MacroDefinition::Expr(expr) => write!(f, " AS {expr}")?,
5439                    MacroDefinition::Table(query) => write!(f, " AS TABLE {query}")?,
5440                }
5441                Ok(())
5442            }
5443            Statement::CreateView(create_view) => create_view.fmt(f),
5444            Statement::CreateTable(create_table) => create_table.fmt(f),
5445            Statement::LoadData {
5446                local,
5447                inpath,
5448                overwrite,
5449                table_name,
5450                partitioned,
5451                table_format,
5452            } => {
5453                write!(
5454                    f,
5455                    "LOAD DATA {local}INPATH '{inpath}' {overwrite}INTO TABLE {table_name}",
5456                    local = if *local { "LOCAL " } else { "" },
5457                    inpath = inpath,
5458                    overwrite = if *overwrite { "OVERWRITE " } else { "" },
5459                    table_name = table_name,
5460                )?;
5461                if let Some(ref parts) = &partitioned {
5462                    if !parts.is_empty() {
5463                        write!(f, " PARTITION ({})", display_comma_separated(parts))?;
5464                    }
5465                }
5466                if let Some(HiveLoadDataFormat {
5467                    serde,
5468                    input_format,
5469                }) = &table_format
5470                {
5471                    write!(f, " INPUTFORMAT {input_format} SERDE {serde}")?;
5472                }
5473                Ok(())
5474            }
5475            Statement::CreateVirtualTable {
5476                name,
5477                if_not_exists,
5478                module_name,
5479                module_args,
5480            } => {
5481                write!(
5482                    f,
5483                    "CREATE VIRTUAL TABLE {if_not_exists}{name} USING {module_name}",
5484                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
5485                    name = name,
5486                    module_name = module_name
5487                )?;
5488                if !module_args.is_empty() {
5489                    write!(f, " ({})", display_comma_separated(module_args))?;
5490                }
5491                Ok(())
5492            }
5493            Statement::CreateIndex(create_index) => create_index.fmt(f),
5494            Statement::CreateExtension(create_extension) => write!(f, "{create_extension}"),
5495            Statement::CreateCollation(create_collation) => write!(f, "{create_collation}"),
5496            Statement::DropExtension(drop_extension) => write!(f, "{drop_extension}"),
5497            Statement::DropOperator(drop_operator) => write!(f, "{drop_operator}"),
5498            Statement::DropOperatorFamily(drop_operator_family) => {
5499                write!(f, "{drop_operator_family}")
5500            }
5501            Statement::DropOperatorClass(drop_operator_class) => {
5502                write!(f, "{drop_operator_class}")
5503            }
5504            Statement::CreateRole(create_role) => write!(f, "{create_role}"),
5505            Statement::CreateSecret {
5506                or_replace,
5507                temporary,
5508                if_not_exists,
5509                name,
5510                storage_specifier,
5511                secret_type,
5512                options,
5513            } => {
5514                write!(
5515                    f,
5516                    "CREATE {or_replace}",
5517                    or_replace = if *or_replace { "OR REPLACE " } else { "" },
5518                )?;
5519                if let Some(t) = temporary {
5520                    write!(f, "{}", if *t { "TEMPORARY " } else { "PERSISTENT " })?;
5521                }
5522                write!(
5523                    f,
5524                    "SECRET {if_not_exists}",
5525                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
5526                )?;
5527                if let Some(n) = name {
5528                    write!(f, "{n} ")?;
5529                };
5530                if let Some(s) = storage_specifier {
5531                    write!(f, "IN {s} ")?;
5532                }
5533                write!(f, "( TYPE {secret_type}",)?;
5534                if !options.is_empty() {
5535                    write!(f, ", {o}", o = display_comma_separated(options))?;
5536                }
5537                write!(f, " )")?;
5538                Ok(())
5539            }
5540            Statement::CreateServer(stmt) => {
5541                write!(f, "{stmt}")
5542            }
5543            Statement::CreatePolicy(policy) => write!(f, "{policy}"),
5544            Statement::CreateConnector(create_connector) => create_connector.fmt(f),
5545            Statement::CreateOperator(create_operator) => create_operator.fmt(f),
5546            Statement::CreateOperatorFamily(create_operator_family) => {
5547                create_operator_family.fmt(f)
5548            }
5549            Statement::CreateOperatorClass(create_operator_class) => create_operator_class.fmt(f),
5550            Statement::AlterTable(alter_table) => write!(f, "{alter_table}"),
5551            Statement::AlterIndex { name, operation } => {
5552                write!(f, "ALTER INDEX {name} {operation}")
5553            }
5554            Statement::AlterView {
5555                name,
5556                columns,
5557                query,
5558                with_options,
5559            } => {
5560                write!(f, "ALTER VIEW {name}")?;
5561                if !with_options.is_empty() {
5562                    write!(f, " WITH ({})", display_comma_separated(with_options))?;
5563                }
5564                if !columns.is_empty() {
5565                    write!(f, " ({})", display_comma_separated(columns))?;
5566                }
5567                write!(f, " AS {query}")
5568            }
5569            Statement::AlterFunction(alter_function) => write!(f, "{alter_function}"),
5570            Statement::AlterType(AlterType { name, operation }) => {
5571                write!(f, "ALTER TYPE {name} {operation}")
5572            }
5573            Statement::AlterCollation(alter_collation) => write!(f, "{alter_collation}"),
5574            Statement::AlterOperator(alter_operator) => write!(f, "{alter_operator}"),
5575            Statement::AlterOperatorFamily(alter_operator_family) => {
5576                write!(f, "{alter_operator_family}")
5577            }
5578            Statement::AlterOperatorClass(alter_operator_class) => {
5579                write!(f, "{alter_operator_class}")
5580            }
5581            Statement::AlterRole { name, operation } => {
5582                write!(f, "ALTER ROLE {name} {operation}")
5583            }
5584            Statement::AlterPolicy(alter_policy) => write!(f, "{alter_policy}"),
5585            Statement::AlterConnector {
5586                name,
5587                properties,
5588                url,
5589                owner,
5590            } => {
5591                write!(f, "ALTER CONNECTOR {name}")?;
5592                if let Some(properties) = properties {
5593                    write!(
5594                        f,
5595                        " SET DCPROPERTIES({})",
5596                        display_comma_separated(properties)
5597                    )?;
5598                }
5599                if let Some(url) = url {
5600                    write!(f, " SET URL '{url}'")?;
5601                }
5602                if let Some(owner) = owner {
5603                    write!(f, " SET OWNER {owner}")?;
5604                }
5605                Ok(())
5606            }
5607            Statement::AlterSession {
5608                set,
5609                session_params,
5610            } => {
5611                write!(
5612                    f,
5613                    "ALTER SESSION {set}",
5614                    set = if *set { "SET" } else { "UNSET" }
5615                )?;
5616                if !session_params.options.is_empty() {
5617                    if *set {
5618                        write!(f, " {session_params}")?;
5619                    } else {
5620                        let options = session_params
5621                            .options
5622                            .iter()
5623                            .map(|p| p.option_name.clone())
5624                            .collect::<Vec<_>>();
5625                        write!(f, " {}", display_separated(&options, ", "))?;
5626                    }
5627                }
5628                Ok(())
5629            }
5630            Statement::Drop {
5631                object_type,
5632                if_exists,
5633                names,
5634                cascade,
5635                restrict,
5636                purge,
5637                temporary,
5638                table,
5639            } => {
5640                write!(
5641                    f,
5642                    "DROP {}{}{} {}{}{}{}",
5643                    if *temporary { "TEMPORARY " } else { "" },
5644                    object_type,
5645                    if *if_exists { " IF EXISTS" } else { "" },
5646                    display_comma_separated(names),
5647                    if *cascade { " CASCADE" } else { "" },
5648                    if *restrict { " RESTRICT" } else { "" },
5649                    if *purge { " PURGE" } else { "" },
5650                )?;
5651                if let Some(table_name) = table.as_ref() {
5652                    write!(f, " ON {table_name}")?;
5653                };
5654                Ok(())
5655            }
5656            Statement::DropFunction(drop_function) => write!(f, "{drop_function}"),
5657            Statement::DropDomain(DropDomain {
5658                if_exists,
5659                name,
5660                drop_behavior,
5661            }) => {
5662                write!(
5663                    f,
5664                    "DROP DOMAIN{} {name}",
5665                    if *if_exists { " IF EXISTS" } else { "" },
5666                )?;
5667                if let Some(op) = drop_behavior {
5668                    write!(f, " {op}")?;
5669                }
5670                Ok(())
5671            }
5672            Statement::DropProcedure {
5673                if_exists,
5674                proc_desc,
5675                drop_behavior,
5676            } => {
5677                write!(
5678                    f,
5679                    "DROP PROCEDURE{} {}",
5680                    if *if_exists { " IF EXISTS" } else { "" },
5681                    display_comma_separated(proc_desc),
5682                )?;
5683                if let Some(op) = drop_behavior {
5684                    write!(f, " {op}")?;
5685                }
5686                Ok(())
5687            }
5688            Statement::DropSecret {
5689                if_exists,
5690                temporary,
5691                name,
5692                storage_specifier,
5693            } => {
5694                write!(f, "DROP ")?;
5695                if let Some(t) = temporary {
5696                    write!(f, "{}", if *t { "TEMPORARY " } else { "PERSISTENT " })?;
5697                }
5698                write!(
5699                    f,
5700                    "SECRET {if_exists}{name}",
5701                    if_exists = if *if_exists { "IF EXISTS " } else { "" },
5702                )?;
5703                if let Some(s) = storage_specifier {
5704                    write!(f, " FROM {s}")?;
5705                }
5706                Ok(())
5707            }
5708            Statement::DropPolicy(policy) => write!(f, "{policy}"),
5709            Statement::DropConnector { if_exists, name } => {
5710                write!(
5711                    f,
5712                    "DROP CONNECTOR {if_exists}{name}",
5713                    if_exists = if *if_exists { "IF EXISTS " } else { "" }
5714                )?;
5715                Ok(())
5716            }
5717            Statement::Discard { object_type } => {
5718                write!(f, "DISCARD {object_type}")?;
5719                Ok(())
5720            }
5721            Self::Set(set) => write!(f, "{set}"),
5722            Statement::ShowVariable { variable } => {
5723                write!(f, "SHOW")?;
5724                if !variable.is_empty() {
5725                    write!(f, " {}", display_separated(variable, " "))?;
5726                }
5727                Ok(())
5728            }
5729            Statement::ShowStatus {
5730                filter,
5731                global,
5732                session,
5733            } => {
5734                write!(f, "SHOW")?;
5735                if *global {
5736                    write!(f, " GLOBAL")?;
5737                }
5738                if *session {
5739                    write!(f, " SESSION")?;
5740                }
5741                write!(f, " STATUS")?;
5742                if let Some(filter) = filter {
5743                    write!(f, " {}", filter)?;
5744                }
5745                Ok(())
5746            }
5747            Statement::ShowVariables {
5748                filter,
5749                global,
5750                session,
5751            } => {
5752                write!(f, "SHOW")?;
5753                if *global {
5754                    write!(f, " GLOBAL")?;
5755                }
5756                if *session {
5757                    write!(f, " SESSION")?;
5758                }
5759                write!(f, " VARIABLES")?;
5760                if let Some(filter) = filter {
5761                    write!(f, " {}", filter)?;
5762                }
5763                Ok(())
5764            }
5765            Statement::ShowCreate { obj_type, obj_name } => {
5766                write!(f, "SHOW CREATE {obj_type} {obj_name}",)?;
5767                Ok(())
5768            }
5769            Statement::ShowColumns {
5770                extended,
5771                full,
5772                show_options,
5773            } => {
5774                write!(
5775                    f,
5776                    "SHOW {extended}{full}COLUMNS{show_options}",
5777                    extended = if *extended { "EXTENDED " } else { "" },
5778                    full = if *full { "FULL " } else { "" },
5779                )?;
5780                Ok(())
5781            }
5782            Statement::ShowDatabases {
5783                terse,
5784                history,
5785                show_options,
5786            } => {
5787                write!(
5788                    f,
5789                    "SHOW {terse}DATABASES{history}{show_options}",
5790                    terse = if *terse { "TERSE " } else { "" },
5791                    history = if *history { " HISTORY" } else { "" },
5792                )?;
5793                Ok(())
5794            }
5795            Statement::ShowCatalogs {
5796                terse,
5797                history,
5798                show_options,
5799            } => {
5800                write!(
5801                    f,
5802                    "SHOW {terse}CATALOGS{history}{show_options}",
5803                    terse = if *terse { "TERSE " } else { "" },
5804                    history = if *history { " HISTORY" } else { "" },
5805                )?;
5806                Ok(())
5807            }
5808            Statement::ShowProcessList { full } => {
5809                write!(
5810                    f,
5811                    "SHOW {full}PROCESSLIST",
5812                    full = if *full { "FULL " } else { "" },
5813                )?;
5814                Ok(())
5815            }
5816            Statement::ShowSchemas {
5817                terse,
5818                history,
5819                show_options,
5820            } => {
5821                write!(
5822                    f,
5823                    "SHOW {terse}SCHEMAS{history}{show_options}",
5824                    terse = if *terse { "TERSE " } else { "" },
5825                    history = if *history { " HISTORY" } else { "" },
5826                )?;
5827                Ok(())
5828            }
5829            Statement::ShowObjects(ShowObjects {
5830                terse,
5831                show_options,
5832            }) => {
5833                write!(
5834                    f,
5835                    "SHOW {terse}OBJECTS{show_options}",
5836                    terse = if *terse { "TERSE " } else { "" },
5837                )?;
5838                Ok(())
5839            }
5840            Statement::ShowTables {
5841                terse,
5842                history,
5843                extended,
5844                full,
5845                external,
5846                show_options,
5847            } => {
5848                write!(
5849                    f,
5850                    "SHOW {terse}{extended}{full}{external}TABLES{history}{show_options}",
5851                    terse = if *terse { "TERSE " } else { "" },
5852                    extended = if *extended { "EXTENDED " } else { "" },
5853                    full = if *full { "FULL " } else { "" },
5854                    external = if *external { "EXTERNAL " } else { "" },
5855                    history = if *history { " HISTORY" } else { "" },
5856                )?;
5857                Ok(())
5858            }
5859            Statement::ShowViews {
5860                terse,
5861                materialized,
5862                show_options,
5863            } => {
5864                write!(
5865                    f,
5866                    "SHOW {terse}{materialized}VIEWS{show_options}",
5867                    terse = if *terse { "TERSE " } else { "" },
5868                    materialized = if *materialized { "MATERIALIZED " } else { "" }
5869                )?;
5870                Ok(())
5871            }
5872            Statement::ShowFunctions { filter } => {
5873                write!(f, "SHOW FUNCTIONS")?;
5874                if let Some(filter) = filter {
5875                    write!(f, " {filter}")?;
5876                }
5877                Ok(())
5878            }
5879            Statement::Use(use_expr) => use_expr.fmt(f),
5880            Statement::ShowCollation { filter } => {
5881                write!(f, "SHOW COLLATION")?;
5882                if let Some(filter) = filter {
5883                    write!(f, " {filter}")?;
5884                }
5885                Ok(())
5886            }
5887            Statement::ShowCharset(show_stm) => show_stm.fmt(f),
5888            Statement::StartTransaction {
5889                modes,
5890                begin: syntax_begin,
5891                transaction,
5892                modifier,
5893                statements,
5894                exception,
5895                has_end_keyword,
5896            } => {
5897                if *syntax_begin {
5898                    if let Some(modifier) = *modifier {
5899                        write!(f, "BEGIN {modifier}")?;
5900                    } else {
5901                        write!(f, "BEGIN")?;
5902                    }
5903                } else {
5904                    write!(f, "START")?;
5905                }
5906                if let Some(transaction) = transaction {
5907                    write!(f, " {transaction}")?;
5908                }
5909                if !modes.is_empty() {
5910                    write!(f, " {}", display_comma_separated(modes))?;
5911                }
5912                if !statements.is_empty() {
5913                    write!(f, " ")?;
5914                    format_statement_list(f, statements)?;
5915                }
5916                if let Some(exception_when) = exception {
5917                    write!(f, " EXCEPTION")?;
5918                    for when in exception_when {
5919                        write!(f, " {when}")?;
5920                    }
5921                }
5922                if *has_end_keyword {
5923                    write!(f, " END")?;
5924                }
5925                Ok(())
5926            }
5927            Statement::Commit {
5928                chain,
5929                end: end_syntax,
5930                modifier,
5931            } => {
5932                if *end_syntax {
5933                    write!(f, "END")?;
5934                    if let Some(modifier) = *modifier {
5935                        write!(f, " {modifier}")?;
5936                    }
5937                    if *chain {
5938                        write!(f, " AND CHAIN")?;
5939                    }
5940                } else {
5941                    write!(f, "COMMIT{}", if *chain { " AND CHAIN" } else { "" })?;
5942                }
5943                Ok(())
5944            }
5945            Statement::Rollback { chain, savepoint } => {
5946                write!(f, "ROLLBACK")?;
5947
5948                if *chain {
5949                    write!(f, " AND CHAIN")?;
5950                }
5951
5952                if let Some(savepoint) = savepoint {
5953                    write!(f, " TO SAVEPOINT {savepoint}")?;
5954                }
5955
5956                Ok(())
5957            }
5958            Statement::CreateSchema {
5959                schema_name,
5960                if_not_exists,
5961                with,
5962                options,
5963                default_collate_spec,
5964                clone,
5965            } => {
5966                write!(
5967                    f,
5968                    "CREATE SCHEMA {if_not_exists}{name}",
5969                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
5970                    name = schema_name
5971                )?;
5972
5973                if let Some(collate) = default_collate_spec {
5974                    write!(f, " DEFAULT COLLATE {collate}")?;
5975                }
5976
5977                if let Some(with) = with {
5978                    write!(f, " WITH ({})", display_comma_separated(with))?;
5979                }
5980
5981                if let Some(options) = options {
5982                    write!(f, " OPTIONS({})", display_comma_separated(options))?;
5983                }
5984
5985                if let Some(clone) = clone {
5986                    write!(f, " CLONE {clone}")?;
5987                }
5988                Ok(())
5989            }
5990            Statement::Assert { condition, message } => {
5991                write!(f, "ASSERT {condition}")?;
5992                if let Some(m) = message {
5993                    write!(f, " AS {m}")?;
5994                }
5995                Ok(())
5996            }
5997            Statement::Grant(grant) => write!(f, "{grant}"),
5998            Statement::Deny(s) => write!(f, "{s}"),
5999            Statement::Revoke(revoke) => write!(f, "{revoke}"),
6000            Statement::Deallocate { name, prepare } => write!(
6001                f,
6002                "DEALLOCATE {prepare}{name}",
6003                prepare = if *prepare { "PREPARE " } else { "" },
6004                name = name,
6005            ),
6006            Statement::Execute {
6007                name,
6008                parameters,
6009                has_parentheses,
6010                immediate,
6011                into,
6012                using,
6013                output,
6014                default,
6015            } => {
6016                let (open, close) = if *has_parentheses {
6017                    // Space before `(` only when there is no name directly preceding it.
6018                    (if name.is_some() { "(" } else { " (" }, ")")
6019                } else {
6020                    (if parameters.is_empty() { "" } else { " " }, "")
6021                };
6022                write!(f, "EXECUTE")?;
6023                if *immediate {
6024                    write!(f, " IMMEDIATE")?;
6025                }
6026                if let Some(name) = name {
6027                    write!(f, " {name}")?;
6028                }
6029                write!(f, "{open}{}{close}", display_comma_separated(parameters),)?;
6030                if !into.is_empty() {
6031                    write!(f, " INTO {}", display_comma_separated(into))?;
6032                }
6033                if !using.is_empty() {
6034                    write!(f, " USING {}", display_comma_separated(using))?;
6035                };
6036                if *output {
6037                    write!(f, " OUTPUT")?;
6038                }
6039                if *default {
6040                    write!(f, " DEFAULT")?;
6041                }
6042                Ok(())
6043            }
6044            Statement::Prepare {
6045                name,
6046                data_types,
6047                statement,
6048            } => {
6049                write!(f, "PREPARE {name} ")?;
6050                if !data_types.is_empty() {
6051                    write!(f, "({}) ", display_comma_separated(data_types))?;
6052                }
6053                write!(f, "AS {statement}")
6054            }
6055            Statement::Comment {
6056                object_type,
6057                object_name,
6058                comment,
6059                if_exists,
6060            } => {
6061                write!(f, "COMMENT ")?;
6062                if *if_exists {
6063                    write!(f, "IF EXISTS ")?
6064                };
6065                write!(f, "ON {object_type} {object_name} IS ")?;
6066                if let Some(c) = comment {
6067                    write!(f, "'{c}'")
6068                } else {
6069                    write!(f, "NULL")
6070                }
6071            }
6072            Statement::Savepoint { name } => {
6073                write!(f, "SAVEPOINT ")?;
6074                write!(f, "{name}")
6075            }
6076            Statement::ReleaseSavepoint { name } => {
6077                write!(f, "RELEASE SAVEPOINT {name}")
6078            }
6079            Statement::Merge(merge) => merge.fmt(f),
6080            Statement::Cache {
6081                table_name,
6082                table_flag,
6083                has_as,
6084                options,
6085                query,
6086            } => {
6087                if let Some(table_flag) = table_flag {
6088                    write!(f, "CACHE {table_flag} TABLE {table_name}")?;
6089                } else {
6090                    write!(f, "CACHE TABLE {table_name}")?;
6091                }
6092
6093                if !options.is_empty() {
6094                    write!(f, " OPTIONS({})", display_comma_separated(options))?;
6095                }
6096
6097                match (*has_as, query) {
6098                    (true, Some(query)) => write!(f, " AS {query}"),
6099                    (true, None) => f.write_str(" AS"),
6100                    (false, Some(query)) => write!(f, " {query}"),
6101                    (false, None) => Ok(()),
6102                }
6103            }
6104            Statement::UNCache {
6105                table_name,
6106                if_exists,
6107            } => {
6108                if *if_exists {
6109                    write!(f, "UNCACHE TABLE IF EXISTS {table_name}")
6110                } else {
6111                    write!(f, "UNCACHE TABLE {table_name}")
6112                }
6113            }
6114            Statement::CreateSequence {
6115                temporary,
6116                if_not_exists,
6117                name,
6118                data_type,
6119                sequence_options,
6120                owned_by,
6121            } => {
6122                let as_type: String = if let Some(dt) = data_type.as_ref() {
6123                    //Cannot use format!(" AS {}", dt), due to format! is not available in --target thumbv6m-none-eabi
6124                    // " AS ".to_owned() + &dt.to_string()
6125                    [" AS ", &dt.to_string()].concat()
6126                } else {
6127                    "".to_string()
6128                };
6129                write!(
6130                    f,
6131                    "CREATE {temporary}SEQUENCE {if_not_exists}{name}{as_type}",
6132                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
6133                    temporary = if *temporary { "TEMPORARY " } else { "" },
6134                    name = name,
6135                    as_type = as_type
6136                )?;
6137                for sequence_option in sequence_options {
6138                    write!(f, "{sequence_option}")?;
6139                }
6140                if let Some(ob) = owned_by.as_ref() {
6141                    write!(f, " OWNED BY {ob}")?;
6142                }
6143                write!(f, "")
6144            }
6145            Statement::CreateStage {
6146                or_replace,
6147                temporary,
6148                if_not_exists,
6149                name,
6150                stage_params,
6151                directory_table_params,
6152                file_format,
6153                copy_options,
6154                comment,
6155                ..
6156            } => {
6157                write!(
6158                    f,
6159                    "CREATE {or_replace}{temp}STAGE {if_not_exists}{name}{stage_params}",
6160                    temp = if *temporary { "TEMPORARY " } else { "" },
6161                    or_replace = if *or_replace { "OR REPLACE " } else { "" },
6162                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
6163                )?;
6164                if !directory_table_params.options.is_empty() {
6165                    write!(f, " DIRECTORY=({directory_table_params})")?;
6166                }
6167                if !file_format.options.is_empty() {
6168                    write!(f, " FILE_FORMAT=({file_format})")?;
6169                }
6170                if !copy_options.options.is_empty() {
6171                    write!(f, " COPY_OPTIONS=({copy_options})")?;
6172                }
6173                if let Some(comment) = comment {
6174                    write!(f, " COMMENT='{}'", comment)?;
6175                }
6176                Ok(())
6177            }
6178            Statement::CopyIntoSnowflake {
6179                kind,
6180                into,
6181                into_columns,
6182                from_obj,
6183                from_obj_alias,
6184                stage_params,
6185                from_transformations,
6186                from_query,
6187                files,
6188                pattern,
6189                file_format,
6190                copy_options,
6191                validation_mode,
6192                partition,
6193            } => {
6194                write!(f, "COPY INTO {into}")?;
6195                if let Some(into_columns) = into_columns {
6196                    write!(f, " ({})", display_comma_separated(into_columns))?;
6197                }
6198                if let Some(from_transformations) = from_transformations {
6199                    // Data load with transformation
6200                    if let Some(from_stage) = from_obj {
6201                        write!(
6202                            f,
6203                            " FROM (SELECT {} FROM {}{}",
6204                            display_separated(from_transformations, ", "),
6205                            from_stage,
6206                            stage_params
6207                        )?;
6208                    }
6209                    if let Some(from_obj_alias) = from_obj_alias {
6210                        write!(f, " AS {from_obj_alias}")?;
6211                    }
6212                    write!(f, ")")?;
6213                } else if let Some(from_obj) = from_obj {
6214                    // Standard data load
6215                    write!(f, " FROM {from_obj}{stage_params}")?;
6216                    if let Some(from_obj_alias) = from_obj_alias {
6217                        write!(f, " AS {from_obj_alias}")?;
6218                    }
6219                } else if let Some(from_query) = from_query {
6220                    // Data unload from query
6221                    write!(f, " FROM ({from_query})")?;
6222                }
6223
6224                if let Some(files) = files {
6225                    write!(f, " FILES = ('{}')", display_separated(files, "', '"))?;
6226                }
6227                if let Some(pattern) = pattern {
6228                    write!(f, " PATTERN = '{pattern}'")?;
6229                }
6230                if let Some(partition) = partition {
6231                    write!(f, " PARTITION BY {partition}")?;
6232                }
6233                if !file_format.options.is_empty() {
6234                    write!(f, " FILE_FORMAT=({file_format})")?;
6235                }
6236                if !copy_options.options.is_empty() {
6237                    match kind {
6238                        CopyIntoSnowflakeKind::Table => {
6239                            write!(f, " COPY_OPTIONS=({copy_options})")?
6240                        }
6241                        CopyIntoSnowflakeKind::Location => write!(f, " {copy_options}")?,
6242                    }
6243                }
6244                if let Some(validation_mode) = validation_mode {
6245                    write!(f, " VALIDATION_MODE = {validation_mode}")?;
6246                }
6247                Ok(())
6248            }
6249            Statement::CreateType {
6250                name,
6251                representation,
6252            } => {
6253                write!(f, "CREATE TYPE {name}")?;
6254                if let Some(repr) = representation {
6255                    write!(f, " {repr}")?;
6256                }
6257                Ok(())
6258            }
6259            Statement::Pragma { name, value, is_eq } => {
6260                write!(f, "PRAGMA {name}")?;
6261                if let Some(value) = value {
6262                    if *is_eq {
6263                        write!(f, " = {value}")?;
6264                    } else {
6265                        write!(f, "({value})")?;
6266                    }
6267                }
6268                Ok(())
6269            }
6270            Statement::Lock(lock) => lock.fmt(f),
6271            Statement::LockTables { tables } => {
6272                write!(f, "LOCK TABLES {}", display_comma_separated(tables))
6273            }
6274            Statement::UnlockTables => {
6275                write!(f, "UNLOCK TABLES")
6276            }
6277            Statement::Unload {
6278                query,
6279                query_text,
6280                to,
6281                auth,
6282                with,
6283                options,
6284            } => {
6285                write!(f, "UNLOAD(")?;
6286                if let Some(query) = query {
6287                    write!(f, "{query}")?;
6288                }
6289                if let Some(query_text) = query_text {
6290                    write!(f, "'{query_text}'")?;
6291                }
6292                write!(f, ") TO {to}")?;
6293                if let Some(auth) = auth {
6294                    write!(f, " IAM_ROLE {auth}")?;
6295                }
6296                if !with.is_empty() {
6297                    write!(f, " WITH ({})", display_comma_separated(with))?;
6298                }
6299                if !options.is_empty() {
6300                    write!(f, " {}", display_separated(options, " "))?;
6301                }
6302                Ok(())
6303            }
6304            Statement::OptimizeTable {
6305                name,
6306                has_table_keyword,
6307                on_cluster,
6308                partition,
6309                include_final,
6310                deduplicate,
6311                predicate,
6312                zorder,
6313            } => {
6314                write!(f, "OPTIMIZE")?;
6315                if *has_table_keyword {
6316                    write!(f, " TABLE")?;
6317                }
6318                write!(f, " {name}")?;
6319                if let Some(on_cluster) = on_cluster {
6320                    write!(f, " ON CLUSTER {on_cluster}")?;
6321                }
6322                if let Some(partition) = partition {
6323                    write!(f, " {partition}")?;
6324                }
6325                if *include_final {
6326                    write!(f, " FINAL")?;
6327                }
6328                if let Some(deduplicate) = deduplicate {
6329                    write!(f, " {deduplicate}")?;
6330                }
6331                if let Some(predicate) = predicate {
6332                    write!(f, " WHERE {predicate}")?;
6333                }
6334                if let Some(zorder) = zorder {
6335                    write!(f, " ZORDER BY ({})", display_comma_separated(zorder))?;
6336                }
6337                Ok(())
6338            }
6339            Statement::LISTEN { channel } => {
6340                write!(f, "LISTEN {channel}")?;
6341                Ok(())
6342            }
6343            Statement::UNLISTEN { channel } => {
6344                write!(f, "UNLISTEN {channel}")?;
6345                Ok(())
6346            }
6347            Statement::NOTIFY { channel, payload } => {
6348                write!(f, "NOTIFY {channel}")?;
6349                if let Some(payload) = payload {
6350                    write!(f, ", '{payload}'")?;
6351                }
6352                Ok(())
6353            }
6354            Statement::RenameTable(rename_tables) => {
6355                write!(f, "RENAME TABLE {}", display_comma_separated(rename_tables))
6356            }
6357            Statement::RaisError {
6358                message,
6359                severity,
6360                state,
6361                arguments,
6362                options,
6363            } => {
6364                write!(f, "RAISERROR({message}, {severity}, {state}")?;
6365                if !arguments.is_empty() {
6366                    write!(f, ", {}", display_comma_separated(arguments))?;
6367                }
6368                write!(f, ")")?;
6369                if !options.is_empty() {
6370                    write!(f, " WITH {}", display_comma_separated(options))?;
6371                }
6372                Ok(())
6373            }
6374            Statement::Throw(s) => write!(f, "{s}"),
6375            Statement::Print(s) => write!(f, "{s}"),
6376            Statement::WaitFor(s) => write!(f, "{s}"),
6377            Statement::Return(r) => write!(f, "{r}"),
6378            Statement::List(command) => write!(f, "LIST {command}"),
6379            Statement::Remove(command) => write!(f, "REMOVE {command}"),
6380            Statement::ExportData(e) => write!(f, "{e}"),
6381            Statement::CreateUser(s) => write!(f, "{s}"),
6382            Statement::AlterSchema(s) => write!(f, "{s}"),
6383            Statement::Vacuum(s) => write!(f, "{s}"),
6384            Statement::AlterUser(s) => write!(f, "{s}"),
6385            Statement::Reset(s) => write!(f, "{s}"),
6386        }
6387    }
6388}
6389
6390/// Can use to describe options in create sequence or table column type identity
6391/// ```sql
6392/// [ INCREMENT [ BY ] increment ]
6393///     [ MINVALUE minvalue | NO MINVALUE ] [ MAXVALUE maxvalue | NO MAXVALUE ]
6394///     [ START [ WITH ] start ] [ CACHE cache ] [ [ NO ] CYCLE ]
6395/// ```
6396#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6397#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6398#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6399pub enum SequenceOptions {
6400    /// `INCREMENT [BY] <expr>` option; second value indicates presence of `BY` keyword.
6401    IncrementBy(Expr, bool),
6402    /// `MINVALUE <expr>` or `NO MINVALUE`.
6403    MinValue(Option<Expr>),
6404    /// `MAXVALUE <expr>` or `NO MAXVALUE`.
6405    MaxValue(Option<Expr>),
6406    /// `START [WITH] <expr>`; second value indicates presence of `WITH`.
6407    StartWith(Expr, bool),
6408    /// `CACHE <expr>` option.
6409    Cache(Expr),
6410    /// `CYCLE` or `NO CYCLE` option.
6411    Cycle(bool),
6412}
6413
6414impl fmt::Display for SequenceOptions {
6415    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6416        match self {
6417            SequenceOptions::IncrementBy(increment, by) => {
6418                write!(
6419                    f,
6420                    " INCREMENT{by} {increment}",
6421                    by = if *by { " BY" } else { "" },
6422                    increment = increment
6423                )
6424            }
6425            SequenceOptions::MinValue(Some(expr)) => {
6426                write!(f, " MINVALUE {expr}")
6427            }
6428            SequenceOptions::MinValue(None) => {
6429                write!(f, " NO MINVALUE")
6430            }
6431            SequenceOptions::MaxValue(Some(expr)) => {
6432                write!(f, " MAXVALUE {expr}")
6433            }
6434            SequenceOptions::MaxValue(None) => {
6435                write!(f, " NO MAXVALUE")
6436            }
6437            SequenceOptions::StartWith(start, with) => {
6438                write!(
6439                    f,
6440                    " START{with} {start}",
6441                    with = if *with { " WITH" } else { "" },
6442                    start = start
6443                )
6444            }
6445            SequenceOptions::Cache(cache) => {
6446                write!(f, " CACHE {}", *cache)
6447            }
6448            SequenceOptions::Cycle(no) => {
6449                write!(f, " {}CYCLE", if *no { "NO " } else { "" })
6450            }
6451        }
6452    }
6453}
6454
6455/// Assignment for a `SET` statement (name [=|TO] value)
6456#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6457#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6458#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6459pub struct SetAssignment {
6460    /// Optional context scope (e.g., SESSION or LOCAL).
6461    pub scope: Option<ContextModifier>,
6462    /// Assignment target name.
6463    pub name: ObjectName,
6464    /// Assigned expression value.
6465    pub value: Expr,
6466}
6467
6468impl fmt::Display for SetAssignment {
6469    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6470        write!(
6471            f,
6472            "{}{} = {}",
6473            self.scope.map(|s| format!("{s}")).unwrap_or_default(),
6474            self.name,
6475            self.value
6476        )
6477    }
6478}
6479
6480/// Target of a `TRUNCATE TABLE` command
6481///
6482/// Note this is its own struct because `visit_relation` requires an `ObjectName` (not a `Vec<ObjectName>`)
6483#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6484#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6485#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6486pub struct TruncateTableTarget {
6487    /// name of the table being truncated
6488    #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
6489    pub name: ObjectName,
6490    /// Postgres-specific option: explicitly exclude descendants (also default without ONLY)
6491    /// ```sql
6492    /// TRUNCATE TABLE ONLY name
6493    /// ```
6494    /// <https://www.postgresql.org/docs/current/sql-truncate.html>
6495    pub only: bool,
6496    /// Postgres-specific option: asterisk after table name to explicitly indicate descendants
6497    /// ```sql
6498    /// TRUNCATE TABLE name [ * ]
6499    /// ```
6500    /// <https://www.postgresql.org/docs/current/sql-truncate.html>
6501    pub has_asterisk: bool,
6502}
6503
6504impl fmt::Display for TruncateTableTarget {
6505    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6506        if self.only {
6507            write!(f, "ONLY ")?;
6508        };
6509        write!(f, "{}", self.name)?;
6510        if self.has_asterisk {
6511            write!(f, " *")?;
6512        };
6513        Ok(())
6514    }
6515}
6516
6517/// A `LOCK` statement.
6518///
6519/// See <https://www.postgresql.org/docs/current/sql-lock.html>
6520#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6521#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6522#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6523pub struct Lock {
6524    /// List of tables to lock.
6525    pub tables: Vec<LockTableTarget>,
6526    /// Lock mode.
6527    pub lock_mode: Option<LockTableMode>,
6528    /// Whether `NOWAIT` was specified.
6529    pub nowait: bool,
6530}
6531
6532impl fmt::Display for Lock {
6533    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6534        write!(f, "LOCK TABLE {}", display_comma_separated(&self.tables))?;
6535        if let Some(lock_mode) = &self.lock_mode {
6536            write!(f, " IN {lock_mode} MODE")?;
6537        }
6538        if self.nowait {
6539            write!(f, " NOWAIT")?;
6540        }
6541        Ok(())
6542    }
6543}
6544
6545/// Target of a `LOCK TABLE` command
6546///
6547/// See <https://www.postgresql.org/docs/current/sql-lock.html>
6548#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6549#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6550#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6551pub struct LockTableTarget {
6552    /// Name of the table being locked.
6553    #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
6554    pub name: ObjectName,
6555    /// Whether `ONLY` was specified to exclude descendant tables.
6556    pub only: bool,
6557    /// Whether `*` was specified to explicitly include descendant tables.
6558    pub has_asterisk: bool,
6559}
6560
6561impl fmt::Display for LockTableTarget {
6562    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6563        if self.only {
6564            write!(f, "ONLY ")?;
6565        }
6566        write!(f, "{}", self.name)?;
6567        if self.has_asterisk {
6568            write!(f, " *")?;
6569        }
6570        Ok(())
6571    }
6572}
6573
6574/// PostgreSQL lock modes for `LOCK TABLE`.
6575///
6576/// See <https://www.postgresql.org/docs/current/sql-lock.html>
6577#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6578#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6579#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6580pub enum LockTableMode {
6581    /// `ACCESS SHARE`
6582    AccessShare,
6583    /// `ROW SHARE`
6584    RowShare,
6585    /// `ROW EXCLUSIVE`
6586    RowExclusive,
6587    /// `SHARE UPDATE EXCLUSIVE`
6588    ShareUpdateExclusive,
6589    /// `SHARE`
6590    Share,
6591    /// `SHARE ROW EXCLUSIVE`
6592    ShareRowExclusive,
6593    /// `EXCLUSIVE`
6594    Exclusive,
6595    /// `ACCESS EXCLUSIVE`
6596    AccessExclusive,
6597}
6598
6599impl fmt::Display for LockTableMode {
6600    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
6601        let text = match self {
6602            Self::AccessShare => "ACCESS SHARE",
6603            Self::RowShare => "ROW SHARE",
6604            Self::RowExclusive => "ROW EXCLUSIVE",
6605            Self::ShareUpdateExclusive => "SHARE UPDATE EXCLUSIVE",
6606            Self::Share => "SHARE",
6607            Self::ShareRowExclusive => "SHARE ROW EXCLUSIVE",
6608            Self::Exclusive => "EXCLUSIVE",
6609            Self::AccessExclusive => "ACCESS EXCLUSIVE",
6610        };
6611        write!(f, "{text}")
6612    }
6613}
6614
6615/// PostgreSQL identity option for TRUNCATE table
6616/// [ RESTART IDENTITY | CONTINUE IDENTITY ]
6617#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6618#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6619#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6620pub enum TruncateIdentityOption {
6621    /// Restart identity values (RESTART IDENTITY).
6622    Restart,
6623    /// Continue identity values (CONTINUE IDENTITY).
6624    Continue,
6625}
6626
6627/// Cascade/restrict option for Postgres TRUNCATE table, MySQL GRANT/REVOKE, etc.
6628/// [ CASCADE | RESTRICT ]
6629#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6630#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6631#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6632pub enum CascadeOption {
6633    /// Apply cascading action (e.g., CASCADE).
6634    Cascade,
6635    /// Restrict the action (e.g., RESTRICT).
6636    Restrict,
6637}
6638
6639impl Display for CascadeOption {
6640    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6641        match self {
6642            CascadeOption::Cascade => write!(f, "CASCADE"),
6643            CascadeOption::Restrict => write!(f, "RESTRICT"),
6644        }
6645    }
6646}
6647
6648/// Transaction started with [ TRANSACTION | WORK | TRAN ]
6649#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6650#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6651#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6652pub enum BeginTransactionKind {
6653    /// Standard `TRANSACTION` keyword.
6654    Transaction,
6655    /// Alternate `WORK` keyword.
6656    Work,
6657    /// MSSQL shorthand `TRAN` keyword.
6658    /// See <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/begin-transaction-transact-sql>
6659    Tran,
6660}
6661
6662impl Display for BeginTransactionKind {
6663    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6664        match self {
6665            BeginTransactionKind::Transaction => write!(f, "TRANSACTION"),
6666            BeginTransactionKind::Work => write!(f, "WORK"),
6667            BeginTransactionKind::Tran => write!(f, "TRAN"),
6668        }
6669    }
6670}
6671
6672/// Can use to describe options in  create sequence or table column type identity
6673/// [ MINVALUE minvalue | NO MINVALUE ] [ MAXVALUE maxvalue | NO MAXVALUE ]
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 MinMaxValue {
6678    /// Clause is not specified.
6679    Empty,
6680    /// NO MINVALUE / NO MAXVALUE.
6681    None,
6682    /// `MINVALUE <expr>` / `MAXVALUE <expr>`.
6683    Some(Expr),
6684}
6685
6686#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6687#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6688#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6689#[non_exhaustive]
6690/// Behavior to apply for `INSERT` when a conflict occurs.
6691pub enum OnInsert {
6692    /// ON DUPLICATE KEY UPDATE (MySQL when the key already exists, then execute an update instead)
6693    DuplicateKeyUpdate(Vec<Assignment>),
6694    /// ON CONFLICT is a PostgreSQL and Sqlite extension
6695    OnConflict(OnConflict),
6696}
6697
6698#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6699#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6700#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6701/// Optional aliases for `INSERT` targets: row alias and optional column aliases.
6702pub struct InsertAliases {
6703    /// Row alias (table-style alias) for the inserted values.
6704    pub row_alias: ObjectName,
6705    /// Optional list of column aliases for the inserted values.
6706    pub col_aliases: Option<Vec<Ident>>,
6707}
6708
6709#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6710#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6711#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6712/// Optional alias for an `INSERT` table; i.e. the table to be inserted into
6713pub struct TableAliasWithoutColumns {
6714    /// `true` if the aliases was explicitly introduced with the "AS" keyword
6715    pub explicit: bool,
6716    /// the alias name itself
6717    pub alias: Ident,
6718}
6719
6720#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6721#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6722#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6723/// `ON CONFLICT` clause representation.
6724pub struct OnConflict {
6725    /// Optional conflict target specifying columns or constraint.
6726    pub conflict_target: Option<ConflictTarget>,
6727    /// Action to take when a conflict occurs.
6728    pub action: OnConflictAction,
6729}
6730#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6731#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6732#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6733/// Target specification for an `ON CONFLICT` clause.
6734pub enum ConflictTarget {
6735    /// Target specified as a list of columns.
6736    Columns(Vec<Ident>),
6737    /// Target specified as a named constraint.
6738    OnConstraint(ObjectName),
6739}
6740#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6741#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6742#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6743/// Action to perform when an `ON CONFLICT` target is matched.
6744pub enum OnConflictAction {
6745    /// Do nothing on conflict.
6746    DoNothing,
6747    /// Perform an update on conflict.
6748    DoUpdate(DoUpdate),
6749}
6750
6751#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6752#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6753#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6754/// Details for `DO UPDATE` action of an `ON CONFLICT` clause.
6755pub struct DoUpdate {
6756    /// Column assignments to perform on update.
6757    pub assignments: Vec<Assignment>,
6758    /// Optional WHERE clause limiting the update.
6759    pub selection: Option<Expr>,
6760}
6761
6762impl fmt::Display for OnInsert {
6763    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6764        match self {
6765            Self::DuplicateKeyUpdate(expr) => write!(
6766                f,
6767                " ON DUPLICATE KEY UPDATE {}",
6768                display_comma_separated(expr)
6769            ),
6770            Self::OnConflict(o) => write!(f, "{o}"),
6771        }
6772    }
6773}
6774impl fmt::Display for OnConflict {
6775    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6776        write!(f, " ON CONFLICT")?;
6777        if let Some(target) = &self.conflict_target {
6778            write!(f, "{target}")?;
6779        }
6780        write!(f, " {}", self.action)
6781    }
6782}
6783impl fmt::Display for ConflictTarget {
6784    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6785        match self {
6786            ConflictTarget::Columns(cols) => write!(f, "({})", display_comma_separated(cols)),
6787            ConflictTarget::OnConstraint(name) => write!(f, " ON CONSTRAINT {name}"),
6788        }
6789    }
6790}
6791impl fmt::Display for OnConflictAction {
6792    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6793        match self {
6794            Self::DoNothing => write!(f, "DO NOTHING"),
6795            Self::DoUpdate(do_update) => {
6796                write!(f, "DO UPDATE")?;
6797                if !do_update.assignments.is_empty() {
6798                    write!(
6799                        f,
6800                        " SET {}",
6801                        display_comma_separated(&do_update.assignments)
6802                    )?;
6803                }
6804                if let Some(selection) = &do_update.selection {
6805                    write!(f, " WHERE {selection}")?;
6806                }
6807                Ok(())
6808            }
6809        }
6810    }
6811}
6812
6813/// Privileges granted in a GRANT statement or revoked in a REVOKE statement.
6814#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6815#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6816#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6817pub enum Privileges {
6818    /// All privileges applicable to the object type
6819    All {
6820        /// Optional keyword from the spec, ignored in practice
6821        with_privileges_keyword: bool,
6822    },
6823    /// Specific privileges (e.g. `SELECT`, `INSERT`)
6824    Actions(Vec<Action>),
6825}
6826
6827impl fmt::Display for Privileges {
6828    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6829        match self {
6830            Privileges::All {
6831                with_privileges_keyword,
6832            } => {
6833                write!(
6834                    f,
6835                    "ALL{}",
6836                    if *with_privileges_keyword {
6837                        " PRIVILEGES"
6838                    } else {
6839                        ""
6840                    }
6841                )
6842            }
6843            Privileges::Actions(actions) => {
6844                write!(f, "{}", display_comma_separated(actions))
6845            }
6846        }
6847    }
6848}
6849
6850/// Specific direction for FETCH statement
6851#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6852#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6853#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6854pub enum FetchDirection {
6855    /// Fetch a specific count of rows.
6856    Count {
6857        /// The limit value for the count.
6858        limit: ValueWithSpan,
6859    },
6860    /// Fetch the next row.
6861    Next,
6862    /// Fetch the prior row.
6863    Prior,
6864    /// Fetch the first row.
6865    First,
6866    /// Fetch the last row.
6867    Last,
6868    /// Fetch an absolute row by index.
6869    Absolute {
6870        /// The absolute index value.
6871        limit: ValueWithSpan,
6872    },
6873    /// Fetch a row relative to the current position.
6874    Relative {
6875        /// The relative offset value.
6876        limit: ValueWithSpan,
6877    },
6878    /// Fetch all rows.
6879    All,
6880    // FORWARD
6881    // FORWARD count
6882    /// Fetch forward by an optional limit.
6883    Forward {
6884        /// Optional forward limit.
6885        limit: Option<ValueWithSpan>,
6886    },
6887    /// Fetch all forward rows.
6888    ForwardAll,
6889    // BACKWARD
6890    // BACKWARD count
6891    /// Fetch backward by an optional limit.
6892    Backward {
6893        /// Optional backward limit.
6894        limit: Option<ValueWithSpan>,
6895    },
6896    /// Fetch all backward rows.
6897    BackwardAll,
6898}
6899
6900impl fmt::Display for FetchDirection {
6901    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6902        match self {
6903            FetchDirection::Count { limit } => f.write_str(&limit.to_string())?,
6904            FetchDirection::Next => f.write_str("NEXT")?,
6905            FetchDirection::Prior => f.write_str("PRIOR")?,
6906            FetchDirection::First => f.write_str("FIRST")?,
6907            FetchDirection::Last => f.write_str("LAST")?,
6908            FetchDirection::Absolute { limit } => {
6909                f.write_str("ABSOLUTE ")?;
6910                f.write_str(&limit.to_string())?;
6911            }
6912            FetchDirection::Relative { limit } => {
6913                f.write_str("RELATIVE ")?;
6914                f.write_str(&limit.to_string())?;
6915            }
6916            FetchDirection::All => f.write_str("ALL")?,
6917            FetchDirection::Forward { limit } => {
6918                f.write_str("FORWARD")?;
6919
6920                if let Some(l) = limit {
6921                    f.write_str(" ")?;
6922                    f.write_str(&l.to_string())?;
6923                }
6924            }
6925            FetchDirection::ForwardAll => f.write_str("FORWARD ALL")?,
6926            FetchDirection::Backward { limit } => {
6927                f.write_str("BACKWARD")?;
6928
6929                if let Some(l) = limit {
6930                    f.write_str(" ")?;
6931                    f.write_str(&l.to_string())?;
6932                }
6933            }
6934            FetchDirection::BackwardAll => f.write_str("BACKWARD ALL")?,
6935        };
6936
6937        Ok(())
6938    }
6939}
6940
6941/// The "position" for a FETCH statement.
6942///
6943/// [MsSql](https://learn.microsoft.com/en-us/sql/t-sql/language-elements/fetch-transact-sql)
6944#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6945#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6946#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6947pub enum FetchPosition {
6948    /// Use `FROM <pos>` position specifier.
6949    From,
6950    /// Use `IN <pos>` position specifier.
6951    In,
6952}
6953
6954impl fmt::Display for FetchPosition {
6955    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6956        match self {
6957            FetchPosition::From => f.write_str("FROM")?,
6958            FetchPosition::In => f.write_str("IN")?,
6959        };
6960
6961        Ok(())
6962    }
6963}
6964
6965/// A privilege on a database object (table, sequence, etc.).
6966#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6967#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6968#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6969pub enum Action {
6970    /// Add a search optimization.
6971    AddSearchOptimization,
6972    /// Apply an `APPLY` operation with a specific type.
6973    Apply {
6974        /// The type of apply operation.
6975        apply_type: ActionApplyType,
6976    },
6977    /// Apply a budget operation.
6978    ApplyBudget,
6979    /// Attach a listing.
6980    AttachListing,
6981    /// Attach a policy.
6982    AttachPolicy,
6983    /// Audit operation.
6984    Audit,
6985    /// Bind a service endpoint.
6986    BindServiceEndpoint,
6987    /// Connect permission.
6988    Connect,
6989    /// Create action, optionally specifying an object type.
6990    Create {
6991        /// Optional object type to create.
6992        obj_type: Option<ActionCreateObjectType>,
6993    },
6994    /// Actions related to database roles.
6995    DatabaseRole {
6996        /// The role name.
6997        role: ObjectName,
6998    },
6999    /// Delete permission.
7000    Delete,
7001    /// Drop permission.
7002    Drop,
7003    /// Evolve schema permission.
7004    EvolveSchema,
7005    /// Exec action (execute) with optional object type.
7006    Exec {
7007        /// Optional execute object type.
7008        obj_type: Option<ActionExecuteObjectType>,
7009    },
7010    /// Execute action with optional object type.
7011    Execute {
7012        /// Optional execute object type.
7013        obj_type: Option<ActionExecuteObjectType>,
7014    },
7015    /// Failover operation.
7016    Failover,
7017    /// Use imported privileges.
7018    ImportedPrivileges,
7019    /// Import a share.
7020    ImportShare,
7021    /// Insert rows with optional column list.
7022    Insert {
7023        /// Optional list of target columns for insert.
7024        columns: Option<Vec<Ident>>,
7025    },
7026    /// Manage operation with a specific manage type.
7027    Manage {
7028        /// The specific manage sub-type.
7029        manage_type: ActionManageType,
7030    },
7031    /// Manage releases.
7032    ManageReleases,
7033    /// Manage versions.
7034    ManageVersions,
7035    /// Modify operation with an optional modify type.
7036    Modify {
7037        /// The optional modify sub-type.
7038        modify_type: Option<ActionModifyType>,
7039    },
7040    /// Monitor operation with an optional monitor type.
7041    Monitor {
7042        /// The optional monitor sub-type.
7043        monitor_type: Option<ActionMonitorType>,
7044    },
7045    /// Operate permission.
7046    Operate,
7047    /// Override share restrictions.
7048    OverrideShareRestrictions,
7049    /// Ownership permission.
7050    Ownership,
7051    /// Purchase a data exchange listing.
7052    PurchaseDataExchangeListing,
7053
7054    /// Read access.
7055    Read,
7056    /// Read session-level access.
7057    ReadSession,
7058    /// References with optional column list.
7059    References {
7060        /// Optional list of referenced column identifiers.
7061        columns: Option<Vec<Ident>>,
7062    },
7063    /// Replication permission.
7064    Replicate,
7065    /// Resolve all references.
7066    ResolveAll,
7067    /// Role-related permission with target role name.
7068    Role {
7069        /// The target role name.
7070        role: ObjectName,
7071    },
7072    /// Select permission with optional column list.
7073    Select {
7074        /// Optional list of selected columns.
7075        columns: Option<Vec<Ident>>,
7076    },
7077    /// Temporary object permission.
7078    Temporary,
7079    /// Trigger-related permission.
7080    Trigger,
7081    /// Truncate permission.
7082    Truncate,
7083    /// Update permission with optional affected columns.
7084    Update {
7085        /// Optional list of columns affected by update.
7086        columns: Option<Vec<Ident>>,
7087    },
7088    /// Usage permission.
7089    Usage,
7090}
7091
7092impl fmt::Display for Action {
7093    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7094        match self {
7095            Action::AddSearchOptimization => f.write_str("ADD SEARCH OPTIMIZATION")?,
7096            Action::Apply { apply_type } => write!(f, "APPLY {apply_type}")?,
7097            Action::ApplyBudget => f.write_str("APPLYBUDGET")?,
7098            Action::AttachListing => f.write_str("ATTACH LISTING")?,
7099            Action::AttachPolicy => f.write_str("ATTACH POLICY")?,
7100            Action::Audit => f.write_str("AUDIT")?,
7101            Action::BindServiceEndpoint => f.write_str("BIND SERVICE ENDPOINT")?,
7102            Action::Connect => f.write_str("CONNECT")?,
7103            Action::Create { obj_type } => {
7104                f.write_str("CREATE")?;
7105                if let Some(obj_type) = obj_type {
7106                    write!(f, " {obj_type}")?
7107                }
7108            }
7109            Action::DatabaseRole { role } => write!(f, "DATABASE ROLE {role}")?,
7110            Action::Delete => f.write_str("DELETE")?,
7111            Action::Drop => f.write_str("DROP")?,
7112            Action::EvolveSchema => f.write_str("EVOLVE SCHEMA")?,
7113            Action::Exec { obj_type } => {
7114                f.write_str("EXEC")?;
7115                if let Some(obj_type) = obj_type {
7116                    write!(f, " {obj_type}")?
7117                }
7118            }
7119            Action::Execute { obj_type } => {
7120                f.write_str("EXECUTE")?;
7121                if let Some(obj_type) = obj_type {
7122                    write!(f, " {obj_type}")?
7123                }
7124            }
7125            Action::Failover => f.write_str("FAILOVER")?,
7126            Action::ImportedPrivileges => f.write_str("IMPORTED PRIVILEGES")?,
7127            Action::ImportShare => f.write_str("IMPORT SHARE")?,
7128            Action::Insert { .. } => f.write_str("INSERT")?,
7129            Action::Manage { manage_type } => write!(f, "MANAGE {manage_type}")?,
7130            Action::ManageReleases => f.write_str("MANAGE RELEASES")?,
7131            Action::ManageVersions => f.write_str("MANAGE VERSIONS")?,
7132            Action::Modify { modify_type } => {
7133                write!(f, "MODIFY")?;
7134                if let Some(modify_type) = modify_type {
7135                    write!(f, " {modify_type}")?;
7136                }
7137            }
7138            Action::Monitor { monitor_type } => {
7139                write!(f, "MONITOR")?;
7140                if let Some(monitor_type) = monitor_type {
7141                    write!(f, " {monitor_type}")?
7142                }
7143            }
7144            Action::Operate => f.write_str("OPERATE")?,
7145            Action::OverrideShareRestrictions => f.write_str("OVERRIDE SHARE RESTRICTIONS")?,
7146            Action::Ownership => f.write_str("OWNERSHIP")?,
7147            Action::PurchaseDataExchangeListing => f.write_str("PURCHASE DATA EXCHANGE LISTING")?,
7148            Action::Read => f.write_str("READ")?,
7149            Action::ReadSession => f.write_str("READ SESSION")?,
7150            Action::References { .. } => f.write_str("REFERENCES")?,
7151            Action::Replicate => f.write_str("REPLICATE")?,
7152            Action::ResolveAll => f.write_str("RESOLVE ALL")?,
7153            Action::Role { role } => write!(f, "ROLE {role}")?,
7154            Action::Select { .. } => f.write_str("SELECT")?,
7155            Action::Temporary => f.write_str("TEMPORARY")?,
7156            Action::Trigger => f.write_str("TRIGGER")?,
7157            Action::Truncate => f.write_str("TRUNCATE")?,
7158            Action::Update { .. } => f.write_str("UPDATE")?,
7159            Action::Usage => f.write_str("USAGE")?,
7160        };
7161        match self {
7162            Action::Insert { columns }
7163            | Action::References { columns }
7164            | Action::Select { columns }
7165            | Action::Update { columns } => {
7166                if let Some(columns) = columns {
7167                    write!(f, " ({})", display_comma_separated(columns))?;
7168                }
7169            }
7170            _ => (),
7171        };
7172        Ok(())
7173    }
7174}
7175
7176#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7177#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7178#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7179/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
7180/// under `globalPrivileges` in the `CREATE` privilege.
7181pub enum ActionCreateObjectType {
7182    /// An account-level object.
7183    Account,
7184    /// An application object.
7185    Application,
7186    /// An application package object.
7187    ApplicationPackage,
7188    /// A compute pool object.
7189    ComputePool,
7190    /// A data exchange listing.
7191    DataExchangeListing,
7192    /// A database object.
7193    Database,
7194    /// An external volume object.
7195    ExternalVolume,
7196    /// A failover group object.
7197    FailoverGroup,
7198    /// An integration object.
7199    Integration,
7200    /// A network policy object.
7201    NetworkPolicy,
7202    /// An organization listing.
7203    OrganiationListing,
7204    /// A replication group object.
7205    ReplicationGroup,
7206    /// A role object.
7207    Role,
7208    /// A schema object.
7209    Schema,
7210    /// A share object.
7211    Share,
7212    /// A user object.
7213    User,
7214    /// A warehouse object.
7215    Warehouse,
7216}
7217
7218impl fmt::Display for ActionCreateObjectType {
7219    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7220        match self {
7221            ActionCreateObjectType::Account => write!(f, "ACCOUNT"),
7222            ActionCreateObjectType::Application => write!(f, "APPLICATION"),
7223            ActionCreateObjectType::ApplicationPackage => write!(f, "APPLICATION PACKAGE"),
7224            ActionCreateObjectType::ComputePool => write!(f, "COMPUTE POOL"),
7225            ActionCreateObjectType::DataExchangeListing => write!(f, "DATA EXCHANGE LISTING"),
7226            ActionCreateObjectType::Database => write!(f, "DATABASE"),
7227            ActionCreateObjectType::ExternalVolume => write!(f, "EXTERNAL VOLUME"),
7228            ActionCreateObjectType::FailoverGroup => write!(f, "FAILOVER GROUP"),
7229            ActionCreateObjectType::Integration => write!(f, "INTEGRATION"),
7230            ActionCreateObjectType::NetworkPolicy => write!(f, "NETWORK POLICY"),
7231            ActionCreateObjectType::OrganiationListing => write!(f, "ORGANIZATION LISTING"),
7232            ActionCreateObjectType::ReplicationGroup => write!(f, "REPLICATION GROUP"),
7233            ActionCreateObjectType::Role => write!(f, "ROLE"),
7234            ActionCreateObjectType::Schema => write!(f, "SCHEMA"),
7235            ActionCreateObjectType::Share => write!(f, "SHARE"),
7236            ActionCreateObjectType::User => write!(f, "USER"),
7237            ActionCreateObjectType::Warehouse => write!(f, "WAREHOUSE"),
7238        }
7239    }
7240}
7241
7242#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7243#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7244#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7245/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
7246/// under `globalPrivileges` in the `APPLY` privilege.
7247pub enum ActionApplyType {
7248    /// Apply an aggregation policy.
7249    AggregationPolicy,
7250    /// Apply an authentication policy.
7251    AuthenticationPolicy,
7252    /// Apply a join policy.
7253    JoinPolicy,
7254    /// Apply a masking policy.
7255    MaskingPolicy,
7256    /// Apply a packages policy.
7257    PackagesPolicy,
7258    /// Apply a password policy.
7259    PasswordPolicy,
7260    /// Apply a projection policy.
7261    ProjectionPolicy,
7262    /// Apply a row access policy.
7263    RowAccessPolicy,
7264    /// Apply a session policy.
7265    SessionPolicy,
7266    /// Apply a tag.
7267    Tag,
7268}
7269
7270impl fmt::Display for ActionApplyType {
7271    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7272        match self {
7273            ActionApplyType::AggregationPolicy => write!(f, "AGGREGATION POLICY"),
7274            ActionApplyType::AuthenticationPolicy => write!(f, "AUTHENTICATION POLICY"),
7275            ActionApplyType::JoinPolicy => write!(f, "JOIN POLICY"),
7276            ActionApplyType::MaskingPolicy => write!(f, "MASKING POLICY"),
7277            ActionApplyType::PackagesPolicy => write!(f, "PACKAGES POLICY"),
7278            ActionApplyType::PasswordPolicy => write!(f, "PASSWORD POLICY"),
7279            ActionApplyType::ProjectionPolicy => write!(f, "PROJECTION POLICY"),
7280            ActionApplyType::RowAccessPolicy => write!(f, "ROW ACCESS POLICY"),
7281            ActionApplyType::SessionPolicy => write!(f, "SESSION POLICY"),
7282            ActionApplyType::Tag => write!(f, "TAG"),
7283        }
7284    }
7285}
7286
7287#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7288#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7289#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7290/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
7291/// under `globalPrivileges` in the `EXECUTE` privilege.
7292pub enum ActionExecuteObjectType {
7293    /// Alert object.
7294    Alert,
7295    /// Data metric function object.
7296    DataMetricFunction,
7297    /// Managed alert object.
7298    ManagedAlert,
7299    /// Managed task object.
7300    ManagedTask,
7301    /// Task object.
7302    Task,
7303}
7304
7305impl fmt::Display for ActionExecuteObjectType {
7306    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7307        match self {
7308            ActionExecuteObjectType::Alert => write!(f, "ALERT"),
7309            ActionExecuteObjectType::DataMetricFunction => write!(f, "DATA METRIC FUNCTION"),
7310            ActionExecuteObjectType::ManagedAlert => write!(f, "MANAGED ALERT"),
7311            ActionExecuteObjectType::ManagedTask => write!(f, "MANAGED TASK"),
7312            ActionExecuteObjectType::Task => write!(f, "TASK"),
7313        }
7314    }
7315}
7316
7317#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7318#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7319#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7320/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
7321/// under `globalPrivileges` in the `MANAGE` privilege.
7322pub enum ActionManageType {
7323    /// Account support cases management.
7324    AccountSupportCases,
7325    /// Event sharing management.
7326    EventSharing,
7327    /// Grants management.
7328    Grants,
7329    /// Listing auto-fulfillment management.
7330    ListingAutoFulfillment,
7331    /// Organization support cases management.
7332    OrganizationSupportCases,
7333    /// User support cases management.
7334    UserSupportCases,
7335    /// Warehouses management.
7336    Warehouses,
7337}
7338
7339impl fmt::Display for ActionManageType {
7340    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7341        match self {
7342            ActionManageType::AccountSupportCases => write!(f, "ACCOUNT SUPPORT CASES"),
7343            ActionManageType::EventSharing => write!(f, "EVENT SHARING"),
7344            ActionManageType::Grants => write!(f, "GRANTS"),
7345            ActionManageType::ListingAutoFulfillment => write!(f, "LISTING AUTO FULFILLMENT"),
7346            ActionManageType::OrganizationSupportCases => write!(f, "ORGANIZATION SUPPORT CASES"),
7347            ActionManageType::UserSupportCases => write!(f, "USER SUPPORT CASES"),
7348            ActionManageType::Warehouses => write!(f, "WAREHOUSES"),
7349        }
7350    }
7351}
7352
7353#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7354#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7355#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7356/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
7357/// under `globalPrivileges` in the `MODIFY` privilege.
7358pub enum ActionModifyType {
7359    /// Modify log level.
7360    LogLevel,
7361    /// Modify trace level.
7362    TraceLevel,
7363    /// Modify session log level.
7364    SessionLogLevel,
7365    /// Modify session trace level.
7366    SessionTraceLevel,
7367}
7368
7369impl fmt::Display for ActionModifyType {
7370    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7371        match self {
7372            ActionModifyType::LogLevel => write!(f, "LOG LEVEL"),
7373            ActionModifyType::TraceLevel => write!(f, "TRACE LEVEL"),
7374            ActionModifyType::SessionLogLevel => write!(f, "SESSION LOG LEVEL"),
7375            ActionModifyType::SessionTraceLevel => write!(f, "SESSION TRACE LEVEL"),
7376        }
7377    }
7378}
7379
7380#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7381#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7382#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7383/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
7384/// under `globalPrivileges` in the `MONITOR` privilege.
7385pub enum ActionMonitorType {
7386    /// Monitor execution.
7387    Execution,
7388    /// Monitor security.
7389    Security,
7390    /// Monitor usage.
7391    Usage,
7392}
7393
7394impl fmt::Display for ActionMonitorType {
7395    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7396        match self {
7397            ActionMonitorType::Execution => write!(f, "EXECUTION"),
7398            ActionMonitorType::Security => write!(f, "SECURITY"),
7399            ActionMonitorType::Usage => write!(f, "USAGE"),
7400        }
7401    }
7402}
7403
7404/// The principal that receives the privileges
7405#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7406#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7407#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7408pub struct Grantee {
7409    /// The category/type of grantee (role, user, share, etc.).
7410    pub grantee_type: GranteesType,
7411    /// Optional name of the grantee (identifier or user@host).
7412    pub name: Option<GranteeName>,
7413}
7414
7415impl fmt::Display for Grantee {
7416    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7417        match self.grantee_type {
7418            GranteesType::Role => {
7419                write!(f, "ROLE ")?;
7420            }
7421            GranteesType::Share => {
7422                write!(f, "SHARE ")?;
7423            }
7424            GranteesType::User => {
7425                write!(f, "USER ")?;
7426            }
7427            GranteesType::Group => {
7428                write!(f, "GROUP ")?;
7429            }
7430            GranteesType::Public => {
7431                write!(f, "PUBLIC ")?;
7432            }
7433            GranteesType::DatabaseRole => {
7434                write!(f, "DATABASE ROLE ")?;
7435            }
7436            GranteesType::Application => {
7437                write!(f, "APPLICATION ")?;
7438            }
7439            GranteesType::ApplicationRole => {
7440                write!(f, "APPLICATION ROLE ")?;
7441            }
7442            GranteesType::None => (),
7443        }
7444        if let Some(ref name) = self.name {
7445            name.fmt(f)?;
7446        }
7447        Ok(())
7448    }
7449}
7450
7451#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7452#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7453#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7454/// The kind of principal receiving privileges.
7455pub enum GranteesType {
7456    /// A role principal.
7457    Role,
7458    /// A share principal.
7459    Share,
7460    /// A user principal.
7461    User,
7462    /// A group principal.
7463    Group,
7464    /// The public principal.
7465    Public,
7466    /// A database role principal.
7467    DatabaseRole,
7468    /// An application principal.
7469    Application,
7470    /// An application role principal.
7471    ApplicationRole,
7472    /// No specific principal (e.g. `NONE`).
7473    None,
7474}
7475
7476/// Users/roles designated in a GRANT/REVOKE
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))]
7480pub enum GranteeName {
7481    /// A bare identifier
7482    ObjectName(ObjectName),
7483    /// A MySQL user/host pair such as 'root'@'%'
7484    UserHost {
7485        /// The user identifier portion.
7486        user: Ident,
7487        /// The host identifier portion.
7488        host: Ident,
7489    },
7490}
7491
7492impl fmt::Display for GranteeName {
7493    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7494        match self {
7495            GranteeName::ObjectName(name) => name.fmt(f),
7496            GranteeName::UserHost { user, host } => {
7497                write!(f, "{user}@{host}")
7498            }
7499        }
7500    }
7501}
7502
7503/// Objects on which privileges are granted in a GRANT statement.
7504#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7505#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7506#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7507pub enum GrantObjects {
7508    /// Grant privileges on `ALL SEQUENCES IN SCHEMA <schema_name> [, ...]`
7509    AllSequencesInSchema {
7510        /// The target schema names.
7511        schemas: Vec<ObjectName>,
7512    },
7513    /// Grant privileges on `ALL TABLES IN SCHEMA <schema_name> [, ...]`
7514    AllTablesInSchema {
7515        /// The target schema names.
7516        schemas: Vec<ObjectName>,
7517    },
7518    /// Grant privileges on `ALL VIEWS IN SCHEMA <schema_name> [, ...]`
7519    AllViewsInSchema {
7520        /// The target schema names.
7521        schemas: Vec<ObjectName>,
7522    },
7523    /// Grant privileges on `ALL MATERIALIZED VIEWS IN SCHEMA <schema_name> [, ...]`
7524    AllMaterializedViewsInSchema {
7525        /// The target schema names.
7526        schemas: Vec<ObjectName>,
7527    },
7528    /// Grant privileges on `ALL EXTERNAL TABLES IN SCHEMA <schema_name> [, ...]`
7529    AllExternalTablesInSchema {
7530        /// The target schema names.
7531        schemas: Vec<ObjectName>,
7532    },
7533    /// Grant privileges on `ALL FUNCTIONS IN SCHEMA <schema_name> [, ...]`
7534    AllFunctionsInSchema {
7535        /// The target schema names.
7536        schemas: Vec<ObjectName>,
7537    },
7538    /// Grant privileges on `FUTURE SCHEMAS IN DATABASE <database_name> [, ...]`
7539    FutureSchemasInDatabase {
7540        /// The target database names.
7541        databases: Vec<ObjectName>,
7542    },
7543    /// Grant privileges on `FUTURE TABLES IN SCHEMA <schema_name> [, ...]`
7544    FutureTablesInSchema {
7545        /// The target schema names.
7546        schemas: Vec<ObjectName>,
7547    },
7548    /// Grant privileges on `FUTURE VIEWS IN SCHEMA <schema_name> [, ...]`
7549    FutureViewsInSchema {
7550        /// The target schema names.
7551        schemas: Vec<ObjectName>,
7552    },
7553    /// Grant privileges on `FUTURE EXTERNAL TABLES IN SCHEMA <schema_name> [, ...]`
7554    FutureExternalTablesInSchema {
7555        /// The target schema names.
7556        schemas: Vec<ObjectName>,
7557    },
7558    /// Grant privileges on `FUTURE MATERIALIZED VIEWS IN SCHEMA <schema_name> [, ...]`
7559    FutureMaterializedViewsInSchema {
7560        /// The target schema names.
7561        schemas: Vec<ObjectName>,
7562    },
7563    /// Grant privileges on `FUTURE SEQUENCES IN SCHEMA <schema_name> [, ...]`
7564    FutureSequencesInSchema {
7565        /// The target schema names.
7566        schemas: Vec<ObjectName>,
7567    },
7568    /// Grant privileges on specific databases
7569    Databases(Vec<ObjectName>),
7570    /// Grant privileges on specific schemas
7571    Schemas(Vec<ObjectName>),
7572    /// Grant privileges on specific sequences
7573    Sequences(Vec<ObjectName>),
7574    /// Grant privileges on specific tables
7575    Tables(Vec<ObjectName>),
7576    /// Grant privileges on specific views
7577    Views(Vec<ObjectName>),
7578    /// Grant privileges on specific warehouses
7579    Warehouses(Vec<ObjectName>),
7580    /// Grant privileges on specific integrations
7581    Integrations(Vec<ObjectName>),
7582    /// Grant privileges on resource monitors
7583    ResourceMonitors(Vec<ObjectName>),
7584    /// Grant privileges on users
7585    Users(Vec<ObjectName>),
7586    /// Grant privileges on compute pools
7587    ComputePools(Vec<ObjectName>),
7588    /// Grant privileges on connections
7589    Connections(Vec<ObjectName>),
7590    /// Grant privileges on failover groups
7591    FailoverGroup(Vec<ObjectName>),
7592    /// Grant privileges on replication group
7593    ReplicationGroup(Vec<ObjectName>),
7594    /// Grant privileges on external volumes
7595    ExternalVolumes(Vec<ObjectName>),
7596    /// Grant privileges on a procedure. In dialects that
7597    /// support overloading, the argument types must be specified.
7598    ///
7599    /// For example:
7600    /// `GRANT USAGE ON PROCEDURE foo(varchar) TO ROLE role1`
7601    Procedure {
7602        /// The procedure name.
7603        name: ObjectName,
7604        /// Optional argument types for overloaded procedures.
7605        arg_types: Vec<DataType>,
7606    },
7607
7608    /// Grant privileges on a function. In dialects that
7609    /// support overloading, the argument types must be specified.
7610    ///
7611    /// For example:
7612    /// `GRANT USAGE ON FUNCTION foo(varchar) TO ROLE role1`
7613    Function {
7614        /// The function name.
7615        name: ObjectName,
7616        /// Optional argument types for overloaded functions.
7617        arg_types: Vec<DataType>,
7618    },
7619}
7620
7621impl fmt::Display for GrantObjects {
7622    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7623        match self {
7624            GrantObjects::Sequences(sequences) => {
7625                write!(f, "SEQUENCE {}", display_comma_separated(sequences))
7626            }
7627            GrantObjects::Databases(databases) => {
7628                write!(f, "DATABASE {}", display_comma_separated(databases))
7629            }
7630            GrantObjects::Schemas(schemas) => {
7631                write!(f, "SCHEMA {}", display_comma_separated(schemas))
7632            }
7633            GrantObjects::Tables(tables) => {
7634                write!(f, "{}", display_comma_separated(tables))
7635            }
7636            GrantObjects::Views(views) => {
7637                write!(f, "VIEW {}", display_comma_separated(views))
7638            }
7639            GrantObjects::Warehouses(warehouses) => {
7640                write!(f, "WAREHOUSE {}", display_comma_separated(warehouses))
7641            }
7642            GrantObjects::Integrations(integrations) => {
7643                write!(f, "INTEGRATION {}", display_comma_separated(integrations))
7644            }
7645            GrantObjects::AllSequencesInSchema { schemas } => {
7646                write!(
7647                    f,
7648                    "ALL SEQUENCES IN SCHEMA {}",
7649                    display_comma_separated(schemas)
7650                )
7651            }
7652            GrantObjects::AllTablesInSchema { schemas } => {
7653                write!(
7654                    f,
7655                    "ALL TABLES IN SCHEMA {}",
7656                    display_comma_separated(schemas)
7657                )
7658            }
7659            GrantObjects::AllExternalTablesInSchema { schemas } => {
7660                write!(
7661                    f,
7662                    "ALL EXTERNAL TABLES IN SCHEMA {}",
7663                    display_comma_separated(schemas)
7664                )
7665            }
7666            GrantObjects::AllViewsInSchema { schemas } => {
7667                write!(
7668                    f,
7669                    "ALL VIEWS IN SCHEMA {}",
7670                    display_comma_separated(schemas)
7671                )
7672            }
7673            GrantObjects::AllMaterializedViewsInSchema { schemas } => {
7674                write!(
7675                    f,
7676                    "ALL MATERIALIZED VIEWS IN SCHEMA {}",
7677                    display_comma_separated(schemas)
7678                )
7679            }
7680            GrantObjects::AllFunctionsInSchema { schemas } => {
7681                write!(
7682                    f,
7683                    "ALL FUNCTIONS IN SCHEMA {}",
7684                    display_comma_separated(schemas)
7685                )
7686            }
7687            GrantObjects::FutureSchemasInDatabase { databases } => {
7688                write!(
7689                    f,
7690                    "FUTURE SCHEMAS IN DATABASE {}",
7691                    display_comma_separated(databases)
7692                )
7693            }
7694            GrantObjects::FutureTablesInSchema { schemas } => {
7695                write!(
7696                    f,
7697                    "FUTURE TABLES IN SCHEMA {}",
7698                    display_comma_separated(schemas)
7699                )
7700            }
7701            GrantObjects::FutureExternalTablesInSchema { schemas } => {
7702                write!(
7703                    f,
7704                    "FUTURE EXTERNAL TABLES IN SCHEMA {}",
7705                    display_comma_separated(schemas)
7706                )
7707            }
7708            GrantObjects::FutureViewsInSchema { schemas } => {
7709                write!(
7710                    f,
7711                    "FUTURE VIEWS IN SCHEMA {}",
7712                    display_comma_separated(schemas)
7713                )
7714            }
7715            GrantObjects::FutureMaterializedViewsInSchema { schemas } => {
7716                write!(
7717                    f,
7718                    "FUTURE MATERIALIZED VIEWS IN SCHEMA {}",
7719                    display_comma_separated(schemas)
7720                )
7721            }
7722            GrantObjects::FutureSequencesInSchema { schemas } => {
7723                write!(
7724                    f,
7725                    "FUTURE SEQUENCES IN SCHEMA {}",
7726                    display_comma_separated(schemas)
7727                )
7728            }
7729            GrantObjects::ResourceMonitors(objects) => {
7730                write!(f, "RESOURCE MONITOR {}", display_comma_separated(objects))
7731            }
7732            GrantObjects::Users(objects) => {
7733                write!(f, "USER {}", display_comma_separated(objects))
7734            }
7735            GrantObjects::ComputePools(objects) => {
7736                write!(f, "COMPUTE POOL {}", display_comma_separated(objects))
7737            }
7738            GrantObjects::Connections(objects) => {
7739                write!(f, "CONNECTION {}", display_comma_separated(objects))
7740            }
7741            GrantObjects::FailoverGroup(objects) => {
7742                write!(f, "FAILOVER GROUP {}", display_comma_separated(objects))
7743            }
7744            GrantObjects::ReplicationGroup(objects) => {
7745                write!(f, "REPLICATION GROUP {}", display_comma_separated(objects))
7746            }
7747            GrantObjects::ExternalVolumes(objects) => {
7748                write!(f, "EXTERNAL VOLUME {}", display_comma_separated(objects))
7749            }
7750            GrantObjects::Procedure { name, arg_types } => {
7751                write!(f, "PROCEDURE {name}")?;
7752                if !arg_types.is_empty() {
7753                    write!(f, "({})", display_comma_separated(arg_types))?;
7754                }
7755                Ok(())
7756            }
7757            GrantObjects::Function { name, arg_types } => {
7758                write!(f, "FUNCTION {name}")?;
7759                if !arg_types.is_empty() {
7760                    write!(f, "({})", display_comma_separated(arg_types))?;
7761                }
7762                Ok(())
7763            }
7764        }
7765    }
7766}
7767
7768/// A `DENY` statement
7769///
7770/// [MsSql](https://learn.microsoft.com/en-us/sql/t-sql/statements/deny-transact-sql)
7771#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7772#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7773#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7774pub struct DenyStatement {
7775    /// The privileges to deny.
7776    pub privileges: Privileges,
7777    /// The objects the privileges apply to.
7778    pub objects: GrantObjects,
7779    /// The grantees (users/roles) to whom the denial applies.
7780    pub grantees: Vec<Grantee>,
7781    /// Optional identifier of the principal that performed the grant.
7782    pub granted_by: Option<Ident>,
7783    /// Optional cascade option controlling dependent objects.
7784    pub cascade: Option<CascadeOption>,
7785}
7786
7787impl fmt::Display for DenyStatement {
7788    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7789        write!(f, "DENY {}", self.privileges)?;
7790        write!(f, " ON {}", self.objects)?;
7791        if !self.grantees.is_empty() {
7792            write!(f, " TO {}", display_comma_separated(&self.grantees))?;
7793        }
7794        if let Some(cascade) = &self.cascade {
7795            write!(f, " {cascade}")?;
7796        }
7797        if let Some(granted_by) = &self.granted_by {
7798            write!(f, " AS {granted_by}")?;
7799        }
7800        Ok(())
7801    }
7802}
7803
7804/// SQL assignment `foo = expr` as used in SQLUpdate
7805#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7806#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7807#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7808pub struct Assignment {
7809    /// The left-hand side of the assignment.
7810    pub target: AssignmentTarget,
7811    /// The expression assigned to the target.
7812    pub value: Expr,
7813}
7814
7815impl fmt::Display for Assignment {
7816    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7817        write!(f, "{} = {}", self.target, self.value)
7818    }
7819}
7820
7821/// Left-hand side of an assignment in an UPDATE statement,
7822/// e.g. `foo` in `foo = 5` (ColumnName assignment) or
7823/// `(a, b)` in `(a, b) = (1, 2)` (Tuple assignment).
7824#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7825#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7826#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7827pub enum AssignmentTarget {
7828    /// A single column
7829    ColumnName(ObjectName),
7830    /// A tuple of columns
7831    Tuple(Vec<ObjectName>),
7832}
7833
7834impl fmt::Display for AssignmentTarget {
7835    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7836        match self {
7837            AssignmentTarget::ColumnName(column) => write!(f, "{column}"),
7838            AssignmentTarget::Tuple(columns) => write!(f, "({})", display_comma_separated(columns)),
7839        }
7840    }
7841}
7842
7843#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7844#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7845#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7846/// Expression forms allowed as a function argument.
7847pub enum FunctionArgExpr {
7848    /// A normal expression argument.
7849    Expr(Expr),
7850    /// Qualified wildcard, e.g. `alias.*` or `schema.table.*`.
7851    QualifiedWildcard(ObjectName),
7852    /// An unqualified `*` wildcard.
7853    Wildcard,
7854    /// An unqualified `*` wildcard with additional options, e.g. `* EXCLUDE(col)`.
7855    ///
7856    /// Used in Snowflake to support expressions like `HASH(* EXCLUDE(col))`.
7857    WildcardWithOptions(WildcardAdditionalOptions),
7858}
7859
7860impl From<Expr> for FunctionArgExpr {
7861    fn from(wildcard_expr: Expr) -> Self {
7862        match wildcard_expr {
7863            Expr::QualifiedWildcard(prefix, _) => Self::QualifiedWildcard(prefix),
7864            Expr::Wildcard(_) => Self::Wildcard,
7865            expr => Self::Expr(expr),
7866        }
7867    }
7868}
7869
7870impl fmt::Display for FunctionArgExpr {
7871    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7872        match self {
7873            FunctionArgExpr::Expr(expr) => write!(f, "{expr}"),
7874            FunctionArgExpr::QualifiedWildcard(prefix) => write!(f, "{prefix}.*"),
7875            FunctionArgExpr::Wildcard => f.write_str("*"),
7876            FunctionArgExpr::WildcardWithOptions(opts) => write!(f, "*{opts}"),
7877        }
7878    }
7879}
7880
7881#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7882#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7883#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7884/// Operator used to separate function arguments
7885pub enum FunctionArgOperator {
7886    /// function(arg1 = value1)
7887    Equals,
7888    /// function(arg1 => value1)
7889    RightArrow,
7890    /// function(arg1 := value1)
7891    Assignment,
7892    /// function(arg1 : value1)
7893    Colon,
7894    /// function(arg1 VALUE value1)
7895    Value,
7896}
7897
7898impl fmt::Display for FunctionArgOperator {
7899    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7900        match self {
7901            FunctionArgOperator::Equals => f.write_str("="),
7902            FunctionArgOperator::RightArrow => f.write_str("=>"),
7903            FunctionArgOperator::Assignment => f.write_str(":="),
7904            FunctionArgOperator::Colon => f.write_str(":"),
7905            FunctionArgOperator::Value => f.write_str("VALUE"),
7906        }
7907    }
7908}
7909
7910#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7911#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7912#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7913/// Forms of function arguments (named, expression-named, or positional).
7914pub enum FunctionArg {
7915    /// `name` is identifier
7916    ///
7917    /// Enabled when `Dialect::supports_named_fn_args_with_expr_name` returns 'false'
7918    Named {
7919        /// The identifier name of the argument.
7920        name: Ident,
7921        /// The argument expression or wildcard form.
7922        arg: FunctionArgExpr,
7923        /// The operator separating name and value.
7924        operator: FunctionArgOperator,
7925    },
7926    /// `name` is arbitrary expression
7927    ///
7928    /// Enabled when `Dialect::supports_named_fn_args_with_expr_name` returns 'true'
7929    ExprNamed {
7930        /// The expression used as the argument name.
7931        name: Expr,
7932        /// The argument expression or wildcard form.
7933        arg: FunctionArgExpr,
7934        /// The operator separating name and value.
7935        operator: FunctionArgOperator,
7936    },
7937    /// An unnamed argument (positional), given by expression or wildcard.
7938    Unnamed(FunctionArgExpr),
7939}
7940
7941impl fmt::Display for FunctionArg {
7942    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7943        match self {
7944            FunctionArg::Named {
7945                name,
7946                arg,
7947                operator,
7948            } => write!(f, "{name} {operator} {arg}"),
7949            FunctionArg::ExprNamed {
7950                name,
7951                arg,
7952                operator,
7953            } => write!(f, "{name} {operator} {arg}"),
7954            FunctionArg::Unnamed(unnamed_arg) => write!(f, "{unnamed_arg}"),
7955        }
7956    }
7957}
7958
7959#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7960#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7961#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7962/// Which cursor(s) to close.
7963pub enum CloseCursor {
7964    /// Close all cursors.
7965    All,
7966    /// Close a specific cursor by name.
7967    Specific {
7968        /// The name of the cursor to close.
7969        name: Ident,
7970    },
7971}
7972
7973impl fmt::Display for CloseCursor {
7974    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7975        match self {
7976            CloseCursor::All => write!(f, "ALL"),
7977            CloseCursor::Specific { name } => write!(f, "{name}"),
7978        }
7979    }
7980}
7981
7982/// A Drop Domain statement
7983#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7984#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7985#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7986pub struct DropDomain {
7987    /// Whether to drop the domain if it exists
7988    pub if_exists: bool,
7989    /// The name of the domain to drop
7990    pub name: ObjectName,
7991    /// The behavior to apply when dropping the domain
7992    pub drop_behavior: Option<DropBehavior>,
7993}
7994
7995/// A constant of form `<data_type> 'value'`.
7996/// This can represent ANSI SQL `DATE`, `TIME`, and `TIMESTAMP` literals (such as `DATE '2020-01-01'`),
7997/// as well as constants of other types (a non-standard PostgreSQL extension).
7998#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7999#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8000#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8001pub struct TypedString {
8002    /// The data type of the typed string (e.g. DATE, TIME, TIMESTAMP).
8003    pub data_type: DataType,
8004    /// The value of the constant.
8005    /// Hint: you can unwrap the string value using `value.into_string()`.
8006    pub value: ValueWithSpan,
8007    /// Flags whether this TypedString uses the [ODBC syntax].
8008    ///
8009    /// Example:
8010    /// ```sql
8011    /// -- An ODBC date literal:
8012    /// SELECT {d '2025-07-16'}
8013    /// -- This is equivalent to the standard ANSI SQL literal:
8014    /// SELECT DATE '2025-07-16'
8015    ///
8016    /// [ODBC syntax]: https://learn.microsoft.com/en-us/sql/odbc/reference/develop-app/date-time-and-timestamp-literals?view=sql-server-2017
8017    pub uses_odbc_syntax: bool,
8018}
8019
8020impl fmt::Display for TypedString {
8021    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8022        let data_type = &self.data_type;
8023        let value = &self.value;
8024        match self.uses_odbc_syntax {
8025            false => {
8026                write!(f, "{data_type}")?;
8027                write!(f, " {value}")
8028            }
8029            true => {
8030                let prefix = match data_type {
8031                    DataType::Date => "d",
8032                    DataType::Time(..) => "t",
8033                    DataType::Timestamp(..) => "ts",
8034                    _ => "?",
8035                };
8036                write!(f, "{{{prefix} {value}}}")
8037            }
8038        }
8039    }
8040}
8041
8042/// A function call
8043#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8044#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8045#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8046pub struct Function {
8047    /// The function name (may be qualified).
8048    pub name: ObjectName,
8049    /// Flags whether this function call uses the [ODBC syntax].
8050    ///
8051    /// Example:
8052    /// ```sql
8053    /// SELECT {fn CONCAT('foo', 'bar')}
8054    /// ```
8055    ///
8056    /// [ODBC syntax]: https://learn.microsoft.com/en-us/sql/odbc/reference/develop-app/scalar-function-calls?view=sql-server-2017
8057    pub uses_odbc_syntax: bool,
8058    /// The parameters to the function, including any options specified within the
8059    /// delimiting parentheses.
8060    ///
8061    /// Example:
8062    /// ```plaintext
8063    /// HISTOGRAM(0.5, 0.6)(x, y)
8064    /// ```
8065    ///
8066    /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/aggregate-functions/parametric-functions)
8067    pub parameters: FunctionArguments,
8068    /// The arguments to the function, including any options specified within the
8069    /// delimiting parentheses.
8070    pub args: FunctionArguments,
8071    /// e.g. `x > 5` in `COUNT(x) FILTER (WHERE x > 5)`
8072    pub filter: Option<Box<Expr>>,
8073    /// Indicates how `NULL`s should be handled in the calculation.
8074    ///
8075    /// Example:
8076    /// ```plaintext
8077    /// FIRST_VALUE( <expr> ) [ { IGNORE | RESPECT } NULLS ] OVER ...
8078    /// ```
8079    ///
8080    /// [Snowflake](https://docs.snowflake.com/en/sql-reference/functions/first_value)
8081    pub null_treatment: Option<NullTreatment>,
8082    /// The `OVER` clause, indicating a window function call.
8083    pub over: Option<WindowType>,
8084    /// A clause used with certain aggregate functions to control the ordering
8085    /// within grouped sets before the function is applied.
8086    ///
8087    /// Syntax:
8088    /// ```plaintext
8089    /// <aggregate_function>(expression) WITHIN GROUP (ORDER BY key [ASC | DESC], ...)
8090    /// ```
8091    pub within_group: Vec<OrderByExpr>,
8092}
8093
8094impl fmt::Display for Function {
8095    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8096        if self.uses_odbc_syntax {
8097            write!(f, "{{fn ")?;
8098        }
8099
8100        write!(f, "{}{}{}", self.name, self.parameters, self.args)?;
8101
8102        if !self.within_group.is_empty() {
8103            write!(
8104                f,
8105                " WITHIN GROUP (ORDER BY {})",
8106                display_comma_separated(&self.within_group)
8107            )?;
8108        }
8109
8110        if let Some(filter_cond) = &self.filter {
8111            write!(f, " FILTER (WHERE {filter_cond})")?;
8112        }
8113
8114        if let Some(null_treatment) = &self.null_treatment {
8115            write!(f, " {null_treatment}")?;
8116        }
8117
8118        if let Some(o) = &self.over {
8119            f.write_str(" OVER ")?;
8120            o.fmt(f)?;
8121        }
8122
8123        if self.uses_odbc_syntax {
8124            write!(f, "}}")?;
8125        }
8126
8127        Ok(())
8128    }
8129}
8130
8131/// The arguments passed to a function call.
8132#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8133#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8134#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8135pub enum FunctionArguments {
8136    /// Used for special functions like `CURRENT_TIMESTAMP` that are invoked
8137    /// without parentheses.
8138    None,
8139    /// On some dialects, a subquery can be passed without surrounding
8140    /// parentheses if it's the sole argument to the function.
8141    Subquery(Box<Query>),
8142    /// A normal function argument list, including any clauses within it such as
8143    /// `DISTINCT` or `ORDER BY`.
8144    List(FunctionArgumentList),
8145}
8146
8147impl fmt::Display for FunctionArguments {
8148    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8149        match self {
8150            FunctionArguments::None => Ok(()),
8151            FunctionArguments::Subquery(query) => write!(f, "({query})"),
8152            FunctionArguments::List(args) => write!(f, "({args})"),
8153        }
8154    }
8155}
8156
8157/// This represents everything inside the parentheses when calling a function.
8158#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8159#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8160#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8161pub struct FunctionArgumentList {
8162    /// `[ ALL | DISTINCT ]`
8163    pub duplicate_treatment: Option<DuplicateTreatment>,
8164    /// The function arguments.
8165    pub args: Vec<FunctionArg>,
8166    /// Additional clauses specified within the argument list.
8167    pub clauses: Vec<FunctionArgumentClause>,
8168}
8169
8170impl fmt::Display for FunctionArgumentList {
8171    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8172        if let Some(duplicate_treatment) = self.duplicate_treatment {
8173            write!(f, "{duplicate_treatment} ")?;
8174        }
8175        write!(f, "{}", display_comma_separated(&self.args))?;
8176        if !self.clauses.is_empty() {
8177            if !self.args.is_empty() {
8178                write!(f, " ")?;
8179            }
8180            write!(f, "{}", display_separated(&self.clauses, " "))?;
8181        }
8182        Ok(())
8183    }
8184}
8185
8186#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8187#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8188#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8189/// Clauses that can appear inside a function argument list.
8190pub enum FunctionArgumentClause {
8191    /// Indicates how `NULL`s should be handled in the calculation, e.g. in `FIRST_VALUE` on [BigQuery].
8192    ///
8193    /// Syntax:
8194    /// ```plaintext
8195    /// { IGNORE | RESPECT } NULLS ]
8196    /// ```
8197    ///
8198    /// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/navigation_functions#first_value
8199    IgnoreOrRespectNulls(NullTreatment),
8200    /// Specifies the the ordering for some ordered set aggregates, e.g. `ARRAY_AGG` on [BigQuery].
8201    ///
8202    /// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/aggregate_functions#array_agg
8203    OrderBy(Vec<OrderByExpr>),
8204    /// Specifies a limit for the `ARRAY_AGG` and `ARRAY_CONCAT_AGG` functions on BigQuery.
8205    Limit(Expr),
8206    /// Specifies the behavior on overflow of the `LISTAGG` function.
8207    ///
8208    /// See <https://trino.io/docs/current/functions/aggregate.html>.
8209    OnOverflow(ListAggOnOverflow),
8210    /// Specifies a minimum or maximum bound on the input to [`ANY_VALUE`] on BigQuery.
8211    ///
8212    /// Syntax:
8213    /// ```plaintext
8214    /// HAVING { MAX | MIN } expression
8215    /// ```
8216    ///
8217    /// [`ANY_VALUE`]: https://cloud.google.com/bigquery/docs/reference/standard-sql/aggregate_functions#any_value
8218    Having(HavingBound),
8219    /// The `SEPARATOR` clause to the [`GROUP_CONCAT`] function in MySQL.
8220    ///
8221    /// [`GROUP_CONCAT`]: https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html#function_group-concat
8222    Separator(ValueWithSpan),
8223    /// The `ON NULL` clause for some JSON functions.
8224    ///
8225    /// [MSSQL `JSON_ARRAY`](https://learn.microsoft.com/en-us/sql/t-sql/functions/json-array-transact-sql?view=sql-server-ver16)
8226    /// [MSSQL `JSON_OBJECT`](https://learn.microsoft.com/en-us/sql/t-sql/functions/json-object-transact-sql?view=sql-server-ver16>)
8227    /// [PostgreSQL JSON functions](https://www.postgresql.org/docs/current/functions-json.html#FUNCTIONS-JSON-PROCESSING)
8228    JsonNullClause(JsonNullClause),
8229    /// The `RETURNING` clause for some JSON functions in PostgreSQL
8230    ///
8231    /// [`JSON_OBJECT`](https://www.postgresql.org/docs/current/functions-json.html#:~:text=json_object)
8232    JsonReturningClause(JsonReturningClause),
8233}
8234
8235impl fmt::Display for FunctionArgumentClause {
8236    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8237        match self {
8238            FunctionArgumentClause::IgnoreOrRespectNulls(null_treatment) => {
8239                write!(f, "{null_treatment}")
8240            }
8241            FunctionArgumentClause::OrderBy(order_by) => {
8242                write!(f, "ORDER BY {}", display_comma_separated(order_by))
8243            }
8244            FunctionArgumentClause::Limit(limit) => write!(f, "LIMIT {limit}"),
8245            FunctionArgumentClause::OnOverflow(on_overflow) => write!(f, "{on_overflow}"),
8246            FunctionArgumentClause::Having(bound) => write!(f, "{bound}"),
8247            FunctionArgumentClause::Separator(sep) => write!(f, "SEPARATOR {sep}"),
8248            FunctionArgumentClause::JsonNullClause(null_clause) => write!(f, "{null_clause}"),
8249            FunctionArgumentClause::JsonReturningClause(returning_clause) => {
8250                write!(f, "{returning_clause}")
8251            }
8252        }
8253    }
8254}
8255
8256/// A method call
8257#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8258#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8259#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8260pub struct Method {
8261    /// The expression on which the method is invoked.
8262    pub expr: Box<Expr>,
8263    // always non-empty
8264    /// The sequence of chained method calls.
8265    pub method_chain: Vec<Function>,
8266}
8267
8268impl fmt::Display for Method {
8269    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8270        write!(
8271            f,
8272            "{}.{}",
8273            self.expr,
8274            display_separated(&self.method_chain, ".")
8275        )
8276    }
8277}
8278
8279#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8280#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8281#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8282/// How duplicate values are treated inside function argument lists.
8283pub enum DuplicateTreatment {
8284    /// Consider only unique values.
8285    Distinct,
8286    /// Retain all duplicate values (the default).
8287    All,
8288}
8289
8290impl fmt::Display for DuplicateTreatment {
8291    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8292        match self {
8293            DuplicateTreatment::Distinct => write!(f, "DISTINCT"),
8294            DuplicateTreatment::All => write!(f, "ALL"),
8295        }
8296    }
8297}
8298
8299#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8300#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8301#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8302/// How the `ANALYZE`/`EXPLAIN ANALYZE` format is specified.
8303pub enum AnalyzeFormatKind {
8304    /// Format provided as a keyword, e.g. `FORMAT JSON`.
8305    Keyword(AnalyzeFormat),
8306    /// Format provided as an assignment, e.g. `FORMAT=JSON`.
8307    Assignment(AnalyzeFormat),
8308}
8309
8310impl fmt::Display for AnalyzeFormatKind {
8311    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
8312        match self {
8313            AnalyzeFormatKind::Keyword(format) => write!(f, "FORMAT {format}"),
8314            AnalyzeFormatKind::Assignment(format) => write!(f, "FORMAT={format}"),
8315        }
8316    }
8317}
8318
8319#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8320#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8321#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8322/// Output formats supported for `ANALYZE`/`EXPLAIN ANALYZE`.
8323pub enum AnalyzeFormat {
8324    /// Plain text format.
8325    TEXT,
8326    /// Graphviz DOT format.
8327    GRAPHVIZ,
8328    /// JSON format.
8329    JSON,
8330    /// Traditional explain output.
8331    TRADITIONAL,
8332    /// Tree-style explain output.
8333    TREE,
8334}
8335
8336impl fmt::Display for AnalyzeFormat {
8337    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
8338        f.write_str(match self {
8339            AnalyzeFormat::TEXT => "TEXT",
8340            AnalyzeFormat::GRAPHVIZ => "GRAPHVIZ",
8341            AnalyzeFormat::JSON => "JSON",
8342            AnalyzeFormat::TRADITIONAL => "TRADITIONAL",
8343            AnalyzeFormat::TREE => "TREE",
8344        })
8345    }
8346}
8347
8348/// External table's available file format
8349#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8350#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8351#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8352pub enum FileFormat {
8353    /// Text file format.
8354    TEXTFILE,
8355    /// Sequence file format.
8356    SEQUENCEFILE,
8357    /// ORC file format.
8358    ORC,
8359    /// Parquet file format.
8360    PARQUET,
8361    /// Avro file format.
8362    AVRO,
8363    /// RCFile format.
8364    RCFILE,
8365    /// JSON file format.
8366    JSONFILE,
8367}
8368
8369impl fmt::Display for FileFormat {
8370    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8371        use self::FileFormat::*;
8372        f.write_str(match self {
8373            TEXTFILE => "TEXTFILE",
8374            SEQUENCEFILE => "SEQUENCEFILE",
8375            ORC => "ORC",
8376            PARQUET => "PARQUET",
8377            AVRO => "AVRO",
8378            RCFILE => "RCFILE",
8379            JSONFILE => "JSONFILE",
8380        })
8381    }
8382}
8383
8384/// The `ON OVERFLOW` clause of a LISTAGG invocation
8385#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8386#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8387#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8388pub enum ListAggOnOverflow {
8389    /// `ON OVERFLOW ERROR`
8390    Error,
8391
8392    /// `ON OVERFLOW TRUNCATE [ <filler> ] WITH[OUT] COUNT`
8393    Truncate {
8394        /// Optional filler expression used when truncating.
8395        filler: Option<Box<Expr>>,
8396        /// Whether to include a count when truncating.
8397        with_count: bool,
8398    },
8399}
8400
8401impl fmt::Display for ListAggOnOverflow {
8402    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8403        write!(f, "ON OVERFLOW")?;
8404        match self {
8405            ListAggOnOverflow::Error => write!(f, " ERROR"),
8406            ListAggOnOverflow::Truncate { filler, with_count } => {
8407                write!(f, " TRUNCATE")?;
8408                if let Some(filler) = filler {
8409                    write!(f, " {filler}")?;
8410                }
8411                if *with_count {
8412                    write!(f, " WITH")?;
8413                } else {
8414                    write!(f, " WITHOUT")?;
8415                }
8416                write!(f, " COUNT")
8417            }
8418        }
8419    }
8420}
8421
8422/// The `HAVING` clause in a call to `ANY_VALUE` on BigQuery.
8423#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8424#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8425#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8426pub struct HavingBound(pub HavingBoundKind, pub Expr);
8427
8428impl fmt::Display for HavingBound {
8429    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8430        write!(f, "HAVING {} {}", self.0, self.1)
8431    }
8432}
8433
8434#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8435#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8436#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8437/// Which bound is used in a HAVING clause for ANY_VALUE on BigQuery.
8438pub enum HavingBoundKind {
8439    /// The minimum bound.
8440    Min,
8441    /// The maximum bound.
8442    Max,
8443}
8444
8445impl fmt::Display for HavingBoundKind {
8446    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8447        match self {
8448            HavingBoundKind::Min => write!(f, "MIN"),
8449            HavingBoundKind::Max => write!(f, "MAX"),
8450        }
8451    }
8452}
8453
8454#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8455#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8456#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8457/// Types of database objects referenced by DDL statements.
8458pub enum ObjectType {
8459    /// A collation.
8460    Collation,
8461    /// A table.
8462    Table,
8463    /// A view.
8464    View,
8465    /// A materialized view.
8466    MaterializedView,
8467    /// An index.
8468    Index,
8469    /// A schema.
8470    Schema,
8471    /// A database.
8472    Database,
8473    /// A role.
8474    Role,
8475    /// A sequence.
8476    Sequence,
8477    /// A stage.
8478    Stage,
8479    /// A type definition.
8480    Type,
8481    /// A user.
8482    User,
8483    /// A stream.
8484    Stream,
8485}
8486
8487impl fmt::Display for ObjectType {
8488    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8489        f.write_str(match self {
8490            ObjectType::Collation => "COLLATION",
8491            ObjectType::Table => "TABLE",
8492            ObjectType::View => "VIEW",
8493            ObjectType::MaterializedView => "MATERIALIZED VIEW",
8494            ObjectType::Index => "INDEX",
8495            ObjectType::Schema => "SCHEMA",
8496            ObjectType::Database => "DATABASE",
8497            ObjectType::Role => "ROLE",
8498            ObjectType::Sequence => "SEQUENCE",
8499            ObjectType::Stage => "STAGE",
8500            ObjectType::Type => "TYPE",
8501            ObjectType::User => "USER",
8502            ObjectType::Stream => "STREAM",
8503        })
8504    }
8505}
8506
8507#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8508#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8509#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8510/// Types supported by `KILL` statements.
8511pub enum KillType {
8512    /// Kill a connection.
8513    Connection,
8514    /// Kill a running query.
8515    Query,
8516    /// Kill a mutation (ClickHouse).
8517    Mutation,
8518}
8519
8520impl fmt::Display for KillType {
8521    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8522        f.write_str(match self {
8523            // MySQL
8524            KillType::Connection => "CONNECTION",
8525            KillType::Query => "QUERY",
8526            // Clickhouse supports Mutation
8527            KillType::Mutation => "MUTATION",
8528        })
8529    }
8530}
8531
8532#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8533#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8534#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8535/// Distribution style options for Hive tables.
8536pub enum HiveDistributionStyle {
8537    /// Partitioned distribution with the given columns.
8538    PARTITIONED {
8539        /// Columns used for partitioning.
8540        columns: Vec<ColumnDef>,
8541    },
8542    /// Skewed distribution definition.
8543    SKEWED {
8544        /// Columns participating in the skew definition.
8545        columns: Vec<ColumnDef>,
8546        /// Columns listed in the `ON` clause for skewing.
8547        on: Vec<ColumnDef>,
8548        /// Whether skewed data is stored as directories.
8549        stored_as_directories: bool,
8550    },
8551    /// No distribution style specified.
8552    NONE,
8553}
8554
8555#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8556#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8557#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8558/// Row format specification for Hive tables (SERDE or DELIMITED).
8559pub enum HiveRowFormat {
8560    /// SerDe class specification with the implementing class name.
8561    SERDE {
8562        /// The SerDe implementation class name.
8563        class: String,
8564    },
8565    /// Delimited row format with one or more delimiter specifications.
8566    DELIMITED {
8567        /// The list of delimiters used for delimiting fields/lines.
8568        delimiters: Vec<HiveRowDelimiter>,
8569    },
8570}
8571
8572#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8573#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8574#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8575/// Format specification for `LOAD DATA` Hive operations.
8576pub struct HiveLoadDataFormat {
8577    /// SerDe expression used for the table.
8578    pub serde: Expr,
8579    /// Input format expression.
8580    pub input_format: Expr,
8581}
8582
8583#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8584#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8585#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8586/// A single row delimiter specification for Hive `ROW FORMAT`.
8587pub struct HiveRowDelimiter {
8588    /// The delimiter kind (fields/lines/etc.).
8589    pub delimiter: HiveDelimiter,
8590    /// The delimiter character identifier.
8591    pub char: Ident,
8592}
8593
8594impl fmt::Display for HiveRowDelimiter {
8595    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8596        write!(f, "{} ", self.delimiter)?;
8597        write!(f, "{}", self.char)
8598    }
8599}
8600
8601#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8602#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8603#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8604/// Kind of delimiter used in Hive `ROW FORMAT` definitions.
8605pub enum HiveDelimiter {
8606    /// Fields terminated by a delimiter.
8607    FieldsTerminatedBy,
8608    /// Fields escaped by a character.
8609    FieldsEscapedBy,
8610    /// Collection items terminated by a delimiter.
8611    CollectionItemsTerminatedBy,
8612    /// Map keys terminated by a delimiter.
8613    MapKeysTerminatedBy,
8614    /// Lines terminated by a delimiter.
8615    LinesTerminatedBy,
8616    /// Null represented by a specific token.
8617    NullDefinedAs,
8618}
8619
8620impl fmt::Display for HiveDelimiter {
8621    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8622        use HiveDelimiter::*;
8623        f.write_str(match self {
8624            FieldsTerminatedBy => "FIELDS TERMINATED BY",
8625            FieldsEscapedBy => "ESCAPED BY",
8626            CollectionItemsTerminatedBy => "COLLECTION ITEMS TERMINATED BY",
8627            MapKeysTerminatedBy => "MAP KEYS TERMINATED BY",
8628            LinesTerminatedBy => "LINES TERMINATED BY",
8629            NullDefinedAs => "NULL DEFINED AS",
8630        })
8631    }
8632}
8633
8634#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8635#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8636#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8637/// Describe output format options for Hive `DESCRIBE`/`EXPLAIN`.
8638pub enum HiveDescribeFormat {
8639    /// Extended describe output.
8640    Extended,
8641    /// Formatted describe output.
8642    Formatted,
8643}
8644
8645impl fmt::Display for HiveDescribeFormat {
8646    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8647        use HiveDescribeFormat::*;
8648        f.write_str(match self {
8649            Extended => "EXTENDED",
8650            Formatted => "FORMATTED",
8651        })
8652    }
8653}
8654
8655#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8656#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8657#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8658/// Aliases accepted for describe-style commands.
8659pub enum DescribeAlias {
8660    /// `DESCRIBE` alias.
8661    Describe,
8662    /// `EXPLAIN` alias.
8663    Explain,
8664    /// `DESC` alias.
8665    Desc,
8666}
8667
8668impl fmt::Display for DescribeAlias {
8669    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8670        use DescribeAlias::*;
8671        f.write_str(match self {
8672            Describe => "DESCRIBE",
8673            Explain => "EXPLAIN",
8674            Desc => "DESC",
8675        })
8676    }
8677}
8678
8679#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8680#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8681#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8682#[allow(clippy::large_enum_variant)]
8683/// Hive input/output format specification used in `CREATE TABLE`.
8684pub enum HiveIOFormat {
8685    /// Generic IO format with separate input and output expressions.
8686    IOF {
8687        /// Expression for the input format.
8688        input_format: Expr,
8689        /// Expression for the output format.
8690        output_format: Expr,
8691    },
8692    /// File format wrapper referencing a `FileFormat` variant.
8693    FileFormat {
8694        /// The file format used for storage.
8695        format: FileFormat,
8696    },
8697    /// `USING <format>` syntax used by Spark SQL.
8698    ///
8699    /// Example: `CREATE TABLE t (i INT) USING PARQUET`
8700    ///
8701    /// See <https://spark.apache.org/docs/latest/sql-ref-syntax-ddl-create-table-datasource.html>
8702    Using {
8703        /// The data source or format name, e.g. `parquet`, `delta`, `csv`.
8704        format: Ident,
8705    },
8706}
8707
8708#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Default)]
8709#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8710#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8711/// Hive table format and storage-related options.
8712pub struct HiveFormat {
8713    /// Optional row format specification.
8714    pub row_format: Option<HiveRowFormat>,
8715    /// Optional SerDe properties expressed as SQL options.
8716    pub serde_properties: Option<Vec<SqlOption>>,
8717    /// Optional input/output storage format details.
8718    pub storage: Option<HiveIOFormat>,
8719    /// Optional location (URI or path) for table data.
8720    pub location: Option<String>,
8721}
8722
8723#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8724#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8725#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8726/// A clustered index column specification.
8727pub struct ClusteredIndex {
8728    /// Column identifier for the clustered index entry.
8729    pub name: Ident,
8730    /// Optional sort direction: `Some(true)` for ASC, `Some(false)` for DESC, `None` for unspecified.
8731    pub asc: Option<bool>,
8732}
8733
8734impl fmt::Display for ClusteredIndex {
8735    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8736        write!(f, "{}", self.name)?;
8737        match self.asc {
8738            Some(true) => write!(f, " ASC"),
8739            Some(false) => write!(f, " DESC"),
8740            _ => Ok(()),
8741        }
8742    }
8743}
8744
8745#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8746#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8747#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8748/// Clustered options used for `CREATE TABLE` clustered/indexed storage.
8749pub enum TableOptionsClustered {
8750    /// Use a columnstore index.
8751    ColumnstoreIndex,
8752    /// Columnstore index with an explicit ordering of columns.
8753    ColumnstoreIndexOrder(Vec<Ident>),
8754    /// A named clustered index with one or more columns.
8755    Index(Vec<ClusteredIndex>),
8756}
8757
8758impl fmt::Display for TableOptionsClustered {
8759    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8760        match self {
8761            TableOptionsClustered::ColumnstoreIndex => {
8762                write!(f, "CLUSTERED COLUMNSTORE INDEX")
8763            }
8764            TableOptionsClustered::ColumnstoreIndexOrder(values) => {
8765                write!(
8766                    f,
8767                    "CLUSTERED COLUMNSTORE INDEX ORDER ({})",
8768                    display_comma_separated(values)
8769                )
8770            }
8771            TableOptionsClustered::Index(values) => {
8772                write!(f, "CLUSTERED INDEX ({})", display_comma_separated(values))
8773            }
8774        }
8775    }
8776}
8777
8778/// Specifies which partition the boundary values on table partitioning belongs to.
8779#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash)]
8780#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8781#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8782pub enum PartitionRangeDirection {
8783    /// LEFT range direction.
8784    Left,
8785    /// RIGHT range direction.
8786    Right,
8787}
8788
8789#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8790#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8791#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8792/// SQL option syntax used in table and server definitions.
8793pub enum SqlOption {
8794    /// Clustered represents the clustered version of table storage for MSSQL.
8795    ///
8796    /// <https://learn.microsoft.com/en-us/sql/t-sql/statements/create-table-azure-sql-data-warehouse?view=aps-pdw-2016-au7#TableOptions>
8797    Clustered(TableOptionsClustered),
8798    /// Single identifier options, e.g. `HEAP` for MSSQL.
8799    ///
8800    /// <https://learn.microsoft.com/en-us/sql/t-sql/statements/create-table-azure-sql-data-warehouse?view=aps-pdw-2016-au7#TableOptions>
8801    Ident(Ident),
8802    /// Any option that consists of a key value pair where the value is an expression. e.g.
8803    ///
8804    ///   WITH(DISTRIBUTION = ROUND_ROBIN)
8805    KeyValue {
8806        /// The option key identifier.
8807        key: Ident,
8808        /// The expression value for the option.
8809        value: Expr,
8810    },
8811    /// One or more table partitions and represents which partition the boundary values belong to,
8812    /// e.g.
8813    ///
8814    ///   PARTITION (id RANGE LEFT FOR VALUES (10, 20, 30, 40))
8815    ///
8816    /// <https://learn.microsoft.com/en-us/sql/t-sql/statements/create-table-azure-sql-data-warehouse?view=aps-pdw-2016-au7#TablePartitionOptions>
8817    Partition {
8818        /// The partition column name.
8819        column_name: Ident,
8820        /// Optional direction for the partition range (LEFT/RIGHT).
8821        range_direction: Option<PartitionRangeDirection>,
8822        /// Values that define the partition boundaries.
8823        for_values: Vec<Expr>,
8824    },
8825    /// Comment parameter (supports `=` and no `=` syntax)
8826    Comment(CommentDef),
8827    /// MySQL TableSpace option
8828    /// <https://dev.mysql.com/doc/refman/8.4/en/create-table.html>
8829    TableSpace(TablespaceOption),
8830    /// An option representing a key value pair, where the value is a parenthesized list and with an optional name
8831    /// e.g.
8832    ///
8833    ///   UNION  = (tbl_name\[,tbl_name\]...) <https://dev.mysql.com/doc/refman/8.4/en/create-table.html>
8834    ///   ENGINE = ReplicatedMergeTree('/table_name','{replica}', ver) <https://clickhouse.com/docs/engines/table-engines/mergetree-family/replication>
8835    ///   ENGINE = SummingMergeTree(\[columns\]) <https://clickhouse.com/docs/engines/table-engines/mergetree-family/summingmergetree>
8836    NamedParenthesizedList(NamedParenthesizedList),
8837}
8838
8839impl fmt::Display for SqlOption {
8840    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8841        match self {
8842            SqlOption::Clustered(c) => write!(f, "{c}"),
8843            SqlOption::Ident(ident) => {
8844                write!(f, "{ident}")
8845            }
8846            SqlOption::KeyValue { key: name, value } => {
8847                write!(f, "{name} = {value}")
8848            }
8849            SqlOption::Partition {
8850                column_name,
8851                range_direction,
8852                for_values,
8853            } => {
8854                let direction = match range_direction {
8855                    Some(PartitionRangeDirection::Left) => " LEFT",
8856                    Some(PartitionRangeDirection::Right) => " RIGHT",
8857                    None => "",
8858                };
8859
8860                write!(
8861                    f,
8862                    "PARTITION ({} RANGE{} FOR VALUES ({}))",
8863                    column_name,
8864                    direction,
8865                    display_comma_separated(for_values)
8866                )
8867            }
8868            SqlOption::TableSpace(tablespace_option) => {
8869                write!(f, "TABLESPACE {}", tablespace_option.name)?;
8870                match tablespace_option.storage {
8871                    Some(StorageType::Disk) => write!(f, " STORAGE DISK"),
8872                    Some(StorageType::Memory) => write!(f, " STORAGE MEMORY"),
8873                    None => Ok(()),
8874                }
8875            }
8876            SqlOption::Comment(comment) => match comment {
8877                CommentDef::WithEq(comment) => {
8878                    write!(f, "COMMENT = '{comment}'")
8879                }
8880                CommentDef::WithoutEq(comment) => {
8881                    write!(f, "COMMENT '{comment}'")
8882                }
8883            },
8884            SqlOption::NamedParenthesizedList(value) => {
8885                write!(f, "{} = ", value.key)?;
8886                if let Some(key) = &value.name {
8887                    write!(f, "{key}")?;
8888                }
8889                if !value.values.is_empty() {
8890                    write!(f, "({})", display_comma_separated(&value.values))?
8891                }
8892                Ok(())
8893            }
8894        }
8895    }
8896}
8897
8898#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
8899#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8900#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8901/// Storage type options for a tablespace.
8902pub enum StorageType {
8903    /// Store on disk.
8904    Disk,
8905    /// Store in memory.
8906    Memory,
8907}
8908
8909#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
8910#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8911#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8912/// MySql TableSpace option
8913/// <https://dev.mysql.com/doc/refman/8.4/en/create-table.html>
8914pub struct TablespaceOption {
8915    /// Name of the tablespace.
8916    pub name: String,
8917    /// Optional storage type for the tablespace.
8918    pub storage: Option<StorageType>,
8919}
8920
8921#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8922#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8923#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8924/// A key/value identifier pair used for secret or key-based options.
8925pub struct SecretOption {
8926    /// The option key identifier.
8927    pub key: Ident,
8928    /// The option value identifier.
8929    pub value: Ident,
8930}
8931
8932impl fmt::Display for SecretOption {
8933    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8934        write!(f, "{} {}", self.key, self.value)
8935    }
8936}
8937
8938/// A `CREATE SERVER` statement.
8939///
8940/// [PostgreSQL Documentation](https://www.postgresql.org/docs/current/sql-createserver.html)
8941#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8942#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8943#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8944pub struct CreateServerStatement {
8945    /// The server name.
8946    pub name: ObjectName,
8947    /// Whether `IF NOT EXISTS` was specified.
8948    pub if_not_exists: bool,
8949    /// Optional server type identifier.
8950    pub server_type: Option<Ident>,
8951    /// Optional server version identifier.
8952    pub version: Option<Ident>,
8953    /// Foreign-data wrapper object name.
8954    pub foreign_data_wrapper: ObjectName,
8955    /// Optional list of server options.
8956    pub options: Option<Vec<CreateServerOption>>,
8957}
8958
8959impl fmt::Display for CreateServerStatement {
8960    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8961        let CreateServerStatement {
8962            name,
8963            if_not_exists,
8964            server_type,
8965            version,
8966            foreign_data_wrapper,
8967            options,
8968        } = self;
8969
8970        write!(
8971            f,
8972            "CREATE SERVER {if_not_exists}{name} ",
8973            if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
8974        )?;
8975
8976        if let Some(st) = server_type {
8977            write!(f, "TYPE {st} ")?;
8978        }
8979
8980        if let Some(v) = version {
8981            write!(f, "VERSION {v} ")?;
8982        }
8983
8984        write!(f, "FOREIGN DATA WRAPPER {foreign_data_wrapper}")?;
8985
8986        if let Some(o) = options {
8987            write!(f, " OPTIONS ({o})", o = display_comma_separated(o))?;
8988        }
8989
8990        Ok(())
8991    }
8992}
8993
8994/// A key/value option for `CREATE SERVER`.
8995#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8996#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8997#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8998pub struct CreateServerOption {
8999    /// Option key identifier.
9000    pub key: Ident,
9001    /// Option value identifier.
9002    pub value: Ident,
9003}
9004
9005impl fmt::Display for CreateServerOption {
9006    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9007        write!(f, "{} {}", self.key, self.value)
9008    }
9009}
9010
9011#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9012#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9013#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9014/// Options supported by DuckDB for `ATTACH DATABASE`.
9015pub enum AttachDuckDBDatabaseOption {
9016    /// READ_ONLY option, optional boolean value.
9017    ReadOnly(Option<bool>),
9018    /// TYPE option specifying a database type identifier.
9019    Type(Ident),
9020}
9021
9022impl fmt::Display for AttachDuckDBDatabaseOption {
9023    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9024        match self {
9025            AttachDuckDBDatabaseOption::ReadOnly(Some(true)) => write!(f, "READ_ONLY true"),
9026            AttachDuckDBDatabaseOption::ReadOnly(Some(false)) => write!(f, "READ_ONLY false"),
9027            AttachDuckDBDatabaseOption::ReadOnly(None) => write!(f, "READ_ONLY"),
9028            AttachDuckDBDatabaseOption::Type(t) => write!(f, "TYPE {t}"),
9029        }
9030    }
9031}
9032
9033#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9034#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9035#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9036/// Mode for transactions: access mode or isolation level.
9037pub enum TransactionMode {
9038    /// Access mode for a transaction (e.g. `READ ONLY` / `READ WRITE`).
9039    AccessMode(TransactionAccessMode),
9040    /// Isolation level for a transaction (e.g. `SERIALIZABLE`).
9041    IsolationLevel(TransactionIsolationLevel),
9042}
9043
9044impl fmt::Display for TransactionMode {
9045    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9046        use TransactionMode::*;
9047        match self {
9048            AccessMode(access_mode) => write!(f, "{access_mode}"),
9049            IsolationLevel(iso_level) => write!(f, "ISOLATION LEVEL {iso_level}"),
9050        }
9051    }
9052}
9053
9054#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9055#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9056#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9057/// Transaction access mode (READ ONLY / READ WRITE).
9058pub enum TransactionAccessMode {
9059    /// READ ONLY access mode.
9060    ReadOnly,
9061    /// READ WRITE access mode.
9062    ReadWrite,
9063}
9064
9065impl fmt::Display for TransactionAccessMode {
9066    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9067        use TransactionAccessMode::*;
9068        f.write_str(match self {
9069            ReadOnly => "READ ONLY",
9070            ReadWrite => "READ WRITE",
9071        })
9072    }
9073}
9074
9075#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9076#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9077#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9078/// Transaction isolation levels.
9079pub enum TransactionIsolationLevel {
9080    /// READ UNCOMMITTED isolation level.
9081    ReadUncommitted,
9082    /// READ COMMITTED isolation level.
9083    ReadCommitted,
9084    /// REPEATABLE READ isolation level.
9085    RepeatableRead,
9086    /// SERIALIZABLE isolation level.
9087    Serializable,
9088    /// SNAPSHOT isolation level.
9089    Snapshot,
9090}
9091
9092impl fmt::Display for TransactionIsolationLevel {
9093    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9094        use TransactionIsolationLevel::*;
9095        f.write_str(match self {
9096            ReadUncommitted => "READ UNCOMMITTED",
9097            ReadCommitted => "READ COMMITTED",
9098            RepeatableRead => "REPEATABLE READ",
9099            Serializable => "SERIALIZABLE",
9100            Snapshot => "SNAPSHOT",
9101        })
9102    }
9103}
9104
9105/// Modifier for the transaction in the `BEGIN` syntax
9106///
9107/// SQLite: <https://sqlite.org/lang_transaction.html>
9108/// MS-SQL: <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/try-catch-transact-sql>
9109#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9110#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9111#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9112pub enum TransactionModifier {
9113    /// DEFERRED transaction modifier.
9114    Deferred,
9115    /// IMMEDIATE transaction modifier.
9116    Immediate,
9117    /// EXCLUSIVE transaction modifier.
9118    Exclusive,
9119    /// TRY block modifier (MS-SQL style TRY/CATCH).
9120    Try,
9121    /// CATCH block modifier (MS-SQL style TRY/CATCH).
9122    Catch,
9123}
9124
9125impl fmt::Display for TransactionModifier {
9126    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9127        use TransactionModifier::*;
9128        f.write_str(match self {
9129            Deferred => "DEFERRED",
9130            Immediate => "IMMEDIATE",
9131            Exclusive => "EXCLUSIVE",
9132            Try => "TRY",
9133            Catch => "CATCH",
9134        })
9135    }
9136}
9137
9138#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9139#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9140#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9141/// Filter forms usable in SHOW statements.
9142pub enum ShowStatementFilter {
9143    /// Filter using LIKE pattern.
9144    Like(String),
9145    /// Filter using ILIKE pattern.
9146    ILike(String),
9147    /// Filter using a WHERE expression.
9148    Where(Expr),
9149    /// Filter provided without a keyword (raw string).
9150    NoKeyword(String),
9151}
9152
9153impl fmt::Display for ShowStatementFilter {
9154    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9155        use ShowStatementFilter::*;
9156        match self {
9157            Like(pattern) => write!(f, "LIKE '{}'", value::escape_single_quote_string(pattern)),
9158            ILike(pattern) => write!(f, "ILIKE {}", value::escape_single_quote_string(pattern)),
9159            Where(expr) => write!(f, "WHERE {expr}"),
9160            NoKeyword(pattern) => write!(f, "'{}'", value::escape_single_quote_string(pattern)),
9161        }
9162    }
9163}
9164
9165#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9166#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9167#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9168/// Clause types used with SHOW ... IN/FROM.
9169pub enum ShowStatementInClause {
9170    /// Use the `IN` clause.
9171    IN,
9172    /// Use the `FROM` clause.
9173    FROM,
9174}
9175
9176impl fmt::Display for ShowStatementInClause {
9177    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9178        use ShowStatementInClause::*;
9179        match self {
9180            FROM => write!(f, "FROM"),
9181            IN => write!(f, "IN"),
9182        }
9183    }
9184}
9185
9186/// Sqlite specific syntax
9187///
9188/// See [Sqlite documentation](https://sqlite.org/lang_conflict.html)
9189/// for more details.
9190#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9191#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9192#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9193pub enum SqliteOnConflict {
9194    /// Use ROLLBACK on conflict.
9195    Rollback,
9196    /// Use ABORT on conflict.
9197    Abort,
9198    /// Use FAIL on conflict.
9199    Fail,
9200    /// Use IGNORE on conflict.
9201    Ignore,
9202    /// Use REPLACE on conflict.
9203    Replace,
9204}
9205
9206impl fmt::Display for SqliteOnConflict {
9207    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9208        use SqliteOnConflict::*;
9209        match self {
9210            Rollback => write!(f, "OR ROLLBACK"),
9211            Abort => write!(f, "OR ABORT"),
9212            Fail => write!(f, "OR FAIL"),
9213            Ignore => write!(f, "OR IGNORE"),
9214            Replace => write!(f, "OR REPLACE"),
9215        }
9216    }
9217}
9218
9219/// Mysql specific syntax
9220///
9221/// See [Mysql documentation](https://dev.mysql.com/doc/refman/8.0/en/replace.html)
9222/// See [Mysql documentation](https://dev.mysql.com/doc/refman/8.0/en/insert.html)
9223/// for more details.
9224#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9225#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9226#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9227pub enum MysqlInsertPriority {
9228    /// LOW_PRIORITY modifier for INSERT/REPLACE.
9229    LowPriority,
9230    /// DELAYED modifier for INSERT/REPLACE.
9231    Delayed,
9232    /// HIGH_PRIORITY modifier for INSERT/REPLACE.
9233    HighPriority,
9234}
9235
9236impl fmt::Display for crate::ast::MysqlInsertPriority {
9237    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9238        use MysqlInsertPriority::*;
9239        match self {
9240            LowPriority => write!(f, "LOW_PRIORITY"),
9241            Delayed => write!(f, "DELAYED"),
9242            HighPriority => write!(f, "HIGH_PRIORITY"),
9243        }
9244    }
9245}
9246
9247#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9248#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9249#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9250/// Source for the `COPY` command: a table or a query.
9251pub enum CopySource {
9252    /// Copy from a table with optional column list.
9253    Table {
9254        /// The name of the table to copy from.
9255        table_name: ObjectName,
9256        /// A list of column names to copy. Empty list means that all columns
9257        /// are copied.
9258        columns: Vec<Ident>,
9259    },
9260    /// Copy from the results of a query.
9261    Query(Box<Query>),
9262}
9263
9264#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9265#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9266#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9267/// Target for the `COPY` command: STDIN, STDOUT, a file, or a program.
9268pub enum CopyTarget {
9269    /// Use standard input as the source.
9270    Stdin,
9271    /// Use standard output as the target.
9272    Stdout,
9273    /// Read from or write to a file.
9274    File {
9275        /// The path name of the input or output file.
9276        filename: String,
9277    },
9278    /// Use a program as the source or target (shell command).
9279    Program {
9280        /// A command to execute
9281        command: String,
9282    },
9283}
9284
9285impl fmt::Display for CopyTarget {
9286    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9287        use CopyTarget::*;
9288        match self {
9289            Stdin => write!(f, "STDIN"),
9290            Stdout => write!(f, "STDOUT"),
9291            File { filename } => write!(f, "'{}'", value::escape_single_quote_string(filename)),
9292            Program { command } => write!(
9293                f,
9294                "PROGRAM '{}'",
9295                value::escape_single_quote_string(command)
9296            ),
9297        }
9298    }
9299}
9300
9301#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9302#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9303#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9304/// Action to take `ON COMMIT` for temporary tables.
9305pub enum OnCommit {
9306    /// Delete rows on commit.
9307    DeleteRows,
9308    /// Preserve rows on commit.
9309    PreserveRows,
9310    /// Drop the table on commit.
9311    Drop,
9312}
9313
9314/// An option in `COPY` statement.
9315///
9316/// <https://www.postgresql.org/docs/14/sql-copy.html>
9317#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9318#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9319#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9320pub enum CopyOption {
9321    /// FORMAT format_name
9322    Format(Ident),
9323    /// FREEZE \[ boolean \]
9324    Freeze(bool),
9325    /// DELIMITER 'delimiter_character'
9326    Delimiter(char),
9327    /// NULL 'null_string'
9328    Null(String),
9329    /// HEADER \[ boolean \]
9330    Header(bool),
9331    /// QUOTE 'quote_character'
9332    Quote(char),
9333    /// ESCAPE 'escape_character'
9334    Escape(char),
9335    /// FORCE_QUOTE { ( column_name [, ...] ) | * }
9336    ForceQuote(Vec<Ident>),
9337    /// FORCE_NOT_NULL ( column_name [, ...] )
9338    ForceNotNull(Vec<Ident>),
9339    /// FORCE_NULL ( column_name [, ...] )
9340    ForceNull(Vec<Ident>),
9341    /// ENCODING 'encoding_name'
9342    Encoding(String),
9343}
9344
9345impl fmt::Display for CopyOption {
9346    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9347        use CopyOption::*;
9348        match self {
9349            Format(name) => write!(f, "FORMAT {name}"),
9350            Freeze(true) => write!(f, "FREEZE"),
9351            Freeze(false) => write!(f, "FREEZE FALSE"),
9352            Delimiter(char) => write!(f, "DELIMITER '{char}'"),
9353            Null(string) => write!(f, "NULL '{}'", value::escape_single_quote_string(string)),
9354            Header(true) => write!(f, "HEADER"),
9355            Header(false) => write!(f, "HEADER FALSE"),
9356            Quote(char) => write!(f, "QUOTE '{char}'"),
9357            Escape(char) => write!(f, "ESCAPE '{char}'"),
9358            ForceQuote(columns) => write!(f, "FORCE_QUOTE ({})", display_comma_separated(columns)),
9359            ForceNotNull(columns) => {
9360                write!(f, "FORCE_NOT_NULL ({})", display_comma_separated(columns))
9361            }
9362            ForceNull(columns) => write!(f, "FORCE_NULL ({})", display_comma_separated(columns)),
9363            Encoding(name) => write!(f, "ENCODING '{}'", value::escape_single_quote_string(name)),
9364        }
9365    }
9366}
9367
9368/// An option in `COPY` statement before PostgreSQL version 9.0.
9369///
9370/// [PostgreSQL](https://www.postgresql.org/docs/8.4/sql-copy.html)
9371/// [Redshift](https://docs.aws.amazon.com/redshift/latest/dg/r_COPY-alphabetical-parm-list.html)
9372#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9373#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9374#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9375pub enum CopyLegacyOption {
9376    /// ACCEPTANYDATE
9377    AcceptAnyDate,
9378    /// ACCEPTINVCHARS
9379    AcceptInvChars(Option<String>),
9380    /// ADDQUOTES
9381    AddQuotes,
9382    /// ALLOWOVERWRITE
9383    AllowOverwrite,
9384    /// BINARY
9385    Binary,
9386    /// BLANKSASNULL
9387    BlankAsNull,
9388    /// BZIP2
9389    Bzip2,
9390    /// CLEANPATH
9391    CleanPath,
9392    /// COMPUPDATE [ PRESET | { ON | TRUE } | { OFF | FALSE } ]
9393    CompUpdate {
9394        /// Whether the COMPUPDATE PRESET option was used.
9395        preset: bool,
9396        /// Optional enabled flag for COMPUPDATE.
9397        enabled: Option<bool>,
9398    },
9399    /// CSV ...
9400    Csv(Vec<CopyLegacyCsvOption>),
9401    /// DATEFORMAT \[ AS \] {'dateformat_string' | 'auto' }
9402    DateFormat(Option<String>),
9403    /// DELIMITER \[ AS \] 'delimiter_character'
9404    Delimiter(char),
9405    /// EMPTYASNULL
9406    EmptyAsNull,
9407    /// `ENCRYPTED \[ AUTO \]`
9408    Encrypted {
9409        /// Whether `AUTO` was specified for encryption.
9410        auto: bool,
9411    },
9412    /// ESCAPE
9413    Escape,
9414    /// EXTENSION 'extension-name'
9415    Extension(String),
9416    /// FIXEDWIDTH \[ AS \] 'fixedwidth-spec'
9417    FixedWidth(String),
9418    /// GZIP
9419    Gzip,
9420    /// HEADER
9421    Header,
9422    /// IAM_ROLE { DEFAULT | 'arn:aws:iam::123456789:role/role1' }
9423    IamRole(IamRoleKind),
9424    /// IGNOREHEADER \[ AS \] number_rows
9425    IgnoreHeader(u64),
9426    /// JSON \[ AS \] 'json_option'
9427    Json(Option<String>),
9428    /// MANIFEST \[ VERBOSE \]
9429    Manifest {
9430        /// Whether the MANIFEST is verbose.
9431        verbose: bool,
9432    },
9433    /// MAXFILESIZE \[ AS \] max-size \[ MB | GB \]
9434    MaxFileSize(FileSize),
9435    /// `NULL \[ AS \] 'null_string'`
9436    Null(String),
9437    /// `PARALLEL [ { ON | TRUE } | { OFF | FALSE } ]`
9438    Parallel(Option<bool>),
9439    /// PARQUET
9440    Parquet,
9441    /// PARTITION BY ( column_name [, ... ] ) \[ INCLUDE \]
9442    PartitionBy(UnloadPartitionBy),
9443    /// REGION \[ AS \] 'aws-region' }
9444    Region(String),
9445    /// REMOVEQUOTES
9446    RemoveQuotes,
9447    /// ROWGROUPSIZE \[ AS \] size \[ MB | GB \]
9448    RowGroupSize(FileSize),
9449    /// STATUPDATE [ { ON | TRUE } | { OFF | FALSE } ]
9450    StatUpdate(Option<bool>),
9451    /// TIMEFORMAT \[ AS \] {'timeformat_string' | 'auto' | 'epochsecs' | 'epochmillisecs' }
9452    TimeFormat(Option<String>),
9453    /// TRUNCATECOLUMNS
9454    TruncateColumns,
9455    /// ZSTD
9456    Zstd,
9457    /// Redshift `CREDENTIALS 'auth-args'`
9458    /// <https://docs.aws.amazon.com/redshift/latest/dg/copy-parameters-authorization.html>
9459    Credentials(String),
9460}
9461
9462impl fmt::Display for CopyLegacyOption {
9463    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9464        use CopyLegacyOption::*;
9465        match self {
9466            AcceptAnyDate => write!(f, "ACCEPTANYDATE"),
9467            AcceptInvChars(ch) => {
9468                write!(f, "ACCEPTINVCHARS")?;
9469                if let Some(ch) = ch {
9470                    write!(f, " '{}'", value::escape_single_quote_string(ch))?;
9471                }
9472                Ok(())
9473            }
9474            AddQuotes => write!(f, "ADDQUOTES"),
9475            AllowOverwrite => write!(f, "ALLOWOVERWRITE"),
9476            Binary => write!(f, "BINARY"),
9477            BlankAsNull => write!(f, "BLANKSASNULL"),
9478            Bzip2 => write!(f, "BZIP2"),
9479            CleanPath => write!(f, "CLEANPATH"),
9480            CompUpdate { preset, enabled } => {
9481                write!(f, "COMPUPDATE")?;
9482                if *preset {
9483                    write!(f, " PRESET")?;
9484                } else if let Some(enabled) = enabled {
9485                    write!(
9486                        f,
9487                        "{}",
9488                        match enabled {
9489                            true => " TRUE",
9490                            false => " FALSE",
9491                        }
9492                    )?;
9493                }
9494                Ok(())
9495            }
9496            Csv(opts) => {
9497                write!(f, "CSV")?;
9498                if !opts.is_empty() {
9499                    write!(f, " {}", display_separated(opts, " "))?;
9500                }
9501                Ok(())
9502            }
9503            DateFormat(fmt) => {
9504                write!(f, "DATEFORMAT")?;
9505                if let Some(fmt) = fmt {
9506                    write!(f, " '{}'", value::escape_single_quote_string(fmt))?;
9507                }
9508                Ok(())
9509            }
9510            Delimiter(char) => write!(f, "DELIMITER '{char}'"),
9511            EmptyAsNull => write!(f, "EMPTYASNULL"),
9512            Encrypted { auto } => write!(f, "ENCRYPTED{}", if *auto { " AUTO" } else { "" }),
9513            Escape => write!(f, "ESCAPE"),
9514            Extension(ext) => write!(f, "EXTENSION '{}'", value::escape_single_quote_string(ext)),
9515            FixedWidth(spec) => write!(
9516                f,
9517                "FIXEDWIDTH '{}'",
9518                value::escape_single_quote_string(spec)
9519            ),
9520            Gzip => write!(f, "GZIP"),
9521            Header => write!(f, "HEADER"),
9522            IamRole(role) => write!(f, "IAM_ROLE {role}"),
9523            IgnoreHeader(num_rows) => write!(f, "IGNOREHEADER {num_rows}"),
9524            Json(opt) => {
9525                write!(f, "JSON")?;
9526                if let Some(opt) = opt {
9527                    write!(f, " AS '{}'", value::escape_single_quote_string(opt))?;
9528                }
9529                Ok(())
9530            }
9531            Manifest { verbose } => write!(f, "MANIFEST{}", if *verbose { " VERBOSE" } else { "" }),
9532            MaxFileSize(file_size) => write!(f, "MAXFILESIZE {file_size}"),
9533            Null(string) => write!(f, "NULL '{}'", value::escape_single_quote_string(string)),
9534            Parallel(enabled) => {
9535                write!(
9536                    f,
9537                    "PARALLEL{}",
9538                    match enabled {
9539                        Some(true) => " TRUE",
9540                        Some(false) => " FALSE",
9541                        _ => "",
9542                    }
9543                )
9544            }
9545            Parquet => write!(f, "PARQUET"),
9546            PartitionBy(p) => write!(f, "{p}"),
9547            Region(region) => write!(f, "REGION '{}'", value::escape_single_quote_string(region)),
9548            RemoveQuotes => write!(f, "REMOVEQUOTES"),
9549            RowGroupSize(file_size) => write!(f, "ROWGROUPSIZE {file_size}"),
9550            StatUpdate(enabled) => {
9551                write!(
9552                    f,
9553                    "STATUPDATE{}",
9554                    match enabled {
9555                        Some(true) => " TRUE",
9556                        Some(false) => " FALSE",
9557                        _ => "",
9558                    }
9559                )
9560            }
9561            TimeFormat(fmt) => {
9562                write!(f, "TIMEFORMAT")?;
9563                if let Some(fmt) = fmt {
9564                    write!(f, " '{}'", value::escape_single_quote_string(fmt))?;
9565                }
9566                Ok(())
9567            }
9568            TruncateColumns => write!(f, "TRUNCATECOLUMNS"),
9569            Zstd => write!(f, "ZSTD"),
9570            Credentials(s) => write!(f, "CREDENTIALS '{}'", value::escape_single_quote_string(s)),
9571        }
9572    }
9573}
9574
9575/// ```sql
9576/// SIZE \[ MB | GB \]
9577/// ```
9578#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9579#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9580#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9581pub struct FileSize {
9582    /// Numeric size value.
9583    pub size: ValueWithSpan,
9584    /// Optional unit for the size (MB or GB).
9585    pub unit: Option<FileSizeUnit>,
9586}
9587
9588impl fmt::Display for FileSize {
9589    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9590        write!(f, "{}", self.size)?;
9591        if let Some(unit) = &self.unit {
9592            write!(f, " {unit}")?;
9593        }
9594        Ok(())
9595    }
9596}
9597
9598/// Units for `FileSize` (MB or GB).
9599#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9600#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9601#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9602pub enum FileSizeUnit {
9603    /// Megabytes.
9604    MB,
9605    /// Gigabytes.
9606    GB,
9607}
9608
9609impl fmt::Display for FileSizeUnit {
9610    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9611        match self {
9612            FileSizeUnit::MB => write!(f, "MB"),
9613            FileSizeUnit::GB => write!(f, "GB"),
9614        }
9615    }
9616}
9617
9618/// Specifies the partition keys for the unload operation
9619///
9620/// ```sql
9621/// PARTITION BY ( column_name [, ... ] ) [ INCLUDE ]
9622/// ```
9623#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9624#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9625#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9626pub struct UnloadPartitionBy {
9627    /// Columns used to partition the unload output.
9628    pub columns: Vec<Ident>,
9629    /// Whether to include the partition in the output.
9630    pub include: bool,
9631}
9632
9633impl fmt::Display for UnloadPartitionBy {
9634    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9635        write!(
9636            f,
9637            "PARTITION BY ({}){}",
9638            display_comma_separated(&self.columns),
9639            if self.include { " INCLUDE" } else { "" }
9640        )
9641    }
9642}
9643
9644/// An `IAM_ROLE` option in the AWS ecosystem
9645///
9646/// [Redshift COPY](https://docs.aws.amazon.com/redshift/latest/dg/copy-parameters-authorization.html#copy-iam-role)
9647#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9648#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9649#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9650pub enum IamRoleKind {
9651    /// Default role
9652    Default,
9653    /// Specific role ARN, for example: `arn:aws:iam::123456789:role/role1`
9654    Arn(String),
9655}
9656
9657impl fmt::Display for IamRoleKind {
9658    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9659        match self {
9660            IamRoleKind::Default => write!(f, "DEFAULT"),
9661            IamRoleKind::Arn(arn) => write!(f, "'{arn}'"),
9662        }
9663    }
9664}
9665
9666/// A `CSV` option in `COPY` statement before PostgreSQL version 9.0.
9667///
9668/// <https://www.postgresql.org/docs/8.4/sql-copy.html>
9669#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9670#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9671#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9672pub enum CopyLegacyCsvOption {
9673    /// HEADER
9674    Header,
9675    /// QUOTE \[ AS \] 'quote_character'
9676    Quote(char),
9677    /// ESCAPE \[ AS \] 'escape_character'
9678    Escape(char),
9679    /// FORCE QUOTE { column_name [, ...] | * }
9680    ForceQuote(Vec<Ident>),
9681    /// FORCE NOT NULL column_name [, ...]
9682    ForceNotNull(Vec<Ident>),
9683}
9684
9685impl fmt::Display for CopyLegacyCsvOption {
9686    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9687        use CopyLegacyCsvOption::*;
9688        match self {
9689            Header => write!(f, "HEADER"),
9690            Quote(char) => write!(f, "QUOTE '{char}'"),
9691            Escape(char) => write!(f, "ESCAPE '{char}'"),
9692            ForceQuote(columns) => write!(f, "FORCE QUOTE {}", display_comma_separated(columns)),
9693            ForceNotNull(columns) => {
9694                write!(f, "FORCE NOT NULL {}", display_comma_separated(columns))
9695            }
9696        }
9697    }
9698}
9699
9700/// Objects that can be discarded with `DISCARD`.
9701#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9702#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9703#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9704pub enum DiscardObject {
9705    /// Discard all session state.
9706    ALL,
9707    /// Discard cached plans.
9708    PLANS,
9709    /// Discard sequence values.
9710    SEQUENCES,
9711    /// Discard temporary objects.
9712    TEMP,
9713}
9714
9715impl fmt::Display for DiscardObject {
9716    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9717        match self {
9718            DiscardObject::ALL => f.write_str("ALL"),
9719            DiscardObject::PLANS => f.write_str("PLANS"),
9720            DiscardObject::SEQUENCES => f.write_str("SEQUENCES"),
9721            DiscardObject::TEMP => f.write_str("TEMP"),
9722        }
9723    }
9724}
9725
9726/// Types of flush operations supported by `FLUSH`.
9727#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9728#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9729#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9730pub enum FlushType {
9731    /// Flush binary logs.
9732    BinaryLogs,
9733    /// Flush engine logs.
9734    EngineLogs,
9735    /// Flush error logs.
9736    ErrorLogs,
9737    /// Flush general logs.
9738    GeneralLogs,
9739    /// Flush hosts information.
9740    Hosts,
9741    /// Flush logs.
9742    Logs,
9743    /// Flush privileges.
9744    Privileges,
9745    /// Flush optimizer costs.
9746    OptimizerCosts,
9747    /// Flush relay logs.
9748    RelayLogs,
9749    /// Flush slow logs.
9750    SlowLogs,
9751    /// Flush status.
9752    Status,
9753    /// Flush user resources.
9754    UserResources,
9755    /// Flush table data.
9756    Tables,
9757}
9758
9759impl fmt::Display for FlushType {
9760    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9761        match self {
9762            FlushType::BinaryLogs => f.write_str("BINARY LOGS"),
9763            FlushType::EngineLogs => f.write_str("ENGINE LOGS"),
9764            FlushType::ErrorLogs => f.write_str("ERROR LOGS"),
9765            FlushType::GeneralLogs => f.write_str("GENERAL LOGS"),
9766            FlushType::Hosts => f.write_str("HOSTS"),
9767            FlushType::Logs => f.write_str("LOGS"),
9768            FlushType::Privileges => f.write_str("PRIVILEGES"),
9769            FlushType::OptimizerCosts => f.write_str("OPTIMIZER_COSTS"),
9770            FlushType::RelayLogs => f.write_str("RELAY LOGS"),
9771            FlushType::SlowLogs => f.write_str("SLOW LOGS"),
9772            FlushType::Status => f.write_str("STATUS"),
9773            FlushType::UserResources => f.write_str("USER_RESOURCES"),
9774            FlushType::Tables => f.write_str("TABLES"),
9775        }
9776    }
9777}
9778
9779/// Location modifier for flush commands.
9780#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9781#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9782#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9783pub enum FlushLocation {
9784    /// Do not write changes to the binary log.
9785    NoWriteToBinlog,
9786    /// Apply flush locally.
9787    Local,
9788}
9789
9790impl fmt::Display for FlushLocation {
9791    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9792        match self {
9793            FlushLocation::NoWriteToBinlog => f.write_str("NO_WRITE_TO_BINLOG"),
9794            FlushLocation::Local => f.write_str("LOCAL"),
9795        }
9796    }
9797}
9798
9799/// Optional context modifier for statements that can be or `LOCAL`, `GLOBAL`, or `SESSION`.
9800#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9801#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9802#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9803pub enum ContextModifier {
9804    /// `LOCAL` identifier, usually related to transactional states.
9805    Local,
9806    /// `SESSION` identifier
9807    Session,
9808    /// `GLOBAL` identifier
9809    Global,
9810}
9811
9812impl fmt::Display for ContextModifier {
9813    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9814        match self {
9815            Self::Local => {
9816                write!(f, "LOCAL ")
9817            }
9818            Self::Session => {
9819                write!(f, "SESSION ")
9820            }
9821            Self::Global => {
9822                write!(f, "GLOBAL ")
9823            }
9824        }
9825    }
9826}
9827
9828/// Function describe in DROP FUNCTION.
9829#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9830#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9831pub enum DropFunctionOption {
9832    /// `RESTRICT` option for DROP FUNCTION.
9833    Restrict,
9834    /// `CASCADE` option for DROP FUNCTION.
9835    Cascade,
9836}
9837
9838impl fmt::Display for DropFunctionOption {
9839    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9840        match self {
9841            DropFunctionOption::Restrict => write!(f, "RESTRICT "),
9842            DropFunctionOption::Cascade => write!(f, "CASCADE  "),
9843        }
9844    }
9845}
9846
9847/// Generic function description for DROP FUNCTION and CREATE TRIGGER.
9848#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9849#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9850#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9851pub struct FunctionDesc {
9852    /// The function name.
9853    pub name: ObjectName,
9854    /// Optional list of function arguments.
9855    pub args: Option<Vec<OperateFunctionArg>>,
9856}
9857
9858impl fmt::Display for FunctionDesc {
9859    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9860        write!(f, "{}", self.name)?;
9861        if let Some(args) = &self.args {
9862            write!(f, "({})", display_comma_separated(args))?;
9863        }
9864        Ok(())
9865    }
9866}
9867
9868/// Function argument in CREATE OR DROP FUNCTION.
9869#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9870#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9871#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9872pub struct OperateFunctionArg {
9873    /// Optional argument mode (`IN`, `OUT`, `INOUT`).
9874    pub mode: Option<ArgMode>,
9875    /// Optional argument identifier/name.
9876    pub name: Option<Ident>,
9877    /// The data type of the argument.
9878    pub data_type: DataType,
9879    /// Optional default expression for the argument.
9880    pub default_expr: Option<Expr>,
9881}
9882
9883impl OperateFunctionArg {
9884    /// Returns an unnamed argument.
9885    pub fn unnamed(data_type: DataType) -> Self {
9886        Self {
9887            mode: None,
9888            name: None,
9889            data_type,
9890            default_expr: None,
9891        }
9892    }
9893
9894    /// Returns an argument with name.
9895    pub fn with_name(name: &str, data_type: DataType) -> Self {
9896        Self {
9897            mode: None,
9898            name: Some(name.into()),
9899            data_type,
9900            default_expr: None,
9901        }
9902    }
9903}
9904
9905impl fmt::Display for OperateFunctionArg {
9906    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9907        if let Some(mode) = &self.mode {
9908            write!(f, "{mode} ")?;
9909        }
9910        if let Some(name) = &self.name {
9911            write!(f, "{name} ")?;
9912        }
9913        write!(f, "{}", self.data_type)?;
9914        if let Some(default_expr) = &self.default_expr {
9915            write!(f, " = {default_expr}")?;
9916        }
9917        Ok(())
9918    }
9919}
9920
9921/// The mode of an argument in CREATE FUNCTION.
9922#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9923#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9924#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9925pub enum ArgMode {
9926    /// `IN` mode.
9927    In,
9928    /// `OUT` mode.
9929    Out,
9930    /// `INOUT` mode.
9931    InOut,
9932    /// `VARIADIC` mode.
9933    Variadic,
9934}
9935
9936impl fmt::Display for ArgMode {
9937    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9938        match self {
9939            ArgMode::In => write!(f, "IN"),
9940            ArgMode::Out => write!(f, "OUT"),
9941            ArgMode::InOut => write!(f, "INOUT"),
9942            ArgMode::Variadic => write!(f, "VARIADIC"),
9943        }
9944    }
9945}
9946
9947/// These attributes inform the query optimizer about the behavior of the function.
9948#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9949#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9950#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9951pub enum FunctionBehavior {
9952    /// Function is immutable.
9953    Immutable,
9954    /// Function is stable.
9955    Stable,
9956    /// Function is volatile.
9957    Volatile,
9958}
9959
9960impl fmt::Display for FunctionBehavior {
9961    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9962        match self {
9963            FunctionBehavior::Immutable => write!(f, "IMMUTABLE"),
9964            FunctionBehavior::Stable => write!(f, "STABLE"),
9965            FunctionBehavior::Volatile => write!(f, "VOLATILE"),
9966        }
9967    }
9968}
9969
9970/// Security attribute for functions: SECURITY DEFINER or SECURITY INVOKER.
9971///
9972/// [PostgreSQL](https://www.postgresql.org/docs/current/sql-createfunction.html)
9973#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9974#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9975#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9976pub enum FunctionSecurity {
9977    /// Execute the function with the privileges of the user who defined it.
9978    Definer,
9979    /// Execute the function with the privileges of the user who invokes it.
9980    Invoker,
9981}
9982
9983impl fmt::Display for FunctionSecurity {
9984    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9985        match self {
9986            FunctionSecurity::Definer => write!(f, "SECURITY DEFINER"),
9987            FunctionSecurity::Invoker => write!(f, "SECURITY INVOKER"),
9988        }
9989    }
9990}
9991
9992/// Value for a SET configuration parameter in a CREATE FUNCTION statement.
9993///
9994/// [PostgreSQL](https://www.postgresql.org/docs/current/sql-createfunction.html)
9995#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9996#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9997#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9998pub enum FunctionSetValue {
9999    /// SET param = DEFAULT / SET param TO DEFAULT
10000    Default,
10001    /// SET param = value1, value2, ...
10002    Values(Vec<Expr>),
10003    /// SET param FROM CURRENT
10004    FromCurrent,
10005}
10006
10007/// A SET configuration_parameter clause in a CREATE FUNCTION statement.
10008///
10009/// [PostgreSQL](https://www.postgresql.org/docs/current/sql-createfunction.html)
10010#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10011#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10012#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10013pub struct FunctionDefinitionSetParam {
10014    /// The name of the configuration parameter.
10015    pub name: ObjectName,
10016    /// The value to set for the parameter.
10017    pub value: FunctionSetValue,
10018}
10019
10020impl fmt::Display for FunctionDefinitionSetParam {
10021    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10022        write!(f, "SET {} ", self.name)?;
10023        match &self.value {
10024            FunctionSetValue::Default => write!(f, "= DEFAULT"),
10025            FunctionSetValue::Values(values) => {
10026                write!(f, "= {}", display_comma_separated(values))
10027            }
10028            FunctionSetValue::FromCurrent => write!(f, "FROM CURRENT"),
10029        }
10030    }
10031}
10032
10033/// These attributes describe the behavior of the function when called with a null argument.
10034#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10035#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10036#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10037pub enum FunctionCalledOnNull {
10038    /// Function is called even when inputs are null.
10039    CalledOnNullInput,
10040    /// Function returns null when any input is null.
10041    ReturnsNullOnNullInput,
10042    /// Function is strict about null inputs.
10043    Strict,
10044}
10045
10046impl fmt::Display for FunctionCalledOnNull {
10047    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10048        match self {
10049            FunctionCalledOnNull::CalledOnNullInput => write!(f, "CALLED ON NULL INPUT"),
10050            FunctionCalledOnNull::ReturnsNullOnNullInput => write!(f, "RETURNS NULL ON NULL INPUT"),
10051            FunctionCalledOnNull::Strict => write!(f, "STRICT"),
10052        }
10053    }
10054}
10055
10056/// If it is safe for PostgreSQL to call the function from multiple threads at once
10057#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10058#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10059#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10060pub enum FunctionParallel {
10061    /// The function is not safe to run in parallel.
10062    Unsafe,
10063    /// The function is restricted for parallel execution.
10064    Restricted,
10065    /// The function is safe to run in parallel.
10066    Safe,
10067}
10068
10069impl fmt::Display for FunctionParallel {
10070    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10071        match self {
10072            FunctionParallel::Unsafe => write!(f, "PARALLEL UNSAFE"),
10073            FunctionParallel::Restricted => write!(f, "PARALLEL RESTRICTED"),
10074            FunctionParallel::Safe => write!(f, "PARALLEL SAFE"),
10075        }
10076    }
10077}
10078
10079/// [BigQuery] Determinism specifier used in a UDF definition.
10080///
10081/// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#syntax_11
10082#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10083#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10084#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10085pub enum FunctionDeterminismSpecifier {
10086    /// Function is deterministic.
10087    Deterministic,
10088    /// Function is not deterministic.
10089    NotDeterministic,
10090}
10091
10092impl fmt::Display for FunctionDeterminismSpecifier {
10093    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10094        match self {
10095            FunctionDeterminismSpecifier::Deterministic => {
10096                write!(f, "DETERMINISTIC")
10097            }
10098            FunctionDeterminismSpecifier::NotDeterministic => {
10099                write!(f, "NOT DETERMINISTIC")
10100            }
10101        }
10102    }
10103}
10104
10105/// Represent the expression body of a `CREATE FUNCTION` statement as well as
10106/// where within the statement, the body shows up.
10107///
10108/// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#syntax_11
10109/// [PostgreSQL]: https://www.postgresql.org/docs/15/sql-createfunction.html
10110/// [MsSql]: https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql
10111#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10112#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10113#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10114pub enum CreateFunctionBody {
10115    /// A function body expression using the 'AS' keyword and shows up
10116    /// before any `OPTIONS` clause.
10117    ///
10118    /// Example:
10119    /// ```sql
10120    /// CREATE FUNCTION myfunc(x FLOAT64, y FLOAT64) RETURNS FLOAT64
10121    /// AS (x * y)
10122    /// OPTIONS(description="desc");
10123    /// ```
10124    ///
10125    /// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#syntax_11
10126    /// [PostgreSQL]: https://www.postgresql.org/docs/current/sql-createfunction.html
10127    AsBeforeOptions {
10128        /// The primary expression.
10129        body: Expr,
10130        /// Link symbol if the primary expression contains the name of shared library file.
10131        ///
10132        /// Example:
10133        /// ```sql
10134        /// CREATE FUNCTION cas_in(input cstring) RETURNS cas
10135        /// AS 'MODULE_PATHNAME', 'cas_in_wrapper'
10136        /// ```
10137        /// [PostgreSQL]: https://www.postgresql.org/docs/current/sql-createfunction.html
10138        link_symbol: Option<Expr>,
10139    },
10140    /// A function body expression using the 'AS' keyword and shows up
10141    /// after any `OPTIONS` clause.
10142    ///
10143    /// Example:
10144    /// ```sql
10145    /// CREATE FUNCTION myfunc(x FLOAT64, y FLOAT64) RETURNS FLOAT64
10146    /// OPTIONS(description="desc")
10147    /// AS (x * y);
10148    /// ```
10149    ///
10150    /// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#syntax_11
10151    AsAfterOptions(Expr),
10152    /// Function body with statements before the `RETURN` keyword.
10153    ///
10154    /// Example:
10155    /// ```sql
10156    /// CREATE FUNCTION my_scalar_udf(a INT, b INT)
10157    /// RETURNS INT
10158    /// AS
10159    /// BEGIN
10160    ///     DECLARE c INT;
10161    ///     SET c = a + b;
10162    ///     RETURN c;
10163    /// END
10164    /// ```
10165    ///
10166    /// [MsSql]: https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql
10167    AsBeginEnd(BeginEndStatements),
10168    /// Function body expression using the 'RETURN' keyword.
10169    ///
10170    /// Example:
10171    /// ```sql
10172    /// CREATE FUNCTION myfunc(a INTEGER, IN b INTEGER = 1) RETURNS INTEGER
10173    /// LANGUAGE SQL
10174    /// RETURN a + b;
10175    /// ```
10176    ///
10177    /// [PostgreSQL]: https://www.postgresql.org/docs/current/sql-createfunction.html
10178    Return(Expr),
10179
10180    /// Function body expression using the 'AS RETURN' keywords
10181    ///
10182    /// Example:
10183    /// ```sql
10184    /// CREATE FUNCTION myfunc(a INT, b INT)
10185    /// RETURNS TABLE
10186    /// AS RETURN (SELECT a + b AS sum);
10187    /// ```
10188    ///
10189    /// [MsSql]: https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql
10190    AsReturnExpr(Expr),
10191
10192    /// Function body expression using the 'AS RETURN' keywords, with an un-parenthesized SELECT query
10193    ///
10194    /// Example:
10195    /// ```sql
10196    /// CREATE FUNCTION myfunc(a INT, b INT)
10197    /// RETURNS TABLE
10198    /// AS RETURN SELECT a + b AS sum;
10199    /// ```
10200    ///
10201    /// [MsSql]: https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql?view=sql-server-ver16#select_stmt
10202    AsReturnSelect(Select),
10203}
10204
10205#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10206#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10207#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10208/// `USING` clause options for `CREATE FUNCTION` (e.g., JAR, FILE, ARCHIVE).
10209pub enum CreateFunctionUsing {
10210    /// Use a JAR file located at the given URI.
10211    Jar(String),
10212    /// Use a file located at the given URI.
10213    File(String),
10214    /// Use an archive located at the given URI.
10215    Archive(String),
10216}
10217
10218impl fmt::Display for CreateFunctionUsing {
10219    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10220        write!(f, "USING ")?;
10221        match self {
10222            CreateFunctionUsing::Jar(uri) => write!(f, "JAR '{uri}'"),
10223            CreateFunctionUsing::File(uri) => write!(f, "FILE '{uri}'"),
10224            CreateFunctionUsing::Archive(uri) => write!(f, "ARCHIVE '{uri}'"),
10225        }
10226    }
10227}
10228
10229/// `NAME = <EXPR>` arguments for DuckDB macros
10230///
10231/// See [Create Macro - DuckDB](https://duckdb.org/docs/sql/statements/create_macro)
10232/// for more details
10233#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10234#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10235#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10236pub struct MacroArg {
10237    /// The argument name.
10238    pub name: Ident,
10239    /// Optional default expression for the argument.
10240    pub default_expr: Option<Expr>,
10241}
10242
10243impl MacroArg {
10244    /// Returns an argument with name.
10245    pub fn new(name: &str) -> Self {
10246        Self {
10247            name: name.into(),
10248            default_expr: None,
10249        }
10250    }
10251}
10252
10253impl fmt::Display for MacroArg {
10254    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10255        write!(f, "{}", self.name)?;
10256        if let Some(default_expr) = &self.default_expr {
10257            write!(f, " := {default_expr}")?;
10258        }
10259        Ok(())
10260    }
10261}
10262
10263#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10264#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10265#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10266/// Definition for a DuckDB macro: either an expression or a table-producing query.
10267pub enum MacroDefinition {
10268    /// The macro is defined as an expression.
10269    Expr(Expr),
10270    /// The macro is defined as a table (query).
10271    Table(Box<Query>),
10272}
10273
10274impl fmt::Display for MacroDefinition {
10275    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10276        match self {
10277            MacroDefinition::Expr(expr) => write!(f, "{expr}")?,
10278            MacroDefinition::Table(query) => write!(f, "{query}")?,
10279        }
10280        Ok(())
10281    }
10282}
10283
10284/// Schema possible naming variants ([1]).
10285///
10286/// [1]: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#schema-definition
10287#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10288#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10289#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10290pub enum SchemaName {
10291    /// Only schema name specified: `<schema name>`.
10292    Simple(ObjectName),
10293    /// Only authorization identifier specified: `AUTHORIZATION <schema authorization identifier>`.
10294    UnnamedAuthorization(Ident),
10295    /// Both schema name and authorization identifier specified: `<schema name>  AUTHORIZATION <schema authorization identifier>`.
10296    NamedAuthorization(ObjectName, Ident),
10297}
10298
10299impl fmt::Display for SchemaName {
10300    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10301        match self {
10302            SchemaName::Simple(name) => {
10303                write!(f, "{name}")
10304            }
10305            SchemaName::UnnamedAuthorization(authorization) => {
10306                write!(f, "AUTHORIZATION {authorization}")
10307            }
10308            SchemaName::NamedAuthorization(name, authorization) => {
10309                write!(f, "{name} AUTHORIZATION {authorization}")
10310            }
10311        }
10312    }
10313}
10314
10315/// Fulltext search modifiers ([1]).
10316///
10317/// [1]: https://dev.mysql.com/doc/refman/8.0/en/fulltext-search.html#function_match
10318#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10319#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10320#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10321pub enum SearchModifier {
10322    /// `IN NATURAL LANGUAGE MODE`.
10323    InNaturalLanguageMode,
10324    /// `IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION`.
10325    InNaturalLanguageModeWithQueryExpansion,
10326    ///`IN BOOLEAN MODE`.
10327    InBooleanMode,
10328    ///`WITH QUERY EXPANSION`.
10329    WithQueryExpansion,
10330}
10331
10332impl fmt::Display for SearchModifier {
10333    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10334        match self {
10335            Self::InNaturalLanguageMode => {
10336                write!(f, "IN NATURAL LANGUAGE MODE")?;
10337            }
10338            Self::InNaturalLanguageModeWithQueryExpansion => {
10339                write!(f, "IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION")?;
10340            }
10341            Self::InBooleanMode => {
10342                write!(f, "IN BOOLEAN MODE")?;
10343            }
10344            Self::WithQueryExpansion => {
10345                write!(f, "WITH QUERY EXPANSION")?;
10346            }
10347        }
10348
10349        Ok(())
10350    }
10351}
10352
10353/// Represents a `LOCK TABLE` clause with optional alias and lock type.
10354#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10355#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10356#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10357pub struct LockTable {
10358    /// The table identifier to lock.
10359    pub table: Ident,
10360    /// Optional alias for the table.
10361    pub alias: Option<Ident>,
10362    /// The type of lock to apply to the table.
10363    pub lock_type: LockTableType,
10364}
10365
10366impl fmt::Display for LockTable {
10367    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10368        let Self {
10369            table: tbl_name,
10370            alias,
10371            lock_type,
10372        } = self;
10373
10374        write!(f, "{tbl_name} ")?;
10375        if let Some(alias) = alias {
10376            write!(f, "AS {alias} ")?;
10377        }
10378        write!(f, "{lock_type}")?;
10379        Ok(())
10380    }
10381}
10382
10383#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10384#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10385#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10386/// The type of lock used in `LOCK TABLE` statements.
10387pub enum LockTableType {
10388    /// Shared/read lock. If `local` is true, it's a local read lock.
10389    Read {
10390        /// Whether the read lock is local.
10391        local: bool,
10392    },
10393    /// Exclusive/write lock. If `low_priority` is true, the write is low priority.
10394    Write {
10395        /// Whether the write lock is low priority.
10396        low_priority: bool,
10397    },
10398}
10399
10400impl fmt::Display for LockTableType {
10401    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10402        match self {
10403            Self::Read { local } => {
10404                write!(f, "READ")?;
10405                if *local {
10406                    write!(f, " LOCAL")?;
10407                }
10408            }
10409            Self::Write { low_priority } => {
10410                if *low_priority {
10411                    write!(f, "LOW_PRIORITY ")?;
10412                }
10413                write!(f, "WRITE")?;
10414            }
10415        }
10416
10417        Ok(())
10418    }
10419}
10420
10421#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10422#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10423#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10424/// Hive-specific `SET LOCATION` helper used in some `LOAD DATA` statements.
10425pub struct HiveSetLocation {
10426    /// Whether the `SET` keyword was present.
10427    pub has_set: bool,
10428    /// The location identifier.
10429    pub location: Ident,
10430}
10431
10432impl fmt::Display for HiveSetLocation {
10433    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10434        if self.has_set {
10435            write!(f, "SET ")?;
10436        }
10437        write!(f, "LOCATION {}", self.location)
10438    }
10439}
10440
10441/// MySQL `ALTER TABLE` only  [FIRST | AFTER column_name]
10442#[allow(clippy::large_enum_variant)]
10443#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10444#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10445#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10446/// MySQL `ALTER TABLE` column position specifier: `FIRST` or `AFTER <column>`.
10447pub enum MySQLColumnPosition {
10448    /// Place the column first in the table.
10449    First,
10450    /// Place the column after the specified identifier.
10451    After(Ident),
10452}
10453
10454impl Display for MySQLColumnPosition {
10455    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10456        match self {
10457            MySQLColumnPosition::First => write!(f, "FIRST"),
10458            MySQLColumnPosition::After(ident) => {
10459                let column_name = &ident.value;
10460                write!(f, "AFTER {column_name}")
10461            }
10462        }
10463    }
10464}
10465
10466/// MySQL `CREATE VIEW` algorithm parameter: [ALGORITHM = {UNDEFINED | MERGE | TEMPTABLE}]
10467#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10468#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10469#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10470/// MySQL `CREATE VIEW` algorithm options.
10471pub enum CreateViewAlgorithm {
10472    /// `UNDEFINED` algorithm.
10473    Undefined,
10474    /// `MERGE` algorithm.
10475    Merge,
10476    /// `TEMPTABLE` algorithm.
10477    TempTable,
10478}
10479
10480impl Display for CreateViewAlgorithm {
10481    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10482        match self {
10483            CreateViewAlgorithm::Undefined => write!(f, "UNDEFINED"),
10484            CreateViewAlgorithm::Merge => write!(f, "MERGE"),
10485            CreateViewAlgorithm::TempTable => write!(f, "TEMPTABLE"),
10486        }
10487    }
10488}
10489/// MySQL `CREATE VIEW` security parameter: [SQL SECURITY { DEFINER | INVOKER }]
10490#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10491#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10492#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10493/// MySQL `CREATE VIEW` SQL SECURITY options.
10494pub enum CreateViewSecurity {
10495    /// The view runs with the privileges of the definer.
10496    Definer,
10497    /// The view runs with the privileges of the invoker.
10498    Invoker,
10499}
10500
10501impl Display for CreateViewSecurity {
10502    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10503        match self {
10504            CreateViewSecurity::Definer => write!(f, "DEFINER"),
10505            CreateViewSecurity::Invoker => write!(f, "INVOKER"),
10506        }
10507    }
10508}
10509
10510/// [MySQL] `CREATE VIEW` additional parameters
10511///
10512/// [MySQL]: https://dev.mysql.com/doc/refman/9.1/en/create-view.html
10513#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10514#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10515#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10516pub struct CreateViewParams {
10517    /// Optional view algorithm (e.g., MERGE, TEMPTABLE).
10518    pub algorithm: Option<CreateViewAlgorithm>,
10519    /// Optional definer (the security principal that will own the view).
10520    pub definer: Option<GranteeName>,
10521    /// Optional SQL SECURITY setting for the view.
10522    pub security: Option<CreateViewSecurity>,
10523}
10524
10525impl Display for CreateViewParams {
10526    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10527        let CreateViewParams {
10528            algorithm,
10529            definer,
10530            security,
10531        } = self;
10532        if let Some(algorithm) = algorithm {
10533            write!(f, "ALGORITHM = {algorithm} ")?;
10534        }
10535        if let Some(definers) = definer {
10536            write!(f, "DEFINER = {definers} ")?;
10537        }
10538        if let Some(security) = security {
10539            write!(f, "SQL SECURITY {security} ")?;
10540        }
10541        Ok(())
10542    }
10543}
10544
10545#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10546#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10547#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10548/// Key/Value, where the value is a (optionally named) list of identifiers
10549///
10550/// ```sql
10551/// UNION = (tbl_name[,tbl_name]...)
10552/// ENGINE = ReplicatedMergeTree('/table_name','{replica}', ver)
10553/// ENGINE = SummingMergeTree([columns])
10554/// ```
10555pub struct NamedParenthesizedList {
10556    /// The option key (identifier) for this named list.
10557    pub key: Ident,
10558    /// Optional secondary name associated with the key.
10559    pub name: Option<Ident>,
10560    /// The list of identifier values for the key.
10561    pub values: Vec<Ident>,
10562}
10563
10564/// Snowflake `WITH ROW ACCESS POLICY policy_name ON (identifier, ...)`
10565///
10566/// <https://docs.snowflake.com/en/sql-reference/sql/create-table>
10567/// <https://docs.snowflake.com/en/user-guide/security-row-intro>
10568#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10569#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10570#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10571pub struct RowAccessPolicy {
10572    /// The fully-qualified policy object name.
10573    pub policy: ObjectName,
10574    /// Identifiers for the columns or objects the policy applies to.
10575    pub on: Vec<Ident>,
10576}
10577
10578impl RowAccessPolicy {
10579    /// Create a new `RowAccessPolicy` for the given `policy` and `on` identifiers.
10580    pub fn new(policy: ObjectName, on: Vec<Ident>) -> Self {
10581        Self { policy, on }
10582    }
10583}
10584
10585impl Display for RowAccessPolicy {
10586    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10587        write!(
10588            f,
10589            "WITH ROW ACCESS POLICY {} ON ({})",
10590            self.policy,
10591            display_comma_separated(self.on.as_slice())
10592        )
10593    }
10594}
10595
10596/// Snowflake `[ WITH ] STORAGE LIFECYCLE POLICY <policy_name> ON ( <col_name> [ , ... ] )`
10597///
10598/// <https://docs.snowflake.com/en/sql-reference/sql/create-table>
10599#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10600#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10601#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10602pub struct StorageLifecyclePolicy {
10603    /// The fully-qualified policy object name.
10604    pub policy: ObjectName,
10605    /// Column names the policy applies to.
10606    pub on: Vec<Ident>,
10607}
10608
10609impl Display for StorageLifecyclePolicy {
10610    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10611        write!(
10612            f,
10613            "WITH STORAGE LIFECYCLE POLICY {} ON ({})",
10614            self.policy,
10615            display_comma_separated(self.on.as_slice())
10616        )
10617    }
10618}
10619
10620/// Snowflake `WITH TAG ( tag_name = '<tag_value>', ...)`
10621///
10622/// <https://docs.snowflake.com/en/sql-reference/sql/create-table>
10623#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10624#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10625#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10626pub struct Tag {
10627    /// The tag key (can be qualified).
10628    pub key: ObjectName,
10629    /// The tag value as a string.
10630    pub value: String,
10631}
10632
10633impl Tag {
10634    /// Create a new `Tag` with the given key and value.
10635    pub fn new(key: ObjectName, value: String) -> Self {
10636        Self { key, value }
10637    }
10638}
10639
10640impl Display for Tag {
10641    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10642        write!(f, "{}='{}'", self.key, self.value)
10643    }
10644}
10645
10646/// Snowflake `WITH CONTACT ( purpose = contact [ , purpose = contact ...] )`
10647///
10648/// <https://docs.snowflake.com/en/sql-reference/sql/create-database>
10649#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10650#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10651#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10652pub struct ContactEntry {
10653    /// The purpose label for the contact entry.
10654    pub purpose: String,
10655    /// The contact information associated with the purpose.
10656    pub contact: String,
10657}
10658
10659impl Display for ContactEntry {
10660    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10661        write!(f, "{} = {}", self.purpose, self.contact)
10662    }
10663}
10664
10665/// Helper to indicate if a comment includes the `=` in the display form
10666#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10667#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10668#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10669pub enum CommentDef {
10670    /// Includes `=` when printing the comment, as `COMMENT = 'comment'`
10671    /// Does not include `=` when printing the comment, as `COMMENT 'comment'`
10672    WithEq(String),
10673    /// Comment variant that omits the `=` when displayed.
10674    WithoutEq(String),
10675}
10676
10677impl Display for CommentDef {
10678    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10679        match self {
10680            CommentDef::WithEq(comment) | CommentDef::WithoutEq(comment) => write!(f, "{comment}"),
10681        }
10682    }
10683}
10684
10685/// Helper to indicate if a collection should be wrapped by a symbol in the display form
10686///
10687/// [`Display`] is implemented for every [`Vec<T>`] where `T: Display`.
10688/// The string output is a comma separated list for the vec items
10689///
10690/// # Examples
10691/// ```
10692/// # use sqlparser::ast::WrappedCollection;
10693/// let items = WrappedCollection::Parentheses(vec!["one", "two", "three"]);
10694/// assert_eq!("(one, two, three)", items.to_string());
10695///
10696/// let items = WrappedCollection::NoWrapping(vec!["one", "two", "three"]);
10697/// assert_eq!("one, two, three", items.to_string());
10698/// ```
10699#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10700#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10701#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10702pub enum WrappedCollection<T> {
10703    /// Print the collection without wrapping symbols, as `item, item, item`
10704    NoWrapping(T),
10705    /// Wraps the collection in Parentheses, as `(item, item, item)`
10706    Parentheses(T),
10707}
10708
10709impl<T> Display for WrappedCollection<Vec<T>>
10710where
10711    T: Display,
10712{
10713    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10714        match self {
10715            WrappedCollection::NoWrapping(inner) => {
10716                write!(f, "{}", display_comma_separated(inner.as_slice()))
10717            }
10718            WrappedCollection::Parentheses(inner) => {
10719                write!(f, "({})", display_comma_separated(inner.as_slice()))
10720            }
10721        }
10722    }
10723}
10724
10725/// Represents a single PostgreSQL utility option.
10726///
10727/// A utility option is a key-value pair where the key is an identifier (IDENT) and the value
10728/// can be one of the following:
10729/// - A number with an optional sign (`+` or `-`). Example: `+10`, `-10.2`, `3`
10730/// - A non-keyword string. Example: `option1`, `'option2'`, `"option3"`
10731/// - keyword: `TRUE`, `FALSE`, `ON` (`off` is also accept).
10732/// - Empty. Example: `ANALYZE` (identifier only)
10733///
10734/// Utility options are used in various PostgreSQL DDL statements, including statements such as
10735/// `CLUSTER`, `EXPLAIN`, `VACUUM`, and `REINDEX`. These statements format options as `( option [, ...] )`.
10736///
10737/// [CLUSTER](https://www.postgresql.org/docs/current/sql-cluster.html)
10738/// [EXPLAIN](https://www.postgresql.org/docs/current/sql-explain.html)
10739/// [VACUUM](https://www.postgresql.org/docs/current/sql-vacuum.html)
10740/// [REINDEX](https://www.postgresql.org/docs/current/sql-reindex.html)
10741///
10742/// For example, the `EXPLAIN` AND `VACUUM` statements with options might look like this:
10743/// ```sql
10744/// EXPLAIN (ANALYZE, VERBOSE TRUE, FORMAT TEXT) SELECT * FROM my_table;
10745///
10746/// VACUUM (VERBOSE, ANALYZE ON, PARALLEL 10) my_table;
10747/// ```
10748#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10749#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10750#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10751pub struct UtilityOption {
10752    /// The option name (identifier).
10753    pub name: Ident,
10754    /// Optional argument for the option (number, string, keyword, etc.).
10755    pub arg: Option<Expr>,
10756}
10757
10758impl Display for UtilityOption {
10759    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10760        if let Some(ref arg) = self.arg {
10761            write!(f, "{} {}", self.name, arg)
10762        } else {
10763            write!(f, "{}", self.name)
10764        }
10765    }
10766}
10767
10768/// Represents the different options available for `SHOW`
10769/// statements to filter the results. Example from Snowflake:
10770/// <https://docs.snowflake.com/en/sql-reference/sql/show-tables>
10771#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10772#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10773#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10774pub struct ShowStatementOptions {
10775    /// Optional scope to show in (for example: TABLE, SCHEMA).
10776    pub show_in: Option<ShowStatementIn>,
10777    /// Optional `STARTS WITH` filter value.
10778    pub starts_with: Option<ValueWithSpan>,
10779    /// Optional `LIMIT` expression.
10780    pub limit: Option<Expr>,
10781    /// Optional `FROM` value used with `LIMIT`.
10782    pub limit_from: Option<ValueWithSpan>,
10783    /// Optional filter position (infix or suffix) for `LIKE`/`FILTER`.
10784    pub filter_position: Option<ShowStatementFilterPosition>,
10785}
10786
10787impl Display for ShowStatementOptions {
10788    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10789        let (like_in_infix, like_in_suffix) = match &self.filter_position {
10790            Some(ShowStatementFilterPosition::Infix(filter)) => {
10791                (format!(" {filter}"), "".to_string())
10792            }
10793            Some(ShowStatementFilterPosition::Suffix(filter)) => {
10794                ("".to_string(), format!(" {filter}"))
10795            }
10796            None => ("".to_string(), "".to_string()),
10797        };
10798        write!(
10799            f,
10800            "{like_in_infix}{show_in}{starts_with}{limit}{from}{like_in_suffix}",
10801            show_in = match &self.show_in {
10802                Some(i) => format!(" {i}"),
10803                None => String::new(),
10804            },
10805            starts_with = match &self.starts_with {
10806                Some(s) => format!(" STARTS WITH {s}"),
10807                None => String::new(),
10808            },
10809            limit = match &self.limit {
10810                Some(l) => format!(" LIMIT {l}"),
10811                None => String::new(),
10812            },
10813            from = match &self.limit_from {
10814                Some(f) => format!(" FROM {f}"),
10815                None => String::new(),
10816            }
10817        )?;
10818        Ok(())
10819    }
10820}
10821
10822#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10823#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10824#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10825/// Where a `SHOW` filter appears relative to the main clause.
10826pub enum ShowStatementFilterPosition {
10827    /// Put the filter in an infix position (e.g. `SHOW COLUMNS LIKE '%name%' IN TABLE tbl`).
10828    Infix(ShowStatementFilter), // For example: SHOW COLUMNS LIKE '%name%' IN TABLE tbl
10829    /// Put the filter in a suffix position (e.g. `SHOW COLUMNS IN tbl LIKE '%name%'`).
10830    Suffix(ShowStatementFilter), // For example: SHOW COLUMNS IN tbl LIKE '%name%'
10831}
10832
10833#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10834#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10835#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10836/// Parent object types usable with `SHOW ... IN <parent>` clauses.
10837pub enum ShowStatementInParentType {
10838    /// ACCOUNT parent type for SHOW statements.
10839    Account,
10840    /// DATABASE parent type for SHOW statements.
10841    Database,
10842    /// SCHEMA parent type for SHOW statements.
10843    Schema,
10844    /// TABLE parent type for SHOW statements.
10845    Table,
10846    /// VIEW parent type for SHOW statements.
10847    View,
10848}
10849
10850impl fmt::Display for ShowStatementInParentType {
10851    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10852        match self {
10853            ShowStatementInParentType::Account => write!(f, "ACCOUNT"),
10854            ShowStatementInParentType::Database => write!(f, "DATABASE"),
10855            ShowStatementInParentType::Schema => write!(f, "SCHEMA"),
10856            ShowStatementInParentType::Table => write!(f, "TABLE"),
10857            ShowStatementInParentType::View => write!(f, "VIEW"),
10858        }
10859    }
10860}
10861
10862#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10863#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10864#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10865/// Represents a `SHOW ... IN` clause with optional parent qualifier and name.
10866pub struct ShowStatementIn {
10867    /// The clause that specifies what to show (e.g. COLUMNS, TABLES).
10868    pub clause: ShowStatementInClause,
10869    /// Optional parent type qualifier (ACCOUNT/DATABASE/...).
10870    pub parent_type: Option<ShowStatementInParentType>,
10871    /// Optional parent object name for the SHOW clause.
10872    #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
10873    pub parent_name: Option<ObjectName>,
10874}
10875
10876impl fmt::Display for ShowStatementIn {
10877    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10878        write!(f, "{}", self.clause)?;
10879        if let Some(parent_type) = &self.parent_type {
10880            write!(f, " {parent_type}")?;
10881        }
10882        if let Some(parent_name) = &self.parent_name {
10883            write!(f, " {parent_name}")?;
10884        }
10885        Ok(())
10886    }
10887}
10888
10889/// A Show Charset statement
10890#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10891#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10892#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10893pub struct ShowCharset {
10894    /// The statement can be written as `SHOW CHARSET` or `SHOW CHARACTER SET`
10895    /// true means CHARSET was used and false means CHARACTER SET was used
10896    pub is_shorthand: bool,
10897    /// Optional `LIKE`/`WHERE`-style filter for the statement.
10898    pub filter: Option<ShowStatementFilter>,
10899}
10900
10901impl fmt::Display for ShowCharset {
10902    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10903        write!(f, "SHOW")?;
10904        if self.is_shorthand {
10905            write!(f, " CHARSET")?;
10906        } else {
10907            write!(f, " CHARACTER SET")?;
10908        }
10909        if let Some(filter) = &self.filter {
10910            write!(f, " {filter}")?;
10911        }
10912        Ok(())
10913    }
10914}
10915
10916#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10917#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10918#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10919/// Options for a `SHOW OBJECTS` statement.
10920pub struct ShowObjects {
10921    /// Whether to show terse output.
10922    pub terse: bool,
10923    /// Additional options controlling the SHOW output.
10924    pub show_options: ShowStatementOptions,
10925}
10926
10927/// MSSQL's json null clause
10928///
10929/// ```plaintext
10930/// <json_null_clause> ::=
10931///       NULL ON NULL
10932///     | ABSENT ON NULL
10933/// ```
10934///
10935/// <https://learn.microsoft.com/en-us/sql/t-sql/functions/json-object-transact-sql?view=sql-server-ver16#json_null_clause>
10936#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10937#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10938#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10939pub enum JsonNullClause {
10940    /// `NULL ON NULL` behavior for JSON functions.
10941    NullOnNull,
10942    /// `ABSENT ON NULL` behavior for JSON functions.
10943    AbsentOnNull,
10944}
10945
10946impl Display for JsonNullClause {
10947    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10948        match self {
10949            JsonNullClause::NullOnNull => write!(f, "NULL ON NULL"),
10950            JsonNullClause::AbsentOnNull => write!(f, "ABSENT ON NULL"),
10951        }
10952    }
10953}
10954
10955/// PostgreSQL JSON function RETURNING clause
10956///
10957/// Example:
10958/// ```sql
10959/// JSON_OBJECT('a': 1 RETURNING jsonb)
10960/// ```
10961#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10962#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10963#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10964pub struct JsonReturningClause {
10965    /// The data type to return from the JSON function (e.g. JSON/JSONB).
10966    pub data_type: DataType,
10967}
10968
10969impl Display for JsonReturningClause {
10970    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10971        write!(f, "RETURNING {}", self.data_type)
10972    }
10973}
10974
10975/// rename object definition
10976#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10977#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10978#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10979pub struct RenameTable {
10980    /// The current name of the object to rename.
10981    pub old_name: ObjectName,
10982    /// The new name for the object.
10983    pub new_name: ObjectName,
10984}
10985
10986impl fmt::Display for RenameTable {
10987    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10988        write!(f, "{} TO {}", self.old_name, self.new_name)?;
10989        Ok(())
10990    }
10991}
10992
10993/// Represents the referenced table in an `INSERT INTO` statement
10994#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10995#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10996#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10997pub enum TableObject {
10998    /// Table specified by name.
10999    /// Example:
11000    /// ```sql
11001    /// INSERT INTO my_table
11002    /// ```
11003    TableName(#[cfg_attr(feature = "visitor", visit(with = "visit_relation"))] ObjectName),
11004
11005    /// Table specified as a function.
11006    /// Example:
11007    /// ```sql
11008    /// INSERT INTO TABLE FUNCTION remote('localhost', default.simple_table)
11009    /// ```
11010    /// [Clickhouse](https://clickhouse.com/docs/en/sql-reference/table-functions)
11011    TableFunction(Function),
11012
11013    /// Table specified through a sub-query
11014    /// Example:
11015    /// ```sql
11016    /// INSERT INTO
11017    /// (SELECT employee_id, last_name, email, hire_date, job_id,  salary, commission_pct FROM employees)
11018    /// VALUES (207, 'Gregory', 'pgregory@example.com', sysdate, 'PU_CLERK', 1.2E3, NULL);
11019    /// ```
11020    /// [Oracle](https://docs.oracle.com/en/database/oracle/oracle-database/21/sqlrf/INSERT.html#GUID-903F8043-0254-4EE9-ACC1-CB8AC0AF3423__I2126242)
11021    TableQuery(Box<Query>),
11022}
11023
11024impl fmt::Display for TableObject {
11025    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11026        match self {
11027            Self::TableName(table_name) => write!(f, "{table_name}"),
11028            Self::TableFunction(func) => write!(f, "FUNCTION {func}"),
11029            Self::TableQuery(table_query) => write!(f, "({table_query})"),
11030        }
11031    }
11032}
11033
11034/// Represents a SET SESSION AUTHORIZATION statement
11035#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11036#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11037#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11038pub struct SetSessionAuthorizationParam {
11039    /// The scope for the `SET SESSION AUTHORIZATION` (e.g., GLOBAL/SESSION).
11040    pub scope: ContextModifier,
11041    /// The specific authorization parameter kind.
11042    pub kind: SetSessionAuthorizationParamKind,
11043}
11044
11045impl fmt::Display for SetSessionAuthorizationParam {
11046    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11047        write!(f, "{}", self.kind)
11048    }
11049}
11050
11051/// Represents the parameter kind for SET SESSION AUTHORIZATION
11052#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11053#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11054#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11055pub enum SetSessionAuthorizationParamKind {
11056    /// Default authorization
11057    Default,
11058
11059    /// User name
11060    User(Ident),
11061}
11062
11063impl fmt::Display for SetSessionAuthorizationParamKind {
11064    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11065        match self {
11066            SetSessionAuthorizationParamKind::Default => write!(f, "DEFAULT"),
11067            SetSessionAuthorizationParamKind::User(name) => write!(f, "{}", name),
11068        }
11069    }
11070}
11071
11072#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11073#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11074#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11075/// Kind of session parameter being set by `SET SESSION`.
11076pub enum SetSessionParamKind {
11077    /// Generic session parameter (name/value pair).
11078    Generic(SetSessionParamGeneric),
11079    /// Identity insert related parameter.
11080    IdentityInsert(SetSessionParamIdentityInsert),
11081    /// Offsets-related parameter.
11082    Offsets(SetSessionParamOffsets),
11083    /// Statistics-related parameter.
11084    Statistics(SetSessionParamStatistics),
11085}
11086
11087impl fmt::Display for SetSessionParamKind {
11088    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11089        match self {
11090            SetSessionParamKind::Generic(x) => write!(f, "{x}"),
11091            SetSessionParamKind::IdentityInsert(x) => write!(f, "{x}"),
11092            SetSessionParamKind::Offsets(x) => write!(f, "{x}"),
11093            SetSessionParamKind::Statistics(x) => write!(f, "{x}"),
11094        }
11095    }
11096}
11097
11098#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11099#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11100#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11101/// Generic `SET SESSION` parameter represented as name(s) and value.
11102pub struct SetSessionParamGeneric {
11103    /// Names of the session parameters being set.
11104    pub names: Vec<String>,
11105    /// The value to assign to the parameter(s).
11106    pub value: String,
11107}
11108
11109impl fmt::Display for SetSessionParamGeneric {
11110    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11111        write!(f, "{} {}", display_comma_separated(&self.names), self.value)
11112    }
11113}
11114
11115#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11116#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11117#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11118/// `IDENTITY_INSERT` session parameter for a specific object.
11119pub struct SetSessionParamIdentityInsert {
11120    /// Object name targeted by `IDENTITY_INSERT`.
11121    pub obj: ObjectName,
11122    /// Value (ON/OFF) for the identity insert setting.
11123    pub value: SessionParamValue,
11124}
11125
11126impl fmt::Display for SetSessionParamIdentityInsert {
11127    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11128        write!(f, "IDENTITY_INSERT {} {}", self.obj, self.value)
11129    }
11130}
11131
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))]
11135/// Offsets-related session parameter with keywords and a value.
11136pub struct SetSessionParamOffsets {
11137    /// Keywords specifying which offsets to modify.
11138    pub keywords: Vec<String>,
11139    /// Value (ON/OFF) for the offsets setting.
11140    pub value: SessionParamValue,
11141}
11142
11143impl fmt::Display for SetSessionParamOffsets {
11144    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11145        write!(
11146            f,
11147            "OFFSETS {} {}",
11148            display_comma_separated(&self.keywords),
11149            self.value
11150        )
11151    }
11152}
11153
11154#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11155#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11156#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11157/// Statistics-related session parameter specifying topic and value.
11158pub struct SetSessionParamStatistics {
11159    /// Statistics topic to set (IO/PROFILE/TIME/XML).
11160    pub topic: SessionParamStatsTopic,
11161    /// Value (ON/OFF) for the statistics topic.
11162    pub value: SessionParamValue,
11163}
11164
11165impl fmt::Display for SetSessionParamStatistics {
11166    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11167        write!(f, "STATISTICS {} {}", self.topic, self.value)
11168    }
11169}
11170
11171#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11172#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11173#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11174/// Topics available for session statistics configuration.
11175pub enum SessionParamStatsTopic {
11176    /// Input/output statistics.
11177    IO,
11178    /// Profile statistics.
11179    Profile,
11180    /// Time statistics.
11181    Time,
11182    /// XML-related statistics.
11183    Xml,
11184}
11185
11186impl fmt::Display for SessionParamStatsTopic {
11187    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11188        match self {
11189            SessionParamStatsTopic::IO => write!(f, "IO"),
11190            SessionParamStatsTopic::Profile => write!(f, "PROFILE"),
11191            SessionParamStatsTopic::Time => write!(f, "TIME"),
11192            SessionParamStatsTopic::Xml => write!(f, "XML"),
11193        }
11194    }
11195}
11196
11197#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11198#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11199#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11200/// Value for a session boolean-like parameter (ON/OFF).
11201pub enum SessionParamValue {
11202    /// Session parameter enabled.
11203    On,
11204    /// Session parameter disabled.
11205    Off,
11206}
11207
11208impl fmt::Display for SessionParamValue {
11209    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11210        match self {
11211            SessionParamValue::On => write!(f, "ON"),
11212            SessionParamValue::Off => write!(f, "OFF"),
11213        }
11214    }
11215}
11216
11217/// Snowflake StorageSerializationPolicy for Iceberg Tables
11218/// ```sql
11219/// [ STORAGE_SERIALIZATION_POLICY = { COMPATIBLE | OPTIMIZED } ]
11220/// ```
11221///
11222/// <https://docs.snowflake.com/en/sql-reference/sql/create-iceberg-table>
11223#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11224#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11225#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11226pub enum StorageSerializationPolicy {
11227    /// Use compatible serialization mode.
11228    Compatible,
11229    /// Use optimized serialization mode.
11230    Optimized,
11231}
11232
11233impl Display for StorageSerializationPolicy {
11234    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
11235        match self {
11236            StorageSerializationPolicy::Compatible => write!(f, "COMPATIBLE"),
11237            StorageSerializationPolicy::Optimized => write!(f, "OPTIMIZED"),
11238        }
11239    }
11240}
11241
11242/// Snowflake CatalogSyncNamespaceMode
11243/// ```sql
11244/// [ CATALOG_SYNC_NAMESPACE_MODE = { NEST | FLATTEN } ]
11245/// ```
11246///
11247/// <https://docs.snowflake.com/en/sql-reference/sql/create-database>
11248#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11249#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11250#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11251pub enum CatalogSyncNamespaceMode {
11252    /// Nest namespaces when syncing catalog.
11253    Nest,
11254    /// Flatten namespaces when syncing catalog.
11255    Flatten,
11256}
11257
11258impl Display for CatalogSyncNamespaceMode {
11259    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
11260        match self {
11261            CatalogSyncNamespaceMode::Nest => write!(f, "NEST"),
11262            CatalogSyncNamespaceMode::Flatten => write!(f, "FLATTEN"),
11263        }
11264    }
11265}
11266
11267/// Variants of the Snowflake `COPY INTO` statement
11268#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11269#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11270#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11271pub enum CopyIntoSnowflakeKind {
11272    /// Loads data from files to a table
11273    /// See: <https://docs.snowflake.com/en/sql-reference/sql/copy-into-table>
11274    Table,
11275    /// Unloads data from a table or query to external files
11276    /// See: <https://docs.snowflake.com/en/sql-reference/sql/copy-into-location>
11277    Location,
11278}
11279
11280#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11281#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11282#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11283/// `PRINT` statement for producing debug/output messages.
11284pub struct PrintStatement {
11285    /// The expression producing the message to print.
11286    pub message: Box<Expr>,
11287}
11288
11289impl fmt::Display for PrintStatement {
11290    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11291        write!(f, "PRINT {}", self.message)
11292    }
11293}
11294
11295/// The type of `WAITFOR` statement (MSSQL).
11296///
11297/// See: <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/waitfor-transact-sql>
11298#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11299#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11300#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11301pub enum WaitForType {
11302    /// `WAITFOR DELAY 'time_to_pass'`
11303    Delay,
11304    /// `WAITFOR TIME 'time_to_execute'`
11305    Time,
11306}
11307
11308impl fmt::Display for WaitForType {
11309    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11310        match self {
11311            WaitForType::Delay => write!(f, "DELAY"),
11312            WaitForType::Time => write!(f, "TIME"),
11313        }
11314    }
11315}
11316
11317/// MSSQL `WAITFOR` statement.
11318///
11319/// See: <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/waitfor-transact-sql>
11320#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11321#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11322#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11323pub struct WaitForStatement {
11324    /// `DELAY` or `TIME`.
11325    pub wait_type: WaitForType,
11326    /// The time expression.
11327    pub expr: Expr,
11328}
11329
11330impl fmt::Display for WaitForStatement {
11331    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11332        write!(f, "WAITFOR {} {}", self.wait_type, self.expr)
11333    }
11334}
11335
11336/// Represents a `Return` statement.
11337///
11338/// [MsSql triggers](https://learn.microsoft.com/en-us/sql/t-sql/statements/create-trigger-transact-sql)
11339/// [MsSql functions](https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql)
11340#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11341#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11342#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11343pub struct ReturnStatement {
11344    /// Optional return value expression.
11345    pub value: Option<ReturnStatementValue>,
11346}
11347
11348impl fmt::Display for ReturnStatement {
11349    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11350        match &self.value {
11351            Some(ReturnStatementValue::Expr(expr)) => write!(f, "RETURN {expr}"),
11352            None => write!(f, "RETURN"),
11353        }
11354    }
11355}
11356
11357/// Variants of a `RETURN` statement
11358#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11359#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11360#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11361pub enum ReturnStatementValue {
11362    /// Return an expression from a function or trigger.
11363    Expr(Expr),
11364}
11365
11366/// Represents an `OPEN` statement.
11367#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11368#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11369#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11370pub struct OpenStatement {
11371    /// Cursor name
11372    pub cursor_name: Ident,
11373}
11374
11375impl fmt::Display for OpenStatement {
11376    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11377        write!(f, "OPEN {}", self.cursor_name)
11378    }
11379}
11380
11381/// Specifies Include / Exclude NULL within UNPIVOT command.
11382/// For example
11383/// `UNPIVOT (column1 FOR new_column IN (col3, col4, col5, col6))`
11384#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11385#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11386#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11387pub enum NullInclusion {
11388    /// Include NULL values in the UNPIVOT output.
11389    IncludeNulls,
11390    /// Exclude NULL values from the UNPIVOT output.
11391    ExcludeNulls,
11392}
11393
11394impl fmt::Display for NullInclusion {
11395    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11396        match self {
11397            NullInclusion::IncludeNulls => write!(f, "INCLUDE NULLS"),
11398            NullInclusion::ExcludeNulls => write!(f, "EXCLUDE NULLS"),
11399        }
11400    }
11401}
11402
11403/// Checks membership of a value in a JSON array
11404///
11405/// Syntax:
11406/// ```sql
11407/// <value> MEMBER OF(<array>)
11408/// ```
11409/// [MySQL](https://dev.mysql.com/doc/refman/8.4/en/json-search-functions.html#operator_member-of)
11410#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11411#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11412#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11413pub struct MemberOf {
11414    /// The value to check for membership.
11415    pub value: Box<Expr>,
11416    /// The JSON array expression to check against.
11417    pub array: Box<Expr>,
11418}
11419
11420impl fmt::Display for MemberOf {
11421    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11422        write!(f, "{} MEMBER OF({})", self.value, self.array)
11423    }
11424}
11425
11426#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11427#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11428#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11429/// Represents an `EXPORT DATA` statement.
11430pub struct ExportData {
11431    /// Options for the export operation.
11432    pub options: Vec<SqlOption>,
11433    /// The query producing the data to export.
11434    pub query: Box<Query>,
11435    /// Optional named connection to use for export.
11436    pub connection: Option<ObjectName>,
11437}
11438
11439impl fmt::Display for ExportData {
11440    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11441        if let Some(connection) = &self.connection {
11442            write!(
11443                f,
11444                "EXPORT DATA WITH CONNECTION {connection} OPTIONS({}) AS {}",
11445                display_comma_separated(&self.options),
11446                self.query
11447            )
11448        } else {
11449            write!(
11450                f,
11451                "EXPORT DATA OPTIONS({}) AS {}",
11452                display_comma_separated(&self.options),
11453                self.query
11454            )
11455        }
11456    }
11457}
11458/// Creates a user
11459///
11460/// Syntax:
11461/// ```sql
11462/// CREATE [OR REPLACE] USER [IF NOT EXISTS] <name> [OPTIONS]
11463/// ```
11464///
11465/// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-user)
11466#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11467#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11468#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11469pub struct CreateUser {
11470    /// Replace existing user if present.
11471    pub or_replace: bool,
11472    /// Only create the user if it does not already exist.
11473    pub if_not_exists: bool,
11474    /// The name of the user to create.
11475    pub name: Ident,
11476    /// Key/value options for user creation.
11477    pub options: KeyValueOptions,
11478    /// Whether tags are specified using `WITH TAG`.
11479    pub with_tags: bool,
11480    /// Tags for the user.
11481    pub tags: KeyValueOptions,
11482}
11483
11484impl fmt::Display for CreateUser {
11485    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11486        write!(f, "CREATE")?;
11487        if self.or_replace {
11488            write!(f, " OR REPLACE")?;
11489        }
11490        write!(f, " USER")?;
11491        if self.if_not_exists {
11492            write!(f, " IF NOT EXISTS")?;
11493        }
11494        write!(f, " {}", self.name)?;
11495        if !self.options.options.is_empty() {
11496            write!(f, " {}", self.options)?;
11497        }
11498        if !self.tags.options.is_empty() {
11499            if self.with_tags {
11500                write!(f, " WITH")?;
11501            }
11502            write!(f, " TAG ({})", self.tags)?;
11503        }
11504        Ok(())
11505    }
11506}
11507
11508/// Modifies the properties of a user
11509///
11510/// [Snowflake Syntax:](https://docs.snowflake.com/en/sql-reference/sql/alter-user)
11511/// ```sql
11512/// ALTER USER [ IF EXISTS ] [ <name> ] [ OPTIONS ]
11513/// ```
11514///
11515/// [PostgreSQL Syntax:](https://www.postgresql.org/docs/current/sql-alteruser.html)
11516/// ```sql
11517/// ALTER USER <role_specification> [ WITH ] option [ ... ]
11518/// ```
11519#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11520#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11521#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11522pub struct AlterUser {
11523    /// Whether to only alter the user if it exists.
11524    pub if_exists: bool,
11525    /// The name of the user to alter.
11526    pub name: Ident,
11527    /// Optional new name for the user (Snowflake-specific).
11528    /// See: <https://docs.snowflake.com/en/sql-reference/sql/alter-user#syntax>
11529    pub rename_to: Option<Ident>,
11530    /// Reset the user's password.
11531    pub reset_password: bool,
11532    /// Abort all running queries for the user.
11533    pub abort_all_queries: bool,
11534    /// Optionally add a delegated role authorization.
11535    pub add_role_delegation: Option<AlterUserAddRoleDelegation>,
11536    /// Optionally remove a delegated role authorization.
11537    pub remove_role_delegation: Option<AlterUserRemoveRoleDelegation>,
11538    /// Enroll the user in MFA.
11539    pub enroll_mfa: bool,
11540    /// Set the default MFA method for the user.
11541    pub set_default_mfa_method: Option<MfaMethodKind>,
11542    /// Remove the user's default MFA method.
11543    pub remove_mfa_method: Option<MfaMethodKind>,
11544    /// Modify an MFA method for the user.
11545    pub modify_mfa_method: Option<AlterUserModifyMfaMethod>,
11546    /// Add an MFA OTP method with optional count.
11547    pub add_mfa_method_otp: Option<AlterUserAddMfaMethodOtp>,
11548    /// Set a user policy.
11549    pub set_policy: Option<AlterUserSetPolicy>,
11550    /// Unset a user policy.
11551    pub unset_policy: Option<UserPolicyKind>,
11552    /// Key/value tag options to set on the user.
11553    pub set_tag: KeyValueOptions,
11554    /// Tags to unset on the user.
11555    pub unset_tag: Vec<String>,
11556    /// Key/value properties to set on the user.
11557    pub set_props: KeyValueOptions,
11558    /// Properties to unset on the user.
11559    pub unset_props: Vec<String>,
11560    /// The following options are PostgreSQL-specific: <https://www.postgresql.org/docs/current/sql-alteruser.html>
11561    pub password: Option<AlterUserPassword>,
11562}
11563
11564/// ```sql
11565/// ALTER USER [ IF EXISTS ] [ <name> ] ADD DELEGATED AUTHORIZATION OF ROLE <role_name> TO SECURITY INTEGRATION <integration_name>
11566/// ```
11567#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11568#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11569#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11570pub struct AlterUserAddRoleDelegation {
11571    /// Role name to delegate.
11572    pub role: Ident,
11573    /// Security integration receiving the delegation.
11574    pub integration: Ident,
11575}
11576
11577/// ```sql
11578/// ALTER USER [ IF EXISTS ] [ <name> ] REMOVE DELEGATED { AUTHORIZATION OF ROLE <role_name> | AUTHORIZATIONS } FROM SECURITY INTEGRATION <integration_name>
11579/// ```
11580#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11581#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11582#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11583pub struct AlterUserRemoveRoleDelegation {
11584    /// Optional role name to remove delegation for.
11585    pub role: Option<Ident>,
11586    /// Security integration from which to remove delegation.
11587    pub integration: Ident,
11588}
11589
11590/// ```sql
11591/// ADD MFA METHOD OTP [ COUNT = number ]
11592/// ```
11593#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11594#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11595#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11596pub struct AlterUserAddMfaMethodOtp {
11597    /// Optional OTP count parameter.
11598    pub count: Option<ValueWithSpan>,
11599}
11600
11601/// ```sql
11602/// ALTER USER [ IF EXISTS ] [ <name> ] MODIFY MFA METHOD <mfa_method> SET COMMENT = '<string>'
11603/// ```
11604#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11605#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11606#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11607pub struct AlterUserModifyMfaMethod {
11608    /// The MFA method being modified.
11609    pub method: MfaMethodKind,
11610    /// The new comment for the MFA method.
11611    pub comment: String,
11612}
11613
11614/// Types of MFA methods
11615#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11616#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11617#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11618pub enum MfaMethodKind {
11619    /// PassKey (hardware or platform passkey) MFA method.
11620    PassKey,
11621    /// Time-based One-Time Password (TOTP) MFA method.
11622    Totp,
11623    /// Duo Security MFA method.
11624    Duo,
11625}
11626
11627impl fmt::Display for MfaMethodKind {
11628    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11629        match self {
11630            MfaMethodKind::PassKey => write!(f, "PASSKEY"),
11631            MfaMethodKind::Totp => write!(f, "TOTP"),
11632            MfaMethodKind::Duo => write!(f, "DUO"),
11633        }
11634    }
11635}
11636
11637/// ```sql
11638/// ALTER USER [ IF EXISTS ] [ <name> ] SET { AUTHENTICATION | PASSWORD | SESSION } POLICY <policy_name>
11639/// ```
11640#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11641#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11642#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11643pub struct AlterUserSetPolicy {
11644    /// The kind of user policy being set (authentication/password/session).
11645    pub policy_kind: UserPolicyKind,
11646    /// The identifier of the policy to apply.
11647    pub policy: Ident,
11648}
11649
11650/// Types of user-based policies
11651#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11652#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11653#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11654pub enum UserPolicyKind {
11655    /// Authentication policy.
11656    Authentication,
11657    /// Password policy.
11658    Password,
11659    /// Session policy.
11660    Session,
11661}
11662
11663impl fmt::Display for UserPolicyKind {
11664    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11665        match self {
11666            UserPolicyKind::Authentication => write!(f, "AUTHENTICATION"),
11667            UserPolicyKind::Password => write!(f, "PASSWORD"),
11668            UserPolicyKind::Session => write!(f, "SESSION"),
11669        }
11670    }
11671}
11672
11673impl fmt::Display for AlterUser {
11674    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11675        write!(f, "ALTER")?;
11676        write!(f, " USER")?;
11677        if self.if_exists {
11678            write!(f, " IF EXISTS")?;
11679        }
11680        write!(f, " {}", self.name)?;
11681        if let Some(new_name) = &self.rename_to {
11682            write!(f, " RENAME TO {new_name}")?;
11683        }
11684        if self.reset_password {
11685            write!(f, " RESET PASSWORD")?;
11686        }
11687        if self.abort_all_queries {
11688            write!(f, " ABORT ALL QUERIES")?;
11689        }
11690        if let Some(role_delegation) = &self.add_role_delegation {
11691            let role = &role_delegation.role;
11692            let integration = &role_delegation.integration;
11693            write!(
11694                f,
11695                " ADD DELEGATED AUTHORIZATION OF ROLE {role} TO SECURITY INTEGRATION {integration}"
11696            )?;
11697        }
11698        if let Some(role_delegation) = &self.remove_role_delegation {
11699            write!(f, " REMOVE DELEGATED")?;
11700            match &role_delegation.role {
11701                Some(role) => write!(f, " AUTHORIZATION OF ROLE {role}")?,
11702                None => write!(f, " AUTHORIZATIONS")?,
11703            }
11704            let integration = &role_delegation.integration;
11705            write!(f, " FROM SECURITY INTEGRATION {integration}")?;
11706        }
11707        if self.enroll_mfa {
11708            write!(f, " ENROLL MFA")?;
11709        }
11710        if let Some(method) = &self.set_default_mfa_method {
11711            write!(f, " SET DEFAULT_MFA_METHOD {method}")?
11712        }
11713        if let Some(method) = &self.remove_mfa_method {
11714            write!(f, " REMOVE MFA METHOD {method}")?;
11715        }
11716        if let Some(modify) = &self.modify_mfa_method {
11717            let method = &modify.method;
11718            let comment = &modify.comment;
11719            write!(
11720                f,
11721                " MODIFY MFA METHOD {method} SET COMMENT '{}'",
11722                value::escape_single_quote_string(comment)
11723            )?;
11724        }
11725        if let Some(add_mfa_method_otp) = &self.add_mfa_method_otp {
11726            write!(f, " ADD MFA METHOD OTP")?;
11727            if let Some(count) = &add_mfa_method_otp.count {
11728                write!(f, " COUNT = {count}")?;
11729            }
11730        }
11731        if let Some(policy) = &self.set_policy {
11732            let policy_kind = &policy.policy_kind;
11733            let name = &policy.policy;
11734            write!(f, " SET {policy_kind} POLICY {name}")?;
11735        }
11736        if let Some(policy_kind) = &self.unset_policy {
11737            write!(f, " UNSET {policy_kind} POLICY")?;
11738        }
11739        if !self.set_tag.options.is_empty() {
11740            write!(f, " SET TAG {}", self.set_tag)?;
11741        }
11742        if !self.unset_tag.is_empty() {
11743            write!(f, " UNSET TAG {}", display_comma_separated(&self.unset_tag))?;
11744        }
11745        let has_props = !self.set_props.options.is_empty();
11746        if has_props {
11747            write!(f, " SET")?;
11748            write!(f, " {}", &self.set_props)?;
11749        }
11750        if !self.unset_props.is_empty() {
11751            write!(f, " UNSET {}", display_comma_separated(&self.unset_props))?;
11752        }
11753        if let Some(password) = &self.password {
11754            write!(f, " {}", password)?;
11755        }
11756        Ok(())
11757    }
11758}
11759
11760/// ```sql
11761/// ALTER USER <role_specification> [ WITH ] PASSWORD { 'password' | NULL }``
11762/// ```
11763#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11764#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11765#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11766pub struct AlterUserPassword {
11767    /// Whether the password is encrypted.
11768    pub encrypted: bool,
11769    /// The password string, or `None` for `NULL`.
11770    pub password: Option<String>,
11771}
11772
11773impl Display for AlterUserPassword {
11774    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11775        if self.encrypted {
11776            write!(f, "ENCRYPTED ")?;
11777        }
11778        write!(f, "PASSWORD")?;
11779        match &self.password {
11780            None => write!(f, " NULL")?,
11781            Some(password) => write!(f, " '{}'", value::escape_single_quote_string(password))?,
11782        }
11783        Ok(())
11784    }
11785}
11786
11787/// Specifies how to create a new table based on an existing table's schema.
11788/// '''sql
11789/// CREATE TABLE new LIKE old ...
11790/// '''
11791#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11792#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11793#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11794pub enum CreateTableLikeKind {
11795    /// '''sql
11796    /// CREATE TABLE new (LIKE old ...)
11797    /// '''
11798    /// [Redshift](https://docs.aws.amazon.com/redshift/latest/dg/r_CREATE_TABLE_NEW.html)
11799    Parenthesized(CreateTableLike),
11800    /// '''sql
11801    /// CREATE TABLE new LIKE old ...
11802    /// '''
11803    /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-table#label-create-table-like)
11804    /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_table_like)
11805    Plain(CreateTableLike),
11806}
11807
11808#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11809#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11810#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11811/// Controls whether defaults are included when creating a table FROM/LILE another.
11812pub enum CreateTableLikeDefaults {
11813    /// Include default values from the source table.
11814    Including,
11815    /// Exclude default values from the source table.
11816    Excluding,
11817}
11818
11819impl fmt::Display for CreateTableLikeDefaults {
11820    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11821        match self {
11822            CreateTableLikeDefaults::Including => write!(f, "INCLUDING DEFAULTS"),
11823            CreateTableLikeDefaults::Excluding => write!(f, "EXCLUDING DEFAULTS"),
11824        }
11825    }
11826}
11827
11828#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11829#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11830#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11831/// Represents the `LIKE` clause of a `CREATE TABLE` statement.
11832pub struct CreateTableLike {
11833    /// The source table name to copy the schema from.
11834    pub name: ObjectName,
11835    /// Optional behavior controlling whether defaults are copied.
11836    pub defaults: Option<CreateTableLikeDefaults>,
11837}
11838
11839impl fmt::Display for CreateTableLike {
11840    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11841        write!(f, "LIKE {}", self.name)?;
11842        if let Some(defaults) = &self.defaults {
11843            write!(f, " {defaults}")?;
11844        }
11845        Ok(())
11846    }
11847}
11848
11849/// Specifies the refresh mode for the dynamic table.
11850///
11851/// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-dynamic-table)
11852#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11853#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11854#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11855pub enum RefreshModeKind {
11856    /// Automatic refresh mode (`AUTO`).
11857    Auto,
11858    /// Full refresh mode (`FULL`).
11859    Full,
11860    /// Incremental refresh mode (`INCREMENTAL`).
11861    Incremental,
11862}
11863
11864impl fmt::Display for RefreshModeKind {
11865    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11866        match self {
11867            RefreshModeKind::Auto => write!(f, "AUTO"),
11868            RefreshModeKind::Full => write!(f, "FULL"),
11869            RefreshModeKind::Incremental => write!(f, "INCREMENTAL"),
11870        }
11871    }
11872}
11873
11874/// Specifies the behavior of the initial refresh of the dynamic table.
11875///
11876/// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-dynamic-table)
11877#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11878#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11879#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11880pub enum InitializeKind {
11881    /// Initialize on creation (`ON CREATE`).
11882    OnCreate,
11883    /// Initialize on schedule (`ON SCHEDULE`).
11884    OnSchedule,
11885}
11886
11887impl fmt::Display for InitializeKind {
11888    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11889        match self {
11890            InitializeKind::OnCreate => write!(f, "ON_CREATE"),
11891            InitializeKind::OnSchedule => write!(f, "ON_SCHEDULE"),
11892        }
11893    }
11894}
11895
11896/// Re-sorts rows and reclaims space in either a specified table or all tables in the current database
11897///
11898/// '''sql
11899/// VACUUM [ FULL | SORT ONLY | DELETE ONLY | REINDEX | RECLUSTER ] [ \[ table_name \] [ TO threshold PERCENT ] \[ BOOST \] ]
11900/// '''
11901/// [Redshift](https://docs.aws.amazon.com/redshift/latest/dg/r_VACUUM_command.html)
11902#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11903#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11904#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11905pub struct VacuumStatement {
11906    /// Whether `FULL` was specified.
11907    pub full: bool,
11908    /// Whether `SORT ONLY` was specified.
11909    pub sort_only: bool,
11910    /// Whether `DELETE ONLY` was specified.
11911    pub delete_only: bool,
11912    /// Whether `REINDEX` was specified.
11913    pub reindex: bool,
11914    /// Whether `RECLUSTER` was specified.
11915    pub recluster: bool,
11916    /// Optional table to run `VACUUM` on.
11917    pub table_name: Option<ObjectName>,
11918    /// Optional threshold value (percent) for `TO threshold PERCENT`.
11919    pub threshold: Option<ValueWithSpan>,
11920    /// Whether `BOOST` was specified.
11921    pub boost: bool,
11922}
11923
11924impl fmt::Display for VacuumStatement {
11925    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11926        write!(
11927            f,
11928            "VACUUM{}{}{}{}{}",
11929            if self.full { " FULL" } else { "" },
11930            if self.sort_only { " SORT ONLY" } else { "" },
11931            if self.delete_only { " DELETE ONLY" } else { "" },
11932            if self.reindex { " REINDEX" } else { "" },
11933            if self.recluster { " RECLUSTER" } else { "" },
11934        )?;
11935        if let Some(table_name) = &self.table_name {
11936            write!(f, " {table_name}")?;
11937        }
11938        if let Some(threshold) = &self.threshold {
11939            write!(f, " TO {threshold} PERCENT")?;
11940        }
11941        if self.boost {
11942            write!(f, " BOOST")?;
11943        }
11944        Ok(())
11945    }
11946}
11947
11948/// Variants of the RESET statement
11949#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11950#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11951#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11952pub enum Reset {
11953    /// Resets all session parameters to their default values.
11954    ALL,
11955
11956    /// Resets a specific session parameter to its default value.
11957    ConfigurationParameter(ObjectName),
11958}
11959
11960/// Resets a session parameter to its default value.
11961/// ```sql
11962/// RESET { ALL | <configuration_parameter> }
11963/// ```
11964#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11965#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11966#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11967pub struct ResetStatement {
11968    /// The reset action to perform (either `ALL` or a specific configuration parameter).
11969    pub reset: Reset,
11970}
11971
11972/// Query optimizer hints are optionally supported comments after the
11973/// `SELECT`, `INSERT`, `UPDATE`, `REPLACE`, `MERGE`, and `DELETE` keywords in
11974/// the corresponding statements.
11975///
11976/// See [Select::optimizer_hints]
11977#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11978#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11979#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11980pub struct OptimizerHint {
11981    /// An optional prefix between the comment marker and `+`.
11982    ///
11983    /// Standard optimizer hints like `/*+ ... */` have an empty prefix,
11984    /// while system-specific hints like `/*abc+ ... */` have `prefix = "abc"`.
11985    /// The prefix is any sequence of ASCII alphanumeric characters
11986    /// immediately before the `+` marker.
11987    pub prefix: String,
11988    /// the raw text of the optimizer hint without its markers
11989    pub text: String,
11990    /// the style of the comment which `text` was extracted from,
11991    /// e.g. `/*+...*/` or `--+...`
11992    ///
11993    /// Not all dialects support all styles, though.
11994    pub style: OptimizerHintStyle,
11995}
11996
11997/// The commentary style of an [optimizer hint](OptimizerHint)
11998#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11999#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
12000#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
12001pub enum OptimizerHintStyle {
12002    /// A hint corresponding to a single line comment,
12003    /// e.g. `--+ LEADING(v.e v.d t)`
12004    SingleLine {
12005        /// the comment prefix, e.g. `--`
12006        prefix: String,
12007    },
12008    /// A hint corresponding to a multi line comment,
12009    /// e.g. `/*+ LEADING(v.e v.d t) */`
12010    MultiLine,
12011}
12012
12013impl fmt::Display for OptimizerHint {
12014    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
12015        match &self.style {
12016            OptimizerHintStyle::SingleLine { prefix } => {
12017                f.write_str(prefix)?;
12018                f.write_str(&self.prefix)?;
12019                f.write_str("+")?;
12020                f.write_str(&self.text)
12021            }
12022            OptimizerHintStyle::MultiLine => {
12023                f.write_str("/*")?;
12024                f.write_str(&self.prefix)?;
12025                f.write_str("+")?;
12026                f.write_str(&self.text)?;
12027                f.write_str("*/")
12028            }
12029        }
12030    }
12031}
12032
12033impl fmt::Display for ResetStatement {
12034    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
12035        match &self.reset {
12036            Reset::ALL => write!(f, "RESET ALL"),
12037            Reset::ConfigurationParameter(param) => write!(f, "RESET {}", param),
12038        }
12039    }
12040}
12041
12042impl From<Set> for Statement {
12043    fn from(s: Set) -> Self {
12044        Self::Set(s)
12045    }
12046}
12047
12048impl From<Query> for Statement {
12049    fn from(q: Query) -> Self {
12050        Box::new(q).into()
12051    }
12052}
12053
12054impl From<Box<Query>> for Statement {
12055    fn from(q: Box<Query>) -> Self {
12056        Self::Query(q)
12057    }
12058}
12059
12060impl From<Insert> for Statement {
12061    fn from(i: Insert) -> Self {
12062        Self::Insert(i)
12063    }
12064}
12065
12066impl From<Update> for Statement {
12067    fn from(u: Update) -> Self {
12068        Self::Update(u)
12069    }
12070}
12071
12072impl From<CreateView> for Statement {
12073    fn from(cv: CreateView) -> Self {
12074        Self::CreateView(cv)
12075    }
12076}
12077
12078impl From<CreateRole> for Statement {
12079    fn from(cr: CreateRole) -> Self {
12080        Self::CreateRole(cr)
12081    }
12082}
12083
12084impl From<AlterTable> for Statement {
12085    fn from(at: AlterTable) -> Self {
12086        Self::AlterTable(at)
12087    }
12088}
12089
12090impl From<DropFunction> for Statement {
12091    fn from(df: DropFunction) -> Self {
12092        Self::DropFunction(df)
12093    }
12094}
12095
12096impl From<CreateExtension> for Statement {
12097    fn from(ce: CreateExtension) -> Self {
12098        Self::CreateExtension(ce)
12099    }
12100}
12101
12102impl From<CreateCollation> for Statement {
12103    fn from(c: CreateCollation) -> Self {
12104        Self::CreateCollation(c)
12105    }
12106}
12107
12108impl From<DropExtension> for Statement {
12109    fn from(de: DropExtension) -> Self {
12110        Self::DropExtension(de)
12111    }
12112}
12113
12114impl From<CaseStatement> for Statement {
12115    fn from(c: CaseStatement) -> Self {
12116        Self::Case(c)
12117    }
12118}
12119
12120impl From<IfStatement> for Statement {
12121    fn from(i: IfStatement) -> Self {
12122        Self::If(i)
12123    }
12124}
12125
12126impl From<WhileStatement> for Statement {
12127    fn from(w: WhileStatement) -> Self {
12128        Self::While(w)
12129    }
12130}
12131
12132impl From<RaiseStatement> for Statement {
12133    fn from(r: RaiseStatement) -> Self {
12134        Self::Raise(r)
12135    }
12136}
12137
12138impl From<ThrowStatement> for Statement {
12139    fn from(t: ThrowStatement) -> Self {
12140        Self::Throw(t)
12141    }
12142}
12143
12144impl From<Function> for Statement {
12145    fn from(f: Function) -> Self {
12146        Self::Call(f)
12147    }
12148}
12149
12150impl From<OpenStatement> for Statement {
12151    fn from(o: OpenStatement) -> Self {
12152        Self::Open(o)
12153    }
12154}
12155
12156impl From<Delete> for Statement {
12157    fn from(d: Delete) -> Self {
12158        Self::Delete(d)
12159    }
12160}
12161
12162impl From<CreateTable> for Statement {
12163    fn from(c: CreateTable) -> Self {
12164        Self::CreateTable(c)
12165    }
12166}
12167
12168impl From<CreateIndex> for Statement {
12169    fn from(c: CreateIndex) -> Self {
12170        Self::CreateIndex(c)
12171    }
12172}
12173
12174impl From<CreateServerStatement> for Statement {
12175    fn from(c: CreateServerStatement) -> Self {
12176        Self::CreateServer(c)
12177    }
12178}
12179
12180impl From<CreateConnector> for Statement {
12181    fn from(c: CreateConnector) -> Self {
12182        Self::CreateConnector(c)
12183    }
12184}
12185
12186impl From<CreateOperator> for Statement {
12187    fn from(c: CreateOperator) -> Self {
12188        Self::CreateOperator(c)
12189    }
12190}
12191
12192impl From<CreateOperatorFamily> for Statement {
12193    fn from(c: CreateOperatorFamily) -> Self {
12194        Self::CreateOperatorFamily(c)
12195    }
12196}
12197
12198impl From<CreateOperatorClass> for Statement {
12199    fn from(c: CreateOperatorClass) -> Self {
12200        Self::CreateOperatorClass(c)
12201    }
12202}
12203
12204impl From<AlterSchema> for Statement {
12205    fn from(a: AlterSchema) -> Self {
12206        Self::AlterSchema(a)
12207    }
12208}
12209
12210impl From<AlterFunction> for Statement {
12211    fn from(a: AlterFunction) -> Self {
12212        Self::AlterFunction(a)
12213    }
12214}
12215
12216impl From<AlterType> for Statement {
12217    fn from(a: AlterType) -> Self {
12218        Self::AlterType(a)
12219    }
12220}
12221
12222impl From<AlterCollation> for Statement {
12223    fn from(a: AlterCollation) -> Self {
12224        Self::AlterCollation(a)
12225    }
12226}
12227
12228impl From<AlterOperator> for Statement {
12229    fn from(a: AlterOperator) -> Self {
12230        Self::AlterOperator(a)
12231    }
12232}
12233
12234impl From<AlterOperatorFamily> for Statement {
12235    fn from(a: AlterOperatorFamily) -> Self {
12236        Self::AlterOperatorFamily(a)
12237    }
12238}
12239
12240impl From<AlterOperatorClass> for Statement {
12241    fn from(a: AlterOperatorClass) -> Self {
12242        Self::AlterOperatorClass(a)
12243    }
12244}
12245
12246impl From<Merge> for Statement {
12247    fn from(m: Merge) -> Self {
12248        Self::Merge(m)
12249    }
12250}
12251
12252impl From<AlterUser> for Statement {
12253    fn from(a: AlterUser) -> Self {
12254        Self::AlterUser(a)
12255    }
12256}
12257
12258impl From<DropDomain> for Statement {
12259    fn from(d: DropDomain) -> Self {
12260        Self::DropDomain(d)
12261    }
12262}
12263
12264impl From<ShowCharset> for Statement {
12265    fn from(s: ShowCharset) -> Self {
12266        Self::ShowCharset(s)
12267    }
12268}
12269
12270impl From<ShowObjects> for Statement {
12271    fn from(s: ShowObjects) -> Self {
12272        Self::ShowObjects(s)
12273    }
12274}
12275
12276impl From<Use> for Statement {
12277    fn from(u: Use) -> Self {
12278        Self::Use(u)
12279    }
12280}
12281
12282impl From<CreateFunction> for Statement {
12283    fn from(c: CreateFunction) -> Self {
12284        Self::CreateFunction(c)
12285    }
12286}
12287
12288impl From<CreateTrigger> for Statement {
12289    fn from(c: CreateTrigger) -> Self {
12290        Self::CreateTrigger(c)
12291    }
12292}
12293
12294impl From<DropTrigger> for Statement {
12295    fn from(d: DropTrigger) -> Self {
12296        Self::DropTrigger(d)
12297    }
12298}
12299
12300impl From<DropOperator> for Statement {
12301    fn from(d: DropOperator) -> Self {
12302        Self::DropOperator(d)
12303    }
12304}
12305
12306impl From<DropOperatorFamily> for Statement {
12307    fn from(d: DropOperatorFamily) -> Self {
12308        Self::DropOperatorFamily(d)
12309    }
12310}
12311
12312impl From<DropOperatorClass> for Statement {
12313    fn from(d: DropOperatorClass) -> Self {
12314        Self::DropOperatorClass(d)
12315    }
12316}
12317
12318impl From<DenyStatement> for Statement {
12319    fn from(d: DenyStatement) -> Self {
12320        Self::Deny(d)
12321    }
12322}
12323
12324impl From<CreateDomain> for Statement {
12325    fn from(c: CreateDomain) -> Self {
12326        Self::CreateDomain(c)
12327    }
12328}
12329
12330impl From<RenameTable> for Statement {
12331    fn from(r: RenameTable) -> Self {
12332        vec![r].into()
12333    }
12334}
12335
12336impl From<Vec<RenameTable>> for Statement {
12337    fn from(r: Vec<RenameTable>) -> Self {
12338        Self::RenameTable(r)
12339    }
12340}
12341
12342impl From<PrintStatement> for Statement {
12343    fn from(p: PrintStatement) -> Self {
12344        Self::Print(p)
12345    }
12346}
12347
12348impl From<ReturnStatement> for Statement {
12349    fn from(r: ReturnStatement) -> Self {
12350        Self::Return(r)
12351    }
12352}
12353
12354impl From<ExportData> for Statement {
12355    fn from(e: ExportData) -> Self {
12356        Self::ExportData(e)
12357    }
12358}
12359
12360impl From<CreateUser> for Statement {
12361    fn from(c: CreateUser) -> Self {
12362        Self::CreateUser(c)
12363    }
12364}
12365
12366impl From<VacuumStatement> for Statement {
12367    fn from(v: VacuumStatement) -> Self {
12368        Self::Vacuum(v)
12369    }
12370}
12371
12372impl From<ResetStatement> for Statement {
12373    fn from(r: ResetStatement) -> Self {
12374        Self::Reset(r)
12375    }
12376}
12377
12378#[cfg(test)]
12379mod tests {
12380    use crate::tokenizer::Location;
12381
12382    use super::*;
12383
12384    #[test]
12385    fn test_window_frame_default() {
12386        let window_frame = WindowFrame::default();
12387        assert_eq!(WindowFrameBound::Preceding(None), window_frame.start_bound);
12388    }
12389
12390    #[test]
12391    fn test_grouping_sets_display() {
12392        // a and b in different group
12393        let grouping_sets = Expr::GroupingSets(vec![
12394            vec![Expr::Identifier(Ident::new("a"))],
12395            vec![Expr::Identifier(Ident::new("b"))],
12396        ]);
12397        assert_eq!("GROUPING SETS ((a), (b))", format!("{grouping_sets}"));
12398
12399        // a and b in the same group
12400        let grouping_sets = Expr::GroupingSets(vec![vec![
12401            Expr::Identifier(Ident::new("a")),
12402            Expr::Identifier(Ident::new("b")),
12403        ]]);
12404        assert_eq!("GROUPING SETS ((a, b))", format!("{grouping_sets}"));
12405
12406        // (a, b) and (c, d) in different group
12407        let grouping_sets = Expr::GroupingSets(vec![
12408            vec![
12409                Expr::Identifier(Ident::new("a")),
12410                Expr::Identifier(Ident::new("b")),
12411            ],
12412            vec![
12413                Expr::Identifier(Ident::new("c")),
12414                Expr::Identifier(Ident::new("d")),
12415            ],
12416        ]);
12417        assert_eq!("GROUPING SETS ((a, b), (c, d))", format!("{grouping_sets}"));
12418    }
12419
12420    #[test]
12421    fn test_rollup_display() {
12422        let rollup = Expr::Rollup(vec![vec![Expr::Identifier(Ident::new("a"))]]);
12423        assert_eq!("ROLLUP (a)", format!("{rollup}"));
12424
12425        let rollup = Expr::Rollup(vec![vec![
12426            Expr::Identifier(Ident::new("a")),
12427            Expr::Identifier(Ident::new("b")),
12428        ]]);
12429        assert_eq!("ROLLUP ((a, b))", format!("{rollup}"));
12430
12431        let rollup = Expr::Rollup(vec![
12432            vec![Expr::Identifier(Ident::new("a"))],
12433            vec![Expr::Identifier(Ident::new("b"))],
12434        ]);
12435        assert_eq!("ROLLUP (a, b)", format!("{rollup}"));
12436
12437        let rollup = Expr::Rollup(vec![
12438            vec![Expr::Identifier(Ident::new("a"))],
12439            vec![
12440                Expr::Identifier(Ident::new("b")),
12441                Expr::Identifier(Ident::new("c")),
12442            ],
12443            vec![Expr::Identifier(Ident::new("d"))],
12444        ]);
12445        assert_eq!("ROLLUP (a, (b, c), d)", format!("{rollup}"));
12446    }
12447
12448    #[test]
12449    fn test_cube_display() {
12450        let cube = Expr::Cube(vec![vec![Expr::Identifier(Ident::new("a"))]]);
12451        assert_eq!("CUBE (a)", format!("{cube}"));
12452
12453        let cube = Expr::Cube(vec![vec![
12454            Expr::Identifier(Ident::new("a")),
12455            Expr::Identifier(Ident::new("b")),
12456        ]]);
12457        assert_eq!("CUBE ((a, b))", format!("{cube}"));
12458
12459        let cube = Expr::Cube(vec![
12460            vec![Expr::Identifier(Ident::new("a"))],
12461            vec![Expr::Identifier(Ident::new("b"))],
12462        ]);
12463        assert_eq!("CUBE (a, b)", format!("{cube}"));
12464
12465        let cube = Expr::Cube(vec![
12466            vec![Expr::Identifier(Ident::new("a"))],
12467            vec![
12468                Expr::Identifier(Ident::new("b")),
12469                Expr::Identifier(Ident::new("c")),
12470            ],
12471            vec![Expr::Identifier(Ident::new("d"))],
12472        ]);
12473        assert_eq!("CUBE (a, (b, c), d)", format!("{cube}"));
12474    }
12475
12476    #[test]
12477    fn test_interval_display() {
12478        let interval = Expr::Interval(Interval {
12479            value: Box::new(Expr::Value(
12480                Value::SingleQuotedString(String::from("123:45.67")).with_empty_span(),
12481            )),
12482            leading_field: Some(DateTimeField::Minute),
12483            leading_precision: Some(10),
12484            last_field: Some(DateTimeField::Second),
12485            fractional_seconds_precision: Some(9),
12486        });
12487        assert_eq!(
12488            "INTERVAL '123:45.67' MINUTE (10) TO SECOND (9)",
12489            format!("{interval}"),
12490        );
12491
12492        let interval = Expr::Interval(Interval {
12493            value: Box::new(Expr::Value(
12494                Value::SingleQuotedString(String::from("5")).with_empty_span(),
12495            )),
12496            leading_field: Some(DateTimeField::Second),
12497            leading_precision: Some(1),
12498            last_field: None,
12499            fractional_seconds_precision: Some(3),
12500        });
12501        assert_eq!("INTERVAL '5' SECOND (1, 3)", format!("{interval}"));
12502    }
12503
12504    #[test]
12505    fn test_one_or_many_with_parens_deref() {
12506        use core::ops::Index;
12507
12508        let one = OneOrManyWithParens::One("a");
12509
12510        assert_eq!(one.deref(), &["a"]);
12511        assert_eq!(<OneOrManyWithParens<_> as Deref>::deref(&one), &["a"]);
12512
12513        assert_eq!(one[0], "a");
12514        assert_eq!(one.index(0), &"a");
12515        assert_eq!(
12516            <<OneOrManyWithParens<_> as Deref>::Target as Index<usize>>::index(&one, 0),
12517            &"a"
12518        );
12519
12520        assert_eq!(one.len(), 1);
12521        assert_eq!(<OneOrManyWithParens<_> as Deref>::Target::len(&one), 1);
12522
12523        let many1 = OneOrManyWithParens::Many(vec!["b"]);
12524
12525        assert_eq!(many1.deref(), &["b"]);
12526        assert_eq!(<OneOrManyWithParens<_> as Deref>::deref(&many1), &["b"]);
12527
12528        assert_eq!(many1[0], "b");
12529        assert_eq!(many1.index(0), &"b");
12530        assert_eq!(
12531            <<OneOrManyWithParens<_> as Deref>::Target as Index<usize>>::index(&many1, 0),
12532            &"b"
12533        );
12534
12535        assert_eq!(many1.len(), 1);
12536        assert_eq!(<OneOrManyWithParens<_> as Deref>::Target::len(&many1), 1);
12537
12538        let many2 = OneOrManyWithParens::Many(vec!["c", "d"]);
12539
12540        assert_eq!(many2.deref(), &["c", "d"]);
12541        assert_eq!(
12542            <OneOrManyWithParens<_> as Deref>::deref(&many2),
12543            &["c", "d"]
12544        );
12545
12546        assert_eq!(many2[0], "c");
12547        assert_eq!(many2.index(0), &"c");
12548        assert_eq!(
12549            <<OneOrManyWithParens<_> as Deref>::Target as Index<usize>>::index(&many2, 0),
12550            &"c"
12551        );
12552
12553        assert_eq!(many2[1], "d");
12554        assert_eq!(many2.index(1), &"d");
12555        assert_eq!(
12556            <<OneOrManyWithParens<_> as Deref>::Target as Index<usize>>::index(&many2, 1),
12557            &"d"
12558        );
12559
12560        assert_eq!(many2.len(), 2);
12561        assert_eq!(<OneOrManyWithParens<_> as Deref>::Target::len(&many2), 2);
12562    }
12563
12564    #[test]
12565    fn test_one_or_many_with_parens_as_ref() {
12566        let one = OneOrManyWithParens::One("a");
12567
12568        assert_eq!(one.as_ref(), &["a"]);
12569        assert_eq!(<OneOrManyWithParens<_> as AsRef<_>>::as_ref(&one), &["a"]);
12570
12571        let many1 = OneOrManyWithParens::Many(vec!["b"]);
12572
12573        assert_eq!(many1.as_ref(), &["b"]);
12574        assert_eq!(<OneOrManyWithParens<_> as AsRef<_>>::as_ref(&many1), &["b"]);
12575
12576        let many2 = OneOrManyWithParens::Many(vec!["c", "d"]);
12577
12578        assert_eq!(many2.as_ref(), &["c", "d"]);
12579        assert_eq!(
12580            <OneOrManyWithParens<_> as AsRef<_>>::as_ref(&many2),
12581            &["c", "d"]
12582        );
12583    }
12584
12585    #[test]
12586    fn test_one_or_many_with_parens_ref_into_iter() {
12587        let one = OneOrManyWithParens::One("a");
12588
12589        assert_eq!(Vec::from_iter(&one), vec![&"a"]);
12590
12591        let many1 = OneOrManyWithParens::Many(vec!["b"]);
12592
12593        assert_eq!(Vec::from_iter(&many1), vec![&"b"]);
12594
12595        let many2 = OneOrManyWithParens::Many(vec!["c", "d"]);
12596
12597        assert_eq!(Vec::from_iter(&many2), vec![&"c", &"d"]);
12598    }
12599
12600    #[test]
12601    fn test_one_or_many_with_parens_value_into_iter() {
12602        use core::iter::once;
12603
12604        //tests that our iterator implemented methods behaves exactly as it's inner iterator, at every step up to n calls to next/next_back
12605        fn test_steps<I>(ours: OneOrManyWithParens<usize>, inner: I, n: usize)
12606        where
12607            I: IntoIterator<Item = usize, IntoIter: DoubleEndedIterator + Clone> + Clone,
12608        {
12609            fn checks<I>(ours: OneOrManyWithParensIntoIter<usize>, inner: I)
12610            where
12611                I: Iterator<Item = usize> + Clone + DoubleEndedIterator,
12612            {
12613                assert_eq!(ours.size_hint(), inner.size_hint());
12614                assert_eq!(ours.clone().count(), inner.clone().count());
12615
12616                assert_eq!(
12617                    ours.clone().fold(1, |a, v| a + v),
12618                    inner.clone().fold(1, |a, v| a + v)
12619                );
12620
12621                assert_eq!(Vec::from_iter(ours.clone()), Vec::from_iter(inner.clone()));
12622                assert_eq!(
12623                    Vec::from_iter(ours.clone().rev()),
12624                    Vec::from_iter(inner.clone().rev())
12625                );
12626            }
12627
12628            let mut ours_next = ours.clone().into_iter();
12629            let mut inner_next = inner.clone().into_iter();
12630
12631            for _ in 0..n {
12632                checks(ours_next.clone(), inner_next.clone());
12633
12634                assert_eq!(ours_next.next(), inner_next.next());
12635            }
12636
12637            let mut ours_next_back = ours.clone().into_iter();
12638            let mut inner_next_back = inner.clone().into_iter();
12639
12640            for _ in 0..n {
12641                checks(ours_next_back.clone(), inner_next_back.clone());
12642
12643                assert_eq!(ours_next_back.next_back(), inner_next_back.next_back());
12644            }
12645
12646            let mut ours_mixed = ours.clone().into_iter();
12647            let mut inner_mixed = inner.clone().into_iter();
12648
12649            for i in 0..n {
12650                checks(ours_mixed.clone(), inner_mixed.clone());
12651
12652                if i % 2 == 0 {
12653                    assert_eq!(ours_mixed.next_back(), inner_mixed.next_back());
12654                } else {
12655                    assert_eq!(ours_mixed.next(), inner_mixed.next());
12656                }
12657            }
12658
12659            let mut ours_mixed2 = ours.into_iter();
12660            let mut inner_mixed2 = inner.into_iter();
12661
12662            for i in 0..n {
12663                checks(ours_mixed2.clone(), inner_mixed2.clone());
12664
12665                if i % 2 == 0 {
12666                    assert_eq!(ours_mixed2.next(), inner_mixed2.next());
12667                } else {
12668                    assert_eq!(ours_mixed2.next_back(), inner_mixed2.next_back());
12669                }
12670            }
12671        }
12672
12673        test_steps(OneOrManyWithParens::One(1), once(1), 3);
12674        test_steps(OneOrManyWithParens::Many(vec![2]), vec![2], 3);
12675        test_steps(OneOrManyWithParens::Many(vec![3, 4]), vec![3, 4], 4);
12676    }
12677
12678    // Tests that the position in the code of an `Ident` does not affect its
12679    // ordering.
12680    #[test]
12681    fn test_ident_ord() {
12682        let mut a = Ident::with_span(Span::new(Location::new(1, 1), Location::new(1, 1)), "a");
12683        let mut b = Ident::with_span(Span::new(Location::new(2, 2), Location::new(2, 2)), "b");
12684
12685        assert!(a < b);
12686        std::mem::swap(&mut a.span, &mut b.span);
12687        assert!(a < b);
12688    }
12689}