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;
34use core::{
35    fmt::{self, Display},
36    hash,
37};
38
39#[cfg(feature = "serde")]
40use serde::{Deserialize, Serialize};
41
42#[cfg(feature = "visitor")]
43use sqlparser_derive::{Visit, VisitMut};
44
45use crate::{
46    display_utils::SpaceOrNewline,
47    tokenizer::{Span, Token},
48};
49use crate::{
50    display_utils::{Indent, NewLine},
51    keywords::Keyword,
52};
53
54pub use self::data_type::{
55    ArrayElemTypeDef, BinaryLength, CharLengthUnits, CharacterLength, DataType, EnumMember,
56    ExactNumberInfo, IntervalFields, StructBracketKind, TimezoneInfo,
57};
58pub use self::dcl::{
59    AlterRoleOperation, CreateRole, Grant, ResetConfig, Revoke, RoleOption, SecondaryRoles,
60    SetConfigValue, Use,
61};
62pub use self::ddl::{
63    Alignment, AlterCollation, AlterCollationOperation, AlterColumnOperation, AlterConnectorOwner,
64    AlterFunction, AlterFunctionAction, AlterFunctionKind, AlterFunctionOperation,
65    AlterIndexOperation, AlterOperator, AlterOperatorClass, AlterOperatorClassOperation,
66    AlterOperatorFamily, AlterOperatorFamilyOperation, AlterOperatorOperation, AlterPolicy,
67    AlterPolicyOperation, AlterSchema, AlterSchemaOperation, AlterTable, AlterTableAlgorithm,
68    AlterTableLock, AlterTableOperation, AlterTableType, AlterType, AlterTypeAddValue,
69    AlterTypeAddValuePosition, AlterTypeOperation, AlterTypeRename, AlterTypeRenameValue,
70    AggregateModifyKind, ClusteredBy, ColumnDef, ColumnOption, ColumnOptionDef, ColumnOptions,
71    ColumnPolicy, ColumnPolicyProperty, ConstraintCharacteristics, CreateAggregate,
72    CreateAggregateOption, CreateCollation, CreateCollationDefinition, CreateConnector,
73    CreateDomain, CreateExtension, CreateForeignDataWrapper, CreateForeignTable, CreateFunction,
74    CreateIndex, CreateOperator, CreateOperatorClass, CreateOperatorFamily, CreatePolicy,
75    CreatePolicyCommand, CreatePolicyType, CreateTable, CreateTextSearchConfiguration,
76    CreateTextSearchDictionary, CreateTextSearchParser, CreateTextSearchTemplate, CreateTrigger,
77    CreateView, Deduplicate, DeferrableInitial, DistStyle, DropBehavior, DropExtension,
78    DropFunction, DropOperator, DropOperatorClass, DropOperatorFamily, DropOperatorSignature,
79    DropPolicy, DropTrigger, FdwRoutineClause, ForValues, FunctionReturnType, GeneratedAs,
80    GeneratedExpressionMode, IdentityParameters, IdentityProperty, IdentityPropertyFormatKind,
81    IdentityPropertyKind, IdentityPropertyOrder, IndexColumn, IndexOption, IndexType,
82    KeyOrIndexDisplay, Msck, NullsDistinctOption, OperatorArgTypes, OperatorClassItem,
83    OperatorFamilyDropItem, OperatorFamilyItem, OperatorOption, OperatorPurpose, Owner, Partition,
84    PartitionBoundValue, ProcedureParam, ReferentialAction, RenameTableNameKind, ReplicaIdentity,
85    TagsColumnOption, TriggerObjectKind, Truncate, UserDefinedTypeCompositeAttributeDef,
86    UserDefinedTypeInternalLength, UserDefinedTypeRangeOption, UserDefinedTypeRepresentation,
87    UserDefinedTypeSqlDefinitionOption, UserDefinedTypeStorage, ViewColumnDef,
88};
89pub use self::dml::{
90    Delete, Insert, Merge, MergeAction, MergeClause, MergeClauseKind, MergeInsertExpr,
91    MergeInsertKind, MergeUpdateExpr, MultiTableInsertIntoClause, MultiTableInsertType,
92    MultiTableInsertValue, MultiTableInsertValues, MultiTableInsertWhenClause, OutputClause,
93    Update,
94};
95pub use self::operator::{BinaryOperator, UnaryOperator};
96pub use self::query::{
97    AfterMatchSkip, ConnectByKind, Cte, CteAsMaterialized, Distinct, EmptyMatchesMode,
98    ExceptSelectItem, ExcludeSelectItem, ExprWithAlias, ExprWithAliasAndOrderBy, Fetch, ForClause,
99    ForJson, ForXml, FormatClause, GroupByExpr, GroupByWithModifier, IdentWithAlias,
100    IlikeSelectItem, InputFormatClause, Interpolate, InterpolateExpr, Join, JoinConstraint,
101    JoinOperator, JsonTableColumn, JsonTableColumnErrorHandling, JsonTableNamedColumn,
102    JsonTableNestedColumn, LateralView, LimitClause, LockClause, LockType, MatchRecognizePattern,
103    MatchRecognizeSymbol, Measure, NamedWindowDefinition, NamedWindowExpr, NonBlock, Offset,
104    OffsetRows, OpenJsonTableColumn, OrderBy, OrderByExpr, OrderByKind, OrderByOptions,
105    PipeOperator, PivotValueSource, ProjectionSelect, Query, RenameSelectItem,
106    RepetitionQuantifier, ReplaceSelectElement, ReplaceSelectItem, RowsPerMatch, Select,
107    SelectFlavor, SelectInto, SelectItem, SelectItemQualifiedWildcardKind, SelectModifiers,
108    SetExpr, SetOperator, SetQuantifier, Setting, SymbolDefinition, Table, TableAlias,
109    TableAliasColumnDef, TableFactor, TableFunctionArgs, TableIndexHintForClause,
110    TableIndexHintType, TableIndexHints, TableIndexType, TableSample, TableSampleBucket,
111    TableSampleKind, TableSampleMethod, TableSampleModifier, TableSampleQuantity, TableSampleSeed,
112    TableSampleSeedModifier, TableSampleUnit, TableVersion, TableWithJoins, Top, TopQuantity,
113    UpdateTableFromKind, ValueTableMode, Values, WildcardAdditionalOptions, With, WithFill,
114    XmlNamespaceDefinition, XmlPassingArgument, XmlPassingClause, XmlTableColumn,
115    XmlTableColumnOption,
116};
117
118pub use self::trigger::{
119    TriggerEvent, TriggerExecBody, TriggerExecBodyType, TriggerObject, TriggerPeriod,
120    TriggerReferencing, TriggerReferencingType,
121};
122
123pub use self::value::{
124    escape_double_quote_string, escape_quoted_string, DateTimeField, DollarQuotedString,
125    NormalizationForm, QuoteDelimitedString, TrimWhereField, Value, ValueWithSpan,
126};
127
128use crate::ast::helpers::key_value_options::KeyValueOptions;
129use crate::ast::helpers::stmt_data_loading::StageParamsObject;
130
131#[cfg(feature = "visitor")]
132pub use visitor::*;
133
134pub use self::data_type::GeometricTypeKind;
135
136mod data_type;
137mod dcl;
138mod ddl;
139mod dml;
140/// Helper modules for building and manipulating AST nodes.
141pub mod helpers;
142pub mod table_constraints;
143pub use table_constraints::{
144    CheckConstraint, ConstraintUsingIndex, ExclusionConstraint, ExclusionElement,
145    ForeignKeyConstraint, FullTextOrSpatialConstraint, IndexConstraint, PrimaryKeyConstraint,
146    TableConstraint, UniqueConstraint,
147};
148mod operator;
149mod query;
150mod spans;
151pub use spans::Spanned;
152
153pub mod comments;
154mod trigger;
155mod value;
156
157#[cfg(feature = "visitor")]
158mod visitor;
159
160/// Helper used to format a slice using a separator string (e.g., `", "`).
161pub struct DisplaySeparated<'a, T>
162where
163    T: fmt::Display,
164{
165    slice: &'a [T],
166    sep: &'static str,
167}
168
169impl<T> fmt::Display for DisplaySeparated<'_, T>
170where
171    T: fmt::Display,
172{
173    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
174        let mut delim = "";
175        for t in self.slice {
176            f.write_str(delim)?;
177            delim = self.sep;
178            t.fmt(f)?;
179        }
180        Ok(())
181    }
182}
183
184pub(crate) fn display_separated<'a, T>(slice: &'a [T], sep: &'static str) -> DisplaySeparated<'a, T>
185where
186    T: fmt::Display,
187{
188    DisplaySeparated { slice, sep }
189}
190
191pub(crate) fn display_comma_separated<T>(slice: &[T]) -> DisplaySeparated<'_, T>
192where
193    T: fmt::Display,
194{
195    DisplaySeparated { slice, sep: ", " }
196}
197
198/// Writes the given statements to the formatter, each ending with
199/// a semicolon and space separated.
200fn format_statement_list(f: &mut fmt::Formatter, statements: &[Statement]) -> fmt::Result {
201    write!(f, "{}", display_separated(statements, "; "))?;
202    // We manually insert semicolon for the last statement,
203    // since display_separated doesn't handle that case.
204    write!(f, ";")
205}
206
207/// An identifier, decomposed into its value or character data and the quote style.
208#[derive(Debug, Clone)]
209#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
210#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
211pub struct Ident {
212    /// The value of the identifier without quotes.
213    pub value: String,
214    /// The starting quote if any. Valid quote characters are the single quote,
215    /// double quote, backtick, and opening square bracket.
216    pub quote_style: Option<char>,
217    /// The span of the identifier in the original SQL string.
218    pub span: Span,
219}
220
221impl PartialEq for Ident {
222    fn eq(&self, other: &Self) -> bool {
223        let Ident {
224            value,
225            quote_style,
226            // exhaustiveness check; we ignore spans in comparisons
227            span: _,
228        } = self;
229
230        value == &other.value && quote_style == &other.quote_style
231    }
232}
233
234impl core::hash::Hash for Ident {
235    fn hash<H: hash::Hasher>(&self, state: &mut H) {
236        let Ident {
237            value,
238            quote_style,
239            // exhaustiveness check; we ignore spans in hashes
240            span: _,
241        } = self;
242
243        value.hash(state);
244        quote_style.hash(state);
245    }
246}
247
248impl Eq for Ident {}
249
250impl PartialOrd for Ident {
251    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
252        Some(self.cmp(other))
253    }
254}
255
256impl Ord for Ident {
257    fn cmp(&self, other: &Self) -> Ordering {
258        let Ident {
259            value,
260            quote_style,
261            // exhaustiveness check; we ignore spans in ordering
262            span: _,
263        } = self;
264
265        let Ident {
266            value: other_value,
267            quote_style: other_quote_style,
268            // exhaustiveness check; we ignore spans in ordering
269            span: _,
270        } = other;
271
272        // First compare by value, then by quote_style
273        value
274            .cmp(other_value)
275            .then_with(|| quote_style.cmp(other_quote_style))
276    }
277}
278
279impl Ident {
280    /// Create a new identifier with the given value and no quotes and an empty span.
281    pub fn new<S>(value: S) -> Self
282    where
283        S: Into<String>,
284    {
285        Ident {
286            value: value.into(),
287            quote_style: None,
288            span: Span::empty(),
289        }
290    }
291
292    /// Create a new quoted identifier with the given quote and value. This function
293    /// panics if the given quote is not a valid quote character.
294    pub fn with_quote<S>(quote: char, value: S) -> Self
295    where
296        S: Into<String>,
297    {
298        assert!(quote == '\'' || quote == '"' || quote == '`' || quote == '[');
299        Ident {
300            value: value.into(),
301            quote_style: Some(quote),
302            span: Span::empty(),
303        }
304    }
305
306    /// Create an `Ident` with the given `span` and `value` (unquoted).
307    pub fn with_span<S>(span: Span, value: S) -> Self
308    where
309        S: Into<String>,
310    {
311        Ident {
312            value: value.into(),
313            quote_style: None,
314            span,
315        }
316    }
317
318    /// Create a quoted `Ident` with the given `quote` and `span`.
319    pub fn with_quote_and_span<S>(quote: char, span: Span, value: S) -> Self
320    where
321        S: Into<String>,
322    {
323        assert!(quote == '\'' || quote == '"' || quote == '`' || quote == '[');
324        Ident {
325            value: value.into(),
326            quote_style: Some(quote),
327            span,
328        }
329    }
330}
331
332impl From<&str> for Ident {
333    fn from(value: &str) -> Self {
334        Ident {
335            value: value.to_string(),
336            quote_style: None,
337            span: Span::empty(),
338        }
339    }
340}
341
342impl fmt::Display for Ident {
343    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
344        match self.quote_style {
345            Some(q) if q == '"' || q == '\'' || q == '`' => {
346                let escaped = value::escape_quoted_string(&self.value, q);
347                write!(f, "{q}{escaped}{q}")
348            }
349            Some('[') => write!(f, "[{}]", self.value),
350            None => f.write_str(&self.value),
351            _ => panic!("unexpected quote style"),
352        }
353    }
354}
355
356/// A name of a table, view, custom type, etc., possibly multi-part, i.e. db.schema.obj
357#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
358#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
359#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
360pub struct ObjectName(pub Vec<ObjectNamePart>);
361
362impl From<Vec<Ident>> for ObjectName {
363    fn from(idents: Vec<Ident>) -> Self {
364        ObjectName(idents.into_iter().map(ObjectNamePart::Identifier).collect())
365    }
366}
367
368impl From<Ident> for ObjectName {
369    fn from(ident: Ident) -> Self {
370        ObjectName(vec![ObjectNamePart::Identifier(ident)])
371    }
372}
373
374impl fmt::Display for ObjectName {
375    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
376        write!(f, "{}", display_separated(&self.0, "."))
377    }
378}
379
380/// A single part of an ObjectName
381#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
382#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
383#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
384pub enum ObjectNamePart {
385    /// A single identifier part, e.g. `schema` or `table`.
386    Identifier(Ident),
387    /// A function that returns an identifier (dialect-specific).
388    Function(ObjectNamePartFunction),
389}
390
391impl ObjectNamePart {
392    /// Return the identifier if this is an `Identifier` variant.
393    pub fn as_ident(&self) -> Option<&Ident> {
394        match self {
395            ObjectNamePart::Identifier(ident) => Some(ident),
396            ObjectNamePart::Function(_) => None,
397        }
398    }
399}
400
401impl fmt::Display for ObjectNamePart {
402    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
403        match self {
404            ObjectNamePart::Identifier(ident) => write!(f, "{ident}"),
405            ObjectNamePart::Function(func) => write!(f, "{func}"),
406        }
407    }
408}
409
410/// An object name part that consists of a function that dynamically
411/// constructs identifiers.
412///
413/// - [Snowflake](https://docs.snowflake.com/en/sql-reference/identifier-literal)
414#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
415#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
416#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
417pub struct ObjectNamePartFunction {
418    /// The function name that produces the object name part.
419    pub name: Ident,
420    /// Function arguments used to compute the identifier.
421    pub args: Vec<FunctionArg>,
422}
423
424impl fmt::Display for ObjectNamePartFunction {
425    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
426        write!(f, "{}(", self.name)?;
427        write!(f, "{})", display_comma_separated(&self.args))
428    }
429}
430
431/// Represents an Array Expression, either
432/// `ARRAY[..]`, or `[..]`
433#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
434#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
435#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
436pub struct Array {
437    /// The list of expressions between brackets
438    pub elem: Vec<Expr>,
439
440    /// `true` for  `ARRAY[..]`, `false` for `[..]`
441    pub named: bool,
442}
443
444impl fmt::Display for Array {
445    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
446        write!(
447            f,
448            "{}[{}]",
449            if self.named { "ARRAY" } else { "" },
450            display_comma_separated(&self.elem)
451        )
452    }
453}
454
455/// Represents an INTERVAL expression, roughly in the following format:
456/// `INTERVAL '<value>' [ <leading_field> [ (<leading_precision>) ] ]
457/// [ TO <last_field> [ (<fractional_seconds_precision>) ] ]`,
458/// e.g. `INTERVAL '123:45.67' MINUTE(3) TO SECOND(2)`.
459///
460/// The parser does not validate the `<value>`, nor does it ensure
461/// that the `<leading_field>` units >= the units in `<last_field>`,
462/// so the user will have to reject intervals like `HOUR TO YEAR`.
463#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
464#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
465#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
466pub struct Interval {
467    /// The interval value expression (commonly a string literal).
468    pub value: Box<Expr>,
469    /// Optional leading time unit (e.g., `HOUR`, `MINUTE`).
470    pub leading_field: Option<DateTimeField>,
471    /// Optional leading precision for the leading field.
472    pub leading_precision: Option<u64>,
473    /// Optional trailing time unit for a range (e.g., `SECOND`).
474    pub last_field: Option<DateTimeField>,
475    /// The fractional seconds precision, when specified.
476    ///
477    /// See SQL `SECOND(n)` or `SECOND(m, n)` forms.
478    pub fractional_seconds_precision: Option<u64>,
479}
480
481impl fmt::Display for Interval {
482    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
483        let value = self.value.as_ref();
484        match (
485            &self.leading_field,
486            self.leading_precision,
487            self.fractional_seconds_precision,
488        ) {
489            (
490                Some(DateTimeField::Second),
491                Some(leading_precision),
492                Some(fractional_seconds_precision),
493            ) => {
494                // When the leading field is SECOND, the parser guarantees that
495                // the last field is None.
496                assert!(self.last_field.is_none());
497                write!(
498                    f,
499                    "INTERVAL {value} SECOND ({leading_precision}, {fractional_seconds_precision})"
500                )
501            }
502            _ => {
503                write!(f, "INTERVAL {value}")?;
504                if let Some(leading_field) = &self.leading_field {
505                    write!(f, " {leading_field}")?;
506                }
507                if let Some(leading_precision) = self.leading_precision {
508                    write!(f, " ({leading_precision})")?;
509                }
510                if let Some(last_field) = &self.last_field {
511                    write!(f, " TO {last_field}")?;
512                }
513                if let Some(fractional_seconds_precision) = self.fractional_seconds_precision {
514                    write!(f, " ({fractional_seconds_precision})")?;
515                }
516                Ok(())
517            }
518        }
519    }
520}
521
522/// A field definition within a struct
523///
524/// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-types#struct_type
525#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
526#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
527#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
528pub struct StructField {
529    /// Optional name of the struct field.
530    pub field_name: Option<Ident>,
531    /// The field data type.
532    pub field_type: DataType,
533    /// Struct field options (e.g., `OPTIONS(...)` on BigQuery).
534    /// See [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#column_name_and_column_schema)
535    pub options: Option<Vec<SqlOption>>,
536}
537
538impl fmt::Display for StructField {
539    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
540        if let Some(name) = &self.field_name {
541            write!(f, "{name} {}", self.field_type)?;
542        } else {
543            write!(f, "{}", self.field_type)?;
544        }
545        if let Some(options) = &self.options {
546            write!(f, " OPTIONS({})", display_separated(options, ", "))
547        } else {
548            Ok(())
549        }
550    }
551}
552
553/// A field definition within a union
554///
555/// [DuckDB]: https://duckdb.org/docs/sql/data_types/union.html
556#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
557#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
558#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
559pub struct UnionField {
560    /// Name of the union field.
561    pub field_name: Ident,
562    /// Type of the union field.
563    pub field_type: DataType,
564}
565
566impl fmt::Display for UnionField {
567    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
568        write!(f, "{} {}", self.field_name, self.field_type)
569    }
570}
571
572/// A dictionary field within a dictionary.
573///
574/// [DuckDB]: https://duckdb.org/docs/sql/data_types/struct#creating-structs
575#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
576#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
577#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
578pub struct DictionaryField {
579    /// Dictionary key identifier.
580    pub key: Ident,
581    /// Value expression for the dictionary entry.
582    pub value: Box<Expr>,
583}
584
585impl fmt::Display for DictionaryField {
586    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
587        write!(f, "{}: {}", self.key, self.value)
588    }
589}
590
591/// Represents a Map expression.
592#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
593#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
594#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
595pub struct Map {
596    /// Entries of the map as key/value pairs.
597    pub entries: Vec<MapEntry>,
598}
599
600impl Display for Map {
601    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
602        write!(f, "MAP {{{}}}", display_comma_separated(&self.entries))
603    }
604}
605
606/// A map field within a map.
607///
608/// [DuckDB]: https://duckdb.org/docs/sql/data_types/map.html#creating-maps
609#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
610#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
611#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
612pub struct MapEntry {
613    /// Key expression of the map entry.
614    pub key: Box<Expr>,
615    /// Value expression of the map entry.
616    pub value: Box<Expr>,
617}
618
619impl fmt::Display for MapEntry {
620    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
621        write!(f, "{}: {}", self.key, self.value)
622    }
623}
624
625/// Options for `CAST` / `TRY_CAST`
626/// BigQuery: <https://cloud.google.com/bigquery/docs/reference/standard-sql/format-elements#formatting_syntax>
627#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
628#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
629#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
630pub enum CastFormat {
631    /// A simple cast format specified by a `Value`.
632    Value(ValueWithSpan),
633    /// A cast format with an explicit time zone: `(format, timezone)`.
634    ValueAtTimeZone(ValueWithSpan, ValueWithSpan),
635}
636
637/// An element of a JSON path.
638#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
639#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
640#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
641pub enum JsonPathElem {
642    /// Accesses an object field using dot notation, e.g. `obj:foo.bar.baz`.
643    ///
644    /// See <https://docs.snowflake.com/en/user-guide/querying-semistructured#dot-notation>.
645    Dot {
646        /// The object key text (without quotes).
647        key: String,
648        /// `true` when the key was quoted in the source.
649        quoted: bool,
650    },
651    /// Accesses an object field or array element using bracket notation,
652    /// e.g. `obj['foo']`.
653    ///
654    /// See <https://docs.snowflake.com/en/user-guide/querying-semistructured#bracket-notation>.
655    Bracket {
656        /// The expression used as the bracket key (string or numeric expression).
657        key: Expr,
658    },
659    /// Access an object field using colon bracket notation
660    /// e.g. `obj:['foo']`
661    ///
662    /// See <https://docs.databricks.com/en/sql/language-manual/functions/colonsign.html>
663    ColonBracket {
664        /// The expression used as the bracket key (string or numeric expression).
665        key: Expr,
666    },
667}
668
669/// A JSON path.
670///
671/// See <https://docs.snowflake.com/en/user-guide/querying-semistructured>.
672/// See <https://docs.databricks.com/en/sql/language-manual/sql-ref-json-path-expression.html>.
673#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
674#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
675#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
676pub struct JsonPath {
677    /// Sequence of path elements that form the JSON path.
678    pub path: Vec<JsonPathElem>,
679}
680
681impl fmt::Display for JsonPath {
682    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
683        for (i, elem) in self.path.iter().enumerate() {
684            match elem {
685                JsonPathElem::Dot { key, quoted } => {
686                    if i == 0 {
687                        write!(f, ":")?;
688                    } else {
689                        write!(f, ".")?;
690                    }
691
692                    if *quoted {
693                        write!(f, "\"{}\"", escape_double_quote_string(key))?;
694                    } else {
695                        write!(f, "{key}")?;
696                    }
697                }
698                JsonPathElem::Bracket { key } => {
699                    write!(f, "[{key}]")?;
700                }
701                JsonPathElem::ColonBracket { key } => {
702                    write!(f, ":[{key}]")?;
703                }
704            }
705        }
706        Ok(())
707    }
708}
709
710/// The syntax used for in a cast expression.
711#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
712#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
713#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
714pub enum CastKind {
715    /// The standard SQL cast syntax, e.g. `CAST(<expr> as <datatype>)`
716    Cast,
717    /// A cast that returns `NULL` on failure, e.g. `TRY_CAST(<expr> as <datatype>)`.
718    ///
719    /// See <https://docs.snowflake.com/en/sql-reference/functions/try_cast>.
720    /// See <https://learn.microsoft.com/en-us/sql/t-sql/functions/try-cast-transact-sql>.
721    TryCast,
722    /// A cast that returns `NULL` on failure, bigQuery-specific ,  e.g. `SAFE_CAST(<expr> as <datatype>)`.
723    ///
724    /// See <https://cloud.google.com/bigquery/docs/reference/standard-sql/functions-and-operators#safe_casting>.
725    SafeCast,
726    /// `<expr> :: <datatype>`
727    DoubleColon,
728}
729
730/// `MATCH` type for constraint references
731///
732/// See: <https://www.postgresql.org/docs/current/sql-createtable.html#SQL-CREATETABLE-PARMS-REFERENCES>
733#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
734#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
735#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
736pub enum ConstraintReferenceMatchKind {
737    /// `MATCH FULL`
738    Full,
739    /// `MATCH PARTIAL`
740    Partial,
741    /// `MATCH SIMPLE`
742    Simple,
743}
744
745impl fmt::Display for ConstraintReferenceMatchKind {
746    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
747        match self {
748            Self::Full => write!(f, "MATCH FULL"),
749            Self::Partial => write!(f, "MATCH PARTIAL"),
750            Self::Simple => write!(f, "MATCH SIMPLE"),
751        }
752    }
753}
754
755/// `EXTRACT` syntax variants.
756///
757/// In Snowflake dialect, the `EXTRACT` expression can support either the `from` syntax
758/// or the comma syntax.
759///
760/// See <https://docs.snowflake.com/en/sql-reference/functions/extract>
761#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
762#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
763#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
764pub enum ExtractSyntax {
765    /// `EXTRACT( <date_or_time_part> FROM <date_or_time_expr> )`
766    From,
767    /// `EXTRACT( <date_or_time_part> , <date_or_timestamp_expr> )`
768    Comma,
769}
770
771/// The syntax used in a CEIL or FLOOR expression.
772///
773/// The `CEIL/FLOOR(<datetime value expression> TO <time unit>)` is an Amazon Kinesis Data Analytics extension.
774/// See <https://docs.aws.amazon.com/kinesisanalytics/latest/sqlref/sql-reference-ceil.html> for
775/// details.
776///
777/// Other dialects either support `CEIL/FLOOR( <expr> [, <scale>])` format or just
778/// `CEIL/FLOOR(<expr>)`.
779#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
780#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
781#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
782pub enum CeilFloorKind {
783    /// `CEIL( <expr> TO <DateTimeField>)`
784    DateTimeField(DateTimeField),
785    /// `CEIL( <expr> [, <scale>])`
786    Scale(ValueWithSpan),
787}
788
789/// A WHEN clause in a CASE expression containing both
790/// the condition and its corresponding result
791#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
792#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
793#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
794pub struct CaseWhen {
795    /// The `WHEN` condition expression.
796    pub condition: Expr,
797    /// The expression returned when `condition` matches.
798    pub result: Expr,
799}
800
801impl fmt::Display for CaseWhen {
802    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
803        f.write_str("WHEN ")?;
804        self.condition.fmt(f)?;
805        f.write_str(" THEN")?;
806        SpaceOrNewline.fmt(f)?;
807        Indent(&self.result).fmt(f)?;
808        Ok(())
809    }
810}
811
812/// An SQL expression of any type.
813///
814/// # Semantics / Type Checking
815///
816/// The parser does not distinguish between expressions of different types
817/// (e.g. boolean vs string). The caller is responsible for detecting and
818/// validating types as necessary (for example  `WHERE 1` vs `SELECT 1=1`)
819/// See the [README.md] for more details.
820///
821/// [README.md]: https://github.com/apache/datafusion-sqlparser-rs/blob/main/README.md#syntax-vs-semantics
822///
823/// # Equality and Hashing Does not Include Source Locations
824///
825/// The `Expr` type implements `PartialEq` and `Eq` based on the semantic value
826/// of the expression (not bitwise comparison). This means that `Expr` instances
827/// that are semantically equivalent but have different spans (locations in the
828/// source tree) will compare as equal.
829#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
830#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
831#[cfg_attr(
832    feature = "visitor",
833    derive(Visit, VisitMut),
834    visit(with = "visit_expr")
835)]
836pub enum Expr {
837    /// Identifier e.g. table name or column name
838    Identifier(Ident),
839    /// Multi-part identifier, e.g. `table_alias.column` or `schema.table.col`
840    CompoundIdentifier(Vec<Ident>),
841    /// Multi-part expression access.
842    ///
843    /// This structure represents an access chain in structured / nested types
844    /// such as maps, arrays, and lists:
845    /// - Array
846    ///     - A 1-dim array `a[1]` will be represented like:
847    ///       `CompoundFieldAccess(Ident('a'), vec![Subscript(1)]`
848    ///     - A 2-dim array `a[1][2]` will be represented like:
849    ///       `CompoundFieldAccess(Ident('a'), vec![Subscript(1), Subscript(2)]`
850    /// - Map or Struct (Bracket-style)
851    ///     - A map `a['field1']` will be represented like:
852    ///       `CompoundFieldAccess(Ident('a'), vec![Subscript('field')]`
853    ///     - A 2-dim map `a['field1']['field2']` will be represented like:
854    ///       `CompoundFieldAccess(Ident('a'), vec![Subscript('field1'), Subscript('field2')]`
855    /// - Struct (Dot-style) (only effect when the chain contains both subscript and expr)
856    ///     - A struct access `a[field1].field2` will be represented like:
857    ///       `CompoundFieldAccess(Ident('a'), vec![Subscript('field1'), Ident('field2')]`
858    /// - If a struct access likes `a.field1.field2`, it will be represented by CompoundIdentifier([a, field1, field2])
859    CompoundFieldAccess {
860        /// The base expression being accessed.
861        root: Box<Expr>,
862        /// Sequence of access operations (subscript or identifier accesses).
863        access_chain: Vec<AccessExpr>,
864    },
865    /// Access data nested in a value containing semi-structured data, such as
866    /// the `VARIANT` type on Snowflake. for example `src:customer[0].name`.
867    ///
868    /// See <https://docs.snowflake.com/en/user-guide/querying-semistructured>.
869    /// See <https://docs.databricks.com/en/sql/language-manual/functions/colonsign.html>.
870    JsonAccess {
871        /// The value being queried.
872        value: Box<Expr>,
873        /// The path to the data to extract.
874        path: JsonPath,
875    },
876    /// `IS FALSE` operator
877    IsFalse(Box<Expr>),
878    /// `IS NOT FALSE` operator
879    IsNotFalse(Box<Expr>),
880    /// `IS TRUE` operator
881    IsTrue(Box<Expr>),
882    /// `IS NOT TRUE` operator
883    IsNotTrue(Box<Expr>),
884    /// `IS NULL` operator
885    IsNull(Box<Expr>),
886    /// `IS NOT NULL` operator
887    IsNotNull(Box<Expr>),
888    /// `IS UNKNOWN` operator
889    IsUnknown(Box<Expr>),
890    /// `IS NOT UNKNOWN` operator
891    IsNotUnknown(Box<Expr>),
892    /// `IS DISTINCT FROM` operator
893    IsDistinctFrom(Box<Expr>, Box<Expr>),
894    /// `IS NOT DISTINCT FROM` operator
895    IsNotDistinctFrom(Box<Expr>, Box<Expr>),
896    /// `<expr> IS [ NOT ] [ form ] NORMALIZED`
897    IsNormalized {
898        /// Expression being tested.
899        expr: Box<Expr>,
900        /// Optional normalization `form` (e.g., NFC, NFD).
901        form: Option<NormalizationForm>,
902        /// `true` when `NOT` is present.
903        negated: bool,
904    },
905    /// `[ NOT ] IN (val1, val2, ...)`
906    InList {
907        /// Left-hand expression to test for membership.
908        expr: Box<Expr>,
909        /// Literal list of expressions to check against.
910        list: Vec<Expr>,
911        /// `true` when the `NOT` modifier is present.
912        negated: bool,
913    },
914    /// `[ NOT ] IN (SELECT ...)`
915    InSubquery {
916        /// Left-hand expression to test for membership.
917        expr: Box<Expr>,
918        /// The subquery providing the candidate values.
919        subquery: Box<Query>,
920        /// `true` when the `NOT` modifier is present.
921        negated: bool,
922    },
923    /// `[ NOT ] IN UNNEST(array_expression)`
924    InUnnest {
925        /// Left-hand expression to test for membership.
926        expr: Box<Expr>,
927        /// Array expression being unnested.
928        array_expr: Box<Expr>,
929        /// `true` when the `NOT` modifier is present.
930        negated: bool,
931    },
932    /// `<expr> [ NOT ] BETWEEN <low> AND <high>`
933    Between {
934        /// Expression being compared.
935        expr: Box<Expr>,
936        /// `true` when the `NOT` modifier is present.
937        negated: bool,
938        /// Lower bound.
939        low: Box<Expr>,
940        /// Upper bound.
941        high: Box<Expr>,
942    },
943    /// Binary operation e.g. `1 + 1` or `foo > bar`
944    BinaryOp {
945        /// Left operand.
946        left: Box<Expr>,
947        /// Operator between operands.
948        op: BinaryOperator,
949        /// Right operand.
950        right: Box<Expr>,
951    },
952    /// `[NOT] LIKE <pattern> [ESCAPE <escape_character>]`
953    Like {
954        /// `true` when `NOT` is present.
955        negated: bool,
956        /// Snowflake supports the ANY keyword to match against a list of patterns
957        /// <https://docs.snowflake.com/en/sql-reference/functions/like_any>
958        any: bool,
959        /// Expression to match.
960        expr: Box<Expr>,
961        /// Pattern expression.
962        pattern: Box<Expr>,
963        /// Optional escape character.
964        escape_char: Option<ValueWithSpan>,
965    },
966    /// `ILIKE` (case-insensitive `LIKE`)
967    ILike {
968        /// `true` when `NOT` is present.
969        negated: bool,
970        /// Snowflake supports the ANY keyword to match against a list of patterns
971        /// <https://docs.snowflake.com/en/sql-reference/functions/like_any>
972        any: bool,
973        /// Expression to match.
974        expr: Box<Expr>,
975        /// Pattern expression.
976        pattern: Box<Expr>,
977        /// Optional escape character.
978        escape_char: Option<ValueWithSpan>,
979    },
980    /// `SIMILAR TO` regex
981    SimilarTo {
982        /// `true` when `NOT` is present.
983        negated: bool,
984        /// Expression to test.
985        expr: Box<Expr>,
986        /// Pattern expression.
987        pattern: Box<Expr>,
988        /// Optional escape character.
989        escape_char: Option<ValueWithSpan>,
990    },
991    /// MySQL: `RLIKE` regex or `REGEXP` regex
992    RLike {
993        /// `true` when `NOT` is present.
994        negated: bool,
995        /// Expression to test.
996        expr: Box<Expr>,
997        /// Pattern expression.
998        pattern: Box<Expr>,
999        /// true for REGEXP, false for RLIKE (no difference in semantics)
1000        regexp: bool,
1001    },
1002    /// `ANY` operation e.g. `foo > ANY(bar)`, comparison operator is one of `[=, >, <, =>, =<, !=]`
1003    /// <https://docs.snowflake.com/en/sql-reference/operators-subquery#all-any>
1004    AnyOp {
1005        /// Left operand.
1006        left: Box<Expr>,
1007        /// Comparison operator.
1008        compare_op: BinaryOperator,
1009        /// Right-hand subquery expression.
1010        right: Box<Expr>,
1011        /// ANY and SOME are synonymous: <https://docs.cloudera.com/cdw-runtime/cloud/using-hiveql/topics/hive_comparison_predicates.html>
1012        is_some: bool,
1013    },
1014    /// `ALL` operation e.g. `foo > ALL(bar)`, comparison operator is one of `[=, >, <, =>, =<, !=]`
1015    /// <https://docs.snowflake.com/en/sql-reference/operators-subquery#all-any>
1016    AllOp {
1017        /// Left operand.
1018        left: Box<Expr>,
1019        /// Comparison operator.
1020        compare_op: BinaryOperator,
1021        /// Right-hand subquery expression.
1022        right: Box<Expr>,
1023    },
1024
1025    /// Unary operation e.g. `NOT foo`
1026    UnaryOp {
1027        /// The unary operator (e.g., `NOT`, `-`).
1028        op: UnaryOperator,
1029        /// Operand expression.
1030        expr: Box<Expr>,
1031    },
1032    /// CONVERT a value to a different data type or character encoding. e.g. `CONVERT(foo USING utf8mb4)`
1033    Convert {
1034        /// CONVERT (false) or TRY_CONVERT (true)
1035        /// <https://learn.microsoft.com/en-us/sql/t-sql/functions/try-convert-transact-sql?view=sql-server-ver16>
1036        is_try: bool,
1037        /// The expression to convert.
1038        expr: Box<Expr>,
1039        /// The target data type, if provided.
1040        data_type: Option<DataType>,
1041        /// Optional target character encoding (e.g., `utf8mb4`).
1042        charset: Option<ObjectName>,
1043        /// `true` when target precedes the value (MSSQL syntax).
1044        target_before_value: bool,
1045        /// How to translate the expression.
1046        ///
1047        /// [MSSQL]: https://learn.microsoft.com/en-us/sql/t-sql/functions/cast-and-convert-transact-sql?view=sql-server-ver16#style
1048        styles: Vec<Expr>,
1049    },
1050    /// `CAST` an expression to a different data type e.g. `CAST(foo AS VARCHAR(123))`
1051    Cast {
1052        /// The cast kind (e.g., `CAST`, `TRY_CAST`).
1053        kind: CastKind,
1054        /// Expression being cast.
1055        expr: Box<Expr>,
1056        /// Target data type.
1057        data_type: DataType,
1058        /// [MySQL] allows CAST(... AS type ARRAY) in functional index definitions for InnoDB
1059        /// multi-valued indices. It's not really a datatype, and is only allowed in `CAST` in key
1060        /// specifications, so it's a flag here.
1061        ///
1062        /// [MySQL]: https://dev.mysql.com/doc/refman/8.4/en/cast-functions.html#function_cast
1063        array: bool,
1064        /// Optional CAST(string_expression AS type FORMAT format_string_expression) as used by [BigQuery]
1065        ///
1066        /// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/format-elements#formatting_syntax
1067        format: Option<CastFormat>,
1068    },
1069    /// AT a timestamp to a different timezone e.g. `FROM_UNIXTIME(0) AT TIME ZONE 'UTC-06:00'`
1070    AtTimeZone {
1071        /// Timestamp expression to shift.
1072        timestamp: Box<Expr>,
1073        /// Time zone expression to apply.
1074        time_zone: Box<Expr>,
1075    },
1076    /// Extract a field from a timestamp e.g. `EXTRACT(MONTH FROM foo)`
1077    /// Or `EXTRACT(MONTH, foo)`
1078    ///
1079    /// Syntax:
1080    /// ```sql
1081    /// EXTRACT(DateTimeField FROM <expr>) | EXTRACT(DateTimeField, <expr>)
1082    /// ```
1083    Extract {
1084        /// Which datetime field is being extracted.
1085        field: DateTimeField,
1086        /// Syntax variant used (`From` or `Comma`).
1087        syntax: ExtractSyntax,
1088        /// Expression to extract from.
1089        expr: Box<Expr>,
1090    },
1091    /// ```sql
1092    /// CEIL(<expr> [TO DateTimeField])
1093    /// ```
1094    /// ```sql
1095    /// CEIL( <input_expr> [, <scale_expr> ] )
1096    /// ```
1097    Ceil {
1098        /// Expression to ceil.
1099        expr: Box<Expr>,
1100        /// The CEIL/FLOOR kind (datetime field or scale).
1101        field: CeilFloorKind,
1102    },
1103    /// ```sql
1104    /// FLOOR(<expr> [TO DateTimeField])
1105    /// ```
1106    /// ```sql
1107    /// FLOOR( <input_expr> [, <scale_expr> ] )
1108    ///
1109    Floor {
1110        /// Expression to floor.
1111        expr: Box<Expr>,
1112        /// The CEIL/FLOOR kind (datetime field or scale).
1113        field: CeilFloorKind,
1114    },
1115    /// ```sql
1116    /// POSITION(<expr> in <expr>)
1117    /// ```
1118    Position {
1119        /// Expression to search for.
1120        expr: Box<Expr>,
1121        /// Expression to search in.
1122        r#in: Box<Expr>,
1123    },
1124    /// ```sql
1125    /// SUBSTRING(<expr> [FROM <expr>] [FOR <expr>])
1126    /// ```
1127    /// or
1128    /// ```sql
1129    /// SUBSTRING(<expr>, <expr>, <expr>)
1130    /// ```
1131    Substring {
1132        /// Source expression.
1133        expr: Box<Expr>,
1134        /// Optional `FROM` expression.
1135        substring_from: Option<Box<Expr>>,
1136        /// Optional `FOR` expression.
1137        substring_for: Option<Box<Expr>>,
1138
1139        /// false if the expression is represented using the `SUBSTRING(expr [FROM start] [FOR len])` syntax
1140        /// true if the expression is represented using the `SUBSTRING(expr, start, len)` syntax
1141        /// This flag is used for formatting.
1142        special: bool,
1143
1144        /// true if the expression is represented using the `SUBSTR` shorthand
1145        /// This flag is used for formatting.
1146        shorthand: bool,
1147    },
1148    /// ```sql
1149    /// TRIM([BOTH | LEADING | TRAILING] [<expr> FROM] <expr>)
1150    /// TRIM(<expr>)
1151    /// TRIM(<expr>, [, characters]) -- PostgreSQL, DuckDB, Snowflake, BigQuery, Generic
1152    /// ```
1153    Trim {
1154        /// Which side to trim: `BOTH`, `LEADING`, or `TRAILING`.
1155        trim_where: Option<TrimWhereField>,
1156        /// Optional expression specifying what to trim from the value `expr`.
1157        trim_what: Option<Box<Expr>>,
1158        /// The expression to trim from.
1159        expr: Box<Expr>,
1160        /// Optional list of characters to trim (dialect-specific).
1161        trim_characters: Option<Vec<Expr>>,
1162    },
1163    /// ```sql
1164    /// OVERLAY(<expr> PLACING <expr> FROM <expr>[ FOR <expr> ]
1165    /// ```
1166    Overlay {
1167        /// The target expression being overlayed.
1168        expr: Box<Expr>,
1169        /// The expression to place into the target.
1170        overlay_what: Box<Expr>,
1171        /// The `FROM` position expression indicating where to start overlay.
1172        overlay_from: Box<Expr>,
1173        /// Optional `FOR` length expression limiting the overlay span.
1174        overlay_for: Option<Box<Expr>>,
1175    },
1176    /// `expr COLLATE collation`
1177    Collate {
1178        /// The expression being collated.
1179        expr: Box<Expr>,
1180        /// The collation name to apply to the expression.
1181        collation: ObjectName,
1182    },
1183    /// Nested expression e.g. `(foo > bar)` or `(1)`
1184    Nested(Box<Expr>),
1185    /// A literal value, such as string, number, date or NULL
1186    Value(ValueWithSpan),
1187    /// Prefixed expression, e.g. introducer strings, projection prefix
1188    /// <https://dev.mysql.com/doc/refman/8.0/en/charset-introducer.html>
1189    /// <https://docs.snowflake.com/en/sql-reference/constructs/connect-by>
1190    Prefixed {
1191        /// The prefix identifier (introducer or projection prefix).
1192        prefix: Ident,
1193        /// The value expression being prefixed.
1194        /// Hint: you can unwrap the string value using `value.into_string()`.
1195        value: Box<Expr>,
1196    },
1197    /// A constant of form `<data_type> 'value'`.
1198    /// This can represent ANSI SQL `DATE`, `TIME`, and `TIMESTAMP` literals (such as `DATE '2020-01-01'`),
1199    /// as well as constants of other types (a non-standard PostgreSQL extension).
1200    TypedString(TypedString),
1201    /// Scalar function call e.g. `LEFT(foo, 5)`
1202    Function(Function),
1203    /// `CASE [<operand>] WHEN <condition> THEN <result> ... [ELSE <result>] END`
1204    ///
1205    /// Note we only recognize a complete single expression as `<condition>`,
1206    /// not `< 0` nor `1, 2, 3` as allowed in a `<simple when clause>` per
1207    /// <https://jakewheat.github.io/sql-overview/sql-2011-foundation-grammar.html#simple-when-clause>
1208    Case {
1209        /// The attached `CASE` token (keeps original spacing/comments).
1210        case_token: AttachedToken,
1211        /// The attached `END` token (keeps original spacing/comments).
1212        end_token: AttachedToken,
1213        /// Optional operand expression after `CASE` (for simple CASE).
1214        operand: Option<Box<Expr>>,
1215        /// The `WHEN ... THEN` conditions and results.
1216        conditions: Vec<CaseWhen>,
1217        /// Optional `ELSE` result expression.
1218        else_result: Option<Box<Expr>>,
1219    },
1220    /// An exists expression `[ NOT ] EXISTS(SELECT ...)`, used in expressions like
1221    /// `WHERE [ NOT ] EXISTS (SELECT ...)`.
1222    Exists {
1223        /// The subquery checked by `EXISTS`.
1224        subquery: Box<Query>,
1225        /// Whether the `EXISTS` is negated (`NOT EXISTS`).
1226        negated: bool,
1227    },
1228    /// A parenthesized subquery `(SELECT ...)`, used in expression like
1229    /// `SELECT (subquery) AS x` or `WHERE (subquery) = x`
1230    Subquery(Box<Query>),
1231    /// The `GROUPING SETS` expr.
1232    GroupingSets(Vec<Vec<Expr>>),
1233    /// The `CUBE` expr.
1234    Cube(Vec<Vec<Expr>>),
1235    /// The `ROLLUP` expr.
1236    Rollup(Vec<Vec<Expr>>),
1237    /// ROW / TUPLE a single value, such as `SELECT (1, 2)`
1238    Tuple(Vec<Expr>),
1239    /// `Struct` literal expression
1240    /// Syntax:
1241    /// ```sql
1242    /// STRUCT<[field_name] field_type, ...>( expr1 [, ... ])
1243    ///
1244    /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-types#struct_type)
1245    /// [Databricks](https://docs.databricks.com/en/sql/language-manual/functions/struct.html)
1246    /// ```
1247    Struct {
1248        /// Struct values.
1249        values: Vec<Expr>,
1250        /// Struct field definitions.
1251        fields: Vec<StructField>,
1252    },
1253    /// `BigQuery` specific: An named expression in a typeless struct [1]
1254    ///
1255    /// Syntax
1256    /// ```sql
1257    /// 1 AS A
1258    /// ```
1259    /// [1]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-types#struct_type
1260    Named {
1261        /// The expression being named.
1262        expr: Box<Expr>,
1263        /// The assigned identifier name for the expression.
1264        name: Ident,
1265    },
1266    /// `DuckDB` specific `Struct` literal expression [1]
1267    ///
1268    /// Syntax:
1269    /// ```sql
1270    /// syntax: {'field_name': expr1[, ... ]}
1271    /// ```
1272    /// [1]: https://duckdb.org/docs/sql/data_types/struct#creating-structs
1273    Dictionary(Vec<DictionaryField>),
1274    /// `DuckDB` specific `Map` literal expression [1]
1275    ///
1276    /// Syntax:
1277    /// ```sql
1278    /// syntax: Map {key1: value1[, ... ]}
1279    /// ```
1280    /// [1]: https://duckdb.org/docs/sql/data_types/map#creating-maps
1281    Map(Map),
1282    /// An array expression e.g. `ARRAY[1, 2]`
1283    Array(Array),
1284    /// An interval expression e.g. `INTERVAL '1' YEAR`
1285    Interval(Interval),
1286    /// `MySQL` specific text search function [(1)].
1287    ///
1288    /// Syntax:
1289    /// ```sql
1290    /// MATCH (<col>, <col>, ...) AGAINST (<expr> [<search modifier>])
1291    ///
1292    /// <col> = CompoundIdentifier
1293    /// <expr> = String literal
1294    /// ```
1295    /// [(1)]: https://dev.mysql.com/doc/refman/8.0/en/fulltext-search.html#function_match
1296    MatchAgainst {
1297        /// `(<col>, <col>, ...)`.
1298        columns: Vec<ObjectName>,
1299        /// `<expr>`.
1300        match_value: ValueWithSpan,
1301        /// `<search modifier>`
1302        opt_search_modifier: Option<SearchModifier>,
1303    },
1304    /// An unqualified `*` wildcard token (e.g. `*`).
1305    Wildcard(AttachedToken),
1306    /// Qualified wildcard, e.g. `alias.*` or `schema.table.*`.
1307    /// (Same caveats apply to `QualifiedWildcard` as to `Wildcard`.)
1308    QualifiedWildcard(ObjectName, AttachedToken),
1309    /// Some dialects support an older syntax for outer joins where columns are
1310    /// marked with the `(+)` operator in the WHERE clause, for example:
1311    ///
1312    /// ```sql
1313    /// SELECT t1.c1, t2.c2 FROM t1, t2 WHERE t1.c1 = t2.c2 (+)
1314    /// ```
1315    ///
1316    /// which is equivalent to
1317    ///
1318    /// ```sql
1319    /// SELECT t1.c1, t2.c2 FROM t1 LEFT OUTER JOIN t2 ON t1.c1 = t2.c2
1320    /// ```
1321    ///
1322    /// See <https://docs.snowflake.com/en/sql-reference/constructs/where#joins-in-the-where-clause>.
1323    OuterJoin(Box<Expr>),
1324    /// A reference to the prior level in a CONNECT BY clause.
1325    Prior(Box<Expr>),
1326    /// A lambda function.
1327    ///
1328    /// Syntax:
1329    /// ```plaintext
1330    /// param -> expr | (param1, ...) -> expr
1331    /// ```
1332    ///
1333    /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/functions#higher-order-functions---operator-and-lambdaparams-expr-function)
1334    /// [Databricks](https://docs.databricks.com/en/sql/language-manual/sql-ref-lambda-functions.html)
1335    /// [DuckDB](https://duckdb.org/docs/stable/sql/functions/lambda)
1336    Lambda(LambdaFunction),
1337    /// Checks membership of a value in a JSON array
1338    MemberOf(MemberOf),
1339}
1340
1341impl Expr {
1342    /// Creates a new [`Expr::Value`]
1343    pub fn value(value: impl Into<ValueWithSpan>) -> Self {
1344        Expr::Value(value.into())
1345    }
1346}
1347
1348/// The contents inside the `[` and `]` in a subscript expression.
1349#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1350#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1351#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1352pub enum Subscript {
1353    /// Accesses the element of the array at the given index.
1354    Index {
1355        /// The index expression used to access the array element.
1356        index: Expr,
1357    },
1358
1359    /// Accesses a slice of an array on PostgreSQL, e.g.
1360    ///
1361    /// ```plaintext
1362    /// => select (array[1,2,3,4,5,6])[2:5];
1363    /// -----------
1364    /// {2,3,4,5}
1365    /// ```
1366    ///
1367    /// The lower and/or upper bound can be omitted to slice from the start or
1368    /// end of the array respectively.
1369    ///
1370    /// See <https://www.postgresql.org/docs/current/arrays.html#ARRAYS-ACCESSING>.
1371    ///
1372    /// Also supports an optional "stride" as the last element (this is not
1373    /// supported by postgres), e.g.
1374    ///
1375    /// ```plaintext
1376    /// => select (array[1,2,3,4,5,6])[1:6:2];
1377    /// -----------
1378    /// {1,3,5}
1379    /// ```
1380    Slice {
1381        /// Optional lower bound for the slice (inclusive).
1382        lower_bound: Option<Expr>,
1383        /// Optional upper bound for the slice (inclusive).
1384        upper_bound: Option<Expr>,
1385        /// Optional stride for the slice (step size).
1386        stride: Option<Expr>,
1387    },
1388}
1389
1390impl fmt::Display for Subscript {
1391    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1392        match self {
1393            Subscript::Index { index } => write!(f, "{index}"),
1394            Subscript::Slice {
1395                lower_bound,
1396                upper_bound,
1397                stride,
1398            } => {
1399                if let Some(lower) = lower_bound {
1400                    write!(f, "{lower}")?;
1401                }
1402                write!(f, ":")?;
1403                if let Some(upper) = upper_bound {
1404                    write!(f, "{upper}")?;
1405                }
1406                if let Some(stride) = stride {
1407                    write!(f, ":")?;
1408                    write!(f, "{stride}")?;
1409                }
1410                Ok(())
1411            }
1412        }
1413    }
1414}
1415
1416/// An element of a [`Expr::CompoundFieldAccess`].
1417/// It can be an expression or a subscript.
1418#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1419#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1420#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1421pub enum AccessExpr {
1422    /// Accesses a field using dot notation, e.g. `foo.bar.baz`.
1423    Dot(Expr),
1424    /// Accesses a field or array element using bracket notation, e.g. `foo['bar']`.
1425    Subscript(Subscript),
1426}
1427
1428impl fmt::Display for AccessExpr {
1429    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1430        match self {
1431            AccessExpr::Dot(expr) => write!(f, ".{expr}"),
1432            AccessExpr::Subscript(subscript) => write!(f, "[{subscript}]"),
1433        }
1434    }
1435}
1436
1437/// A lambda function.
1438#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1439#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1440#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1441pub struct LambdaFunction {
1442    /// The parameters to the lambda function.
1443    pub params: OneOrManyWithParens<LambdaFunctionParameter>,
1444    /// The body of the lambda function.
1445    pub body: Box<Expr>,
1446    /// The syntax style used to write the lambda function.
1447    pub syntax: LambdaSyntax,
1448}
1449
1450impl fmt::Display for LambdaFunction {
1451    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1452        match self.syntax {
1453            LambdaSyntax::Arrow => write!(f, "{} -> {}", self.params, self.body),
1454            LambdaSyntax::LambdaKeyword => {
1455                // For lambda keyword syntax, display params without parentheses
1456                // e.g., `lambda x, y : expr` not `lambda (x, y) : expr`
1457                write!(f, "lambda ")?;
1458                match &self.params {
1459                    OneOrManyWithParens::One(p) => write!(f, "{p}")?,
1460                    OneOrManyWithParens::Many(ps) => write!(f, "{}", display_comma_separated(ps))?,
1461                };
1462                write!(f, " : {}", self.body)
1463            }
1464        }
1465    }
1466}
1467
1468/// A parameter to a lambda function, optionally with a data type.
1469#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1470#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1471#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1472pub struct LambdaFunctionParameter {
1473    /// The name of the parameter
1474    pub name: Ident,
1475    /// The optional data type of the parameter
1476    /// [Snowflake Syntax](https://docs.snowflake.com/en/sql-reference/functions/filter#arguments)
1477    pub data_type: Option<DataType>,
1478}
1479
1480impl fmt::Display for LambdaFunctionParameter {
1481    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1482        match &self.data_type {
1483            Some(dt) => write!(f, "{} {}", self.name, dt),
1484            None => write!(f, "{}", self.name),
1485        }
1486    }
1487}
1488
1489/// The syntax style for a lambda function.
1490#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Copy)]
1491#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1492#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1493pub enum LambdaSyntax {
1494    /// Arrow syntax: `param -> expr` or `(param1, param2) -> expr`
1495    ///
1496    /// <https://docs.databricks.com/aws/en/sql/language-manual/sql-ref-lambda-functions>
1497    ///
1498    /// Supported, but deprecated in DuckDB:
1499    /// <https://duckdb.org/docs/stable/sql/functions/lambda>
1500    Arrow,
1501    /// Lambda keyword syntax: `lambda param : expr` or `lambda param1, param2 : expr`
1502    ///
1503    /// Recommended in DuckDB:
1504    /// <https://duckdb.org/docs/stable/sql/functions/lambda>
1505    LambdaKeyword,
1506}
1507
1508/// Encapsulates the common pattern in SQL where either one unparenthesized item
1509/// such as an identifier or expression is permitted, or multiple of the same
1510/// item in a parenthesized list. For accessing items regardless of the form,
1511/// `OneOrManyWithParens` implements `Deref<Target = [T]>` and `IntoIterator`,
1512/// so you can call slice methods on it and iterate over items
1513/// # Examples
1514/// Accessing as a slice:
1515/// ```
1516/// # use sqlparser::ast::OneOrManyWithParens;
1517/// let one = OneOrManyWithParens::One("a");
1518///
1519/// assert_eq!(one[0], "a");
1520/// assert_eq!(one.len(), 1);
1521/// ```
1522/// Iterating:
1523/// ```
1524/// # use sqlparser::ast::OneOrManyWithParens;
1525/// let one = OneOrManyWithParens::One("a");
1526/// let many = OneOrManyWithParens::Many(vec!["a", "b"]);
1527///
1528/// assert_eq!(one.into_iter().chain(many).collect::<Vec<_>>(), vec!["a", "a", "b"] );
1529/// ```
1530#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1531#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1532#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1533pub enum OneOrManyWithParens<T> {
1534    /// A single `T`, unparenthesized.
1535    One(T),
1536    /// One or more `T`s, parenthesized.
1537    Many(Vec<T>),
1538}
1539
1540impl<T> Deref for OneOrManyWithParens<T> {
1541    type Target = [T];
1542
1543    fn deref(&self) -> &[T] {
1544        match self {
1545            OneOrManyWithParens::One(one) => core::slice::from_ref(one),
1546            OneOrManyWithParens::Many(many) => many,
1547        }
1548    }
1549}
1550
1551impl<T> AsRef<[T]> for OneOrManyWithParens<T> {
1552    fn as_ref(&self) -> &[T] {
1553        self
1554    }
1555}
1556
1557impl<'a, T> IntoIterator for &'a OneOrManyWithParens<T> {
1558    type Item = &'a T;
1559    type IntoIter = core::slice::Iter<'a, T>;
1560
1561    fn into_iter(self) -> Self::IntoIter {
1562        self.iter()
1563    }
1564}
1565
1566/// Owned iterator implementation of `OneOrManyWithParens`
1567#[derive(Debug, Clone)]
1568pub struct OneOrManyWithParensIntoIter<T> {
1569    inner: OneOrManyWithParensIntoIterInner<T>,
1570}
1571
1572#[derive(Debug, Clone)]
1573enum OneOrManyWithParensIntoIterInner<T> {
1574    One(core::iter::Once<T>),
1575    Many(<Vec<T> as IntoIterator>::IntoIter),
1576}
1577
1578impl<T> core::iter::FusedIterator for OneOrManyWithParensIntoIter<T>
1579where
1580    core::iter::Once<T>: core::iter::FusedIterator,
1581    <Vec<T> as IntoIterator>::IntoIter: core::iter::FusedIterator,
1582{
1583}
1584
1585impl<T> core::iter::ExactSizeIterator for OneOrManyWithParensIntoIter<T>
1586where
1587    core::iter::Once<T>: core::iter::ExactSizeIterator,
1588    <Vec<T> as IntoIterator>::IntoIter: core::iter::ExactSizeIterator,
1589{
1590}
1591
1592impl<T> core::iter::Iterator for OneOrManyWithParensIntoIter<T> {
1593    type Item = T;
1594
1595    fn next(&mut self) -> Option<Self::Item> {
1596        match &mut self.inner {
1597            OneOrManyWithParensIntoIterInner::One(one) => one.next(),
1598            OneOrManyWithParensIntoIterInner::Many(many) => many.next(),
1599        }
1600    }
1601
1602    fn size_hint(&self) -> (usize, Option<usize>) {
1603        match &self.inner {
1604            OneOrManyWithParensIntoIterInner::One(one) => one.size_hint(),
1605            OneOrManyWithParensIntoIterInner::Many(many) => many.size_hint(),
1606        }
1607    }
1608
1609    fn count(self) -> usize
1610    where
1611        Self: Sized,
1612    {
1613        match self.inner {
1614            OneOrManyWithParensIntoIterInner::One(one) => one.count(),
1615            OneOrManyWithParensIntoIterInner::Many(many) => many.count(),
1616        }
1617    }
1618
1619    fn fold<B, F>(mut self, init: B, f: F) -> B
1620    where
1621        Self: Sized,
1622        F: FnMut(B, Self::Item) -> B,
1623    {
1624        match &mut self.inner {
1625            OneOrManyWithParensIntoIterInner::One(one) => one.fold(init, f),
1626            OneOrManyWithParensIntoIterInner::Many(many) => many.fold(init, f),
1627        }
1628    }
1629}
1630
1631impl<T> core::iter::DoubleEndedIterator for OneOrManyWithParensIntoIter<T> {
1632    fn next_back(&mut self) -> Option<Self::Item> {
1633        match &mut self.inner {
1634            OneOrManyWithParensIntoIterInner::One(one) => one.next_back(),
1635            OneOrManyWithParensIntoIterInner::Many(many) => many.next_back(),
1636        }
1637    }
1638}
1639
1640impl<T> IntoIterator for OneOrManyWithParens<T> {
1641    type Item = T;
1642
1643    type IntoIter = OneOrManyWithParensIntoIter<T>;
1644
1645    fn into_iter(self) -> Self::IntoIter {
1646        let inner = match self {
1647            OneOrManyWithParens::One(one) => {
1648                OneOrManyWithParensIntoIterInner::One(core::iter::once(one))
1649            }
1650            OneOrManyWithParens::Many(many) => {
1651                OneOrManyWithParensIntoIterInner::Many(many.into_iter())
1652            }
1653        };
1654
1655        OneOrManyWithParensIntoIter { inner }
1656    }
1657}
1658
1659impl<T> fmt::Display for OneOrManyWithParens<T>
1660where
1661    T: fmt::Display,
1662{
1663    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1664        match self {
1665            OneOrManyWithParens::One(value) => write!(f, "{value}"),
1666            OneOrManyWithParens::Many(values) => {
1667                write!(f, "({})", display_comma_separated(values))
1668            }
1669        }
1670    }
1671}
1672
1673impl fmt::Display for CastFormat {
1674    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1675        match self {
1676            CastFormat::Value(v) => write!(f, "{v}"),
1677            CastFormat::ValueAtTimeZone(v, tz) => write!(f, "{v} AT TIME ZONE {tz}"),
1678        }
1679    }
1680}
1681
1682impl fmt::Display for Expr {
1683    #[cfg_attr(feature = "recursive-protection", recursive::recursive)]
1684    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1685        match self {
1686            Expr::Identifier(s) => write!(f, "{s}"),
1687            Expr::Wildcard(_) => f.write_str("*"),
1688            Expr::QualifiedWildcard(prefix, _) => write!(f, "{prefix}.*"),
1689            Expr::CompoundIdentifier(s) => write!(f, "{}", display_separated(s, ".")),
1690            Expr::CompoundFieldAccess { root, access_chain } => {
1691                write!(f, "{root}")?;
1692                for field in access_chain {
1693                    write!(f, "{field}")?;
1694                }
1695                Ok(())
1696            }
1697            Expr::IsTrue(ast) => write!(f, "{ast} IS TRUE"),
1698            Expr::IsNotTrue(ast) => write!(f, "{ast} IS NOT TRUE"),
1699            Expr::IsFalse(ast) => write!(f, "{ast} IS FALSE"),
1700            Expr::IsNotFalse(ast) => write!(f, "{ast} IS NOT FALSE"),
1701            Expr::IsNull(ast) => write!(f, "{ast} IS NULL"),
1702            Expr::IsNotNull(ast) => write!(f, "{ast} IS NOT NULL"),
1703            Expr::IsUnknown(ast) => write!(f, "{ast} IS UNKNOWN"),
1704            Expr::IsNotUnknown(ast) => write!(f, "{ast} IS NOT UNKNOWN"),
1705            Expr::InList {
1706                expr,
1707                list,
1708                negated,
1709            } => write!(
1710                f,
1711                "{} {}IN ({})",
1712                expr,
1713                if *negated { "NOT " } else { "" },
1714                display_comma_separated(list)
1715            ),
1716            Expr::InSubquery {
1717                expr,
1718                subquery,
1719                negated,
1720            } => write!(
1721                f,
1722                "{} {}IN ({})",
1723                expr,
1724                if *negated { "NOT " } else { "" },
1725                subquery
1726            ),
1727            Expr::InUnnest {
1728                expr,
1729                array_expr,
1730                negated,
1731            } => write!(
1732                f,
1733                "{} {}IN UNNEST({})",
1734                expr,
1735                if *negated { "NOT " } else { "" },
1736                array_expr
1737            ),
1738            Expr::Between {
1739                expr,
1740                negated,
1741                low,
1742                high,
1743            } => write!(
1744                f,
1745                "{} {}BETWEEN {} AND {}",
1746                expr,
1747                if *negated { "NOT " } else { "" },
1748                low,
1749                high
1750            ),
1751            Expr::BinaryOp { left, op, right } => write!(f, "{left} {op} {right}"),
1752            Expr::Like {
1753                negated,
1754                expr,
1755                pattern,
1756                escape_char,
1757                any,
1758            } => match escape_char {
1759                Some(ch) => write!(
1760                    f,
1761                    "{} {}LIKE {}{} ESCAPE {}",
1762                    expr,
1763                    if *negated { "NOT " } else { "" },
1764                    if *any { "ANY " } else { "" },
1765                    pattern,
1766                    ch
1767                ),
1768                _ => write!(
1769                    f,
1770                    "{} {}LIKE {}{}",
1771                    expr,
1772                    if *negated { "NOT " } else { "" },
1773                    if *any { "ANY " } else { "" },
1774                    pattern
1775                ),
1776            },
1777            Expr::ILike {
1778                negated,
1779                expr,
1780                pattern,
1781                escape_char,
1782                any,
1783            } => match escape_char {
1784                Some(ch) => write!(
1785                    f,
1786                    "{} {}ILIKE {}{} ESCAPE {}",
1787                    expr,
1788                    if *negated { "NOT " } else { "" },
1789                    if *any { "ANY" } else { "" },
1790                    pattern,
1791                    ch
1792                ),
1793                _ => write!(
1794                    f,
1795                    "{} {}ILIKE {}{}",
1796                    expr,
1797                    if *negated { "NOT " } else { "" },
1798                    if *any { "ANY " } else { "" },
1799                    pattern
1800                ),
1801            },
1802            Expr::RLike {
1803                negated,
1804                expr,
1805                pattern,
1806                regexp,
1807            } => write!(
1808                f,
1809                "{} {}{} {}",
1810                expr,
1811                if *negated { "NOT " } else { "" },
1812                if *regexp { "REGEXP" } else { "RLIKE" },
1813                pattern
1814            ),
1815            Expr::IsNormalized {
1816                expr,
1817                form,
1818                negated,
1819            } => {
1820                let not_ = if *negated { "NOT " } else { "" };
1821                if form.is_none() {
1822                    write!(f, "{expr} IS {not_}NORMALIZED")
1823                } else {
1824                    write!(
1825                        f,
1826                        "{} IS {}{} NORMALIZED",
1827                        expr,
1828                        not_,
1829                        form.as_ref().unwrap()
1830                    )
1831                }
1832            }
1833            Expr::SimilarTo {
1834                negated,
1835                expr,
1836                pattern,
1837                escape_char,
1838            } => match escape_char {
1839                Some(ch) => write!(
1840                    f,
1841                    "{} {}SIMILAR TO {} ESCAPE {}",
1842                    expr,
1843                    if *negated { "NOT " } else { "" },
1844                    pattern,
1845                    ch
1846                ),
1847                _ => write!(
1848                    f,
1849                    "{} {}SIMILAR TO {}",
1850                    expr,
1851                    if *negated { "NOT " } else { "" },
1852                    pattern
1853                ),
1854            },
1855            Expr::AnyOp {
1856                left,
1857                compare_op,
1858                right,
1859                is_some,
1860            } => {
1861                let add_parens = !matches!(right.as_ref(), Expr::Subquery(_));
1862                write!(
1863                    f,
1864                    "{left} {compare_op} {}{}{right}{}",
1865                    if *is_some { "SOME" } else { "ANY" },
1866                    if add_parens { "(" } else { "" },
1867                    if add_parens { ")" } else { "" },
1868                )
1869            }
1870            Expr::AllOp {
1871                left,
1872                compare_op,
1873                right,
1874            } => {
1875                let add_parens = !matches!(right.as_ref(), Expr::Subquery(_));
1876                write!(
1877                    f,
1878                    "{left} {compare_op} ALL{}{right}{}",
1879                    if add_parens { "(" } else { "" },
1880                    if add_parens { ")" } else { "" },
1881                )
1882            }
1883            Expr::UnaryOp { op, expr } => {
1884                if op == &UnaryOperator::PGPostfixFactorial {
1885                    write!(f, "{expr}{op}")
1886                } else if matches!(
1887                    op,
1888                    UnaryOperator::Not
1889                        | UnaryOperator::Hash
1890                        | UnaryOperator::AtDashAt
1891                        | UnaryOperator::DoubleAt
1892                        | UnaryOperator::QuestionDash
1893                        | UnaryOperator::QuestionPipe
1894                ) {
1895                    write!(f, "{op} {expr}")
1896                } else {
1897                    write!(f, "{op}{expr}")
1898                }
1899            }
1900            Expr::Convert {
1901                is_try,
1902                expr,
1903                target_before_value,
1904                data_type,
1905                charset,
1906                styles,
1907            } => {
1908                write!(f, "{}CONVERT(", if *is_try { "TRY_" } else { "" })?;
1909                if let Some(data_type) = data_type {
1910                    if let Some(charset) = charset {
1911                        write!(f, "{expr}, {data_type} CHARACTER SET {charset}")
1912                    } else if *target_before_value {
1913                        write!(f, "{data_type}, {expr}")
1914                    } else {
1915                        write!(f, "{expr}, {data_type}")
1916                    }
1917                } else if let Some(charset) = charset {
1918                    write!(f, "{expr} USING {charset}")
1919                } else {
1920                    write!(f, "{expr}") // This should never happen
1921                }?;
1922                if !styles.is_empty() {
1923                    write!(f, ", {}", display_comma_separated(styles))?;
1924                }
1925                write!(f, ")")
1926            }
1927            Expr::Cast {
1928                kind,
1929                expr,
1930                data_type,
1931                array,
1932                format,
1933            } => match kind {
1934                CastKind::Cast => {
1935                    write!(f, "CAST({expr} AS {data_type}")?;
1936                    if *array {
1937                        write!(f, " ARRAY")?;
1938                    }
1939                    if let Some(format) = format {
1940                        write!(f, " FORMAT {format}")?;
1941                    }
1942                    write!(f, ")")
1943                }
1944                CastKind::TryCast => {
1945                    if let Some(format) = format {
1946                        write!(f, "TRY_CAST({expr} AS {data_type} FORMAT {format})")
1947                    } else {
1948                        write!(f, "TRY_CAST({expr} AS {data_type})")
1949                    }
1950                }
1951                CastKind::SafeCast => {
1952                    if let Some(format) = format {
1953                        write!(f, "SAFE_CAST({expr} AS {data_type} FORMAT {format})")
1954                    } else {
1955                        write!(f, "SAFE_CAST({expr} AS {data_type})")
1956                    }
1957                }
1958                CastKind::DoubleColon => {
1959                    write!(f, "{expr}::{data_type}")
1960                }
1961            },
1962            Expr::Extract {
1963                field,
1964                syntax,
1965                expr,
1966            } => match syntax {
1967                ExtractSyntax::From => write!(f, "EXTRACT({field} FROM {expr})"),
1968                ExtractSyntax::Comma => write!(f, "EXTRACT({field}, {expr})"),
1969            },
1970            Expr::Ceil { expr, field } => match field {
1971                CeilFloorKind::DateTimeField(DateTimeField::NoDateTime) => {
1972                    write!(f, "CEIL({expr})")
1973                }
1974                CeilFloorKind::DateTimeField(dt_field) => write!(f, "CEIL({expr} TO {dt_field})"),
1975                CeilFloorKind::Scale(s) => write!(f, "CEIL({expr}, {s})"),
1976            },
1977            Expr::Floor { expr, field } => match field {
1978                CeilFloorKind::DateTimeField(DateTimeField::NoDateTime) => {
1979                    write!(f, "FLOOR({expr})")
1980                }
1981                CeilFloorKind::DateTimeField(dt_field) => write!(f, "FLOOR({expr} TO {dt_field})"),
1982                CeilFloorKind::Scale(s) => write!(f, "FLOOR({expr}, {s})"),
1983            },
1984            Expr::Position { expr, r#in } => write!(f, "POSITION({expr} IN {in})"),
1985            Expr::Collate { expr, collation } => write!(f, "{expr} COLLATE {collation}"),
1986            Expr::Nested(ast) => write!(f, "({ast})"),
1987            Expr::Value(v) => write!(f, "{v}"),
1988            Expr::Prefixed { prefix, value } => write!(f, "{prefix} {value}"),
1989            Expr::TypedString(ts) => ts.fmt(f),
1990            Expr::Function(fun) => fun.fmt(f),
1991            Expr::Case {
1992                case_token: _,
1993                end_token: _,
1994                operand,
1995                conditions,
1996                else_result,
1997            } => {
1998                f.write_str("CASE")?;
1999                if let Some(operand) = operand {
2000                    f.write_str(" ")?;
2001                    operand.fmt(f)?;
2002                }
2003                for when in conditions {
2004                    SpaceOrNewline.fmt(f)?;
2005                    Indent(when).fmt(f)?;
2006                }
2007                if let Some(else_result) = else_result {
2008                    SpaceOrNewline.fmt(f)?;
2009                    Indent("ELSE").fmt(f)?;
2010                    SpaceOrNewline.fmt(f)?;
2011                    Indent(Indent(else_result)).fmt(f)?;
2012                }
2013                SpaceOrNewline.fmt(f)?;
2014                f.write_str("END")
2015            }
2016            Expr::Exists { subquery, negated } => write!(
2017                f,
2018                "{}EXISTS ({})",
2019                if *negated { "NOT " } else { "" },
2020                subquery
2021            ),
2022            Expr::Subquery(s) => write!(f, "({s})"),
2023            Expr::GroupingSets(sets) => {
2024                write!(f, "GROUPING SETS (")?;
2025                let mut sep = "";
2026                for set in sets {
2027                    write!(f, "{sep}")?;
2028                    sep = ", ";
2029                    write!(f, "({})", display_comma_separated(set))?;
2030                }
2031                write!(f, ")")
2032            }
2033            Expr::Cube(sets) => {
2034                write!(f, "CUBE (")?;
2035                let mut sep = "";
2036                for set in sets {
2037                    write!(f, "{sep}")?;
2038                    sep = ", ";
2039                    if set.len() == 1 {
2040                        write!(f, "{}", set[0])?;
2041                    } else {
2042                        write!(f, "({})", display_comma_separated(set))?;
2043                    }
2044                }
2045                write!(f, ")")
2046            }
2047            Expr::Rollup(sets) => {
2048                write!(f, "ROLLUP (")?;
2049                let mut sep = "";
2050                for set in sets {
2051                    write!(f, "{sep}")?;
2052                    sep = ", ";
2053                    if set.len() == 1 {
2054                        write!(f, "{}", set[0])?;
2055                    } else {
2056                        write!(f, "({})", display_comma_separated(set))?;
2057                    }
2058                }
2059                write!(f, ")")
2060            }
2061            Expr::Substring {
2062                expr,
2063                substring_from,
2064                substring_for,
2065                special,
2066                shorthand,
2067            } => {
2068                f.write_str("SUBSTR")?;
2069                if !*shorthand {
2070                    f.write_str("ING")?;
2071                }
2072                write!(f, "({expr}")?;
2073                if let Some(from_part) = substring_from {
2074                    if *special {
2075                        write!(f, ", {from_part}")?;
2076                    } else {
2077                        write!(f, " FROM {from_part}")?;
2078                    }
2079                }
2080                if let Some(for_part) = substring_for {
2081                    if *special {
2082                        write!(f, ", {for_part}")?;
2083                    } else {
2084                        write!(f, " FOR {for_part}")?;
2085                    }
2086                }
2087
2088                write!(f, ")")
2089            }
2090            Expr::Overlay {
2091                expr,
2092                overlay_what,
2093                overlay_from,
2094                overlay_for,
2095            } => {
2096                write!(
2097                    f,
2098                    "OVERLAY({expr} PLACING {overlay_what} FROM {overlay_from}"
2099                )?;
2100                if let Some(for_part) = overlay_for {
2101                    write!(f, " FOR {for_part}")?;
2102                }
2103
2104                write!(f, ")")
2105            }
2106            Expr::IsDistinctFrom(a, b) => write!(f, "{a} IS DISTINCT FROM {b}"),
2107            Expr::IsNotDistinctFrom(a, b) => write!(f, "{a} IS NOT DISTINCT FROM {b}"),
2108            Expr::Trim {
2109                expr,
2110                trim_where,
2111                trim_what,
2112                trim_characters,
2113            } => {
2114                write!(f, "TRIM(")?;
2115                if let Some(ident) = trim_where {
2116                    write!(f, "{ident} ")?;
2117                }
2118                if let Some(trim_char) = trim_what {
2119                    write!(f, "{trim_char} FROM {expr}")?;
2120                } else {
2121                    write!(f, "{expr}")?;
2122                }
2123                if let Some(characters) = trim_characters {
2124                    write!(f, ", {}", display_comma_separated(characters))?;
2125                }
2126
2127                write!(f, ")")
2128            }
2129            Expr::Tuple(exprs) => {
2130                write!(f, "({})", display_comma_separated(exprs))
2131            }
2132            Expr::Struct { values, fields } => {
2133                if !fields.is_empty() {
2134                    write!(
2135                        f,
2136                        "STRUCT<{}>({})",
2137                        display_comma_separated(fields),
2138                        display_comma_separated(values)
2139                    )
2140                } else {
2141                    write!(f, "STRUCT({})", display_comma_separated(values))
2142                }
2143            }
2144            Expr::Named { expr, name } => {
2145                write!(f, "{expr} AS {name}")
2146            }
2147            Expr::Dictionary(fields) => {
2148                write!(f, "{{{}}}", display_comma_separated(fields))
2149            }
2150            Expr::Map(map) => {
2151                write!(f, "{map}")
2152            }
2153            Expr::Array(set) => {
2154                write!(f, "{set}")
2155            }
2156            Expr::JsonAccess { value, path } => {
2157                write!(f, "{value}{path}")
2158            }
2159            Expr::AtTimeZone {
2160                timestamp,
2161                time_zone,
2162            } => {
2163                write!(f, "{timestamp} AT TIME ZONE {time_zone}")
2164            }
2165            Expr::Interval(interval) => {
2166                write!(f, "{interval}")
2167            }
2168            Expr::MatchAgainst {
2169                columns,
2170                match_value: match_expr,
2171                opt_search_modifier,
2172            } => {
2173                write!(f, "MATCH ({}) AGAINST ", display_comma_separated(columns),)?;
2174
2175                if let Some(search_modifier) = opt_search_modifier {
2176                    write!(f, "({match_expr} {search_modifier})")?;
2177                } else {
2178                    write!(f, "({match_expr})")?;
2179                }
2180
2181                Ok(())
2182            }
2183            Expr::OuterJoin(expr) => {
2184                write!(f, "{expr} (+)")
2185            }
2186            Expr::Prior(expr) => write!(f, "PRIOR {expr}"),
2187            Expr::Lambda(lambda) => write!(f, "{lambda}"),
2188            Expr::MemberOf(member_of) => write!(f, "{member_of}"),
2189        }
2190    }
2191}
2192
2193/// The type of a window used in `OVER` clauses.
2194///
2195/// A window can be either an inline specification (`WindowSpec`) or a
2196/// reference to a previously defined named window.
2197///
2198/// - `WindowSpec(WindowSpec)`: An inline window specification, e.g.
2199///   `OVER (PARTITION BY ... ORDER BY ...)`.
2200/// - `NamedWindow(Ident)`: A reference to a named window declared elsewhere.
2201#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2202#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2203#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2204pub enum WindowType {
2205    /// An inline window specification.
2206    WindowSpec(WindowSpec),
2207    /// A reference to a previously defined named window.
2208    NamedWindow(Ident),
2209}
2210
2211impl Display for WindowType {
2212    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2213        match self {
2214            WindowType::WindowSpec(spec) => {
2215                f.write_str("(")?;
2216                NewLine.fmt(f)?;
2217                Indent(spec).fmt(f)?;
2218                NewLine.fmt(f)?;
2219                f.write_str(")")
2220            }
2221            WindowType::NamedWindow(name) => name.fmt(f),
2222        }
2223    }
2224}
2225
2226/// A window specification (i.e. `OVER ([window_name] PARTITION BY .. ORDER BY .. etc.)`)
2227#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2228#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2229#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2230pub struct WindowSpec {
2231    /// Optional window name.
2232    ///
2233    /// You can find it at least in [MySQL][1], [BigQuery][2], [PostgreSQL][3]
2234    ///
2235    /// [1]: https://dev.mysql.com/doc/refman/8.0/en/window-functions-named-windows.html
2236    /// [2]: https://cloud.google.com/bigquery/docs/reference/standard-sql/window-function-calls
2237    /// [3]: https://www.postgresql.org/docs/current/sql-expressions.html#SYNTAX-WINDOW-FUNCTIONS
2238    pub window_name: Option<Ident>,
2239    /// `OVER (PARTITION BY ...)`
2240    pub partition_by: Vec<Expr>,
2241    /// `OVER (ORDER BY ...)`
2242    pub order_by: Vec<OrderByExpr>,
2243    /// `OVER (window frame)`
2244    pub window_frame: Option<WindowFrame>,
2245}
2246
2247impl fmt::Display for WindowSpec {
2248    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2249        let mut is_first = true;
2250        if let Some(window_name) = &self.window_name {
2251            if !is_first {
2252                SpaceOrNewline.fmt(f)?;
2253            }
2254            is_first = false;
2255            write!(f, "{window_name}")?;
2256        }
2257        if !self.partition_by.is_empty() {
2258            if !is_first {
2259                SpaceOrNewline.fmt(f)?;
2260            }
2261            is_first = false;
2262            write!(
2263                f,
2264                "PARTITION BY {}",
2265                display_comma_separated(&self.partition_by)
2266            )?;
2267        }
2268        if !self.order_by.is_empty() {
2269            if !is_first {
2270                SpaceOrNewline.fmt(f)?;
2271            }
2272            is_first = false;
2273            write!(f, "ORDER BY {}", display_comma_separated(&self.order_by))?;
2274        }
2275        if let Some(window_frame) = &self.window_frame {
2276            if !is_first {
2277                SpaceOrNewline.fmt(f)?;
2278            }
2279            if let Some(end_bound) = &window_frame.end_bound {
2280                write!(
2281                    f,
2282                    "{} BETWEEN {} AND {}",
2283                    window_frame.units, window_frame.start_bound, end_bound
2284                )?;
2285            } else {
2286                write!(f, "{} {}", window_frame.units, window_frame.start_bound)?;
2287            }
2288        }
2289        Ok(())
2290    }
2291}
2292
2293/// Specifies the data processed by a window function, e.g.
2294/// `RANGE UNBOUNDED PRECEDING` or `ROWS BETWEEN 5 PRECEDING AND CURRENT ROW`.
2295///
2296/// Note: The parser does not validate the specified bounds; the caller should
2297/// reject invalid bounds like `ROWS UNBOUNDED FOLLOWING` before execution.
2298#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2299#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2300#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2301pub struct WindowFrame {
2302    /// Units for the frame (e.g. `ROWS`, `RANGE`, `GROUPS`).
2303    pub units: WindowFrameUnits,
2304    /// The start bound of the window frame.
2305    pub start_bound: WindowFrameBound,
2306    /// The right bound of the `BETWEEN .. AND` clause. The end bound of `None`
2307    /// indicates the shorthand form (e.g. `ROWS 1 PRECEDING`), which must
2308    /// behave the same as `end_bound = WindowFrameBound::CurrentRow`.
2309    pub end_bound: Option<WindowFrameBound>,
2310    // TBD: EXCLUDE
2311}
2312
2313impl Default for WindowFrame {
2314    /// Returns default value for window frame
2315    ///
2316    /// See [this page](https://www.sqlite.org/windowfunctions.html#frame_specifications) for more details.
2317    fn default() -> Self {
2318        Self {
2319            units: WindowFrameUnits::Range,
2320            start_bound: WindowFrameBound::Preceding(None),
2321            end_bound: None,
2322        }
2323    }
2324}
2325
2326#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2327#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2328#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2329/// Units used to describe the window frame scope.
2330pub enum WindowFrameUnits {
2331    /// `ROWS` unit.
2332    Rows,
2333    /// `RANGE` unit.
2334    Range,
2335    /// `GROUPS` unit.
2336    Groups,
2337}
2338
2339impl fmt::Display for WindowFrameUnits {
2340    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2341        f.write_str(match self {
2342            WindowFrameUnits::Rows => "ROWS",
2343            WindowFrameUnits::Range => "RANGE",
2344            WindowFrameUnits::Groups => "GROUPS",
2345        })
2346    }
2347}
2348
2349/// Specifies Ignore / Respect NULL within window functions.
2350/// For example
2351/// `FIRST_VALUE(column2) IGNORE NULLS OVER (PARTITION BY column1)`
2352#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2353#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2354#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2355/// How NULL values are treated in certain window functions.
2356pub enum NullTreatment {
2357    /// Ignore NULL values (e.g. `IGNORE NULLS`).
2358    IgnoreNulls,
2359    /// Respect NULL values (e.g. `RESPECT NULLS`).
2360    RespectNulls,
2361}
2362
2363impl fmt::Display for NullTreatment {
2364    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2365        f.write_str(match self {
2366            NullTreatment::IgnoreNulls => "IGNORE NULLS",
2367            NullTreatment::RespectNulls => "RESPECT NULLS",
2368        })
2369    }
2370}
2371
2372/// Specifies [WindowFrame]'s `start_bound` and `end_bound`
2373#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2374#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2375#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2376pub enum WindowFrameBound {
2377    /// `CURRENT ROW`
2378    CurrentRow,
2379    /// `<N> PRECEDING` or `UNBOUNDED PRECEDING`
2380    Preceding(Option<Box<Expr>>),
2381    /// `<N> FOLLOWING` or `UNBOUNDED FOLLOWING`.
2382    Following(Option<Box<Expr>>),
2383}
2384
2385impl fmt::Display for WindowFrameBound {
2386    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2387        match self {
2388            WindowFrameBound::CurrentRow => f.write_str("CURRENT ROW"),
2389            WindowFrameBound::Preceding(None) => f.write_str("UNBOUNDED PRECEDING"),
2390            WindowFrameBound::Following(None) => f.write_str("UNBOUNDED FOLLOWING"),
2391            WindowFrameBound::Preceding(Some(n)) => write!(f, "{n} PRECEDING"),
2392            WindowFrameBound::Following(Some(n)) => write!(f, "{n} FOLLOWING"),
2393        }
2394    }
2395}
2396
2397#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2398#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2399#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2400/// Indicates partition operation type for partition management statements.
2401pub enum AddDropSync {
2402    /// Add partitions.
2403    ADD,
2404    /// Drop partitions.
2405    DROP,
2406    /// Sync partitions.
2407    SYNC,
2408}
2409
2410impl fmt::Display for AddDropSync {
2411    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2412        match self {
2413            AddDropSync::SYNC => f.write_str("SYNC PARTITIONS"),
2414            AddDropSync::DROP => f.write_str("DROP PARTITIONS"),
2415            AddDropSync::ADD => f.write_str("ADD PARTITIONS"),
2416        }
2417    }
2418}
2419
2420#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2421#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2422#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2423/// Object kinds supported by `SHOW CREATE` statements.
2424pub enum ShowCreateObject {
2425    /// An event object for `SHOW CREATE EVENT`.
2426    Event,
2427    /// A function object for `SHOW CREATE FUNCTION`.
2428    Function,
2429    /// A procedure object for `SHOW CREATE PROCEDURE`.
2430    Procedure,
2431    /// A table object for `SHOW CREATE TABLE`.
2432    Table,
2433    /// A trigger object for `SHOW CREATE TRIGGER`.
2434    Trigger,
2435    /// A view object for `SHOW CREATE VIEW`.
2436    View,
2437}
2438
2439impl fmt::Display for ShowCreateObject {
2440    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2441        match self {
2442            ShowCreateObject::Event => f.write_str("EVENT"),
2443            ShowCreateObject::Function => f.write_str("FUNCTION"),
2444            ShowCreateObject::Procedure => f.write_str("PROCEDURE"),
2445            ShowCreateObject::Table => f.write_str("TABLE"),
2446            ShowCreateObject::Trigger => f.write_str("TRIGGER"),
2447            ShowCreateObject::View => f.write_str("VIEW"),
2448        }
2449    }
2450}
2451
2452#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2453#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2454#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2455/// Objects that can be targeted by a `COMMENT` statement.
2456pub enum CommentObject {
2457    /// A collation.
2458    Collation,
2459    /// A table column.
2460    Column,
2461    /// A database.
2462    Database,
2463    /// A domain.
2464    Domain,
2465    /// An extension.
2466    Extension,
2467    /// A function.
2468    Function,
2469    /// An index.
2470    Index,
2471    /// A materialized view.
2472    MaterializedView,
2473    /// A procedure.
2474    Procedure,
2475    /// A role.
2476    Role,
2477    /// A schema.
2478    Schema,
2479    /// A sequence.
2480    Sequence,
2481    /// A table.
2482    Table,
2483    /// A type.
2484    Type,
2485    /// A user.
2486    User,
2487    /// A view.
2488    View,
2489}
2490
2491impl fmt::Display for CommentObject {
2492    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2493        match self {
2494            CommentObject::Collation => f.write_str("COLLATION"),
2495            CommentObject::Column => f.write_str("COLUMN"),
2496            CommentObject::Database => f.write_str("DATABASE"),
2497            CommentObject::Domain => f.write_str("DOMAIN"),
2498            CommentObject::Extension => f.write_str("EXTENSION"),
2499            CommentObject::Function => f.write_str("FUNCTION"),
2500            CommentObject::Index => f.write_str("INDEX"),
2501            CommentObject::MaterializedView => f.write_str("MATERIALIZED VIEW"),
2502            CommentObject::Procedure => f.write_str("PROCEDURE"),
2503            CommentObject::Role => f.write_str("ROLE"),
2504            CommentObject::Schema => f.write_str("SCHEMA"),
2505            CommentObject::Sequence => f.write_str("SEQUENCE"),
2506            CommentObject::Table => f.write_str("TABLE"),
2507            CommentObject::Type => f.write_str("TYPE"),
2508            CommentObject::User => f.write_str("USER"),
2509            CommentObject::View => f.write_str("VIEW"),
2510        }
2511    }
2512}
2513
2514#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2515#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2516#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2517/// Password specification variants used in user-related statements.
2518pub enum Password {
2519    /// A concrete password expression.
2520    Password(Expr),
2521    /// Represents a `NULL` password.
2522    NullPassword,
2523}
2524
2525/// A `CASE` statement.
2526///
2527/// Examples:
2528/// ```sql
2529/// CASE
2530///     WHEN EXISTS(SELECT 1)
2531///         THEN SELECT 1 FROM T;
2532///     WHEN EXISTS(SELECT 2)
2533///         THEN SELECT 1 FROM U;
2534///     ELSE
2535///         SELECT 1 FROM V;
2536/// END CASE;
2537/// ```
2538///
2539/// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#case_search_expression)
2540/// [Snowflake](https://docs.snowflake.com/en/sql-reference/snowflake-scripting/case)
2541#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2542#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2543#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2544pub struct CaseStatement {
2545    /// The `CASE` token that starts the statement.
2546    pub case_token: AttachedToken,
2547    /// Optional expression to match against in `CASE ... WHEN`.
2548    pub match_expr: Option<Expr>,
2549    /// The `WHEN ... THEN` blocks of the `CASE` statement.
2550    pub when_blocks: Vec<ConditionalStatementBlock>,
2551    /// Optional `ELSE` block for the `CASE` statement.
2552    pub else_block: Option<ConditionalStatementBlock>,
2553    /// The last token of the statement (`END` or `CASE`).
2554    pub end_case_token: AttachedToken,
2555}
2556
2557impl fmt::Display for CaseStatement {
2558    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2559        let CaseStatement {
2560            case_token: _,
2561            match_expr,
2562            when_blocks,
2563            else_block,
2564            end_case_token: AttachedToken(end),
2565        } = self;
2566
2567        write!(f, "CASE")?;
2568
2569        if let Some(expr) = match_expr {
2570            write!(f, " {expr}")?;
2571        }
2572
2573        if !when_blocks.is_empty() {
2574            write!(f, " {}", display_separated(when_blocks, " "))?;
2575        }
2576
2577        if let Some(else_block) = else_block {
2578            write!(f, " {else_block}")?;
2579        }
2580
2581        write!(f, " END")?;
2582
2583        if let Token::Word(w) = &end.token {
2584            if w.keyword == Keyword::CASE {
2585                write!(f, " CASE")?;
2586            }
2587        }
2588
2589        Ok(())
2590    }
2591}
2592
2593/// An `IF` statement.
2594///
2595/// Example (BigQuery or Snowflake):
2596/// ```sql
2597/// IF TRUE THEN
2598///     SELECT 1;
2599///     SELECT 2;
2600/// ELSEIF TRUE THEN
2601///     SELECT 3;
2602/// ELSE
2603///     SELECT 4;
2604/// END IF
2605/// ```
2606/// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#if)
2607/// [Snowflake](https://docs.snowflake.com/en/sql-reference/snowflake-scripting/if)
2608///
2609/// Example (MSSQL):
2610/// ```sql
2611/// IF 1=1 SELECT 1 ELSE SELECT 2
2612/// ```
2613/// [MSSQL](https://learn.microsoft.com/en-us/sql/t-sql/language-elements/if-else-transact-sql?view=sql-server-ver16)
2614#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2615#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2616#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2617pub struct IfStatement {
2618    /// The initial `IF` block containing the condition and statements.
2619    pub if_block: ConditionalStatementBlock,
2620    /// Additional `ELSEIF` blocks.
2621    pub elseif_blocks: Vec<ConditionalStatementBlock>,
2622    /// Optional `ELSE` block.
2623    pub else_block: Option<ConditionalStatementBlock>,
2624    /// Optional trailing `END` token for the `IF` statement.
2625    pub end_token: Option<AttachedToken>,
2626}
2627
2628impl fmt::Display for IfStatement {
2629    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2630        let IfStatement {
2631            if_block,
2632            elseif_blocks,
2633            else_block,
2634            end_token,
2635        } = self;
2636
2637        write!(f, "{if_block}")?;
2638
2639        for elseif_block in elseif_blocks {
2640            write!(f, " {elseif_block}")?;
2641        }
2642
2643        if let Some(else_block) = else_block {
2644            write!(f, " {else_block}")?;
2645        }
2646
2647        if let Some(AttachedToken(end_token)) = end_token {
2648            write!(f, " END {end_token}")?;
2649        }
2650
2651        Ok(())
2652    }
2653}
2654
2655/// A `WHILE` statement.
2656///
2657/// Example:
2658/// ```sql
2659/// WHILE @@FETCH_STATUS = 0
2660/// BEGIN
2661///    FETCH NEXT FROM c1 INTO @var1, @var2;
2662/// END
2663/// ```
2664///
2665/// [MsSql](https://learn.microsoft.com/en-us/sql/t-sql/language-elements/while-transact-sql)
2666#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2667#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2668#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2669pub struct WhileStatement {
2670    /// Block executed while the condition holds.
2671    pub while_block: ConditionalStatementBlock,
2672}
2673
2674impl fmt::Display for WhileStatement {
2675    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2676        let WhileStatement { while_block } = self;
2677        write!(f, "{while_block}")?;
2678        Ok(())
2679    }
2680}
2681
2682/// A block within a [Statement::Case] or [Statement::If] or [Statement::While]-like statement
2683///
2684/// Example 1:
2685/// ```sql
2686/// WHEN EXISTS(SELECT 1) THEN SELECT 1;
2687/// ```
2688///
2689/// Example 2:
2690/// ```sql
2691/// IF TRUE THEN SELECT 1; SELECT 2;
2692/// ```
2693///
2694/// Example 3:
2695/// ```sql
2696/// ELSE SELECT 1; SELECT 2;
2697/// ```
2698///
2699/// Example 4:
2700/// ```sql
2701/// WHILE @@FETCH_STATUS = 0
2702/// BEGIN
2703///    FETCH NEXT FROM c1 INTO @var1, @var2;
2704/// END
2705/// ```
2706#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2707#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2708#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2709pub struct ConditionalStatementBlock {
2710    /// Token representing the start of the block (e.g., WHEN/IF/WHILE).
2711    pub start_token: AttachedToken,
2712    /// Optional condition expression for the block.
2713    pub condition: Option<Expr>,
2714    /// Optional token for the `THEN` keyword.
2715    pub then_token: Option<AttachedToken>,
2716    /// The statements contained in this conditional block.
2717    pub conditional_statements: ConditionalStatements,
2718}
2719
2720impl ConditionalStatementBlock {
2721    /// Get the statements in this conditional block.
2722    pub fn statements(&self) -> &Vec<Statement> {
2723        self.conditional_statements.statements()
2724    }
2725}
2726
2727impl fmt::Display for ConditionalStatementBlock {
2728    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2729        let ConditionalStatementBlock {
2730            start_token: AttachedToken(start_token),
2731            condition,
2732            then_token,
2733            conditional_statements,
2734        } = self;
2735
2736        write!(f, "{start_token}")?;
2737
2738        if let Some(condition) = condition {
2739            write!(f, " {condition}")?;
2740        }
2741
2742        if then_token.is_some() {
2743            write!(f, " THEN")?;
2744        }
2745
2746        if !conditional_statements.statements().is_empty() {
2747            write!(f, " {conditional_statements}")?;
2748        }
2749
2750        Ok(())
2751    }
2752}
2753
2754/// A list of statements in a [ConditionalStatementBlock].
2755#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2756#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2757#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2758/// Statements used inside conditional blocks (`IF`, `WHEN`, `WHILE`).
2759pub enum ConditionalStatements {
2760    /// Simple sequence of statements (no `BEGIN`/`END`).
2761    Sequence {
2762        /// The statements in the sequence.
2763        statements: Vec<Statement>,
2764    },
2765    /// Block enclosed by `BEGIN` and `END`.
2766    BeginEnd(BeginEndStatements),
2767}
2768
2769impl ConditionalStatements {
2770    /// Get the statements in this conditional statements block.
2771    pub fn statements(&self) -> &Vec<Statement> {
2772        match self {
2773            ConditionalStatements::Sequence { statements } => statements,
2774            ConditionalStatements::BeginEnd(bes) => &bes.statements,
2775        }
2776    }
2777}
2778
2779impl fmt::Display for ConditionalStatements {
2780    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2781        match self {
2782            ConditionalStatements::Sequence { statements } => {
2783                if !statements.is_empty() {
2784                    format_statement_list(f, statements)?;
2785                }
2786                Ok(())
2787            }
2788            ConditionalStatements::BeginEnd(bes) => write!(f, "{bes}"),
2789        }
2790    }
2791}
2792
2793/// Represents a list of statements enclosed within `BEGIN` and `END` keywords.
2794/// Example:
2795/// ```sql
2796/// BEGIN
2797///     SELECT 1;
2798///     SELECT 2;
2799/// END
2800/// ```
2801#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2802#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2803#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2804pub struct BeginEndStatements {
2805    /// Token representing the `BEGIN` keyword (may include span info).
2806    pub begin_token: AttachedToken,
2807    /// Statements contained within the block.
2808    pub statements: Vec<Statement>,
2809    /// Token representing the `END` keyword (may include span info).
2810    pub end_token: AttachedToken,
2811}
2812
2813impl fmt::Display for BeginEndStatements {
2814    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2815        let BeginEndStatements {
2816            begin_token: AttachedToken(begin_token),
2817            statements,
2818            end_token: AttachedToken(end_token),
2819        } = self;
2820
2821        if begin_token.token != Token::EOF {
2822            write!(f, "{begin_token} ")?;
2823        }
2824        if !statements.is_empty() {
2825            format_statement_list(f, statements)?;
2826        }
2827        if end_token.token != Token::EOF {
2828            write!(f, " {end_token}")?;
2829        }
2830        Ok(())
2831    }
2832}
2833
2834/// A `RAISE` statement.
2835///
2836/// Examples:
2837/// ```sql
2838/// RAISE USING MESSAGE = 'error';
2839///
2840/// RAISE myerror;
2841/// ```
2842///
2843/// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#raise)
2844/// [Snowflake](https://docs.snowflake.com/en/sql-reference/snowflake-scripting/raise)
2845#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2846#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2847#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2848pub struct RaiseStatement {
2849    /// Optional value provided to the RAISE statement.
2850    pub value: Option<RaiseStatementValue>,
2851}
2852
2853impl fmt::Display for RaiseStatement {
2854    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2855        let RaiseStatement { value } = self;
2856
2857        write!(f, "RAISE")?;
2858        if let Some(value) = value {
2859            write!(f, " {value}")?;
2860        }
2861
2862        Ok(())
2863    }
2864}
2865
2866/// Represents the error value of a [RaiseStatement].
2867#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2868#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2869#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2870pub enum RaiseStatementValue {
2871    /// `RAISE USING MESSAGE = 'error'`
2872    UsingMessage(Expr),
2873    /// `RAISE myerror`
2874    Expr(Expr),
2875}
2876
2877impl fmt::Display for RaiseStatementValue {
2878    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2879        match self {
2880            RaiseStatementValue::Expr(expr) => write!(f, "{expr}"),
2881            RaiseStatementValue::UsingMessage(expr) => write!(f, "USING MESSAGE = {expr}"),
2882        }
2883    }
2884}
2885
2886/// A MSSQL `THROW` statement.
2887///
2888/// ```sql
2889/// THROW [ error_number, message, state ]
2890/// ```
2891///
2892/// [MSSQL](https://learn.microsoft.com/en-us/sql/t-sql/language-elements/throw-transact-sql)
2893#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2894#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2895#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2896pub struct ThrowStatement {
2897    /// Error number expression.
2898    pub error_number: Option<Box<Expr>>,
2899    /// Error message expression.
2900    pub message: Option<Box<Expr>>,
2901    /// State expression.
2902    pub state: Option<Box<Expr>>,
2903}
2904
2905impl fmt::Display for ThrowStatement {
2906    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2907        let ThrowStatement {
2908            error_number,
2909            message,
2910            state,
2911        } = self;
2912
2913        write!(f, "THROW")?;
2914        if let (Some(error_number), Some(message), Some(state)) = (error_number, message, state) {
2915            write!(f, " {error_number}, {message}, {state}")?;
2916        }
2917        Ok(())
2918    }
2919}
2920
2921/// Represents an expression assignment within a variable `DECLARE` statement.
2922///
2923/// Examples:
2924/// ```sql
2925/// DECLARE variable_name := 42
2926/// DECLARE variable_name DEFAULT 42
2927/// ```
2928#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2929#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2930#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2931pub enum DeclareAssignment {
2932    /// Plain expression specified.
2933    Expr(Box<Expr>),
2934
2935    /// Expression assigned via the `DEFAULT` keyword
2936    Default(Box<Expr>),
2937
2938    /// Expression assigned via the `:=` syntax
2939    ///
2940    /// Example:
2941    /// ```sql
2942    /// DECLARE variable_name := 42;
2943    /// ```
2944    DuckAssignment(Box<Expr>),
2945
2946    /// Expression via the `FOR` keyword
2947    ///
2948    /// Example:
2949    /// ```sql
2950    /// DECLARE c1 CURSOR FOR res
2951    /// ```
2952    For(Box<Expr>),
2953
2954    /// Expression via the `=` syntax.
2955    ///
2956    /// Example:
2957    /// ```sql
2958    /// DECLARE @variable AS INT = 100
2959    /// ```
2960    MsSqlAssignment(Box<Expr>),
2961}
2962
2963impl fmt::Display for DeclareAssignment {
2964    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2965        match self {
2966            DeclareAssignment::Expr(expr) => {
2967                write!(f, "{expr}")
2968            }
2969            DeclareAssignment::Default(expr) => {
2970                write!(f, "DEFAULT {expr}")
2971            }
2972            DeclareAssignment::DuckAssignment(expr) => {
2973                write!(f, ":= {expr}")
2974            }
2975            DeclareAssignment::MsSqlAssignment(expr) => {
2976                write!(f, "= {expr}")
2977            }
2978            DeclareAssignment::For(expr) => {
2979                write!(f, "FOR {expr}")
2980            }
2981        }
2982    }
2983}
2984
2985/// Represents the type of a `DECLARE` statement.
2986#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2987#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2988#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2989pub enum DeclareType {
2990    /// Cursor variable type. e.g. [Snowflake] [PostgreSQL] [MsSql]
2991    ///
2992    /// [Snowflake]: https://docs.snowflake.com/en/developer-guide/snowflake-scripting/cursors#declaring-a-cursor
2993    /// [PostgreSQL]: https://www.postgresql.org/docs/current/plpgsql-cursors.html
2994    /// [MsSql]: https://learn.microsoft.com/en-us/sql/t-sql/language-elements/declare-cursor-transact-sql
2995    Cursor,
2996
2997    /// Result set variable type. [Snowflake]
2998    ///
2999    /// Syntax:
3000    /// ```text
3001    /// <resultset_name> RESULTSET [ { DEFAULT | := } ( <query> ) ] ;
3002    /// ```
3003    /// [Snowflake]: https://docs.snowflake.com/en/sql-reference/snowflake-scripting/declare#resultset-declaration-syntax
3004    ResultSet,
3005
3006    /// Exception declaration syntax. [Snowflake]
3007    ///
3008    /// Syntax:
3009    /// ```text
3010    /// <exception_name> EXCEPTION [ ( <exception_number> , '<exception_message>' ) ] ;
3011    /// ```
3012    /// [Snowflake]: https://docs.snowflake.com/en/sql-reference/snowflake-scripting/declare#exception-declaration-syntax
3013    Exception,
3014}
3015
3016impl fmt::Display for DeclareType {
3017    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3018        match self {
3019            DeclareType::Cursor => {
3020                write!(f, "CURSOR")
3021            }
3022            DeclareType::ResultSet => {
3023                write!(f, "RESULTSET")
3024            }
3025            DeclareType::Exception => {
3026                write!(f, "EXCEPTION")
3027            }
3028        }
3029    }
3030}
3031
3032/// A `DECLARE` statement.
3033/// [PostgreSQL] [Snowflake] [BigQuery]
3034///
3035/// Examples:
3036/// ```sql
3037/// DECLARE variable_name := 42
3038/// DECLARE liahona CURSOR FOR SELECT * FROM films;
3039/// ```
3040///
3041/// [PostgreSQL]: https://www.postgresql.org/docs/current/sql-declare.html
3042/// [Snowflake]: https://docs.snowflake.com/en/sql-reference/snowflake-scripting/declare
3043/// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#declare
3044#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3045#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3046#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3047pub struct Declare {
3048    /// The name(s) being declared.
3049    /// Example: `DECLARE a, b, c DEFAULT 42;
3050    pub names: Vec<Ident>,
3051    /// Data-type assigned to the declared variable.
3052    /// Example: `DECLARE x INT64 DEFAULT 42;
3053    pub data_type: Option<DataType>,
3054    /// Expression being assigned to the declared variable.
3055    pub assignment: Option<DeclareAssignment>,
3056    /// Represents the type of the declared variable.
3057    pub declare_type: Option<DeclareType>,
3058    /// Causes the cursor to return data in binary rather than in text format.
3059    pub binary: Option<bool>,
3060    /// None = Not specified
3061    /// Some(true) = INSENSITIVE
3062    /// Some(false) = ASENSITIVE
3063    pub sensitive: Option<bool>,
3064    /// None = Not specified
3065    /// Some(true) = SCROLL
3066    /// Some(false) = NO SCROLL
3067    pub scroll: Option<bool>,
3068    /// None = Not specified
3069    /// Some(true) = WITH HOLD, specifies that the cursor can continue to be used after the transaction that created it successfully commits
3070    /// Some(false) = WITHOUT HOLD, specifies that the cursor cannot be used outside of the transaction that created it
3071    pub hold: Option<bool>,
3072    /// `FOR <query>` clause in a CURSOR declaration.
3073    pub for_query: Option<Box<Query>>,
3074}
3075
3076impl fmt::Display for Declare {
3077    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3078        let Declare {
3079            names,
3080            data_type,
3081            assignment,
3082            declare_type,
3083            binary,
3084            sensitive,
3085            scroll,
3086            hold,
3087            for_query,
3088        } = self;
3089        write!(f, "{}", display_comma_separated(names))?;
3090
3091        if let Some(true) = binary {
3092            write!(f, " BINARY")?;
3093        }
3094
3095        if let Some(sensitive) = sensitive {
3096            if *sensitive {
3097                write!(f, " INSENSITIVE")?;
3098            } else {
3099                write!(f, " ASENSITIVE")?;
3100            }
3101        }
3102
3103        if let Some(scroll) = scroll {
3104            if *scroll {
3105                write!(f, " SCROLL")?;
3106            } else {
3107                write!(f, " NO SCROLL")?;
3108            }
3109        }
3110
3111        if let Some(declare_type) = declare_type {
3112            write!(f, " {declare_type}")?;
3113        }
3114
3115        if let Some(hold) = hold {
3116            if *hold {
3117                write!(f, " WITH HOLD")?;
3118            } else {
3119                write!(f, " WITHOUT HOLD")?;
3120            }
3121        }
3122
3123        if let Some(query) = for_query {
3124            write!(f, " FOR {query}")?;
3125        }
3126
3127        if let Some(data_type) = data_type {
3128            write!(f, " {data_type}")?;
3129        }
3130
3131        if let Some(expr) = assignment {
3132            write!(f, " {expr}")?;
3133        }
3134        Ok(())
3135    }
3136}
3137
3138/// Sql options of a `CREATE TABLE` statement.
3139#[derive(Debug, Default, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3140#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3141#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3142/// Options allowed within a `CREATE TABLE` statement.
3143pub enum CreateTableOptions {
3144    /// No options specified.
3145    #[default]
3146    None,
3147    /// Options specified using the `WITH` keyword, e.g. `WITH (k = v)`.
3148    With(Vec<SqlOption>),
3149    /// Options specified using the `OPTIONS(...)` clause.
3150    Options(Vec<SqlOption>),
3151    /// Plain space-separated options.
3152    Plain(Vec<SqlOption>),
3153    /// Table properties (e.g., TBLPROPERTIES / storage properties).
3154    TableProperties(Vec<SqlOption>),
3155}
3156
3157impl fmt::Display for CreateTableOptions {
3158    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3159        match self {
3160            CreateTableOptions::With(with_options) => {
3161                write!(f, "WITH ({})", display_comma_separated(with_options))
3162            }
3163            CreateTableOptions::Options(options) => {
3164                write!(f, "OPTIONS({})", display_comma_separated(options))
3165            }
3166            CreateTableOptions::TableProperties(options) => {
3167                write!(f, "TBLPROPERTIES ({})", display_comma_separated(options))
3168            }
3169            CreateTableOptions::Plain(options) => {
3170                write!(f, "{}", display_separated(options, " "))
3171            }
3172            CreateTableOptions::None => Ok(()),
3173        }
3174    }
3175}
3176
3177/// A `FROM` clause within a `DELETE` statement.
3178///
3179/// Syntax
3180/// ```sql
3181/// [FROM] table
3182/// ```
3183#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3184#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3185#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3186pub enum FromTable {
3187    /// An explicit `FROM` keyword was specified.
3188    WithFromKeyword(Vec<TableWithJoins>),
3189    /// BigQuery: `FROM` keyword was omitted.
3190    /// <https://cloud.google.com/bigquery/docs/reference/standard-sql/dml-syntax#delete_statement>
3191    WithoutKeyword(Vec<TableWithJoins>),
3192}
3193impl Display for FromTable {
3194    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3195        match self {
3196            FromTable::WithFromKeyword(tables) => {
3197                write!(f, "FROM {}", display_comma_separated(tables))
3198            }
3199            FromTable::WithoutKeyword(tables) => {
3200                write!(f, "{}", display_comma_separated(tables))
3201            }
3202        }
3203    }
3204}
3205
3206#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3207#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3208#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3209/// Variants for the `SET` family of statements.
3210pub enum Set {
3211    /// SQL Standard-style
3212    /// SET a = 1;
3213    /// `SET var = value` (standard SQL-style assignment).
3214    SingleAssignment {
3215        /// Optional scope modifier (`SESSION` / `LOCAL`).
3216        scope: Option<ContextModifier>,
3217        /// Whether this is a Hive-style `HIVEVAR:` assignment.
3218        hivevar: bool,
3219        /// Variable name to assign.
3220        variable: ObjectName,
3221        /// Values assigned to the variable.
3222        values: Vec<Expr>,
3223    },
3224    /// Snowflake-style
3225    /// SET (a, b, ..) = (1, 2, ..);
3226    /// `SET (a, b) = (1, 2)` (tuple assignment syntax).
3227    ParenthesizedAssignments {
3228        /// Variables being assigned in tuple form.
3229        variables: Vec<ObjectName>,
3230        /// Corresponding values for the variables.
3231        values: Vec<Expr>,
3232    },
3233    /// MySQL-style
3234    /// SET a = 1, b = 2, ..;
3235    /// `SET a = 1, b = 2` (MySQL-style comma-separated assignments).
3236    MultipleAssignments {
3237        /// List of `SET` assignments (MySQL-style comma-separated).
3238        assignments: Vec<SetAssignment>,
3239    },
3240    /// Session authorization for Postgres/Redshift
3241    ///
3242    /// ```sql
3243    /// SET SESSION AUTHORIZATION { user_name | DEFAULT }
3244    /// ```
3245    ///
3246    /// See <https://www.postgresql.org/docs/current/sql-set-session-authorization.html>
3247    /// See <https://docs.aws.amazon.com/redshift/latest/dg/r_SET_SESSION_AUTHORIZATION.html>
3248    SetSessionAuthorization(SetSessionAuthorizationParam),
3249    /// MS-SQL session
3250    ///
3251    /// See <https://learn.microsoft.com/en-us/sql/t-sql/statements/set-statements-transact-sql>
3252    SetSessionParam(SetSessionParamKind),
3253    /// ```sql
3254    /// SET [ SESSION | LOCAL ] ROLE role_name
3255    /// ```
3256    ///
3257    /// Sets session state. Examples: [ANSI][1], [Postgresql][2], [MySQL][3], and [Oracle][4]
3258    ///
3259    /// [1]: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#set-role-statement
3260    /// [2]: https://www.postgresql.org/docs/14/sql-set-role.html
3261    /// [3]: https://dev.mysql.com/doc/refman/8.0/en/set-role.html
3262    /// [4]: https://docs.oracle.com/cd/B19306_01/server.102/b14200/statements_10004.htm
3263    SetRole {
3264        /// Non-ANSI optional identifier to inform if the role is defined inside the current session (`SESSION`) or transaction (`LOCAL`).
3265        context_modifier: Option<ContextModifier>,
3266        /// Role name. If NONE is specified, then the current role name is removed.
3267        role_name: Option<Ident>,
3268    },
3269    /// ```sql
3270    /// SET TIME ZONE <value>
3271    /// ```
3272    ///
3273    /// Note: this is a PostgreSQL-specific statements
3274    /// `SET TIME ZONE <value>` is an alias for `SET timezone TO <value>` in PostgreSQL
3275    /// However, we allow it for all dialects.
3276    /// `SET TIME ZONE` statement. `local` indicates the `LOCAL` keyword.
3277    /// `SET TIME ZONE <value>` statement.
3278    SetTimeZone {
3279        /// Whether the `LOCAL` keyword was specified.
3280        local: bool,
3281        /// Time zone expression value.
3282        value: Expr,
3283    },
3284    /// ```sql
3285    /// SET NAMES 'charset_name' [COLLATE 'collation_name']
3286    /// ```
3287    SetNames {
3288        /// Character set name to set.
3289        charset_name: Ident,
3290        /// Optional collation name.
3291        collation_name: Option<String>,
3292    },
3293    /// ```sql
3294    /// SET NAMES DEFAULT
3295    /// ```
3296    ///
3297    /// Note: this is a MySQL-specific statement.
3298    SetNamesDefault {},
3299    /// ```sql
3300    /// SET TRANSACTION ...
3301    /// ```
3302    SetTransaction {
3303        /// Transaction modes (e.g., ISOLATION LEVEL, READ ONLY).
3304        modes: Vec<TransactionMode>,
3305        /// Optional snapshot value for transaction snapshot control.
3306        snapshot: Option<ValueWithSpan>,
3307        /// `true` when the `SESSION` keyword was used.
3308        session: bool,
3309    },
3310}
3311
3312impl Display for Set {
3313    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3314        match self {
3315            Self::ParenthesizedAssignments { variables, values } => write!(
3316                f,
3317                "SET ({}) = ({})",
3318                display_comma_separated(variables),
3319                display_comma_separated(values)
3320            ),
3321            Self::MultipleAssignments { assignments } => {
3322                write!(f, "SET {}", display_comma_separated(assignments))
3323            }
3324            Self::SetRole {
3325                context_modifier,
3326                role_name,
3327            } => {
3328                let role_name = role_name.clone().unwrap_or_else(|| Ident::new("NONE"));
3329                write!(
3330                    f,
3331                    "SET {modifier}ROLE {role_name}",
3332                    modifier = context_modifier.map(|m| format!("{m}")).unwrap_or_default()
3333                )
3334            }
3335            Self::SetSessionAuthorization(kind) => write!(f, "SET SESSION AUTHORIZATION {kind}"),
3336            Self::SetSessionParam(kind) => write!(f, "SET {kind}"),
3337            Self::SetTransaction {
3338                modes,
3339                snapshot,
3340                session,
3341            } => {
3342                if *session {
3343                    write!(f, "SET SESSION CHARACTERISTICS AS TRANSACTION")?;
3344                } else {
3345                    write!(f, "SET TRANSACTION")?;
3346                }
3347                if !modes.is_empty() {
3348                    write!(f, " {}", display_comma_separated(modes))?;
3349                }
3350                if let Some(snapshot_id) = snapshot {
3351                    write!(f, " SNAPSHOT {snapshot_id}")?;
3352                }
3353                Ok(())
3354            }
3355            Self::SetTimeZone { local, value } => {
3356                f.write_str("SET ")?;
3357                if *local {
3358                    f.write_str("LOCAL ")?;
3359                }
3360                write!(f, "TIME ZONE {value}")
3361            }
3362            Self::SetNames {
3363                charset_name,
3364                collation_name,
3365            } => {
3366                write!(f, "SET NAMES {charset_name}")?;
3367
3368                if let Some(collation) = collation_name {
3369                    f.write_str(" COLLATE ")?;
3370                    f.write_str(collation)?;
3371                };
3372
3373                Ok(())
3374            }
3375            Self::SetNamesDefault {} => {
3376                f.write_str("SET NAMES DEFAULT")?;
3377
3378                Ok(())
3379            }
3380            Set::SingleAssignment {
3381                scope,
3382                hivevar,
3383                variable,
3384                values,
3385            } => {
3386                write!(
3387                    f,
3388                    "SET {}{}{} = {}",
3389                    scope.map(|s| format!("{s}")).unwrap_or_default(),
3390                    if *hivevar { "HIVEVAR:" } else { "" },
3391                    variable,
3392                    display_comma_separated(values)
3393                )
3394            }
3395        }
3396    }
3397}
3398
3399/// A representation of a `WHEN` arm with all the identifiers catched and the statements to execute
3400/// for the arm.
3401///
3402/// Snowflake: <https://docs.snowflake.com/en/sql-reference/snowflake-scripting/exception>
3403/// BigQuery: <https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#beginexceptionend>
3404#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3405#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3406#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3407pub struct ExceptionWhen {
3408    /// Identifiers that trigger this branch (error conditions).
3409    pub idents: Vec<Ident>,
3410    /// Statements to execute when the condition matches.
3411    pub statements: Vec<Statement>,
3412}
3413
3414impl Display for ExceptionWhen {
3415    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3416        write!(
3417            f,
3418            "WHEN {idents} THEN",
3419            idents = display_separated(&self.idents, " OR ")
3420        )?;
3421
3422        if !self.statements.is_empty() {
3423            write!(f, " ")?;
3424            format_statement_list(f, &self.statements)?;
3425        }
3426
3427        Ok(())
3428    }
3429}
3430
3431/// ANALYZE statement
3432///
3433/// Supported syntax varies by dialect:
3434/// - Hive: `ANALYZE TABLE t [PARTITION (...)] COMPUTE STATISTICS [NOSCAN] [FOR COLUMNS [col1, ...]] [CACHE METADATA]`
3435/// - PostgreSQL: `ANALYZE [VERBOSE] [t [(col1, ...)]]` See <https://www.postgresql.org/docs/current/sql-analyze.html>
3436/// - General: `ANALYZE [TABLE] t`
3437#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3438#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3439#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3440pub struct Analyze {
3441    #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
3442    /// Name of the table to analyze. `None` for bare `ANALYZE`.
3443    pub table_name: Option<ObjectName>,
3444    /// Optional partition expressions to restrict the analysis.
3445    pub partitions: Option<Vec<Expr>>,
3446    /// `true` when analyzing specific columns (Hive `FOR COLUMNS` syntax).
3447    pub for_columns: bool,
3448    /// Columns to analyze.
3449    pub columns: Vec<Ident>,
3450    /// Whether to cache metadata before analyzing.
3451    pub cache_metadata: bool,
3452    /// Whether to skip scanning the table.
3453    pub noscan: bool,
3454    /// Whether to compute statistics during analysis.
3455    pub compute_statistics: bool,
3456    /// Whether the `TABLE` keyword was present.
3457    pub has_table_keyword: bool,
3458}
3459
3460impl fmt::Display for Analyze {
3461    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3462        write!(f, "ANALYZE")?;
3463        if let Some(ref table_name) = self.table_name {
3464            if self.has_table_keyword {
3465                write!(f, " TABLE")?;
3466            }
3467            write!(f, " {table_name}")?;
3468        }
3469        if !self.for_columns && !self.columns.is_empty() {
3470            write!(f, " ({})", display_comma_separated(&self.columns))?;
3471        }
3472        if let Some(ref parts) = self.partitions {
3473            if !parts.is_empty() {
3474                write!(f, " PARTITION ({})", display_comma_separated(parts))?;
3475            }
3476        }
3477        if self.compute_statistics {
3478            write!(f, " COMPUTE STATISTICS")?;
3479        }
3480        if self.noscan {
3481            write!(f, " NOSCAN")?;
3482        }
3483        if self.cache_metadata {
3484            write!(f, " CACHE METADATA")?;
3485        }
3486        if self.for_columns {
3487            write!(f, " FOR COLUMNS")?;
3488            if !self.columns.is_empty() {
3489                write!(f, " {}", display_comma_separated(&self.columns))?;
3490            }
3491        }
3492        Ok(())
3493    }
3494}
3495
3496/// A top-level statement (SELECT, INSERT, CREATE, etc.)
3497#[allow(clippy::large_enum_variant)]
3498#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3499#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3500#[cfg_attr(
3501    feature = "visitor",
3502    derive(Visit, VisitMut),
3503    visit(with = "visit_statement")
3504)]
3505pub enum Statement {
3506    /// ```sql
3507    /// ANALYZE
3508    /// ```
3509    /// Analyze (Hive)
3510    Analyze(Analyze),
3511    /// `SET` statements (session, transaction, timezone, etc.).
3512    Set(Set),
3513    /// ```sql
3514    /// TRUNCATE
3515    /// ```
3516    /// Truncate (Hive)
3517    Truncate(Truncate),
3518    /// ```sql
3519    /// MSCK
3520    /// ```
3521    /// Msck (Hive)
3522    Msck(Msck),
3523    /// ```sql
3524    /// SELECT
3525    /// ```
3526    Query(Box<Query>),
3527    /// ```sql
3528    /// INSERT
3529    /// ```
3530    Insert(Insert),
3531    /// ```sql
3532    /// INSTALL
3533    /// ```
3534    Install {
3535        /// Only for DuckDB
3536        extension_name: Ident,
3537    },
3538    /// ```sql
3539    /// LOAD
3540    /// ```
3541    Load {
3542        /// Only for DuckDB
3543        extension_name: Ident,
3544    },
3545    // TODO: Support ROW FORMAT
3546    /// LOAD DATA from a directory or query source.
3547    Directory {
3548        /// Whether to overwrite existing files.
3549        overwrite: bool,
3550        /// Whether the directory is local to the server.
3551        local: bool,
3552        /// Path to the directory or files.
3553        path: String,
3554        /// Optional file format for the data.
3555        file_format: Option<FileFormat>,
3556        /// Source query providing data to load.
3557        source: Box<Query>,
3558    },
3559    /// A `CASE` statement.
3560    Case(CaseStatement),
3561    /// An `IF` statement.
3562    If(IfStatement),
3563    /// A `WHILE` statement.
3564    While(WhileStatement),
3565    /// A `RAISE` statement.
3566    Raise(RaiseStatement),
3567    /// ```sql
3568    /// CALL <function>
3569    /// ```
3570    Call(Function),
3571    /// ```sql
3572    /// COPY [TO | FROM] ...
3573    /// ```
3574    Copy {
3575        /// The source of 'COPY TO', or the target of 'COPY FROM'
3576        source: CopySource,
3577        /// If true, is a 'COPY TO' statement. If false is a 'COPY FROM'
3578        to: bool,
3579        /// The target of 'COPY TO', or the source of 'COPY FROM'
3580        target: CopyTarget,
3581        /// WITH options (from PostgreSQL version 9.0)
3582        options: Vec<CopyOption>,
3583        /// WITH options (before PostgreSQL version 9.0)
3584        legacy_options: Vec<CopyLegacyOption>,
3585        /// VALUES a vector of values to be copied
3586        values: Vec<Option<String>>,
3587    },
3588    /// ```sql
3589    /// COPY INTO <table> | <location>
3590    /// ```
3591    /// See:
3592    /// <https://docs.snowflake.com/en/sql-reference/sql/copy-into-table>
3593    /// <https://docs.snowflake.com/en/sql-reference/sql/copy-into-location>
3594    ///
3595    /// Copy Into syntax available for Snowflake is different than the one implemented in
3596    /// Postgres. Although they share common prefix, it is reasonable to implement them
3597    /// in different enums. This can be refactored later once custom dialects
3598    /// are allowed to have custom Statements.
3599    CopyIntoSnowflake {
3600        /// Kind of COPY INTO operation (table or location).
3601        kind: CopyIntoSnowflakeKind,
3602        /// Target object for the COPY INTO operation.
3603        into: ObjectName,
3604        /// Optional list of target columns.
3605        into_columns: Option<Vec<Ident>>,
3606        /// Optional source object name (staged data).
3607        from_obj: Option<ObjectName>,
3608        /// Optional alias for the source object.
3609        from_obj_alias: Option<Ident>,
3610        /// Stage-specific parameters (e.g., credentials, path).
3611        stage_params: StageParamsObject,
3612        /// Optional list of transformations applied when loading.
3613        from_transformations: Option<Vec<StageLoadSelectItemKind>>,
3614        /// Optional source query instead of a staged object.
3615        from_query: Option<Box<Query>>,
3616        /// Optional list of specific file names to load.
3617        files: Option<Vec<String>>,
3618        /// Optional filename matching pattern.
3619        pattern: Option<String>,
3620        /// File format options.
3621        file_format: KeyValueOptions,
3622        /// Additional copy options.
3623        copy_options: KeyValueOptions,
3624        /// Optional validation mode string.
3625        validation_mode: Option<String>,
3626        /// Optional partition expression for loading.
3627        partition: Option<Box<Expr>>,
3628    },
3629    /// ```sql
3630    /// OPEN cursor_name
3631    /// ```
3632    /// Opens a cursor.
3633    Open(OpenStatement),
3634    /// ```sql
3635    /// CLOSE
3636    /// ```
3637    /// Closes the portal underlying an open cursor.
3638    Close {
3639        /// Cursor name
3640        cursor: CloseCursor,
3641    },
3642    /// ```sql
3643    /// UPDATE
3644    /// ```
3645    Update(Update),
3646    /// ```sql
3647    /// DELETE
3648    /// ```
3649    Delete(Delete),
3650    /// ```sql
3651    /// CREATE VIEW
3652    /// ```
3653    CreateView(CreateView),
3654    /// ```sql
3655    /// CREATE TABLE
3656    /// ```
3657    CreateTable(CreateTable),
3658    /// ```sql
3659    /// CREATE VIRTUAL TABLE .. USING <module_name> (<module_args>)`
3660    /// ```
3661    /// Sqlite specific statement
3662    CreateVirtualTable {
3663        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
3664        /// Name of the virtual table module instance.
3665        name: ObjectName,
3666        /// `true` when `IF NOT EXISTS` was specified.
3667        if_not_exists: bool,
3668        /// Module name used by the virtual table.
3669        module_name: Ident,
3670        /// Arguments passed to the module.
3671        module_args: Vec<Ident>,
3672    },
3673    /// ```sql
3674    /// `CREATE INDEX`
3675    /// ```
3676    CreateIndex(CreateIndex),
3677    /// ```sql
3678    /// CREATE ROLE
3679    /// ```
3680    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createrole.html)
3681    CreateRole(CreateRole),
3682    /// ```sql
3683    /// CREATE SECRET
3684    /// ```
3685    /// See [DuckDB](https://duckdb.org/docs/sql/statements/create_secret.html)
3686    CreateSecret {
3687        /// `true` when `OR REPLACE` was specified.
3688        or_replace: bool,
3689        /// Optional `TEMPORARY` flag.
3690        temporary: Option<bool>,
3691        /// `true` when `IF NOT EXISTS` was present.
3692        if_not_exists: bool,
3693        /// Optional secret name.
3694        name: Option<Ident>,
3695        /// Optional storage specifier identifier.
3696        storage_specifier: Option<Ident>,
3697        /// The secret type identifier.
3698        secret_type: Ident,
3699        /// Additional secret options.
3700        options: Vec<SecretOption>,
3701    },
3702    /// A `CREATE SERVER` statement.
3703    CreateServer(CreateServerStatement),
3704    /// ```sql
3705    /// CREATE FOREIGN DATA WRAPPER
3706    /// ```
3707    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createforeigndatawrapper.html)
3708    CreateForeignDataWrapper(CreateForeignDataWrapper),
3709    /// ```sql
3710    /// CREATE FOREIGN TABLE
3711    /// ```
3712    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createforeigntable.html)
3713    CreateForeignTable(CreateForeignTable),
3714    /// ```sql
3715    /// CREATE POLICY
3716    /// ```
3717    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createpolicy.html)
3718    CreatePolicy(CreatePolicy),
3719    /// ```sql
3720    /// CREATE CONNECTOR
3721    /// ```
3722    /// See [Hive](https://cwiki.apache.org/confluence/pages/viewpage.action?pageId=27362034#LanguageManualDDL-CreateDataConnectorCreateConnector)
3723    CreateConnector(CreateConnector),
3724    /// ```sql
3725    /// CREATE OPERATOR
3726    /// ```
3727    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createoperator.html)
3728    CreateOperator(CreateOperator),
3729    /// ```sql
3730    /// CREATE OPERATOR FAMILY
3731    /// ```
3732    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createopfamily.html)
3733    CreateOperatorFamily(CreateOperatorFamily),
3734    /// ```sql
3735    /// CREATE OPERATOR CLASS
3736    /// ```
3737    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createopclass.html)
3738    CreateOperatorClass(CreateOperatorClass),
3739    /// ```sql
3740    /// CREATE AGGREGATE
3741    /// ```
3742    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createaggregate.html)
3743    CreateAggregate(CreateAggregate),
3744    /// ```sql
3745    /// ALTER TABLE
3746    /// ```
3747    AlterTable(AlterTable),
3748    /// ```sql
3749    /// ALTER SCHEMA
3750    /// ```
3751    /// See [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#alter_schema_collate_statement)
3752    AlterSchema(AlterSchema),
3753    /// ```sql
3754    /// ALTER INDEX
3755    /// ```
3756    AlterIndex {
3757        /// Name of the index to alter.
3758        name: ObjectName,
3759        /// The operation to perform on the index.
3760        operation: AlterIndexOperation,
3761    },
3762    /// ```sql
3763    /// ALTER VIEW
3764    /// ```
3765    AlterView {
3766        /// View name being altered.
3767        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
3768        name: ObjectName,
3769        /// Optional new column list for the view.
3770        columns: Vec<Ident>,
3771        /// Replacement query for the view definition.
3772        query: Box<Query>,
3773        /// Additional WITH options for the view.
3774        with_options: Vec<SqlOption>,
3775    },
3776    /// ```sql
3777    /// ALTER FUNCTION
3778    /// ALTER AGGREGATE
3779    /// ```
3780    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-alterfunction.html)
3781    /// and [PostgreSQL](https://www.postgresql.org/docs/current/sql-alteraggregate.html)
3782    AlterFunction(AlterFunction),
3783    /// ```sql
3784    /// ALTER TYPE
3785    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-altertype.html)
3786    /// ```
3787    AlterType(AlterType),
3788    /// ```sql
3789    /// ALTER COLLATION
3790    /// ```
3791    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-altercollation.html)
3792    AlterCollation(AlterCollation),
3793    /// ```sql
3794    /// ALTER OPERATOR
3795    /// ```
3796    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-alteroperator.html)
3797    AlterOperator(AlterOperator),
3798    /// ```sql
3799    /// ALTER OPERATOR FAMILY
3800    /// ```
3801    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-alteropfamily.html)
3802    AlterOperatorFamily(AlterOperatorFamily),
3803    /// ```sql
3804    /// ALTER OPERATOR CLASS
3805    /// ```
3806    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-alteropclass.html)
3807    AlterOperatorClass(AlterOperatorClass),
3808    /// ```sql
3809    /// ALTER ROLE
3810    /// ```
3811    AlterRole {
3812        /// Role name being altered.
3813        name: Ident,
3814        /// Operation to perform on the role.
3815        operation: AlterRoleOperation,
3816    },
3817    /// ```sql
3818    /// ALTER POLICY <NAME> ON <TABLE NAME> [<OPERATION>]
3819    /// ```
3820    /// (Postgresql-specific)
3821    AlterPolicy(AlterPolicy),
3822    /// ```sql
3823    /// ALTER CONNECTOR connector_name SET DCPROPERTIES(property_name=property_value, ...);
3824    /// or
3825    /// ALTER CONNECTOR connector_name SET URL new_url;
3826    /// or
3827    /// ALTER CONNECTOR connector_name SET OWNER [USER|ROLE] user_or_role;
3828    /// ```
3829    /// (Hive-specific)
3830    AlterConnector {
3831        /// Name of the connector to alter.
3832        name: Ident,
3833        /// Optional connector properties to set.
3834        properties: Option<Vec<SqlOption>>,
3835        /// Optional new URL for the connector.
3836        url: Option<String>,
3837        /// Optional new owner specification.
3838        owner: Option<ddl::AlterConnectorOwner>,
3839    },
3840    /// ```sql
3841    /// ALTER SESSION SET sessionParam
3842    /// ALTER SESSION UNSET <param_name> [ , <param_name> , ... ]
3843    /// ```
3844    /// See <https://docs.snowflake.com/en/sql-reference/sql/alter-session>
3845    AlterSession {
3846        /// true is to set for the session parameters, false is to unset
3847        set: bool,
3848        /// The session parameters to set or unset
3849        session_params: KeyValueOptions,
3850    },
3851    /// ```sql
3852    /// ATTACH DATABASE 'path/to/file' AS alias
3853    /// ```
3854    /// (SQLite-specific)
3855    AttachDatabase {
3856        /// The name to bind to the newly attached database
3857        schema_name: Ident,
3858        /// An expression that indicates the path to the database file
3859        database_file_name: Expr,
3860        /// true if the syntax is 'ATTACH DATABASE', false if it's just 'ATTACH'
3861        database: bool,
3862    },
3863    /// (DuckDB-specific)
3864    /// ```sql
3865    /// ATTACH 'sqlite_file.db' AS sqlite_db (READ_ONLY, TYPE SQLITE);
3866    /// ```
3867    /// See <https://duckdb.org/docs/sql/statements/attach.html>
3868    AttachDuckDBDatabase {
3869        /// `true` when `IF NOT EXISTS` was present.
3870        if_not_exists: bool,
3871        /// `true` if the syntax used `ATTACH DATABASE` rather than `ATTACH`.
3872        database: bool,
3873        /// The path identifier to the database file being attached.
3874        database_path: Ident,
3875        /// Optional alias assigned to the attached database.
3876        database_alias: Option<Ident>,
3877        /// Dialect-specific attach options (e.g., `READ_ONLY`).
3878        attach_options: Vec<AttachDuckDBDatabaseOption>,
3879    },
3880    /// (DuckDB-specific)
3881    /// ```sql
3882    /// DETACH db_alias;
3883    /// ```
3884    /// See <https://duckdb.org/docs/sql/statements/attach.html>
3885    DetachDuckDBDatabase {
3886        /// `true` when `IF EXISTS` was present.
3887        if_exists: bool,
3888        /// `true` if the syntax used `DETACH DATABASE` rather than `DETACH`.
3889        database: bool,
3890        /// Alias of the database to detach.
3891        database_alias: Ident,
3892    },
3893    /// ```sql
3894    /// DROP [TABLE, VIEW, ...]
3895    /// ```
3896    Drop {
3897        /// The type of the object to drop: TABLE, VIEW, etc.
3898        object_type: ObjectType,
3899        /// An optional `IF EXISTS` clause. (Non-standard.)
3900        if_exists: bool,
3901        /// One or more objects to drop. (ANSI SQL requires exactly one.)
3902        names: Vec<ObjectName>,
3903        /// Whether `CASCADE` was specified. This will be `false` when
3904        /// `RESTRICT` or no drop behavior at all was specified.
3905        cascade: bool,
3906        /// Whether `RESTRICT` was specified. This will be `false` when
3907        /// `CASCADE` or no drop behavior at all was specified.
3908        restrict: bool,
3909        /// Hive allows you specify whether the table's stored data will be
3910        /// deleted along with the dropped table
3911        purge: bool,
3912        /// MySQL-specific "TEMPORARY" keyword
3913        temporary: bool,
3914        /// MySQL-specific drop index syntax, which requires table specification
3915        /// See <https://dev.mysql.com/doc/refman/8.4/en/drop-index.html>
3916        table: Option<ObjectName>,
3917    },
3918    /// ```sql
3919    /// DROP FUNCTION
3920    /// ```
3921    DropFunction(DropFunction),
3922    /// ```sql
3923    /// DROP DOMAIN
3924    /// ```
3925    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-dropdomain.html)
3926    ///
3927    /// DROP DOMAIN [ IF EXISTS ] name [, ...] [ CASCADE | RESTRICT ]
3928    ///
3929    DropDomain(DropDomain),
3930    /// ```sql
3931    /// DROP PROCEDURE
3932    /// ```
3933    DropProcedure {
3934        /// `true` when `IF EXISTS` was present.
3935        if_exists: bool,
3936        /// One or more functions/procedures to drop.
3937        proc_desc: Vec<FunctionDesc>,
3938        /// Optional drop behavior (`CASCADE` or `RESTRICT`).
3939        drop_behavior: Option<DropBehavior>,
3940    },
3941    /// ```sql
3942    /// DROP SECRET
3943    /// ```
3944    DropSecret {
3945        /// `true` when `IF EXISTS` was present.
3946        if_exists: bool,
3947        /// Optional `TEMPORARY` marker.
3948        temporary: Option<bool>,
3949        /// Name of the secret to drop.
3950        name: Ident,
3951        /// Optional storage specifier identifier.
3952        storage_specifier: Option<Ident>,
3953    },
3954    ///```sql
3955    /// DROP POLICY
3956    /// ```
3957    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-droppolicy.html)
3958    DropPolicy(DropPolicy),
3959    /// ```sql
3960    /// DROP CONNECTOR
3961    /// ```
3962    /// See [Hive](https://cwiki.apache.org/confluence/pages/viewpage.action?pageId=27362034#LanguageManualDDL-DropConnector)
3963    DropConnector {
3964        /// `true` when `IF EXISTS` was present.
3965        if_exists: bool,
3966        /// Name of the connector to drop.
3967        name: Ident,
3968    },
3969    /// ```sql
3970    /// DECLARE
3971    /// ```
3972    /// Declare Cursor Variables
3973    ///
3974    /// Note: this is a PostgreSQL-specific statement,
3975    /// but may also compatible with other SQL.
3976    Declare {
3977        /// Cursor declaration statements collected by `DECLARE`.
3978        stmts: Vec<Declare>,
3979    },
3980    /// ```sql
3981    /// CREATE EXTENSION [ IF NOT EXISTS ] extension_name
3982    ///     [ WITH ] [ SCHEMA schema_name ]
3983    ///              [ VERSION version ]
3984    ///              [ CASCADE ]
3985    /// ```
3986    ///
3987    /// Note: this is a PostgreSQL-specific statement,
3988    CreateExtension(CreateExtension),
3989    /// ```sql
3990    /// CREATE COLLATION
3991    /// ```
3992    /// Note: this is a PostgreSQL-specific statement.
3993    /// <https://www.postgresql.org/docs/current/sql-createcollation.html>
3994    CreateCollation(CreateCollation),
3995    /// ```sql
3996    /// CREATE TEXT SEARCH CONFIGURATION name ( PARSER = parser_name )
3997    /// ```
3998    /// Note: this is a PostgreSQL-specific statement.
3999    /// <https://www.postgresql.org/docs/current/sql-createtsconfig.html>
4000    CreateTextSearchConfiguration(CreateTextSearchConfiguration),
4001    /// ```sql
4002    /// CREATE TEXT SEARCH DICTIONARY name ( TEMPLATE = template_name [, option = value, ...] )
4003    /// ```
4004    /// Note: this is a PostgreSQL-specific statement.
4005    /// <https://www.postgresql.org/docs/current/sql-createtsdictionary.html>
4006    CreateTextSearchDictionary(CreateTextSearchDictionary),
4007    /// ```sql
4008    /// CREATE TEXT SEARCH PARSER name ( START = start_fn, GETTOKEN = gettoken_fn, END = end_fn, LEXTYPES = lextypes_fn [, HEADLINE = headline_fn] )
4009    /// ```
4010    /// Note: this is a PostgreSQL-specific statement.
4011    /// <https://www.postgresql.org/docs/current/sql-createtsparser.html>
4012    CreateTextSearchParser(CreateTextSearchParser),
4013    /// ```sql
4014    /// CREATE TEXT SEARCH TEMPLATE name ( [INIT = init_fn,] LEXIZE = lexize_fn )
4015    /// ```
4016    /// Note: this is a PostgreSQL-specific statement.
4017    /// <https://www.postgresql.org/docs/current/sql-createtstemplate.html>
4018    CreateTextSearchTemplate(CreateTextSearchTemplate),
4019    /// ```sql
4020    /// DROP EXTENSION [ IF EXISTS ] name [, ...] [ CASCADE | RESTRICT ]
4021    /// ```
4022    /// Note: this is a PostgreSQL-specific statement.
4023    /// <https://www.postgresql.org/docs/current/sql-dropextension.html>
4024    DropExtension(DropExtension),
4025    /// ```sql
4026    /// DROP OPERATOR [ IF EXISTS ] name ( { left_type | NONE } , right_type ) [, ...] [ CASCADE | RESTRICT ]
4027    /// ```
4028    /// Note: this is a PostgreSQL-specific statement.
4029    /// <https://www.postgresql.org/docs/current/sql-dropoperator.html>
4030    DropOperator(DropOperator),
4031    /// ```sql
4032    /// DROP OPERATOR FAMILY [ IF EXISTS ] name USING index_method [ CASCADE | RESTRICT ]
4033    /// ```
4034    /// Note: this is a PostgreSQL-specific statement.
4035    /// <https://www.postgresql.org/docs/current/sql-dropopfamily.html>
4036    DropOperatorFamily(DropOperatorFamily),
4037    /// ```sql
4038    /// DROP OPERATOR CLASS [ IF EXISTS ] name USING index_method [ CASCADE | RESTRICT ]
4039    /// ```
4040    /// Note: this is a PostgreSQL-specific statement.
4041    /// <https://www.postgresql.org/docs/current/sql-dropopclass.html>
4042    DropOperatorClass(DropOperatorClass),
4043    /// ```sql
4044    /// FETCH
4045    /// ```
4046    /// Retrieve rows from a query using a cursor
4047    ///
4048    /// Note: this is a PostgreSQL-specific statement,
4049    /// but may also compatible with other SQL.
4050    Fetch {
4051        /// Cursor name
4052        name: Ident,
4053        /// The fetch direction (e.g., `FORWARD`, `BACKWARD`).
4054        direction: FetchDirection,
4055        /// The fetch position (e.g., `ALL`, `NEXT`, `ABSOLUTE`).
4056        position: FetchPosition,
4057        /// Optional target table to fetch rows into.
4058        into: Option<ObjectName>,
4059    },
4060    /// ```sql
4061    /// FLUSH [NO_WRITE_TO_BINLOG | LOCAL] flush_option [, flush_option] ... | tables_option
4062    /// ```
4063    ///
4064    /// Note: this is a Mysql-specific statement,
4065    /// but may also compatible with other SQL.
4066    Flush {
4067        /// The specific flush option or object to flush.
4068        object_type: FlushType,
4069        /// Optional flush location (dialect-specific).
4070        location: Option<FlushLocation>,
4071        /// Optional channel name used for flush operations.
4072        channel: Option<String>,
4073        /// Whether a read lock was requested.
4074        read_lock: bool,
4075        /// Whether this is an export flush operation.
4076        export: bool,
4077        /// Optional list of tables involved in the flush.
4078        tables: Vec<ObjectName>,
4079    },
4080    /// ```sql
4081    /// DISCARD [ ALL | PLANS | SEQUENCES | TEMPORARY | TEMP ]
4082    /// ```
4083    ///
4084    /// Note: this is a PostgreSQL-specific statement,
4085    /// but may also compatible with other SQL.
4086    Discard {
4087        /// The kind of object(s) to discard (ALL, PLANS, etc.).
4088        object_type: DiscardObject,
4089    },
4090    /// `SHOW FUNCTIONS`
4091    ///
4092    /// Note: this is a Presto-specific statement.
4093    ShowFunctions {
4094        /// Optional filter for which functions to display.
4095        filter: Option<ShowStatementFilter>,
4096    },
4097    /// ```sql
4098    /// SHOW <variable>
4099    /// ```
4100    ///
4101    /// Note: this is a PostgreSQL-specific statement.
4102    ShowVariable {
4103        /// Variable name as one or more identifiers.
4104        variable: Vec<Ident>,
4105    },
4106    /// ```sql
4107    /// SHOW [GLOBAL | SESSION] STATUS [LIKE 'pattern' | WHERE expr]
4108    /// ```
4109    ///
4110    /// Note: this is a MySQL-specific statement.
4111    ShowStatus {
4112        /// Optional filter for which status entries to display.
4113        filter: Option<ShowStatementFilter>,
4114        /// `true` when `GLOBAL` scope was requested.
4115        global: bool,
4116        /// `true` when `SESSION` scope was requested.
4117        session: bool,
4118    },
4119    /// ```sql
4120    /// SHOW VARIABLES
4121    /// ```
4122    ///
4123    /// Note: this is a MySQL-specific statement.
4124    ShowVariables {
4125        /// Optional filter for which variables to display.
4126        filter: Option<ShowStatementFilter>,
4127        /// `true` when `GLOBAL` scope was requested.
4128        global: bool,
4129        /// `true` when `SESSION` scope was requested.
4130        session: bool,
4131    },
4132    /// ```sql
4133    /// SHOW CREATE TABLE
4134    /// ```
4135    ///
4136    /// Note: this is a MySQL-specific statement.
4137    ShowCreate {
4138        /// The kind of object being shown (TABLE, VIEW, etc.).
4139        obj_type: ShowCreateObject,
4140        /// The name of the object to show create statement for.
4141        obj_name: ObjectName,
4142    },
4143    /// ```sql
4144    /// SHOW COLUMNS
4145    /// ```
4146    ShowColumns {
4147        /// `true` when extended column information was requested.
4148        extended: bool,
4149        /// `true` when full column details were requested.
4150        full: bool,
4151        /// Additional options for `SHOW COLUMNS`.
4152        show_options: ShowStatementOptions,
4153    },
4154    /// ```sql
4155    /// SHOW CATALOGS
4156    /// ```
4157    ShowCatalogs {
4158        /// `true` when terse output format was requested.
4159        terse: bool,
4160        /// `true` when history information was requested.
4161        history: bool,
4162        /// Additional options for `SHOW CATALOGS`.
4163        show_options: ShowStatementOptions,
4164    },
4165    /// ```sql
4166    /// SHOW DATABASES
4167    /// ```
4168    ShowDatabases {
4169        /// `true` when terse output format was requested.
4170        terse: bool,
4171        /// `true` when history information was requested.
4172        history: bool,
4173        /// Additional options for `SHOW DATABASES`.
4174        show_options: ShowStatementOptions,
4175    },
4176    /// ```sql
4177    /// SHOW [FULL] PROCESSLIST
4178    /// ```
4179    ///
4180    /// Note: this is a MySQL-specific statement.
4181    ShowProcessList {
4182        /// `true` when full process information was requested.
4183        full: bool,
4184    },
4185    /// ```sql
4186    /// SHOW SCHEMAS
4187    /// ```
4188    ShowSchemas {
4189        /// `true` when terse (compact) output was requested.
4190        terse: bool,
4191        /// `true` when history information was requested.
4192        history: bool,
4193        /// Additional options for `SHOW SCHEMAS`.
4194        show_options: ShowStatementOptions,
4195    },
4196    // ```sql
4197    // SHOW {CHARACTER SET | CHARSET}
4198    // ```
4199    // [MySQL]:
4200    // <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>
4201    /// Show the available character sets (alias `CHARSET`).
4202    ShowCharset(ShowCharset),
4203    /// ```sql
4204    /// SHOW OBJECTS LIKE 'line%' IN mydb.public
4205    /// ```
4206    /// Snowflake-specific statement
4207    /// <https://docs.snowflake.com/en/sql-reference/sql/show-objects>
4208    ShowObjects(ShowObjects),
4209    /// ```sql
4210    /// SHOW TABLES
4211    /// ```
4212    ShowTables {
4213        /// `true` when terse output format was requested (compact listing).
4214        terse: bool,
4215        /// `true` when history rows are requested.
4216        history: bool,
4217        /// `true` when extended information should be shown.
4218        extended: bool,
4219        /// `true` when a full listing was requested.
4220        full: bool,
4221        /// `true` when external tables should be included.
4222        external: bool,
4223        /// Additional options for `SHOW` statements.
4224        show_options: ShowStatementOptions,
4225    },
4226    /// ```sql
4227    /// SHOW VIEWS
4228    /// ```
4229    ShowViews {
4230        /// `true` when terse output format was requested.
4231        terse: bool,
4232        /// `true` when materialized views should be included.
4233        materialized: bool,
4234        /// Additional options for `SHOW` statements.
4235        show_options: ShowStatementOptions,
4236    },
4237    /// ```sql
4238    /// SHOW COLLATION
4239    /// ```
4240    ///
4241    /// Note: this is a MySQL-specific statement.
4242    ShowCollation {
4243        /// Optional filter for which collations to display.
4244        filter: Option<ShowStatementFilter>,
4245    },
4246    /// ```sql
4247    /// `USE ...`
4248    /// ```
4249    Use(Use),
4250    /// ```sql
4251    /// START  [ TRANSACTION | WORK ] | START TRANSACTION } ...
4252    /// ```
4253    /// If `begin` is false.
4254    ///
4255    /// ```sql
4256    /// `BEGIN  [ TRANSACTION | WORK ] | START TRANSACTION } ...`
4257    /// ```
4258    /// If `begin` is true
4259    StartTransaction {
4260        /// Transaction modes such as `ISOLATION LEVEL` or `READ WRITE`.
4261        modes: Vec<TransactionMode>,
4262        /// `true` when this was parsed as `BEGIN` instead of `START`.
4263        begin: bool,
4264        /// Optional specific keyword used: `TRANSACTION` or `WORK`.
4265        transaction: Option<BeginTransactionKind>,
4266        /// Optional transaction modifier (e.g., `AND NO CHAIN`).
4267        modifier: Option<TransactionModifier>,
4268        /// List of statements belonging to the `BEGIN` block.
4269        /// Example:
4270        /// ```sql
4271        /// BEGIN
4272        ///     SELECT 1;
4273        ///     SELECT 2;
4274        /// END;
4275        /// ```
4276        statements: Vec<Statement>,
4277        /// Exception handling with exception clauses.
4278        /// Example:
4279        /// ```sql
4280        /// EXCEPTION
4281        ///     WHEN EXCEPTION_1 THEN
4282        ///         SELECT 2;
4283        ///     WHEN EXCEPTION_2 OR EXCEPTION_3 THEN
4284        ///         SELECT 3;
4285        ///     WHEN OTHER THEN
4286        ///         SELECT 4;
4287        /// ```
4288        /// <https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#beginexceptionend>
4289        /// <https://docs.snowflake.com/en/sql-reference/snowflake-scripting/exception>
4290        exception: Option<Vec<ExceptionWhen>>,
4291        /// TRUE if the statement has an `END` keyword.
4292        has_end_keyword: bool,
4293    },
4294    /// ```sql
4295    /// COMMENT ON ...
4296    /// ```
4297    ///
4298    /// Note: this is a PostgreSQL-specific statement.
4299    Comment {
4300        /// Type of object being commented (table, column, etc.).
4301        object_type: CommentObject,
4302        /// Name of the object the comment applies to.
4303        object_name: ObjectName,
4304        /// Optional comment text (None to remove comment).
4305        comment: Option<String>,
4306        /// An optional `IF EXISTS` clause. (Non-standard.)
4307        /// See <https://docs.snowflake.com/en/sql-reference/sql/comment>
4308        if_exists: bool,
4309    },
4310    /// ```sql
4311    /// COMMIT [ TRANSACTION | WORK ] [ AND [ NO ] CHAIN ]
4312    /// ```
4313    /// If `end` is false
4314    ///
4315    /// ```sql
4316    /// END [ TRY | CATCH ]
4317    /// ```
4318    /// If `end` is true
4319    Commit {
4320        /// `true` when `AND [ NO ] CHAIN` was present.
4321        chain: bool,
4322        /// `true` when this `COMMIT` was parsed as an `END` block terminator.
4323        end: bool,
4324        /// Optional transaction modifier for commit semantics.
4325        modifier: Option<TransactionModifier>,
4326    },
4327    /// ```sql
4328    /// ROLLBACK [ TRANSACTION | WORK ] [ AND [ NO ] CHAIN ] [ TO [ SAVEPOINT ] savepoint_name ]
4329    /// ```
4330    Rollback {
4331        /// `true` when `AND [ NO ] CHAIN` was present.
4332        chain: bool,
4333        /// Optional savepoint name to roll back to.
4334        savepoint: Option<Ident>,
4335    },
4336    /// ```sql
4337    /// CREATE SCHEMA
4338    /// ```
4339    CreateSchema {
4340        /// `<schema name> | AUTHORIZATION <schema authorization identifier>  | <schema name>  AUTHORIZATION <schema authorization identifier>`
4341        schema_name: SchemaName,
4342        /// `true` when `IF NOT EXISTS` was present.
4343        if_not_exists: bool,
4344        /// Schema properties.
4345        ///
4346        /// ```sql
4347        /// CREATE SCHEMA myschema WITH (key1='value1');
4348        /// ```
4349        ///
4350        /// [Trino](https://trino.io/docs/current/sql/create-schema.html)
4351        with: Option<Vec<SqlOption>>,
4352        /// Schema options.
4353        ///
4354        /// ```sql
4355        /// CREATE SCHEMA myschema OPTIONS(key1='value1');
4356        /// ```
4357        ///
4358        /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_schema_statement)
4359        options: Option<Vec<SqlOption>>,
4360        /// Default collation specification for the schema.
4361        ///
4362        /// ```sql
4363        /// CREATE SCHEMA myschema DEFAULT COLLATE 'und:ci';
4364        /// ```
4365        ///
4366        /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_schema_statement)
4367        default_collate_spec: Option<Expr>,
4368        /// Clones a schema
4369        ///
4370        /// ```sql
4371        /// CREATE SCHEMA myschema CLONE otherschema
4372        /// ```
4373        ///
4374        /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-clone#databases-schemas)
4375        clone: Option<ObjectName>,
4376    },
4377    /// ```sql
4378    /// CREATE DATABASE
4379    /// ```
4380    /// See:
4381    /// <https://docs.snowflake.com/en/sql-reference/sql/create-database>
4382    CreateDatabase {
4383        /// Database name.
4384        db_name: ObjectName,
4385        /// `IF NOT EXISTS` flag.
4386        if_not_exists: bool,
4387        /// Optional location URI.
4388        location: Option<String>,
4389        /// Optional managed location.
4390        managed_location: Option<String>,
4391        /// `OR REPLACE` flag.
4392        or_replace: bool,
4393        /// `TRANSIENT` flag.
4394        transient: bool,
4395        /// Optional clone source.
4396        clone: Option<ObjectName>,
4397        /// Optional data retention time in days.
4398        data_retention_time_in_days: Option<u64>,
4399        /// Optional maximum data extension time in days.
4400        max_data_extension_time_in_days: Option<u64>,
4401        /// Optional external volume identifier.
4402        external_volume: Option<String>,
4403        /// Optional catalog name.
4404        catalog: Option<String>,
4405        /// Whether to replace invalid characters.
4406        replace_invalid_characters: Option<bool>,
4407        /// Default DDL collation string.
4408        default_ddl_collation: Option<String>,
4409        /// Storage serialization policy.
4410        storage_serialization_policy: Option<StorageSerializationPolicy>,
4411        /// Optional comment.
4412        comment: Option<String>,
4413        /// Optional default character set (MySQL).
4414        default_charset: Option<String>,
4415        /// Optional default collation (MySQL).
4416        default_collation: Option<String>,
4417        /// Optional catalog sync identifier.
4418        catalog_sync: Option<String>,
4419        /// Catalog sync namespace mode.
4420        catalog_sync_namespace_mode: Option<CatalogSyncNamespaceMode>,
4421        /// Optional flatten delimiter for namespace sync.
4422        catalog_sync_namespace_flatten_delimiter: Option<String>,
4423        /// Optional tags for the database.
4424        with_tags: Option<Vec<Tag>>,
4425        /// Optional contact entries for the database.
4426        with_contacts: Option<Vec<ContactEntry>>,
4427    },
4428    /// ```sql
4429    /// CREATE FUNCTION
4430    /// ```
4431    ///
4432    /// Supported variants:
4433    /// 1. [Hive](https://cwiki.apache.org/confluence/display/hive/languagemanual+ddl#LanguageManualDDL-Create/Drop/ReloadFunction)
4434    /// 2. [PostgreSQL](https://www.postgresql.org/docs/15/sql-createfunction.html)
4435    /// 3. [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_function_statement)
4436    /// 4. [MsSql](https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql)
4437    CreateFunction(CreateFunction),
4438    /// CREATE TRIGGER statement. See struct [CreateTrigger] for details.
4439    CreateTrigger(CreateTrigger),
4440    /// DROP TRIGGER statement. See struct [DropTrigger] for details.
4441    DropTrigger(DropTrigger),
4442    /// ```sql
4443    /// CREATE PROCEDURE
4444    /// ```
4445    CreateProcedure {
4446        /// `OR ALTER` flag.
4447        or_alter: bool,
4448        /// Procedure name.
4449        name: ObjectName,
4450        /// Optional procedure parameters.
4451        params: Option<Vec<ProcedureParam>>,
4452        /// Optional language identifier.
4453        language: Option<Ident>,
4454        /// Procedure body statements.
4455        body: ConditionalStatements,
4456    },
4457    /// ```sql
4458    /// CREATE MACRO
4459    /// ```
4460    ///
4461    /// Supported variants:
4462    /// 1. [DuckDB](https://duckdb.org/docs/sql/statements/create_macro)
4463    CreateMacro {
4464        /// `OR REPLACE` flag.
4465        or_replace: bool,
4466        /// Whether macro is temporary.
4467        temporary: bool,
4468        /// Macro name.
4469        name: ObjectName,
4470        /// Optional macro arguments.
4471        args: Option<Vec<MacroArg>>,
4472        /// Macro definition body.
4473        definition: MacroDefinition,
4474    },
4475    /// ```sql
4476    /// CREATE STAGE
4477    /// ```
4478    /// See <https://docs.snowflake.com/en/sql-reference/sql/create-stage>
4479    CreateStage {
4480        /// `OR REPLACE` flag for stage.
4481        or_replace: bool,
4482        /// Whether stage is temporary.
4483        temporary: bool,
4484        /// `IF NOT EXISTS` flag.
4485        if_not_exists: bool,
4486        /// Stage name.
4487        name: ObjectName,
4488        /// Stage parameters.
4489        stage_params: StageParamsObject,
4490        /// Directory table parameters.
4491        directory_table_params: KeyValueOptions,
4492        /// File format options.
4493        file_format: KeyValueOptions,
4494        /// Copy options for stage.
4495        copy_options: KeyValueOptions,
4496        /// Optional comment.
4497        comment: Option<String>,
4498    },
4499    /// ```sql
4500    /// ASSERT <condition> [AS <message>]
4501    /// ```
4502    Assert {
4503        /// Assertion condition expression.
4504        condition: Expr,
4505        /// Optional message expression.
4506        message: Option<Expr>,
4507    },
4508    /// ```sql
4509    /// GRANT privileges ON objects TO grantees
4510    /// ```
4511    Grant(Grant),
4512    /// ```sql
4513    /// DENY privileges ON object TO grantees
4514    /// ```
4515    Deny(DenyStatement),
4516    /// ```sql
4517    /// REVOKE privileges ON objects FROM grantees
4518    /// ```
4519    Revoke(Revoke),
4520    /// ```sql
4521    /// DEALLOCATE [ PREPARE ] { name | ALL }
4522    /// ```
4523    ///
4524    /// Note: this is a PostgreSQL-specific statement.
4525    Deallocate {
4526        /// Name to deallocate (or `ALL`).
4527        name: Ident,
4528        /// Whether `PREPARE` keyword was present.
4529        prepare: bool,
4530    },
4531    /// ```sql
4532    /// An `EXECUTE` statement
4533    /// ```
4534    ///
4535    /// Postgres: <https://www.postgresql.org/docs/current/sql-execute.html>
4536    /// MSSQL: <https://learn.microsoft.com/en-us/sql/relational-databases/stored-procedures/execute-a-stored-procedure>
4537    /// BigQuery: <https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#execute_immediate>
4538    /// Snowflake: <https://docs.snowflake.com/en/sql-reference/sql/execute-immediate>
4539    Execute {
4540        /// Optional function/procedure name.
4541        name: Option<ObjectName>,
4542        /// Parameter expressions passed to execute.
4543        parameters: Vec<Expr>,
4544        /// Whether parentheses were present around `parameters`.
4545        has_parentheses: bool,
4546        /// Is this an `EXECUTE IMMEDIATE`.
4547        immediate: bool,
4548        /// Identifiers to capture results into.
4549        into: Vec<Ident>,
4550        /// `USING` expressions with optional aliases.
4551        using: Vec<ExprWithAlias>,
4552        /// Whether the last parameter is the return value of the procedure
4553        /// MSSQL: <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/execute-transact-sql?view=sql-server-ver17#output>
4554        output: bool,
4555        /// Whether to invoke the procedure with the default parameter values
4556        /// MSSQL: <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/execute-transact-sql?view=sql-server-ver17#default>
4557        default: bool,
4558    },
4559    /// ```sql
4560    /// PREPARE name [ ( data_type [, ...] ) ] AS statement
4561    /// ```
4562    ///
4563    /// Note: this is a PostgreSQL-specific statement.
4564    Prepare {
4565        /// Name of the prepared statement.
4566        name: Ident,
4567        /// Optional data types for parameters.
4568        data_types: Vec<DataType>,
4569        /// Statement being prepared.
4570        statement: Box<Statement>,
4571    },
4572    /// ```sql
4573    /// KILL [CONNECTION | QUERY | MUTATION]
4574    /// ```
4575    ///
4576    /// See <https://clickhouse.com/docs/en/sql-reference/statements/kill/>
4577    /// See <https://dev.mysql.com/doc/refman/8.0/en/kill.html>
4578    Kill {
4579        /// Optional kill modifier (CONNECTION, QUERY, MUTATION).
4580        modifier: Option<KillType>,
4581        // processlist_id
4582        /// The id of the process to kill.
4583        id: u64,
4584    },
4585    /// ```sql
4586    /// [EXPLAIN | DESC | DESCRIBE] TABLE
4587    /// ```
4588    /// Note: this is a MySQL-specific statement. See <https://dev.mysql.com/doc/refman/8.0/en/explain.html>
4589    ExplainTable {
4590        /// `EXPLAIN | DESC | DESCRIBE`
4591        describe_alias: DescribeAlias,
4592        /// Hive style `FORMATTED | EXTENDED`
4593        hive_format: Option<HiveDescribeFormat>,
4594        /// Snowflake and ClickHouse support `DESC|DESCRIBE TABLE <table_name>` syntax
4595        ///
4596        /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/desc-table.html)
4597        /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/describe-table)
4598        has_table_keyword: bool,
4599        /// Table name
4600        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
4601        table_name: ObjectName,
4602    },
4603    /// ```sql
4604    /// [EXPLAIN | DESC | DESCRIBE]  <statement>
4605    /// ```
4606    Explain {
4607        /// `EXPLAIN | DESC | DESCRIBE`
4608        describe_alias: DescribeAlias,
4609        /// Carry out the command and show actual run times and other statistics.
4610        analyze: bool,
4611        /// Display additional information regarding the plan.
4612        verbose: bool,
4613        /// `EXPLAIN QUERY PLAN`
4614        /// Display the query plan without running the query.
4615        ///
4616        /// [SQLite](https://sqlite.org/lang_explain.html)
4617        query_plan: bool,
4618        /// `EXPLAIN ESTIMATE`
4619        /// [Clickhouse](https://clickhouse.com/docs/en/sql-reference/statements/explain#explain-estimate)
4620        estimate: bool,
4621        /// A SQL query that specifies what to explain
4622        statement: Box<Statement>,
4623        /// Optional output format of explain
4624        format: Option<AnalyzeFormatKind>,
4625        /// Postgres style utility options, `(analyze, verbose true)`
4626        options: Option<Vec<UtilityOption>>,
4627    },
4628    /// ```sql
4629    /// SAVEPOINT
4630    /// ```
4631    /// Define a new savepoint within the current transaction
4632    Savepoint {
4633        /// Name of the savepoint being defined.
4634        name: Ident,
4635    },
4636    /// ```sql
4637    /// RELEASE [ SAVEPOINT ] savepoint_name
4638    /// ```
4639    ReleaseSavepoint {
4640        /// Name of the savepoint to release.
4641        name: Ident,
4642    },
4643    /// A `MERGE` statement.
4644    ///
4645    /// ```sql
4646    /// MERGE INTO <target_table> USING <source> ON <join_expr> { matchedClause | notMatchedClause } [ ... ]
4647    /// ```
4648    /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/merge)
4649    /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/dml-syntax#merge_statement)
4650    /// [MSSQL](https://learn.microsoft.com/en-us/sql/t-sql/statements/merge-transact-sql?view=sql-server-ver16)
4651    Merge(Merge),
4652    /// ```sql
4653    /// CACHE [ FLAG ] TABLE <table_name> [ OPTIONS('K1' = 'V1', 'K2' = V2) ] [ AS ] [ <query> ]
4654    /// ```
4655    ///
4656    /// See [Spark SQL docs] for more details.
4657    ///
4658    /// [Spark SQL docs]: https://docs.databricks.com/spark/latest/spark-sql/language-manual/sql-ref-syntax-aux-cache-cache-table.html
4659    Cache {
4660        /// Table flag
4661        table_flag: Option<ObjectName>,
4662        /// Table name
4663        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
4664        table_name: ObjectName,
4665        /// `true` if `AS` keyword was present before the query.
4666        has_as: bool,
4667        /// Table confs
4668        options: Vec<SqlOption>,
4669        /// Cache table as a Query
4670        query: Option<Box<Query>>,
4671    },
4672    /// ```sql
4673    /// UNCACHE TABLE [ IF EXISTS ]  <table_name>
4674    /// ```
4675    UNCache {
4676        /// Table name
4677        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
4678        table_name: ObjectName,
4679        /// `true` when `IF EXISTS` was present.
4680        if_exists: bool,
4681    },
4682    /// ```sql
4683    /// CREATE [ { TEMPORARY | TEMP } ] SEQUENCE [ IF NOT EXISTS ] <sequence_name>
4684    /// ```
4685    /// Define a new sequence:
4686    CreateSequence {
4687        /// Whether the sequence is temporary.
4688        temporary: bool,
4689        /// `IF NOT EXISTS` flag.
4690        if_not_exists: bool,
4691        /// Sequence name.
4692        name: ObjectName,
4693        /// Optional data type for the sequence.
4694        data_type: Option<DataType>,
4695        /// Sequence options (INCREMENT, MINVALUE, etc.).
4696        sequence_options: Vec<SequenceOptions>,
4697        /// Optional `OWNED BY` target.
4698        owned_by: Option<ObjectName>,
4699    },
4700    /// A `CREATE DOMAIN` statement.
4701    CreateDomain(CreateDomain),
4702    /// ```sql
4703    /// CREATE TYPE <name>
4704    /// ```
4705    CreateType {
4706        /// Type name to create.
4707        name: ObjectName,
4708        /// Optional type representation details.
4709        representation: Option<UserDefinedTypeRepresentation>,
4710    },
4711    /// ```sql
4712    /// PRAGMA <schema-name>.<pragma-name> = <pragma-value>
4713    /// ```
4714    Pragma {
4715        /// Pragma name (possibly qualified).
4716        name: ObjectName,
4717        /// Optional pragma value.
4718        value: Option<ValueWithSpan>,
4719        /// Whether the pragma used `=`.
4720        is_eq: bool,
4721    },
4722    /// ```sql
4723    /// LOCK [ TABLE ] [ ONLY ] name [ * ] [, ...] [ IN lockmode MODE ] [ NOWAIT ]
4724    /// ```
4725    ///
4726    /// See <https://www.postgresql.org/docs/current/sql-lock.html>
4727    Lock(Lock),
4728    /// ```sql
4729    /// LOCK TABLES <table_name> [READ [LOCAL] | [LOW_PRIORITY] WRITE]
4730    /// ```
4731    /// Note: this is a MySQL-specific statement. See <https://dev.mysql.com/doc/refman/8.0/en/lock-tables.html>
4732    LockTables {
4733        /// List of tables to lock with modes.
4734        tables: Vec<LockTable>,
4735    },
4736    /// ```sql
4737    /// UNLOCK TABLES
4738    /// ```
4739    /// Note: this is a MySQL-specific statement. See <https://dev.mysql.com/doc/refman/8.0/en/lock-tables.html>
4740    UnlockTables,
4741    /// Unloads the result of a query to file
4742    ///
4743    /// [Athena](https://docs.aws.amazon.com/athena/latest/ug/unload.html):
4744    /// ```sql
4745    /// UNLOAD(statement) TO <destination> [ WITH options ]
4746    /// ```
4747    ///
4748    /// [Redshift](https://docs.aws.amazon.com/redshift/latest/dg/r_UNLOAD.html):
4749    /// ```sql
4750    /// UNLOAD('statement') TO <destination> [ OPTIONS ]
4751    /// ```
4752    Unload {
4753        /// Optional query AST to unload.
4754        query: Option<Box<Query>>,
4755        /// Optional original query text.
4756        query_text: Option<String>,
4757        /// Destination identifier.
4758        to: Ident,
4759        /// Optional IAM role/auth information.
4760        auth: Option<IamRoleKind>,
4761        /// Additional `WITH` options.
4762        with: Vec<SqlOption>,
4763        /// Legacy copy-style options.
4764        options: Vec<CopyLegacyOption>,
4765    },
4766    /// ClickHouse:
4767    /// ```sql
4768    /// OPTIMIZE TABLE [db.]name [ON CLUSTER cluster] [PARTITION partition | PARTITION ID 'partition_id'] [FINAL] [DEDUPLICATE [BY expression]]
4769    /// ```
4770    /// See ClickHouse <https://clickhouse.com/docs/en/sql-reference/statements/optimize>
4771    ///
4772    /// Databricks:
4773    /// ```sql
4774    /// OPTIMIZE table_name [WHERE predicate] [ZORDER BY (col_name1 [, ...])]
4775    /// ```
4776    /// See Databricks <https://docs.databricks.com/en/sql/language-manual/delta-optimize.html>
4777    OptimizeTable {
4778        /// Table name to optimize.
4779        name: ObjectName,
4780        /// Whether the `TABLE` keyword was present (ClickHouse uses `OPTIMIZE TABLE`, Databricks uses `OPTIMIZE`).
4781        has_table_keyword: bool,
4782        /// Optional cluster identifier.
4783        /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/optimize)
4784        on_cluster: Option<Ident>,
4785        /// Optional partition spec.
4786        /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/optimize)
4787        partition: Option<Partition>,
4788        /// Whether `FINAL` was specified.
4789        /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/optimize)
4790        include_final: bool,
4791        /// Optional deduplication settings.
4792        /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/optimize)
4793        deduplicate: Option<Deduplicate>,
4794        /// Optional WHERE predicate.
4795        /// [Databricks](https://docs.databricks.com/en/sql/language-manual/delta-optimize.html)
4796        predicate: Option<Expr>,
4797        /// Optional ZORDER BY columns.
4798        /// [Databricks](https://docs.databricks.com/en/sql/language-manual/delta-optimize.html)
4799        zorder: Option<Vec<Expr>>,
4800    },
4801    /// ```sql
4802    /// LISTEN
4803    /// ```
4804    /// listen for a notification channel
4805    ///
4806    /// See Postgres <https://www.postgresql.org/docs/current/sql-listen.html>
4807    LISTEN {
4808        /// Notification channel identifier.
4809        channel: Ident,
4810    },
4811    /// ```sql
4812    /// UNLISTEN
4813    /// ```
4814    /// stop listening for a notification
4815    ///
4816    /// See Postgres <https://www.postgresql.org/docs/current/sql-unlisten.html>
4817    UNLISTEN {
4818        /// Notification channel identifier.
4819        channel: Ident,
4820    },
4821    /// ```sql
4822    /// NOTIFY channel [ , payload ]
4823    /// ```
4824    /// send a notification event together with an optional "payload" string to channel
4825    ///
4826    /// See Postgres <https://www.postgresql.org/docs/current/sql-notify.html>
4827    NOTIFY {
4828        /// Notification channel identifier.
4829        channel: Ident,
4830        /// Optional payload string.
4831        payload: Option<String>,
4832    },
4833    /// ```sql
4834    /// LOAD DATA [LOCAL] INPATH 'filepath' [OVERWRITE] INTO TABLE tablename
4835    /// [PARTITION (partcol1=val1, partcol2=val2 ...)]
4836    /// [INPUTFORMAT 'inputformat' SERDE 'serde']
4837    /// ```
4838    /// Loading files into tables
4839    ///
4840    /// See Hive <https://cwiki.apache.org/confluence/pages/viewpage.action?pageId=27362036#LanguageManualDML-Loadingfilesintotables>
4841    LoadData {
4842        /// Whether `LOCAL` is present.
4843        local: bool,
4844        /// Input path for files to load.
4845        inpath: String,
4846        /// Whether `OVERWRITE` was specified.
4847        overwrite: bool,
4848        /// Target table name to load into.
4849        table_name: ObjectName,
4850        /// Optional partition specification.
4851        partitioned: Option<Vec<Expr>>,
4852        /// Optional table format information.
4853        table_format: Option<HiveLoadDataFormat>,
4854    },
4855    /// ```sql
4856    /// Rename TABLE tbl_name TO new_tbl_name[, tbl_name2 TO new_tbl_name2] ...
4857    /// ```
4858    /// Renames one or more tables
4859    ///
4860    /// See Mysql <https://dev.mysql.com/doc/refman/9.1/en/rename-table.html>
4861    RenameTable(Vec<RenameTable>),
4862    /// Snowflake `LIST`
4863    /// See: <https://docs.snowflake.com/en/sql-reference/sql/list>
4864    List(FileStagingCommand),
4865    /// Snowflake `REMOVE`
4866    /// See: <https://docs.snowflake.com/en/sql-reference/sql/remove>
4867    Remove(FileStagingCommand),
4868    /// RaiseError (MSSQL)
4869    /// RAISERROR ( { msg_id | msg_str | @local_variable }
4870    /// { , severity , state }
4871    /// [ , argument [ , ...n ] ] )
4872    /// [ WITH option [ , ...n ] ]
4873    /// See <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/raiserror-transact-sql?view=sql-server-ver16>
4874    RaisError {
4875        /// Error message expression or identifier.
4876        message: Box<Expr>,
4877        /// Severity expression.
4878        severity: Box<Expr>,
4879        /// State expression.
4880        state: Box<Expr>,
4881        /// Substitution arguments for the message.
4882        arguments: Vec<Expr>,
4883        /// Additional `WITH` options for RAISERROR.
4884        options: Vec<RaisErrorOption>,
4885    },
4886    /// A MSSQL `THROW` statement.
4887    Throw(ThrowStatement),
4888    /// ```sql
4889    /// PRINT msg_str | @local_variable | string_expr
4890    /// ```
4891    ///
4892    /// See: <https://learn.microsoft.com/en-us/sql/t-sql/statements/print-transact-sql>
4893    Print(PrintStatement),
4894    /// MSSQL `WAITFOR` statement.
4895    ///
4896    /// See: <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/waitfor-transact-sql>
4897    WaitFor(WaitForStatement),
4898    /// ```sql
4899    /// RETURN [ expression ]
4900    /// ```
4901    ///
4902    /// See [ReturnStatement]
4903    Return(ReturnStatement),
4904    /// Export data statement
4905    ///
4906    /// Example:
4907    /// ```sql
4908    /// EXPORT DATA OPTIONS(uri='gs://bucket/folder/*', format='PARQUET', overwrite=true) AS
4909    /// SELECT field1, field2 FROM mydataset.table1 ORDER BY field1 LIMIT 10
4910    /// ```
4911    /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/export-statements)
4912    ExportData(ExportData),
4913    /// ```sql
4914    /// CREATE [OR REPLACE] USER <user> [IF NOT EXISTS]
4915    /// ```
4916    /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-user)
4917    CreateUser(CreateUser),
4918    /// ```sql
4919    /// ALTER USER \[ IF EXISTS \] \[ <name> \]
4920    /// ```
4921    /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/alter-user)
4922    AlterUser(AlterUser),
4923    /// Re-sorts rows and reclaims space in either a specified table or all tables in the current database
4924    ///
4925    /// ```sql
4926    /// VACUUM tbl
4927    /// ```
4928    /// [Redshift](https://docs.aws.amazon.com/redshift/latest/dg/r_VACUUM_command.html)
4929    Vacuum(VacuumStatement),
4930    /// Restore the value of a run-time parameter to the default value.
4931    ///
4932    /// ```sql
4933    /// RESET configuration_parameter;
4934    /// RESET ALL;
4935    /// ```
4936    /// [PostgreSQL](https://www.postgresql.org/docs/current/sql-reset.html)
4937    Reset(ResetStatement),
4938}
4939
4940impl From<Analyze> for Statement {
4941    fn from(analyze: Analyze) -> Self {
4942        Statement::Analyze(analyze)
4943    }
4944}
4945
4946impl From<ddl::Truncate> for Statement {
4947    fn from(truncate: ddl::Truncate) -> Self {
4948        Statement::Truncate(truncate)
4949    }
4950}
4951
4952impl From<Lock> for Statement {
4953    fn from(lock: Lock) -> Self {
4954        Statement::Lock(lock)
4955    }
4956}
4957
4958impl From<ddl::Msck> for Statement {
4959    fn from(msck: ddl::Msck) -> Self {
4960        Statement::Msck(msck)
4961    }
4962}
4963
4964/// ```sql
4965/// {COPY | REVOKE} CURRENT GRANTS
4966/// ```
4967///
4968/// - [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/grant-ownership#optional-parameters)
4969#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
4970#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4971#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
4972pub enum CurrentGrantsKind {
4973    /// `COPY CURRENT GRANTS` (copy current grants to target).
4974    CopyCurrentGrants,
4975    /// `REVOKE CURRENT GRANTS` (revoke current grants from target).
4976    RevokeCurrentGrants,
4977}
4978
4979impl fmt::Display for CurrentGrantsKind {
4980    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
4981        match self {
4982            CurrentGrantsKind::CopyCurrentGrants => write!(f, "COPY CURRENT GRANTS"),
4983            CurrentGrantsKind::RevokeCurrentGrants => write!(f, "REVOKE CURRENT GRANTS"),
4984        }
4985    }
4986}
4987
4988#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
4989#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4990#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
4991/// `RAISERROR` options
4992/// See <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/raiserror-transact-sql?view=sql-server-ver16#options>
4993pub enum RaisErrorOption {
4994    /// Log the error.
4995    Log,
4996    /// Do not wait for completion.
4997    NoWait,
4998    /// Set the error state.
4999    SetError,
5000}
5001
5002impl fmt::Display for RaisErrorOption {
5003    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
5004        match self {
5005            RaisErrorOption::Log => write!(f, "LOG"),
5006            RaisErrorOption::NoWait => write!(f, "NOWAIT"),
5007            RaisErrorOption::SetError => write!(f, "SETERROR"),
5008        }
5009    }
5010}
5011
5012impl fmt::Display for Statement {
5013    /// Formats a SQL statement with support for pretty printing.
5014    ///
5015    /// When using the alternate flag (`{:#}`), the statement will be formatted with proper
5016    /// indentation and line breaks. For example:
5017    ///
5018    /// ```
5019    /// # use sqlparser::dialect::GenericDialect;
5020    /// # use sqlparser::parser::Parser;
5021    /// let sql = "SELECT a, b FROM table_1";
5022    /// let ast = Parser::parse_sql(&GenericDialect, sql).unwrap();
5023    ///
5024    /// // Regular formatting
5025    /// assert_eq!(format!("{}", ast[0]), "SELECT a, b FROM table_1");
5026    ///
5027    /// // Pretty printing
5028    /// assert_eq!(format!("{:#}", ast[0]),
5029    /// r#"SELECT
5030    ///   a,
5031    ///   b
5032    /// FROM
5033    ///   table_1"#);
5034    /// ```
5035    // Clippy thinks this function is too complicated, but it is painful to
5036    // split up without extracting structs for each `Statement` variant.
5037    #[allow(clippy::cognitive_complexity)]
5038    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
5039        match self {
5040            Statement::Flush {
5041                object_type,
5042                location,
5043                channel,
5044                read_lock,
5045                export,
5046                tables,
5047            } => {
5048                write!(f, "FLUSH")?;
5049                if let Some(location) = location {
5050                    f.write_str(" ")?;
5051                    location.fmt(f)?;
5052                }
5053                write!(f, " {object_type}")?;
5054
5055                if let Some(channel) = channel {
5056                    write!(f, " FOR CHANNEL {channel}")?;
5057                }
5058
5059                write!(
5060                    f,
5061                    "{tables}{read}{export}",
5062                    tables = if !tables.is_empty() {
5063                        format!(" {}", display_comma_separated(tables))
5064                    } else {
5065                        String::new()
5066                    },
5067                    export = if *export { " FOR EXPORT" } else { "" },
5068                    read = if *read_lock { " WITH READ LOCK" } else { "" }
5069                )
5070            }
5071            Statement::Kill { modifier, id } => {
5072                write!(f, "KILL ")?;
5073
5074                if let Some(m) = modifier {
5075                    write!(f, "{m} ")?;
5076                }
5077
5078                write!(f, "{id}")
5079            }
5080            Statement::ExplainTable {
5081                describe_alias,
5082                hive_format,
5083                has_table_keyword,
5084                table_name,
5085            } => {
5086                write!(f, "{describe_alias} ")?;
5087
5088                if let Some(format) = hive_format {
5089                    write!(f, "{format} ")?;
5090                }
5091                if *has_table_keyword {
5092                    write!(f, "TABLE ")?;
5093                }
5094
5095                write!(f, "{table_name}")
5096            }
5097            Statement::Explain {
5098                describe_alias,
5099                verbose,
5100                analyze,
5101                query_plan,
5102                estimate,
5103                statement,
5104                format,
5105                options,
5106            } => {
5107                write!(f, "{describe_alias} ")?;
5108
5109                if *query_plan {
5110                    write!(f, "QUERY PLAN ")?;
5111                }
5112                if *analyze {
5113                    write!(f, "ANALYZE ")?;
5114                }
5115                if *estimate {
5116                    write!(f, "ESTIMATE ")?;
5117                }
5118
5119                if *verbose {
5120                    write!(f, "VERBOSE ")?;
5121                }
5122
5123                if let Some(format) = format {
5124                    write!(f, "{format} ")?;
5125                }
5126
5127                if let Some(options) = options {
5128                    write!(f, "({}) ", display_comma_separated(options))?;
5129                }
5130
5131                write!(f, "{statement}")
5132            }
5133            Statement::Query(s) => s.fmt(f),
5134            Statement::Declare { stmts } => {
5135                write!(f, "DECLARE ")?;
5136                write!(f, "{}", display_separated(stmts, "; "))
5137            }
5138            Statement::Fetch {
5139                name,
5140                direction,
5141                position,
5142                into,
5143            } => {
5144                write!(f, "FETCH {direction} {position} {name}")?;
5145
5146                if let Some(into) = into {
5147                    write!(f, " INTO {into}")?;
5148                }
5149
5150                Ok(())
5151            }
5152            Statement::Directory {
5153                overwrite,
5154                local,
5155                path,
5156                file_format,
5157                source,
5158            } => {
5159                write!(
5160                    f,
5161                    "INSERT{overwrite}{local} DIRECTORY '{path}'",
5162                    overwrite = if *overwrite { " OVERWRITE" } else { "" },
5163                    local = if *local { " LOCAL" } else { "" },
5164                    path = path
5165                )?;
5166                if let Some(ref ff) = file_format {
5167                    write!(f, " STORED AS {ff}")?
5168                }
5169                write!(f, " {source}")
5170            }
5171            Statement::Msck(msck) => msck.fmt(f),
5172            Statement::Truncate(truncate) => truncate.fmt(f),
5173            Statement::Case(stmt) => {
5174                write!(f, "{stmt}")
5175            }
5176            Statement::If(stmt) => {
5177                write!(f, "{stmt}")
5178            }
5179            Statement::While(stmt) => {
5180                write!(f, "{stmt}")
5181            }
5182            Statement::Raise(stmt) => {
5183                write!(f, "{stmt}")
5184            }
5185            Statement::AttachDatabase {
5186                schema_name,
5187                database_file_name,
5188                database,
5189            } => {
5190                let keyword = if *database { "DATABASE " } else { "" };
5191                write!(f, "ATTACH {keyword}{database_file_name} AS {schema_name}")
5192            }
5193            Statement::AttachDuckDBDatabase {
5194                if_not_exists,
5195                database,
5196                database_path,
5197                database_alias,
5198                attach_options,
5199            } => {
5200                write!(
5201                    f,
5202                    "ATTACH{database}{if_not_exists} {database_path}",
5203                    database = if *database { " DATABASE" } else { "" },
5204                    if_not_exists = if *if_not_exists { " IF NOT EXISTS" } else { "" },
5205                )?;
5206                if let Some(alias) = database_alias {
5207                    write!(f, " AS {alias}")?;
5208                }
5209                if !attach_options.is_empty() {
5210                    write!(f, " ({})", display_comma_separated(attach_options))?;
5211                }
5212                Ok(())
5213            }
5214            Statement::DetachDuckDBDatabase {
5215                if_exists,
5216                database,
5217                database_alias,
5218            } => {
5219                write!(
5220                    f,
5221                    "DETACH{database}{if_exists} {database_alias}",
5222                    database = if *database { " DATABASE" } else { "" },
5223                    if_exists = if *if_exists { " IF EXISTS" } else { "" },
5224                )?;
5225                Ok(())
5226            }
5227            Statement::Analyze(analyze) => analyze.fmt(f),
5228            Statement::Insert(insert) => insert.fmt(f),
5229            Statement::Install {
5230                extension_name: name,
5231            } => write!(f, "INSTALL {name}"),
5232
5233            Statement::Load {
5234                extension_name: name,
5235            } => write!(f, "LOAD {name}"),
5236
5237            Statement::Call(function) => write!(f, "CALL {function}"),
5238
5239            Statement::Copy {
5240                source,
5241                to,
5242                target,
5243                options,
5244                legacy_options,
5245                values,
5246            } => {
5247                write!(f, "COPY")?;
5248                match source {
5249                    CopySource::Query(query) => write!(f, " ({query})")?,
5250                    CopySource::Table {
5251                        table_name,
5252                        columns,
5253                    } => {
5254                        write!(f, " {table_name}")?;
5255                        if !columns.is_empty() {
5256                            write!(f, " ({})", display_comma_separated(columns))?;
5257                        }
5258                    }
5259                }
5260                write!(f, " {} {}", if *to { "TO" } else { "FROM" }, target)?;
5261                if !options.is_empty() {
5262                    write!(f, " ({})", display_comma_separated(options))?;
5263                }
5264                if !legacy_options.is_empty() {
5265                    write!(f, " {}", display_separated(legacy_options, " "))?;
5266                }
5267                if !values.is_empty() {
5268                    writeln!(f, ";")?;
5269                    let mut delim = "";
5270                    for v in values {
5271                        write!(f, "{delim}")?;
5272                        delim = "\t";
5273                        if let Some(v) = v {
5274                            write!(f, "{v}")?;
5275                        } else {
5276                            write!(f, "\\N")?;
5277                        }
5278                    }
5279                    write!(f, "\n\\.")?;
5280                }
5281                Ok(())
5282            }
5283            Statement::Update(update) => update.fmt(f),
5284            Statement::Delete(delete) => delete.fmt(f),
5285            Statement::Open(open) => open.fmt(f),
5286            Statement::Close { cursor } => {
5287                write!(f, "CLOSE {cursor}")?;
5288
5289                Ok(())
5290            }
5291            Statement::CreateDatabase {
5292                db_name,
5293                if_not_exists,
5294                location,
5295                managed_location,
5296                or_replace,
5297                transient,
5298                clone,
5299                data_retention_time_in_days,
5300                max_data_extension_time_in_days,
5301                external_volume,
5302                catalog,
5303                replace_invalid_characters,
5304                default_ddl_collation,
5305                storage_serialization_policy,
5306                comment,
5307                default_charset,
5308                default_collation,
5309                catalog_sync,
5310                catalog_sync_namespace_mode,
5311                catalog_sync_namespace_flatten_delimiter,
5312                with_tags,
5313                with_contacts,
5314            } => {
5315                write!(
5316                    f,
5317                    "CREATE {or_replace}{transient}DATABASE {if_not_exists}{name}",
5318                    or_replace = if *or_replace { "OR REPLACE " } else { "" },
5319                    transient = if *transient { "TRANSIENT " } else { "" },
5320                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
5321                    name = db_name,
5322                )?;
5323
5324                if let Some(l) = location {
5325                    write!(f, " LOCATION '{l}'")?;
5326                }
5327                if let Some(ml) = managed_location {
5328                    write!(f, " MANAGEDLOCATION '{ml}'")?;
5329                }
5330                if let Some(clone) = clone {
5331                    write!(f, " CLONE {clone}")?;
5332                }
5333
5334                if let Some(value) = data_retention_time_in_days {
5335                    write!(f, " DATA_RETENTION_TIME_IN_DAYS = {value}")?;
5336                }
5337
5338                if let Some(value) = max_data_extension_time_in_days {
5339                    write!(f, " MAX_DATA_EXTENSION_TIME_IN_DAYS = {value}")?;
5340                }
5341
5342                if let Some(vol) = external_volume {
5343                    write!(f, " EXTERNAL_VOLUME = '{vol}'")?;
5344                }
5345
5346                if let Some(cat) = catalog {
5347                    write!(f, " CATALOG = '{cat}'")?;
5348                }
5349
5350                if let Some(true) = replace_invalid_characters {
5351                    write!(f, " REPLACE_INVALID_CHARACTERS = TRUE")?;
5352                } else if let Some(false) = replace_invalid_characters {
5353                    write!(f, " REPLACE_INVALID_CHARACTERS = FALSE")?;
5354                }
5355
5356                if let Some(collation) = default_ddl_collation {
5357                    write!(f, " DEFAULT_DDL_COLLATION = '{collation}'")?;
5358                }
5359
5360                if let Some(policy) = storage_serialization_policy {
5361                    write!(f, " STORAGE_SERIALIZATION_POLICY = {policy}")?;
5362                }
5363
5364                if let Some(comment) = comment {
5365                    write!(f, " COMMENT = '{comment}'")?;
5366                }
5367
5368                if let Some(charset) = default_charset {
5369                    write!(f, " DEFAULT CHARACTER SET {charset}")?;
5370                }
5371
5372                if let Some(collation) = default_collation {
5373                    write!(f, " DEFAULT COLLATE {collation}")?;
5374                }
5375
5376                if let Some(sync) = catalog_sync {
5377                    write!(f, " CATALOG_SYNC = '{sync}'")?;
5378                }
5379
5380                if let Some(mode) = catalog_sync_namespace_mode {
5381                    write!(f, " CATALOG_SYNC_NAMESPACE_MODE = {mode}")?;
5382                }
5383
5384                if let Some(delim) = catalog_sync_namespace_flatten_delimiter {
5385                    write!(f, " CATALOG_SYNC_NAMESPACE_FLATTEN_DELIMITER = '{delim}'")?;
5386                }
5387
5388                if let Some(tags) = with_tags {
5389                    write!(f, " WITH TAG ({})", display_comma_separated(tags))?;
5390                }
5391
5392                if let Some(contacts) = with_contacts {
5393                    write!(f, " WITH CONTACT ({})", display_comma_separated(contacts))?;
5394                }
5395                Ok(())
5396            }
5397            Statement::CreateFunction(create_function) => create_function.fmt(f),
5398            Statement::CreateDomain(create_domain) => create_domain.fmt(f),
5399            Statement::CreateTrigger(create_trigger) => create_trigger.fmt(f),
5400            Statement::DropTrigger(drop_trigger) => drop_trigger.fmt(f),
5401            Statement::CreateProcedure {
5402                name,
5403                or_alter,
5404                params,
5405                language,
5406                body,
5407            } => {
5408                write!(
5409                    f,
5410                    "CREATE {or_alter}PROCEDURE {name}",
5411                    or_alter = if *or_alter { "OR ALTER " } else { "" },
5412                    name = name
5413                )?;
5414
5415                if let Some(p) = params {
5416                    if !p.is_empty() {
5417                        write!(f, " ({})", display_comma_separated(p))?;
5418                    }
5419                }
5420
5421                if let Some(language) = language {
5422                    write!(f, " LANGUAGE {language}")?;
5423                }
5424
5425                write!(f, " AS {body}")
5426            }
5427            Statement::CreateMacro {
5428                or_replace,
5429                temporary,
5430                name,
5431                args,
5432                definition,
5433            } => {
5434                write!(
5435                    f,
5436                    "CREATE {or_replace}{temp}MACRO {name}",
5437                    temp = if *temporary { "TEMPORARY " } else { "" },
5438                    or_replace = if *or_replace { "OR REPLACE " } else { "" },
5439                )?;
5440                if let Some(args) = args {
5441                    write!(f, "({})", display_comma_separated(args))?;
5442                }
5443                match definition {
5444                    MacroDefinition::Expr(expr) => write!(f, " AS {expr}")?,
5445                    MacroDefinition::Table(query) => write!(f, " AS TABLE {query}")?,
5446                }
5447                Ok(())
5448            }
5449            Statement::CreateView(create_view) => create_view.fmt(f),
5450            Statement::CreateTable(create_table) => create_table.fmt(f),
5451            Statement::LoadData {
5452                local,
5453                inpath,
5454                overwrite,
5455                table_name,
5456                partitioned,
5457                table_format,
5458            } => {
5459                write!(
5460                    f,
5461                    "LOAD DATA {local}INPATH '{inpath}' {overwrite}INTO TABLE {table_name}",
5462                    local = if *local { "LOCAL " } else { "" },
5463                    inpath = inpath,
5464                    overwrite = if *overwrite { "OVERWRITE " } else { "" },
5465                    table_name = table_name,
5466                )?;
5467                if let Some(ref parts) = &partitioned {
5468                    if !parts.is_empty() {
5469                        write!(f, " PARTITION ({})", display_comma_separated(parts))?;
5470                    }
5471                }
5472                if let Some(HiveLoadDataFormat {
5473                    serde,
5474                    input_format,
5475                }) = &table_format
5476                {
5477                    write!(f, " INPUTFORMAT {input_format} SERDE {serde}")?;
5478                }
5479                Ok(())
5480            }
5481            Statement::CreateVirtualTable {
5482                name,
5483                if_not_exists,
5484                module_name,
5485                module_args,
5486            } => {
5487                write!(
5488                    f,
5489                    "CREATE VIRTUAL TABLE {if_not_exists}{name} USING {module_name}",
5490                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
5491                    name = name,
5492                    module_name = module_name
5493                )?;
5494                if !module_args.is_empty() {
5495                    write!(f, " ({})", display_comma_separated(module_args))?;
5496                }
5497                Ok(())
5498            }
5499            Statement::CreateIndex(create_index) => create_index.fmt(f),
5500            Statement::CreateExtension(create_extension) => write!(f, "{create_extension}"),
5501            Statement::CreateCollation(create_collation) => write!(f, "{create_collation}"),
5502            Statement::CreateTextSearchConfiguration(v) => write!(f, "{v}"),
5503            Statement::CreateTextSearchDictionary(v) => write!(f, "{v}"),
5504            Statement::CreateTextSearchParser(v) => write!(f, "{v}"),
5505            Statement::CreateTextSearchTemplate(v) => write!(f, "{v}"),
5506            Statement::DropExtension(drop_extension) => write!(f, "{drop_extension}"),
5507            Statement::DropOperator(drop_operator) => write!(f, "{drop_operator}"),
5508            Statement::DropOperatorFamily(drop_operator_family) => {
5509                write!(f, "{drop_operator_family}")
5510            }
5511            Statement::DropOperatorClass(drop_operator_class) => {
5512                write!(f, "{drop_operator_class}")
5513            }
5514            Statement::CreateRole(create_role) => write!(f, "{create_role}"),
5515            Statement::CreateSecret {
5516                or_replace,
5517                temporary,
5518                if_not_exists,
5519                name,
5520                storage_specifier,
5521                secret_type,
5522                options,
5523            } => {
5524                write!(
5525                    f,
5526                    "CREATE {or_replace}",
5527                    or_replace = if *or_replace { "OR REPLACE " } else { "" },
5528                )?;
5529                if let Some(t) = temporary {
5530                    write!(f, "{}", if *t { "TEMPORARY " } else { "PERSISTENT " })?;
5531                }
5532                write!(
5533                    f,
5534                    "SECRET {if_not_exists}",
5535                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
5536                )?;
5537                if let Some(n) = name {
5538                    write!(f, "{n} ")?;
5539                };
5540                if let Some(s) = storage_specifier {
5541                    write!(f, "IN {s} ")?;
5542                }
5543                write!(f, "( TYPE {secret_type}",)?;
5544                if !options.is_empty() {
5545                    write!(f, ", {o}", o = display_comma_separated(options))?;
5546                }
5547                write!(f, " )")?;
5548                Ok(())
5549            }
5550            Statement::CreateServer(stmt) => {
5551                write!(f, "{stmt}")
5552            }
5553            Statement::CreateForeignDataWrapper(stmt) => write!(f, "{stmt}"),
5554            Statement::CreateForeignTable(stmt) => write!(f, "{stmt}"),
5555            Statement::CreatePolicy(policy) => write!(f, "{policy}"),
5556            Statement::CreateConnector(create_connector) => create_connector.fmt(f),
5557            Statement::CreateOperator(create_operator) => create_operator.fmt(f),
5558            Statement::CreateOperatorFamily(create_operator_family) => {
5559                create_operator_family.fmt(f)
5560            }
5561            Statement::CreateOperatorClass(create_operator_class) => create_operator_class.fmt(f),
5562            Statement::CreateAggregate(create_aggregate) => create_aggregate.fmt(f),
5563            Statement::AlterTable(alter_table) => write!(f, "{alter_table}"),
5564            Statement::AlterIndex { name, operation } => {
5565                write!(f, "ALTER INDEX {name} {operation}")
5566            }
5567            Statement::AlterView {
5568                name,
5569                columns,
5570                query,
5571                with_options,
5572            } => {
5573                write!(f, "ALTER VIEW {name}")?;
5574                if !with_options.is_empty() {
5575                    write!(f, " WITH ({})", display_comma_separated(with_options))?;
5576                }
5577                if !columns.is_empty() {
5578                    write!(f, " ({})", display_comma_separated(columns))?;
5579                }
5580                write!(f, " AS {query}")
5581            }
5582            Statement::AlterFunction(alter_function) => write!(f, "{alter_function}"),
5583            Statement::AlterType(AlterType { name, operation }) => {
5584                write!(f, "ALTER TYPE {name} {operation}")
5585            }
5586            Statement::AlterCollation(alter_collation) => write!(f, "{alter_collation}"),
5587            Statement::AlterOperator(alter_operator) => write!(f, "{alter_operator}"),
5588            Statement::AlterOperatorFamily(alter_operator_family) => {
5589                write!(f, "{alter_operator_family}")
5590            }
5591            Statement::AlterOperatorClass(alter_operator_class) => {
5592                write!(f, "{alter_operator_class}")
5593            }
5594            Statement::AlterRole { name, operation } => {
5595                write!(f, "ALTER ROLE {name} {operation}")
5596            }
5597            Statement::AlterPolicy(alter_policy) => write!(f, "{alter_policy}"),
5598            Statement::AlterConnector {
5599                name,
5600                properties,
5601                url,
5602                owner,
5603            } => {
5604                write!(f, "ALTER CONNECTOR {name}")?;
5605                if let Some(properties) = properties {
5606                    write!(
5607                        f,
5608                        " SET DCPROPERTIES({})",
5609                        display_comma_separated(properties)
5610                    )?;
5611                }
5612                if let Some(url) = url {
5613                    write!(f, " SET URL '{url}'")?;
5614                }
5615                if let Some(owner) = owner {
5616                    write!(f, " SET OWNER {owner}")?;
5617                }
5618                Ok(())
5619            }
5620            Statement::AlterSession {
5621                set,
5622                session_params,
5623            } => {
5624                write!(
5625                    f,
5626                    "ALTER SESSION {set}",
5627                    set = if *set { "SET" } else { "UNSET" }
5628                )?;
5629                if !session_params.options.is_empty() {
5630                    if *set {
5631                        write!(f, " {session_params}")?;
5632                    } else {
5633                        let options = session_params
5634                            .options
5635                            .iter()
5636                            .map(|p| p.option_name.clone())
5637                            .collect::<Vec<_>>();
5638                        write!(f, " {}", display_separated(&options, ", "))?;
5639                    }
5640                }
5641                Ok(())
5642            }
5643            Statement::Drop {
5644                object_type,
5645                if_exists,
5646                names,
5647                cascade,
5648                restrict,
5649                purge,
5650                temporary,
5651                table,
5652            } => {
5653                write!(
5654                    f,
5655                    "DROP {}{}{} {}{}{}{}",
5656                    if *temporary { "TEMPORARY " } else { "" },
5657                    object_type,
5658                    if *if_exists { " IF EXISTS" } else { "" },
5659                    display_comma_separated(names),
5660                    if *cascade { " CASCADE" } else { "" },
5661                    if *restrict { " RESTRICT" } else { "" },
5662                    if *purge { " PURGE" } else { "" },
5663                )?;
5664                if let Some(table_name) = table.as_ref() {
5665                    write!(f, " ON {table_name}")?;
5666                };
5667                Ok(())
5668            }
5669            Statement::DropFunction(drop_function) => write!(f, "{drop_function}"),
5670            Statement::DropDomain(DropDomain {
5671                if_exists,
5672                name,
5673                drop_behavior,
5674            }) => {
5675                write!(
5676                    f,
5677                    "DROP DOMAIN{} {name}",
5678                    if *if_exists { " IF EXISTS" } else { "" },
5679                )?;
5680                if let Some(op) = drop_behavior {
5681                    write!(f, " {op}")?;
5682                }
5683                Ok(())
5684            }
5685            Statement::DropProcedure {
5686                if_exists,
5687                proc_desc,
5688                drop_behavior,
5689            } => {
5690                write!(
5691                    f,
5692                    "DROP PROCEDURE{} {}",
5693                    if *if_exists { " IF EXISTS" } else { "" },
5694                    display_comma_separated(proc_desc),
5695                )?;
5696                if let Some(op) = drop_behavior {
5697                    write!(f, " {op}")?;
5698                }
5699                Ok(())
5700            }
5701            Statement::DropSecret {
5702                if_exists,
5703                temporary,
5704                name,
5705                storage_specifier,
5706            } => {
5707                write!(f, "DROP ")?;
5708                if let Some(t) = temporary {
5709                    write!(f, "{}", if *t { "TEMPORARY " } else { "PERSISTENT " })?;
5710                }
5711                write!(
5712                    f,
5713                    "SECRET {if_exists}{name}",
5714                    if_exists = if *if_exists { "IF EXISTS " } else { "" },
5715                )?;
5716                if let Some(s) = storage_specifier {
5717                    write!(f, " FROM {s}")?;
5718                }
5719                Ok(())
5720            }
5721            Statement::DropPolicy(policy) => write!(f, "{policy}"),
5722            Statement::DropConnector { if_exists, name } => {
5723                write!(
5724                    f,
5725                    "DROP CONNECTOR {if_exists}{name}",
5726                    if_exists = if *if_exists { "IF EXISTS " } else { "" }
5727                )?;
5728                Ok(())
5729            }
5730            Statement::Discard { object_type } => {
5731                write!(f, "DISCARD {object_type}")?;
5732                Ok(())
5733            }
5734            Self::Set(set) => write!(f, "{set}"),
5735            Statement::ShowVariable { variable } => {
5736                write!(f, "SHOW")?;
5737                if !variable.is_empty() {
5738                    write!(f, " {}", display_separated(variable, " "))?;
5739                }
5740                Ok(())
5741            }
5742            Statement::ShowStatus {
5743                filter,
5744                global,
5745                session,
5746            } => {
5747                write!(f, "SHOW")?;
5748                if *global {
5749                    write!(f, " GLOBAL")?;
5750                }
5751                if *session {
5752                    write!(f, " SESSION")?;
5753                }
5754                write!(f, " STATUS")?;
5755                if filter.is_some() {
5756                    write!(f, " {}", filter.as_ref().unwrap())?;
5757                }
5758                Ok(())
5759            }
5760            Statement::ShowVariables {
5761                filter,
5762                global,
5763                session,
5764            } => {
5765                write!(f, "SHOW")?;
5766                if *global {
5767                    write!(f, " GLOBAL")?;
5768                }
5769                if *session {
5770                    write!(f, " SESSION")?;
5771                }
5772                write!(f, " VARIABLES")?;
5773                if filter.is_some() {
5774                    write!(f, " {}", filter.as_ref().unwrap())?;
5775                }
5776                Ok(())
5777            }
5778            Statement::ShowCreate { obj_type, obj_name } => {
5779                write!(f, "SHOW CREATE {obj_type} {obj_name}",)?;
5780                Ok(())
5781            }
5782            Statement::ShowColumns {
5783                extended,
5784                full,
5785                show_options,
5786            } => {
5787                write!(
5788                    f,
5789                    "SHOW {extended}{full}COLUMNS{show_options}",
5790                    extended = if *extended { "EXTENDED " } else { "" },
5791                    full = if *full { "FULL " } else { "" },
5792                )?;
5793                Ok(())
5794            }
5795            Statement::ShowDatabases {
5796                terse,
5797                history,
5798                show_options,
5799            } => {
5800                write!(
5801                    f,
5802                    "SHOW {terse}DATABASES{history}{show_options}",
5803                    terse = if *terse { "TERSE " } else { "" },
5804                    history = if *history { " HISTORY" } else { "" },
5805                )?;
5806                Ok(())
5807            }
5808            Statement::ShowCatalogs {
5809                terse,
5810                history,
5811                show_options,
5812            } => {
5813                write!(
5814                    f,
5815                    "SHOW {terse}CATALOGS{history}{show_options}",
5816                    terse = if *terse { "TERSE " } else { "" },
5817                    history = if *history { " HISTORY" } else { "" },
5818                )?;
5819                Ok(())
5820            }
5821            Statement::ShowProcessList { full } => {
5822                write!(
5823                    f,
5824                    "SHOW {full}PROCESSLIST",
5825                    full = if *full { "FULL " } else { "" },
5826                )?;
5827                Ok(())
5828            }
5829            Statement::ShowSchemas {
5830                terse,
5831                history,
5832                show_options,
5833            } => {
5834                write!(
5835                    f,
5836                    "SHOW {terse}SCHEMAS{history}{show_options}",
5837                    terse = if *terse { "TERSE " } else { "" },
5838                    history = if *history { " HISTORY" } else { "" },
5839                )?;
5840                Ok(())
5841            }
5842            Statement::ShowObjects(ShowObjects {
5843                terse,
5844                show_options,
5845            }) => {
5846                write!(
5847                    f,
5848                    "SHOW {terse}OBJECTS{show_options}",
5849                    terse = if *terse { "TERSE " } else { "" },
5850                )?;
5851                Ok(())
5852            }
5853            Statement::ShowTables {
5854                terse,
5855                history,
5856                extended,
5857                full,
5858                external,
5859                show_options,
5860            } => {
5861                write!(
5862                    f,
5863                    "SHOW {terse}{extended}{full}{external}TABLES{history}{show_options}",
5864                    terse = if *terse { "TERSE " } else { "" },
5865                    extended = if *extended { "EXTENDED " } else { "" },
5866                    full = if *full { "FULL " } else { "" },
5867                    external = if *external { "EXTERNAL " } else { "" },
5868                    history = if *history { " HISTORY" } else { "" },
5869                )?;
5870                Ok(())
5871            }
5872            Statement::ShowViews {
5873                terse,
5874                materialized,
5875                show_options,
5876            } => {
5877                write!(
5878                    f,
5879                    "SHOW {terse}{materialized}VIEWS{show_options}",
5880                    terse = if *terse { "TERSE " } else { "" },
5881                    materialized = if *materialized { "MATERIALIZED " } else { "" }
5882                )?;
5883                Ok(())
5884            }
5885            Statement::ShowFunctions { filter } => {
5886                write!(f, "SHOW FUNCTIONS")?;
5887                if let Some(filter) = filter {
5888                    write!(f, " {filter}")?;
5889                }
5890                Ok(())
5891            }
5892            Statement::Use(use_expr) => use_expr.fmt(f),
5893            Statement::ShowCollation { filter } => {
5894                write!(f, "SHOW COLLATION")?;
5895                if let Some(filter) = filter {
5896                    write!(f, " {filter}")?;
5897                }
5898                Ok(())
5899            }
5900            Statement::ShowCharset(show_stm) => show_stm.fmt(f),
5901            Statement::StartTransaction {
5902                modes,
5903                begin: syntax_begin,
5904                transaction,
5905                modifier,
5906                statements,
5907                exception,
5908                has_end_keyword,
5909            } => {
5910                if *syntax_begin {
5911                    if let Some(modifier) = *modifier {
5912                        write!(f, "BEGIN {modifier}")?;
5913                    } else {
5914                        write!(f, "BEGIN")?;
5915                    }
5916                } else {
5917                    write!(f, "START")?;
5918                }
5919                if let Some(transaction) = transaction {
5920                    write!(f, " {transaction}")?;
5921                }
5922                if !modes.is_empty() {
5923                    write!(f, " {}", display_comma_separated(modes))?;
5924                }
5925                if !statements.is_empty() {
5926                    write!(f, " ")?;
5927                    format_statement_list(f, statements)?;
5928                }
5929                if let Some(exception_when) = exception {
5930                    write!(f, " EXCEPTION")?;
5931                    for when in exception_when {
5932                        write!(f, " {when}")?;
5933                    }
5934                }
5935                if *has_end_keyword {
5936                    write!(f, " END")?;
5937                }
5938                Ok(())
5939            }
5940            Statement::Commit {
5941                chain,
5942                end: end_syntax,
5943                modifier,
5944            } => {
5945                if *end_syntax {
5946                    write!(f, "END")?;
5947                    if let Some(modifier) = *modifier {
5948                        write!(f, " {modifier}")?;
5949                    }
5950                    if *chain {
5951                        write!(f, " AND CHAIN")?;
5952                    }
5953                } else {
5954                    write!(f, "COMMIT{}", if *chain { " AND CHAIN" } else { "" })?;
5955                }
5956                Ok(())
5957            }
5958            Statement::Rollback { chain, savepoint } => {
5959                write!(f, "ROLLBACK")?;
5960
5961                if *chain {
5962                    write!(f, " AND CHAIN")?;
5963                }
5964
5965                if let Some(savepoint) = savepoint {
5966                    write!(f, " TO SAVEPOINT {savepoint}")?;
5967                }
5968
5969                Ok(())
5970            }
5971            Statement::CreateSchema {
5972                schema_name,
5973                if_not_exists,
5974                with,
5975                options,
5976                default_collate_spec,
5977                clone,
5978            } => {
5979                write!(
5980                    f,
5981                    "CREATE SCHEMA {if_not_exists}{name}",
5982                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
5983                    name = schema_name
5984                )?;
5985
5986                if let Some(collate) = default_collate_spec {
5987                    write!(f, " DEFAULT COLLATE {collate}")?;
5988                }
5989
5990                if let Some(with) = with {
5991                    write!(f, " WITH ({})", display_comma_separated(with))?;
5992                }
5993
5994                if let Some(options) = options {
5995                    write!(f, " OPTIONS({})", display_comma_separated(options))?;
5996                }
5997
5998                if let Some(clone) = clone {
5999                    write!(f, " CLONE {clone}")?;
6000                }
6001                Ok(())
6002            }
6003            Statement::Assert { condition, message } => {
6004                write!(f, "ASSERT {condition}")?;
6005                if let Some(m) = message {
6006                    write!(f, " AS {m}")?;
6007                }
6008                Ok(())
6009            }
6010            Statement::Grant(grant) => write!(f, "{grant}"),
6011            Statement::Deny(s) => write!(f, "{s}"),
6012            Statement::Revoke(revoke) => write!(f, "{revoke}"),
6013            Statement::Deallocate { name, prepare } => write!(
6014                f,
6015                "DEALLOCATE {prepare}{name}",
6016                prepare = if *prepare { "PREPARE " } else { "" },
6017                name = name,
6018            ),
6019            Statement::Execute {
6020                name,
6021                parameters,
6022                has_parentheses,
6023                immediate,
6024                into,
6025                using,
6026                output,
6027                default,
6028            } => {
6029                let (open, close) = if *has_parentheses {
6030                    // Space before `(` only when there is no name directly preceding it.
6031                    (if name.is_some() { "(" } else { " (" }, ")")
6032                } else {
6033                    (if parameters.is_empty() { "" } else { " " }, "")
6034                };
6035                write!(f, "EXECUTE")?;
6036                if *immediate {
6037                    write!(f, " IMMEDIATE")?;
6038                }
6039                if let Some(name) = name {
6040                    write!(f, " {name}")?;
6041                }
6042                write!(f, "{open}{}{close}", display_comma_separated(parameters),)?;
6043                if !into.is_empty() {
6044                    write!(f, " INTO {}", display_comma_separated(into))?;
6045                }
6046                if !using.is_empty() {
6047                    write!(f, " USING {}", display_comma_separated(using))?;
6048                };
6049                if *output {
6050                    write!(f, " OUTPUT")?;
6051                }
6052                if *default {
6053                    write!(f, " DEFAULT")?;
6054                }
6055                Ok(())
6056            }
6057            Statement::Prepare {
6058                name,
6059                data_types,
6060                statement,
6061            } => {
6062                write!(f, "PREPARE {name} ")?;
6063                if !data_types.is_empty() {
6064                    write!(f, "({}) ", display_comma_separated(data_types))?;
6065                }
6066                write!(f, "AS {statement}")
6067            }
6068            Statement::Comment {
6069                object_type,
6070                object_name,
6071                comment,
6072                if_exists,
6073            } => {
6074                write!(f, "COMMENT ")?;
6075                if *if_exists {
6076                    write!(f, "IF EXISTS ")?
6077                };
6078                write!(f, "ON {object_type} {object_name} IS ")?;
6079                if let Some(c) = comment {
6080                    write!(f, "'{c}'")
6081                } else {
6082                    write!(f, "NULL")
6083                }
6084            }
6085            Statement::Savepoint { name } => {
6086                write!(f, "SAVEPOINT ")?;
6087                write!(f, "{name}")
6088            }
6089            Statement::ReleaseSavepoint { name } => {
6090                write!(f, "RELEASE SAVEPOINT {name}")
6091            }
6092            Statement::Merge(merge) => merge.fmt(f),
6093            Statement::Cache {
6094                table_name,
6095                table_flag,
6096                has_as,
6097                options,
6098                query,
6099            } => {
6100                if let Some(table_flag) = table_flag {
6101                    write!(f, "CACHE {table_flag} TABLE {table_name}")?;
6102                } else {
6103                    write!(f, "CACHE TABLE {table_name}")?;
6104                }
6105
6106                if !options.is_empty() {
6107                    write!(f, " OPTIONS({})", display_comma_separated(options))?;
6108                }
6109
6110                match (*has_as, query) {
6111                    (true, Some(query)) => write!(f, " AS {query}"),
6112                    (true, None) => f.write_str(" AS"),
6113                    (false, Some(query)) => write!(f, " {query}"),
6114                    (false, None) => Ok(()),
6115                }
6116            }
6117            Statement::UNCache {
6118                table_name,
6119                if_exists,
6120            } => {
6121                if *if_exists {
6122                    write!(f, "UNCACHE TABLE IF EXISTS {table_name}")
6123                } else {
6124                    write!(f, "UNCACHE TABLE {table_name}")
6125                }
6126            }
6127            Statement::CreateSequence {
6128                temporary,
6129                if_not_exists,
6130                name,
6131                data_type,
6132                sequence_options,
6133                owned_by,
6134            } => {
6135                let as_type: String = if let Some(dt) = data_type.as_ref() {
6136                    //Cannot use format!(" AS {}", dt), due to format! is not available in --target thumbv6m-none-eabi
6137                    // " AS ".to_owned() + &dt.to_string()
6138                    [" AS ", &dt.to_string()].concat()
6139                } else {
6140                    "".to_string()
6141                };
6142                write!(
6143                    f,
6144                    "CREATE {temporary}SEQUENCE {if_not_exists}{name}{as_type}",
6145                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
6146                    temporary = if *temporary { "TEMPORARY " } else { "" },
6147                    name = name,
6148                    as_type = as_type
6149                )?;
6150                for sequence_option in sequence_options {
6151                    write!(f, "{sequence_option}")?;
6152                }
6153                if let Some(ob) = owned_by.as_ref() {
6154                    write!(f, " OWNED BY {ob}")?;
6155                }
6156                write!(f, "")
6157            }
6158            Statement::CreateStage {
6159                or_replace,
6160                temporary,
6161                if_not_exists,
6162                name,
6163                stage_params,
6164                directory_table_params,
6165                file_format,
6166                copy_options,
6167                comment,
6168                ..
6169            } => {
6170                write!(
6171                    f,
6172                    "CREATE {or_replace}{temp}STAGE {if_not_exists}{name}{stage_params}",
6173                    temp = if *temporary { "TEMPORARY " } else { "" },
6174                    or_replace = if *or_replace { "OR REPLACE " } else { "" },
6175                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
6176                )?;
6177                if !directory_table_params.options.is_empty() {
6178                    write!(f, " DIRECTORY=({directory_table_params})")?;
6179                }
6180                if !file_format.options.is_empty() {
6181                    write!(f, " FILE_FORMAT=({file_format})")?;
6182                }
6183                if !copy_options.options.is_empty() {
6184                    write!(f, " COPY_OPTIONS=({copy_options})")?;
6185                }
6186                if comment.is_some() {
6187                    write!(f, " COMMENT='{}'", comment.as_ref().unwrap())?;
6188                }
6189                Ok(())
6190            }
6191            Statement::CopyIntoSnowflake {
6192                kind,
6193                into,
6194                into_columns,
6195                from_obj,
6196                from_obj_alias,
6197                stage_params,
6198                from_transformations,
6199                from_query,
6200                files,
6201                pattern,
6202                file_format,
6203                copy_options,
6204                validation_mode,
6205                partition,
6206            } => {
6207                write!(f, "COPY INTO {into}")?;
6208                if let Some(into_columns) = into_columns {
6209                    write!(f, " ({})", display_comma_separated(into_columns))?;
6210                }
6211                if let Some(from_transformations) = from_transformations {
6212                    // Data load with transformation
6213                    if let Some(from_stage) = from_obj {
6214                        write!(
6215                            f,
6216                            " FROM (SELECT {} FROM {}{}",
6217                            display_separated(from_transformations, ", "),
6218                            from_stage,
6219                            stage_params
6220                        )?;
6221                    }
6222                    if let Some(from_obj_alias) = from_obj_alias {
6223                        write!(f, " AS {from_obj_alias}")?;
6224                    }
6225                    write!(f, ")")?;
6226                } else if let Some(from_obj) = from_obj {
6227                    // Standard data load
6228                    write!(f, " FROM {from_obj}{stage_params}")?;
6229                    if let Some(from_obj_alias) = from_obj_alias {
6230                        write!(f, " AS {from_obj_alias}")?;
6231                    }
6232                } else if let Some(from_query) = from_query {
6233                    // Data unload from query
6234                    write!(f, " FROM ({from_query})")?;
6235                }
6236
6237                if let Some(files) = files {
6238                    write!(f, " FILES = ('{}')", display_separated(files, "', '"))?;
6239                }
6240                if let Some(pattern) = pattern {
6241                    write!(f, " PATTERN = '{pattern}'")?;
6242                }
6243                if let Some(partition) = partition {
6244                    write!(f, " PARTITION BY {partition}")?;
6245                }
6246                if !file_format.options.is_empty() {
6247                    write!(f, " FILE_FORMAT=({file_format})")?;
6248                }
6249                if !copy_options.options.is_empty() {
6250                    match kind {
6251                        CopyIntoSnowflakeKind::Table => {
6252                            write!(f, " COPY_OPTIONS=({copy_options})")?
6253                        }
6254                        CopyIntoSnowflakeKind::Location => write!(f, " {copy_options}")?,
6255                    }
6256                }
6257                if let Some(validation_mode) = validation_mode {
6258                    write!(f, " VALIDATION_MODE = {validation_mode}")?;
6259                }
6260                Ok(())
6261            }
6262            Statement::CreateType {
6263                name,
6264                representation,
6265            } => {
6266                write!(f, "CREATE TYPE {name}")?;
6267                if let Some(repr) = representation {
6268                    write!(f, " {repr}")?;
6269                }
6270                Ok(())
6271            }
6272            Statement::Pragma { name, value, is_eq } => {
6273                write!(f, "PRAGMA {name}")?;
6274                if value.is_some() {
6275                    let val = value.as_ref().unwrap();
6276                    if *is_eq {
6277                        write!(f, " = {val}")?;
6278                    } else {
6279                        write!(f, "({val})")?;
6280                    }
6281                }
6282                Ok(())
6283            }
6284            Statement::Lock(lock) => lock.fmt(f),
6285            Statement::LockTables { tables } => {
6286                write!(f, "LOCK TABLES {}", display_comma_separated(tables))
6287            }
6288            Statement::UnlockTables => {
6289                write!(f, "UNLOCK TABLES")
6290            }
6291            Statement::Unload {
6292                query,
6293                query_text,
6294                to,
6295                auth,
6296                with,
6297                options,
6298            } => {
6299                write!(f, "UNLOAD(")?;
6300                if let Some(query) = query {
6301                    write!(f, "{query}")?;
6302                }
6303                if let Some(query_text) = query_text {
6304                    write!(f, "'{query_text}'")?;
6305                }
6306                write!(f, ") TO {to}")?;
6307                if let Some(auth) = auth {
6308                    write!(f, " IAM_ROLE {auth}")?;
6309                }
6310                if !with.is_empty() {
6311                    write!(f, " WITH ({})", display_comma_separated(with))?;
6312                }
6313                if !options.is_empty() {
6314                    write!(f, " {}", display_separated(options, " "))?;
6315                }
6316                Ok(())
6317            }
6318            Statement::OptimizeTable {
6319                name,
6320                has_table_keyword,
6321                on_cluster,
6322                partition,
6323                include_final,
6324                deduplicate,
6325                predicate,
6326                zorder,
6327            } => {
6328                write!(f, "OPTIMIZE")?;
6329                if *has_table_keyword {
6330                    write!(f, " TABLE")?;
6331                }
6332                write!(f, " {name}")?;
6333                if let Some(on_cluster) = on_cluster {
6334                    write!(f, " ON CLUSTER {on_cluster}")?;
6335                }
6336                if let Some(partition) = partition {
6337                    write!(f, " {partition}")?;
6338                }
6339                if *include_final {
6340                    write!(f, " FINAL")?;
6341                }
6342                if let Some(deduplicate) = deduplicate {
6343                    write!(f, " {deduplicate}")?;
6344                }
6345                if let Some(predicate) = predicate {
6346                    write!(f, " WHERE {predicate}")?;
6347                }
6348                if let Some(zorder) = zorder {
6349                    write!(f, " ZORDER BY ({})", display_comma_separated(zorder))?;
6350                }
6351                Ok(())
6352            }
6353            Statement::LISTEN { channel } => {
6354                write!(f, "LISTEN {channel}")?;
6355                Ok(())
6356            }
6357            Statement::UNLISTEN { channel } => {
6358                write!(f, "UNLISTEN {channel}")?;
6359                Ok(())
6360            }
6361            Statement::NOTIFY { channel, payload } => {
6362                write!(f, "NOTIFY {channel}")?;
6363                if let Some(payload) = payload {
6364                    write!(f, ", '{payload}'")?;
6365                }
6366                Ok(())
6367            }
6368            Statement::RenameTable(rename_tables) => {
6369                write!(f, "RENAME TABLE {}", display_comma_separated(rename_tables))
6370            }
6371            Statement::RaisError {
6372                message,
6373                severity,
6374                state,
6375                arguments,
6376                options,
6377            } => {
6378                write!(f, "RAISERROR({message}, {severity}, {state}")?;
6379                if !arguments.is_empty() {
6380                    write!(f, ", {}", display_comma_separated(arguments))?;
6381                }
6382                write!(f, ")")?;
6383                if !options.is_empty() {
6384                    write!(f, " WITH {}", display_comma_separated(options))?;
6385                }
6386                Ok(())
6387            }
6388            Statement::Throw(s) => write!(f, "{s}"),
6389            Statement::Print(s) => write!(f, "{s}"),
6390            Statement::WaitFor(s) => write!(f, "{s}"),
6391            Statement::Return(r) => write!(f, "{r}"),
6392            Statement::List(command) => write!(f, "LIST {command}"),
6393            Statement::Remove(command) => write!(f, "REMOVE {command}"),
6394            Statement::ExportData(e) => write!(f, "{e}"),
6395            Statement::CreateUser(s) => write!(f, "{s}"),
6396            Statement::AlterSchema(s) => write!(f, "{s}"),
6397            Statement::Vacuum(s) => write!(f, "{s}"),
6398            Statement::AlterUser(s) => write!(f, "{s}"),
6399            Statement::Reset(s) => write!(f, "{s}"),
6400        }
6401    }
6402}
6403
6404/// Can use to describe options in create sequence or table column type identity
6405/// ```sql
6406/// [ INCREMENT [ BY ] increment ]
6407///     [ MINVALUE minvalue | NO MINVALUE ] [ MAXVALUE maxvalue | NO MAXVALUE ]
6408///     [ START [ WITH ] start ] [ CACHE cache ] [ [ NO ] CYCLE ]
6409/// ```
6410#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6411#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6412#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6413pub enum SequenceOptions {
6414    /// `INCREMENT [BY] <expr>` option; second value indicates presence of `BY` keyword.
6415    IncrementBy(Expr, bool),
6416    /// `MINVALUE <expr>` or `NO MINVALUE`.
6417    MinValue(Option<Expr>),
6418    /// `MAXVALUE <expr>` or `NO MAXVALUE`.
6419    MaxValue(Option<Expr>),
6420    /// `START [WITH] <expr>`; second value indicates presence of `WITH`.
6421    StartWith(Expr, bool),
6422    /// `CACHE <expr>` option.
6423    Cache(Expr),
6424    /// `CYCLE` or `NO CYCLE` option.
6425    Cycle(bool),
6426}
6427
6428impl fmt::Display for SequenceOptions {
6429    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6430        match self {
6431            SequenceOptions::IncrementBy(increment, by) => {
6432                write!(
6433                    f,
6434                    " INCREMENT{by} {increment}",
6435                    by = if *by { " BY" } else { "" },
6436                    increment = increment
6437                )
6438            }
6439            SequenceOptions::MinValue(Some(expr)) => {
6440                write!(f, " MINVALUE {expr}")
6441            }
6442            SequenceOptions::MinValue(None) => {
6443                write!(f, " NO MINVALUE")
6444            }
6445            SequenceOptions::MaxValue(Some(expr)) => {
6446                write!(f, " MAXVALUE {expr}")
6447            }
6448            SequenceOptions::MaxValue(None) => {
6449                write!(f, " NO MAXVALUE")
6450            }
6451            SequenceOptions::StartWith(start, with) => {
6452                write!(
6453                    f,
6454                    " START{with} {start}",
6455                    with = if *with { " WITH" } else { "" },
6456                    start = start
6457                )
6458            }
6459            SequenceOptions::Cache(cache) => {
6460                write!(f, " CACHE {}", *cache)
6461            }
6462            SequenceOptions::Cycle(no) => {
6463                write!(f, " {}CYCLE", if *no { "NO " } else { "" })
6464            }
6465        }
6466    }
6467}
6468
6469/// Assignment for a `SET` statement (name [=|TO] value)
6470#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6471#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6472#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6473pub struct SetAssignment {
6474    /// Optional context scope (e.g., SESSION or LOCAL).
6475    pub scope: Option<ContextModifier>,
6476    /// Assignment target name.
6477    pub name: ObjectName,
6478    /// Assigned expression value.
6479    pub value: Expr,
6480}
6481
6482impl fmt::Display for SetAssignment {
6483    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6484        write!(
6485            f,
6486            "{}{} = {}",
6487            self.scope.map(|s| format!("{s}")).unwrap_or_default(),
6488            self.name,
6489            self.value
6490        )
6491    }
6492}
6493
6494/// Target of a `TRUNCATE TABLE` command
6495///
6496/// Note this is its own struct because `visit_relation` requires an `ObjectName` (not a `Vec<ObjectName>`)
6497#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6498#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6499#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6500pub struct TruncateTableTarget {
6501    /// name of the table being truncated
6502    #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
6503    pub name: ObjectName,
6504    /// Postgres-specific option: explicitly exclude descendants (also default without ONLY)
6505    /// ```sql
6506    /// TRUNCATE TABLE ONLY name
6507    /// ```
6508    /// <https://www.postgresql.org/docs/current/sql-truncate.html>
6509    pub only: bool,
6510    /// Postgres-specific option: asterisk after table name to explicitly indicate descendants
6511    /// ```sql
6512    /// TRUNCATE TABLE name [ * ]
6513    /// ```
6514    /// <https://www.postgresql.org/docs/current/sql-truncate.html>
6515    pub has_asterisk: bool,
6516}
6517
6518impl fmt::Display for TruncateTableTarget {
6519    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6520        if self.only {
6521            write!(f, "ONLY ")?;
6522        };
6523        write!(f, "{}", self.name)?;
6524        if self.has_asterisk {
6525            write!(f, " *")?;
6526        };
6527        Ok(())
6528    }
6529}
6530
6531/// A `LOCK` statement.
6532///
6533/// See <https://www.postgresql.org/docs/current/sql-lock.html>
6534#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6535#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6536#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6537pub struct Lock {
6538    /// List of tables to lock.
6539    pub tables: Vec<LockTableTarget>,
6540    /// Lock mode.
6541    pub lock_mode: Option<LockTableMode>,
6542    /// Whether `NOWAIT` was specified.
6543    pub nowait: bool,
6544}
6545
6546impl fmt::Display for Lock {
6547    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6548        write!(f, "LOCK TABLE {}", display_comma_separated(&self.tables))?;
6549        if let Some(lock_mode) = &self.lock_mode {
6550            write!(f, " IN {lock_mode} MODE")?;
6551        }
6552        if self.nowait {
6553            write!(f, " NOWAIT")?;
6554        }
6555        Ok(())
6556    }
6557}
6558
6559/// Target of a `LOCK TABLE` command
6560///
6561/// See <https://www.postgresql.org/docs/current/sql-lock.html>
6562#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6563#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6564#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6565pub struct LockTableTarget {
6566    /// Name of the table being locked.
6567    #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
6568    pub name: ObjectName,
6569    /// Whether `ONLY` was specified to exclude descendant tables.
6570    pub only: bool,
6571    /// Whether `*` was specified to explicitly include descendant tables.
6572    pub has_asterisk: bool,
6573}
6574
6575impl fmt::Display for LockTableTarget {
6576    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6577        if self.only {
6578            write!(f, "ONLY ")?;
6579        }
6580        write!(f, "{}", self.name)?;
6581        if self.has_asterisk {
6582            write!(f, " *")?;
6583        }
6584        Ok(())
6585    }
6586}
6587
6588/// PostgreSQL lock modes for `LOCK TABLE`.
6589///
6590/// See <https://www.postgresql.org/docs/current/sql-lock.html>
6591#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6592#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6593#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6594pub enum LockTableMode {
6595    /// `ACCESS SHARE`
6596    AccessShare,
6597    /// `ROW SHARE`
6598    RowShare,
6599    /// `ROW EXCLUSIVE`
6600    RowExclusive,
6601    /// `SHARE UPDATE EXCLUSIVE`
6602    ShareUpdateExclusive,
6603    /// `SHARE`
6604    Share,
6605    /// `SHARE ROW EXCLUSIVE`
6606    ShareRowExclusive,
6607    /// `EXCLUSIVE`
6608    Exclusive,
6609    /// `ACCESS EXCLUSIVE`
6610    AccessExclusive,
6611}
6612
6613impl fmt::Display for LockTableMode {
6614    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
6615        let text = match self {
6616            Self::AccessShare => "ACCESS SHARE",
6617            Self::RowShare => "ROW SHARE",
6618            Self::RowExclusive => "ROW EXCLUSIVE",
6619            Self::ShareUpdateExclusive => "SHARE UPDATE EXCLUSIVE",
6620            Self::Share => "SHARE",
6621            Self::ShareRowExclusive => "SHARE ROW EXCLUSIVE",
6622            Self::Exclusive => "EXCLUSIVE",
6623            Self::AccessExclusive => "ACCESS EXCLUSIVE",
6624        };
6625        write!(f, "{text}")
6626    }
6627}
6628
6629/// PostgreSQL identity option for TRUNCATE table
6630/// [ RESTART IDENTITY | CONTINUE IDENTITY ]
6631#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6632#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6633#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6634pub enum TruncateIdentityOption {
6635    /// Restart identity values (RESTART IDENTITY).
6636    Restart,
6637    /// Continue identity values (CONTINUE IDENTITY).
6638    Continue,
6639}
6640
6641/// Cascade/restrict option for Postgres TRUNCATE table, MySQL GRANT/REVOKE, etc.
6642/// [ CASCADE | RESTRICT ]
6643#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6644#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6645#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6646pub enum CascadeOption {
6647    /// Apply cascading action (e.g., CASCADE).
6648    Cascade,
6649    /// Restrict the action (e.g., RESTRICT).
6650    Restrict,
6651}
6652
6653impl Display for CascadeOption {
6654    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6655        match self {
6656            CascadeOption::Cascade => write!(f, "CASCADE"),
6657            CascadeOption::Restrict => write!(f, "RESTRICT"),
6658        }
6659    }
6660}
6661
6662/// Transaction started with [ TRANSACTION | WORK | TRAN ]
6663#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6664#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6665#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6666pub enum BeginTransactionKind {
6667    /// Standard `TRANSACTION` keyword.
6668    Transaction,
6669    /// Alternate `WORK` keyword.
6670    Work,
6671    /// MSSQL shorthand `TRAN` keyword.
6672    /// See <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/begin-transaction-transact-sql>
6673    Tran,
6674}
6675
6676impl Display for BeginTransactionKind {
6677    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6678        match self {
6679            BeginTransactionKind::Transaction => write!(f, "TRANSACTION"),
6680            BeginTransactionKind::Work => write!(f, "WORK"),
6681            BeginTransactionKind::Tran => write!(f, "TRAN"),
6682        }
6683    }
6684}
6685
6686/// Can use to describe options in  create sequence or table column type identity
6687/// [ MINVALUE minvalue | NO MINVALUE ] [ MAXVALUE maxvalue | NO MAXVALUE ]
6688#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6689#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6690#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6691pub enum MinMaxValue {
6692    /// Clause is not specified.
6693    Empty,
6694    /// NO MINVALUE / NO MAXVALUE.
6695    None,
6696    /// `MINVALUE <expr>` / `MAXVALUE <expr>`.
6697    Some(Expr),
6698}
6699
6700#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6701#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6702#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6703#[non_exhaustive]
6704/// Behavior to apply for `INSERT` when a conflict occurs.
6705pub enum OnInsert {
6706    /// ON DUPLICATE KEY UPDATE (MySQL when the key already exists, then execute an update instead)
6707    DuplicateKeyUpdate(Vec<Assignment>),
6708    /// ON CONFLICT is a PostgreSQL and Sqlite extension
6709    OnConflict(OnConflict),
6710}
6711
6712#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6713#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6714#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6715/// Optional aliases for `INSERT` targets: row alias and optional column aliases.
6716pub struct InsertAliases {
6717    /// Row alias (table-style alias) for the inserted values.
6718    pub row_alias: ObjectName,
6719    /// Optional list of column aliases for the inserted values.
6720    pub col_aliases: Option<Vec<Ident>>,
6721}
6722
6723#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6724#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6725#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6726/// Optional alias for an `INSERT` table; i.e. the table to be inserted into
6727pub struct TableAliasWithoutColumns {
6728    /// `true` if the aliases was explicitly introduced with the "AS" keyword
6729    pub explicit: bool,
6730    /// the alias name itself
6731    pub alias: Ident,
6732}
6733
6734#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6735#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6736#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6737/// `ON CONFLICT` clause representation.
6738pub struct OnConflict {
6739    /// Optional conflict target specifying columns or constraint.
6740    pub conflict_target: Option<ConflictTarget>,
6741    /// Action to take when a conflict occurs.
6742    pub action: OnConflictAction,
6743}
6744#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6745#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6746#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6747/// Target specification for an `ON CONFLICT` clause.
6748pub enum ConflictTarget {
6749    /// Target specified as a list of columns.
6750    Columns(Vec<Ident>),
6751    /// Target specified as a named constraint.
6752    OnConstraint(ObjectName),
6753}
6754#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6755#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6756#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6757/// Action to perform when an `ON CONFLICT` target is matched.
6758pub enum OnConflictAction {
6759    /// Do nothing on conflict.
6760    DoNothing,
6761    /// Perform an update on conflict.
6762    DoUpdate(DoUpdate),
6763}
6764
6765#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6766#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6767#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6768/// Details for `DO UPDATE` action of an `ON CONFLICT` clause.
6769pub struct DoUpdate {
6770    /// Column assignments to perform on update.
6771    pub assignments: Vec<Assignment>,
6772    /// Optional WHERE clause limiting the update.
6773    pub selection: Option<Expr>,
6774}
6775
6776impl fmt::Display for OnInsert {
6777    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6778        match self {
6779            Self::DuplicateKeyUpdate(expr) => write!(
6780                f,
6781                " ON DUPLICATE KEY UPDATE {}",
6782                display_comma_separated(expr)
6783            ),
6784            Self::OnConflict(o) => write!(f, "{o}"),
6785        }
6786    }
6787}
6788impl fmt::Display for OnConflict {
6789    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6790        write!(f, " ON CONFLICT")?;
6791        if let Some(target) = &self.conflict_target {
6792            write!(f, "{target}")?;
6793        }
6794        write!(f, " {}", self.action)
6795    }
6796}
6797impl fmt::Display for ConflictTarget {
6798    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6799        match self {
6800            ConflictTarget::Columns(cols) => write!(f, "({})", display_comma_separated(cols)),
6801            ConflictTarget::OnConstraint(name) => write!(f, " ON CONSTRAINT {name}"),
6802        }
6803    }
6804}
6805impl fmt::Display for OnConflictAction {
6806    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6807        match self {
6808            Self::DoNothing => write!(f, "DO NOTHING"),
6809            Self::DoUpdate(do_update) => {
6810                write!(f, "DO UPDATE")?;
6811                if !do_update.assignments.is_empty() {
6812                    write!(
6813                        f,
6814                        " SET {}",
6815                        display_comma_separated(&do_update.assignments)
6816                    )?;
6817                }
6818                if let Some(selection) = &do_update.selection {
6819                    write!(f, " WHERE {selection}")?;
6820                }
6821                Ok(())
6822            }
6823        }
6824    }
6825}
6826
6827/// Privileges granted in a GRANT statement or revoked in a REVOKE statement.
6828#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6829#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6830#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6831pub enum Privileges {
6832    /// All privileges applicable to the object type
6833    All {
6834        /// Optional keyword from the spec, ignored in practice
6835        with_privileges_keyword: bool,
6836    },
6837    /// Specific privileges (e.g. `SELECT`, `INSERT`)
6838    Actions(Vec<Action>),
6839}
6840
6841impl fmt::Display for Privileges {
6842    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6843        match self {
6844            Privileges::All {
6845                with_privileges_keyword,
6846            } => {
6847                write!(
6848                    f,
6849                    "ALL{}",
6850                    if *with_privileges_keyword {
6851                        " PRIVILEGES"
6852                    } else {
6853                        ""
6854                    }
6855                )
6856            }
6857            Privileges::Actions(actions) => {
6858                write!(f, "{}", display_comma_separated(actions))
6859            }
6860        }
6861    }
6862}
6863
6864/// Specific direction for FETCH statement
6865#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6866#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6867#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6868pub enum FetchDirection {
6869    /// Fetch a specific count of rows.
6870    Count {
6871        /// The limit value for the count.
6872        limit: ValueWithSpan,
6873    },
6874    /// Fetch the next row.
6875    Next,
6876    /// Fetch the prior row.
6877    Prior,
6878    /// Fetch the first row.
6879    First,
6880    /// Fetch the last row.
6881    Last,
6882    /// Fetch an absolute row by index.
6883    Absolute {
6884        /// The absolute index value.
6885        limit: ValueWithSpan,
6886    },
6887    /// Fetch a row relative to the current position.
6888    Relative {
6889        /// The relative offset value.
6890        limit: ValueWithSpan,
6891    },
6892    /// Fetch all rows.
6893    All,
6894    // FORWARD
6895    // FORWARD count
6896    /// Fetch forward by an optional limit.
6897    Forward {
6898        /// Optional forward limit.
6899        limit: Option<ValueWithSpan>,
6900    },
6901    /// Fetch all forward rows.
6902    ForwardAll,
6903    // BACKWARD
6904    // BACKWARD count
6905    /// Fetch backward by an optional limit.
6906    Backward {
6907        /// Optional backward limit.
6908        limit: Option<ValueWithSpan>,
6909    },
6910    /// Fetch all backward rows.
6911    BackwardAll,
6912}
6913
6914impl fmt::Display for FetchDirection {
6915    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6916        match self {
6917            FetchDirection::Count { limit } => f.write_str(&limit.to_string())?,
6918            FetchDirection::Next => f.write_str("NEXT")?,
6919            FetchDirection::Prior => f.write_str("PRIOR")?,
6920            FetchDirection::First => f.write_str("FIRST")?,
6921            FetchDirection::Last => f.write_str("LAST")?,
6922            FetchDirection::Absolute { limit } => {
6923                f.write_str("ABSOLUTE ")?;
6924                f.write_str(&limit.to_string())?;
6925            }
6926            FetchDirection::Relative { limit } => {
6927                f.write_str("RELATIVE ")?;
6928                f.write_str(&limit.to_string())?;
6929            }
6930            FetchDirection::All => f.write_str("ALL")?,
6931            FetchDirection::Forward { limit } => {
6932                f.write_str("FORWARD")?;
6933
6934                if let Some(l) = limit {
6935                    f.write_str(" ")?;
6936                    f.write_str(&l.to_string())?;
6937                }
6938            }
6939            FetchDirection::ForwardAll => f.write_str("FORWARD ALL")?,
6940            FetchDirection::Backward { limit } => {
6941                f.write_str("BACKWARD")?;
6942
6943                if let Some(l) = limit {
6944                    f.write_str(" ")?;
6945                    f.write_str(&l.to_string())?;
6946                }
6947            }
6948            FetchDirection::BackwardAll => f.write_str("BACKWARD ALL")?,
6949        };
6950
6951        Ok(())
6952    }
6953}
6954
6955/// The "position" for a FETCH statement.
6956///
6957/// [MsSql](https://learn.microsoft.com/en-us/sql/t-sql/language-elements/fetch-transact-sql)
6958#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6959#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6960#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6961pub enum FetchPosition {
6962    /// Use `FROM <pos>` position specifier.
6963    From,
6964    /// Use `IN <pos>` position specifier.
6965    In,
6966}
6967
6968impl fmt::Display for FetchPosition {
6969    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6970        match self {
6971            FetchPosition::From => f.write_str("FROM")?,
6972            FetchPosition::In => f.write_str("IN")?,
6973        };
6974
6975        Ok(())
6976    }
6977}
6978
6979/// A privilege on a database object (table, sequence, etc.).
6980#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6981#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6982#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6983pub enum Action {
6984    /// Add a search optimization.
6985    AddSearchOptimization,
6986    /// Apply an `APPLY` operation with a specific type.
6987    Apply {
6988        /// The type of apply operation.
6989        apply_type: ActionApplyType,
6990    },
6991    /// Apply a budget operation.
6992    ApplyBudget,
6993    /// Attach a listing.
6994    AttachListing,
6995    /// Attach a policy.
6996    AttachPolicy,
6997    /// Audit operation.
6998    Audit,
6999    /// Bind a service endpoint.
7000    BindServiceEndpoint,
7001    /// Connect permission.
7002    Connect,
7003    /// Create action, optionally specifying an object type.
7004    Create {
7005        /// Optional object type to create.
7006        obj_type: Option<ActionCreateObjectType>,
7007    },
7008    /// Actions related to database roles.
7009    DatabaseRole {
7010        /// The role name.
7011        role: ObjectName,
7012    },
7013    /// Delete permission.
7014    Delete,
7015    /// Drop permission.
7016    Drop,
7017    /// Evolve schema permission.
7018    EvolveSchema,
7019    /// Exec action (execute) with optional object type.
7020    Exec {
7021        /// Optional execute object type.
7022        obj_type: Option<ActionExecuteObjectType>,
7023    },
7024    /// Execute action with optional object type.
7025    Execute {
7026        /// Optional execute object type.
7027        obj_type: Option<ActionExecuteObjectType>,
7028    },
7029    /// Failover operation.
7030    Failover,
7031    /// Use imported privileges.
7032    ImportedPrivileges,
7033    /// Import a share.
7034    ImportShare,
7035    /// Insert rows with optional column list.
7036    Insert {
7037        /// Optional list of target columns for insert.
7038        columns: Option<Vec<Ident>>,
7039    },
7040    /// Manage operation with a specific manage type.
7041    Manage {
7042        /// The specific manage sub-type.
7043        manage_type: ActionManageType,
7044    },
7045    /// Manage releases.
7046    ManageReleases,
7047    /// Manage versions.
7048    ManageVersions,
7049    /// Modify operation with an optional modify type.
7050    Modify {
7051        /// The optional modify sub-type.
7052        modify_type: Option<ActionModifyType>,
7053    },
7054    /// Monitor operation with an optional monitor type.
7055    Monitor {
7056        /// The optional monitor sub-type.
7057        monitor_type: Option<ActionMonitorType>,
7058    },
7059    /// Operate permission.
7060    Operate,
7061    /// Override share restrictions.
7062    OverrideShareRestrictions,
7063    /// Ownership permission.
7064    Ownership,
7065    /// Purchase a data exchange listing.
7066    PurchaseDataExchangeListing,
7067
7068    /// Read access.
7069    Read,
7070    /// Read session-level access.
7071    ReadSession,
7072    /// References with optional column list.
7073    References {
7074        /// Optional list of referenced column identifiers.
7075        columns: Option<Vec<Ident>>,
7076    },
7077    /// Replication permission.
7078    Replicate,
7079    /// Resolve all references.
7080    ResolveAll,
7081    /// Role-related permission with target role name.
7082    Role {
7083        /// The target role name.
7084        role: ObjectName,
7085    },
7086    /// Select permission with optional column list.
7087    Select {
7088        /// Optional list of selected columns.
7089        columns: Option<Vec<Ident>>,
7090    },
7091    /// Temporary object permission.
7092    Temporary,
7093    /// Trigger-related permission.
7094    Trigger,
7095    /// Truncate permission.
7096    Truncate,
7097    /// Update permission with optional affected columns.
7098    Update {
7099        /// Optional list of columns affected by update.
7100        columns: Option<Vec<Ident>>,
7101    },
7102    /// Usage permission.
7103    Usage,
7104}
7105
7106impl fmt::Display for Action {
7107    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7108        match self {
7109            Action::AddSearchOptimization => f.write_str("ADD SEARCH OPTIMIZATION")?,
7110            Action::Apply { apply_type } => write!(f, "APPLY {apply_type}")?,
7111            Action::ApplyBudget => f.write_str("APPLYBUDGET")?,
7112            Action::AttachListing => f.write_str("ATTACH LISTING")?,
7113            Action::AttachPolicy => f.write_str("ATTACH POLICY")?,
7114            Action::Audit => f.write_str("AUDIT")?,
7115            Action::BindServiceEndpoint => f.write_str("BIND SERVICE ENDPOINT")?,
7116            Action::Connect => f.write_str("CONNECT")?,
7117            Action::Create { obj_type } => {
7118                f.write_str("CREATE")?;
7119                if let Some(obj_type) = obj_type {
7120                    write!(f, " {obj_type}")?
7121                }
7122            }
7123            Action::DatabaseRole { role } => write!(f, "DATABASE ROLE {role}")?,
7124            Action::Delete => f.write_str("DELETE")?,
7125            Action::Drop => f.write_str("DROP")?,
7126            Action::EvolveSchema => f.write_str("EVOLVE SCHEMA")?,
7127            Action::Exec { obj_type } => {
7128                f.write_str("EXEC")?;
7129                if let Some(obj_type) = obj_type {
7130                    write!(f, " {obj_type}")?
7131                }
7132            }
7133            Action::Execute { obj_type } => {
7134                f.write_str("EXECUTE")?;
7135                if let Some(obj_type) = obj_type {
7136                    write!(f, " {obj_type}")?
7137                }
7138            }
7139            Action::Failover => f.write_str("FAILOVER")?,
7140            Action::ImportedPrivileges => f.write_str("IMPORTED PRIVILEGES")?,
7141            Action::ImportShare => f.write_str("IMPORT SHARE")?,
7142            Action::Insert { .. } => f.write_str("INSERT")?,
7143            Action::Manage { manage_type } => write!(f, "MANAGE {manage_type}")?,
7144            Action::ManageReleases => f.write_str("MANAGE RELEASES")?,
7145            Action::ManageVersions => f.write_str("MANAGE VERSIONS")?,
7146            Action::Modify { modify_type } => {
7147                write!(f, "MODIFY")?;
7148                if let Some(modify_type) = modify_type {
7149                    write!(f, " {modify_type}")?;
7150                }
7151            }
7152            Action::Monitor { monitor_type } => {
7153                write!(f, "MONITOR")?;
7154                if let Some(monitor_type) = monitor_type {
7155                    write!(f, " {monitor_type}")?
7156                }
7157            }
7158            Action::Operate => f.write_str("OPERATE")?,
7159            Action::OverrideShareRestrictions => f.write_str("OVERRIDE SHARE RESTRICTIONS")?,
7160            Action::Ownership => f.write_str("OWNERSHIP")?,
7161            Action::PurchaseDataExchangeListing => f.write_str("PURCHASE DATA EXCHANGE LISTING")?,
7162            Action::Read => f.write_str("READ")?,
7163            Action::ReadSession => f.write_str("READ SESSION")?,
7164            Action::References { .. } => f.write_str("REFERENCES")?,
7165            Action::Replicate => f.write_str("REPLICATE")?,
7166            Action::ResolveAll => f.write_str("RESOLVE ALL")?,
7167            Action::Role { role } => write!(f, "ROLE {role}")?,
7168            Action::Select { .. } => f.write_str("SELECT")?,
7169            Action::Temporary => f.write_str("TEMPORARY")?,
7170            Action::Trigger => f.write_str("TRIGGER")?,
7171            Action::Truncate => f.write_str("TRUNCATE")?,
7172            Action::Update { .. } => f.write_str("UPDATE")?,
7173            Action::Usage => f.write_str("USAGE")?,
7174        };
7175        match self {
7176            Action::Insert { columns }
7177            | Action::References { columns }
7178            | Action::Select { columns }
7179            | Action::Update { columns } => {
7180                if let Some(columns) = columns {
7181                    write!(f, " ({})", display_comma_separated(columns))?;
7182                }
7183            }
7184            _ => (),
7185        };
7186        Ok(())
7187    }
7188}
7189
7190#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7191#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7192#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7193/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
7194/// under `globalPrivileges` in the `CREATE` privilege.
7195pub enum ActionCreateObjectType {
7196    /// An account-level object.
7197    Account,
7198    /// An application object.
7199    Application,
7200    /// An application package object.
7201    ApplicationPackage,
7202    /// A compute pool object.
7203    ComputePool,
7204    /// A data exchange listing.
7205    DataExchangeListing,
7206    /// A database object.
7207    Database,
7208    /// An external volume object.
7209    ExternalVolume,
7210    /// A failover group object.
7211    FailoverGroup,
7212    /// An integration object.
7213    Integration,
7214    /// A network policy object.
7215    NetworkPolicy,
7216    /// An organization listing.
7217    OrganiationListing,
7218    /// A replication group object.
7219    ReplicationGroup,
7220    /// A role object.
7221    Role,
7222    /// A schema object.
7223    Schema,
7224    /// A share object.
7225    Share,
7226    /// A user object.
7227    User,
7228    /// A warehouse object.
7229    Warehouse,
7230}
7231
7232impl fmt::Display for ActionCreateObjectType {
7233    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7234        match self {
7235            ActionCreateObjectType::Account => write!(f, "ACCOUNT"),
7236            ActionCreateObjectType::Application => write!(f, "APPLICATION"),
7237            ActionCreateObjectType::ApplicationPackage => write!(f, "APPLICATION PACKAGE"),
7238            ActionCreateObjectType::ComputePool => write!(f, "COMPUTE POOL"),
7239            ActionCreateObjectType::DataExchangeListing => write!(f, "DATA EXCHANGE LISTING"),
7240            ActionCreateObjectType::Database => write!(f, "DATABASE"),
7241            ActionCreateObjectType::ExternalVolume => write!(f, "EXTERNAL VOLUME"),
7242            ActionCreateObjectType::FailoverGroup => write!(f, "FAILOVER GROUP"),
7243            ActionCreateObjectType::Integration => write!(f, "INTEGRATION"),
7244            ActionCreateObjectType::NetworkPolicy => write!(f, "NETWORK POLICY"),
7245            ActionCreateObjectType::OrganiationListing => write!(f, "ORGANIZATION LISTING"),
7246            ActionCreateObjectType::ReplicationGroup => write!(f, "REPLICATION GROUP"),
7247            ActionCreateObjectType::Role => write!(f, "ROLE"),
7248            ActionCreateObjectType::Schema => write!(f, "SCHEMA"),
7249            ActionCreateObjectType::Share => write!(f, "SHARE"),
7250            ActionCreateObjectType::User => write!(f, "USER"),
7251            ActionCreateObjectType::Warehouse => write!(f, "WAREHOUSE"),
7252        }
7253    }
7254}
7255
7256#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7257#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7258#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7259/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
7260/// under `globalPrivileges` in the `APPLY` privilege.
7261pub enum ActionApplyType {
7262    /// Apply an aggregation policy.
7263    AggregationPolicy,
7264    /// Apply an authentication policy.
7265    AuthenticationPolicy,
7266    /// Apply a join policy.
7267    JoinPolicy,
7268    /// Apply a masking policy.
7269    MaskingPolicy,
7270    /// Apply a packages policy.
7271    PackagesPolicy,
7272    /// Apply a password policy.
7273    PasswordPolicy,
7274    /// Apply a projection policy.
7275    ProjectionPolicy,
7276    /// Apply a row access policy.
7277    RowAccessPolicy,
7278    /// Apply a session policy.
7279    SessionPolicy,
7280    /// Apply a tag.
7281    Tag,
7282}
7283
7284impl fmt::Display for ActionApplyType {
7285    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7286        match self {
7287            ActionApplyType::AggregationPolicy => write!(f, "AGGREGATION POLICY"),
7288            ActionApplyType::AuthenticationPolicy => write!(f, "AUTHENTICATION POLICY"),
7289            ActionApplyType::JoinPolicy => write!(f, "JOIN POLICY"),
7290            ActionApplyType::MaskingPolicy => write!(f, "MASKING POLICY"),
7291            ActionApplyType::PackagesPolicy => write!(f, "PACKAGES POLICY"),
7292            ActionApplyType::PasswordPolicy => write!(f, "PASSWORD POLICY"),
7293            ActionApplyType::ProjectionPolicy => write!(f, "PROJECTION POLICY"),
7294            ActionApplyType::RowAccessPolicy => write!(f, "ROW ACCESS POLICY"),
7295            ActionApplyType::SessionPolicy => write!(f, "SESSION POLICY"),
7296            ActionApplyType::Tag => write!(f, "TAG"),
7297        }
7298    }
7299}
7300
7301#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7302#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7303#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7304/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
7305/// under `globalPrivileges` in the `EXECUTE` privilege.
7306pub enum ActionExecuteObjectType {
7307    /// Alert object.
7308    Alert,
7309    /// Data metric function object.
7310    DataMetricFunction,
7311    /// Managed alert object.
7312    ManagedAlert,
7313    /// Managed task object.
7314    ManagedTask,
7315    /// Task object.
7316    Task,
7317}
7318
7319impl fmt::Display for ActionExecuteObjectType {
7320    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7321        match self {
7322            ActionExecuteObjectType::Alert => write!(f, "ALERT"),
7323            ActionExecuteObjectType::DataMetricFunction => write!(f, "DATA METRIC FUNCTION"),
7324            ActionExecuteObjectType::ManagedAlert => write!(f, "MANAGED ALERT"),
7325            ActionExecuteObjectType::ManagedTask => write!(f, "MANAGED TASK"),
7326            ActionExecuteObjectType::Task => write!(f, "TASK"),
7327        }
7328    }
7329}
7330
7331#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7332#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7333#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7334/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
7335/// under `globalPrivileges` in the `MANAGE` privilege.
7336pub enum ActionManageType {
7337    /// Account support cases management.
7338    AccountSupportCases,
7339    /// Event sharing management.
7340    EventSharing,
7341    /// Grants management.
7342    Grants,
7343    /// Listing auto-fulfillment management.
7344    ListingAutoFulfillment,
7345    /// Organization support cases management.
7346    OrganizationSupportCases,
7347    /// User support cases management.
7348    UserSupportCases,
7349    /// Warehouses management.
7350    Warehouses,
7351}
7352
7353impl fmt::Display for ActionManageType {
7354    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7355        match self {
7356            ActionManageType::AccountSupportCases => write!(f, "ACCOUNT SUPPORT CASES"),
7357            ActionManageType::EventSharing => write!(f, "EVENT SHARING"),
7358            ActionManageType::Grants => write!(f, "GRANTS"),
7359            ActionManageType::ListingAutoFulfillment => write!(f, "LISTING AUTO FULFILLMENT"),
7360            ActionManageType::OrganizationSupportCases => write!(f, "ORGANIZATION SUPPORT CASES"),
7361            ActionManageType::UserSupportCases => write!(f, "USER SUPPORT CASES"),
7362            ActionManageType::Warehouses => write!(f, "WAREHOUSES"),
7363        }
7364    }
7365}
7366
7367#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7368#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7369#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7370/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
7371/// under `globalPrivileges` in the `MODIFY` privilege.
7372pub enum ActionModifyType {
7373    /// Modify log level.
7374    LogLevel,
7375    /// Modify trace level.
7376    TraceLevel,
7377    /// Modify session log level.
7378    SessionLogLevel,
7379    /// Modify session trace level.
7380    SessionTraceLevel,
7381}
7382
7383impl fmt::Display for ActionModifyType {
7384    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7385        match self {
7386            ActionModifyType::LogLevel => write!(f, "LOG LEVEL"),
7387            ActionModifyType::TraceLevel => write!(f, "TRACE LEVEL"),
7388            ActionModifyType::SessionLogLevel => write!(f, "SESSION LOG LEVEL"),
7389            ActionModifyType::SessionTraceLevel => write!(f, "SESSION TRACE LEVEL"),
7390        }
7391    }
7392}
7393
7394#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7395#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7396#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7397/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
7398/// under `globalPrivileges` in the `MONITOR` privilege.
7399pub enum ActionMonitorType {
7400    /// Monitor execution.
7401    Execution,
7402    /// Monitor security.
7403    Security,
7404    /// Monitor usage.
7405    Usage,
7406}
7407
7408impl fmt::Display for ActionMonitorType {
7409    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7410        match self {
7411            ActionMonitorType::Execution => write!(f, "EXECUTION"),
7412            ActionMonitorType::Security => write!(f, "SECURITY"),
7413            ActionMonitorType::Usage => write!(f, "USAGE"),
7414        }
7415    }
7416}
7417
7418/// The principal that receives the privileges
7419#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7420#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7421#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7422pub struct Grantee {
7423    /// The category/type of grantee (role, user, share, etc.).
7424    pub grantee_type: GranteesType,
7425    /// Optional name of the grantee (identifier or user@host).
7426    pub name: Option<GranteeName>,
7427}
7428
7429impl fmt::Display for Grantee {
7430    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7431        match self.grantee_type {
7432            GranteesType::Role => {
7433                write!(f, "ROLE ")?;
7434            }
7435            GranteesType::Share => {
7436                write!(f, "SHARE ")?;
7437            }
7438            GranteesType::User => {
7439                write!(f, "USER ")?;
7440            }
7441            GranteesType::Group => {
7442                write!(f, "GROUP ")?;
7443            }
7444            GranteesType::Public => {
7445                write!(f, "PUBLIC ")?;
7446            }
7447            GranteesType::DatabaseRole => {
7448                write!(f, "DATABASE ROLE ")?;
7449            }
7450            GranteesType::Application => {
7451                write!(f, "APPLICATION ")?;
7452            }
7453            GranteesType::ApplicationRole => {
7454                write!(f, "APPLICATION ROLE ")?;
7455            }
7456            GranteesType::None => (),
7457        }
7458        if let Some(ref name) = self.name {
7459            name.fmt(f)?;
7460        }
7461        Ok(())
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/// The kind of principal receiving privileges.
7469pub enum GranteesType {
7470    /// A role principal.
7471    Role,
7472    /// A share principal.
7473    Share,
7474    /// A user principal.
7475    User,
7476    /// A group principal.
7477    Group,
7478    /// The public principal.
7479    Public,
7480    /// A database role principal.
7481    DatabaseRole,
7482    /// An application principal.
7483    Application,
7484    /// An application role principal.
7485    ApplicationRole,
7486    /// No specific principal (e.g. `NONE`).
7487    None,
7488}
7489
7490/// Users/roles designated in a GRANT/REVOKE
7491#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7492#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7493#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7494pub enum GranteeName {
7495    /// A bare identifier
7496    ObjectName(ObjectName),
7497    /// A MySQL user/host pair such as 'root'@'%'
7498    UserHost {
7499        /// The user identifier portion.
7500        user: Ident,
7501        /// The host identifier portion.
7502        host: Ident,
7503    },
7504}
7505
7506impl fmt::Display for GranteeName {
7507    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7508        match self {
7509            GranteeName::ObjectName(name) => name.fmt(f),
7510            GranteeName::UserHost { user, host } => {
7511                write!(f, "{user}@{host}")
7512            }
7513        }
7514    }
7515}
7516
7517/// Objects on which privileges are granted in a GRANT statement.
7518#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7519#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7520#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7521pub enum GrantObjects {
7522    /// Grant privileges on `ALL SEQUENCES IN SCHEMA <schema_name> [, ...]`
7523    AllSequencesInSchema {
7524        /// The target schema names.
7525        schemas: Vec<ObjectName>,
7526    },
7527    /// Grant privileges on `ALL TABLES IN SCHEMA <schema_name> [, ...]`
7528    AllTablesInSchema {
7529        /// The target schema names.
7530        schemas: Vec<ObjectName>,
7531    },
7532    /// Grant privileges on `ALL VIEWS IN SCHEMA <schema_name> [, ...]`
7533    AllViewsInSchema {
7534        /// The target schema names.
7535        schemas: Vec<ObjectName>,
7536    },
7537    /// Grant privileges on `ALL MATERIALIZED VIEWS IN SCHEMA <schema_name> [, ...]`
7538    AllMaterializedViewsInSchema {
7539        /// The target schema names.
7540        schemas: Vec<ObjectName>,
7541    },
7542    /// Grant privileges on `ALL EXTERNAL TABLES IN SCHEMA <schema_name> [, ...]`
7543    AllExternalTablesInSchema {
7544        /// The target schema names.
7545        schemas: Vec<ObjectName>,
7546    },
7547    /// Grant privileges on `ALL FUNCTIONS IN SCHEMA <schema_name> [, ...]`
7548    AllFunctionsInSchema {
7549        /// The target schema names.
7550        schemas: Vec<ObjectName>,
7551    },
7552    /// Grant privileges on `FUTURE SCHEMAS IN DATABASE <database_name> [, ...]`
7553    FutureSchemasInDatabase {
7554        /// The target database names.
7555        databases: Vec<ObjectName>,
7556    },
7557    /// Grant privileges on `FUTURE TABLES IN SCHEMA <schema_name> [, ...]`
7558    FutureTablesInSchema {
7559        /// The target schema names.
7560        schemas: Vec<ObjectName>,
7561    },
7562    /// Grant privileges on `FUTURE VIEWS IN SCHEMA <schema_name> [, ...]`
7563    FutureViewsInSchema {
7564        /// The target schema names.
7565        schemas: Vec<ObjectName>,
7566    },
7567    /// Grant privileges on `FUTURE EXTERNAL TABLES IN SCHEMA <schema_name> [, ...]`
7568    FutureExternalTablesInSchema {
7569        /// The target schema names.
7570        schemas: Vec<ObjectName>,
7571    },
7572    /// Grant privileges on `FUTURE MATERIALIZED VIEWS IN SCHEMA <schema_name> [, ...]`
7573    FutureMaterializedViewsInSchema {
7574        /// The target schema names.
7575        schemas: Vec<ObjectName>,
7576    },
7577    /// Grant privileges on `FUTURE SEQUENCES IN SCHEMA <schema_name> [, ...]`
7578    FutureSequencesInSchema {
7579        /// The target schema names.
7580        schemas: Vec<ObjectName>,
7581    },
7582    /// Grant privileges on specific databases
7583    Databases(Vec<ObjectName>),
7584    /// Grant privileges on specific schemas
7585    Schemas(Vec<ObjectName>),
7586    /// Grant privileges on specific sequences
7587    Sequences(Vec<ObjectName>),
7588    /// Grant privileges on specific tables
7589    Tables(Vec<ObjectName>),
7590    /// Grant privileges on specific views
7591    Views(Vec<ObjectName>),
7592    /// Grant privileges on specific warehouses
7593    Warehouses(Vec<ObjectName>),
7594    /// Grant privileges on specific integrations
7595    Integrations(Vec<ObjectName>),
7596    /// Grant privileges on resource monitors
7597    ResourceMonitors(Vec<ObjectName>),
7598    /// Grant privileges on users
7599    Users(Vec<ObjectName>),
7600    /// Grant privileges on compute pools
7601    ComputePools(Vec<ObjectName>),
7602    /// Grant privileges on connections
7603    Connections(Vec<ObjectName>),
7604    /// Grant privileges on failover groups
7605    FailoverGroup(Vec<ObjectName>),
7606    /// Grant privileges on replication group
7607    ReplicationGroup(Vec<ObjectName>),
7608    /// Grant privileges on external volumes
7609    ExternalVolumes(Vec<ObjectName>),
7610    /// Grant privileges on a procedure. In dialects that
7611    /// support overloading, the argument types must be specified.
7612    ///
7613    /// For example:
7614    /// `GRANT USAGE ON PROCEDURE foo(varchar) TO ROLE role1`
7615    Procedure {
7616        /// The procedure name.
7617        name: ObjectName,
7618        /// Optional argument types for overloaded procedures.
7619        arg_types: Vec<DataType>,
7620    },
7621
7622    /// Grant privileges on a function. In dialects that
7623    /// support overloading, the argument types must be specified.
7624    ///
7625    /// For example:
7626    /// `GRANT USAGE ON FUNCTION foo(varchar) TO ROLE role1`
7627    Function {
7628        /// The function name.
7629        name: ObjectName,
7630        /// Optional argument types for overloaded functions.
7631        arg_types: Vec<DataType>,
7632    },
7633}
7634
7635impl fmt::Display for GrantObjects {
7636    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7637        match self {
7638            GrantObjects::Sequences(sequences) => {
7639                write!(f, "SEQUENCE {}", display_comma_separated(sequences))
7640            }
7641            GrantObjects::Databases(databases) => {
7642                write!(f, "DATABASE {}", display_comma_separated(databases))
7643            }
7644            GrantObjects::Schemas(schemas) => {
7645                write!(f, "SCHEMA {}", display_comma_separated(schemas))
7646            }
7647            GrantObjects::Tables(tables) => {
7648                write!(f, "{}", display_comma_separated(tables))
7649            }
7650            GrantObjects::Views(views) => {
7651                write!(f, "VIEW {}", display_comma_separated(views))
7652            }
7653            GrantObjects::Warehouses(warehouses) => {
7654                write!(f, "WAREHOUSE {}", display_comma_separated(warehouses))
7655            }
7656            GrantObjects::Integrations(integrations) => {
7657                write!(f, "INTEGRATION {}", display_comma_separated(integrations))
7658            }
7659            GrantObjects::AllSequencesInSchema { schemas } => {
7660                write!(
7661                    f,
7662                    "ALL SEQUENCES IN SCHEMA {}",
7663                    display_comma_separated(schemas)
7664                )
7665            }
7666            GrantObjects::AllTablesInSchema { schemas } => {
7667                write!(
7668                    f,
7669                    "ALL TABLES IN SCHEMA {}",
7670                    display_comma_separated(schemas)
7671                )
7672            }
7673            GrantObjects::AllExternalTablesInSchema { schemas } => {
7674                write!(
7675                    f,
7676                    "ALL EXTERNAL TABLES IN SCHEMA {}",
7677                    display_comma_separated(schemas)
7678                )
7679            }
7680            GrantObjects::AllViewsInSchema { schemas } => {
7681                write!(
7682                    f,
7683                    "ALL VIEWS IN SCHEMA {}",
7684                    display_comma_separated(schemas)
7685                )
7686            }
7687            GrantObjects::AllMaterializedViewsInSchema { schemas } => {
7688                write!(
7689                    f,
7690                    "ALL MATERIALIZED VIEWS IN SCHEMA {}",
7691                    display_comma_separated(schemas)
7692                )
7693            }
7694            GrantObjects::AllFunctionsInSchema { schemas } => {
7695                write!(
7696                    f,
7697                    "ALL FUNCTIONS IN SCHEMA {}",
7698                    display_comma_separated(schemas)
7699                )
7700            }
7701            GrantObjects::FutureSchemasInDatabase { databases } => {
7702                write!(
7703                    f,
7704                    "FUTURE SCHEMAS IN DATABASE {}",
7705                    display_comma_separated(databases)
7706                )
7707            }
7708            GrantObjects::FutureTablesInSchema { schemas } => {
7709                write!(
7710                    f,
7711                    "FUTURE TABLES IN SCHEMA {}",
7712                    display_comma_separated(schemas)
7713                )
7714            }
7715            GrantObjects::FutureExternalTablesInSchema { schemas } => {
7716                write!(
7717                    f,
7718                    "FUTURE EXTERNAL TABLES IN SCHEMA {}",
7719                    display_comma_separated(schemas)
7720                )
7721            }
7722            GrantObjects::FutureViewsInSchema { schemas } => {
7723                write!(
7724                    f,
7725                    "FUTURE VIEWS IN SCHEMA {}",
7726                    display_comma_separated(schemas)
7727                )
7728            }
7729            GrantObjects::FutureMaterializedViewsInSchema { schemas } => {
7730                write!(
7731                    f,
7732                    "FUTURE MATERIALIZED VIEWS IN SCHEMA {}",
7733                    display_comma_separated(schemas)
7734                )
7735            }
7736            GrantObjects::FutureSequencesInSchema { schemas } => {
7737                write!(
7738                    f,
7739                    "FUTURE SEQUENCES IN SCHEMA {}",
7740                    display_comma_separated(schemas)
7741                )
7742            }
7743            GrantObjects::ResourceMonitors(objects) => {
7744                write!(f, "RESOURCE MONITOR {}", display_comma_separated(objects))
7745            }
7746            GrantObjects::Users(objects) => {
7747                write!(f, "USER {}", display_comma_separated(objects))
7748            }
7749            GrantObjects::ComputePools(objects) => {
7750                write!(f, "COMPUTE POOL {}", display_comma_separated(objects))
7751            }
7752            GrantObjects::Connections(objects) => {
7753                write!(f, "CONNECTION {}", display_comma_separated(objects))
7754            }
7755            GrantObjects::FailoverGroup(objects) => {
7756                write!(f, "FAILOVER GROUP {}", display_comma_separated(objects))
7757            }
7758            GrantObjects::ReplicationGroup(objects) => {
7759                write!(f, "REPLICATION GROUP {}", display_comma_separated(objects))
7760            }
7761            GrantObjects::ExternalVolumes(objects) => {
7762                write!(f, "EXTERNAL VOLUME {}", display_comma_separated(objects))
7763            }
7764            GrantObjects::Procedure { name, arg_types } => {
7765                write!(f, "PROCEDURE {name}")?;
7766                if !arg_types.is_empty() {
7767                    write!(f, "({})", display_comma_separated(arg_types))?;
7768                }
7769                Ok(())
7770            }
7771            GrantObjects::Function { name, arg_types } => {
7772                write!(f, "FUNCTION {name}")?;
7773                if !arg_types.is_empty() {
7774                    write!(f, "({})", display_comma_separated(arg_types))?;
7775                }
7776                Ok(())
7777            }
7778        }
7779    }
7780}
7781
7782/// A `DENY` statement
7783///
7784/// [MsSql](https://learn.microsoft.com/en-us/sql/t-sql/statements/deny-transact-sql)
7785#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7786#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7787#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7788pub struct DenyStatement {
7789    /// The privileges to deny.
7790    pub privileges: Privileges,
7791    /// The objects the privileges apply to.
7792    pub objects: GrantObjects,
7793    /// The grantees (users/roles) to whom the denial applies.
7794    pub grantees: Vec<Grantee>,
7795    /// Optional identifier of the principal that performed the grant.
7796    pub granted_by: Option<Ident>,
7797    /// Optional cascade option controlling dependent objects.
7798    pub cascade: Option<CascadeOption>,
7799}
7800
7801impl fmt::Display for DenyStatement {
7802    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7803        write!(f, "DENY {}", self.privileges)?;
7804        write!(f, " ON {}", self.objects)?;
7805        if !self.grantees.is_empty() {
7806            write!(f, " TO {}", display_comma_separated(&self.grantees))?;
7807        }
7808        if let Some(cascade) = &self.cascade {
7809            write!(f, " {cascade}")?;
7810        }
7811        if let Some(granted_by) = &self.granted_by {
7812            write!(f, " AS {granted_by}")?;
7813        }
7814        Ok(())
7815    }
7816}
7817
7818/// SQL assignment `foo = expr` as used in SQLUpdate
7819#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7820#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7821#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7822pub struct Assignment {
7823    /// The left-hand side of the assignment.
7824    pub target: AssignmentTarget,
7825    /// The expression assigned to the target.
7826    pub value: Expr,
7827}
7828
7829impl fmt::Display for Assignment {
7830    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7831        write!(f, "{} = {}", self.target, self.value)
7832    }
7833}
7834
7835/// Left-hand side of an assignment in an UPDATE statement,
7836/// e.g. `foo` in `foo = 5` (ColumnName assignment) or
7837/// `(a, b)` in `(a, b) = (1, 2)` (Tuple assignment).
7838#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7839#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7840#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7841pub enum AssignmentTarget {
7842    /// A single column
7843    ColumnName(ObjectName),
7844    /// A tuple of columns
7845    Tuple(Vec<ObjectName>),
7846}
7847
7848impl fmt::Display for AssignmentTarget {
7849    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7850        match self {
7851            AssignmentTarget::ColumnName(column) => write!(f, "{column}"),
7852            AssignmentTarget::Tuple(columns) => write!(f, "({})", display_comma_separated(columns)),
7853        }
7854    }
7855}
7856
7857#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7858#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7859#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7860/// Expression forms allowed as a function argument.
7861pub enum FunctionArgExpr {
7862    /// A normal expression argument.
7863    Expr(Expr),
7864    /// Qualified wildcard, e.g. `alias.*` or `schema.table.*`.
7865    QualifiedWildcard(ObjectName),
7866    /// An unqualified `*` wildcard.
7867    Wildcard,
7868    /// An unqualified `*` wildcard with additional options, e.g. `* EXCLUDE(col)`.
7869    ///
7870    /// Used in Snowflake to support expressions like `HASH(* EXCLUDE(col))`.
7871    WildcardWithOptions(WildcardAdditionalOptions),
7872}
7873
7874impl From<Expr> for FunctionArgExpr {
7875    fn from(wildcard_expr: Expr) -> Self {
7876        match wildcard_expr {
7877            Expr::QualifiedWildcard(prefix, _) => Self::QualifiedWildcard(prefix),
7878            Expr::Wildcard(_) => Self::Wildcard,
7879            expr => Self::Expr(expr),
7880        }
7881    }
7882}
7883
7884impl fmt::Display for FunctionArgExpr {
7885    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7886        match self {
7887            FunctionArgExpr::Expr(expr) => write!(f, "{expr}"),
7888            FunctionArgExpr::QualifiedWildcard(prefix) => write!(f, "{prefix}.*"),
7889            FunctionArgExpr::Wildcard => f.write_str("*"),
7890            FunctionArgExpr::WildcardWithOptions(opts) => write!(f, "*{opts}"),
7891        }
7892    }
7893}
7894
7895#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7896#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7897#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7898/// Operator used to separate function arguments
7899pub enum FunctionArgOperator {
7900    /// function(arg1 = value1)
7901    Equals,
7902    /// function(arg1 => value1)
7903    RightArrow,
7904    /// function(arg1 := value1)
7905    Assignment,
7906    /// function(arg1 : value1)
7907    Colon,
7908    /// function(arg1 VALUE value1)
7909    Value,
7910}
7911
7912impl fmt::Display for FunctionArgOperator {
7913    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7914        match self {
7915            FunctionArgOperator::Equals => f.write_str("="),
7916            FunctionArgOperator::RightArrow => f.write_str("=>"),
7917            FunctionArgOperator::Assignment => f.write_str(":="),
7918            FunctionArgOperator::Colon => f.write_str(":"),
7919            FunctionArgOperator::Value => f.write_str("VALUE"),
7920        }
7921    }
7922}
7923
7924#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7925#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7926#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7927/// Forms of function arguments (named, expression-named, or positional).
7928pub enum FunctionArg {
7929    /// `name` is identifier
7930    ///
7931    /// Enabled when `Dialect::supports_named_fn_args_with_expr_name` returns 'false'
7932    Named {
7933        /// The identifier name of the argument.
7934        name: Ident,
7935        /// The argument expression or wildcard form.
7936        arg: FunctionArgExpr,
7937        /// The operator separating name and value.
7938        operator: FunctionArgOperator,
7939    },
7940    /// `name` is arbitrary expression
7941    ///
7942    /// Enabled when `Dialect::supports_named_fn_args_with_expr_name` returns 'true'
7943    ExprNamed {
7944        /// The expression used as the argument name.
7945        name: Expr,
7946        /// The argument expression or wildcard form.
7947        arg: FunctionArgExpr,
7948        /// The operator separating name and value.
7949        operator: FunctionArgOperator,
7950    },
7951    /// An unnamed argument (positional), given by expression or wildcard.
7952    Unnamed(FunctionArgExpr),
7953}
7954
7955impl fmt::Display for FunctionArg {
7956    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7957        match self {
7958            FunctionArg::Named {
7959                name,
7960                arg,
7961                operator,
7962            } => write!(f, "{name} {operator} {arg}"),
7963            FunctionArg::ExprNamed {
7964                name,
7965                arg,
7966                operator,
7967            } => write!(f, "{name} {operator} {arg}"),
7968            FunctionArg::Unnamed(unnamed_arg) => write!(f, "{unnamed_arg}"),
7969        }
7970    }
7971}
7972
7973#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7974#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7975#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7976/// Which cursor(s) to close.
7977pub enum CloseCursor {
7978    /// Close all cursors.
7979    All,
7980    /// Close a specific cursor by name.
7981    Specific {
7982        /// The name of the cursor to close.
7983        name: Ident,
7984    },
7985}
7986
7987impl fmt::Display for CloseCursor {
7988    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7989        match self {
7990            CloseCursor::All => write!(f, "ALL"),
7991            CloseCursor::Specific { name } => write!(f, "{name}"),
7992        }
7993    }
7994}
7995
7996/// A Drop Domain statement
7997#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7998#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7999#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8000pub struct DropDomain {
8001    /// Whether to drop the domain if it exists
8002    pub if_exists: bool,
8003    /// The name of the domain to drop
8004    pub name: ObjectName,
8005    /// The behavior to apply when dropping the domain
8006    pub drop_behavior: Option<DropBehavior>,
8007}
8008
8009/// A constant of form `<data_type> 'value'`.
8010/// This can represent ANSI SQL `DATE`, `TIME`, and `TIMESTAMP` literals (such as `DATE '2020-01-01'`),
8011/// as well as constants of other types (a non-standard PostgreSQL extension).
8012#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8013#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8014#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8015pub struct TypedString {
8016    /// The data type of the typed string (e.g. DATE, TIME, TIMESTAMP).
8017    pub data_type: DataType,
8018    /// The value of the constant.
8019    /// Hint: you can unwrap the string value using `value.into_string()`.
8020    pub value: ValueWithSpan,
8021    /// Flags whether this TypedString uses the [ODBC syntax].
8022    ///
8023    /// Example:
8024    /// ```sql
8025    /// -- An ODBC date literal:
8026    /// SELECT {d '2025-07-16'}
8027    /// -- This is equivalent to the standard ANSI SQL literal:
8028    /// SELECT DATE '2025-07-16'
8029    ///
8030    /// [ODBC syntax]: https://learn.microsoft.com/en-us/sql/odbc/reference/develop-app/date-time-and-timestamp-literals?view=sql-server-2017
8031    pub uses_odbc_syntax: bool,
8032}
8033
8034impl fmt::Display for TypedString {
8035    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8036        let data_type = &self.data_type;
8037        let value = &self.value;
8038        match self.uses_odbc_syntax {
8039            false => {
8040                write!(f, "{data_type}")?;
8041                write!(f, " {value}")
8042            }
8043            true => {
8044                let prefix = match data_type {
8045                    DataType::Date => "d",
8046                    DataType::Time(..) => "t",
8047                    DataType::Timestamp(..) => "ts",
8048                    _ => "?",
8049                };
8050                write!(f, "{{{prefix} {value}}}")
8051            }
8052        }
8053    }
8054}
8055
8056/// A function call
8057#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8058#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8059#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8060pub struct Function {
8061    /// The function name (may be qualified).
8062    pub name: ObjectName,
8063    /// Flags whether this function call uses the [ODBC syntax].
8064    ///
8065    /// Example:
8066    /// ```sql
8067    /// SELECT {fn CONCAT('foo', 'bar')}
8068    /// ```
8069    ///
8070    /// [ODBC syntax]: https://learn.microsoft.com/en-us/sql/odbc/reference/develop-app/scalar-function-calls?view=sql-server-2017
8071    pub uses_odbc_syntax: bool,
8072    /// The parameters to the function, including any options specified within the
8073    /// delimiting parentheses.
8074    ///
8075    /// Example:
8076    /// ```plaintext
8077    /// HISTOGRAM(0.5, 0.6)(x, y)
8078    /// ```
8079    ///
8080    /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/aggregate-functions/parametric-functions)
8081    pub parameters: FunctionArguments,
8082    /// The arguments to the function, including any options specified within the
8083    /// delimiting parentheses.
8084    pub args: FunctionArguments,
8085    /// e.g. `x > 5` in `COUNT(x) FILTER (WHERE x > 5)`
8086    pub filter: Option<Box<Expr>>,
8087    /// Indicates how `NULL`s should be handled in the calculation.
8088    ///
8089    /// Example:
8090    /// ```plaintext
8091    /// FIRST_VALUE( <expr> ) [ { IGNORE | RESPECT } NULLS ] OVER ...
8092    /// ```
8093    ///
8094    /// [Snowflake](https://docs.snowflake.com/en/sql-reference/functions/first_value)
8095    pub null_treatment: Option<NullTreatment>,
8096    /// The `OVER` clause, indicating a window function call.
8097    pub over: Option<WindowType>,
8098    /// A clause used with certain aggregate functions to control the ordering
8099    /// within grouped sets before the function is applied.
8100    ///
8101    /// Syntax:
8102    /// ```plaintext
8103    /// <aggregate_function>(expression) WITHIN GROUP (ORDER BY key [ASC | DESC], ...)
8104    /// ```
8105    pub within_group: Vec<OrderByExpr>,
8106}
8107
8108impl fmt::Display for Function {
8109    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8110        if self.uses_odbc_syntax {
8111            write!(f, "{{fn ")?;
8112        }
8113
8114        write!(f, "{}{}{}", self.name, self.parameters, self.args)?;
8115
8116        if !self.within_group.is_empty() {
8117            write!(
8118                f,
8119                " WITHIN GROUP (ORDER BY {})",
8120                display_comma_separated(&self.within_group)
8121            )?;
8122        }
8123
8124        if let Some(filter_cond) = &self.filter {
8125            write!(f, " FILTER (WHERE {filter_cond})")?;
8126        }
8127
8128        if let Some(null_treatment) = &self.null_treatment {
8129            write!(f, " {null_treatment}")?;
8130        }
8131
8132        if let Some(o) = &self.over {
8133            f.write_str(" OVER ")?;
8134            o.fmt(f)?;
8135        }
8136
8137        if self.uses_odbc_syntax {
8138            write!(f, "}}")?;
8139        }
8140
8141        Ok(())
8142    }
8143}
8144
8145/// The arguments passed to a function call.
8146#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8147#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8148#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8149pub enum FunctionArguments {
8150    /// Used for special functions like `CURRENT_TIMESTAMP` that are invoked
8151    /// without parentheses.
8152    None,
8153    /// On some dialects, a subquery can be passed without surrounding
8154    /// parentheses if it's the sole argument to the function.
8155    Subquery(Box<Query>),
8156    /// A normal function argument list, including any clauses within it such as
8157    /// `DISTINCT` or `ORDER BY`.
8158    List(FunctionArgumentList),
8159}
8160
8161impl fmt::Display for FunctionArguments {
8162    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8163        match self {
8164            FunctionArguments::None => Ok(()),
8165            FunctionArguments::Subquery(query) => write!(f, "({query})"),
8166            FunctionArguments::List(args) => write!(f, "({args})"),
8167        }
8168    }
8169}
8170
8171/// This represents everything inside the parentheses when calling a function.
8172#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8173#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8174#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8175pub struct FunctionArgumentList {
8176    /// `[ ALL | DISTINCT ]`
8177    pub duplicate_treatment: Option<DuplicateTreatment>,
8178    /// The function arguments.
8179    pub args: Vec<FunctionArg>,
8180    /// Additional clauses specified within the argument list.
8181    pub clauses: Vec<FunctionArgumentClause>,
8182}
8183
8184impl fmt::Display for FunctionArgumentList {
8185    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8186        if let Some(duplicate_treatment) = self.duplicate_treatment {
8187            write!(f, "{duplicate_treatment} ")?;
8188        }
8189        write!(f, "{}", display_comma_separated(&self.args))?;
8190        if !self.clauses.is_empty() {
8191            if !self.args.is_empty() {
8192                write!(f, " ")?;
8193            }
8194            write!(f, "{}", display_separated(&self.clauses, " "))?;
8195        }
8196        Ok(())
8197    }
8198}
8199
8200#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8201#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8202#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8203/// Clauses that can appear inside a function argument list.
8204pub enum FunctionArgumentClause {
8205    /// Indicates how `NULL`s should be handled in the calculation, e.g. in `FIRST_VALUE` on [BigQuery].
8206    ///
8207    /// Syntax:
8208    /// ```plaintext
8209    /// { IGNORE | RESPECT } NULLS ]
8210    /// ```
8211    ///
8212    /// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/navigation_functions#first_value
8213    IgnoreOrRespectNulls(NullTreatment),
8214    /// Specifies the the ordering for some ordered set aggregates, e.g. `ARRAY_AGG` on [BigQuery].
8215    ///
8216    /// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/aggregate_functions#array_agg
8217    OrderBy(Vec<OrderByExpr>),
8218    /// Specifies a limit for the `ARRAY_AGG` and `ARRAY_CONCAT_AGG` functions on BigQuery.
8219    Limit(Expr),
8220    /// Specifies the behavior on overflow of the `LISTAGG` function.
8221    ///
8222    /// See <https://trino.io/docs/current/functions/aggregate.html>.
8223    OnOverflow(ListAggOnOverflow),
8224    /// Specifies a minimum or maximum bound on the input to [`ANY_VALUE`] on BigQuery.
8225    ///
8226    /// Syntax:
8227    /// ```plaintext
8228    /// HAVING { MAX | MIN } expression
8229    /// ```
8230    ///
8231    /// [`ANY_VALUE`]: https://cloud.google.com/bigquery/docs/reference/standard-sql/aggregate_functions#any_value
8232    Having(HavingBound),
8233    /// The `SEPARATOR` clause to the [`GROUP_CONCAT`] function in MySQL.
8234    ///
8235    /// [`GROUP_CONCAT`]: https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html#function_group-concat
8236    Separator(ValueWithSpan),
8237    /// The `ON NULL` clause for some JSON functions.
8238    ///
8239    /// [MSSQL `JSON_ARRAY`](https://learn.microsoft.com/en-us/sql/t-sql/functions/json-array-transact-sql?view=sql-server-ver16)
8240    /// [MSSQL `JSON_OBJECT`](https://learn.microsoft.com/en-us/sql/t-sql/functions/json-object-transact-sql?view=sql-server-ver16>)
8241    /// [PostgreSQL JSON functions](https://www.postgresql.org/docs/current/functions-json.html#FUNCTIONS-JSON-PROCESSING)
8242    JsonNullClause(JsonNullClause),
8243    /// The `RETURNING` clause for some JSON functions in PostgreSQL
8244    ///
8245    /// [`JSON_OBJECT`](https://www.postgresql.org/docs/current/functions-json.html#:~:text=json_object)
8246    JsonReturningClause(JsonReturningClause),
8247}
8248
8249impl fmt::Display for FunctionArgumentClause {
8250    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8251        match self {
8252            FunctionArgumentClause::IgnoreOrRespectNulls(null_treatment) => {
8253                write!(f, "{null_treatment}")
8254            }
8255            FunctionArgumentClause::OrderBy(order_by) => {
8256                write!(f, "ORDER BY {}", display_comma_separated(order_by))
8257            }
8258            FunctionArgumentClause::Limit(limit) => write!(f, "LIMIT {limit}"),
8259            FunctionArgumentClause::OnOverflow(on_overflow) => write!(f, "{on_overflow}"),
8260            FunctionArgumentClause::Having(bound) => write!(f, "{bound}"),
8261            FunctionArgumentClause::Separator(sep) => write!(f, "SEPARATOR {sep}"),
8262            FunctionArgumentClause::JsonNullClause(null_clause) => write!(f, "{null_clause}"),
8263            FunctionArgumentClause::JsonReturningClause(returning_clause) => {
8264                write!(f, "{returning_clause}")
8265            }
8266        }
8267    }
8268}
8269
8270/// A method call
8271#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8272#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8273#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8274pub struct Method {
8275    /// The expression on which the method is invoked.
8276    pub expr: Box<Expr>,
8277    // always non-empty
8278    /// The sequence of chained method calls.
8279    pub method_chain: Vec<Function>,
8280}
8281
8282impl fmt::Display for Method {
8283    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8284        write!(
8285            f,
8286            "{}.{}",
8287            self.expr,
8288            display_separated(&self.method_chain, ".")
8289        )
8290    }
8291}
8292
8293#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8294#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8295#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8296/// How duplicate values are treated inside function argument lists.
8297pub enum DuplicateTreatment {
8298    /// Consider only unique values.
8299    Distinct,
8300    /// Retain all duplicate values (the default).
8301    All,
8302}
8303
8304impl fmt::Display for DuplicateTreatment {
8305    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8306        match self {
8307            DuplicateTreatment::Distinct => write!(f, "DISTINCT"),
8308            DuplicateTreatment::All => write!(f, "ALL"),
8309        }
8310    }
8311}
8312
8313#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8314#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8315#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8316/// How the `ANALYZE`/`EXPLAIN ANALYZE` format is specified.
8317pub enum AnalyzeFormatKind {
8318    /// Format provided as a keyword, e.g. `FORMAT JSON`.
8319    Keyword(AnalyzeFormat),
8320    /// Format provided as an assignment, e.g. `FORMAT=JSON`.
8321    Assignment(AnalyzeFormat),
8322}
8323
8324impl fmt::Display for AnalyzeFormatKind {
8325    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
8326        match self {
8327            AnalyzeFormatKind::Keyword(format) => write!(f, "FORMAT {format}"),
8328            AnalyzeFormatKind::Assignment(format) => write!(f, "FORMAT={format}"),
8329        }
8330    }
8331}
8332
8333#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8334#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8335#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8336/// Output formats supported for `ANALYZE`/`EXPLAIN ANALYZE`.
8337pub enum AnalyzeFormat {
8338    /// Plain text format.
8339    TEXT,
8340    /// Graphviz DOT format.
8341    GRAPHVIZ,
8342    /// JSON format.
8343    JSON,
8344    /// Traditional explain output.
8345    TRADITIONAL,
8346    /// Tree-style explain output.
8347    TREE,
8348}
8349
8350impl fmt::Display for AnalyzeFormat {
8351    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
8352        f.write_str(match self {
8353            AnalyzeFormat::TEXT => "TEXT",
8354            AnalyzeFormat::GRAPHVIZ => "GRAPHVIZ",
8355            AnalyzeFormat::JSON => "JSON",
8356            AnalyzeFormat::TRADITIONAL => "TRADITIONAL",
8357            AnalyzeFormat::TREE => "TREE",
8358        })
8359    }
8360}
8361
8362/// External table's available file format
8363#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8364#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8365#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8366pub enum FileFormat {
8367    /// Text file format.
8368    TEXTFILE,
8369    /// Sequence file format.
8370    SEQUENCEFILE,
8371    /// ORC file format.
8372    ORC,
8373    /// Parquet file format.
8374    PARQUET,
8375    /// Avro file format.
8376    AVRO,
8377    /// RCFile format.
8378    RCFILE,
8379    /// JSON file format.
8380    JSONFILE,
8381}
8382
8383impl fmt::Display for FileFormat {
8384    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8385        use self::FileFormat::*;
8386        f.write_str(match self {
8387            TEXTFILE => "TEXTFILE",
8388            SEQUENCEFILE => "SEQUENCEFILE",
8389            ORC => "ORC",
8390            PARQUET => "PARQUET",
8391            AVRO => "AVRO",
8392            RCFILE => "RCFILE",
8393            JSONFILE => "JSONFILE",
8394        })
8395    }
8396}
8397
8398/// The `ON OVERFLOW` clause of a LISTAGG invocation
8399#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8400#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8401#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8402pub enum ListAggOnOverflow {
8403    /// `ON OVERFLOW ERROR`
8404    Error,
8405
8406    /// `ON OVERFLOW TRUNCATE [ <filler> ] WITH[OUT] COUNT`
8407    Truncate {
8408        /// Optional filler expression used when truncating.
8409        filler: Option<Box<Expr>>,
8410        /// Whether to include a count when truncating.
8411        with_count: bool,
8412    },
8413}
8414
8415impl fmt::Display for ListAggOnOverflow {
8416    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8417        write!(f, "ON OVERFLOW")?;
8418        match self {
8419            ListAggOnOverflow::Error => write!(f, " ERROR"),
8420            ListAggOnOverflow::Truncate { filler, with_count } => {
8421                write!(f, " TRUNCATE")?;
8422                if let Some(filler) = filler {
8423                    write!(f, " {filler}")?;
8424                }
8425                if *with_count {
8426                    write!(f, " WITH")?;
8427                } else {
8428                    write!(f, " WITHOUT")?;
8429                }
8430                write!(f, " COUNT")
8431            }
8432        }
8433    }
8434}
8435
8436/// The `HAVING` clause in a call to `ANY_VALUE` on BigQuery.
8437#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8438#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8439#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8440pub struct HavingBound(pub HavingBoundKind, pub Expr);
8441
8442impl fmt::Display for HavingBound {
8443    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8444        write!(f, "HAVING {} {}", self.0, self.1)
8445    }
8446}
8447
8448#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8449#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8450#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8451/// Which bound is used in a HAVING clause for ANY_VALUE on BigQuery.
8452pub enum HavingBoundKind {
8453    /// The minimum bound.
8454    Min,
8455    /// The maximum bound.
8456    Max,
8457}
8458
8459impl fmt::Display for HavingBoundKind {
8460    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8461        match self {
8462            HavingBoundKind::Min => write!(f, "MIN"),
8463            HavingBoundKind::Max => write!(f, "MAX"),
8464        }
8465    }
8466}
8467
8468#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8469#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8470#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8471/// Types of database objects referenced by DDL statements.
8472pub enum ObjectType {
8473    /// A collation.
8474    Collation,
8475    /// A table.
8476    Table,
8477    /// A view.
8478    View,
8479    /// A materialized view.
8480    MaterializedView,
8481    /// An index.
8482    Index,
8483    /// A schema.
8484    Schema,
8485    /// A database.
8486    Database,
8487    /// A role.
8488    Role,
8489    /// A sequence.
8490    Sequence,
8491    /// A stage.
8492    Stage,
8493    /// A type definition.
8494    Type,
8495    /// A user.
8496    User,
8497    /// A stream.
8498    Stream,
8499}
8500
8501impl fmt::Display for ObjectType {
8502    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8503        f.write_str(match self {
8504            ObjectType::Collation => "COLLATION",
8505            ObjectType::Table => "TABLE",
8506            ObjectType::View => "VIEW",
8507            ObjectType::MaterializedView => "MATERIALIZED VIEW",
8508            ObjectType::Index => "INDEX",
8509            ObjectType::Schema => "SCHEMA",
8510            ObjectType::Database => "DATABASE",
8511            ObjectType::Role => "ROLE",
8512            ObjectType::Sequence => "SEQUENCE",
8513            ObjectType::Stage => "STAGE",
8514            ObjectType::Type => "TYPE",
8515            ObjectType::User => "USER",
8516            ObjectType::Stream => "STREAM",
8517        })
8518    }
8519}
8520
8521#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8522#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8523#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8524/// Types supported by `KILL` statements.
8525pub enum KillType {
8526    /// Kill a connection.
8527    Connection,
8528    /// Kill a running query.
8529    Query,
8530    /// Kill a mutation (ClickHouse).
8531    Mutation,
8532}
8533
8534impl fmt::Display for KillType {
8535    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8536        f.write_str(match self {
8537            // MySQL
8538            KillType::Connection => "CONNECTION",
8539            KillType::Query => "QUERY",
8540            // Clickhouse supports Mutation
8541            KillType::Mutation => "MUTATION",
8542        })
8543    }
8544}
8545
8546#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8547#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8548#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8549/// Distribution style options for Hive tables.
8550pub enum HiveDistributionStyle {
8551    /// Partitioned distribution with the given columns.
8552    PARTITIONED {
8553        /// Columns used for partitioning.
8554        columns: Vec<ColumnDef>,
8555    },
8556    /// Skewed distribution definition.
8557    SKEWED {
8558        /// Columns participating in the skew definition.
8559        columns: Vec<ColumnDef>,
8560        /// Columns listed in the `ON` clause for skewing.
8561        on: Vec<ColumnDef>,
8562        /// Whether skewed data is stored as directories.
8563        stored_as_directories: bool,
8564    },
8565    /// No distribution style specified.
8566    NONE,
8567}
8568
8569#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8570#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8571#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8572/// Row format specification for Hive tables (SERDE or DELIMITED).
8573pub enum HiveRowFormat {
8574    /// SerDe class specification with the implementing class name.
8575    SERDE {
8576        /// The SerDe implementation class name.
8577        class: String,
8578    },
8579    /// Delimited row format with one or more delimiter specifications.
8580    DELIMITED {
8581        /// The list of delimiters used for delimiting fields/lines.
8582        delimiters: Vec<HiveRowDelimiter>,
8583    },
8584}
8585
8586#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8587#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8588#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8589/// Format specification for `LOAD DATA` Hive operations.
8590pub struct HiveLoadDataFormat {
8591    /// SerDe expression used for the table.
8592    pub serde: Expr,
8593    /// Input format expression.
8594    pub input_format: Expr,
8595}
8596
8597#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8598#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8599#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8600/// A single row delimiter specification for Hive `ROW FORMAT`.
8601pub struct HiveRowDelimiter {
8602    /// The delimiter kind (fields/lines/etc.).
8603    pub delimiter: HiveDelimiter,
8604    /// The delimiter character identifier.
8605    pub char: Ident,
8606}
8607
8608impl fmt::Display for HiveRowDelimiter {
8609    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8610        write!(f, "{} ", self.delimiter)?;
8611        write!(f, "{}", self.char)
8612    }
8613}
8614
8615#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8616#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8617#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8618/// Kind of delimiter used in Hive `ROW FORMAT` definitions.
8619pub enum HiveDelimiter {
8620    /// Fields terminated by a delimiter.
8621    FieldsTerminatedBy,
8622    /// Fields escaped by a character.
8623    FieldsEscapedBy,
8624    /// Collection items terminated by a delimiter.
8625    CollectionItemsTerminatedBy,
8626    /// Map keys terminated by a delimiter.
8627    MapKeysTerminatedBy,
8628    /// Lines terminated by a delimiter.
8629    LinesTerminatedBy,
8630    /// Null represented by a specific token.
8631    NullDefinedAs,
8632}
8633
8634impl fmt::Display for HiveDelimiter {
8635    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8636        use HiveDelimiter::*;
8637        f.write_str(match self {
8638            FieldsTerminatedBy => "FIELDS TERMINATED BY",
8639            FieldsEscapedBy => "ESCAPED BY",
8640            CollectionItemsTerminatedBy => "COLLECTION ITEMS TERMINATED BY",
8641            MapKeysTerminatedBy => "MAP KEYS TERMINATED BY",
8642            LinesTerminatedBy => "LINES TERMINATED BY",
8643            NullDefinedAs => "NULL DEFINED AS",
8644        })
8645    }
8646}
8647
8648#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8649#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8650#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8651/// Describe output format options for Hive `DESCRIBE`/`EXPLAIN`.
8652pub enum HiveDescribeFormat {
8653    /// Extended describe output.
8654    Extended,
8655    /// Formatted describe output.
8656    Formatted,
8657}
8658
8659impl fmt::Display for HiveDescribeFormat {
8660    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8661        use HiveDescribeFormat::*;
8662        f.write_str(match self {
8663            Extended => "EXTENDED",
8664            Formatted => "FORMATTED",
8665        })
8666    }
8667}
8668
8669#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8670#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8671#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8672/// Aliases accepted for describe-style commands.
8673pub enum DescribeAlias {
8674    /// `DESCRIBE` alias.
8675    Describe,
8676    /// `EXPLAIN` alias.
8677    Explain,
8678    /// `DESC` alias.
8679    Desc,
8680}
8681
8682impl fmt::Display for DescribeAlias {
8683    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8684        use DescribeAlias::*;
8685        f.write_str(match self {
8686            Describe => "DESCRIBE",
8687            Explain => "EXPLAIN",
8688            Desc => "DESC",
8689        })
8690    }
8691}
8692
8693#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8694#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8695#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8696#[allow(clippy::large_enum_variant)]
8697/// Hive input/output format specification used in `CREATE TABLE`.
8698pub enum HiveIOFormat {
8699    /// Generic IO format with separate input and output expressions.
8700    IOF {
8701        /// Expression for the input format.
8702        input_format: Expr,
8703        /// Expression for the output format.
8704        output_format: Expr,
8705    },
8706    /// File format wrapper referencing a `FileFormat` variant.
8707    FileFormat {
8708        /// The file format used for storage.
8709        format: FileFormat,
8710    },
8711}
8712
8713#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Default)]
8714#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8715#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8716/// Hive table format and storage-related options.
8717pub struct HiveFormat {
8718    /// Optional row format specification.
8719    pub row_format: Option<HiveRowFormat>,
8720    /// Optional SerDe properties expressed as SQL options.
8721    pub serde_properties: Option<Vec<SqlOption>>,
8722    /// Optional input/output storage format details.
8723    pub storage: Option<HiveIOFormat>,
8724    /// Optional location (URI or path) for table data.
8725    pub location: Option<String>,
8726}
8727
8728#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8729#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8730#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8731/// A clustered index column specification.
8732pub struct ClusteredIndex {
8733    /// Column identifier for the clustered index entry.
8734    pub name: Ident,
8735    /// Optional sort direction: `Some(true)` for ASC, `Some(false)` for DESC, `None` for unspecified.
8736    pub asc: Option<bool>,
8737}
8738
8739impl fmt::Display for ClusteredIndex {
8740    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8741        write!(f, "{}", self.name)?;
8742        match self.asc {
8743            Some(true) => write!(f, " ASC"),
8744            Some(false) => write!(f, " DESC"),
8745            _ => Ok(()),
8746        }
8747    }
8748}
8749
8750#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8751#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8752#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8753/// Clustered options used for `CREATE TABLE` clustered/indexed storage.
8754pub enum TableOptionsClustered {
8755    /// Use a columnstore index.
8756    ColumnstoreIndex,
8757    /// Columnstore index with an explicit ordering of columns.
8758    ColumnstoreIndexOrder(Vec<Ident>),
8759    /// A named clustered index with one or more columns.
8760    Index(Vec<ClusteredIndex>),
8761}
8762
8763impl fmt::Display for TableOptionsClustered {
8764    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8765        match self {
8766            TableOptionsClustered::ColumnstoreIndex => {
8767                write!(f, "CLUSTERED COLUMNSTORE INDEX")
8768            }
8769            TableOptionsClustered::ColumnstoreIndexOrder(values) => {
8770                write!(
8771                    f,
8772                    "CLUSTERED COLUMNSTORE INDEX ORDER ({})",
8773                    display_comma_separated(values)
8774                )
8775            }
8776            TableOptionsClustered::Index(values) => {
8777                write!(f, "CLUSTERED INDEX ({})", display_comma_separated(values))
8778            }
8779        }
8780    }
8781}
8782
8783/// Specifies which partition the boundary values on table partitioning belongs to.
8784#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash)]
8785#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8786#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8787pub enum PartitionRangeDirection {
8788    /// LEFT range direction.
8789    Left,
8790    /// RIGHT range direction.
8791    Right,
8792}
8793
8794#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8795#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8796#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8797/// SQL option syntax used in table and server definitions.
8798pub enum SqlOption {
8799    /// Clustered represents the clustered version of table storage for MSSQL.
8800    ///
8801    /// <https://learn.microsoft.com/en-us/sql/t-sql/statements/create-table-azure-sql-data-warehouse?view=aps-pdw-2016-au7#TableOptions>
8802    Clustered(TableOptionsClustered),
8803    /// Single identifier options, e.g. `HEAP` for MSSQL.
8804    ///
8805    /// <https://learn.microsoft.com/en-us/sql/t-sql/statements/create-table-azure-sql-data-warehouse?view=aps-pdw-2016-au7#TableOptions>
8806    Ident(Ident),
8807    /// Any option that consists of a key value pair where the value is an expression. e.g.
8808    ///
8809    ///   WITH(DISTRIBUTION = ROUND_ROBIN)
8810    KeyValue {
8811        /// The option key identifier.
8812        key: Ident,
8813        /// The expression value for the option.
8814        value: Expr,
8815    },
8816    /// One or more table partitions and represents which partition the boundary values belong to,
8817    /// e.g.
8818    ///
8819    ///   PARTITION (id RANGE LEFT FOR VALUES (10, 20, 30, 40))
8820    ///
8821    /// <https://learn.microsoft.com/en-us/sql/t-sql/statements/create-table-azure-sql-data-warehouse?view=aps-pdw-2016-au7#TablePartitionOptions>
8822    Partition {
8823        /// The partition column name.
8824        column_name: Ident,
8825        /// Optional direction for the partition range (LEFT/RIGHT).
8826        range_direction: Option<PartitionRangeDirection>,
8827        /// Values that define the partition boundaries.
8828        for_values: Vec<Expr>,
8829    },
8830    /// Comment parameter (supports `=` and no `=` syntax)
8831    Comment(CommentDef),
8832    /// MySQL TableSpace option
8833    /// <https://dev.mysql.com/doc/refman/8.4/en/create-table.html>
8834    TableSpace(TablespaceOption),
8835    /// An option representing a key value pair, where the value is a parenthesized list and with an optional name
8836    /// e.g.
8837    ///
8838    ///   UNION  = (tbl_name\[,tbl_name\]...) <https://dev.mysql.com/doc/refman/8.4/en/create-table.html>
8839    ///   ENGINE = ReplicatedMergeTree('/table_name','{replica}', ver) <https://clickhouse.com/docs/engines/table-engines/mergetree-family/replication>
8840    ///   ENGINE = SummingMergeTree(\[columns\]) <https://clickhouse.com/docs/engines/table-engines/mergetree-family/summingmergetree>
8841    NamedParenthesizedList(NamedParenthesizedList),
8842}
8843
8844impl fmt::Display for SqlOption {
8845    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8846        match self {
8847            SqlOption::Clustered(c) => write!(f, "{c}"),
8848            SqlOption::Ident(ident) => {
8849                write!(f, "{ident}")
8850            }
8851            SqlOption::KeyValue { key: name, value } => {
8852                write!(f, "{name} = {value}")
8853            }
8854            SqlOption::Partition {
8855                column_name,
8856                range_direction,
8857                for_values,
8858            } => {
8859                let direction = match range_direction {
8860                    Some(PartitionRangeDirection::Left) => " LEFT",
8861                    Some(PartitionRangeDirection::Right) => " RIGHT",
8862                    None => "",
8863                };
8864
8865                write!(
8866                    f,
8867                    "PARTITION ({} RANGE{} FOR VALUES ({}))",
8868                    column_name,
8869                    direction,
8870                    display_comma_separated(for_values)
8871                )
8872            }
8873            SqlOption::TableSpace(tablespace_option) => {
8874                write!(f, "TABLESPACE {}", tablespace_option.name)?;
8875                match tablespace_option.storage {
8876                    Some(StorageType::Disk) => write!(f, " STORAGE DISK"),
8877                    Some(StorageType::Memory) => write!(f, " STORAGE MEMORY"),
8878                    None => Ok(()),
8879                }
8880            }
8881            SqlOption::Comment(comment) => match comment {
8882                CommentDef::WithEq(comment) => {
8883                    write!(f, "COMMENT = '{comment}'")
8884                }
8885                CommentDef::WithoutEq(comment) => {
8886                    write!(f, "COMMENT '{comment}'")
8887                }
8888            },
8889            SqlOption::NamedParenthesizedList(value) => {
8890                write!(f, "{} = ", value.key)?;
8891                if let Some(key) = &value.name {
8892                    write!(f, "{key}")?;
8893                }
8894                if !value.values.is_empty() {
8895                    write!(f, "({})", display_comma_separated(&value.values))?
8896                }
8897                Ok(())
8898            }
8899        }
8900    }
8901}
8902
8903#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
8904#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8905#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8906/// Storage type options for a tablespace.
8907pub enum StorageType {
8908    /// Store on disk.
8909    Disk,
8910    /// Store in memory.
8911    Memory,
8912}
8913
8914#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
8915#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8916#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8917/// MySql TableSpace option
8918/// <https://dev.mysql.com/doc/refman/8.4/en/create-table.html>
8919pub struct TablespaceOption {
8920    /// Name of the tablespace.
8921    pub name: String,
8922    /// Optional storage type for the tablespace.
8923    pub storage: Option<StorageType>,
8924}
8925
8926#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8927#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8928#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8929/// A key/value identifier pair used for secret or key-based options.
8930pub struct SecretOption {
8931    /// The option key identifier.
8932    pub key: Ident,
8933    /// The option value identifier.
8934    pub value: Ident,
8935}
8936
8937impl fmt::Display for SecretOption {
8938    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8939        write!(f, "{} {}", self.key, self.value)
8940    }
8941}
8942
8943/// A `CREATE SERVER` statement.
8944///
8945/// [PostgreSQL Documentation](https://www.postgresql.org/docs/current/sql-createserver.html)
8946#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8947#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8948#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8949pub struct CreateServerStatement {
8950    /// The server name.
8951    pub name: ObjectName,
8952    /// Whether `IF NOT EXISTS` was specified.
8953    pub if_not_exists: bool,
8954    /// Optional server type identifier.
8955    pub server_type: Option<Ident>,
8956    /// Optional server version identifier.
8957    pub version: Option<Ident>,
8958    /// Foreign-data wrapper object name.
8959    pub foreign_data_wrapper: ObjectName,
8960    /// Optional list of server options.
8961    pub options: Option<Vec<CreateServerOption>>,
8962}
8963
8964impl fmt::Display for CreateServerStatement {
8965    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8966        let CreateServerStatement {
8967            name,
8968            if_not_exists,
8969            server_type,
8970            version,
8971            foreign_data_wrapper,
8972            options,
8973        } = self;
8974
8975        write!(
8976            f,
8977            "CREATE SERVER {if_not_exists}{name} ",
8978            if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
8979        )?;
8980
8981        if let Some(st) = server_type {
8982            write!(f, "TYPE {st} ")?;
8983        }
8984
8985        if let Some(v) = version {
8986            write!(f, "VERSION {v} ")?;
8987        }
8988
8989        write!(f, "FOREIGN DATA WRAPPER {foreign_data_wrapper}")?;
8990
8991        if let Some(o) = options {
8992            write!(f, " OPTIONS ({o})", o = display_comma_separated(o))?;
8993        }
8994
8995        Ok(())
8996    }
8997}
8998
8999/// A key/value option for `CREATE SERVER`.
9000#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9001#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9002#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9003pub struct CreateServerOption {
9004    /// Option key identifier.
9005    pub key: Ident,
9006    /// Option value identifier.
9007    pub value: Ident,
9008}
9009
9010impl fmt::Display for CreateServerOption {
9011    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9012        write!(f, "{} {}", self.key, self.value)
9013    }
9014}
9015
9016#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9017#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9018#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9019/// Options supported by DuckDB for `ATTACH DATABASE`.
9020pub enum AttachDuckDBDatabaseOption {
9021    /// READ_ONLY option, optional boolean value.
9022    ReadOnly(Option<bool>),
9023    /// TYPE option specifying a database type identifier.
9024    Type(Ident),
9025}
9026
9027impl fmt::Display for AttachDuckDBDatabaseOption {
9028    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9029        match self {
9030            AttachDuckDBDatabaseOption::ReadOnly(Some(true)) => write!(f, "READ_ONLY true"),
9031            AttachDuckDBDatabaseOption::ReadOnly(Some(false)) => write!(f, "READ_ONLY false"),
9032            AttachDuckDBDatabaseOption::ReadOnly(None) => write!(f, "READ_ONLY"),
9033            AttachDuckDBDatabaseOption::Type(t) => write!(f, "TYPE {t}"),
9034        }
9035    }
9036}
9037
9038#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9039#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9040#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9041/// Mode for transactions: access mode or isolation level.
9042pub enum TransactionMode {
9043    /// Access mode for a transaction (e.g. `READ ONLY` / `READ WRITE`).
9044    AccessMode(TransactionAccessMode),
9045    /// Isolation level for a transaction (e.g. `SERIALIZABLE`).
9046    IsolationLevel(TransactionIsolationLevel),
9047}
9048
9049impl fmt::Display for TransactionMode {
9050    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9051        use TransactionMode::*;
9052        match self {
9053            AccessMode(access_mode) => write!(f, "{access_mode}"),
9054            IsolationLevel(iso_level) => write!(f, "ISOLATION LEVEL {iso_level}"),
9055        }
9056    }
9057}
9058
9059#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9060#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9061#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9062/// Transaction access mode (READ ONLY / READ WRITE).
9063pub enum TransactionAccessMode {
9064    /// READ ONLY access mode.
9065    ReadOnly,
9066    /// READ WRITE access mode.
9067    ReadWrite,
9068}
9069
9070impl fmt::Display for TransactionAccessMode {
9071    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9072        use TransactionAccessMode::*;
9073        f.write_str(match self {
9074            ReadOnly => "READ ONLY",
9075            ReadWrite => "READ WRITE",
9076        })
9077    }
9078}
9079
9080#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9081#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9082#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9083/// Transaction isolation levels.
9084pub enum TransactionIsolationLevel {
9085    /// READ UNCOMMITTED isolation level.
9086    ReadUncommitted,
9087    /// READ COMMITTED isolation level.
9088    ReadCommitted,
9089    /// REPEATABLE READ isolation level.
9090    RepeatableRead,
9091    /// SERIALIZABLE isolation level.
9092    Serializable,
9093    /// SNAPSHOT isolation level.
9094    Snapshot,
9095}
9096
9097impl fmt::Display for TransactionIsolationLevel {
9098    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9099        use TransactionIsolationLevel::*;
9100        f.write_str(match self {
9101            ReadUncommitted => "READ UNCOMMITTED",
9102            ReadCommitted => "READ COMMITTED",
9103            RepeatableRead => "REPEATABLE READ",
9104            Serializable => "SERIALIZABLE",
9105            Snapshot => "SNAPSHOT",
9106        })
9107    }
9108}
9109
9110/// Modifier for the transaction in the `BEGIN` syntax
9111///
9112/// SQLite: <https://sqlite.org/lang_transaction.html>
9113/// MS-SQL: <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/try-catch-transact-sql>
9114#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9115#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9116#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9117pub enum TransactionModifier {
9118    /// DEFERRED transaction modifier.
9119    Deferred,
9120    /// IMMEDIATE transaction modifier.
9121    Immediate,
9122    /// EXCLUSIVE transaction modifier.
9123    Exclusive,
9124    /// TRY block modifier (MS-SQL style TRY/CATCH).
9125    Try,
9126    /// CATCH block modifier (MS-SQL style TRY/CATCH).
9127    Catch,
9128}
9129
9130impl fmt::Display for TransactionModifier {
9131    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9132        use TransactionModifier::*;
9133        f.write_str(match self {
9134            Deferred => "DEFERRED",
9135            Immediate => "IMMEDIATE",
9136            Exclusive => "EXCLUSIVE",
9137            Try => "TRY",
9138            Catch => "CATCH",
9139        })
9140    }
9141}
9142
9143#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9144#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9145#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9146/// Filter forms usable in SHOW statements.
9147pub enum ShowStatementFilter {
9148    /// Filter using LIKE pattern.
9149    Like(String),
9150    /// Filter using ILIKE pattern.
9151    ILike(String),
9152    /// Filter using a WHERE expression.
9153    Where(Expr),
9154    /// Filter provided without a keyword (raw string).
9155    NoKeyword(String),
9156}
9157
9158impl fmt::Display for ShowStatementFilter {
9159    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9160        use ShowStatementFilter::*;
9161        match self {
9162            Like(pattern) => write!(f, "LIKE '{}'", value::escape_single_quote_string(pattern)),
9163            ILike(pattern) => write!(f, "ILIKE {}", value::escape_single_quote_string(pattern)),
9164            Where(expr) => write!(f, "WHERE {expr}"),
9165            NoKeyword(pattern) => write!(f, "'{}'", value::escape_single_quote_string(pattern)),
9166        }
9167    }
9168}
9169
9170#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9171#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9172#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9173/// Clause types used with SHOW ... IN/FROM.
9174pub enum ShowStatementInClause {
9175    /// Use the `IN` clause.
9176    IN,
9177    /// Use the `FROM` clause.
9178    FROM,
9179}
9180
9181impl fmt::Display for ShowStatementInClause {
9182    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9183        use ShowStatementInClause::*;
9184        match self {
9185            FROM => write!(f, "FROM"),
9186            IN => write!(f, "IN"),
9187        }
9188    }
9189}
9190
9191/// Sqlite specific syntax
9192///
9193/// See [Sqlite documentation](https://sqlite.org/lang_conflict.html)
9194/// for more details.
9195#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9196#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9197#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9198pub enum SqliteOnConflict {
9199    /// Use ROLLBACK on conflict.
9200    Rollback,
9201    /// Use ABORT on conflict.
9202    Abort,
9203    /// Use FAIL on conflict.
9204    Fail,
9205    /// Use IGNORE on conflict.
9206    Ignore,
9207    /// Use REPLACE on conflict.
9208    Replace,
9209}
9210
9211impl fmt::Display for SqliteOnConflict {
9212    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9213        use SqliteOnConflict::*;
9214        match self {
9215            Rollback => write!(f, "OR ROLLBACK"),
9216            Abort => write!(f, "OR ABORT"),
9217            Fail => write!(f, "OR FAIL"),
9218            Ignore => write!(f, "OR IGNORE"),
9219            Replace => write!(f, "OR REPLACE"),
9220        }
9221    }
9222}
9223
9224/// Mysql specific syntax
9225///
9226/// See [Mysql documentation](https://dev.mysql.com/doc/refman/8.0/en/replace.html)
9227/// See [Mysql documentation](https://dev.mysql.com/doc/refman/8.0/en/insert.html)
9228/// for more details.
9229#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9230#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9231#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9232pub enum MysqlInsertPriority {
9233    /// LOW_PRIORITY modifier for INSERT/REPLACE.
9234    LowPriority,
9235    /// DELAYED modifier for INSERT/REPLACE.
9236    Delayed,
9237    /// HIGH_PRIORITY modifier for INSERT/REPLACE.
9238    HighPriority,
9239}
9240
9241impl fmt::Display for crate::ast::MysqlInsertPriority {
9242    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9243        use MysqlInsertPriority::*;
9244        match self {
9245            LowPriority => write!(f, "LOW_PRIORITY"),
9246            Delayed => write!(f, "DELAYED"),
9247            HighPriority => write!(f, "HIGH_PRIORITY"),
9248        }
9249    }
9250}
9251
9252#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9253#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9254#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9255/// Source for the `COPY` command: a table or a query.
9256pub enum CopySource {
9257    /// Copy from a table with optional column list.
9258    Table {
9259        /// The name of the table to copy from.
9260        table_name: ObjectName,
9261        /// A list of column names to copy. Empty list means that all columns
9262        /// are copied.
9263        columns: Vec<Ident>,
9264    },
9265    /// Copy from the results of a query.
9266    Query(Box<Query>),
9267}
9268
9269#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9270#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9271#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9272/// Target for the `COPY` command: STDIN, STDOUT, a file, or a program.
9273pub enum CopyTarget {
9274    /// Use standard input as the source.
9275    Stdin,
9276    /// Use standard output as the target.
9277    Stdout,
9278    /// Read from or write to a file.
9279    File {
9280        /// The path name of the input or output file.
9281        filename: String,
9282    },
9283    /// Use a program as the source or target (shell command).
9284    Program {
9285        /// A command to execute
9286        command: String,
9287    },
9288}
9289
9290impl fmt::Display for CopyTarget {
9291    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9292        use CopyTarget::*;
9293        match self {
9294            Stdin => write!(f, "STDIN"),
9295            Stdout => write!(f, "STDOUT"),
9296            File { filename } => write!(f, "'{}'", value::escape_single_quote_string(filename)),
9297            Program { command } => write!(
9298                f,
9299                "PROGRAM '{}'",
9300                value::escape_single_quote_string(command)
9301            ),
9302        }
9303    }
9304}
9305
9306#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9307#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9308#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9309/// Action to take `ON COMMIT` for temporary tables.
9310pub enum OnCommit {
9311    /// Delete rows on commit.
9312    DeleteRows,
9313    /// Preserve rows on commit.
9314    PreserveRows,
9315    /// Drop the table on commit.
9316    Drop,
9317}
9318
9319/// An option in `COPY` statement.
9320///
9321/// <https://www.postgresql.org/docs/14/sql-copy.html>
9322#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9323#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9324#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9325pub enum CopyOption {
9326    /// FORMAT format_name
9327    Format(Ident),
9328    /// FREEZE \[ boolean \]
9329    Freeze(bool),
9330    /// DELIMITER 'delimiter_character'
9331    Delimiter(char),
9332    /// NULL 'null_string'
9333    Null(String),
9334    /// HEADER \[ boolean \]
9335    Header(bool),
9336    /// QUOTE 'quote_character'
9337    Quote(char),
9338    /// ESCAPE 'escape_character'
9339    Escape(char),
9340    /// FORCE_QUOTE { ( column_name [, ...] ) | * }
9341    ForceQuote(Vec<Ident>),
9342    /// FORCE_NOT_NULL ( column_name [, ...] )
9343    ForceNotNull(Vec<Ident>),
9344    /// FORCE_NULL ( column_name [, ...] )
9345    ForceNull(Vec<Ident>),
9346    /// ENCODING 'encoding_name'
9347    Encoding(String),
9348}
9349
9350impl fmt::Display for CopyOption {
9351    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9352        use CopyOption::*;
9353        match self {
9354            Format(name) => write!(f, "FORMAT {name}"),
9355            Freeze(true) => write!(f, "FREEZE"),
9356            Freeze(false) => write!(f, "FREEZE FALSE"),
9357            Delimiter(char) => write!(f, "DELIMITER '{char}'"),
9358            Null(string) => write!(f, "NULL '{}'", value::escape_single_quote_string(string)),
9359            Header(true) => write!(f, "HEADER"),
9360            Header(false) => write!(f, "HEADER FALSE"),
9361            Quote(char) => write!(f, "QUOTE '{char}'"),
9362            Escape(char) => write!(f, "ESCAPE '{char}'"),
9363            ForceQuote(columns) => write!(f, "FORCE_QUOTE ({})", display_comma_separated(columns)),
9364            ForceNotNull(columns) => {
9365                write!(f, "FORCE_NOT_NULL ({})", display_comma_separated(columns))
9366            }
9367            ForceNull(columns) => write!(f, "FORCE_NULL ({})", display_comma_separated(columns)),
9368            Encoding(name) => write!(f, "ENCODING '{}'", value::escape_single_quote_string(name)),
9369        }
9370    }
9371}
9372
9373/// An option in `COPY` statement before PostgreSQL version 9.0.
9374///
9375/// [PostgreSQL](https://www.postgresql.org/docs/8.4/sql-copy.html)
9376/// [Redshift](https://docs.aws.amazon.com/redshift/latest/dg/r_COPY-alphabetical-parm-list.html)
9377#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9378#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9379#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9380pub enum CopyLegacyOption {
9381    /// ACCEPTANYDATE
9382    AcceptAnyDate,
9383    /// ACCEPTINVCHARS
9384    AcceptInvChars(Option<String>),
9385    /// ADDQUOTES
9386    AddQuotes,
9387    /// ALLOWOVERWRITE
9388    AllowOverwrite,
9389    /// BINARY
9390    Binary,
9391    /// BLANKSASNULL
9392    BlankAsNull,
9393    /// BZIP2
9394    Bzip2,
9395    /// CLEANPATH
9396    CleanPath,
9397    /// COMPUPDATE [ PRESET | { ON | TRUE } | { OFF | FALSE } ]
9398    CompUpdate {
9399        /// Whether the COMPUPDATE PRESET option was used.
9400        preset: bool,
9401        /// Optional enabled flag for COMPUPDATE.
9402        enabled: Option<bool>,
9403    },
9404    /// CSV ...
9405    Csv(Vec<CopyLegacyCsvOption>),
9406    /// DATEFORMAT \[ AS \] {'dateformat_string' | 'auto' }
9407    DateFormat(Option<String>),
9408    /// DELIMITER \[ AS \] 'delimiter_character'
9409    Delimiter(char),
9410    /// EMPTYASNULL
9411    EmptyAsNull,
9412    /// `ENCRYPTED \[ AUTO \]`
9413    Encrypted {
9414        /// Whether `AUTO` was specified for encryption.
9415        auto: bool,
9416    },
9417    /// ESCAPE
9418    Escape,
9419    /// EXTENSION 'extension-name'
9420    Extension(String),
9421    /// FIXEDWIDTH \[ AS \] 'fixedwidth-spec'
9422    FixedWidth(String),
9423    /// GZIP
9424    Gzip,
9425    /// HEADER
9426    Header,
9427    /// IAM_ROLE { DEFAULT | 'arn:aws:iam::123456789:role/role1' }
9428    IamRole(IamRoleKind),
9429    /// IGNOREHEADER \[ AS \] number_rows
9430    IgnoreHeader(u64),
9431    /// JSON \[ AS \] 'json_option'
9432    Json(Option<String>),
9433    /// MANIFEST \[ VERBOSE \]
9434    Manifest {
9435        /// Whether the MANIFEST is verbose.
9436        verbose: bool,
9437    },
9438    /// MAXFILESIZE \[ AS \] max-size \[ MB | GB \]
9439    MaxFileSize(FileSize),
9440    /// `NULL \[ AS \] 'null_string'`
9441    Null(String),
9442    /// `PARALLEL [ { ON | TRUE } | { OFF | FALSE } ]`
9443    Parallel(Option<bool>),
9444    /// PARQUET
9445    Parquet,
9446    /// PARTITION BY ( column_name [, ... ] ) \[ INCLUDE \]
9447    PartitionBy(UnloadPartitionBy),
9448    /// REGION \[ AS \] 'aws-region' }
9449    Region(String),
9450    /// REMOVEQUOTES
9451    RemoveQuotes,
9452    /// ROWGROUPSIZE \[ AS \] size \[ MB | GB \]
9453    RowGroupSize(FileSize),
9454    /// STATUPDATE [ { ON | TRUE } | { OFF | FALSE } ]
9455    StatUpdate(Option<bool>),
9456    /// TIMEFORMAT \[ AS \] {'timeformat_string' | 'auto' | 'epochsecs' | 'epochmillisecs' }
9457    TimeFormat(Option<String>),
9458    /// TRUNCATECOLUMNS
9459    TruncateColumns,
9460    /// ZSTD
9461    Zstd,
9462    /// Redshift `CREDENTIALS 'auth-args'`
9463    /// <https://docs.aws.amazon.com/redshift/latest/dg/copy-parameters-authorization.html>
9464    Credentials(String),
9465}
9466
9467impl fmt::Display for CopyLegacyOption {
9468    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9469        use CopyLegacyOption::*;
9470        match self {
9471            AcceptAnyDate => write!(f, "ACCEPTANYDATE"),
9472            AcceptInvChars(ch) => {
9473                write!(f, "ACCEPTINVCHARS")?;
9474                if let Some(ch) = ch {
9475                    write!(f, " '{}'", value::escape_single_quote_string(ch))?;
9476                }
9477                Ok(())
9478            }
9479            AddQuotes => write!(f, "ADDQUOTES"),
9480            AllowOverwrite => write!(f, "ALLOWOVERWRITE"),
9481            Binary => write!(f, "BINARY"),
9482            BlankAsNull => write!(f, "BLANKSASNULL"),
9483            Bzip2 => write!(f, "BZIP2"),
9484            CleanPath => write!(f, "CLEANPATH"),
9485            CompUpdate { preset, enabled } => {
9486                write!(f, "COMPUPDATE")?;
9487                if *preset {
9488                    write!(f, " PRESET")?;
9489                } else if let Some(enabled) = enabled {
9490                    write!(
9491                        f,
9492                        "{}",
9493                        match enabled {
9494                            true => " TRUE",
9495                            false => " FALSE",
9496                        }
9497                    )?;
9498                }
9499                Ok(())
9500            }
9501            Csv(opts) => {
9502                write!(f, "CSV")?;
9503                if !opts.is_empty() {
9504                    write!(f, " {}", display_separated(opts, " "))?;
9505                }
9506                Ok(())
9507            }
9508            DateFormat(fmt) => {
9509                write!(f, "DATEFORMAT")?;
9510                if let Some(fmt) = fmt {
9511                    write!(f, " '{}'", value::escape_single_quote_string(fmt))?;
9512                }
9513                Ok(())
9514            }
9515            Delimiter(char) => write!(f, "DELIMITER '{char}'"),
9516            EmptyAsNull => write!(f, "EMPTYASNULL"),
9517            Encrypted { auto } => write!(f, "ENCRYPTED{}", if *auto { " AUTO" } else { "" }),
9518            Escape => write!(f, "ESCAPE"),
9519            Extension(ext) => write!(f, "EXTENSION '{}'", value::escape_single_quote_string(ext)),
9520            FixedWidth(spec) => write!(
9521                f,
9522                "FIXEDWIDTH '{}'",
9523                value::escape_single_quote_string(spec)
9524            ),
9525            Gzip => write!(f, "GZIP"),
9526            Header => write!(f, "HEADER"),
9527            IamRole(role) => write!(f, "IAM_ROLE {role}"),
9528            IgnoreHeader(num_rows) => write!(f, "IGNOREHEADER {num_rows}"),
9529            Json(opt) => {
9530                write!(f, "JSON")?;
9531                if let Some(opt) = opt {
9532                    write!(f, " AS '{}'", value::escape_single_quote_string(opt))?;
9533                }
9534                Ok(())
9535            }
9536            Manifest { verbose } => write!(f, "MANIFEST{}", if *verbose { " VERBOSE" } else { "" }),
9537            MaxFileSize(file_size) => write!(f, "MAXFILESIZE {file_size}"),
9538            Null(string) => write!(f, "NULL '{}'", value::escape_single_quote_string(string)),
9539            Parallel(enabled) => {
9540                write!(
9541                    f,
9542                    "PARALLEL{}",
9543                    match enabled {
9544                        Some(true) => " TRUE",
9545                        Some(false) => " FALSE",
9546                        _ => "",
9547                    }
9548                )
9549            }
9550            Parquet => write!(f, "PARQUET"),
9551            PartitionBy(p) => write!(f, "{p}"),
9552            Region(region) => write!(f, "REGION '{}'", value::escape_single_quote_string(region)),
9553            RemoveQuotes => write!(f, "REMOVEQUOTES"),
9554            RowGroupSize(file_size) => write!(f, "ROWGROUPSIZE {file_size}"),
9555            StatUpdate(enabled) => {
9556                write!(
9557                    f,
9558                    "STATUPDATE{}",
9559                    match enabled {
9560                        Some(true) => " TRUE",
9561                        Some(false) => " FALSE",
9562                        _ => "",
9563                    }
9564                )
9565            }
9566            TimeFormat(fmt) => {
9567                write!(f, "TIMEFORMAT")?;
9568                if let Some(fmt) = fmt {
9569                    write!(f, " '{}'", value::escape_single_quote_string(fmt))?;
9570                }
9571                Ok(())
9572            }
9573            TruncateColumns => write!(f, "TRUNCATECOLUMNS"),
9574            Zstd => write!(f, "ZSTD"),
9575            Credentials(s) => write!(f, "CREDENTIALS '{}'", value::escape_single_quote_string(s)),
9576        }
9577    }
9578}
9579
9580/// ```sql
9581/// SIZE \[ MB | GB \]
9582/// ```
9583#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9584#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9585#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9586pub struct FileSize {
9587    /// Numeric size value.
9588    pub size: ValueWithSpan,
9589    /// Optional unit for the size (MB or GB).
9590    pub unit: Option<FileSizeUnit>,
9591}
9592
9593impl fmt::Display for FileSize {
9594    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9595        write!(f, "{}", self.size)?;
9596        if let Some(unit) = &self.unit {
9597            write!(f, " {unit}")?;
9598        }
9599        Ok(())
9600    }
9601}
9602
9603/// Units for `FileSize` (MB or GB).
9604#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9605#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9606#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9607pub enum FileSizeUnit {
9608    /// Megabytes.
9609    MB,
9610    /// Gigabytes.
9611    GB,
9612}
9613
9614impl fmt::Display for FileSizeUnit {
9615    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9616        match self {
9617            FileSizeUnit::MB => write!(f, "MB"),
9618            FileSizeUnit::GB => write!(f, "GB"),
9619        }
9620    }
9621}
9622
9623/// Specifies the partition keys for the unload operation
9624///
9625/// ```sql
9626/// PARTITION BY ( column_name [, ... ] ) [ INCLUDE ]
9627/// ```
9628#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9629#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9630#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9631pub struct UnloadPartitionBy {
9632    /// Columns used to partition the unload output.
9633    pub columns: Vec<Ident>,
9634    /// Whether to include the partition in the output.
9635    pub include: bool,
9636}
9637
9638impl fmt::Display for UnloadPartitionBy {
9639    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9640        write!(
9641            f,
9642            "PARTITION BY ({}){}",
9643            display_comma_separated(&self.columns),
9644            if self.include { " INCLUDE" } else { "" }
9645        )
9646    }
9647}
9648
9649/// An `IAM_ROLE` option in the AWS ecosystem
9650///
9651/// [Redshift COPY](https://docs.aws.amazon.com/redshift/latest/dg/copy-parameters-authorization.html#copy-iam-role)
9652#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9653#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9654#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9655pub enum IamRoleKind {
9656    /// Default role
9657    Default,
9658    /// Specific role ARN, for example: `arn:aws:iam::123456789:role/role1`
9659    Arn(String),
9660}
9661
9662impl fmt::Display for IamRoleKind {
9663    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9664        match self {
9665            IamRoleKind::Default => write!(f, "DEFAULT"),
9666            IamRoleKind::Arn(arn) => write!(f, "'{arn}'"),
9667        }
9668    }
9669}
9670
9671/// A `CSV` option in `COPY` statement before PostgreSQL version 9.0.
9672///
9673/// <https://www.postgresql.org/docs/8.4/sql-copy.html>
9674#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9675#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9676#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9677pub enum CopyLegacyCsvOption {
9678    /// HEADER
9679    Header,
9680    /// QUOTE \[ AS \] 'quote_character'
9681    Quote(char),
9682    /// ESCAPE \[ AS \] 'escape_character'
9683    Escape(char),
9684    /// FORCE QUOTE { column_name [, ...] | * }
9685    ForceQuote(Vec<Ident>),
9686    /// FORCE NOT NULL column_name [, ...]
9687    ForceNotNull(Vec<Ident>),
9688}
9689
9690impl fmt::Display for CopyLegacyCsvOption {
9691    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9692        use CopyLegacyCsvOption::*;
9693        match self {
9694            Header => write!(f, "HEADER"),
9695            Quote(char) => write!(f, "QUOTE '{char}'"),
9696            Escape(char) => write!(f, "ESCAPE '{char}'"),
9697            ForceQuote(columns) => write!(f, "FORCE QUOTE {}", display_comma_separated(columns)),
9698            ForceNotNull(columns) => {
9699                write!(f, "FORCE NOT NULL {}", display_comma_separated(columns))
9700            }
9701        }
9702    }
9703}
9704
9705/// Objects that can be discarded with `DISCARD`.
9706#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9707#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9708#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9709pub enum DiscardObject {
9710    /// Discard all session state.
9711    ALL,
9712    /// Discard cached plans.
9713    PLANS,
9714    /// Discard sequence values.
9715    SEQUENCES,
9716    /// Discard temporary objects.
9717    TEMP,
9718}
9719
9720impl fmt::Display for DiscardObject {
9721    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9722        match self {
9723            DiscardObject::ALL => f.write_str("ALL"),
9724            DiscardObject::PLANS => f.write_str("PLANS"),
9725            DiscardObject::SEQUENCES => f.write_str("SEQUENCES"),
9726            DiscardObject::TEMP => f.write_str("TEMP"),
9727        }
9728    }
9729}
9730
9731/// Types of flush operations supported by `FLUSH`.
9732#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9733#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9734#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9735pub enum FlushType {
9736    /// Flush binary logs.
9737    BinaryLogs,
9738    /// Flush engine logs.
9739    EngineLogs,
9740    /// Flush error logs.
9741    ErrorLogs,
9742    /// Flush general logs.
9743    GeneralLogs,
9744    /// Flush hosts information.
9745    Hosts,
9746    /// Flush logs.
9747    Logs,
9748    /// Flush privileges.
9749    Privileges,
9750    /// Flush optimizer costs.
9751    OptimizerCosts,
9752    /// Flush relay logs.
9753    RelayLogs,
9754    /// Flush slow logs.
9755    SlowLogs,
9756    /// Flush status.
9757    Status,
9758    /// Flush user resources.
9759    UserResources,
9760    /// Flush table data.
9761    Tables,
9762}
9763
9764impl fmt::Display for FlushType {
9765    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9766        match self {
9767            FlushType::BinaryLogs => f.write_str("BINARY LOGS"),
9768            FlushType::EngineLogs => f.write_str("ENGINE LOGS"),
9769            FlushType::ErrorLogs => f.write_str("ERROR LOGS"),
9770            FlushType::GeneralLogs => f.write_str("GENERAL LOGS"),
9771            FlushType::Hosts => f.write_str("HOSTS"),
9772            FlushType::Logs => f.write_str("LOGS"),
9773            FlushType::Privileges => f.write_str("PRIVILEGES"),
9774            FlushType::OptimizerCosts => f.write_str("OPTIMIZER_COSTS"),
9775            FlushType::RelayLogs => f.write_str("RELAY LOGS"),
9776            FlushType::SlowLogs => f.write_str("SLOW LOGS"),
9777            FlushType::Status => f.write_str("STATUS"),
9778            FlushType::UserResources => f.write_str("USER_RESOURCES"),
9779            FlushType::Tables => f.write_str("TABLES"),
9780        }
9781    }
9782}
9783
9784/// Location modifier for flush commands.
9785#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9786#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9787#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9788pub enum FlushLocation {
9789    /// Do not write changes to the binary log.
9790    NoWriteToBinlog,
9791    /// Apply flush locally.
9792    Local,
9793}
9794
9795impl fmt::Display for FlushLocation {
9796    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9797        match self {
9798            FlushLocation::NoWriteToBinlog => f.write_str("NO_WRITE_TO_BINLOG"),
9799            FlushLocation::Local => f.write_str("LOCAL"),
9800        }
9801    }
9802}
9803
9804/// Optional context modifier for statements that can be or `LOCAL`, `GLOBAL`, or `SESSION`.
9805#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9806#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9807#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9808pub enum ContextModifier {
9809    /// `LOCAL` identifier, usually related to transactional states.
9810    Local,
9811    /// `SESSION` identifier
9812    Session,
9813    /// `GLOBAL` identifier
9814    Global,
9815}
9816
9817impl fmt::Display for ContextModifier {
9818    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9819        match self {
9820            Self::Local => {
9821                write!(f, "LOCAL ")
9822            }
9823            Self::Session => {
9824                write!(f, "SESSION ")
9825            }
9826            Self::Global => {
9827                write!(f, "GLOBAL ")
9828            }
9829        }
9830    }
9831}
9832
9833/// Function describe in DROP FUNCTION.
9834#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9835#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9836pub enum DropFunctionOption {
9837    /// `RESTRICT` option for DROP FUNCTION.
9838    Restrict,
9839    /// `CASCADE` option for DROP FUNCTION.
9840    Cascade,
9841}
9842
9843impl fmt::Display for DropFunctionOption {
9844    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9845        match self {
9846            DropFunctionOption::Restrict => write!(f, "RESTRICT "),
9847            DropFunctionOption::Cascade => write!(f, "CASCADE  "),
9848        }
9849    }
9850}
9851
9852/// Generic function description for DROP FUNCTION and CREATE TRIGGER.
9853#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9854#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9855#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9856pub struct FunctionDesc {
9857    /// The function name.
9858    pub name: ObjectName,
9859    /// Optional list of function arguments.
9860    pub args: Option<Vec<OperateFunctionArg>>,
9861}
9862
9863impl fmt::Display for FunctionDesc {
9864    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9865        write!(f, "{}", self.name)?;
9866        if let Some(args) = &self.args {
9867            write!(f, "({})", display_comma_separated(args))?;
9868        }
9869        Ok(())
9870    }
9871}
9872
9873/// Function argument in CREATE OR DROP FUNCTION.
9874#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9875#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9876#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9877pub struct OperateFunctionArg {
9878    /// Optional argument mode (`IN`, `OUT`, `INOUT`).
9879    pub mode: Option<ArgMode>,
9880    /// Optional argument identifier/name.
9881    pub name: Option<Ident>,
9882    /// The data type of the argument.
9883    pub data_type: DataType,
9884    /// Optional default expression for the argument.
9885    pub default_expr: Option<Expr>,
9886}
9887
9888impl OperateFunctionArg {
9889    /// Returns an unnamed argument.
9890    pub fn unnamed(data_type: DataType) -> Self {
9891        Self {
9892            mode: None,
9893            name: None,
9894            data_type,
9895            default_expr: None,
9896        }
9897    }
9898
9899    /// Returns an argument with name.
9900    pub fn with_name(name: &str, data_type: DataType) -> Self {
9901        Self {
9902            mode: None,
9903            name: Some(name.into()),
9904            data_type,
9905            default_expr: None,
9906        }
9907    }
9908}
9909
9910impl fmt::Display for OperateFunctionArg {
9911    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9912        if let Some(mode) = &self.mode {
9913            write!(f, "{mode} ")?;
9914        }
9915        if let Some(name) = &self.name {
9916            write!(f, "{name} ")?;
9917        }
9918        write!(f, "{}", self.data_type)?;
9919        if let Some(default_expr) = &self.default_expr {
9920            write!(f, " = {default_expr}")?;
9921        }
9922        Ok(())
9923    }
9924}
9925
9926/// The mode of an argument in CREATE FUNCTION.
9927#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9928#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9929#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9930pub enum ArgMode {
9931    /// `IN` mode.
9932    In,
9933    /// `OUT` mode.
9934    Out,
9935    /// `INOUT` mode.
9936    InOut,
9937    /// `VARIADIC` mode.
9938    Variadic,
9939}
9940
9941impl fmt::Display for ArgMode {
9942    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9943        match self {
9944            ArgMode::In => write!(f, "IN"),
9945            ArgMode::Out => write!(f, "OUT"),
9946            ArgMode::InOut => write!(f, "INOUT"),
9947            ArgMode::Variadic => write!(f, "VARIADIC"),
9948        }
9949    }
9950}
9951
9952/// These attributes inform the query optimizer about the behavior of the function.
9953#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9954#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9955#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9956pub enum FunctionBehavior {
9957    /// Function is immutable.
9958    Immutable,
9959    /// Function is stable.
9960    Stable,
9961    /// Function is volatile.
9962    Volatile,
9963}
9964
9965impl fmt::Display for FunctionBehavior {
9966    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9967        match self {
9968            FunctionBehavior::Immutable => write!(f, "IMMUTABLE"),
9969            FunctionBehavior::Stable => write!(f, "STABLE"),
9970            FunctionBehavior::Volatile => write!(f, "VOLATILE"),
9971        }
9972    }
9973}
9974
9975/// Security attribute for functions: SECURITY DEFINER or SECURITY INVOKER.
9976///
9977/// [PostgreSQL](https://www.postgresql.org/docs/current/sql-createfunction.html)
9978#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9979#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9980#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9981pub enum FunctionSecurity {
9982    /// Execute the function with the privileges of the user who defined it.
9983    Definer,
9984    /// Execute the function with the privileges of the user who invokes it.
9985    Invoker,
9986}
9987
9988impl fmt::Display for FunctionSecurity {
9989    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9990        match self {
9991            FunctionSecurity::Definer => write!(f, "SECURITY DEFINER"),
9992            FunctionSecurity::Invoker => write!(f, "SECURITY INVOKER"),
9993        }
9994    }
9995}
9996
9997/// Value for a SET configuration parameter in a CREATE FUNCTION statement.
9998///
9999/// [PostgreSQL](https://www.postgresql.org/docs/current/sql-createfunction.html)
10000#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10001#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10002#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10003pub enum FunctionSetValue {
10004    /// SET param = DEFAULT / SET param TO DEFAULT
10005    Default,
10006    /// SET param = value1, value2, ...
10007    Values(Vec<Expr>),
10008    /// SET param FROM CURRENT
10009    FromCurrent,
10010}
10011
10012/// A SET configuration_parameter clause in a CREATE FUNCTION statement.
10013///
10014/// [PostgreSQL](https://www.postgresql.org/docs/current/sql-createfunction.html)
10015#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10016#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10017#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10018pub struct FunctionDefinitionSetParam {
10019    /// The name of the configuration parameter.
10020    pub name: ObjectName,
10021    /// The value to set for the parameter.
10022    pub value: FunctionSetValue,
10023}
10024
10025impl fmt::Display for FunctionDefinitionSetParam {
10026    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10027        write!(f, "SET {} ", self.name)?;
10028        match &self.value {
10029            FunctionSetValue::Default => write!(f, "= DEFAULT"),
10030            FunctionSetValue::Values(values) => {
10031                write!(f, "= {}", display_comma_separated(values))
10032            }
10033            FunctionSetValue::FromCurrent => write!(f, "FROM CURRENT"),
10034        }
10035    }
10036}
10037
10038/// These attributes describe the behavior of the function when called with a null argument.
10039#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10040#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10041#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10042pub enum FunctionCalledOnNull {
10043    /// Function is called even when inputs are null.
10044    CalledOnNullInput,
10045    /// Function returns null when any input is null.
10046    ReturnsNullOnNullInput,
10047    /// Function is strict about null inputs.
10048    Strict,
10049}
10050
10051impl fmt::Display for FunctionCalledOnNull {
10052    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10053        match self {
10054            FunctionCalledOnNull::CalledOnNullInput => write!(f, "CALLED ON NULL INPUT"),
10055            FunctionCalledOnNull::ReturnsNullOnNullInput => write!(f, "RETURNS NULL ON NULL INPUT"),
10056            FunctionCalledOnNull::Strict => write!(f, "STRICT"),
10057        }
10058    }
10059}
10060
10061/// If it is safe for PostgreSQL to call the function from multiple threads at once
10062#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10063#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10064#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10065pub enum FunctionParallel {
10066    /// The function is not safe to run in parallel.
10067    Unsafe,
10068    /// The function is restricted for parallel execution.
10069    Restricted,
10070    /// The function is safe to run in parallel.
10071    Safe,
10072}
10073
10074impl fmt::Display for FunctionParallel {
10075    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10076        match self {
10077            FunctionParallel::Unsafe => write!(f, "PARALLEL UNSAFE"),
10078            FunctionParallel::Restricted => write!(f, "PARALLEL RESTRICTED"),
10079            FunctionParallel::Safe => write!(f, "PARALLEL SAFE"),
10080        }
10081    }
10082}
10083
10084/// [BigQuery] Determinism specifier used in a UDF definition.
10085///
10086/// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#syntax_11
10087#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10088#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10089#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10090pub enum FunctionDeterminismSpecifier {
10091    /// Function is deterministic.
10092    Deterministic,
10093    /// Function is not deterministic.
10094    NotDeterministic,
10095}
10096
10097impl fmt::Display for FunctionDeterminismSpecifier {
10098    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10099        match self {
10100            FunctionDeterminismSpecifier::Deterministic => {
10101                write!(f, "DETERMINISTIC")
10102            }
10103            FunctionDeterminismSpecifier::NotDeterministic => {
10104                write!(f, "NOT DETERMINISTIC")
10105            }
10106        }
10107    }
10108}
10109
10110/// Represent the expression body of a `CREATE FUNCTION` statement as well as
10111/// where within the statement, the body shows up.
10112///
10113/// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#syntax_11
10114/// [PostgreSQL]: https://www.postgresql.org/docs/15/sql-createfunction.html
10115/// [MsSql]: https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql
10116#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10117#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10118#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10119pub enum CreateFunctionBody {
10120    /// A function body expression using the 'AS' keyword and shows up
10121    /// before any `OPTIONS` clause.
10122    ///
10123    /// Example:
10124    /// ```sql
10125    /// CREATE FUNCTION myfunc(x FLOAT64, y FLOAT64) RETURNS FLOAT64
10126    /// AS (x * y)
10127    /// OPTIONS(description="desc");
10128    /// ```
10129    ///
10130    /// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#syntax_11
10131    /// [PostgreSQL]: https://www.postgresql.org/docs/current/sql-createfunction.html
10132    AsBeforeOptions {
10133        /// The primary expression.
10134        body: Expr,
10135        /// Link symbol if the primary expression contains the name of shared library file.
10136        ///
10137        /// Example:
10138        /// ```sql
10139        /// CREATE FUNCTION cas_in(input cstring) RETURNS cas
10140        /// AS 'MODULE_PATHNAME', 'cas_in_wrapper'
10141        /// ```
10142        /// [PostgreSQL]: https://www.postgresql.org/docs/current/sql-createfunction.html
10143        link_symbol: Option<Expr>,
10144    },
10145    /// A function body expression using the 'AS' keyword and shows up
10146    /// after any `OPTIONS` clause.
10147    ///
10148    /// Example:
10149    /// ```sql
10150    /// CREATE FUNCTION myfunc(x FLOAT64, y FLOAT64) RETURNS FLOAT64
10151    /// OPTIONS(description="desc")
10152    /// AS (x * y);
10153    /// ```
10154    ///
10155    /// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#syntax_11
10156    AsAfterOptions(Expr),
10157    /// Function body with statements before the `RETURN` keyword.
10158    ///
10159    /// Example:
10160    /// ```sql
10161    /// CREATE FUNCTION my_scalar_udf(a INT, b INT)
10162    /// RETURNS INT
10163    /// AS
10164    /// BEGIN
10165    ///     DECLARE c INT;
10166    ///     SET c = a + b;
10167    ///     RETURN c;
10168    /// END
10169    /// ```
10170    ///
10171    /// [MsSql]: https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql
10172    AsBeginEnd(BeginEndStatements),
10173    /// Function body expression using the 'RETURN' keyword.
10174    ///
10175    /// Example:
10176    /// ```sql
10177    /// CREATE FUNCTION myfunc(a INTEGER, IN b INTEGER = 1) RETURNS INTEGER
10178    /// LANGUAGE SQL
10179    /// RETURN a + b;
10180    /// ```
10181    ///
10182    /// [PostgreSQL]: https://www.postgresql.org/docs/current/sql-createfunction.html
10183    Return(Expr),
10184
10185    /// Function body expression using the 'AS RETURN' keywords
10186    ///
10187    /// Example:
10188    /// ```sql
10189    /// CREATE FUNCTION myfunc(a INT, b INT)
10190    /// RETURNS TABLE
10191    /// AS RETURN (SELECT a + b AS sum);
10192    /// ```
10193    ///
10194    /// [MsSql]: https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql
10195    AsReturnExpr(Expr),
10196
10197    /// Function body expression using the 'AS RETURN' keywords, with an un-parenthesized SELECT query
10198    ///
10199    /// Example:
10200    /// ```sql
10201    /// CREATE FUNCTION myfunc(a INT, b INT)
10202    /// RETURNS TABLE
10203    /// AS RETURN SELECT a + b AS sum;
10204    /// ```
10205    ///
10206    /// [MsSql]: https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql?view=sql-server-ver16#select_stmt
10207    AsReturnSelect(Select),
10208}
10209
10210#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10211#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10212#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10213/// `USING` clause options for `CREATE FUNCTION` (e.g., JAR, FILE, ARCHIVE).
10214pub enum CreateFunctionUsing {
10215    /// Use a JAR file located at the given URI.
10216    Jar(String),
10217    /// Use a file located at the given URI.
10218    File(String),
10219    /// Use an archive located at the given URI.
10220    Archive(String),
10221}
10222
10223impl fmt::Display for CreateFunctionUsing {
10224    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10225        write!(f, "USING ")?;
10226        match self {
10227            CreateFunctionUsing::Jar(uri) => write!(f, "JAR '{uri}'"),
10228            CreateFunctionUsing::File(uri) => write!(f, "FILE '{uri}'"),
10229            CreateFunctionUsing::Archive(uri) => write!(f, "ARCHIVE '{uri}'"),
10230        }
10231    }
10232}
10233
10234/// `NAME = <EXPR>` arguments for DuckDB macros
10235///
10236/// See [Create Macro - DuckDB](https://duckdb.org/docs/sql/statements/create_macro)
10237/// for more details
10238#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10239#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10240#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10241pub struct MacroArg {
10242    /// The argument name.
10243    pub name: Ident,
10244    /// Optional default expression for the argument.
10245    pub default_expr: Option<Expr>,
10246}
10247
10248impl MacroArg {
10249    /// Returns an argument with name.
10250    pub fn new(name: &str) -> Self {
10251        Self {
10252            name: name.into(),
10253            default_expr: None,
10254        }
10255    }
10256}
10257
10258impl fmt::Display for MacroArg {
10259    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10260        write!(f, "{}", self.name)?;
10261        if let Some(default_expr) = &self.default_expr {
10262            write!(f, " := {default_expr}")?;
10263        }
10264        Ok(())
10265    }
10266}
10267
10268#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10269#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10270#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10271/// Definition for a DuckDB macro: either an expression or a table-producing query.
10272pub enum MacroDefinition {
10273    /// The macro is defined as an expression.
10274    Expr(Expr),
10275    /// The macro is defined as a table (query).
10276    Table(Box<Query>),
10277}
10278
10279impl fmt::Display for MacroDefinition {
10280    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10281        match self {
10282            MacroDefinition::Expr(expr) => write!(f, "{expr}")?,
10283            MacroDefinition::Table(query) => write!(f, "{query}")?,
10284        }
10285        Ok(())
10286    }
10287}
10288
10289/// Schema possible naming variants ([1]).
10290///
10291/// [1]: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#schema-definition
10292#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10293#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10294#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10295pub enum SchemaName {
10296    /// Only schema name specified: `<schema name>`.
10297    Simple(ObjectName),
10298    /// Only authorization identifier specified: `AUTHORIZATION <schema authorization identifier>`.
10299    UnnamedAuthorization(Ident),
10300    /// Both schema name and authorization identifier specified: `<schema name>  AUTHORIZATION <schema authorization identifier>`.
10301    NamedAuthorization(ObjectName, Ident),
10302}
10303
10304impl fmt::Display for SchemaName {
10305    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10306        match self {
10307            SchemaName::Simple(name) => {
10308                write!(f, "{name}")
10309            }
10310            SchemaName::UnnamedAuthorization(authorization) => {
10311                write!(f, "AUTHORIZATION {authorization}")
10312            }
10313            SchemaName::NamedAuthorization(name, authorization) => {
10314                write!(f, "{name} AUTHORIZATION {authorization}")
10315            }
10316        }
10317    }
10318}
10319
10320/// Fulltext search modifiers ([1]).
10321///
10322/// [1]: https://dev.mysql.com/doc/refman/8.0/en/fulltext-search.html#function_match
10323#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10324#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10325#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10326pub enum SearchModifier {
10327    /// `IN NATURAL LANGUAGE MODE`.
10328    InNaturalLanguageMode,
10329    /// `IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION`.
10330    InNaturalLanguageModeWithQueryExpansion,
10331    ///`IN BOOLEAN MODE`.
10332    InBooleanMode,
10333    ///`WITH QUERY EXPANSION`.
10334    WithQueryExpansion,
10335}
10336
10337impl fmt::Display for SearchModifier {
10338    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10339        match self {
10340            Self::InNaturalLanguageMode => {
10341                write!(f, "IN NATURAL LANGUAGE MODE")?;
10342            }
10343            Self::InNaturalLanguageModeWithQueryExpansion => {
10344                write!(f, "IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION")?;
10345            }
10346            Self::InBooleanMode => {
10347                write!(f, "IN BOOLEAN MODE")?;
10348            }
10349            Self::WithQueryExpansion => {
10350                write!(f, "WITH QUERY EXPANSION")?;
10351            }
10352        }
10353
10354        Ok(())
10355    }
10356}
10357
10358/// Represents a `LOCK TABLE` clause with optional alias and lock type.
10359#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10360#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10361#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10362pub struct LockTable {
10363    /// The table identifier to lock.
10364    pub table: Ident,
10365    /// Optional alias for the table.
10366    pub alias: Option<Ident>,
10367    /// The type of lock to apply to the table.
10368    pub lock_type: LockTableType,
10369}
10370
10371impl fmt::Display for LockTable {
10372    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10373        let Self {
10374            table: tbl_name,
10375            alias,
10376            lock_type,
10377        } = self;
10378
10379        write!(f, "{tbl_name} ")?;
10380        if let Some(alias) = alias {
10381            write!(f, "AS {alias} ")?;
10382        }
10383        write!(f, "{lock_type}")?;
10384        Ok(())
10385    }
10386}
10387
10388#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10389#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10390#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10391/// The type of lock used in `LOCK TABLE` statements.
10392pub enum LockTableType {
10393    /// Shared/read lock. If `local` is true, it's a local read lock.
10394    Read {
10395        /// Whether the read lock is local.
10396        local: bool,
10397    },
10398    /// Exclusive/write lock. If `low_priority` is true, the write is low priority.
10399    Write {
10400        /// Whether the write lock is low priority.
10401        low_priority: bool,
10402    },
10403}
10404
10405impl fmt::Display for LockTableType {
10406    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10407        match self {
10408            Self::Read { local } => {
10409                write!(f, "READ")?;
10410                if *local {
10411                    write!(f, " LOCAL")?;
10412                }
10413            }
10414            Self::Write { low_priority } => {
10415                if *low_priority {
10416                    write!(f, "LOW_PRIORITY ")?;
10417                }
10418                write!(f, "WRITE")?;
10419            }
10420        }
10421
10422        Ok(())
10423    }
10424}
10425
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))]
10429/// Hive-specific `SET LOCATION` helper used in some `LOAD DATA` statements.
10430pub struct HiveSetLocation {
10431    /// Whether the `SET` keyword was present.
10432    pub has_set: bool,
10433    /// The location identifier.
10434    pub location: Ident,
10435}
10436
10437impl fmt::Display for HiveSetLocation {
10438    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10439        if self.has_set {
10440            write!(f, "SET ")?;
10441        }
10442        write!(f, "LOCATION {}", self.location)
10443    }
10444}
10445
10446/// MySQL `ALTER TABLE` only  [FIRST | AFTER column_name]
10447#[allow(clippy::large_enum_variant)]
10448#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10449#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10450#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10451/// MySQL `ALTER TABLE` column position specifier: `FIRST` or `AFTER <column>`.
10452pub enum MySQLColumnPosition {
10453    /// Place the column first in the table.
10454    First,
10455    /// Place the column after the specified identifier.
10456    After(Ident),
10457}
10458
10459impl Display for MySQLColumnPosition {
10460    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10461        match self {
10462            MySQLColumnPosition::First => write!(f, "FIRST"),
10463            MySQLColumnPosition::After(ident) => {
10464                let column_name = &ident.value;
10465                write!(f, "AFTER {column_name}")
10466            }
10467        }
10468    }
10469}
10470
10471/// MySQL `CREATE VIEW` algorithm parameter: [ALGORITHM = {UNDEFINED | MERGE | TEMPTABLE}]
10472#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10473#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10474#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10475/// MySQL `CREATE VIEW` algorithm options.
10476pub enum CreateViewAlgorithm {
10477    /// `UNDEFINED` algorithm.
10478    Undefined,
10479    /// `MERGE` algorithm.
10480    Merge,
10481    /// `TEMPTABLE` algorithm.
10482    TempTable,
10483}
10484
10485impl Display for CreateViewAlgorithm {
10486    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10487        match self {
10488            CreateViewAlgorithm::Undefined => write!(f, "UNDEFINED"),
10489            CreateViewAlgorithm::Merge => write!(f, "MERGE"),
10490            CreateViewAlgorithm::TempTable => write!(f, "TEMPTABLE"),
10491        }
10492    }
10493}
10494/// MySQL `CREATE VIEW` security parameter: [SQL SECURITY { DEFINER | INVOKER }]
10495#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10496#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10497#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10498/// MySQL `CREATE VIEW` SQL SECURITY options.
10499pub enum CreateViewSecurity {
10500    /// The view runs with the privileges of the definer.
10501    Definer,
10502    /// The view runs with the privileges of the invoker.
10503    Invoker,
10504}
10505
10506impl Display for CreateViewSecurity {
10507    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10508        match self {
10509            CreateViewSecurity::Definer => write!(f, "DEFINER"),
10510            CreateViewSecurity::Invoker => write!(f, "INVOKER"),
10511        }
10512    }
10513}
10514
10515/// [MySQL] `CREATE VIEW` additional parameters
10516///
10517/// [MySQL]: https://dev.mysql.com/doc/refman/9.1/en/create-view.html
10518#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10519#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10520#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10521pub struct CreateViewParams {
10522    /// Optional view algorithm (e.g., MERGE, TEMPTABLE).
10523    pub algorithm: Option<CreateViewAlgorithm>,
10524    /// Optional definer (the security principal that will own the view).
10525    pub definer: Option<GranteeName>,
10526    /// Optional SQL SECURITY setting for the view.
10527    pub security: Option<CreateViewSecurity>,
10528}
10529
10530impl Display for CreateViewParams {
10531    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10532        let CreateViewParams {
10533            algorithm,
10534            definer,
10535            security,
10536        } = self;
10537        if let Some(algorithm) = algorithm {
10538            write!(f, "ALGORITHM = {algorithm} ")?;
10539        }
10540        if let Some(definers) = definer {
10541            write!(f, "DEFINER = {definers} ")?;
10542        }
10543        if let Some(security) = security {
10544            write!(f, "SQL SECURITY {security} ")?;
10545        }
10546        Ok(())
10547    }
10548}
10549
10550#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10551#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10552#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10553/// Key/Value, where the value is a (optionally named) list of identifiers
10554///
10555/// ```sql
10556/// UNION = (tbl_name[,tbl_name]...)
10557/// ENGINE = ReplicatedMergeTree('/table_name','{replica}', ver)
10558/// ENGINE = SummingMergeTree([columns])
10559/// ```
10560pub struct NamedParenthesizedList {
10561    /// The option key (identifier) for this named list.
10562    pub key: Ident,
10563    /// Optional secondary name associated with the key.
10564    pub name: Option<Ident>,
10565    /// The list of identifier values for the key.
10566    pub values: Vec<Ident>,
10567}
10568
10569/// Snowflake `WITH ROW ACCESS POLICY policy_name ON (identifier, ...)`
10570///
10571/// <https://docs.snowflake.com/en/sql-reference/sql/create-table>
10572/// <https://docs.snowflake.com/en/user-guide/security-row-intro>
10573#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10574#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10575#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10576pub struct RowAccessPolicy {
10577    /// The fully-qualified policy object name.
10578    pub policy: ObjectName,
10579    /// Identifiers for the columns or objects the policy applies to.
10580    pub on: Vec<Ident>,
10581}
10582
10583impl RowAccessPolicy {
10584    /// Create a new `RowAccessPolicy` for the given `policy` and `on` identifiers.
10585    pub fn new(policy: ObjectName, on: Vec<Ident>) -> Self {
10586        Self { policy, on }
10587    }
10588}
10589
10590impl Display for RowAccessPolicy {
10591    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10592        write!(
10593            f,
10594            "WITH ROW ACCESS POLICY {} ON ({})",
10595            self.policy,
10596            display_comma_separated(self.on.as_slice())
10597        )
10598    }
10599}
10600
10601/// Snowflake `[ WITH ] STORAGE LIFECYCLE POLICY <policy_name> ON ( <col_name> [ , ... ] )`
10602///
10603/// <https://docs.snowflake.com/en/sql-reference/sql/create-table>
10604#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10605#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10606#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10607pub struct StorageLifecyclePolicy {
10608    /// The fully-qualified policy object name.
10609    pub policy: ObjectName,
10610    /// Column names the policy applies to.
10611    pub on: Vec<Ident>,
10612}
10613
10614impl Display for StorageLifecyclePolicy {
10615    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10616        write!(
10617            f,
10618            "WITH STORAGE LIFECYCLE POLICY {} ON ({})",
10619            self.policy,
10620            display_comma_separated(self.on.as_slice())
10621        )
10622    }
10623}
10624
10625/// Snowflake `WITH TAG ( tag_name = '<tag_value>', ...)`
10626///
10627/// <https://docs.snowflake.com/en/sql-reference/sql/create-table>
10628#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10629#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10630#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10631pub struct Tag {
10632    /// The tag key (can be qualified).
10633    pub key: ObjectName,
10634    /// The tag value as a string.
10635    pub value: String,
10636}
10637
10638impl Tag {
10639    /// Create a new `Tag` with the given key and value.
10640    pub fn new(key: ObjectName, value: String) -> Self {
10641        Self { key, value }
10642    }
10643}
10644
10645impl Display for Tag {
10646    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10647        write!(f, "{}='{}'", self.key, self.value)
10648    }
10649}
10650
10651/// Snowflake `WITH CONTACT ( purpose = contact [ , purpose = contact ...] )`
10652///
10653/// <https://docs.snowflake.com/en/sql-reference/sql/create-database>
10654#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10655#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10656#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10657pub struct ContactEntry {
10658    /// The purpose label for the contact entry.
10659    pub purpose: String,
10660    /// The contact information associated with the purpose.
10661    pub contact: String,
10662}
10663
10664impl Display for ContactEntry {
10665    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10666        write!(f, "{} = {}", self.purpose, self.contact)
10667    }
10668}
10669
10670/// Helper to indicate if a comment includes the `=` in the display form
10671#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10672#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10673#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10674pub enum CommentDef {
10675    /// Includes `=` when printing the comment, as `COMMENT = 'comment'`
10676    /// Does not include `=` when printing the comment, as `COMMENT 'comment'`
10677    WithEq(String),
10678    /// Comment variant that omits the `=` when displayed.
10679    WithoutEq(String),
10680}
10681
10682impl Display for CommentDef {
10683    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10684        match self {
10685            CommentDef::WithEq(comment) | CommentDef::WithoutEq(comment) => write!(f, "{comment}"),
10686        }
10687    }
10688}
10689
10690/// Helper to indicate if a collection should be wrapped by a symbol in the display form
10691///
10692/// [`Display`] is implemented for every [`Vec<T>`] where `T: Display`.
10693/// The string output is a comma separated list for the vec items
10694///
10695/// # Examples
10696/// ```
10697/// # use sqlparser::ast::WrappedCollection;
10698/// let items = WrappedCollection::Parentheses(vec!["one", "two", "three"]);
10699/// assert_eq!("(one, two, three)", items.to_string());
10700///
10701/// let items = WrappedCollection::NoWrapping(vec!["one", "two", "three"]);
10702/// assert_eq!("one, two, three", items.to_string());
10703/// ```
10704#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10705#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10706#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10707pub enum WrappedCollection<T> {
10708    /// Print the collection without wrapping symbols, as `item, item, item`
10709    NoWrapping(T),
10710    /// Wraps the collection in Parentheses, as `(item, item, item)`
10711    Parentheses(T),
10712}
10713
10714impl<T> Display for WrappedCollection<Vec<T>>
10715where
10716    T: Display,
10717{
10718    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10719        match self {
10720            WrappedCollection::NoWrapping(inner) => {
10721                write!(f, "{}", display_comma_separated(inner.as_slice()))
10722            }
10723            WrappedCollection::Parentheses(inner) => {
10724                write!(f, "({})", display_comma_separated(inner.as_slice()))
10725            }
10726        }
10727    }
10728}
10729
10730/// Represents a single PostgreSQL utility option.
10731///
10732/// A utility option is a key-value pair where the key is an identifier (IDENT) and the value
10733/// can be one of the following:
10734/// - A number with an optional sign (`+` or `-`). Example: `+10`, `-10.2`, `3`
10735/// - A non-keyword string. Example: `option1`, `'option2'`, `"option3"`
10736/// - keyword: `TRUE`, `FALSE`, `ON` (`off` is also accept).
10737/// - Empty. Example: `ANALYZE` (identifier only)
10738///
10739/// Utility options are used in various PostgreSQL DDL statements, including statements such as
10740/// `CLUSTER`, `EXPLAIN`, `VACUUM`, and `REINDEX`. These statements format options as `( option [, ...] )`.
10741///
10742/// [CLUSTER](https://www.postgresql.org/docs/current/sql-cluster.html)
10743/// [EXPLAIN](https://www.postgresql.org/docs/current/sql-explain.html)
10744/// [VACUUM](https://www.postgresql.org/docs/current/sql-vacuum.html)
10745/// [REINDEX](https://www.postgresql.org/docs/current/sql-reindex.html)
10746///
10747/// For example, the `EXPLAIN` AND `VACUUM` statements with options might look like this:
10748/// ```sql
10749/// EXPLAIN (ANALYZE, VERBOSE TRUE, FORMAT TEXT) SELECT * FROM my_table;
10750///
10751/// VACUUM (VERBOSE, ANALYZE ON, PARALLEL 10) my_table;
10752/// ```
10753#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10754#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10755#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10756pub struct UtilityOption {
10757    /// The option name (identifier).
10758    pub name: Ident,
10759    /// Optional argument for the option (number, string, keyword, etc.).
10760    pub arg: Option<Expr>,
10761}
10762
10763impl Display for UtilityOption {
10764    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10765        if let Some(ref arg) = self.arg {
10766            write!(f, "{} {}", self.name, arg)
10767        } else {
10768            write!(f, "{}", self.name)
10769        }
10770    }
10771}
10772
10773/// Represents the different options available for `SHOW`
10774/// statements to filter the results. Example from Snowflake:
10775/// <https://docs.snowflake.com/en/sql-reference/sql/show-tables>
10776#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10777#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10778#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10779pub struct ShowStatementOptions {
10780    /// Optional scope to show in (for example: TABLE, SCHEMA).
10781    pub show_in: Option<ShowStatementIn>,
10782    /// Optional `STARTS WITH` filter value.
10783    pub starts_with: Option<ValueWithSpan>,
10784    /// Optional `LIMIT` expression.
10785    pub limit: Option<Expr>,
10786    /// Optional `FROM` value used with `LIMIT`.
10787    pub limit_from: Option<ValueWithSpan>,
10788    /// Optional filter position (infix or suffix) for `LIKE`/`FILTER`.
10789    pub filter_position: Option<ShowStatementFilterPosition>,
10790}
10791
10792impl Display for ShowStatementOptions {
10793    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10794        let (like_in_infix, like_in_suffix) = match &self.filter_position {
10795            Some(ShowStatementFilterPosition::Infix(filter)) => {
10796                (format!(" {filter}"), "".to_string())
10797            }
10798            Some(ShowStatementFilterPosition::Suffix(filter)) => {
10799                ("".to_string(), format!(" {filter}"))
10800            }
10801            None => ("".to_string(), "".to_string()),
10802        };
10803        write!(
10804            f,
10805            "{like_in_infix}{show_in}{starts_with}{limit}{from}{like_in_suffix}",
10806            show_in = match &self.show_in {
10807                Some(i) => format!(" {i}"),
10808                None => String::new(),
10809            },
10810            starts_with = match &self.starts_with {
10811                Some(s) => format!(" STARTS WITH {s}"),
10812                None => String::new(),
10813            },
10814            limit = match &self.limit {
10815                Some(l) => format!(" LIMIT {l}"),
10816                None => String::new(),
10817            },
10818            from = match &self.limit_from {
10819                Some(f) => format!(" FROM {f}"),
10820                None => String::new(),
10821            }
10822        )?;
10823        Ok(())
10824    }
10825}
10826
10827#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10828#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10829#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10830/// Where a `SHOW` filter appears relative to the main clause.
10831pub enum ShowStatementFilterPosition {
10832    /// Put the filter in an infix position (e.g. `SHOW COLUMNS LIKE '%name%' IN TABLE tbl`).
10833    Infix(ShowStatementFilter), // For example: SHOW COLUMNS LIKE '%name%' IN TABLE tbl
10834    /// Put the filter in a suffix position (e.g. `SHOW COLUMNS IN tbl LIKE '%name%'`).
10835    Suffix(ShowStatementFilter), // For example: SHOW COLUMNS IN tbl LIKE '%name%'
10836}
10837
10838#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10839#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10840#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10841/// Parent object types usable with `SHOW ... IN <parent>` clauses.
10842pub enum ShowStatementInParentType {
10843    /// ACCOUNT parent type for SHOW statements.
10844    Account,
10845    /// DATABASE parent type for SHOW statements.
10846    Database,
10847    /// SCHEMA parent type for SHOW statements.
10848    Schema,
10849    /// TABLE parent type for SHOW statements.
10850    Table,
10851    /// VIEW parent type for SHOW statements.
10852    View,
10853}
10854
10855impl fmt::Display for ShowStatementInParentType {
10856    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10857        match self {
10858            ShowStatementInParentType::Account => write!(f, "ACCOUNT"),
10859            ShowStatementInParentType::Database => write!(f, "DATABASE"),
10860            ShowStatementInParentType::Schema => write!(f, "SCHEMA"),
10861            ShowStatementInParentType::Table => write!(f, "TABLE"),
10862            ShowStatementInParentType::View => write!(f, "VIEW"),
10863        }
10864    }
10865}
10866
10867#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10868#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10869#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10870/// Represents a `SHOW ... IN` clause with optional parent qualifier and name.
10871pub struct ShowStatementIn {
10872    /// The clause that specifies what to show (e.g. COLUMNS, TABLES).
10873    pub clause: ShowStatementInClause,
10874    /// Optional parent type qualifier (ACCOUNT/DATABASE/...).
10875    pub parent_type: Option<ShowStatementInParentType>,
10876    /// Optional parent object name for the SHOW clause.
10877    #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
10878    pub parent_name: Option<ObjectName>,
10879}
10880
10881impl fmt::Display for ShowStatementIn {
10882    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10883        write!(f, "{}", self.clause)?;
10884        if let Some(parent_type) = &self.parent_type {
10885            write!(f, " {parent_type}")?;
10886        }
10887        if let Some(parent_name) = &self.parent_name {
10888            write!(f, " {parent_name}")?;
10889        }
10890        Ok(())
10891    }
10892}
10893
10894/// A Show Charset statement
10895#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10896#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10897#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10898pub struct ShowCharset {
10899    /// The statement can be written as `SHOW CHARSET` or `SHOW CHARACTER SET`
10900    /// true means CHARSET was used and false means CHARACTER SET was used
10901    pub is_shorthand: bool,
10902    /// Optional `LIKE`/`WHERE`-style filter for the statement.
10903    pub filter: Option<ShowStatementFilter>,
10904}
10905
10906impl fmt::Display for ShowCharset {
10907    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10908        write!(f, "SHOW")?;
10909        if self.is_shorthand {
10910            write!(f, " CHARSET")?;
10911        } else {
10912            write!(f, " CHARACTER SET")?;
10913        }
10914        if let Some(filter) = &self.filter {
10915            write!(f, " {filter}")?;
10916        }
10917        Ok(())
10918    }
10919}
10920
10921#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10922#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10923#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10924/// Options for a `SHOW OBJECTS` statement.
10925pub struct ShowObjects {
10926    /// Whether to show terse output.
10927    pub terse: bool,
10928    /// Additional options controlling the SHOW output.
10929    pub show_options: ShowStatementOptions,
10930}
10931
10932/// MSSQL's json null clause
10933///
10934/// ```plaintext
10935/// <json_null_clause> ::=
10936///       NULL ON NULL
10937///     | ABSENT ON NULL
10938/// ```
10939///
10940/// <https://learn.microsoft.com/en-us/sql/t-sql/functions/json-object-transact-sql?view=sql-server-ver16#json_null_clause>
10941#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10942#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10943#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10944pub enum JsonNullClause {
10945    /// `NULL ON NULL` behavior for JSON functions.
10946    NullOnNull,
10947    /// `ABSENT ON NULL` behavior for JSON functions.
10948    AbsentOnNull,
10949}
10950
10951impl Display for JsonNullClause {
10952    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10953        match self {
10954            JsonNullClause::NullOnNull => write!(f, "NULL ON NULL"),
10955            JsonNullClause::AbsentOnNull => write!(f, "ABSENT ON NULL"),
10956        }
10957    }
10958}
10959
10960/// PostgreSQL JSON function RETURNING clause
10961///
10962/// Example:
10963/// ```sql
10964/// JSON_OBJECT('a': 1 RETURNING jsonb)
10965/// ```
10966#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10967#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10968#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10969pub struct JsonReturningClause {
10970    /// The data type to return from the JSON function (e.g. JSON/JSONB).
10971    pub data_type: DataType,
10972}
10973
10974impl Display for JsonReturningClause {
10975    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10976        write!(f, "RETURNING {}", self.data_type)
10977    }
10978}
10979
10980/// rename object definition
10981#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10982#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10983#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10984pub struct RenameTable {
10985    /// The current name of the object to rename.
10986    pub old_name: ObjectName,
10987    /// The new name for the object.
10988    pub new_name: ObjectName,
10989}
10990
10991impl fmt::Display for RenameTable {
10992    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10993        write!(f, "{} TO {}", self.old_name, self.new_name)?;
10994        Ok(())
10995    }
10996}
10997
10998/// Represents the referenced table in an `INSERT INTO` statement
10999#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11000#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11001#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11002pub enum TableObject {
11003    /// Table specified by name.
11004    /// Example:
11005    /// ```sql
11006    /// INSERT INTO my_table
11007    /// ```
11008    TableName(#[cfg_attr(feature = "visitor", visit(with = "visit_relation"))] ObjectName),
11009
11010    /// Table specified as a function.
11011    /// Example:
11012    /// ```sql
11013    /// INSERT INTO TABLE FUNCTION remote('localhost', default.simple_table)
11014    /// ```
11015    /// [Clickhouse](https://clickhouse.com/docs/en/sql-reference/table-functions)
11016    TableFunction(Function),
11017
11018    /// Table specified through a sub-query
11019    /// Example:
11020    /// ```sql
11021    /// INSERT INTO
11022    /// (SELECT employee_id, last_name, email, hire_date, job_id,  salary, commission_pct FROM employees)
11023    /// VALUES (207, 'Gregory', 'pgregory@example.com', sysdate, 'PU_CLERK', 1.2E3, NULL);
11024    /// ```
11025    /// [Oracle](https://docs.oracle.com/en/database/oracle/oracle-database/21/sqlrf/INSERT.html#GUID-903F8043-0254-4EE9-ACC1-CB8AC0AF3423__I2126242)
11026    TableQuery(Box<Query>),
11027}
11028
11029impl fmt::Display for TableObject {
11030    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11031        match self {
11032            Self::TableName(table_name) => write!(f, "{table_name}"),
11033            Self::TableFunction(func) => write!(f, "FUNCTION {func}"),
11034            Self::TableQuery(table_query) => write!(f, "({table_query})"),
11035        }
11036    }
11037}
11038
11039/// Represents a SET SESSION AUTHORIZATION statement
11040#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11041#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11042#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11043pub struct SetSessionAuthorizationParam {
11044    /// The scope for the `SET SESSION AUTHORIZATION` (e.g., GLOBAL/SESSION).
11045    pub scope: ContextModifier,
11046    /// The specific authorization parameter kind.
11047    pub kind: SetSessionAuthorizationParamKind,
11048}
11049
11050impl fmt::Display for SetSessionAuthorizationParam {
11051    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11052        write!(f, "{}", self.kind)
11053    }
11054}
11055
11056/// Represents the parameter kind for SET SESSION AUTHORIZATION
11057#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11058#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11059#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11060pub enum SetSessionAuthorizationParamKind {
11061    /// Default authorization
11062    Default,
11063
11064    /// User name
11065    User(Ident),
11066}
11067
11068impl fmt::Display for SetSessionAuthorizationParamKind {
11069    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11070        match self {
11071            SetSessionAuthorizationParamKind::Default => write!(f, "DEFAULT"),
11072            SetSessionAuthorizationParamKind::User(name) => write!(f, "{}", name),
11073        }
11074    }
11075}
11076
11077#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11078#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11079#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11080/// Kind of session parameter being set by `SET SESSION`.
11081pub enum SetSessionParamKind {
11082    /// Generic session parameter (name/value pair).
11083    Generic(SetSessionParamGeneric),
11084    /// Identity insert related parameter.
11085    IdentityInsert(SetSessionParamIdentityInsert),
11086    /// Offsets-related parameter.
11087    Offsets(SetSessionParamOffsets),
11088    /// Statistics-related parameter.
11089    Statistics(SetSessionParamStatistics),
11090}
11091
11092impl fmt::Display for SetSessionParamKind {
11093    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11094        match self {
11095            SetSessionParamKind::Generic(x) => write!(f, "{x}"),
11096            SetSessionParamKind::IdentityInsert(x) => write!(f, "{x}"),
11097            SetSessionParamKind::Offsets(x) => write!(f, "{x}"),
11098            SetSessionParamKind::Statistics(x) => write!(f, "{x}"),
11099        }
11100    }
11101}
11102
11103#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11104#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11105#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11106/// Generic `SET SESSION` parameter represented as name(s) and value.
11107pub struct SetSessionParamGeneric {
11108    /// Names of the session parameters being set.
11109    pub names: Vec<String>,
11110    /// The value to assign to the parameter(s).
11111    pub value: String,
11112}
11113
11114impl fmt::Display for SetSessionParamGeneric {
11115    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11116        write!(f, "{} {}", display_comma_separated(&self.names), self.value)
11117    }
11118}
11119
11120#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11121#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11122#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11123/// `IDENTITY_INSERT` session parameter for a specific object.
11124pub struct SetSessionParamIdentityInsert {
11125    /// Object name targeted by `IDENTITY_INSERT`.
11126    pub obj: ObjectName,
11127    /// Value (ON/OFF) for the identity insert setting.
11128    pub value: SessionParamValue,
11129}
11130
11131impl fmt::Display for SetSessionParamIdentityInsert {
11132    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11133        write!(f, "IDENTITY_INSERT {} {}", self.obj, self.value)
11134    }
11135}
11136
11137#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11138#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11139#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11140/// Offsets-related session parameter with keywords and a value.
11141pub struct SetSessionParamOffsets {
11142    /// Keywords specifying which offsets to modify.
11143    pub keywords: Vec<String>,
11144    /// Value (ON/OFF) for the offsets setting.
11145    pub value: SessionParamValue,
11146}
11147
11148impl fmt::Display for SetSessionParamOffsets {
11149    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11150        write!(
11151            f,
11152            "OFFSETS {} {}",
11153            display_comma_separated(&self.keywords),
11154            self.value
11155        )
11156    }
11157}
11158
11159#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11160#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11161#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11162/// Statistics-related session parameter specifying topic and value.
11163pub struct SetSessionParamStatistics {
11164    /// Statistics topic to set (IO/PROFILE/TIME/XML).
11165    pub topic: SessionParamStatsTopic,
11166    /// Value (ON/OFF) for the statistics topic.
11167    pub value: SessionParamValue,
11168}
11169
11170impl fmt::Display for SetSessionParamStatistics {
11171    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11172        write!(f, "STATISTICS {} {}", self.topic, self.value)
11173    }
11174}
11175
11176#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11177#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11178#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11179/// Topics available for session statistics configuration.
11180pub enum SessionParamStatsTopic {
11181    /// Input/output statistics.
11182    IO,
11183    /// Profile statistics.
11184    Profile,
11185    /// Time statistics.
11186    Time,
11187    /// XML-related statistics.
11188    Xml,
11189}
11190
11191impl fmt::Display for SessionParamStatsTopic {
11192    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11193        match self {
11194            SessionParamStatsTopic::IO => write!(f, "IO"),
11195            SessionParamStatsTopic::Profile => write!(f, "PROFILE"),
11196            SessionParamStatsTopic::Time => write!(f, "TIME"),
11197            SessionParamStatsTopic::Xml => write!(f, "XML"),
11198        }
11199    }
11200}
11201
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))]
11205/// Value for a session boolean-like parameter (ON/OFF).
11206pub enum SessionParamValue {
11207    /// Session parameter enabled.
11208    On,
11209    /// Session parameter disabled.
11210    Off,
11211}
11212
11213impl fmt::Display for SessionParamValue {
11214    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11215        match self {
11216            SessionParamValue::On => write!(f, "ON"),
11217            SessionParamValue::Off => write!(f, "OFF"),
11218        }
11219    }
11220}
11221
11222/// Snowflake StorageSerializationPolicy for Iceberg Tables
11223/// ```sql
11224/// [ STORAGE_SERIALIZATION_POLICY = { COMPATIBLE | OPTIMIZED } ]
11225/// ```
11226///
11227/// <https://docs.snowflake.com/en/sql-reference/sql/create-iceberg-table>
11228#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11229#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11230#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11231pub enum StorageSerializationPolicy {
11232    /// Use compatible serialization mode.
11233    Compatible,
11234    /// Use optimized serialization mode.
11235    Optimized,
11236}
11237
11238impl Display for StorageSerializationPolicy {
11239    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
11240        match self {
11241            StorageSerializationPolicy::Compatible => write!(f, "COMPATIBLE"),
11242            StorageSerializationPolicy::Optimized => write!(f, "OPTIMIZED"),
11243        }
11244    }
11245}
11246
11247/// Snowflake CatalogSyncNamespaceMode
11248/// ```sql
11249/// [ CATALOG_SYNC_NAMESPACE_MODE = { NEST | FLATTEN } ]
11250/// ```
11251///
11252/// <https://docs.snowflake.com/en/sql-reference/sql/create-database>
11253#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11254#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11255#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11256pub enum CatalogSyncNamespaceMode {
11257    /// Nest namespaces when syncing catalog.
11258    Nest,
11259    /// Flatten namespaces when syncing catalog.
11260    Flatten,
11261}
11262
11263impl Display for CatalogSyncNamespaceMode {
11264    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
11265        match self {
11266            CatalogSyncNamespaceMode::Nest => write!(f, "NEST"),
11267            CatalogSyncNamespaceMode::Flatten => write!(f, "FLATTEN"),
11268        }
11269    }
11270}
11271
11272/// Variants of the Snowflake `COPY INTO` statement
11273#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11274#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11275#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11276pub enum CopyIntoSnowflakeKind {
11277    /// Loads data from files to a table
11278    /// See: <https://docs.snowflake.com/en/sql-reference/sql/copy-into-table>
11279    Table,
11280    /// Unloads data from a table or query to external files
11281    /// See: <https://docs.snowflake.com/en/sql-reference/sql/copy-into-location>
11282    Location,
11283}
11284
11285#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11286#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11287#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11288/// `PRINT` statement for producing debug/output messages.
11289pub struct PrintStatement {
11290    /// The expression producing the message to print.
11291    pub message: Box<Expr>,
11292}
11293
11294impl fmt::Display for PrintStatement {
11295    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11296        write!(f, "PRINT {}", self.message)
11297    }
11298}
11299
11300/// The type of `WAITFOR` statement (MSSQL).
11301///
11302/// See: <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/waitfor-transact-sql>
11303#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11304#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11305#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11306pub enum WaitForType {
11307    /// `WAITFOR DELAY 'time_to_pass'`
11308    Delay,
11309    /// `WAITFOR TIME 'time_to_execute'`
11310    Time,
11311}
11312
11313impl fmt::Display for WaitForType {
11314    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11315        match self {
11316            WaitForType::Delay => write!(f, "DELAY"),
11317            WaitForType::Time => write!(f, "TIME"),
11318        }
11319    }
11320}
11321
11322/// MSSQL `WAITFOR` statement.
11323///
11324/// See: <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/waitfor-transact-sql>
11325#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11326#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11327#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11328pub struct WaitForStatement {
11329    /// `DELAY` or `TIME`.
11330    pub wait_type: WaitForType,
11331    /// The time expression.
11332    pub expr: Expr,
11333}
11334
11335impl fmt::Display for WaitForStatement {
11336    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11337        write!(f, "WAITFOR {} {}", self.wait_type, self.expr)
11338    }
11339}
11340
11341/// Represents a `Return` statement.
11342///
11343/// [MsSql triggers](https://learn.microsoft.com/en-us/sql/t-sql/statements/create-trigger-transact-sql)
11344/// [MsSql functions](https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql)
11345#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11346#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11347#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11348pub struct ReturnStatement {
11349    /// Optional return value expression.
11350    pub value: Option<ReturnStatementValue>,
11351}
11352
11353impl fmt::Display for ReturnStatement {
11354    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11355        match &self.value {
11356            Some(ReturnStatementValue::Expr(expr)) => write!(f, "RETURN {expr}"),
11357            None => write!(f, "RETURN"),
11358        }
11359    }
11360}
11361
11362/// Variants of a `RETURN` statement
11363#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11364#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11365#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11366pub enum ReturnStatementValue {
11367    /// Return an expression from a function or trigger.
11368    Expr(Expr),
11369}
11370
11371/// Represents an `OPEN` statement.
11372#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11373#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11374#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11375pub struct OpenStatement {
11376    /// Cursor name
11377    pub cursor_name: Ident,
11378}
11379
11380impl fmt::Display for OpenStatement {
11381    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11382        write!(f, "OPEN {}", self.cursor_name)
11383    }
11384}
11385
11386/// Specifies Include / Exclude NULL within UNPIVOT command.
11387/// For example
11388/// `UNPIVOT (column1 FOR new_column IN (col3, col4, col5, col6))`
11389#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11390#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11391#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11392pub enum NullInclusion {
11393    /// Include NULL values in the UNPIVOT output.
11394    IncludeNulls,
11395    /// Exclude NULL values from the UNPIVOT output.
11396    ExcludeNulls,
11397}
11398
11399impl fmt::Display for NullInclusion {
11400    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11401        match self {
11402            NullInclusion::IncludeNulls => write!(f, "INCLUDE NULLS"),
11403            NullInclusion::ExcludeNulls => write!(f, "EXCLUDE NULLS"),
11404        }
11405    }
11406}
11407
11408/// Checks membership of a value in a JSON array
11409///
11410/// Syntax:
11411/// ```sql
11412/// <value> MEMBER OF(<array>)
11413/// ```
11414/// [MySQL](https://dev.mysql.com/doc/refman/8.4/en/json-search-functions.html#operator_member-of)
11415#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11416#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11417#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11418pub struct MemberOf {
11419    /// The value to check for membership.
11420    pub value: Box<Expr>,
11421    /// The JSON array expression to check against.
11422    pub array: Box<Expr>,
11423}
11424
11425impl fmt::Display for MemberOf {
11426    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11427        write!(f, "{} MEMBER OF({})", self.value, self.array)
11428    }
11429}
11430
11431#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11432#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11433#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11434/// Represents an `EXPORT DATA` statement.
11435pub struct ExportData {
11436    /// Options for the export operation.
11437    pub options: Vec<SqlOption>,
11438    /// The query producing the data to export.
11439    pub query: Box<Query>,
11440    /// Optional named connection to use for export.
11441    pub connection: Option<ObjectName>,
11442}
11443
11444impl fmt::Display for ExportData {
11445    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11446        if let Some(connection) = &self.connection {
11447            write!(
11448                f,
11449                "EXPORT DATA WITH CONNECTION {connection} OPTIONS({}) AS {}",
11450                display_comma_separated(&self.options),
11451                self.query
11452            )
11453        } else {
11454            write!(
11455                f,
11456                "EXPORT DATA OPTIONS({}) AS {}",
11457                display_comma_separated(&self.options),
11458                self.query
11459            )
11460        }
11461    }
11462}
11463/// Creates a user
11464///
11465/// Syntax:
11466/// ```sql
11467/// CREATE [OR REPLACE] USER [IF NOT EXISTS] <name> [OPTIONS]
11468/// ```
11469///
11470/// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-user)
11471#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11472#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11473#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11474pub struct CreateUser {
11475    /// Replace existing user if present.
11476    pub or_replace: bool,
11477    /// Only create the user if it does not already exist.
11478    pub if_not_exists: bool,
11479    /// The name of the user to create.
11480    pub name: Ident,
11481    /// Key/value options for user creation.
11482    pub options: KeyValueOptions,
11483    /// Whether tags are specified using `WITH TAG`.
11484    pub with_tags: bool,
11485    /// Tags for the user.
11486    pub tags: KeyValueOptions,
11487}
11488
11489impl fmt::Display for CreateUser {
11490    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11491        write!(f, "CREATE")?;
11492        if self.or_replace {
11493            write!(f, " OR REPLACE")?;
11494        }
11495        write!(f, " USER")?;
11496        if self.if_not_exists {
11497            write!(f, " IF NOT EXISTS")?;
11498        }
11499        write!(f, " {}", self.name)?;
11500        if !self.options.options.is_empty() {
11501            write!(f, " {}", self.options)?;
11502        }
11503        if !self.tags.options.is_empty() {
11504            if self.with_tags {
11505                write!(f, " WITH")?;
11506            }
11507            write!(f, " TAG ({})", self.tags)?;
11508        }
11509        Ok(())
11510    }
11511}
11512
11513/// Modifies the properties of a user
11514///
11515/// [Snowflake Syntax:](https://docs.snowflake.com/en/sql-reference/sql/alter-user)
11516/// ```sql
11517/// ALTER USER [ IF EXISTS ] [ <name> ] [ OPTIONS ]
11518/// ```
11519///
11520/// [PostgreSQL Syntax:](https://www.postgresql.org/docs/current/sql-alteruser.html)
11521/// ```sql
11522/// ALTER USER <role_specification> [ WITH ] option [ ... ]
11523/// ```
11524#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11525#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11526#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11527pub struct AlterUser {
11528    /// Whether to only alter the user if it exists.
11529    pub if_exists: bool,
11530    /// The name of the user to alter.
11531    pub name: Ident,
11532    /// Optional new name for the user (Snowflake-specific).
11533    /// See: <https://docs.snowflake.com/en/sql-reference/sql/alter-user#syntax>
11534    pub rename_to: Option<Ident>,
11535    /// Reset the user's password.
11536    pub reset_password: bool,
11537    /// Abort all running queries for the user.
11538    pub abort_all_queries: bool,
11539    /// Optionally add a delegated role authorization.
11540    pub add_role_delegation: Option<AlterUserAddRoleDelegation>,
11541    /// Optionally remove a delegated role authorization.
11542    pub remove_role_delegation: Option<AlterUserRemoveRoleDelegation>,
11543    /// Enroll the user in MFA.
11544    pub enroll_mfa: bool,
11545    /// Set the default MFA method for the user.
11546    pub set_default_mfa_method: Option<MfaMethodKind>,
11547    /// Remove the user's default MFA method.
11548    pub remove_mfa_method: Option<MfaMethodKind>,
11549    /// Modify an MFA method for the user.
11550    pub modify_mfa_method: Option<AlterUserModifyMfaMethod>,
11551    /// Add an MFA OTP method with optional count.
11552    pub add_mfa_method_otp: Option<AlterUserAddMfaMethodOtp>,
11553    /// Set a user policy.
11554    pub set_policy: Option<AlterUserSetPolicy>,
11555    /// Unset a user policy.
11556    pub unset_policy: Option<UserPolicyKind>,
11557    /// Key/value tag options to set on the user.
11558    pub set_tag: KeyValueOptions,
11559    /// Tags to unset on the user.
11560    pub unset_tag: Vec<String>,
11561    /// Key/value properties to set on the user.
11562    pub set_props: KeyValueOptions,
11563    /// Properties to unset on the user.
11564    pub unset_props: Vec<String>,
11565    /// The following options are PostgreSQL-specific: <https://www.postgresql.org/docs/current/sql-alteruser.html>
11566    pub password: Option<AlterUserPassword>,
11567}
11568
11569/// ```sql
11570/// ALTER USER [ IF EXISTS ] [ <name> ] ADD DELEGATED AUTHORIZATION OF ROLE <role_name> TO SECURITY INTEGRATION <integration_name>
11571/// ```
11572#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11573#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11574#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11575pub struct AlterUserAddRoleDelegation {
11576    /// Role name to delegate.
11577    pub role: Ident,
11578    /// Security integration receiving the delegation.
11579    pub integration: Ident,
11580}
11581
11582/// ```sql
11583/// ALTER USER [ IF EXISTS ] [ <name> ] REMOVE DELEGATED { AUTHORIZATION OF ROLE <role_name> | AUTHORIZATIONS } FROM SECURITY INTEGRATION <integration_name>
11584/// ```
11585#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11586#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11587#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11588pub struct AlterUserRemoveRoleDelegation {
11589    /// Optional role name to remove delegation for.
11590    pub role: Option<Ident>,
11591    /// Security integration from which to remove delegation.
11592    pub integration: Ident,
11593}
11594
11595/// ```sql
11596/// ADD MFA METHOD OTP [ COUNT = number ]
11597/// ```
11598#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11599#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11600#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11601pub struct AlterUserAddMfaMethodOtp {
11602    /// Optional OTP count parameter.
11603    pub count: Option<ValueWithSpan>,
11604}
11605
11606/// ```sql
11607/// ALTER USER [ IF EXISTS ] [ <name> ] MODIFY MFA METHOD <mfa_method> SET COMMENT = '<string>'
11608/// ```
11609#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11610#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11611#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11612pub struct AlterUserModifyMfaMethod {
11613    /// The MFA method being modified.
11614    pub method: MfaMethodKind,
11615    /// The new comment for the MFA method.
11616    pub comment: String,
11617}
11618
11619/// Types of MFA methods
11620#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11621#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11622#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11623pub enum MfaMethodKind {
11624    /// PassKey (hardware or platform passkey) MFA method.
11625    PassKey,
11626    /// Time-based One-Time Password (TOTP) MFA method.
11627    Totp,
11628    /// Duo Security MFA method.
11629    Duo,
11630}
11631
11632impl fmt::Display for MfaMethodKind {
11633    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11634        match self {
11635            MfaMethodKind::PassKey => write!(f, "PASSKEY"),
11636            MfaMethodKind::Totp => write!(f, "TOTP"),
11637            MfaMethodKind::Duo => write!(f, "DUO"),
11638        }
11639    }
11640}
11641
11642/// ```sql
11643/// ALTER USER [ IF EXISTS ] [ <name> ] SET { AUTHENTICATION | PASSWORD | SESSION } POLICY <policy_name>
11644/// ```
11645#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11646#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11647#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11648pub struct AlterUserSetPolicy {
11649    /// The kind of user policy being set (authentication/password/session).
11650    pub policy_kind: UserPolicyKind,
11651    /// The identifier of the policy to apply.
11652    pub policy: Ident,
11653}
11654
11655/// Types of user-based policies
11656#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11657#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11658#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11659pub enum UserPolicyKind {
11660    /// Authentication policy.
11661    Authentication,
11662    /// Password policy.
11663    Password,
11664    /// Session policy.
11665    Session,
11666}
11667
11668impl fmt::Display for UserPolicyKind {
11669    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11670        match self {
11671            UserPolicyKind::Authentication => write!(f, "AUTHENTICATION"),
11672            UserPolicyKind::Password => write!(f, "PASSWORD"),
11673            UserPolicyKind::Session => write!(f, "SESSION"),
11674        }
11675    }
11676}
11677
11678impl fmt::Display for AlterUser {
11679    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11680        write!(f, "ALTER")?;
11681        write!(f, " USER")?;
11682        if self.if_exists {
11683            write!(f, " IF EXISTS")?;
11684        }
11685        write!(f, " {}", self.name)?;
11686        if let Some(new_name) = &self.rename_to {
11687            write!(f, " RENAME TO {new_name}")?;
11688        }
11689        if self.reset_password {
11690            write!(f, " RESET PASSWORD")?;
11691        }
11692        if self.abort_all_queries {
11693            write!(f, " ABORT ALL QUERIES")?;
11694        }
11695        if let Some(role_delegation) = &self.add_role_delegation {
11696            let role = &role_delegation.role;
11697            let integration = &role_delegation.integration;
11698            write!(
11699                f,
11700                " ADD DELEGATED AUTHORIZATION OF ROLE {role} TO SECURITY INTEGRATION {integration}"
11701            )?;
11702        }
11703        if let Some(role_delegation) = &self.remove_role_delegation {
11704            write!(f, " REMOVE DELEGATED")?;
11705            match &role_delegation.role {
11706                Some(role) => write!(f, " AUTHORIZATION OF ROLE {role}")?,
11707                None => write!(f, " AUTHORIZATIONS")?,
11708            }
11709            let integration = &role_delegation.integration;
11710            write!(f, " FROM SECURITY INTEGRATION {integration}")?;
11711        }
11712        if self.enroll_mfa {
11713            write!(f, " ENROLL MFA")?;
11714        }
11715        if let Some(method) = &self.set_default_mfa_method {
11716            write!(f, " SET DEFAULT_MFA_METHOD {method}")?
11717        }
11718        if let Some(method) = &self.remove_mfa_method {
11719            write!(f, " REMOVE MFA METHOD {method}")?;
11720        }
11721        if let Some(modify) = &self.modify_mfa_method {
11722            let method = &modify.method;
11723            let comment = &modify.comment;
11724            write!(
11725                f,
11726                " MODIFY MFA METHOD {method} SET COMMENT '{}'",
11727                value::escape_single_quote_string(comment)
11728            )?;
11729        }
11730        if let Some(add_mfa_method_otp) = &self.add_mfa_method_otp {
11731            write!(f, " ADD MFA METHOD OTP")?;
11732            if let Some(count) = &add_mfa_method_otp.count {
11733                write!(f, " COUNT = {count}")?;
11734            }
11735        }
11736        if let Some(policy) = &self.set_policy {
11737            let policy_kind = &policy.policy_kind;
11738            let name = &policy.policy;
11739            write!(f, " SET {policy_kind} POLICY {name}")?;
11740        }
11741        if let Some(policy_kind) = &self.unset_policy {
11742            write!(f, " UNSET {policy_kind} POLICY")?;
11743        }
11744        if !self.set_tag.options.is_empty() {
11745            write!(f, " SET TAG {}", self.set_tag)?;
11746        }
11747        if !self.unset_tag.is_empty() {
11748            write!(f, " UNSET TAG {}", display_comma_separated(&self.unset_tag))?;
11749        }
11750        let has_props = !self.set_props.options.is_empty();
11751        if has_props {
11752            write!(f, " SET")?;
11753            write!(f, " {}", &self.set_props)?;
11754        }
11755        if !self.unset_props.is_empty() {
11756            write!(f, " UNSET {}", display_comma_separated(&self.unset_props))?;
11757        }
11758        if let Some(password) = &self.password {
11759            write!(f, " {}", password)?;
11760        }
11761        Ok(())
11762    }
11763}
11764
11765/// ```sql
11766/// ALTER USER <role_specification> [ WITH ] PASSWORD { 'password' | NULL }``
11767/// ```
11768#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11769#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11770#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11771pub struct AlterUserPassword {
11772    /// Whether the password is encrypted.
11773    pub encrypted: bool,
11774    /// The password string, or `None` for `NULL`.
11775    pub password: Option<String>,
11776}
11777
11778impl Display for AlterUserPassword {
11779    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11780        if self.encrypted {
11781            write!(f, "ENCRYPTED ")?;
11782        }
11783        write!(f, "PASSWORD")?;
11784        match &self.password {
11785            None => write!(f, " NULL")?,
11786            Some(password) => write!(f, " '{}'", value::escape_single_quote_string(password))?,
11787        }
11788        Ok(())
11789    }
11790}
11791
11792/// Specifies how to create a new table based on an existing table's schema.
11793/// '''sql
11794/// CREATE TABLE new LIKE old ...
11795/// '''
11796#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11797#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11798#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11799pub enum CreateTableLikeKind {
11800    /// '''sql
11801    /// CREATE TABLE new (LIKE old ...)
11802    /// '''
11803    /// [Redshift](https://docs.aws.amazon.com/redshift/latest/dg/r_CREATE_TABLE_NEW.html)
11804    Parenthesized(CreateTableLike),
11805    /// '''sql
11806    /// CREATE TABLE new LIKE old ...
11807    /// '''
11808    /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-table#label-create-table-like)
11809    /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_table_like)
11810    Plain(CreateTableLike),
11811}
11812
11813#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11814#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11815#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11816/// Controls whether defaults are included when creating a table FROM/LILE another.
11817pub enum CreateTableLikeDefaults {
11818    /// Include default values from the source table.
11819    Including,
11820    /// Exclude default values from the source table.
11821    Excluding,
11822}
11823
11824impl fmt::Display for CreateTableLikeDefaults {
11825    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11826        match self {
11827            CreateTableLikeDefaults::Including => write!(f, "INCLUDING DEFAULTS"),
11828            CreateTableLikeDefaults::Excluding => write!(f, "EXCLUDING DEFAULTS"),
11829        }
11830    }
11831}
11832
11833#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11834#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11835#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11836/// Represents the `LIKE` clause of a `CREATE TABLE` statement.
11837pub struct CreateTableLike {
11838    /// The source table name to copy the schema from.
11839    pub name: ObjectName,
11840    /// Optional behavior controlling whether defaults are copied.
11841    pub defaults: Option<CreateTableLikeDefaults>,
11842}
11843
11844impl fmt::Display for CreateTableLike {
11845    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11846        write!(f, "LIKE {}", self.name)?;
11847        if let Some(defaults) = &self.defaults {
11848            write!(f, " {defaults}")?;
11849        }
11850        Ok(())
11851    }
11852}
11853
11854/// Specifies the refresh mode for the dynamic table.
11855///
11856/// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-dynamic-table)
11857#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11858#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11859#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11860pub enum RefreshModeKind {
11861    /// Automatic refresh mode (`AUTO`).
11862    Auto,
11863    /// Full refresh mode (`FULL`).
11864    Full,
11865    /// Incremental refresh mode (`INCREMENTAL`).
11866    Incremental,
11867}
11868
11869impl fmt::Display for RefreshModeKind {
11870    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11871        match self {
11872            RefreshModeKind::Auto => write!(f, "AUTO"),
11873            RefreshModeKind::Full => write!(f, "FULL"),
11874            RefreshModeKind::Incremental => write!(f, "INCREMENTAL"),
11875        }
11876    }
11877}
11878
11879/// Specifies the behavior of the initial refresh of the dynamic table.
11880///
11881/// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-dynamic-table)
11882#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11883#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11884#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11885pub enum InitializeKind {
11886    /// Initialize on creation (`ON CREATE`).
11887    OnCreate,
11888    /// Initialize on schedule (`ON SCHEDULE`).
11889    OnSchedule,
11890}
11891
11892impl fmt::Display for InitializeKind {
11893    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11894        match self {
11895            InitializeKind::OnCreate => write!(f, "ON_CREATE"),
11896            InitializeKind::OnSchedule => write!(f, "ON_SCHEDULE"),
11897        }
11898    }
11899}
11900
11901/// Re-sorts rows and reclaims space in either a specified table or all tables in the current database
11902///
11903/// '''sql
11904/// VACUUM [ FULL | SORT ONLY | DELETE ONLY | REINDEX | RECLUSTER ] [ \[ table_name \] [ TO threshold PERCENT ] \[ BOOST \] ]
11905/// '''
11906/// [Redshift](https://docs.aws.amazon.com/redshift/latest/dg/r_VACUUM_command.html)
11907#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11908#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11909#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11910pub struct VacuumStatement {
11911    /// Whether `FULL` was specified.
11912    pub full: bool,
11913    /// Whether `SORT ONLY` was specified.
11914    pub sort_only: bool,
11915    /// Whether `DELETE ONLY` was specified.
11916    pub delete_only: bool,
11917    /// Whether `REINDEX` was specified.
11918    pub reindex: bool,
11919    /// Whether `RECLUSTER` was specified.
11920    pub recluster: bool,
11921    /// Optional table to run `VACUUM` on.
11922    pub table_name: Option<ObjectName>,
11923    /// Optional threshold value (percent) for `TO threshold PERCENT`.
11924    pub threshold: Option<ValueWithSpan>,
11925    /// Whether `BOOST` was specified.
11926    pub boost: bool,
11927}
11928
11929impl fmt::Display for VacuumStatement {
11930    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11931        write!(
11932            f,
11933            "VACUUM{}{}{}{}{}",
11934            if self.full { " FULL" } else { "" },
11935            if self.sort_only { " SORT ONLY" } else { "" },
11936            if self.delete_only { " DELETE ONLY" } else { "" },
11937            if self.reindex { " REINDEX" } else { "" },
11938            if self.recluster { " RECLUSTER" } else { "" },
11939        )?;
11940        if let Some(table_name) = &self.table_name {
11941            write!(f, " {table_name}")?;
11942        }
11943        if let Some(threshold) = &self.threshold {
11944            write!(f, " TO {threshold} PERCENT")?;
11945        }
11946        if self.boost {
11947            write!(f, " BOOST")?;
11948        }
11949        Ok(())
11950    }
11951}
11952
11953/// Variants of the RESET statement
11954#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11955#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11956#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11957pub enum Reset {
11958    /// Resets all session parameters to their default values.
11959    ALL,
11960
11961    /// Resets a specific session parameter to its default value.
11962    ConfigurationParameter(ObjectName),
11963}
11964
11965/// Resets a session parameter to its default value.
11966/// ```sql
11967/// RESET { ALL | <configuration_parameter> }
11968/// ```
11969#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11970#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11971#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11972pub struct ResetStatement {
11973    /// The reset action to perform (either `ALL` or a specific configuration parameter).
11974    pub reset: Reset,
11975}
11976
11977/// Query optimizer hints are optionally supported comments after the
11978/// `SELECT`, `INSERT`, `UPDATE`, `REPLACE`, `MERGE`, and `DELETE` keywords in
11979/// the corresponding statements.
11980///
11981/// See [Select::optimizer_hints]
11982#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11983#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11984#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11985pub struct OptimizerHint {
11986    /// An optional prefix between the comment marker and `+`.
11987    ///
11988    /// Standard optimizer hints like `/*+ ... */` have an empty prefix,
11989    /// while system-specific hints like `/*abc+ ... */` have `prefix = "abc"`.
11990    /// The prefix is any sequence of ASCII alphanumeric characters
11991    /// immediately before the `+` marker.
11992    pub prefix: String,
11993    /// the raw text of the optimizer hint without its markers
11994    pub text: String,
11995    /// the style of the comment which `text` was extracted from,
11996    /// e.g. `/*+...*/` or `--+...`
11997    ///
11998    /// Not all dialects support all styles, though.
11999    pub style: OptimizerHintStyle,
12000}
12001
12002/// The commentary style of an [optimizer hint](OptimizerHint)
12003#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
12004#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
12005#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
12006pub enum OptimizerHintStyle {
12007    /// A hint corresponding to a single line comment,
12008    /// e.g. `--+ LEADING(v.e v.d t)`
12009    SingleLine {
12010        /// the comment prefix, e.g. `--`
12011        prefix: String,
12012    },
12013    /// A hint corresponding to a multi line comment,
12014    /// e.g. `/*+ LEADING(v.e v.d t) */`
12015    MultiLine,
12016}
12017
12018impl fmt::Display for OptimizerHint {
12019    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
12020        match &self.style {
12021            OptimizerHintStyle::SingleLine { prefix } => {
12022                f.write_str(prefix)?;
12023                f.write_str(&self.prefix)?;
12024                f.write_str("+")?;
12025                f.write_str(&self.text)
12026            }
12027            OptimizerHintStyle::MultiLine => {
12028                f.write_str("/*")?;
12029                f.write_str(&self.prefix)?;
12030                f.write_str("+")?;
12031                f.write_str(&self.text)?;
12032                f.write_str("*/")
12033            }
12034        }
12035    }
12036}
12037
12038impl fmt::Display for ResetStatement {
12039    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
12040        match &self.reset {
12041            Reset::ALL => write!(f, "RESET ALL"),
12042            Reset::ConfigurationParameter(param) => write!(f, "RESET {}", param),
12043        }
12044    }
12045}
12046
12047impl From<Set> for Statement {
12048    fn from(s: Set) -> Self {
12049        Self::Set(s)
12050    }
12051}
12052
12053impl From<Query> for Statement {
12054    fn from(q: Query) -> Self {
12055        Box::new(q).into()
12056    }
12057}
12058
12059impl From<Box<Query>> for Statement {
12060    fn from(q: Box<Query>) -> Self {
12061        Self::Query(q)
12062    }
12063}
12064
12065impl From<Insert> for Statement {
12066    fn from(i: Insert) -> Self {
12067        Self::Insert(i)
12068    }
12069}
12070
12071impl From<Update> for Statement {
12072    fn from(u: Update) -> Self {
12073        Self::Update(u)
12074    }
12075}
12076
12077impl From<CreateView> for Statement {
12078    fn from(cv: CreateView) -> Self {
12079        Self::CreateView(cv)
12080    }
12081}
12082
12083impl From<CreateRole> for Statement {
12084    fn from(cr: CreateRole) -> Self {
12085        Self::CreateRole(cr)
12086    }
12087}
12088
12089impl From<AlterTable> for Statement {
12090    fn from(at: AlterTable) -> Self {
12091        Self::AlterTable(at)
12092    }
12093}
12094
12095impl From<DropFunction> for Statement {
12096    fn from(df: DropFunction) -> Self {
12097        Self::DropFunction(df)
12098    }
12099}
12100
12101impl From<CreateExtension> for Statement {
12102    fn from(ce: CreateExtension) -> Self {
12103        Self::CreateExtension(ce)
12104    }
12105}
12106
12107impl From<CreateCollation> for Statement {
12108    fn from(c: CreateCollation) -> Self {
12109        Self::CreateCollation(c)
12110    }
12111}
12112
12113impl From<DropExtension> for Statement {
12114    fn from(de: DropExtension) -> Self {
12115        Self::DropExtension(de)
12116    }
12117}
12118
12119impl From<CaseStatement> for Statement {
12120    fn from(c: CaseStatement) -> Self {
12121        Self::Case(c)
12122    }
12123}
12124
12125impl From<IfStatement> for Statement {
12126    fn from(i: IfStatement) -> Self {
12127        Self::If(i)
12128    }
12129}
12130
12131impl From<WhileStatement> for Statement {
12132    fn from(w: WhileStatement) -> Self {
12133        Self::While(w)
12134    }
12135}
12136
12137impl From<RaiseStatement> for Statement {
12138    fn from(r: RaiseStatement) -> Self {
12139        Self::Raise(r)
12140    }
12141}
12142
12143impl From<ThrowStatement> for Statement {
12144    fn from(t: ThrowStatement) -> Self {
12145        Self::Throw(t)
12146    }
12147}
12148
12149impl From<Function> for Statement {
12150    fn from(f: Function) -> Self {
12151        Self::Call(f)
12152    }
12153}
12154
12155impl From<OpenStatement> for Statement {
12156    fn from(o: OpenStatement) -> Self {
12157        Self::Open(o)
12158    }
12159}
12160
12161impl From<Delete> for Statement {
12162    fn from(d: Delete) -> Self {
12163        Self::Delete(d)
12164    }
12165}
12166
12167impl From<CreateTable> for Statement {
12168    fn from(c: CreateTable) -> Self {
12169        Self::CreateTable(c)
12170    }
12171}
12172
12173impl From<CreateIndex> for Statement {
12174    fn from(c: CreateIndex) -> Self {
12175        Self::CreateIndex(c)
12176    }
12177}
12178
12179impl From<CreateServerStatement> for Statement {
12180    fn from(c: CreateServerStatement) -> Self {
12181        Self::CreateServer(c)
12182    }
12183}
12184
12185impl From<CreateConnector> for Statement {
12186    fn from(c: CreateConnector) -> Self {
12187        Self::CreateConnector(c)
12188    }
12189}
12190
12191impl From<CreateOperator> for Statement {
12192    fn from(c: CreateOperator) -> Self {
12193        Self::CreateOperator(c)
12194    }
12195}
12196
12197impl From<CreateOperatorFamily> for Statement {
12198    fn from(c: CreateOperatorFamily) -> Self {
12199        Self::CreateOperatorFamily(c)
12200    }
12201}
12202
12203impl From<CreateOperatorClass> for Statement {
12204    fn from(c: CreateOperatorClass) -> Self {
12205        Self::CreateOperatorClass(c)
12206    }
12207}
12208
12209impl From<AlterSchema> for Statement {
12210    fn from(a: AlterSchema) -> Self {
12211        Self::AlterSchema(a)
12212    }
12213}
12214
12215impl From<AlterFunction> for Statement {
12216    fn from(a: AlterFunction) -> Self {
12217        Self::AlterFunction(a)
12218    }
12219}
12220
12221impl From<AlterType> for Statement {
12222    fn from(a: AlterType) -> Self {
12223        Self::AlterType(a)
12224    }
12225}
12226
12227impl From<AlterCollation> for Statement {
12228    fn from(a: AlterCollation) -> Self {
12229        Self::AlterCollation(a)
12230    }
12231}
12232
12233impl From<AlterOperator> for Statement {
12234    fn from(a: AlterOperator) -> Self {
12235        Self::AlterOperator(a)
12236    }
12237}
12238
12239impl From<AlterOperatorFamily> for Statement {
12240    fn from(a: AlterOperatorFamily) -> Self {
12241        Self::AlterOperatorFamily(a)
12242    }
12243}
12244
12245impl From<AlterOperatorClass> for Statement {
12246    fn from(a: AlterOperatorClass) -> Self {
12247        Self::AlterOperatorClass(a)
12248    }
12249}
12250
12251impl From<Merge> for Statement {
12252    fn from(m: Merge) -> Self {
12253        Self::Merge(m)
12254    }
12255}
12256
12257impl From<AlterUser> for Statement {
12258    fn from(a: AlterUser) -> Self {
12259        Self::AlterUser(a)
12260    }
12261}
12262
12263impl From<DropDomain> for Statement {
12264    fn from(d: DropDomain) -> Self {
12265        Self::DropDomain(d)
12266    }
12267}
12268
12269impl From<ShowCharset> for Statement {
12270    fn from(s: ShowCharset) -> Self {
12271        Self::ShowCharset(s)
12272    }
12273}
12274
12275impl From<ShowObjects> for Statement {
12276    fn from(s: ShowObjects) -> Self {
12277        Self::ShowObjects(s)
12278    }
12279}
12280
12281impl From<Use> for Statement {
12282    fn from(u: Use) -> Self {
12283        Self::Use(u)
12284    }
12285}
12286
12287impl From<CreateFunction> for Statement {
12288    fn from(c: CreateFunction) -> Self {
12289        Self::CreateFunction(c)
12290    }
12291}
12292
12293impl From<CreateTrigger> for Statement {
12294    fn from(c: CreateTrigger) -> Self {
12295        Self::CreateTrigger(c)
12296    }
12297}
12298
12299impl From<DropTrigger> for Statement {
12300    fn from(d: DropTrigger) -> Self {
12301        Self::DropTrigger(d)
12302    }
12303}
12304
12305impl From<DropOperator> for Statement {
12306    fn from(d: DropOperator) -> Self {
12307        Self::DropOperator(d)
12308    }
12309}
12310
12311impl From<DropOperatorFamily> for Statement {
12312    fn from(d: DropOperatorFamily) -> Self {
12313        Self::DropOperatorFamily(d)
12314    }
12315}
12316
12317impl From<DropOperatorClass> for Statement {
12318    fn from(d: DropOperatorClass) -> Self {
12319        Self::DropOperatorClass(d)
12320    }
12321}
12322
12323impl From<DenyStatement> for Statement {
12324    fn from(d: DenyStatement) -> Self {
12325        Self::Deny(d)
12326    }
12327}
12328
12329impl From<CreateDomain> for Statement {
12330    fn from(c: CreateDomain) -> Self {
12331        Self::CreateDomain(c)
12332    }
12333}
12334
12335impl From<RenameTable> for Statement {
12336    fn from(r: RenameTable) -> Self {
12337        vec![r].into()
12338    }
12339}
12340
12341impl From<Vec<RenameTable>> for Statement {
12342    fn from(r: Vec<RenameTable>) -> Self {
12343        Self::RenameTable(r)
12344    }
12345}
12346
12347impl From<PrintStatement> for Statement {
12348    fn from(p: PrintStatement) -> Self {
12349        Self::Print(p)
12350    }
12351}
12352
12353impl From<ReturnStatement> for Statement {
12354    fn from(r: ReturnStatement) -> Self {
12355        Self::Return(r)
12356    }
12357}
12358
12359impl From<ExportData> for Statement {
12360    fn from(e: ExportData) -> Self {
12361        Self::ExportData(e)
12362    }
12363}
12364
12365impl From<CreateUser> for Statement {
12366    fn from(c: CreateUser) -> Self {
12367        Self::CreateUser(c)
12368    }
12369}
12370
12371impl From<VacuumStatement> for Statement {
12372    fn from(v: VacuumStatement) -> Self {
12373        Self::Vacuum(v)
12374    }
12375}
12376
12377impl From<ResetStatement> for Statement {
12378    fn from(r: ResetStatement) -> Self {
12379        Self::Reset(r)
12380    }
12381}
12382
12383#[cfg(test)]
12384mod tests {
12385    use crate::tokenizer::Location;
12386
12387    use super::*;
12388
12389    #[test]
12390    fn test_window_frame_default() {
12391        let window_frame = WindowFrame::default();
12392        assert_eq!(WindowFrameBound::Preceding(None), window_frame.start_bound);
12393    }
12394
12395    #[test]
12396    fn test_grouping_sets_display() {
12397        // a and b in different group
12398        let grouping_sets = Expr::GroupingSets(vec![
12399            vec![Expr::Identifier(Ident::new("a"))],
12400            vec![Expr::Identifier(Ident::new("b"))],
12401        ]);
12402        assert_eq!("GROUPING SETS ((a), (b))", format!("{grouping_sets}"));
12403
12404        // a and b in the same group
12405        let grouping_sets = Expr::GroupingSets(vec![vec![
12406            Expr::Identifier(Ident::new("a")),
12407            Expr::Identifier(Ident::new("b")),
12408        ]]);
12409        assert_eq!("GROUPING SETS ((a, b))", format!("{grouping_sets}"));
12410
12411        // (a, b) and (c, d) in different group
12412        let grouping_sets = Expr::GroupingSets(vec![
12413            vec![
12414                Expr::Identifier(Ident::new("a")),
12415                Expr::Identifier(Ident::new("b")),
12416            ],
12417            vec![
12418                Expr::Identifier(Ident::new("c")),
12419                Expr::Identifier(Ident::new("d")),
12420            ],
12421        ]);
12422        assert_eq!("GROUPING SETS ((a, b), (c, d))", format!("{grouping_sets}"));
12423    }
12424
12425    #[test]
12426    fn test_rollup_display() {
12427        let rollup = Expr::Rollup(vec![vec![Expr::Identifier(Ident::new("a"))]]);
12428        assert_eq!("ROLLUP (a)", format!("{rollup}"));
12429
12430        let rollup = Expr::Rollup(vec![vec![
12431            Expr::Identifier(Ident::new("a")),
12432            Expr::Identifier(Ident::new("b")),
12433        ]]);
12434        assert_eq!("ROLLUP ((a, b))", format!("{rollup}"));
12435
12436        let rollup = Expr::Rollup(vec![
12437            vec![Expr::Identifier(Ident::new("a"))],
12438            vec![Expr::Identifier(Ident::new("b"))],
12439        ]);
12440        assert_eq!("ROLLUP (a, b)", format!("{rollup}"));
12441
12442        let rollup = Expr::Rollup(vec![
12443            vec![Expr::Identifier(Ident::new("a"))],
12444            vec![
12445                Expr::Identifier(Ident::new("b")),
12446                Expr::Identifier(Ident::new("c")),
12447            ],
12448            vec![Expr::Identifier(Ident::new("d"))],
12449        ]);
12450        assert_eq!("ROLLUP (a, (b, c), d)", format!("{rollup}"));
12451    }
12452
12453    #[test]
12454    fn test_cube_display() {
12455        let cube = Expr::Cube(vec![vec![Expr::Identifier(Ident::new("a"))]]);
12456        assert_eq!("CUBE (a)", format!("{cube}"));
12457
12458        let cube = Expr::Cube(vec![vec![
12459            Expr::Identifier(Ident::new("a")),
12460            Expr::Identifier(Ident::new("b")),
12461        ]]);
12462        assert_eq!("CUBE ((a, b))", format!("{cube}"));
12463
12464        let cube = Expr::Cube(vec![
12465            vec![Expr::Identifier(Ident::new("a"))],
12466            vec![Expr::Identifier(Ident::new("b"))],
12467        ]);
12468        assert_eq!("CUBE (a, b)", format!("{cube}"));
12469
12470        let cube = Expr::Cube(vec![
12471            vec![Expr::Identifier(Ident::new("a"))],
12472            vec![
12473                Expr::Identifier(Ident::new("b")),
12474                Expr::Identifier(Ident::new("c")),
12475            ],
12476            vec![Expr::Identifier(Ident::new("d"))],
12477        ]);
12478        assert_eq!("CUBE (a, (b, c), d)", format!("{cube}"));
12479    }
12480
12481    #[test]
12482    fn test_interval_display() {
12483        let interval = Expr::Interval(Interval {
12484            value: Box::new(Expr::Value(
12485                Value::SingleQuotedString(String::from("123:45.67")).with_empty_span(),
12486            )),
12487            leading_field: Some(DateTimeField::Minute),
12488            leading_precision: Some(10),
12489            last_field: Some(DateTimeField::Second),
12490            fractional_seconds_precision: Some(9),
12491        });
12492        assert_eq!(
12493            "INTERVAL '123:45.67' MINUTE (10) TO SECOND (9)",
12494            format!("{interval}"),
12495        );
12496
12497        let interval = Expr::Interval(Interval {
12498            value: Box::new(Expr::Value(
12499                Value::SingleQuotedString(String::from("5")).with_empty_span(),
12500            )),
12501            leading_field: Some(DateTimeField::Second),
12502            leading_precision: Some(1),
12503            last_field: None,
12504            fractional_seconds_precision: Some(3),
12505        });
12506        assert_eq!("INTERVAL '5' SECOND (1, 3)", format!("{interval}"));
12507    }
12508
12509    #[test]
12510    fn test_one_or_many_with_parens_deref() {
12511        use core::ops::Index;
12512
12513        let one = OneOrManyWithParens::One("a");
12514
12515        assert_eq!(one.deref(), &["a"]);
12516        assert_eq!(<OneOrManyWithParens<_> as Deref>::deref(&one), &["a"]);
12517
12518        assert_eq!(one[0], "a");
12519        assert_eq!(one.index(0), &"a");
12520        assert_eq!(
12521            <<OneOrManyWithParens<_> as Deref>::Target as Index<usize>>::index(&one, 0),
12522            &"a"
12523        );
12524
12525        assert_eq!(one.len(), 1);
12526        assert_eq!(<OneOrManyWithParens<_> as Deref>::Target::len(&one), 1);
12527
12528        let many1 = OneOrManyWithParens::Many(vec!["b"]);
12529
12530        assert_eq!(many1.deref(), &["b"]);
12531        assert_eq!(<OneOrManyWithParens<_> as Deref>::deref(&many1), &["b"]);
12532
12533        assert_eq!(many1[0], "b");
12534        assert_eq!(many1.index(0), &"b");
12535        assert_eq!(
12536            <<OneOrManyWithParens<_> as Deref>::Target as Index<usize>>::index(&many1, 0),
12537            &"b"
12538        );
12539
12540        assert_eq!(many1.len(), 1);
12541        assert_eq!(<OneOrManyWithParens<_> as Deref>::Target::len(&many1), 1);
12542
12543        let many2 = OneOrManyWithParens::Many(vec!["c", "d"]);
12544
12545        assert_eq!(many2.deref(), &["c", "d"]);
12546        assert_eq!(
12547            <OneOrManyWithParens<_> as Deref>::deref(&many2),
12548            &["c", "d"]
12549        );
12550
12551        assert_eq!(many2[0], "c");
12552        assert_eq!(many2.index(0), &"c");
12553        assert_eq!(
12554            <<OneOrManyWithParens<_> as Deref>::Target as Index<usize>>::index(&many2, 0),
12555            &"c"
12556        );
12557
12558        assert_eq!(many2[1], "d");
12559        assert_eq!(many2.index(1), &"d");
12560        assert_eq!(
12561            <<OneOrManyWithParens<_> as Deref>::Target as Index<usize>>::index(&many2, 1),
12562            &"d"
12563        );
12564
12565        assert_eq!(many2.len(), 2);
12566        assert_eq!(<OneOrManyWithParens<_> as Deref>::Target::len(&many2), 2);
12567    }
12568
12569    #[test]
12570    fn test_one_or_many_with_parens_as_ref() {
12571        let one = OneOrManyWithParens::One("a");
12572
12573        assert_eq!(one.as_ref(), &["a"]);
12574        assert_eq!(<OneOrManyWithParens<_> as AsRef<_>>::as_ref(&one), &["a"]);
12575
12576        let many1 = OneOrManyWithParens::Many(vec!["b"]);
12577
12578        assert_eq!(many1.as_ref(), &["b"]);
12579        assert_eq!(<OneOrManyWithParens<_> as AsRef<_>>::as_ref(&many1), &["b"]);
12580
12581        let many2 = OneOrManyWithParens::Many(vec!["c", "d"]);
12582
12583        assert_eq!(many2.as_ref(), &["c", "d"]);
12584        assert_eq!(
12585            <OneOrManyWithParens<_> as AsRef<_>>::as_ref(&many2),
12586            &["c", "d"]
12587        );
12588    }
12589
12590    #[test]
12591    fn test_one_or_many_with_parens_ref_into_iter() {
12592        let one = OneOrManyWithParens::One("a");
12593
12594        assert_eq!(Vec::from_iter(&one), vec![&"a"]);
12595
12596        let many1 = OneOrManyWithParens::Many(vec!["b"]);
12597
12598        assert_eq!(Vec::from_iter(&many1), vec![&"b"]);
12599
12600        let many2 = OneOrManyWithParens::Many(vec!["c", "d"]);
12601
12602        assert_eq!(Vec::from_iter(&many2), vec![&"c", &"d"]);
12603    }
12604
12605    #[test]
12606    fn test_one_or_many_with_parens_value_into_iter() {
12607        use core::iter::once;
12608
12609        //tests that our iterator implemented methods behaves exactly as it's inner iterator, at every step up to n calls to next/next_back
12610        fn test_steps<I>(ours: OneOrManyWithParens<usize>, inner: I, n: usize)
12611        where
12612            I: IntoIterator<Item = usize, IntoIter: DoubleEndedIterator + Clone> + Clone,
12613        {
12614            fn checks<I>(ours: OneOrManyWithParensIntoIter<usize>, inner: I)
12615            where
12616                I: Iterator<Item = usize> + Clone + DoubleEndedIterator,
12617            {
12618                assert_eq!(ours.size_hint(), inner.size_hint());
12619                assert_eq!(ours.clone().count(), inner.clone().count());
12620
12621                assert_eq!(
12622                    ours.clone().fold(1, |a, v| a + v),
12623                    inner.clone().fold(1, |a, v| a + v)
12624                );
12625
12626                assert_eq!(Vec::from_iter(ours.clone()), Vec::from_iter(inner.clone()));
12627                assert_eq!(
12628                    Vec::from_iter(ours.clone().rev()),
12629                    Vec::from_iter(inner.clone().rev())
12630                );
12631            }
12632
12633            let mut ours_next = ours.clone().into_iter();
12634            let mut inner_next = inner.clone().into_iter();
12635
12636            for _ in 0..n {
12637                checks(ours_next.clone(), inner_next.clone());
12638
12639                assert_eq!(ours_next.next(), inner_next.next());
12640            }
12641
12642            let mut ours_next_back = ours.clone().into_iter();
12643            let mut inner_next_back = inner.clone().into_iter();
12644
12645            for _ in 0..n {
12646                checks(ours_next_back.clone(), inner_next_back.clone());
12647
12648                assert_eq!(ours_next_back.next_back(), inner_next_back.next_back());
12649            }
12650
12651            let mut ours_mixed = ours.clone().into_iter();
12652            let mut inner_mixed = inner.clone().into_iter();
12653
12654            for i in 0..n {
12655                checks(ours_mixed.clone(), inner_mixed.clone());
12656
12657                if i % 2 == 0 {
12658                    assert_eq!(ours_mixed.next_back(), inner_mixed.next_back());
12659                } else {
12660                    assert_eq!(ours_mixed.next(), inner_mixed.next());
12661                }
12662            }
12663
12664            let mut ours_mixed2 = ours.into_iter();
12665            let mut inner_mixed2 = inner.into_iter();
12666
12667            for i in 0..n {
12668                checks(ours_mixed2.clone(), inner_mixed2.clone());
12669
12670                if i % 2 == 0 {
12671                    assert_eq!(ours_mixed2.next(), inner_mixed2.next());
12672                } else {
12673                    assert_eq!(ours_mixed2.next_back(), inner_mixed2.next_back());
12674                }
12675            }
12676        }
12677
12678        test_steps(OneOrManyWithParens::One(1), once(1), 3);
12679        test_steps(OneOrManyWithParens::Many(vec![2]), vec![2], 3);
12680        test_steps(OneOrManyWithParens::Many(vec![3, 4]), vec![3, 4], 4);
12681    }
12682
12683    // Tests that the position in the code of an `Ident` does not affect its
12684    // ordering.
12685    #[test]
12686    fn test_ident_ord() {
12687        let mut a = Ident::with_span(Span::new(Location::new(1, 1), Location::new(1, 1)), "a");
12688        let mut b = Ident::with_span(Span::new(Location::new(2, 2), Location::new(2, 2)), "b");
12689
12690        assert!(a < b);
12691        std::mem::swap(&mut a.span, &mut b.span);
12692        assert!(a < b);
12693    }
12694}