Skip to main content

sqlparser/ast/
mod.rs

1// Licensed to the Apache Software Foundation (ASF) under one
2// or more contributor license agreements.  See the NOTICE file
3// distributed with this work for additional information
4// regarding copyright ownership.  The ASF licenses this file
5// to you under the Apache License, Version 2.0 (the
6// "License"); you may not use this file except in compliance
7// with the License.  You may obtain a copy of the License at
8//
9//   http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing,
12// software distributed under the License is distributed on an
13// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14// KIND, either express or implied.  See the License for the
15// specific language governing permissions and limitations
16// under the License.
17
18//! SQL Abstract Syntax Tree (AST) types
19#[cfg(not(feature = "std"))]
20use alloc::{
21    boxed::Box,
22    format,
23    string::{String, ToString},
24    vec,
25    vec::Vec,
26};
27use helpers::{
28    attached_token::AttachedToken,
29    stmt_data_loading::{FileStagingCommand, StageLoadSelectItemKind},
30};
31
32use core::cmp::Ordering;
33use core::ops::{Deref, DerefMut};
34use core::{
35    fmt::{self, Display},
36    hash,
37};
38
39#[cfg(feature = "serde")]
40use serde::{Deserialize, Serialize};
41
42#[cfg(feature = "visitor")]
43use core::ops::ControlFlow;
44#[cfg(feature = "visitor")]
45use sqlparser_derive::{Visit, VisitMut};
46
47use crate::{
48    display_utils::SpaceOrNewline,
49    tokenizer::{Span, Token},
50};
51use crate::{
52    display_utils::{Indent, NewLine},
53    keywords::Keyword,
54};
55
56pub use self::data_type::{
57    ArrayElemTypeDef, BinaryLength, CharLengthUnits, CharacterLength, DataType, EnumMember,
58    ExactNumberInfo, IntervalFields, MapBracketKind, StructBracketKind, TimezoneInfo,
59};
60pub use self::dcl::{
61    AlterRoleOperation, CreateRole, Grant, ResetConfig, Revoke, RoleOption, SecondaryRoles,
62    SetConfigValue, Use,
63};
64pub use self::ddl::{
65    Alignment, AlterCollation, AlterCollationOperation, AlterColumnOperation, AlterConnectorOwner,
66    AlterFunction, AlterFunctionAction, AlterFunctionKind, AlterFunctionOperation,
67    AlterIndexOperation, AlterOperator, AlterOperatorClass, AlterOperatorClassOperation,
68    AlterOperatorFamily, AlterOperatorFamilyOperation, AlterOperatorOperation, AlterPolicy,
69    AlterPolicyOperation, AlterSchema, AlterSchemaOperation, AlterTable, AlterTableAlgorithm,
70    AlterTableLock, AlterTableOperation, AlterTableType, AlterTextSearch, AlterTextSearchOperation,
71    AlterTextSearchOption, AlterType, AlterTypeAddValue, AlterTypeAddValuePosition,
72    AlterTypeOperation, AlterTypeRename, AlterTypeRenameValue, ClusteredBy, ColumnDef,
73    ColumnOption, ColumnOptionDef, ColumnOptions, ColumnPolicy, ColumnPolicyProperty,
74    ConstraintCharacteristics, CreateCollation, CreateCollationDefinition, CreateConnector,
75    CreateDomain, CreateExtension, CreateForeignTable, CreateFunction, CreateIndex, CreateOperator,
76    CreateOperatorClass, CreateOperatorFamily, CreatePolicy, CreatePolicyCommand, CreatePolicyType,
77    CreateTable, CreateTextSearch, CreateTrigger, CreateView, Deduplicate, DeferrableInitial,
78    DistStyle, DropBehavior, DropExtension, DropFunction, DropOperator, DropOperatorClass,
79    DropOperatorFamily, DropOperatorSignature, DropPolicy, DropTrigger, ForValues,
80    FunctionReturnType, GeneratedAs, GeneratedExpressionMode, IdentityParameters, IdentityProperty,
81    IdentityPropertyFormatKind, IdentityPropertyKind, IdentityPropertyOrder, IndexColumn,
82    IndexOption, IndexType, KeyOrIndexDisplay, Msck, NullsDistinctOption, OperatorArgTypes,
83    OperatorClassItem, OperatorFamilyDropItem, OperatorFamilyItem, OperatorOption, OperatorPurpose,
84    Owner, Partition, PartitionBoundValue, ProcedureParam, ReferentialAction, RenameTableNameKind,
85    ReplicaIdentity, TagsColumnOption, TextSearchObjectType, TriggerObjectKind, Truncate,
86    UserDefinedTypeCompositeAttributeDef, UserDefinedTypeInternalLength,
87    UserDefinedTypeRangeOption, UserDefinedTypeRepresentation, UserDefinedTypeSqlDefinitionOption,
88    UserDefinedTypeStorage, ViewColumnDef, WithData,
89};
90pub use self::dml::{
91    Delete, Insert, Merge, MergeAction, MergeClause, MergeClauseKind, MergeInsertExpr,
92    MergeInsertKind, MergeUpdateExpr, MergeUpdateKind, MultiTableInsertIntoClause,
93    MultiTableInsertType, MultiTableInsertValue, MultiTableInsertValues,
94    MultiTableInsertWhenClause, OutputClause, Update,
95};
96pub use self::operator::{BinaryOperator, UnaryOperator};
97pub use self::procedural::{
98    DoStatement, PlPgSqlBlock, PlPgSqlDeclaration, PlPgSqlIfBranch, PlPgSqlStatement,
99};
100pub use self::query::{
101    AfterMatchSkip, ConnectByKind, Cte, CteAsMaterialized, Distinct, EmptyMatchesMode,
102    ExceptSelectItem, ExcludeSelectItem, ExprWithAlias, ExprWithAliasAndOrderBy, Fetch, ForClause,
103    ForJson, ForXml, FormatClause, GroupByExpr, GroupByWithModifier, IdentWithAlias,
104    IlikeSelectItem, InputFormatClause, Interpolate, InterpolateExpr, Join, JoinConstraint,
105    JoinOperator, JsonTableColumn, JsonTableColumnErrorHandling, JsonTableNamedColumn,
106    JsonTableNestedColumn, LateralView, LimitClause, LockClause, LockType, MatchRecognizePattern,
107    MatchRecognizeSymbol, Measure, NamedWindowDefinition, NamedWindowExpr, NonBlock, Offset,
108    OffsetRows, OpenJsonTableColumn, OrderBy, OrderByExpr, OrderByKind, OrderByOptions,
109    OrderBySort, PipeOperator, PivotValueSource, ProjectionSelect, Query, RenameSelectItem,
110    RepetitionQuantifier, ReplaceSelectElement, ReplaceSelectItem, RowsPerMatch, Select,
111    SelectFlavor, SelectInto, SelectItem, SelectItemQualifiedWildcardKind, SelectModifiers,
112    SetExpr, SetOperator, SetQuantifier, Setting, SymbolDefinition, Table, TableAlias,
113    TableAliasColumnDef, TableFactor, TableFunctionArgs, TableIndexHintForClause,
114    TableIndexHintType, TableIndexHints, TableIndexType, TableSample, TableSampleBucket,
115    TableSampleKind, TableSampleMethod, TableSampleModifier, TableSampleQuantity, TableSampleSeed,
116    TableSampleSeedModifier, TableSampleUnit, TableVersion, TableWithJoins, Top, TopQuantity,
117    UpdateTableFromKind, ValueTableMode, Values, WildcardAdditionalOptions, With, WithFill,
118    XmlNamespaceDefinition, XmlPassingArgument, XmlPassingClause, XmlTableColumn,
119    XmlTableColumnOption,
120};
121
122pub use self::trigger::{
123    TriggerEvent, TriggerExecBody, TriggerExecBodyType, TriggerObject, TriggerPeriod,
124    TriggerReferencing, TriggerReferencingType,
125};
126
127pub use self::value::{
128    escape_double_quote_string, escape_quoted_string, DateTimeField, DollarQuotedString,
129    NormalizationForm, QuoteDelimitedString, TrimWhereField, Value, ValueWithSpan,
130};
131
132use crate::ast::helpers::key_value_options::KeyValueOptions;
133use crate::ast::helpers::stmt_data_loading::StageParamsObject;
134
135#[cfg(feature = "visitor")]
136pub use visitor::*;
137
138pub use self::data_type::GeometricTypeKind;
139
140mod data_type;
141mod dcl;
142mod ddl;
143mod dml;
144/// Helper modules for building and manipulating AST nodes.
145pub mod helpers;
146pub mod table_constraints;
147pub use table_constraints::{
148    CheckConstraint, ConstraintUsingIndex, ExcludeConstraint, ExcludeConstraintElement,
149    ExcludeConstraintOperator, ForeignKeyConstraint, FullTextOrSpatialConstraint, IndexConstraint,
150    PrimaryKeyConstraint, TableConstraint, UniqueConstraint,
151};
152mod operator;
153mod procedural;
154mod query;
155mod spans;
156pub use spans::Spanned;
157
158pub mod comments;
159mod trigger;
160mod value;
161
162#[cfg(feature = "visitor")]
163mod visitor;
164
165/// Helper used to format a slice using a separator string (e.g., `", "`).
166pub struct DisplaySeparated<'a, T>
167where
168    T: fmt::Display,
169{
170    slice: &'a [T],
171    sep: &'static str,
172}
173
174impl<T> fmt::Display for DisplaySeparated<'_, T>
175where
176    T: fmt::Display,
177{
178    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
179        let mut delim = "";
180        for t in self.slice {
181            f.write_str(delim)?;
182            delim = self.sep;
183            t.fmt(f)?;
184        }
185        Ok(())
186    }
187}
188
189pub(crate) fn display_separated<'a, T>(slice: &'a [T], sep: &'static str) -> DisplaySeparated<'a, T>
190where
191    T: fmt::Display,
192{
193    DisplaySeparated { slice, sep }
194}
195
196pub(crate) fn display_comma_separated<T>(slice: &[T]) -> DisplaySeparated<'_, T>
197where
198    T: fmt::Display,
199{
200    DisplaySeparated { slice, sep: ", " }
201}
202
203/// Writes the given statements to the formatter, each ending with
204/// a semicolon and space separated.
205fn format_statement_list(f: &mut fmt::Formatter, statements: &[Statement]) -> fmt::Result {
206    write!(f, "{}", display_separated(statements, "; "))?;
207    // We manually insert semicolon for the last statement,
208    // since display_separated doesn't handle that case.
209    write!(f, ";")
210}
211
212/// A item `T` enclosed in a pair of parentheses
213#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
214#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
215#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
216pub struct Parens<T> {
217    /// the opening parenthesis token, i.e. `(`
218    pub opening_token: AttachedToken,
219    /// content enclosed in parentheses
220    pub content: T,
221    /// the closing parenthesis token, i.e. `)`
222    pub closing_token: AttachedToken,
223}
224
225impl<T> Parens<T> {
226    /// Constructor wrapping `content` into `Parens` with an empty span;
227    /// useful for testing purposes.
228    pub fn with_empty_span(content: T) -> Self {
229        Self {
230            opening_token: AttachedToken::empty(),
231            content,
232            closing_token: AttachedToken::empty(),
233        }
234    }
235}
236
237impl<T> Deref for Parens<T> {
238    type Target = T;
239
240    fn deref(&self) -> &Self::Target {
241        &self.content
242    }
243}
244
245impl<T> DerefMut for Parens<T> {
246    fn deref_mut(&mut self) -> &mut Self::Target {
247        &mut self.content
248    }
249}
250
251/// An identifier, decomposed into its value or character data and the quote style.
252#[derive(Debug, Clone)]
253#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
254pub struct Ident {
255    /// The value of the identifier without quotes.
256    pub value: String,
257    /// The starting quote if any. Valid quote characters are the single quote,
258    /// double quote, backtick, and opening square bracket.
259    pub quote_style: Option<char>,
260    /// The span of the identifier in the original SQL string.
261    pub span: Span,
262}
263
264impl PartialEq for Ident {
265    fn eq(&self, other: &Self) -> bool {
266        let Ident {
267            value,
268            quote_style,
269            // exhaustiveness check; we ignore spans in comparisons
270            span: _,
271        } = self;
272
273        value == &other.value && quote_style == &other.quote_style
274    }
275}
276
277impl core::hash::Hash for Ident {
278    fn hash<H: hash::Hasher>(&self, state: &mut H) {
279        let Ident {
280            value,
281            quote_style,
282            // exhaustiveness check; we ignore spans in hashes
283            span: _,
284        } = self;
285
286        value.hash(state);
287        quote_style.hash(state);
288    }
289}
290
291impl Eq for Ident {}
292
293impl PartialOrd for Ident {
294    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
295        Some(self.cmp(other))
296    }
297}
298
299impl Ord for Ident {
300    fn cmp(&self, other: &Self) -> Ordering {
301        let Ident {
302            value,
303            quote_style,
304            // exhaustiveness check; we ignore spans in ordering
305            span: _,
306        } = self;
307
308        let Ident {
309            value: other_value,
310            quote_style: other_quote_style,
311            // exhaustiveness check; we ignore spans in ordering
312            span: _,
313        } = other;
314
315        // First compare by value, then by quote_style
316        value
317            .cmp(other_value)
318            .then_with(|| quote_style.cmp(other_quote_style))
319    }
320}
321
322impl Ident {
323    /// Create a new identifier with the given value and no quotes and an empty span.
324    pub fn new<S>(value: S) -> Self
325    where
326        S: Into<String>,
327    {
328        Ident {
329            value: value.into(),
330            quote_style: None,
331            span: Span::empty(),
332        }
333    }
334
335    /// Create a new quoted identifier with the given quote and value. This function
336    /// panics if the given quote is not a valid quote character.
337    pub fn with_quote<S>(quote: char, value: S) -> Self
338    where
339        S: Into<String>,
340    {
341        assert!(quote == '\'' || quote == '"' || quote == '`' || quote == '[');
342        Ident {
343            value: value.into(),
344            quote_style: Some(quote),
345            span: Span::empty(),
346        }
347    }
348
349    /// Create an `Ident` with the given `span` and `value` (unquoted).
350    pub fn with_span<S>(span: Span, value: S) -> Self
351    where
352        S: Into<String>,
353    {
354        Ident {
355            value: value.into(),
356            quote_style: None,
357            span,
358        }
359    }
360
361    /// Create a quoted `Ident` with the given `quote` and `span`.
362    pub fn with_quote_and_span<S>(quote: char, span: Span, value: S) -> Self
363    where
364        S: Into<String>,
365    {
366        assert!(quote == '\'' || quote == '"' || quote == '`' || quote == '[');
367        Ident {
368            value: value.into(),
369            quote_style: Some(quote),
370            span,
371        }
372    }
373}
374
375impl From<&str> for Ident {
376    fn from(value: &str) -> Self {
377        Ident {
378            value: value.to_string(),
379            quote_style: None,
380            span: Span::empty(),
381        }
382    }
383}
384
385pub(crate) fn fmt_ident(
386    f: &mut fmt::Formatter,
387    value: &str,
388    quote_style: Option<char>,
389) -> fmt::Result {
390    match quote_style {
391        Some('[') => write!(f, "[{value}]"),
392        Some(q) => {
393            let escaped = value::escape_quoted_string(value, q);
394            write!(f, "{q}{escaped}{q}")
395        }
396        None => f.write_str(value),
397    }
398}
399
400impl fmt::Display for Ident {
401    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
402        fmt_ident(f, &self.value, self.quote_style)
403    }
404}
405
406#[cfg(feature = "visitor")]
407impl Visit for Ident {
408    fn visit<V: Visitor>(&self, visitor: &mut V) -> ControlFlow<V::Break> {
409        visitor.pre_visit_ident(self)?;
410        visitor.post_visit_ident(self)
411    }
412}
413
414#[cfg(feature = "visitor")]
415impl VisitMut for Ident {
416    fn visit<V: VisitorMut>(&mut self, visitor: &mut V) -> ControlFlow<V::Break> {
417        visitor.pre_visit_ident(self)?;
418        visitor.post_visit_ident(self)
419    }
420}
421
422/// A name of a table, view, custom type, etc., possibly multi-part, i.e. db.schema.obj
423#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
424#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
425#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
426pub struct ObjectName(pub Vec<ObjectNamePart>);
427
428impl From<Vec<Ident>> for ObjectName {
429    fn from(idents: Vec<Ident>) -> Self {
430        ObjectName(idents.into_iter().map(ObjectNamePart::Identifier).collect())
431    }
432}
433
434impl From<Ident> for ObjectName {
435    fn from(ident: Ident) -> Self {
436        ObjectName(vec![ObjectNamePart::Identifier(ident)])
437    }
438}
439
440impl fmt::Display for ObjectName {
441    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
442        write!(f, "{}", display_separated(&self.0, "."))
443    }
444}
445
446/// A single part of an ObjectName
447#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
448#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
449#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
450pub enum ObjectNamePart {
451    /// A single identifier part, e.g. `schema` or `table`.
452    Identifier(Ident),
453    /// A function that returns an identifier (dialect-specific).
454    Function(ObjectNamePartFunction),
455}
456
457impl ObjectNamePart {
458    /// Return the identifier if this is an `Identifier` variant.
459    pub fn as_ident(&self) -> Option<&Ident> {
460        match self {
461            ObjectNamePart::Identifier(ident) => Some(ident),
462            ObjectNamePart::Function(_) => None,
463        }
464    }
465}
466
467impl fmt::Display for ObjectNamePart {
468    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
469        match self {
470            ObjectNamePart::Identifier(ident) => write!(f, "{ident}"),
471            ObjectNamePart::Function(func) => write!(f, "{func}"),
472        }
473    }
474}
475
476/// An object name part that consists of a function that dynamically
477/// constructs identifiers.
478///
479/// - [Snowflake](https://docs.snowflake.com/en/sql-reference/identifier-literal)
480#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
481#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
482#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
483pub struct ObjectNamePartFunction {
484    /// The function name that produces the object name part.
485    pub name: Ident,
486    /// Function arguments used to compute the identifier.
487    pub args: Vec<FunctionArg>,
488}
489
490impl fmt::Display for ObjectNamePartFunction {
491    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
492        write!(f, "{}(", self.name)?;
493        write!(f, "{})", display_comma_separated(&self.args))
494    }
495}
496
497/// Represents an Array Expression, either
498/// `ARRAY[..]`, or `[..]`
499#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
500#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
501#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
502pub struct Array {
503    /// The list of expressions between brackets
504    pub elem: Vec<Expr>,
505
506    /// `true` for  `ARRAY[..]`, `false` for `[..]`
507    pub named: bool,
508}
509
510impl fmt::Display for Array {
511    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
512        write!(
513            f,
514            "{}[{}]",
515            if self.named { "ARRAY" } else { "" },
516            display_comma_separated(&self.elem)
517        )
518    }
519}
520
521/// Represents an INTERVAL expression, roughly in the following format:
522/// `INTERVAL '<value>' [ <leading_field> [ (<leading_precision>) ] ]
523/// [ TO <last_field> [ (<fractional_seconds_precision>) ] ]`,
524/// e.g. `INTERVAL '123:45.67' MINUTE(3) TO SECOND(2)`.
525///
526/// The parser does not validate the `<value>`, nor does it ensure
527/// that the `<leading_field>` units >= the units in `<last_field>`,
528/// so the user will have to reject intervals like `HOUR TO YEAR`.
529#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
530#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
531#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
532pub struct Interval {
533    /// The interval value expression (commonly a string literal).
534    pub value: Box<Expr>,
535    /// Optional leading time unit (e.g., `HOUR`, `MINUTE`).
536    pub leading_field: Option<DateTimeField>,
537    /// Optional leading precision for the leading field.
538    pub leading_precision: Option<u64>,
539    /// Optional trailing time unit for a range (e.g., `SECOND`).
540    pub last_field: Option<DateTimeField>,
541    /// The fractional seconds precision, when specified.
542    ///
543    /// See SQL `SECOND(n)` or `SECOND(m, n)` forms.
544    pub fractional_seconds_precision: Option<u64>,
545}
546
547impl fmt::Display for Interval {
548    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
549        let value = self.value.as_ref();
550        match (
551            &self.leading_field,
552            self.leading_precision,
553            self.fractional_seconds_precision,
554        ) {
555            (
556                Some(DateTimeField::Second),
557                Some(leading_precision),
558                Some(fractional_seconds_precision),
559            ) => {
560                // When the leading field is SECOND, the parser guarantees that
561                // the last field is None.
562                assert!(self.last_field.is_none());
563                write!(
564                    f,
565                    "INTERVAL {value} SECOND ({leading_precision}, {fractional_seconds_precision})"
566                )
567            }
568            _ => {
569                write!(f, "INTERVAL {value}")?;
570                if let Some(leading_field) = &self.leading_field {
571                    write!(f, " {leading_field}")?;
572                }
573                if let Some(leading_precision) = self.leading_precision {
574                    write!(f, " ({leading_precision})")?;
575                }
576                if let Some(last_field) = &self.last_field {
577                    write!(f, " TO {last_field}")?;
578                }
579                if let Some(fractional_seconds_precision) = self.fractional_seconds_precision {
580                    write!(f, " ({fractional_seconds_precision})")?;
581                }
582                Ok(())
583            }
584        }
585    }
586}
587
588/// A field definition within a struct
589///
590/// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-types#struct_type
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 StructField {
595    /// Optional name of the struct field.
596    pub field_name: Option<Ident>,
597    /// The field data type.
598    pub field_type: DataType,
599    /// Struct field options (e.g., `OPTIONS(...)` on BigQuery).
600    /// See [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#column_name_and_column_schema)
601    pub options: Option<Vec<SqlOption>>,
602}
603
604impl fmt::Display for StructField {
605    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
606        if let Some(name) = &self.field_name {
607            write!(f, "{name} {}", self.field_type)?;
608        } else {
609            write!(f, "{}", self.field_type)?;
610        }
611        if let Some(options) = &self.options {
612            write!(f, " OPTIONS({})", display_separated(options, ", "))
613        } else {
614            Ok(())
615        }
616    }
617}
618
619/// A field definition within a union
620///
621/// [DuckDB]: https://duckdb.org/docs/sql/data_types/union.html
622#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
623#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
624#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
625pub struct UnionField {
626    /// Name of the union field.
627    pub field_name: Ident,
628    /// Type of the union field.
629    pub field_type: DataType,
630}
631
632impl fmt::Display for UnionField {
633    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
634        write!(f, "{} {}", self.field_name, self.field_type)
635    }
636}
637
638/// A dictionary field within a dictionary.
639///
640/// [DuckDB]: https://duckdb.org/docs/sql/data_types/struct#creating-structs
641#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
642#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
643#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
644pub struct DictionaryField {
645    /// Dictionary key identifier.
646    pub key: Ident,
647    /// Value expression for the dictionary entry.
648    pub value: Box<Expr>,
649}
650
651impl fmt::Display for DictionaryField {
652    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
653        write!(f, "{}: {}", self.key, self.value)
654    }
655}
656
657/// Represents a Map expression.
658#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
659#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
660#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
661pub struct Map {
662    /// Entries of the map as key/value pairs.
663    pub entries: Vec<MapEntry>,
664}
665
666impl Display for Map {
667    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
668        write!(f, "MAP {{{}}}", display_comma_separated(&self.entries))
669    }
670}
671
672/// A map field within a map.
673///
674/// [DuckDB]: https://duckdb.org/docs/sql/data_types/map.html#creating-maps
675#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
676#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
677#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
678pub struct MapEntry {
679    /// Key expression of the map entry.
680    pub key: Box<Expr>,
681    /// Value expression of the map entry.
682    pub value: Box<Expr>,
683}
684
685impl fmt::Display for MapEntry {
686    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
687        write!(f, "{}: {}", self.key, self.value)
688    }
689}
690
691/// Options for `CAST` / `TRY_CAST`
692/// BigQuery: <https://cloud.google.com/bigquery/docs/reference/standard-sql/format-elements#formatting_syntax>
693#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
694#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
695#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
696pub enum CastFormat {
697    /// A simple cast format specified by a `Value`.
698    Value(ValueWithSpan),
699    /// A cast format with an explicit time zone: `(format, timezone)`.
700    ValueAtTimeZone(ValueWithSpan, ValueWithSpan),
701}
702
703/// An element of a JSON path.
704#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
705#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
706#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
707pub enum JsonPathElem {
708    /// Accesses an object field using dot notation, e.g. `obj:foo.bar.baz`.
709    ///
710    /// See <https://docs.snowflake.com/en/user-guide/querying-semistructured#dot-notation>.
711    Dot {
712        /// The object key text (without quotes).
713        key: String,
714        /// `true` when the key was quoted in the source.
715        quoted: bool,
716    },
717    /// Accesses an object field or array element using bracket notation,
718    /// e.g. `obj['foo']`.
719    ///
720    /// See <https://docs.snowflake.com/en/user-guide/querying-semistructured#bracket-notation>.
721    Bracket {
722        /// The expression used as the bracket key (string or numeric expression).
723        key: Expr,
724    },
725    /// Access an object field using colon bracket notation
726    /// e.g. `obj:['foo']`
727    ///
728    /// See <https://docs.databricks.com/en/sql/language-manual/functions/colonsign.html>
729    ColonBracket {
730        /// The expression used as the bracket key (string or numeric expression).
731        key: Expr,
732    },
733}
734
735/// A JSON path.
736///
737/// See <https://docs.snowflake.com/en/user-guide/querying-semistructured>.
738/// See <https://docs.databricks.com/en/sql/language-manual/sql-ref-json-path-expression.html>.
739#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
740#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
741#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
742pub struct JsonPath {
743    /// Sequence of path elements that form the JSON path.
744    pub path: Vec<JsonPathElem>,
745}
746
747impl fmt::Display for JsonPath {
748    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
749        for (i, elem) in self.path.iter().enumerate() {
750            match elem {
751                JsonPathElem::Dot { key, quoted } => {
752                    if i == 0 {
753                        write!(f, ":")?;
754                    } else {
755                        write!(f, ".")?;
756                    }
757
758                    if *quoted {
759                        write!(f, "\"{}\"", escape_double_quote_string(key))?;
760                    } else {
761                        write!(f, "{key}")?;
762                    }
763                }
764                JsonPathElem::Bracket { key } => {
765                    write!(f, "[{key}]")?;
766                }
767                JsonPathElem::ColonBracket { key } => {
768                    write!(f, ":[{key}]")?;
769                }
770            }
771        }
772        Ok(())
773    }
774}
775
776/// The syntax used for in a cast expression.
777#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
778#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
779#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
780pub enum CastKind {
781    /// The standard SQL cast syntax, e.g. `CAST(<expr> as <datatype>)`
782    Cast,
783    /// A cast that returns `NULL` on failure, e.g. `TRY_CAST(<expr> as <datatype>)`.
784    ///
785    /// See <https://docs.snowflake.com/en/sql-reference/functions/try_cast>.
786    /// See <https://learn.microsoft.com/en-us/sql/t-sql/functions/try-cast-transact-sql>.
787    TryCast,
788    /// A cast that returns `NULL` on failure, bigQuery-specific ,  e.g. `SAFE_CAST(<expr> as <datatype>)`.
789    ///
790    /// See <https://cloud.google.com/bigquery/docs/reference/standard-sql/functions-and-operators#safe_casting>.
791    SafeCast,
792    /// `<expr> :: <datatype>`
793    DoubleColon,
794}
795
796/// `MATCH` type for constraint references
797///
798/// See: <https://www.postgresql.org/docs/current/sql-createtable.html#SQL-CREATETABLE-PARMS-REFERENCES>
799#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
800#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
801#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
802pub enum ConstraintReferenceMatchKind {
803    /// `MATCH FULL`
804    Full,
805    /// `MATCH PARTIAL`
806    Partial,
807    /// `MATCH SIMPLE`
808    Simple,
809}
810
811impl fmt::Display for ConstraintReferenceMatchKind {
812    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
813        match self {
814            Self::Full => write!(f, "MATCH FULL"),
815            Self::Partial => write!(f, "MATCH PARTIAL"),
816            Self::Simple => write!(f, "MATCH SIMPLE"),
817        }
818    }
819}
820
821/// `EXTRACT` syntax variants.
822///
823/// In Snowflake dialect, the `EXTRACT` expression can support either the `from` syntax
824/// or the comma syntax.
825///
826/// See <https://docs.snowflake.com/en/sql-reference/functions/extract>
827#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
828#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
829#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
830pub enum ExtractSyntax {
831    /// `EXTRACT( <date_or_time_part> FROM <date_or_time_expr> )`
832    From,
833    /// `EXTRACT( <date_or_time_part> , <date_or_timestamp_expr> )`
834    Comma,
835}
836
837/// The syntax used in a CEIL or FLOOR expression.
838///
839/// The `CEIL/FLOOR(<datetime value expression> TO <time unit>)` is an Amazon Kinesis Data Analytics extension.
840/// See <https://docs.aws.amazon.com/kinesisanalytics/latest/sqlref/sql-reference-ceil.html> for
841/// details.
842///
843/// Other dialects either support `CEIL/FLOOR( <expr> [, <scale>])` format or just
844/// `CEIL/FLOOR(<expr>)`.
845#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
846#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
847#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
848pub enum CeilFloorKind {
849    /// `CEIL( <expr> TO <DateTimeField>)`
850    DateTimeField(DateTimeField),
851    /// `CEIL( <expr> [, <scale>])`
852    Scale(ValueWithSpan),
853}
854
855/// A WHEN clause in a CASE expression containing both
856/// the condition and its corresponding result
857#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
858#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
859#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
860pub struct CaseWhen {
861    /// The `WHEN` condition expression.
862    pub condition: Expr,
863    /// The expression returned when `condition` matches.
864    pub result: Expr,
865}
866
867impl fmt::Display for CaseWhen {
868    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
869        f.write_str("WHEN ")?;
870        self.condition.fmt(f)?;
871        f.write_str(" THEN")?;
872        SpaceOrNewline.fmt(f)?;
873        Indent(&self.result).fmt(f)?;
874        Ok(())
875    }
876}
877
878/// An SQL expression of any type.
879///
880/// # Semantics / Type Checking
881///
882/// The parser does not distinguish between expressions of different types
883/// (e.g. boolean vs string). The caller is responsible for detecting and
884/// validating types as necessary (for example  `WHERE 1` vs `SELECT 1=1`)
885/// See the [README.md] for more details.
886///
887/// [README.md]: https://github.com/apache/datafusion-sqlparser-rs/blob/main/README.md#syntax-vs-semantics
888///
889/// # Equality and Hashing Does not Include Source Locations
890///
891/// The `Expr` type implements `PartialEq` and `Eq` based on the semantic value
892/// of the expression (not bitwise comparison). This means that `Expr` instances
893/// that are semantically equivalent but have different spans (locations in the
894/// source tree) will compare as equal.
895#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
896#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
897#[cfg_attr(
898    feature = "visitor",
899    derive(Visit, VisitMut),
900    visit(with = "visit_expr")
901)]
902pub enum Expr {
903    /// Identifier e.g. table name or column name
904    Identifier(Ident),
905    /// Multi-part identifier, e.g. `table_alias.column` or `schema.table.col`
906    CompoundIdentifier(Vec<Ident>),
907    /// Multi-part expression access.
908    ///
909    /// This structure represents an access chain in structured / nested types
910    /// such as maps, arrays, and lists:
911    /// - Array
912    ///     - A 1-dim array `a[1]` will be represented like:
913    ///       `CompoundFieldAccess(Ident('a'), vec![Subscript(1)]`
914    ///     - A 2-dim array `a[1][2]` will be represented like:
915    ///       `CompoundFieldAccess(Ident('a'), vec![Subscript(1), Subscript(2)]`
916    /// - Map or Struct (Bracket-style)
917    ///     - A map `a['field1']` will be represented like:
918    ///       `CompoundFieldAccess(Ident('a'), vec![Subscript('field')]`
919    ///     - A 2-dim map `a['field1']['field2']` will be represented like:
920    ///       `CompoundFieldAccess(Ident('a'), vec![Subscript('field1'), Subscript('field2')]`
921    /// - Struct (Dot-style) (only effect when the chain contains both subscript and expr)
922    ///     - A struct access `a[field1].field2` will be represented like:
923    ///       `CompoundFieldAccess(Ident('a'), vec![Subscript('field1'), Ident('field2')]`
924    /// - If a struct access likes `a.field1.field2`, it will be represented by CompoundIdentifier([a, field1, field2])
925    CompoundFieldAccess {
926        /// The base expression being accessed.
927        root: Box<Expr>,
928        /// Sequence of access operations (subscript or identifier accesses).
929        access_chain: Vec<AccessExpr>,
930    },
931    /// Access data nested in a value containing semi-structured data, such as
932    /// the `VARIANT` type on Snowflake. for example `src:customer[0].name`.
933    ///
934    /// See <https://docs.snowflake.com/en/user-guide/querying-semistructured>.
935    /// See <https://docs.databricks.com/en/sql/language-manual/functions/colonsign.html>.
936    JsonAccess {
937        /// The value being queried.
938        value: Box<Expr>,
939        /// The path to the data to extract.
940        path: JsonPath,
941    },
942    /// `IS FALSE` operator
943    IsFalse(Box<Expr>),
944    /// `IS NOT FALSE` operator
945    IsNotFalse(Box<Expr>),
946    /// `IS TRUE` operator
947    IsTrue(Box<Expr>),
948    /// `IS NOT TRUE` operator
949    IsNotTrue(Box<Expr>),
950    /// `IS NULL` operator
951    IsNull(Box<Expr>),
952    /// `IS NOT NULL` operator
953    IsNotNull(Box<Expr>),
954    /// `IS UNKNOWN` operator
955    IsUnknown(Box<Expr>),
956    /// `IS NOT UNKNOWN` operator
957    IsNotUnknown(Box<Expr>),
958    /// `IS DISTINCT FROM` operator
959    IsDistinctFrom(Box<Expr>, Box<Expr>),
960    /// `IS NOT DISTINCT FROM` operator
961    IsNotDistinctFrom(Box<Expr>, Box<Expr>),
962    /// `<expr> IS [NOT] JSON [VALUE|SCALAR|ARRAY|OBJECT] [WITH|WITHOUT UNIQUE [KEYS]]`
963    IsJson {
964        /// Expression being tested.
965        expr: Box<Expr>,
966        /// Optional JSON shape constraint.
967        kind: Option<JsonPredicateType>,
968        /// Optional duplicate-key handling constraint for JSON objects.
969        unique_keys: Option<JsonKeyUniqueness>,
970        /// `true` when `NOT` is present.
971        negated: bool,
972    },
973    /// `<expr> IS [ NOT ] [ form ] NORMALIZED`
974    IsNormalized {
975        /// Expression being tested.
976        expr: Box<Expr>,
977        /// Optional normalization `form` (e.g., NFC, NFD).
978        form: Option<NormalizationForm>,
979        /// `true` when `NOT` is present.
980        negated: bool,
981    },
982    /// `[ NOT ] IN (val1, val2, ...)`
983    InList {
984        /// Left-hand expression to test for membership.
985        expr: Box<Expr>,
986        /// Literal list of expressions to check against.
987        list: Vec<Expr>,
988        /// `true` when the `NOT` modifier is present.
989        negated: bool,
990    },
991    /// `[ NOT ] IN (SELECT ...)`
992    InSubquery {
993        /// Left-hand expression to test for membership.
994        expr: Box<Expr>,
995        /// The subquery providing the candidate values.
996        subquery: Box<Query>,
997        /// `true` when the `NOT` modifier is present.
998        negated: bool,
999    },
1000    /// `[ NOT ] IN UNNEST(array_expression)`
1001    InUnnest {
1002        /// Left-hand expression to test for membership.
1003        expr: Box<Expr>,
1004        /// Array expression being unnested.
1005        array_expr: Box<Expr>,
1006        /// `true` when the `NOT` modifier is present.
1007        negated: bool,
1008    },
1009    /// `<expr> [ NOT ] BETWEEN <low> AND <high>`
1010    Between {
1011        /// Expression being compared.
1012        expr: Box<Expr>,
1013        /// `true` when the `NOT` modifier is present.
1014        negated: bool,
1015        /// Lower bound.
1016        low: Box<Expr>,
1017        /// Upper bound.
1018        high: Box<Expr>,
1019    },
1020    /// Binary operation e.g. `1 + 1` or `foo > bar`
1021    BinaryOp {
1022        /// Left operand.
1023        left: Box<Expr>,
1024        /// Operator between operands.
1025        op: BinaryOperator,
1026        /// Right operand.
1027        right: Box<Expr>,
1028    },
1029    /// `[NOT] LIKE <pattern> [ESCAPE <escape_character>]`
1030    Like {
1031        /// `true` when `NOT` is present.
1032        negated: bool,
1033        /// Snowflake supports the ANY keyword to match against a list of patterns
1034        /// <https://docs.snowflake.com/en/sql-reference/functions/like_any>
1035        any: bool,
1036        /// Expression to match.
1037        expr: Box<Expr>,
1038        /// Pattern expression.
1039        pattern: Box<Expr>,
1040        /// Optional escape character.
1041        escape_char: Option<Box<Expr>>,
1042    },
1043    /// `ILIKE` (case-insensitive `LIKE`)
1044    ILike {
1045        /// `true` when `NOT` is present.
1046        negated: bool,
1047        /// Snowflake supports the ANY keyword to match against a list of patterns
1048        /// <https://docs.snowflake.com/en/sql-reference/functions/like_any>
1049        any: bool,
1050        /// Expression to match.
1051        expr: Box<Expr>,
1052        /// Pattern expression.
1053        pattern: Box<Expr>,
1054        /// Optional escape character.
1055        escape_char: Option<Box<Expr>>,
1056    },
1057    /// `SIMILAR TO` regex
1058    SimilarTo {
1059        /// `true` when `NOT` is present.
1060        negated: bool,
1061        /// Expression to test.
1062        expr: Box<Expr>,
1063        /// Pattern expression.
1064        pattern: Box<Expr>,
1065        /// Optional escape character.
1066        escape_char: Option<Box<Expr>>,
1067    },
1068    /// MySQL: `RLIKE` regex or `REGEXP` regex
1069    RLike {
1070        /// `true` when `NOT` is present.
1071        negated: bool,
1072        /// Expression to test.
1073        expr: Box<Expr>,
1074        /// Pattern expression.
1075        pattern: Box<Expr>,
1076        /// true for REGEXP, false for RLIKE (no difference in semantics)
1077        regexp: bool,
1078    },
1079    /// `ANY` operation e.g. `foo > ANY(bar)`, comparison operator is one of `[=, >, <, =>, =<, !=]`
1080    /// <https://docs.snowflake.com/en/sql-reference/operators-subquery#all-any>
1081    AnyOp {
1082        /// Left operand.
1083        left: Box<Expr>,
1084        /// Comparison operator.
1085        compare_op: BinaryOperator,
1086        /// Right-hand subquery expression.
1087        right: Box<Expr>,
1088        /// ANY and SOME are synonymous: <https://docs.cloudera.com/cdw-runtime/cloud/using-hiveql/topics/hive_comparison_predicates.html>
1089        is_some: bool,
1090    },
1091    /// `ALL` operation e.g. `foo > ALL(bar)`, comparison operator is one of `[=, >, <, =>, =<, !=]`
1092    /// <https://docs.snowflake.com/en/sql-reference/operators-subquery#all-any>
1093    AllOp {
1094        /// Left operand.
1095        left: Box<Expr>,
1096        /// Comparison operator.
1097        compare_op: BinaryOperator,
1098        /// Right-hand subquery expression.
1099        right: Box<Expr>,
1100    },
1101
1102    /// Unary operation e.g. `NOT foo`
1103    UnaryOp {
1104        /// The unary operator (e.g., `NOT`, `-`).
1105        op: UnaryOperator,
1106        /// Operand expression.
1107        expr: Box<Expr>,
1108    },
1109    /// CONVERT a value to a different data type or character encoding. e.g. `CONVERT(foo USING utf8mb4)`
1110    Convert {
1111        /// CONVERT (false) or TRY_CONVERT (true)
1112        /// <https://learn.microsoft.com/en-us/sql/t-sql/functions/try-convert-transact-sql?view=sql-server-ver16>
1113        is_try: bool,
1114        /// The expression to convert.
1115        expr: Box<Expr>,
1116        /// The target data type, if provided.
1117        data_type: Option<DataType>,
1118        /// Optional target character encoding (e.g., `utf8mb4`).
1119        charset: Option<ObjectName>,
1120        /// `true` when target precedes the value (MSSQL syntax).
1121        target_before_value: bool,
1122        /// How to translate the expression.
1123        ///
1124        /// [MSSQL]: https://learn.microsoft.com/en-us/sql/t-sql/functions/cast-and-convert-transact-sql?view=sql-server-ver16#style
1125        styles: Vec<Expr>,
1126    },
1127    /// `CAST` an expression to a different data type e.g. `CAST(foo AS VARCHAR(123))`
1128    Cast {
1129        /// The cast kind (e.g., `CAST`, `TRY_CAST`).
1130        kind: CastKind,
1131        /// Expression being cast.
1132        expr: Box<Expr>,
1133        /// Target data type.
1134        data_type: DataType,
1135        /// Optional CAST(string_expression AS type FORMAT format_string_expression) as used by [BigQuery]
1136        ///
1137        /// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/format-elements#formatting_syntax
1138        format: Option<CastFormat>,
1139    },
1140    /// AT a timestamp to a different timezone e.g. `FROM_UNIXTIME(0) AT TIME ZONE 'UTC-06:00'`
1141    AtTimeZone {
1142        /// Timestamp expression to shift.
1143        timestamp: Box<Expr>,
1144        /// Time zone expression to apply.
1145        time_zone: Box<Expr>,
1146    },
1147    /// Extract a field from a timestamp e.g. `EXTRACT(MONTH FROM foo)`
1148    /// Or `EXTRACT(MONTH, foo)`
1149    ///
1150    /// Syntax:
1151    /// ```sql
1152    /// EXTRACT(DateTimeField FROM <expr>) | EXTRACT(DateTimeField, <expr>)
1153    /// ```
1154    Extract {
1155        /// Which datetime field is being extracted.
1156        field: DateTimeField,
1157        /// Syntax variant used (`From` or `Comma`).
1158        syntax: ExtractSyntax,
1159        /// Expression to extract from.
1160        expr: Box<Expr>,
1161    },
1162    /// ```sql
1163    /// CEIL(<expr> [TO DateTimeField])
1164    /// ```
1165    /// ```sql
1166    /// CEIL( <input_expr> [, <scale_expr> ] )
1167    /// ```
1168    Ceil {
1169        /// Expression to ceil.
1170        expr: Box<Expr>,
1171        /// The CEIL/FLOOR kind (datetime field or scale).
1172        field: CeilFloorKind,
1173    },
1174    /// ```sql
1175    /// FLOOR(<expr> [TO DateTimeField])
1176    /// ```
1177    /// ```sql
1178    /// FLOOR( <input_expr> [, <scale_expr> ] )
1179    ///
1180    Floor {
1181        /// Expression to floor.
1182        expr: Box<Expr>,
1183        /// The CEIL/FLOOR kind (datetime field or scale).
1184        field: CeilFloorKind,
1185    },
1186    /// ```sql
1187    /// POSITION(<expr> in <expr>)
1188    /// ```
1189    Position {
1190        /// Expression to search for.
1191        expr: Box<Expr>,
1192        /// Expression to search in.
1193        r#in: Box<Expr>,
1194    },
1195    /// ```sql
1196    /// SUBSTRING(<expr> [FROM <expr>] [FOR <expr>])
1197    /// ```
1198    /// or
1199    /// ```sql
1200    /// SUBSTRING(<expr>, <expr>, <expr>)
1201    /// ```
1202    Substring {
1203        /// Source expression.
1204        expr: Box<Expr>,
1205        /// Optional `FROM` expression.
1206        substring_from: Option<Box<Expr>>,
1207        /// Optional `FOR` expression.
1208        substring_for: Option<Box<Expr>>,
1209
1210        /// false if the expression is represented using the `SUBSTRING(expr [FROM start] [FOR len])` syntax
1211        /// true if the expression is represented using the `SUBSTRING(expr, start, len)` syntax
1212        /// This flag is used for formatting.
1213        special: bool,
1214
1215        /// true if the expression is represented using the `SUBSTR` shorthand
1216        /// This flag is used for formatting.
1217        shorthand: bool,
1218    },
1219    /// ```sql
1220    /// TRIM([BOTH | LEADING | TRAILING] [<expr> FROM] <expr>)
1221    /// TRIM(<expr>)
1222    /// TRIM(<expr>, [, characters]) -- PostgreSQL, DuckDB, Snowflake, BigQuery, Generic
1223    /// ```
1224    Trim {
1225        /// Which side to trim: `BOTH`, `LEADING`, or `TRAILING`.
1226        trim_where: Option<TrimWhereField>,
1227        /// Optional expression specifying what to trim from the value `expr`.
1228        trim_what: Option<Box<Expr>>,
1229        /// The expression to trim from.
1230        expr: Box<Expr>,
1231        /// Optional list of characters to trim (dialect-specific).
1232        trim_characters: Option<Vec<Expr>>,
1233    },
1234    /// ```sql
1235    /// OVERLAY(<expr> PLACING <expr> FROM <expr>[ FOR <expr> ]
1236    /// ```
1237    Overlay {
1238        /// The target expression being overlayed.
1239        expr: Box<Expr>,
1240        /// The expression to place into the target.
1241        overlay_what: Box<Expr>,
1242        /// The `FROM` position expression indicating where to start overlay.
1243        overlay_from: Box<Expr>,
1244        /// Optional `FOR` length expression limiting the overlay span.
1245        overlay_for: Option<Box<Expr>>,
1246    },
1247    /// `expr COLLATE collation`
1248    Collate {
1249        /// The expression being collated.
1250        expr: Box<Expr>,
1251        /// The collation name to apply to the expression.
1252        collation: ObjectName,
1253    },
1254    /// Nested expression e.g. `(foo > bar)` or `(1)`
1255    Nested(Box<Expr>),
1256    /// A literal value, such as string, number, date or NULL
1257    Value(ValueWithSpan),
1258    /// Prefixed expression, e.g. introducer strings, projection prefix
1259    /// <https://dev.mysql.com/doc/refman/8.0/en/charset-introducer.html>
1260    /// <https://docs.snowflake.com/en/sql-reference/constructs/connect-by>
1261    Prefixed {
1262        /// The prefix identifier (introducer or projection prefix).
1263        prefix: Ident,
1264        /// The value expression being prefixed.
1265        /// Hint: you can unwrap the string value using `value.into_string()`.
1266        value: Box<Expr>,
1267    },
1268    /// A constant of form `<data_type> 'value'`.
1269    /// This can represent ANSI SQL `DATE`, `TIME`, and `TIMESTAMP` literals (such as `DATE '2020-01-01'`),
1270    /// as well as constants of other types (a non-standard PostgreSQL extension).
1271    TypedString(TypedString),
1272    /// Scalar function call e.g. `LEFT(foo, 5)`
1273    Function(Function),
1274    /// `CASE [<operand>] WHEN <condition> THEN <result> ... [ELSE <result>] END`
1275    ///
1276    /// Note we only recognize a complete single expression as `<condition>`,
1277    /// not `< 0` nor `1, 2, 3` as allowed in a `<simple when clause>` per
1278    /// <https://jakewheat.github.io/sql-overview/sql-2011-foundation-grammar.html#simple-when-clause>
1279    Case {
1280        /// The attached `CASE` token (keeps original spacing/comments).
1281        case_token: AttachedToken,
1282        /// The attached `END` token (keeps original spacing/comments).
1283        end_token: AttachedToken,
1284        /// Optional operand expression after `CASE` (for simple CASE).
1285        operand: Option<Box<Expr>>,
1286        /// The `WHEN ... THEN` conditions and results.
1287        conditions: Vec<CaseWhen>,
1288        /// Optional `ELSE` result expression.
1289        else_result: Option<Box<Expr>>,
1290    },
1291    /// An exists expression `[ NOT ] EXISTS(SELECT ...)`, used in expressions like
1292    /// `WHERE [ NOT ] EXISTS (SELECT ...)`.
1293    Exists {
1294        /// The subquery checked by `EXISTS`.
1295        subquery: Box<Query>,
1296        /// Whether the `EXISTS` is negated (`NOT EXISTS`).
1297        negated: bool,
1298    },
1299    /// A parenthesized subquery `(SELECT ...)`, used in expression like
1300    /// `SELECT (subquery) AS x` or `WHERE (subquery) = x`
1301    Subquery(Box<Query>),
1302    /// The `GROUPING SETS` expr.
1303    GroupingSets(Vec<Vec<Expr>>),
1304    /// The `CUBE` expr.
1305    Cube(Vec<Vec<Expr>>),
1306    /// The `ROLLUP` expr.
1307    Rollup(Vec<Vec<Expr>>),
1308    /// ROW / TUPLE a single value, such as `SELECT (1, 2)`
1309    Tuple(Vec<Expr>),
1310    /// `Struct` literal expression
1311    /// Syntax:
1312    /// ```sql
1313    /// STRUCT<[field_name] field_type, ...>( expr1 [, ... ])
1314    ///
1315    /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-types#struct_type)
1316    /// [Databricks](https://docs.databricks.com/en/sql/language-manual/functions/struct.html)
1317    /// ```
1318    Struct {
1319        /// Struct values.
1320        values: Vec<Expr>,
1321        /// Struct field definitions.
1322        fields: Vec<StructField>,
1323    },
1324    /// A named expression: `1 AS A`. Used in `BigQuery` typeless structs [1]
1325    /// and in aliased function arguments, e.g. `XMLFOREST(a AS x)` in
1326    /// PostgreSQL [2].
1327    ///
1328    /// [1]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-types#struct_type
1329    /// [2]: https://www.postgresql.org/docs/current/functions-xml.html#FUNCTIONS-PRODUCING-XML-XMLFOREST
1330    Named {
1331        /// The expression being named.
1332        expr: Box<Expr>,
1333        /// The assigned identifier name for the expression.
1334        name: Ident,
1335    },
1336    /// `DuckDB` specific `Struct` literal expression [1]
1337    ///
1338    /// Syntax:
1339    /// ```sql
1340    /// syntax: {'field_name': expr1[, ... ]}
1341    /// ```
1342    /// [1]: https://duckdb.org/docs/sql/data_types/struct#creating-structs
1343    Dictionary(Vec<DictionaryField>),
1344    /// `DuckDB` specific `Map` literal expression [1]
1345    ///
1346    /// Syntax:
1347    /// ```sql
1348    /// syntax: Map {key1: value1[, ... ]}
1349    /// ```
1350    /// [1]: https://duckdb.org/docs/sql/data_types/map#creating-maps
1351    Map(Map),
1352    /// An array expression e.g. `ARRAY[1, 2]`
1353    Array(Array),
1354    /// An interval expression e.g. `INTERVAL '1' YEAR`
1355    Interval(Interval),
1356    /// `MySQL` specific text search function [(1)].
1357    ///
1358    /// Syntax:
1359    /// ```sql
1360    /// MATCH (<col>, <col>, ...) AGAINST (<expr> [<search modifier>])
1361    ///
1362    /// <col> = CompoundIdentifier
1363    /// <expr> = String literal
1364    /// ```
1365    /// [(1)]: https://dev.mysql.com/doc/refman/8.0/en/fulltext-search.html#function_match
1366    MatchAgainst {
1367        /// `(<col>, <col>, ...)`.
1368        columns: Vec<ObjectName>,
1369        /// `<expr>`.
1370        match_value: ValueWithSpan,
1371        /// `<search modifier>`
1372        opt_search_modifier: Option<SearchModifier>,
1373    },
1374    /// An unqualified `*` wildcard token (e.g. `*`).
1375    Wildcard(AttachedToken),
1376    /// Qualified wildcard, e.g. `alias.*` or `schema.table.*`.
1377    /// (Same caveats apply to `QualifiedWildcard` as to `Wildcard`.)
1378    QualifiedWildcard(ObjectName, AttachedToken),
1379    /// Some dialects support an older syntax for outer joins where columns are
1380    /// marked with the `(+)` operator in the WHERE clause, for example:
1381    ///
1382    /// ```sql
1383    /// SELECT t1.c1, t2.c2 FROM t1, t2 WHERE t1.c1 = t2.c2 (+)
1384    /// ```
1385    ///
1386    /// which is equivalent to
1387    ///
1388    /// ```sql
1389    /// SELECT t1.c1, t2.c2 FROM t1 LEFT OUTER JOIN t2 ON t1.c1 = t2.c2
1390    /// ```
1391    ///
1392    /// See <https://docs.snowflake.com/en/sql-reference/constructs/where#joins-in-the-where-clause>.
1393    OuterJoin(Box<Expr>),
1394    /// A reference to the prior level in a CONNECT BY clause.
1395    Prior(Box<Expr>),
1396    /// A lambda function.
1397    ///
1398    /// Syntax:
1399    /// ```plaintext
1400    /// param -> expr | (param1, ...) -> expr
1401    /// ```
1402    ///
1403    /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/functions#higher-order-functions---operator-and-lambdaparams-expr-function)
1404    /// [Databricks](https://docs.databricks.com/en/sql/language-manual/sql-ref-lambda-functions.html)
1405    /// [DuckDB](https://duckdb.org/docs/stable/sql/functions/lambda)
1406    Lambda(LambdaFunction),
1407    /// Checks membership of a value in a JSON array
1408    MemberOf(MemberOf),
1409}
1410
1411impl Expr {
1412    /// Creates a new [`Expr::Value`]
1413    pub fn value(value: impl Into<ValueWithSpan>) -> Self {
1414        Expr::Value(value.into())
1415    }
1416}
1417
1418/// The contents inside the `[` and `]` in a subscript expression.
1419#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1420#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1421#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1422pub enum Subscript {
1423    /// Accesses the element of the array at the given index.
1424    Index {
1425        /// The index expression used to access the array element.
1426        index: Expr,
1427    },
1428
1429    /// Accesses a slice of an array on PostgreSQL, e.g.
1430    ///
1431    /// ```plaintext
1432    /// => select (array[1,2,3,4,5,6])[2:5];
1433    /// -----------
1434    /// {2,3,4,5}
1435    /// ```
1436    ///
1437    /// The lower and/or upper bound can be omitted to slice from the start or
1438    /// end of the array respectively.
1439    ///
1440    /// See <https://www.postgresql.org/docs/current/arrays.html#ARRAYS-ACCESSING>.
1441    ///
1442    /// Also supports an optional "stride" as the last element (this is not
1443    /// supported by postgres), e.g.
1444    ///
1445    /// ```plaintext
1446    /// => select (array[1,2,3,4,5,6])[1:6:2];
1447    /// -----------
1448    /// {1,3,5}
1449    /// ```
1450    Slice {
1451        /// Optional lower bound for the slice (inclusive).
1452        lower_bound: Option<Expr>,
1453        /// Optional upper bound for the slice (inclusive).
1454        upper_bound: Option<Expr>,
1455        /// Optional stride for the slice (step size).
1456        stride: Option<Expr>,
1457    },
1458}
1459
1460impl fmt::Display for Subscript {
1461    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1462        match self {
1463            Subscript::Index { index } => write!(f, "{index}"),
1464            Subscript::Slice {
1465                lower_bound,
1466                upper_bound,
1467                stride,
1468            } => {
1469                if let Some(lower) = lower_bound {
1470                    write!(f, "{lower}")?;
1471                }
1472                write!(f, ":")?;
1473                if let Some(upper) = upper_bound {
1474                    write!(f, "{upper}")?;
1475                }
1476                if let Some(stride) = stride {
1477                    write!(f, ":")?;
1478                    write!(f, "{stride}")?;
1479                }
1480                Ok(())
1481            }
1482        }
1483    }
1484}
1485
1486/// An element of a [`Expr::CompoundFieldAccess`].
1487/// It can be an expression or a subscript.
1488#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1489#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1490#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1491pub enum AccessExpr {
1492    /// Accesses a field using dot notation, e.g. `foo.bar.baz`.
1493    Dot(Expr),
1494    /// Accesses a field or array element using bracket notation, e.g. `foo['bar']`.
1495    Subscript(Subscript),
1496}
1497
1498const fn is_number_expr(expr: &Expr) -> bool {
1499    matches!(expr, Expr::Value(v) if matches!(v.value, Value::Number(_, _)))
1500}
1501
1502impl fmt::Display for AccessExpr {
1503    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1504        match self {
1505            AccessExpr::Dot(expr) if is_number_expr(expr) => write!(f, " . {expr}"),
1506            AccessExpr::Dot(expr) => write!(f, ".{expr}"),
1507            AccessExpr::Subscript(subscript) => write!(f, "[{subscript}]"),
1508        }
1509    }
1510}
1511
1512/// A lambda function.
1513#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1514#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1515#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1516pub struct LambdaFunction {
1517    /// The parameters to the lambda function.
1518    pub params: OneOrManyWithParens<LambdaFunctionParameter>,
1519    /// The body of the lambda function.
1520    pub body: Box<Expr>,
1521    /// The syntax style used to write the lambda function.
1522    pub syntax: LambdaSyntax,
1523}
1524
1525impl fmt::Display for LambdaFunction {
1526    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1527        match self.syntax {
1528            LambdaSyntax::Arrow => write!(f, "{} -> {}", self.params, self.body),
1529            LambdaSyntax::LambdaKeyword => {
1530                // For lambda keyword syntax, display params without parentheses
1531                // e.g., `lambda x, y : expr` not `lambda (x, y) : expr`
1532                write!(f, "lambda ")?;
1533                match &self.params {
1534                    OneOrManyWithParens::One(p) => write!(f, "{p}")?,
1535                    OneOrManyWithParens::Many(ps) => write!(f, "{}", display_comma_separated(ps))?,
1536                };
1537                write!(f, " : {}", self.body)
1538            }
1539        }
1540    }
1541}
1542
1543/// A parameter to a lambda function, optionally with a data type.
1544#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1545#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1546#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1547pub struct LambdaFunctionParameter {
1548    /// The name of the parameter
1549    pub name: Ident,
1550    /// The optional data type of the parameter
1551    /// [Snowflake Syntax](https://docs.snowflake.com/en/sql-reference/functions/filter#arguments)
1552    pub data_type: Option<DataType>,
1553}
1554
1555impl fmt::Display for LambdaFunctionParameter {
1556    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1557        match &self.data_type {
1558            Some(dt) => write!(f, "{} {}", self.name, dt),
1559            None => write!(f, "{}", self.name),
1560        }
1561    }
1562}
1563
1564/// The syntax style for a lambda function.
1565#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Copy)]
1566#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1567#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1568pub enum LambdaSyntax {
1569    /// Arrow syntax: `param -> expr` or `(param1, param2) -> expr`
1570    ///
1571    /// <https://docs.databricks.com/aws/en/sql/language-manual/sql-ref-lambda-functions>
1572    ///
1573    /// Supported, but deprecated in DuckDB:
1574    /// <https://duckdb.org/docs/stable/sql/functions/lambda>
1575    Arrow,
1576    /// Lambda keyword syntax: `lambda param : expr` or `lambda param1, param2 : expr`
1577    ///
1578    /// Recommended in DuckDB:
1579    /// <https://duckdb.org/docs/stable/sql/functions/lambda>
1580    LambdaKeyword,
1581}
1582
1583/// Encapsulates the common pattern in SQL where either one unparenthesized item
1584/// such as an identifier or expression is permitted, or multiple of the same
1585/// item in a parenthesized list. For accessing items regardless of the form,
1586/// `OneOrManyWithParens` implements `Deref<Target = [T]>` and `IntoIterator`,
1587/// so you can call slice methods on it and iterate over items
1588/// # Examples
1589/// Accessing as a slice:
1590/// ```
1591/// # use sqlparser::ast::OneOrManyWithParens;
1592/// let one = OneOrManyWithParens::One("a");
1593///
1594/// assert_eq!(one[0], "a");
1595/// assert_eq!(one.len(), 1);
1596/// ```
1597/// Iterating:
1598/// ```
1599/// # use sqlparser::ast::OneOrManyWithParens;
1600/// let one = OneOrManyWithParens::One("a");
1601/// let many = OneOrManyWithParens::Many(vec!["a", "b"]);
1602///
1603/// assert_eq!(one.into_iter().chain(many).collect::<Vec<_>>(), vec!["a", "a", "b"] );
1604/// ```
1605#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1606#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1607#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1608pub enum OneOrManyWithParens<T> {
1609    /// A single `T`, unparenthesized.
1610    One(T),
1611    /// One or more `T`s, parenthesized.
1612    Many(Vec<T>),
1613}
1614
1615impl<T> Deref for OneOrManyWithParens<T> {
1616    type Target = [T];
1617
1618    fn deref(&self) -> &[T] {
1619        match self {
1620            OneOrManyWithParens::One(one) => core::slice::from_ref(one),
1621            OneOrManyWithParens::Many(many) => many,
1622        }
1623    }
1624}
1625
1626impl<T> AsRef<[T]> for OneOrManyWithParens<T> {
1627    fn as_ref(&self) -> &[T] {
1628        self
1629    }
1630}
1631
1632impl<'a, T> IntoIterator for &'a OneOrManyWithParens<T> {
1633    type Item = &'a T;
1634    type IntoIter = core::slice::Iter<'a, T>;
1635
1636    fn into_iter(self) -> Self::IntoIter {
1637        self.iter()
1638    }
1639}
1640
1641/// Owned iterator implementation of `OneOrManyWithParens`
1642#[derive(Debug, Clone)]
1643pub struct OneOrManyWithParensIntoIter<T> {
1644    inner: OneOrManyWithParensIntoIterInner<T>,
1645}
1646
1647#[derive(Debug, Clone)]
1648enum OneOrManyWithParensIntoIterInner<T> {
1649    One(core::iter::Once<T>),
1650    Many(<Vec<T> as IntoIterator>::IntoIter),
1651}
1652
1653impl<T> core::iter::FusedIterator for OneOrManyWithParensIntoIter<T>
1654where
1655    core::iter::Once<T>: core::iter::FusedIterator,
1656    <Vec<T> as IntoIterator>::IntoIter: core::iter::FusedIterator,
1657{
1658}
1659
1660impl<T> core::iter::ExactSizeIterator for OneOrManyWithParensIntoIter<T>
1661where
1662    core::iter::Once<T>: core::iter::ExactSizeIterator,
1663    <Vec<T> as IntoIterator>::IntoIter: core::iter::ExactSizeIterator,
1664{
1665}
1666
1667impl<T> core::iter::Iterator for OneOrManyWithParensIntoIter<T> {
1668    type Item = T;
1669
1670    fn next(&mut self) -> Option<Self::Item> {
1671        match &mut self.inner {
1672            OneOrManyWithParensIntoIterInner::One(one) => one.next(),
1673            OneOrManyWithParensIntoIterInner::Many(many) => many.next(),
1674        }
1675    }
1676
1677    fn size_hint(&self) -> (usize, Option<usize>) {
1678        match &self.inner {
1679            OneOrManyWithParensIntoIterInner::One(one) => one.size_hint(),
1680            OneOrManyWithParensIntoIterInner::Many(many) => many.size_hint(),
1681        }
1682    }
1683
1684    fn count(self) -> usize
1685    where
1686        Self: Sized,
1687    {
1688        match self.inner {
1689            OneOrManyWithParensIntoIterInner::One(one) => one.count(),
1690            OneOrManyWithParensIntoIterInner::Many(many) => many.count(),
1691        }
1692    }
1693
1694    fn fold<B, F>(mut self, init: B, f: F) -> B
1695    where
1696        Self: Sized,
1697        F: FnMut(B, Self::Item) -> B,
1698    {
1699        match &mut self.inner {
1700            OneOrManyWithParensIntoIterInner::One(one) => one.fold(init, f),
1701            OneOrManyWithParensIntoIterInner::Many(many) => many.fold(init, f),
1702        }
1703    }
1704}
1705
1706impl<T> core::iter::DoubleEndedIterator for OneOrManyWithParensIntoIter<T> {
1707    fn next_back(&mut self) -> Option<Self::Item> {
1708        match &mut self.inner {
1709            OneOrManyWithParensIntoIterInner::One(one) => one.next_back(),
1710            OneOrManyWithParensIntoIterInner::Many(many) => many.next_back(),
1711        }
1712    }
1713}
1714
1715impl<T> IntoIterator for OneOrManyWithParens<T> {
1716    type Item = T;
1717
1718    type IntoIter = OneOrManyWithParensIntoIter<T>;
1719
1720    fn into_iter(self) -> Self::IntoIter {
1721        let inner = match self {
1722            OneOrManyWithParens::One(one) => {
1723                OneOrManyWithParensIntoIterInner::One(core::iter::once(one))
1724            }
1725            OneOrManyWithParens::Many(many) => {
1726                OneOrManyWithParensIntoIterInner::Many(many.into_iter())
1727            }
1728        };
1729
1730        OneOrManyWithParensIntoIter { inner }
1731    }
1732}
1733
1734impl<T> fmt::Display for OneOrManyWithParens<T>
1735where
1736    T: fmt::Display,
1737{
1738    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1739        match self {
1740            OneOrManyWithParens::One(value) => write!(f, "{value}"),
1741            OneOrManyWithParens::Many(values) => {
1742                write!(f, "({})", display_comma_separated(values))
1743            }
1744        }
1745    }
1746}
1747
1748impl fmt::Display for CastFormat {
1749    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1750        match self {
1751            CastFormat::Value(v) => write!(f, "{v}"),
1752            CastFormat::ValueAtTimeZone(v, tz) => write!(f, "{v} AT TIME ZONE {tz}"),
1753        }
1754    }
1755}
1756
1757impl fmt::Display for Expr {
1758    #[cfg_attr(feature = "recursive-protection", recursive::recursive)]
1759    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1760        match self {
1761            Expr::Identifier(s) => write!(f, "{s}"),
1762            Expr::Wildcard(_) => f.write_str("*"),
1763            Expr::QualifiedWildcard(prefix, _) => write!(f, "{prefix}.*"),
1764            Expr::CompoundIdentifier(s) => write!(f, "{}", display_separated(s, ".")),
1765            Expr::CompoundFieldAccess { root, access_chain } => {
1766                write!(f, "{root}")?;
1767                let mut prev_is_number = is_number_expr(root);
1768                for field in access_chain {
1769                    match field {
1770                        AccessExpr::Dot(expr) if prev_is_number => write!(f, " . {expr}")?,
1771                        _ => write!(f, "{field}")?,
1772                    }
1773                    prev_is_number = matches!(field, AccessExpr::Dot(expr) if is_number_expr(expr));
1774                }
1775                Ok(())
1776            }
1777            Expr::IsTrue(ast) => write!(f, "{ast} IS TRUE"),
1778            Expr::IsNotTrue(ast) => write!(f, "{ast} IS NOT TRUE"),
1779            Expr::IsFalse(ast) => write!(f, "{ast} IS FALSE"),
1780            Expr::IsNotFalse(ast) => write!(f, "{ast} IS NOT FALSE"),
1781            Expr::IsNull(ast) => write!(f, "{ast} IS NULL"),
1782            Expr::IsNotNull(ast) => write!(f, "{ast} IS NOT NULL"),
1783            Expr::IsUnknown(ast) => write!(f, "{ast} IS UNKNOWN"),
1784            Expr::IsNotUnknown(ast) => write!(f, "{ast} IS NOT UNKNOWN"),
1785            Expr::IsJson {
1786                expr,
1787                kind,
1788                unique_keys,
1789                negated,
1790            } => {
1791                write!(f, "{expr} IS ")?;
1792                if *negated {
1793                    write!(f, "NOT ")?;
1794                }
1795                write!(f, "JSON")?;
1796                if let Some(kind) = kind {
1797                    write!(f, " {kind}")?;
1798                }
1799                if let Some(unique_keys) = unique_keys {
1800                    write!(f, " {unique_keys}")?;
1801                }
1802                Ok(())
1803            }
1804            Expr::InList {
1805                expr,
1806                list,
1807                negated,
1808            } => write!(
1809                f,
1810                "{} {}IN ({})",
1811                expr,
1812                if *negated { "NOT " } else { "" },
1813                display_comma_separated(list)
1814            ),
1815            Expr::InSubquery {
1816                expr,
1817                subquery,
1818                negated,
1819            } => write!(
1820                f,
1821                "{} {}IN ({})",
1822                expr,
1823                if *negated { "NOT " } else { "" },
1824                subquery
1825            ),
1826            Expr::InUnnest {
1827                expr,
1828                array_expr,
1829                negated,
1830            } => write!(
1831                f,
1832                "{} {}IN UNNEST({})",
1833                expr,
1834                if *negated { "NOT " } else { "" },
1835                array_expr
1836            ),
1837            Expr::Between {
1838                expr,
1839                negated,
1840                low,
1841                high,
1842            } => write!(
1843                f,
1844                "{} {}BETWEEN {} AND {}",
1845                expr,
1846                if *negated { "NOT " } else { "" },
1847                low,
1848                high
1849            ),
1850            Expr::BinaryOp { left, op, right } => write!(f, "{left} {op} {right}"),
1851            Expr::Like {
1852                negated,
1853                expr,
1854                pattern,
1855                escape_char,
1856                any,
1857            } => match escape_char {
1858                Some(ch) => write!(
1859                    f,
1860                    "{} {}LIKE {}{} ESCAPE {}",
1861                    expr,
1862                    if *negated { "NOT " } else { "" },
1863                    if *any { "ANY " } else { "" },
1864                    pattern,
1865                    ch
1866                ),
1867                _ => write!(
1868                    f,
1869                    "{} {}LIKE {}{}",
1870                    expr,
1871                    if *negated { "NOT " } else { "" },
1872                    if *any { "ANY " } else { "" },
1873                    pattern
1874                ),
1875            },
1876            Expr::ILike {
1877                negated,
1878                expr,
1879                pattern,
1880                escape_char,
1881                any,
1882            } => match escape_char {
1883                Some(ch) => write!(
1884                    f,
1885                    "{} {}ILIKE {}{} ESCAPE {}",
1886                    expr,
1887                    if *negated { "NOT " } else { "" },
1888                    if *any { "ANY" } else { "" },
1889                    pattern,
1890                    ch
1891                ),
1892                _ => write!(
1893                    f,
1894                    "{} {}ILIKE {}{}",
1895                    expr,
1896                    if *negated { "NOT " } else { "" },
1897                    if *any { "ANY " } else { "" },
1898                    pattern
1899                ),
1900            },
1901            Expr::RLike {
1902                negated,
1903                expr,
1904                pattern,
1905                regexp,
1906            } => write!(
1907                f,
1908                "{} {}{} {}",
1909                expr,
1910                if *negated { "NOT " } else { "" },
1911                if *regexp { "REGEXP" } else { "RLIKE" },
1912                pattern
1913            ),
1914            Expr::IsNormalized {
1915                expr,
1916                form,
1917                negated,
1918            } => {
1919                let not_ = if *negated { "NOT " } else { "" };
1920                if let Some(form) = form {
1921                    write!(f, "{} IS {}{} NORMALIZED", expr, not_, form)
1922                } else {
1923                    write!(f, "{expr} IS {not_}NORMALIZED")
1924                }
1925            }
1926            Expr::SimilarTo {
1927                negated,
1928                expr,
1929                pattern,
1930                escape_char,
1931            } => match escape_char {
1932                Some(ch) => write!(
1933                    f,
1934                    "{} {}SIMILAR TO {} ESCAPE {}",
1935                    expr,
1936                    if *negated { "NOT " } else { "" },
1937                    pattern,
1938                    ch
1939                ),
1940                _ => write!(
1941                    f,
1942                    "{} {}SIMILAR TO {}",
1943                    expr,
1944                    if *negated { "NOT " } else { "" },
1945                    pattern
1946                ),
1947            },
1948            Expr::AnyOp {
1949                left,
1950                compare_op,
1951                right,
1952                is_some,
1953            } => {
1954                let add_parens = !matches!(right.as_ref(), Expr::Subquery(_));
1955                write!(
1956                    f,
1957                    "{left} {compare_op} {}{}{right}{}",
1958                    if *is_some { "SOME" } else { "ANY" },
1959                    if add_parens { "(" } else { "" },
1960                    if add_parens { ")" } else { "" },
1961                )
1962            }
1963            Expr::AllOp {
1964                left,
1965                compare_op,
1966                right,
1967            } => {
1968                let add_parens = !matches!(right.as_ref(), Expr::Subquery(_));
1969                write!(
1970                    f,
1971                    "{left} {compare_op} ALL{}{right}{}",
1972                    if add_parens { "(" } else { "" },
1973                    if add_parens { ")" } else { "" },
1974                )
1975            }
1976            Expr::UnaryOp { op, expr } => match op {
1977                UnaryOperator::PGPostfixFactorial => {
1978                    if matches!(
1979                        expr.as_ref(),
1980                        Expr::UnaryOp {
1981                            op: UnaryOperator::PGPostfixFactorial,
1982                            ..
1983                        }
1984                    ) {
1985                        write!(f, "{expr} {op}")
1986                    } else {
1987                        write!(f, "{expr}{op}")
1988                    }
1989                }
1990                UnaryOperator::Not
1991                | UnaryOperator::BitwiseNot
1992                | UnaryOperator::Hash
1993                | UnaryOperator::AtDashAt
1994                | UnaryOperator::DoubleAt
1995                | UnaryOperator::PGAbs
1996                | UnaryOperator::QuestionDash
1997                | UnaryOperator::QuestionPipe
1998                | UnaryOperator::PGSquareRoot
1999                | UnaryOperator::PGCubeRoot => write!(f, "{op} {expr}"),
2000                UnaryOperator::Minus | UnaryOperator::BangNot => {
2001                    if starts_with_operator_char(expr) {
2002                        write!(f, "{op} {expr}")
2003                    } else {
2004                        write!(f, "{op}{expr}")
2005                    }
2006                }
2007                UnaryOperator::Plus | UnaryOperator::PGPrefixFactorial => write!(f, "{op}{expr}"),
2008            },
2009            Expr::Convert {
2010                is_try,
2011                expr,
2012                target_before_value,
2013                data_type,
2014                charset,
2015                styles,
2016            } => {
2017                write!(f, "{}CONVERT(", if *is_try { "TRY_" } else { "" })?;
2018                if let Some(data_type) = data_type {
2019                    if let Some(charset) = charset {
2020                        write!(f, "{expr}, {data_type} CHARACTER SET {charset}")
2021                    } else if *target_before_value {
2022                        write!(f, "{data_type}, {expr}")
2023                    } else {
2024                        write!(f, "{expr}, {data_type}")
2025                    }
2026                } else if let Some(charset) = charset {
2027                    write!(f, "{expr} USING {charset}")
2028                } else {
2029                    write!(f, "{expr}") // This should never happen
2030                }?;
2031                if !styles.is_empty() {
2032                    write!(f, ", {}", display_comma_separated(styles))?;
2033                }
2034                write!(f, ")")
2035            }
2036            Expr::Cast {
2037                kind,
2038                expr,
2039                data_type,
2040                format,
2041            } => match kind {
2042                CastKind::Cast => {
2043                    if matches!(data_type, DataType::Unspecified) {
2044                        write!(f, "CAST({expr} AS")?;
2045                    } else {
2046                        write!(f, "CAST({expr} AS {data_type}")?;
2047                    }
2048                    if let Some(format) = format {
2049                        write!(f, " FORMAT {format}")?;
2050                    }
2051                    write!(f, ")")
2052                }
2053                CastKind::TryCast => {
2054                    if let Some(format) = format {
2055                        write!(f, "TRY_CAST({expr} AS {data_type} FORMAT {format})")
2056                    } else {
2057                        write!(f, "TRY_CAST({expr} AS {data_type})")
2058                    }
2059                }
2060                CastKind::SafeCast => {
2061                    if let Some(format) = format {
2062                        write!(f, "SAFE_CAST({expr} AS {data_type} FORMAT {format})")
2063                    } else {
2064                        write!(f, "SAFE_CAST({expr} AS {data_type})")
2065                    }
2066                }
2067                CastKind::DoubleColon => {
2068                    write!(f, "{expr}::{data_type}")
2069                }
2070            },
2071            Expr::Extract {
2072                field,
2073                syntax,
2074                expr,
2075            } => match syntax {
2076                ExtractSyntax::From => write!(f, "EXTRACT({field} FROM {expr})"),
2077                ExtractSyntax::Comma => write!(f, "EXTRACT({field}, {expr})"),
2078            },
2079            Expr::Ceil { expr, field } => match field {
2080                CeilFloorKind::DateTimeField(DateTimeField::NoDateTime) => {
2081                    write!(f, "CEIL({expr})")
2082                }
2083                CeilFloorKind::DateTimeField(dt_field) => write!(f, "CEIL({expr} TO {dt_field})"),
2084                CeilFloorKind::Scale(s) => write!(f, "CEIL({expr}, {s})"),
2085            },
2086            Expr::Floor { expr, field } => match field {
2087                CeilFloorKind::DateTimeField(DateTimeField::NoDateTime) => {
2088                    write!(f, "FLOOR({expr})")
2089                }
2090                CeilFloorKind::DateTimeField(dt_field) => write!(f, "FLOOR({expr} TO {dt_field})"),
2091                CeilFloorKind::Scale(s) => write!(f, "FLOOR({expr}, {s})"),
2092            },
2093            Expr::Position { expr, r#in } => write!(f, "POSITION({expr} IN {in})"),
2094            Expr::Collate { expr, collation } => write!(f, "{expr} COLLATE {collation}"),
2095            Expr::Nested(ast) => write!(f, "({ast})"),
2096            Expr::Value(v) => write!(f, "{v}"),
2097            Expr::Prefixed { prefix, value } => write!(f, "{prefix} {value}"),
2098            Expr::TypedString(ts) => ts.fmt(f),
2099            Expr::Function(fun) => fun.fmt(f),
2100            Expr::Case {
2101                case_token: _,
2102                end_token: _,
2103                operand,
2104                conditions,
2105                else_result,
2106            } => {
2107                f.write_str("CASE")?;
2108                if let Some(operand) = operand {
2109                    f.write_str(" ")?;
2110                    operand.fmt(f)?;
2111                }
2112                for when in conditions {
2113                    SpaceOrNewline.fmt(f)?;
2114                    Indent(when).fmt(f)?;
2115                }
2116                if let Some(else_result) = else_result {
2117                    SpaceOrNewline.fmt(f)?;
2118                    Indent("ELSE").fmt(f)?;
2119                    SpaceOrNewline.fmt(f)?;
2120                    Indent(Indent(else_result)).fmt(f)?;
2121                }
2122                SpaceOrNewline.fmt(f)?;
2123                f.write_str("END")
2124            }
2125            Expr::Exists { subquery, negated } => write!(
2126                f,
2127                "{}EXISTS ({})",
2128                if *negated { "NOT " } else { "" },
2129                subquery
2130            ),
2131            Expr::Subquery(s) => write!(f, "({s})"),
2132            Expr::GroupingSets(sets) => {
2133                write!(f, "GROUPING SETS (")?;
2134                let mut sep = "";
2135                for set in sets {
2136                    write!(f, "{sep}")?;
2137                    sep = ", ";
2138                    write!(f, "({})", display_comma_separated(set))?;
2139                }
2140                write!(f, ")")
2141            }
2142            Expr::Cube(sets) => {
2143                write!(f, "CUBE (")?;
2144                let mut sep = "";
2145                for set in sets {
2146                    write!(f, "{sep}")?;
2147                    sep = ", ";
2148                    if set.len() == 1 {
2149                        write!(f, "{}", set[0])?;
2150                    } else {
2151                        write!(f, "({})", display_comma_separated(set))?;
2152                    }
2153                }
2154                write!(f, ")")
2155            }
2156            Expr::Rollup(sets) => {
2157                write!(f, "ROLLUP (")?;
2158                let mut sep = "";
2159                for set in sets {
2160                    write!(f, "{sep}")?;
2161                    sep = ", ";
2162                    if set.len() == 1 {
2163                        write!(f, "{}", set[0])?;
2164                    } else {
2165                        write!(f, "({})", display_comma_separated(set))?;
2166                    }
2167                }
2168                write!(f, ")")
2169            }
2170            Expr::Substring {
2171                expr,
2172                substring_from,
2173                substring_for,
2174                special,
2175                shorthand,
2176            } => {
2177                f.write_str("SUBSTR")?;
2178                if !*shorthand {
2179                    f.write_str("ING")?;
2180                }
2181                write!(f, "({expr}")?;
2182                if let Some(from_part) = substring_from {
2183                    if *special {
2184                        write!(f, ", {from_part}")?;
2185                    } else {
2186                        write!(f, " FROM {from_part}")?;
2187                    }
2188                }
2189                if let Some(for_part) = substring_for {
2190                    if *special {
2191                        write!(f, ", {for_part}")?;
2192                    } else {
2193                        write!(f, " FOR {for_part}")?;
2194                    }
2195                }
2196
2197                write!(f, ")")
2198            }
2199            Expr::Overlay {
2200                expr,
2201                overlay_what,
2202                overlay_from,
2203                overlay_for,
2204            } => {
2205                write!(
2206                    f,
2207                    "OVERLAY({expr} PLACING {overlay_what} FROM {overlay_from}"
2208                )?;
2209                if let Some(for_part) = overlay_for {
2210                    write!(f, " FOR {for_part}")?;
2211                }
2212
2213                write!(f, ")")
2214            }
2215            Expr::IsDistinctFrom(a, b) => write!(f, "{a} IS DISTINCT FROM {b}"),
2216            Expr::IsNotDistinctFrom(a, b) => write!(f, "{a} IS NOT DISTINCT FROM {b}"),
2217            Expr::Trim {
2218                expr,
2219                trim_where,
2220                trim_what,
2221                trim_characters,
2222            } => {
2223                write!(f, "TRIM(")?;
2224                if let Some(ident) = trim_where {
2225                    write!(f, "{ident} ")?;
2226                }
2227                if let Some(trim_char) = trim_what {
2228                    write!(f, "{trim_char} FROM {expr}")?;
2229                } else {
2230                    write!(f, "{expr}")?;
2231                }
2232                if let Some(characters) = trim_characters {
2233                    write!(f, ", {}", display_comma_separated(characters))?;
2234                }
2235
2236                write!(f, ")")
2237            }
2238            Expr::Tuple(exprs) => {
2239                write!(f, "({})", display_comma_separated(exprs))
2240            }
2241            Expr::Struct { values, fields } => {
2242                if !fields.is_empty() {
2243                    write!(
2244                        f,
2245                        "STRUCT<{}>({})",
2246                        display_comma_separated(fields),
2247                        display_comma_separated(values)
2248                    )
2249                } else {
2250                    write!(f, "STRUCT({})", display_comma_separated(values))
2251                }
2252            }
2253            Expr::Named { expr, name } => {
2254                write!(f, "{expr} AS {name}")
2255            }
2256            Expr::Dictionary(fields) => {
2257                write!(f, "{{{}}}", display_comma_separated(fields))
2258            }
2259            Expr::Map(map) => {
2260                write!(f, "{map}")
2261            }
2262            Expr::Array(set) => {
2263                write!(f, "{set}")
2264            }
2265            Expr::JsonAccess { value, path } => {
2266                write!(f, "{value}{path}")
2267            }
2268            Expr::AtTimeZone {
2269                timestamp,
2270                time_zone,
2271            } => {
2272                write!(f, "{timestamp} AT TIME ZONE {time_zone}")
2273            }
2274            Expr::Interval(interval) => {
2275                write!(f, "{interval}")
2276            }
2277            Expr::MatchAgainst {
2278                columns,
2279                match_value: match_expr,
2280                opt_search_modifier,
2281            } => {
2282                write!(f, "MATCH ({}) AGAINST ", display_comma_separated(columns),)?;
2283
2284                if let Some(search_modifier) = opt_search_modifier {
2285                    write!(f, "({match_expr} {search_modifier})")?;
2286                } else {
2287                    write!(f, "({match_expr})")?;
2288                }
2289
2290                Ok(())
2291            }
2292            Expr::OuterJoin(expr) => {
2293                write!(f, "{expr} (+)")
2294            }
2295            Expr::Prior(expr) => write!(f, "PRIOR {expr}"),
2296            Expr::Lambda(lambda) => write!(f, "{lambda}"),
2297            Expr::MemberOf(member_of) => write!(f, "{member_of}"),
2298        }
2299    }
2300}
2301
2302/// The type of a window used in `OVER` clauses.
2303///
2304/// A window can be either an inline specification (`WindowSpec`) or a
2305/// reference to a previously defined named window.
2306///
2307/// - `WindowSpec(WindowSpec)`: An inline window specification, e.g.
2308///   `OVER (PARTITION BY ... ORDER BY ...)`.
2309/// - `NamedWindow(Ident)`: A reference to a named window declared elsewhere.
2310#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2311#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2312#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2313pub enum WindowType {
2314    /// An inline window specification.
2315    WindowSpec(WindowSpec),
2316    /// A reference to a previously defined named window.
2317    NamedWindow(Ident),
2318}
2319
2320impl Display for WindowType {
2321    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2322        match self {
2323            WindowType::WindowSpec(spec) => {
2324                f.write_str("(")?;
2325                NewLine.fmt(f)?;
2326                Indent(spec).fmt(f)?;
2327                NewLine.fmt(f)?;
2328                f.write_str(")")
2329            }
2330            WindowType::NamedWindow(name) => name.fmt(f),
2331        }
2332    }
2333}
2334
2335/// A window specification (i.e. `OVER ([window_name] PARTITION BY .. ORDER BY .. etc.)`)
2336#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2337#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2338#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2339pub struct WindowSpec {
2340    /// Optional window name.
2341    ///
2342    /// You can find it at least in [MySQL][1], [BigQuery][2], [PostgreSQL][3]
2343    ///
2344    /// [1]: https://dev.mysql.com/doc/refman/8.0/en/window-functions-named-windows.html
2345    /// [2]: https://cloud.google.com/bigquery/docs/reference/standard-sql/window-function-calls
2346    /// [3]: https://www.postgresql.org/docs/current/sql-expressions.html#SYNTAX-WINDOW-FUNCTIONS
2347    pub window_name: Option<Ident>,
2348    /// `OVER (PARTITION BY ...)`
2349    pub partition_by: Vec<Expr>,
2350    /// `OVER (ORDER BY ...)`
2351    pub order_by: Vec<OrderByExpr>,
2352    /// `OVER (window frame)`
2353    pub window_frame: Option<WindowFrame>,
2354}
2355
2356impl fmt::Display for WindowSpec {
2357    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2358        let mut is_first = true;
2359        if let Some(window_name) = &self.window_name {
2360            if !is_first {
2361                SpaceOrNewline.fmt(f)?;
2362            }
2363            is_first = false;
2364            write!(f, "{window_name}")?;
2365        }
2366        if !self.partition_by.is_empty() {
2367            if !is_first {
2368                SpaceOrNewline.fmt(f)?;
2369            }
2370            is_first = false;
2371            write!(
2372                f,
2373                "PARTITION BY {}",
2374                display_comma_separated(&self.partition_by)
2375            )?;
2376        }
2377        if !self.order_by.is_empty() {
2378            if !is_first {
2379                SpaceOrNewline.fmt(f)?;
2380            }
2381            is_first = false;
2382            write!(f, "ORDER BY {}", display_comma_separated(&self.order_by))?;
2383        }
2384        if let Some(window_frame) = &self.window_frame {
2385            if !is_first {
2386                SpaceOrNewline.fmt(f)?;
2387            }
2388            if let Some(end_bound) = &window_frame.end_bound {
2389                write!(
2390                    f,
2391                    "{} BETWEEN {} AND {}",
2392                    window_frame.units, window_frame.start_bound, end_bound
2393                )?;
2394            } else {
2395                write!(f, "{} {}", window_frame.units, window_frame.start_bound)?;
2396            }
2397        }
2398        Ok(())
2399    }
2400}
2401
2402/// Specifies the data processed by a window function, e.g.
2403/// `RANGE UNBOUNDED PRECEDING` or `ROWS BETWEEN 5 PRECEDING AND CURRENT ROW`.
2404///
2405/// Note: The parser does not validate the specified bounds; the caller should
2406/// reject invalid bounds like `ROWS UNBOUNDED FOLLOWING` before execution.
2407#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2408#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2409#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2410pub struct WindowFrame {
2411    /// Units for the frame (e.g. `ROWS`, `RANGE`, `GROUPS`).
2412    pub units: WindowFrameUnits,
2413    /// The start bound of the window frame.
2414    pub start_bound: WindowFrameBound,
2415    /// The right bound of the `BETWEEN .. AND` clause. The end bound of `None`
2416    /// indicates the shorthand form (e.g. `ROWS 1 PRECEDING`), which must
2417    /// behave the same as `end_bound = WindowFrameBound::CurrentRow`.
2418    pub end_bound: Option<WindowFrameBound>,
2419    // TBD: EXCLUDE
2420}
2421
2422impl Default for WindowFrame {
2423    /// Returns default value for window frame
2424    ///
2425    /// See [this page](https://www.sqlite.org/windowfunctions.html#frame_specifications) for more details.
2426    fn default() -> Self {
2427        Self {
2428            units: WindowFrameUnits::Range,
2429            start_bound: WindowFrameBound::Preceding(None),
2430            end_bound: None,
2431        }
2432    }
2433}
2434
2435#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2436#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2437#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2438/// Units used to describe the window frame scope.
2439pub enum WindowFrameUnits {
2440    /// `ROWS` unit.
2441    Rows,
2442    /// `RANGE` unit.
2443    Range,
2444    /// `GROUPS` unit.
2445    Groups,
2446}
2447
2448impl fmt::Display for WindowFrameUnits {
2449    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2450        f.write_str(match self {
2451            WindowFrameUnits::Rows => "ROWS",
2452            WindowFrameUnits::Range => "RANGE",
2453            WindowFrameUnits::Groups => "GROUPS",
2454        })
2455    }
2456}
2457
2458/// Specifies Ignore / Respect NULL within window functions.
2459/// For example
2460/// `FIRST_VALUE(column2) IGNORE NULLS OVER (PARTITION BY column1)`
2461#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2462#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2463#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2464/// How NULL values are treated in certain window functions.
2465pub enum NullTreatment {
2466    /// Ignore NULL values (e.g. `IGNORE NULLS`).
2467    IgnoreNulls,
2468    /// Respect NULL values (e.g. `RESPECT NULLS`).
2469    RespectNulls,
2470}
2471
2472impl fmt::Display for NullTreatment {
2473    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2474        f.write_str(match self {
2475            NullTreatment::IgnoreNulls => "IGNORE NULLS",
2476            NullTreatment::RespectNulls => "RESPECT NULLS",
2477        })
2478    }
2479}
2480
2481/// Specifies [WindowFrame]'s `start_bound` and `end_bound`
2482#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2483#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2484#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2485pub enum WindowFrameBound {
2486    /// `CURRENT ROW`
2487    CurrentRow,
2488    /// `<N> PRECEDING` or `UNBOUNDED PRECEDING`
2489    Preceding(Option<Box<Expr>>),
2490    /// `<N> FOLLOWING` or `UNBOUNDED FOLLOWING`.
2491    Following(Option<Box<Expr>>),
2492}
2493
2494impl fmt::Display for WindowFrameBound {
2495    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2496        match self {
2497            WindowFrameBound::CurrentRow => f.write_str("CURRENT ROW"),
2498            WindowFrameBound::Preceding(None) => f.write_str("UNBOUNDED PRECEDING"),
2499            WindowFrameBound::Following(None) => f.write_str("UNBOUNDED FOLLOWING"),
2500            WindowFrameBound::Preceding(Some(n)) => write!(f, "{n} PRECEDING"),
2501            WindowFrameBound::Following(Some(n)) => write!(f, "{n} FOLLOWING"),
2502        }
2503    }
2504}
2505
2506#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2507#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2508#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2509/// Indicates partition operation type for partition management statements.
2510pub enum AddDropSync {
2511    /// Add partitions.
2512    ADD,
2513    /// Drop partitions.
2514    DROP,
2515    /// Sync partitions.
2516    SYNC,
2517}
2518
2519impl fmt::Display for AddDropSync {
2520    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2521        match self {
2522            AddDropSync::SYNC => f.write_str("SYNC PARTITIONS"),
2523            AddDropSync::DROP => f.write_str("DROP PARTITIONS"),
2524            AddDropSync::ADD => f.write_str("ADD PARTITIONS"),
2525        }
2526    }
2527}
2528
2529#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2530#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2531#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2532/// Object kinds supported by `SHOW CREATE` statements.
2533pub enum ShowCreateObject {
2534    /// An event object for `SHOW CREATE EVENT`.
2535    Event,
2536    /// A function object for `SHOW CREATE FUNCTION`.
2537    Function,
2538    /// A procedure object for `SHOW CREATE PROCEDURE`.
2539    Procedure,
2540    /// A table object for `SHOW CREATE TABLE`.
2541    Table,
2542    /// A trigger object for `SHOW CREATE TRIGGER`.
2543    Trigger,
2544    /// A view object for `SHOW CREATE VIEW`.
2545    View,
2546}
2547
2548impl fmt::Display for ShowCreateObject {
2549    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2550        match self {
2551            ShowCreateObject::Event => f.write_str("EVENT"),
2552            ShowCreateObject::Function => f.write_str("FUNCTION"),
2553            ShowCreateObject::Procedure => f.write_str("PROCEDURE"),
2554            ShowCreateObject::Table => f.write_str("TABLE"),
2555            ShowCreateObject::Trigger => f.write_str("TRIGGER"),
2556            ShowCreateObject::View => f.write_str("VIEW"),
2557        }
2558    }
2559}
2560
2561#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2562#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2563#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2564/// Objects that can be targeted by a `COMMENT` statement.
2565pub enum CommentObject {
2566    /// A collation.
2567    Collation,
2568    /// A table column.
2569    Column,
2570    /// A database.
2571    Database,
2572    /// A domain.
2573    Domain,
2574    /// An extension.
2575    Extension,
2576    /// A function.
2577    Function,
2578    /// An index.
2579    Index,
2580    /// A materialized view.
2581    MaterializedView,
2582    /// A procedure.
2583    Procedure,
2584    /// A role.
2585    Role,
2586    /// A schema.
2587    Schema,
2588    /// A sequence.
2589    Sequence,
2590    /// A table.
2591    Table,
2592    /// A type.
2593    Type,
2594    /// A user.
2595    User,
2596    /// A view.
2597    View,
2598}
2599
2600impl fmt::Display for CommentObject {
2601    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2602        match self {
2603            CommentObject::Collation => f.write_str("COLLATION"),
2604            CommentObject::Column => f.write_str("COLUMN"),
2605            CommentObject::Database => f.write_str("DATABASE"),
2606            CommentObject::Domain => f.write_str("DOMAIN"),
2607            CommentObject::Extension => f.write_str("EXTENSION"),
2608            CommentObject::Function => f.write_str("FUNCTION"),
2609            CommentObject::Index => f.write_str("INDEX"),
2610            CommentObject::MaterializedView => f.write_str("MATERIALIZED VIEW"),
2611            CommentObject::Procedure => f.write_str("PROCEDURE"),
2612            CommentObject::Role => f.write_str("ROLE"),
2613            CommentObject::Schema => f.write_str("SCHEMA"),
2614            CommentObject::Sequence => f.write_str("SEQUENCE"),
2615            CommentObject::Table => f.write_str("TABLE"),
2616            CommentObject::Type => f.write_str("TYPE"),
2617            CommentObject::User => f.write_str("USER"),
2618            CommentObject::View => f.write_str("VIEW"),
2619        }
2620    }
2621}
2622
2623#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2624#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2625#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2626/// Password specification variants used in user-related statements.
2627pub enum Password {
2628    /// A concrete password expression.
2629    Password(Expr),
2630    /// Represents a `NULL` password.
2631    NullPassword,
2632}
2633
2634/// A `CASE` statement.
2635///
2636/// Examples:
2637/// ```sql
2638/// CASE
2639///     WHEN EXISTS(SELECT 1)
2640///         THEN SELECT 1 FROM T;
2641///     WHEN EXISTS(SELECT 2)
2642///         THEN SELECT 1 FROM U;
2643///     ELSE
2644///         SELECT 1 FROM V;
2645/// END CASE;
2646/// ```
2647///
2648/// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#case_search_expression)
2649/// [Snowflake](https://docs.snowflake.com/en/sql-reference/snowflake-scripting/case)
2650#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2651#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2652#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2653pub struct CaseStatement {
2654    /// The `CASE` token that starts the statement.
2655    pub case_token: AttachedToken,
2656    /// Optional expression to match against in `CASE ... WHEN`.
2657    pub match_expr: Option<Expr>,
2658    /// The `WHEN ... THEN` blocks of the `CASE` statement.
2659    pub when_blocks: Vec<ConditionalStatementBlock>,
2660    /// Optional `ELSE` block for the `CASE` statement.
2661    pub else_block: Option<ConditionalStatementBlock>,
2662    /// The last token of the statement (`END` or `CASE`).
2663    pub end_case_token: AttachedToken,
2664}
2665
2666impl fmt::Display for CaseStatement {
2667    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2668        let CaseStatement {
2669            case_token: _,
2670            match_expr,
2671            when_blocks,
2672            else_block,
2673            end_case_token: AttachedToken(end),
2674        } = self;
2675
2676        write!(f, "CASE")?;
2677
2678        if let Some(expr) = match_expr {
2679            write!(f, " {expr}")?;
2680        }
2681
2682        if !when_blocks.is_empty() {
2683            write!(f, " {}", display_separated(when_blocks, " "))?;
2684        }
2685
2686        if let Some(else_block) = else_block {
2687            write!(f, " {else_block}")?;
2688        }
2689
2690        write!(f, " END")?;
2691
2692        if let Token::Word(w) = &end.token {
2693            if w.keyword == Keyword::CASE {
2694                write!(f, " CASE")?;
2695            }
2696        }
2697
2698        Ok(())
2699    }
2700}
2701
2702/// An `IF` statement.
2703///
2704/// Example (BigQuery or Snowflake):
2705/// ```sql
2706/// IF TRUE THEN
2707///     SELECT 1;
2708///     SELECT 2;
2709/// ELSEIF TRUE THEN
2710///     SELECT 3;
2711/// ELSE
2712///     SELECT 4;
2713/// END IF
2714/// ```
2715/// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#if)
2716/// [Snowflake](https://docs.snowflake.com/en/sql-reference/snowflake-scripting/if)
2717///
2718/// Example (MSSQL):
2719/// ```sql
2720/// IF 1=1 SELECT 1 ELSE SELECT 2
2721/// ```
2722/// [MSSQL](https://learn.microsoft.com/en-us/sql/t-sql/language-elements/if-else-transact-sql?view=sql-server-ver16)
2723#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2724#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2725#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2726pub struct IfStatement {
2727    /// The initial `IF` block containing the condition and statements.
2728    pub if_block: ConditionalStatementBlock,
2729    /// Additional `ELSEIF` blocks.
2730    pub elseif_blocks: Vec<ConditionalStatementBlock>,
2731    /// Optional `ELSE` block.
2732    pub else_block: Option<ConditionalStatementBlock>,
2733    /// Optional trailing `END` token for the `IF` statement.
2734    pub end_token: Option<AttachedToken>,
2735}
2736
2737impl fmt::Display for IfStatement {
2738    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2739        let IfStatement {
2740            if_block,
2741            elseif_blocks,
2742            else_block,
2743            end_token,
2744        } = self;
2745
2746        write!(f, "{if_block}")?;
2747
2748        for elseif_block in elseif_blocks {
2749            write!(f, " {elseif_block}")?;
2750        }
2751
2752        if let Some(else_block) = else_block {
2753            write!(f, " {else_block}")?;
2754        }
2755
2756        if let Some(AttachedToken(end_token)) = end_token {
2757            write!(f, " END {end_token}")?;
2758        }
2759
2760        Ok(())
2761    }
2762}
2763
2764/// A `WHILE` statement.
2765///
2766/// Example:
2767/// ```sql
2768/// WHILE @@FETCH_STATUS = 0
2769/// BEGIN
2770///    FETCH NEXT FROM c1 INTO @var1, @var2;
2771/// END
2772/// ```
2773///
2774/// [MsSql](https://learn.microsoft.com/en-us/sql/t-sql/language-elements/while-transact-sql)
2775#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2776#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2777#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2778pub struct WhileStatement {
2779    /// Block executed while the condition holds.
2780    pub while_block: ConditionalStatementBlock,
2781}
2782
2783impl fmt::Display for WhileStatement {
2784    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2785        let WhileStatement { while_block } = self;
2786        write!(f, "{while_block}")?;
2787        Ok(())
2788    }
2789}
2790
2791/// A block within a [Statement::Case] or [Statement::If] or [Statement::While]-like statement
2792///
2793/// Example 1:
2794/// ```sql
2795/// WHEN EXISTS(SELECT 1) THEN SELECT 1;
2796/// ```
2797///
2798/// Example 2:
2799/// ```sql
2800/// IF TRUE THEN SELECT 1; SELECT 2;
2801/// ```
2802///
2803/// Example 3:
2804/// ```sql
2805/// ELSE SELECT 1; SELECT 2;
2806/// ```
2807///
2808/// Example 4:
2809/// ```sql
2810/// WHILE @@FETCH_STATUS = 0
2811/// BEGIN
2812///    FETCH NEXT FROM c1 INTO @var1, @var2;
2813/// END
2814/// ```
2815#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2816#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2817#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2818pub struct ConditionalStatementBlock {
2819    /// Token representing the start of the block (e.g., WHEN/IF/WHILE).
2820    pub start_token: AttachedToken,
2821    /// Optional condition expression for the block.
2822    pub condition: Option<Expr>,
2823    /// Optional token for the `THEN` keyword.
2824    pub then_token: Option<AttachedToken>,
2825    /// The statements contained in this conditional block.
2826    pub conditional_statements: ConditionalStatements,
2827}
2828
2829impl ConditionalStatementBlock {
2830    /// Get the statements in this conditional block.
2831    pub fn statements(&self) -> &Vec<Statement> {
2832        self.conditional_statements.statements()
2833    }
2834}
2835
2836impl fmt::Display for ConditionalStatementBlock {
2837    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2838        let ConditionalStatementBlock {
2839            start_token: AttachedToken(start_token),
2840            condition,
2841            then_token,
2842            conditional_statements,
2843        } = self;
2844
2845        write!(f, "{start_token}")?;
2846
2847        if let Some(condition) = condition {
2848            write!(f, " {condition}")?;
2849        }
2850
2851        if then_token.is_some() {
2852            write!(f, " THEN")?;
2853        }
2854
2855        if !conditional_statements.statements().is_empty() {
2856            write!(f, " {conditional_statements}")?;
2857        }
2858
2859        Ok(())
2860    }
2861}
2862
2863/// A list of statements in a [ConditionalStatementBlock].
2864#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2865#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2866#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2867/// Statements used inside conditional blocks (`IF`, `WHEN`, `WHILE`).
2868pub enum ConditionalStatements {
2869    /// Simple sequence of statements (no `BEGIN`/`END`).
2870    Sequence {
2871        /// The statements in the sequence.
2872        statements: Vec<Statement>,
2873    },
2874    /// Block enclosed by `BEGIN` and `END`.
2875    BeginEnd(BeginEndStatements),
2876}
2877
2878impl ConditionalStatements {
2879    /// Get the statements in this conditional statements block.
2880    pub fn statements(&self) -> &Vec<Statement> {
2881        match self {
2882            ConditionalStatements::Sequence { statements } => statements,
2883            ConditionalStatements::BeginEnd(bes) => &bes.statements,
2884        }
2885    }
2886}
2887
2888impl fmt::Display for ConditionalStatements {
2889    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2890        match self {
2891            ConditionalStatements::Sequence { statements } => {
2892                if !statements.is_empty() {
2893                    format_statement_list(f, statements)?;
2894                }
2895                Ok(())
2896            }
2897            ConditionalStatements::BeginEnd(bes) => write!(f, "{bes}"),
2898        }
2899    }
2900}
2901
2902/// Represents a list of statements enclosed within `BEGIN` and `END` keywords.
2903/// Example:
2904/// ```sql
2905/// BEGIN
2906///     SELECT 1;
2907///     SELECT 2;
2908/// END
2909/// ```
2910#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2911#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2912#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2913pub struct BeginEndStatements {
2914    /// Token representing the `BEGIN` keyword (may include span info).
2915    pub begin_token: AttachedToken,
2916    /// Statements contained within the block.
2917    pub statements: Vec<Statement>,
2918    /// Token representing the `END` keyword (may include span info).
2919    pub end_token: AttachedToken,
2920}
2921
2922impl fmt::Display for BeginEndStatements {
2923    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2924        let BeginEndStatements {
2925            begin_token: AttachedToken(begin_token),
2926            statements,
2927            end_token: AttachedToken(end_token),
2928        } = self;
2929
2930        if begin_token.token != Token::EOF {
2931            write!(f, "{begin_token} ")?;
2932        }
2933        if !statements.is_empty() {
2934            format_statement_list(f, statements)?;
2935        }
2936        if end_token.token != Token::EOF {
2937            write!(f, " {end_token}")?;
2938        }
2939        Ok(())
2940    }
2941}
2942
2943/// A `RAISE` statement.
2944///
2945/// Examples:
2946/// ```sql
2947/// RAISE USING MESSAGE = 'error';
2948///
2949/// RAISE myerror;
2950/// ```
2951///
2952/// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#raise)
2953/// [Snowflake](https://docs.snowflake.com/en/sql-reference/snowflake-scripting/raise)
2954#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2955#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2956#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2957pub struct RaiseStatement {
2958    /// Optional value provided to the RAISE statement.
2959    pub value: Option<RaiseStatementValue>,
2960}
2961
2962impl fmt::Display for RaiseStatement {
2963    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2964        let RaiseStatement { value } = self;
2965
2966        write!(f, "RAISE")?;
2967        if let Some(value) = value {
2968            write!(f, " {value}")?;
2969        }
2970
2971        Ok(())
2972    }
2973}
2974
2975/// Represents the error value of a [RaiseStatement].
2976#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2977#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2978#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2979pub enum RaiseStatementValue {
2980    /// `RAISE USING MESSAGE = 'error'`
2981    UsingMessage(Expr),
2982    /// `RAISE myerror`
2983    Expr(Expr),
2984}
2985
2986impl fmt::Display for RaiseStatementValue {
2987    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2988        match self {
2989            RaiseStatementValue::Expr(expr) => write!(f, "{expr}"),
2990            RaiseStatementValue::UsingMessage(expr) => write!(f, "USING MESSAGE = {expr}"),
2991        }
2992    }
2993}
2994
2995/// A MSSQL `THROW` statement.
2996///
2997/// ```sql
2998/// THROW [ error_number, message, state ]
2999/// ```
3000///
3001/// [MSSQL](https://learn.microsoft.com/en-us/sql/t-sql/language-elements/throw-transact-sql)
3002#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3003#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3004#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3005pub struct ThrowStatement {
3006    /// Error number expression.
3007    pub error_number: Option<Box<Expr>>,
3008    /// Error message expression.
3009    pub message: Option<Box<Expr>>,
3010    /// State expression.
3011    pub state: Option<Box<Expr>>,
3012}
3013
3014impl fmt::Display for ThrowStatement {
3015    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3016        let ThrowStatement {
3017            error_number,
3018            message,
3019            state,
3020        } = self;
3021
3022        write!(f, "THROW")?;
3023        if let (Some(error_number), Some(message), Some(state)) = (error_number, message, state) {
3024            write!(f, " {error_number}, {message}, {state}")?;
3025        }
3026        Ok(())
3027    }
3028}
3029
3030/// Represents an expression assignment within a variable `DECLARE` statement.
3031///
3032/// Examples:
3033/// ```sql
3034/// DECLARE variable_name := 42
3035/// DECLARE variable_name DEFAULT 42
3036/// ```
3037#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3038#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3039#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3040pub enum DeclareAssignment {
3041    /// Plain expression specified.
3042    Expr(Box<Expr>),
3043
3044    /// Expression assigned via the `DEFAULT` keyword
3045    Default(Box<Expr>),
3046
3047    /// Expression assigned via the `:=` syntax
3048    ///
3049    /// Example:
3050    /// ```sql
3051    /// DECLARE variable_name := 42;
3052    /// ```
3053    DuckAssignment(Box<Expr>),
3054
3055    /// Expression via the `FOR` keyword
3056    ///
3057    /// Example:
3058    /// ```sql
3059    /// DECLARE c1 CURSOR FOR res
3060    /// ```
3061    For(Box<Expr>),
3062
3063    /// Expression via the `=` syntax.
3064    ///
3065    /// Example:
3066    /// ```sql
3067    /// DECLARE @variable AS INT = 100
3068    /// ```
3069    MsSqlAssignment(Box<Expr>),
3070}
3071
3072impl fmt::Display for DeclareAssignment {
3073    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3074        match self {
3075            DeclareAssignment::Expr(expr) => {
3076                write!(f, "{expr}")
3077            }
3078            DeclareAssignment::Default(expr) => {
3079                write!(f, "DEFAULT {expr}")
3080            }
3081            DeclareAssignment::DuckAssignment(expr) => {
3082                write!(f, ":= {expr}")
3083            }
3084            DeclareAssignment::MsSqlAssignment(expr) => {
3085                write!(f, "= {expr}")
3086            }
3087            DeclareAssignment::For(expr) => {
3088                write!(f, "FOR {expr}")
3089            }
3090        }
3091    }
3092}
3093
3094/// Represents the type of a `DECLARE` statement.
3095#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3096#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3097#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3098pub enum DeclareType {
3099    /// Cursor variable type. e.g. [Snowflake] [PostgreSQL] [MsSql]
3100    ///
3101    /// [Snowflake]: https://docs.snowflake.com/en/developer-guide/snowflake-scripting/cursors#declaring-a-cursor
3102    /// [PostgreSQL]: https://www.postgresql.org/docs/current/plpgsql-cursors.html
3103    /// [MsSql]: https://learn.microsoft.com/en-us/sql/t-sql/language-elements/declare-cursor-transact-sql
3104    Cursor,
3105
3106    /// Result set variable type. [Snowflake]
3107    ///
3108    /// Syntax:
3109    /// ```text
3110    /// <resultset_name> RESULTSET [ { DEFAULT | := } ( <query> ) ] ;
3111    /// ```
3112    /// [Snowflake]: https://docs.snowflake.com/en/sql-reference/snowflake-scripting/declare#resultset-declaration-syntax
3113    ResultSet,
3114
3115    /// Exception declaration syntax. [Snowflake]
3116    ///
3117    /// Syntax:
3118    /// ```text
3119    /// <exception_name> EXCEPTION [ ( <exception_number> , '<exception_message>' ) ] ;
3120    /// ```
3121    /// [Snowflake]: https://docs.snowflake.com/en/sql-reference/snowflake-scripting/declare#exception-declaration-syntax
3122    Exception,
3123}
3124
3125impl fmt::Display for DeclareType {
3126    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3127        match self {
3128            DeclareType::Cursor => {
3129                write!(f, "CURSOR")
3130            }
3131            DeclareType::ResultSet => {
3132                write!(f, "RESULTSET")
3133            }
3134            DeclareType::Exception => {
3135                write!(f, "EXCEPTION")
3136            }
3137        }
3138    }
3139}
3140
3141/// A `DECLARE` statement.
3142/// [PostgreSQL] [Snowflake] [BigQuery]
3143///
3144/// Examples:
3145/// ```sql
3146/// DECLARE variable_name := 42
3147/// DECLARE liahona CURSOR FOR SELECT * FROM films;
3148/// ```
3149///
3150/// [PostgreSQL]: https://www.postgresql.org/docs/current/sql-declare.html
3151/// [Snowflake]: https://docs.snowflake.com/en/sql-reference/snowflake-scripting/declare
3152/// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#declare
3153#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3154#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3155#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3156pub struct Declare {
3157    /// The name(s) being declared.
3158    /// Example: `DECLARE a, b, c DEFAULT 42;
3159    pub names: Vec<Ident>,
3160    /// Data-type assigned to the declared variable.
3161    /// Example: `DECLARE x INT64 DEFAULT 42;
3162    pub data_type: Option<DataType>,
3163    /// Expression being assigned to the declared variable.
3164    pub assignment: Option<DeclareAssignment>,
3165    /// Represents the type of the declared variable.
3166    pub declare_type: Option<DeclareType>,
3167    /// Causes the cursor to return data in binary rather than in text format.
3168    pub binary: Option<bool>,
3169    /// None = Not specified
3170    /// Some(true) = INSENSITIVE
3171    /// Some(false) = ASENSITIVE
3172    pub sensitive: Option<bool>,
3173    /// None = Not specified
3174    /// Some(true) = SCROLL
3175    /// Some(false) = NO SCROLL
3176    pub scroll: Option<bool>,
3177    /// None = Not specified
3178    /// Some(true) = WITH HOLD, specifies that the cursor can continue to be used after the transaction that created it successfully commits
3179    /// Some(false) = WITHOUT HOLD, specifies that the cursor cannot be used outside of the transaction that created it
3180    pub hold: Option<bool>,
3181    /// `FOR <query>` clause in a CURSOR declaration.
3182    pub for_query: Option<Box<Query>>,
3183}
3184
3185impl fmt::Display for Declare {
3186    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3187        let Declare {
3188            names,
3189            data_type,
3190            assignment,
3191            declare_type,
3192            binary,
3193            sensitive,
3194            scroll,
3195            hold,
3196            for_query,
3197        } = self;
3198        write!(f, "{}", display_comma_separated(names))?;
3199
3200        if let Some(true) = binary {
3201            write!(f, " BINARY")?;
3202        }
3203
3204        if let Some(sensitive) = sensitive {
3205            if *sensitive {
3206                write!(f, " INSENSITIVE")?;
3207            } else {
3208                write!(f, " ASENSITIVE")?;
3209            }
3210        }
3211
3212        if let Some(scroll) = scroll {
3213            if *scroll {
3214                write!(f, " SCROLL")?;
3215            } else {
3216                write!(f, " NO SCROLL")?;
3217            }
3218        }
3219
3220        if let Some(declare_type) = declare_type {
3221            write!(f, " {declare_type}")?;
3222        }
3223
3224        if let Some(hold) = hold {
3225            if *hold {
3226                write!(f, " WITH HOLD")?;
3227            } else {
3228                write!(f, " WITHOUT HOLD")?;
3229            }
3230        }
3231
3232        if let Some(query) = for_query {
3233            write!(f, " FOR {query}")?;
3234        }
3235
3236        if let Some(data_type) = data_type {
3237            write!(f, " {data_type}")?;
3238        }
3239
3240        if let Some(expr) = assignment {
3241            write!(f, " {expr}")?;
3242        }
3243        Ok(())
3244    }
3245}
3246
3247/// Sql options of a `CREATE TABLE` statement.
3248#[derive(Debug, Default, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3249#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3250#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3251/// Options allowed within a `CREATE TABLE` statement.
3252pub enum CreateTableOptions {
3253    /// No options specified.
3254    #[default]
3255    None,
3256    /// Options specified using the `WITH` keyword, e.g. `WITH (k = v)`.
3257    With(Vec<SqlOption>),
3258    /// Options specified using the `OPTIONS(...)` clause.
3259    Options(Vec<SqlOption>),
3260    /// Plain space-separated options.
3261    Plain(Vec<SqlOption>),
3262    /// Table properties (e.g., TBLPROPERTIES / storage properties).
3263    TableProperties(Vec<SqlOption>),
3264}
3265
3266impl fmt::Display for CreateTableOptions {
3267    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3268        match self {
3269            CreateTableOptions::With(with_options) => {
3270                write!(f, "WITH ({})", display_comma_separated(with_options))
3271            }
3272            CreateTableOptions::Options(options) => {
3273                write!(f, "OPTIONS({})", display_comma_separated(options))
3274            }
3275            CreateTableOptions::TableProperties(options) => {
3276                write!(f, "TBLPROPERTIES ({})", display_comma_separated(options))
3277            }
3278            CreateTableOptions::Plain(options) => {
3279                write!(f, "{}", display_separated(options, " "))
3280            }
3281            CreateTableOptions::None => Ok(()),
3282        }
3283    }
3284}
3285
3286/// A `FROM` clause within a `DELETE` statement.
3287///
3288/// Syntax
3289/// ```sql
3290/// [FROM] table
3291/// ```
3292#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3293#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3294#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3295pub enum FromTable {
3296    /// An explicit `FROM` keyword was specified.
3297    WithFromKeyword(Vec<TableWithJoins>),
3298    /// BigQuery: `FROM` keyword was omitted.
3299    /// <https://cloud.google.com/bigquery/docs/reference/standard-sql/dml-syntax#delete_statement>
3300    WithoutKeyword(Vec<TableWithJoins>),
3301}
3302impl Display for FromTable {
3303    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3304        match self {
3305            FromTable::WithFromKeyword(tables) => {
3306                write!(f, "FROM {}", display_comma_separated(tables))
3307            }
3308            FromTable::WithoutKeyword(tables) => {
3309                write!(f, "{}", display_comma_separated(tables))
3310            }
3311        }
3312    }
3313}
3314
3315#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3316#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3317#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3318/// Variants for the `SET` family of statements.
3319pub enum Set {
3320    /// SQL Standard-style
3321    /// SET a = 1;
3322    /// `SET var = value` (standard SQL-style assignment).
3323    SingleAssignment {
3324        /// Optional scope modifier (`SESSION` / `LOCAL`).
3325        scope: Option<ContextModifier>,
3326        /// Whether this is a Hive-style `HIVEVAR:` assignment.
3327        hivevar: bool,
3328        /// Variable name to assign.
3329        variable: ObjectName,
3330        /// Values assigned to the variable.
3331        values: Vec<Expr>,
3332    },
3333    /// Snowflake-style
3334    /// SET (a, b, ..) = (1, 2, ..);
3335    /// `SET (a, b) = (1, 2)` (tuple assignment syntax).
3336    ParenthesizedAssignments {
3337        /// Variables being assigned in tuple form.
3338        variables: Vec<ObjectName>,
3339        /// Corresponding values for the variables.
3340        values: Vec<Expr>,
3341    },
3342    /// MySQL-style
3343    /// SET a = 1, b = 2, ..;
3344    /// `SET a = 1, b = 2` (MySQL-style comma-separated assignments).
3345    MultipleAssignments {
3346        /// List of `SET` assignments (MySQL-style comma-separated).
3347        assignments: Vec<SetAssignment>,
3348    },
3349    /// Session authorization for Postgres/Redshift
3350    ///
3351    /// ```sql
3352    /// SET SESSION AUTHORIZATION { user_name | DEFAULT }
3353    /// ```
3354    ///
3355    /// See <https://www.postgresql.org/docs/current/sql-set-session-authorization.html>
3356    /// See <https://docs.aws.amazon.com/redshift/latest/dg/r_SET_SESSION_AUTHORIZATION.html>
3357    SetSessionAuthorization(SetSessionAuthorizationParam),
3358    /// MS-SQL session
3359    ///
3360    /// See <https://learn.microsoft.com/en-us/sql/t-sql/statements/set-statements-transact-sql>
3361    SetSessionParam(SetSessionParamKind),
3362    /// ```sql
3363    /// SET [ SESSION | LOCAL ] ROLE role_name
3364    /// ```
3365    ///
3366    /// Sets session state. Examples: [ANSI][1], [Postgresql][2], [MySQL][3], and [Oracle][4]
3367    ///
3368    /// [1]: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#set-role-statement
3369    /// [2]: https://www.postgresql.org/docs/14/sql-set-role.html
3370    /// [3]: https://dev.mysql.com/doc/refman/8.0/en/set-role.html
3371    /// [4]: https://docs.oracle.com/cd/B19306_01/server.102/b14200/statements_10004.htm
3372    SetRole {
3373        /// Non-ANSI optional identifier to inform if the role is defined inside the current session (`SESSION`) or transaction (`LOCAL`).
3374        context_modifier: Option<ContextModifier>,
3375        /// Role name. If NONE is specified, then the current role name is removed.
3376        role_name: Option<Ident>,
3377    },
3378    /// ```sql
3379    /// SET TIME ZONE <value>
3380    /// ```
3381    ///
3382    /// Note: this is a PostgreSQL-specific statements
3383    /// `SET TIME ZONE <value>` is an alias for `SET timezone TO <value>` in PostgreSQL
3384    /// However, we allow it for all dialects.
3385    /// `SET TIME ZONE` statement. `local` indicates the `LOCAL` keyword.
3386    /// `SET TIME ZONE <value>` statement.
3387    SetTimeZone {
3388        /// Whether the `LOCAL` keyword was specified.
3389        local: bool,
3390        /// Time zone expression value.
3391        value: Expr,
3392    },
3393    /// ```sql
3394    /// SET NAMES 'charset_name' [COLLATE 'collation_name']
3395    /// ```
3396    SetNames {
3397        /// Character set name to set.
3398        charset_name: Ident,
3399        /// Optional collation name.
3400        collation_name: Option<String>,
3401    },
3402    /// ```sql
3403    /// SET NAMES DEFAULT
3404    /// ```
3405    ///
3406    /// Note: this is a MySQL-specific statement.
3407    SetNamesDefault {},
3408    /// ```sql
3409    /// SET TRANSACTION ...
3410    /// ```
3411    SetTransaction {
3412        /// Transaction modes (e.g., ISOLATION LEVEL, READ ONLY).
3413        modes: Vec<TransactionMode>,
3414        /// Optional snapshot value for transaction snapshot control.
3415        snapshot: Option<ValueWithSpan>,
3416        /// `true` when the `SESSION` keyword was used.
3417        session: bool,
3418    },
3419}
3420
3421impl Display for Set {
3422    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3423        match self {
3424            Self::ParenthesizedAssignments { variables, values } => write!(
3425                f,
3426                "SET ({}) = ({})",
3427                display_comma_separated(variables),
3428                display_comma_separated(values)
3429            ),
3430            Self::MultipleAssignments { assignments } => {
3431                write!(f, "SET {}", display_comma_separated(assignments))
3432            }
3433            Self::SetRole {
3434                context_modifier,
3435                role_name,
3436            } => {
3437                let role_name = role_name.clone().unwrap_or_else(|| Ident::new("NONE"));
3438                write!(
3439                    f,
3440                    "SET {modifier}ROLE {role_name}",
3441                    modifier = context_modifier.map(|m| format!("{m}")).unwrap_or_default()
3442                )
3443            }
3444            Self::SetSessionAuthorization(kind) => write!(f, "SET SESSION AUTHORIZATION {kind}"),
3445            Self::SetSessionParam(kind) => write!(f, "SET {kind}"),
3446            Self::SetTransaction {
3447                modes,
3448                snapshot,
3449                session,
3450            } => {
3451                if *session {
3452                    write!(f, "SET SESSION CHARACTERISTICS AS TRANSACTION")?;
3453                } else {
3454                    write!(f, "SET TRANSACTION")?;
3455                }
3456                if !modes.is_empty() {
3457                    write!(f, " {}", display_comma_separated(modes))?;
3458                }
3459                if let Some(snapshot_id) = snapshot {
3460                    write!(f, " SNAPSHOT {snapshot_id}")?;
3461                }
3462                Ok(())
3463            }
3464            Self::SetTimeZone { local, value } => {
3465                f.write_str("SET ")?;
3466                if *local {
3467                    f.write_str("LOCAL ")?;
3468                }
3469                write!(f, "TIME ZONE {value}")
3470            }
3471            Self::SetNames {
3472                charset_name,
3473                collation_name,
3474            } => {
3475                write!(f, "SET NAMES {charset_name}")?;
3476
3477                if let Some(collation) = collation_name {
3478                    f.write_str(" COLLATE ")?;
3479                    f.write_str(collation)?;
3480                };
3481
3482                Ok(())
3483            }
3484            Self::SetNamesDefault {} => {
3485                f.write_str("SET NAMES DEFAULT")?;
3486
3487                Ok(())
3488            }
3489            Set::SingleAssignment {
3490                scope,
3491                hivevar,
3492                variable,
3493                values,
3494            } => {
3495                write!(
3496                    f,
3497                    "SET {}{}{} = {}",
3498                    scope.map(|s| format!("{s}")).unwrap_or_default(),
3499                    if *hivevar { "HIVEVAR:" } else { "" },
3500                    variable,
3501                    display_comma_separated(values)
3502                )
3503            }
3504        }
3505    }
3506}
3507
3508/// A representation of a `WHEN` arm with all the identifiers catched and the statements to execute
3509/// for the arm.
3510///
3511/// Snowflake: <https://docs.snowflake.com/en/sql-reference/snowflake-scripting/exception>
3512/// BigQuery: <https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#beginexceptionend>
3513#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3514#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3515#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3516pub struct ExceptionWhen {
3517    /// Identifiers that trigger this branch (error conditions).
3518    pub idents: Vec<Ident>,
3519    /// Statements to execute when the condition matches.
3520    pub statements: Vec<Statement>,
3521}
3522
3523impl Display for ExceptionWhen {
3524    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3525        write!(
3526            f,
3527            "WHEN {idents} THEN",
3528            idents = display_separated(&self.idents, " OR ")
3529        )?;
3530
3531        if !self.statements.is_empty() {
3532            write!(f, " ")?;
3533            format_statement_list(f, &self.statements)?;
3534        }
3535
3536        Ok(())
3537    }
3538}
3539
3540/// ANALYZE statement
3541///
3542/// Supported syntax varies by dialect:
3543/// - Hive: `ANALYZE TABLE t [PARTITION (...)] COMPUTE STATISTICS [NOSCAN] [FOR COLUMNS [col1, ...]] [CACHE METADATA]`
3544/// - PostgreSQL: `ANALYZE [VERBOSE] [t [(col1, ...)]]` See <https://www.postgresql.org/docs/current/sql-analyze.html>
3545/// - General: `ANALYZE [TABLE] t`
3546#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3547#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3548#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3549pub struct Analyze {
3550    #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
3551    /// Name of the table to analyze. `None` for bare `ANALYZE`.
3552    pub table_name: Option<ObjectName>,
3553    /// Optional partition expressions to restrict the analysis.
3554    pub partitions: Option<Vec<Expr>>,
3555    /// `true` when analyzing specific columns (Hive `FOR COLUMNS` syntax).
3556    pub for_columns: bool,
3557    /// Columns to analyze.
3558    pub columns: Vec<Ident>,
3559    /// Whether to cache metadata before analyzing.
3560    pub cache_metadata: bool,
3561    /// Whether to skip scanning the table.
3562    pub noscan: bool,
3563    /// Whether to compute statistics during analysis.
3564    pub compute_statistics: bool,
3565    /// Whether the `TABLE` keyword was present.
3566    pub has_table_keyword: bool,
3567}
3568
3569impl fmt::Display for Analyze {
3570    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3571        write!(f, "ANALYZE")?;
3572        if let Some(ref table_name) = self.table_name {
3573            if self.has_table_keyword {
3574                write!(f, " TABLE")?;
3575            }
3576            write!(f, " {table_name}")?;
3577        }
3578        if !self.for_columns && !self.columns.is_empty() {
3579            write!(f, " ({})", display_comma_separated(&self.columns))?;
3580        }
3581        if let Some(ref parts) = self.partitions {
3582            if !parts.is_empty() {
3583                write!(f, " PARTITION ({})", display_comma_separated(parts))?;
3584            }
3585        }
3586        if self.compute_statistics {
3587            write!(f, " COMPUTE STATISTICS")?;
3588        }
3589        if self.noscan {
3590            write!(f, " NOSCAN")?;
3591        }
3592        if self.cache_metadata {
3593            write!(f, " CACHE METADATA")?;
3594        }
3595        if self.for_columns {
3596            write!(f, " FOR COLUMNS")?;
3597            if !self.columns.is_empty() {
3598                write!(f, " {}", display_comma_separated(&self.columns))?;
3599            }
3600        }
3601        Ok(())
3602    }
3603}
3604
3605/// A top-level statement (SELECT, INSERT, CREATE, etc.)
3606#[allow(clippy::large_enum_variant)]
3607#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3608#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3609#[cfg_attr(
3610    feature = "visitor",
3611    derive(Visit, VisitMut),
3612    visit(with = "visit_statement")
3613)]
3614pub enum Statement {
3615    /// ```sql
3616    /// ANALYZE
3617    /// ```
3618    /// Analyze (Hive)
3619    Analyze(Analyze),
3620    /// `SET` statements (session, transaction, timezone, etc.).
3621    Set(Set),
3622    /// ```sql
3623    /// TRUNCATE
3624    /// ```
3625    /// Truncate (Hive)
3626    Truncate(Truncate),
3627    /// ```sql
3628    /// MSCK
3629    /// ```
3630    /// Msck (Hive)
3631    Msck(Msck),
3632    /// ```sql
3633    /// SELECT
3634    /// ```
3635    Query(Box<Query>),
3636    /// ```sql
3637    /// INSERT
3638    /// ```
3639    Insert(Insert),
3640    /// ```sql
3641    /// INSTALL
3642    /// ```
3643    Install {
3644        /// Only for DuckDB
3645        extension_name: Ident,
3646    },
3647    /// ```sql
3648    /// LOAD
3649    /// ```
3650    Load {
3651        /// Only for DuckDB
3652        extension_name: Ident,
3653    },
3654    // TODO: Support ROW FORMAT
3655    /// LOAD DATA from a directory or query source.
3656    Directory {
3657        /// Whether to overwrite existing files.
3658        overwrite: bool,
3659        /// Whether the directory is local to the server.
3660        local: bool,
3661        /// Path to the directory or files.
3662        path: String,
3663        /// Optional file format for the data.
3664        file_format: Option<FileFormat>,
3665        /// Source query providing data to load.
3666        source: Box<Query>,
3667    },
3668    /// A `CASE` statement.
3669    Case(CaseStatement),
3670    /// An `IF` statement.
3671    If(IfStatement),
3672    /// A `WHILE` statement.
3673    While(WhileStatement),
3674    /// A `RAISE` statement.
3675    Raise(RaiseStatement),
3676    /// PostgreSQL anonymous procedural block.
3677    Do(DoStatement),
3678    /// ```sql
3679    /// CALL <function>
3680    /// ```
3681    Call(Function),
3682    /// ```sql
3683    /// COPY [TO | FROM] ...
3684    /// ```
3685    Copy {
3686        /// The source of 'COPY TO', or the target of 'COPY FROM'
3687        source: CopySource,
3688        /// If true, is a 'COPY TO' statement. If false is a 'COPY FROM'
3689        to: bool,
3690        /// The target of 'COPY TO', or the source of 'COPY FROM'
3691        target: CopyTarget,
3692        /// WITH options (from PostgreSQL version 9.0)
3693        options: Vec<CopyOption>,
3694        /// WITH options (before PostgreSQL version 9.0)
3695        legacy_options: Vec<CopyLegacyOption>,
3696        /// VALUES a vector of values to be copied
3697        values: Vec<Option<String>>,
3698    },
3699    /// ```sql
3700    /// COPY INTO <table> | <location>
3701    /// ```
3702    /// See:
3703    /// <https://docs.snowflake.com/en/sql-reference/sql/copy-into-table>
3704    /// <https://docs.snowflake.com/en/sql-reference/sql/copy-into-location>
3705    ///
3706    /// Copy Into syntax available for Snowflake is different than the one implemented in
3707    /// Postgres. Although they share common prefix, it is reasonable to implement them
3708    /// in different enums. This can be refactored later once custom dialects
3709    /// are allowed to have custom Statements.
3710    CopyIntoSnowflake {
3711        /// Kind of COPY INTO operation (table or location).
3712        kind: CopyIntoSnowflakeKind,
3713        /// Target object for the COPY INTO operation.
3714        into: ObjectName,
3715        /// Optional list of target columns.
3716        into_columns: Option<Vec<Ident>>,
3717        /// Optional source object name (staged data).
3718        from_obj: Option<ObjectName>,
3719        /// Optional alias for the source object.
3720        from_obj_alias: Option<Ident>,
3721        /// Stage-specific parameters (e.g., credentials, path).
3722        stage_params: StageParamsObject,
3723        /// Optional list of transformations applied when loading.
3724        from_transformations: Option<Vec<StageLoadSelectItemKind>>,
3725        /// Optional source query instead of a staged object.
3726        from_query: Option<Box<Query>>,
3727        /// Optional list of specific file names to load.
3728        files: Option<Vec<String>>,
3729        /// Optional filename matching pattern.
3730        pattern: Option<String>,
3731        /// File format options.
3732        file_format: KeyValueOptions,
3733        /// Additional copy options.
3734        copy_options: KeyValueOptions,
3735        /// Optional validation mode string.
3736        validation_mode: Option<String>,
3737        /// Optional partition expression for loading.
3738        partition: Option<Box<Expr>>,
3739    },
3740    /// ```sql
3741    /// OPEN cursor_name
3742    /// ```
3743    /// Opens a cursor.
3744    Open(OpenStatement),
3745    /// ```sql
3746    /// CLOSE
3747    /// ```
3748    /// Closes the portal underlying an open cursor.
3749    Close {
3750        /// Cursor name
3751        cursor: CloseCursor,
3752    },
3753    /// ```sql
3754    /// UPDATE
3755    /// ```
3756    Update(Update),
3757    /// ```sql
3758    /// DELETE
3759    /// ```
3760    Delete(Delete),
3761    /// ```sql
3762    /// CREATE VIEW
3763    /// ```
3764    CreateView(CreateView),
3765    /// ```sql
3766    /// CREATE TABLE
3767    /// ```
3768    CreateTable(CreateTable),
3769    /// ```sql
3770    /// CREATE VIRTUAL TABLE .. USING <module_name> (<module_args>)`
3771    /// ```
3772    /// Sqlite specific statement
3773    CreateVirtualTable {
3774        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
3775        /// Name of the virtual table module instance.
3776        name: ObjectName,
3777        /// `true` when `IF NOT EXISTS` was specified.
3778        if_not_exists: bool,
3779        /// Module name used by the virtual table.
3780        module_name: Ident,
3781        /// Arguments passed to the module.
3782        module_args: Vec<Ident>,
3783    },
3784    /// ```sql
3785    /// `CREATE INDEX`
3786    /// ```
3787    CreateIndex(CreateIndex),
3788    /// ```sql
3789    /// CREATE ROLE
3790    /// ```
3791    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createrole.html)
3792    CreateRole(CreateRole),
3793    /// ```sql
3794    /// CREATE SECRET
3795    /// ```
3796    /// See [DuckDB](https://duckdb.org/docs/sql/statements/create_secret.html)
3797    CreateSecret {
3798        /// `true` when `OR REPLACE` was specified.
3799        or_replace: bool,
3800        /// Optional `TEMPORARY` flag.
3801        temporary: Option<bool>,
3802        /// `true` when `IF NOT EXISTS` was present.
3803        if_not_exists: bool,
3804        /// Optional secret name.
3805        name: Option<Ident>,
3806        /// Optional storage specifier identifier.
3807        storage_specifier: Option<Ident>,
3808        /// The secret type identifier.
3809        secret_type: Ident,
3810        /// Additional secret options.
3811        options: Vec<SecretOption>,
3812    },
3813    /// A `CREATE SERVER` statement.
3814    CreateServer(CreateServerStatement),
3815    /// ```sql
3816    /// CREATE FOREIGN TABLE
3817    /// ```
3818    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createforeigntable.html)
3819    CreateForeignTable(CreateForeignTable),
3820    /// ```sql
3821    /// CREATE POLICY
3822    /// ```
3823    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createpolicy.html)
3824    CreatePolicy(CreatePolicy),
3825    /// ```sql
3826    /// CREATE CONNECTOR
3827    /// ```
3828    /// See [Hive](https://cwiki.apache.org/confluence/pages/viewpage.action?pageId=27362034#LanguageManualDDL-CreateDataConnectorCreateConnector)
3829    CreateConnector(CreateConnector),
3830    /// ```sql
3831    /// CREATE OPERATOR
3832    /// ```
3833    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createoperator.html)
3834    CreateOperator(CreateOperator),
3835    /// ```sql
3836    /// CREATE OPERATOR FAMILY
3837    /// ```
3838    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createopfamily.html)
3839    CreateOperatorFamily(CreateOperatorFamily),
3840    /// ```sql
3841    /// CREATE OPERATOR CLASS
3842    /// ```
3843    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createopclass.html)
3844    CreateOperatorClass(CreateOperatorClass),
3845    /// A `CREATE TEXT SEARCH` statement.
3846    ///
3847    /// See [PostgreSQL](https://www.postgresql.org/docs/current/textsearch-intro.html)
3848    CreateTextSearch(CreateTextSearch),
3849    /// ```sql
3850    /// ALTER TABLE
3851    /// ```
3852    AlterTable(AlterTable),
3853    /// ```sql
3854    /// ALTER SCHEMA
3855    /// ```
3856    /// See [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#alter_schema_collate_statement)
3857    AlterSchema(AlterSchema),
3858    /// ```sql
3859    /// ALTER INDEX
3860    /// ```
3861    AlterIndex {
3862        /// Whether `IF EXISTS` was specified.
3863        if_exists: bool,
3864        /// Name of the index to alter.
3865        name: ObjectName,
3866        /// The operation to perform on the index.
3867        operation: AlterIndexOperation,
3868    },
3869    /// ```sql
3870    /// ALTER TRIGGER name ON table RENAME TO new_name
3871    /// ```
3872    AlterTrigger {
3873        /// Name of the trigger to alter.
3874        name: Ident,
3875        /// Table containing the trigger.
3876        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
3877        table_name: ObjectName,
3878        /// New trigger name.
3879        new_name: Ident,
3880    },
3881    /// ```sql
3882    /// ALTER VIEW
3883    /// ```
3884    AlterView {
3885        /// View name being altered.
3886        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
3887        name: ObjectName,
3888        /// Optional new column list for the view.
3889        columns: Vec<Ident>,
3890        /// Replacement query for the view definition.
3891        query: Box<Query>,
3892        /// Additional WITH options for the view.
3893        with_options: Vec<SqlOption>,
3894    },
3895    /// ```sql
3896    /// ALTER FUNCTION
3897    /// ALTER AGGREGATE
3898    /// ```
3899    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-alterfunction.html)
3900    /// and [PostgreSQL](https://www.postgresql.org/docs/current/sql-alteraggregate.html)
3901    AlterFunction(AlterFunction),
3902    /// ```sql
3903    /// ALTER TYPE
3904    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-altertype.html)
3905    /// ```
3906    AlterType(AlterType),
3907    /// ```sql
3908    /// ALTER COLLATION
3909    /// ```
3910    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-altercollation.html)
3911    AlterCollation(AlterCollation),
3912    /// ```sql
3913    /// ALTER OPERATOR
3914    /// ```
3915    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-alteroperator.html)
3916    AlterOperator(AlterOperator),
3917    /// ```sql
3918    /// ALTER OPERATOR FAMILY
3919    /// ```
3920    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-alteropfamily.html)
3921    AlterOperatorFamily(AlterOperatorFamily),
3922    /// ```sql
3923    /// ALTER OPERATOR CLASS
3924    /// ```
3925    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-alteropclass.html)
3926    AlterOperatorClass(AlterOperatorClass),
3927    /// An `ALTER TEXT SEARCH` statement.
3928    ///
3929    /// See [PostgreSQL](https://www.postgresql.org/docs/current/textsearch-configuration.html)
3930    AlterTextSearch(AlterTextSearch),
3931    /// ```sql
3932    /// ALTER ROLE
3933    /// ```
3934    AlterRole {
3935        /// Role name being altered.
3936        name: Ident,
3937        /// Operation to perform on the role.
3938        operation: AlterRoleOperation,
3939    },
3940    /// ```sql
3941    /// ALTER POLICY <NAME> ON <TABLE NAME> [<OPERATION>]
3942    /// ```
3943    /// (Postgresql-specific)
3944    AlterPolicy(AlterPolicy),
3945    /// ```sql
3946    /// ALTER CONNECTOR connector_name SET DCPROPERTIES(property_name=property_value, ...);
3947    /// or
3948    /// ALTER CONNECTOR connector_name SET URL new_url;
3949    /// or
3950    /// ALTER CONNECTOR connector_name SET OWNER [USER|ROLE] user_or_role;
3951    /// ```
3952    /// (Hive-specific)
3953    AlterConnector {
3954        /// Name of the connector to alter.
3955        name: Ident,
3956        /// Optional connector properties to set.
3957        properties: Option<Vec<SqlOption>>,
3958        /// Optional new URL for the connector.
3959        url: Option<String>,
3960        /// Optional new owner specification.
3961        owner: Option<ddl::AlterConnectorOwner>,
3962    },
3963    /// ```sql
3964    /// ALTER SESSION SET sessionParam
3965    /// ALTER SESSION UNSET <param_name> [ , <param_name> , ... ]
3966    /// ```
3967    /// See <https://docs.snowflake.com/en/sql-reference/sql/alter-session>
3968    AlterSession {
3969        /// true is to set for the session parameters, false is to unset
3970        set: bool,
3971        /// The session parameters to set or unset
3972        session_params: KeyValueOptions,
3973    },
3974    /// ```sql
3975    /// ATTACH DATABASE 'path/to/file' AS alias
3976    /// ```
3977    /// (SQLite-specific)
3978    AttachDatabase {
3979        /// The name to bind to the newly attached database
3980        schema_name: Ident,
3981        /// An expression that indicates the path to the database file
3982        database_file_name: Expr,
3983        /// true if the syntax is 'ATTACH DATABASE', false if it's just 'ATTACH'
3984        database: bool,
3985    },
3986    /// (DuckDB-specific)
3987    /// ```sql
3988    /// ATTACH 'sqlite_file.db' AS sqlite_db (READ_ONLY, TYPE SQLITE);
3989    /// ```
3990    /// See <https://duckdb.org/docs/sql/statements/attach.html>
3991    AttachDuckDBDatabase {
3992        /// `true` when `IF NOT EXISTS` was present.
3993        if_not_exists: bool,
3994        /// `true` if the syntax used `ATTACH DATABASE` rather than `ATTACH`.
3995        database: bool,
3996        /// The path identifier to the database file being attached.
3997        database_path: Ident,
3998        /// Optional alias assigned to the attached database.
3999        database_alias: Option<Ident>,
4000        /// Dialect-specific attach options (e.g., `READ_ONLY`).
4001        attach_options: Vec<AttachDuckDBDatabaseOption>,
4002    },
4003    /// (DuckDB-specific)
4004    /// ```sql
4005    /// DETACH db_alias;
4006    /// ```
4007    /// See <https://duckdb.org/docs/sql/statements/attach.html>
4008    DetachDuckDBDatabase {
4009        /// `true` when `IF EXISTS` was present.
4010        if_exists: bool,
4011        /// `true` if the syntax used `DETACH DATABASE` rather than `DETACH`.
4012        database: bool,
4013        /// Alias of the database to detach.
4014        database_alias: Ident,
4015    },
4016    /// ```sql
4017    /// DROP [TABLE, VIEW, ...]
4018    /// ```
4019    Drop {
4020        /// The type of the object to drop: TABLE, VIEW, etc.
4021        object_type: ObjectType,
4022        /// An optional `IF EXISTS` clause. (Non-standard.)
4023        if_exists: bool,
4024        /// One or more objects to drop. (ANSI SQL requires exactly one.)
4025        names: Vec<ObjectName>,
4026        /// Whether `CASCADE` was specified. This will be `false` when
4027        /// `RESTRICT` or no drop behavior at all was specified.
4028        cascade: bool,
4029        /// Whether `RESTRICT` was specified. This will be `false` when
4030        /// `CASCADE` or no drop behavior at all was specified.
4031        restrict: bool,
4032        /// Hive allows you specify whether the table's stored data will be
4033        /// deleted along with the dropped table
4034        purge: bool,
4035        /// MySQL-specific "TEMPORARY" keyword
4036        temporary: bool,
4037        /// MySQL-specific drop index syntax, which requires table specification
4038        /// See <https://dev.mysql.com/doc/refman/8.4/en/drop-index.html>
4039        table: Option<ObjectName>,
4040    },
4041    /// ```sql
4042    /// DROP FUNCTION
4043    /// ```
4044    DropFunction(DropFunction),
4045    /// ```sql
4046    /// DROP DOMAIN
4047    /// ```
4048    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-dropdomain.html)
4049    ///
4050    /// DROP DOMAIN [ IF EXISTS ] name [, ...] [ CASCADE | RESTRICT ]
4051    ///
4052    DropDomain(DropDomain),
4053    /// ```sql
4054    /// DROP PROCEDURE
4055    /// ```
4056    DropProcedure {
4057        /// `true` when `IF EXISTS` was present.
4058        if_exists: bool,
4059        /// One or more functions/procedures to drop.
4060        proc_desc: Vec<FunctionDesc>,
4061        /// Optional drop behavior (`CASCADE` or `RESTRICT`).
4062        drop_behavior: Option<DropBehavior>,
4063    },
4064    /// ```sql
4065    /// DROP SECRET
4066    /// ```
4067    DropSecret {
4068        /// `true` when `IF EXISTS` was present.
4069        if_exists: bool,
4070        /// Optional `TEMPORARY` marker.
4071        temporary: Option<bool>,
4072        /// Name of the secret to drop.
4073        name: Ident,
4074        /// Optional storage specifier identifier.
4075        storage_specifier: Option<Ident>,
4076    },
4077    ///```sql
4078    /// DROP POLICY
4079    /// ```
4080    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-droppolicy.html)
4081    DropPolicy(DropPolicy),
4082    /// ```sql
4083    /// DROP CONNECTOR
4084    /// ```
4085    /// See [Hive](https://cwiki.apache.org/confluence/pages/viewpage.action?pageId=27362034#LanguageManualDDL-DropConnector)
4086    DropConnector {
4087        /// `true` when `IF EXISTS` was present.
4088        if_exists: bool,
4089        /// Name of the connector to drop.
4090        name: Ident,
4091    },
4092    /// ```sql
4093    /// DECLARE
4094    /// ```
4095    /// Declare Cursor Variables
4096    ///
4097    /// Note: this is a PostgreSQL-specific statement,
4098    /// but may also compatible with other SQL.
4099    Declare {
4100        /// Cursor declaration statements collected by `DECLARE`.
4101        stmts: Vec<Declare>,
4102    },
4103    /// ```sql
4104    /// CREATE EXTENSION [ IF NOT EXISTS ] extension_name
4105    ///     [ WITH ] [ SCHEMA schema_name ]
4106    ///              [ VERSION version ]
4107    ///              [ CASCADE ]
4108    /// ```
4109    ///
4110    /// Note: this is a PostgreSQL-specific statement,
4111    CreateExtension(CreateExtension),
4112    /// ```sql
4113    /// CREATE COLLATION
4114    /// ```
4115    /// Note: this is a PostgreSQL-specific statement.
4116    /// <https://www.postgresql.org/docs/current/sql-createcollation.html>
4117    CreateCollation(CreateCollation),
4118    /// ```sql
4119    /// DROP EXTENSION [ IF EXISTS ] name [, ...] [ CASCADE | RESTRICT ]
4120    /// ```
4121    /// Note: this is a PostgreSQL-specific statement.
4122    /// <https://www.postgresql.org/docs/current/sql-dropextension.html>
4123    DropExtension(DropExtension),
4124    /// ```sql
4125    /// DROP OPERATOR [ IF EXISTS ] name ( { left_type | NONE } , right_type ) [, ...] [ CASCADE | RESTRICT ]
4126    /// ```
4127    /// Note: this is a PostgreSQL-specific statement.
4128    /// <https://www.postgresql.org/docs/current/sql-dropoperator.html>
4129    DropOperator(DropOperator),
4130    /// ```sql
4131    /// DROP OPERATOR FAMILY [ IF EXISTS ] name USING index_method [ CASCADE | RESTRICT ]
4132    /// ```
4133    /// Note: this is a PostgreSQL-specific statement.
4134    /// <https://www.postgresql.org/docs/current/sql-dropopfamily.html>
4135    DropOperatorFamily(DropOperatorFamily),
4136    /// ```sql
4137    /// DROP OPERATOR CLASS [ IF EXISTS ] name USING index_method [ CASCADE | RESTRICT ]
4138    /// ```
4139    /// Note: this is a PostgreSQL-specific statement.
4140    /// <https://www.postgresql.org/docs/current/sql-dropopclass.html>
4141    DropOperatorClass(DropOperatorClass),
4142    /// ```sql
4143    /// FETCH
4144    /// ```
4145    /// Retrieve rows from a query using a cursor
4146    ///
4147    /// Note: this is a PostgreSQL-specific statement,
4148    /// but may also compatible with other SQL.
4149    Fetch {
4150        /// Cursor name
4151        name: Ident,
4152        /// The fetch direction (e.g., `FORWARD`, `BACKWARD`).
4153        direction: FetchDirection,
4154        /// The fetch position (e.g., `ALL`, `NEXT`, `ABSOLUTE`).
4155        position: FetchPosition,
4156        /// Optional target table to fetch rows into.
4157        into: Option<ObjectName>,
4158    },
4159    /// ```sql
4160    /// FLUSH [NO_WRITE_TO_BINLOG | LOCAL] flush_option [, flush_option] ... | tables_option
4161    /// ```
4162    ///
4163    /// Note: this is a Mysql-specific statement,
4164    /// but may also compatible with other SQL.
4165    Flush {
4166        /// The specific flush option or object to flush.
4167        object_type: FlushType,
4168        /// Optional flush location (dialect-specific).
4169        location: Option<FlushLocation>,
4170        /// Optional channel name used for flush operations.
4171        channel: Option<String>,
4172        /// Whether a read lock was requested.
4173        read_lock: bool,
4174        /// Whether this is an export flush operation.
4175        export: bool,
4176        /// Optional list of tables involved in the flush.
4177        tables: Vec<ObjectName>,
4178    },
4179    /// ```sql
4180    /// DISCARD [ ALL | PLANS | SEQUENCES | TEMPORARY | TEMP ]
4181    /// ```
4182    ///
4183    /// Note: this is a PostgreSQL-specific statement,
4184    /// but may also compatible with other SQL.
4185    Discard {
4186        /// The kind of object(s) to discard (ALL, PLANS, etc.).
4187        object_type: DiscardObject,
4188    },
4189    /// `SHOW FUNCTIONS`
4190    ///
4191    /// Note: this is a Presto-specific statement.
4192    ShowFunctions {
4193        /// Optional filter for which functions to display.
4194        filter: Option<ShowStatementFilter>,
4195    },
4196    /// ```sql
4197    /// SHOW <variable>
4198    /// ```
4199    ///
4200    /// Note: this is a PostgreSQL-specific statement.
4201    ShowVariable {
4202        /// Variable name as one or more identifiers.
4203        variable: Vec<Ident>,
4204    },
4205    /// ```sql
4206    /// SHOW [GLOBAL | SESSION] STATUS [LIKE 'pattern' | WHERE expr]
4207    /// ```
4208    ///
4209    /// Note: this is a MySQL-specific statement.
4210    ShowStatus {
4211        /// Optional filter for which status entries to display.
4212        filter: Option<ShowStatementFilter>,
4213        /// `true` when `GLOBAL` scope was requested.
4214        global: bool,
4215        /// `true` when `SESSION` scope was requested.
4216        session: bool,
4217    },
4218    /// ```sql
4219    /// SHOW VARIABLES
4220    /// ```
4221    ///
4222    /// Note: this is a MySQL-specific statement.
4223    ShowVariables {
4224        /// Optional filter for which variables to display.
4225        filter: Option<ShowStatementFilter>,
4226        /// `true` when `GLOBAL` scope was requested.
4227        global: bool,
4228        /// `true` when `SESSION` scope was requested.
4229        session: bool,
4230    },
4231    /// ```sql
4232    /// SHOW CREATE TABLE
4233    /// ```
4234    ///
4235    /// Note: this is a MySQL-specific statement.
4236    ShowCreate {
4237        /// The kind of object being shown (TABLE, VIEW, etc.).
4238        obj_type: ShowCreateObject,
4239        /// The name of the object to show create statement for.
4240        obj_name: ObjectName,
4241    },
4242    /// ```sql
4243    /// SHOW COLUMNS
4244    /// ```
4245    ShowColumns {
4246        /// `true` when extended column information was requested.
4247        extended: bool,
4248        /// `true` when full column details were requested.
4249        full: bool,
4250        /// Additional options for `SHOW COLUMNS`.
4251        show_options: ShowStatementOptions,
4252    },
4253    /// ```sql
4254    /// SHOW CATALOGS
4255    /// ```
4256    ShowCatalogs {
4257        /// `true` when terse output format was requested.
4258        terse: bool,
4259        /// `true` when history information was requested.
4260        history: bool,
4261        /// Additional options for `SHOW CATALOGS`.
4262        show_options: ShowStatementOptions,
4263    },
4264    /// ```sql
4265    /// SHOW DATABASES
4266    /// ```
4267    ShowDatabases {
4268        /// `true` when terse output format was requested.
4269        terse: bool,
4270        /// `true` when history information was requested.
4271        history: bool,
4272        /// Additional options for `SHOW DATABASES`.
4273        show_options: ShowStatementOptions,
4274    },
4275    /// ```sql
4276    /// SHOW [FULL] PROCESSLIST
4277    /// ```
4278    ///
4279    /// Note: this is a MySQL-specific statement.
4280    ShowProcessList {
4281        /// `true` when full process information was requested.
4282        full: bool,
4283    },
4284    /// ```sql
4285    /// SHOW SCHEMAS
4286    /// ```
4287    ShowSchemas {
4288        /// `true` when terse (compact) output was requested.
4289        terse: bool,
4290        /// `true` when history information was requested.
4291        history: bool,
4292        /// Additional options for `SHOW SCHEMAS`.
4293        show_options: ShowStatementOptions,
4294    },
4295    // ```sql
4296    // SHOW {CHARACTER SET | CHARSET}
4297    // ```
4298    // [MySQL]:
4299    // <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>
4300    /// Show the available character sets (alias `CHARSET`).
4301    ShowCharset(ShowCharset),
4302    /// ```sql
4303    /// SHOW OBJECTS LIKE 'line%' IN mydb.public
4304    /// ```
4305    /// Snowflake-specific statement
4306    /// <https://docs.snowflake.com/en/sql-reference/sql/show-objects>
4307    ShowObjects(ShowObjects),
4308    /// ```sql
4309    /// SHOW TABLES
4310    /// ```
4311    ShowTables {
4312        /// `true` when terse output format was requested (compact listing).
4313        terse: bool,
4314        /// `true` when history rows are requested.
4315        history: bool,
4316        /// `true` when extended information should be shown.
4317        extended: bool,
4318        /// `true` when a full listing was requested.
4319        full: bool,
4320        /// `true` when external tables should be included.
4321        external: bool,
4322        /// Additional options for `SHOW` statements.
4323        show_options: ShowStatementOptions,
4324    },
4325    /// ```sql
4326    /// SHOW VIEWS
4327    /// ```
4328    ShowViews {
4329        /// `true` when terse output format was requested.
4330        terse: bool,
4331        /// `true` when materialized views should be included.
4332        materialized: bool,
4333        /// Additional options for `SHOW` statements.
4334        show_options: ShowStatementOptions,
4335    },
4336    /// ```sql
4337    /// SHOW COLLATION
4338    /// ```
4339    ///
4340    /// Note: this is a MySQL-specific statement.
4341    ShowCollation {
4342        /// Optional filter for which collations to display.
4343        filter: Option<ShowStatementFilter>,
4344    },
4345    /// ```sql
4346    /// `USE ...`
4347    /// ```
4348    Use(Use),
4349    /// ```sql
4350    /// START  [ TRANSACTION | WORK ] | START TRANSACTION } ...
4351    /// ```
4352    /// If `begin` is false.
4353    ///
4354    /// ```sql
4355    /// `BEGIN  [ TRANSACTION | WORK ] | START TRANSACTION } ...`
4356    /// ```
4357    /// If `begin` is true
4358    StartTransaction {
4359        /// Transaction modes such as `ISOLATION LEVEL` or `READ WRITE`.
4360        modes: Vec<TransactionMode>,
4361        /// `true` when this was parsed as `BEGIN` instead of `START`.
4362        begin: bool,
4363        /// Optional specific keyword used: `TRANSACTION` or `WORK`.
4364        transaction: Option<BeginTransactionKind>,
4365        /// Optional transaction modifier (e.g., `AND NO CHAIN`).
4366        modifier: Option<TransactionModifier>,
4367        /// List of statements belonging to the `BEGIN` block.
4368        /// Example:
4369        /// ```sql
4370        /// BEGIN
4371        ///     SELECT 1;
4372        ///     SELECT 2;
4373        /// END;
4374        /// ```
4375        statements: Vec<Statement>,
4376        /// Exception handling with exception clauses.
4377        /// Example:
4378        /// ```sql
4379        /// EXCEPTION
4380        ///     WHEN EXCEPTION_1 THEN
4381        ///         SELECT 2;
4382        ///     WHEN EXCEPTION_2 OR EXCEPTION_3 THEN
4383        ///         SELECT 3;
4384        ///     WHEN OTHER THEN
4385        ///         SELECT 4;
4386        /// ```
4387        /// <https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#beginexceptionend>
4388        /// <https://docs.snowflake.com/en/sql-reference/snowflake-scripting/exception>
4389        exception: Option<Vec<ExceptionWhen>>,
4390        /// TRUE if the statement has an `END` keyword.
4391        has_end_keyword: bool,
4392    },
4393    /// ```sql
4394    /// COMMENT ON ...
4395    /// ```
4396    ///
4397    /// Note: this is a PostgreSQL-specific statement.
4398    Comment {
4399        /// Type of object being commented (table, column, etc.).
4400        object_type: CommentObject,
4401        /// Name of the object the comment applies to.
4402        object_name: ObjectName,
4403        /// Optional comment text (None to remove comment).
4404        comment: Option<String>,
4405        /// An optional `IF EXISTS` clause. (Non-standard.)
4406        /// See <https://docs.snowflake.com/en/sql-reference/sql/comment>
4407        if_exists: bool,
4408    },
4409    /// ```sql
4410    /// COMMIT [ TRANSACTION | WORK ] [ AND [ NO ] CHAIN ]
4411    /// ```
4412    /// If `end` is false
4413    ///
4414    /// ```sql
4415    /// END [ TRY | CATCH ]
4416    /// ```
4417    /// If `end` is true
4418    Commit {
4419        /// `true` when `AND [ NO ] CHAIN` was present.
4420        chain: bool,
4421        /// `true` when this `COMMIT` was parsed as an `END` block terminator.
4422        end: bool,
4423        /// Optional transaction modifier for commit semantics.
4424        modifier: Option<TransactionModifier>,
4425    },
4426    /// ```sql
4427    /// ROLLBACK [ TRANSACTION | WORK ] [ AND [ NO ] CHAIN ] [ TO [ SAVEPOINT ] savepoint_name ]
4428    /// ```
4429    Rollback {
4430        /// `true` when `AND [ NO ] CHAIN` was present.
4431        chain: bool,
4432        /// Optional savepoint name to roll back to.
4433        savepoint: Option<Ident>,
4434    },
4435    /// ```sql
4436    /// CREATE SCHEMA
4437    /// ```
4438    CreateSchema {
4439        /// `<schema name> | AUTHORIZATION <schema authorization identifier>  | <schema name>  AUTHORIZATION <schema authorization identifier>`
4440        schema_name: SchemaName,
4441        /// `true` when `OR REPLACE` was present.
4442        or_replace: bool,
4443        /// `true` when `IF NOT EXISTS` was present.
4444        if_not_exists: bool,
4445        /// Schema properties.
4446        ///
4447        /// ```sql
4448        /// CREATE SCHEMA myschema WITH (key1='value1');
4449        /// ```
4450        ///
4451        /// [Trino](https://trino.io/docs/current/sql/create-schema.html)
4452        with: Option<Vec<SqlOption>>,
4453        /// Schema options.
4454        ///
4455        /// ```sql
4456        /// CREATE SCHEMA myschema OPTIONS(key1='value1');
4457        /// ```
4458        ///
4459        /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_schema_statement)
4460        options: Option<Vec<SqlOption>>,
4461        /// Default collation specification for the schema.
4462        ///
4463        /// ```sql
4464        /// CREATE SCHEMA myschema DEFAULT COLLATE 'und:ci';
4465        /// ```
4466        ///
4467        /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_schema_statement)
4468        default_collate_spec: Option<Expr>,
4469        /// Clones a schema
4470        ///
4471        /// ```sql
4472        /// CREATE SCHEMA myschema CLONE otherschema
4473        /// ```
4474        ///
4475        /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-clone#databases-schemas)
4476        clone: Option<ObjectName>,
4477    },
4478    /// ```sql
4479    /// CREATE DATABASE
4480    /// ```
4481    /// See:
4482    /// <https://docs.snowflake.com/en/sql-reference/sql/create-database>
4483    CreateDatabase {
4484        /// Database name.
4485        db_name: ObjectName,
4486        /// `IF NOT EXISTS` flag.
4487        if_not_exists: bool,
4488        /// Optional location URI.
4489        location: Option<String>,
4490        /// Optional managed location.
4491        managed_location: Option<String>,
4492        /// `OR REPLACE` flag.
4493        or_replace: bool,
4494        /// `TRANSIENT` flag.
4495        transient: bool,
4496        /// Optional clone source.
4497        clone: Option<ObjectName>,
4498        /// Optional data retention time in days.
4499        data_retention_time_in_days: Option<u64>,
4500        /// Optional maximum data extension time in days.
4501        max_data_extension_time_in_days: Option<u64>,
4502        /// Optional external volume identifier.
4503        external_volume: Option<String>,
4504        /// Optional catalog name.
4505        catalog: Option<String>,
4506        /// Whether to replace invalid characters.
4507        replace_invalid_characters: Option<bool>,
4508        /// Default DDL collation string.
4509        default_ddl_collation: Option<String>,
4510        /// Storage serialization policy.
4511        storage_serialization_policy: Option<StorageSerializationPolicy>,
4512        /// Optional comment.
4513        comment: Option<String>,
4514        /// Optional default character set (MySQL).
4515        default_charset: Option<String>,
4516        /// Optional default collation (MySQL).
4517        default_collation: Option<String>,
4518        /// Optional catalog sync identifier.
4519        catalog_sync: Option<String>,
4520        /// Catalog sync namespace mode.
4521        catalog_sync_namespace_mode: Option<CatalogSyncNamespaceMode>,
4522        /// Optional flatten delimiter for namespace sync.
4523        catalog_sync_namespace_flatten_delimiter: Option<String>,
4524        /// Optional tags for the database.
4525        with_tags: Option<Vec<Tag>>,
4526        /// Optional contact entries for the database.
4527        with_contacts: Option<Vec<ContactEntry>>,
4528    },
4529    /// ```sql
4530    /// CREATE FUNCTION
4531    /// ```
4532    ///
4533    /// Supported variants:
4534    /// 1. [Hive](https://cwiki.apache.org/confluence/display/hive/languagemanual+ddl#LanguageManualDDL-Create/Drop/ReloadFunction)
4535    /// 2. [PostgreSQL](https://www.postgresql.org/docs/15/sql-createfunction.html)
4536    /// 3. [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_function_statement)
4537    /// 4. [MsSql](https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql)
4538    CreateFunction(CreateFunction),
4539    /// CREATE TRIGGER statement. See struct [CreateTrigger] for details.
4540    CreateTrigger(CreateTrigger),
4541    /// DROP TRIGGER statement. See struct [DropTrigger] for details.
4542    DropTrigger(DropTrigger),
4543    /// ```sql
4544    /// CREATE PROCEDURE
4545    /// ```
4546    CreateProcedure {
4547        /// `OR ALTER` flag.
4548        or_alter: bool,
4549        /// Procedure name.
4550        name: ObjectName,
4551        /// Optional procedure parameters.
4552        params: Option<Vec<ProcedureParam>>,
4553        /// Optional language identifier.
4554        language: Option<Ident>,
4555        /// Procedure body statements.
4556        body: ConditionalStatements,
4557    },
4558    /// ```sql
4559    /// CREATE MACRO
4560    /// ```
4561    ///
4562    /// Supported variants:
4563    /// 1. [DuckDB](https://duckdb.org/docs/sql/statements/create_macro)
4564    CreateMacro {
4565        /// `OR REPLACE` flag.
4566        or_replace: bool,
4567        /// Whether macro is temporary.
4568        temporary: bool,
4569        /// Macro name.
4570        name: ObjectName,
4571        /// Optional macro arguments.
4572        args: Option<Vec<MacroArg>>,
4573        /// Macro definition body.
4574        definition: MacroDefinition,
4575    },
4576    /// ```sql
4577    /// CREATE STAGE
4578    /// ```
4579    /// See <https://docs.snowflake.com/en/sql-reference/sql/create-stage>
4580    CreateStage {
4581        /// `OR REPLACE` flag for stage.
4582        or_replace: bool,
4583        /// Whether stage is temporary.
4584        temporary: bool,
4585        /// `IF NOT EXISTS` flag.
4586        if_not_exists: bool,
4587        /// Stage name.
4588        name: ObjectName,
4589        /// Stage parameters.
4590        stage_params: StageParamsObject,
4591        /// Directory table parameters.
4592        directory_table_params: KeyValueOptions,
4593        /// File format options.
4594        file_format: KeyValueOptions,
4595        /// Copy options for stage.
4596        copy_options: KeyValueOptions,
4597        /// Optional comment.
4598        comment: Option<String>,
4599    },
4600    /// ```sql
4601    /// CREATE [ OR REPLACE ] [ { TEMP | TEMPORARY | VOLATILE } ] FILE FORMAT [ IF NOT EXISTS ] <name>
4602    ///   [ TYPE = { CSV | JSON | AVRO | ORC | PARQUET | XML } [ formatTypeOptions ] ]
4603    ///   [ COMMENT = '<string_literal>' ]
4604    /// ```
4605    /// See <https://docs.snowflake.com/en/sql-reference/sql/create-file-format>
4606    CreateFileFormat {
4607        /// `OR REPLACE` flag.
4608        or_replace: bool,
4609        /// Whether file format is temporary.
4610        temporary: bool,
4611        /// Whether file format is volatile.
4612        volatile: bool,
4613        /// `IF NOT EXISTS` flag.
4614        if_not_exists: bool,
4615        /// File format name.
4616        name: ObjectName,
4617        /// Format type options (e.g. `TYPE`, `FIELD_DELIMITER`, `COMPRESSION`, ...).
4618        options: KeyValueOptions,
4619        /// Optional comment.
4620        comment: Option<String>,
4621    },
4622    /// ```sql
4623    /// CREATE [ OR REPLACE ] WAREHOUSE [ IF NOT EXISTS ] <name>
4624    ///   [ [ WITH ] <property> = <value> [ ... ] ]
4625    /// ```
4626    /// Snowflake-specific statement to create a virtual warehouse.
4627    ///
4628    /// See <https://docs.snowflake.com/en/sql-reference/sql/create-warehouse>
4629    CreateWarehouse(CreateWarehouse),
4630    /// ```sql
4631    /// ASSERT <condition> [AS <message>]
4632    /// ```
4633    Assert {
4634        /// Assertion condition expression.
4635        condition: Expr,
4636        /// Optional message expression.
4637        message: Option<Expr>,
4638    },
4639    /// ```sql
4640    /// GRANT privileges ON objects TO grantees
4641    /// ```
4642    Grant(Grant),
4643    /// ```sql
4644    /// DENY privileges ON object TO grantees
4645    /// ```
4646    Deny(DenyStatement),
4647    /// ```sql
4648    /// REVOKE privileges ON objects FROM grantees
4649    /// ```
4650    Revoke(Revoke),
4651    /// ```sql
4652    /// DEALLOCATE [ PREPARE ] { name | ALL }
4653    /// ```
4654    ///
4655    /// Note: this is a PostgreSQL-specific statement.
4656    Deallocate {
4657        /// Name to deallocate (or `ALL`).
4658        name: Ident,
4659        /// Whether `PREPARE` keyword was present.
4660        prepare: bool,
4661    },
4662    /// ```sql
4663    /// An `EXECUTE` statement
4664    /// ```
4665    ///
4666    /// Postgres: <https://www.postgresql.org/docs/current/sql-execute.html>
4667    /// MSSQL: <https://learn.microsoft.com/en-us/sql/relational-databases/stored-procedures/execute-a-stored-procedure>
4668    /// BigQuery: <https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#execute_immediate>
4669    /// Snowflake: <https://docs.snowflake.com/en/sql-reference/sql/execute-immediate>
4670    Execute {
4671        /// Optional function/procedure name.
4672        name: Option<ObjectName>,
4673        /// Parameter expressions passed to execute.
4674        parameters: Vec<Expr>,
4675        /// Whether parentheses were present around `parameters`.
4676        has_parentheses: bool,
4677        /// Is this an `EXECUTE IMMEDIATE`.
4678        immediate: bool,
4679        /// Identifiers to capture results into.
4680        into: Vec<Ident>,
4681        /// `USING` expressions with optional aliases.
4682        using: Vec<ExprWithAlias>,
4683        /// Whether the last parameter is the return value of the procedure
4684        /// MSSQL: <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/execute-transact-sql?view=sql-server-ver17#output>
4685        output: bool,
4686        /// Whether to invoke the procedure with the default parameter values
4687        /// MSSQL: <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/execute-transact-sql?view=sql-server-ver17#default>
4688        default: bool,
4689    },
4690    /// ```sql
4691    /// PREPARE name [ ( data_type [, ...] ) ] AS statement
4692    /// ```
4693    ///
4694    /// Note: this is a PostgreSQL-specific statement.
4695    Prepare {
4696        /// Name of the prepared statement.
4697        name: Ident,
4698        /// Optional data types for parameters.
4699        data_types: Vec<DataType>,
4700        /// Statement being prepared.
4701        statement: Box<Statement>,
4702    },
4703    /// ```sql
4704    /// KILL [CONNECTION | QUERY | MUTATION]
4705    /// ```
4706    ///
4707    /// See <https://clickhouse.com/docs/en/sql-reference/statements/kill/>
4708    /// See <https://dev.mysql.com/doc/refman/8.0/en/kill.html>
4709    Kill {
4710        /// Optional kill modifier (CONNECTION, QUERY, MUTATION).
4711        modifier: Option<KillType>,
4712        // processlist_id
4713        /// The id of the process to kill.
4714        id: u64,
4715    },
4716    /// ```sql
4717    /// [EXPLAIN | DESC | DESCRIBE] TABLE
4718    /// ```
4719    /// Note: this is a MySQL-specific statement. See <https://dev.mysql.com/doc/refman/8.0/en/explain.html>
4720    ExplainTable {
4721        /// `EXPLAIN | DESC | DESCRIBE`
4722        describe_alias: DescribeAlias,
4723        /// Hive style `FORMATTED | EXTENDED`
4724        hive_format: Option<HiveDescribeFormat>,
4725        /// Snowflake and ClickHouse support `DESC|DESCRIBE TABLE <table_name>` syntax
4726        ///
4727        /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/desc-table.html)
4728        /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/describe-table)
4729        has_table_keyword: bool,
4730        /// Table name
4731        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
4732        table_name: ObjectName,
4733    },
4734    /// ```sql
4735    /// [EXPLAIN | DESC | DESCRIBE]  <statement>
4736    /// ```
4737    Explain {
4738        /// `EXPLAIN | DESC | DESCRIBE`
4739        describe_alias: DescribeAlias,
4740        /// Carry out the command and show actual run times and other statistics.
4741        analyze: bool,
4742        /// Display additional information regarding the plan.
4743        verbose: bool,
4744        /// `EXPLAIN QUERY PLAN`
4745        /// Display the query plan without running the query.
4746        ///
4747        /// [SQLite](https://sqlite.org/lang_explain.html)
4748        query_plan: bool,
4749        /// `EXPLAIN ESTIMATE`
4750        /// [Clickhouse](https://clickhouse.com/docs/en/sql-reference/statements/explain#explain-estimate)
4751        estimate: bool,
4752        /// A SQL query that specifies what to explain
4753        statement: Box<Statement>,
4754        /// Optional output format of explain
4755        format: Option<AnalyzeFormatKind>,
4756        /// Postgres style utility options, `(analyze, verbose true)`
4757        options: Option<Vec<UtilityOption>>,
4758    },
4759    /// ```sql
4760    /// SAVEPOINT
4761    /// ```
4762    /// Define a new savepoint within the current transaction
4763    Savepoint {
4764        /// Name of the savepoint being defined.
4765        name: Ident,
4766    },
4767    /// ```sql
4768    /// RELEASE [ SAVEPOINT ] savepoint_name
4769    /// ```
4770    ReleaseSavepoint {
4771        /// Name of the savepoint to release.
4772        name: Ident,
4773    },
4774    /// A `MERGE` statement.
4775    ///
4776    /// ```sql
4777    /// MERGE INTO <target_table> USING <source> ON <join_expr> { matchedClause | notMatchedClause } [ ... ]
4778    /// ```
4779    /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/merge)
4780    /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/dml-syntax#merge_statement)
4781    /// [MSSQL](https://learn.microsoft.com/en-us/sql/t-sql/statements/merge-transact-sql?view=sql-server-ver16)
4782    Merge(Merge),
4783    /// ```sql
4784    /// CACHE [ FLAG ] TABLE <table_name> [ OPTIONS('K1' = 'V1', 'K2' = V2) ] [ AS ] [ <query> ]
4785    /// ```
4786    ///
4787    /// See [Spark SQL docs] for more details.
4788    ///
4789    /// [Spark SQL docs]: https://docs.databricks.com/spark/latest/spark-sql/language-manual/sql-ref-syntax-aux-cache-cache-table.html
4790    Cache {
4791        /// Table flag
4792        table_flag: Option<ObjectName>,
4793        /// Table name
4794        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
4795        table_name: ObjectName,
4796        /// `true` if `AS` keyword was present before the query.
4797        has_as: bool,
4798        /// Table confs
4799        options: Vec<SqlOption>,
4800        /// Cache table as a Query
4801        query: Option<Box<Query>>,
4802    },
4803    /// ```sql
4804    /// UNCACHE TABLE [ IF EXISTS ]  <table_name>
4805    /// ```
4806    UNCache {
4807        /// Table name
4808        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
4809        table_name: ObjectName,
4810        /// `true` when `IF EXISTS` was present.
4811        if_exists: bool,
4812    },
4813    /// ```sql
4814    /// CREATE [ { TEMPORARY | TEMP } ] SEQUENCE [ IF NOT EXISTS ] <sequence_name>
4815    /// ```
4816    /// Define a new sequence:
4817    CreateSequence {
4818        /// Whether the sequence is temporary.
4819        temporary: bool,
4820        /// `IF NOT EXISTS` flag.
4821        if_not_exists: bool,
4822        /// Sequence name.
4823        name: ObjectName,
4824        /// Optional data type for the sequence.
4825        data_type: Option<DataType>,
4826        /// Sequence options (INCREMENT, MINVALUE, etc.).
4827        sequence_options: Vec<SequenceOptions>,
4828        /// Optional `OWNED BY` target.
4829        owned_by: Option<ObjectName>,
4830    },
4831    /// A `CREATE DOMAIN` statement.
4832    CreateDomain(CreateDomain),
4833    /// ```sql
4834    /// CREATE TYPE <name>
4835    /// ```
4836    CreateType {
4837        /// Type name to create.
4838        name: ObjectName,
4839        /// Optional type representation details.
4840        representation: Option<UserDefinedTypeRepresentation>,
4841    },
4842    /// ```sql
4843    /// PRAGMA <schema-name>.<pragma-name> = <pragma-value>
4844    /// ```
4845    Pragma {
4846        /// Pragma name (possibly qualified).
4847        name: ObjectName,
4848        /// Optional pragma value.
4849        value: Option<ValueWithSpan>,
4850        /// Whether the pragma used `=`.
4851        is_eq: bool,
4852    },
4853    /// ```sql
4854    /// LOCK [ TABLE ] [ ONLY ] name [ * ] [, ...] [ IN lockmode MODE ] [ NOWAIT ]
4855    /// ```
4856    ///
4857    /// See <https://www.postgresql.org/docs/current/sql-lock.html>
4858    Lock(Lock),
4859    /// ```sql
4860    /// LOCK TABLES <table_name> [READ [LOCAL] | [LOW_PRIORITY] WRITE]
4861    /// ```
4862    /// Note: this is a MySQL-specific statement. See <https://dev.mysql.com/doc/refman/8.0/en/lock-tables.html>
4863    LockTables {
4864        /// List of tables to lock with modes.
4865        tables: Vec<LockTable>,
4866    },
4867    /// ```sql
4868    /// UNLOCK TABLES
4869    /// ```
4870    /// Note: this is a MySQL-specific statement. See <https://dev.mysql.com/doc/refman/8.0/en/lock-tables.html>
4871    UnlockTables,
4872    /// Unloads the result of a query to file
4873    ///
4874    /// [Athena](https://docs.aws.amazon.com/athena/latest/ug/unload.html):
4875    /// ```sql
4876    /// UNLOAD(statement) TO <destination> [ WITH options ]
4877    /// ```
4878    ///
4879    /// [Redshift](https://docs.aws.amazon.com/redshift/latest/dg/r_UNLOAD.html):
4880    /// ```sql
4881    /// UNLOAD('statement') TO <destination> [ OPTIONS ]
4882    /// ```
4883    Unload {
4884        /// Optional query AST to unload.
4885        query: Option<Box<Query>>,
4886        /// Optional original query text.
4887        query_text: Option<String>,
4888        /// Destination identifier.
4889        to: Ident,
4890        /// Optional IAM role/auth information.
4891        auth: Option<IamRoleKind>,
4892        /// Additional `WITH` options.
4893        with: Vec<SqlOption>,
4894        /// Legacy copy-style options.
4895        options: Vec<CopyLegacyOption>,
4896    },
4897    /// ClickHouse:
4898    /// ```sql
4899    /// OPTIMIZE TABLE [db.]name [ON CLUSTER cluster] [PARTITION partition | PARTITION ID 'partition_id'] [FINAL] [DEDUPLICATE [BY expression]]
4900    /// ```
4901    /// See ClickHouse <https://clickhouse.com/docs/en/sql-reference/statements/optimize>
4902    ///
4903    /// Databricks:
4904    /// ```sql
4905    /// OPTIMIZE table_name [WHERE predicate] [ZORDER BY (col_name1 [, ...])]
4906    /// ```
4907    /// See Databricks <https://docs.databricks.com/en/sql/language-manual/delta-optimize.html>
4908    OptimizeTable {
4909        /// Table name to optimize.
4910        name: ObjectName,
4911        /// Whether the `TABLE` keyword was present (ClickHouse uses `OPTIMIZE TABLE`, Databricks uses `OPTIMIZE`).
4912        has_table_keyword: bool,
4913        /// Optional cluster identifier.
4914        /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/optimize)
4915        on_cluster: Option<Ident>,
4916        /// Optional partition spec.
4917        /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/optimize)
4918        partition: Option<Partition>,
4919        /// Whether `FINAL` was specified.
4920        /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/optimize)
4921        include_final: bool,
4922        /// Optional deduplication settings.
4923        /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/optimize)
4924        deduplicate: Option<Deduplicate>,
4925        /// Optional WHERE predicate.
4926        /// [Databricks](https://docs.databricks.com/en/sql/language-manual/delta-optimize.html)
4927        predicate: Option<Expr>,
4928        /// Optional ZORDER BY columns.
4929        /// [Databricks](https://docs.databricks.com/en/sql/language-manual/delta-optimize.html)
4930        zorder: Option<Vec<Expr>>,
4931    },
4932    /// ```sql
4933    /// LISTEN
4934    /// ```
4935    /// listen for a notification channel
4936    ///
4937    /// See Postgres <https://www.postgresql.org/docs/current/sql-listen.html>
4938    LISTEN {
4939        /// Notification channel identifier.
4940        channel: Ident,
4941    },
4942    /// ```sql
4943    /// UNLISTEN
4944    /// ```
4945    /// stop listening for a notification
4946    ///
4947    /// See Postgres <https://www.postgresql.org/docs/current/sql-unlisten.html>
4948    UNLISTEN {
4949        /// Notification channel identifier.
4950        channel: Ident,
4951    },
4952    /// ```sql
4953    /// NOTIFY channel [ , payload ]
4954    /// ```
4955    /// send a notification event together with an optional "payload" string to channel
4956    ///
4957    /// See Postgres <https://www.postgresql.org/docs/current/sql-notify.html>
4958    NOTIFY {
4959        /// Notification channel identifier.
4960        channel: Ident,
4961        /// Optional payload string.
4962        payload: Option<String>,
4963    },
4964    /// ```sql
4965    /// LOAD DATA [LOCAL] INPATH 'filepath' [OVERWRITE] INTO TABLE tablename
4966    /// [PARTITION (partcol1=val1, partcol2=val2 ...)]
4967    /// [INPUTFORMAT 'inputformat' SERDE 'serde']
4968    /// ```
4969    /// Loading files into tables
4970    ///
4971    /// See Hive <https://cwiki.apache.org/confluence/pages/viewpage.action?pageId=27362036#LanguageManualDML-Loadingfilesintotables>
4972    LoadData {
4973        /// Whether `LOCAL` is present.
4974        local: bool,
4975        /// Input path for files to load.
4976        inpath: String,
4977        /// Whether `OVERWRITE` was specified.
4978        overwrite: bool,
4979        /// Target table name to load into.
4980        table_name: ObjectName,
4981        /// Optional partition specification.
4982        partitioned: Option<Vec<Expr>>,
4983        /// Optional table format information.
4984        table_format: Option<HiveLoadDataFormat>,
4985    },
4986    /// ```sql
4987    /// Rename TABLE tbl_name TO new_tbl_name[, tbl_name2 TO new_tbl_name2] ...
4988    /// ```
4989    /// Renames one or more tables
4990    ///
4991    /// See Mysql <https://dev.mysql.com/doc/refman/9.1/en/rename-table.html>
4992    RenameTable(Vec<RenameTable>),
4993    /// Snowflake `LIST`
4994    /// See: <https://docs.snowflake.com/en/sql-reference/sql/list>
4995    List(FileStagingCommand),
4996    /// Snowflake `PUT`
4997    /// ```sql
4998    /// PUT 'file://<path>' <internalStage> [ <option> = <value> ... ]
4999    /// ```
5000    /// Options include `PARALLEL`, `AUTO_COMPRESS`, `SOURCE_COMPRESSION`, `OVERWRITE`.
5001    /// See: <https://docs.snowflake.com/en/sql-reference/sql/put>
5002    Put {
5003        /// Local source URI as written in the statement, e.g. `file:///tmp/data.csv`.
5004        source: String,
5005        /// Target internal stage (e.g. `@mystage`, `@~`, `@%table`).
5006        stage: ObjectName,
5007        /// Trailing options (`PARALLEL=4`, `AUTO_COMPRESS=TRUE`, ...).
5008        options: KeyValueOptions,
5009    },
5010    /// Snowflake `REMOVE`
5011    /// See: <https://docs.snowflake.com/en/sql-reference/sql/remove>
5012    Remove(FileStagingCommand),
5013    /// RaiseError (MSSQL)
5014    /// RAISERROR ( { msg_id | msg_str | @local_variable }
5015    /// { , severity , state }
5016    /// [ , argument [ , ...n ] ] )
5017    /// [ WITH option [ , ...n ] ]
5018    /// See <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/raiserror-transact-sql?view=sql-server-ver16>
5019    RaisError {
5020        /// Error message expression or identifier.
5021        message: Box<Expr>,
5022        /// Severity expression.
5023        severity: Box<Expr>,
5024        /// State expression.
5025        state: Box<Expr>,
5026        /// Substitution arguments for the message.
5027        arguments: Vec<Expr>,
5028        /// Additional `WITH` options for RAISERROR.
5029        options: Vec<RaisErrorOption>,
5030    },
5031    /// A MSSQL `THROW` statement.
5032    Throw(ThrowStatement),
5033    /// ```sql
5034    /// PRINT msg_str | @local_variable | string_expr
5035    /// ```
5036    ///
5037    /// See: <https://learn.microsoft.com/en-us/sql/t-sql/statements/print-transact-sql>
5038    Print(PrintStatement),
5039    /// MSSQL `WAITFOR` statement.
5040    ///
5041    /// See: <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/waitfor-transact-sql>
5042    WaitFor(WaitForStatement),
5043    /// ```sql
5044    /// RETURN [ expression ]
5045    /// ```
5046    ///
5047    /// See [ReturnStatement]
5048    Return(ReturnStatement),
5049    /// Export data statement
5050    ///
5051    /// Example:
5052    /// ```sql
5053    /// EXPORT DATA OPTIONS(uri='gs://bucket/folder/*', format='PARQUET', overwrite=true) AS
5054    /// SELECT field1, field2 FROM mydataset.table1 ORDER BY field1 LIMIT 10
5055    /// ```
5056    /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/export-statements)
5057    ExportData(ExportData),
5058    /// ```sql
5059    /// CREATE [OR REPLACE] USER <user> [IF NOT EXISTS]
5060    /// ```
5061    /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-user)
5062    CreateUser(CreateUser),
5063    /// ```sql
5064    /// ALTER USER \[ IF EXISTS \] \[ <name> \]
5065    /// ```
5066    /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/alter-user)
5067    AlterUser(AlterUser),
5068    /// Re-sorts rows and reclaims space in either a specified table or all tables in the current database
5069    ///
5070    /// ```sql
5071    /// VACUUM tbl
5072    /// ```
5073    /// [Redshift](https://docs.aws.amazon.com/redshift/latest/dg/r_VACUUM_command.html)
5074    Vacuum(VacuumStatement),
5075    /// Restore the value of a run-time parameter to the default value.
5076    ///
5077    /// ```sql
5078    /// RESET configuration_parameter;
5079    /// RESET ALL;
5080    /// ```
5081    /// [PostgreSQL](https://www.postgresql.org/docs/current/sql-reset.html)
5082    Reset(ResetStatement),
5083}
5084
5085impl From<Analyze> for Statement {
5086    fn from(analyze: Analyze) -> Self {
5087        Statement::Analyze(analyze)
5088    }
5089}
5090
5091impl From<ddl::Truncate> for Statement {
5092    fn from(truncate: ddl::Truncate) -> Self {
5093        Statement::Truncate(truncate)
5094    }
5095}
5096
5097impl From<Lock> for Statement {
5098    fn from(lock: Lock) -> Self {
5099        Statement::Lock(lock)
5100    }
5101}
5102
5103impl From<ddl::Msck> for Statement {
5104    fn from(msck: ddl::Msck) -> Self {
5105        Statement::Msck(msck)
5106    }
5107}
5108
5109/// ```sql
5110/// {COPY | REVOKE} CURRENT GRANTS
5111/// ```
5112///
5113/// - [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/grant-ownership#optional-parameters)
5114#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
5115#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
5116#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
5117pub enum CurrentGrantsKind {
5118    /// `COPY CURRENT GRANTS` (copy current grants to target).
5119    CopyCurrentGrants,
5120    /// `REVOKE CURRENT GRANTS` (revoke current grants from target).
5121    RevokeCurrentGrants,
5122}
5123
5124impl fmt::Display for CurrentGrantsKind {
5125    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
5126        match self {
5127            CurrentGrantsKind::CopyCurrentGrants => write!(f, "COPY CURRENT GRANTS"),
5128            CurrentGrantsKind::RevokeCurrentGrants => write!(f, "REVOKE CURRENT GRANTS"),
5129        }
5130    }
5131}
5132
5133#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
5134#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
5135#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
5136/// `RAISERROR` options
5137/// See <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/raiserror-transact-sql?view=sql-server-ver16#options>
5138pub enum RaisErrorOption {
5139    /// Log the error.
5140    Log,
5141    /// Do not wait for completion.
5142    NoWait,
5143    /// Set the error state.
5144    SetError,
5145}
5146
5147impl fmt::Display for RaisErrorOption {
5148    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
5149        match self {
5150            RaisErrorOption::Log => write!(f, "LOG"),
5151            RaisErrorOption::NoWait => write!(f, "NOWAIT"),
5152            RaisErrorOption::SetError => write!(f, "SETERROR"),
5153        }
5154    }
5155}
5156
5157impl fmt::Display for Statement {
5158    /// Formats a SQL statement with support for pretty printing.
5159    ///
5160    /// When using the alternate flag (`{:#}`), the statement will be formatted with proper
5161    /// indentation and line breaks. For example:
5162    ///
5163    /// ```
5164    /// # use sqlparser::dialect::GenericDialect;
5165    /// # use sqlparser::parser::Parser;
5166    /// let sql = "SELECT a, b FROM table_1";
5167    /// let ast = Parser::parse_sql(&GenericDialect, sql).unwrap();
5168    ///
5169    /// // Regular formatting
5170    /// assert_eq!(format!("{}", ast[0]), "SELECT a, b FROM table_1");
5171    ///
5172    /// // Pretty printing
5173    /// assert_eq!(format!("{:#}", ast[0]),
5174    /// r#"SELECT
5175    ///   a,
5176    ///   b
5177    /// FROM
5178    ///   table_1"#);
5179    /// ```
5180    // Clippy thinks this function is too complicated, but it is painful to
5181    // split up without extracting structs for each `Statement` variant.
5182    #[allow(clippy::cognitive_complexity)]
5183    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
5184        match self {
5185            Statement::Flush {
5186                object_type,
5187                location,
5188                channel,
5189                read_lock,
5190                export,
5191                tables,
5192            } => {
5193                write!(f, "FLUSH")?;
5194                if let Some(location) = location {
5195                    f.write_str(" ")?;
5196                    location.fmt(f)?;
5197                }
5198                write!(f, " {object_type}")?;
5199
5200                if let Some(channel) = channel {
5201                    write!(f, " FOR CHANNEL {channel}")?;
5202                }
5203
5204                write!(
5205                    f,
5206                    "{tables}{read}{export}",
5207                    tables = if !tables.is_empty() {
5208                        format!(" {}", display_comma_separated(tables))
5209                    } else {
5210                        String::new()
5211                    },
5212                    export = if *export { " FOR EXPORT" } else { "" },
5213                    read = if *read_lock { " WITH READ LOCK" } else { "" }
5214                )
5215            }
5216            Statement::Kill { modifier, id } => {
5217                write!(f, "KILL ")?;
5218
5219                if let Some(m) = modifier {
5220                    write!(f, "{m} ")?;
5221                }
5222
5223                write!(f, "{id}")
5224            }
5225            Statement::ExplainTable {
5226                describe_alias,
5227                hive_format,
5228                has_table_keyword,
5229                table_name,
5230            } => {
5231                write!(f, "{describe_alias} ")?;
5232
5233                if let Some(format) = hive_format {
5234                    write!(f, "{format} ")?;
5235                }
5236                if *has_table_keyword {
5237                    write!(f, "TABLE ")?;
5238                }
5239
5240                write!(f, "{table_name}")
5241            }
5242            Statement::Explain {
5243                describe_alias,
5244                verbose,
5245                analyze,
5246                query_plan,
5247                estimate,
5248                statement,
5249                format,
5250                options,
5251            } => {
5252                write!(f, "{describe_alias} ")?;
5253
5254                if *query_plan {
5255                    write!(f, "QUERY PLAN ")?;
5256                }
5257                if *analyze {
5258                    write!(f, "ANALYZE ")?;
5259                }
5260                if *estimate {
5261                    write!(f, "ESTIMATE ")?;
5262                }
5263
5264                if *verbose {
5265                    write!(f, "VERBOSE ")?;
5266                }
5267
5268                if let Some(format) = format {
5269                    write!(f, "{format} ")?;
5270                }
5271
5272                if let Some(options) = options {
5273                    write!(f, "({}) ", display_comma_separated(options))?;
5274                }
5275
5276                write!(f, "{statement}")
5277            }
5278            Statement::Query(s) => s.fmt(f),
5279            Statement::Declare { stmts } => {
5280                write!(f, "DECLARE ")?;
5281                write!(f, "{}", display_separated(stmts, "; "))
5282            }
5283            Statement::Fetch {
5284                name,
5285                direction,
5286                position,
5287                into,
5288            } => {
5289                write!(f, "FETCH {direction} {position} {name}")?;
5290
5291                if let Some(into) = into {
5292                    write!(f, " INTO {into}")?;
5293                }
5294
5295                Ok(())
5296            }
5297            Statement::Directory {
5298                overwrite,
5299                local,
5300                path,
5301                file_format,
5302                source,
5303            } => {
5304                write!(
5305                    f,
5306                    "INSERT{overwrite}{local} DIRECTORY '{path}'",
5307                    overwrite = if *overwrite { " OVERWRITE" } else { "" },
5308                    local = if *local { " LOCAL" } else { "" },
5309                    path = path
5310                )?;
5311                if let Some(ref ff) = file_format {
5312                    write!(f, " STORED AS {ff}")?
5313                }
5314                write!(f, " {source}")
5315            }
5316            Statement::Msck(msck) => msck.fmt(f),
5317            Statement::Truncate(truncate) => truncate.fmt(f),
5318            Statement::Case(stmt) => {
5319                write!(f, "{stmt}")
5320            }
5321            Statement::If(stmt) => {
5322                write!(f, "{stmt}")
5323            }
5324            Statement::While(stmt) => {
5325                write!(f, "{stmt}")
5326            }
5327            Statement::Raise(stmt) => {
5328                write!(f, "{stmt}")
5329            }
5330            Statement::Do(stmt) => {
5331                write!(f, "{stmt}")
5332            }
5333            Statement::AttachDatabase {
5334                schema_name,
5335                database_file_name,
5336                database,
5337            } => {
5338                let keyword = if *database { "DATABASE " } else { "" };
5339                write!(f, "ATTACH {keyword}{database_file_name} AS {schema_name}")
5340            }
5341            Statement::AttachDuckDBDatabase {
5342                if_not_exists,
5343                database,
5344                database_path,
5345                database_alias,
5346                attach_options,
5347            } => {
5348                write!(
5349                    f,
5350                    "ATTACH{database}{if_not_exists} {database_path}",
5351                    database = if *database { " DATABASE" } else { "" },
5352                    if_not_exists = if *if_not_exists { " IF NOT EXISTS" } else { "" },
5353                )?;
5354                if let Some(alias) = database_alias {
5355                    write!(f, " AS {alias}")?;
5356                }
5357                if !attach_options.is_empty() {
5358                    write!(f, " ({})", display_comma_separated(attach_options))?;
5359                }
5360                Ok(())
5361            }
5362            Statement::DetachDuckDBDatabase {
5363                if_exists,
5364                database,
5365                database_alias,
5366            } => {
5367                write!(
5368                    f,
5369                    "DETACH{database}{if_exists} {database_alias}",
5370                    database = if *database { " DATABASE" } else { "" },
5371                    if_exists = if *if_exists { " IF EXISTS" } else { "" },
5372                )?;
5373                Ok(())
5374            }
5375            Statement::Analyze(analyze) => analyze.fmt(f),
5376            Statement::Insert(insert) => insert.fmt(f),
5377            Statement::Install {
5378                extension_name: name,
5379            } => write!(f, "INSTALL {name}"),
5380
5381            Statement::Load {
5382                extension_name: name,
5383            } => write!(f, "LOAD {name}"),
5384
5385            Statement::Call(function) => write!(f, "CALL {function}"),
5386
5387            Statement::Copy {
5388                source,
5389                to,
5390                target,
5391                options,
5392                legacy_options,
5393                values,
5394            } => {
5395                write!(f, "COPY")?;
5396                match source {
5397                    CopySource::Query(query) => write!(f, " ({query})")?,
5398                    CopySource::Table {
5399                        table_name,
5400                        columns,
5401                    } => {
5402                        write!(f, " {table_name}")?;
5403                        if !columns.is_empty() {
5404                            write!(f, " ({})", display_comma_separated(columns))?;
5405                        }
5406                    }
5407                }
5408                write!(f, " {} {}", if *to { "TO" } else { "FROM" }, target)?;
5409                if !options.is_empty() {
5410                    write!(f, " ({})", display_comma_separated(options))?;
5411                }
5412                if !legacy_options.is_empty() {
5413                    write!(f, " {}", display_separated(legacy_options, " "))?;
5414                }
5415                if !values.is_empty() {
5416                    writeln!(f, ";")?;
5417                    let mut delim = "";
5418                    for v in values {
5419                        write!(f, "{delim}")?;
5420                        delim = "\t";
5421                        if let Some(v) = v {
5422                            write!(f, "{v}")?;
5423                        } else {
5424                            write!(f, "\\N")?;
5425                        }
5426                    }
5427                    write!(f, "\n\\.")?;
5428                }
5429                Ok(())
5430            }
5431            Statement::Update(update) => update.fmt(f),
5432            Statement::Delete(delete) => delete.fmt(f),
5433            Statement::Open(open) => open.fmt(f),
5434            Statement::Close { cursor } => {
5435                write!(f, "CLOSE {cursor}")?;
5436
5437                Ok(())
5438            }
5439            Statement::CreateDatabase {
5440                db_name,
5441                if_not_exists,
5442                location,
5443                managed_location,
5444                or_replace,
5445                transient,
5446                clone,
5447                data_retention_time_in_days,
5448                max_data_extension_time_in_days,
5449                external_volume,
5450                catalog,
5451                replace_invalid_characters,
5452                default_ddl_collation,
5453                storage_serialization_policy,
5454                comment,
5455                default_charset,
5456                default_collation,
5457                catalog_sync,
5458                catalog_sync_namespace_mode,
5459                catalog_sync_namespace_flatten_delimiter,
5460                with_tags,
5461                with_contacts,
5462            } => {
5463                write!(
5464                    f,
5465                    "CREATE {or_replace}{transient}DATABASE {if_not_exists}{name}",
5466                    or_replace = if *or_replace { "OR REPLACE " } else { "" },
5467                    transient = if *transient { "TRANSIENT " } else { "" },
5468                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
5469                    name = db_name,
5470                )?;
5471
5472                if let Some(l) = location {
5473                    write!(f, " LOCATION '{l}'")?;
5474                }
5475                if let Some(ml) = managed_location {
5476                    write!(f, " MANAGEDLOCATION '{ml}'")?;
5477                }
5478                if let Some(clone) = clone {
5479                    write!(f, " CLONE {clone}")?;
5480                }
5481
5482                if let Some(value) = data_retention_time_in_days {
5483                    write!(f, " DATA_RETENTION_TIME_IN_DAYS = {value}")?;
5484                }
5485
5486                if let Some(value) = max_data_extension_time_in_days {
5487                    write!(f, " MAX_DATA_EXTENSION_TIME_IN_DAYS = {value}")?;
5488                }
5489
5490                if let Some(vol) = external_volume {
5491                    write!(f, " EXTERNAL_VOLUME = '{vol}'")?;
5492                }
5493
5494                if let Some(cat) = catalog {
5495                    write!(f, " CATALOG = '{cat}'")?;
5496                }
5497
5498                if let Some(true) = replace_invalid_characters {
5499                    write!(f, " REPLACE_INVALID_CHARACTERS = TRUE")?;
5500                } else if let Some(false) = replace_invalid_characters {
5501                    write!(f, " REPLACE_INVALID_CHARACTERS = FALSE")?;
5502                }
5503
5504                if let Some(collation) = default_ddl_collation {
5505                    write!(f, " DEFAULT_DDL_COLLATION = '{collation}'")?;
5506                }
5507
5508                if let Some(policy) = storage_serialization_policy {
5509                    write!(f, " STORAGE_SERIALIZATION_POLICY = {policy}")?;
5510                }
5511
5512                if let Some(comment) = comment {
5513                    write!(f, " COMMENT = '{comment}'")?;
5514                }
5515
5516                if let Some(charset) = default_charset {
5517                    write!(f, " DEFAULT CHARACTER SET {charset}")?;
5518                }
5519
5520                if let Some(collation) = default_collation {
5521                    write!(f, " DEFAULT COLLATE {collation}")?;
5522                }
5523
5524                if let Some(sync) = catalog_sync {
5525                    write!(f, " CATALOG_SYNC = '{sync}'")?;
5526                }
5527
5528                if let Some(mode) = catalog_sync_namespace_mode {
5529                    write!(f, " CATALOG_SYNC_NAMESPACE_MODE = {mode}")?;
5530                }
5531
5532                if let Some(delim) = catalog_sync_namespace_flatten_delimiter {
5533                    write!(f, " CATALOG_SYNC_NAMESPACE_FLATTEN_DELIMITER = '{delim}'")?;
5534                }
5535
5536                if let Some(tags) = with_tags {
5537                    write!(f, " WITH TAG ({})", display_comma_separated(tags))?;
5538                }
5539
5540                if let Some(contacts) = with_contacts {
5541                    write!(f, " WITH CONTACT ({})", display_comma_separated(contacts))?;
5542                }
5543                Ok(())
5544            }
5545            Statement::CreateFunction(create_function) => create_function.fmt(f),
5546            Statement::CreateDomain(create_domain) => create_domain.fmt(f),
5547            Statement::CreateTrigger(create_trigger) => create_trigger.fmt(f),
5548            Statement::DropTrigger(drop_trigger) => drop_trigger.fmt(f),
5549            Statement::CreateProcedure {
5550                name,
5551                or_alter,
5552                params,
5553                language,
5554                body,
5555            } => {
5556                write!(
5557                    f,
5558                    "CREATE {or_alter}PROCEDURE {name}",
5559                    or_alter = if *or_alter { "OR ALTER " } else { "" },
5560                    name = name
5561                )?;
5562
5563                if let Some(p) = params {
5564                    if !p.is_empty() {
5565                        write!(f, " ({})", display_comma_separated(p))?;
5566                    }
5567                }
5568
5569                if let Some(language) = language {
5570                    write!(f, " LANGUAGE {language}")?;
5571                }
5572
5573                write!(f, " AS {body}")
5574            }
5575            Statement::CreateMacro {
5576                or_replace,
5577                temporary,
5578                name,
5579                args,
5580                definition,
5581            } => {
5582                write!(
5583                    f,
5584                    "CREATE {or_replace}{temp}MACRO {name}",
5585                    temp = if *temporary { "TEMPORARY " } else { "" },
5586                    or_replace = if *or_replace { "OR REPLACE " } else { "" },
5587                )?;
5588                if let Some(args) = args {
5589                    write!(f, "({})", display_comma_separated(args))?;
5590                }
5591                match definition {
5592                    MacroDefinition::Expr(expr) => write!(f, " AS {expr}")?,
5593                    MacroDefinition::Table(query) => write!(f, " AS TABLE {query}")?,
5594                }
5595                Ok(())
5596            }
5597            Statement::CreateView(create_view) => create_view.fmt(f),
5598            Statement::CreateTable(create_table) => create_table.fmt(f),
5599            Statement::LoadData {
5600                local,
5601                inpath,
5602                overwrite,
5603                table_name,
5604                partitioned,
5605                table_format,
5606            } => {
5607                write!(
5608                    f,
5609                    "LOAD DATA {local}INPATH '{inpath}' {overwrite}INTO TABLE {table_name}",
5610                    local = if *local { "LOCAL " } else { "" },
5611                    inpath = inpath,
5612                    overwrite = if *overwrite { "OVERWRITE " } else { "" },
5613                    table_name = table_name,
5614                )?;
5615                if let Some(ref parts) = &partitioned {
5616                    if !parts.is_empty() {
5617                        write!(f, " PARTITION ({})", display_comma_separated(parts))?;
5618                    }
5619                }
5620                if let Some(HiveLoadDataFormat {
5621                    serde,
5622                    input_format,
5623                }) = &table_format
5624                {
5625                    write!(f, " INPUTFORMAT {input_format} SERDE {serde}")?;
5626                }
5627                Ok(())
5628            }
5629            Statement::CreateVirtualTable {
5630                name,
5631                if_not_exists,
5632                module_name,
5633                module_args,
5634            } => {
5635                write!(
5636                    f,
5637                    "CREATE VIRTUAL TABLE {if_not_exists}{name} USING {module_name}",
5638                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
5639                    name = name,
5640                    module_name = module_name
5641                )?;
5642                if !module_args.is_empty() {
5643                    write!(f, " ({})", display_comma_separated(module_args))?;
5644                }
5645                Ok(())
5646            }
5647            Statement::CreateIndex(create_index) => create_index.fmt(f),
5648            Statement::CreateExtension(create_extension) => write!(f, "{create_extension}"),
5649            Statement::CreateCollation(create_collation) => write!(f, "{create_collation}"),
5650            Statement::DropExtension(drop_extension) => write!(f, "{drop_extension}"),
5651            Statement::DropOperator(drop_operator) => write!(f, "{drop_operator}"),
5652            Statement::DropOperatorFamily(drop_operator_family) => {
5653                write!(f, "{drop_operator_family}")
5654            }
5655            Statement::DropOperatorClass(drop_operator_class) => {
5656                write!(f, "{drop_operator_class}")
5657            }
5658            Statement::CreateRole(create_role) => write!(f, "{create_role}"),
5659            Statement::CreateSecret {
5660                or_replace,
5661                temporary,
5662                if_not_exists,
5663                name,
5664                storage_specifier,
5665                secret_type,
5666                options,
5667            } => {
5668                write!(
5669                    f,
5670                    "CREATE {or_replace}",
5671                    or_replace = if *or_replace { "OR REPLACE " } else { "" },
5672                )?;
5673                if let Some(t) = temporary {
5674                    write!(f, "{}", if *t { "TEMPORARY " } else { "PERSISTENT " })?;
5675                }
5676                write!(
5677                    f,
5678                    "SECRET {if_not_exists}",
5679                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
5680                )?;
5681                if let Some(n) = name {
5682                    write!(f, "{n} ")?;
5683                };
5684                if let Some(s) = storage_specifier {
5685                    write!(f, "IN {s} ")?;
5686                }
5687                write!(f, "( TYPE {secret_type}",)?;
5688                if !options.is_empty() {
5689                    write!(f, ", {o}", o = display_comma_separated(options))?;
5690                }
5691                write!(f, " )")?;
5692                Ok(())
5693            }
5694            Statement::CreateServer(stmt) => {
5695                write!(f, "{stmt}")
5696            }
5697            Statement::CreateForeignTable(stmt) => write!(f, "{stmt}"),
5698            Statement::CreatePolicy(policy) => write!(f, "{policy}"),
5699            Statement::CreateConnector(create_connector) => create_connector.fmt(f),
5700            Statement::CreateOperator(create_operator) => create_operator.fmt(f),
5701            Statement::CreateOperatorFamily(create_operator_family) => {
5702                create_operator_family.fmt(f)
5703            }
5704            Statement::CreateOperatorClass(create_operator_class) => create_operator_class.fmt(f),
5705            Statement::CreateTextSearch(create_text_search) => create_text_search.fmt(f),
5706            Statement::AlterTable(alter_table) => write!(f, "{alter_table}"),
5707            Statement::AlterIndex {
5708                if_exists,
5709                name,
5710                operation,
5711            } => {
5712                write!(
5713                    f,
5714                    "ALTER INDEX {if_exists}{name} {operation}",
5715                    if_exists = if *if_exists { "IF EXISTS " } else { "" }
5716                )
5717            }
5718            Statement::AlterTrigger {
5719                name,
5720                table_name,
5721                new_name,
5722            } => write!(
5723                f,
5724                "ALTER TRIGGER {name} ON {table_name} RENAME TO {new_name}"
5725            ),
5726            Statement::AlterView {
5727                name,
5728                columns,
5729                query,
5730                with_options,
5731            } => {
5732                write!(f, "ALTER VIEW {name}")?;
5733                if !with_options.is_empty() {
5734                    write!(f, " WITH ({})", display_comma_separated(with_options))?;
5735                }
5736                if !columns.is_empty() {
5737                    write!(f, " ({})", display_comma_separated(columns))?;
5738                }
5739                write!(f, " AS {query}")
5740            }
5741            Statement::AlterFunction(alter_function) => write!(f, "{alter_function}"),
5742            Statement::AlterType(AlterType { name, operation }) => {
5743                write!(f, "ALTER TYPE {name} {operation}")
5744            }
5745            Statement::AlterCollation(alter_collation) => write!(f, "{alter_collation}"),
5746            Statement::AlterOperator(alter_operator) => write!(f, "{alter_operator}"),
5747            Statement::AlterOperatorFamily(alter_operator_family) => {
5748                write!(f, "{alter_operator_family}")
5749            }
5750            Statement::AlterOperatorClass(alter_operator_class) => {
5751                write!(f, "{alter_operator_class}")
5752            }
5753            Statement::AlterTextSearch(alter_text_search) => write!(f, "{alter_text_search}"),
5754            Statement::AlterRole { name, operation } => {
5755                write!(f, "ALTER ROLE {name} {operation}")
5756            }
5757            Statement::AlterPolicy(alter_policy) => write!(f, "{alter_policy}"),
5758            Statement::AlterConnector {
5759                name,
5760                properties,
5761                url,
5762                owner,
5763            } => {
5764                write!(f, "ALTER CONNECTOR {name}")?;
5765                if let Some(properties) = properties {
5766                    write!(
5767                        f,
5768                        " SET DCPROPERTIES({})",
5769                        display_comma_separated(properties)
5770                    )?;
5771                }
5772                if let Some(url) = url {
5773                    write!(f, " SET URL '{url}'")?;
5774                }
5775                if let Some(owner) = owner {
5776                    write!(f, " SET OWNER {owner}")?;
5777                }
5778                Ok(())
5779            }
5780            Statement::AlterSession {
5781                set,
5782                session_params,
5783            } => {
5784                write!(
5785                    f,
5786                    "ALTER SESSION {set}",
5787                    set = if *set { "SET" } else { "UNSET" }
5788                )?;
5789                if !session_params.options.is_empty() {
5790                    if *set {
5791                        write!(f, " {session_params}")?;
5792                    } else {
5793                        let options = session_params
5794                            .options
5795                            .iter()
5796                            .map(|p| p.option_name.clone())
5797                            .collect::<Vec<_>>();
5798                        write!(f, " {}", display_separated(&options, ", "))?;
5799                    }
5800                }
5801                Ok(())
5802            }
5803            Statement::Drop {
5804                object_type,
5805                if_exists,
5806                names,
5807                cascade,
5808                restrict,
5809                purge,
5810                temporary,
5811                table,
5812            } => {
5813                write!(
5814                    f,
5815                    "DROP {}{}{} {}{}{}{}",
5816                    if *temporary { "TEMPORARY " } else { "" },
5817                    object_type,
5818                    if *if_exists { " IF EXISTS" } else { "" },
5819                    display_comma_separated(names),
5820                    if *cascade { " CASCADE" } else { "" },
5821                    if *restrict { " RESTRICT" } else { "" },
5822                    if *purge { " PURGE" } else { "" },
5823                )?;
5824                if let Some(table_name) = table.as_ref() {
5825                    write!(f, " ON {table_name}")?;
5826                };
5827                Ok(())
5828            }
5829            Statement::DropFunction(drop_function) => write!(f, "{drop_function}"),
5830            Statement::DropDomain(DropDomain {
5831                if_exists,
5832                name,
5833                drop_behavior,
5834            }) => {
5835                write!(
5836                    f,
5837                    "DROP DOMAIN{} {name}",
5838                    if *if_exists { " IF EXISTS" } else { "" },
5839                )?;
5840                if let Some(op) = drop_behavior {
5841                    write!(f, " {op}")?;
5842                }
5843                Ok(())
5844            }
5845            Statement::DropProcedure {
5846                if_exists,
5847                proc_desc,
5848                drop_behavior,
5849            } => {
5850                write!(
5851                    f,
5852                    "DROP PROCEDURE{} {}",
5853                    if *if_exists { " IF EXISTS" } else { "" },
5854                    display_comma_separated(proc_desc),
5855                )?;
5856                if let Some(op) = drop_behavior {
5857                    write!(f, " {op}")?;
5858                }
5859                Ok(())
5860            }
5861            Statement::DropSecret {
5862                if_exists,
5863                temporary,
5864                name,
5865                storage_specifier,
5866            } => {
5867                write!(f, "DROP ")?;
5868                if let Some(t) = temporary {
5869                    write!(f, "{}", if *t { "TEMPORARY " } else { "PERSISTENT " })?;
5870                }
5871                write!(
5872                    f,
5873                    "SECRET {if_exists}{name}",
5874                    if_exists = if *if_exists { "IF EXISTS " } else { "" },
5875                )?;
5876                if let Some(s) = storage_specifier {
5877                    write!(f, " FROM {s}")?;
5878                }
5879                Ok(())
5880            }
5881            Statement::DropPolicy(policy) => write!(f, "{policy}"),
5882            Statement::DropConnector { if_exists, name } => {
5883                write!(
5884                    f,
5885                    "DROP CONNECTOR {if_exists}{name}",
5886                    if_exists = if *if_exists { "IF EXISTS " } else { "" }
5887                )?;
5888                Ok(())
5889            }
5890            Statement::Discard { object_type } => {
5891                write!(f, "DISCARD {object_type}")?;
5892                Ok(())
5893            }
5894            Self::Set(set) => write!(f, "{set}"),
5895            Statement::ShowVariable { variable } => {
5896                write!(f, "SHOW")?;
5897                if !variable.is_empty() {
5898                    write!(f, " {}", display_separated(variable, " "))?;
5899                }
5900                Ok(())
5901            }
5902            Statement::ShowStatus {
5903                filter,
5904                global,
5905                session,
5906            } => {
5907                write!(f, "SHOW")?;
5908                if *global {
5909                    write!(f, " GLOBAL")?;
5910                }
5911                if *session {
5912                    write!(f, " SESSION")?;
5913                }
5914                write!(f, " STATUS")?;
5915                if let Some(filter) = filter {
5916                    write!(f, " {}", filter)?;
5917                }
5918                Ok(())
5919            }
5920            Statement::ShowVariables {
5921                filter,
5922                global,
5923                session,
5924            } => {
5925                write!(f, "SHOW")?;
5926                if *global {
5927                    write!(f, " GLOBAL")?;
5928                }
5929                if *session {
5930                    write!(f, " SESSION")?;
5931                }
5932                write!(f, " VARIABLES")?;
5933                if let Some(filter) = filter {
5934                    write!(f, " {}", filter)?;
5935                }
5936                Ok(())
5937            }
5938            Statement::ShowCreate { obj_type, obj_name } => {
5939                write!(f, "SHOW CREATE {obj_type} {obj_name}",)?;
5940                Ok(())
5941            }
5942            Statement::ShowColumns {
5943                extended,
5944                full,
5945                show_options,
5946            } => {
5947                write!(
5948                    f,
5949                    "SHOW {extended}{full}COLUMNS{show_options}",
5950                    extended = if *extended { "EXTENDED " } else { "" },
5951                    full = if *full { "FULL " } else { "" },
5952                )?;
5953                Ok(())
5954            }
5955            Statement::ShowDatabases {
5956                terse,
5957                history,
5958                show_options,
5959            } => {
5960                write!(
5961                    f,
5962                    "SHOW {terse}DATABASES{history}{show_options}",
5963                    terse = if *terse { "TERSE " } else { "" },
5964                    history = if *history { " HISTORY" } else { "" },
5965                )?;
5966                Ok(())
5967            }
5968            Statement::ShowCatalogs {
5969                terse,
5970                history,
5971                show_options,
5972            } => {
5973                write!(
5974                    f,
5975                    "SHOW {terse}CATALOGS{history}{show_options}",
5976                    terse = if *terse { "TERSE " } else { "" },
5977                    history = if *history { " HISTORY" } else { "" },
5978                )?;
5979                Ok(())
5980            }
5981            Statement::ShowProcessList { full } => {
5982                write!(
5983                    f,
5984                    "SHOW {full}PROCESSLIST",
5985                    full = if *full { "FULL " } else { "" },
5986                )?;
5987                Ok(())
5988            }
5989            Statement::ShowSchemas {
5990                terse,
5991                history,
5992                show_options,
5993            } => {
5994                write!(
5995                    f,
5996                    "SHOW {terse}SCHEMAS{history}{show_options}",
5997                    terse = if *terse { "TERSE " } else { "" },
5998                    history = if *history { " HISTORY" } else { "" },
5999                )?;
6000                Ok(())
6001            }
6002            Statement::ShowObjects(ShowObjects {
6003                terse,
6004                show_options,
6005            }) => {
6006                write!(
6007                    f,
6008                    "SHOW {terse}OBJECTS{show_options}",
6009                    terse = if *terse { "TERSE " } else { "" },
6010                )?;
6011                Ok(())
6012            }
6013            Statement::ShowTables {
6014                terse,
6015                history,
6016                extended,
6017                full,
6018                external,
6019                show_options,
6020            } => {
6021                write!(
6022                    f,
6023                    "SHOW {terse}{extended}{full}{external}TABLES{history}{show_options}",
6024                    terse = if *terse { "TERSE " } else { "" },
6025                    extended = if *extended { "EXTENDED " } else { "" },
6026                    full = if *full { "FULL " } else { "" },
6027                    external = if *external { "EXTERNAL " } else { "" },
6028                    history = if *history { " HISTORY" } else { "" },
6029                )?;
6030                Ok(())
6031            }
6032            Statement::ShowViews {
6033                terse,
6034                materialized,
6035                show_options,
6036            } => {
6037                write!(
6038                    f,
6039                    "SHOW {terse}{materialized}VIEWS{show_options}",
6040                    terse = if *terse { "TERSE " } else { "" },
6041                    materialized = if *materialized { "MATERIALIZED " } else { "" }
6042                )?;
6043                Ok(())
6044            }
6045            Statement::ShowFunctions { filter } => {
6046                write!(f, "SHOW FUNCTIONS")?;
6047                if let Some(filter) = filter {
6048                    write!(f, " {filter}")?;
6049                }
6050                Ok(())
6051            }
6052            Statement::Use(use_expr) => use_expr.fmt(f),
6053            Statement::ShowCollation { filter } => {
6054                write!(f, "SHOW COLLATION")?;
6055                if let Some(filter) = filter {
6056                    write!(f, " {filter}")?;
6057                }
6058                Ok(())
6059            }
6060            Statement::ShowCharset(show_stm) => show_stm.fmt(f),
6061            Statement::StartTransaction {
6062                modes,
6063                begin: syntax_begin,
6064                transaction,
6065                modifier,
6066                statements,
6067                exception,
6068                has_end_keyword,
6069            } => {
6070                if *syntax_begin {
6071                    if let Some(modifier) = *modifier {
6072                        write!(f, "BEGIN {modifier}")?;
6073                    } else {
6074                        write!(f, "BEGIN")?;
6075                    }
6076                } else {
6077                    write!(f, "START")?;
6078                }
6079                if let Some(transaction) = transaction {
6080                    write!(f, " {transaction}")?;
6081                }
6082                if !modes.is_empty() {
6083                    write!(f, " {}", display_comma_separated(modes))?;
6084                }
6085                if !statements.is_empty() {
6086                    write!(f, " ")?;
6087                    format_statement_list(f, statements)?;
6088                }
6089                if let Some(exception_when) = exception {
6090                    write!(f, " EXCEPTION")?;
6091                    for when in exception_when {
6092                        write!(f, " {when}")?;
6093                    }
6094                }
6095                if *has_end_keyword {
6096                    write!(f, " END")?;
6097                }
6098                Ok(())
6099            }
6100            Statement::Commit {
6101                chain,
6102                end: end_syntax,
6103                modifier,
6104            } => {
6105                if *end_syntax {
6106                    write!(f, "END")?;
6107                    if let Some(modifier) = *modifier {
6108                        write!(f, " {modifier}")?;
6109                    }
6110                    if *chain {
6111                        write!(f, " AND CHAIN")?;
6112                    }
6113                } else {
6114                    write!(f, "COMMIT{}", if *chain { " AND CHAIN" } else { "" })?;
6115                }
6116                Ok(())
6117            }
6118            Statement::Rollback { chain, savepoint } => {
6119                write!(f, "ROLLBACK")?;
6120
6121                if *chain {
6122                    write!(f, " AND CHAIN")?;
6123                }
6124
6125                if let Some(savepoint) = savepoint {
6126                    write!(f, " TO SAVEPOINT {savepoint}")?;
6127                }
6128
6129                Ok(())
6130            }
6131            Statement::CreateSchema {
6132                schema_name,
6133                or_replace,
6134                if_not_exists,
6135                with,
6136                options,
6137                default_collate_spec,
6138                clone,
6139            } => {
6140                write!(
6141                    f,
6142                    "CREATE {or_replace}SCHEMA {if_not_exists}{name}",
6143                    or_replace = if *or_replace { "OR REPLACE " } else { "" },
6144                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
6145                    name = schema_name
6146                )?;
6147
6148                if let Some(collate) = default_collate_spec {
6149                    write!(f, " DEFAULT COLLATE {collate}")?;
6150                }
6151
6152                if let Some(with) = with {
6153                    write!(f, " WITH ({})", display_comma_separated(with))?;
6154                }
6155
6156                if let Some(options) = options {
6157                    write!(f, " OPTIONS({})", display_comma_separated(options))?;
6158                }
6159
6160                if let Some(clone) = clone {
6161                    write!(f, " CLONE {clone}")?;
6162                }
6163                Ok(())
6164            }
6165            Statement::Assert { condition, message } => {
6166                write!(f, "ASSERT {condition}")?;
6167                if let Some(m) = message {
6168                    write!(f, " AS {m}")?;
6169                }
6170                Ok(())
6171            }
6172            Statement::Grant(grant) => write!(f, "{grant}"),
6173            Statement::Deny(s) => write!(f, "{s}"),
6174            Statement::Revoke(revoke) => write!(f, "{revoke}"),
6175            Statement::Deallocate { name, prepare } => write!(
6176                f,
6177                "DEALLOCATE {prepare}{name}",
6178                prepare = if *prepare { "PREPARE " } else { "" },
6179                name = name,
6180            ),
6181            Statement::Execute {
6182                name,
6183                parameters,
6184                has_parentheses,
6185                immediate,
6186                into,
6187                using,
6188                output,
6189                default,
6190            } => {
6191                let (open, close) = if *has_parentheses {
6192                    // Space before `(` only when there is no name directly preceding it.
6193                    (if name.is_some() { "(" } else { " (" }, ")")
6194                } else {
6195                    (if parameters.is_empty() { "" } else { " " }, "")
6196                };
6197                write!(f, "EXECUTE")?;
6198                if *immediate {
6199                    write!(f, " IMMEDIATE")?;
6200                }
6201                if let Some(name) = name {
6202                    write!(f, " {name}")?;
6203                }
6204                write!(f, "{open}{}{close}", display_comma_separated(parameters),)?;
6205                if !into.is_empty() {
6206                    write!(f, " INTO {}", display_comma_separated(into))?;
6207                }
6208                if !using.is_empty() {
6209                    write!(f, " USING {}", display_comma_separated(using))?;
6210                };
6211                if *output {
6212                    write!(f, " OUTPUT")?;
6213                }
6214                if *default {
6215                    write!(f, " DEFAULT")?;
6216                }
6217                Ok(())
6218            }
6219            Statement::Prepare {
6220                name,
6221                data_types,
6222                statement,
6223            } => {
6224                write!(f, "PREPARE {name} ")?;
6225                if !data_types.is_empty() {
6226                    write!(f, "({}) ", display_comma_separated(data_types))?;
6227                }
6228                write!(f, "AS {statement}")
6229            }
6230            Statement::Comment {
6231                object_type,
6232                object_name,
6233                comment,
6234                if_exists,
6235            } => {
6236                write!(f, "COMMENT ")?;
6237                if *if_exists {
6238                    write!(f, "IF EXISTS ")?
6239                };
6240                write!(f, "ON {object_type} {object_name} IS ")?;
6241                if let Some(c) = comment {
6242                    write!(f, "'{c}'")
6243                } else {
6244                    write!(f, "NULL")
6245                }
6246            }
6247            Statement::Savepoint { name } => {
6248                write!(f, "SAVEPOINT ")?;
6249                write!(f, "{name}")
6250            }
6251            Statement::ReleaseSavepoint { name } => {
6252                write!(f, "RELEASE SAVEPOINT {name}")
6253            }
6254            Statement::Merge(merge) => merge.fmt(f),
6255            Statement::Cache {
6256                table_name,
6257                table_flag,
6258                has_as,
6259                options,
6260                query,
6261            } => {
6262                if let Some(table_flag) = table_flag {
6263                    write!(f, "CACHE {table_flag} TABLE {table_name}")?;
6264                } else {
6265                    write!(f, "CACHE TABLE {table_name}")?;
6266                }
6267
6268                if !options.is_empty() {
6269                    write!(f, " OPTIONS({})", display_comma_separated(options))?;
6270                }
6271
6272                match (*has_as, query) {
6273                    (true, Some(query)) => write!(f, " AS {query}"),
6274                    (true, None) => f.write_str(" AS"),
6275                    (false, Some(query)) => write!(f, " {query}"),
6276                    (false, None) => Ok(()),
6277                }
6278            }
6279            Statement::UNCache {
6280                table_name,
6281                if_exists,
6282            } => {
6283                if *if_exists {
6284                    write!(f, "UNCACHE TABLE IF EXISTS {table_name}")
6285                } else {
6286                    write!(f, "UNCACHE TABLE {table_name}")
6287                }
6288            }
6289            Statement::CreateSequence {
6290                temporary,
6291                if_not_exists,
6292                name,
6293                data_type,
6294                sequence_options,
6295                owned_by,
6296            } => {
6297                let as_type: String = if let Some(dt) = data_type.as_ref() {
6298                    //Cannot use format!(" AS {}", dt), due to format! is not available in --target thumbv6m-none-eabi
6299                    // " AS ".to_owned() + &dt.to_string()
6300                    [" AS ", &dt.to_string()].concat()
6301                } else {
6302                    "".to_string()
6303                };
6304                write!(
6305                    f,
6306                    "CREATE {temporary}SEQUENCE {if_not_exists}{name}{as_type}",
6307                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
6308                    temporary = if *temporary { "TEMPORARY " } else { "" },
6309                    name = name,
6310                    as_type = as_type
6311                )?;
6312                for sequence_option in sequence_options {
6313                    write!(f, "{sequence_option}")?;
6314                }
6315                if let Some(ob) = owned_by.as_ref() {
6316                    write!(f, " OWNED BY {ob}")?;
6317                }
6318                write!(f, "")
6319            }
6320            Statement::CreateStage {
6321                or_replace,
6322                temporary,
6323                if_not_exists,
6324                name,
6325                stage_params,
6326                directory_table_params,
6327                file_format,
6328                copy_options,
6329                comment,
6330                ..
6331            } => {
6332                write!(
6333                    f,
6334                    "CREATE {or_replace}{temp}STAGE {if_not_exists}{name}{stage_params}",
6335                    temp = if *temporary { "TEMPORARY " } else { "" },
6336                    or_replace = if *or_replace { "OR REPLACE " } else { "" },
6337                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
6338                )?;
6339                if !directory_table_params.options.is_empty() {
6340                    write!(f, " DIRECTORY=({directory_table_params})")?;
6341                }
6342                if !file_format.options.is_empty() {
6343                    write!(f, " FILE_FORMAT=({file_format})")?;
6344                }
6345                if !copy_options.options.is_empty() {
6346                    write!(f, " COPY_OPTIONS=({copy_options})")?;
6347                }
6348                if let Some(comment) = comment {
6349                    write!(f, " COMMENT='{}'", comment)?;
6350                }
6351                Ok(())
6352            }
6353            Statement::CreateFileFormat {
6354                or_replace,
6355                temporary,
6356                volatile,
6357                if_not_exists,
6358                name,
6359                options,
6360                comment,
6361            } => {
6362                write!(
6363                    f,
6364                    "CREATE {or_replace}{temp}{volatile}FILE FORMAT {if_not_exists}{name}",
6365                    or_replace = if *or_replace { "OR REPLACE " } else { "" },
6366                    temp = if *temporary { "TEMPORARY " } else { "" },
6367                    volatile = if *volatile { "VOLATILE " } else { "" },
6368                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
6369                )?;
6370                if !options.options.is_empty() {
6371                    write!(f, " {options}")?;
6372                }
6373                if let Some(comment) = comment {
6374                    write!(f, " COMMENT='{}'", comment)?;
6375                }
6376                Ok(())
6377            }
6378            Statement::CreateWarehouse(s) => write!(f, "{s}"),
6379            Statement::CopyIntoSnowflake {
6380                kind,
6381                into,
6382                into_columns,
6383                from_obj,
6384                from_obj_alias,
6385                stage_params,
6386                from_transformations,
6387                from_query,
6388                files,
6389                pattern,
6390                file_format,
6391                copy_options,
6392                validation_mode,
6393                partition,
6394            } => {
6395                write!(f, "COPY INTO {into}")?;
6396                if let Some(into_columns) = into_columns {
6397                    write!(f, " ({})", display_comma_separated(into_columns))?;
6398                }
6399                if let Some(from_transformations) = from_transformations {
6400                    // Data load with transformation
6401                    if let Some(from_stage) = from_obj {
6402                        write!(
6403                            f,
6404                            " FROM (SELECT {} FROM {}{}",
6405                            display_separated(from_transformations, ", "),
6406                            from_stage,
6407                            stage_params
6408                        )?;
6409                    }
6410                    if let Some(from_obj_alias) = from_obj_alias {
6411                        write!(f, " AS {from_obj_alias}")?;
6412                    }
6413                    write!(f, ")")?;
6414                } else if let Some(from_obj) = from_obj {
6415                    // Standard data load
6416                    write!(f, " FROM {from_obj}{stage_params}")?;
6417                    if let Some(from_obj_alias) = from_obj_alias {
6418                        write!(f, " AS {from_obj_alias}")?;
6419                    }
6420                } else if let Some(from_query) = from_query {
6421                    // Data unload from query
6422                    write!(f, " FROM ({from_query})")?;
6423                }
6424
6425                if let Some(files) = files {
6426                    write!(f, " FILES = ('{}')", display_separated(files, "', '"))?;
6427                }
6428                if let Some(pattern) = pattern {
6429                    write!(f, " PATTERN = '{pattern}'")?;
6430                }
6431                if let Some(partition) = partition {
6432                    write!(f, " PARTITION BY {partition}")?;
6433                }
6434                if !file_format.options.is_empty() {
6435                    write!(f, " FILE_FORMAT=({file_format})")?;
6436                }
6437                if !copy_options.options.is_empty() {
6438                    match kind {
6439                        CopyIntoSnowflakeKind::Table => {
6440                            write!(f, " COPY_OPTIONS=({copy_options})")?
6441                        }
6442                        CopyIntoSnowflakeKind::Location => write!(f, " {copy_options}")?,
6443                    }
6444                }
6445                if let Some(validation_mode) = validation_mode {
6446                    write!(f, " VALIDATION_MODE = {validation_mode}")?;
6447                }
6448                Ok(())
6449            }
6450            Statement::CreateType {
6451                name,
6452                representation,
6453            } => {
6454                write!(f, "CREATE TYPE {name}")?;
6455                if let Some(repr) = representation {
6456                    write!(f, " {repr}")?;
6457                }
6458                Ok(())
6459            }
6460            Statement::Pragma { name, value, is_eq } => {
6461                write!(f, "PRAGMA {name}")?;
6462                if let Some(value) = value {
6463                    if *is_eq {
6464                        write!(f, " = {value}")?;
6465                    } else {
6466                        write!(f, "({value})")?;
6467                    }
6468                }
6469                Ok(())
6470            }
6471            Statement::Lock(lock) => lock.fmt(f),
6472            Statement::LockTables { tables } => {
6473                write!(f, "LOCK TABLES {}", display_comma_separated(tables))
6474            }
6475            Statement::UnlockTables => {
6476                write!(f, "UNLOCK TABLES")
6477            }
6478            Statement::Unload {
6479                query,
6480                query_text,
6481                to,
6482                auth,
6483                with,
6484                options,
6485            } => {
6486                write!(f, "UNLOAD(")?;
6487                if let Some(query) = query {
6488                    write!(f, "{query}")?;
6489                }
6490                if let Some(query_text) = query_text {
6491                    write!(f, "'{query_text}'")?;
6492                }
6493                write!(f, ") TO {to}")?;
6494                if let Some(auth) = auth {
6495                    write!(f, " IAM_ROLE {auth}")?;
6496                }
6497                if !with.is_empty() {
6498                    write!(f, " WITH ({})", display_comma_separated(with))?;
6499                }
6500                if !options.is_empty() {
6501                    write!(f, " {}", display_separated(options, " "))?;
6502                }
6503                Ok(())
6504            }
6505            Statement::OptimizeTable {
6506                name,
6507                has_table_keyword,
6508                on_cluster,
6509                partition,
6510                include_final,
6511                deduplicate,
6512                predicate,
6513                zorder,
6514            } => {
6515                write!(f, "OPTIMIZE")?;
6516                if *has_table_keyword {
6517                    write!(f, " TABLE")?;
6518                }
6519                write!(f, " {name}")?;
6520                if let Some(on_cluster) = on_cluster {
6521                    write!(f, " ON CLUSTER {on_cluster}")?;
6522                }
6523                if let Some(partition) = partition {
6524                    write!(f, " {partition}")?;
6525                }
6526                if *include_final {
6527                    write!(f, " FINAL")?;
6528                }
6529                if let Some(deduplicate) = deduplicate {
6530                    write!(f, " {deduplicate}")?;
6531                }
6532                if let Some(predicate) = predicate {
6533                    write!(f, " WHERE {predicate}")?;
6534                }
6535                if let Some(zorder) = zorder {
6536                    write!(f, " ZORDER BY ({})", display_comma_separated(zorder))?;
6537                }
6538                Ok(())
6539            }
6540            Statement::LISTEN { channel } => {
6541                write!(f, "LISTEN {channel}")?;
6542                Ok(())
6543            }
6544            Statement::UNLISTEN { channel } => {
6545                write!(f, "UNLISTEN {channel}")?;
6546                Ok(())
6547            }
6548            Statement::NOTIFY { channel, payload } => {
6549                write!(f, "NOTIFY {channel}")?;
6550                if let Some(payload) = payload {
6551                    write!(f, ", '{payload}'")?;
6552                }
6553                Ok(())
6554            }
6555            Statement::RenameTable(rename_tables) => {
6556                write!(f, "RENAME TABLE {}", display_comma_separated(rename_tables))
6557            }
6558            Statement::RaisError {
6559                message,
6560                severity,
6561                state,
6562                arguments,
6563                options,
6564            } => {
6565                write!(f, "RAISERROR({message}, {severity}, {state}")?;
6566                if !arguments.is_empty() {
6567                    write!(f, ", {}", display_comma_separated(arguments))?;
6568                }
6569                write!(f, ")")?;
6570                if !options.is_empty() {
6571                    write!(f, " WITH {}", display_comma_separated(options))?;
6572                }
6573                Ok(())
6574            }
6575            Statement::Throw(s) => write!(f, "{s}"),
6576            Statement::Print(s) => write!(f, "{s}"),
6577            Statement::WaitFor(s) => write!(f, "{s}"),
6578            Statement::Return(r) => write!(f, "{r}"),
6579            Statement::List(command) => write!(f, "LIST {command}"),
6580            Statement::Put {
6581                source,
6582                stage,
6583                options,
6584            } => {
6585                write!(f, "PUT '{source}' {stage}")?;
6586                if !options.options.is_empty() {
6587                    write!(f, " {options}")?;
6588                }
6589                Ok(())
6590            }
6591            Statement::Remove(command) => write!(f, "REMOVE {command}"),
6592            Statement::ExportData(e) => write!(f, "{e}"),
6593            Statement::CreateUser(s) => write!(f, "{s}"),
6594            Statement::AlterSchema(s) => write!(f, "{s}"),
6595            Statement::Vacuum(s) => write!(f, "{s}"),
6596            Statement::AlterUser(s) => write!(f, "{s}"),
6597            Statement::Reset(s) => write!(f, "{s}"),
6598        }
6599    }
6600}
6601
6602/// Can use to describe options in create sequence or table column type identity
6603/// ```sql
6604/// [ INCREMENT [ BY ] increment ]
6605///     [ MINVALUE minvalue | NO MINVALUE ] [ MAXVALUE maxvalue | NO MAXVALUE ]
6606///     [ START [ WITH ] start ] [ CACHE cache ] [ [ NO ] CYCLE ]
6607/// ```
6608#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6609#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6610#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6611pub enum SequenceOptions {
6612    /// `INCREMENT [BY] <expr>` option; second value indicates presence of `BY` keyword.
6613    IncrementBy(Expr, bool),
6614    /// `MINVALUE <expr>` or `NO MINVALUE`.
6615    MinValue(Option<Expr>),
6616    /// `MAXVALUE <expr>` or `NO MAXVALUE`.
6617    MaxValue(Option<Expr>),
6618    /// `START [WITH] <expr>`; second value indicates presence of `WITH`.
6619    StartWith(Expr, bool),
6620    /// `CACHE <expr>` option.
6621    Cache(Expr),
6622    /// `CYCLE` or `NO CYCLE` option.
6623    Cycle(bool),
6624}
6625
6626impl fmt::Display for SequenceOptions {
6627    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6628        match self {
6629            SequenceOptions::IncrementBy(increment, by) => {
6630                write!(
6631                    f,
6632                    " INCREMENT{by} {increment}",
6633                    by = if *by { " BY" } else { "" },
6634                    increment = increment
6635                )
6636            }
6637            SequenceOptions::MinValue(Some(expr)) => {
6638                write!(f, " MINVALUE {expr}")
6639            }
6640            SequenceOptions::MinValue(None) => {
6641                write!(f, " NO MINVALUE")
6642            }
6643            SequenceOptions::MaxValue(Some(expr)) => {
6644                write!(f, " MAXVALUE {expr}")
6645            }
6646            SequenceOptions::MaxValue(None) => {
6647                write!(f, " NO MAXVALUE")
6648            }
6649            SequenceOptions::StartWith(start, with) => {
6650                write!(
6651                    f,
6652                    " START{with} {start}",
6653                    with = if *with { " WITH" } else { "" },
6654                    start = start
6655                )
6656            }
6657            SequenceOptions::Cache(cache) => {
6658                write!(f, " CACHE {}", *cache)
6659            }
6660            SequenceOptions::Cycle(no) => {
6661                write!(f, " {}CYCLE", if *no { "NO " } else { "" })
6662            }
6663        }
6664    }
6665}
6666
6667/// Assignment for a `SET` statement (name [=|TO] value)
6668#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6669#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6670#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6671pub struct SetAssignment {
6672    /// Optional context scope (e.g., SESSION or LOCAL).
6673    pub scope: Option<ContextModifier>,
6674    /// Assignment target name.
6675    pub name: ObjectName,
6676    /// Assigned expression value.
6677    pub value: Expr,
6678}
6679
6680impl fmt::Display for SetAssignment {
6681    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6682        write!(
6683            f,
6684            "{}{} = {}",
6685            self.scope.map(|s| format!("{s}")).unwrap_or_default(),
6686            self.name,
6687            self.value
6688        )
6689    }
6690}
6691
6692/// Target of a `TRUNCATE TABLE` command
6693///
6694/// Note this is its own struct because `visit_relation` requires an `ObjectName` (not a `Vec<ObjectName>`)
6695#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6696#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6697#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6698pub struct TruncateTableTarget {
6699    /// name of the table being truncated
6700    #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
6701    pub name: ObjectName,
6702    /// Postgres-specific option: explicitly exclude descendants (also default without ONLY)
6703    /// ```sql
6704    /// TRUNCATE TABLE ONLY name
6705    /// ```
6706    /// <https://www.postgresql.org/docs/current/sql-truncate.html>
6707    pub only: bool,
6708    /// Postgres-specific option: asterisk after table name to explicitly indicate descendants
6709    /// ```sql
6710    /// TRUNCATE TABLE name [ * ]
6711    /// ```
6712    /// <https://www.postgresql.org/docs/current/sql-truncate.html>
6713    pub has_asterisk: bool,
6714}
6715
6716impl fmt::Display for TruncateTableTarget {
6717    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6718        if self.only {
6719            write!(f, "ONLY ")?;
6720        };
6721        write!(f, "{}", self.name)?;
6722        if self.has_asterisk {
6723            write!(f, " *")?;
6724        };
6725        Ok(())
6726    }
6727}
6728
6729/// A `LOCK` statement.
6730///
6731/// See <https://www.postgresql.org/docs/current/sql-lock.html>
6732#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6733#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6734#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6735pub struct Lock {
6736    /// List of tables to lock.
6737    pub tables: Vec<LockTableTarget>,
6738    /// Lock mode.
6739    pub lock_mode: Option<LockTableMode>,
6740    /// Whether `NOWAIT` was specified.
6741    pub nowait: bool,
6742}
6743
6744impl fmt::Display for Lock {
6745    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6746        write!(f, "LOCK TABLE {}", display_comma_separated(&self.tables))?;
6747        if let Some(lock_mode) = &self.lock_mode {
6748            write!(f, " IN {lock_mode} MODE")?;
6749        }
6750        if self.nowait {
6751            write!(f, " NOWAIT")?;
6752        }
6753        Ok(())
6754    }
6755}
6756
6757/// Target of a `LOCK TABLE` command
6758///
6759/// See <https://www.postgresql.org/docs/current/sql-lock.html>
6760#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6761#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6762#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6763pub struct LockTableTarget {
6764    /// Name of the table being locked.
6765    #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
6766    pub name: ObjectName,
6767    /// Whether `ONLY` was specified to exclude descendant tables.
6768    pub only: bool,
6769    /// Whether `*` was specified to explicitly include descendant tables.
6770    pub has_asterisk: bool,
6771}
6772
6773impl fmt::Display for LockTableTarget {
6774    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6775        if self.only {
6776            write!(f, "ONLY ")?;
6777        }
6778        write!(f, "{}", self.name)?;
6779        if self.has_asterisk {
6780            write!(f, " *")?;
6781        }
6782        Ok(())
6783    }
6784}
6785
6786/// PostgreSQL lock modes for `LOCK TABLE`.
6787///
6788/// See <https://www.postgresql.org/docs/current/sql-lock.html>
6789#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6790#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6791#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6792pub enum LockTableMode {
6793    /// `ACCESS SHARE`
6794    AccessShare,
6795    /// `ROW SHARE`
6796    RowShare,
6797    /// `ROW EXCLUSIVE`
6798    RowExclusive,
6799    /// `SHARE UPDATE EXCLUSIVE`
6800    ShareUpdateExclusive,
6801    /// `SHARE`
6802    Share,
6803    /// `SHARE ROW EXCLUSIVE`
6804    ShareRowExclusive,
6805    /// `EXCLUSIVE`
6806    Exclusive,
6807    /// `ACCESS EXCLUSIVE`
6808    AccessExclusive,
6809}
6810
6811impl fmt::Display for LockTableMode {
6812    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
6813        let text = match self {
6814            Self::AccessShare => "ACCESS SHARE",
6815            Self::RowShare => "ROW SHARE",
6816            Self::RowExclusive => "ROW EXCLUSIVE",
6817            Self::ShareUpdateExclusive => "SHARE UPDATE EXCLUSIVE",
6818            Self::Share => "SHARE",
6819            Self::ShareRowExclusive => "SHARE ROW EXCLUSIVE",
6820            Self::Exclusive => "EXCLUSIVE",
6821            Self::AccessExclusive => "ACCESS EXCLUSIVE",
6822        };
6823        write!(f, "{text}")
6824    }
6825}
6826
6827/// PostgreSQL identity option for TRUNCATE table
6828/// [ RESTART IDENTITY | CONTINUE IDENTITY ]
6829#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6830#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6831#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6832pub enum TruncateIdentityOption {
6833    /// Restart identity values (RESTART IDENTITY).
6834    Restart,
6835    /// Continue identity values (CONTINUE IDENTITY).
6836    Continue,
6837}
6838
6839/// Cascade/restrict option for Postgres TRUNCATE table, MySQL GRANT/REVOKE, etc.
6840/// [ CASCADE | RESTRICT ]
6841#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6842#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6843#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6844pub enum CascadeOption {
6845    /// Apply cascading action (e.g., CASCADE).
6846    Cascade,
6847    /// Restrict the action (e.g., RESTRICT).
6848    Restrict,
6849}
6850
6851impl Display for CascadeOption {
6852    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6853        match self {
6854            CascadeOption::Cascade => write!(f, "CASCADE"),
6855            CascadeOption::Restrict => write!(f, "RESTRICT"),
6856        }
6857    }
6858}
6859
6860/// Transaction started with [ TRANSACTION | WORK | TRAN ]
6861#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6862#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6863#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6864pub enum BeginTransactionKind {
6865    /// Standard `TRANSACTION` keyword.
6866    Transaction,
6867    /// Alternate `WORK` keyword.
6868    Work,
6869    /// MSSQL shorthand `TRAN` keyword.
6870    /// See <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/begin-transaction-transact-sql>
6871    Tran,
6872}
6873
6874impl Display for BeginTransactionKind {
6875    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6876        match self {
6877            BeginTransactionKind::Transaction => write!(f, "TRANSACTION"),
6878            BeginTransactionKind::Work => write!(f, "WORK"),
6879            BeginTransactionKind::Tran => write!(f, "TRAN"),
6880        }
6881    }
6882}
6883
6884/// Can use to describe options in  create sequence or table column type identity
6885/// [ MINVALUE minvalue | NO MINVALUE ] [ MAXVALUE maxvalue | NO MAXVALUE ]
6886#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6887#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6888#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6889pub enum MinMaxValue {
6890    /// Clause is not specified.
6891    Empty,
6892    /// NO MINVALUE / NO MAXVALUE.
6893    None,
6894    /// `MINVALUE <expr>` / `MAXVALUE <expr>`.
6895    Some(Expr),
6896}
6897
6898#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6899#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6900#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6901#[non_exhaustive]
6902/// Behavior to apply for `INSERT` when a conflict occurs.
6903pub enum OnInsert {
6904    /// ON DUPLICATE KEY UPDATE (MySQL when the key already exists, then execute an update instead)
6905    DuplicateKeyUpdate(Vec<Assignment>),
6906    /// ON CONFLICT is a PostgreSQL and Sqlite extension
6907    OnConflict(OnConflict),
6908}
6909
6910#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6911#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6912#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6913/// Optional aliases for `INSERT` targets: row alias and optional column aliases.
6914pub struct InsertAliases {
6915    /// Row alias (table-style alias) for the inserted values.
6916    pub row_alias: ObjectName,
6917    /// Optional list of column aliases for the inserted values.
6918    pub col_aliases: Option<Vec<Ident>>,
6919}
6920
6921#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6922#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6923#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6924/// Optional alias for an `INSERT` table; i.e. the table to be inserted into
6925pub struct TableAliasWithoutColumns {
6926    /// `true` if the aliases was explicitly introduced with the "AS" keyword
6927    pub explicit: bool,
6928    /// the alias name itself
6929    pub alias: Ident,
6930}
6931
6932#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6933#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6934#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6935/// `ON CONFLICT` clause representation.
6936pub struct OnConflict {
6937    /// Optional conflict target specifying columns or constraint.
6938    pub conflict_target: Option<ConflictTarget>,
6939    /// Action to take when a conflict occurs.
6940    pub action: OnConflictAction,
6941}
6942#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6943#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6944#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6945/// Target specification for an `ON CONFLICT` clause.
6946pub enum ConflictTarget {
6947    /// Target specified as a list of columns.
6948    Columns {
6949        /// Columns used to infer a unique index.
6950        columns: Vec<Ident>,
6951        /// Optional predicate used to infer a partial unique index.
6952        predicate: Option<Expr>,
6953    },
6954    /// Target specified as a named constraint.
6955    OnConstraint(ObjectName),
6956}
6957#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6958#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6959#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6960/// Action to perform when an `ON CONFLICT` target is matched.
6961pub enum OnConflictAction {
6962    /// Do nothing on conflict.
6963    DoNothing,
6964    /// Perform an update on conflict.
6965    DoUpdate(DoUpdate),
6966}
6967
6968#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6969#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6970#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6971/// Details for `DO UPDATE` action of an `ON CONFLICT` clause.
6972pub struct DoUpdate {
6973    /// Column assignments to perform on update.
6974    pub assignments: Vec<Assignment>,
6975    /// Optional WHERE clause limiting the update.
6976    pub selection: Option<Expr>,
6977}
6978
6979impl fmt::Display for OnInsert {
6980    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6981        match self {
6982            Self::DuplicateKeyUpdate(expr) => write!(
6983                f,
6984                " ON DUPLICATE KEY UPDATE {}",
6985                display_comma_separated(expr)
6986            ),
6987            Self::OnConflict(o) => write!(f, "{o}"),
6988        }
6989    }
6990}
6991impl fmt::Display for OnConflict {
6992    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6993        write!(f, " ON CONFLICT")?;
6994        if let Some(target) = &self.conflict_target {
6995            write!(f, "{target}")?;
6996        }
6997        write!(f, " {}", self.action)
6998    }
6999}
7000impl fmt::Display for ConflictTarget {
7001    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7002        match self {
7003            ConflictTarget::Columns { columns, predicate } => {
7004                write!(f, "({})", display_comma_separated(columns))?;
7005                if let Some(predicate) = predicate {
7006                    write!(f, " WHERE {predicate}")?;
7007                }
7008                Ok(())
7009            }
7010            ConflictTarget::OnConstraint(name) => write!(f, " ON CONSTRAINT {name}"),
7011        }
7012    }
7013}
7014impl fmt::Display for OnConflictAction {
7015    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7016        match self {
7017            Self::DoNothing => write!(f, "DO NOTHING"),
7018            Self::DoUpdate(do_update) => {
7019                write!(f, "DO UPDATE")?;
7020                if !do_update.assignments.is_empty() {
7021                    write!(
7022                        f,
7023                        " SET {}",
7024                        display_comma_separated(&do_update.assignments)
7025                    )?;
7026                }
7027                if let Some(selection) = &do_update.selection {
7028                    write!(f, " WHERE {selection}")?;
7029                }
7030                Ok(())
7031            }
7032        }
7033    }
7034}
7035
7036/// Privileges granted in a GRANT statement or revoked in a REVOKE statement.
7037#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7038#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7039#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7040pub enum Privileges {
7041    /// All privileges applicable to the object type
7042    All {
7043        /// Optional keyword from the spec, ignored in practice
7044        with_privileges_keyword: bool,
7045    },
7046    /// Specific privileges (e.g. `SELECT`, `INSERT`)
7047    Actions(Vec<Action>),
7048}
7049
7050impl fmt::Display for Privileges {
7051    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7052        match self {
7053            Privileges::All {
7054                with_privileges_keyword,
7055            } => {
7056                write!(
7057                    f,
7058                    "ALL{}",
7059                    if *with_privileges_keyword {
7060                        " PRIVILEGES"
7061                    } else {
7062                        ""
7063                    }
7064                )
7065            }
7066            Privileges::Actions(actions) => {
7067                write!(f, "{}", display_comma_separated(actions))
7068            }
7069        }
7070    }
7071}
7072
7073/// Specific direction for FETCH statement
7074#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7075#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7076#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7077pub enum FetchDirection {
7078    /// Fetch a specific count of rows.
7079    Count {
7080        /// The limit value for the count.
7081        limit: ValueWithSpan,
7082    },
7083    /// Fetch the next row.
7084    Next,
7085    /// Fetch the prior row.
7086    Prior,
7087    /// Fetch the first row.
7088    First,
7089    /// Fetch the last row.
7090    Last,
7091    /// Fetch an absolute row by index.
7092    Absolute {
7093        /// The absolute index value.
7094        limit: ValueWithSpan,
7095    },
7096    /// Fetch a row relative to the current position.
7097    Relative {
7098        /// The relative offset value.
7099        limit: ValueWithSpan,
7100    },
7101    /// Fetch all rows.
7102    All,
7103    // FORWARD
7104    // FORWARD count
7105    /// Fetch forward by an optional limit.
7106    Forward {
7107        /// Optional forward limit.
7108        limit: Option<ValueWithSpan>,
7109    },
7110    /// Fetch all forward rows.
7111    ForwardAll,
7112    // BACKWARD
7113    // BACKWARD count
7114    /// Fetch backward by an optional limit.
7115    Backward {
7116        /// Optional backward limit.
7117        limit: Option<ValueWithSpan>,
7118    },
7119    /// Fetch all backward rows.
7120    BackwardAll,
7121}
7122
7123impl fmt::Display for FetchDirection {
7124    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7125        match self {
7126            FetchDirection::Count { limit } => f.write_str(&limit.to_string())?,
7127            FetchDirection::Next => f.write_str("NEXT")?,
7128            FetchDirection::Prior => f.write_str("PRIOR")?,
7129            FetchDirection::First => f.write_str("FIRST")?,
7130            FetchDirection::Last => f.write_str("LAST")?,
7131            FetchDirection::Absolute { limit } => {
7132                f.write_str("ABSOLUTE ")?;
7133                f.write_str(&limit.to_string())?;
7134            }
7135            FetchDirection::Relative { limit } => {
7136                f.write_str("RELATIVE ")?;
7137                f.write_str(&limit.to_string())?;
7138            }
7139            FetchDirection::All => f.write_str("ALL")?,
7140            FetchDirection::Forward { limit } => {
7141                f.write_str("FORWARD")?;
7142
7143                if let Some(l) = limit {
7144                    f.write_str(" ")?;
7145                    f.write_str(&l.to_string())?;
7146                }
7147            }
7148            FetchDirection::ForwardAll => f.write_str("FORWARD ALL")?,
7149            FetchDirection::Backward { limit } => {
7150                f.write_str("BACKWARD")?;
7151
7152                if let Some(l) = limit {
7153                    f.write_str(" ")?;
7154                    f.write_str(&l.to_string())?;
7155                }
7156            }
7157            FetchDirection::BackwardAll => f.write_str("BACKWARD ALL")?,
7158        };
7159
7160        Ok(())
7161    }
7162}
7163
7164/// The "position" for a FETCH statement.
7165///
7166/// [MsSql](https://learn.microsoft.com/en-us/sql/t-sql/language-elements/fetch-transact-sql)
7167#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7168#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7169#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7170pub enum FetchPosition {
7171    /// Use `FROM <pos>` position specifier.
7172    From,
7173    /// Use `IN <pos>` position specifier.
7174    In,
7175}
7176
7177impl fmt::Display for FetchPosition {
7178    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7179        match self {
7180            FetchPosition::From => f.write_str("FROM")?,
7181            FetchPosition::In => f.write_str("IN")?,
7182        };
7183
7184        Ok(())
7185    }
7186}
7187
7188/// A privilege on a database object (table, sequence, etc.).
7189#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7190#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7191#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7192pub enum Action {
7193    /// Add a search optimization.
7194    AddSearchOptimization,
7195    /// Apply an `APPLY` operation with a specific type.
7196    Apply {
7197        /// The type of apply operation.
7198        apply_type: ActionApplyType,
7199    },
7200    /// Apply a budget operation.
7201    ApplyBudget,
7202    /// Attach a listing.
7203    AttachListing,
7204    /// Attach a policy.
7205    AttachPolicy,
7206    /// Audit operation.
7207    Audit,
7208    /// Bind a service endpoint.
7209    BindServiceEndpoint,
7210    /// Connect permission.
7211    Connect,
7212    /// Create action, optionally specifying an object type.
7213    Create {
7214        /// Optional object type to create.
7215        obj_type: Option<ActionCreateObjectType>,
7216    },
7217    /// Actions related to database roles.
7218    DatabaseRole {
7219        /// The role name.
7220        role: ObjectName,
7221    },
7222    /// Delete permission.
7223    Delete,
7224    /// Drop permission.
7225    Drop,
7226    /// Evolve schema permission.
7227    EvolveSchema,
7228    /// Exec action (execute) with optional object type.
7229    Exec {
7230        /// Optional execute object type.
7231        obj_type: Option<ActionExecuteObjectType>,
7232    },
7233    /// Execute action with optional object type.
7234    Execute {
7235        /// Optional execute object type.
7236        obj_type: Option<ActionExecuteObjectType>,
7237    },
7238    /// Failover operation.
7239    Failover,
7240    /// Use imported privileges.
7241    ImportedPrivileges,
7242    /// Import a share.
7243    ImportShare,
7244    /// Insert rows with optional column list.
7245    Insert {
7246        /// Optional list of target columns for insert.
7247        columns: Option<Vec<Ident>>,
7248    },
7249    /// Manage operation with a specific manage type.
7250    Manage {
7251        /// The specific manage sub-type.
7252        manage_type: ActionManageType,
7253    },
7254    /// Manage releases.
7255    ManageReleases,
7256    /// Manage versions.
7257    ManageVersions,
7258    /// Modify operation with an optional modify type.
7259    Modify {
7260        /// The optional modify sub-type.
7261        modify_type: Option<ActionModifyType>,
7262    },
7263    /// Monitor operation with an optional monitor type.
7264    Monitor {
7265        /// The optional monitor sub-type.
7266        monitor_type: Option<ActionMonitorType>,
7267    },
7268    /// Operate permission.
7269    Operate,
7270    /// Override share restrictions.
7271    OverrideShareRestrictions,
7272    /// Ownership permission.
7273    Ownership,
7274    /// Purchase a data exchange listing.
7275    PurchaseDataExchangeListing,
7276
7277    /// Read access.
7278    Read,
7279    /// Read session-level access.
7280    ReadSession,
7281    /// References with optional column list.
7282    References {
7283        /// Optional list of referenced column identifiers.
7284        columns: Option<Vec<Ident>>,
7285    },
7286    /// Replication permission.
7287    Replicate,
7288    /// Resolve all references.
7289    ResolveAll,
7290    /// Role-related permission with target role name.
7291    Role {
7292        /// The target role name.
7293        role: ObjectName,
7294    },
7295    /// Select permission with optional column list.
7296    Select {
7297        /// Optional list of selected columns.
7298        columns: Option<Vec<Ident>>,
7299    },
7300    /// Temporary object permission.
7301    Temporary,
7302    /// Trigger-related permission.
7303    Trigger,
7304    /// Truncate permission.
7305    Truncate,
7306    /// Update permission with optional affected columns.
7307    Update {
7308        /// Optional list of columns affected by update.
7309        columns: Option<Vec<Ident>>,
7310    },
7311    /// Usage permission.
7312    Usage,
7313}
7314
7315impl fmt::Display for Action {
7316    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7317        match self {
7318            Action::AddSearchOptimization => f.write_str("ADD SEARCH OPTIMIZATION")?,
7319            Action::Apply { apply_type } => write!(f, "APPLY {apply_type}")?,
7320            Action::ApplyBudget => f.write_str("APPLYBUDGET")?,
7321            Action::AttachListing => f.write_str("ATTACH LISTING")?,
7322            Action::AttachPolicy => f.write_str("ATTACH POLICY")?,
7323            Action::Audit => f.write_str("AUDIT")?,
7324            Action::BindServiceEndpoint => f.write_str("BIND SERVICE ENDPOINT")?,
7325            Action::Connect => f.write_str("CONNECT")?,
7326            Action::Create { obj_type } => {
7327                f.write_str("CREATE")?;
7328                if let Some(obj_type) = obj_type {
7329                    write!(f, " {obj_type}")?
7330                }
7331            }
7332            Action::DatabaseRole { role } => write!(f, "DATABASE ROLE {role}")?,
7333            Action::Delete => f.write_str("DELETE")?,
7334            Action::Drop => f.write_str("DROP")?,
7335            Action::EvolveSchema => f.write_str("EVOLVE SCHEMA")?,
7336            Action::Exec { obj_type } => {
7337                f.write_str("EXEC")?;
7338                if let Some(obj_type) = obj_type {
7339                    write!(f, " {obj_type}")?
7340                }
7341            }
7342            Action::Execute { obj_type } => {
7343                f.write_str("EXECUTE")?;
7344                if let Some(obj_type) = obj_type {
7345                    write!(f, " {obj_type}")?
7346                }
7347            }
7348            Action::Failover => f.write_str("FAILOVER")?,
7349            Action::ImportedPrivileges => f.write_str("IMPORTED PRIVILEGES")?,
7350            Action::ImportShare => f.write_str("IMPORT SHARE")?,
7351            Action::Insert { .. } => f.write_str("INSERT")?,
7352            Action::Manage { manage_type } => write!(f, "MANAGE {manage_type}")?,
7353            Action::ManageReleases => f.write_str("MANAGE RELEASES")?,
7354            Action::ManageVersions => f.write_str("MANAGE VERSIONS")?,
7355            Action::Modify { modify_type } => {
7356                write!(f, "MODIFY")?;
7357                if let Some(modify_type) = modify_type {
7358                    write!(f, " {modify_type}")?;
7359                }
7360            }
7361            Action::Monitor { monitor_type } => {
7362                write!(f, "MONITOR")?;
7363                if let Some(monitor_type) = monitor_type {
7364                    write!(f, " {monitor_type}")?
7365                }
7366            }
7367            Action::Operate => f.write_str("OPERATE")?,
7368            Action::OverrideShareRestrictions => f.write_str("OVERRIDE SHARE RESTRICTIONS")?,
7369            Action::Ownership => f.write_str("OWNERSHIP")?,
7370            Action::PurchaseDataExchangeListing => f.write_str("PURCHASE DATA EXCHANGE LISTING")?,
7371            Action::Read => f.write_str("READ")?,
7372            Action::ReadSession => f.write_str("READ SESSION")?,
7373            Action::References { .. } => f.write_str("REFERENCES")?,
7374            Action::Replicate => f.write_str("REPLICATE")?,
7375            Action::ResolveAll => f.write_str("RESOLVE ALL")?,
7376            Action::Role { role } => write!(f, "ROLE {role}")?,
7377            Action::Select { .. } => f.write_str("SELECT")?,
7378            Action::Temporary => f.write_str("TEMPORARY")?,
7379            Action::Trigger => f.write_str("TRIGGER")?,
7380            Action::Truncate => f.write_str("TRUNCATE")?,
7381            Action::Update { .. } => f.write_str("UPDATE")?,
7382            Action::Usage => f.write_str("USAGE")?,
7383        };
7384        match self {
7385            Action::Insert { columns }
7386            | Action::References { columns }
7387            | Action::Select { columns }
7388            | Action::Update { columns } => {
7389                if let Some(columns) = columns {
7390                    write!(f, " ({})", display_comma_separated(columns))?;
7391                }
7392            }
7393            _ => (),
7394        };
7395        Ok(())
7396    }
7397}
7398
7399#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7400#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7401#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7402/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
7403/// under `globalPrivileges` in the `CREATE` privilege.
7404pub enum ActionCreateObjectType {
7405    /// An account-level object.
7406    Account,
7407    /// An application object.
7408    Application,
7409    /// An application package object.
7410    ApplicationPackage,
7411    /// A compute pool object.
7412    ComputePool,
7413    /// A data exchange listing.
7414    DataExchangeListing,
7415    /// A database object.
7416    Database,
7417    /// An external volume object.
7418    ExternalVolume,
7419    /// A failover group object.
7420    FailoverGroup,
7421    /// An integration object.
7422    Integration,
7423    /// A network policy object.
7424    NetworkPolicy,
7425    /// An organization listing.
7426    OrganiationListing,
7427    /// A replication group object.
7428    ReplicationGroup,
7429    /// A role object.
7430    Role,
7431    /// A schema object.
7432    Schema,
7433    /// A share object.
7434    Share,
7435    /// A user object.
7436    User,
7437    /// A warehouse object.
7438    Warehouse,
7439}
7440
7441impl fmt::Display for ActionCreateObjectType {
7442    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7443        match self {
7444            ActionCreateObjectType::Account => write!(f, "ACCOUNT"),
7445            ActionCreateObjectType::Application => write!(f, "APPLICATION"),
7446            ActionCreateObjectType::ApplicationPackage => write!(f, "APPLICATION PACKAGE"),
7447            ActionCreateObjectType::ComputePool => write!(f, "COMPUTE POOL"),
7448            ActionCreateObjectType::DataExchangeListing => write!(f, "DATA EXCHANGE LISTING"),
7449            ActionCreateObjectType::Database => write!(f, "DATABASE"),
7450            ActionCreateObjectType::ExternalVolume => write!(f, "EXTERNAL VOLUME"),
7451            ActionCreateObjectType::FailoverGroup => write!(f, "FAILOVER GROUP"),
7452            ActionCreateObjectType::Integration => write!(f, "INTEGRATION"),
7453            ActionCreateObjectType::NetworkPolicy => write!(f, "NETWORK POLICY"),
7454            ActionCreateObjectType::OrganiationListing => write!(f, "ORGANIZATION LISTING"),
7455            ActionCreateObjectType::ReplicationGroup => write!(f, "REPLICATION GROUP"),
7456            ActionCreateObjectType::Role => write!(f, "ROLE"),
7457            ActionCreateObjectType::Schema => write!(f, "SCHEMA"),
7458            ActionCreateObjectType::Share => write!(f, "SHARE"),
7459            ActionCreateObjectType::User => write!(f, "USER"),
7460            ActionCreateObjectType::Warehouse => write!(f, "WAREHOUSE"),
7461        }
7462    }
7463}
7464
7465#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7466#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7467#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7468/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
7469/// under `globalPrivileges` in the `APPLY` privilege.
7470pub enum ActionApplyType {
7471    /// Apply an aggregation policy.
7472    AggregationPolicy,
7473    /// Apply an authentication policy.
7474    AuthenticationPolicy,
7475    /// Apply a join policy.
7476    JoinPolicy,
7477    /// Apply a masking policy.
7478    MaskingPolicy,
7479    /// Apply a packages policy.
7480    PackagesPolicy,
7481    /// Apply a password policy.
7482    PasswordPolicy,
7483    /// Apply a projection policy.
7484    ProjectionPolicy,
7485    /// Apply a row access policy.
7486    RowAccessPolicy,
7487    /// Apply a session policy.
7488    SessionPolicy,
7489    /// Apply a tag.
7490    Tag,
7491}
7492
7493impl fmt::Display for ActionApplyType {
7494    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7495        match self {
7496            ActionApplyType::AggregationPolicy => write!(f, "AGGREGATION POLICY"),
7497            ActionApplyType::AuthenticationPolicy => write!(f, "AUTHENTICATION POLICY"),
7498            ActionApplyType::JoinPolicy => write!(f, "JOIN POLICY"),
7499            ActionApplyType::MaskingPolicy => write!(f, "MASKING POLICY"),
7500            ActionApplyType::PackagesPolicy => write!(f, "PACKAGES POLICY"),
7501            ActionApplyType::PasswordPolicy => write!(f, "PASSWORD POLICY"),
7502            ActionApplyType::ProjectionPolicy => write!(f, "PROJECTION POLICY"),
7503            ActionApplyType::RowAccessPolicy => write!(f, "ROW ACCESS POLICY"),
7504            ActionApplyType::SessionPolicy => write!(f, "SESSION POLICY"),
7505            ActionApplyType::Tag => write!(f, "TAG"),
7506        }
7507    }
7508}
7509
7510#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7511#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7512#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7513/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
7514/// under `globalPrivileges` in the `EXECUTE` privilege.
7515pub enum ActionExecuteObjectType {
7516    /// Alert object.
7517    Alert,
7518    /// Data metric function object.
7519    DataMetricFunction,
7520    /// Managed alert object.
7521    ManagedAlert,
7522    /// Managed task object.
7523    ManagedTask,
7524    /// Task object.
7525    Task,
7526}
7527
7528impl fmt::Display for ActionExecuteObjectType {
7529    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7530        match self {
7531            ActionExecuteObjectType::Alert => write!(f, "ALERT"),
7532            ActionExecuteObjectType::DataMetricFunction => write!(f, "DATA METRIC FUNCTION"),
7533            ActionExecuteObjectType::ManagedAlert => write!(f, "MANAGED ALERT"),
7534            ActionExecuteObjectType::ManagedTask => write!(f, "MANAGED TASK"),
7535            ActionExecuteObjectType::Task => write!(f, "TASK"),
7536        }
7537    }
7538}
7539
7540#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7541#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7542#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7543/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
7544/// under `globalPrivileges` in the `MANAGE` privilege.
7545pub enum ActionManageType {
7546    /// Account support cases management.
7547    AccountSupportCases,
7548    /// Event sharing management.
7549    EventSharing,
7550    /// Grants management.
7551    Grants,
7552    /// Listing auto-fulfillment management.
7553    ListingAutoFulfillment,
7554    /// Organization support cases management.
7555    OrganizationSupportCases,
7556    /// User support cases management.
7557    UserSupportCases,
7558    /// Warehouses management.
7559    Warehouses,
7560}
7561
7562impl fmt::Display for ActionManageType {
7563    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7564        match self {
7565            ActionManageType::AccountSupportCases => write!(f, "ACCOUNT SUPPORT CASES"),
7566            ActionManageType::EventSharing => write!(f, "EVENT SHARING"),
7567            ActionManageType::Grants => write!(f, "GRANTS"),
7568            ActionManageType::ListingAutoFulfillment => write!(f, "LISTING AUTO FULFILLMENT"),
7569            ActionManageType::OrganizationSupportCases => write!(f, "ORGANIZATION SUPPORT CASES"),
7570            ActionManageType::UserSupportCases => write!(f, "USER SUPPORT CASES"),
7571            ActionManageType::Warehouses => write!(f, "WAREHOUSES"),
7572        }
7573    }
7574}
7575
7576#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7577#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7578#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7579/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
7580/// under `globalPrivileges` in the `MODIFY` privilege.
7581pub enum ActionModifyType {
7582    /// Modify log level.
7583    LogLevel,
7584    /// Modify trace level.
7585    TraceLevel,
7586    /// Modify session log level.
7587    SessionLogLevel,
7588    /// Modify session trace level.
7589    SessionTraceLevel,
7590}
7591
7592impl fmt::Display for ActionModifyType {
7593    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7594        match self {
7595            ActionModifyType::LogLevel => write!(f, "LOG LEVEL"),
7596            ActionModifyType::TraceLevel => write!(f, "TRACE LEVEL"),
7597            ActionModifyType::SessionLogLevel => write!(f, "SESSION LOG LEVEL"),
7598            ActionModifyType::SessionTraceLevel => write!(f, "SESSION TRACE LEVEL"),
7599        }
7600    }
7601}
7602
7603#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7604#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7605#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7606/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
7607/// under `globalPrivileges` in the `MONITOR` privilege.
7608pub enum ActionMonitorType {
7609    /// Monitor execution.
7610    Execution,
7611    /// Monitor security.
7612    Security,
7613    /// Monitor usage.
7614    Usage,
7615}
7616
7617impl fmt::Display for ActionMonitorType {
7618    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7619        match self {
7620            ActionMonitorType::Execution => write!(f, "EXECUTION"),
7621            ActionMonitorType::Security => write!(f, "SECURITY"),
7622            ActionMonitorType::Usage => write!(f, "USAGE"),
7623        }
7624    }
7625}
7626
7627/// The principal that receives the privileges
7628#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7629#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7630#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7631pub struct Grantee {
7632    /// The category/type of grantee (role, user, share, etc.).
7633    pub grantee_type: GranteesType,
7634    /// Optional name of the grantee (identifier or user@host).
7635    pub name: Option<GranteeName>,
7636}
7637
7638impl fmt::Display for Grantee {
7639    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7640        let keyword = match self.grantee_type {
7641            GranteesType::Role => "ROLE",
7642            GranteesType::Share => "SHARE",
7643            GranteesType::User => "USER",
7644            GranteesType::Group => "GROUP",
7645            GranteesType::Public => "PUBLIC",
7646            GranteesType::DatabaseRole => "DATABASE ROLE",
7647            GranteesType::Application => "APPLICATION",
7648            GranteesType::ApplicationRole => "APPLICATION ROLE",
7649            GranteesType::None => "",
7650        };
7651        f.write_str(keyword)?;
7652        if let Some(name) = &self.name {
7653            if !keyword.is_empty() {
7654                f.write_str(" ")?;
7655            }
7656            name.fmt(f)?;
7657        }
7658        Ok(())
7659    }
7660}
7661
7662#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7663#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7664#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7665/// The kind of principal receiving privileges.
7666pub enum GranteesType {
7667    /// A role principal.
7668    Role,
7669    /// A share principal.
7670    Share,
7671    /// A user principal.
7672    User,
7673    /// A group principal.
7674    Group,
7675    /// The public principal.
7676    Public,
7677    /// A database role principal.
7678    DatabaseRole,
7679    /// An application principal.
7680    Application,
7681    /// An application role principal.
7682    ApplicationRole,
7683    /// No specific principal (e.g. `NONE`).
7684    None,
7685}
7686
7687/// Users/roles designated in a GRANT/REVOKE
7688#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7689#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7690#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7691pub enum GranteeName {
7692    /// A bare identifier
7693    ObjectName(ObjectName),
7694    /// A MySQL user/host pair such as 'root'@'%'
7695    UserHost {
7696        /// The user identifier portion.
7697        user: Ident,
7698        /// The host identifier portion.
7699        host: Ident,
7700    },
7701}
7702
7703impl fmt::Display for GranteeName {
7704    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7705        match self {
7706            GranteeName::ObjectName(name) => name.fmt(f),
7707            GranteeName::UserHost { user, host } => {
7708                write!(f, "{user}@{host}")
7709            }
7710        }
7711    }
7712}
7713
7714/// Objects on which privileges are granted in a GRANT statement.
7715#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7716#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7717#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7718pub enum GrantObjects {
7719    /// Grant privileges on `ALL SEQUENCES IN SCHEMA <schema_name> [, ...]`
7720    AllSequencesInSchema {
7721        /// The target schema names.
7722        schemas: Vec<ObjectName>,
7723    },
7724    /// Grant privileges on `ALL TABLES IN SCHEMA <schema_name> [, ...]`
7725    AllTablesInSchema {
7726        /// The target schema names.
7727        schemas: Vec<ObjectName>,
7728    },
7729    /// Grant privileges on `ALL VIEWS IN SCHEMA <schema_name> [, ...]`
7730    AllViewsInSchema {
7731        /// The target schema names.
7732        schemas: Vec<ObjectName>,
7733    },
7734    /// Grant privileges on `ALL MATERIALIZED VIEWS IN SCHEMA <schema_name> [, ...]`
7735    AllMaterializedViewsInSchema {
7736        /// The target schema names.
7737        schemas: Vec<ObjectName>,
7738    },
7739    /// Grant privileges on `ALL EXTERNAL TABLES IN SCHEMA <schema_name> [, ...]`
7740    AllExternalTablesInSchema {
7741        /// The target schema names.
7742        schemas: Vec<ObjectName>,
7743    },
7744    /// Grant privileges on `ALL FUNCTIONS IN SCHEMA <schema_name> [, ...]`
7745    AllFunctionsInSchema {
7746        /// The target schema names.
7747        schemas: Vec<ObjectName>,
7748    },
7749    /// Grant privileges on `FUTURE SCHEMAS IN DATABASE <database_name> [, ...]`
7750    FutureSchemasInDatabase {
7751        /// The target database names.
7752        databases: Vec<ObjectName>,
7753    },
7754    /// Grant privileges on `FUTURE TABLES IN SCHEMA <schema_name> [, ...]`
7755    FutureTablesInSchema {
7756        /// The target schema names.
7757        schemas: Vec<ObjectName>,
7758    },
7759    /// Grant privileges on `FUTURE VIEWS IN SCHEMA <schema_name> [, ...]`
7760    FutureViewsInSchema {
7761        /// The target schema names.
7762        schemas: Vec<ObjectName>,
7763    },
7764    /// Grant privileges on `FUTURE EXTERNAL TABLES IN SCHEMA <schema_name> [, ...]`
7765    FutureExternalTablesInSchema {
7766        /// The target schema names.
7767        schemas: Vec<ObjectName>,
7768    },
7769    /// Grant privileges on `FUTURE MATERIALIZED VIEWS IN SCHEMA <schema_name> [, ...]`
7770    FutureMaterializedViewsInSchema {
7771        /// The target schema names.
7772        schemas: Vec<ObjectName>,
7773    },
7774    /// Grant privileges on `FUTURE SEQUENCES IN SCHEMA <schema_name> [, ...]`
7775    FutureSequencesInSchema {
7776        /// The target schema names.
7777        schemas: Vec<ObjectName>,
7778    },
7779    /// Grant privileges on specific databases
7780    Databases(Vec<ObjectName>),
7781    /// Grant privileges on specific schemas
7782    Schemas(Vec<ObjectName>),
7783    /// Grant privileges on specific sequences
7784    Sequences(Vec<ObjectName>),
7785    /// Grant privileges on specific tables
7786    Tables(Vec<ObjectName>),
7787    /// Grant privileges on specific views
7788    Views(Vec<ObjectName>),
7789    /// Grant privileges on specific warehouses
7790    Warehouses(Vec<ObjectName>),
7791    /// Grant privileges on specific integrations
7792    Integrations(Vec<ObjectName>),
7793    /// Grant privileges on resource monitors
7794    ResourceMonitors(Vec<ObjectName>),
7795    /// Grant privileges on users
7796    Users(Vec<ObjectName>),
7797    /// Grant privileges on compute pools
7798    ComputePools(Vec<ObjectName>),
7799    /// Grant privileges on connections
7800    Connections(Vec<ObjectName>),
7801    /// Grant privileges on failover groups
7802    FailoverGroup(Vec<ObjectName>),
7803    /// Grant privileges on replication group
7804    ReplicationGroup(Vec<ObjectName>),
7805    /// Grant privileges on external volumes
7806    ExternalVolumes(Vec<ObjectName>),
7807    /// Grant privileges on a procedure. In dialects that
7808    /// support overloading, the argument types must be specified.
7809    ///
7810    /// For example:
7811    /// `GRANT USAGE ON PROCEDURE foo(varchar) TO ROLE role1`
7812    Procedure {
7813        /// The procedure name.
7814        name: ObjectName,
7815        /// Optional argument types for overloaded procedures.
7816        arg_types: Vec<DataType>,
7817    },
7818
7819    /// Grant privileges on a function. In dialects that
7820    /// support overloading, the argument types must be specified.
7821    ///
7822    /// For example:
7823    /// `GRANT USAGE ON FUNCTION foo(varchar) TO ROLE role1`
7824    Function {
7825        /// The function name.
7826        name: ObjectName,
7827        /// Optional argument types for overloaded functions.
7828        arg_types: Vec<DataType>,
7829    },
7830}
7831
7832impl fmt::Display for GrantObjects {
7833    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7834        match self {
7835            GrantObjects::Sequences(sequences) => {
7836                write!(f, "SEQUENCE {}", display_comma_separated(sequences))
7837            }
7838            GrantObjects::Databases(databases) => {
7839                write!(f, "DATABASE {}", display_comma_separated(databases))
7840            }
7841            GrantObjects::Schemas(schemas) => {
7842                write!(f, "SCHEMA {}", display_comma_separated(schemas))
7843            }
7844            GrantObjects::Tables(tables) => {
7845                write!(f, "{}", display_comma_separated(tables))
7846            }
7847            GrantObjects::Views(views) => {
7848                write!(f, "VIEW {}", display_comma_separated(views))
7849            }
7850            GrantObjects::Warehouses(warehouses) => {
7851                write!(f, "WAREHOUSE {}", display_comma_separated(warehouses))
7852            }
7853            GrantObjects::Integrations(integrations) => {
7854                write!(f, "INTEGRATION {}", display_comma_separated(integrations))
7855            }
7856            GrantObjects::AllSequencesInSchema { schemas } => {
7857                write!(
7858                    f,
7859                    "ALL SEQUENCES IN SCHEMA {}",
7860                    display_comma_separated(schemas)
7861                )
7862            }
7863            GrantObjects::AllTablesInSchema { schemas } => {
7864                write!(
7865                    f,
7866                    "ALL TABLES IN SCHEMA {}",
7867                    display_comma_separated(schemas)
7868                )
7869            }
7870            GrantObjects::AllExternalTablesInSchema { schemas } => {
7871                write!(
7872                    f,
7873                    "ALL EXTERNAL TABLES IN SCHEMA {}",
7874                    display_comma_separated(schemas)
7875                )
7876            }
7877            GrantObjects::AllViewsInSchema { schemas } => {
7878                write!(
7879                    f,
7880                    "ALL VIEWS IN SCHEMA {}",
7881                    display_comma_separated(schemas)
7882                )
7883            }
7884            GrantObjects::AllMaterializedViewsInSchema { schemas } => {
7885                write!(
7886                    f,
7887                    "ALL MATERIALIZED VIEWS IN SCHEMA {}",
7888                    display_comma_separated(schemas)
7889                )
7890            }
7891            GrantObjects::AllFunctionsInSchema { schemas } => {
7892                write!(
7893                    f,
7894                    "ALL FUNCTIONS IN SCHEMA {}",
7895                    display_comma_separated(schemas)
7896                )
7897            }
7898            GrantObjects::FutureSchemasInDatabase { databases } => {
7899                write!(
7900                    f,
7901                    "FUTURE SCHEMAS IN DATABASE {}",
7902                    display_comma_separated(databases)
7903                )
7904            }
7905            GrantObjects::FutureTablesInSchema { schemas } => {
7906                write!(
7907                    f,
7908                    "FUTURE TABLES IN SCHEMA {}",
7909                    display_comma_separated(schemas)
7910                )
7911            }
7912            GrantObjects::FutureExternalTablesInSchema { schemas } => {
7913                write!(
7914                    f,
7915                    "FUTURE EXTERNAL TABLES IN SCHEMA {}",
7916                    display_comma_separated(schemas)
7917                )
7918            }
7919            GrantObjects::FutureViewsInSchema { schemas } => {
7920                write!(
7921                    f,
7922                    "FUTURE VIEWS IN SCHEMA {}",
7923                    display_comma_separated(schemas)
7924                )
7925            }
7926            GrantObjects::FutureMaterializedViewsInSchema { schemas } => {
7927                write!(
7928                    f,
7929                    "FUTURE MATERIALIZED VIEWS IN SCHEMA {}",
7930                    display_comma_separated(schemas)
7931                )
7932            }
7933            GrantObjects::FutureSequencesInSchema { schemas } => {
7934                write!(
7935                    f,
7936                    "FUTURE SEQUENCES IN SCHEMA {}",
7937                    display_comma_separated(schemas)
7938                )
7939            }
7940            GrantObjects::ResourceMonitors(objects) => {
7941                write!(f, "RESOURCE MONITOR {}", display_comma_separated(objects))
7942            }
7943            GrantObjects::Users(objects) => {
7944                write!(f, "USER {}", display_comma_separated(objects))
7945            }
7946            GrantObjects::ComputePools(objects) => {
7947                write!(f, "COMPUTE POOL {}", display_comma_separated(objects))
7948            }
7949            GrantObjects::Connections(objects) => {
7950                write!(f, "CONNECTION {}", display_comma_separated(objects))
7951            }
7952            GrantObjects::FailoverGroup(objects) => {
7953                write!(f, "FAILOVER GROUP {}", display_comma_separated(objects))
7954            }
7955            GrantObjects::ReplicationGroup(objects) => {
7956                write!(f, "REPLICATION GROUP {}", display_comma_separated(objects))
7957            }
7958            GrantObjects::ExternalVolumes(objects) => {
7959                write!(f, "EXTERNAL VOLUME {}", display_comma_separated(objects))
7960            }
7961            GrantObjects::Procedure { name, arg_types } => {
7962                write!(f, "PROCEDURE {name}")?;
7963                if !arg_types.is_empty() {
7964                    write!(f, "({})", display_comma_separated(arg_types))?;
7965                }
7966                Ok(())
7967            }
7968            GrantObjects::Function { name, arg_types } => {
7969                write!(f, "FUNCTION {name}")?;
7970                if !arg_types.is_empty() {
7971                    write!(f, "({})", display_comma_separated(arg_types))?;
7972                }
7973                Ok(())
7974            }
7975        }
7976    }
7977}
7978
7979/// A `DENY` statement
7980///
7981/// [MsSql](https://learn.microsoft.com/en-us/sql/t-sql/statements/deny-transact-sql)
7982#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7983#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7984#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7985pub struct DenyStatement {
7986    /// The privileges to deny.
7987    pub privileges: Privileges,
7988    /// The objects the privileges apply to.
7989    pub objects: GrantObjects,
7990    /// The grantees (users/roles) to whom the denial applies.
7991    pub grantees: Vec<Grantee>,
7992    /// Optional identifier of the principal that performed the grant.
7993    pub granted_by: Option<Ident>,
7994    /// Optional cascade option controlling dependent objects.
7995    pub cascade: Option<CascadeOption>,
7996}
7997
7998impl fmt::Display for DenyStatement {
7999    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8000        write!(f, "DENY {}", self.privileges)?;
8001        write!(f, " ON {}", self.objects)?;
8002        if !self.grantees.is_empty() {
8003            write!(f, " TO {}", display_comma_separated(&self.grantees))?;
8004        }
8005        if let Some(cascade) = &self.cascade {
8006            write!(f, " {cascade}")?;
8007        }
8008        if let Some(granted_by) = &self.granted_by {
8009            write!(f, " AS {granted_by}")?;
8010        }
8011        Ok(())
8012    }
8013}
8014
8015/// SQL assignment `foo = expr` as used in SQLUpdate
8016#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8017#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8018#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8019pub struct Assignment {
8020    /// The left-hand side of the assignment.
8021    pub target: AssignmentTarget,
8022    /// The expression assigned to the target.
8023    pub value: Expr,
8024}
8025
8026impl fmt::Display for Assignment {
8027    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8028        write!(f, "{} = {}", self.target, self.value)
8029    }
8030}
8031
8032/// Left-hand side of an assignment in an UPDATE statement,
8033/// e.g. `foo` in `foo = 5` (ColumnName assignment) or
8034/// `(a, b)` in `(a, b) = (1, 2)` (Tuple assignment).
8035#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8036#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8037#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8038pub enum AssignmentTarget {
8039    /// A single column
8040    ColumnName(ObjectName),
8041    /// An array element or slice assignment target.
8042    Subscript {
8043        /// The array column being assigned.
8044        column: ObjectName,
8045        /// One or more array indexes or slices.
8046        subscripts: Vec<Subscript>,
8047    },
8048    /// A tuple of columns
8049    Tuple(Vec<ObjectName>),
8050}
8051
8052impl fmt::Display for AssignmentTarget {
8053    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8054        match self {
8055            AssignmentTarget::ColumnName(column) => write!(f, "{column}"),
8056            AssignmentTarget::Subscript { column, subscripts } => {
8057                write!(f, "{column}")?;
8058                for subscript in subscripts {
8059                    write!(f, "[{subscript}]")?;
8060                }
8061                Ok(())
8062            }
8063            AssignmentTarget::Tuple(columns) => write!(f, "({})", display_comma_separated(columns)),
8064        }
8065    }
8066}
8067
8068#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8069#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8070#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8071/// Expression forms allowed as a function argument.
8072pub enum FunctionArgExpr {
8073    /// A normal expression argument.
8074    Expr(Expr),
8075    /// Qualified wildcard, e.g. `alias.*` or `schema.table.*`.
8076    QualifiedWildcard(ObjectName),
8077    /// An unqualified `*` wildcard.
8078    Wildcard,
8079    /// An unqualified `*` wildcard with additional options, e.g. `* EXCLUDE(col)`.
8080    ///
8081    /// Used in Snowflake to support expressions like `HASH(* EXCLUDE(col))`.
8082    WildcardWithOptions(WildcardAdditionalOptions),
8083}
8084
8085impl From<Expr> for FunctionArgExpr {
8086    fn from(wildcard_expr: Expr) -> Self {
8087        match wildcard_expr {
8088            Expr::QualifiedWildcard(prefix, _) => Self::QualifiedWildcard(prefix),
8089            Expr::Wildcard(_) => Self::Wildcard,
8090            expr => Self::Expr(expr),
8091        }
8092    }
8093}
8094
8095impl fmt::Display for FunctionArgExpr {
8096    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8097        match self {
8098            FunctionArgExpr::Expr(expr) => write!(f, "{expr}"),
8099            FunctionArgExpr::QualifiedWildcard(prefix) => write!(f, "{prefix}.*"),
8100            FunctionArgExpr::Wildcard => f.write_str("*"),
8101            FunctionArgExpr::WildcardWithOptions(opts) => write!(f, "*{opts}"),
8102        }
8103    }
8104}
8105
8106#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8107#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8108#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8109/// Operator used to separate function arguments
8110pub enum FunctionArgOperator {
8111    /// function(arg1 = value1)
8112    Equals,
8113    /// function(arg1 => value1)
8114    RightArrow,
8115    /// function(arg1 := value1)
8116    Assignment,
8117    /// function(arg1 : value1)
8118    Colon,
8119    /// function(arg1 VALUE value1)
8120    Value,
8121    /// function(arg1 value1), with no operator between the name and the value,
8122    /// as in PostgreSQL `XMLPARSE(DOCUMENT value)`
8123    ///
8124    /// [PostgreSQL](https://www.postgresql.org/docs/current/datatype-xml.html#DATATYPE-XML-CREATING)
8125    Space,
8126}
8127
8128impl fmt::Display for FunctionArgOperator {
8129    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8130        match self {
8131            FunctionArgOperator::Equals => f.write_str("="),
8132            FunctionArgOperator::RightArrow => f.write_str("=>"),
8133            FunctionArgOperator::Assignment => f.write_str(":="),
8134            FunctionArgOperator::Colon => f.write_str(":"),
8135            FunctionArgOperator::Value => f.write_str("VALUE"),
8136            FunctionArgOperator::Space => Ok(()),
8137        }
8138    }
8139}
8140
8141#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8142#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8143#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8144/// Forms of function arguments (named, expression-named, or positional).
8145pub enum FunctionArg {
8146    /// `name` is identifier
8147    ///
8148    /// Enabled when `Dialect::supports_named_fn_args_with_expr_name` returns 'false'
8149    Named {
8150        /// The identifier name of the argument.
8151        name: Ident,
8152        /// The argument expression or wildcard form.
8153        arg: FunctionArgExpr,
8154        /// The operator separating name and value.
8155        operator: FunctionArgOperator,
8156    },
8157    /// `name` is arbitrary expression
8158    ///
8159    /// Enabled when `Dialect::supports_named_fn_args_with_expr_name` returns 'true'
8160    ExprNamed {
8161        /// The expression used as the argument name.
8162        name: Expr,
8163        /// The argument expression or wildcard form.
8164        arg: FunctionArgExpr,
8165        /// The operator separating name and value.
8166        operator: FunctionArgOperator,
8167    },
8168    /// An unnamed argument (positional), given by expression or wildcard.
8169    Unnamed(FunctionArgExpr),
8170}
8171
8172impl fmt::Display for FunctionArg {
8173    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8174        match self {
8175            FunctionArg::Named {
8176                name,
8177                arg,
8178                operator,
8179            } => fmt_named_function_arg(f, name, operator, arg),
8180            FunctionArg::ExprNamed {
8181                name,
8182                arg,
8183                operator,
8184            } => fmt_named_function_arg(f, name, operator, arg),
8185            FunctionArg::Unnamed(unnamed_arg) => write!(f, "{unnamed_arg}"),
8186        }
8187    }
8188}
8189
8190/// Whether `expr` renders with an operator character first. A prefix `-` or `!`
8191/// must not abut one, since `--` starts a line comment and compound tokens
8192/// like `!!` or `!~` alter the parsed AST or fail to parse.
8193fn starts_with_operator_char(mut expr: &Expr) -> bool {
8194    loop {
8195        match expr {
8196            Expr::UnaryOp { op, .. } => return !matches!(op, UnaryOperator::Not),
8197            Expr::BinaryOp { left, .. } => expr = left,
8198            _ => return false,
8199        }
8200    }
8201}
8202
8203/// `FunctionArgOperator::Space` has no token of its own, so the name and the
8204/// value are separated by a single space instead.
8205fn fmt_named_function_arg(
8206    f: &mut fmt::Formatter,
8207    name: &impl fmt::Display,
8208    operator: &FunctionArgOperator,
8209    arg: &FunctionArgExpr,
8210) -> fmt::Result {
8211    match operator {
8212        FunctionArgOperator::Space => write!(f, "{name} {arg}"),
8213        _ => write!(f, "{name} {operator} {arg}"),
8214    }
8215}
8216
8217#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8218#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8219#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8220/// Which cursor(s) to close.
8221pub enum CloseCursor {
8222    /// Close all cursors.
8223    All,
8224    /// Close a specific cursor by name.
8225    Specific {
8226        /// The name of the cursor to close.
8227        name: Ident,
8228    },
8229}
8230
8231impl fmt::Display for CloseCursor {
8232    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8233        match self {
8234            CloseCursor::All => write!(f, "ALL"),
8235            CloseCursor::Specific { name } => write!(f, "{name}"),
8236        }
8237    }
8238}
8239
8240/// A Drop Domain statement
8241#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8242#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8243#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8244pub struct DropDomain {
8245    /// Whether to drop the domain if it exists
8246    pub if_exists: bool,
8247    /// The name of the domain to drop
8248    pub name: ObjectName,
8249    /// The behavior to apply when dropping the domain
8250    pub drop_behavior: Option<DropBehavior>,
8251}
8252
8253/// A constant of form `<data_type> 'value'`.
8254/// This can represent ANSI SQL `DATE`, `TIME`, and `TIMESTAMP` literals (such as `DATE '2020-01-01'`),
8255/// as well as constants of other types (a non-standard PostgreSQL extension).
8256#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8257#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8258#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8259pub struct TypedString {
8260    /// The data type of the typed string (e.g. DATE, TIME, TIMESTAMP).
8261    pub data_type: DataType,
8262    /// The value of the constant.
8263    /// Hint: you can unwrap the string value using `value.into_string()`.
8264    pub value: ValueWithSpan,
8265    /// Flags whether this TypedString uses the [ODBC syntax].
8266    ///
8267    /// Example:
8268    /// ```sql
8269    /// -- An ODBC date literal:
8270    /// SELECT {d '2025-07-16'}
8271    /// -- This is equivalent to the standard ANSI SQL literal:
8272    /// SELECT DATE '2025-07-16'
8273    ///
8274    /// [ODBC syntax]: https://learn.microsoft.com/en-us/sql/odbc/reference/develop-app/date-time-and-timestamp-literals?view=sql-server-2017
8275    pub uses_odbc_syntax: bool,
8276}
8277
8278impl fmt::Display for TypedString {
8279    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8280        let data_type = &self.data_type;
8281        let value = &self.value;
8282        match self.uses_odbc_syntax {
8283            false => {
8284                write!(f, "{data_type}")?;
8285                write!(f, " {value}")
8286            }
8287            true => {
8288                let prefix = match data_type {
8289                    DataType::Date => "d",
8290                    DataType::Time(..) => "t",
8291                    DataType::Timestamp(..) => "ts",
8292                    _ => "?",
8293                };
8294                write!(f, "{{{prefix} {value}}}")
8295            }
8296        }
8297    }
8298}
8299
8300/// A function call
8301#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8302#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8303#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8304pub struct Function {
8305    /// The function name (may be qualified).
8306    pub name: ObjectName,
8307    /// Flags whether this function call uses the [ODBC syntax].
8308    ///
8309    /// Example:
8310    /// ```sql
8311    /// SELECT {fn CONCAT('foo', 'bar')}
8312    /// ```
8313    ///
8314    /// [ODBC syntax]: https://learn.microsoft.com/en-us/sql/odbc/reference/develop-app/scalar-function-calls?view=sql-server-2017
8315    pub uses_odbc_syntax: bool,
8316    /// The parameters to the function, including any options specified within the
8317    /// delimiting parentheses.
8318    ///
8319    /// Example:
8320    /// ```plaintext
8321    /// HISTOGRAM(0.5, 0.6)(x, y)
8322    /// ```
8323    ///
8324    /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/aggregate-functions/parametric-functions)
8325    pub parameters: FunctionArguments,
8326    /// The arguments to the function, including any options specified within the
8327    /// delimiting parentheses.
8328    pub args: FunctionArguments,
8329    /// A clause used with certain aggregate functions to control the ordering
8330    /// within grouped sets before the function is applied.
8331    ///
8332    /// Syntax:
8333    /// ```plaintext
8334    /// <aggregate_function>(expression) WITHIN GROUP (ORDER BY key [ASC | DESC], ...)
8335    /// ```
8336    pub within_group: Vec<OrderByExpr>,
8337    /// e.g. `x > 5` in `COUNT(x) FILTER (WHERE x > 5)`
8338    pub filter: Option<Box<Expr>>,
8339    /// Indicates how `NULL`s should be handled in the calculation.
8340    ///
8341    /// Example:
8342    /// ```plaintext
8343    /// FIRST_VALUE( <expr> ) [ { IGNORE | RESPECT } NULLS ] OVER ...
8344    /// ```
8345    ///
8346    /// [Snowflake](https://docs.snowflake.com/en/sql-reference/functions/first_value)
8347    pub null_treatment: Option<NullTreatment>,
8348    /// The `OVER` clause, indicating a window function call.
8349    pub over: Option<WindowType>,
8350}
8351
8352impl fmt::Display for Function {
8353    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8354        if self.uses_odbc_syntax {
8355            write!(f, "{{fn ")?;
8356        }
8357
8358        write!(f, "{}{}{}", self.name, self.parameters, self.args)?;
8359
8360        if !self.within_group.is_empty() {
8361            write!(
8362                f,
8363                " WITHIN GROUP (ORDER BY {})",
8364                display_comma_separated(&self.within_group)
8365            )?;
8366        }
8367
8368        if let Some(filter_cond) = &self.filter {
8369            write!(f, " FILTER (WHERE {filter_cond})")?;
8370        }
8371
8372        if let Some(null_treatment) = &self.null_treatment {
8373            write!(f, " {null_treatment}")?;
8374        }
8375
8376        if let Some(o) = &self.over {
8377            f.write_str(" OVER ")?;
8378            o.fmt(f)?;
8379        }
8380
8381        if self.uses_odbc_syntax {
8382            write!(f, "}}")?;
8383        }
8384
8385        Ok(())
8386    }
8387}
8388
8389/// The arguments passed to a function call.
8390#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8391#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8392#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8393pub enum FunctionArguments {
8394    /// Used for special functions like `CURRENT_TIMESTAMP` that are invoked
8395    /// without parentheses.
8396    None,
8397    /// On some dialects, a subquery can be passed without surrounding
8398    /// parentheses if it's the sole argument to the function.
8399    Subquery(Box<Query>),
8400    /// A normal function argument list, including any clauses within it such as
8401    /// `DISTINCT` or `ORDER BY`.
8402    List(FunctionArgumentList),
8403}
8404
8405impl fmt::Display for FunctionArguments {
8406    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8407        match self {
8408            FunctionArguments::None => Ok(()),
8409            FunctionArguments::Subquery(query) => write!(f, "({query})"),
8410            FunctionArguments::List(args) => write!(f, "({args})"),
8411        }
8412    }
8413}
8414
8415/// This represents everything inside the parentheses when calling a function.
8416#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8417#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8418#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8419pub struct FunctionArgumentList {
8420    /// `[ ALL | DISTINCT ]`
8421    pub duplicate_treatment: Option<DuplicateTreatment>,
8422    /// The function arguments.
8423    pub args: Vec<FunctionArg>,
8424    /// Additional clauses specified within the argument list.
8425    pub clauses: Vec<FunctionArgumentClause>,
8426}
8427
8428impl fmt::Display for FunctionArgumentList {
8429    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8430        if let Some(duplicate_treatment) = self.duplicate_treatment {
8431            write!(f, "{duplicate_treatment} ")?;
8432        }
8433        write!(f, "{}", display_comma_separated(&self.args))?;
8434        if !self.clauses.is_empty() {
8435            if !self.args.is_empty() {
8436                write!(f, " ")?;
8437            }
8438            write!(f, "{}", display_separated(&self.clauses, " "))?;
8439        }
8440        Ok(())
8441    }
8442}
8443
8444#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8445#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8446#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8447/// Clauses that can appear inside a function argument list.
8448pub enum FunctionArgumentClause {
8449    /// Indicates how `NULL`s should be handled in the calculation, e.g. in `FIRST_VALUE` on [BigQuery].
8450    ///
8451    /// Syntax:
8452    /// ```plaintext
8453    /// { IGNORE | RESPECT } NULLS ]
8454    /// ```
8455    ///
8456    /// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/navigation_functions#first_value
8457    IgnoreOrRespectNulls(NullTreatment),
8458    /// The inline `WHERE` filter clause on an aggregate call, e.g.
8459    /// `COUNT(* WHERE cond)` / `SUM(x WHERE cond)` / `ARRAY_AGG(x WHERE cond ORDER BY ..)`.
8460    /// Popularized by [GoogleSQL]; equivalent to the standard `AGG(x) FILTER (WHERE cond)`.
8461    /// Accepted for all dialects since `WHERE` cannot otherwise begin a function argument.
8462    ///
8463    /// [GoogleSQL]: https://cloud.google.com/bigquery/docs/reference/standard-sql/aggregate_functions#grouping_and_filtering
8464    Where(Expr),
8465    /// Specifies the the ordering for some ordered set aggregates, e.g. `ARRAY_AGG` on [BigQuery].
8466    ///
8467    /// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/aggregate_functions#array_agg
8468    OrderBy(Vec<OrderByExpr>),
8469    /// Specifies a limit for the `ARRAY_AGG` and `ARRAY_CONCAT_AGG` functions on BigQuery.
8470    Limit(Expr),
8471    /// Specifies the behavior on overflow of the `LISTAGG` function.
8472    ///
8473    /// See <https://trino.io/docs/current/functions/aggregate.html>.
8474    OnOverflow(ListAggOnOverflow),
8475    /// Specifies a minimum or maximum bound on the input to [`ANY_VALUE`] on BigQuery.
8476    ///
8477    /// Syntax:
8478    /// ```plaintext
8479    /// HAVING { MAX | MIN } expression
8480    /// ```
8481    ///
8482    /// [`ANY_VALUE`]: https://cloud.google.com/bigquery/docs/reference/standard-sql/aggregate_functions#any_value
8483    Having(HavingBound),
8484    /// The `SEPARATOR` clause to the [`GROUP_CONCAT`] function in MySQL.
8485    ///
8486    /// [`GROUP_CONCAT`]: https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html#function_group-concat
8487    Separator(ValueWithSpan),
8488    /// The `ON NULL` clause for some JSON functions.
8489    ///
8490    /// [MSSQL `JSON_ARRAY`](https://learn.microsoft.com/en-us/sql/t-sql/functions/json-array-transact-sql?view=sql-server-ver16)
8491    /// [MSSQL `JSON_OBJECT`](https://learn.microsoft.com/en-us/sql/t-sql/functions/json-object-transact-sql?view=sql-server-ver16>)
8492    /// [PostgreSQL JSON functions](https://www.postgresql.org/docs/current/functions-json.html#FUNCTIONS-JSON-PROCESSING)
8493    JsonNullClause(JsonNullClause),
8494    /// The `RETURNING` clause for some JSON functions in PostgreSQL
8495    ///
8496    /// [`JSON_OBJECT`](https://www.postgresql.org/docs/current/functions-json.html#:~:text=json_object)
8497    JsonReturningClause(JsonReturningClause),
8498}
8499
8500impl fmt::Display for FunctionArgumentClause {
8501    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8502        match self {
8503            FunctionArgumentClause::IgnoreOrRespectNulls(null_treatment) => {
8504                write!(f, "{null_treatment}")
8505            }
8506            FunctionArgumentClause::Where(expr) => write!(f, "WHERE {expr}"),
8507            FunctionArgumentClause::OrderBy(order_by) => {
8508                write!(f, "ORDER BY {}", display_comma_separated(order_by))
8509            }
8510            FunctionArgumentClause::Limit(limit) => write!(f, "LIMIT {limit}"),
8511            FunctionArgumentClause::OnOverflow(on_overflow) => write!(f, "{on_overflow}"),
8512            FunctionArgumentClause::Having(bound) => write!(f, "{bound}"),
8513            FunctionArgumentClause::Separator(sep) => write!(f, "SEPARATOR {sep}"),
8514            FunctionArgumentClause::JsonNullClause(null_clause) => write!(f, "{null_clause}"),
8515            FunctionArgumentClause::JsonReturningClause(returning_clause) => {
8516                write!(f, "{returning_clause}")
8517            }
8518        }
8519    }
8520}
8521
8522/// A method call
8523#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8524#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8525#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8526pub struct Method {
8527    /// The expression on which the method is invoked.
8528    pub expr: Box<Expr>,
8529    // always non-empty
8530    /// The sequence of chained method calls.
8531    pub method_chain: Vec<Function>,
8532}
8533
8534impl fmt::Display for Method {
8535    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8536        write!(
8537            f,
8538            "{}.{}",
8539            self.expr,
8540            display_separated(&self.method_chain, ".")
8541        )
8542    }
8543}
8544
8545#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8546#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8547#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8548/// How duplicate values are treated inside function argument lists.
8549pub enum DuplicateTreatment {
8550    /// Consider only unique values.
8551    Distinct,
8552    /// Retain all duplicate values (the default).
8553    All,
8554}
8555
8556impl fmt::Display for DuplicateTreatment {
8557    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8558        match self {
8559            DuplicateTreatment::Distinct => write!(f, "DISTINCT"),
8560            DuplicateTreatment::All => write!(f, "ALL"),
8561        }
8562    }
8563}
8564
8565#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8566#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8567#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8568/// How the `ANALYZE`/`EXPLAIN ANALYZE` format is specified.
8569pub enum AnalyzeFormatKind {
8570    /// Format provided as a keyword, e.g. `FORMAT JSON`.
8571    Keyword(AnalyzeFormat),
8572    /// Format provided as an assignment, e.g. `FORMAT=JSON`.
8573    Assignment(AnalyzeFormat),
8574}
8575
8576impl fmt::Display for AnalyzeFormatKind {
8577    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
8578        match self {
8579            AnalyzeFormatKind::Keyword(format) => write!(f, "FORMAT {format}"),
8580            AnalyzeFormatKind::Assignment(format) => write!(f, "FORMAT={format}"),
8581        }
8582    }
8583}
8584
8585#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8586#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8587#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8588/// Output formats supported for `ANALYZE`/`EXPLAIN ANALYZE`.
8589pub enum AnalyzeFormat {
8590    /// Plain text format.
8591    TEXT,
8592    /// Graphviz DOT format.
8593    GRAPHVIZ,
8594    /// JSON format.
8595    JSON,
8596    /// Traditional explain output.
8597    TRADITIONAL,
8598    /// Tree-style explain output.
8599    TREE,
8600}
8601
8602/// Optional type constraint for `IS JSON`.
8603#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash)]
8604#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8605#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8606pub enum JsonPredicateType {
8607    /// `VALUE` form.
8608    Value,
8609    /// `SCALAR` form.
8610    Scalar,
8611    /// `ARRAY` form.
8612    Array,
8613    /// `OBJECT` form.
8614    Object,
8615}
8616
8617impl fmt::Display for JsonPredicateType {
8618    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8619        match self {
8620            JsonPredicateType::Value => write!(f, "VALUE"),
8621            JsonPredicateType::Scalar => write!(f, "SCALAR"),
8622            JsonPredicateType::Array => write!(f, "ARRAY"),
8623            JsonPredicateType::Object => write!(f, "OBJECT"),
8624        }
8625    }
8626}
8627
8628/// Optional duplicate-key handling for `IS JSON`.
8629#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash)]
8630#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8631#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8632pub enum JsonKeyUniqueness {
8633    /// `WITH UNIQUE KEYS` form.
8634    WithUniqueKeys,
8635    /// `WITHOUT UNIQUE KEYS` form.
8636    WithoutUniqueKeys,
8637}
8638
8639impl fmt::Display for JsonKeyUniqueness {
8640    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8641        match self {
8642            JsonKeyUniqueness::WithUniqueKeys => write!(f, "WITH UNIQUE KEYS"),
8643            JsonKeyUniqueness::WithoutUniqueKeys => write!(f, "WITHOUT UNIQUE KEYS"),
8644        }
8645    }
8646}
8647
8648impl fmt::Display for AnalyzeFormat {
8649    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
8650        f.write_str(match self {
8651            AnalyzeFormat::TEXT => "TEXT",
8652            AnalyzeFormat::GRAPHVIZ => "GRAPHVIZ",
8653            AnalyzeFormat::JSON => "JSON",
8654            AnalyzeFormat::TRADITIONAL => "TRADITIONAL",
8655            AnalyzeFormat::TREE => "TREE",
8656        })
8657    }
8658}
8659
8660/// External table's available file format
8661#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8662#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8663#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8664pub enum FileFormat {
8665    /// Text file format.
8666    TEXTFILE,
8667    /// Sequence file format.
8668    SEQUENCEFILE,
8669    /// ORC file format.
8670    ORC,
8671    /// Parquet file format.
8672    PARQUET,
8673    /// Avro file format.
8674    AVRO,
8675    /// RCFile format.
8676    RCFILE,
8677    /// JSON file format.
8678    JSONFILE,
8679}
8680
8681impl fmt::Display for FileFormat {
8682    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8683        use self::FileFormat::*;
8684        f.write_str(match self {
8685            TEXTFILE => "TEXTFILE",
8686            SEQUENCEFILE => "SEQUENCEFILE",
8687            ORC => "ORC",
8688            PARQUET => "PARQUET",
8689            AVRO => "AVRO",
8690            RCFILE => "RCFILE",
8691            JSONFILE => "JSONFILE",
8692        })
8693    }
8694}
8695
8696/// The `ON OVERFLOW` clause of a LISTAGG invocation
8697#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8698#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8699#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8700pub enum ListAggOnOverflow {
8701    /// `ON OVERFLOW ERROR`
8702    Error,
8703
8704    /// `ON OVERFLOW TRUNCATE [ <filler> ] WITH[OUT] COUNT`
8705    Truncate {
8706        /// Optional filler expression used when truncating.
8707        filler: Option<Box<Expr>>,
8708        /// Whether to include a count when truncating.
8709        with_count: bool,
8710    },
8711}
8712
8713impl fmt::Display for ListAggOnOverflow {
8714    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8715        write!(f, "ON OVERFLOW")?;
8716        match self {
8717            ListAggOnOverflow::Error => write!(f, " ERROR"),
8718            ListAggOnOverflow::Truncate { filler, with_count } => {
8719                write!(f, " TRUNCATE")?;
8720                if let Some(filler) = filler {
8721                    write!(f, " {filler}")?;
8722                }
8723                if *with_count {
8724                    write!(f, " WITH")?;
8725                } else {
8726                    write!(f, " WITHOUT")?;
8727                }
8728                write!(f, " COUNT")
8729            }
8730        }
8731    }
8732}
8733
8734/// The `HAVING` clause in a call to `ANY_VALUE` on BigQuery.
8735#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8736#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8737#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8738pub struct HavingBound(pub HavingBoundKind, pub Expr);
8739
8740impl fmt::Display for HavingBound {
8741    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8742        write!(f, "HAVING {} {}", self.0, self.1)
8743    }
8744}
8745
8746#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8747#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8748#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8749/// Which bound is used in a HAVING clause for ANY_VALUE on BigQuery.
8750pub enum HavingBoundKind {
8751    /// The minimum bound.
8752    Min,
8753    /// The maximum bound.
8754    Max,
8755}
8756
8757impl fmt::Display for HavingBoundKind {
8758    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8759        match self {
8760            HavingBoundKind::Min => write!(f, "MIN"),
8761            HavingBoundKind::Max => write!(f, "MAX"),
8762        }
8763    }
8764}
8765
8766#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8767#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8768#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8769/// Types of database objects referenced by DDL statements.
8770pub enum ObjectType {
8771    /// A collation.
8772    Collation,
8773    /// A table.
8774    Table,
8775    /// A view.
8776    View,
8777    /// A materialized view.
8778    MaterializedView,
8779    /// An index.
8780    Index,
8781    /// A schema.
8782    Schema,
8783    /// A database.
8784    Database,
8785    /// A role.
8786    Role,
8787    /// A sequence.
8788    Sequence,
8789    /// A stage.
8790    Stage,
8791    /// A type definition.
8792    Type,
8793    /// A user.
8794    User,
8795    /// A stream.
8796    Stream,
8797    /// A warehouse.
8798    Warehouse,
8799}
8800
8801impl fmt::Display for ObjectType {
8802    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8803        f.write_str(match self {
8804            ObjectType::Collation => "COLLATION",
8805            ObjectType::Table => "TABLE",
8806            ObjectType::View => "VIEW",
8807            ObjectType::MaterializedView => "MATERIALIZED VIEW",
8808            ObjectType::Index => "INDEX",
8809            ObjectType::Schema => "SCHEMA",
8810            ObjectType::Database => "DATABASE",
8811            ObjectType::Role => "ROLE",
8812            ObjectType::Sequence => "SEQUENCE",
8813            ObjectType::Stage => "STAGE",
8814            ObjectType::Type => "TYPE",
8815            ObjectType::User => "USER",
8816            ObjectType::Stream => "STREAM",
8817            ObjectType::Warehouse => "WAREHOUSE",
8818        })
8819    }
8820}
8821
8822#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8823#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8824#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8825/// Types supported by `KILL` statements.
8826pub enum KillType {
8827    /// Kill a connection.
8828    Connection,
8829    /// Kill a running query.
8830    Query,
8831    /// Kill a mutation (ClickHouse).
8832    Mutation,
8833}
8834
8835impl fmt::Display for KillType {
8836    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8837        f.write_str(match self {
8838            // MySQL
8839            KillType::Connection => "CONNECTION",
8840            KillType::Query => "QUERY",
8841            // Clickhouse supports Mutation
8842            KillType::Mutation => "MUTATION",
8843        })
8844    }
8845}
8846
8847#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8848#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8849#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8850/// Distribution style options for Hive tables.
8851pub enum HiveDistributionStyle {
8852    /// Partitioned distribution with the given columns.
8853    PARTITIONED {
8854        /// Columns used for partitioning.
8855        columns: Vec<ColumnDef>,
8856    },
8857    /// Skewed distribution definition.
8858    SKEWED {
8859        /// Columns participating in the skew definition.
8860        columns: Vec<ColumnDef>,
8861        /// Columns listed in the `ON` clause for skewing.
8862        on: Vec<ColumnDef>,
8863        /// Whether skewed data is stored as directories.
8864        stored_as_directories: bool,
8865    },
8866    /// No distribution style specified.
8867    NONE,
8868}
8869
8870#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8871#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8872#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8873/// Row format specification for Hive tables (SERDE or DELIMITED).
8874pub enum HiveRowFormat {
8875    /// SerDe class specification with the implementing class name.
8876    SERDE {
8877        /// The SerDe implementation class name.
8878        class: String,
8879    },
8880    /// Delimited row format with one or more delimiter specifications.
8881    DELIMITED {
8882        /// The list of delimiters used for delimiting fields/lines.
8883        delimiters: Vec<HiveRowDelimiter>,
8884    },
8885}
8886
8887#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8888#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8889#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8890/// Format specification for `LOAD DATA` Hive operations.
8891pub struct HiveLoadDataFormat {
8892    /// SerDe expression used for the table.
8893    pub serde: Expr,
8894    /// Input format expression.
8895    pub input_format: Expr,
8896}
8897
8898#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8899#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8900#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8901/// A single row delimiter specification for Hive `ROW FORMAT`.
8902pub struct HiveRowDelimiter {
8903    /// The delimiter kind (fields/lines/etc.).
8904    pub delimiter: HiveDelimiter,
8905    /// The delimiter character identifier.
8906    pub char: Ident,
8907}
8908
8909impl fmt::Display for HiveRowDelimiter {
8910    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8911        write!(f, "{} ", self.delimiter)?;
8912        write!(f, "{}", self.char)
8913    }
8914}
8915
8916#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8917#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8918#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8919/// Kind of delimiter used in Hive `ROW FORMAT` definitions.
8920pub enum HiveDelimiter {
8921    /// Fields terminated by a delimiter.
8922    FieldsTerminatedBy,
8923    /// Fields escaped by a character.
8924    FieldsEscapedBy,
8925    /// Collection items terminated by a delimiter.
8926    CollectionItemsTerminatedBy,
8927    /// Map keys terminated by a delimiter.
8928    MapKeysTerminatedBy,
8929    /// Lines terminated by a delimiter.
8930    LinesTerminatedBy,
8931    /// Null represented by a specific token.
8932    NullDefinedAs,
8933}
8934
8935impl fmt::Display for HiveDelimiter {
8936    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8937        use HiveDelimiter::*;
8938        f.write_str(match self {
8939            FieldsTerminatedBy => "FIELDS TERMINATED BY",
8940            FieldsEscapedBy => "ESCAPED BY",
8941            CollectionItemsTerminatedBy => "COLLECTION ITEMS TERMINATED BY",
8942            MapKeysTerminatedBy => "MAP KEYS TERMINATED BY",
8943            LinesTerminatedBy => "LINES TERMINATED BY",
8944            NullDefinedAs => "NULL DEFINED AS",
8945        })
8946    }
8947}
8948
8949#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8950#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8951#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8952/// Describe output format options for Hive `DESCRIBE`/`EXPLAIN`.
8953pub enum HiveDescribeFormat {
8954    /// Extended describe output.
8955    Extended,
8956    /// Formatted describe output.
8957    Formatted,
8958}
8959
8960impl fmt::Display for HiveDescribeFormat {
8961    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8962        use HiveDescribeFormat::*;
8963        f.write_str(match self {
8964            Extended => "EXTENDED",
8965            Formatted => "FORMATTED",
8966        })
8967    }
8968}
8969
8970#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8971#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8972#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8973/// Aliases accepted for describe-style commands.
8974pub enum DescribeAlias {
8975    /// `DESCRIBE` alias.
8976    Describe,
8977    /// `EXPLAIN` alias.
8978    Explain,
8979    /// `DESC` alias.
8980    Desc,
8981}
8982
8983impl fmt::Display for DescribeAlias {
8984    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8985        use DescribeAlias::*;
8986        f.write_str(match self {
8987            Describe => "DESCRIBE",
8988            Explain => "EXPLAIN",
8989            Desc => "DESC",
8990        })
8991    }
8992}
8993
8994#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8995#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8996#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8997#[allow(clippy::large_enum_variant)]
8998/// Hive input/output format specification used in `CREATE TABLE`.
8999pub enum HiveIOFormat {
9000    /// Generic IO format with separate input and output expressions.
9001    IOF {
9002        /// Expression for the input format.
9003        input_format: Expr,
9004        /// Expression for the output format.
9005        output_format: Expr,
9006    },
9007    /// File format wrapper referencing a `FileFormat` variant.
9008    FileFormat {
9009        /// The file format used for storage.
9010        format: FileFormat,
9011    },
9012    /// `USING <format>` syntax used by Spark SQL.
9013    ///
9014    /// Example: `CREATE TABLE t (i INT) USING PARQUET`
9015    ///
9016    /// See <https://spark.apache.org/docs/latest/sql-ref-syntax-ddl-create-table-datasource.html>
9017    Using {
9018        /// The data source or format name, e.g. `parquet`, `delta`, `csv`.
9019        format: Ident,
9020    },
9021}
9022
9023#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Default)]
9024#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9025#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9026/// Hive table format and storage-related options.
9027pub struct HiveFormat {
9028    /// Optional row format specification.
9029    pub row_format: Option<HiveRowFormat>,
9030    /// Optional SerDe properties expressed as SQL options.
9031    pub serde_properties: Option<Vec<SqlOption>>,
9032    /// Optional input/output storage format details.
9033    pub storage: Option<HiveIOFormat>,
9034    /// Optional location (URI or path) for table data.
9035    pub location: Option<String>,
9036}
9037
9038#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9039#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9040#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9041/// A clustered index column specification.
9042pub struct ClusteredIndex {
9043    /// Column identifier for the clustered index entry.
9044    pub name: Ident,
9045    /// Optional sort direction: `Some(true)` for ASC, `Some(false)` for DESC, `None` for unspecified.
9046    pub asc: Option<bool>,
9047}
9048
9049impl fmt::Display for ClusteredIndex {
9050    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9051        write!(f, "{}", self.name)?;
9052        match self.asc {
9053            Some(true) => write!(f, " ASC"),
9054            Some(false) => write!(f, " DESC"),
9055            _ => Ok(()),
9056        }
9057    }
9058}
9059
9060#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9061#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9062#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9063/// Clustered options used for `CREATE TABLE` clustered/indexed storage.
9064pub enum TableOptionsClustered {
9065    /// Use a columnstore index.
9066    ColumnstoreIndex,
9067    /// Columnstore index with an explicit ordering of columns.
9068    ColumnstoreIndexOrder(Vec<Ident>),
9069    /// A named clustered index with one or more columns.
9070    Index(Vec<ClusteredIndex>),
9071}
9072
9073impl fmt::Display for TableOptionsClustered {
9074    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9075        match self {
9076            TableOptionsClustered::ColumnstoreIndex => {
9077                write!(f, "CLUSTERED COLUMNSTORE INDEX")
9078            }
9079            TableOptionsClustered::ColumnstoreIndexOrder(values) => {
9080                write!(
9081                    f,
9082                    "CLUSTERED COLUMNSTORE INDEX ORDER ({})",
9083                    display_comma_separated(values)
9084                )
9085            }
9086            TableOptionsClustered::Index(values) => {
9087                write!(f, "CLUSTERED INDEX ({})", display_comma_separated(values))
9088            }
9089        }
9090    }
9091}
9092
9093/// Specifies which partition the boundary values on table partitioning belongs to.
9094#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash)]
9095#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9096#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9097pub enum PartitionRangeDirection {
9098    /// LEFT range direction.
9099    Left,
9100    /// RIGHT range direction.
9101    Right,
9102}
9103
9104#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9105#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9106#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9107/// SQL option syntax used in table and server definitions.
9108pub enum SqlOption {
9109    /// Clustered represents the clustered version of table storage for MSSQL.
9110    ///
9111    /// <https://learn.microsoft.com/en-us/sql/t-sql/statements/create-table-azure-sql-data-warehouse?view=aps-pdw-2016-au7#TableOptions>
9112    Clustered(TableOptionsClustered),
9113    /// Single identifier options, e.g. `HEAP` for MSSQL.
9114    ///
9115    /// <https://learn.microsoft.com/en-us/sql/t-sql/statements/create-table-azure-sql-data-warehouse?view=aps-pdw-2016-au7#TableOptions>
9116    Ident(Ident),
9117    /// Any option that consists of a key value pair where the value is an expression. e.g.
9118    ///
9119    ///   WITH(DISTRIBUTION = ROUND_ROBIN)
9120    KeyValue {
9121        /// The option key identifier.
9122        key: Ident,
9123        /// The expression value for the option.
9124        value: Expr,
9125    },
9126    /// One or more table partitions and represents which partition the boundary values belong to,
9127    /// e.g.
9128    ///
9129    ///   PARTITION (id RANGE LEFT FOR VALUES (10, 20, 30, 40))
9130    ///
9131    /// <https://learn.microsoft.com/en-us/sql/t-sql/statements/create-table-azure-sql-data-warehouse?view=aps-pdw-2016-au7#TablePartitionOptions>
9132    Partition {
9133        /// The partition column name.
9134        column_name: Ident,
9135        /// Optional direction for the partition range (LEFT/RIGHT).
9136        range_direction: Option<PartitionRangeDirection>,
9137        /// Values that define the partition boundaries.
9138        for_values: Vec<Expr>,
9139    },
9140    /// Comment parameter (supports `=` and no `=` syntax)
9141    Comment(CommentDef),
9142    /// MySQL TableSpace option
9143    /// <https://dev.mysql.com/doc/refman/8.4/en/create-table.html>
9144    TableSpace(TablespaceOption),
9145    /// An option representing a key value pair, where the value is a parenthesized list and with an optional name
9146    /// e.g.
9147    ///
9148    ///   UNION  = (tbl_name\[,tbl_name\]...) <https://dev.mysql.com/doc/refman/8.4/en/create-table.html>
9149    ///   ENGINE = ReplicatedMergeTree('/table_name','{replica}', ver) <https://clickhouse.com/docs/engines/table-engines/mergetree-family/replication>
9150    ///   ENGINE = SummingMergeTree(\[columns\]) <https://clickhouse.com/docs/engines/table-engines/mergetree-family/summingmergetree>
9151    NamedParenthesizedList(NamedParenthesizedList),
9152}
9153
9154impl fmt::Display for SqlOption {
9155    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9156        match self {
9157            SqlOption::Clustered(c) => write!(f, "{c}"),
9158            SqlOption::Ident(ident) => {
9159                write!(f, "{ident}")
9160            }
9161            SqlOption::KeyValue { key: name, value } => {
9162                write!(f, "{name} = {value}")
9163            }
9164            SqlOption::Partition {
9165                column_name,
9166                range_direction,
9167                for_values,
9168            } => {
9169                let direction = match range_direction {
9170                    Some(PartitionRangeDirection::Left) => " LEFT",
9171                    Some(PartitionRangeDirection::Right) => " RIGHT",
9172                    None => "",
9173                };
9174
9175                write!(
9176                    f,
9177                    "PARTITION ({} RANGE{} FOR VALUES ({}))",
9178                    column_name,
9179                    direction,
9180                    display_comma_separated(for_values)
9181                )
9182            }
9183            SqlOption::TableSpace(tablespace_option) => {
9184                write!(f, "TABLESPACE {}", tablespace_option.name)?;
9185                match tablespace_option.storage {
9186                    Some(StorageType::Disk) => write!(f, " STORAGE DISK"),
9187                    Some(StorageType::Memory) => write!(f, " STORAGE MEMORY"),
9188                    None => Ok(()),
9189                }
9190            }
9191            SqlOption::Comment(comment) => match comment {
9192                CommentDef::WithEq(comment) => {
9193                    write!(f, "COMMENT = '{comment}'")
9194                }
9195                CommentDef::WithoutEq(comment) => {
9196                    write!(f, "COMMENT '{comment}'")
9197                }
9198            },
9199            SqlOption::NamedParenthesizedList(value) => {
9200                write!(f, "{} = ", value.key)?;
9201                if let Some(key) = &value.name {
9202                    write!(f, "{key}")?;
9203                }
9204                if !value.values.is_empty() {
9205                    write!(f, "({})", display_comma_separated(&value.values))?
9206                }
9207                Ok(())
9208            }
9209        }
9210    }
9211}
9212
9213#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
9214#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9215#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9216/// Storage type options for a tablespace.
9217pub enum StorageType {
9218    /// Store on disk.
9219    Disk,
9220    /// Store in memory.
9221    Memory,
9222}
9223
9224#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
9225#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9226#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9227/// MySql TableSpace option
9228/// <https://dev.mysql.com/doc/refman/8.4/en/create-table.html>
9229pub struct TablespaceOption {
9230    /// Name of the tablespace.
9231    pub name: String,
9232    /// Optional storage type for the tablespace.
9233    pub storage: Option<StorageType>,
9234}
9235
9236#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9237#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9238#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9239/// A key/value identifier pair used for secret or key-based options.
9240pub struct SecretOption {
9241    /// The option key identifier.
9242    pub key: Ident,
9243    /// The option value identifier.
9244    pub value: Ident,
9245}
9246
9247impl fmt::Display for SecretOption {
9248    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9249        write!(f, "{} {}", self.key, self.value)
9250    }
9251}
9252
9253/// A `CREATE SERVER` statement.
9254///
9255/// [PostgreSQL Documentation](https://www.postgresql.org/docs/current/sql-createserver.html)
9256#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9257#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9258#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9259pub struct CreateServerStatement {
9260    /// The server name.
9261    pub name: ObjectName,
9262    /// Whether `IF NOT EXISTS` was specified.
9263    pub if_not_exists: bool,
9264    /// Optional server type identifier.
9265    pub server_type: Option<Ident>,
9266    /// Optional server version identifier.
9267    pub version: Option<Ident>,
9268    /// Foreign-data wrapper object name.
9269    pub foreign_data_wrapper: ObjectName,
9270    /// Optional list of server options.
9271    pub options: Option<Vec<CreateServerOption>>,
9272}
9273
9274impl fmt::Display for CreateServerStatement {
9275    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
9276        let CreateServerStatement {
9277            name,
9278            if_not_exists,
9279            server_type,
9280            version,
9281            foreign_data_wrapper,
9282            options,
9283        } = self;
9284
9285        write!(
9286            f,
9287            "CREATE SERVER {if_not_exists}{name} ",
9288            if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
9289        )?;
9290
9291        if let Some(st) = server_type {
9292            write!(f, "TYPE {st} ")?;
9293        }
9294
9295        if let Some(v) = version {
9296            write!(f, "VERSION {v} ")?;
9297        }
9298
9299        write!(f, "FOREIGN DATA WRAPPER {foreign_data_wrapper}")?;
9300
9301        if let Some(o) = options {
9302            write!(f, " OPTIONS ({o})", o = display_comma_separated(o))?;
9303        }
9304
9305        Ok(())
9306    }
9307}
9308
9309/// A key/value entry in a Postgres `OPTIONS ( ... )` clause.
9310#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9311#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9312#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9313pub struct CreateServerOption {
9314    /// Option key identifier.
9315    pub key: Ident,
9316    /// Option value identifier.
9317    pub value: Ident,
9318}
9319
9320impl fmt::Display for CreateServerOption {
9321    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9322        write!(f, "{} {}", self.key, self.value)
9323    }
9324}
9325
9326#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9327#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9328#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9329/// Options supported by DuckDB for `ATTACH DATABASE`.
9330pub enum AttachDuckDBDatabaseOption {
9331    /// READ_ONLY option, optional boolean value.
9332    ReadOnly(Option<bool>),
9333    /// TYPE option specifying a database type identifier.
9334    Type(Ident),
9335}
9336
9337impl fmt::Display for AttachDuckDBDatabaseOption {
9338    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9339        match self {
9340            AttachDuckDBDatabaseOption::ReadOnly(Some(true)) => write!(f, "READ_ONLY true"),
9341            AttachDuckDBDatabaseOption::ReadOnly(Some(false)) => write!(f, "READ_ONLY false"),
9342            AttachDuckDBDatabaseOption::ReadOnly(None) => write!(f, "READ_ONLY"),
9343            AttachDuckDBDatabaseOption::Type(t) => write!(f, "TYPE {t}"),
9344        }
9345    }
9346}
9347
9348#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9349#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9350#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9351/// Mode for transactions: access mode or isolation level.
9352pub enum TransactionMode {
9353    /// Access mode for a transaction (e.g. `READ ONLY` / `READ WRITE`).
9354    AccessMode(TransactionAccessMode),
9355    /// Isolation level for a transaction (e.g. `SERIALIZABLE`).
9356    IsolationLevel(TransactionIsolationLevel),
9357}
9358
9359impl fmt::Display for TransactionMode {
9360    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9361        use TransactionMode::*;
9362        match self {
9363            AccessMode(access_mode) => write!(f, "{access_mode}"),
9364            IsolationLevel(iso_level) => write!(f, "ISOLATION LEVEL {iso_level}"),
9365        }
9366    }
9367}
9368
9369#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9370#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9371#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9372/// Transaction access mode (READ ONLY / READ WRITE).
9373pub enum TransactionAccessMode {
9374    /// READ ONLY access mode.
9375    ReadOnly,
9376    /// READ WRITE access mode.
9377    ReadWrite,
9378}
9379
9380impl fmt::Display for TransactionAccessMode {
9381    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9382        use TransactionAccessMode::*;
9383        f.write_str(match self {
9384            ReadOnly => "READ ONLY",
9385            ReadWrite => "READ WRITE",
9386        })
9387    }
9388}
9389
9390#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9391#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9392#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9393/// Transaction isolation levels.
9394pub enum TransactionIsolationLevel {
9395    /// READ UNCOMMITTED isolation level.
9396    ReadUncommitted,
9397    /// READ COMMITTED isolation level.
9398    ReadCommitted,
9399    /// REPEATABLE READ isolation level.
9400    RepeatableRead,
9401    /// SERIALIZABLE isolation level.
9402    Serializable,
9403    /// SNAPSHOT isolation level.
9404    Snapshot,
9405}
9406
9407impl fmt::Display for TransactionIsolationLevel {
9408    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9409        use TransactionIsolationLevel::*;
9410        f.write_str(match self {
9411            ReadUncommitted => "READ UNCOMMITTED",
9412            ReadCommitted => "READ COMMITTED",
9413            RepeatableRead => "REPEATABLE READ",
9414            Serializable => "SERIALIZABLE",
9415            Snapshot => "SNAPSHOT",
9416        })
9417    }
9418}
9419
9420/// Modifier for the transaction in the `BEGIN` syntax
9421///
9422/// SQLite: <https://sqlite.org/lang_transaction.html>
9423/// MS-SQL: <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/try-catch-transact-sql>
9424#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9425#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9426#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9427pub enum TransactionModifier {
9428    /// DEFERRED transaction modifier.
9429    Deferred,
9430    /// IMMEDIATE transaction modifier.
9431    Immediate,
9432    /// EXCLUSIVE transaction modifier.
9433    Exclusive,
9434    /// TRY block modifier (MS-SQL style TRY/CATCH).
9435    Try,
9436    /// CATCH block modifier (MS-SQL style TRY/CATCH).
9437    Catch,
9438}
9439
9440impl fmt::Display for TransactionModifier {
9441    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9442        use TransactionModifier::*;
9443        f.write_str(match self {
9444            Deferred => "DEFERRED",
9445            Immediate => "IMMEDIATE",
9446            Exclusive => "EXCLUSIVE",
9447            Try => "TRY",
9448            Catch => "CATCH",
9449        })
9450    }
9451}
9452
9453#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9454#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9455#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9456/// Filter forms usable in SHOW statements.
9457pub enum ShowStatementFilter {
9458    /// Filter using LIKE pattern.
9459    Like(String),
9460    /// Filter using ILIKE pattern.
9461    ILike(String),
9462    /// Filter using a WHERE expression.
9463    Where(Expr),
9464    /// Filter provided without a keyword (raw string).
9465    NoKeyword(String),
9466}
9467
9468impl fmt::Display for ShowStatementFilter {
9469    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9470        use ShowStatementFilter::*;
9471        match self {
9472            Like(pattern) => write!(f, "LIKE '{}'", value::escape_single_quote_string(pattern)),
9473            ILike(pattern) => write!(f, "ILIKE {}", value::escape_single_quote_string(pattern)),
9474            Where(expr) => write!(f, "WHERE {expr}"),
9475            NoKeyword(pattern) => write!(f, "'{}'", value::escape_single_quote_string(pattern)),
9476        }
9477    }
9478}
9479
9480#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9481#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9482#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9483/// Clause types used with SHOW ... IN/FROM.
9484pub enum ShowStatementInClause {
9485    /// Use the `IN` clause.
9486    IN,
9487    /// Use the `FROM` clause.
9488    FROM,
9489}
9490
9491impl fmt::Display for ShowStatementInClause {
9492    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9493        use ShowStatementInClause::*;
9494        match self {
9495            FROM => write!(f, "FROM"),
9496            IN => write!(f, "IN"),
9497        }
9498    }
9499}
9500
9501/// Sqlite specific syntax
9502///
9503/// See [Sqlite documentation](https://sqlite.org/lang_conflict.html)
9504/// for more details.
9505#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9506#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9507#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9508pub enum SqliteOnConflict {
9509    /// Use ROLLBACK on conflict.
9510    Rollback,
9511    /// Use ABORT on conflict.
9512    Abort,
9513    /// Use FAIL on conflict.
9514    Fail,
9515    /// Use IGNORE on conflict.
9516    Ignore,
9517    /// Use REPLACE on conflict.
9518    Replace,
9519}
9520
9521impl fmt::Display for SqliteOnConflict {
9522    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9523        use SqliteOnConflict::*;
9524        match self {
9525            Rollback => write!(f, "OR ROLLBACK"),
9526            Abort => write!(f, "OR ABORT"),
9527            Fail => write!(f, "OR FAIL"),
9528            Ignore => write!(f, "OR IGNORE"),
9529            Replace => write!(f, "OR REPLACE"),
9530        }
9531    }
9532}
9533
9534/// Mysql specific syntax
9535///
9536/// See [Mysql documentation](https://dev.mysql.com/doc/refman/8.0/en/replace.html)
9537/// See [Mysql documentation](https://dev.mysql.com/doc/refman/8.0/en/insert.html)
9538/// for more details.
9539#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9540#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9541#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9542pub enum MysqlInsertPriority {
9543    /// LOW_PRIORITY modifier for INSERT/REPLACE.
9544    LowPriority,
9545    /// DELAYED modifier for INSERT/REPLACE.
9546    Delayed,
9547    /// HIGH_PRIORITY modifier for INSERT/REPLACE.
9548    HighPriority,
9549}
9550
9551impl fmt::Display for crate::ast::MysqlInsertPriority {
9552    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9553        use MysqlInsertPriority::*;
9554        match self {
9555            LowPriority => write!(f, "LOW_PRIORITY"),
9556            Delayed => write!(f, "DELAYED"),
9557            HighPriority => write!(f, "HIGH_PRIORITY"),
9558        }
9559    }
9560}
9561
9562#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9563#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9564#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9565/// Source for the `COPY` command: a table or a query.
9566pub enum CopySource {
9567    /// Copy from a table with optional column list.
9568    Table {
9569        /// The name of the table to copy from.
9570        table_name: ObjectName,
9571        /// A list of column names to copy. Empty list means that all columns
9572        /// are copied.
9573        columns: Vec<Ident>,
9574    },
9575    /// Copy from the results of a query.
9576    Query(Box<Query>),
9577}
9578
9579#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9580#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9581#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9582/// Target for the `COPY` command: STDIN, STDOUT, a file, or a program.
9583pub enum CopyTarget {
9584    /// Use standard input as the source.
9585    Stdin,
9586    /// Use standard output as the target.
9587    Stdout,
9588    /// Read from or write to a file.
9589    File {
9590        /// The path name of the input or output file.
9591        filename: String,
9592    },
9593    /// Use a program as the source or target (shell command).
9594    Program {
9595        /// A command to execute
9596        command: String,
9597    },
9598}
9599
9600impl fmt::Display for CopyTarget {
9601    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9602        use CopyTarget::*;
9603        match self {
9604            Stdin => write!(f, "STDIN"),
9605            Stdout => write!(f, "STDOUT"),
9606            File { filename } => write!(f, "'{}'", value::escape_single_quote_string(filename)),
9607            Program { command } => write!(
9608                f,
9609                "PROGRAM '{}'",
9610                value::escape_single_quote_string(command)
9611            ),
9612        }
9613    }
9614}
9615
9616#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9617#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9618#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9619/// Action to take `ON COMMIT` for temporary tables.
9620pub enum OnCommit {
9621    /// Delete rows on commit.
9622    DeleteRows,
9623    /// Preserve rows on commit.
9624    PreserveRows,
9625    /// Drop the table on commit.
9626    Drop,
9627}
9628
9629/// An option in `COPY` statement.
9630///
9631/// <https://www.postgresql.org/docs/14/sql-copy.html>
9632#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9633#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9634#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9635pub enum CopyOption {
9636    /// FORMAT format_name
9637    Format(Ident),
9638    /// FREEZE \[ boolean \]
9639    Freeze(bool),
9640    /// DELIMITER 'delimiter_character'
9641    Delimiter(char),
9642    /// NULL 'null_string'
9643    Null(String),
9644    /// HEADER \[ boolean \]
9645    Header(bool),
9646    /// QUOTE 'quote_character'
9647    Quote(char),
9648    /// ESCAPE 'escape_character'
9649    Escape(char),
9650    /// FORCE_QUOTE { ( column_name [, ...] ) | * }
9651    ForceQuote(Vec<Ident>),
9652    /// FORCE_NOT_NULL ( column_name [, ...] )
9653    ForceNotNull(Vec<Ident>),
9654    /// FORCE_NULL ( column_name [, ...] )
9655    ForceNull(Vec<Ident>),
9656    /// ENCODING 'encoding_name'
9657    Encoding(String),
9658}
9659
9660impl fmt::Display for CopyOption {
9661    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9662        use CopyOption::*;
9663        match self {
9664            Format(name) => write!(f, "FORMAT {name}"),
9665            Freeze(true) => write!(f, "FREEZE"),
9666            Freeze(false) => write!(f, "FREEZE FALSE"),
9667            Delimiter(char) => write!(f, "DELIMITER '{char}'"),
9668            Null(string) => write!(f, "NULL '{}'", value::escape_single_quote_string(string)),
9669            Header(true) => write!(f, "HEADER"),
9670            Header(false) => write!(f, "HEADER FALSE"),
9671            Quote(char) => write!(f, "QUOTE '{char}'"),
9672            Escape(char) => write!(f, "ESCAPE '{char}'"),
9673            ForceQuote(columns) => write!(f, "FORCE_QUOTE ({})", display_comma_separated(columns)),
9674            ForceNotNull(columns) => {
9675                write!(f, "FORCE_NOT_NULL ({})", display_comma_separated(columns))
9676            }
9677            ForceNull(columns) => write!(f, "FORCE_NULL ({})", display_comma_separated(columns)),
9678            Encoding(name) => write!(f, "ENCODING '{}'", value::escape_single_quote_string(name)),
9679        }
9680    }
9681}
9682
9683/// An option in `COPY` statement before PostgreSQL version 9.0.
9684///
9685/// [PostgreSQL](https://www.postgresql.org/docs/8.4/sql-copy.html)
9686/// [Redshift](https://docs.aws.amazon.com/redshift/latest/dg/r_COPY-alphabetical-parm-list.html)
9687#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9688#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9689#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9690pub enum CopyLegacyOption {
9691    /// ACCEPTANYDATE
9692    AcceptAnyDate,
9693    /// ACCEPTINVCHARS
9694    AcceptInvChars(Option<String>),
9695    /// ADDQUOTES
9696    AddQuotes,
9697    /// ALLOWOVERWRITE
9698    AllowOverwrite,
9699    /// BINARY
9700    Binary,
9701    /// BLANKSASNULL
9702    BlankAsNull,
9703    /// BZIP2
9704    Bzip2,
9705    /// CLEANPATH
9706    CleanPath,
9707    /// COMPUPDATE [ PRESET | { ON | TRUE } | { OFF | FALSE } ]
9708    CompUpdate {
9709        /// Whether the COMPUPDATE PRESET option was used.
9710        preset: bool,
9711        /// Optional enabled flag for COMPUPDATE.
9712        enabled: Option<bool>,
9713    },
9714    /// CSV ...
9715    Csv(Vec<CopyLegacyCsvOption>),
9716    /// DATEFORMAT \[ AS \] {'dateformat_string' | 'auto' }
9717    DateFormat(Option<String>),
9718    /// DELIMITER \[ AS \] 'delimiter_character'
9719    Delimiter(char),
9720    /// EMPTYASNULL
9721    EmptyAsNull,
9722    /// `ENCRYPTED \[ AUTO \]`
9723    Encrypted {
9724        /// Whether `AUTO` was specified for encryption.
9725        auto: bool,
9726    },
9727    /// ESCAPE
9728    Escape,
9729    /// EXTENSION 'extension-name'
9730    Extension(String),
9731    /// FIXEDWIDTH \[ AS \] 'fixedwidth-spec'
9732    FixedWidth(String),
9733    /// GZIP
9734    Gzip,
9735    /// HEADER
9736    Header,
9737    /// IAM_ROLE { DEFAULT | 'arn:aws:iam::123456789:role/role1' }
9738    IamRole(IamRoleKind),
9739    /// IGNOREHEADER \[ AS \] number_rows
9740    IgnoreHeader(u64),
9741    /// JSON \[ AS \] 'json_option'
9742    Json(Option<String>),
9743    /// MANIFEST \[ VERBOSE \]
9744    Manifest {
9745        /// Whether the MANIFEST is verbose.
9746        verbose: bool,
9747    },
9748    /// MAXFILESIZE \[ AS \] max-size \[ MB | GB \]
9749    MaxFileSize(FileSize),
9750    /// `NULL \[ AS \] 'null_string'`
9751    Null(String),
9752    /// `PARALLEL [ { ON | TRUE } | { OFF | FALSE } ]`
9753    Parallel(Option<bool>),
9754    /// PARQUET
9755    Parquet,
9756    /// PARTITION BY ( column_name [, ... ] ) \[ INCLUDE \]
9757    PartitionBy(UnloadPartitionBy),
9758    /// REGION \[ AS \] 'aws-region' }
9759    Region(String),
9760    /// REMOVEQUOTES
9761    RemoveQuotes,
9762    /// ROWGROUPSIZE \[ AS \] size \[ MB | GB \]
9763    RowGroupSize(FileSize),
9764    /// STATUPDATE [ { ON | TRUE } | { OFF | FALSE } ]
9765    StatUpdate(Option<bool>),
9766    /// TIMEFORMAT \[ AS \] {'timeformat_string' | 'auto' | 'epochsecs' | 'epochmillisecs' }
9767    TimeFormat(Option<String>),
9768    /// TRUNCATECOLUMNS
9769    TruncateColumns,
9770    /// ZSTD
9771    Zstd,
9772    /// Redshift `CREDENTIALS 'auth-args'`
9773    /// <https://docs.aws.amazon.com/redshift/latest/dg/copy-parameters-authorization.html>
9774    Credentials(String),
9775}
9776
9777impl fmt::Display for CopyLegacyOption {
9778    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9779        use CopyLegacyOption::*;
9780        match self {
9781            AcceptAnyDate => write!(f, "ACCEPTANYDATE"),
9782            AcceptInvChars(ch) => {
9783                write!(f, "ACCEPTINVCHARS")?;
9784                if let Some(ch) = ch {
9785                    write!(f, " '{}'", value::escape_single_quote_string(ch))?;
9786                }
9787                Ok(())
9788            }
9789            AddQuotes => write!(f, "ADDQUOTES"),
9790            AllowOverwrite => write!(f, "ALLOWOVERWRITE"),
9791            Binary => write!(f, "BINARY"),
9792            BlankAsNull => write!(f, "BLANKSASNULL"),
9793            Bzip2 => write!(f, "BZIP2"),
9794            CleanPath => write!(f, "CLEANPATH"),
9795            CompUpdate { preset, enabled } => {
9796                write!(f, "COMPUPDATE")?;
9797                if *preset {
9798                    write!(f, " PRESET")?;
9799                } else if let Some(enabled) = enabled {
9800                    write!(
9801                        f,
9802                        "{}",
9803                        match enabled {
9804                            true => " TRUE",
9805                            false => " FALSE",
9806                        }
9807                    )?;
9808                }
9809                Ok(())
9810            }
9811            Csv(opts) => {
9812                write!(f, "CSV")?;
9813                if !opts.is_empty() {
9814                    write!(f, " {}", display_separated(opts, " "))?;
9815                }
9816                Ok(())
9817            }
9818            DateFormat(fmt) => {
9819                write!(f, "DATEFORMAT")?;
9820                if let Some(fmt) = fmt {
9821                    write!(f, " '{}'", value::escape_single_quote_string(fmt))?;
9822                }
9823                Ok(())
9824            }
9825            Delimiter(char) => write!(f, "DELIMITER '{char}'"),
9826            EmptyAsNull => write!(f, "EMPTYASNULL"),
9827            Encrypted { auto } => write!(f, "ENCRYPTED{}", if *auto { " AUTO" } else { "" }),
9828            Escape => write!(f, "ESCAPE"),
9829            Extension(ext) => write!(f, "EXTENSION '{}'", value::escape_single_quote_string(ext)),
9830            FixedWidth(spec) => write!(
9831                f,
9832                "FIXEDWIDTH '{}'",
9833                value::escape_single_quote_string(spec)
9834            ),
9835            Gzip => write!(f, "GZIP"),
9836            Header => write!(f, "HEADER"),
9837            IamRole(role) => write!(f, "IAM_ROLE {role}"),
9838            IgnoreHeader(num_rows) => write!(f, "IGNOREHEADER {num_rows}"),
9839            Json(opt) => {
9840                write!(f, "JSON")?;
9841                if let Some(opt) = opt {
9842                    write!(f, " AS '{}'", value::escape_single_quote_string(opt))?;
9843                }
9844                Ok(())
9845            }
9846            Manifest { verbose } => write!(f, "MANIFEST{}", if *verbose { " VERBOSE" } else { "" }),
9847            MaxFileSize(file_size) => write!(f, "MAXFILESIZE {file_size}"),
9848            Null(string) => write!(f, "NULL '{}'", value::escape_single_quote_string(string)),
9849            Parallel(enabled) => {
9850                write!(
9851                    f,
9852                    "PARALLEL{}",
9853                    match enabled {
9854                        Some(true) => " TRUE",
9855                        Some(false) => " FALSE",
9856                        _ => "",
9857                    }
9858                )
9859            }
9860            Parquet => write!(f, "PARQUET"),
9861            PartitionBy(p) => write!(f, "{p}"),
9862            Region(region) => write!(f, "REGION '{}'", value::escape_single_quote_string(region)),
9863            RemoveQuotes => write!(f, "REMOVEQUOTES"),
9864            RowGroupSize(file_size) => write!(f, "ROWGROUPSIZE {file_size}"),
9865            StatUpdate(enabled) => {
9866                write!(
9867                    f,
9868                    "STATUPDATE{}",
9869                    match enabled {
9870                        Some(true) => " TRUE",
9871                        Some(false) => " FALSE",
9872                        _ => "",
9873                    }
9874                )
9875            }
9876            TimeFormat(fmt) => {
9877                write!(f, "TIMEFORMAT")?;
9878                if let Some(fmt) = fmt {
9879                    write!(f, " '{}'", value::escape_single_quote_string(fmt))?;
9880                }
9881                Ok(())
9882            }
9883            TruncateColumns => write!(f, "TRUNCATECOLUMNS"),
9884            Zstd => write!(f, "ZSTD"),
9885            Credentials(s) => write!(f, "CREDENTIALS '{}'", value::escape_single_quote_string(s)),
9886        }
9887    }
9888}
9889
9890/// ```sql
9891/// SIZE \[ MB | GB \]
9892/// ```
9893#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9894#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9895#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9896pub struct FileSize {
9897    /// Numeric size value.
9898    pub size: ValueWithSpan,
9899    /// Optional unit for the size (MB or GB).
9900    pub unit: Option<FileSizeUnit>,
9901}
9902
9903impl fmt::Display for FileSize {
9904    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9905        write!(f, "{}", self.size)?;
9906        if let Some(unit) = &self.unit {
9907            write!(f, " {unit}")?;
9908        }
9909        Ok(())
9910    }
9911}
9912
9913/// Units for `FileSize` (MB or GB).
9914#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9915#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9916#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9917pub enum FileSizeUnit {
9918    /// Megabytes.
9919    MB,
9920    /// Gigabytes.
9921    GB,
9922}
9923
9924impl fmt::Display for FileSizeUnit {
9925    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9926        match self {
9927            FileSizeUnit::MB => write!(f, "MB"),
9928            FileSizeUnit::GB => write!(f, "GB"),
9929        }
9930    }
9931}
9932
9933/// Specifies the partition keys for the unload operation
9934///
9935/// ```sql
9936/// PARTITION BY ( column_name [, ... ] ) [ INCLUDE ]
9937/// ```
9938#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9939#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9940#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9941pub struct UnloadPartitionBy {
9942    /// Columns used to partition the unload output.
9943    pub columns: Vec<Ident>,
9944    /// Whether to include the partition in the output.
9945    pub include: bool,
9946}
9947
9948impl fmt::Display for UnloadPartitionBy {
9949    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9950        write!(
9951            f,
9952            "PARTITION BY ({}){}",
9953            display_comma_separated(&self.columns),
9954            if self.include { " INCLUDE" } else { "" }
9955        )
9956    }
9957}
9958
9959/// An `IAM_ROLE` option in the AWS ecosystem
9960///
9961/// [Redshift COPY](https://docs.aws.amazon.com/redshift/latest/dg/copy-parameters-authorization.html#copy-iam-role)
9962#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9963#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9964#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9965pub enum IamRoleKind {
9966    /// Default role
9967    Default,
9968    /// Specific role ARN, for example: `arn:aws:iam::123456789:role/role1`
9969    Arn(String),
9970}
9971
9972impl fmt::Display for IamRoleKind {
9973    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9974        match self {
9975            IamRoleKind::Default => write!(f, "DEFAULT"),
9976            IamRoleKind::Arn(arn) => write!(f, "'{arn}'"),
9977        }
9978    }
9979}
9980
9981/// A `CSV` option in `COPY` statement before PostgreSQL version 9.0.
9982///
9983/// <https://www.postgresql.org/docs/8.4/sql-copy.html>
9984#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9985#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9986#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9987pub enum CopyLegacyCsvOption {
9988    /// HEADER
9989    Header,
9990    /// QUOTE \[ AS \] 'quote_character'
9991    Quote(char),
9992    /// ESCAPE \[ AS \] 'escape_character'
9993    Escape(char),
9994    /// FORCE QUOTE { column_name [, ...] | * }
9995    ForceQuote(Vec<Ident>),
9996    /// FORCE NOT NULL column_name [, ...]
9997    ForceNotNull(Vec<Ident>),
9998}
9999
10000impl fmt::Display for CopyLegacyCsvOption {
10001    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10002        use CopyLegacyCsvOption::*;
10003        match self {
10004            Header => write!(f, "HEADER"),
10005            Quote(char) => write!(f, "QUOTE '{char}'"),
10006            Escape(char) => write!(f, "ESCAPE '{char}'"),
10007            ForceQuote(columns) => write!(f, "FORCE QUOTE {}", display_comma_separated(columns)),
10008            ForceNotNull(columns) => {
10009                write!(f, "FORCE NOT NULL {}", display_comma_separated(columns))
10010            }
10011        }
10012    }
10013}
10014
10015/// Objects that can be discarded with `DISCARD`.
10016#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10017#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10018#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10019pub enum DiscardObject {
10020    /// Discard all session state.
10021    ALL,
10022    /// Discard cached plans.
10023    PLANS,
10024    /// Discard sequence values.
10025    SEQUENCES,
10026    /// Discard temporary objects.
10027    TEMP,
10028}
10029
10030impl fmt::Display for DiscardObject {
10031    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10032        match self {
10033            DiscardObject::ALL => f.write_str("ALL"),
10034            DiscardObject::PLANS => f.write_str("PLANS"),
10035            DiscardObject::SEQUENCES => f.write_str("SEQUENCES"),
10036            DiscardObject::TEMP => f.write_str("TEMP"),
10037        }
10038    }
10039}
10040
10041/// Types of flush operations supported by `FLUSH`.
10042#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10043#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10044#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10045pub enum FlushType {
10046    /// Flush binary logs.
10047    BinaryLogs,
10048    /// Flush engine logs.
10049    EngineLogs,
10050    /// Flush error logs.
10051    ErrorLogs,
10052    /// Flush general logs.
10053    GeneralLogs,
10054    /// Flush hosts information.
10055    Hosts,
10056    /// Flush logs.
10057    Logs,
10058    /// Flush privileges.
10059    Privileges,
10060    /// Flush optimizer costs.
10061    OptimizerCosts,
10062    /// Flush relay logs.
10063    RelayLogs,
10064    /// Flush slow logs.
10065    SlowLogs,
10066    /// Flush status.
10067    Status,
10068    /// Flush user resources.
10069    UserResources,
10070    /// Flush table data.
10071    Tables,
10072}
10073
10074impl fmt::Display for FlushType {
10075    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10076        match self {
10077            FlushType::BinaryLogs => f.write_str("BINARY LOGS"),
10078            FlushType::EngineLogs => f.write_str("ENGINE LOGS"),
10079            FlushType::ErrorLogs => f.write_str("ERROR LOGS"),
10080            FlushType::GeneralLogs => f.write_str("GENERAL LOGS"),
10081            FlushType::Hosts => f.write_str("HOSTS"),
10082            FlushType::Logs => f.write_str("LOGS"),
10083            FlushType::Privileges => f.write_str("PRIVILEGES"),
10084            FlushType::OptimizerCosts => f.write_str("OPTIMIZER_COSTS"),
10085            FlushType::RelayLogs => f.write_str("RELAY LOGS"),
10086            FlushType::SlowLogs => f.write_str("SLOW LOGS"),
10087            FlushType::Status => f.write_str("STATUS"),
10088            FlushType::UserResources => f.write_str("USER_RESOURCES"),
10089            FlushType::Tables => f.write_str("TABLES"),
10090        }
10091    }
10092}
10093
10094/// Location modifier for flush commands.
10095#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10096#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10097#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10098pub enum FlushLocation {
10099    /// Do not write changes to the binary log.
10100    NoWriteToBinlog,
10101    /// Apply flush locally.
10102    Local,
10103}
10104
10105impl fmt::Display for FlushLocation {
10106    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10107        match self {
10108            FlushLocation::NoWriteToBinlog => f.write_str("NO_WRITE_TO_BINLOG"),
10109            FlushLocation::Local => f.write_str("LOCAL"),
10110        }
10111    }
10112}
10113
10114/// Optional context modifier for statements that can be or `LOCAL`, `GLOBAL`, or `SESSION`.
10115#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10116#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10117#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10118pub enum ContextModifier {
10119    /// `LOCAL` identifier, usually related to transactional states.
10120    Local,
10121    /// `SESSION` identifier
10122    Session,
10123    /// `GLOBAL` identifier
10124    Global,
10125}
10126
10127impl fmt::Display for ContextModifier {
10128    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10129        match self {
10130            Self::Local => {
10131                write!(f, "LOCAL ")
10132            }
10133            Self::Session => {
10134                write!(f, "SESSION ")
10135            }
10136            Self::Global => {
10137                write!(f, "GLOBAL ")
10138            }
10139        }
10140    }
10141}
10142
10143/// Function describe in DROP FUNCTION.
10144#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10145#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10146pub enum DropFunctionOption {
10147    /// `RESTRICT` option for DROP FUNCTION.
10148    Restrict,
10149    /// `CASCADE` option for DROP FUNCTION.
10150    Cascade,
10151}
10152
10153impl fmt::Display for DropFunctionOption {
10154    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10155        match self {
10156            DropFunctionOption::Restrict => write!(f, "RESTRICT "),
10157            DropFunctionOption::Cascade => write!(f, "CASCADE  "),
10158        }
10159    }
10160}
10161
10162/// Generic function description for DROP FUNCTION and CREATE TRIGGER.
10163#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10164#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10165#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10166pub struct FunctionDesc {
10167    /// The function name.
10168    pub name: ObjectName,
10169    /// Optional list of function arguments.
10170    pub args: Option<Vec<OperateFunctionArg>>,
10171}
10172
10173impl fmt::Display for FunctionDesc {
10174    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10175        write!(f, "{}", self.name)?;
10176        if let Some(args) = &self.args {
10177            write!(f, "({})", display_comma_separated(args))?;
10178        }
10179        Ok(())
10180    }
10181}
10182
10183/// Function argument in CREATE OR DROP FUNCTION.
10184#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10185#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10186#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10187pub struct OperateFunctionArg {
10188    /// Optional argument mode (`IN`, `OUT`, `INOUT`).
10189    pub mode: Option<ArgMode>,
10190    /// Optional argument identifier/name.
10191    pub name: Option<Ident>,
10192    /// The data type of the argument.
10193    pub data_type: DataType,
10194    /// Optional default expression for the argument.
10195    pub default_expr: Option<Expr>,
10196}
10197
10198impl OperateFunctionArg {
10199    /// Returns an unnamed argument.
10200    pub fn unnamed(data_type: DataType) -> Self {
10201        Self {
10202            mode: None,
10203            name: None,
10204            data_type,
10205            default_expr: None,
10206        }
10207    }
10208
10209    /// Returns an argument with name.
10210    pub fn with_name(name: &str, data_type: DataType) -> Self {
10211        Self {
10212            mode: None,
10213            name: Some(name.into()),
10214            data_type,
10215            default_expr: None,
10216        }
10217    }
10218}
10219
10220impl fmt::Display for OperateFunctionArg {
10221    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10222        if let Some(mode) = &self.mode {
10223            write!(f, "{mode} ")?;
10224        }
10225        if let Some(name) = &self.name {
10226            write!(f, "{name} ")?;
10227        }
10228        write!(f, "{}", self.data_type)?;
10229        if let Some(default_expr) = &self.default_expr {
10230            write!(f, " = {default_expr}")?;
10231        }
10232        Ok(())
10233    }
10234}
10235
10236/// The mode of an argument in CREATE FUNCTION.
10237#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10238#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10239#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10240pub enum ArgMode {
10241    /// `IN` mode.
10242    In,
10243    /// `OUT` mode.
10244    Out,
10245    /// `INOUT` mode.
10246    InOut,
10247    /// `VARIADIC` mode.
10248    Variadic,
10249}
10250
10251impl fmt::Display for ArgMode {
10252    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10253        match self {
10254            ArgMode::In => write!(f, "IN"),
10255            ArgMode::Out => write!(f, "OUT"),
10256            ArgMode::InOut => write!(f, "INOUT"),
10257            ArgMode::Variadic => write!(f, "VARIADIC"),
10258        }
10259    }
10260}
10261
10262/// These attributes inform the query optimizer about the behavior of the function.
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))]
10266pub enum FunctionBehavior {
10267    /// Function is immutable.
10268    Immutable,
10269    /// Function is stable.
10270    Stable,
10271    /// Function is volatile.
10272    Volatile,
10273}
10274
10275impl fmt::Display for FunctionBehavior {
10276    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10277        match self {
10278            FunctionBehavior::Immutable => write!(f, "IMMUTABLE"),
10279            FunctionBehavior::Stable => write!(f, "STABLE"),
10280            FunctionBehavior::Volatile => write!(f, "VOLATILE"),
10281        }
10282    }
10283}
10284
10285/// Security attribute for functions: SECURITY DEFINER or SECURITY INVOKER.
10286///
10287/// [PostgreSQL](https://www.postgresql.org/docs/current/sql-createfunction.html)
10288#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10289#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10290#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10291pub enum FunctionSecurity {
10292    /// Execute the function with the privileges of the user who defined it.
10293    Definer,
10294    /// Execute the function with the privileges of the user who invokes it.
10295    Invoker,
10296}
10297
10298impl fmt::Display for FunctionSecurity {
10299    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10300        match self {
10301            FunctionSecurity::Definer => write!(f, "SECURITY DEFINER"),
10302            FunctionSecurity::Invoker => write!(f, "SECURITY INVOKER"),
10303        }
10304    }
10305}
10306
10307/// Value for a SET configuration parameter in a CREATE FUNCTION statement.
10308///
10309/// [PostgreSQL](https://www.postgresql.org/docs/current/sql-createfunction.html)
10310#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10311#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10312#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10313pub enum FunctionSetValue {
10314    /// SET param = DEFAULT / SET param TO DEFAULT
10315    Default,
10316    /// SET param = value1, value2, ...
10317    Values(Vec<Expr>),
10318    /// SET param FROM CURRENT
10319    FromCurrent,
10320}
10321
10322/// A SET configuration_parameter clause in a CREATE FUNCTION statement.
10323///
10324/// [PostgreSQL](https://www.postgresql.org/docs/current/sql-createfunction.html)
10325#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10326#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10327#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10328pub struct FunctionDefinitionSetParam {
10329    /// The name of the configuration parameter.
10330    pub name: ObjectName,
10331    /// The value to set for the parameter.
10332    pub value: FunctionSetValue,
10333}
10334
10335impl fmt::Display for FunctionDefinitionSetParam {
10336    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10337        write!(f, "SET {} ", self.name)?;
10338        match &self.value {
10339            FunctionSetValue::Default => write!(f, "= DEFAULT"),
10340            FunctionSetValue::Values(values) => {
10341                write!(f, "= {}", display_comma_separated(values))
10342            }
10343            FunctionSetValue::FromCurrent => write!(f, "FROM CURRENT"),
10344        }
10345    }
10346}
10347
10348/// These attributes describe the behavior of the function when called with a null argument.
10349#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10350#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10351#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10352pub enum FunctionCalledOnNull {
10353    /// Function is called even when inputs are null.
10354    CalledOnNullInput,
10355    /// Function returns null when any input is null.
10356    ReturnsNullOnNullInput,
10357    /// Function is strict about null inputs.
10358    Strict,
10359}
10360
10361impl fmt::Display for FunctionCalledOnNull {
10362    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10363        match self {
10364            FunctionCalledOnNull::CalledOnNullInput => write!(f, "CALLED ON NULL INPUT"),
10365            FunctionCalledOnNull::ReturnsNullOnNullInput => write!(f, "RETURNS NULL ON NULL INPUT"),
10366            FunctionCalledOnNull::Strict => write!(f, "STRICT"),
10367        }
10368    }
10369}
10370
10371/// If it is safe for PostgreSQL to call the function from multiple threads at once
10372#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10373#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10374#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10375pub enum FunctionParallel {
10376    /// The function is not safe to run in parallel.
10377    Unsafe,
10378    /// The function is restricted for parallel execution.
10379    Restricted,
10380    /// The function is safe to run in parallel.
10381    Safe,
10382}
10383
10384impl fmt::Display for FunctionParallel {
10385    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10386        match self {
10387            FunctionParallel::Unsafe => write!(f, "PARALLEL UNSAFE"),
10388            FunctionParallel::Restricted => write!(f, "PARALLEL RESTRICTED"),
10389            FunctionParallel::Safe => write!(f, "PARALLEL SAFE"),
10390        }
10391    }
10392}
10393
10394/// [BigQuery] Determinism specifier used in a UDF definition.
10395///
10396/// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#syntax_11
10397#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10398#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10399#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10400pub enum FunctionDeterminismSpecifier {
10401    /// Function is deterministic.
10402    Deterministic,
10403    /// Function is not deterministic.
10404    NotDeterministic,
10405}
10406
10407impl fmt::Display for FunctionDeterminismSpecifier {
10408    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10409        match self {
10410            FunctionDeterminismSpecifier::Deterministic => {
10411                write!(f, "DETERMINISTIC")
10412            }
10413            FunctionDeterminismSpecifier::NotDeterministic => {
10414                write!(f, "NOT DETERMINISTIC")
10415            }
10416        }
10417    }
10418}
10419
10420/// Represent the expression body of a `CREATE FUNCTION` statement as well as
10421/// where within the statement, the body shows up.
10422///
10423/// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#syntax_11
10424/// [PostgreSQL]: https://www.postgresql.org/docs/15/sql-createfunction.html
10425/// [MsSql]: https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql
10426#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10427#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10428#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10429pub enum CreateFunctionBody {
10430    /// A function body expression using the 'AS' keyword and shows up
10431    /// before any `OPTIONS` clause.
10432    ///
10433    /// Example:
10434    /// ```sql
10435    /// CREATE FUNCTION myfunc(x FLOAT64, y FLOAT64) RETURNS FLOAT64
10436    /// AS (x * y)
10437    /// OPTIONS(description="desc");
10438    /// ```
10439    ///
10440    /// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#syntax_11
10441    /// [PostgreSQL]: https://www.postgresql.org/docs/current/sql-createfunction.html
10442    AsBeforeOptions {
10443        /// The primary expression.
10444        body: Expr,
10445        /// Link symbol if the primary expression contains the name of shared library file.
10446        ///
10447        /// Example:
10448        /// ```sql
10449        /// CREATE FUNCTION cas_in(input cstring) RETURNS cas
10450        /// AS 'MODULE_PATHNAME', 'cas_in_wrapper'
10451        /// ```
10452        /// [PostgreSQL]: https://www.postgresql.org/docs/current/sql-createfunction.html
10453        link_symbol: Option<Expr>,
10454    },
10455    /// A function body expression using the 'AS' keyword and shows up
10456    /// after any `OPTIONS` clause.
10457    ///
10458    /// Example:
10459    /// ```sql
10460    /// CREATE FUNCTION myfunc(x FLOAT64, y FLOAT64) RETURNS FLOAT64
10461    /// OPTIONS(description="desc")
10462    /// AS (x * y);
10463    /// ```
10464    ///
10465    /// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#syntax_11
10466    AsAfterOptions(Expr),
10467    /// Function body with statements before the `RETURN` keyword.
10468    ///
10469    /// Example:
10470    /// ```sql
10471    /// CREATE FUNCTION my_scalar_udf(a INT, b INT)
10472    /// RETURNS INT
10473    /// AS
10474    /// BEGIN
10475    ///     DECLARE c INT;
10476    ///     SET c = a + b;
10477    ///     RETURN c;
10478    /// END
10479    /// ```
10480    ///
10481    /// [MsSql]: https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql
10482    AsBeginEnd(BeginEndStatements),
10483    /// Function body expression using the 'RETURN' keyword.
10484    ///
10485    /// Example:
10486    /// ```sql
10487    /// CREATE FUNCTION myfunc(a INTEGER, IN b INTEGER = 1) RETURNS INTEGER
10488    /// LANGUAGE SQL
10489    /// RETURN a + b;
10490    /// ```
10491    ///
10492    /// [PostgreSQL]: https://www.postgresql.org/docs/current/sql-createfunction.html
10493    Return(Expr),
10494
10495    /// Function body expression using the 'AS RETURN' keywords
10496    ///
10497    /// Example:
10498    /// ```sql
10499    /// CREATE FUNCTION myfunc(a INT, b INT)
10500    /// RETURNS TABLE
10501    /// AS RETURN (SELECT a + b AS sum);
10502    /// ```
10503    ///
10504    /// [MsSql]: https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql
10505    AsReturnExpr(Expr),
10506
10507    /// Function body expression using the 'AS RETURN' keywords, with an un-parenthesized SELECT query
10508    ///
10509    /// Example:
10510    /// ```sql
10511    /// CREATE FUNCTION myfunc(a INT, b INT)
10512    /// RETURNS TABLE
10513    /// AS RETURN SELECT a + b AS sum;
10514    /// ```
10515    ///
10516    /// [MsSql]: https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql?view=sql-server-ver16#select_stmt
10517    AsReturnSelect(Select),
10518}
10519
10520#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10521#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10522#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10523/// `USING` clause options for `CREATE FUNCTION` (e.g., JAR, FILE, ARCHIVE).
10524pub enum CreateFunctionUsing {
10525    /// Use a JAR file located at the given URI.
10526    Jar(String),
10527    /// Use a file located at the given URI.
10528    File(String),
10529    /// Use an archive located at the given URI.
10530    Archive(String),
10531}
10532
10533impl fmt::Display for CreateFunctionUsing {
10534    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10535        write!(f, "USING ")?;
10536        match self {
10537            CreateFunctionUsing::Jar(uri) => write!(f, "JAR '{uri}'"),
10538            CreateFunctionUsing::File(uri) => write!(f, "FILE '{uri}'"),
10539            CreateFunctionUsing::Archive(uri) => write!(f, "ARCHIVE '{uri}'"),
10540        }
10541    }
10542}
10543
10544/// `NAME = <EXPR>` arguments for DuckDB macros
10545///
10546/// See [Create Macro - DuckDB](https://duckdb.org/docs/sql/statements/create_macro)
10547/// for more details
10548#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10549#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10550#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10551pub struct MacroArg {
10552    /// The argument name.
10553    pub name: Ident,
10554    /// Optional default expression for the argument.
10555    pub default_expr: Option<Expr>,
10556}
10557
10558impl MacroArg {
10559    /// Returns an argument with name.
10560    pub fn new(name: &str) -> Self {
10561        Self {
10562            name: name.into(),
10563            default_expr: None,
10564        }
10565    }
10566}
10567
10568impl fmt::Display for MacroArg {
10569    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10570        write!(f, "{}", self.name)?;
10571        if let Some(default_expr) = &self.default_expr {
10572            write!(f, " := {default_expr}")?;
10573        }
10574        Ok(())
10575    }
10576}
10577
10578#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10579#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10580#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10581/// Definition for a DuckDB macro: either an expression or a table-producing query.
10582pub enum MacroDefinition {
10583    /// The macro is defined as an expression.
10584    Expr(Expr),
10585    /// The macro is defined as a table (query).
10586    Table(Box<Query>),
10587}
10588
10589impl fmt::Display for MacroDefinition {
10590    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10591        match self {
10592            MacroDefinition::Expr(expr) => write!(f, "{expr}")?,
10593            MacroDefinition::Table(query) => write!(f, "{query}")?,
10594        }
10595        Ok(())
10596    }
10597}
10598
10599/// Schema possible naming variants ([1]).
10600///
10601/// [1]: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#schema-definition
10602#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10603#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10604#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10605pub enum SchemaName {
10606    /// Only schema name specified: `<schema name>`.
10607    Simple(ObjectName),
10608    /// Only authorization identifier specified: `AUTHORIZATION <schema authorization identifier>`.
10609    UnnamedAuthorization(Ident),
10610    /// Both schema name and authorization identifier specified: `<schema name>  AUTHORIZATION <schema authorization identifier>`.
10611    NamedAuthorization(ObjectName, Ident),
10612}
10613
10614impl fmt::Display for SchemaName {
10615    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10616        match self {
10617            SchemaName::Simple(name) => {
10618                write!(f, "{name}")
10619            }
10620            SchemaName::UnnamedAuthorization(authorization) => {
10621                write!(f, "AUTHORIZATION {authorization}")
10622            }
10623            SchemaName::NamedAuthorization(name, authorization) => {
10624                write!(f, "{name} AUTHORIZATION {authorization}")
10625            }
10626        }
10627    }
10628}
10629
10630/// Fulltext search modifiers ([1]).
10631///
10632/// [1]: https://dev.mysql.com/doc/refman/8.0/en/fulltext-search.html#function_match
10633#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10634#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10635#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10636pub enum SearchModifier {
10637    /// `IN NATURAL LANGUAGE MODE`.
10638    InNaturalLanguageMode,
10639    /// `IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION`.
10640    InNaturalLanguageModeWithQueryExpansion,
10641    ///`IN BOOLEAN MODE`.
10642    InBooleanMode,
10643    ///`WITH QUERY EXPANSION`.
10644    WithQueryExpansion,
10645}
10646
10647impl fmt::Display for SearchModifier {
10648    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10649        match self {
10650            Self::InNaturalLanguageMode => {
10651                write!(f, "IN NATURAL LANGUAGE MODE")?;
10652            }
10653            Self::InNaturalLanguageModeWithQueryExpansion => {
10654                write!(f, "IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION")?;
10655            }
10656            Self::InBooleanMode => {
10657                write!(f, "IN BOOLEAN MODE")?;
10658            }
10659            Self::WithQueryExpansion => {
10660                write!(f, "WITH QUERY EXPANSION")?;
10661            }
10662        }
10663
10664        Ok(())
10665    }
10666}
10667
10668/// Represents a `LOCK TABLE` clause with optional alias and lock type.
10669#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10670#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10671#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10672pub struct LockTable {
10673    /// The table identifier to lock.
10674    pub table: Ident,
10675    /// Optional alias for the table.
10676    pub alias: Option<Ident>,
10677    /// The type of lock to apply to the table.
10678    pub lock_type: LockTableType,
10679}
10680
10681impl fmt::Display for LockTable {
10682    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10683        let Self {
10684            table: tbl_name,
10685            alias,
10686            lock_type,
10687        } = self;
10688
10689        write!(f, "{tbl_name} ")?;
10690        if let Some(alias) = alias {
10691            write!(f, "AS {alias} ")?;
10692        }
10693        write!(f, "{lock_type}")?;
10694        Ok(())
10695    }
10696}
10697
10698#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10699#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10700#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10701/// The type of lock used in `LOCK TABLE` statements.
10702pub enum LockTableType {
10703    /// Shared/read lock. If `local` is true, it's a local read lock.
10704    Read {
10705        /// Whether the read lock is local.
10706        local: bool,
10707    },
10708    /// Exclusive/write lock. If `low_priority` is true, the write is low priority.
10709    Write {
10710        /// Whether the write lock is low priority.
10711        low_priority: bool,
10712    },
10713}
10714
10715impl fmt::Display for LockTableType {
10716    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10717        match self {
10718            Self::Read { local } => {
10719                write!(f, "READ")?;
10720                if *local {
10721                    write!(f, " LOCAL")?;
10722                }
10723            }
10724            Self::Write { low_priority } => {
10725                if *low_priority {
10726                    write!(f, "LOW_PRIORITY ")?;
10727                }
10728                write!(f, "WRITE")?;
10729            }
10730        }
10731
10732        Ok(())
10733    }
10734}
10735
10736#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10737#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10738#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10739/// Hive-specific `SET LOCATION` helper used in some `LOAD DATA` statements.
10740pub struct HiveSetLocation {
10741    /// Whether the `SET` keyword was present.
10742    pub has_set: bool,
10743    /// The location identifier.
10744    pub location: Ident,
10745}
10746
10747impl fmt::Display for HiveSetLocation {
10748    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10749        if self.has_set {
10750            write!(f, "SET ")?;
10751        }
10752        write!(f, "LOCATION {}", self.location)
10753    }
10754}
10755
10756/// MySQL `ALTER TABLE` only  [FIRST | AFTER column_name]
10757#[allow(clippy::large_enum_variant)]
10758#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10759#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10760#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10761/// MySQL `ALTER TABLE` column position specifier: `FIRST` or `AFTER <column>`.
10762pub enum MySQLColumnPosition {
10763    /// Place the column first in the table.
10764    First,
10765    /// Place the column after the specified identifier.
10766    After(Ident),
10767}
10768
10769impl Display for MySQLColumnPosition {
10770    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10771        match self {
10772            MySQLColumnPosition::First => write!(f, "FIRST"),
10773            MySQLColumnPosition::After(ident) => write!(f, "AFTER {ident}"),
10774        }
10775    }
10776}
10777
10778/// MySQL `CREATE VIEW` algorithm parameter: [ALGORITHM = {UNDEFINED | MERGE | TEMPTABLE}]
10779#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10780#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10781#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10782/// MySQL `CREATE VIEW` algorithm options.
10783pub enum CreateViewAlgorithm {
10784    /// `UNDEFINED` algorithm.
10785    Undefined,
10786    /// `MERGE` algorithm.
10787    Merge,
10788    /// `TEMPTABLE` algorithm.
10789    TempTable,
10790}
10791
10792impl Display for CreateViewAlgorithm {
10793    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10794        match self {
10795            CreateViewAlgorithm::Undefined => write!(f, "UNDEFINED"),
10796            CreateViewAlgorithm::Merge => write!(f, "MERGE"),
10797            CreateViewAlgorithm::TempTable => write!(f, "TEMPTABLE"),
10798        }
10799    }
10800}
10801/// MySQL `CREATE VIEW` security parameter: [SQL SECURITY { DEFINER | INVOKER }]
10802#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10803#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10804#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10805/// MySQL `CREATE VIEW` SQL SECURITY options.
10806pub enum CreateViewSecurity {
10807    /// The view runs with the privileges of the definer.
10808    Definer,
10809    /// The view runs with the privileges of the invoker.
10810    Invoker,
10811}
10812
10813impl Display for CreateViewSecurity {
10814    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10815        match self {
10816            CreateViewSecurity::Definer => write!(f, "DEFINER"),
10817            CreateViewSecurity::Invoker => write!(f, "INVOKER"),
10818        }
10819    }
10820}
10821
10822/// [MySQL] `CREATE VIEW` additional parameters
10823///
10824/// [MySQL]: https://dev.mysql.com/doc/refman/9.1/en/create-view.html
10825#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10826#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10827#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10828pub struct CreateViewParams {
10829    /// Optional view algorithm (e.g., MERGE, TEMPTABLE).
10830    pub algorithm: Option<CreateViewAlgorithm>,
10831    /// Optional definer (the security principal that will own the view).
10832    pub definer: Option<GranteeName>,
10833    /// Optional SQL SECURITY setting for the view.
10834    pub security: Option<CreateViewSecurity>,
10835}
10836
10837impl Display for CreateViewParams {
10838    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10839        let CreateViewParams {
10840            algorithm,
10841            definer,
10842            security,
10843        } = self;
10844        if let Some(algorithm) = algorithm {
10845            write!(f, "ALGORITHM = {algorithm} ")?;
10846        }
10847        if let Some(definers) = definer {
10848            write!(f, "DEFINER = {definers} ")?;
10849        }
10850        if let Some(security) = security {
10851            write!(f, "SQL SECURITY {security} ")?;
10852        }
10853        Ok(())
10854    }
10855}
10856
10857#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10858#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10859#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10860/// Key/Value, where the value is a (optionally named) list of identifiers
10861///
10862/// ```sql
10863/// UNION = (tbl_name[,tbl_name]...)
10864/// ENGINE = ReplicatedMergeTree('/table_name','{replica}', ver)
10865/// ENGINE = SummingMergeTree([columns])
10866/// ```
10867pub struct NamedParenthesizedList {
10868    /// The option key (identifier) for this named list.
10869    pub key: Ident,
10870    /// Optional secondary name associated with the key.
10871    pub name: Option<Ident>,
10872    /// The list of identifier values for the key.
10873    pub values: Vec<Ident>,
10874}
10875
10876/// Snowflake `WITH ROW ACCESS POLICY policy_name ON (identifier, ...)`
10877///
10878/// <https://docs.snowflake.com/en/sql-reference/sql/create-table>
10879/// <https://docs.snowflake.com/en/user-guide/security-row-intro>
10880#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10881#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10882#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10883pub struct RowAccessPolicy {
10884    /// The fully-qualified policy object name.
10885    pub policy: ObjectName,
10886    /// Identifiers for the columns or objects the policy applies to.
10887    pub on: Vec<Ident>,
10888}
10889
10890impl RowAccessPolicy {
10891    /// Create a new `RowAccessPolicy` for the given `policy` and `on` identifiers.
10892    pub fn new(policy: ObjectName, on: Vec<Ident>) -> Self {
10893        Self { policy, on }
10894    }
10895}
10896
10897impl Display for RowAccessPolicy {
10898    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10899        write!(
10900            f,
10901            "WITH ROW ACCESS POLICY {} ON ({})",
10902            self.policy,
10903            display_comma_separated(self.on.as_slice())
10904        )
10905    }
10906}
10907
10908/// Snowflake `[ WITH ] STORAGE LIFECYCLE POLICY <policy_name> ON ( <col_name> [ , ... ] )`
10909///
10910/// <https://docs.snowflake.com/en/sql-reference/sql/create-table>
10911#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10912#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10913#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10914pub struct StorageLifecyclePolicy {
10915    /// The fully-qualified policy object name.
10916    pub policy: ObjectName,
10917    /// Column names the policy applies to.
10918    pub on: Vec<Ident>,
10919}
10920
10921impl Display for StorageLifecyclePolicy {
10922    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10923        write!(
10924            f,
10925            "WITH STORAGE LIFECYCLE POLICY {} ON ({})",
10926            self.policy,
10927            display_comma_separated(self.on.as_slice())
10928        )
10929    }
10930}
10931
10932/// Snowflake `WITH TAG ( tag_name = '<tag_value>', ...)`
10933///
10934/// <https://docs.snowflake.com/en/sql-reference/sql/create-table>
10935#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10936#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10937#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10938pub struct Tag {
10939    /// The tag key (can be qualified).
10940    pub key: ObjectName,
10941    /// The tag value as a string.
10942    pub value: String,
10943}
10944
10945impl Tag {
10946    /// Create a new `Tag` with the given key and value.
10947    pub fn new(key: ObjectName, value: String) -> Self {
10948        Self { key, value }
10949    }
10950}
10951
10952impl Display for Tag {
10953    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10954        write!(f, "{}='{}'", self.key, self.value)
10955    }
10956}
10957
10958/// Snowflake `WITH CONTACT ( purpose = contact [ , purpose = contact ...] )`
10959///
10960/// <https://docs.snowflake.com/en/sql-reference/sql/create-database>
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 ContactEntry {
10965    /// The purpose label for the contact entry.
10966    pub purpose: String,
10967    /// The contact information associated with the purpose.
10968    pub contact: String,
10969}
10970
10971impl Display for ContactEntry {
10972    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10973        write!(f, "{} = {}", self.purpose, self.contact)
10974    }
10975}
10976
10977/// Helper to indicate if a comment includes the `=` in the display form
10978#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10979#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10980#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10981pub enum CommentDef {
10982    /// Includes `=` when printing the comment, as `COMMENT = 'comment'`
10983    /// Does not include `=` when printing the comment, as `COMMENT 'comment'`
10984    WithEq(String),
10985    /// Comment variant that omits the `=` when displayed.
10986    WithoutEq(String),
10987}
10988
10989impl Display for CommentDef {
10990    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10991        match self {
10992            CommentDef::WithEq(comment) | CommentDef::WithoutEq(comment) => write!(f, "{comment}"),
10993        }
10994    }
10995}
10996
10997/// Helper to indicate if a collection should be wrapped by a symbol in the display form
10998///
10999/// [`Display`] is implemented for every [`Vec<T>`] where `T: Display`.
11000/// The string output is a comma separated list for the vec items
11001///
11002/// # Examples
11003/// ```
11004/// # use sqlparser::ast::WrappedCollection;
11005/// let items = WrappedCollection::Parentheses(vec!["one", "two", "three"]);
11006/// assert_eq!("(one, two, three)", items.to_string());
11007///
11008/// let items = WrappedCollection::NoWrapping(vec!["one", "two", "three"]);
11009/// assert_eq!("one, two, three", items.to_string());
11010/// ```
11011#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11012#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11013#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11014pub enum WrappedCollection<T> {
11015    /// Print the collection without wrapping symbols, as `item, item, item`
11016    NoWrapping(T),
11017    /// Wraps the collection in Parentheses, as `(item, item, item)`
11018    Parentheses(T),
11019}
11020
11021impl<T> Display for WrappedCollection<Vec<T>>
11022where
11023    T: Display,
11024{
11025    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
11026        match self {
11027            WrappedCollection::NoWrapping(inner) => {
11028                write!(f, "{}", display_comma_separated(inner.as_slice()))
11029            }
11030            WrappedCollection::Parentheses(inner) => {
11031                write!(f, "({})", display_comma_separated(inner.as_slice()))
11032            }
11033        }
11034    }
11035}
11036
11037/// Represents a single PostgreSQL utility option.
11038///
11039/// A utility option is a key-value pair where the key is an identifier (IDENT) and the value
11040/// can be one of the following:
11041/// - A number with an optional sign (`+` or `-`). Example: `+10`, `-10.2`, `3`
11042/// - A non-keyword string. Example: `option1`, `'option2'`, `"option3"`
11043/// - keyword: `TRUE`, `FALSE`, `ON` (`off` is also accept).
11044/// - Empty. Example: `ANALYZE` (identifier only)
11045///
11046/// Utility options are used in various PostgreSQL DDL statements, including statements such as
11047/// `CLUSTER`, `EXPLAIN`, `VACUUM`, and `REINDEX`. These statements format options as `( option [, ...] )`.
11048///
11049/// [CLUSTER](https://www.postgresql.org/docs/current/sql-cluster.html)
11050/// [EXPLAIN](https://www.postgresql.org/docs/current/sql-explain.html)
11051/// [VACUUM](https://www.postgresql.org/docs/current/sql-vacuum.html)
11052/// [REINDEX](https://www.postgresql.org/docs/current/sql-reindex.html)
11053///
11054/// For example, the `EXPLAIN` AND `VACUUM` statements with options might look like this:
11055/// ```sql
11056/// EXPLAIN (ANALYZE, VERBOSE TRUE, FORMAT TEXT) SELECT * FROM my_table;
11057///
11058/// VACUUM (VERBOSE, ANALYZE ON, PARALLEL 10) my_table;
11059/// ```
11060#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11061#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11062#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11063pub struct UtilityOption {
11064    /// The option name (identifier).
11065    pub name: Ident,
11066    /// Optional argument for the option (number, string, keyword, etc.).
11067    pub arg: Option<Expr>,
11068}
11069
11070impl Display for UtilityOption {
11071    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
11072        if let Some(ref arg) = self.arg {
11073            write!(f, "{} {}", self.name, arg)
11074        } else {
11075            write!(f, "{}", self.name)
11076        }
11077    }
11078}
11079
11080/// Represents the different options available for `SHOW`
11081/// statements to filter the results. Example from Snowflake:
11082/// <https://docs.snowflake.com/en/sql-reference/sql/show-tables>
11083#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11084#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11085#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11086pub struct ShowStatementOptions {
11087    /// Optional scope to show in (for example: TABLE, SCHEMA).
11088    pub show_in: Option<ShowStatementIn>,
11089    /// Optional `STARTS WITH` filter value.
11090    pub starts_with: Option<ValueWithSpan>,
11091    /// Optional `LIMIT` expression.
11092    pub limit: Option<Expr>,
11093    /// Optional `FROM` value used with `LIMIT`.
11094    pub limit_from: Option<ValueWithSpan>,
11095    /// Optional filter position (infix or suffix) for `LIKE`/`FILTER`.
11096    pub filter_position: Option<ShowStatementFilterPosition>,
11097}
11098
11099impl Display for ShowStatementOptions {
11100    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
11101        let (like_in_infix, like_in_suffix) = match &self.filter_position {
11102            Some(ShowStatementFilterPosition::Infix(filter)) => {
11103                (format!(" {filter}"), "".to_string())
11104            }
11105            Some(ShowStatementFilterPosition::Suffix(filter)) => {
11106                ("".to_string(), format!(" {filter}"))
11107            }
11108            None => ("".to_string(), "".to_string()),
11109        };
11110        write!(
11111            f,
11112            "{like_in_infix}{show_in}{starts_with}{limit}{from}{like_in_suffix}",
11113            show_in = match &self.show_in {
11114                Some(i) => format!(" {i}"),
11115                None => String::new(),
11116            },
11117            starts_with = match &self.starts_with {
11118                Some(s) => format!(" STARTS WITH {s}"),
11119                None => String::new(),
11120            },
11121            limit = match &self.limit {
11122                Some(l) => format!(" LIMIT {l}"),
11123                None => String::new(),
11124            },
11125            from = match &self.limit_from {
11126                Some(f) => format!(" FROM {f}"),
11127                None => String::new(),
11128            }
11129        )?;
11130        Ok(())
11131    }
11132}
11133
11134#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11135#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11136#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11137/// Where a `SHOW` filter appears relative to the main clause.
11138pub enum ShowStatementFilterPosition {
11139    /// Put the filter in an infix position (e.g. `SHOW COLUMNS LIKE '%name%' IN TABLE tbl`).
11140    Infix(ShowStatementFilter), // For example: SHOW COLUMNS LIKE '%name%' IN TABLE tbl
11141    /// Put the filter in a suffix position (e.g. `SHOW COLUMNS IN tbl LIKE '%name%'`).
11142    Suffix(ShowStatementFilter), // For example: SHOW COLUMNS IN tbl LIKE '%name%'
11143}
11144
11145#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11146#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11147#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11148/// Parent object types usable with `SHOW ... IN <parent>` clauses.
11149pub enum ShowStatementInParentType {
11150    /// ACCOUNT parent type for SHOW statements.
11151    Account,
11152    /// DATABASE parent type for SHOW statements.
11153    Database,
11154    /// SCHEMA parent type for SHOW statements.
11155    Schema,
11156    /// TABLE parent type for SHOW statements.
11157    Table,
11158    /// VIEW parent type for SHOW statements.
11159    View,
11160}
11161
11162impl fmt::Display for ShowStatementInParentType {
11163    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11164        match self {
11165            ShowStatementInParentType::Account => write!(f, "ACCOUNT"),
11166            ShowStatementInParentType::Database => write!(f, "DATABASE"),
11167            ShowStatementInParentType::Schema => write!(f, "SCHEMA"),
11168            ShowStatementInParentType::Table => write!(f, "TABLE"),
11169            ShowStatementInParentType::View => write!(f, "VIEW"),
11170        }
11171    }
11172}
11173
11174#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11175#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11176#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11177/// Represents a `SHOW ... IN` clause with optional parent qualifier and name.
11178pub struct ShowStatementIn {
11179    /// The clause that specifies what to show (e.g. COLUMNS, TABLES).
11180    pub clause: ShowStatementInClause,
11181    /// Optional parent type qualifier (ACCOUNT/DATABASE/...).
11182    pub parent_type: Option<ShowStatementInParentType>,
11183    /// Optional parent object name for the SHOW clause.
11184    #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
11185    pub parent_name: Option<ObjectName>,
11186}
11187
11188impl fmt::Display for ShowStatementIn {
11189    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11190        write!(f, "{}", self.clause)?;
11191        if let Some(parent_type) = &self.parent_type {
11192            write!(f, " {parent_type}")?;
11193        }
11194        if let Some(parent_name) = &self.parent_name {
11195            write!(f, " {parent_name}")?;
11196        }
11197        Ok(())
11198    }
11199}
11200
11201/// A Show Charset statement
11202#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11203#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11204#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11205pub struct ShowCharset {
11206    /// The statement can be written as `SHOW CHARSET` or `SHOW CHARACTER SET`
11207    /// true means CHARSET was used and false means CHARACTER SET was used
11208    pub is_shorthand: bool,
11209    /// Optional `LIKE`/`WHERE`-style filter for the statement.
11210    pub filter: Option<ShowStatementFilter>,
11211}
11212
11213impl fmt::Display for ShowCharset {
11214    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11215        write!(f, "SHOW")?;
11216        if self.is_shorthand {
11217            write!(f, " CHARSET")?;
11218        } else {
11219            write!(f, " CHARACTER SET")?;
11220        }
11221        if let Some(filter) = &self.filter {
11222            write!(f, " {filter}")?;
11223        }
11224        Ok(())
11225    }
11226}
11227
11228#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11229#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11230#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11231/// Options for a `SHOW OBJECTS` statement.
11232pub struct ShowObjects {
11233    /// Whether to show terse output.
11234    pub terse: bool,
11235    /// Additional options controlling the SHOW output.
11236    pub show_options: ShowStatementOptions,
11237}
11238
11239/// MSSQL's json null clause
11240///
11241/// ```plaintext
11242/// <json_null_clause> ::=
11243///       NULL ON NULL
11244///     | ABSENT ON NULL
11245/// ```
11246///
11247/// <https://learn.microsoft.com/en-us/sql/t-sql/functions/json-object-transact-sql?view=sql-server-ver16#json_null_clause>
11248#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11249#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11250#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11251pub enum JsonNullClause {
11252    /// `NULL ON NULL` behavior for JSON functions.
11253    NullOnNull,
11254    /// `ABSENT ON NULL` behavior for JSON functions.
11255    AbsentOnNull,
11256}
11257
11258impl Display for JsonNullClause {
11259    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
11260        match self {
11261            JsonNullClause::NullOnNull => write!(f, "NULL ON NULL"),
11262            JsonNullClause::AbsentOnNull => write!(f, "ABSENT ON NULL"),
11263        }
11264    }
11265}
11266
11267/// PostgreSQL JSON function RETURNING clause
11268///
11269/// Example:
11270/// ```sql
11271/// JSON_OBJECT('a': 1 RETURNING jsonb)
11272/// ```
11273#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11274#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11275#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11276pub struct JsonReturningClause {
11277    /// The data type to return from the JSON function (e.g. JSON/JSONB).
11278    pub data_type: DataType,
11279}
11280
11281impl Display for JsonReturningClause {
11282    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
11283        write!(f, "RETURNING {}", self.data_type)
11284    }
11285}
11286
11287/// rename object definition
11288#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11289#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11290#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11291pub struct RenameTable {
11292    /// The current name of the object to rename.
11293    pub old_name: ObjectName,
11294    /// The new name for the object.
11295    pub new_name: ObjectName,
11296}
11297
11298impl fmt::Display for RenameTable {
11299    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11300        write!(f, "{} TO {}", self.old_name, self.new_name)?;
11301        Ok(())
11302    }
11303}
11304
11305/// Represents the referenced table in an `INSERT INTO` statement
11306#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11307#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11308#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11309pub enum TableObject {
11310    /// Table specified by name.
11311    /// Example:
11312    /// ```sql
11313    /// INSERT INTO my_table
11314    /// ```
11315    TableName(#[cfg_attr(feature = "visitor", visit(with = "visit_relation"))] ObjectName),
11316
11317    /// Table specified as a function.
11318    /// Example:
11319    /// ```sql
11320    /// INSERT INTO TABLE FUNCTION remote('localhost', default.simple_table)
11321    /// ```
11322    /// [Clickhouse](https://clickhouse.com/docs/en/sql-reference/table-functions)
11323    TableFunction(Function),
11324
11325    /// Table specified through a sub-query
11326    /// Example:
11327    /// ```sql
11328    /// INSERT INTO
11329    /// (SELECT employee_id, last_name, email, hire_date, job_id,  salary, commission_pct FROM employees)
11330    /// VALUES (207, 'Gregory', 'pgregory@example.com', sysdate, 'PU_CLERK', 1.2E3, NULL);
11331    /// ```
11332    /// [Oracle](https://docs.oracle.com/en/database/oracle/oracle-database/21/sqlrf/INSERT.html#GUID-903F8043-0254-4EE9-ACC1-CB8AC0AF3423__I2126242)
11333    TableQuery(Box<Query>),
11334}
11335
11336impl fmt::Display for TableObject {
11337    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11338        match self {
11339            Self::TableName(table_name) => write!(f, "{table_name}"),
11340            Self::TableFunction(func) => write!(f, "FUNCTION {func}"),
11341            Self::TableQuery(table_query) => write!(f, "({table_query})"),
11342        }
11343    }
11344}
11345
11346/// Represents a SET SESSION AUTHORIZATION statement
11347#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11348#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11349#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11350pub struct SetSessionAuthorizationParam {
11351    /// The scope for the `SET SESSION AUTHORIZATION` (e.g., GLOBAL/SESSION).
11352    pub scope: ContextModifier,
11353    /// The specific authorization parameter kind.
11354    pub kind: SetSessionAuthorizationParamKind,
11355}
11356
11357impl fmt::Display for SetSessionAuthorizationParam {
11358    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11359        write!(f, "{}", self.kind)
11360    }
11361}
11362
11363/// Represents the parameter kind for SET SESSION AUTHORIZATION
11364#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11365#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11366#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11367pub enum SetSessionAuthorizationParamKind {
11368    /// Default authorization
11369    Default,
11370
11371    /// User name
11372    User(Ident),
11373}
11374
11375impl fmt::Display for SetSessionAuthorizationParamKind {
11376    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11377        match self {
11378            SetSessionAuthorizationParamKind::Default => write!(f, "DEFAULT"),
11379            SetSessionAuthorizationParamKind::User(name) => write!(f, "{}", name),
11380        }
11381    }
11382}
11383
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))]
11387/// Kind of session parameter being set by `SET SESSION`.
11388pub enum SetSessionParamKind {
11389    /// Generic session parameter (name/value pair).
11390    Generic(SetSessionParamGeneric),
11391    /// Identity insert related parameter.
11392    IdentityInsert(SetSessionParamIdentityInsert),
11393    /// Offsets-related parameter.
11394    Offsets(SetSessionParamOffsets),
11395    /// Statistics-related parameter.
11396    Statistics(SetSessionParamStatistics),
11397}
11398
11399impl fmt::Display for SetSessionParamKind {
11400    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11401        match self {
11402            SetSessionParamKind::Generic(x) => write!(f, "{x}"),
11403            SetSessionParamKind::IdentityInsert(x) => write!(f, "{x}"),
11404            SetSessionParamKind::Offsets(x) => write!(f, "{x}"),
11405            SetSessionParamKind::Statistics(x) => write!(f, "{x}"),
11406        }
11407    }
11408}
11409
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))]
11413/// Generic `SET SESSION` parameter represented as name(s) and value.
11414pub struct SetSessionParamGeneric {
11415    /// Names of the session parameters being set.
11416    pub names: Vec<String>,
11417    /// The value to assign to the parameter(s).
11418    pub value: String,
11419}
11420
11421impl fmt::Display for SetSessionParamGeneric {
11422    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11423        write!(f, "{} {}", display_comma_separated(&self.names), self.value)
11424    }
11425}
11426
11427#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11428#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11429#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11430/// `IDENTITY_INSERT` session parameter for a specific object.
11431pub struct SetSessionParamIdentityInsert {
11432    /// Object name targeted by `IDENTITY_INSERT`.
11433    pub obj: ObjectName,
11434    /// Value (ON/OFF) for the identity insert setting.
11435    pub value: SessionParamValue,
11436}
11437
11438impl fmt::Display for SetSessionParamIdentityInsert {
11439    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11440        write!(f, "IDENTITY_INSERT {} {}", self.obj, self.value)
11441    }
11442}
11443
11444#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11445#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11446#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11447/// Offsets-related session parameter with keywords and a value.
11448pub struct SetSessionParamOffsets {
11449    /// Keywords specifying which offsets to modify.
11450    pub keywords: Vec<String>,
11451    /// Value (ON/OFF) for the offsets setting.
11452    pub value: SessionParamValue,
11453}
11454
11455impl fmt::Display for SetSessionParamOffsets {
11456    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11457        write!(
11458            f,
11459            "OFFSETS {} {}",
11460            display_comma_separated(&self.keywords),
11461            self.value
11462        )
11463    }
11464}
11465
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))]
11469/// Statistics-related session parameter specifying topic and value.
11470pub struct SetSessionParamStatistics {
11471    /// Statistics topic to set (IO/PROFILE/TIME/XML).
11472    pub topic: SessionParamStatsTopic,
11473    /// Value (ON/OFF) for the statistics topic.
11474    pub value: SessionParamValue,
11475}
11476
11477impl fmt::Display for SetSessionParamStatistics {
11478    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11479        write!(f, "STATISTICS {} {}", self.topic, self.value)
11480    }
11481}
11482
11483#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11484#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11485#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11486/// Topics available for session statistics configuration.
11487pub enum SessionParamStatsTopic {
11488    /// Input/output statistics.
11489    IO,
11490    /// Profile statistics.
11491    Profile,
11492    /// Time statistics.
11493    Time,
11494    /// XML-related statistics.
11495    Xml,
11496}
11497
11498impl fmt::Display for SessionParamStatsTopic {
11499    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11500        match self {
11501            SessionParamStatsTopic::IO => write!(f, "IO"),
11502            SessionParamStatsTopic::Profile => write!(f, "PROFILE"),
11503            SessionParamStatsTopic::Time => write!(f, "TIME"),
11504            SessionParamStatsTopic::Xml => write!(f, "XML"),
11505        }
11506    }
11507}
11508
11509#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11510#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11511#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11512/// Value for a session boolean-like parameter (ON/OFF).
11513pub enum SessionParamValue {
11514    /// Session parameter enabled.
11515    On,
11516    /// Session parameter disabled.
11517    Off,
11518}
11519
11520impl fmt::Display for SessionParamValue {
11521    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11522        match self {
11523            SessionParamValue::On => write!(f, "ON"),
11524            SessionParamValue::Off => write!(f, "OFF"),
11525        }
11526    }
11527}
11528
11529/// Snowflake StorageSerializationPolicy for Iceberg Tables
11530/// ```sql
11531/// [ STORAGE_SERIALIZATION_POLICY = { COMPATIBLE | OPTIMIZED } ]
11532/// ```
11533///
11534/// <https://docs.snowflake.com/en/sql-reference/sql/create-iceberg-table>
11535#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11536#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11537#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11538pub enum StorageSerializationPolicy {
11539    /// Use compatible serialization mode.
11540    Compatible,
11541    /// Use optimized serialization mode.
11542    Optimized,
11543}
11544
11545impl Display for StorageSerializationPolicy {
11546    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
11547        match self {
11548            StorageSerializationPolicy::Compatible => write!(f, "COMPATIBLE"),
11549            StorageSerializationPolicy::Optimized => write!(f, "OPTIMIZED"),
11550        }
11551    }
11552}
11553
11554/// Snowflake CatalogSyncNamespaceMode
11555/// ```sql
11556/// [ CATALOG_SYNC_NAMESPACE_MODE = { NEST | FLATTEN } ]
11557/// ```
11558///
11559/// <https://docs.snowflake.com/en/sql-reference/sql/create-database>
11560#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11561#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11562#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11563pub enum CatalogSyncNamespaceMode {
11564    /// Nest namespaces when syncing catalog.
11565    Nest,
11566    /// Flatten namespaces when syncing catalog.
11567    Flatten,
11568}
11569
11570impl Display for CatalogSyncNamespaceMode {
11571    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
11572        match self {
11573            CatalogSyncNamespaceMode::Nest => write!(f, "NEST"),
11574            CatalogSyncNamespaceMode::Flatten => write!(f, "FLATTEN"),
11575        }
11576    }
11577}
11578
11579/// Variants of the Snowflake `COPY INTO` statement
11580#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11581#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11582#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11583pub enum CopyIntoSnowflakeKind {
11584    /// Loads data from files to a table
11585    /// See: <https://docs.snowflake.com/en/sql-reference/sql/copy-into-table>
11586    Table,
11587    /// Unloads data from a table or query to external files
11588    /// See: <https://docs.snowflake.com/en/sql-reference/sql/copy-into-location>
11589    Location,
11590}
11591
11592#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11593#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11594#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11595/// `PRINT` statement for producing debug/output messages.
11596pub struct PrintStatement {
11597    /// The expression producing the message to print.
11598    pub message: Box<Expr>,
11599}
11600
11601impl fmt::Display for PrintStatement {
11602    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11603        write!(f, "PRINT {}", self.message)
11604    }
11605}
11606
11607/// The type of `WAITFOR` statement (MSSQL).
11608///
11609/// See: <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/waitfor-transact-sql>
11610#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11611#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11612#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11613pub enum WaitForType {
11614    /// `WAITFOR DELAY 'time_to_pass'`
11615    Delay,
11616    /// `WAITFOR TIME 'time_to_execute'`
11617    Time,
11618}
11619
11620impl fmt::Display for WaitForType {
11621    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11622        match self {
11623            WaitForType::Delay => write!(f, "DELAY"),
11624            WaitForType::Time => write!(f, "TIME"),
11625        }
11626    }
11627}
11628
11629/// MSSQL `WAITFOR` statement.
11630///
11631/// See: <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/waitfor-transact-sql>
11632#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11633#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11634#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11635pub struct WaitForStatement {
11636    /// `DELAY` or `TIME`.
11637    pub wait_type: WaitForType,
11638    /// The time expression.
11639    pub expr: Expr,
11640}
11641
11642impl fmt::Display for WaitForStatement {
11643    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11644        write!(f, "WAITFOR {} {}", self.wait_type, self.expr)
11645    }
11646}
11647
11648/// Represents a `Return` statement.
11649///
11650/// [MsSql triggers](https://learn.microsoft.com/en-us/sql/t-sql/statements/create-trigger-transact-sql)
11651/// [MsSql functions](https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql)
11652#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11653#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11654#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11655pub struct ReturnStatement {
11656    /// Optional return value expression.
11657    pub value: Option<ReturnStatementValue>,
11658}
11659
11660impl fmt::Display for ReturnStatement {
11661    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11662        match &self.value {
11663            Some(ReturnStatementValue::Expr(expr)) => write!(f, "RETURN {expr}"),
11664            None => write!(f, "RETURN"),
11665        }
11666    }
11667}
11668
11669/// Variants of a `RETURN` statement
11670#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11671#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11672#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11673pub enum ReturnStatementValue {
11674    /// Return an expression from a function or trigger.
11675    Expr(Expr),
11676}
11677
11678/// Represents an `OPEN` statement.
11679#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11680#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11681#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11682pub struct OpenStatement {
11683    /// Cursor name
11684    pub cursor_name: Ident,
11685}
11686
11687impl fmt::Display for OpenStatement {
11688    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11689        write!(f, "OPEN {}", self.cursor_name)
11690    }
11691}
11692
11693/// Specifies Include / Exclude NULL within UNPIVOT command.
11694/// For example
11695/// `UNPIVOT (column1 FOR new_column IN (col3, col4, col5, col6))`
11696#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11697#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11698#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11699pub enum NullInclusion {
11700    /// Include NULL values in the UNPIVOT output.
11701    IncludeNulls,
11702    /// Exclude NULL values from the UNPIVOT output.
11703    ExcludeNulls,
11704}
11705
11706impl fmt::Display for NullInclusion {
11707    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11708        match self {
11709            NullInclusion::IncludeNulls => write!(f, "INCLUDE NULLS"),
11710            NullInclusion::ExcludeNulls => write!(f, "EXCLUDE NULLS"),
11711        }
11712    }
11713}
11714
11715/// Checks membership of a value in a JSON array
11716///
11717/// Syntax:
11718/// ```sql
11719/// <value> MEMBER OF(<array>)
11720/// ```
11721/// [MySQL](https://dev.mysql.com/doc/refman/8.4/en/json-search-functions.html#operator_member-of)
11722#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11723#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11724#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11725pub struct MemberOf {
11726    /// The value to check for membership.
11727    pub value: Box<Expr>,
11728    /// The JSON array expression to check against.
11729    pub array: Box<Expr>,
11730}
11731
11732impl fmt::Display for MemberOf {
11733    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11734        write!(f, "{} MEMBER OF({})", self.value, self.array)
11735    }
11736}
11737
11738#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11739#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11740#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11741/// Represents an `EXPORT DATA` statement.
11742pub struct ExportData {
11743    /// Options for the export operation.
11744    pub options: Vec<SqlOption>,
11745    /// The query producing the data to export.
11746    pub query: Box<Query>,
11747    /// Optional named connection to use for export.
11748    pub connection: Option<ObjectName>,
11749}
11750
11751impl fmt::Display for ExportData {
11752    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11753        if let Some(connection) = &self.connection {
11754            write!(
11755                f,
11756                "EXPORT DATA WITH CONNECTION {connection} OPTIONS({}) AS {}",
11757                display_comma_separated(&self.options),
11758                self.query
11759            )
11760        } else {
11761            write!(
11762                f,
11763                "EXPORT DATA OPTIONS({}) AS {}",
11764                display_comma_separated(&self.options),
11765                self.query
11766            )
11767        }
11768    }
11769}
11770/// Creates a user
11771///
11772/// Syntax:
11773/// ```sql
11774/// CREATE [OR REPLACE] USER [IF NOT EXISTS] <name> [OPTIONS]
11775/// ```
11776///
11777/// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-user)
11778#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11779#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11780#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11781pub struct CreateUser {
11782    /// Replace existing user if present.
11783    pub or_replace: bool,
11784    /// Only create the user if it does not already exist.
11785    pub if_not_exists: bool,
11786    /// The name of the user to create.
11787    pub name: Ident,
11788    /// Key/value options for user creation.
11789    pub options: KeyValueOptions,
11790    /// Whether tags are specified using `WITH TAG`.
11791    pub with_tags: bool,
11792    /// Tags for the user.
11793    pub tags: KeyValueOptions,
11794}
11795
11796impl fmt::Display for CreateUser {
11797    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11798        write!(f, "CREATE")?;
11799        if self.or_replace {
11800            write!(f, " OR REPLACE")?;
11801        }
11802        write!(f, " USER")?;
11803        if self.if_not_exists {
11804            write!(f, " IF NOT EXISTS")?;
11805        }
11806        write!(f, " {}", self.name)?;
11807        if !self.options.options.is_empty() {
11808            write!(f, " {}", self.options)?;
11809        }
11810        if !self.tags.options.is_empty() {
11811            if self.with_tags {
11812                write!(f, " WITH")?;
11813            }
11814            write!(f, " TAG ({})", self.tags)?;
11815        }
11816        Ok(())
11817    }
11818}
11819
11820/// ```sql
11821/// CREATE [ OR REPLACE ] WAREHOUSE [ IF NOT EXISTS ] <name>
11822///   [ [ WITH ] <property> = <value> [ ... ] ]
11823/// ```
11824/// Snowflake-specific statement to create a virtual warehouse.
11825///
11826/// See <https://docs.snowflake.com/en/sql-reference/sql/create-warehouse>
11827#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11828#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11829#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11830pub struct CreateWarehouse {
11831    /// `OR REPLACE` flag.
11832    pub or_replace: bool,
11833    /// `IF NOT EXISTS` flag.
11834    pub if_not_exists: bool,
11835    /// Warehouse name.
11836    pub name: ObjectName,
11837    /// Warehouse properties and parameters (e.g. `WAREHOUSE_SIZE = 'XSMALL'`).
11838    pub options: KeyValueOptions,
11839}
11840
11841impl fmt::Display for CreateWarehouse {
11842    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11843        write!(f, "CREATE")?;
11844        if self.or_replace {
11845            write!(f, " OR REPLACE")?;
11846        }
11847        write!(f, " WAREHOUSE")?;
11848        if self.if_not_exists {
11849            write!(f, " IF NOT EXISTS")?;
11850        }
11851        write!(f, " {}", self.name)?;
11852        if !self.options.options.is_empty() {
11853            write!(f, " {}", self.options)?;
11854        }
11855        Ok(())
11856    }
11857}
11858
11859/// Modifies the properties of a user
11860///
11861/// [Snowflake Syntax:](https://docs.snowflake.com/en/sql-reference/sql/alter-user)
11862/// ```sql
11863/// ALTER USER [ IF EXISTS ] [ <name> ] [ OPTIONS ]
11864/// ```
11865///
11866/// [PostgreSQL Syntax:](https://www.postgresql.org/docs/current/sql-alteruser.html)
11867/// ```sql
11868/// ALTER USER <role_specification> [ WITH ] option [ ... ]
11869/// ```
11870#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11871#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11872#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11873pub struct AlterUser {
11874    /// Whether to only alter the user if it exists.
11875    pub if_exists: bool,
11876    /// The name of the user to alter.
11877    pub name: Ident,
11878    /// Optional new name for the user (Snowflake-specific).
11879    /// See: <https://docs.snowflake.com/en/sql-reference/sql/alter-user#syntax>
11880    pub rename_to: Option<Ident>,
11881    /// Reset the user's password.
11882    pub reset_password: bool,
11883    /// Abort all running queries for the user.
11884    pub abort_all_queries: bool,
11885    /// Optionally add a delegated role authorization.
11886    pub add_role_delegation: Option<AlterUserAddRoleDelegation>,
11887    /// Optionally remove a delegated role authorization.
11888    pub remove_role_delegation: Option<AlterUserRemoveRoleDelegation>,
11889    /// Enroll the user in MFA.
11890    pub enroll_mfa: bool,
11891    /// Set the default MFA method for the user.
11892    pub set_default_mfa_method: Option<MfaMethodKind>,
11893    /// Remove the user's default MFA method.
11894    pub remove_mfa_method: Option<MfaMethodKind>,
11895    /// Modify an MFA method for the user.
11896    pub modify_mfa_method: Option<AlterUserModifyMfaMethod>,
11897    /// Add an MFA OTP method with optional count.
11898    pub add_mfa_method_otp: Option<AlterUserAddMfaMethodOtp>,
11899    /// Set a user policy.
11900    pub set_policy: Option<AlterUserSetPolicy>,
11901    /// Unset a user policy.
11902    pub unset_policy: Option<UserPolicyKind>,
11903    /// Key/value tag options to set on the user.
11904    pub set_tag: KeyValueOptions,
11905    /// Tags to unset on the user.
11906    pub unset_tag: Vec<String>,
11907    /// Key/value properties to set on the user.
11908    pub set_props: KeyValueOptions,
11909    /// Properties to unset on the user.
11910    pub unset_props: Vec<String>,
11911    /// The following options are PostgreSQL-specific: <https://www.postgresql.org/docs/current/sql-alteruser.html>
11912    pub password: Option<AlterUserPassword>,
11913}
11914
11915/// ```sql
11916/// ALTER USER [ IF EXISTS ] [ <name> ] ADD DELEGATED AUTHORIZATION OF ROLE <role_name> TO SECURITY INTEGRATION <integration_name>
11917/// ```
11918#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11919#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11920#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11921pub struct AlterUserAddRoleDelegation {
11922    /// Role name to delegate.
11923    pub role: Ident,
11924    /// Security integration receiving the delegation.
11925    pub integration: Ident,
11926}
11927
11928/// ```sql
11929/// ALTER USER [ IF EXISTS ] [ <name> ] REMOVE DELEGATED { AUTHORIZATION OF ROLE <role_name> | AUTHORIZATIONS } FROM SECURITY INTEGRATION <integration_name>
11930/// ```
11931#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11932#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11933#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11934pub struct AlterUserRemoveRoleDelegation {
11935    /// Optional role name to remove delegation for.
11936    pub role: Option<Ident>,
11937    /// Security integration from which to remove delegation.
11938    pub integration: Ident,
11939}
11940
11941/// ```sql
11942/// ADD MFA METHOD OTP [ COUNT = number ]
11943/// ```
11944#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11945#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11946#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11947pub struct AlterUserAddMfaMethodOtp {
11948    /// Optional OTP count parameter.
11949    pub count: Option<ValueWithSpan>,
11950}
11951
11952/// ```sql
11953/// ALTER USER [ IF EXISTS ] [ <name> ] MODIFY MFA METHOD <mfa_method> SET COMMENT = '<string>'
11954/// ```
11955#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11956#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11957#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11958pub struct AlterUserModifyMfaMethod {
11959    /// The MFA method being modified.
11960    pub method: MfaMethodKind,
11961    /// The new comment for the MFA method.
11962    pub comment: String,
11963}
11964
11965/// Types of MFA methods
11966#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11967#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11968#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11969pub enum MfaMethodKind {
11970    /// PassKey (hardware or platform passkey) MFA method.
11971    PassKey,
11972    /// Time-based One-Time Password (TOTP) MFA method.
11973    Totp,
11974    /// Duo Security MFA method.
11975    Duo,
11976}
11977
11978impl fmt::Display for MfaMethodKind {
11979    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11980        match self {
11981            MfaMethodKind::PassKey => write!(f, "PASSKEY"),
11982            MfaMethodKind::Totp => write!(f, "TOTP"),
11983            MfaMethodKind::Duo => write!(f, "DUO"),
11984        }
11985    }
11986}
11987
11988/// ```sql
11989/// ALTER USER [ IF EXISTS ] [ <name> ] SET { AUTHENTICATION | PASSWORD | SESSION } POLICY <policy_name>
11990/// ```
11991#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11992#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11993#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11994pub struct AlterUserSetPolicy {
11995    /// The kind of user policy being set (authentication/password/session).
11996    pub policy_kind: UserPolicyKind,
11997    /// The identifier of the policy to apply.
11998    pub policy: Ident,
11999}
12000
12001/// Types of user-based policies
12002#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
12003#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
12004#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
12005pub enum UserPolicyKind {
12006    /// Authentication policy.
12007    Authentication,
12008    /// Password policy.
12009    Password,
12010    /// Session policy.
12011    Session,
12012}
12013
12014impl fmt::Display for UserPolicyKind {
12015    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
12016        match self {
12017            UserPolicyKind::Authentication => write!(f, "AUTHENTICATION"),
12018            UserPolicyKind::Password => write!(f, "PASSWORD"),
12019            UserPolicyKind::Session => write!(f, "SESSION"),
12020        }
12021    }
12022}
12023
12024impl fmt::Display for AlterUser {
12025    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
12026        write!(f, "ALTER")?;
12027        write!(f, " USER")?;
12028        if self.if_exists {
12029            write!(f, " IF EXISTS")?;
12030        }
12031        write!(f, " {}", self.name)?;
12032        if let Some(new_name) = &self.rename_to {
12033            write!(f, " RENAME TO {new_name}")?;
12034        }
12035        if self.reset_password {
12036            write!(f, " RESET PASSWORD")?;
12037        }
12038        if self.abort_all_queries {
12039            write!(f, " ABORT ALL QUERIES")?;
12040        }
12041        if let Some(role_delegation) = &self.add_role_delegation {
12042            let role = &role_delegation.role;
12043            let integration = &role_delegation.integration;
12044            write!(
12045                f,
12046                " ADD DELEGATED AUTHORIZATION OF ROLE {role} TO SECURITY INTEGRATION {integration}"
12047            )?;
12048        }
12049        if let Some(role_delegation) = &self.remove_role_delegation {
12050            write!(f, " REMOVE DELEGATED")?;
12051            match &role_delegation.role {
12052                Some(role) => write!(f, " AUTHORIZATION OF ROLE {role}")?,
12053                None => write!(f, " AUTHORIZATIONS")?,
12054            }
12055            let integration = &role_delegation.integration;
12056            write!(f, " FROM SECURITY INTEGRATION {integration}")?;
12057        }
12058        if self.enroll_mfa {
12059            write!(f, " ENROLL MFA")?;
12060        }
12061        if let Some(method) = &self.set_default_mfa_method {
12062            write!(f, " SET DEFAULT_MFA_METHOD {method}")?
12063        }
12064        if let Some(method) = &self.remove_mfa_method {
12065            write!(f, " REMOVE MFA METHOD {method}")?;
12066        }
12067        if let Some(modify) = &self.modify_mfa_method {
12068            let method = &modify.method;
12069            let comment = &modify.comment;
12070            write!(
12071                f,
12072                " MODIFY MFA METHOD {method} SET COMMENT '{}'",
12073                value::escape_single_quote_string(comment)
12074            )?;
12075        }
12076        if let Some(add_mfa_method_otp) = &self.add_mfa_method_otp {
12077            write!(f, " ADD MFA METHOD OTP")?;
12078            if let Some(count) = &add_mfa_method_otp.count {
12079                write!(f, " COUNT = {count}")?;
12080            }
12081        }
12082        if let Some(policy) = &self.set_policy {
12083            let policy_kind = &policy.policy_kind;
12084            let name = &policy.policy;
12085            write!(f, " SET {policy_kind} POLICY {name}")?;
12086        }
12087        if let Some(policy_kind) = &self.unset_policy {
12088            write!(f, " UNSET {policy_kind} POLICY")?;
12089        }
12090        if !self.set_tag.options.is_empty() {
12091            write!(f, " SET TAG {}", self.set_tag)?;
12092        }
12093        if !self.unset_tag.is_empty() {
12094            write!(f, " UNSET TAG {}", display_comma_separated(&self.unset_tag))?;
12095        }
12096        let has_props = !self.set_props.options.is_empty();
12097        if has_props {
12098            write!(f, " SET")?;
12099            write!(f, " {}", self.set_props)?;
12100        }
12101        if !self.unset_props.is_empty() {
12102            write!(f, " UNSET {}", display_comma_separated(&self.unset_props))?;
12103        }
12104        if let Some(password) = &self.password {
12105            write!(f, " {}", password)?;
12106        }
12107        Ok(())
12108    }
12109}
12110
12111/// ```sql
12112/// ALTER USER <role_specification> [ WITH ] PASSWORD { 'password' | NULL }``
12113/// ```
12114#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
12115#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
12116#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
12117pub struct AlterUserPassword {
12118    /// Whether the password is encrypted.
12119    pub encrypted: bool,
12120    /// The password string, or `None` for `NULL`.
12121    pub password: Option<String>,
12122}
12123
12124impl Display for AlterUserPassword {
12125    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
12126        if self.encrypted {
12127            write!(f, "ENCRYPTED ")?;
12128        }
12129        write!(f, "PASSWORD")?;
12130        match &self.password {
12131            None => write!(f, " NULL")?,
12132            Some(password) => write!(f, " '{}'", value::escape_single_quote_string(password))?,
12133        }
12134        Ok(())
12135    }
12136}
12137
12138/// Specifies how to create a new table based on an existing table's schema.
12139/// '''sql
12140/// CREATE TABLE new LIKE old ...
12141/// '''
12142#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
12143#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
12144#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
12145pub enum CreateTableLikeKind {
12146    /// '''sql
12147    /// CREATE TABLE new (LIKE old ...)
12148    /// '''
12149    /// [Redshift](https://docs.aws.amazon.com/redshift/latest/dg/r_CREATE_TABLE_NEW.html)
12150    Parenthesized(CreateTableLike),
12151    /// '''sql
12152    /// CREATE TABLE new LIKE old ...
12153    /// '''
12154    /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-table#label-create-table-like)
12155    /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_table_like)
12156    Plain(CreateTableLike),
12157}
12158
12159#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
12160#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
12161#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
12162/// Controls whether defaults are included when creating a table FROM/LILE another.
12163pub enum CreateTableLikeDefaults {
12164    /// Include default values from the source table.
12165    Including,
12166    /// Exclude default values from the source table.
12167    Excluding,
12168}
12169
12170impl fmt::Display for CreateTableLikeDefaults {
12171    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
12172        match self {
12173            CreateTableLikeDefaults::Including => write!(f, "INCLUDING DEFAULTS"),
12174            CreateTableLikeDefaults::Excluding => write!(f, "EXCLUDING DEFAULTS"),
12175        }
12176    }
12177}
12178
12179#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
12180#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
12181#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
12182/// Represents the `LIKE` clause of a `CREATE TABLE` statement.
12183pub struct CreateTableLike {
12184    /// The source table name to copy the schema from.
12185    pub name: ObjectName,
12186    /// Optional behavior controlling whether defaults are copied.
12187    pub defaults: Option<CreateTableLikeDefaults>,
12188}
12189
12190impl fmt::Display for CreateTableLike {
12191    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
12192        write!(f, "LIKE {}", self.name)?;
12193        if let Some(defaults) = &self.defaults {
12194            write!(f, " {defaults}")?;
12195        }
12196        Ok(())
12197    }
12198}
12199
12200/// Specifies the refresh mode for the dynamic table.
12201///
12202/// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-dynamic-table)
12203#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
12204#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
12205#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
12206pub enum RefreshModeKind {
12207    /// Automatic refresh mode (`AUTO`).
12208    Auto,
12209    /// Full refresh mode (`FULL`).
12210    Full,
12211    /// Incremental refresh mode (`INCREMENTAL`).
12212    Incremental,
12213}
12214
12215impl fmt::Display for RefreshModeKind {
12216    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
12217        match self {
12218            RefreshModeKind::Auto => write!(f, "AUTO"),
12219            RefreshModeKind::Full => write!(f, "FULL"),
12220            RefreshModeKind::Incremental => write!(f, "INCREMENTAL"),
12221        }
12222    }
12223}
12224
12225/// Specifies the behavior of the initial refresh of the dynamic table.
12226///
12227/// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-dynamic-table)
12228#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
12229#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
12230#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
12231pub enum InitializeKind {
12232    /// Initialize on creation (`ON CREATE`).
12233    OnCreate,
12234    /// Initialize on schedule (`ON SCHEDULE`).
12235    OnSchedule,
12236}
12237
12238impl fmt::Display for InitializeKind {
12239    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
12240        match self {
12241            InitializeKind::OnCreate => write!(f, "ON_CREATE"),
12242            InitializeKind::OnSchedule => write!(f, "ON_SCHEDULE"),
12243        }
12244    }
12245}
12246
12247/// Re-sorts rows and reclaims space in either a specified table or all tables in the current database
12248///
12249/// '''sql
12250/// VACUUM [ FULL | SORT ONLY | DELETE ONLY | REINDEX | RECLUSTER ] [ \[ table_name \] [ TO threshold PERCENT ] \[ BOOST \] ]
12251/// '''
12252/// [Redshift](https://docs.aws.amazon.com/redshift/latest/dg/r_VACUUM_command.html)
12253#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
12254#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
12255#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
12256pub struct VacuumStatement {
12257    /// Whether `FULL` was specified.
12258    pub full: bool,
12259    /// Whether `SORT ONLY` was specified.
12260    pub sort_only: bool,
12261    /// Whether `DELETE ONLY` was specified.
12262    pub delete_only: bool,
12263    /// Whether `REINDEX` was specified.
12264    pub reindex: bool,
12265    /// Whether `RECLUSTER` was specified.
12266    pub recluster: bool,
12267    /// Optional table to run `VACUUM` on.
12268    pub table_name: Option<ObjectName>,
12269    /// Optional threshold value (percent) for `TO threshold PERCENT`.
12270    pub threshold: Option<ValueWithSpan>,
12271    /// Whether `BOOST` was specified.
12272    pub boost: bool,
12273}
12274
12275impl fmt::Display for VacuumStatement {
12276    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
12277        write!(
12278            f,
12279            "VACUUM{}{}{}{}{}",
12280            if self.full { " FULL" } else { "" },
12281            if self.sort_only { " SORT ONLY" } else { "" },
12282            if self.delete_only { " DELETE ONLY" } else { "" },
12283            if self.reindex { " REINDEX" } else { "" },
12284            if self.recluster { " RECLUSTER" } else { "" },
12285        )?;
12286        if let Some(table_name) = &self.table_name {
12287            write!(f, " {table_name}")?;
12288        }
12289        if let Some(threshold) = &self.threshold {
12290            write!(f, " TO {threshold} PERCENT")?;
12291        }
12292        if self.boost {
12293            write!(f, " BOOST")?;
12294        }
12295        Ok(())
12296    }
12297}
12298
12299/// Variants of the RESET statement
12300#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
12301#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
12302#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
12303pub enum Reset {
12304    /// Resets all session parameters to their default values.
12305    ALL,
12306
12307    /// Resets session authorization to the session user.
12308    SessionAuthorization,
12309
12310    /// Resets a specific session parameter to its default value.
12311    ConfigurationParameter(ObjectName),
12312}
12313
12314/// Resets a session parameter to its default value.
12315/// ```sql
12316/// RESET { ALL | SESSION AUTHORIZATION | <configuration_parameter> }
12317/// ```
12318#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
12319#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
12320#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
12321pub struct ResetStatement {
12322    /// The reset action to perform (either `ALL` or a specific configuration parameter).
12323    pub reset: Reset,
12324}
12325
12326/// Query optimizer hints are optionally supported comments after the
12327/// `SELECT`, `INSERT`, `UPDATE`, `REPLACE`, `MERGE`, and `DELETE` keywords in
12328/// the corresponding statements.
12329///
12330/// See [Select::optimizer_hints]
12331#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
12332#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
12333#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
12334pub struct OptimizerHint {
12335    /// An optional prefix between the comment marker and `+`.
12336    ///
12337    /// Standard optimizer hints like `/*+ ... */` have an empty prefix,
12338    /// while system-specific hints like `/*abc+ ... */` have `prefix = "abc"`.
12339    /// The prefix is any sequence of ASCII alphanumeric characters
12340    /// immediately before the `+` marker.
12341    pub prefix: String,
12342    /// the raw text of the optimizer hint without its markers
12343    pub text: String,
12344    /// the style of the comment which `text` was extracted from,
12345    /// e.g. `/*+...*/` or `--+...`
12346    ///
12347    /// Not all dialects support all styles, though.
12348    pub style: OptimizerHintStyle,
12349}
12350
12351/// The commentary style of an [optimizer hint](OptimizerHint)
12352#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
12353#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
12354#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
12355pub enum OptimizerHintStyle {
12356    /// A hint corresponding to a single line comment,
12357    /// e.g. `--+ LEADING(v.e v.d t)`
12358    SingleLine {
12359        /// the comment prefix, e.g. `--`
12360        prefix: String,
12361    },
12362    /// A hint corresponding to a multi line comment,
12363    /// e.g. `/*+ LEADING(v.e v.d t) */`
12364    MultiLine,
12365}
12366
12367impl fmt::Display for OptimizerHint {
12368    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
12369        match &self.style {
12370            OptimizerHintStyle::SingleLine { prefix } => {
12371                f.write_str(prefix)?;
12372                f.write_str(&self.prefix)?;
12373                f.write_str("+")?;
12374                f.write_str(&self.text)?;
12375                f.write_str("\n")
12376            }
12377            OptimizerHintStyle::MultiLine => {
12378                f.write_str("/*")?;
12379                f.write_str(&self.prefix)?;
12380                f.write_str("+")?;
12381                f.write_str(&self.text)?;
12382                f.write_str("*/")
12383            }
12384        }
12385    }
12386}
12387
12388impl fmt::Display for ResetStatement {
12389    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
12390        match &self.reset {
12391            Reset::ALL => write!(f, "RESET ALL"),
12392            Reset::SessionAuthorization => write!(f, "RESET SESSION AUTHORIZATION"),
12393            Reset::ConfigurationParameter(param) => write!(f, "RESET {}", param),
12394        }
12395    }
12396}
12397
12398impl From<Set> for Statement {
12399    fn from(s: Set) -> Self {
12400        Self::Set(s)
12401    }
12402}
12403
12404impl From<Query> for Statement {
12405    fn from(q: Query) -> Self {
12406        Box::new(q).into()
12407    }
12408}
12409
12410impl From<Box<Query>> for Statement {
12411    fn from(q: Box<Query>) -> Self {
12412        Self::Query(q)
12413    }
12414}
12415
12416impl From<Insert> for Statement {
12417    fn from(i: Insert) -> Self {
12418        Self::Insert(i)
12419    }
12420}
12421
12422impl From<Update> for Statement {
12423    fn from(u: Update) -> Self {
12424        Self::Update(u)
12425    }
12426}
12427
12428impl From<CreateView> for Statement {
12429    fn from(cv: CreateView) -> Self {
12430        Self::CreateView(cv)
12431    }
12432}
12433
12434impl From<CreateRole> for Statement {
12435    fn from(cr: CreateRole) -> Self {
12436        Self::CreateRole(cr)
12437    }
12438}
12439
12440impl From<AlterTable> for Statement {
12441    fn from(at: AlterTable) -> Self {
12442        Self::AlterTable(at)
12443    }
12444}
12445
12446impl From<DropFunction> for Statement {
12447    fn from(df: DropFunction) -> Self {
12448        Self::DropFunction(df)
12449    }
12450}
12451
12452impl From<CreateExtension> for Statement {
12453    fn from(ce: CreateExtension) -> Self {
12454        Self::CreateExtension(ce)
12455    }
12456}
12457
12458impl From<CreateCollation> for Statement {
12459    fn from(c: CreateCollation) -> Self {
12460        Self::CreateCollation(c)
12461    }
12462}
12463
12464impl From<DropExtension> for Statement {
12465    fn from(de: DropExtension) -> Self {
12466        Self::DropExtension(de)
12467    }
12468}
12469
12470impl From<CaseStatement> for Statement {
12471    fn from(c: CaseStatement) -> Self {
12472        Self::Case(c)
12473    }
12474}
12475
12476impl From<IfStatement> for Statement {
12477    fn from(i: IfStatement) -> Self {
12478        Self::If(i)
12479    }
12480}
12481
12482impl From<WhileStatement> for Statement {
12483    fn from(w: WhileStatement) -> Self {
12484        Self::While(w)
12485    }
12486}
12487
12488impl From<RaiseStatement> for Statement {
12489    fn from(r: RaiseStatement) -> Self {
12490        Self::Raise(r)
12491    }
12492}
12493
12494impl From<DoStatement> for Statement {
12495    fn from(statement: DoStatement) -> Self {
12496        Self::Do(statement)
12497    }
12498}
12499
12500impl From<ThrowStatement> for Statement {
12501    fn from(t: ThrowStatement) -> Self {
12502        Self::Throw(t)
12503    }
12504}
12505
12506impl From<Function> for Statement {
12507    fn from(f: Function) -> Self {
12508        Self::Call(f)
12509    }
12510}
12511
12512impl From<OpenStatement> for Statement {
12513    fn from(o: OpenStatement) -> Self {
12514        Self::Open(o)
12515    }
12516}
12517
12518impl From<Delete> for Statement {
12519    fn from(d: Delete) -> Self {
12520        Self::Delete(d)
12521    }
12522}
12523
12524impl From<CreateTable> for Statement {
12525    fn from(c: CreateTable) -> Self {
12526        Self::CreateTable(c)
12527    }
12528}
12529
12530impl From<CreateIndex> for Statement {
12531    fn from(c: CreateIndex) -> Self {
12532        Self::CreateIndex(c)
12533    }
12534}
12535
12536impl From<CreateServerStatement> for Statement {
12537    fn from(c: CreateServerStatement) -> Self {
12538        Self::CreateServer(c)
12539    }
12540}
12541
12542impl From<CreateConnector> for Statement {
12543    fn from(c: CreateConnector) -> Self {
12544        Self::CreateConnector(c)
12545    }
12546}
12547
12548impl From<CreateOperator> for Statement {
12549    fn from(c: CreateOperator) -> Self {
12550        Self::CreateOperator(c)
12551    }
12552}
12553
12554impl From<CreateOperatorFamily> for Statement {
12555    fn from(c: CreateOperatorFamily) -> Self {
12556        Self::CreateOperatorFamily(c)
12557    }
12558}
12559
12560impl From<CreateOperatorClass> for Statement {
12561    fn from(c: CreateOperatorClass) -> Self {
12562        Self::CreateOperatorClass(c)
12563    }
12564}
12565
12566impl From<CreateTextSearch> for Statement {
12567    fn from(c: CreateTextSearch) -> Self {
12568        Self::CreateTextSearch(c)
12569    }
12570}
12571
12572impl From<AlterSchema> for Statement {
12573    fn from(a: AlterSchema) -> Self {
12574        Self::AlterSchema(a)
12575    }
12576}
12577
12578impl From<AlterFunction> for Statement {
12579    fn from(a: AlterFunction) -> Self {
12580        Self::AlterFunction(a)
12581    }
12582}
12583
12584impl From<AlterType> for Statement {
12585    fn from(a: AlterType) -> Self {
12586        Self::AlterType(a)
12587    }
12588}
12589
12590impl From<AlterCollation> for Statement {
12591    fn from(a: AlterCollation) -> Self {
12592        Self::AlterCollation(a)
12593    }
12594}
12595
12596impl From<AlterOperator> for Statement {
12597    fn from(a: AlterOperator) -> Self {
12598        Self::AlterOperator(a)
12599    }
12600}
12601
12602impl From<AlterOperatorFamily> for Statement {
12603    fn from(a: AlterOperatorFamily) -> Self {
12604        Self::AlterOperatorFamily(a)
12605    }
12606}
12607
12608impl From<AlterOperatorClass> for Statement {
12609    fn from(a: AlterOperatorClass) -> Self {
12610        Self::AlterOperatorClass(a)
12611    }
12612}
12613
12614impl From<AlterTextSearch> for Statement {
12615    fn from(a: AlterTextSearch) -> Self {
12616        Self::AlterTextSearch(a)
12617    }
12618}
12619
12620impl From<Merge> for Statement {
12621    fn from(m: Merge) -> Self {
12622        Self::Merge(m)
12623    }
12624}
12625
12626impl From<AlterUser> for Statement {
12627    fn from(a: AlterUser) -> Self {
12628        Self::AlterUser(a)
12629    }
12630}
12631
12632impl From<DropDomain> for Statement {
12633    fn from(d: DropDomain) -> Self {
12634        Self::DropDomain(d)
12635    }
12636}
12637
12638impl From<ShowCharset> for Statement {
12639    fn from(s: ShowCharset) -> Self {
12640        Self::ShowCharset(s)
12641    }
12642}
12643
12644impl From<ShowObjects> for Statement {
12645    fn from(s: ShowObjects) -> Self {
12646        Self::ShowObjects(s)
12647    }
12648}
12649
12650impl From<Use> for Statement {
12651    fn from(u: Use) -> Self {
12652        Self::Use(u)
12653    }
12654}
12655
12656impl From<CreateFunction> for Statement {
12657    fn from(c: CreateFunction) -> Self {
12658        Self::CreateFunction(c)
12659    }
12660}
12661
12662impl From<CreateTrigger> for Statement {
12663    fn from(c: CreateTrigger) -> Self {
12664        Self::CreateTrigger(c)
12665    }
12666}
12667
12668impl From<DropTrigger> for Statement {
12669    fn from(d: DropTrigger) -> Self {
12670        Self::DropTrigger(d)
12671    }
12672}
12673
12674impl From<DropOperator> for Statement {
12675    fn from(d: DropOperator) -> Self {
12676        Self::DropOperator(d)
12677    }
12678}
12679
12680impl From<DropOperatorFamily> for Statement {
12681    fn from(d: DropOperatorFamily) -> Self {
12682        Self::DropOperatorFamily(d)
12683    }
12684}
12685
12686impl From<DropOperatorClass> for Statement {
12687    fn from(d: DropOperatorClass) -> Self {
12688        Self::DropOperatorClass(d)
12689    }
12690}
12691
12692impl From<DenyStatement> for Statement {
12693    fn from(d: DenyStatement) -> Self {
12694        Self::Deny(d)
12695    }
12696}
12697
12698impl From<CreateDomain> for Statement {
12699    fn from(c: CreateDomain) -> Self {
12700        Self::CreateDomain(c)
12701    }
12702}
12703
12704impl From<RenameTable> for Statement {
12705    fn from(r: RenameTable) -> Self {
12706        vec![r].into()
12707    }
12708}
12709
12710impl From<Vec<RenameTable>> for Statement {
12711    fn from(r: Vec<RenameTable>) -> Self {
12712        Self::RenameTable(r)
12713    }
12714}
12715
12716impl From<PrintStatement> for Statement {
12717    fn from(p: PrintStatement) -> Self {
12718        Self::Print(p)
12719    }
12720}
12721
12722impl From<ReturnStatement> for Statement {
12723    fn from(r: ReturnStatement) -> Self {
12724        Self::Return(r)
12725    }
12726}
12727
12728impl From<ExportData> for Statement {
12729    fn from(e: ExportData) -> Self {
12730        Self::ExportData(e)
12731    }
12732}
12733
12734impl From<CreateUser> for Statement {
12735    fn from(c: CreateUser) -> Self {
12736        Self::CreateUser(c)
12737    }
12738}
12739
12740impl From<CreateWarehouse> for Statement {
12741    fn from(c: CreateWarehouse) -> Self {
12742        Self::CreateWarehouse(c)
12743    }
12744}
12745
12746impl From<VacuumStatement> for Statement {
12747    fn from(v: VacuumStatement) -> Self {
12748        Self::Vacuum(v)
12749    }
12750}
12751
12752impl From<ResetStatement> for Statement {
12753    fn from(r: ResetStatement) -> Self {
12754        Self::Reset(r)
12755    }
12756}
12757
12758#[cfg(test)]
12759mod tests {
12760    use crate::tokenizer::Location;
12761
12762    use super::*;
12763
12764    #[test]
12765    fn test_window_frame_default() {
12766        let window_frame = WindowFrame::default();
12767        assert_eq!(WindowFrameBound::Preceding(None), window_frame.start_bound);
12768    }
12769
12770    #[test]
12771    fn test_grouping_sets_display() {
12772        // a and b in different group
12773        let grouping_sets = Expr::GroupingSets(vec![
12774            vec![Expr::Identifier(Ident::new("a"))],
12775            vec![Expr::Identifier(Ident::new("b"))],
12776        ]);
12777        assert_eq!("GROUPING SETS ((a), (b))", format!("{grouping_sets}"));
12778
12779        // a and b in the same group
12780        let grouping_sets = Expr::GroupingSets(vec![vec![
12781            Expr::Identifier(Ident::new("a")),
12782            Expr::Identifier(Ident::new("b")),
12783        ]]);
12784        assert_eq!("GROUPING SETS ((a, b))", format!("{grouping_sets}"));
12785
12786        // (a, b) and (c, d) in different group
12787        let grouping_sets = Expr::GroupingSets(vec![
12788            vec![
12789                Expr::Identifier(Ident::new("a")),
12790                Expr::Identifier(Ident::new("b")),
12791            ],
12792            vec![
12793                Expr::Identifier(Ident::new("c")),
12794                Expr::Identifier(Ident::new("d")),
12795            ],
12796        ]);
12797        assert_eq!("GROUPING SETS ((a, b), (c, d))", format!("{grouping_sets}"));
12798    }
12799
12800    #[test]
12801    fn test_rollup_display() {
12802        let rollup = Expr::Rollup(vec![vec![Expr::Identifier(Ident::new("a"))]]);
12803        assert_eq!("ROLLUP (a)", format!("{rollup}"));
12804
12805        let rollup = Expr::Rollup(vec![vec![
12806            Expr::Identifier(Ident::new("a")),
12807            Expr::Identifier(Ident::new("b")),
12808        ]]);
12809        assert_eq!("ROLLUP ((a, b))", format!("{rollup}"));
12810
12811        let rollup = Expr::Rollup(vec![
12812            vec![Expr::Identifier(Ident::new("a"))],
12813            vec![Expr::Identifier(Ident::new("b"))],
12814        ]);
12815        assert_eq!("ROLLUP (a, b)", format!("{rollup}"));
12816
12817        let rollup = Expr::Rollup(vec![
12818            vec![Expr::Identifier(Ident::new("a"))],
12819            vec![
12820                Expr::Identifier(Ident::new("b")),
12821                Expr::Identifier(Ident::new("c")),
12822            ],
12823            vec![Expr::Identifier(Ident::new("d"))],
12824        ]);
12825        assert_eq!("ROLLUP (a, (b, c), d)", format!("{rollup}"));
12826    }
12827
12828    #[test]
12829    fn test_cube_display() {
12830        let cube = Expr::Cube(vec![vec![Expr::Identifier(Ident::new("a"))]]);
12831        assert_eq!("CUBE (a)", format!("{cube}"));
12832
12833        let cube = Expr::Cube(vec![vec![
12834            Expr::Identifier(Ident::new("a")),
12835            Expr::Identifier(Ident::new("b")),
12836        ]]);
12837        assert_eq!("CUBE ((a, b))", format!("{cube}"));
12838
12839        let cube = Expr::Cube(vec![
12840            vec![Expr::Identifier(Ident::new("a"))],
12841            vec![Expr::Identifier(Ident::new("b"))],
12842        ]);
12843        assert_eq!("CUBE (a, b)", format!("{cube}"));
12844
12845        let cube = Expr::Cube(vec![
12846            vec![Expr::Identifier(Ident::new("a"))],
12847            vec![
12848                Expr::Identifier(Ident::new("b")),
12849                Expr::Identifier(Ident::new("c")),
12850            ],
12851            vec![Expr::Identifier(Ident::new("d"))],
12852        ]);
12853        assert_eq!("CUBE (a, (b, c), d)", format!("{cube}"));
12854    }
12855
12856    #[test]
12857    fn test_interval_display() {
12858        let interval = Expr::Interval(Interval {
12859            value: Box::new(Expr::Value(
12860                Value::SingleQuotedString(String::from("123:45.67")).with_empty_span(),
12861            )),
12862            leading_field: Some(DateTimeField::Minute),
12863            leading_precision: Some(10),
12864            last_field: Some(DateTimeField::Second),
12865            fractional_seconds_precision: Some(9),
12866        });
12867        assert_eq!(
12868            "INTERVAL '123:45.67' MINUTE (10) TO SECOND (9)",
12869            format!("{interval}"),
12870        );
12871
12872        let interval = Expr::Interval(Interval {
12873            value: Box::new(Expr::Value(
12874                Value::SingleQuotedString(String::from("5")).with_empty_span(),
12875            )),
12876            leading_field: Some(DateTimeField::Second),
12877            leading_precision: Some(1),
12878            last_field: None,
12879            fractional_seconds_precision: Some(3),
12880        });
12881        assert_eq!("INTERVAL '5' SECOND (1, 3)", format!("{interval}"));
12882    }
12883
12884    #[test]
12885    fn test_one_or_many_with_parens_deref() {
12886        use core::ops::Index;
12887
12888        let one = OneOrManyWithParens::One("a");
12889
12890        assert_eq!(one.deref(), &["a"]);
12891        assert_eq!(<OneOrManyWithParens<_> as Deref>::deref(&one), &["a"]);
12892
12893        assert_eq!(one[0], "a");
12894        assert_eq!(one.index(0), &"a");
12895        assert_eq!(
12896            <<OneOrManyWithParens<_> as Deref>::Target as Index<usize>>::index(&one, 0),
12897            &"a"
12898        );
12899
12900        assert_eq!(one.len(), 1);
12901        assert_eq!(<OneOrManyWithParens<_> as Deref>::Target::len(&one), 1);
12902
12903        let many1 = OneOrManyWithParens::Many(vec!["b"]);
12904
12905        assert_eq!(many1.deref(), &["b"]);
12906        assert_eq!(<OneOrManyWithParens<_> as Deref>::deref(&many1), &["b"]);
12907
12908        assert_eq!(many1[0], "b");
12909        assert_eq!(many1.index(0), &"b");
12910        assert_eq!(
12911            <<OneOrManyWithParens<_> as Deref>::Target as Index<usize>>::index(&many1, 0),
12912            &"b"
12913        );
12914
12915        assert_eq!(many1.len(), 1);
12916        assert_eq!(<OneOrManyWithParens<_> as Deref>::Target::len(&many1), 1);
12917
12918        let many2 = OneOrManyWithParens::Many(vec!["c", "d"]);
12919
12920        assert_eq!(many2.deref(), &["c", "d"]);
12921        assert_eq!(
12922            <OneOrManyWithParens<_> as Deref>::deref(&many2),
12923            &["c", "d"]
12924        );
12925
12926        assert_eq!(many2[0], "c");
12927        assert_eq!(many2.index(0), &"c");
12928        assert_eq!(
12929            <<OneOrManyWithParens<_> as Deref>::Target as Index<usize>>::index(&many2, 0),
12930            &"c"
12931        );
12932
12933        assert_eq!(many2[1], "d");
12934        assert_eq!(many2.index(1), &"d");
12935        assert_eq!(
12936            <<OneOrManyWithParens<_> as Deref>::Target as Index<usize>>::index(&many2, 1),
12937            &"d"
12938        );
12939
12940        assert_eq!(many2.len(), 2);
12941        assert_eq!(<OneOrManyWithParens<_> as Deref>::Target::len(&many2), 2);
12942    }
12943
12944    #[test]
12945    fn test_one_or_many_with_parens_as_ref() {
12946        let one = OneOrManyWithParens::One("a");
12947
12948        assert_eq!(one.as_ref(), &["a"]);
12949        assert_eq!(<OneOrManyWithParens<_> as AsRef<_>>::as_ref(&one), &["a"]);
12950
12951        let many1 = OneOrManyWithParens::Many(vec!["b"]);
12952
12953        assert_eq!(many1.as_ref(), &["b"]);
12954        assert_eq!(<OneOrManyWithParens<_> as AsRef<_>>::as_ref(&many1), &["b"]);
12955
12956        let many2 = OneOrManyWithParens::Many(vec!["c", "d"]);
12957
12958        assert_eq!(many2.as_ref(), &["c", "d"]);
12959        assert_eq!(
12960            <OneOrManyWithParens<_> as AsRef<_>>::as_ref(&many2),
12961            &["c", "d"]
12962        );
12963    }
12964
12965    #[test]
12966    fn test_one_or_many_with_parens_ref_into_iter() {
12967        let one = OneOrManyWithParens::One("a");
12968
12969        assert_eq!(Vec::from_iter(&one), vec![&"a"]);
12970
12971        let many1 = OneOrManyWithParens::Many(vec!["b"]);
12972
12973        assert_eq!(Vec::from_iter(&many1), vec![&"b"]);
12974
12975        let many2 = OneOrManyWithParens::Many(vec!["c", "d"]);
12976
12977        assert_eq!(Vec::from_iter(&many2), vec![&"c", &"d"]);
12978    }
12979
12980    #[test]
12981    fn test_one_or_many_with_parens_value_into_iter() {
12982        use core::iter::once;
12983
12984        //tests that our iterator implemented methods behaves exactly as it's inner iterator, at every step up to n calls to next/next_back
12985        fn test_steps<I>(ours: OneOrManyWithParens<usize>, inner: I, n: usize)
12986        where
12987            I: IntoIterator<Item = usize, IntoIter: DoubleEndedIterator + Clone> + Clone,
12988        {
12989            fn checks<I>(ours: OneOrManyWithParensIntoIter<usize>, inner: I)
12990            where
12991                I: Iterator<Item = usize> + Clone + DoubleEndedIterator,
12992            {
12993                assert_eq!(ours.size_hint(), inner.size_hint());
12994                assert_eq!(ours.clone().count(), inner.clone().count());
12995
12996                assert_eq!(
12997                    ours.clone().fold(1, |a, v| a + v),
12998                    inner.clone().fold(1, |a, v| a + v)
12999                );
13000
13001                assert_eq!(Vec::from_iter(ours.clone()), Vec::from_iter(inner.clone()));
13002                assert_eq!(
13003                    Vec::from_iter(ours.clone().rev()),
13004                    Vec::from_iter(inner.clone().rev())
13005                );
13006            }
13007
13008            let mut ours_next = ours.clone().into_iter();
13009            let mut inner_next = inner.clone().into_iter();
13010
13011            for _ in 0..n {
13012                checks(ours_next.clone(), inner_next.clone());
13013
13014                assert_eq!(ours_next.next(), inner_next.next());
13015            }
13016
13017            let mut ours_next_back = ours.clone().into_iter();
13018            let mut inner_next_back = inner.clone().into_iter();
13019
13020            for _ in 0..n {
13021                checks(ours_next_back.clone(), inner_next_back.clone());
13022
13023                assert_eq!(ours_next_back.next_back(), inner_next_back.next_back());
13024            }
13025
13026            let mut ours_mixed = ours.clone().into_iter();
13027            let mut inner_mixed = inner.clone().into_iter();
13028
13029            for i in 0..n {
13030                checks(ours_mixed.clone(), inner_mixed.clone());
13031
13032                if i % 2 == 0 {
13033                    assert_eq!(ours_mixed.next_back(), inner_mixed.next_back());
13034                } else {
13035                    assert_eq!(ours_mixed.next(), inner_mixed.next());
13036                }
13037            }
13038
13039            let mut ours_mixed2 = ours.into_iter();
13040            let mut inner_mixed2 = inner.into_iter();
13041
13042            for i in 0..n {
13043                checks(ours_mixed2.clone(), inner_mixed2.clone());
13044
13045                if i % 2 == 0 {
13046                    assert_eq!(ours_mixed2.next(), inner_mixed2.next());
13047                } else {
13048                    assert_eq!(ours_mixed2.next_back(), inner_mixed2.next_back());
13049                }
13050            }
13051        }
13052
13053        test_steps(OneOrManyWithParens::One(1), once(1), 3);
13054        test_steps(OneOrManyWithParens::Many(vec![2]), vec![2], 3);
13055        test_steps(OneOrManyWithParens::Many(vec![3, 4]), vec![3, 4], 4);
13056    }
13057
13058    // Tests that the position in the code of an `Ident` does not affect its
13059    // ordering.
13060    #[test]
13061    fn test_ident_ord() {
13062        let mut a = Ident::with_span(Span::new(Location::new(1, 1), Location::new(1, 1)), "a");
13063        let mut b = Ident::with_span(Span::new(Location::new(2, 2), Location::new(2, 2)), "b");
13064
13065        assert!(a < b);
13066        std::mem::swap(&mut a.span, &mut b.span);
13067        assert!(a < b);
13068    }
13069}