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    AlterDomain, AlterDomainOperation, AlterExtension, AlterExtensionOperation,
65    AlterFunction, AlterFunctionAction, AlterFunctionKind, AlterFunctionOperation,
66    AlterIndexOperation, AlterOperator, AlterOperatorClass, AlterOperatorClassOperation,
67    AlterOperatorFamily, AlterOperatorFamilyOperation, AlterOperatorOperation, AlterPolicy,
68    AlterPolicyOperation, AlterSchema, AlterSchemaOperation, AlterTable, AlterTableAlgorithm,
69    AlterTableLock, AlterTableOperation, AlterTableType, AlterTrigger, AlterTriggerOperation,
70    AlterType, AlterTypeAddValue,
71    AlterTypeAddValuePosition, AlterTypeOperation, AlterTypeRename, AlterTypeRenameValue,
72    AggregateModifyKind, ClusteredBy, ColumnDef, ColumnOption, ColumnOptionDef, ColumnOptions,
73    ColumnPolicy, ColumnPolicyProperty, ConstraintCharacteristics, CreateAggregate,
74    CreateAggregateOption, CreateCollation, CreateCollationDefinition, CreateConnector,
75    CreateDomain, CreateExtension, CreateForeignDataWrapper, CreateForeignTable, CreateFunction,
76    CreateIndex, CreateOperator, CreateOperatorClass, CreateOperatorFamily, CreatePolicy,
77    CreatePolicyCommand, CreatePolicyType, CreatePublication, CreateSubscription, CreateTable,
78    CreateTextSearchConfiguration, CreateTextSearchDictionary, CreateTextSearchParser,
79    CreateTextSearchTemplate, CreateTrigger, PublicationTarget,
80    CreateView, Deduplicate, DeferrableInitial, DistStyle, DropBehavior, DropExtension,
81    DropFunction, DropOperator, DropOperatorClass, DropOperatorFamily, DropOperatorSignature,
82    DropPolicy, DropTrigger, FdwRoutineClause, ForValues, FunctionReturnType, GeneratedAs,
83    GeneratedExpressionMode, IdentityParameters, IdentityProperty, IdentityPropertyFormatKind,
84    IdentityPropertyKind, IdentityPropertyOrder, IndexColumn, IndexOption, IndexType,
85    KeyOrIndexDisplay, Msck, NullsDistinctOption, OperatorArgTypes, OperatorClassItem,
86    OperatorFamilyDropItem, OperatorFamilyItem, OperatorOption, OperatorPurpose, Owner, Partition,
87    PartitionBoundValue, ProcedureParam, ReferentialAction, RenameTableNameKind, ReplicaIdentity,
88    TagsColumnOption, TriggerObjectKind, Truncate, UserDefinedTypeCompositeAttributeDef,
89    UserDefinedTypeInternalLength, UserDefinedTypeRangeOption, UserDefinedTypeRepresentation,
90    UserDefinedTypeSqlDefinitionOption, UserDefinedTypeStorage, ViewColumnDef,
91};
92pub use self::dml::{
93    Delete, Insert, Merge, MergeAction, MergeClause, MergeClauseKind, MergeInsertExpr,
94    MergeInsertKind, MergeUpdateExpr, MultiTableInsertIntoClause, MultiTableInsertType,
95    MultiTableInsertValue, MultiTableInsertValues, MultiTableInsertWhenClause, OutputClause,
96    Update,
97};
98pub use self::operator::{BinaryOperator, UnaryOperator};
99pub use self::query::{
100    AfterMatchSkip, ConnectByKind, Cte, CteAsMaterialized, Distinct, EmptyMatchesMode,
101    ExceptSelectItem, ExcludeSelectItem, ExprWithAlias, ExprWithAliasAndOrderBy, Fetch, ForClause,
102    ForJson, ForXml, FormatClause, GroupByExpr, GroupByWithModifier, IdentWithAlias,
103    IlikeSelectItem, InputFormatClause, Interpolate, InterpolateExpr, Join, JoinConstraint,
104    JoinOperator, JsonTableColumn, JsonTableColumnErrorHandling, JsonTableNamedColumn,
105    JsonTableNestedColumn, LateralView, LimitClause, LockClause, LockType, MatchRecognizePattern,
106    MatchRecognizeSymbol, Measure, NamedWindowDefinition, NamedWindowExpr, NonBlock, Offset,
107    OffsetRows, OpenJsonTableColumn, OrderBy, OrderByExpr, OrderByKind, OrderByOptions,
108    PipeOperator, PivotValueSource, ProjectionSelect, Query, RenameSelectItem,
109    RepetitionQuantifier, ReplaceSelectElement, ReplaceSelectItem, RowsPerMatch, Select,
110    SelectFlavor, SelectInto, SelectItem, SelectItemQualifiedWildcardKind, SelectModifiers,
111    SetExpr, SetOperator, SetQuantifier, Setting, SymbolDefinition, Table, TableAlias,
112    TableAliasColumnDef, TableFactor, TableFunctionArgs, TableIndexHintForClause,
113    TableIndexHintType, TableIndexHints, TableIndexType, TableSample, TableSampleBucket,
114    TableSampleKind, TableSampleMethod, TableSampleModifier, TableSampleQuantity, TableSampleSeed,
115    TableSampleSeedModifier, TableSampleUnit, TableVersion, TableWithJoins, Top, TopQuantity,
116    UpdateTableFromKind, ValueTableMode, Values, WildcardAdditionalOptions, With, WithFill,
117    XmlNamespaceDefinition, XmlPassingArgument, XmlPassingClause, XmlTableColumn,
118    XmlTableColumnOption,
119};
120
121pub use self::trigger::{
122    TriggerEvent, TriggerExecBody, TriggerExecBodyType, TriggerObject, TriggerPeriod,
123    TriggerReferencing, TriggerReferencingType,
124};
125
126pub use self::value::{
127    escape_double_quote_string, escape_quoted_string, DateTimeField, DollarQuotedString,
128    NormalizationForm, QuoteDelimitedString, TrimWhereField, Value, ValueWithSpan,
129};
130
131use crate::ast::helpers::key_value_options::KeyValueOptions;
132use crate::ast::helpers::stmt_data_loading::StageParamsObject;
133
134#[cfg(feature = "visitor")]
135pub use visitor::*;
136
137pub use self::data_type::GeometricTypeKind;
138
139mod data_type;
140mod dcl;
141mod ddl;
142mod dml;
143/// Helper modules for building and manipulating AST nodes.
144pub mod helpers;
145pub mod table_constraints;
146pub use table_constraints::{
147    CheckConstraint, ConstraintUsingIndex, ExclusionConstraint, ExclusionElement,
148    ForeignKeyConstraint, FullTextOrSpatialConstraint, IndexConstraint, PrimaryKeyConstraint,
149    TableConstraint, UniqueConstraint,
150};
151mod operator;
152mod query;
153mod spans;
154pub use spans::Spanned;
155
156pub mod comments;
157mod trigger;
158mod value;
159
160#[cfg(feature = "visitor")]
161mod visitor;
162
163/// Helper used to format a slice using a separator string (e.g., `", "`).
164pub struct DisplaySeparated<'a, T>
165where
166    T: fmt::Display,
167{
168    slice: &'a [T],
169    sep: &'static str,
170}
171
172impl<T> fmt::Display for DisplaySeparated<'_, T>
173where
174    T: fmt::Display,
175{
176    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
177        let mut delim = "";
178        for t in self.slice {
179            f.write_str(delim)?;
180            delim = self.sep;
181            t.fmt(f)?;
182        }
183        Ok(())
184    }
185}
186
187pub(crate) fn display_separated<'a, T>(slice: &'a [T], sep: &'static str) -> DisplaySeparated<'a, T>
188where
189    T: fmt::Display,
190{
191    DisplaySeparated { slice, sep }
192}
193
194pub(crate) fn display_comma_separated<T>(slice: &[T]) -> DisplaySeparated<'_, T>
195where
196    T: fmt::Display,
197{
198    DisplaySeparated { slice, sep: ", " }
199}
200
201/// Writes the given statements to the formatter, each ending with
202/// a semicolon and space separated.
203fn format_statement_list(f: &mut fmt::Formatter, statements: &[Statement]) -> fmt::Result {
204    write!(f, "{}", display_separated(statements, "; "))?;
205    // We manually insert semicolon for the last statement,
206    // since display_separated doesn't handle that case.
207    write!(f, ";")
208}
209
210/// An identifier, decomposed into its value or character data and the quote style.
211#[derive(Debug, Clone)]
212#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
213#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
214pub struct Ident {
215    /// The value of the identifier without quotes.
216    pub value: String,
217    /// The starting quote if any. Valid quote characters are the single quote,
218    /// double quote, backtick, and opening square bracket.
219    pub quote_style: Option<char>,
220    /// The span of the identifier in the original SQL string.
221    pub span: Span,
222}
223
224impl PartialEq for Ident {
225    fn eq(&self, other: &Self) -> bool {
226        let Ident {
227            value,
228            quote_style,
229            // exhaustiveness check; we ignore spans in comparisons
230            span: _,
231        } = self;
232
233        value == &other.value && quote_style == &other.quote_style
234    }
235}
236
237impl core::hash::Hash for Ident {
238    fn hash<H: hash::Hasher>(&self, state: &mut H) {
239        let Ident {
240            value,
241            quote_style,
242            // exhaustiveness check; we ignore spans in hashes
243            span: _,
244        } = self;
245
246        value.hash(state);
247        quote_style.hash(state);
248    }
249}
250
251impl Eq for Ident {}
252
253impl PartialOrd for Ident {
254    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
255        Some(self.cmp(other))
256    }
257}
258
259impl Ord for Ident {
260    fn cmp(&self, other: &Self) -> Ordering {
261        let Ident {
262            value,
263            quote_style,
264            // exhaustiveness check; we ignore spans in ordering
265            span: _,
266        } = self;
267
268        let Ident {
269            value: other_value,
270            quote_style: other_quote_style,
271            // exhaustiveness check; we ignore spans in ordering
272            span: _,
273        } = other;
274
275        // First compare by value, then by quote_style
276        value
277            .cmp(other_value)
278            .then_with(|| quote_style.cmp(other_quote_style))
279    }
280}
281
282impl Ident {
283    /// Create a new identifier with the given value and no quotes and an empty span.
284    pub fn new<S>(value: S) -> Self
285    where
286        S: Into<String>,
287    {
288        Ident {
289            value: value.into(),
290            quote_style: None,
291            span: Span::empty(),
292        }
293    }
294
295    /// Create a new quoted identifier with the given quote and value. This function
296    /// panics if the given quote is not a valid quote character.
297    pub fn with_quote<S>(quote: char, value: S) -> Self
298    where
299        S: Into<String>,
300    {
301        assert!(quote == '\'' || quote == '"' || quote == '`' || quote == '[');
302        Ident {
303            value: value.into(),
304            quote_style: Some(quote),
305            span: Span::empty(),
306        }
307    }
308
309    /// Create an `Ident` with the given `span` and `value` (unquoted).
310    pub fn with_span<S>(span: Span, value: S) -> Self
311    where
312        S: Into<String>,
313    {
314        Ident {
315            value: value.into(),
316            quote_style: None,
317            span,
318        }
319    }
320
321    /// Create a quoted `Ident` with the given `quote` and `span`.
322    pub fn with_quote_and_span<S>(quote: char, span: Span, value: S) -> Self
323    where
324        S: Into<String>,
325    {
326        assert!(quote == '\'' || quote == '"' || quote == '`' || quote == '[');
327        Ident {
328            value: value.into(),
329            quote_style: Some(quote),
330            span,
331        }
332    }
333}
334
335impl From<&str> for Ident {
336    fn from(value: &str) -> Self {
337        Ident {
338            value: value.to_string(),
339            quote_style: None,
340            span: Span::empty(),
341        }
342    }
343}
344
345impl fmt::Display for Ident {
346    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
347        match self.quote_style {
348            Some(q) if q == '"' || q == '\'' || q == '`' => {
349                let escaped = value::escape_quoted_string(&self.value, q);
350                write!(f, "{q}{escaped}{q}")
351            }
352            Some('[') => write!(f, "[{}]", self.value),
353            None => f.write_str(&self.value),
354            _ => panic!("unexpected quote style"),
355        }
356    }
357}
358
359/// A name of a table, view, custom type, etc., possibly multi-part, i.e. db.schema.obj
360#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
361#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
362#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
363pub struct ObjectName(pub Vec<ObjectNamePart>);
364
365impl From<Vec<Ident>> for ObjectName {
366    fn from(idents: Vec<Ident>) -> Self {
367        ObjectName(idents.into_iter().map(ObjectNamePart::Identifier).collect())
368    }
369}
370
371impl From<Ident> for ObjectName {
372    fn from(ident: Ident) -> Self {
373        ObjectName(vec![ObjectNamePart::Identifier(ident)])
374    }
375}
376
377impl fmt::Display for ObjectName {
378    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
379        write!(f, "{}", display_separated(&self.0, "."))
380    }
381}
382
383/// A single part of an ObjectName
384#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
385#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
386#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
387pub enum ObjectNamePart {
388    /// A single identifier part, e.g. `schema` or `table`.
389    Identifier(Ident),
390    /// A function that returns an identifier (dialect-specific).
391    Function(ObjectNamePartFunction),
392}
393
394impl ObjectNamePart {
395    /// Return the identifier if this is an `Identifier` variant.
396    pub fn as_ident(&self) -> Option<&Ident> {
397        match self {
398            ObjectNamePart::Identifier(ident) => Some(ident),
399            ObjectNamePart::Function(_) => None,
400        }
401    }
402}
403
404impl fmt::Display for ObjectNamePart {
405    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
406        match self {
407            ObjectNamePart::Identifier(ident) => write!(f, "{ident}"),
408            ObjectNamePart::Function(func) => write!(f, "{func}"),
409        }
410    }
411}
412
413/// An object name part that consists of a function that dynamically
414/// constructs identifiers.
415///
416/// - [Snowflake](https://docs.snowflake.com/en/sql-reference/identifier-literal)
417#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
418#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
419#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
420pub struct ObjectNamePartFunction {
421    /// The function name that produces the object name part.
422    pub name: Ident,
423    /// Function arguments used to compute the identifier.
424    pub args: Vec<FunctionArg>,
425}
426
427impl fmt::Display for ObjectNamePartFunction {
428    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
429        write!(f, "{}(", self.name)?;
430        write!(f, "{})", display_comma_separated(&self.args))
431    }
432}
433
434/// Represents an Array Expression, either
435/// `ARRAY[..]`, or `[..]`
436#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
437#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
438#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
439pub struct Array {
440    /// The list of expressions between brackets
441    pub elem: Vec<Expr>,
442
443    /// `true` for  `ARRAY[..]`, `false` for `[..]`
444    pub named: bool,
445}
446
447impl fmt::Display for Array {
448    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
449        write!(
450            f,
451            "{}[{}]",
452            if self.named { "ARRAY" } else { "" },
453            display_comma_separated(&self.elem)
454        )
455    }
456}
457
458/// Represents an INTERVAL expression, roughly in the following format:
459/// `INTERVAL '<value>' [ <leading_field> [ (<leading_precision>) ] ]
460/// [ TO <last_field> [ (<fractional_seconds_precision>) ] ]`,
461/// e.g. `INTERVAL '123:45.67' MINUTE(3) TO SECOND(2)`.
462///
463/// The parser does not validate the `<value>`, nor does it ensure
464/// that the `<leading_field>` units >= the units in `<last_field>`,
465/// so the user will have to reject intervals like `HOUR TO YEAR`.
466#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
467#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
468#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
469pub struct Interval {
470    /// The interval value expression (commonly a string literal).
471    pub value: Box<Expr>,
472    /// Optional leading time unit (e.g., `HOUR`, `MINUTE`).
473    pub leading_field: Option<DateTimeField>,
474    /// Optional leading precision for the leading field.
475    pub leading_precision: Option<u64>,
476    /// Optional trailing time unit for a range (e.g., `SECOND`).
477    pub last_field: Option<DateTimeField>,
478    /// The fractional seconds precision, when specified.
479    ///
480    /// See SQL `SECOND(n)` or `SECOND(m, n)` forms.
481    pub fractional_seconds_precision: Option<u64>,
482}
483
484impl fmt::Display for Interval {
485    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
486        let value = self.value.as_ref();
487        match (
488            &self.leading_field,
489            self.leading_precision,
490            self.fractional_seconds_precision,
491        ) {
492            (
493                Some(DateTimeField::Second),
494                Some(leading_precision),
495                Some(fractional_seconds_precision),
496            ) => {
497                // When the leading field is SECOND, the parser guarantees that
498                // the last field is None.
499                assert!(self.last_field.is_none());
500                write!(
501                    f,
502                    "INTERVAL {value} SECOND ({leading_precision}, {fractional_seconds_precision})"
503                )
504            }
505            _ => {
506                write!(f, "INTERVAL {value}")?;
507                if let Some(leading_field) = &self.leading_field {
508                    write!(f, " {leading_field}")?;
509                }
510                if let Some(leading_precision) = self.leading_precision {
511                    write!(f, " ({leading_precision})")?;
512                }
513                if let Some(last_field) = &self.last_field {
514                    write!(f, " TO {last_field}")?;
515                }
516                if let Some(fractional_seconds_precision) = self.fractional_seconds_precision {
517                    write!(f, " ({fractional_seconds_precision})")?;
518                }
519                Ok(())
520            }
521        }
522    }
523}
524
525/// A field definition within a struct
526///
527/// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-types#struct_type
528#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
529#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
530#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
531pub struct StructField {
532    /// Optional name of the struct field.
533    pub field_name: Option<Ident>,
534    /// The field data type.
535    pub field_type: DataType,
536    /// Struct field options (e.g., `OPTIONS(...)` on BigQuery).
537    /// See [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#column_name_and_column_schema)
538    pub options: Option<Vec<SqlOption>>,
539}
540
541impl fmt::Display for StructField {
542    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
543        if let Some(name) = &self.field_name {
544            write!(f, "{name} {}", self.field_type)?;
545        } else {
546            write!(f, "{}", self.field_type)?;
547        }
548        if let Some(options) = &self.options {
549            write!(f, " OPTIONS({})", display_separated(options, ", "))
550        } else {
551            Ok(())
552        }
553    }
554}
555
556/// A field definition within a union
557///
558/// [DuckDB]: https://duckdb.org/docs/sql/data_types/union.html
559#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
560#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
561#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
562pub struct UnionField {
563    /// Name of the union field.
564    pub field_name: Ident,
565    /// Type of the union field.
566    pub field_type: DataType,
567}
568
569impl fmt::Display for UnionField {
570    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
571        write!(f, "{} {}", self.field_name, self.field_type)
572    }
573}
574
575/// A dictionary field within a dictionary.
576///
577/// [DuckDB]: https://duckdb.org/docs/sql/data_types/struct#creating-structs
578#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
579#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
580#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
581pub struct DictionaryField {
582    /// Dictionary key identifier.
583    pub key: Ident,
584    /// Value expression for the dictionary entry.
585    pub value: Box<Expr>,
586}
587
588impl fmt::Display for DictionaryField {
589    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
590        write!(f, "{}: {}", self.key, self.value)
591    }
592}
593
594/// Represents a Map expression.
595#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
596#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
597#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
598pub struct Map {
599    /// Entries of the map as key/value pairs.
600    pub entries: Vec<MapEntry>,
601}
602
603impl Display for Map {
604    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
605        write!(f, "MAP {{{}}}", display_comma_separated(&self.entries))
606    }
607}
608
609/// A map field within a map.
610///
611/// [DuckDB]: https://duckdb.org/docs/sql/data_types/map.html#creating-maps
612#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
613#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
614#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
615pub struct MapEntry {
616    /// Key expression of the map entry.
617    pub key: Box<Expr>,
618    /// Value expression of the map entry.
619    pub value: Box<Expr>,
620}
621
622impl fmt::Display for MapEntry {
623    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
624        write!(f, "{}: {}", self.key, self.value)
625    }
626}
627
628/// Options for `CAST` / `TRY_CAST`
629/// BigQuery: <https://cloud.google.com/bigquery/docs/reference/standard-sql/format-elements#formatting_syntax>
630#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
631#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
632#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
633pub enum CastFormat {
634    /// A simple cast format specified by a `Value`.
635    Value(ValueWithSpan),
636    /// A cast format with an explicit time zone: `(format, timezone)`.
637    ValueAtTimeZone(ValueWithSpan, ValueWithSpan),
638}
639
640/// An element of a JSON path.
641#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
642#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
643#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
644pub enum JsonPathElem {
645    /// Accesses an object field using dot notation, e.g. `obj:foo.bar.baz`.
646    ///
647    /// See <https://docs.snowflake.com/en/user-guide/querying-semistructured#dot-notation>.
648    Dot {
649        /// The object key text (without quotes).
650        key: String,
651        /// `true` when the key was quoted in the source.
652        quoted: bool,
653    },
654    /// Accesses an object field or array element using bracket notation,
655    /// e.g. `obj['foo']`.
656    ///
657    /// See <https://docs.snowflake.com/en/user-guide/querying-semistructured#bracket-notation>.
658    Bracket {
659        /// The expression used as the bracket key (string or numeric expression).
660        key: Expr,
661    },
662    /// Access an object field using colon bracket notation
663    /// e.g. `obj:['foo']`
664    ///
665    /// See <https://docs.databricks.com/en/sql/language-manual/functions/colonsign.html>
666    ColonBracket {
667        /// The expression used as the bracket key (string or numeric expression).
668        key: Expr,
669    },
670}
671
672/// A JSON path.
673///
674/// See <https://docs.snowflake.com/en/user-guide/querying-semistructured>.
675/// See <https://docs.databricks.com/en/sql/language-manual/sql-ref-json-path-expression.html>.
676#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
677#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
678#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
679pub struct JsonPath {
680    /// Sequence of path elements that form the JSON path.
681    pub path: Vec<JsonPathElem>,
682}
683
684impl fmt::Display for JsonPath {
685    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
686        for (i, elem) in self.path.iter().enumerate() {
687            match elem {
688                JsonPathElem::Dot { key, quoted } => {
689                    if i == 0 {
690                        write!(f, ":")?;
691                    } else {
692                        write!(f, ".")?;
693                    }
694
695                    if *quoted {
696                        write!(f, "\"{}\"", escape_double_quote_string(key))?;
697                    } else {
698                        write!(f, "{key}")?;
699                    }
700                }
701                JsonPathElem::Bracket { key } => {
702                    write!(f, "[{key}]")?;
703                }
704                JsonPathElem::ColonBracket { key } => {
705                    write!(f, ":[{key}]")?;
706                }
707            }
708        }
709        Ok(())
710    }
711}
712
713/// The syntax used for in a cast expression.
714#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
715#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
716#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
717pub enum CastKind {
718    /// The standard SQL cast syntax, e.g. `CAST(<expr> as <datatype>)`
719    Cast,
720    /// A cast that returns `NULL` on failure, e.g. `TRY_CAST(<expr> as <datatype>)`.
721    ///
722    /// See <https://docs.snowflake.com/en/sql-reference/functions/try_cast>.
723    /// See <https://learn.microsoft.com/en-us/sql/t-sql/functions/try-cast-transact-sql>.
724    TryCast,
725    /// A cast that returns `NULL` on failure, bigQuery-specific ,  e.g. `SAFE_CAST(<expr> as <datatype>)`.
726    ///
727    /// See <https://cloud.google.com/bigquery/docs/reference/standard-sql/functions-and-operators#safe_casting>.
728    SafeCast,
729    /// `<expr> :: <datatype>`
730    DoubleColon,
731}
732
733/// `MATCH` type for constraint references
734///
735/// See: <https://www.postgresql.org/docs/current/sql-createtable.html#SQL-CREATETABLE-PARMS-REFERENCES>
736#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
737#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
738#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
739pub enum ConstraintReferenceMatchKind {
740    /// `MATCH FULL`
741    Full,
742    /// `MATCH PARTIAL`
743    Partial,
744    /// `MATCH SIMPLE`
745    Simple,
746}
747
748impl fmt::Display for ConstraintReferenceMatchKind {
749    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
750        match self {
751            Self::Full => write!(f, "MATCH FULL"),
752            Self::Partial => write!(f, "MATCH PARTIAL"),
753            Self::Simple => write!(f, "MATCH SIMPLE"),
754        }
755    }
756}
757
758/// `EXTRACT` syntax variants.
759///
760/// In Snowflake dialect, the `EXTRACT` expression can support either the `from` syntax
761/// or the comma syntax.
762///
763/// See <https://docs.snowflake.com/en/sql-reference/functions/extract>
764#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
765#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
766#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
767pub enum ExtractSyntax {
768    /// `EXTRACT( <date_or_time_part> FROM <date_or_time_expr> )`
769    From,
770    /// `EXTRACT( <date_or_time_part> , <date_or_timestamp_expr> )`
771    Comma,
772}
773
774/// The syntax used in a CEIL or FLOOR expression.
775///
776/// The `CEIL/FLOOR(<datetime value expression> TO <time unit>)` is an Amazon Kinesis Data Analytics extension.
777/// See <https://docs.aws.amazon.com/kinesisanalytics/latest/sqlref/sql-reference-ceil.html> for
778/// details.
779///
780/// Other dialects either support `CEIL/FLOOR( <expr> [, <scale>])` format or just
781/// `CEIL/FLOOR(<expr>)`.
782#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
783#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
784#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
785pub enum CeilFloorKind {
786    /// `CEIL( <expr> TO <DateTimeField>)`
787    DateTimeField(DateTimeField),
788    /// `CEIL( <expr> [, <scale>])`
789    Scale(ValueWithSpan),
790}
791
792/// A WHEN clause in a CASE expression containing both
793/// the condition and its corresponding result
794#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
795#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
796#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
797pub struct CaseWhen {
798    /// The `WHEN` condition expression.
799    pub condition: Expr,
800    /// The expression returned when `condition` matches.
801    pub result: Expr,
802}
803
804impl fmt::Display for CaseWhen {
805    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
806        f.write_str("WHEN ")?;
807        self.condition.fmt(f)?;
808        f.write_str(" THEN")?;
809        SpaceOrNewline.fmt(f)?;
810        Indent(&self.result).fmt(f)?;
811        Ok(())
812    }
813}
814
815/// An SQL expression of any type.
816///
817/// # Semantics / Type Checking
818///
819/// The parser does not distinguish between expressions of different types
820/// (e.g. boolean vs string). The caller is responsible for detecting and
821/// validating types as necessary (for example  `WHERE 1` vs `SELECT 1=1`)
822/// See the [README.md] for more details.
823///
824/// [README.md]: https://github.com/apache/datafusion-sqlparser-rs/blob/main/README.md#syntax-vs-semantics
825///
826/// # Equality and Hashing Does not Include Source Locations
827///
828/// The `Expr` type implements `PartialEq` and `Eq` based on the semantic value
829/// of the expression (not bitwise comparison). This means that `Expr` instances
830/// that are semantically equivalent but have different spans (locations in the
831/// source tree) will compare as equal.
832#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
833#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
834#[cfg_attr(
835    feature = "visitor",
836    derive(Visit, VisitMut),
837    visit(with = "visit_expr")
838)]
839pub enum Expr {
840    /// Identifier e.g. table name or column name
841    Identifier(Ident),
842    /// Multi-part identifier, e.g. `table_alias.column` or `schema.table.col`
843    CompoundIdentifier(Vec<Ident>),
844    /// Multi-part expression access.
845    ///
846    /// This structure represents an access chain in structured / nested types
847    /// such as maps, arrays, and lists:
848    /// - Array
849    ///     - A 1-dim array `a[1]` will be represented like:
850    ///       `CompoundFieldAccess(Ident('a'), vec![Subscript(1)]`
851    ///     - A 2-dim array `a[1][2]` will be represented like:
852    ///       `CompoundFieldAccess(Ident('a'), vec![Subscript(1), Subscript(2)]`
853    /// - Map or Struct (Bracket-style)
854    ///     - A map `a['field1']` will be represented like:
855    ///       `CompoundFieldAccess(Ident('a'), vec![Subscript('field')]`
856    ///     - A 2-dim map `a['field1']['field2']` will be represented like:
857    ///       `CompoundFieldAccess(Ident('a'), vec![Subscript('field1'), Subscript('field2')]`
858    /// - Struct (Dot-style) (only effect when the chain contains both subscript and expr)
859    ///     - A struct access `a[field1].field2` will be represented like:
860    ///       `CompoundFieldAccess(Ident('a'), vec![Subscript('field1'), Ident('field2')]`
861    /// - If a struct access likes `a.field1.field2`, it will be represented by CompoundIdentifier([a, field1, field2])
862    CompoundFieldAccess {
863        /// The base expression being accessed.
864        root: Box<Expr>,
865        /// Sequence of access operations (subscript or identifier accesses).
866        access_chain: Vec<AccessExpr>,
867    },
868    /// Access data nested in a value containing semi-structured data, such as
869    /// the `VARIANT` type on Snowflake. for example `src:customer[0].name`.
870    ///
871    /// See <https://docs.snowflake.com/en/user-guide/querying-semistructured>.
872    /// See <https://docs.databricks.com/en/sql/language-manual/functions/colonsign.html>.
873    JsonAccess {
874        /// The value being queried.
875        value: Box<Expr>,
876        /// The path to the data to extract.
877        path: JsonPath,
878    },
879    /// `IS FALSE` operator
880    IsFalse(Box<Expr>),
881    /// `IS NOT FALSE` operator
882    IsNotFalse(Box<Expr>),
883    /// `IS TRUE` operator
884    IsTrue(Box<Expr>),
885    /// `IS NOT TRUE` operator
886    IsNotTrue(Box<Expr>),
887    /// `IS NULL` operator
888    IsNull(Box<Expr>),
889    /// `IS NOT NULL` operator
890    IsNotNull(Box<Expr>),
891    /// `IS UNKNOWN` operator
892    IsUnknown(Box<Expr>),
893    /// `IS NOT UNKNOWN` operator
894    IsNotUnknown(Box<Expr>),
895    /// `IS DISTINCT FROM` operator
896    IsDistinctFrom(Box<Expr>, Box<Expr>),
897    /// `IS NOT DISTINCT FROM` operator
898    IsNotDistinctFrom(Box<Expr>, Box<Expr>),
899    /// `<expr> IS [ NOT ] [ form ] NORMALIZED`
900    IsNormalized {
901        /// Expression being tested.
902        expr: Box<Expr>,
903        /// Optional normalization `form` (e.g., NFC, NFD).
904        form: Option<NormalizationForm>,
905        /// `true` when `NOT` is present.
906        negated: bool,
907    },
908    /// `[ NOT ] IN (val1, val2, ...)`
909    InList {
910        /// Left-hand expression to test for membership.
911        expr: Box<Expr>,
912        /// Literal list of expressions to check against.
913        list: Vec<Expr>,
914        /// `true` when the `NOT` modifier is present.
915        negated: bool,
916    },
917    /// `[ NOT ] IN (SELECT ...)`
918    InSubquery {
919        /// Left-hand expression to test for membership.
920        expr: Box<Expr>,
921        /// The subquery providing the candidate values.
922        subquery: Box<Query>,
923        /// `true` when the `NOT` modifier is present.
924        negated: bool,
925    },
926    /// `[ NOT ] IN UNNEST(array_expression)`
927    InUnnest {
928        /// Left-hand expression to test for membership.
929        expr: Box<Expr>,
930        /// Array expression being unnested.
931        array_expr: Box<Expr>,
932        /// `true` when the `NOT` modifier is present.
933        negated: bool,
934    },
935    /// `<expr> [ NOT ] BETWEEN <low> AND <high>`
936    Between {
937        /// Expression being compared.
938        expr: Box<Expr>,
939        /// `true` when the `NOT` modifier is present.
940        negated: bool,
941        /// Lower bound.
942        low: Box<Expr>,
943        /// Upper bound.
944        high: Box<Expr>,
945    },
946    /// Binary operation e.g. `1 + 1` or `foo > bar`
947    BinaryOp {
948        /// Left operand.
949        left: Box<Expr>,
950        /// Operator between operands.
951        op: BinaryOperator,
952        /// Right operand.
953        right: Box<Expr>,
954    },
955    /// `[NOT] LIKE <pattern> [ESCAPE <escape_character>]`
956    Like {
957        /// `true` when `NOT` is present.
958        negated: bool,
959        /// Snowflake supports the ANY keyword to match against a list of patterns
960        /// <https://docs.snowflake.com/en/sql-reference/functions/like_any>
961        any: bool,
962        /// Expression to match.
963        expr: Box<Expr>,
964        /// Pattern expression.
965        pattern: Box<Expr>,
966        /// Optional escape character.
967        escape_char: Option<ValueWithSpan>,
968    },
969    /// `ILIKE` (case-insensitive `LIKE`)
970    ILike {
971        /// `true` when `NOT` is present.
972        negated: bool,
973        /// Snowflake supports the ANY keyword to match against a list of patterns
974        /// <https://docs.snowflake.com/en/sql-reference/functions/like_any>
975        any: bool,
976        /// Expression to match.
977        expr: Box<Expr>,
978        /// Pattern expression.
979        pattern: Box<Expr>,
980        /// Optional escape character.
981        escape_char: Option<ValueWithSpan>,
982    },
983    /// `SIMILAR TO` regex
984    SimilarTo {
985        /// `true` when `NOT` is present.
986        negated: bool,
987        /// Expression to test.
988        expr: Box<Expr>,
989        /// Pattern expression.
990        pattern: Box<Expr>,
991        /// Optional escape character.
992        escape_char: Option<ValueWithSpan>,
993    },
994    /// MySQL: `RLIKE` regex or `REGEXP` regex
995    RLike {
996        /// `true` when `NOT` is present.
997        negated: bool,
998        /// Expression to test.
999        expr: Box<Expr>,
1000        /// Pattern expression.
1001        pattern: Box<Expr>,
1002        /// true for REGEXP, false for RLIKE (no difference in semantics)
1003        regexp: bool,
1004    },
1005    /// `ANY` operation e.g. `foo > ANY(bar)`, comparison operator is one of `[=, >, <, =>, =<, !=]`
1006    /// <https://docs.snowflake.com/en/sql-reference/operators-subquery#all-any>
1007    AnyOp {
1008        /// Left operand.
1009        left: Box<Expr>,
1010        /// Comparison operator.
1011        compare_op: BinaryOperator,
1012        /// Right-hand subquery expression.
1013        right: Box<Expr>,
1014        /// ANY and SOME are synonymous: <https://docs.cloudera.com/cdw-runtime/cloud/using-hiveql/topics/hive_comparison_predicates.html>
1015        is_some: bool,
1016    },
1017    /// `ALL` operation e.g. `foo > ALL(bar)`, comparison operator is one of `[=, >, <, =>, =<, !=]`
1018    /// <https://docs.snowflake.com/en/sql-reference/operators-subquery#all-any>
1019    AllOp {
1020        /// Left operand.
1021        left: Box<Expr>,
1022        /// Comparison operator.
1023        compare_op: BinaryOperator,
1024        /// Right-hand subquery expression.
1025        right: Box<Expr>,
1026    },
1027
1028    /// Unary operation e.g. `NOT foo`
1029    UnaryOp {
1030        /// The unary operator (e.g., `NOT`, `-`).
1031        op: UnaryOperator,
1032        /// Operand expression.
1033        expr: Box<Expr>,
1034    },
1035    /// CONVERT a value to a different data type or character encoding. e.g. `CONVERT(foo USING utf8mb4)`
1036    Convert {
1037        /// CONVERT (false) or TRY_CONVERT (true)
1038        /// <https://learn.microsoft.com/en-us/sql/t-sql/functions/try-convert-transact-sql?view=sql-server-ver16>
1039        is_try: bool,
1040        /// The expression to convert.
1041        expr: Box<Expr>,
1042        /// The target data type, if provided.
1043        data_type: Option<DataType>,
1044        /// Optional target character encoding (e.g., `utf8mb4`).
1045        charset: Option<ObjectName>,
1046        /// `true` when target precedes the value (MSSQL syntax).
1047        target_before_value: bool,
1048        /// How to translate the expression.
1049        ///
1050        /// [MSSQL]: https://learn.microsoft.com/en-us/sql/t-sql/functions/cast-and-convert-transact-sql?view=sql-server-ver16#style
1051        styles: Vec<Expr>,
1052    },
1053    /// `CAST` an expression to a different data type e.g. `CAST(foo AS VARCHAR(123))`
1054    Cast {
1055        /// The cast kind (e.g., `CAST`, `TRY_CAST`).
1056        kind: CastKind,
1057        /// Expression being cast.
1058        expr: Box<Expr>,
1059        /// Target data type.
1060        data_type: DataType,
1061        /// [MySQL] allows CAST(... AS type ARRAY) in functional index definitions for InnoDB
1062        /// multi-valued indices. It's not really a datatype, and is only allowed in `CAST` in key
1063        /// specifications, so it's a flag here.
1064        ///
1065        /// [MySQL]: https://dev.mysql.com/doc/refman/8.4/en/cast-functions.html#function_cast
1066        array: bool,
1067        /// Optional CAST(string_expression AS type FORMAT format_string_expression) as used by [BigQuery]
1068        ///
1069        /// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/format-elements#formatting_syntax
1070        format: Option<CastFormat>,
1071    },
1072    /// AT a timestamp to a different timezone e.g. `FROM_UNIXTIME(0) AT TIME ZONE 'UTC-06:00'`
1073    AtTimeZone {
1074        /// Timestamp expression to shift.
1075        timestamp: Box<Expr>,
1076        /// Time zone expression to apply.
1077        time_zone: Box<Expr>,
1078    },
1079    /// Extract a field from a timestamp e.g. `EXTRACT(MONTH FROM foo)`
1080    /// Or `EXTRACT(MONTH, foo)`
1081    ///
1082    /// Syntax:
1083    /// ```sql
1084    /// EXTRACT(DateTimeField FROM <expr>) | EXTRACT(DateTimeField, <expr>)
1085    /// ```
1086    Extract {
1087        /// Which datetime field is being extracted.
1088        field: DateTimeField,
1089        /// Syntax variant used (`From` or `Comma`).
1090        syntax: ExtractSyntax,
1091        /// Expression to extract from.
1092        expr: Box<Expr>,
1093    },
1094    /// ```sql
1095    /// CEIL(<expr> [TO DateTimeField])
1096    /// ```
1097    /// ```sql
1098    /// CEIL( <input_expr> [, <scale_expr> ] )
1099    /// ```
1100    Ceil {
1101        /// Expression to ceil.
1102        expr: Box<Expr>,
1103        /// The CEIL/FLOOR kind (datetime field or scale).
1104        field: CeilFloorKind,
1105    },
1106    /// ```sql
1107    /// FLOOR(<expr> [TO DateTimeField])
1108    /// ```
1109    /// ```sql
1110    /// FLOOR( <input_expr> [, <scale_expr> ] )
1111    ///
1112    Floor {
1113        /// Expression to floor.
1114        expr: Box<Expr>,
1115        /// The CEIL/FLOOR kind (datetime field or scale).
1116        field: CeilFloorKind,
1117    },
1118    /// ```sql
1119    /// POSITION(<expr> in <expr>)
1120    /// ```
1121    Position {
1122        /// Expression to search for.
1123        expr: Box<Expr>,
1124        /// Expression to search in.
1125        r#in: Box<Expr>,
1126    },
1127    /// ```sql
1128    /// SUBSTRING(<expr> [FROM <expr>] [FOR <expr>])
1129    /// ```
1130    /// or
1131    /// ```sql
1132    /// SUBSTRING(<expr>, <expr>, <expr>)
1133    /// ```
1134    Substring {
1135        /// Source expression.
1136        expr: Box<Expr>,
1137        /// Optional `FROM` expression.
1138        substring_from: Option<Box<Expr>>,
1139        /// Optional `FOR` expression.
1140        substring_for: Option<Box<Expr>>,
1141
1142        /// false if the expression is represented using the `SUBSTRING(expr [FROM start] [FOR len])` syntax
1143        /// true if the expression is represented using the `SUBSTRING(expr, start, len)` syntax
1144        /// This flag is used for formatting.
1145        special: bool,
1146
1147        /// true if the expression is represented using the `SUBSTR` shorthand
1148        /// This flag is used for formatting.
1149        shorthand: bool,
1150    },
1151    /// ```sql
1152    /// TRIM([BOTH | LEADING | TRAILING] [<expr> FROM] <expr>)
1153    /// TRIM(<expr>)
1154    /// TRIM(<expr>, [, characters]) -- PostgreSQL, DuckDB, Snowflake, BigQuery, Generic
1155    /// ```
1156    Trim {
1157        /// Which side to trim: `BOTH`, `LEADING`, or `TRAILING`.
1158        trim_where: Option<TrimWhereField>,
1159        /// Optional expression specifying what to trim from the value `expr`.
1160        trim_what: Option<Box<Expr>>,
1161        /// The expression to trim from.
1162        expr: Box<Expr>,
1163        /// Optional list of characters to trim (dialect-specific).
1164        trim_characters: Option<Vec<Expr>>,
1165    },
1166    /// ```sql
1167    /// OVERLAY(<expr> PLACING <expr> FROM <expr>[ FOR <expr> ]
1168    /// ```
1169    Overlay {
1170        /// The target expression being overlayed.
1171        expr: Box<Expr>,
1172        /// The expression to place into the target.
1173        overlay_what: Box<Expr>,
1174        /// The `FROM` position expression indicating where to start overlay.
1175        overlay_from: Box<Expr>,
1176        /// Optional `FOR` length expression limiting the overlay span.
1177        overlay_for: Option<Box<Expr>>,
1178    },
1179    /// `expr COLLATE collation`
1180    Collate {
1181        /// The expression being collated.
1182        expr: Box<Expr>,
1183        /// The collation name to apply to the expression.
1184        collation: ObjectName,
1185    },
1186    /// Nested expression e.g. `(foo > bar)` or `(1)`
1187    Nested(Box<Expr>),
1188    /// A literal value, such as string, number, date or NULL
1189    Value(ValueWithSpan),
1190    /// Prefixed expression, e.g. introducer strings, projection prefix
1191    /// <https://dev.mysql.com/doc/refman/8.0/en/charset-introducer.html>
1192    /// <https://docs.snowflake.com/en/sql-reference/constructs/connect-by>
1193    Prefixed {
1194        /// The prefix identifier (introducer or projection prefix).
1195        prefix: Ident,
1196        /// The value expression being prefixed.
1197        /// Hint: you can unwrap the string value using `value.into_string()`.
1198        value: Box<Expr>,
1199    },
1200    /// A constant of form `<data_type> 'value'`.
1201    /// This can represent ANSI SQL `DATE`, `TIME`, and `TIMESTAMP` literals (such as `DATE '2020-01-01'`),
1202    /// as well as constants of other types (a non-standard PostgreSQL extension).
1203    TypedString(TypedString),
1204    /// Scalar function call e.g. `LEFT(foo, 5)`
1205    Function(Function),
1206    /// `CASE [<operand>] WHEN <condition> THEN <result> ... [ELSE <result>] END`
1207    ///
1208    /// Note we only recognize a complete single expression as `<condition>`,
1209    /// not `< 0` nor `1, 2, 3` as allowed in a `<simple when clause>` per
1210    /// <https://jakewheat.github.io/sql-overview/sql-2011-foundation-grammar.html#simple-when-clause>
1211    Case {
1212        /// The attached `CASE` token (keeps original spacing/comments).
1213        case_token: AttachedToken,
1214        /// The attached `END` token (keeps original spacing/comments).
1215        end_token: AttachedToken,
1216        /// Optional operand expression after `CASE` (for simple CASE).
1217        operand: Option<Box<Expr>>,
1218        /// The `WHEN ... THEN` conditions and results.
1219        conditions: Vec<CaseWhen>,
1220        /// Optional `ELSE` result expression.
1221        else_result: Option<Box<Expr>>,
1222    },
1223    /// An exists expression `[ NOT ] EXISTS(SELECT ...)`, used in expressions like
1224    /// `WHERE [ NOT ] EXISTS (SELECT ...)`.
1225    Exists {
1226        /// The subquery checked by `EXISTS`.
1227        subquery: Box<Query>,
1228        /// Whether the `EXISTS` is negated (`NOT EXISTS`).
1229        negated: bool,
1230    },
1231    /// A parenthesized subquery `(SELECT ...)`, used in expression like
1232    /// `SELECT (subquery) AS x` or `WHERE (subquery) = x`
1233    Subquery(Box<Query>),
1234    /// The `GROUPING SETS` expr.
1235    GroupingSets(Vec<Vec<Expr>>),
1236    /// The `CUBE` expr.
1237    Cube(Vec<Vec<Expr>>),
1238    /// The `ROLLUP` expr.
1239    Rollup(Vec<Vec<Expr>>),
1240    /// ROW / TUPLE a single value, such as `SELECT (1, 2)`
1241    Tuple(Vec<Expr>),
1242    /// `Struct` literal expression
1243    /// Syntax:
1244    /// ```sql
1245    /// STRUCT<[field_name] field_type, ...>( expr1 [, ... ])
1246    ///
1247    /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-types#struct_type)
1248    /// [Databricks](https://docs.databricks.com/en/sql/language-manual/functions/struct.html)
1249    /// ```
1250    Struct {
1251        /// Struct values.
1252        values: Vec<Expr>,
1253        /// Struct field definitions.
1254        fields: Vec<StructField>,
1255    },
1256    /// `BigQuery` specific: An named expression in a typeless struct [1]
1257    ///
1258    /// Syntax
1259    /// ```sql
1260    /// 1 AS A
1261    /// ```
1262    /// [1]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-types#struct_type
1263    Named {
1264        /// The expression being named.
1265        expr: Box<Expr>,
1266        /// The assigned identifier name for the expression.
1267        name: Ident,
1268    },
1269    /// `DuckDB` specific `Struct` literal expression [1]
1270    ///
1271    /// Syntax:
1272    /// ```sql
1273    /// syntax: {'field_name': expr1[, ... ]}
1274    /// ```
1275    /// [1]: https://duckdb.org/docs/sql/data_types/struct#creating-structs
1276    Dictionary(Vec<DictionaryField>),
1277    /// `DuckDB` specific `Map` literal expression [1]
1278    ///
1279    /// Syntax:
1280    /// ```sql
1281    /// syntax: Map {key1: value1[, ... ]}
1282    /// ```
1283    /// [1]: https://duckdb.org/docs/sql/data_types/map#creating-maps
1284    Map(Map),
1285    /// An array expression e.g. `ARRAY[1, 2]`
1286    Array(Array),
1287    /// An interval expression e.g. `INTERVAL '1' YEAR`
1288    Interval(Interval),
1289    /// `MySQL` specific text search function [(1)].
1290    ///
1291    /// Syntax:
1292    /// ```sql
1293    /// MATCH (<col>, <col>, ...) AGAINST (<expr> [<search modifier>])
1294    ///
1295    /// <col> = CompoundIdentifier
1296    /// <expr> = String literal
1297    /// ```
1298    /// [(1)]: https://dev.mysql.com/doc/refman/8.0/en/fulltext-search.html#function_match
1299    MatchAgainst {
1300        /// `(<col>, <col>, ...)`.
1301        columns: Vec<ObjectName>,
1302        /// `<expr>`.
1303        match_value: ValueWithSpan,
1304        /// `<search modifier>`
1305        opt_search_modifier: Option<SearchModifier>,
1306    },
1307    /// An unqualified `*` wildcard token (e.g. `*`).
1308    Wildcard(AttachedToken),
1309    /// Qualified wildcard, e.g. `alias.*` or `schema.table.*`.
1310    /// (Same caveats apply to `QualifiedWildcard` as to `Wildcard`.)
1311    QualifiedWildcard(ObjectName, AttachedToken),
1312    /// Some dialects support an older syntax for outer joins where columns are
1313    /// marked with the `(+)` operator in the WHERE clause, for example:
1314    ///
1315    /// ```sql
1316    /// SELECT t1.c1, t2.c2 FROM t1, t2 WHERE t1.c1 = t2.c2 (+)
1317    /// ```
1318    ///
1319    /// which is equivalent to
1320    ///
1321    /// ```sql
1322    /// SELECT t1.c1, t2.c2 FROM t1 LEFT OUTER JOIN t2 ON t1.c1 = t2.c2
1323    /// ```
1324    ///
1325    /// See <https://docs.snowflake.com/en/sql-reference/constructs/where#joins-in-the-where-clause>.
1326    OuterJoin(Box<Expr>),
1327    /// A reference to the prior level in a CONNECT BY clause.
1328    Prior(Box<Expr>),
1329    /// A lambda function.
1330    ///
1331    /// Syntax:
1332    /// ```plaintext
1333    /// param -> expr | (param1, ...) -> expr
1334    /// ```
1335    ///
1336    /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/functions#higher-order-functions---operator-and-lambdaparams-expr-function)
1337    /// [Databricks](https://docs.databricks.com/en/sql/language-manual/sql-ref-lambda-functions.html)
1338    /// [DuckDB](https://duckdb.org/docs/stable/sql/functions/lambda)
1339    Lambda(LambdaFunction),
1340    /// Checks membership of a value in a JSON array
1341    MemberOf(MemberOf),
1342}
1343
1344impl Expr {
1345    /// Creates a new [`Expr::Value`]
1346    pub fn value(value: impl Into<ValueWithSpan>) -> Self {
1347        Expr::Value(value.into())
1348    }
1349}
1350
1351/// The contents inside the `[` and `]` in a subscript expression.
1352#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1353#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1354#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1355pub enum Subscript {
1356    /// Accesses the element of the array at the given index.
1357    Index {
1358        /// The index expression used to access the array element.
1359        index: Expr,
1360    },
1361
1362    /// Accesses a slice of an array on PostgreSQL, e.g.
1363    ///
1364    /// ```plaintext
1365    /// => select (array[1,2,3,4,5,6])[2:5];
1366    /// -----------
1367    /// {2,3,4,5}
1368    /// ```
1369    ///
1370    /// The lower and/or upper bound can be omitted to slice from the start or
1371    /// end of the array respectively.
1372    ///
1373    /// See <https://www.postgresql.org/docs/current/arrays.html#ARRAYS-ACCESSING>.
1374    ///
1375    /// Also supports an optional "stride" as the last element (this is not
1376    /// supported by postgres), e.g.
1377    ///
1378    /// ```plaintext
1379    /// => select (array[1,2,3,4,5,6])[1:6:2];
1380    /// -----------
1381    /// {1,3,5}
1382    /// ```
1383    Slice {
1384        /// Optional lower bound for the slice (inclusive).
1385        lower_bound: Option<Expr>,
1386        /// Optional upper bound for the slice (inclusive).
1387        upper_bound: Option<Expr>,
1388        /// Optional stride for the slice (step size).
1389        stride: Option<Expr>,
1390    },
1391}
1392
1393impl fmt::Display for Subscript {
1394    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1395        match self {
1396            Subscript::Index { index } => write!(f, "{index}"),
1397            Subscript::Slice {
1398                lower_bound,
1399                upper_bound,
1400                stride,
1401            } => {
1402                if let Some(lower) = lower_bound {
1403                    write!(f, "{lower}")?;
1404                }
1405                write!(f, ":")?;
1406                if let Some(upper) = upper_bound {
1407                    write!(f, "{upper}")?;
1408                }
1409                if let Some(stride) = stride {
1410                    write!(f, ":")?;
1411                    write!(f, "{stride}")?;
1412                }
1413                Ok(())
1414            }
1415        }
1416    }
1417}
1418
1419/// An element of a [`Expr::CompoundFieldAccess`].
1420/// It can be an expression or a subscript.
1421#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1422#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1423#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1424pub enum AccessExpr {
1425    /// Accesses a field using dot notation, e.g. `foo.bar.baz`.
1426    Dot(Expr),
1427    /// Accesses a field or array element using bracket notation, e.g. `foo['bar']`.
1428    Subscript(Subscript),
1429}
1430
1431impl fmt::Display for AccessExpr {
1432    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1433        match self {
1434            AccessExpr::Dot(expr) => write!(f, ".{expr}"),
1435            AccessExpr::Subscript(subscript) => write!(f, "[{subscript}]"),
1436        }
1437    }
1438}
1439
1440/// A lambda function.
1441#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1442#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1443#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1444pub struct LambdaFunction {
1445    /// The parameters to the lambda function.
1446    pub params: OneOrManyWithParens<LambdaFunctionParameter>,
1447    /// The body of the lambda function.
1448    pub body: Box<Expr>,
1449    /// The syntax style used to write the lambda function.
1450    pub syntax: LambdaSyntax,
1451}
1452
1453impl fmt::Display for LambdaFunction {
1454    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1455        match self.syntax {
1456            LambdaSyntax::Arrow => write!(f, "{} -> {}", self.params, self.body),
1457            LambdaSyntax::LambdaKeyword => {
1458                // For lambda keyword syntax, display params without parentheses
1459                // e.g., `lambda x, y : expr` not `lambda (x, y) : expr`
1460                write!(f, "lambda ")?;
1461                match &self.params {
1462                    OneOrManyWithParens::One(p) => write!(f, "{p}")?,
1463                    OneOrManyWithParens::Many(ps) => write!(f, "{}", display_comma_separated(ps))?,
1464                };
1465                write!(f, " : {}", self.body)
1466            }
1467        }
1468    }
1469}
1470
1471/// A parameter to a lambda function, optionally with a data type.
1472#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1473#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1474#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1475pub struct LambdaFunctionParameter {
1476    /// The name of the parameter
1477    pub name: Ident,
1478    /// The optional data type of the parameter
1479    /// [Snowflake Syntax](https://docs.snowflake.com/en/sql-reference/functions/filter#arguments)
1480    pub data_type: Option<DataType>,
1481}
1482
1483impl fmt::Display for LambdaFunctionParameter {
1484    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1485        match &self.data_type {
1486            Some(dt) => write!(f, "{} {}", self.name, dt),
1487            None => write!(f, "{}", self.name),
1488        }
1489    }
1490}
1491
1492/// The syntax style for a lambda function.
1493#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Copy)]
1494#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1495#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1496pub enum LambdaSyntax {
1497    /// Arrow syntax: `param -> expr` or `(param1, param2) -> expr`
1498    ///
1499    /// <https://docs.databricks.com/aws/en/sql/language-manual/sql-ref-lambda-functions>
1500    ///
1501    /// Supported, but deprecated in DuckDB:
1502    /// <https://duckdb.org/docs/stable/sql/functions/lambda>
1503    Arrow,
1504    /// Lambda keyword syntax: `lambda param : expr` or `lambda param1, param2 : expr`
1505    ///
1506    /// Recommended in DuckDB:
1507    /// <https://duckdb.org/docs/stable/sql/functions/lambda>
1508    LambdaKeyword,
1509}
1510
1511/// Encapsulates the common pattern in SQL where either one unparenthesized item
1512/// such as an identifier or expression is permitted, or multiple of the same
1513/// item in a parenthesized list. For accessing items regardless of the form,
1514/// `OneOrManyWithParens` implements `Deref<Target = [T]>` and `IntoIterator`,
1515/// so you can call slice methods on it and iterate over items
1516/// # Examples
1517/// Accessing as a slice:
1518/// ```
1519/// # use sqlparser::ast::OneOrManyWithParens;
1520/// let one = OneOrManyWithParens::One("a");
1521///
1522/// assert_eq!(one[0], "a");
1523/// assert_eq!(one.len(), 1);
1524/// ```
1525/// Iterating:
1526/// ```
1527/// # use sqlparser::ast::OneOrManyWithParens;
1528/// let one = OneOrManyWithParens::One("a");
1529/// let many = OneOrManyWithParens::Many(vec!["a", "b"]);
1530///
1531/// assert_eq!(one.into_iter().chain(many).collect::<Vec<_>>(), vec!["a", "a", "b"] );
1532/// ```
1533#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1534#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1535#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1536pub enum OneOrManyWithParens<T> {
1537    /// A single `T`, unparenthesized.
1538    One(T),
1539    /// One or more `T`s, parenthesized.
1540    Many(Vec<T>),
1541}
1542
1543impl<T> Deref for OneOrManyWithParens<T> {
1544    type Target = [T];
1545
1546    fn deref(&self) -> &[T] {
1547        match self {
1548            OneOrManyWithParens::One(one) => core::slice::from_ref(one),
1549            OneOrManyWithParens::Many(many) => many,
1550        }
1551    }
1552}
1553
1554impl<T> AsRef<[T]> for OneOrManyWithParens<T> {
1555    fn as_ref(&self) -> &[T] {
1556        self
1557    }
1558}
1559
1560impl<'a, T> IntoIterator for &'a OneOrManyWithParens<T> {
1561    type Item = &'a T;
1562    type IntoIter = core::slice::Iter<'a, T>;
1563
1564    fn into_iter(self) -> Self::IntoIter {
1565        self.iter()
1566    }
1567}
1568
1569/// Owned iterator implementation of `OneOrManyWithParens`
1570#[derive(Debug, Clone)]
1571pub struct OneOrManyWithParensIntoIter<T> {
1572    inner: OneOrManyWithParensIntoIterInner<T>,
1573}
1574
1575#[derive(Debug, Clone)]
1576enum OneOrManyWithParensIntoIterInner<T> {
1577    One(core::iter::Once<T>),
1578    Many(<Vec<T> as IntoIterator>::IntoIter),
1579}
1580
1581impl<T> core::iter::FusedIterator for OneOrManyWithParensIntoIter<T>
1582where
1583    core::iter::Once<T>: core::iter::FusedIterator,
1584    <Vec<T> as IntoIterator>::IntoIter: core::iter::FusedIterator,
1585{
1586}
1587
1588impl<T> core::iter::ExactSizeIterator for OneOrManyWithParensIntoIter<T>
1589where
1590    core::iter::Once<T>: core::iter::ExactSizeIterator,
1591    <Vec<T> as IntoIterator>::IntoIter: core::iter::ExactSizeIterator,
1592{
1593}
1594
1595impl<T> core::iter::Iterator for OneOrManyWithParensIntoIter<T> {
1596    type Item = T;
1597
1598    fn next(&mut self) -> Option<Self::Item> {
1599        match &mut self.inner {
1600            OneOrManyWithParensIntoIterInner::One(one) => one.next(),
1601            OneOrManyWithParensIntoIterInner::Many(many) => many.next(),
1602        }
1603    }
1604
1605    fn size_hint(&self) -> (usize, Option<usize>) {
1606        match &self.inner {
1607            OneOrManyWithParensIntoIterInner::One(one) => one.size_hint(),
1608            OneOrManyWithParensIntoIterInner::Many(many) => many.size_hint(),
1609        }
1610    }
1611
1612    fn count(self) -> usize
1613    where
1614        Self: Sized,
1615    {
1616        match self.inner {
1617            OneOrManyWithParensIntoIterInner::One(one) => one.count(),
1618            OneOrManyWithParensIntoIterInner::Many(many) => many.count(),
1619        }
1620    }
1621
1622    fn fold<B, F>(mut self, init: B, f: F) -> B
1623    where
1624        Self: Sized,
1625        F: FnMut(B, Self::Item) -> B,
1626    {
1627        match &mut self.inner {
1628            OneOrManyWithParensIntoIterInner::One(one) => one.fold(init, f),
1629            OneOrManyWithParensIntoIterInner::Many(many) => many.fold(init, f),
1630        }
1631    }
1632}
1633
1634impl<T> core::iter::DoubleEndedIterator for OneOrManyWithParensIntoIter<T> {
1635    fn next_back(&mut self) -> Option<Self::Item> {
1636        match &mut self.inner {
1637            OneOrManyWithParensIntoIterInner::One(one) => one.next_back(),
1638            OneOrManyWithParensIntoIterInner::Many(many) => many.next_back(),
1639        }
1640    }
1641}
1642
1643impl<T> IntoIterator for OneOrManyWithParens<T> {
1644    type Item = T;
1645
1646    type IntoIter = OneOrManyWithParensIntoIter<T>;
1647
1648    fn into_iter(self) -> Self::IntoIter {
1649        let inner = match self {
1650            OneOrManyWithParens::One(one) => {
1651                OneOrManyWithParensIntoIterInner::One(core::iter::once(one))
1652            }
1653            OneOrManyWithParens::Many(many) => {
1654                OneOrManyWithParensIntoIterInner::Many(many.into_iter())
1655            }
1656        };
1657
1658        OneOrManyWithParensIntoIter { inner }
1659    }
1660}
1661
1662impl<T> fmt::Display for OneOrManyWithParens<T>
1663where
1664    T: fmt::Display,
1665{
1666    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1667        match self {
1668            OneOrManyWithParens::One(value) => write!(f, "{value}"),
1669            OneOrManyWithParens::Many(values) => {
1670                write!(f, "({})", display_comma_separated(values))
1671            }
1672        }
1673    }
1674}
1675
1676impl fmt::Display for CastFormat {
1677    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1678        match self {
1679            CastFormat::Value(v) => write!(f, "{v}"),
1680            CastFormat::ValueAtTimeZone(v, tz) => write!(f, "{v} AT TIME ZONE {tz}"),
1681        }
1682    }
1683}
1684
1685impl fmt::Display for Expr {
1686    #[cfg_attr(feature = "recursive-protection", recursive::recursive)]
1687    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1688        match self {
1689            Expr::Identifier(s) => write!(f, "{s}"),
1690            Expr::Wildcard(_) => f.write_str("*"),
1691            Expr::QualifiedWildcard(prefix, _) => write!(f, "{prefix}.*"),
1692            Expr::CompoundIdentifier(s) => write!(f, "{}", display_separated(s, ".")),
1693            Expr::CompoundFieldAccess { root, access_chain } => {
1694                write!(f, "{root}")?;
1695                for field in access_chain {
1696                    write!(f, "{field}")?;
1697                }
1698                Ok(())
1699            }
1700            Expr::IsTrue(ast) => write!(f, "{ast} IS TRUE"),
1701            Expr::IsNotTrue(ast) => write!(f, "{ast} IS NOT TRUE"),
1702            Expr::IsFalse(ast) => write!(f, "{ast} IS FALSE"),
1703            Expr::IsNotFalse(ast) => write!(f, "{ast} IS NOT FALSE"),
1704            Expr::IsNull(ast) => write!(f, "{ast} IS NULL"),
1705            Expr::IsNotNull(ast) => write!(f, "{ast} IS NOT NULL"),
1706            Expr::IsUnknown(ast) => write!(f, "{ast} IS UNKNOWN"),
1707            Expr::IsNotUnknown(ast) => write!(f, "{ast} IS NOT UNKNOWN"),
1708            Expr::InList {
1709                expr,
1710                list,
1711                negated,
1712            } => write!(
1713                f,
1714                "{} {}IN ({})",
1715                expr,
1716                if *negated { "NOT " } else { "" },
1717                display_comma_separated(list)
1718            ),
1719            Expr::InSubquery {
1720                expr,
1721                subquery,
1722                negated,
1723            } => write!(
1724                f,
1725                "{} {}IN ({})",
1726                expr,
1727                if *negated { "NOT " } else { "" },
1728                subquery
1729            ),
1730            Expr::InUnnest {
1731                expr,
1732                array_expr,
1733                negated,
1734            } => write!(
1735                f,
1736                "{} {}IN UNNEST({})",
1737                expr,
1738                if *negated { "NOT " } else { "" },
1739                array_expr
1740            ),
1741            Expr::Between {
1742                expr,
1743                negated,
1744                low,
1745                high,
1746            } => write!(
1747                f,
1748                "{} {}BETWEEN {} AND {}",
1749                expr,
1750                if *negated { "NOT " } else { "" },
1751                low,
1752                high
1753            ),
1754            Expr::BinaryOp { left, op, right } => write!(f, "{left} {op} {right}"),
1755            Expr::Like {
1756                negated,
1757                expr,
1758                pattern,
1759                escape_char,
1760                any,
1761            } => match escape_char {
1762                Some(ch) => write!(
1763                    f,
1764                    "{} {}LIKE {}{} ESCAPE {}",
1765                    expr,
1766                    if *negated { "NOT " } else { "" },
1767                    if *any { "ANY " } else { "" },
1768                    pattern,
1769                    ch
1770                ),
1771                _ => write!(
1772                    f,
1773                    "{} {}LIKE {}{}",
1774                    expr,
1775                    if *negated { "NOT " } else { "" },
1776                    if *any { "ANY " } else { "" },
1777                    pattern
1778                ),
1779            },
1780            Expr::ILike {
1781                negated,
1782                expr,
1783                pattern,
1784                escape_char,
1785                any,
1786            } => match escape_char {
1787                Some(ch) => write!(
1788                    f,
1789                    "{} {}ILIKE {}{} ESCAPE {}",
1790                    expr,
1791                    if *negated { "NOT " } else { "" },
1792                    if *any { "ANY" } else { "" },
1793                    pattern,
1794                    ch
1795                ),
1796                _ => write!(
1797                    f,
1798                    "{} {}ILIKE {}{}",
1799                    expr,
1800                    if *negated { "NOT " } else { "" },
1801                    if *any { "ANY " } else { "" },
1802                    pattern
1803                ),
1804            },
1805            Expr::RLike {
1806                negated,
1807                expr,
1808                pattern,
1809                regexp,
1810            } => write!(
1811                f,
1812                "{} {}{} {}",
1813                expr,
1814                if *negated { "NOT " } else { "" },
1815                if *regexp { "REGEXP" } else { "RLIKE" },
1816                pattern
1817            ),
1818            Expr::IsNormalized {
1819                expr,
1820                form,
1821                negated,
1822            } => {
1823                let not_ = if *negated { "NOT " } else { "" };
1824                if form.is_none() {
1825                    write!(f, "{expr} IS {not_}NORMALIZED")
1826                } else {
1827                    write!(
1828                        f,
1829                        "{} IS {}{} NORMALIZED",
1830                        expr,
1831                        not_,
1832                        form.as_ref().unwrap()
1833                    )
1834                }
1835            }
1836            Expr::SimilarTo {
1837                negated,
1838                expr,
1839                pattern,
1840                escape_char,
1841            } => match escape_char {
1842                Some(ch) => write!(
1843                    f,
1844                    "{} {}SIMILAR TO {} ESCAPE {}",
1845                    expr,
1846                    if *negated { "NOT " } else { "" },
1847                    pattern,
1848                    ch
1849                ),
1850                _ => write!(
1851                    f,
1852                    "{} {}SIMILAR TO {}",
1853                    expr,
1854                    if *negated { "NOT " } else { "" },
1855                    pattern
1856                ),
1857            },
1858            Expr::AnyOp {
1859                left,
1860                compare_op,
1861                right,
1862                is_some,
1863            } => {
1864                let add_parens = !matches!(right.as_ref(), Expr::Subquery(_));
1865                write!(
1866                    f,
1867                    "{left} {compare_op} {}{}{right}{}",
1868                    if *is_some { "SOME" } else { "ANY" },
1869                    if add_parens { "(" } else { "" },
1870                    if add_parens { ")" } else { "" },
1871                )
1872            }
1873            Expr::AllOp {
1874                left,
1875                compare_op,
1876                right,
1877            } => {
1878                let add_parens = !matches!(right.as_ref(), Expr::Subquery(_));
1879                write!(
1880                    f,
1881                    "{left} {compare_op} ALL{}{right}{}",
1882                    if add_parens { "(" } else { "" },
1883                    if add_parens { ")" } else { "" },
1884                )
1885            }
1886            Expr::UnaryOp { op, expr } => {
1887                if op == &UnaryOperator::PGPostfixFactorial {
1888                    write!(f, "{expr}{op}")
1889                } else if matches!(
1890                    op,
1891                    UnaryOperator::Not
1892                        | UnaryOperator::Hash
1893                        | UnaryOperator::AtDashAt
1894                        | UnaryOperator::DoubleAt
1895                        | UnaryOperator::QuestionDash
1896                        | UnaryOperator::QuestionPipe
1897                ) {
1898                    write!(f, "{op} {expr}")
1899                } else {
1900                    write!(f, "{op}{expr}")
1901                }
1902            }
1903            Expr::Convert {
1904                is_try,
1905                expr,
1906                target_before_value,
1907                data_type,
1908                charset,
1909                styles,
1910            } => {
1911                write!(f, "{}CONVERT(", if *is_try { "TRY_" } else { "" })?;
1912                if let Some(data_type) = data_type {
1913                    if let Some(charset) = charset {
1914                        write!(f, "{expr}, {data_type} CHARACTER SET {charset}")
1915                    } else if *target_before_value {
1916                        write!(f, "{data_type}, {expr}")
1917                    } else {
1918                        write!(f, "{expr}, {data_type}")
1919                    }
1920                } else if let Some(charset) = charset {
1921                    write!(f, "{expr} USING {charset}")
1922                } else {
1923                    write!(f, "{expr}") // This should never happen
1924                }?;
1925                if !styles.is_empty() {
1926                    write!(f, ", {}", display_comma_separated(styles))?;
1927                }
1928                write!(f, ")")
1929            }
1930            Expr::Cast {
1931                kind,
1932                expr,
1933                data_type,
1934                array,
1935                format,
1936            } => match kind {
1937                CastKind::Cast => {
1938                    write!(f, "CAST({expr} AS {data_type}")?;
1939                    if *array {
1940                        write!(f, " ARRAY")?;
1941                    }
1942                    if let Some(format) = format {
1943                        write!(f, " FORMAT {format}")?;
1944                    }
1945                    write!(f, ")")
1946                }
1947                CastKind::TryCast => {
1948                    if let Some(format) = format {
1949                        write!(f, "TRY_CAST({expr} AS {data_type} FORMAT {format})")
1950                    } else {
1951                        write!(f, "TRY_CAST({expr} AS {data_type})")
1952                    }
1953                }
1954                CastKind::SafeCast => {
1955                    if let Some(format) = format {
1956                        write!(f, "SAFE_CAST({expr} AS {data_type} FORMAT {format})")
1957                    } else {
1958                        write!(f, "SAFE_CAST({expr} AS {data_type})")
1959                    }
1960                }
1961                CastKind::DoubleColon => {
1962                    write!(f, "{expr}::{data_type}")
1963                }
1964            },
1965            Expr::Extract {
1966                field,
1967                syntax,
1968                expr,
1969            } => match syntax {
1970                ExtractSyntax::From => write!(f, "EXTRACT({field} FROM {expr})"),
1971                ExtractSyntax::Comma => write!(f, "EXTRACT({field}, {expr})"),
1972            },
1973            Expr::Ceil { expr, field } => match field {
1974                CeilFloorKind::DateTimeField(DateTimeField::NoDateTime) => {
1975                    write!(f, "CEIL({expr})")
1976                }
1977                CeilFloorKind::DateTimeField(dt_field) => write!(f, "CEIL({expr} TO {dt_field})"),
1978                CeilFloorKind::Scale(s) => write!(f, "CEIL({expr}, {s})"),
1979            },
1980            Expr::Floor { expr, field } => match field {
1981                CeilFloorKind::DateTimeField(DateTimeField::NoDateTime) => {
1982                    write!(f, "FLOOR({expr})")
1983                }
1984                CeilFloorKind::DateTimeField(dt_field) => write!(f, "FLOOR({expr} TO {dt_field})"),
1985                CeilFloorKind::Scale(s) => write!(f, "FLOOR({expr}, {s})"),
1986            },
1987            Expr::Position { expr, r#in } => write!(f, "POSITION({expr} IN {in})"),
1988            Expr::Collate { expr, collation } => write!(f, "{expr} COLLATE {collation}"),
1989            Expr::Nested(ast) => write!(f, "({ast})"),
1990            Expr::Value(v) => write!(f, "{v}"),
1991            Expr::Prefixed { prefix, value } => write!(f, "{prefix} {value}"),
1992            Expr::TypedString(ts) => ts.fmt(f),
1993            Expr::Function(fun) => fun.fmt(f),
1994            Expr::Case {
1995                case_token: _,
1996                end_token: _,
1997                operand,
1998                conditions,
1999                else_result,
2000            } => {
2001                f.write_str("CASE")?;
2002                if let Some(operand) = operand {
2003                    f.write_str(" ")?;
2004                    operand.fmt(f)?;
2005                }
2006                for when in conditions {
2007                    SpaceOrNewline.fmt(f)?;
2008                    Indent(when).fmt(f)?;
2009                }
2010                if let Some(else_result) = else_result {
2011                    SpaceOrNewline.fmt(f)?;
2012                    Indent("ELSE").fmt(f)?;
2013                    SpaceOrNewline.fmt(f)?;
2014                    Indent(Indent(else_result)).fmt(f)?;
2015                }
2016                SpaceOrNewline.fmt(f)?;
2017                f.write_str("END")
2018            }
2019            Expr::Exists { subquery, negated } => write!(
2020                f,
2021                "{}EXISTS ({})",
2022                if *negated { "NOT " } else { "" },
2023                subquery
2024            ),
2025            Expr::Subquery(s) => write!(f, "({s})"),
2026            Expr::GroupingSets(sets) => {
2027                write!(f, "GROUPING SETS (")?;
2028                let mut sep = "";
2029                for set in sets {
2030                    write!(f, "{sep}")?;
2031                    sep = ", ";
2032                    write!(f, "({})", display_comma_separated(set))?;
2033                }
2034                write!(f, ")")
2035            }
2036            Expr::Cube(sets) => {
2037                write!(f, "CUBE (")?;
2038                let mut sep = "";
2039                for set in sets {
2040                    write!(f, "{sep}")?;
2041                    sep = ", ";
2042                    if set.len() == 1 {
2043                        write!(f, "{}", set[0])?;
2044                    } else {
2045                        write!(f, "({})", display_comma_separated(set))?;
2046                    }
2047                }
2048                write!(f, ")")
2049            }
2050            Expr::Rollup(sets) => {
2051                write!(f, "ROLLUP (")?;
2052                let mut sep = "";
2053                for set in sets {
2054                    write!(f, "{sep}")?;
2055                    sep = ", ";
2056                    if set.len() == 1 {
2057                        write!(f, "{}", set[0])?;
2058                    } else {
2059                        write!(f, "({})", display_comma_separated(set))?;
2060                    }
2061                }
2062                write!(f, ")")
2063            }
2064            Expr::Substring {
2065                expr,
2066                substring_from,
2067                substring_for,
2068                special,
2069                shorthand,
2070            } => {
2071                f.write_str("SUBSTR")?;
2072                if !*shorthand {
2073                    f.write_str("ING")?;
2074                }
2075                write!(f, "({expr}")?;
2076                if let Some(from_part) = substring_from {
2077                    if *special {
2078                        write!(f, ", {from_part}")?;
2079                    } else {
2080                        write!(f, " FROM {from_part}")?;
2081                    }
2082                }
2083                if let Some(for_part) = substring_for {
2084                    if *special {
2085                        write!(f, ", {for_part}")?;
2086                    } else {
2087                        write!(f, " FOR {for_part}")?;
2088                    }
2089                }
2090
2091                write!(f, ")")
2092            }
2093            Expr::Overlay {
2094                expr,
2095                overlay_what,
2096                overlay_from,
2097                overlay_for,
2098            } => {
2099                write!(
2100                    f,
2101                    "OVERLAY({expr} PLACING {overlay_what} FROM {overlay_from}"
2102                )?;
2103                if let Some(for_part) = overlay_for {
2104                    write!(f, " FOR {for_part}")?;
2105                }
2106
2107                write!(f, ")")
2108            }
2109            Expr::IsDistinctFrom(a, b) => write!(f, "{a} IS DISTINCT FROM {b}"),
2110            Expr::IsNotDistinctFrom(a, b) => write!(f, "{a} IS NOT DISTINCT FROM {b}"),
2111            Expr::Trim {
2112                expr,
2113                trim_where,
2114                trim_what,
2115                trim_characters,
2116            } => {
2117                write!(f, "TRIM(")?;
2118                if let Some(ident) = trim_where {
2119                    write!(f, "{ident} ")?;
2120                }
2121                if let Some(trim_char) = trim_what {
2122                    write!(f, "{trim_char} FROM {expr}")?;
2123                } else {
2124                    write!(f, "{expr}")?;
2125                }
2126                if let Some(characters) = trim_characters {
2127                    write!(f, ", {}", display_comma_separated(characters))?;
2128                }
2129
2130                write!(f, ")")
2131            }
2132            Expr::Tuple(exprs) => {
2133                write!(f, "({})", display_comma_separated(exprs))
2134            }
2135            Expr::Struct { values, fields } => {
2136                if !fields.is_empty() {
2137                    write!(
2138                        f,
2139                        "STRUCT<{}>({})",
2140                        display_comma_separated(fields),
2141                        display_comma_separated(values)
2142                    )
2143                } else {
2144                    write!(f, "STRUCT({})", display_comma_separated(values))
2145                }
2146            }
2147            Expr::Named { expr, name } => {
2148                write!(f, "{expr} AS {name}")
2149            }
2150            Expr::Dictionary(fields) => {
2151                write!(f, "{{{}}}", display_comma_separated(fields))
2152            }
2153            Expr::Map(map) => {
2154                write!(f, "{map}")
2155            }
2156            Expr::Array(set) => {
2157                write!(f, "{set}")
2158            }
2159            Expr::JsonAccess { value, path } => {
2160                write!(f, "{value}{path}")
2161            }
2162            Expr::AtTimeZone {
2163                timestamp,
2164                time_zone,
2165            } => {
2166                write!(f, "{timestamp} AT TIME ZONE {time_zone}")
2167            }
2168            Expr::Interval(interval) => {
2169                write!(f, "{interval}")
2170            }
2171            Expr::MatchAgainst {
2172                columns,
2173                match_value: match_expr,
2174                opt_search_modifier,
2175            } => {
2176                write!(f, "MATCH ({}) AGAINST ", display_comma_separated(columns),)?;
2177
2178                if let Some(search_modifier) = opt_search_modifier {
2179                    write!(f, "({match_expr} {search_modifier})")?;
2180                } else {
2181                    write!(f, "({match_expr})")?;
2182                }
2183
2184                Ok(())
2185            }
2186            Expr::OuterJoin(expr) => {
2187                write!(f, "{expr} (+)")
2188            }
2189            Expr::Prior(expr) => write!(f, "PRIOR {expr}"),
2190            Expr::Lambda(lambda) => write!(f, "{lambda}"),
2191            Expr::MemberOf(member_of) => write!(f, "{member_of}"),
2192        }
2193    }
2194}
2195
2196/// The type of a window used in `OVER` clauses.
2197///
2198/// A window can be either an inline specification (`WindowSpec`) or a
2199/// reference to a previously defined named window.
2200///
2201/// - `WindowSpec(WindowSpec)`: An inline window specification, e.g.
2202///   `OVER (PARTITION BY ... ORDER BY ...)`.
2203/// - `NamedWindow(Ident)`: A reference to a named window declared elsewhere.
2204#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2205#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2206#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2207pub enum WindowType {
2208    /// An inline window specification.
2209    WindowSpec(WindowSpec),
2210    /// A reference to a previously defined named window.
2211    NamedWindow(Ident),
2212}
2213
2214impl Display for WindowType {
2215    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2216        match self {
2217            WindowType::WindowSpec(spec) => {
2218                f.write_str("(")?;
2219                NewLine.fmt(f)?;
2220                Indent(spec).fmt(f)?;
2221                NewLine.fmt(f)?;
2222                f.write_str(")")
2223            }
2224            WindowType::NamedWindow(name) => name.fmt(f),
2225        }
2226    }
2227}
2228
2229/// A window specification (i.e. `OVER ([window_name] PARTITION BY .. ORDER BY .. etc.)`)
2230#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2231#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2232#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2233pub struct WindowSpec {
2234    /// Optional window name.
2235    ///
2236    /// You can find it at least in [MySQL][1], [BigQuery][2], [PostgreSQL][3]
2237    ///
2238    /// [1]: https://dev.mysql.com/doc/refman/8.0/en/window-functions-named-windows.html
2239    /// [2]: https://cloud.google.com/bigquery/docs/reference/standard-sql/window-function-calls
2240    /// [3]: https://www.postgresql.org/docs/current/sql-expressions.html#SYNTAX-WINDOW-FUNCTIONS
2241    pub window_name: Option<Ident>,
2242    /// `OVER (PARTITION BY ...)`
2243    pub partition_by: Vec<Expr>,
2244    /// `OVER (ORDER BY ...)`
2245    pub order_by: Vec<OrderByExpr>,
2246    /// `OVER (window frame)`
2247    pub window_frame: Option<WindowFrame>,
2248}
2249
2250impl fmt::Display for WindowSpec {
2251    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2252        let mut is_first = true;
2253        if let Some(window_name) = &self.window_name {
2254            if !is_first {
2255                SpaceOrNewline.fmt(f)?;
2256            }
2257            is_first = false;
2258            write!(f, "{window_name}")?;
2259        }
2260        if !self.partition_by.is_empty() {
2261            if !is_first {
2262                SpaceOrNewline.fmt(f)?;
2263            }
2264            is_first = false;
2265            write!(
2266                f,
2267                "PARTITION BY {}",
2268                display_comma_separated(&self.partition_by)
2269            )?;
2270        }
2271        if !self.order_by.is_empty() {
2272            if !is_first {
2273                SpaceOrNewline.fmt(f)?;
2274            }
2275            is_first = false;
2276            write!(f, "ORDER BY {}", display_comma_separated(&self.order_by))?;
2277        }
2278        if let Some(window_frame) = &self.window_frame {
2279            if !is_first {
2280                SpaceOrNewline.fmt(f)?;
2281            }
2282            if let Some(end_bound) = &window_frame.end_bound {
2283                write!(
2284                    f,
2285                    "{} BETWEEN {} AND {}",
2286                    window_frame.units, window_frame.start_bound, end_bound
2287                )?;
2288            } else {
2289                write!(f, "{} {}", window_frame.units, window_frame.start_bound)?;
2290            }
2291        }
2292        Ok(())
2293    }
2294}
2295
2296/// Specifies the data processed by a window function, e.g.
2297/// `RANGE UNBOUNDED PRECEDING` or `ROWS BETWEEN 5 PRECEDING AND CURRENT ROW`.
2298///
2299/// Note: The parser does not validate the specified bounds; the caller should
2300/// reject invalid bounds like `ROWS UNBOUNDED FOLLOWING` before execution.
2301#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2302#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2303#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2304pub struct WindowFrame {
2305    /// Units for the frame (e.g. `ROWS`, `RANGE`, `GROUPS`).
2306    pub units: WindowFrameUnits,
2307    /// The start bound of the window frame.
2308    pub start_bound: WindowFrameBound,
2309    /// The right bound of the `BETWEEN .. AND` clause. The end bound of `None`
2310    /// indicates the shorthand form (e.g. `ROWS 1 PRECEDING`), which must
2311    /// behave the same as `end_bound = WindowFrameBound::CurrentRow`.
2312    pub end_bound: Option<WindowFrameBound>,
2313    // TBD: EXCLUDE
2314}
2315
2316impl Default for WindowFrame {
2317    /// Returns default value for window frame
2318    ///
2319    /// See [this page](https://www.sqlite.org/windowfunctions.html#frame_specifications) for more details.
2320    fn default() -> Self {
2321        Self {
2322            units: WindowFrameUnits::Range,
2323            start_bound: WindowFrameBound::Preceding(None),
2324            end_bound: None,
2325        }
2326    }
2327}
2328
2329#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2330#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2331#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2332/// Units used to describe the window frame scope.
2333pub enum WindowFrameUnits {
2334    /// `ROWS` unit.
2335    Rows,
2336    /// `RANGE` unit.
2337    Range,
2338    /// `GROUPS` unit.
2339    Groups,
2340}
2341
2342impl fmt::Display for WindowFrameUnits {
2343    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2344        f.write_str(match self {
2345            WindowFrameUnits::Rows => "ROWS",
2346            WindowFrameUnits::Range => "RANGE",
2347            WindowFrameUnits::Groups => "GROUPS",
2348        })
2349    }
2350}
2351
2352/// Specifies Ignore / Respect NULL within window functions.
2353/// For example
2354/// `FIRST_VALUE(column2) IGNORE NULLS OVER (PARTITION BY column1)`
2355#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2356#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2357#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2358/// How NULL values are treated in certain window functions.
2359pub enum NullTreatment {
2360    /// Ignore NULL values (e.g. `IGNORE NULLS`).
2361    IgnoreNulls,
2362    /// Respect NULL values (e.g. `RESPECT NULLS`).
2363    RespectNulls,
2364}
2365
2366impl fmt::Display for NullTreatment {
2367    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2368        f.write_str(match self {
2369            NullTreatment::IgnoreNulls => "IGNORE NULLS",
2370            NullTreatment::RespectNulls => "RESPECT NULLS",
2371        })
2372    }
2373}
2374
2375/// Specifies [WindowFrame]'s `start_bound` and `end_bound`
2376#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2377#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2378#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2379pub enum WindowFrameBound {
2380    /// `CURRENT ROW`
2381    CurrentRow,
2382    /// `<N> PRECEDING` or `UNBOUNDED PRECEDING`
2383    Preceding(Option<Box<Expr>>),
2384    /// `<N> FOLLOWING` or `UNBOUNDED FOLLOWING`.
2385    Following(Option<Box<Expr>>),
2386}
2387
2388impl fmt::Display for WindowFrameBound {
2389    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2390        match self {
2391            WindowFrameBound::CurrentRow => f.write_str("CURRENT ROW"),
2392            WindowFrameBound::Preceding(None) => f.write_str("UNBOUNDED PRECEDING"),
2393            WindowFrameBound::Following(None) => f.write_str("UNBOUNDED FOLLOWING"),
2394            WindowFrameBound::Preceding(Some(n)) => write!(f, "{n} PRECEDING"),
2395            WindowFrameBound::Following(Some(n)) => write!(f, "{n} FOLLOWING"),
2396        }
2397    }
2398}
2399
2400#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2401#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2402#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2403/// Indicates partition operation type for partition management statements.
2404pub enum AddDropSync {
2405    /// Add partitions.
2406    ADD,
2407    /// Drop partitions.
2408    DROP,
2409    /// Sync partitions.
2410    SYNC,
2411}
2412
2413impl fmt::Display for AddDropSync {
2414    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2415        match self {
2416            AddDropSync::SYNC => f.write_str("SYNC PARTITIONS"),
2417            AddDropSync::DROP => f.write_str("DROP PARTITIONS"),
2418            AddDropSync::ADD => f.write_str("ADD PARTITIONS"),
2419        }
2420    }
2421}
2422
2423#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2424#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2425#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2426/// Object kinds supported by `SHOW CREATE` statements.
2427pub enum ShowCreateObject {
2428    /// An event object for `SHOW CREATE EVENT`.
2429    Event,
2430    /// A function object for `SHOW CREATE FUNCTION`.
2431    Function,
2432    /// A procedure object for `SHOW CREATE PROCEDURE`.
2433    Procedure,
2434    /// A table object for `SHOW CREATE TABLE`.
2435    Table,
2436    /// A trigger object for `SHOW CREATE TRIGGER`.
2437    Trigger,
2438    /// A view object for `SHOW CREATE VIEW`.
2439    View,
2440}
2441
2442impl fmt::Display for ShowCreateObject {
2443    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2444        match self {
2445            ShowCreateObject::Event => f.write_str("EVENT"),
2446            ShowCreateObject::Function => f.write_str("FUNCTION"),
2447            ShowCreateObject::Procedure => f.write_str("PROCEDURE"),
2448            ShowCreateObject::Table => f.write_str("TABLE"),
2449            ShowCreateObject::Trigger => f.write_str("TRIGGER"),
2450            ShowCreateObject::View => f.write_str("VIEW"),
2451        }
2452    }
2453}
2454
2455#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2456#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2457#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2458/// Objects that can be targeted by a `COMMENT` statement.
2459pub enum CommentObject {
2460    /// A collation.
2461    Collation,
2462    /// A table column.
2463    Column,
2464    /// A database.
2465    Database,
2466    /// A domain.
2467    Domain,
2468    /// An extension.
2469    Extension,
2470    /// A function.
2471    Function,
2472    /// An index.
2473    Index,
2474    /// A materialized view.
2475    MaterializedView,
2476    /// A procedure.
2477    Procedure,
2478    /// A role.
2479    Role,
2480    /// A schema.
2481    Schema,
2482    /// A sequence.
2483    Sequence,
2484    /// A table.
2485    Table,
2486    /// A type.
2487    Type,
2488    /// A user.
2489    User,
2490    /// A view.
2491    View,
2492}
2493
2494impl fmt::Display for CommentObject {
2495    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2496        match self {
2497            CommentObject::Collation => f.write_str("COLLATION"),
2498            CommentObject::Column => f.write_str("COLUMN"),
2499            CommentObject::Database => f.write_str("DATABASE"),
2500            CommentObject::Domain => f.write_str("DOMAIN"),
2501            CommentObject::Extension => f.write_str("EXTENSION"),
2502            CommentObject::Function => f.write_str("FUNCTION"),
2503            CommentObject::Index => f.write_str("INDEX"),
2504            CommentObject::MaterializedView => f.write_str("MATERIALIZED VIEW"),
2505            CommentObject::Procedure => f.write_str("PROCEDURE"),
2506            CommentObject::Role => f.write_str("ROLE"),
2507            CommentObject::Schema => f.write_str("SCHEMA"),
2508            CommentObject::Sequence => f.write_str("SEQUENCE"),
2509            CommentObject::Table => f.write_str("TABLE"),
2510            CommentObject::Type => f.write_str("TYPE"),
2511            CommentObject::User => f.write_str("USER"),
2512            CommentObject::View => f.write_str("VIEW"),
2513        }
2514    }
2515}
2516
2517#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2518#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2519#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2520/// Password specification variants used in user-related statements.
2521pub enum Password {
2522    /// A concrete password expression.
2523    Password(Expr),
2524    /// Represents a `NULL` password.
2525    NullPassword,
2526}
2527
2528/// A `CASE` statement.
2529///
2530/// Examples:
2531/// ```sql
2532/// CASE
2533///     WHEN EXISTS(SELECT 1)
2534///         THEN SELECT 1 FROM T;
2535///     WHEN EXISTS(SELECT 2)
2536///         THEN SELECT 1 FROM U;
2537///     ELSE
2538///         SELECT 1 FROM V;
2539/// END CASE;
2540/// ```
2541///
2542/// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#case_search_expression)
2543/// [Snowflake](https://docs.snowflake.com/en/sql-reference/snowflake-scripting/case)
2544#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2545#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2546#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2547pub struct CaseStatement {
2548    /// The `CASE` token that starts the statement.
2549    pub case_token: AttachedToken,
2550    /// Optional expression to match against in `CASE ... WHEN`.
2551    pub match_expr: Option<Expr>,
2552    /// The `WHEN ... THEN` blocks of the `CASE` statement.
2553    pub when_blocks: Vec<ConditionalStatementBlock>,
2554    /// Optional `ELSE` block for the `CASE` statement.
2555    pub else_block: Option<ConditionalStatementBlock>,
2556    /// The last token of the statement (`END` or `CASE`).
2557    pub end_case_token: AttachedToken,
2558}
2559
2560impl fmt::Display for CaseStatement {
2561    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2562        let CaseStatement {
2563            case_token: _,
2564            match_expr,
2565            when_blocks,
2566            else_block,
2567            end_case_token: AttachedToken(end),
2568        } = self;
2569
2570        write!(f, "CASE")?;
2571
2572        if let Some(expr) = match_expr {
2573            write!(f, " {expr}")?;
2574        }
2575
2576        if !when_blocks.is_empty() {
2577            write!(f, " {}", display_separated(when_blocks, " "))?;
2578        }
2579
2580        if let Some(else_block) = else_block {
2581            write!(f, " {else_block}")?;
2582        }
2583
2584        write!(f, " END")?;
2585
2586        if let Token::Word(w) = &end.token {
2587            if w.keyword == Keyword::CASE {
2588                write!(f, " CASE")?;
2589            }
2590        }
2591
2592        Ok(())
2593    }
2594}
2595
2596/// An `IF` statement.
2597///
2598/// Example (BigQuery or Snowflake):
2599/// ```sql
2600/// IF TRUE THEN
2601///     SELECT 1;
2602///     SELECT 2;
2603/// ELSEIF TRUE THEN
2604///     SELECT 3;
2605/// ELSE
2606///     SELECT 4;
2607/// END IF
2608/// ```
2609/// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#if)
2610/// [Snowflake](https://docs.snowflake.com/en/sql-reference/snowflake-scripting/if)
2611///
2612/// Example (MSSQL):
2613/// ```sql
2614/// IF 1=1 SELECT 1 ELSE SELECT 2
2615/// ```
2616/// [MSSQL](https://learn.microsoft.com/en-us/sql/t-sql/language-elements/if-else-transact-sql?view=sql-server-ver16)
2617#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2618#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2619#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2620pub struct IfStatement {
2621    /// The initial `IF` block containing the condition and statements.
2622    pub if_block: ConditionalStatementBlock,
2623    /// Additional `ELSEIF` blocks.
2624    pub elseif_blocks: Vec<ConditionalStatementBlock>,
2625    /// Optional `ELSE` block.
2626    pub else_block: Option<ConditionalStatementBlock>,
2627    /// Optional trailing `END` token for the `IF` statement.
2628    pub end_token: Option<AttachedToken>,
2629}
2630
2631impl fmt::Display for IfStatement {
2632    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2633        let IfStatement {
2634            if_block,
2635            elseif_blocks,
2636            else_block,
2637            end_token,
2638        } = self;
2639
2640        write!(f, "{if_block}")?;
2641
2642        for elseif_block in elseif_blocks {
2643            write!(f, " {elseif_block}")?;
2644        }
2645
2646        if let Some(else_block) = else_block {
2647            write!(f, " {else_block}")?;
2648        }
2649
2650        if let Some(AttachedToken(end_token)) = end_token {
2651            write!(f, " END {end_token}")?;
2652        }
2653
2654        Ok(())
2655    }
2656}
2657
2658/// A `WHILE` statement.
2659///
2660/// Example:
2661/// ```sql
2662/// WHILE @@FETCH_STATUS = 0
2663/// BEGIN
2664///    FETCH NEXT FROM c1 INTO @var1, @var2;
2665/// END
2666/// ```
2667///
2668/// [MsSql](https://learn.microsoft.com/en-us/sql/t-sql/language-elements/while-transact-sql)
2669#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2670#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2671#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2672pub struct WhileStatement {
2673    /// Block executed while the condition holds.
2674    pub while_block: ConditionalStatementBlock,
2675}
2676
2677impl fmt::Display for WhileStatement {
2678    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2679        let WhileStatement { while_block } = self;
2680        write!(f, "{while_block}")?;
2681        Ok(())
2682    }
2683}
2684
2685/// A block within a [Statement::Case] or [Statement::If] or [Statement::While]-like statement
2686///
2687/// Example 1:
2688/// ```sql
2689/// WHEN EXISTS(SELECT 1) THEN SELECT 1;
2690/// ```
2691///
2692/// Example 2:
2693/// ```sql
2694/// IF TRUE THEN SELECT 1; SELECT 2;
2695/// ```
2696///
2697/// Example 3:
2698/// ```sql
2699/// ELSE SELECT 1; SELECT 2;
2700/// ```
2701///
2702/// Example 4:
2703/// ```sql
2704/// WHILE @@FETCH_STATUS = 0
2705/// BEGIN
2706///    FETCH NEXT FROM c1 INTO @var1, @var2;
2707/// END
2708/// ```
2709#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2710#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2711#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2712pub struct ConditionalStatementBlock {
2713    /// Token representing the start of the block (e.g., WHEN/IF/WHILE).
2714    pub start_token: AttachedToken,
2715    /// Optional condition expression for the block.
2716    pub condition: Option<Expr>,
2717    /// Optional token for the `THEN` keyword.
2718    pub then_token: Option<AttachedToken>,
2719    /// The statements contained in this conditional block.
2720    pub conditional_statements: ConditionalStatements,
2721}
2722
2723impl ConditionalStatementBlock {
2724    /// Get the statements in this conditional block.
2725    pub fn statements(&self) -> &Vec<Statement> {
2726        self.conditional_statements.statements()
2727    }
2728}
2729
2730impl fmt::Display for ConditionalStatementBlock {
2731    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2732        let ConditionalStatementBlock {
2733            start_token: AttachedToken(start_token),
2734            condition,
2735            then_token,
2736            conditional_statements,
2737        } = self;
2738
2739        write!(f, "{start_token}")?;
2740
2741        if let Some(condition) = condition {
2742            write!(f, " {condition}")?;
2743        }
2744
2745        if then_token.is_some() {
2746            write!(f, " THEN")?;
2747        }
2748
2749        if !conditional_statements.statements().is_empty() {
2750            write!(f, " {conditional_statements}")?;
2751        }
2752
2753        Ok(())
2754    }
2755}
2756
2757/// A list of statements in a [ConditionalStatementBlock].
2758#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2759#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2760#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2761/// Statements used inside conditional blocks (`IF`, `WHEN`, `WHILE`).
2762pub enum ConditionalStatements {
2763    /// Simple sequence of statements (no `BEGIN`/`END`).
2764    Sequence {
2765        /// The statements in the sequence.
2766        statements: Vec<Statement>,
2767    },
2768    /// Block enclosed by `BEGIN` and `END`.
2769    BeginEnd(BeginEndStatements),
2770}
2771
2772impl ConditionalStatements {
2773    /// Get the statements in this conditional statements block.
2774    pub fn statements(&self) -> &Vec<Statement> {
2775        match self {
2776            ConditionalStatements::Sequence { statements } => statements,
2777            ConditionalStatements::BeginEnd(bes) => &bes.statements,
2778        }
2779    }
2780}
2781
2782impl fmt::Display for ConditionalStatements {
2783    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2784        match self {
2785            ConditionalStatements::Sequence { statements } => {
2786                if !statements.is_empty() {
2787                    format_statement_list(f, statements)?;
2788                }
2789                Ok(())
2790            }
2791            ConditionalStatements::BeginEnd(bes) => write!(f, "{bes}"),
2792        }
2793    }
2794}
2795
2796/// Represents a list of statements enclosed within `BEGIN` and `END` keywords.
2797/// Example:
2798/// ```sql
2799/// BEGIN
2800///     SELECT 1;
2801///     SELECT 2;
2802/// END
2803/// ```
2804#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2805#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2806#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2807pub struct BeginEndStatements {
2808    /// Token representing the `BEGIN` keyword (may include span info).
2809    pub begin_token: AttachedToken,
2810    /// Statements contained within the block.
2811    pub statements: Vec<Statement>,
2812    /// Token representing the `END` keyword (may include span info).
2813    pub end_token: AttachedToken,
2814}
2815
2816impl fmt::Display for BeginEndStatements {
2817    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2818        let BeginEndStatements {
2819            begin_token: AttachedToken(begin_token),
2820            statements,
2821            end_token: AttachedToken(end_token),
2822        } = self;
2823
2824        if begin_token.token != Token::EOF {
2825            write!(f, "{begin_token} ")?;
2826        }
2827        if !statements.is_empty() {
2828            format_statement_list(f, statements)?;
2829        }
2830        if end_token.token != Token::EOF {
2831            write!(f, " {end_token}")?;
2832        }
2833        Ok(())
2834    }
2835}
2836
2837/// A `RAISE` statement.
2838///
2839/// Examples:
2840/// ```sql
2841/// RAISE USING MESSAGE = 'error';
2842///
2843/// RAISE myerror;
2844/// ```
2845///
2846/// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#raise)
2847/// [Snowflake](https://docs.snowflake.com/en/sql-reference/snowflake-scripting/raise)
2848#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2849#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2850#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2851pub struct RaiseStatement {
2852    /// Optional value provided to the RAISE statement.
2853    pub value: Option<RaiseStatementValue>,
2854}
2855
2856impl fmt::Display for RaiseStatement {
2857    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2858        let RaiseStatement { value } = self;
2859
2860        write!(f, "RAISE")?;
2861        if let Some(value) = value {
2862            write!(f, " {value}")?;
2863        }
2864
2865        Ok(())
2866    }
2867}
2868
2869/// Represents the error value of a [RaiseStatement].
2870#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2871#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2872#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2873pub enum RaiseStatementValue {
2874    /// `RAISE USING MESSAGE = 'error'`
2875    UsingMessage(Expr),
2876    /// `RAISE myerror`
2877    Expr(Expr),
2878}
2879
2880impl fmt::Display for RaiseStatementValue {
2881    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2882        match self {
2883            RaiseStatementValue::Expr(expr) => write!(f, "{expr}"),
2884            RaiseStatementValue::UsingMessage(expr) => write!(f, "USING MESSAGE = {expr}"),
2885        }
2886    }
2887}
2888
2889/// A MSSQL `THROW` statement.
2890///
2891/// ```sql
2892/// THROW [ error_number, message, state ]
2893/// ```
2894///
2895/// [MSSQL](https://learn.microsoft.com/en-us/sql/t-sql/language-elements/throw-transact-sql)
2896#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2897#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2898#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2899pub struct ThrowStatement {
2900    /// Error number expression.
2901    pub error_number: Option<Box<Expr>>,
2902    /// Error message expression.
2903    pub message: Option<Box<Expr>>,
2904    /// State expression.
2905    pub state: Option<Box<Expr>>,
2906}
2907
2908impl fmt::Display for ThrowStatement {
2909    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2910        let ThrowStatement {
2911            error_number,
2912            message,
2913            state,
2914        } = self;
2915
2916        write!(f, "THROW")?;
2917        if let (Some(error_number), Some(message), Some(state)) = (error_number, message, state) {
2918            write!(f, " {error_number}, {message}, {state}")?;
2919        }
2920        Ok(())
2921    }
2922}
2923
2924/// Represents an expression assignment within a variable `DECLARE` statement.
2925///
2926/// Examples:
2927/// ```sql
2928/// DECLARE variable_name := 42
2929/// DECLARE variable_name DEFAULT 42
2930/// ```
2931#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2932#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2933#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2934pub enum DeclareAssignment {
2935    /// Plain expression specified.
2936    Expr(Box<Expr>),
2937
2938    /// Expression assigned via the `DEFAULT` keyword
2939    Default(Box<Expr>),
2940
2941    /// Expression assigned via the `:=` syntax
2942    ///
2943    /// Example:
2944    /// ```sql
2945    /// DECLARE variable_name := 42;
2946    /// ```
2947    DuckAssignment(Box<Expr>),
2948
2949    /// Expression via the `FOR` keyword
2950    ///
2951    /// Example:
2952    /// ```sql
2953    /// DECLARE c1 CURSOR FOR res
2954    /// ```
2955    For(Box<Expr>),
2956
2957    /// Expression via the `=` syntax.
2958    ///
2959    /// Example:
2960    /// ```sql
2961    /// DECLARE @variable AS INT = 100
2962    /// ```
2963    MsSqlAssignment(Box<Expr>),
2964}
2965
2966impl fmt::Display for DeclareAssignment {
2967    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2968        match self {
2969            DeclareAssignment::Expr(expr) => {
2970                write!(f, "{expr}")
2971            }
2972            DeclareAssignment::Default(expr) => {
2973                write!(f, "DEFAULT {expr}")
2974            }
2975            DeclareAssignment::DuckAssignment(expr) => {
2976                write!(f, ":= {expr}")
2977            }
2978            DeclareAssignment::MsSqlAssignment(expr) => {
2979                write!(f, "= {expr}")
2980            }
2981            DeclareAssignment::For(expr) => {
2982                write!(f, "FOR {expr}")
2983            }
2984        }
2985    }
2986}
2987
2988/// Represents the type of a `DECLARE` statement.
2989#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2990#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2991#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2992pub enum DeclareType {
2993    /// Cursor variable type. e.g. [Snowflake] [PostgreSQL] [MsSql]
2994    ///
2995    /// [Snowflake]: https://docs.snowflake.com/en/developer-guide/snowflake-scripting/cursors#declaring-a-cursor
2996    /// [PostgreSQL]: https://www.postgresql.org/docs/current/plpgsql-cursors.html
2997    /// [MsSql]: https://learn.microsoft.com/en-us/sql/t-sql/language-elements/declare-cursor-transact-sql
2998    Cursor,
2999
3000    /// Result set variable type. [Snowflake]
3001    ///
3002    /// Syntax:
3003    /// ```text
3004    /// <resultset_name> RESULTSET [ { DEFAULT | := } ( <query> ) ] ;
3005    /// ```
3006    /// [Snowflake]: https://docs.snowflake.com/en/sql-reference/snowflake-scripting/declare#resultset-declaration-syntax
3007    ResultSet,
3008
3009    /// Exception declaration syntax. [Snowflake]
3010    ///
3011    /// Syntax:
3012    /// ```text
3013    /// <exception_name> EXCEPTION [ ( <exception_number> , '<exception_message>' ) ] ;
3014    /// ```
3015    /// [Snowflake]: https://docs.snowflake.com/en/sql-reference/snowflake-scripting/declare#exception-declaration-syntax
3016    Exception,
3017}
3018
3019impl fmt::Display for DeclareType {
3020    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3021        match self {
3022            DeclareType::Cursor => {
3023                write!(f, "CURSOR")
3024            }
3025            DeclareType::ResultSet => {
3026                write!(f, "RESULTSET")
3027            }
3028            DeclareType::Exception => {
3029                write!(f, "EXCEPTION")
3030            }
3031        }
3032    }
3033}
3034
3035/// A `DECLARE` statement.
3036/// [PostgreSQL] [Snowflake] [BigQuery]
3037///
3038/// Examples:
3039/// ```sql
3040/// DECLARE variable_name := 42
3041/// DECLARE liahona CURSOR FOR SELECT * FROM films;
3042/// ```
3043///
3044/// [PostgreSQL]: https://www.postgresql.org/docs/current/sql-declare.html
3045/// [Snowflake]: https://docs.snowflake.com/en/sql-reference/snowflake-scripting/declare
3046/// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#declare
3047#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3048#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3049#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3050pub struct Declare {
3051    /// The name(s) being declared.
3052    /// Example: `DECLARE a, b, c DEFAULT 42;
3053    pub names: Vec<Ident>,
3054    /// Data-type assigned to the declared variable.
3055    /// Example: `DECLARE x INT64 DEFAULT 42;
3056    pub data_type: Option<DataType>,
3057    /// Expression being assigned to the declared variable.
3058    pub assignment: Option<DeclareAssignment>,
3059    /// Represents the type of the declared variable.
3060    pub declare_type: Option<DeclareType>,
3061    /// Causes the cursor to return data in binary rather than in text format.
3062    pub binary: Option<bool>,
3063    /// None = Not specified
3064    /// Some(true) = INSENSITIVE
3065    /// Some(false) = ASENSITIVE
3066    pub sensitive: Option<bool>,
3067    /// None = Not specified
3068    /// Some(true) = SCROLL
3069    /// Some(false) = NO SCROLL
3070    pub scroll: Option<bool>,
3071    /// None = Not specified
3072    /// Some(true) = WITH HOLD, specifies that the cursor can continue to be used after the transaction that created it successfully commits
3073    /// Some(false) = WITHOUT HOLD, specifies that the cursor cannot be used outside of the transaction that created it
3074    pub hold: Option<bool>,
3075    /// `FOR <query>` clause in a CURSOR declaration.
3076    pub for_query: Option<Box<Query>>,
3077}
3078
3079impl fmt::Display for Declare {
3080    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3081        let Declare {
3082            names,
3083            data_type,
3084            assignment,
3085            declare_type,
3086            binary,
3087            sensitive,
3088            scroll,
3089            hold,
3090            for_query,
3091        } = self;
3092        write!(f, "{}", display_comma_separated(names))?;
3093
3094        if let Some(true) = binary {
3095            write!(f, " BINARY")?;
3096        }
3097
3098        if let Some(sensitive) = sensitive {
3099            if *sensitive {
3100                write!(f, " INSENSITIVE")?;
3101            } else {
3102                write!(f, " ASENSITIVE")?;
3103            }
3104        }
3105
3106        if let Some(scroll) = scroll {
3107            if *scroll {
3108                write!(f, " SCROLL")?;
3109            } else {
3110                write!(f, " NO SCROLL")?;
3111            }
3112        }
3113
3114        if let Some(declare_type) = declare_type {
3115            write!(f, " {declare_type}")?;
3116        }
3117
3118        if let Some(hold) = hold {
3119            if *hold {
3120                write!(f, " WITH HOLD")?;
3121            } else {
3122                write!(f, " WITHOUT HOLD")?;
3123            }
3124        }
3125
3126        if let Some(query) = for_query {
3127            write!(f, " FOR {query}")?;
3128        }
3129
3130        if let Some(data_type) = data_type {
3131            write!(f, " {data_type}")?;
3132        }
3133
3134        if let Some(expr) = assignment {
3135            write!(f, " {expr}")?;
3136        }
3137        Ok(())
3138    }
3139}
3140
3141/// Sql options of a `CREATE TABLE` statement.
3142#[derive(Debug, Default, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3143#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3144#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3145/// Options allowed within a `CREATE TABLE` statement.
3146pub enum CreateTableOptions {
3147    /// No options specified.
3148    #[default]
3149    None,
3150    /// Options specified using the `WITH` keyword, e.g. `WITH (k = v)`.
3151    With(Vec<SqlOption>),
3152    /// Options specified using the `OPTIONS(...)` clause.
3153    Options(Vec<SqlOption>),
3154    /// Plain space-separated options.
3155    Plain(Vec<SqlOption>),
3156    /// Table properties (e.g., TBLPROPERTIES / storage properties).
3157    TableProperties(Vec<SqlOption>),
3158}
3159
3160impl fmt::Display for CreateTableOptions {
3161    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3162        match self {
3163            CreateTableOptions::With(with_options) => {
3164                write!(f, "WITH ({})", display_comma_separated(with_options))
3165            }
3166            CreateTableOptions::Options(options) => {
3167                write!(f, "OPTIONS({})", display_comma_separated(options))
3168            }
3169            CreateTableOptions::TableProperties(options) => {
3170                write!(f, "TBLPROPERTIES ({})", display_comma_separated(options))
3171            }
3172            CreateTableOptions::Plain(options) => {
3173                write!(f, "{}", display_separated(options, " "))
3174            }
3175            CreateTableOptions::None => Ok(()),
3176        }
3177    }
3178}
3179
3180/// A `FROM` clause within a `DELETE` statement.
3181///
3182/// Syntax
3183/// ```sql
3184/// [FROM] table
3185/// ```
3186#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3187#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3188#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3189pub enum FromTable {
3190    /// An explicit `FROM` keyword was specified.
3191    WithFromKeyword(Vec<TableWithJoins>),
3192    /// BigQuery: `FROM` keyword was omitted.
3193    /// <https://cloud.google.com/bigquery/docs/reference/standard-sql/dml-syntax#delete_statement>
3194    WithoutKeyword(Vec<TableWithJoins>),
3195}
3196impl Display for FromTable {
3197    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3198        match self {
3199            FromTable::WithFromKeyword(tables) => {
3200                write!(f, "FROM {}", display_comma_separated(tables))
3201            }
3202            FromTable::WithoutKeyword(tables) => {
3203                write!(f, "{}", display_comma_separated(tables))
3204            }
3205        }
3206    }
3207}
3208
3209#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3210#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3211#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3212/// Variants for the `SET` family of statements.
3213pub enum Set {
3214    /// SQL Standard-style
3215    /// SET a = 1;
3216    /// `SET var = value` (standard SQL-style assignment).
3217    SingleAssignment {
3218        /// Optional scope modifier (`SESSION` / `LOCAL`).
3219        scope: Option<ContextModifier>,
3220        /// Whether this is a Hive-style `HIVEVAR:` assignment.
3221        hivevar: bool,
3222        /// Variable name to assign.
3223        variable: ObjectName,
3224        /// Values assigned to the variable.
3225        values: Vec<Expr>,
3226    },
3227    /// Snowflake-style
3228    /// SET (a, b, ..) = (1, 2, ..);
3229    /// `SET (a, b) = (1, 2)` (tuple assignment syntax).
3230    ParenthesizedAssignments {
3231        /// Variables being assigned in tuple form.
3232        variables: Vec<ObjectName>,
3233        /// Corresponding values for the variables.
3234        values: Vec<Expr>,
3235    },
3236    /// MySQL-style
3237    /// SET a = 1, b = 2, ..;
3238    /// `SET a = 1, b = 2` (MySQL-style comma-separated assignments).
3239    MultipleAssignments {
3240        /// List of `SET` assignments (MySQL-style comma-separated).
3241        assignments: Vec<SetAssignment>,
3242    },
3243    /// Session authorization for Postgres/Redshift
3244    ///
3245    /// ```sql
3246    /// SET SESSION AUTHORIZATION { user_name | DEFAULT }
3247    /// ```
3248    ///
3249    /// See <https://www.postgresql.org/docs/current/sql-set-session-authorization.html>
3250    /// See <https://docs.aws.amazon.com/redshift/latest/dg/r_SET_SESSION_AUTHORIZATION.html>
3251    SetSessionAuthorization(SetSessionAuthorizationParam),
3252    /// MS-SQL session
3253    ///
3254    /// See <https://learn.microsoft.com/en-us/sql/t-sql/statements/set-statements-transact-sql>
3255    SetSessionParam(SetSessionParamKind),
3256    /// ```sql
3257    /// SET [ SESSION | LOCAL ] ROLE role_name
3258    /// ```
3259    ///
3260    /// Sets session state. Examples: [ANSI][1], [Postgresql][2], [MySQL][3], and [Oracle][4]
3261    ///
3262    /// [1]: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#set-role-statement
3263    /// [2]: https://www.postgresql.org/docs/14/sql-set-role.html
3264    /// [3]: https://dev.mysql.com/doc/refman/8.0/en/set-role.html
3265    /// [4]: https://docs.oracle.com/cd/B19306_01/server.102/b14200/statements_10004.htm
3266    SetRole {
3267        /// Non-ANSI optional identifier to inform if the role is defined inside the current session (`SESSION`) or transaction (`LOCAL`).
3268        context_modifier: Option<ContextModifier>,
3269        /// Role name. If NONE is specified, then the current role name is removed.
3270        role_name: Option<Ident>,
3271    },
3272    /// ```sql
3273    /// SET TIME ZONE <value>
3274    /// ```
3275    ///
3276    /// Note: this is a PostgreSQL-specific statements
3277    /// `SET TIME ZONE <value>` is an alias for `SET timezone TO <value>` in PostgreSQL
3278    /// However, we allow it for all dialects.
3279    /// `SET TIME ZONE` statement. `local` indicates the `LOCAL` keyword.
3280    /// `SET TIME ZONE <value>` statement.
3281    SetTimeZone {
3282        /// Whether the `LOCAL` keyword was specified.
3283        local: bool,
3284        /// Time zone expression value.
3285        value: Expr,
3286    },
3287    /// ```sql
3288    /// SET NAMES 'charset_name' [COLLATE 'collation_name']
3289    /// ```
3290    SetNames {
3291        /// Character set name to set.
3292        charset_name: Ident,
3293        /// Optional collation name.
3294        collation_name: Option<String>,
3295    },
3296    /// ```sql
3297    /// SET NAMES DEFAULT
3298    /// ```
3299    ///
3300    /// Note: this is a MySQL-specific statement.
3301    SetNamesDefault {},
3302    /// ```sql
3303    /// SET TRANSACTION ...
3304    /// ```
3305    SetTransaction {
3306        /// Transaction modes (e.g., ISOLATION LEVEL, READ ONLY).
3307        modes: Vec<TransactionMode>,
3308        /// Optional snapshot value for transaction snapshot control.
3309        snapshot: Option<ValueWithSpan>,
3310        /// `true` when the `SESSION` keyword was used.
3311        session: bool,
3312    },
3313}
3314
3315impl Display for Set {
3316    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3317        match self {
3318            Self::ParenthesizedAssignments { variables, values } => write!(
3319                f,
3320                "SET ({}) = ({})",
3321                display_comma_separated(variables),
3322                display_comma_separated(values)
3323            ),
3324            Self::MultipleAssignments { assignments } => {
3325                write!(f, "SET {}", display_comma_separated(assignments))
3326            }
3327            Self::SetRole {
3328                context_modifier,
3329                role_name,
3330            } => {
3331                let role_name = role_name.clone().unwrap_or_else(|| Ident::new("NONE"));
3332                write!(
3333                    f,
3334                    "SET {modifier}ROLE {role_name}",
3335                    modifier = context_modifier.map(|m| format!("{m}")).unwrap_or_default()
3336                )
3337            }
3338            Self::SetSessionAuthorization(kind) => write!(f, "SET SESSION AUTHORIZATION {kind}"),
3339            Self::SetSessionParam(kind) => write!(f, "SET {kind}"),
3340            Self::SetTransaction {
3341                modes,
3342                snapshot,
3343                session,
3344            } => {
3345                if *session {
3346                    write!(f, "SET SESSION CHARACTERISTICS AS TRANSACTION")?;
3347                } else {
3348                    write!(f, "SET TRANSACTION")?;
3349                }
3350                if !modes.is_empty() {
3351                    write!(f, " {}", display_comma_separated(modes))?;
3352                }
3353                if let Some(snapshot_id) = snapshot {
3354                    write!(f, " SNAPSHOT {snapshot_id}")?;
3355                }
3356                Ok(())
3357            }
3358            Self::SetTimeZone { local, value } => {
3359                f.write_str("SET ")?;
3360                if *local {
3361                    f.write_str("LOCAL ")?;
3362                }
3363                write!(f, "TIME ZONE {value}")
3364            }
3365            Self::SetNames {
3366                charset_name,
3367                collation_name,
3368            } => {
3369                write!(f, "SET NAMES {charset_name}")?;
3370
3371                if let Some(collation) = collation_name {
3372                    f.write_str(" COLLATE ")?;
3373                    f.write_str(collation)?;
3374                };
3375
3376                Ok(())
3377            }
3378            Self::SetNamesDefault {} => {
3379                f.write_str("SET NAMES DEFAULT")?;
3380
3381                Ok(())
3382            }
3383            Set::SingleAssignment {
3384                scope,
3385                hivevar,
3386                variable,
3387                values,
3388            } => {
3389                write!(
3390                    f,
3391                    "SET {}{}{} = {}",
3392                    scope.map(|s| format!("{s}")).unwrap_or_default(),
3393                    if *hivevar { "HIVEVAR:" } else { "" },
3394                    variable,
3395                    display_comma_separated(values)
3396                )
3397            }
3398        }
3399    }
3400}
3401
3402/// A representation of a `WHEN` arm with all the identifiers catched and the statements to execute
3403/// for the arm.
3404///
3405/// Snowflake: <https://docs.snowflake.com/en/sql-reference/snowflake-scripting/exception>
3406/// BigQuery: <https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#beginexceptionend>
3407#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3408#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3409#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3410pub struct ExceptionWhen {
3411    /// Identifiers that trigger this branch (error conditions).
3412    pub idents: Vec<Ident>,
3413    /// Statements to execute when the condition matches.
3414    pub statements: Vec<Statement>,
3415}
3416
3417impl Display for ExceptionWhen {
3418    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3419        write!(
3420            f,
3421            "WHEN {idents} THEN",
3422            idents = display_separated(&self.idents, " OR ")
3423        )?;
3424
3425        if !self.statements.is_empty() {
3426            write!(f, " ")?;
3427            format_statement_list(f, &self.statements)?;
3428        }
3429
3430        Ok(())
3431    }
3432}
3433
3434/// ANALYZE statement
3435///
3436/// Supported syntax varies by dialect:
3437/// - Hive: `ANALYZE TABLE t [PARTITION (...)] COMPUTE STATISTICS [NOSCAN] [FOR COLUMNS [col1, ...]] [CACHE METADATA]`
3438/// - PostgreSQL: `ANALYZE [VERBOSE] [t [(col1, ...)]]` See <https://www.postgresql.org/docs/current/sql-analyze.html>
3439/// - General: `ANALYZE [TABLE] t`
3440#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3441#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3442#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3443pub struct Analyze {
3444    #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
3445    /// Name of the table to analyze. `None` for bare `ANALYZE`.
3446    pub table_name: Option<ObjectName>,
3447    /// Optional partition expressions to restrict the analysis.
3448    pub partitions: Option<Vec<Expr>>,
3449    /// `true` when analyzing specific columns (Hive `FOR COLUMNS` syntax).
3450    pub for_columns: bool,
3451    /// Columns to analyze.
3452    pub columns: Vec<Ident>,
3453    /// Whether to cache metadata before analyzing.
3454    pub cache_metadata: bool,
3455    /// Whether to skip scanning the table.
3456    pub noscan: bool,
3457    /// Whether to compute statistics during analysis.
3458    pub compute_statistics: bool,
3459    /// Whether the `TABLE` keyword was present.
3460    pub has_table_keyword: bool,
3461}
3462
3463impl fmt::Display for Analyze {
3464    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3465        write!(f, "ANALYZE")?;
3466        if let Some(ref table_name) = self.table_name {
3467            if self.has_table_keyword {
3468                write!(f, " TABLE")?;
3469            }
3470            write!(f, " {table_name}")?;
3471        }
3472        if !self.for_columns && !self.columns.is_empty() {
3473            write!(f, " ({})", display_comma_separated(&self.columns))?;
3474        }
3475        if let Some(ref parts) = self.partitions {
3476            if !parts.is_empty() {
3477                write!(f, " PARTITION ({})", display_comma_separated(parts))?;
3478            }
3479        }
3480        if self.compute_statistics {
3481            write!(f, " COMPUTE STATISTICS")?;
3482        }
3483        if self.noscan {
3484            write!(f, " NOSCAN")?;
3485        }
3486        if self.cache_metadata {
3487            write!(f, " CACHE METADATA")?;
3488        }
3489        if self.for_columns {
3490            write!(f, " FOR COLUMNS")?;
3491            if !self.columns.is_empty() {
3492                write!(f, " {}", display_comma_separated(&self.columns))?;
3493            }
3494        }
3495        Ok(())
3496    }
3497}
3498
3499/// A top-level statement (SELECT, INSERT, CREATE, etc.)
3500#[allow(clippy::large_enum_variant)]
3501#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3502#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3503#[cfg_attr(
3504    feature = "visitor",
3505    derive(Visit, VisitMut),
3506    visit(with = "visit_statement")
3507)]
3508pub enum Statement {
3509    /// ```sql
3510    /// ANALYZE
3511    /// ```
3512    /// Analyze (Hive)
3513    Analyze(Analyze),
3514    /// `SET` statements (session, transaction, timezone, etc.).
3515    Set(Set),
3516    /// ```sql
3517    /// TRUNCATE
3518    /// ```
3519    /// Truncate (Hive)
3520    Truncate(Truncate),
3521    /// ```sql
3522    /// MSCK
3523    /// ```
3524    /// Msck (Hive)
3525    Msck(Msck),
3526    /// ```sql
3527    /// SELECT
3528    /// ```
3529    Query(Box<Query>),
3530    /// ```sql
3531    /// INSERT
3532    /// ```
3533    Insert(Insert),
3534    /// ```sql
3535    /// INSTALL
3536    /// ```
3537    Install {
3538        /// Only for DuckDB
3539        extension_name: Ident,
3540    },
3541    /// ```sql
3542    /// LOAD
3543    /// ```
3544    Load {
3545        /// Only for DuckDB
3546        extension_name: Ident,
3547    },
3548    // TODO: Support ROW FORMAT
3549    /// LOAD DATA from a directory or query source.
3550    Directory {
3551        /// Whether to overwrite existing files.
3552        overwrite: bool,
3553        /// Whether the directory is local to the server.
3554        local: bool,
3555        /// Path to the directory or files.
3556        path: String,
3557        /// Optional file format for the data.
3558        file_format: Option<FileFormat>,
3559        /// Source query providing data to load.
3560        source: Box<Query>,
3561    },
3562    /// A `CASE` statement.
3563    Case(CaseStatement),
3564    /// An `IF` statement.
3565    If(IfStatement),
3566    /// A `WHILE` statement.
3567    While(WhileStatement),
3568    /// A `RAISE` statement.
3569    Raise(RaiseStatement),
3570    /// ```sql
3571    /// CALL <function>
3572    /// ```
3573    Call(Function),
3574    /// ```sql
3575    /// COPY [TO | FROM] ...
3576    /// ```
3577    Copy {
3578        /// The source of 'COPY TO', or the target of 'COPY FROM'
3579        source: CopySource,
3580        /// If true, is a 'COPY TO' statement. If false is a 'COPY FROM'
3581        to: bool,
3582        /// The target of 'COPY TO', or the source of 'COPY FROM'
3583        target: CopyTarget,
3584        /// WITH options (from PostgreSQL version 9.0)
3585        options: Vec<CopyOption>,
3586        /// WITH options (before PostgreSQL version 9.0)
3587        legacy_options: Vec<CopyLegacyOption>,
3588        /// VALUES a vector of values to be copied
3589        values: Vec<Option<String>>,
3590    },
3591    /// ```sql
3592    /// COPY INTO <table> | <location>
3593    /// ```
3594    /// See:
3595    /// <https://docs.snowflake.com/en/sql-reference/sql/copy-into-table>
3596    /// <https://docs.snowflake.com/en/sql-reference/sql/copy-into-location>
3597    ///
3598    /// Copy Into syntax available for Snowflake is different than the one implemented in
3599    /// Postgres. Although they share common prefix, it is reasonable to implement them
3600    /// in different enums. This can be refactored later once custom dialects
3601    /// are allowed to have custom Statements.
3602    CopyIntoSnowflake {
3603        /// Kind of COPY INTO operation (table or location).
3604        kind: CopyIntoSnowflakeKind,
3605        /// Target object for the COPY INTO operation.
3606        into: ObjectName,
3607        /// Optional list of target columns.
3608        into_columns: Option<Vec<Ident>>,
3609        /// Optional source object name (staged data).
3610        from_obj: Option<ObjectName>,
3611        /// Optional alias for the source object.
3612        from_obj_alias: Option<Ident>,
3613        /// Stage-specific parameters (e.g., credentials, path).
3614        stage_params: StageParamsObject,
3615        /// Optional list of transformations applied when loading.
3616        from_transformations: Option<Vec<StageLoadSelectItemKind>>,
3617        /// Optional source query instead of a staged object.
3618        from_query: Option<Box<Query>>,
3619        /// Optional list of specific file names to load.
3620        files: Option<Vec<String>>,
3621        /// Optional filename matching pattern.
3622        pattern: Option<String>,
3623        /// File format options.
3624        file_format: KeyValueOptions,
3625        /// Additional copy options.
3626        copy_options: KeyValueOptions,
3627        /// Optional validation mode string.
3628        validation_mode: Option<String>,
3629        /// Optional partition expression for loading.
3630        partition: Option<Box<Expr>>,
3631    },
3632    /// ```sql
3633    /// OPEN cursor_name
3634    /// ```
3635    /// Opens a cursor.
3636    Open(OpenStatement),
3637    /// ```sql
3638    /// CLOSE
3639    /// ```
3640    /// Closes the portal underlying an open cursor.
3641    Close {
3642        /// Cursor name
3643        cursor: CloseCursor,
3644    },
3645    /// ```sql
3646    /// UPDATE
3647    /// ```
3648    Update(Update),
3649    /// ```sql
3650    /// DELETE
3651    /// ```
3652    Delete(Delete),
3653    /// ```sql
3654    /// CREATE VIEW
3655    /// ```
3656    CreateView(CreateView),
3657    /// ```sql
3658    /// CREATE TABLE
3659    /// ```
3660    CreateTable(CreateTable),
3661    /// ```sql
3662    /// CREATE VIRTUAL TABLE .. USING <module_name> (<module_args>)`
3663    /// ```
3664    /// Sqlite specific statement
3665    CreateVirtualTable {
3666        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
3667        /// Name of the virtual table module instance.
3668        name: ObjectName,
3669        /// `true` when `IF NOT EXISTS` was specified.
3670        if_not_exists: bool,
3671        /// Module name used by the virtual table.
3672        module_name: Ident,
3673        /// Arguments passed to the module.
3674        module_args: Vec<Ident>,
3675    },
3676    /// ```sql
3677    /// `CREATE INDEX`
3678    /// ```
3679    CreateIndex(CreateIndex),
3680    /// ```sql
3681    /// CREATE ROLE
3682    /// ```
3683    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createrole.html)
3684    CreateRole(CreateRole),
3685    /// ```sql
3686    /// CREATE SECRET
3687    /// ```
3688    /// See [DuckDB](https://duckdb.org/docs/sql/statements/create_secret.html)
3689    CreateSecret {
3690        /// `true` when `OR REPLACE` was specified.
3691        or_replace: bool,
3692        /// Optional `TEMPORARY` flag.
3693        temporary: Option<bool>,
3694        /// `true` when `IF NOT EXISTS` was present.
3695        if_not_exists: bool,
3696        /// Optional secret name.
3697        name: Option<Ident>,
3698        /// Optional storage specifier identifier.
3699        storage_specifier: Option<Ident>,
3700        /// The secret type identifier.
3701        secret_type: Ident,
3702        /// Additional secret options.
3703        options: Vec<SecretOption>,
3704    },
3705    /// A `CREATE SERVER` statement.
3706    CreateServer(CreateServerStatement),
3707    /// ```sql
3708    /// CREATE FOREIGN DATA WRAPPER
3709    /// ```
3710    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createforeigndatawrapper.html)
3711    CreateForeignDataWrapper(CreateForeignDataWrapper),
3712    /// ```sql
3713    /// CREATE FOREIGN TABLE
3714    /// ```
3715    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createforeigntable.html)
3716    CreateForeignTable(CreateForeignTable),
3717    /// ```sql
3718    /// CREATE POLICY
3719    /// ```
3720    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createpolicy.html)
3721    CreatePolicy(CreatePolicy),
3722    /// ```sql
3723    /// CREATE CONNECTOR
3724    /// ```
3725    /// See [Hive](https://cwiki.apache.org/confluence/pages/viewpage.action?pageId=27362034#LanguageManualDDL-CreateDataConnectorCreateConnector)
3726    CreateConnector(CreateConnector),
3727    /// ```sql
3728    /// CREATE OPERATOR
3729    /// ```
3730    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createoperator.html)
3731    CreateOperator(CreateOperator),
3732    /// ```sql
3733    /// CREATE OPERATOR FAMILY
3734    /// ```
3735    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createopfamily.html)
3736    CreateOperatorFamily(CreateOperatorFamily),
3737    /// ```sql
3738    /// CREATE OPERATOR CLASS
3739    /// ```
3740    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createopclass.html)
3741    CreateOperatorClass(CreateOperatorClass),
3742    /// ```sql
3743    /// CREATE AGGREGATE
3744    /// ```
3745    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createaggregate.html)
3746    CreateAggregate(CreateAggregate),
3747    /// ```sql
3748    /// ALTER TABLE
3749    /// ```
3750    AlterTable(AlterTable),
3751    /// ```sql
3752    /// ALTER SCHEMA
3753    /// ```
3754    /// See [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#alter_schema_collate_statement)
3755    AlterSchema(AlterSchema),
3756    /// ```sql
3757    /// ALTER INDEX
3758    /// ```
3759    AlterIndex {
3760        /// Name of the index to alter.
3761        name: ObjectName,
3762        /// The operation to perform on the index.
3763        operation: AlterIndexOperation,
3764    },
3765    /// ```sql
3766    /// ALTER VIEW
3767    /// ```
3768    AlterView {
3769        /// View name being altered.
3770        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
3771        name: ObjectName,
3772        /// Optional new column list for the view.
3773        columns: Vec<Ident>,
3774        /// Replacement query for the view definition.
3775        query: Box<Query>,
3776        /// Additional WITH options for the view.
3777        with_options: Vec<SqlOption>,
3778    },
3779    /// ```sql
3780    /// ALTER DOMAIN
3781    /// ```
3782    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-alterdomain.html)
3783    AlterDomain(AlterDomain),
3784    /// ```sql
3785    /// ALTER EXTENSION
3786    /// ```
3787    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-alterextension.html)
3788    AlterExtension(AlterExtension),
3789    /// ```sql
3790    /// ALTER FUNCTION
3791    /// ALTER AGGREGATE
3792    /// ALTER PROCEDURE
3793    /// ```
3794    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-alterfunction.html)
3795    /// and [PostgreSQL](https://www.postgresql.org/docs/current/sql-alteraggregate.html)
3796    /// and [PostgreSQL](https://www.postgresql.org/docs/current/sql-alterprocedure.html)
3797    AlterFunction(AlterFunction),
3798    /// ```sql
3799    /// ALTER TYPE
3800    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-altertype.html)
3801    /// ```
3802    AlterType(AlterType),
3803    /// ```sql
3804    /// ALTER TRIGGER
3805    /// ```
3806    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-altertrigger.html)
3807    AlterTrigger(AlterTrigger),
3808    /// ```sql
3809    /// ALTER COLLATION
3810    /// ```
3811    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-altercollation.html)
3812    AlterCollation(AlterCollation),
3813    /// ```sql
3814    /// ALTER OPERATOR
3815    /// ```
3816    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-alteroperator.html)
3817    AlterOperator(AlterOperator),
3818    /// ```sql
3819    /// ALTER OPERATOR FAMILY
3820    /// ```
3821    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-alteropfamily.html)
3822    AlterOperatorFamily(AlterOperatorFamily),
3823    /// ```sql
3824    /// ALTER OPERATOR CLASS
3825    /// ```
3826    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-alteropclass.html)
3827    AlterOperatorClass(AlterOperatorClass),
3828    /// ```sql
3829    /// ALTER ROLE
3830    /// ```
3831    AlterRole {
3832        /// Role name being altered.
3833        name: Ident,
3834        /// Operation to perform on the role.
3835        operation: AlterRoleOperation,
3836    },
3837    /// ```sql
3838    /// ALTER POLICY <NAME> ON <TABLE NAME> [<OPERATION>]
3839    /// ```
3840    /// (Postgresql-specific)
3841    AlterPolicy(AlterPolicy),
3842    /// ```sql
3843    /// ALTER CONNECTOR connector_name SET DCPROPERTIES(property_name=property_value, ...);
3844    /// or
3845    /// ALTER CONNECTOR connector_name SET URL new_url;
3846    /// or
3847    /// ALTER CONNECTOR connector_name SET OWNER [USER|ROLE] user_or_role;
3848    /// ```
3849    /// (Hive-specific)
3850    AlterConnector {
3851        /// Name of the connector to alter.
3852        name: Ident,
3853        /// Optional connector properties to set.
3854        properties: Option<Vec<SqlOption>>,
3855        /// Optional new URL for the connector.
3856        url: Option<String>,
3857        /// Optional new owner specification.
3858        owner: Option<ddl::AlterConnectorOwner>,
3859    },
3860    /// ```sql
3861    /// ALTER SESSION SET sessionParam
3862    /// ALTER SESSION UNSET <param_name> [ , <param_name> , ... ]
3863    /// ```
3864    /// See <https://docs.snowflake.com/en/sql-reference/sql/alter-session>
3865    AlterSession {
3866        /// true is to set for the session parameters, false is to unset
3867        set: bool,
3868        /// The session parameters to set or unset
3869        session_params: KeyValueOptions,
3870    },
3871    /// ```sql
3872    /// ATTACH DATABASE 'path/to/file' AS alias
3873    /// ```
3874    /// (SQLite-specific)
3875    AttachDatabase {
3876        /// The name to bind to the newly attached database
3877        schema_name: Ident,
3878        /// An expression that indicates the path to the database file
3879        database_file_name: Expr,
3880        /// true if the syntax is 'ATTACH DATABASE', false if it's just 'ATTACH'
3881        database: bool,
3882    },
3883    /// (DuckDB-specific)
3884    /// ```sql
3885    /// ATTACH 'sqlite_file.db' AS sqlite_db (READ_ONLY, TYPE SQLITE);
3886    /// ```
3887    /// See <https://duckdb.org/docs/sql/statements/attach.html>
3888    AttachDuckDBDatabase {
3889        /// `true` when `IF NOT EXISTS` was present.
3890        if_not_exists: bool,
3891        /// `true` if the syntax used `ATTACH DATABASE` rather than `ATTACH`.
3892        database: bool,
3893        /// The path identifier to the database file being attached.
3894        database_path: Ident,
3895        /// Optional alias assigned to the attached database.
3896        database_alias: Option<Ident>,
3897        /// Dialect-specific attach options (e.g., `READ_ONLY`).
3898        attach_options: Vec<AttachDuckDBDatabaseOption>,
3899    },
3900    /// (DuckDB-specific)
3901    /// ```sql
3902    /// DETACH db_alias;
3903    /// ```
3904    /// See <https://duckdb.org/docs/sql/statements/attach.html>
3905    DetachDuckDBDatabase {
3906        /// `true` when `IF EXISTS` was present.
3907        if_exists: bool,
3908        /// `true` if the syntax used `DETACH DATABASE` rather than `DETACH`.
3909        database: bool,
3910        /// Alias of the database to detach.
3911        database_alias: Ident,
3912    },
3913    /// ```sql
3914    /// DROP [TABLE, VIEW, ...]
3915    /// ```
3916    Drop {
3917        /// The type of the object to drop: TABLE, VIEW, etc.
3918        object_type: ObjectType,
3919        /// An optional `IF EXISTS` clause. (Non-standard.)
3920        if_exists: bool,
3921        /// One or more objects to drop. (ANSI SQL requires exactly one.)
3922        names: Vec<ObjectName>,
3923        /// Whether `CASCADE` was specified. This will be `false` when
3924        /// `RESTRICT` or no drop behavior at all was specified.
3925        cascade: bool,
3926        /// Whether `RESTRICT` was specified. This will be `false` when
3927        /// `CASCADE` or no drop behavior at all was specified.
3928        restrict: bool,
3929        /// Hive allows you specify whether the table's stored data will be
3930        /// deleted along with the dropped table
3931        purge: bool,
3932        /// MySQL-specific "TEMPORARY" keyword
3933        temporary: bool,
3934        /// MySQL-specific drop index syntax, which requires table specification
3935        /// See <https://dev.mysql.com/doc/refman/8.4/en/drop-index.html>
3936        table: Option<ObjectName>,
3937    },
3938    /// ```sql
3939    /// DROP FUNCTION
3940    /// ```
3941    DropFunction(DropFunction),
3942    /// ```sql
3943    /// DROP DOMAIN
3944    /// ```
3945    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-dropdomain.html)
3946    ///
3947    /// DROP DOMAIN [ IF EXISTS ] name [, ...] [ CASCADE | RESTRICT ]
3948    ///
3949    DropDomain(DropDomain),
3950    /// ```sql
3951    /// DROP PROCEDURE
3952    /// ```
3953    DropProcedure {
3954        /// `true` when `IF EXISTS` was present.
3955        if_exists: bool,
3956        /// One or more functions/procedures to drop.
3957        proc_desc: Vec<FunctionDesc>,
3958        /// Optional drop behavior (`CASCADE` or `RESTRICT`).
3959        drop_behavior: Option<DropBehavior>,
3960    },
3961    /// ```sql
3962    /// DROP SECRET
3963    /// ```
3964    DropSecret {
3965        /// `true` when `IF EXISTS` was present.
3966        if_exists: bool,
3967        /// Optional `TEMPORARY` marker.
3968        temporary: Option<bool>,
3969        /// Name of the secret to drop.
3970        name: Ident,
3971        /// Optional storage specifier identifier.
3972        storage_specifier: Option<Ident>,
3973    },
3974    ///```sql
3975    /// DROP POLICY
3976    /// ```
3977    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-droppolicy.html)
3978    DropPolicy(DropPolicy),
3979    /// ```sql
3980    /// DROP CONNECTOR
3981    /// ```
3982    /// See [Hive](https://cwiki.apache.org/confluence/pages/viewpage.action?pageId=27362034#LanguageManualDDL-DropConnector)
3983    DropConnector {
3984        /// `true` when `IF EXISTS` was present.
3985        if_exists: bool,
3986        /// Name of the connector to drop.
3987        name: Ident,
3988    },
3989    /// ```sql
3990    /// DECLARE
3991    /// ```
3992    /// Declare Cursor Variables
3993    ///
3994    /// Note: this is a PostgreSQL-specific statement,
3995    /// but may also compatible with other SQL.
3996    Declare {
3997        /// Cursor declaration statements collected by `DECLARE`.
3998        stmts: Vec<Declare>,
3999    },
4000    /// ```sql
4001    /// CREATE EXTENSION [ IF NOT EXISTS ] extension_name
4002    ///     [ WITH ] [ SCHEMA schema_name ]
4003    ///              [ VERSION version ]
4004    ///              [ CASCADE ]
4005    /// ```
4006    ///
4007    /// Note: this is a PostgreSQL-specific statement,
4008    CreateExtension(CreateExtension),
4009    /// ```sql
4010    /// CREATE COLLATION
4011    /// ```
4012    /// Note: this is a PostgreSQL-specific statement.
4013    /// <https://www.postgresql.org/docs/current/sql-createcollation.html>
4014    CreateCollation(CreateCollation),
4015    /// ```sql
4016    /// CREATE TEXT SEARCH CONFIGURATION name ( PARSER = parser_name )
4017    /// ```
4018    /// Note: this is a PostgreSQL-specific statement.
4019    /// <https://www.postgresql.org/docs/current/sql-createtsconfig.html>
4020    CreateTextSearchConfiguration(CreateTextSearchConfiguration),
4021    /// ```sql
4022    /// CREATE TEXT SEARCH DICTIONARY name ( TEMPLATE = template_name [, option = value, ...] )
4023    /// ```
4024    /// Note: this is a PostgreSQL-specific statement.
4025    /// <https://www.postgresql.org/docs/current/sql-createtsdictionary.html>
4026    CreateTextSearchDictionary(CreateTextSearchDictionary),
4027    /// ```sql
4028    /// CREATE TEXT SEARCH PARSER name ( START = start_fn, GETTOKEN = gettoken_fn, END = end_fn, LEXTYPES = lextypes_fn [, HEADLINE = headline_fn] )
4029    /// ```
4030    /// Note: this is a PostgreSQL-specific statement.
4031    /// <https://www.postgresql.org/docs/current/sql-createtsparser.html>
4032    CreateTextSearchParser(CreateTextSearchParser),
4033    /// ```sql
4034    /// CREATE TEXT SEARCH TEMPLATE name ( [INIT = init_fn,] LEXIZE = lexize_fn )
4035    /// ```
4036    /// Note: this is a PostgreSQL-specific statement.
4037    /// <https://www.postgresql.org/docs/current/sql-createtstemplate.html>
4038    CreateTextSearchTemplate(CreateTextSearchTemplate),
4039    /// ```sql
4040    /// CREATE PUBLICATION name [ FOR ALL TABLES | FOR TABLE table [, ...] | FOR TABLES IN SCHEMA schema [, ...] ] [ WITH ( option = value [, ...] ) ]
4041    /// ```
4042    /// Note: this is a PostgreSQL-specific statement.
4043    /// <https://www.postgresql.org/docs/current/sql-createpublication.html>
4044    CreatePublication(CreatePublication),
4045    /// ```sql
4046    /// CREATE SUBSCRIPTION name CONNECTION 'conninfo' PUBLICATION publication_name [, ...] [ WITH ( option = value [, ...] ) ]
4047    /// ```
4048    /// Note: this is a PostgreSQL-specific statement.
4049    /// <https://www.postgresql.org/docs/current/sql-createsubscription.html>
4050    CreateSubscription(CreateSubscription),
4051    /// ```sql
4052    /// DROP EXTENSION [ IF EXISTS ] name [, ...] [ CASCADE | RESTRICT ]
4053    /// ```
4054    /// Note: this is a PostgreSQL-specific statement.
4055    /// <https://www.postgresql.org/docs/current/sql-dropextension.html>
4056    DropExtension(DropExtension),
4057    /// ```sql
4058    /// DROP OPERATOR [ IF EXISTS ] name ( { left_type | NONE } , right_type ) [, ...] [ CASCADE | RESTRICT ]
4059    /// ```
4060    /// Note: this is a PostgreSQL-specific statement.
4061    /// <https://www.postgresql.org/docs/current/sql-dropoperator.html>
4062    DropOperator(DropOperator),
4063    /// ```sql
4064    /// DROP OPERATOR FAMILY [ IF EXISTS ] name USING index_method [ CASCADE | RESTRICT ]
4065    /// ```
4066    /// Note: this is a PostgreSQL-specific statement.
4067    /// <https://www.postgresql.org/docs/current/sql-dropopfamily.html>
4068    DropOperatorFamily(DropOperatorFamily),
4069    /// ```sql
4070    /// DROP OPERATOR CLASS [ IF EXISTS ] name USING index_method [ CASCADE | RESTRICT ]
4071    /// ```
4072    /// Note: this is a PostgreSQL-specific statement.
4073    /// <https://www.postgresql.org/docs/current/sql-dropopclass.html>
4074    DropOperatorClass(DropOperatorClass),
4075    /// ```sql
4076    /// FETCH
4077    /// ```
4078    /// Retrieve rows from a query using a cursor
4079    ///
4080    /// Note: this is a PostgreSQL-specific statement,
4081    /// but may also compatible with other SQL.
4082    Fetch {
4083        /// Cursor name
4084        name: Ident,
4085        /// The fetch direction (e.g., `FORWARD`, `BACKWARD`).
4086        direction: FetchDirection,
4087        /// The fetch position (e.g., `ALL`, `NEXT`, `ABSOLUTE`).
4088        position: FetchPosition,
4089        /// Optional target table to fetch rows into.
4090        into: Option<ObjectName>,
4091    },
4092    /// ```sql
4093    /// FLUSH [NO_WRITE_TO_BINLOG | LOCAL] flush_option [, flush_option] ... | tables_option
4094    /// ```
4095    ///
4096    /// Note: this is a Mysql-specific statement,
4097    /// but may also compatible with other SQL.
4098    Flush {
4099        /// The specific flush option or object to flush.
4100        object_type: FlushType,
4101        /// Optional flush location (dialect-specific).
4102        location: Option<FlushLocation>,
4103        /// Optional channel name used for flush operations.
4104        channel: Option<String>,
4105        /// Whether a read lock was requested.
4106        read_lock: bool,
4107        /// Whether this is an export flush operation.
4108        export: bool,
4109        /// Optional list of tables involved in the flush.
4110        tables: Vec<ObjectName>,
4111    },
4112    /// ```sql
4113    /// DISCARD [ ALL | PLANS | SEQUENCES | TEMPORARY | TEMP ]
4114    /// ```
4115    ///
4116    /// Note: this is a PostgreSQL-specific statement,
4117    /// but may also compatible with other SQL.
4118    Discard {
4119        /// The kind of object(s) to discard (ALL, PLANS, etc.).
4120        object_type: DiscardObject,
4121    },
4122    /// `SHOW FUNCTIONS`
4123    ///
4124    /// Note: this is a Presto-specific statement.
4125    ShowFunctions {
4126        /// Optional filter for which functions to display.
4127        filter: Option<ShowStatementFilter>,
4128    },
4129    /// ```sql
4130    /// SHOW <variable>
4131    /// ```
4132    ///
4133    /// Note: this is a PostgreSQL-specific statement.
4134    ShowVariable {
4135        /// Variable name as one or more identifiers.
4136        variable: Vec<Ident>,
4137    },
4138    /// ```sql
4139    /// SHOW [GLOBAL | SESSION] STATUS [LIKE 'pattern' | WHERE expr]
4140    /// ```
4141    ///
4142    /// Note: this is a MySQL-specific statement.
4143    ShowStatus {
4144        /// Optional filter for which status entries to display.
4145        filter: Option<ShowStatementFilter>,
4146        /// `true` when `GLOBAL` scope was requested.
4147        global: bool,
4148        /// `true` when `SESSION` scope was requested.
4149        session: bool,
4150    },
4151    /// ```sql
4152    /// SHOW VARIABLES
4153    /// ```
4154    ///
4155    /// Note: this is a MySQL-specific statement.
4156    ShowVariables {
4157        /// Optional filter for which variables to display.
4158        filter: Option<ShowStatementFilter>,
4159        /// `true` when `GLOBAL` scope was requested.
4160        global: bool,
4161        /// `true` when `SESSION` scope was requested.
4162        session: bool,
4163    },
4164    /// ```sql
4165    /// SHOW CREATE TABLE
4166    /// ```
4167    ///
4168    /// Note: this is a MySQL-specific statement.
4169    ShowCreate {
4170        /// The kind of object being shown (TABLE, VIEW, etc.).
4171        obj_type: ShowCreateObject,
4172        /// The name of the object to show create statement for.
4173        obj_name: ObjectName,
4174    },
4175    /// ```sql
4176    /// SHOW COLUMNS
4177    /// ```
4178    ShowColumns {
4179        /// `true` when extended column information was requested.
4180        extended: bool,
4181        /// `true` when full column details were requested.
4182        full: bool,
4183        /// Additional options for `SHOW COLUMNS`.
4184        show_options: ShowStatementOptions,
4185    },
4186    /// ```sql
4187    /// SHOW CATALOGS
4188    /// ```
4189    ShowCatalogs {
4190        /// `true` when terse output format was requested.
4191        terse: bool,
4192        /// `true` when history information was requested.
4193        history: bool,
4194        /// Additional options for `SHOW CATALOGS`.
4195        show_options: ShowStatementOptions,
4196    },
4197    /// ```sql
4198    /// SHOW DATABASES
4199    /// ```
4200    ShowDatabases {
4201        /// `true` when terse output format was requested.
4202        terse: bool,
4203        /// `true` when history information was requested.
4204        history: bool,
4205        /// Additional options for `SHOW DATABASES`.
4206        show_options: ShowStatementOptions,
4207    },
4208    /// ```sql
4209    /// SHOW [FULL] PROCESSLIST
4210    /// ```
4211    ///
4212    /// Note: this is a MySQL-specific statement.
4213    ShowProcessList {
4214        /// `true` when full process information was requested.
4215        full: bool,
4216    },
4217    /// ```sql
4218    /// SHOW SCHEMAS
4219    /// ```
4220    ShowSchemas {
4221        /// `true` when terse (compact) output was requested.
4222        terse: bool,
4223        /// `true` when history information was requested.
4224        history: bool,
4225        /// Additional options for `SHOW SCHEMAS`.
4226        show_options: ShowStatementOptions,
4227    },
4228    // ```sql
4229    // SHOW {CHARACTER SET | CHARSET}
4230    // ```
4231    // [MySQL]:
4232    // <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>
4233    /// Show the available character sets (alias `CHARSET`).
4234    ShowCharset(ShowCharset),
4235    /// ```sql
4236    /// SHOW OBJECTS LIKE 'line%' IN mydb.public
4237    /// ```
4238    /// Snowflake-specific statement
4239    /// <https://docs.snowflake.com/en/sql-reference/sql/show-objects>
4240    ShowObjects(ShowObjects),
4241    /// ```sql
4242    /// SHOW TABLES
4243    /// ```
4244    ShowTables {
4245        /// `true` when terse output format was requested (compact listing).
4246        terse: bool,
4247        /// `true` when history rows are requested.
4248        history: bool,
4249        /// `true` when extended information should be shown.
4250        extended: bool,
4251        /// `true` when a full listing was requested.
4252        full: bool,
4253        /// `true` when external tables should be included.
4254        external: bool,
4255        /// Additional options for `SHOW` statements.
4256        show_options: ShowStatementOptions,
4257    },
4258    /// ```sql
4259    /// SHOW VIEWS
4260    /// ```
4261    ShowViews {
4262        /// `true` when terse output format was requested.
4263        terse: bool,
4264        /// `true` when materialized views should be included.
4265        materialized: bool,
4266        /// Additional options for `SHOW` statements.
4267        show_options: ShowStatementOptions,
4268    },
4269    /// ```sql
4270    /// SHOW COLLATION
4271    /// ```
4272    ///
4273    /// Note: this is a MySQL-specific statement.
4274    ShowCollation {
4275        /// Optional filter for which collations to display.
4276        filter: Option<ShowStatementFilter>,
4277    },
4278    /// ```sql
4279    /// `USE ...`
4280    /// ```
4281    Use(Use),
4282    /// ```sql
4283    /// START  [ TRANSACTION | WORK ] | START TRANSACTION } ...
4284    /// ```
4285    /// If `begin` is false.
4286    ///
4287    /// ```sql
4288    /// `BEGIN  [ TRANSACTION | WORK ] | START TRANSACTION } ...`
4289    /// ```
4290    /// If `begin` is true
4291    StartTransaction {
4292        /// Transaction modes such as `ISOLATION LEVEL` or `READ WRITE`.
4293        modes: Vec<TransactionMode>,
4294        /// `true` when this was parsed as `BEGIN` instead of `START`.
4295        begin: bool,
4296        /// Optional specific keyword used: `TRANSACTION` or `WORK`.
4297        transaction: Option<BeginTransactionKind>,
4298        /// Optional transaction modifier (e.g., `AND NO CHAIN`).
4299        modifier: Option<TransactionModifier>,
4300        /// List of statements belonging to the `BEGIN` block.
4301        /// Example:
4302        /// ```sql
4303        /// BEGIN
4304        ///     SELECT 1;
4305        ///     SELECT 2;
4306        /// END;
4307        /// ```
4308        statements: Vec<Statement>,
4309        /// Exception handling with exception clauses.
4310        /// Example:
4311        /// ```sql
4312        /// EXCEPTION
4313        ///     WHEN EXCEPTION_1 THEN
4314        ///         SELECT 2;
4315        ///     WHEN EXCEPTION_2 OR EXCEPTION_3 THEN
4316        ///         SELECT 3;
4317        ///     WHEN OTHER THEN
4318        ///         SELECT 4;
4319        /// ```
4320        /// <https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#beginexceptionend>
4321        /// <https://docs.snowflake.com/en/sql-reference/snowflake-scripting/exception>
4322        exception: Option<Vec<ExceptionWhen>>,
4323        /// TRUE if the statement has an `END` keyword.
4324        has_end_keyword: bool,
4325    },
4326    /// ```sql
4327    /// COMMENT ON ...
4328    /// ```
4329    ///
4330    /// Note: this is a PostgreSQL-specific statement.
4331    Comment {
4332        /// Type of object being commented (table, column, etc.).
4333        object_type: CommentObject,
4334        /// Name of the object the comment applies to.
4335        object_name: ObjectName,
4336        /// Optional comment text (None to remove comment).
4337        comment: Option<String>,
4338        /// An optional `IF EXISTS` clause. (Non-standard.)
4339        /// See <https://docs.snowflake.com/en/sql-reference/sql/comment>
4340        if_exists: bool,
4341    },
4342    /// ```sql
4343    /// COMMIT [ TRANSACTION | WORK ] [ AND [ NO ] CHAIN ]
4344    /// ```
4345    /// If `end` is false
4346    ///
4347    /// ```sql
4348    /// END [ TRY | CATCH ]
4349    /// ```
4350    /// If `end` is true
4351    Commit {
4352        /// `true` when `AND [ NO ] CHAIN` was present.
4353        chain: bool,
4354        /// `true` when this `COMMIT` was parsed as an `END` block terminator.
4355        end: bool,
4356        /// Optional transaction modifier for commit semantics.
4357        modifier: Option<TransactionModifier>,
4358    },
4359    /// ```sql
4360    /// ROLLBACK [ TRANSACTION | WORK ] [ AND [ NO ] CHAIN ] [ TO [ SAVEPOINT ] savepoint_name ]
4361    /// ```
4362    Rollback {
4363        /// `true` when `AND [ NO ] CHAIN` was present.
4364        chain: bool,
4365        /// Optional savepoint name to roll back to.
4366        savepoint: Option<Ident>,
4367    },
4368    /// ```sql
4369    /// CREATE SCHEMA
4370    /// ```
4371    CreateSchema {
4372        /// `<schema name> | AUTHORIZATION <schema authorization identifier>  | <schema name>  AUTHORIZATION <schema authorization identifier>`
4373        schema_name: SchemaName,
4374        /// `true` when `IF NOT EXISTS` was present.
4375        if_not_exists: bool,
4376        /// Schema properties.
4377        ///
4378        /// ```sql
4379        /// CREATE SCHEMA myschema WITH (key1='value1');
4380        /// ```
4381        ///
4382        /// [Trino](https://trino.io/docs/current/sql/create-schema.html)
4383        with: Option<Vec<SqlOption>>,
4384        /// Schema options.
4385        ///
4386        /// ```sql
4387        /// CREATE SCHEMA myschema OPTIONS(key1='value1');
4388        /// ```
4389        ///
4390        /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_schema_statement)
4391        options: Option<Vec<SqlOption>>,
4392        /// Default collation specification for the schema.
4393        ///
4394        /// ```sql
4395        /// CREATE SCHEMA myschema DEFAULT COLLATE 'und:ci';
4396        /// ```
4397        ///
4398        /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_schema_statement)
4399        default_collate_spec: Option<Expr>,
4400        /// Clones a schema
4401        ///
4402        /// ```sql
4403        /// CREATE SCHEMA myschema CLONE otherschema
4404        /// ```
4405        ///
4406        /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-clone#databases-schemas)
4407        clone: Option<ObjectName>,
4408    },
4409    /// ```sql
4410    /// CREATE DATABASE
4411    /// ```
4412    /// See:
4413    /// <https://docs.snowflake.com/en/sql-reference/sql/create-database>
4414    CreateDatabase {
4415        /// Database name.
4416        db_name: ObjectName,
4417        /// `IF NOT EXISTS` flag.
4418        if_not_exists: bool,
4419        /// Optional location URI.
4420        location: Option<String>,
4421        /// Optional managed location.
4422        managed_location: Option<String>,
4423        /// `OR REPLACE` flag.
4424        or_replace: bool,
4425        /// `TRANSIENT` flag.
4426        transient: bool,
4427        /// Optional clone source.
4428        clone: Option<ObjectName>,
4429        /// Optional data retention time in days.
4430        data_retention_time_in_days: Option<u64>,
4431        /// Optional maximum data extension time in days.
4432        max_data_extension_time_in_days: Option<u64>,
4433        /// Optional external volume identifier.
4434        external_volume: Option<String>,
4435        /// Optional catalog name.
4436        catalog: Option<String>,
4437        /// Whether to replace invalid characters.
4438        replace_invalid_characters: Option<bool>,
4439        /// Default DDL collation string.
4440        default_ddl_collation: Option<String>,
4441        /// Storage serialization policy.
4442        storage_serialization_policy: Option<StorageSerializationPolicy>,
4443        /// Optional comment.
4444        comment: Option<String>,
4445        /// Optional default character set (MySQL).
4446        default_charset: Option<String>,
4447        /// Optional default collation (MySQL).
4448        default_collation: Option<String>,
4449        /// Optional catalog sync identifier.
4450        catalog_sync: Option<String>,
4451        /// Catalog sync namespace mode.
4452        catalog_sync_namespace_mode: Option<CatalogSyncNamespaceMode>,
4453        /// Optional flatten delimiter for namespace sync.
4454        catalog_sync_namespace_flatten_delimiter: Option<String>,
4455        /// Optional tags for the database.
4456        with_tags: Option<Vec<Tag>>,
4457        /// Optional contact entries for the database.
4458        with_contacts: Option<Vec<ContactEntry>>,
4459    },
4460    /// ```sql
4461    /// CREATE FUNCTION
4462    /// ```
4463    ///
4464    /// Supported variants:
4465    /// 1. [Hive](https://cwiki.apache.org/confluence/display/hive/languagemanual+ddl#LanguageManualDDL-Create/Drop/ReloadFunction)
4466    /// 2. [PostgreSQL](https://www.postgresql.org/docs/15/sql-createfunction.html)
4467    /// 3. [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_function_statement)
4468    /// 4. [MsSql](https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql)
4469    CreateFunction(CreateFunction),
4470    /// CREATE TRIGGER statement. See struct [CreateTrigger] for details.
4471    CreateTrigger(CreateTrigger),
4472    /// DROP TRIGGER statement. See struct [DropTrigger] for details.
4473    DropTrigger(DropTrigger),
4474    /// ```sql
4475    /// CREATE PROCEDURE
4476    /// ```
4477    CreateProcedure {
4478        /// `OR ALTER` flag.
4479        or_alter: bool,
4480        /// Procedure name.
4481        name: ObjectName,
4482        /// Optional procedure parameters.
4483        params: Option<Vec<ProcedureParam>>,
4484        /// Optional language identifier.
4485        language: Option<Ident>,
4486        /// Procedure body statements.
4487        body: ConditionalStatements,
4488    },
4489    /// ```sql
4490    /// CREATE MACRO
4491    /// ```
4492    ///
4493    /// Supported variants:
4494    /// 1. [DuckDB](https://duckdb.org/docs/sql/statements/create_macro)
4495    CreateMacro {
4496        /// `OR REPLACE` flag.
4497        or_replace: bool,
4498        /// Whether macro is temporary.
4499        temporary: bool,
4500        /// Macro name.
4501        name: ObjectName,
4502        /// Optional macro arguments.
4503        args: Option<Vec<MacroArg>>,
4504        /// Macro definition body.
4505        definition: MacroDefinition,
4506    },
4507    /// ```sql
4508    /// CREATE STAGE
4509    /// ```
4510    /// See <https://docs.snowflake.com/en/sql-reference/sql/create-stage>
4511    CreateStage {
4512        /// `OR REPLACE` flag for stage.
4513        or_replace: bool,
4514        /// Whether stage is temporary.
4515        temporary: bool,
4516        /// `IF NOT EXISTS` flag.
4517        if_not_exists: bool,
4518        /// Stage name.
4519        name: ObjectName,
4520        /// Stage parameters.
4521        stage_params: StageParamsObject,
4522        /// Directory table parameters.
4523        directory_table_params: KeyValueOptions,
4524        /// File format options.
4525        file_format: KeyValueOptions,
4526        /// Copy options for stage.
4527        copy_options: KeyValueOptions,
4528        /// Optional comment.
4529        comment: Option<String>,
4530    },
4531    /// ```sql
4532    /// ASSERT <condition> [AS <message>]
4533    /// ```
4534    Assert {
4535        /// Assertion condition expression.
4536        condition: Expr,
4537        /// Optional message expression.
4538        message: Option<Expr>,
4539    },
4540    /// ```sql
4541    /// GRANT privileges ON objects TO grantees
4542    /// ```
4543    Grant(Grant),
4544    /// ```sql
4545    /// DENY privileges ON object TO grantees
4546    /// ```
4547    Deny(DenyStatement),
4548    /// ```sql
4549    /// REVOKE privileges ON objects FROM grantees
4550    /// ```
4551    Revoke(Revoke),
4552    /// ```sql
4553    /// DEALLOCATE [ PREPARE ] { name | ALL }
4554    /// ```
4555    ///
4556    /// Note: this is a PostgreSQL-specific statement.
4557    Deallocate {
4558        /// Name to deallocate (or `ALL`).
4559        name: Ident,
4560        /// Whether `PREPARE` keyword was present.
4561        prepare: bool,
4562    },
4563    /// ```sql
4564    /// An `EXECUTE` statement
4565    /// ```
4566    ///
4567    /// Postgres: <https://www.postgresql.org/docs/current/sql-execute.html>
4568    /// MSSQL: <https://learn.microsoft.com/en-us/sql/relational-databases/stored-procedures/execute-a-stored-procedure>
4569    /// BigQuery: <https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#execute_immediate>
4570    /// Snowflake: <https://docs.snowflake.com/en/sql-reference/sql/execute-immediate>
4571    Execute {
4572        /// Optional function/procedure name.
4573        name: Option<ObjectName>,
4574        /// Parameter expressions passed to execute.
4575        parameters: Vec<Expr>,
4576        /// Whether parentheses were present around `parameters`.
4577        has_parentheses: bool,
4578        /// Is this an `EXECUTE IMMEDIATE`.
4579        immediate: bool,
4580        /// Identifiers to capture results into.
4581        into: Vec<Ident>,
4582        /// `USING` expressions with optional aliases.
4583        using: Vec<ExprWithAlias>,
4584        /// Whether the last parameter is the return value of the procedure
4585        /// MSSQL: <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/execute-transact-sql?view=sql-server-ver17#output>
4586        output: bool,
4587        /// Whether to invoke the procedure with the default parameter values
4588        /// MSSQL: <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/execute-transact-sql?view=sql-server-ver17#default>
4589        default: bool,
4590    },
4591    /// ```sql
4592    /// PREPARE name [ ( data_type [, ...] ) ] AS statement
4593    /// ```
4594    ///
4595    /// Note: this is a PostgreSQL-specific statement.
4596    Prepare {
4597        /// Name of the prepared statement.
4598        name: Ident,
4599        /// Optional data types for parameters.
4600        data_types: Vec<DataType>,
4601        /// Statement being prepared.
4602        statement: Box<Statement>,
4603    },
4604    /// ```sql
4605    /// KILL [CONNECTION | QUERY | MUTATION]
4606    /// ```
4607    ///
4608    /// See <https://clickhouse.com/docs/en/sql-reference/statements/kill/>
4609    /// See <https://dev.mysql.com/doc/refman/8.0/en/kill.html>
4610    Kill {
4611        /// Optional kill modifier (CONNECTION, QUERY, MUTATION).
4612        modifier: Option<KillType>,
4613        // processlist_id
4614        /// The id of the process to kill.
4615        id: u64,
4616    },
4617    /// ```sql
4618    /// [EXPLAIN | DESC | DESCRIBE] TABLE
4619    /// ```
4620    /// Note: this is a MySQL-specific statement. See <https://dev.mysql.com/doc/refman/8.0/en/explain.html>
4621    ExplainTable {
4622        /// `EXPLAIN | DESC | DESCRIBE`
4623        describe_alias: DescribeAlias,
4624        /// Hive style `FORMATTED | EXTENDED`
4625        hive_format: Option<HiveDescribeFormat>,
4626        /// Snowflake and ClickHouse support `DESC|DESCRIBE TABLE <table_name>` syntax
4627        ///
4628        /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/desc-table.html)
4629        /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/describe-table)
4630        has_table_keyword: bool,
4631        /// Table name
4632        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
4633        table_name: ObjectName,
4634    },
4635    /// ```sql
4636    /// [EXPLAIN | DESC | DESCRIBE]  <statement>
4637    /// ```
4638    Explain {
4639        /// `EXPLAIN | DESC | DESCRIBE`
4640        describe_alias: DescribeAlias,
4641        /// Carry out the command and show actual run times and other statistics.
4642        analyze: bool,
4643        /// Display additional information regarding the plan.
4644        verbose: bool,
4645        /// `EXPLAIN QUERY PLAN`
4646        /// Display the query plan without running the query.
4647        ///
4648        /// [SQLite](https://sqlite.org/lang_explain.html)
4649        query_plan: bool,
4650        /// `EXPLAIN ESTIMATE`
4651        /// [Clickhouse](https://clickhouse.com/docs/en/sql-reference/statements/explain#explain-estimate)
4652        estimate: bool,
4653        /// A SQL query that specifies what to explain
4654        statement: Box<Statement>,
4655        /// Optional output format of explain
4656        format: Option<AnalyzeFormatKind>,
4657        /// Postgres style utility options, `(analyze, verbose true)`
4658        options: Option<Vec<UtilityOption>>,
4659    },
4660    /// ```sql
4661    /// SAVEPOINT
4662    /// ```
4663    /// Define a new savepoint within the current transaction
4664    Savepoint {
4665        /// Name of the savepoint being defined.
4666        name: Ident,
4667    },
4668    /// ```sql
4669    /// RELEASE [ SAVEPOINT ] savepoint_name
4670    /// ```
4671    ReleaseSavepoint {
4672        /// Name of the savepoint to release.
4673        name: Ident,
4674    },
4675    /// A `MERGE` statement.
4676    ///
4677    /// ```sql
4678    /// MERGE INTO <target_table> USING <source> ON <join_expr> { matchedClause | notMatchedClause } [ ... ]
4679    /// ```
4680    /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/merge)
4681    /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/dml-syntax#merge_statement)
4682    /// [MSSQL](https://learn.microsoft.com/en-us/sql/t-sql/statements/merge-transact-sql?view=sql-server-ver16)
4683    Merge(Merge),
4684    /// ```sql
4685    /// CACHE [ FLAG ] TABLE <table_name> [ OPTIONS('K1' = 'V1', 'K2' = V2) ] [ AS ] [ <query> ]
4686    /// ```
4687    ///
4688    /// See [Spark SQL docs] for more details.
4689    ///
4690    /// [Spark SQL docs]: https://docs.databricks.com/spark/latest/spark-sql/language-manual/sql-ref-syntax-aux-cache-cache-table.html
4691    Cache {
4692        /// Table flag
4693        table_flag: Option<ObjectName>,
4694        /// Table name
4695        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
4696        table_name: ObjectName,
4697        /// `true` if `AS` keyword was present before the query.
4698        has_as: bool,
4699        /// Table confs
4700        options: Vec<SqlOption>,
4701        /// Cache table as a Query
4702        query: Option<Box<Query>>,
4703    },
4704    /// ```sql
4705    /// UNCACHE TABLE [ IF EXISTS ]  <table_name>
4706    /// ```
4707    UNCache {
4708        /// Table name
4709        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
4710        table_name: ObjectName,
4711        /// `true` when `IF EXISTS` was present.
4712        if_exists: bool,
4713    },
4714    /// ```sql
4715    /// CREATE [ { TEMPORARY | TEMP } ] SEQUENCE [ IF NOT EXISTS ] <sequence_name>
4716    /// ```
4717    /// Define a new sequence:
4718    CreateSequence {
4719        /// Whether the sequence is temporary.
4720        temporary: bool,
4721        /// `IF NOT EXISTS` flag.
4722        if_not_exists: bool,
4723        /// Sequence name.
4724        name: ObjectName,
4725        /// Optional data type for the sequence.
4726        data_type: Option<DataType>,
4727        /// Sequence options (INCREMENT, MINVALUE, etc.).
4728        sequence_options: Vec<SequenceOptions>,
4729        /// Optional `OWNED BY` target.
4730        owned_by: Option<ObjectName>,
4731    },
4732    /// A `CREATE DOMAIN` statement.
4733    CreateDomain(CreateDomain),
4734    /// ```sql
4735    /// CREATE TYPE <name>
4736    /// ```
4737    CreateType {
4738        /// Type name to create.
4739        name: ObjectName,
4740        /// Optional type representation details.
4741        representation: Option<UserDefinedTypeRepresentation>,
4742    },
4743    /// ```sql
4744    /// PRAGMA <schema-name>.<pragma-name> = <pragma-value>
4745    /// ```
4746    Pragma {
4747        /// Pragma name (possibly qualified).
4748        name: ObjectName,
4749        /// Optional pragma value.
4750        value: Option<ValueWithSpan>,
4751        /// Whether the pragma used `=`.
4752        is_eq: bool,
4753    },
4754    /// ```sql
4755    /// LOCK [ TABLE ] [ ONLY ] name [ * ] [, ...] [ IN lockmode MODE ] [ NOWAIT ]
4756    /// ```
4757    ///
4758    /// See <https://www.postgresql.org/docs/current/sql-lock.html>
4759    Lock(Lock),
4760    /// ```sql
4761    /// LOCK TABLES <table_name> [READ [LOCAL] | [LOW_PRIORITY] WRITE]
4762    /// ```
4763    /// Note: this is a MySQL-specific statement. See <https://dev.mysql.com/doc/refman/8.0/en/lock-tables.html>
4764    LockTables {
4765        /// List of tables to lock with modes.
4766        tables: Vec<LockTable>,
4767    },
4768    /// ```sql
4769    /// UNLOCK TABLES
4770    /// ```
4771    /// Note: this is a MySQL-specific statement. See <https://dev.mysql.com/doc/refman/8.0/en/lock-tables.html>
4772    UnlockTables,
4773    /// Unloads the result of a query to file
4774    ///
4775    /// [Athena](https://docs.aws.amazon.com/athena/latest/ug/unload.html):
4776    /// ```sql
4777    /// UNLOAD(statement) TO <destination> [ WITH options ]
4778    /// ```
4779    ///
4780    /// [Redshift](https://docs.aws.amazon.com/redshift/latest/dg/r_UNLOAD.html):
4781    /// ```sql
4782    /// UNLOAD('statement') TO <destination> [ OPTIONS ]
4783    /// ```
4784    Unload {
4785        /// Optional query AST to unload.
4786        query: Option<Box<Query>>,
4787        /// Optional original query text.
4788        query_text: Option<String>,
4789        /// Destination identifier.
4790        to: Ident,
4791        /// Optional IAM role/auth information.
4792        auth: Option<IamRoleKind>,
4793        /// Additional `WITH` options.
4794        with: Vec<SqlOption>,
4795        /// Legacy copy-style options.
4796        options: Vec<CopyLegacyOption>,
4797    },
4798    /// ClickHouse:
4799    /// ```sql
4800    /// OPTIMIZE TABLE [db.]name [ON CLUSTER cluster] [PARTITION partition | PARTITION ID 'partition_id'] [FINAL] [DEDUPLICATE [BY expression]]
4801    /// ```
4802    /// See ClickHouse <https://clickhouse.com/docs/en/sql-reference/statements/optimize>
4803    ///
4804    /// Databricks:
4805    /// ```sql
4806    /// OPTIMIZE table_name [WHERE predicate] [ZORDER BY (col_name1 [, ...])]
4807    /// ```
4808    /// See Databricks <https://docs.databricks.com/en/sql/language-manual/delta-optimize.html>
4809    OptimizeTable {
4810        /// Table name to optimize.
4811        name: ObjectName,
4812        /// Whether the `TABLE` keyword was present (ClickHouse uses `OPTIMIZE TABLE`, Databricks uses `OPTIMIZE`).
4813        has_table_keyword: bool,
4814        /// Optional cluster identifier.
4815        /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/optimize)
4816        on_cluster: Option<Ident>,
4817        /// Optional partition spec.
4818        /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/optimize)
4819        partition: Option<Partition>,
4820        /// Whether `FINAL` was specified.
4821        /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/optimize)
4822        include_final: bool,
4823        /// Optional deduplication settings.
4824        /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/optimize)
4825        deduplicate: Option<Deduplicate>,
4826        /// Optional WHERE predicate.
4827        /// [Databricks](https://docs.databricks.com/en/sql/language-manual/delta-optimize.html)
4828        predicate: Option<Expr>,
4829        /// Optional ZORDER BY columns.
4830        /// [Databricks](https://docs.databricks.com/en/sql/language-manual/delta-optimize.html)
4831        zorder: Option<Vec<Expr>>,
4832    },
4833    /// ```sql
4834    /// LISTEN
4835    /// ```
4836    /// listen for a notification channel
4837    ///
4838    /// See Postgres <https://www.postgresql.org/docs/current/sql-listen.html>
4839    LISTEN {
4840        /// Notification channel identifier.
4841        channel: Ident,
4842    },
4843    /// ```sql
4844    /// UNLISTEN
4845    /// ```
4846    /// stop listening for a notification
4847    ///
4848    /// See Postgres <https://www.postgresql.org/docs/current/sql-unlisten.html>
4849    UNLISTEN {
4850        /// Notification channel identifier.
4851        channel: Ident,
4852    },
4853    /// ```sql
4854    /// NOTIFY channel [ , payload ]
4855    /// ```
4856    /// send a notification event together with an optional "payload" string to channel
4857    ///
4858    /// See Postgres <https://www.postgresql.org/docs/current/sql-notify.html>
4859    NOTIFY {
4860        /// Notification channel identifier.
4861        channel: Ident,
4862        /// Optional payload string.
4863        payload: Option<String>,
4864    },
4865    /// ```sql
4866    /// LOAD DATA [LOCAL] INPATH 'filepath' [OVERWRITE] INTO TABLE tablename
4867    /// [PARTITION (partcol1=val1, partcol2=val2 ...)]
4868    /// [INPUTFORMAT 'inputformat' SERDE 'serde']
4869    /// ```
4870    /// Loading files into tables
4871    ///
4872    /// See Hive <https://cwiki.apache.org/confluence/pages/viewpage.action?pageId=27362036#LanguageManualDML-Loadingfilesintotables>
4873    LoadData {
4874        /// Whether `LOCAL` is present.
4875        local: bool,
4876        /// Input path for files to load.
4877        inpath: String,
4878        /// Whether `OVERWRITE` was specified.
4879        overwrite: bool,
4880        /// Target table name to load into.
4881        table_name: ObjectName,
4882        /// Optional partition specification.
4883        partitioned: Option<Vec<Expr>>,
4884        /// Optional table format information.
4885        table_format: Option<HiveLoadDataFormat>,
4886    },
4887    /// ```sql
4888    /// Rename TABLE tbl_name TO new_tbl_name[, tbl_name2 TO new_tbl_name2] ...
4889    /// ```
4890    /// Renames one or more tables
4891    ///
4892    /// See Mysql <https://dev.mysql.com/doc/refman/9.1/en/rename-table.html>
4893    RenameTable(Vec<RenameTable>),
4894    /// Snowflake `LIST`
4895    /// See: <https://docs.snowflake.com/en/sql-reference/sql/list>
4896    List(FileStagingCommand),
4897    /// Snowflake `REMOVE`
4898    /// See: <https://docs.snowflake.com/en/sql-reference/sql/remove>
4899    Remove(FileStagingCommand),
4900    /// RaiseError (MSSQL)
4901    /// RAISERROR ( { msg_id | msg_str | @local_variable }
4902    /// { , severity , state }
4903    /// [ , argument [ , ...n ] ] )
4904    /// [ WITH option [ , ...n ] ]
4905    /// See <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/raiserror-transact-sql?view=sql-server-ver16>
4906    RaisError {
4907        /// Error message expression or identifier.
4908        message: Box<Expr>,
4909        /// Severity expression.
4910        severity: Box<Expr>,
4911        /// State expression.
4912        state: Box<Expr>,
4913        /// Substitution arguments for the message.
4914        arguments: Vec<Expr>,
4915        /// Additional `WITH` options for RAISERROR.
4916        options: Vec<RaisErrorOption>,
4917    },
4918    /// A MSSQL `THROW` statement.
4919    Throw(ThrowStatement),
4920    /// ```sql
4921    /// PRINT msg_str | @local_variable | string_expr
4922    /// ```
4923    ///
4924    /// See: <https://learn.microsoft.com/en-us/sql/t-sql/statements/print-transact-sql>
4925    Print(PrintStatement),
4926    /// MSSQL `WAITFOR` statement.
4927    ///
4928    /// See: <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/waitfor-transact-sql>
4929    WaitFor(WaitForStatement),
4930    /// ```sql
4931    /// RETURN [ expression ]
4932    /// ```
4933    ///
4934    /// See [ReturnStatement]
4935    Return(ReturnStatement),
4936    /// Export data statement
4937    ///
4938    /// Example:
4939    /// ```sql
4940    /// EXPORT DATA OPTIONS(uri='gs://bucket/folder/*', format='PARQUET', overwrite=true) AS
4941    /// SELECT field1, field2 FROM mydataset.table1 ORDER BY field1 LIMIT 10
4942    /// ```
4943    /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/export-statements)
4944    ExportData(ExportData),
4945    /// ```sql
4946    /// CREATE [OR REPLACE] USER <user> [IF NOT EXISTS]
4947    /// ```
4948    /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-user)
4949    CreateUser(CreateUser),
4950    /// ```sql
4951    /// ALTER USER \[ IF EXISTS \] \[ <name> \]
4952    /// ```
4953    /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/alter-user)
4954    AlterUser(AlterUser),
4955    /// Re-sorts rows and reclaims space in either a specified table or all tables in the current database
4956    ///
4957    /// ```sql
4958    /// VACUUM tbl
4959    /// ```
4960    /// [Redshift](https://docs.aws.amazon.com/redshift/latest/dg/r_VACUUM_command.html)
4961    Vacuum(VacuumStatement),
4962    /// Restore the value of a run-time parameter to the default value.
4963    ///
4964    /// ```sql
4965    /// RESET configuration_parameter;
4966    /// RESET ALL;
4967    /// ```
4968    /// [PostgreSQL](https://www.postgresql.org/docs/current/sql-reset.html)
4969    Reset(ResetStatement),
4970}
4971
4972impl From<Analyze> for Statement {
4973    fn from(analyze: Analyze) -> Self {
4974        Statement::Analyze(analyze)
4975    }
4976}
4977
4978impl From<ddl::Truncate> for Statement {
4979    fn from(truncate: ddl::Truncate) -> Self {
4980        Statement::Truncate(truncate)
4981    }
4982}
4983
4984impl From<Lock> for Statement {
4985    fn from(lock: Lock) -> Self {
4986        Statement::Lock(lock)
4987    }
4988}
4989
4990impl From<ddl::Msck> for Statement {
4991    fn from(msck: ddl::Msck) -> Self {
4992        Statement::Msck(msck)
4993    }
4994}
4995
4996/// ```sql
4997/// {COPY | REVOKE} CURRENT GRANTS
4998/// ```
4999///
5000/// - [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/grant-ownership#optional-parameters)
5001#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
5002#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
5003#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
5004pub enum CurrentGrantsKind {
5005    /// `COPY CURRENT GRANTS` (copy current grants to target).
5006    CopyCurrentGrants,
5007    /// `REVOKE CURRENT GRANTS` (revoke current grants from target).
5008    RevokeCurrentGrants,
5009}
5010
5011impl fmt::Display for CurrentGrantsKind {
5012    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
5013        match self {
5014            CurrentGrantsKind::CopyCurrentGrants => write!(f, "COPY CURRENT GRANTS"),
5015            CurrentGrantsKind::RevokeCurrentGrants => write!(f, "REVOKE CURRENT GRANTS"),
5016        }
5017    }
5018}
5019
5020#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
5021#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
5022#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
5023/// `RAISERROR` options
5024/// See <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/raiserror-transact-sql?view=sql-server-ver16#options>
5025pub enum RaisErrorOption {
5026    /// Log the error.
5027    Log,
5028    /// Do not wait for completion.
5029    NoWait,
5030    /// Set the error state.
5031    SetError,
5032}
5033
5034impl fmt::Display for RaisErrorOption {
5035    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
5036        match self {
5037            RaisErrorOption::Log => write!(f, "LOG"),
5038            RaisErrorOption::NoWait => write!(f, "NOWAIT"),
5039            RaisErrorOption::SetError => write!(f, "SETERROR"),
5040        }
5041    }
5042}
5043
5044impl fmt::Display for Statement {
5045    /// Formats a SQL statement with support for pretty printing.
5046    ///
5047    /// When using the alternate flag (`{:#}`), the statement will be formatted with proper
5048    /// indentation and line breaks. For example:
5049    ///
5050    /// ```
5051    /// # use sqlparser::dialect::GenericDialect;
5052    /// # use sqlparser::parser::Parser;
5053    /// let sql = "SELECT a, b FROM table_1";
5054    /// let ast = Parser::parse_sql(&GenericDialect, sql).unwrap();
5055    ///
5056    /// // Regular formatting
5057    /// assert_eq!(format!("{}", ast[0]), "SELECT a, b FROM table_1");
5058    ///
5059    /// // Pretty printing
5060    /// assert_eq!(format!("{:#}", ast[0]),
5061    /// r#"SELECT
5062    ///   a,
5063    ///   b
5064    /// FROM
5065    ///   table_1"#);
5066    /// ```
5067    // Clippy thinks this function is too complicated, but it is painful to
5068    // split up without extracting structs for each `Statement` variant.
5069    #[allow(clippy::cognitive_complexity)]
5070    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
5071        match self {
5072            Statement::Flush {
5073                object_type,
5074                location,
5075                channel,
5076                read_lock,
5077                export,
5078                tables,
5079            } => {
5080                write!(f, "FLUSH")?;
5081                if let Some(location) = location {
5082                    f.write_str(" ")?;
5083                    location.fmt(f)?;
5084                }
5085                write!(f, " {object_type}")?;
5086
5087                if let Some(channel) = channel {
5088                    write!(f, " FOR CHANNEL {channel}")?;
5089                }
5090
5091                write!(
5092                    f,
5093                    "{tables}{read}{export}",
5094                    tables = if !tables.is_empty() {
5095                        format!(" {}", display_comma_separated(tables))
5096                    } else {
5097                        String::new()
5098                    },
5099                    export = if *export { " FOR EXPORT" } else { "" },
5100                    read = if *read_lock { " WITH READ LOCK" } else { "" }
5101                )
5102            }
5103            Statement::Kill { modifier, id } => {
5104                write!(f, "KILL ")?;
5105
5106                if let Some(m) = modifier {
5107                    write!(f, "{m} ")?;
5108                }
5109
5110                write!(f, "{id}")
5111            }
5112            Statement::ExplainTable {
5113                describe_alias,
5114                hive_format,
5115                has_table_keyword,
5116                table_name,
5117            } => {
5118                write!(f, "{describe_alias} ")?;
5119
5120                if let Some(format) = hive_format {
5121                    write!(f, "{format} ")?;
5122                }
5123                if *has_table_keyword {
5124                    write!(f, "TABLE ")?;
5125                }
5126
5127                write!(f, "{table_name}")
5128            }
5129            Statement::Explain {
5130                describe_alias,
5131                verbose,
5132                analyze,
5133                query_plan,
5134                estimate,
5135                statement,
5136                format,
5137                options,
5138            } => {
5139                write!(f, "{describe_alias} ")?;
5140
5141                if *query_plan {
5142                    write!(f, "QUERY PLAN ")?;
5143                }
5144                if *analyze {
5145                    write!(f, "ANALYZE ")?;
5146                }
5147                if *estimate {
5148                    write!(f, "ESTIMATE ")?;
5149                }
5150
5151                if *verbose {
5152                    write!(f, "VERBOSE ")?;
5153                }
5154
5155                if let Some(format) = format {
5156                    write!(f, "{format} ")?;
5157                }
5158
5159                if let Some(options) = options {
5160                    write!(f, "({}) ", display_comma_separated(options))?;
5161                }
5162
5163                write!(f, "{statement}")
5164            }
5165            Statement::Query(s) => s.fmt(f),
5166            Statement::Declare { stmts } => {
5167                write!(f, "DECLARE ")?;
5168                write!(f, "{}", display_separated(stmts, "; "))
5169            }
5170            Statement::Fetch {
5171                name,
5172                direction,
5173                position,
5174                into,
5175            } => {
5176                write!(f, "FETCH {direction} {position} {name}")?;
5177
5178                if let Some(into) = into {
5179                    write!(f, " INTO {into}")?;
5180                }
5181
5182                Ok(())
5183            }
5184            Statement::Directory {
5185                overwrite,
5186                local,
5187                path,
5188                file_format,
5189                source,
5190            } => {
5191                write!(
5192                    f,
5193                    "INSERT{overwrite}{local} DIRECTORY '{path}'",
5194                    overwrite = if *overwrite { " OVERWRITE" } else { "" },
5195                    local = if *local { " LOCAL" } else { "" },
5196                    path = path
5197                )?;
5198                if let Some(ref ff) = file_format {
5199                    write!(f, " STORED AS {ff}")?
5200                }
5201                write!(f, " {source}")
5202            }
5203            Statement::Msck(msck) => msck.fmt(f),
5204            Statement::Truncate(truncate) => truncate.fmt(f),
5205            Statement::Case(stmt) => {
5206                write!(f, "{stmt}")
5207            }
5208            Statement::If(stmt) => {
5209                write!(f, "{stmt}")
5210            }
5211            Statement::While(stmt) => {
5212                write!(f, "{stmt}")
5213            }
5214            Statement::Raise(stmt) => {
5215                write!(f, "{stmt}")
5216            }
5217            Statement::AttachDatabase {
5218                schema_name,
5219                database_file_name,
5220                database,
5221            } => {
5222                let keyword = if *database { "DATABASE " } else { "" };
5223                write!(f, "ATTACH {keyword}{database_file_name} AS {schema_name}")
5224            }
5225            Statement::AttachDuckDBDatabase {
5226                if_not_exists,
5227                database,
5228                database_path,
5229                database_alias,
5230                attach_options,
5231            } => {
5232                write!(
5233                    f,
5234                    "ATTACH{database}{if_not_exists} {database_path}",
5235                    database = if *database { " DATABASE" } else { "" },
5236                    if_not_exists = if *if_not_exists { " IF NOT EXISTS" } else { "" },
5237                )?;
5238                if let Some(alias) = database_alias {
5239                    write!(f, " AS {alias}")?;
5240                }
5241                if !attach_options.is_empty() {
5242                    write!(f, " ({})", display_comma_separated(attach_options))?;
5243                }
5244                Ok(())
5245            }
5246            Statement::DetachDuckDBDatabase {
5247                if_exists,
5248                database,
5249                database_alias,
5250            } => {
5251                write!(
5252                    f,
5253                    "DETACH{database}{if_exists} {database_alias}",
5254                    database = if *database { " DATABASE" } else { "" },
5255                    if_exists = if *if_exists { " IF EXISTS" } else { "" },
5256                )?;
5257                Ok(())
5258            }
5259            Statement::Analyze(analyze) => analyze.fmt(f),
5260            Statement::Insert(insert) => insert.fmt(f),
5261            Statement::Install {
5262                extension_name: name,
5263            } => write!(f, "INSTALL {name}"),
5264
5265            Statement::Load {
5266                extension_name: name,
5267            } => write!(f, "LOAD {name}"),
5268
5269            Statement::Call(function) => write!(f, "CALL {function}"),
5270
5271            Statement::Copy {
5272                source,
5273                to,
5274                target,
5275                options,
5276                legacy_options,
5277                values,
5278            } => {
5279                write!(f, "COPY")?;
5280                match source {
5281                    CopySource::Query(query) => write!(f, " ({query})")?,
5282                    CopySource::Table {
5283                        table_name,
5284                        columns,
5285                    } => {
5286                        write!(f, " {table_name}")?;
5287                        if !columns.is_empty() {
5288                            write!(f, " ({})", display_comma_separated(columns))?;
5289                        }
5290                    }
5291                }
5292                write!(f, " {} {}", if *to { "TO" } else { "FROM" }, target)?;
5293                if !options.is_empty() {
5294                    write!(f, " ({})", display_comma_separated(options))?;
5295                }
5296                if !legacy_options.is_empty() {
5297                    write!(f, " {}", display_separated(legacy_options, " "))?;
5298                }
5299                if !values.is_empty() {
5300                    writeln!(f, ";")?;
5301                    let mut delim = "";
5302                    for v in values {
5303                        write!(f, "{delim}")?;
5304                        delim = "\t";
5305                        if let Some(v) = v {
5306                            write!(f, "{v}")?;
5307                        } else {
5308                            write!(f, "\\N")?;
5309                        }
5310                    }
5311                    write!(f, "\n\\.")?;
5312                }
5313                Ok(())
5314            }
5315            Statement::Update(update) => update.fmt(f),
5316            Statement::Delete(delete) => delete.fmt(f),
5317            Statement::Open(open) => open.fmt(f),
5318            Statement::Close { cursor } => {
5319                write!(f, "CLOSE {cursor}")?;
5320
5321                Ok(())
5322            }
5323            Statement::CreateDatabase {
5324                db_name,
5325                if_not_exists,
5326                location,
5327                managed_location,
5328                or_replace,
5329                transient,
5330                clone,
5331                data_retention_time_in_days,
5332                max_data_extension_time_in_days,
5333                external_volume,
5334                catalog,
5335                replace_invalid_characters,
5336                default_ddl_collation,
5337                storage_serialization_policy,
5338                comment,
5339                default_charset,
5340                default_collation,
5341                catalog_sync,
5342                catalog_sync_namespace_mode,
5343                catalog_sync_namespace_flatten_delimiter,
5344                with_tags,
5345                with_contacts,
5346            } => {
5347                write!(
5348                    f,
5349                    "CREATE {or_replace}{transient}DATABASE {if_not_exists}{name}",
5350                    or_replace = if *or_replace { "OR REPLACE " } else { "" },
5351                    transient = if *transient { "TRANSIENT " } else { "" },
5352                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
5353                    name = db_name,
5354                )?;
5355
5356                if let Some(l) = location {
5357                    write!(f, " LOCATION '{l}'")?;
5358                }
5359                if let Some(ml) = managed_location {
5360                    write!(f, " MANAGEDLOCATION '{ml}'")?;
5361                }
5362                if let Some(clone) = clone {
5363                    write!(f, " CLONE {clone}")?;
5364                }
5365
5366                if let Some(value) = data_retention_time_in_days {
5367                    write!(f, " DATA_RETENTION_TIME_IN_DAYS = {value}")?;
5368                }
5369
5370                if let Some(value) = max_data_extension_time_in_days {
5371                    write!(f, " MAX_DATA_EXTENSION_TIME_IN_DAYS = {value}")?;
5372                }
5373
5374                if let Some(vol) = external_volume {
5375                    write!(f, " EXTERNAL_VOLUME = '{vol}'")?;
5376                }
5377
5378                if let Some(cat) = catalog {
5379                    write!(f, " CATALOG = '{cat}'")?;
5380                }
5381
5382                if let Some(true) = replace_invalid_characters {
5383                    write!(f, " REPLACE_INVALID_CHARACTERS = TRUE")?;
5384                } else if let Some(false) = replace_invalid_characters {
5385                    write!(f, " REPLACE_INVALID_CHARACTERS = FALSE")?;
5386                }
5387
5388                if let Some(collation) = default_ddl_collation {
5389                    write!(f, " DEFAULT_DDL_COLLATION = '{collation}'")?;
5390                }
5391
5392                if let Some(policy) = storage_serialization_policy {
5393                    write!(f, " STORAGE_SERIALIZATION_POLICY = {policy}")?;
5394                }
5395
5396                if let Some(comment) = comment {
5397                    write!(f, " COMMENT = '{comment}'")?;
5398                }
5399
5400                if let Some(charset) = default_charset {
5401                    write!(f, " DEFAULT CHARACTER SET {charset}")?;
5402                }
5403
5404                if let Some(collation) = default_collation {
5405                    write!(f, " DEFAULT COLLATE {collation}")?;
5406                }
5407
5408                if let Some(sync) = catalog_sync {
5409                    write!(f, " CATALOG_SYNC = '{sync}'")?;
5410                }
5411
5412                if let Some(mode) = catalog_sync_namespace_mode {
5413                    write!(f, " CATALOG_SYNC_NAMESPACE_MODE = {mode}")?;
5414                }
5415
5416                if let Some(delim) = catalog_sync_namespace_flatten_delimiter {
5417                    write!(f, " CATALOG_SYNC_NAMESPACE_FLATTEN_DELIMITER = '{delim}'")?;
5418                }
5419
5420                if let Some(tags) = with_tags {
5421                    write!(f, " WITH TAG ({})", display_comma_separated(tags))?;
5422                }
5423
5424                if let Some(contacts) = with_contacts {
5425                    write!(f, " WITH CONTACT ({})", display_comma_separated(contacts))?;
5426                }
5427                Ok(())
5428            }
5429            Statement::CreateFunction(create_function) => create_function.fmt(f),
5430            Statement::CreateDomain(create_domain) => create_domain.fmt(f),
5431            Statement::CreateTrigger(create_trigger) => create_trigger.fmt(f),
5432            Statement::DropTrigger(drop_trigger) => drop_trigger.fmt(f),
5433            Statement::CreateProcedure {
5434                name,
5435                or_alter,
5436                params,
5437                language,
5438                body,
5439            } => {
5440                write!(
5441                    f,
5442                    "CREATE {or_alter}PROCEDURE {name}",
5443                    or_alter = if *or_alter { "OR ALTER " } else { "" },
5444                    name = name
5445                )?;
5446
5447                if let Some(p) = params {
5448                    if !p.is_empty() {
5449                        write!(f, " ({})", display_comma_separated(p))?;
5450                    }
5451                }
5452
5453                if let Some(language) = language {
5454                    write!(f, " LANGUAGE {language}")?;
5455                }
5456
5457                write!(f, " AS {body}")
5458            }
5459            Statement::CreateMacro {
5460                or_replace,
5461                temporary,
5462                name,
5463                args,
5464                definition,
5465            } => {
5466                write!(
5467                    f,
5468                    "CREATE {or_replace}{temp}MACRO {name}",
5469                    temp = if *temporary { "TEMPORARY " } else { "" },
5470                    or_replace = if *or_replace { "OR REPLACE " } else { "" },
5471                )?;
5472                if let Some(args) = args {
5473                    write!(f, "({})", display_comma_separated(args))?;
5474                }
5475                match definition {
5476                    MacroDefinition::Expr(expr) => write!(f, " AS {expr}")?,
5477                    MacroDefinition::Table(query) => write!(f, " AS TABLE {query}")?,
5478                }
5479                Ok(())
5480            }
5481            Statement::CreateView(create_view) => create_view.fmt(f),
5482            Statement::CreateTable(create_table) => create_table.fmt(f),
5483            Statement::LoadData {
5484                local,
5485                inpath,
5486                overwrite,
5487                table_name,
5488                partitioned,
5489                table_format,
5490            } => {
5491                write!(
5492                    f,
5493                    "LOAD DATA {local}INPATH '{inpath}' {overwrite}INTO TABLE {table_name}",
5494                    local = if *local { "LOCAL " } else { "" },
5495                    inpath = inpath,
5496                    overwrite = if *overwrite { "OVERWRITE " } else { "" },
5497                    table_name = table_name,
5498                )?;
5499                if let Some(ref parts) = &partitioned {
5500                    if !parts.is_empty() {
5501                        write!(f, " PARTITION ({})", display_comma_separated(parts))?;
5502                    }
5503                }
5504                if let Some(HiveLoadDataFormat {
5505                    serde,
5506                    input_format,
5507                }) = &table_format
5508                {
5509                    write!(f, " INPUTFORMAT {input_format} SERDE {serde}")?;
5510                }
5511                Ok(())
5512            }
5513            Statement::CreateVirtualTable {
5514                name,
5515                if_not_exists,
5516                module_name,
5517                module_args,
5518            } => {
5519                write!(
5520                    f,
5521                    "CREATE VIRTUAL TABLE {if_not_exists}{name} USING {module_name}",
5522                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
5523                    name = name,
5524                    module_name = module_name
5525                )?;
5526                if !module_args.is_empty() {
5527                    write!(f, " ({})", display_comma_separated(module_args))?;
5528                }
5529                Ok(())
5530            }
5531            Statement::CreateIndex(create_index) => create_index.fmt(f),
5532            Statement::CreateExtension(create_extension) => write!(f, "{create_extension}"),
5533            Statement::CreateCollation(create_collation) => write!(f, "{create_collation}"),
5534            Statement::CreateTextSearchConfiguration(v) => write!(f, "{v}"),
5535            Statement::CreateTextSearchDictionary(v) => write!(f, "{v}"),
5536            Statement::CreateTextSearchParser(v) => write!(f, "{v}"),
5537            Statement::CreateTextSearchTemplate(v) => write!(f, "{v}"),
5538            Statement::CreatePublication(v) => write!(f, "{v}"),
5539            Statement::CreateSubscription(v) => write!(f, "{v}"),
5540            Statement::DropExtension(drop_extension) => write!(f, "{drop_extension}"),
5541            Statement::DropOperator(drop_operator) => write!(f, "{drop_operator}"),
5542            Statement::DropOperatorFamily(drop_operator_family) => {
5543                write!(f, "{drop_operator_family}")
5544            }
5545            Statement::DropOperatorClass(drop_operator_class) => {
5546                write!(f, "{drop_operator_class}")
5547            }
5548            Statement::CreateRole(create_role) => write!(f, "{create_role}"),
5549            Statement::CreateSecret {
5550                or_replace,
5551                temporary,
5552                if_not_exists,
5553                name,
5554                storage_specifier,
5555                secret_type,
5556                options,
5557            } => {
5558                write!(
5559                    f,
5560                    "CREATE {or_replace}",
5561                    or_replace = if *or_replace { "OR REPLACE " } else { "" },
5562                )?;
5563                if let Some(t) = temporary {
5564                    write!(f, "{}", if *t { "TEMPORARY " } else { "PERSISTENT " })?;
5565                }
5566                write!(
5567                    f,
5568                    "SECRET {if_not_exists}",
5569                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
5570                )?;
5571                if let Some(n) = name {
5572                    write!(f, "{n} ")?;
5573                };
5574                if let Some(s) = storage_specifier {
5575                    write!(f, "IN {s} ")?;
5576                }
5577                write!(f, "( TYPE {secret_type}",)?;
5578                if !options.is_empty() {
5579                    write!(f, ", {o}", o = display_comma_separated(options))?;
5580                }
5581                write!(f, " )")?;
5582                Ok(())
5583            }
5584            Statement::CreateServer(stmt) => {
5585                write!(f, "{stmt}")
5586            }
5587            Statement::CreateForeignDataWrapper(stmt) => write!(f, "{stmt}"),
5588            Statement::CreateForeignTable(stmt) => write!(f, "{stmt}"),
5589            Statement::CreatePolicy(policy) => write!(f, "{policy}"),
5590            Statement::CreateConnector(create_connector) => create_connector.fmt(f),
5591            Statement::CreateOperator(create_operator) => create_operator.fmt(f),
5592            Statement::CreateOperatorFamily(create_operator_family) => {
5593                create_operator_family.fmt(f)
5594            }
5595            Statement::CreateOperatorClass(create_operator_class) => create_operator_class.fmt(f),
5596            Statement::CreateAggregate(create_aggregate) => create_aggregate.fmt(f),
5597            Statement::AlterTable(alter_table) => write!(f, "{alter_table}"),
5598            Statement::AlterIndex { name, operation } => {
5599                write!(f, "ALTER INDEX {name} {operation}")
5600            }
5601            Statement::AlterView {
5602                name,
5603                columns,
5604                query,
5605                with_options,
5606            } => {
5607                write!(f, "ALTER VIEW {name}")?;
5608                if !with_options.is_empty() {
5609                    write!(f, " WITH ({})", display_comma_separated(with_options))?;
5610                }
5611                if !columns.is_empty() {
5612                    write!(f, " ({})", display_comma_separated(columns))?;
5613                }
5614                write!(f, " AS {query}")
5615            }
5616            Statement::AlterDomain(alter_domain) => write!(f, "{alter_domain}"),
5617            Statement::AlterExtension(alter_extension) => write!(f, "{alter_extension}"),
5618            Statement::AlterFunction(alter_function) => write!(f, "{alter_function}"),
5619            Statement::AlterTrigger(alter_trigger) => write!(f, "{alter_trigger}"),
5620            Statement::AlterType(AlterType { name, operation }) => {
5621                write!(f, "ALTER TYPE {name} {operation}")
5622            }
5623            Statement::AlterCollation(alter_collation) => write!(f, "{alter_collation}"),
5624            Statement::AlterOperator(alter_operator) => write!(f, "{alter_operator}"),
5625            Statement::AlterOperatorFamily(alter_operator_family) => {
5626                write!(f, "{alter_operator_family}")
5627            }
5628            Statement::AlterOperatorClass(alter_operator_class) => {
5629                write!(f, "{alter_operator_class}")
5630            }
5631            Statement::AlterRole { name, operation } => {
5632                write!(f, "ALTER ROLE {name} {operation}")
5633            }
5634            Statement::AlterPolicy(alter_policy) => write!(f, "{alter_policy}"),
5635            Statement::AlterConnector {
5636                name,
5637                properties,
5638                url,
5639                owner,
5640            } => {
5641                write!(f, "ALTER CONNECTOR {name}")?;
5642                if let Some(properties) = properties {
5643                    write!(
5644                        f,
5645                        " SET DCPROPERTIES({})",
5646                        display_comma_separated(properties)
5647                    )?;
5648                }
5649                if let Some(url) = url {
5650                    write!(f, " SET URL '{url}'")?;
5651                }
5652                if let Some(owner) = owner {
5653                    write!(f, " SET OWNER {owner}")?;
5654                }
5655                Ok(())
5656            }
5657            Statement::AlterSession {
5658                set,
5659                session_params,
5660            } => {
5661                write!(
5662                    f,
5663                    "ALTER SESSION {set}",
5664                    set = if *set { "SET" } else { "UNSET" }
5665                )?;
5666                if !session_params.options.is_empty() {
5667                    if *set {
5668                        write!(f, " {session_params}")?;
5669                    } else {
5670                        let options = session_params
5671                            .options
5672                            .iter()
5673                            .map(|p| p.option_name.clone())
5674                            .collect::<Vec<_>>();
5675                        write!(f, " {}", display_separated(&options, ", "))?;
5676                    }
5677                }
5678                Ok(())
5679            }
5680            Statement::Drop {
5681                object_type,
5682                if_exists,
5683                names,
5684                cascade,
5685                restrict,
5686                purge,
5687                temporary,
5688                table,
5689            } => {
5690                write!(
5691                    f,
5692                    "DROP {}{}{} {}{}{}{}",
5693                    if *temporary { "TEMPORARY " } else { "" },
5694                    object_type,
5695                    if *if_exists { " IF EXISTS" } else { "" },
5696                    display_comma_separated(names),
5697                    if *cascade { " CASCADE" } else { "" },
5698                    if *restrict { " RESTRICT" } else { "" },
5699                    if *purge { " PURGE" } else { "" },
5700                )?;
5701                if let Some(table_name) = table.as_ref() {
5702                    write!(f, " ON {table_name}")?;
5703                };
5704                Ok(())
5705            }
5706            Statement::DropFunction(drop_function) => write!(f, "{drop_function}"),
5707            Statement::DropDomain(DropDomain {
5708                if_exists,
5709                name,
5710                drop_behavior,
5711            }) => {
5712                write!(
5713                    f,
5714                    "DROP DOMAIN{} {name}",
5715                    if *if_exists { " IF EXISTS" } else { "" },
5716                )?;
5717                if let Some(op) = drop_behavior {
5718                    write!(f, " {op}")?;
5719                }
5720                Ok(())
5721            }
5722            Statement::DropProcedure {
5723                if_exists,
5724                proc_desc,
5725                drop_behavior,
5726            } => {
5727                write!(
5728                    f,
5729                    "DROP PROCEDURE{} {}",
5730                    if *if_exists { " IF EXISTS" } else { "" },
5731                    display_comma_separated(proc_desc),
5732                )?;
5733                if let Some(op) = drop_behavior {
5734                    write!(f, " {op}")?;
5735                }
5736                Ok(())
5737            }
5738            Statement::DropSecret {
5739                if_exists,
5740                temporary,
5741                name,
5742                storage_specifier,
5743            } => {
5744                write!(f, "DROP ")?;
5745                if let Some(t) = temporary {
5746                    write!(f, "{}", if *t { "TEMPORARY " } else { "PERSISTENT " })?;
5747                }
5748                write!(
5749                    f,
5750                    "SECRET {if_exists}{name}",
5751                    if_exists = if *if_exists { "IF EXISTS " } else { "" },
5752                )?;
5753                if let Some(s) = storage_specifier {
5754                    write!(f, " FROM {s}")?;
5755                }
5756                Ok(())
5757            }
5758            Statement::DropPolicy(policy) => write!(f, "{policy}"),
5759            Statement::DropConnector { if_exists, name } => {
5760                write!(
5761                    f,
5762                    "DROP CONNECTOR {if_exists}{name}",
5763                    if_exists = if *if_exists { "IF EXISTS " } else { "" }
5764                )?;
5765                Ok(())
5766            }
5767            Statement::Discard { object_type } => {
5768                write!(f, "DISCARD {object_type}")?;
5769                Ok(())
5770            }
5771            Self::Set(set) => write!(f, "{set}"),
5772            Statement::ShowVariable { variable } => {
5773                write!(f, "SHOW")?;
5774                if !variable.is_empty() {
5775                    write!(f, " {}", display_separated(variable, " "))?;
5776                }
5777                Ok(())
5778            }
5779            Statement::ShowStatus {
5780                filter,
5781                global,
5782                session,
5783            } => {
5784                write!(f, "SHOW")?;
5785                if *global {
5786                    write!(f, " GLOBAL")?;
5787                }
5788                if *session {
5789                    write!(f, " SESSION")?;
5790                }
5791                write!(f, " STATUS")?;
5792                if filter.is_some() {
5793                    write!(f, " {}", filter.as_ref().unwrap())?;
5794                }
5795                Ok(())
5796            }
5797            Statement::ShowVariables {
5798                filter,
5799                global,
5800                session,
5801            } => {
5802                write!(f, "SHOW")?;
5803                if *global {
5804                    write!(f, " GLOBAL")?;
5805                }
5806                if *session {
5807                    write!(f, " SESSION")?;
5808                }
5809                write!(f, " VARIABLES")?;
5810                if filter.is_some() {
5811                    write!(f, " {}", filter.as_ref().unwrap())?;
5812                }
5813                Ok(())
5814            }
5815            Statement::ShowCreate { obj_type, obj_name } => {
5816                write!(f, "SHOW CREATE {obj_type} {obj_name}",)?;
5817                Ok(())
5818            }
5819            Statement::ShowColumns {
5820                extended,
5821                full,
5822                show_options,
5823            } => {
5824                write!(
5825                    f,
5826                    "SHOW {extended}{full}COLUMNS{show_options}",
5827                    extended = if *extended { "EXTENDED " } else { "" },
5828                    full = if *full { "FULL " } else { "" },
5829                )?;
5830                Ok(())
5831            }
5832            Statement::ShowDatabases {
5833                terse,
5834                history,
5835                show_options,
5836            } => {
5837                write!(
5838                    f,
5839                    "SHOW {terse}DATABASES{history}{show_options}",
5840                    terse = if *terse { "TERSE " } else { "" },
5841                    history = if *history { " HISTORY" } else { "" },
5842                )?;
5843                Ok(())
5844            }
5845            Statement::ShowCatalogs {
5846                terse,
5847                history,
5848                show_options,
5849            } => {
5850                write!(
5851                    f,
5852                    "SHOW {terse}CATALOGS{history}{show_options}",
5853                    terse = if *terse { "TERSE " } else { "" },
5854                    history = if *history { " HISTORY" } else { "" },
5855                )?;
5856                Ok(())
5857            }
5858            Statement::ShowProcessList { full } => {
5859                write!(
5860                    f,
5861                    "SHOW {full}PROCESSLIST",
5862                    full = if *full { "FULL " } else { "" },
5863                )?;
5864                Ok(())
5865            }
5866            Statement::ShowSchemas {
5867                terse,
5868                history,
5869                show_options,
5870            } => {
5871                write!(
5872                    f,
5873                    "SHOW {terse}SCHEMAS{history}{show_options}",
5874                    terse = if *terse { "TERSE " } else { "" },
5875                    history = if *history { " HISTORY" } else { "" },
5876                )?;
5877                Ok(())
5878            }
5879            Statement::ShowObjects(ShowObjects {
5880                terse,
5881                show_options,
5882            }) => {
5883                write!(
5884                    f,
5885                    "SHOW {terse}OBJECTS{show_options}",
5886                    terse = if *terse { "TERSE " } else { "" },
5887                )?;
5888                Ok(())
5889            }
5890            Statement::ShowTables {
5891                terse,
5892                history,
5893                extended,
5894                full,
5895                external,
5896                show_options,
5897            } => {
5898                write!(
5899                    f,
5900                    "SHOW {terse}{extended}{full}{external}TABLES{history}{show_options}",
5901                    terse = if *terse { "TERSE " } else { "" },
5902                    extended = if *extended { "EXTENDED " } else { "" },
5903                    full = if *full { "FULL " } else { "" },
5904                    external = if *external { "EXTERNAL " } else { "" },
5905                    history = if *history { " HISTORY" } else { "" },
5906                )?;
5907                Ok(())
5908            }
5909            Statement::ShowViews {
5910                terse,
5911                materialized,
5912                show_options,
5913            } => {
5914                write!(
5915                    f,
5916                    "SHOW {terse}{materialized}VIEWS{show_options}",
5917                    terse = if *terse { "TERSE " } else { "" },
5918                    materialized = if *materialized { "MATERIALIZED " } else { "" }
5919                )?;
5920                Ok(())
5921            }
5922            Statement::ShowFunctions { filter } => {
5923                write!(f, "SHOW FUNCTIONS")?;
5924                if let Some(filter) = filter {
5925                    write!(f, " {filter}")?;
5926                }
5927                Ok(())
5928            }
5929            Statement::Use(use_expr) => use_expr.fmt(f),
5930            Statement::ShowCollation { filter } => {
5931                write!(f, "SHOW COLLATION")?;
5932                if let Some(filter) = filter {
5933                    write!(f, " {filter}")?;
5934                }
5935                Ok(())
5936            }
5937            Statement::ShowCharset(show_stm) => show_stm.fmt(f),
5938            Statement::StartTransaction {
5939                modes,
5940                begin: syntax_begin,
5941                transaction,
5942                modifier,
5943                statements,
5944                exception,
5945                has_end_keyword,
5946            } => {
5947                if *syntax_begin {
5948                    if let Some(modifier) = *modifier {
5949                        write!(f, "BEGIN {modifier}")?;
5950                    } else {
5951                        write!(f, "BEGIN")?;
5952                    }
5953                } else {
5954                    write!(f, "START")?;
5955                }
5956                if let Some(transaction) = transaction {
5957                    write!(f, " {transaction}")?;
5958                }
5959                if !modes.is_empty() {
5960                    write!(f, " {}", display_comma_separated(modes))?;
5961                }
5962                if !statements.is_empty() {
5963                    write!(f, " ")?;
5964                    format_statement_list(f, statements)?;
5965                }
5966                if let Some(exception_when) = exception {
5967                    write!(f, " EXCEPTION")?;
5968                    for when in exception_when {
5969                        write!(f, " {when}")?;
5970                    }
5971                }
5972                if *has_end_keyword {
5973                    write!(f, " END")?;
5974                }
5975                Ok(())
5976            }
5977            Statement::Commit {
5978                chain,
5979                end: end_syntax,
5980                modifier,
5981            } => {
5982                if *end_syntax {
5983                    write!(f, "END")?;
5984                    if let Some(modifier) = *modifier {
5985                        write!(f, " {modifier}")?;
5986                    }
5987                    if *chain {
5988                        write!(f, " AND CHAIN")?;
5989                    }
5990                } else {
5991                    write!(f, "COMMIT{}", if *chain { " AND CHAIN" } else { "" })?;
5992                }
5993                Ok(())
5994            }
5995            Statement::Rollback { chain, savepoint } => {
5996                write!(f, "ROLLBACK")?;
5997
5998                if *chain {
5999                    write!(f, " AND CHAIN")?;
6000                }
6001
6002                if let Some(savepoint) = savepoint {
6003                    write!(f, " TO SAVEPOINT {savepoint}")?;
6004                }
6005
6006                Ok(())
6007            }
6008            Statement::CreateSchema {
6009                schema_name,
6010                if_not_exists,
6011                with,
6012                options,
6013                default_collate_spec,
6014                clone,
6015            } => {
6016                write!(
6017                    f,
6018                    "CREATE SCHEMA {if_not_exists}{name}",
6019                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
6020                    name = schema_name
6021                )?;
6022
6023                if let Some(collate) = default_collate_spec {
6024                    write!(f, " DEFAULT COLLATE {collate}")?;
6025                }
6026
6027                if let Some(with) = with {
6028                    write!(f, " WITH ({})", display_comma_separated(with))?;
6029                }
6030
6031                if let Some(options) = options {
6032                    write!(f, " OPTIONS({})", display_comma_separated(options))?;
6033                }
6034
6035                if let Some(clone) = clone {
6036                    write!(f, " CLONE {clone}")?;
6037                }
6038                Ok(())
6039            }
6040            Statement::Assert { condition, message } => {
6041                write!(f, "ASSERT {condition}")?;
6042                if let Some(m) = message {
6043                    write!(f, " AS {m}")?;
6044                }
6045                Ok(())
6046            }
6047            Statement::Grant(grant) => write!(f, "{grant}"),
6048            Statement::Deny(s) => write!(f, "{s}"),
6049            Statement::Revoke(revoke) => write!(f, "{revoke}"),
6050            Statement::Deallocate { name, prepare } => write!(
6051                f,
6052                "DEALLOCATE {prepare}{name}",
6053                prepare = if *prepare { "PREPARE " } else { "" },
6054                name = name,
6055            ),
6056            Statement::Execute {
6057                name,
6058                parameters,
6059                has_parentheses,
6060                immediate,
6061                into,
6062                using,
6063                output,
6064                default,
6065            } => {
6066                let (open, close) = if *has_parentheses {
6067                    // Space before `(` only when there is no name directly preceding it.
6068                    (if name.is_some() { "(" } else { " (" }, ")")
6069                } else {
6070                    (if parameters.is_empty() { "" } else { " " }, "")
6071                };
6072                write!(f, "EXECUTE")?;
6073                if *immediate {
6074                    write!(f, " IMMEDIATE")?;
6075                }
6076                if let Some(name) = name {
6077                    write!(f, " {name}")?;
6078                }
6079                write!(f, "{open}{}{close}", display_comma_separated(parameters),)?;
6080                if !into.is_empty() {
6081                    write!(f, " INTO {}", display_comma_separated(into))?;
6082                }
6083                if !using.is_empty() {
6084                    write!(f, " USING {}", display_comma_separated(using))?;
6085                };
6086                if *output {
6087                    write!(f, " OUTPUT")?;
6088                }
6089                if *default {
6090                    write!(f, " DEFAULT")?;
6091                }
6092                Ok(())
6093            }
6094            Statement::Prepare {
6095                name,
6096                data_types,
6097                statement,
6098            } => {
6099                write!(f, "PREPARE {name} ")?;
6100                if !data_types.is_empty() {
6101                    write!(f, "({}) ", display_comma_separated(data_types))?;
6102                }
6103                write!(f, "AS {statement}")
6104            }
6105            Statement::Comment {
6106                object_type,
6107                object_name,
6108                comment,
6109                if_exists,
6110            } => {
6111                write!(f, "COMMENT ")?;
6112                if *if_exists {
6113                    write!(f, "IF EXISTS ")?
6114                };
6115                write!(f, "ON {object_type} {object_name} IS ")?;
6116                if let Some(c) = comment {
6117                    write!(f, "'{c}'")
6118                } else {
6119                    write!(f, "NULL")
6120                }
6121            }
6122            Statement::Savepoint { name } => {
6123                write!(f, "SAVEPOINT ")?;
6124                write!(f, "{name}")
6125            }
6126            Statement::ReleaseSavepoint { name } => {
6127                write!(f, "RELEASE SAVEPOINT {name}")
6128            }
6129            Statement::Merge(merge) => merge.fmt(f),
6130            Statement::Cache {
6131                table_name,
6132                table_flag,
6133                has_as,
6134                options,
6135                query,
6136            } => {
6137                if let Some(table_flag) = table_flag {
6138                    write!(f, "CACHE {table_flag} TABLE {table_name}")?;
6139                } else {
6140                    write!(f, "CACHE TABLE {table_name}")?;
6141                }
6142
6143                if !options.is_empty() {
6144                    write!(f, " OPTIONS({})", display_comma_separated(options))?;
6145                }
6146
6147                match (*has_as, query) {
6148                    (true, Some(query)) => write!(f, " AS {query}"),
6149                    (true, None) => f.write_str(" AS"),
6150                    (false, Some(query)) => write!(f, " {query}"),
6151                    (false, None) => Ok(()),
6152                }
6153            }
6154            Statement::UNCache {
6155                table_name,
6156                if_exists,
6157            } => {
6158                if *if_exists {
6159                    write!(f, "UNCACHE TABLE IF EXISTS {table_name}")
6160                } else {
6161                    write!(f, "UNCACHE TABLE {table_name}")
6162                }
6163            }
6164            Statement::CreateSequence {
6165                temporary,
6166                if_not_exists,
6167                name,
6168                data_type,
6169                sequence_options,
6170                owned_by,
6171            } => {
6172                let as_type: String = if let Some(dt) = data_type.as_ref() {
6173                    //Cannot use format!(" AS {}", dt), due to format! is not available in --target thumbv6m-none-eabi
6174                    // " AS ".to_owned() + &dt.to_string()
6175                    [" AS ", &dt.to_string()].concat()
6176                } else {
6177                    "".to_string()
6178                };
6179                write!(
6180                    f,
6181                    "CREATE {temporary}SEQUENCE {if_not_exists}{name}{as_type}",
6182                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
6183                    temporary = if *temporary { "TEMPORARY " } else { "" },
6184                    name = name,
6185                    as_type = as_type
6186                )?;
6187                for sequence_option in sequence_options {
6188                    write!(f, "{sequence_option}")?;
6189                }
6190                if let Some(ob) = owned_by.as_ref() {
6191                    write!(f, " OWNED BY {ob}")?;
6192                }
6193                write!(f, "")
6194            }
6195            Statement::CreateStage {
6196                or_replace,
6197                temporary,
6198                if_not_exists,
6199                name,
6200                stage_params,
6201                directory_table_params,
6202                file_format,
6203                copy_options,
6204                comment,
6205                ..
6206            } => {
6207                write!(
6208                    f,
6209                    "CREATE {or_replace}{temp}STAGE {if_not_exists}{name}{stage_params}",
6210                    temp = if *temporary { "TEMPORARY " } else { "" },
6211                    or_replace = if *or_replace { "OR REPLACE " } else { "" },
6212                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
6213                )?;
6214                if !directory_table_params.options.is_empty() {
6215                    write!(f, " DIRECTORY=({directory_table_params})")?;
6216                }
6217                if !file_format.options.is_empty() {
6218                    write!(f, " FILE_FORMAT=({file_format})")?;
6219                }
6220                if !copy_options.options.is_empty() {
6221                    write!(f, " COPY_OPTIONS=({copy_options})")?;
6222                }
6223                if comment.is_some() {
6224                    write!(f, " COMMENT='{}'", comment.as_ref().unwrap())?;
6225                }
6226                Ok(())
6227            }
6228            Statement::CopyIntoSnowflake {
6229                kind,
6230                into,
6231                into_columns,
6232                from_obj,
6233                from_obj_alias,
6234                stage_params,
6235                from_transformations,
6236                from_query,
6237                files,
6238                pattern,
6239                file_format,
6240                copy_options,
6241                validation_mode,
6242                partition,
6243            } => {
6244                write!(f, "COPY INTO {into}")?;
6245                if let Some(into_columns) = into_columns {
6246                    write!(f, " ({})", display_comma_separated(into_columns))?;
6247                }
6248                if let Some(from_transformations) = from_transformations {
6249                    // Data load with transformation
6250                    if let Some(from_stage) = from_obj {
6251                        write!(
6252                            f,
6253                            " FROM (SELECT {} FROM {}{}",
6254                            display_separated(from_transformations, ", "),
6255                            from_stage,
6256                            stage_params
6257                        )?;
6258                    }
6259                    if let Some(from_obj_alias) = from_obj_alias {
6260                        write!(f, " AS {from_obj_alias}")?;
6261                    }
6262                    write!(f, ")")?;
6263                } else if let Some(from_obj) = from_obj {
6264                    // Standard data load
6265                    write!(f, " FROM {from_obj}{stage_params}")?;
6266                    if let Some(from_obj_alias) = from_obj_alias {
6267                        write!(f, " AS {from_obj_alias}")?;
6268                    }
6269                } else if let Some(from_query) = from_query {
6270                    // Data unload from query
6271                    write!(f, " FROM ({from_query})")?;
6272                }
6273
6274                if let Some(files) = files {
6275                    write!(f, " FILES = ('{}')", display_separated(files, "', '"))?;
6276                }
6277                if let Some(pattern) = pattern {
6278                    write!(f, " PATTERN = '{pattern}'")?;
6279                }
6280                if let Some(partition) = partition {
6281                    write!(f, " PARTITION BY {partition}")?;
6282                }
6283                if !file_format.options.is_empty() {
6284                    write!(f, " FILE_FORMAT=({file_format})")?;
6285                }
6286                if !copy_options.options.is_empty() {
6287                    match kind {
6288                        CopyIntoSnowflakeKind::Table => {
6289                            write!(f, " COPY_OPTIONS=({copy_options})")?
6290                        }
6291                        CopyIntoSnowflakeKind::Location => write!(f, " {copy_options}")?,
6292                    }
6293                }
6294                if let Some(validation_mode) = validation_mode {
6295                    write!(f, " VALIDATION_MODE = {validation_mode}")?;
6296                }
6297                Ok(())
6298            }
6299            Statement::CreateType {
6300                name,
6301                representation,
6302            } => {
6303                write!(f, "CREATE TYPE {name}")?;
6304                if let Some(repr) = representation {
6305                    write!(f, " {repr}")?;
6306                }
6307                Ok(())
6308            }
6309            Statement::Pragma { name, value, is_eq } => {
6310                write!(f, "PRAGMA {name}")?;
6311                if value.is_some() {
6312                    let val = value.as_ref().unwrap();
6313                    if *is_eq {
6314                        write!(f, " = {val}")?;
6315                    } else {
6316                        write!(f, "({val})")?;
6317                    }
6318                }
6319                Ok(())
6320            }
6321            Statement::Lock(lock) => lock.fmt(f),
6322            Statement::LockTables { tables } => {
6323                write!(f, "LOCK TABLES {}", display_comma_separated(tables))
6324            }
6325            Statement::UnlockTables => {
6326                write!(f, "UNLOCK TABLES")
6327            }
6328            Statement::Unload {
6329                query,
6330                query_text,
6331                to,
6332                auth,
6333                with,
6334                options,
6335            } => {
6336                write!(f, "UNLOAD(")?;
6337                if let Some(query) = query {
6338                    write!(f, "{query}")?;
6339                }
6340                if let Some(query_text) = query_text {
6341                    write!(f, "'{query_text}'")?;
6342                }
6343                write!(f, ") TO {to}")?;
6344                if let Some(auth) = auth {
6345                    write!(f, " IAM_ROLE {auth}")?;
6346                }
6347                if !with.is_empty() {
6348                    write!(f, " WITH ({})", display_comma_separated(with))?;
6349                }
6350                if !options.is_empty() {
6351                    write!(f, " {}", display_separated(options, " "))?;
6352                }
6353                Ok(())
6354            }
6355            Statement::OptimizeTable {
6356                name,
6357                has_table_keyword,
6358                on_cluster,
6359                partition,
6360                include_final,
6361                deduplicate,
6362                predicate,
6363                zorder,
6364            } => {
6365                write!(f, "OPTIMIZE")?;
6366                if *has_table_keyword {
6367                    write!(f, " TABLE")?;
6368                }
6369                write!(f, " {name}")?;
6370                if let Some(on_cluster) = on_cluster {
6371                    write!(f, " ON CLUSTER {on_cluster}")?;
6372                }
6373                if let Some(partition) = partition {
6374                    write!(f, " {partition}")?;
6375                }
6376                if *include_final {
6377                    write!(f, " FINAL")?;
6378                }
6379                if let Some(deduplicate) = deduplicate {
6380                    write!(f, " {deduplicate}")?;
6381                }
6382                if let Some(predicate) = predicate {
6383                    write!(f, " WHERE {predicate}")?;
6384                }
6385                if let Some(zorder) = zorder {
6386                    write!(f, " ZORDER BY ({})", display_comma_separated(zorder))?;
6387                }
6388                Ok(())
6389            }
6390            Statement::LISTEN { channel } => {
6391                write!(f, "LISTEN {channel}")?;
6392                Ok(())
6393            }
6394            Statement::UNLISTEN { channel } => {
6395                write!(f, "UNLISTEN {channel}")?;
6396                Ok(())
6397            }
6398            Statement::NOTIFY { channel, payload } => {
6399                write!(f, "NOTIFY {channel}")?;
6400                if let Some(payload) = payload {
6401                    write!(f, ", '{payload}'")?;
6402                }
6403                Ok(())
6404            }
6405            Statement::RenameTable(rename_tables) => {
6406                write!(f, "RENAME TABLE {}", display_comma_separated(rename_tables))
6407            }
6408            Statement::RaisError {
6409                message,
6410                severity,
6411                state,
6412                arguments,
6413                options,
6414            } => {
6415                write!(f, "RAISERROR({message}, {severity}, {state}")?;
6416                if !arguments.is_empty() {
6417                    write!(f, ", {}", display_comma_separated(arguments))?;
6418                }
6419                write!(f, ")")?;
6420                if !options.is_empty() {
6421                    write!(f, " WITH {}", display_comma_separated(options))?;
6422                }
6423                Ok(())
6424            }
6425            Statement::Throw(s) => write!(f, "{s}"),
6426            Statement::Print(s) => write!(f, "{s}"),
6427            Statement::WaitFor(s) => write!(f, "{s}"),
6428            Statement::Return(r) => write!(f, "{r}"),
6429            Statement::List(command) => write!(f, "LIST {command}"),
6430            Statement::Remove(command) => write!(f, "REMOVE {command}"),
6431            Statement::ExportData(e) => write!(f, "{e}"),
6432            Statement::CreateUser(s) => write!(f, "{s}"),
6433            Statement::AlterSchema(s) => write!(f, "{s}"),
6434            Statement::Vacuum(s) => write!(f, "{s}"),
6435            Statement::AlterUser(s) => write!(f, "{s}"),
6436            Statement::Reset(s) => write!(f, "{s}"),
6437        }
6438    }
6439}
6440
6441/// Can use to describe options in create sequence or table column type identity
6442/// ```sql
6443/// [ INCREMENT [ BY ] increment ]
6444///     [ MINVALUE minvalue | NO MINVALUE ] [ MAXVALUE maxvalue | NO MAXVALUE ]
6445///     [ START [ WITH ] start ] [ CACHE cache ] [ [ NO ] CYCLE ]
6446/// ```
6447#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6448#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6449#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6450pub enum SequenceOptions {
6451    /// `INCREMENT [BY] <expr>` option; second value indicates presence of `BY` keyword.
6452    IncrementBy(Expr, bool),
6453    /// `MINVALUE <expr>` or `NO MINVALUE`.
6454    MinValue(Option<Expr>),
6455    /// `MAXVALUE <expr>` or `NO MAXVALUE`.
6456    MaxValue(Option<Expr>),
6457    /// `START [WITH] <expr>`; second value indicates presence of `WITH`.
6458    StartWith(Expr, bool),
6459    /// `CACHE <expr>` option.
6460    Cache(Expr),
6461    /// `CYCLE` or `NO CYCLE` option.
6462    Cycle(bool),
6463}
6464
6465impl fmt::Display for SequenceOptions {
6466    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6467        match self {
6468            SequenceOptions::IncrementBy(increment, by) => {
6469                write!(
6470                    f,
6471                    " INCREMENT{by} {increment}",
6472                    by = if *by { " BY" } else { "" },
6473                    increment = increment
6474                )
6475            }
6476            SequenceOptions::MinValue(Some(expr)) => {
6477                write!(f, " MINVALUE {expr}")
6478            }
6479            SequenceOptions::MinValue(None) => {
6480                write!(f, " NO MINVALUE")
6481            }
6482            SequenceOptions::MaxValue(Some(expr)) => {
6483                write!(f, " MAXVALUE {expr}")
6484            }
6485            SequenceOptions::MaxValue(None) => {
6486                write!(f, " NO MAXVALUE")
6487            }
6488            SequenceOptions::StartWith(start, with) => {
6489                write!(
6490                    f,
6491                    " START{with} {start}",
6492                    with = if *with { " WITH" } else { "" },
6493                    start = start
6494                )
6495            }
6496            SequenceOptions::Cache(cache) => {
6497                write!(f, " CACHE {}", *cache)
6498            }
6499            SequenceOptions::Cycle(no) => {
6500                write!(f, " {}CYCLE", if *no { "NO " } else { "" })
6501            }
6502        }
6503    }
6504}
6505
6506/// Assignment for a `SET` statement (name [=|TO] value)
6507#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6508#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6509#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6510pub struct SetAssignment {
6511    /// Optional context scope (e.g., SESSION or LOCAL).
6512    pub scope: Option<ContextModifier>,
6513    /// Assignment target name.
6514    pub name: ObjectName,
6515    /// Assigned expression value.
6516    pub value: Expr,
6517}
6518
6519impl fmt::Display for SetAssignment {
6520    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6521        write!(
6522            f,
6523            "{}{} = {}",
6524            self.scope.map(|s| format!("{s}")).unwrap_or_default(),
6525            self.name,
6526            self.value
6527        )
6528    }
6529}
6530
6531/// Target of a `TRUNCATE TABLE` command
6532///
6533/// Note this is its own struct because `visit_relation` requires an `ObjectName` (not a `Vec<ObjectName>`)
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 TruncateTableTarget {
6538    /// name of the table being truncated
6539    #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
6540    pub name: ObjectName,
6541    /// Postgres-specific option: explicitly exclude descendants (also default without ONLY)
6542    /// ```sql
6543    /// TRUNCATE TABLE ONLY name
6544    /// ```
6545    /// <https://www.postgresql.org/docs/current/sql-truncate.html>
6546    pub only: bool,
6547    /// Postgres-specific option: asterisk after table name to explicitly indicate descendants
6548    /// ```sql
6549    /// TRUNCATE TABLE name [ * ]
6550    /// ```
6551    /// <https://www.postgresql.org/docs/current/sql-truncate.html>
6552    pub has_asterisk: bool,
6553}
6554
6555impl fmt::Display for TruncateTableTarget {
6556    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6557        if self.only {
6558            write!(f, "ONLY ")?;
6559        };
6560        write!(f, "{}", self.name)?;
6561        if self.has_asterisk {
6562            write!(f, " *")?;
6563        };
6564        Ok(())
6565    }
6566}
6567
6568/// A `LOCK` statement.
6569///
6570/// See <https://www.postgresql.org/docs/current/sql-lock.html>
6571#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6572#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6573#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6574pub struct Lock {
6575    /// List of tables to lock.
6576    pub tables: Vec<LockTableTarget>,
6577    /// Lock mode.
6578    pub lock_mode: Option<LockTableMode>,
6579    /// Whether `NOWAIT` was specified.
6580    pub nowait: bool,
6581}
6582
6583impl fmt::Display for Lock {
6584    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6585        write!(f, "LOCK TABLE {}", display_comma_separated(&self.tables))?;
6586        if let Some(lock_mode) = &self.lock_mode {
6587            write!(f, " IN {lock_mode} MODE")?;
6588        }
6589        if self.nowait {
6590            write!(f, " NOWAIT")?;
6591        }
6592        Ok(())
6593    }
6594}
6595
6596/// Target of a `LOCK TABLE` command
6597///
6598/// See <https://www.postgresql.org/docs/current/sql-lock.html>
6599#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6600#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6601#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6602pub struct LockTableTarget {
6603    /// Name of the table being locked.
6604    #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
6605    pub name: ObjectName,
6606    /// Whether `ONLY` was specified to exclude descendant tables.
6607    pub only: bool,
6608    /// Whether `*` was specified to explicitly include descendant tables.
6609    pub has_asterisk: bool,
6610}
6611
6612impl fmt::Display for LockTableTarget {
6613    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6614        if self.only {
6615            write!(f, "ONLY ")?;
6616        }
6617        write!(f, "{}", self.name)?;
6618        if self.has_asterisk {
6619            write!(f, " *")?;
6620        }
6621        Ok(())
6622    }
6623}
6624
6625/// PostgreSQL lock modes for `LOCK TABLE`.
6626///
6627/// See <https://www.postgresql.org/docs/current/sql-lock.html>
6628#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6629#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6630#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6631pub enum LockTableMode {
6632    /// `ACCESS SHARE`
6633    AccessShare,
6634    /// `ROW SHARE`
6635    RowShare,
6636    /// `ROW EXCLUSIVE`
6637    RowExclusive,
6638    /// `SHARE UPDATE EXCLUSIVE`
6639    ShareUpdateExclusive,
6640    /// `SHARE`
6641    Share,
6642    /// `SHARE ROW EXCLUSIVE`
6643    ShareRowExclusive,
6644    /// `EXCLUSIVE`
6645    Exclusive,
6646    /// `ACCESS EXCLUSIVE`
6647    AccessExclusive,
6648}
6649
6650impl fmt::Display for LockTableMode {
6651    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
6652        let text = match self {
6653            Self::AccessShare => "ACCESS SHARE",
6654            Self::RowShare => "ROW SHARE",
6655            Self::RowExclusive => "ROW EXCLUSIVE",
6656            Self::ShareUpdateExclusive => "SHARE UPDATE EXCLUSIVE",
6657            Self::Share => "SHARE",
6658            Self::ShareRowExclusive => "SHARE ROW EXCLUSIVE",
6659            Self::Exclusive => "EXCLUSIVE",
6660            Self::AccessExclusive => "ACCESS EXCLUSIVE",
6661        };
6662        write!(f, "{text}")
6663    }
6664}
6665
6666/// PostgreSQL identity option for TRUNCATE table
6667/// [ RESTART IDENTITY | CONTINUE IDENTITY ]
6668#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6669#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6670#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6671pub enum TruncateIdentityOption {
6672    /// Restart identity values (RESTART IDENTITY).
6673    Restart,
6674    /// Continue identity values (CONTINUE IDENTITY).
6675    Continue,
6676}
6677
6678/// Cascade/restrict option for Postgres TRUNCATE table, MySQL GRANT/REVOKE, etc.
6679/// [ CASCADE | RESTRICT ]
6680#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6681#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6682#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6683pub enum CascadeOption {
6684    /// Apply cascading action (e.g., CASCADE).
6685    Cascade,
6686    /// Restrict the action (e.g., RESTRICT).
6687    Restrict,
6688}
6689
6690impl Display for CascadeOption {
6691    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6692        match self {
6693            CascadeOption::Cascade => write!(f, "CASCADE"),
6694            CascadeOption::Restrict => write!(f, "RESTRICT"),
6695        }
6696    }
6697}
6698
6699/// Transaction started with [ TRANSACTION | WORK | TRAN ]
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))]
6703pub enum BeginTransactionKind {
6704    /// Standard `TRANSACTION` keyword.
6705    Transaction,
6706    /// Alternate `WORK` keyword.
6707    Work,
6708    /// MSSQL shorthand `TRAN` keyword.
6709    /// See <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/begin-transaction-transact-sql>
6710    Tran,
6711}
6712
6713impl Display for BeginTransactionKind {
6714    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6715        match self {
6716            BeginTransactionKind::Transaction => write!(f, "TRANSACTION"),
6717            BeginTransactionKind::Work => write!(f, "WORK"),
6718            BeginTransactionKind::Tran => write!(f, "TRAN"),
6719        }
6720    }
6721}
6722
6723/// Can use to describe options in  create sequence or table column type identity
6724/// [ MINVALUE minvalue | NO MINVALUE ] [ MAXVALUE maxvalue | NO MAXVALUE ]
6725#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6726#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6727#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6728pub enum MinMaxValue {
6729    /// Clause is not specified.
6730    Empty,
6731    /// NO MINVALUE / NO MAXVALUE.
6732    None,
6733    /// `MINVALUE <expr>` / `MAXVALUE <expr>`.
6734    Some(Expr),
6735}
6736
6737#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6738#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6739#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6740#[non_exhaustive]
6741/// Behavior to apply for `INSERT` when a conflict occurs.
6742pub enum OnInsert {
6743    /// ON DUPLICATE KEY UPDATE (MySQL when the key already exists, then execute an update instead)
6744    DuplicateKeyUpdate(Vec<Assignment>),
6745    /// ON CONFLICT is a PostgreSQL and Sqlite extension
6746    OnConflict(OnConflict),
6747}
6748
6749#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6750#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6751#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6752/// Optional aliases for `INSERT` targets: row alias and optional column aliases.
6753pub struct InsertAliases {
6754    /// Row alias (table-style alias) for the inserted values.
6755    pub row_alias: ObjectName,
6756    /// Optional list of column aliases for the inserted values.
6757    pub col_aliases: Option<Vec<Ident>>,
6758}
6759
6760#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6761#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6762#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6763/// Optional alias for an `INSERT` table; i.e. the table to be inserted into
6764pub struct TableAliasWithoutColumns {
6765    /// `true` if the aliases was explicitly introduced with the "AS" keyword
6766    pub explicit: bool,
6767    /// the alias name itself
6768    pub alias: Ident,
6769}
6770
6771#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6772#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6773#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6774/// `ON CONFLICT` clause representation.
6775pub struct OnConflict {
6776    /// Optional conflict target specifying columns or constraint.
6777    pub conflict_target: Option<ConflictTarget>,
6778    /// Action to take when a conflict occurs.
6779    pub action: OnConflictAction,
6780}
6781#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6782#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6783#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6784/// Target specification for an `ON CONFLICT` clause.
6785pub enum ConflictTarget {
6786    /// Target specified as a list of columns.
6787    Columns(Vec<Ident>),
6788    /// Target specified as a named constraint.
6789    OnConstraint(ObjectName),
6790}
6791#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6792#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6793#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6794/// Action to perform when an `ON CONFLICT` target is matched.
6795pub enum OnConflictAction {
6796    /// Do nothing on conflict.
6797    DoNothing,
6798    /// Perform an update on conflict.
6799    DoUpdate(DoUpdate),
6800}
6801
6802#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6803#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6804#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6805/// Details for `DO UPDATE` action of an `ON CONFLICT` clause.
6806pub struct DoUpdate {
6807    /// Column assignments to perform on update.
6808    pub assignments: Vec<Assignment>,
6809    /// Optional WHERE clause limiting the update.
6810    pub selection: Option<Expr>,
6811}
6812
6813impl fmt::Display for OnInsert {
6814    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6815        match self {
6816            Self::DuplicateKeyUpdate(expr) => write!(
6817                f,
6818                " ON DUPLICATE KEY UPDATE {}",
6819                display_comma_separated(expr)
6820            ),
6821            Self::OnConflict(o) => write!(f, "{o}"),
6822        }
6823    }
6824}
6825impl fmt::Display for OnConflict {
6826    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6827        write!(f, " ON CONFLICT")?;
6828        if let Some(target) = &self.conflict_target {
6829            write!(f, "{target}")?;
6830        }
6831        write!(f, " {}", self.action)
6832    }
6833}
6834impl fmt::Display for ConflictTarget {
6835    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6836        match self {
6837            ConflictTarget::Columns(cols) => write!(f, "({})", display_comma_separated(cols)),
6838            ConflictTarget::OnConstraint(name) => write!(f, " ON CONSTRAINT {name}"),
6839        }
6840    }
6841}
6842impl fmt::Display for OnConflictAction {
6843    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6844        match self {
6845            Self::DoNothing => write!(f, "DO NOTHING"),
6846            Self::DoUpdate(do_update) => {
6847                write!(f, "DO UPDATE")?;
6848                if !do_update.assignments.is_empty() {
6849                    write!(
6850                        f,
6851                        " SET {}",
6852                        display_comma_separated(&do_update.assignments)
6853                    )?;
6854                }
6855                if let Some(selection) = &do_update.selection {
6856                    write!(f, " WHERE {selection}")?;
6857                }
6858                Ok(())
6859            }
6860        }
6861    }
6862}
6863
6864/// Privileges granted in a GRANT statement or revoked in a REVOKE 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 Privileges {
6869    /// All privileges applicable to the object type
6870    All {
6871        /// Optional keyword from the spec, ignored in practice
6872        with_privileges_keyword: bool,
6873    },
6874    /// Specific privileges (e.g. `SELECT`, `INSERT`)
6875    Actions(Vec<Action>),
6876}
6877
6878impl fmt::Display for Privileges {
6879    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6880        match self {
6881            Privileges::All {
6882                with_privileges_keyword,
6883            } => {
6884                write!(
6885                    f,
6886                    "ALL{}",
6887                    if *with_privileges_keyword {
6888                        " PRIVILEGES"
6889                    } else {
6890                        ""
6891                    }
6892                )
6893            }
6894            Privileges::Actions(actions) => {
6895                write!(f, "{}", display_comma_separated(actions))
6896            }
6897        }
6898    }
6899}
6900
6901/// Specific direction for FETCH statement
6902#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6903#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6904#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6905pub enum FetchDirection {
6906    /// Fetch a specific count of rows.
6907    Count {
6908        /// The limit value for the count.
6909        limit: ValueWithSpan,
6910    },
6911    /// Fetch the next row.
6912    Next,
6913    /// Fetch the prior row.
6914    Prior,
6915    /// Fetch the first row.
6916    First,
6917    /// Fetch the last row.
6918    Last,
6919    /// Fetch an absolute row by index.
6920    Absolute {
6921        /// The absolute index value.
6922        limit: ValueWithSpan,
6923    },
6924    /// Fetch a row relative to the current position.
6925    Relative {
6926        /// The relative offset value.
6927        limit: ValueWithSpan,
6928    },
6929    /// Fetch all rows.
6930    All,
6931    // FORWARD
6932    // FORWARD count
6933    /// Fetch forward by an optional limit.
6934    Forward {
6935        /// Optional forward limit.
6936        limit: Option<ValueWithSpan>,
6937    },
6938    /// Fetch all forward rows.
6939    ForwardAll,
6940    // BACKWARD
6941    // BACKWARD count
6942    /// Fetch backward by an optional limit.
6943    Backward {
6944        /// Optional backward limit.
6945        limit: Option<ValueWithSpan>,
6946    },
6947    /// Fetch all backward rows.
6948    BackwardAll,
6949}
6950
6951impl fmt::Display for FetchDirection {
6952    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6953        match self {
6954            FetchDirection::Count { limit } => f.write_str(&limit.to_string())?,
6955            FetchDirection::Next => f.write_str("NEXT")?,
6956            FetchDirection::Prior => f.write_str("PRIOR")?,
6957            FetchDirection::First => f.write_str("FIRST")?,
6958            FetchDirection::Last => f.write_str("LAST")?,
6959            FetchDirection::Absolute { limit } => {
6960                f.write_str("ABSOLUTE ")?;
6961                f.write_str(&limit.to_string())?;
6962            }
6963            FetchDirection::Relative { limit } => {
6964                f.write_str("RELATIVE ")?;
6965                f.write_str(&limit.to_string())?;
6966            }
6967            FetchDirection::All => f.write_str("ALL")?,
6968            FetchDirection::Forward { limit } => {
6969                f.write_str("FORWARD")?;
6970
6971                if let Some(l) = limit {
6972                    f.write_str(" ")?;
6973                    f.write_str(&l.to_string())?;
6974                }
6975            }
6976            FetchDirection::ForwardAll => f.write_str("FORWARD ALL")?,
6977            FetchDirection::Backward { limit } => {
6978                f.write_str("BACKWARD")?;
6979
6980                if let Some(l) = limit {
6981                    f.write_str(" ")?;
6982                    f.write_str(&l.to_string())?;
6983                }
6984            }
6985            FetchDirection::BackwardAll => f.write_str("BACKWARD ALL")?,
6986        };
6987
6988        Ok(())
6989    }
6990}
6991
6992/// The "position" for a FETCH statement.
6993///
6994/// [MsSql](https://learn.microsoft.com/en-us/sql/t-sql/language-elements/fetch-transact-sql)
6995#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6996#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6997#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6998pub enum FetchPosition {
6999    /// Use `FROM <pos>` position specifier.
7000    From,
7001    /// Use `IN <pos>` position specifier.
7002    In,
7003}
7004
7005impl fmt::Display for FetchPosition {
7006    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7007        match self {
7008            FetchPosition::From => f.write_str("FROM")?,
7009            FetchPosition::In => f.write_str("IN")?,
7010        };
7011
7012        Ok(())
7013    }
7014}
7015
7016/// A privilege on a database object (table, sequence, etc.).
7017#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7018#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7019#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7020pub enum Action {
7021    /// Add a search optimization.
7022    AddSearchOptimization,
7023    /// Apply an `APPLY` operation with a specific type.
7024    Apply {
7025        /// The type of apply operation.
7026        apply_type: ActionApplyType,
7027    },
7028    /// Apply a budget operation.
7029    ApplyBudget,
7030    /// Attach a listing.
7031    AttachListing,
7032    /// Attach a policy.
7033    AttachPolicy,
7034    /// Audit operation.
7035    Audit,
7036    /// Bind a service endpoint.
7037    BindServiceEndpoint,
7038    /// Connect permission.
7039    Connect,
7040    /// Create action, optionally specifying an object type.
7041    Create {
7042        /// Optional object type to create.
7043        obj_type: Option<ActionCreateObjectType>,
7044    },
7045    /// Actions related to database roles.
7046    DatabaseRole {
7047        /// The role name.
7048        role: ObjectName,
7049    },
7050    /// Delete permission.
7051    Delete,
7052    /// Drop permission.
7053    Drop,
7054    /// Evolve schema permission.
7055    EvolveSchema,
7056    /// Exec action (execute) with optional object type.
7057    Exec {
7058        /// Optional execute object type.
7059        obj_type: Option<ActionExecuteObjectType>,
7060    },
7061    /// Execute action with optional object type.
7062    Execute {
7063        /// Optional execute object type.
7064        obj_type: Option<ActionExecuteObjectType>,
7065    },
7066    /// Failover operation.
7067    Failover,
7068    /// Use imported privileges.
7069    ImportedPrivileges,
7070    /// Import a share.
7071    ImportShare,
7072    /// Insert rows with optional column list.
7073    Insert {
7074        /// Optional list of target columns for insert.
7075        columns: Option<Vec<Ident>>,
7076    },
7077    /// Manage operation with a specific manage type.
7078    Manage {
7079        /// The specific manage sub-type.
7080        manage_type: ActionManageType,
7081    },
7082    /// Manage releases.
7083    ManageReleases,
7084    /// Manage versions.
7085    ManageVersions,
7086    /// Modify operation with an optional modify type.
7087    Modify {
7088        /// The optional modify sub-type.
7089        modify_type: Option<ActionModifyType>,
7090    },
7091    /// Monitor operation with an optional monitor type.
7092    Monitor {
7093        /// The optional monitor sub-type.
7094        monitor_type: Option<ActionMonitorType>,
7095    },
7096    /// Operate permission.
7097    Operate,
7098    /// Override share restrictions.
7099    OverrideShareRestrictions,
7100    /// Ownership permission.
7101    Ownership,
7102    /// Purchase a data exchange listing.
7103    PurchaseDataExchangeListing,
7104
7105    /// Read access.
7106    Read,
7107    /// Read session-level access.
7108    ReadSession,
7109    /// References with optional column list.
7110    References {
7111        /// Optional list of referenced column identifiers.
7112        columns: Option<Vec<Ident>>,
7113    },
7114    /// Replication permission.
7115    Replicate,
7116    /// Resolve all references.
7117    ResolveAll,
7118    /// Role-related permission with target role name.
7119    Role {
7120        /// The target role name.
7121        role: ObjectName,
7122    },
7123    /// Select permission with optional column list.
7124    Select {
7125        /// Optional list of selected columns.
7126        columns: Option<Vec<Ident>>,
7127    },
7128    /// Temporary object permission.
7129    Temporary,
7130    /// Trigger-related permission.
7131    Trigger,
7132    /// Truncate permission.
7133    Truncate,
7134    /// Update permission with optional affected columns.
7135    Update {
7136        /// Optional list of columns affected by update.
7137        columns: Option<Vec<Ident>>,
7138    },
7139    /// Usage permission.
7140    Usage,
7141}
7142
7143impl fmt::Display for Action {
7144    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7145        match self {
7146            Action::AddSearchOptimization => f.write_str("ADD SEARCH OPTIMIZATION")?,
7147            Action::Apply { apply_type } => write!(f, "APPLY {apply_type}")?,
7148            Action::ApplyBudget => f.write_str("APPLYBUDGET")?,
7149            Action::AttachListing => f.write_str("ATTACH LISTING")?,
7150            Action::AttachPolicy => f.write_str("ATTACH POLICY")?,
7151            Action::Audit => f.write_str("AUDIT")?,
7152            Action::BindServiceEndpoint => f.write_str("BIND SERVICE ENDPOINT")?,
7153            Action::Connect => f.write_str("CONNECT")?,
7154            Action::Create { obj_type } => {
7155                f.write_str("CREATE")?;
7156                if let Some(obj_type) = obj_type {
7157                    write!(f, " {obj_type}")?
7158                }
7159            }
7160            Action::DatabaseRole { role } => write!(f, "DATABASE ROLE {role}")?,
7161            Action::Delete => f.write_str("DELETE")?,
7162            Action::Drop => f.write_str("DROP")?,
7163            Action::EvolveSchema => f.write_str("EVOLVE SCHEMA")?,
7164            Action::Exec { obj_type } => {
7165                f.write_str("EXEC")?;
7166                if let Some(obj_type) = obj_type {
7167                    write!(f, " {obj_type}")?
7168                }
7169            }
7170            Action::Execute { obj_type } => {
7171                f.write_str("EXECUTE")?;
7172                if let Some(obj_type) = obj_type {
7173                    write!(f, " {obj_type}")?
7174                }
7175            }
7176            Action::Failover => f.write_str("FAILOVER")?,
7177            Action::ImportedPrivileges => f.write_str("IMPORTED PRIVILEGES")?,
7178            Action::ImportShare => f.write_str("IMPORT SHARE")?,
7179            Action::Insert { .. } => f.write_str("INSERT")?,
7180            Action::Manage { manage_type } => write!(f, "MANAGE {manage_type}")?,
7181            Action::ManageReleases => f.write_str("MANAGE RELEASES")?,
7182            Action::ManageVersions => f.write_str("MANAGE VERSIONS")?,
7183            Action::Modify { modify_type } => {
7184                write!(f, "MODIFY")?;
7185                if let Some(modify_type) = modify_type {
7186                    write!(f, " {modify_type}")?;
7187                }
7188            }
7189            Action::Monitor { monitor_type } => {
7190                write!(f, "MONITOR")?;
7191                if let Some(monitor_type) = monitor_type {
7192                    write!(f, " {monitor_type}")?
7193                }
7194            }
7195            Action::Operate => f.write_str("OPERATE")?,
7196            Action::OverrideShareRestrictions => f.write_str("OVERRIDE SHARE RESTRICTIONS")?,
7197            Action::Ownership => f.write_str("OWNERSHIP")?,
7198            Action::PurchaseDataExchangeListing => f.write_str("PURCHASE DATA EXCHANGE LISTING")?,
7199            Action::Read => f.write_str("READ")?,
7200            Action::ReadSession => f.write_str("READ SESSION")?,
7201            Action::References { .. } => f.write_str("REFERENCES")?,
7202            Action::Replicate => f.write_str("REPLICATE")?,
7203            Action::ResolveAll => f.write_str("RESOLVE ALL")?,
7204            Action::Role { role } => write!(f, "ROLE {role}")?,
7205            Action::Select { .. } => f.write_str("SELECT")?,
7206            Action::Temporary => f.write_str("TEMPORARY")?,
7207            Action::Trigger => f.write_str("TRIGGER")?,
7208            Action::Truncate => f.write_str("TRUNCATE")?,
7209            Action::Update { .. } => f.write_str("UPDATE")?,
7210            Action::Usage => f.write_str("USAGE")?,
7211        };
7212        match self {
7213            Action::Insert { columns }
7214            | Action::References { columns }
7215            | Action::Select { columns }
7216            | Action::Update { columns } => {
7217                if let Some(columns) = columns {
7218                    write!(f, " ({})", display_comma_separated(columns))?;
7219                }
7220            }
7221            _ => (),
7222        };
7223        Ok(())
7224    }
7225}
7226
7227#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7228#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7229#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7230/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
7231/// under `globalPrivileges` in the `CREATE` privilege.
7232pub enum ActionCreateObjectType {
7233    /// An account-level object.
7234    Account,
7235    /// An application object.
7236    Application,
7237    /// An application package object.
7238    ApplicationPackage,
7239    /// A compute pool object.
7240    ComputePool,
7241    /// A data exchange listing.
7242    DataExchangeListing,
7243    /// A database object.
7244    Database,
7245    /// An external volume object.
7246    ExternalVolume,
7247    /// A failover group object.
7248    FailoverGroup,
7249    /// An integration object.
7250    Integration,
7251    /// A network policy object.
7252    NetworkPolicy,
7253    /// An organization listing.
7254    OrganiationListing,
7255    /// A replication group object.
7256    ReplicationGroup,
7257    /// A role object.
7258    Role,
7259    /// A schema object.
7260    Schema,
7261    /// A share object.
7262    Share,
7263    /// A user object.
7264    User,
7265    /// A warehouse object.
7266    Warehouse,
7267}
7268
7269impl fmt::Display for ActionCreateObjectType {
7270    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7271        match self {
7272            ActionCreateObjectType::Account => write!(f, "ACCOUNT"),
7273            ActionCreateObjectType::Application => write!(f, "APPLICATION"),
7274            ActionCreateObjectType::ApplicationPackage => write!(f, "APPLICATION PACKAGE"),
7275            ActionCreateObjectType::ComputePool => write!(f, "COMPUTE POOL"),
7276            ActionCreateObjectType::DataExchangeListing => write!(f, "DATA EXCHANGE LISTING"),
7277            ActionCreateObjectType::Database => write!(f, "DATABASE"),
7278            ActionCreateObjectType::ExternalVolume => write!(f, "EXTERNAL VOLUME"),
7279            ActionCreateObjectType::FailoverGroup => write!(f, "FAILOVER GROUP"),
7280            ActionCreateObjectType::Integration => write!(f, "INTEGRATION"),
7281            ActionCreateObjectType::NetworkPolicy => write!(f, "NETWORK POLICY"),
7282            ActionCreateObjectType::OrganiationListing => write!(f, "ORGANIZATION LISTING"),
7283            ActionCreateObjectType::ReplicationGroup => write!(f, "REPLICATION GROUP"),
7284            ActionCreateObjectType::Role => write!(f, "ROLE"),
7285            ActionCreateObjectType::Schema => write!(f, "SCHEMA"),
7286            ActionCreateObjectType::Share => write!(f, "SHARE"),
7287            ActionCreateObjectType::User => write!(f, "USER"),
7288            ActionCreateObjectType::Warehouse => write!(f, "WAREHOUSE"),
7289        }
7290    }
7291}
7292
7293#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7294#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7295#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7296/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
7297/// under `globalPrivileges` in the `APPLY` privilege.
7298pub enum ActionApplyType {
7299    /// Apply an aggregation policy.
7300    AggregationPolicy,
7301    /// Apply an authentication policy.
7302    AuthenticationPolicy,
7303    /// Apply a join policy.
7304    JoinPolicy,
7305    /// Apply a masking policy.
7306    MaskingPolicy,
7307    /// Apply a packages policy.
7308    PackagesPolicy,
7309    /// Apply a password policy.
7310    PasswordPolicy,
7311    /// Apply a projection policy.
7312    ProjectionPolicy,
7313    /// Apply a row access policy.
7314    RowAccessPolicy,
7315    /// Apply a session policy.
7316    SessionPolicy,
7317    /// Apply a tag.
7318    Tag,
7319}
7320
7321impl fmt::Display for ActionApplyType {
7322    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7323        match self {
7324            ActionApplyType::AggregationPolicy => write!(f, "AGGREGATION POLICY"),
7325            ActionApplyType::AuthenticationPolicy => write!(f, "AUTHENTICATION POLICY"),
7326            ActionApplyType::JoinPolicy => write!(f, "JOIN POLICY"),
7327            ActionApplyType::MaskingPolicy => write!(f, "MASKING POLICY"),
7328            ActionApplyType::PackagesPolicy => write!(f, "PACKAGES POLICY"),
7329            ActionApplyType::PasswordPolicy => write!(f, "PASSWORD POLICY"),
7330            ActionApplyType::ProjectionPolicy => write!(f, "PROJECTION POLICY"),
7331            ActionApplyType::RowAccessPolicy => write!(f, "ROW ACCESS POLICY"),
7332            ActionApplyType::SessionPolicy => write!(f, "SESSION POLICY"),
7333            ActionApplyType::Tag => write!(f, "TAG"),
7334        }
7335    }
7336}
7337
7338#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7339#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7340#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7341/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
7342/// under `globalPrivileges` in the `EXECUTE` privilege.
7343pub enum ActionExecuteObjectType {
7344    /// Alert object.
7345    Alert,
7346    /// Data metric function object.
7347    DataMetricFunction,
7348    /// Managed alert object.
7349    ManagedAlert,
7350    /// Managed task object.
7351    ManagedTask,
7352    /// Task object.
7353    Task,
7354}
7355
7356impl fmt::Display for ActionExecuteObjectType {
7357    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7358        match self {
7359            ActionExecuteObjectType::Alert => write!(f, "ALERT"),
7360            ActionExecuteObjectType::DataMetricFunction => write!(f, "DATA METRIC FUNCTION"),
7361            ActionExecuteObjectType::ManagedAlert => write!(f, "MANAGED ALERT"),
7362            ActionExecuteObjectType::ManagedTask => write!(f, "MANAGED TASK"),
7363            ActionExecuteObjectType::Task => write!(f, "TASK"),
7364        }
7365    }
7366}
7367
7368#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7369#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7370#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7371/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
7372/// under `globalPrivileges` in the `MANAGE` privilege.
7373pub enum ActionManageType {
7374    /// Account support cases management.
7375    AccountSupportCases,
7376    /// Event sharing management.
7377    EventSharing,
7378    /// Grants management.
7379    Grants,
7380    /// Listing auto-fulfillment management.
7381    ListingAutoFulfillment,
7382    /// Organization support cases management.
7383    OrganizationSupportCases,
7384    /// User support cases management.
7385    UserSupportCases,
7386    /// Warehouses management.
7387    Warehouses,
7388}
7389
7390impl fmt::Display for ActionManageType {
7391    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7392        match self {
7393            ActionManageType::AccountSupportCases => write!(f, "ACCOUNT SUPPORT CASES"),
7394            ActionManageType::EventSharing => write!(f, "EVENT SHARING"),
7395            ActionManageType::Grants => write!(f, "GRANTS"),
7396            ActionManageType::ListingAutoFulfillment => write!(f, "LISTING AUTO FULFILLMENT"),
7397            ActionManageType::OrganizationSupportCases => write!(f, "ORGANIZATION SUPPORT CASES"),
7398            ActionManageType::UserSupportCases => write!(f, "USER SUPPORT CASES"),
7399            ActionManageType::Warehouses => write!(f, "WAREHOUSES"),
7400        }
7401    }
7402}
7403
7404#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7405#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7406#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7407/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
7408/// under `globalPrivileges` in the `MODIFY` privilege.
7409pub enum ActionModifyType {
7410    /// Modify log level.
7411    LogLevel,
7412    /// Modify trace level.
7413    TraceLevel,
7414    /// Modify session log level.
7415    SessionLogLevel,
7416    /// Modify session trace level.
7417    SessionTraceLevel,
7418}
7419
7420impl fmt::Display for ActionModifyType {
7421    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7422        match self {
7423            ActionModifyType::LogLevel => write!(f, "LOG LEVEL"),
7424            ActionModifyType::TraceLevel => write!(f, "TRACE LEVEL"),
7425            ActionModifyType::SessionLogLevel => write!(f, "SESSION LOG LEVEL"),
7426            ActionModifyType::SessionTraceLevel => write!(f, "SESSION TRACE LEVEL"),
7427        }
7428    }
7429}
7430
7431#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7432#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7433#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7434/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
7435/// under `globalPrivileges` in the `MONITOR` privilege.
7436pub enum ActionMonitorType {
7437    /// Monitor execution.
7438    Execution,
7439    /// Monitor security.
7440    Security,
7441    /// Monitor usage.
7442    Usage,
7443}
7444
7445impl fmt::Display for ActionMonitorType {
7446    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7447        match self {
7448            ActionMonitorType::Execution => write!(f, "EXECUTION"),
7449            ActionMonitorType::Security => write!(f, "SECURITY"),
7450            ActionMonitorType::Usage => write!(f, "USAGE"),
7451        }
7452    }
7453}
7454
7455/// The principal that receives the privileges
7456#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7457#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7458#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7459pub struct Grantee {
7460    /// The category/type of grantee (role, user, share, etc.).
7461    pub grantee_type: GranteesType,
7462    /// Optional name of the grantee (identifier or user@host).
7463    pub name: Option<GranteeName>,
7464}
7465
7466impl fmt::Display for Grantee {
7467    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7468        match self.grantee_type {
7469            GranteesType::Role => {
7470                write!(f, "ROLE ")?;
7471            }
7472            GranteesType::Share => {
7473                write!(f, "SHARE ")?;
7474            }
7475            GranteesType::User => {
7476                write!(f, "USER ")?;
7477            }
7478            GranteesType::Group => {
7479                write!(f, "GROUP ")?;
7480            }
7481            GranteesType::Public => {
7482                write!(f, "PUBLIC ")?;
7483            }
7484            GranteesType::DatabaseRole => {
7485                write!(f, "DATABASE ROLE ")?;
7486            }
7487            GranteesType::Application => {
7488                write!(f, "APPLICATION ")?;
7489            }
7490            GranteesType::ApplicationRole => {
7491                write!(f, "APPLICATION ROLE ")?;
7492            }
7493            GranteesType::None => (),
7494        }
7495        if let Some(ref name) = self.name {
7496            name.fmt(f)?;
7497        }
7498        Ok(())
7499    }
7500}
7501
7502#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7503#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7504#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7505/// The kind of principal receiving privileges.
7506pub enum GranteesType {
7507    /// A role principal.
7508    Role,
7509    /// A share principal.
7510    Share,
7511    /// A user principal.
7512    User,
7513    /// A group principal.
7514    Group,
7515    /// The public principal.
7516    Public,
7517    /// A database role principal.
7518    DatabaseRole,
7519    /// An application principal.
7520    Application,
7521    /// An application role principal.
7522    ApplicationRole,
7523    /// No specific principal (e.g. `NONE`).
7524    None,
7525}
7526
7527/// Users/roles designated in a GRANT/REVOKE
7528#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7529#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7530#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7531pub enum GranteeName {
7532    /// A bare identifier
7533    ObjectName(ObjectName),
7534    /// A MySQL user/host pair such as 'root'@'%'
7535    UserHost {
7536        /// The user identifier portion.
7537        user: Ident,
7538        /// The host identifier portion.
7539        host: Ident,
7540    },
7541}
7542
7543impl fmt::Display for GranteeName {
7544    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7545        match self {
7546            GranteeName::ObjectName(name) => name.fmt(f),
7547            GranteeName::UserHost { user, host } => {
7548                write!(f, "{user}@{host}")
7549            }
7550        }
7551    }
7552}
7553
7554/// Objects on which privileges are granted in a GRANT statement.
7555#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7556#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7557#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7558pub enum GrantObjects {
7559    /// Grant privileges on `ALL SEQUENCES IN SCHEMA <schema_name> [, ...]`
7560    AllSequencesInSchema {
7561        /// The target schema names.
7562        schemas: Vec<ObjectName>,
7563    },
7564    /// Grant privileges on `ALL TABLES IN SCHEMA <schema_name> [, ...]`
7565    AllTablesInSchema {
7566        /// The target schema names.
7567        schemas: Vec<ObjectName>,
7568    },
7569    /// Grant privileges on `ALL VIEWS IN SCHEMA <schema_name> [, ...]`
7570    AllViewsInSchema {
7571        /// The target schema names.
7572        schemas: Vec<ObjectName>,
7573    },
7574    /// Grant privileges on `ALL MATERIALIZED VIEWS IN SCHEMA <schema_name> [, ...]`
7575    AllMaterializedViewsInSchema {
7576        /// The target schema names.
7577        schemas: Vec<ObjectName>,
7578    },
7579    /// Grant privileges on `ALL EXTERNAL TABLES IN SCHEMA <schema_name> [, ...]`
7580    AllExternalTablesInSchema {
7581        /// The target schema names.
7582        schemas: Vec<ObjectName>,
7583    },
7584    /// Grant privileges on `ALL FUNCTIONS IN SCHEMA <schema_name> [, ...]`
7585    AllFunctionsInSchema {
7586        /// The target schema names.
7587        schemas: Vec<ObjectName>,
7588    },
7589    /// Grant privileges on `FUTURE SCHEMAS IN DATABASE <database_name> [, ...]`
7590    FutureSchemasInDatabase {
7591        /// The target database names.
7592        databases: Vec<ObjectName>,
7593    },
7594    /// Grant privileges on `FUTURE TABLES IN SCHEMA <schema_name> [, ...]`
7595    FutureTablesInSchema {
7596        /// The target schema names.
7597        schemas: Vec<ObjectName>,
7598    },
7599    /// Grant privileges on `FUTURE VIEWS IN SCHEMA <schema_name> [, ...]`
7600    FutureViewsInSchema {
7601        /// The target schema names.
7602        schemas: Vec<ObjectName>,
7603    },
7604    /// Grant privileges on `FUTURE EXTERNAL TABLES IN SCHEMA <schema_name> [, ...]`
7605    FutureExternalTablesInSchema {
7606        /// The target schema names.
7607        schemas: Vec<ObjectName>,
7608    },
7609    /// Grant privileges on `FUTURE MATERIALIZED VIEWS IN SCHEMA <schema_name> [, ...]`
7610    FutureMaterializedViewsInSchema {
7611        /// The target schema names.
7612        schemas: Vec<ObjectName>,
7613    },
7614    /// Grant privileges on `FUTURE SEQUENCES IN SCHEMA <schema_name> [, ...]`
7615    FutureSequencesInSchema {
7616        /// The target schema names.
7617        schemas: Vec<ObjectName>,
7618    },
7619    /// Grant privileges on specific databases
7620    Databases(Vec<ObjectName>),
7621    /// Grant privileges on specific schemas
7622    Schemas(Vec<ObjectName>),
7623    /// Grant privileges on specific sequences
7624    Sequences(Vec<ObjectName>),
7625    /// Grant privileges on specific tables
7626    Tables(Vec<ObjectName>),
7627    /// Grant privileges on specific views
7628    Views(Vec<ObjectName>),
7629    /// Grant privileges on specific warehouses
7630    Warehouses(Vec<ObjectName>),
7631    /// Grant privileges on specific integrations
7632    Integrations(Vec<ObjectName>),
7633    /// Grant privileges on resource monitors
7634    ResourceMonitors(Vec<ObjectName>),
7635    /// Grant privileges on users
7636    Users(Vec<ObjectName>),
7637    /// Grant privileges on compute pools
7638    ComputePools(Vec<ObjectName>),
7639    /// Grant privileges on connections
7640    Connections(Vec<ObjectName>),
7641    /// Grant privileges on failover groups
7642    FailoverGroup(Vec<ObjectName>),
7643    /// Grant privileges on replication group
7644    ReplicationGroup(Vec<ObjectName>),
7645    /// Grant privileges on external volumes
7646    ExternalVolumes(Vec<ObjectName>),
7647    /// Grant privileges on a procedure. In dialects that
7648    /// support overloading, the argument types must be specified.
7649    ///
7650    /// For example:
7651    /// `GRANT USAGE ON PROCEDURE foo(varchar) TO ROLE role1`
7652    Procedure {
7653        /// The procedure name.
7654        name: ObjectName,
7655        /// Optional argument types for overloaded procedures.
7656        arg_types: Vec<DataType>,
7657    },
7658
7659    /// Grant privileges on a function. In dialects that
7660    /// support overloading, the argument types must be specified.
7661    ///
7662    /// For example:
7663    /// `GRANT USAGE ON FUNCTION foo(varchar) TO ROLE role1`
7664    Function {
7665        /// The function name.
7666        name: ObjectName,
7667        /// Optional argument types for overloaded functions.
7668        arg_types: Vec<DataType>,
7669    },
7670}
7671
7672impl fmt::Display for GrantObjects {
7673    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7674        match self {
7675            GrantObjects::Sequences(sequences) => {
7676                write!(f, "SEQUENCE {}", display_comma_separated(sequences))
7677            }
7678            GrantObjects::Databases(databases) => {
7679                write!(f, "DATABASE {}", display_comma_separated(databases))
7680            }
7681            GrantObjects::Schemas(schemas) => {
7682                write!(f, "SCHEMA {}", display_comma_separated(schemas))
7683            }
7684            GrantObjects::Tables(tables) => {
7685                write!(f, "{}", display_comma_separated(tables))
7686            }
7687            GrantObjects::Views(views) => {
7688                write!(f, "VIEW {}", display_comma_separated(views))
7689            }
7690            GrantObjects::Warehouses(warehouses) => {
7691                write!(f, "WAREHOUSE {}", display_comma_separated(warehouses))
7692            }
7693            GrantObjects::Integrations(integrations) => {
7694                write!(f, "INTEGRATION {}", display_comma_separated(integrations))
7695            }
7696            GrantObjects::AllSequencesInSchema { schemas } => {
7697                write!(
7698                    f,
7699                    "ALL SEQUENCES IN SCHEMA {}",
7700                    display_comma_separated(schemas)
7701                )
7702            }
7703            GrantObjects::AllTablesInSchema { schemas } => {
7704                write!(
7705                    f,
7706                    "ALL TABLES IN SCHEMA {}",
7707                    display_comma_separated(schemas)
7708                )
7709            }
7710            GrantObjects::AllExternalTablesInSchema { schemas } => {
7711                write!(
7712                    f,
7713                    "ALL EXTERNAL TABLES IN SCHEMA {}",
7714                    display_comma_separated(schemas)
7715                )
7716            }
7717            GrantObjects::AllViewsInSchema { schemas } => {
7718                write!(
7719                    f,
7720                    "ALL VIEWS IN SCHEMA {}",
7721                    display_comma_separated(schemas)
7722                )
7723            }
7724            GrantObjects::AllMaterializedViewsInSchema { schemas } => {
7725                write!(
7726                    f,
7727                    "ALL MATERIALIZED VIEWS IN SCHEMA {}",
7728                    display_comma_separated(schemas)
7729                )
7730            }
7731            GrantObjects::AllFunctionsInSchema { schemas } => {
7732                write!(
7733                    f,
7734                    "ALL FUNCTIONS IN SCHEMA {}",
7735                    display_comma_separated(schemas)
7736                )
7737            }
7738            GrantObjects::FutureSchemasInDatabase { databases } => {
7739                write!(
7740                    f,
7741                    "FUTURE SCHEMAS IN DATABASE {}",
7742                    display_comma_separated(databases)
7743                )
7744            }
7745            GrantObjects::FutureTablesInSchema { schemas } => {
7746                write!(
7747                    f,
7748                    "FUTURE TABLES IN SCHEMA {}",
7749                    display_comma_separated(schemas)
7750                )
7751            }
7752            GrantObjects::FutureExternalTablesInSchema { schemas } => {
7753                write!(
7754                    f,
7755                    "FUTURE EXTERNAL TABLES IN SCHEMA {}",
7756                    display_comma_separated(schemas)
7757                )
7758            }
7759            GrantObjects::FutureViewsInSchema { schemas } => {
7760                write!(
7761                    f,
7762                    "FUTURE VIEWS IN SCHEMA {}",
7763                    display_comma_separated(schemas)
7764                )
7765            }
7766            GrantObjects::FutureMaterializedViewsInSchema { schemas } => {
7767                write!(
7768                    f,
7769                    "FUTURE MATERIALIZED VIEWS IN SCHEMA {}",
7770                    display_comma_separated(schemas)
7771                )
7772            }
7773            GrantObjects::FutureSequencesInSchema { schemas } => {
7774                write!(
7775                    f,
7776                    "FUTURE SEQUENCES IN SCHEMA {}",
7777                    display_comma_separated(schemas)
7778                )
7779            }
7780            GrantObjects::ResourceMonitors(objects) => {
7781                write!(f, "RESOURCE MONITOR {}", display_comma_separated(objects))
7782            }
7783            GrantObjects::Users(objects) => {
7784                write!(f, "USER {}", display_comma_separated(objects))
7785            }
7786            GrantObjects::ComputePools(objects) => {
7787                write!(f, "COMPUTE POOL {}", display_comma_separated(objects))
7788            }
7789            GrantObjects::Connections(objects) => {
7790                write!(f, "CONNECTION {}", display_comma_separated(objects))
7791            }
7792            GrantObjects::FailoverGroup(objects) => {
7793                write!(f, "FAILOVER GROUP {}", display_comma_separated(objects))
7794            }
7795            GrantObjects::ReplicationGroup(objects) => {
7796                write!(f, "REPLICATION GROUP {}", display_comma_separated(objects))
7797            }
7798            GrantObjects::ExternalVolumes(objects) => {
7799                write!(f, "EXTERNAL VOLUME {}", display_comma_separated(objects))
7800            }
7801            GrantObjects::Procedure { name, arg_types } => {
7802                write!(f, "PROCEDURE {name}")?;
7803                if !arg_types.is_empty() {
7804                    write!(f, "({})", display_comma_separated(arg_types))?;
7805                }
7806                Ok(())
7807            }
7808            GrantObjects::Function { name, arg_types } => {
7809                write!(f, "FUNCTION {name}")?;
7810                if !arg_types.is_empty() {
7811                    write!(f, "({})", display_comma_separated(arg_types))?;
7812                }
7813                Ok(())
7814            }
7815        }
7816    }
7817}
7818
7819/// A `DENY` statement
7820///
7821/// [MsSql](https://learn.microsoft.com/en-us/sql/t-sql/statements/deny-transact-sql)
7822#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7823#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7824#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7825pub struct DenyStatement {
7826    /// The privileges to deny.
7827    pub privileges: Privileges,
7828    /// The objects the privileges apply to.
7829    pub objects: GrantObjects,
7830    /// The grantees (users/roles) to whom the denial applies.
7831    pub grantees: Vec<Grantee>,
7832    /// Optional identifier of the principal that performed the grant.
7833    pub granted_by: Option<Ident>,
7834    /// Optional cascade option controlling dependent objects.
7835    pub cascade: Option<CascadeOption>,
7836}
7837
7838impl fmt::Display for DenyStatement {
7839    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7840        write!(f, "DENY {}", self.privileges)?;
7841        write!(f, " ON {}", self.objects)?;
7842        if !self.grantees.is_empty() {
7843            write!(f, " TO {}", display_comma_separated(&self.grantees))?;
7844        }
7845        if let Some(cascade) = &self.cascade {
7846            write!(f, " {cascade}")?;
7847        }
7848        if let Some(granted_by) = &self.granted_by {
7849            write!(f, " AS {granted_by}")?;
7850        }
7851        Ok(())
7852    }
7853}
7854
7855/// SQL assignment `foo = expr` as used in SQLUpdate
7856#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7857#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7858#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7859pub struct Assignment {
7860    /// The left-hand side of the assignment.
7861    pub target: AssignmentTarget,
7862    /// The expression assigned to the target.
7863    pub value: Expr,
7864}
7865
7866impl fmt::Display for Assignment {
7867    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7868        write!(f, "{} = {}", self.target, self.value)
7869    }
7870}
7871
7872/// Left-hand side of an assignment in an UPDATE statement,
7873/// e.g. `foo` in `foo = 5` (ColumnName assignment) or
7874/// `(a, b)` in `(a, b) = (1, 2)` (Tuple assignment).
7875#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7876#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7877#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7878pub enum AssignmentTarget {
7879    /// A single column
7880    ColumnName(ObjectName),
7881    /// A tuple of columns
7882    Tuple(Vec<ObjectName>),
7883}
7884
7885impl fmt::Display for AssignmentTarget {
7886    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7887        match self {
7888            AssignmentTarget::ColumnName(column) => write!(f, "{column}"),
7889            AssignmentTarget::Tuple(columns) => write!(f, "({})", display_comma_separated(columns)),
7890        }
7891    }
7892}
7893
7894#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7895#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7896#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7897/// Expression forms allowed as a function argument.
7898pub enum FunctionArgExpr {
7899    /// A normal expression argument.
7900    Expr(Expr),
7901    /// Qualified wildcard, e.g. `alias.*` or `schema.table.*`.
7902    QualifiedWildcard(ObjectName),
7903    /// An unqualified `*` wildcard.
7904    Wildcard,
7905    /// An unqualified `*` wildcard with additional options, e.g. `* EXCLUDE(col)`.
7906    ///
7907    /// Used in Snowflake to support expressions like `HASH(* EXCLUDE(col))`.
7908    WildcardWithOptions(WildcardAdditionalOptions),
7909}
7910
7911impl From<Expr> for FunctionArgExpr {
7912    fn from(wildcard_expr: Expr) -> Self {
7913        match wildcard_expr {
7914            Expr::QualifiedWildcard(prefix, _) => Self::QualifiedWildcard(prefix),
7915            Expr::Wildcard(_) => Self::Wildcard,
7916            expr => Self::Expr(expr),
7917        }
7918    }
7919}
7920
7921impl fmt::Display for FunctionArgExpr {
7922    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7923        match self {
7924            FunctionArgExpr::Expr(expr) => write!(f, "{expr}"),
7925            FunctionArgExpr::QualifiedWildcard(prefix) => write!(f, "{prefix}.*"),
7926            FunctionArgExpr::Wildcard => f.write_str("*"),
7927            FunctionArgExpr::WildcardWithOptions(opts) => write!(f, "*{opts}"),
7928        }
7929    }
7930}
7931
7932#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7933#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7934#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7935/// Operator used to separate function arguments
7936pub enum FunctionArgOperator {
7937    /// function(arg1 = value1)
7938    Equals,
7939    /// function(arg1 => value1)
7940    RightArrow,
7941    /// function(arg1 := value1)
7942    Assignment,
7943    /// function(arg1 : value1)
7944    Colon,
7945    /// function(arg1 VALUE value1)
7946    Value,
7947}
7948
7949impl fmt::Display for FunctionArgOperator {
7950    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7951        match self {
7952            FunctionArgOperator::Equals => f.write_str("="),
7953            FunctionArgOperator::RightArrow => f.write_str("=>"),
7954            FunctionArgOperator::Assignment => f.write_str(":="),
7955            FunctionArgOperator::Colon => f.write_str(":"),
7956            FunctionArgOperator::Value => f.write_str("VALUE"),
7957        }
7958    }
7959}
7960
7961#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7962#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7963#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7964/// Forms of function arguments (named, expression-named, or positional).
7965pub enum FunctionArg {
7966    /// `name` is identifier
7967    ///
7968    /// Enabled when `Dialect::supports_named_fn_args_with_expr_name` returns 'false'
7969    Named {
7970        /// The identifier name of the argument.
7971        name: Ident,
7972        /// The argument expression or wildcard form.
7973        arg: FunctionArgExpr,
7974        /// The operator separating name and value.
7975        operator: FunctionArgOperator,
7976    },
7977    /// `name` is arbitrary expression
7978    ///
7979    /// Enabled when `Dialect::supports_named_fn_args_with_expr_name` returns 'true'
7980    ExprNamed {
7981        /// The expression used as the argument name.
7982        name: Expr,
7983        /// The argument expression or wildcard form.
7984        arg: FunctionArgExpr,
7985        /// The operator separating name and value.
7986        operator: FunctionArgOperator,
7987    },
7988    /// An unnamed argument (positional), given by expression or wildcard.
7989    Unnamed(FunctionArgExpr),
7990}
7991
7992impl fmt::Display for FunctionArg {
7993    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7994        match self {
7995            FunctionArg::Named {
7996                name,
7997                arg,
7998                operator,
7999            } => write!(f, "{name} {operator} {arg}"),
8000            FunctionArg::ExprNamed {
8001                name,
8002                arg,
8003                operator,
8004            } => write!(f, "{name} {operator} {arg}"),
8005            FunctionArg::Unnamed(unnamed_arg) => write!(f, "{unnamed_arg}"),
8006        }
8007    }
8008}
8009
8010#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8011#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8012#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8013/// Which cursor(s) to close.
8014pub enum CloseCursor {
8015    /// Close all cursors.
8016    All,
8017    /// Close a specific cursor by name.
8018    Specific {
8019        /// The name of the cursor to close.
8020        name: Ident,
8021    },
8022}
8023
8024impl fmt::Display for CloseCursor {
8025    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8026        match self {
8027            CloseCursor::All => write!(f, "ALL"),
8028            CloseCursor::Specific { name } => write!(f, "{name}"),
8029        }
8030    }
8031}
8032
8033/// A Drop Domain statement
8034#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8035#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8036#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8037pub struct DropDomain {
8038    /// Whether to drop the domain if it exists
8039    pub if_exists: bool,
8040    /// The name of the domain to drop
8041    pub name: ObjectName,
8042    /// The behavior to apply when dropping the domain
8043    pub drop_behavior: Option<DropBehavior>,
8044}
8045
8046/// A constant of form `<data_type> 'value'`.
8047/// This can represent ANSI SQL `DATE`, `TIME`, and `TIMESTAMP` literals (such as `DATE '2020-01-01'`),
8048/// as well as constants of other types (a non-standard PostgreSQL extension).
8049#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8050#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8051#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8052pub struct TypedString {
8053    /// The data type of the typed string (e.g. DATE, TIME, TIMESTAMP).
8054    pub data_type: DataType,
8055    /// The value of the constant.
8056    /// Hint: you can unwrap the string value using `value.into_string()`.
8057    pub value: ValueWithSpan,
8058    /// Flags whether this TypedString uses the [ODBC syntax].
8059    ///
8060    /// Example:
8061    /// ```sql
8062    /// -- An ODBC date literal:
8063    /// SELECT {d '2025-07-16'}
8064    /// -- This is equivalent to the standard ANSI SQL literal:
8065    /// SELECT DATE '2025-07-16'
8066    ///
8067    /// [ODBC syntax]: https://learn.microsoft.com/en-us/sql/odbc/reference/develop-app/date-time-and-timestamp-literals?view=sql-server-2017
8068    pub uses_odbc_syntax: bool,
8069}
8070
8071impl fmt::Display for TypedString {
8072    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8073        let data_type = &self.data_type;
8074        let value = &self.value;
8075        match self.uses_odbc_syntax {
8076            false => {
8077                write!(f, "{data_type}")?;
8078                write!(f, " {value}")
8079            }
8080            true => {
8081                let prefix = match data_type {
8082                    DataType::Date => "d",
8083                    DataType::Time(..) => "t",
8084                    DataType::Timestamp(..) => "ts",
8085                    _ => "?",
8086                };
8087                write!(f, "{{{prefix} {value}}}")
8088            }
8089        }
8090    }
8091}
8092
8093/// A function call
8094#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8095#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8096#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8097pub struct Function {
8098    /// The function name (may be qualified).
8099    pub name: ObjectName,
8100    /// Flags whether this function call uses the [ODBC syntax].
8101    ///
8102    /// Example:
8103    /// ```sql
8104    /// SELECT {fn CONCAT('foo', 'bar')}
8105    /// ```
8106    ///
8107    /// [ODBC syntax]: https://learn.microsoft.com/en-us/sql/odbc/reference/develop-app/scalar-function-calls?view=sql-server-2017
8108    pub uses_odbc_syntax: bool,
8109    /// The parameters to the function, including any options specified within the
8110    /// delimiting parentheses.
8111    ///
8112    /// Example:
8113    /// ```plaintext
8114    /// HISTOGRAM(0.5, 0.6)(x, y)
8115    /// ```
8116    ///
8117    /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/aggregate-functions/parametric-functions)
8118    pub parameters: FunctionArguments,
8119    /// The arguments to the function, including any options specified within the
8120    /// delimiting parentheses.
8121    pub args: FunctionArguments,
8122    /// e.g. `x > 5` in `COUNT(x) FILTER (WHERE x > 5)`
8123    pub filter: Option<Box<Expr>>,
8124    /// Indicates how `NULL`s should be handled in the calculation.
8125    ///
8126    /// Example:
8127    /// ```plaintext
8128    /// FIRST_VALUE( <expr> ) [ { IGNORE | RESPECT } NULLS ] OVER ...
8129    /// ```
8130    ///
8131    /// [Snowflake](https://docs.snowflake.com/en/sql-reference/functions/first_value)
8132    pub null_treatment: Option<NullTreatment>,
8133    /// The `OVER` clause, indicating a window function call.
8134    pub over: Option<WindowType>,
8135    /// A clause used with certain aggregate functions to control the ordering
8136    /// within grouped sets before the function is applied.
8137    ///
8138    /// Syntax:
8139    /// ```plaintext
8140    /// <aggregate_function>(expression) WITHIN GROUP (ORDER BY key [ASC | DESC], ...)
8141    /// ```
8142    pub within_group: Vec<OrderByExpr>,
8143}
8144
8145impl fmt::Display for Function {
8146    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8147        if self.uses_odbc_syntax {
8148            write!(f, "{{fn ")?;
8149        }
8150
8151        write!(f, "{}{}{}", self.name, self.parameters, self.args)?;
8152
8153        if !self.within_group.is_empty() {
8154            write!(
8155                f,
8156                " WITHIN GROUP (ORDER BY {})",
8157                display_comma_separated(&self.within_group)
8158            )?;
8159        }
8160
8161        if let Some(filter_cond) = &self.filter {
8162            write!(f, " FILTER (WHERE {filter_cond})")?;
8163        }
8164
8165        if let Some(null_treatment) = &self.null_treatment {
8166            write!(f, " {null_treatment}")?;
8167        }
8168
8169        if let Some(o) = &self.over {
8170            f.write_str(" OVER ")?;
8171            o.fmt(f)?;
8172        }
8173
8174        if self.uses_odbc_syntax {
8175            write!(f, "}}")?;
8176        }
8177
8178        Ok(())
8179    }
8180}
8181
8182/// The arguments passed to a function call.
8183#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8184#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8185#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8186pub enum FunctionArguments {
8187    /// Used for special functions like `CURRENT_TIMESTAMP` that are invoked
8188    /// without parentheses.
8189    None,
8190    /// On some dialects, a subquery can be passed without surrounding
8191    /// parentheses if it's the sole argument to the function.
8192    Subquery(Box<Query>),
8193    /// A normal function argument list, including any clauses within it such as
8194    /// `DISTINCT` or `ORDER BY`.
8195    List(FunctionArgumentList),
8196}
8197
8198impl fmt::Display for FunctionArguments {
8199    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8200        match self {
8201            FunctionArguments::None => Ok(()),
8202            FunctionArguments::Subquery(query) => write!(f, "({query})"),
8203            FunctionArguments::List(args) => write!(f, "({args})"),
8204        }
8205    }
8206}
8207
8208/// This represents everything inside the parentheses when calling a function.
8209#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8210#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8211#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8212pub struct FunctionArgumentList {
8213    /// `[ ALL | DISTINCT ]`
8214    pub duplicate_treatment: Option<DuplicateTreatment>,
8215    /// The function arguments.
8216    pub args: Vec<FunctionArg>,
8217    /// Additional clauses specified within the argument list.
8218    pub clauses: Vec<FunctionArgumentClause>,
8219}
8220
8221impl fmt::Display for FunctionArgumentList {
8222    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8223        if let Some(duplicate_treatment) = self.duplicate_treatment {
8224            write!(f, "{duplicate_treatment} ")?;
8225        }
8226        write!(f, "{}", display_comma_separated(&self.args))?;
8227        if !self.clauses.is_empty() {
8228            if !self.args.is_empty() {
8229                write!(f, " ")?;
8230            }
8231            write!(f, "{}", display_separated(&self.clauses, " "))?;
8232        }
8233        Ok(())
8234    }
8235}
8236
8237#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8238#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8239#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8240/// Clauses that can appear inside a function argument list.
8241pub enum FunctionArgumentClause {
8242    /// Indicates how `NULL`s should be handled in the calculation, e.g. in `FIRST_VALUE` on [BigQuery].
8243    ///
8244    /// Syntax:
8245    /// ```plaintext
8246    /// { IGNORE | RESPECT } NULLS ]
8247    /// ```
8248    ///
8249    /// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/navigation_functions#first_value
8250    IgnoreOrRespectNulls(NullTreatment),
8251    /// Specifies the the ordering for some ordered set aggregates, e.g. `ARRAY_AGG` on [BigQuery].
8252    ///
8253    /// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/aggregate_functions#array_agg
8254    OrderBy(Vec<OrderByExpr>),
8255    /// Specifies a limit for the `ARRAY_AGG` and `ARRAY_CONCAT_AGG` functions on BigQuery.
8256    Limit(Expr),
8257    /// Specifies the behavior on overflow of the `LISTAGG` function.
8258    ///
8259    /// See <https://trino.io/docs/current/functions/aggregate.html>.
8260    OnOverflow(ListAggOnOverflow),
8261    /// Specifies a minimum or maximum bound on the input to [`ANY_VALUE`] on BigQuery.
8262    ///
8263    /// Syntax:
8264    /// ```plaintext
8265    /// HAVING { MAX | MIN } expression
8266    /// ```
8267    ///
8268    /// [`ANY_VALUE`]: https://cloud.google.com/bigquery/docs/reference/standard-sql/aggregate_functions#any_value
8269    Having(HavingBound),
8270    /// The `SEPARATOR` clause to the [`GROUP_CONCAT`] function in MySQL.
8271    ///
8272    /// [`GROUP_CONCAT`]: https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html#function_group-concat
8273    Separator(ValueWithSpan),
8274    /// The `ON NULL` clause for some JSON functions.
8275    ///
8276    /// [MSSQL `JSON_ARRAY`](https://learn.microsoft.com/en-us/sql/t-sql/functions/json-array-transact-sql?view=sql-server-ver16)
8277    /// [MSSQL `JSON_OBJECT`](https://learn.microsoft.com/en-us/sql/t-sql/functions/json-object-transact-sql?view=sql-server-ver16>)
8278    /// [PostgreSQL JSON functions](https://www.postgresql.org/docs/current/functions-json.html#FUNCTIONS-JSON-PROCESSING)
8279    JsonNullClause(JsonNullClause),
8280    /// The `RETURNING` clause for some JSON functions in PostgreSQL
8281    ///
8282    /// [`JSON_OBJECT`](https://www.postgresql.org/docs/current/functions-json.html#:~:text=json_object)
8283    JsonReturningClause(JsonReturningClause),
8284}
8285
8286impl fmt::Display for FunctionArgumentClause {
8287    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8288        match self {
8289            FunctionArgumentClause::IgnoreOrRespectNulls(null_treatment) => {
8290                write!(f, "{null_treatment}")
8291            }
8292            FunctionArgumentClause::OrderBy(order_by) => {
8293                write!(f, "ORDER BY {}", display_comma_separated(order_by))
8294            }
8295            FunctionArgumentClause::Limit(limit) => write!(f, "LIMIT {limit}"),
8296            FunctionArgumentClause::OnOverflow(on_overflow) => write!(f, "{on_overflow}"),
8297            FunctionArgumentClause::Having(bound) => write!(f, "{bound}"),
8298            FunctionArgumentClause::Separator(sep) => write!(f, "SEPARATOR {sep}"),
8299            FunctionArgumentClause::JsonNullClause(null_clause) => write!(f, "{null_clause}"),
8300            FunctionArgumentClause::JsonReturningClause(returning_clause) => {
8301                write!(f, "{returning_clause}")
8302            }
8303        }
8304    }
8305}
8306
8307/// A method call
8308#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8309#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8310#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8311pub struct Method {
8312    /// The expression on which the method is invoked.
8313    pub expr: Box<Expr>,
8314    // always non-empty
8315    /// The sequence of chained method calls.
8316    pub method_chain: Vec<Function>,
8317}
8318
8319impl fmt::Display for Method {
8320    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8321        write!(
8322            f,
8323            "{}.{}",
8324            self.expr,
8325            display_separated(&self.method_chain, ".")
8326        )
8327    }
8328}
8329
8330#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8331#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8332#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8333/// How duplicate values are treated inside function argument lists.
8334pub enum DuplicateTreatment {
8335    /// Consider only unique values.
8336    Distinct,
8337    /// Retain all duplicate values (the default).
8338    All,
8339}
8340
8341impl fmt::Display for DuplicateTreatment {
8342    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8343        match self {
8344            DuplicateTreatment::Distinct => write!(f, "DISTINCT"),
8345            DuplicateTreatment::All => write!(f, "ALL"),
8346        }
8347    }
8348}
8349
8350#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8351#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8352#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8353/// How the `ANALYZE`/`EXPLAIN ANALYZE` format is specified.
8354pub enum AnalyzeFormatKind {
8355    /// Format provided as a keyword, e.g. `FORMAT JSON`.
8356    Keyword(AnalyzeFormat),
8357    /// Format provided as an assignment, e.g. `FORMAT=JSON`.
8358    Assignment(AnalyzeFormat),
8359}
8360
8361impl fmt::Display for AnalyzeFormatKind {
8362    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
8363        match self {
8364            AnalyzeFormatKind::Keyword(format) => write!(f, "FORMAT {format}"),
8365            AnalyzeFormatKind::Assignment(format) => write!(f, "FORMAT={format}"),
8366        }
8367    }
8368}
8369
8370#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8371#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8372#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8373/// Output formats supported for `ANALYZE`/`EXPLAIN ANALYZE`.
8374pub enum AnalyzeFormat {
8375    /// Plain text format.
8376    TEXT,
8377    /// Graphviz DOT format.
8378    GRAPHVIZ,
8379    /// JSON format.
8380    JSON,
8381    /// Traditional explain output.
8382    TRADITIONAL,
8383    /// Tree-style explain output.
8384    TREE,
8385}
8386
8387impl fmt::Display for AnalyzeFormat {
8388    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
8389        f.write_str(match self {
8390            AnalyzeFormat::TEXT => "TEXT",
8391            AnalyzeFormat::GRAPHVIZ => "GRAPHVIZ",
8392            AnalyzeFormat::JSON => "JSON",
8393            AnalyzeFormat::TRADITIONAL => "TRADITIONAL",
8394            AnalyzeFormat::TREE => "TREE",
8395        })
8396    }
8397}
8398
8399/// External table's available file format
8400#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8401#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8402#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8403pub enum FileFormat {
8404    /// Text file format.
8405    TEXTFILE,
8406    /// Sequence file format.
8407    SEQUENCEFILE,
8408    /// ORC file format.
8409    ORC,
8410    /// Parquet file format.
8411    PARQUET,
8412    /// Avro file format.
8413    AVRO,
8414    /// RCFile format.
8415    RCFILE,
8416    /// JSON file format.
8417    JSONFILE,
8418}
8419
8420impl fmt::Display for FileFormat {
8421    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8422        use self::FileFormat::*;
8423        f.write_str(match self {
8424            TEXTFILE => "TEXTFILE",
8425            SEQUENCEFILE => "SEQUENCEFILE",
8426            ORC => "ORC",
8427            PARQUET => "PARQUET",
8428            AVRO => "AVRO",
8429            RCFILE => "RCFILE",
8430            JSONFILE => "JSONFILE",
8431        })
8432    }
8433}
8434
8435/// The `ON OVERFLOW` clause of a LISTAGG invocation
8436#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8437#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8438#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8439pub enum ListAggOnOverflow {
8440    /// `ON OVERFLOW ERROR`
8441    Error,
8442
8443    /// `ON OVERFLOW TRUNCATE [ <filler> ] WITH[OUT] COUNT`
8444    Truncate {
8445        /// Optional filler expression used when truncating.
8446        filler: Option<Box<Expr>>,
8447        /// Whether to include a count when truncating.
8448        with_count: bool,
8449    },
8450}
8451
8452impl fmt::Display for ListAggOnOverflow {
8453    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8454        write!(f, "ON OVERFLOW")?;
8455        match self {
8456            ListAggOnOverflow::Error => write!(f, " ERROR"),
8457            ListAggOnOverflow::Truncate { filler, with_count } => {
8458                write!(f, " TRUNCATE")?;
8459                if let Some(filler) = filler {
8460                    write!(f, " {filler}")?;
8461                }
8462                if *with_count {
8463                    write!(f, " WITH")?;
8464                } else {
8465                    write!(f, " WITHOUT")?;
8466                }
8467                write!(f, " COUNT")
8468            }
8469        }
8470    }
8471}
8472
8473/// The `HAVING` clause in a call to `ANY_VALUE` on BigQuery.
8474#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8475#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8476#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8477pub struct HavingBound(pub HavingBoundKind, pub Expr);
8478
8479impl fmt::Display for HavingBound {
8480    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8481        write!(f, "HAVING {} {}", self.0, self.1)
8482    }
8483}
8484
8485#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8486#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8487#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8488/// Which bound is used in a HAVING clause for ANY_VALUE on BigQuery.
8489pub enum HavingBoundKind {
8490    /// The minimum bound.
8491    Min,
8492    /// The maximum bound.
8493    Max,
8494}
8495
8496impl fmt::Display for HavingBoundKind {
8497    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8498        match self {
8499            HavingBoundKind::Min => write!(f, "MIN"),
8500            HavingBoundKind::Max => write!(f, "MAX"),
8501        }
8502    }
8503}
8504
8505#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8506#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8507#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8508/// Types of database objects referenced by DDL statements.
8509pub enum ObjectType {
8510    /// A collation.
8511    Collation,
8512    /// A table.
8513    Table,
8514    /// A view.
8515    View,
8516    /// A materialized view.
8517    MaterializedView,
8518    /// An index.
8519    Index,
8520    /// A schema.
8521    Schema,
8522    /// A database.
8523    Database,
8524    /// A role.
8525    Role,
8526    /// A sequence.
8527    Sequence,
8528    /// A stage.
8529    Stage,
8530    /// A type definition.
8531    Type,
8532    /// A user.
8533    User,
8534    /// A stream.
8535    Stream,
8536}
8537
8538impl fmt::Display for ObjectType {
8539    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8540        f.write_str(match self {
8541            ObjectType::Collation => "COLLATION",
8542            ObjectType::Table => "TABLE",
8543            ObjectType::View => "VIEW",
8544            ObjectType::MaterializedView => "MATERIALIZED VIEW",
8545            ObjectType::Index => "INDEX",
8546            ObjectType::Schema => "SCHEMA",
8547            ObjectType::Database => "DATABASE",
8548            ObjectType::Role => "ROLE",
8549            ObjectType::Sequence => "SEQUENCE",
8550            ObjectType::Stage => "STAGE",
8551            ObjectType::Type => "TYPE",
8552            ObjectType::User => "USER",
8553            ObjectType::Stream => "STREAM",
8554        })
8555    }
8556}
8557
8558#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8559#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8560#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8561/// Types supported by `KILL` statements.
8562pub enum KillType {
8563    /// Kill a connection.
8564    Connection,
8565    /// Kill a running query.
8566    Query,
8567    /// Kill a mutation (ClickHouse).
8568    Mutation,
8569}
8570
8571impl fmt::Display for KillType {
8572    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8573        f.write_str(match self {
8574            // MySQL
8575            KillType::Connection => "CONNECTION",
8576            KillType::Query => "QUERY",
8577            // Clickhouse supports Mutation
8578            KillType::Mutation => "MUTATION",
8579        })
8580    }
8581}
8582
8583#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8584#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8585#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8586/// Distribution style options for Hive tables.
8587pub enum HiveDistributionStyle {
8588    /// Partitioned distribution with the given columns.
8589    PARTITIONED {
8590        /// Columns used for partitioning.
8591        columns: Vec<ColumnDef>,
8592    },
8593    /// Skewed distribution definition.
8594    SKEWED {
8595        /// Columns participating in the skew definition.
8596        columns: Vec<ColumnDef>,
8597        /// Columns listed in the `ON` clause for skewing.
8598        on: Vec<ColumnDef>,
8599        /// Whether skewed data is stored as directories.
8600        stored_as_directories: bool,
8601    },
8602    /// No distribution style specified.
8603    NONE,
8604}
8605
8606#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8607#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8608#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8609/// Row format specification for Hive tables (SERDE or DELIMITED).
8610pub enum HiveRowFormat {
8611    /// SerDe class specification with the implementing class name.
8612    SERDE {
8613        /// The SerDe implementation class name.
8614        class: String,
8615    },
8616    /// Delimited row format with one or more delimiter specifications.
8617    DELIMITED {
8618        /// The list of delimiters used for delimiting fields/lines.
8619        delimiters: Vec<HiveRowDelimiter>,
8620    },
8621}
8622
8623#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8624#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8625#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8626/// Format specification for `LOAD DATA` Hive operations.
8627pub struct HiveLoadDataFormat {
8628    /// SerDe expression used for the table.
8629    pub serde: Expr,
8630    /// Input format expression.
8631    pub input_format: Expr,
8632}
8633
8634#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8635#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8636#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8637/// A single row delimiter specification for Hive `ROW FORMAT`.
8638pub struct HiveRowDelimiter {
8639    /// The delimiter kind (fields/lines/etc.).
8640    pub delimiter: HiveDelimiter,
8641    /// The delimiter character identifier.
8642    pub char: Ident,
8643}
8644
8645impl fmt::Display for HiveRowDelimiter {
8646    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8647        write!(f, "{} ", self.delimiter)?;
8648        write!(f, "{}", self.char)
8649    }
8650}
8651
8652#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8653#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8654#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8655/// Kind of delimiter used in Hive `ROW FORMAT` definitions.
8656pub enum HiveDelimiter {
8657    /// Fields terminated by a delimiter.
8658    FieldsTerminatedBy,
8659    /// Fields escaped by a character.
8660    FieldsEscapedBy,
8661    /// Collection items terminated by a delimiter.
8662    CollectionItemsTerminatedBy,
8663    /// Map keys terminated by a delimiter.
8664    MapKeysTerminatedBy,
8665    /// Lines terminated by a delimiter.
8666    LinesTerminatedBy,
8667    /// Null represented by a specific token.
8668    NullDefinedAs,
8669}
8670
8671impl fmt::Display for HiveDelimiter {
8672    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8673        use HiveDelimiter::*;
8674        f.write_str(match self {
8675            FieldsTerminatedBy => "FIELDS TERMINATED BY",
8676            FieldsEscapedBy => "ESCAPED BY",
8677            CollectionItemsTerminatedBy => "COLLECTION ITEMS TERMINATED BY",
8678            MapKeysTerminatedBy => "MAP KEYS TERMINATED BY",
8679            LinesTerminatedBy => "LINES TERMINATED BY",
8680            NullDefinedAs => "NULL DEFINED AS",
8681        })
8682    }
8683}
8684
8685#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8686#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8687#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8688/// Describe output format options for Hive `DESCRIBE`/`EXPLAIN`.
8689pub enum HiveDescribeFormat {
8690    /// Extended describe output.
8691    Extended,
8692    /// Formatted describe output.
8693    Formatted,
8694}
8695
8696impl fmt::Display for HiveDescribeFormat {
8697    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8698        use HiveDescribeFormat::*;
8699        f.write_str(match self {
8700            Extended => "EXTENDED",
8701            Formatted => "FORMATTED",
8702        })
8703    }
8704}
8705
8706#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8707#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8708#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8709/// Aliases accepted for describe-style commands.
8710pub enum DescribeAlias {
8711    /// `DESCRIBE` alias.
8712    Describe,
8713    /// `EXPLAIN` alias.
8714    Explain,
8715    /// `DESC` alias.
8716    Desc,
8717}
8718
8719impl fmt::Display for DescribeAlias {
8720    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8721        use DescribeAlias::*;
8722        f.write_str(match self {
8723            Describe => "DESCRIBE",
8724            Explain => "EXPLAIN",
8725            Desc => "DESC",
8726        })
8727    }
8728}
8729
8730#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8731#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8732#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8733#[allow(clippy::large_enum_variant)]
8734/// Hive input/output format specification used in `CREATE TABLE`.
8735pub enum HiveIOFormat {
8736    /// Generic IO format with separate input and output expressions.
8737    IOF {
8738        /// Expression for the input format.
8739        input_format: Expr,
8740        /// Expression for the output format.
8741        output_format: Expr,
8742    },
8743    /// File format wrapper referencing a `FileFormat` variant.
8744    FileFormat {
8745        /// The file format used for storage.
8746        format: FileFormat,
8747    },
8748}
8749
8750#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Default)]
8751#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8752#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8753/// Hive table format and storage-related options.
8754pub struct HiveFormat {
8755    /// Optional row format specification.
8756    pub row_format: Option<HiveRowFormat>,
8757    /// Optional SerDe properties expressed as SQL options.
8758    pub serde_properties: Option<Vec<SqlOption>>,
8759    /// Optional input/output storage format details.
8760    pub storage: Option<HiveIOFormat>,
8761    /// Optional location (URI or path) for table data.
8762    pub location: Option<String>,
8763}
8764
8765#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8766#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8767#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8768/// A clustered index column specification.
8769pub struct ClusteredIndex {
8770    /// Column identifier for the clustered index entry.
8771    pub name: Ident,
8772    /// Optional sort direction: `Some(true)` for ASC, `Some(false)` for DESC, `None` for unspecified.
8773    pub asc: Option<bool>,
8774}
8775
8776impl fmt::Display for ClusteredIndex {
8777    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8778        write!(f, "{}", self.name)?;
8779        match self.asc {
8780            Some(true) => write!(f, " ASC"),
8781            Some(false) => write!(f, " DESC"),
8782            _ => Ok(()),
8783        }
8784    }
8785}
8786
8787#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8788#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8789#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8790/// Clustered options used for `CREATE TABLE` clustered/indexed storage.
8791pub enum TableOptionsClustered {
8792    /// Use a columnstore index.
8793    ColumnstoreIndex,
8794    /// Columnstore index with an explicit ordering of columns.
8795    ColumnstoreIndexOrder(Vec<Ident>),
8796    /// A named clustered index with one or more columns.
8797    Index(Vec<ClusteredIndex>),
8798}
8799
8800impl fmt::Display for TableOptionsClustered {
8801    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8802        match self {
8803            TableOptionsClustered::ColumnstoreIndex => {
8804                write!(f, "CLUSTERED COLUMNSTORE INDEX")
8805            }
8806            TableOptionsClustered::ColumnstoreIndexOrder(values) => {
8807                write!(
8808                    f,
8809                    "CLUSTERED COLUMNSTORE INDEX ORDER ({})",
8810                    display_comma_separated(values)
8811                )
8812            }
8813            TableOptionsClustered::Index(values) => {
8814                write!(f, "CLUSTERED INDEX ({})", display_comma_separated(values))
8815            }
8816        }
8817    }
8818}
8819
8820/// Specifies which partition the boundary values on table partitioning belongs to.
8821#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash)]
8822#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8823#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8824pub enum PartitionRangeDirection {
8825    /// LEFT range direction.
8826    Left,
8827    /// RIGHT range direction.
8828    Right,
8829}
8830
8831#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8832#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8833#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8834/// SQL option syntax used in table and server definitions.
8835pub enum SqlOption {
8836    /// Clustered represents the clustered version of table storage for MSSQL.
8837    ///
8838    /// <https://learn.microsoft.com/en-us/sql/t-sql/statements/create-table-azure-sql-data-warehouse?view=aps-pdw-2016-au7#TableOptions>
8839    Clustered(TableOptionsClustered),
8840    /// Single identifier options, e.g. `HEAP` for MSSQL.
8841    ///
8842    /// <https://learn.microsoft.com/en-us/sql/t-sql/statements/create-table-azure-sql-data-warehouse?view=aps-pdw-2016-au7#TableOptions>
8843    Ident(Ident),
8844    /// Any option that consists of a key value pair where the value is an expression. e.g.
8845    ///
8846    ///   WITH(DISTRIBUTION = ROUND_ROBIN)
8847    KeyValue {
8848        /// The option key identifier.
8849        key: Ident,
8850        /// The expression value for the option.
8851        value: Expr,
8852    },
8853    /// One or more table partitions and represents which partition the boundary values belong to,
8854    /// e.g.
8855    ///
8856    ///   PARTITION (id RANGE LEFT FOR VALUES (10, 20, 30, 40))
8857    ///
8858    /// <https://learn.microsoft.com/en-us/sql/t-sql/statements/create-table-azure-sql-data-warehouse?view=aps-pdw-2016-au7#TablePartitionOptions>
8859    Partition {
8860        /// The partition column name.
8861        column_name: Ident,
8862        /// Optional direction for the partition range (LEFT/RIGHT).
8863        range_direction: Option<PartitionRangeDirection>,
8864        /// Values that define the partition boundaries.
8865        for_values: Vec<Expr>,
8866    },
8867    /// Comment parameter (supports `=` and no `=` syntax)
8868    Comment(CommentDef),
8869    /// MySQL TableSpace option
8870    /// <https://dev.mysql.com/doc/refman/8.4/en/create-table.html>
8871    TableSpace(TablespaceOption),
8872    /// An option representing a key value pair, where the value is a parenthesized list and with an optional name
8873    /// e.g.
8874    ///
8875    ///   UNION  = (tbl_name\[,tbl_name\]...) <https://dev.mysql.com/doc/refman/8.4/en/create-table.html>
8876    ///   ENGINE = ReplicatedMergeTree('/table_name','{replica}', ver) <https://clickhouse.com/docs/engines/table-engines/mergetree-family/replication>
8877    ///   ENGINE = SummingMergeTree(\[columns\]) <https://clickhouse.com/docs/engines/table-engines/mergetree-family/summingmergetree>
8878    NamedParenthesizedList(NamedParenthesizedList),
8879}
8880
8881impl fmt::Display for SqlOption {
8882    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8883        match self {
8884            SqlOption::Clustered(c) => write!(f, "{c}"),
8885            SqlOption::Ident(ident) => {
8886                write!(f, "{ident}")
8887            }
8888            SqlOption::KeyValue { key: name, value } => {
8889                write!(f, "{name} = {value}")
8890            }
8891            SqlOption::Partition {
8892                column_name,
8893                range_direction,
8894                for_values,
8895            } => {
8896                let direction = match range_direction {
8897                    Some(PartitionRangeDirection::Left) => " LEFT",
8898                    Some(PartitionRangeDirection::Right) => " RIGHT",
8899                    None => "",
8900                };
8901
8902                write!(
8903                    f,
8904                    "PARTITION ({} RANGE{} FOR VALUES ({}))",
8905                    column_name,
8906                    direction,
8907                    display_comma_separated(for_values)
8908                )
8909            }
8910            SqlOption::TableSpace(tablespace_option) => {
8911                write!(f, "TABLESPACE {}", tablespace_option.name)?;
8912                match tablespace_option.storage {
8913                    Some(StorageType::Disk) => write!(f, " STORAGE DISK"),
8914                    Some(StorageType::Memory) => write!(f, " STORAGE MEMORY"),
8915                    None => Ok(()),
8916                }
8917            }
8918            SqlOption::Comment(comment) => match comment {
8919                CommentDef::WithEq(comment) => {
8920                    write!(f, "COMMENT = '{comment}'")
8921                }
8922                CommentDef::WithoutEq(comment) => {
8923                    write!(f, "COMMENT '{comment}'")
8924                }
8925            },
8926            SqlOption::NamedParenthesizedList(value) => {
8927                write!(f, "{} = ", value.key)?;
8928                if let Some(key) = &value.name {
8929                    write!(f, "{key}")?;
8930                }
8931                if !value.values.is_empty() {
8932                    write!(f, "({})", display_comma_separated(&value.values))?
8933                }
8934                Ok(())
8935            }
8936        }
8937    }
8938}
8939
8940#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
8941#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8942#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8943/// Storage type options for a tablespace.
8944pub enum StorageType {
8945    /// Store on disk.
8946    Disk,
8947    /// Store in memory.
8948    Memory,
8949}
8950
8951#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
8952#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8953#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8954/// MySql TableSpace option
8955/// <https://dev.mysql.com/doc/refman/8.4/en/create-table.html>
8956pub struct TablespaceOption {
8957    /// Name of the tablespace.
8958    pub name: String,
8959    /// Optional storage type for the tablespace.
8960    pub storage: Option<StorageType>,
8961}
8962
8963#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8964#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8965#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8966/// A key/value identifier pair used for secret or key-based options.
8967pub struct SecretOption {
8968    /// The option key identifier.
8969    pub key: Ident,
8970    /// The option value identifier.
8971    pub value: Ident,
8972}
8973
8974impl fmt::Display for SecretOption {
8975    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8976        write!(f, "{} {}", self.key, self.value)
8977    }
8978}
8979
8980/// A `CREATE SERVER` statement.
8981///
8982/// [PostgreSQL Documentation](https://www.postgresql.org/docs/current/sql-createserver.html)
8983#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8984#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8985#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8986pub struct CreateServerStatement {
8987    /// The server name.
8988    pub name: ObjectName,
8989    /// Whether `IF NOT EXISTS` was specified.
8990    pub if_not_exists: bool,
8991    /// Optional server type identifier.
8992    pub server_type: Option<Ident>,
8993    /// Optional server version identifier.
8994    pub version: Option<Ident>,
8995    /// Foreign-data wrapper object name.
8996    pub foreign_data_wrapper: ObjectName,
8997    /// Optional list of server options.
8998    pub options: Option<Vec<CreateServerOption>>,
8999}
9000
9001impl fmt::Display for CreateServerStatement {
9002    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
9003        let CreateServerStatement {
9004            name,
9005            if_not_exists,
9006            server_type,
9007            version,
9008            foreign_data_wrapper,
9009            options,
9010        } = self;
9011
9012        write!(
9013            f,
9014            "CREATE SERVER {if_not_exists}{name} ",
9015            if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
9016        )?;
9017
9018        if let Some(st) = server_type {
9019            write!(f, "TYPE {st} ")?;
9020        }
9021
9022        if let Some(v) = version {
9023            write!(f, "VERSION {v} ")?;
9024        }
9025
9026        write!(f, "FOREIGN DATA WRAPPER {foreign_data_wrapper}")?;
9027
9028        if let Some(o) = options {
9029            write!(f, " OPTIONS ({o})", o = display_comma_separated(o))?;
9030        }
9031
9032        Ok(())
9033    }
9034}
9035
9036/// A key/value option for `CREATE SERVER`.
9037#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9038#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9039#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9040pub struct CreateServerOption {
9041    /// Option key identifier.
9042    pub key: Ident,
9043    /// Option value identifier.
9044    pub value: Ident,
9045}
9046
9047impl fmt::Display for CreateServerOption {
9048    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9049        write!(f, "{} {}", self.key, self.value)
9050    }
9051}
9052
9053#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9054#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9055#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9056/// Options supported by DuckDB for `ATTACH DATABASE`.
9057pub enum AttachDuckDBDatabaseOption {
9058    /// READ_ONLY option, optional boolean value.
9059    ReadOnly(Option<bool>),
9060    /// TYPE option specifying a database type identifier.
9061    Type(Ident),
9062}
9063
9064impl fmt::Display for AttachDuckDBDatabaseOption {
9065    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9066        match self {
9067            AttachDuckDBDatabaseOption::ReadOnly(Some(true)) => write!(f, "READ_ONLY true"),
9068            AttachDuckDBDatabaseOption::ReadOnly(Some(false)) => write!(f, "READ_ONLY false"),
9069            AttachDuckDBDatabaseOption::ReadOnly(None) => write!(f, "READ_ONLY"),
9070            AttachDuckDBDatabaseOption::Type(t) => write!(f, "TYPE {t}"),
9071        }
9072    }
9073}
9074
9075#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9076#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9077#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9078/// Mode for transactions: access mode or isolation level.
9079pub enum TransactionMode {
9080    /// Access mode for a transaction (e.g. `READ ONLY` / `READ WRITE`).
9081    AccessMode(TransactionAccessMode),
9082    /// Isolation level for a transaction (e.g. `SERIALIZABLE`).
9083    IsolationLevel(TransactionIsolationLevel),
9084}
9085
9086impl fmt::Display for TransactionMode {
9087    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9088        use TransactionMode::*;
9089        match self {
9090            AccessMode(access_mode) => write!(f, "{access_mode}"),
9091            IsolationLevel(iso_level) => write!(f, "ISOLATION LEVEL {iso_level}"),
9092        }
9093    }
9094}
9095
9096#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9097#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9098#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9099/// Transaction access mode (READ ONLY / READ WRITE).
9100pub enum TransactionAccessMode {
9101    /// READ ONLY access mode.
9102    ReadOnly,
9103    /// READ WRITE access mode.
9104    ReadWrite,
9105}
9106
9107impl fmt::Display for TransactionAccessMode {
9108    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9109        use TransactionAccessMode::*;
9110        f.write_str(match self {
9111            ReadOnly => "READ ONLY",
9112            ReadWrite => "READ WRITE",
9113        })
9114    }
9115}
9116
9117#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9118#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9119#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9120/// Transaction isolation levels.
9121pub enum TransactionIsolationLevel {
9122    /// READ UNCOMMITTED isolation level.
9123    ReadUncommitted,
9124    /// READ COMMITTED isolation level.
9125    ReadCommitted,
9126    /// REPEATABLE READ isolation level.
9127    RepeatableRead,
9128    /// SERIALIZABLE isolation level.
9129    Serializable,
9130    /// SNAPSHOT isolation level.
9131    Snapshot,
9132}
9133
9134impl fmt::Display for TransactionIsolationLevel {
9135    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9136        use TransactionIsolationLevel::*;
9137        f.write_str(match self {
9138            ReadUncommitted => "READ UNCOMMITTED",
9139            ReadCommitted => "READ COMMITTED",
9140            RepeatableRead => "REPEATABLE READ",
9141            Serializable => "SERIALIZABLE",
9142            Snapshot => "SNAPSHOT",
9143        })
9144    }
9145}
9146
9147/// Modifier for the transaction in the `BEGIN` syntax
9148///
9149/// SQLite: <https://sqlite.org/lang_transaction.html>
9150/// MS-SQL: <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/try-catch-transact-sql>
9151#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9152#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9153#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9154pub enum TransactionModifier {
9155    /// DEFERRED transaction modifier.
9156    Deferred,
9157    /// IMMEDIATE transaction modifier.
9158    Immediate,
9159    /// EXCLUSIVE transaction modifier.
9160    Exclusive,
9161    /// TRY block modifier (MS-SQL style TRY/CATCH).
9162    Try,
9163    /// CATCH block modifier (MS-SQL style TRY/CATCH).
9164    Catch,
9165}
9166
9167impl fmt::Display for TransactionModifier {
9168    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9169        use TransactionModifier::*;
9170        f.write_str(match self {
9171            Deferred => "DEFERRED",
9172            Immediate => "IMMEDIATE",
9173            Exclusive => "EXCLUSIVE",
9174            Try => "TRY",
9175            Catch => "CATCH",
9176        })
9177    }
9178}
9179
9180#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9181#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9182#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9183/// Filter forms usable in SHOW statements.
9184pub enum ShowStatementFilter {
9185    /// Filter using LIKE pattern.
9186    Like(String),
9187    /// Filter using ILIKE pattern.
9188    ILike(String),
9189    /// Filter using a WHERE expression.
9190    Where(Expr),
9191    /// Filter provided without a keyword (raw string).
9192    NoKeyword(String),
9193}
9194
9195impl fmt::Display for ShowStatementFilter {
9196    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9197        use ShowStatementFilter::*;
9198        match self {
9199            Like(pattern) => write!(f, "LIKE '{}'", value::escape_single_quote_string(pattern)),
9200            ILike(pattern) => write!(f, "ILIKE {}", value::escape_single_quote_string(pattern)),
9201            Where(expr) => write!(f, "WHERE {expr}"),
9202            NoKeyword(pattern) => write!(f, "'{}'", value::escape_single_quote_string(pattern)),
9203        }
9204    }
9205}
9206
9207#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9208#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9209#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9210/// Clause types used with SHOW ... IN/FROM.
9211pub enum ShowStatementInClause {
9212    /// Use the `IN` clause.
9213    IN,
9214    /// Use the `FROM` clause.
9215    FROM,
9216}
9217
9218impl fmt::Display for ShowStatementInClause {
9219    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9220        use ShowStatementInClause::*;
9221        match self {
9222            FROM => write!(f, "FROM"),
9223            IN => write!(f, "IN"),
9224        }
9225    }
9226}
9227
9228/// Sqlite specific syntax
9229///
9230/// See [Sqlite documentation](https://sqlite.org/lang_conflict.html)
9231/// for more details.
9232#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9233#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9234#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9235pub enum SqliteOnConflict {
9236    /// Use ROLLBACK on conflict.
9237    Rollback,
9238    /// Use ABORT on conflict.
9239    Abort,
9240    /// Use FAIL on conflict.
9241    Fail,
9242    /// Use IGNORE on conflict.
9243    Ignore,
9244    /// Use REPLACE on conflict.
9245    Replace,
9246}
9247
9248impl fmt::Display for SqliteOnConflict {
9249    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9250        use SqliteOnConflict::*;
9251        match self {
9252            Rollback => write!(f, "OR ROLLBACK"),
9253            Abort => write!(f, "OR ABORT"),
9254            Fail => write!(f, "OR FAIL"),
9255            Ignore => write!(f, "OR IGNORE"),
9256            Replace => write!(f, "OR REPLACE"),
9257        }
9258    }
9259}
9260
9261/// Mysql specific syntax
9262///
9263/// See [Mysql documentation](https://dev.mysql.com/doc/refman/8.0/en/replace.html)
9264/// See [Mysql documentation](https://dev.mysql.com/doc/refman/8.0/en/insert.html)
9265/// for more details.
9266#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9267#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9268#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9269pub enum MysqlInsertPriority {
9270    /// LOW_PRIORITY modifier for INSERT/REPLACE.
9271    LowPriority,
9272    /// DELAYED modifier for INSERT/REPLACE.
9273    Delayed,
9274    /// HIGH_PRIORITY modifier for INSERT/REPLACE.
9275    HighPriority,
9276}
9277
9278impl fmt::Display for crate::ast::MysqlInsertPriority {
9279    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9280        use MysqlInsertPriority::*;
9281        match self {
9282            LowPriority => write!(f, "LOW_PRIORITY"),
9283            Delayed => write!(f, "DELAYED"),
9284            HighPriority => write!(f, "HIGH_PRIORITY"),
9285        }
9286    }
9287}
9288
9289#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9290#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9291#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9292/// Source for the `COPY` command: a table or a query.
9293pub enum CopySource {
9294    /// Copy from a table with optional column list.
9295    Table {
9296        /// The name of the table to copy from.
9297        table_name: ObjectName,
9298        /// A list of column names to copy. Empty list means that all columns
9299        /// are copied.
9300        columns: Vec<Ident>,
9301    },
9302    /// Copy from the results of a query.
9303    Query(Box<Query>),
9304}
9305
9306#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9307#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9308#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9309/// Target for the `COPY` command: STDIN, STDOUT, a file, or a program.
9310pub enum CopyTarget {
9311    /// Use standard input as the source.
9312    Stdin,
9313    /// Use standard output as the target.
9314    Stdout,
9315    /// Read from or write to a file.
9316    File {
9317        /// The path name of the input or output file.
9318        filename: String,
9319    },
9320    /// Use a program as the source or target (shell command).
9321    Program {
9322        /// A command to execute
9323        command: String,
9324    },
9325}
9326
9327impl fmt::Display for CopyTarget {
9328    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9329        use CopyTarget::*;
9330        match self {
9331            Stdin => write!(f, "STDIN"),
9332            Stdout => write!(f, "STDOUT"),
9333            File { filename } => write!(f, "'{}'", value::escape_single_quote_string(filename)),
9334            Program { command } => write!(
9335                f,
9336                "PROGRAM '{}'",
9337                value::escape_single_quote_string(command)
9338            ),
9339        }
9340    }
9341}
9342
9343#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9344#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9345#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9346/// Action to take `ON COMMIT` for temporary tables.
9347pub enum OnCommit {
9348    /// Delete rows on commit.
9349    DeleteRows,
9350    /// Preserve rows on commit.
9351    PreserveRows,
9352    /// Drop the table on commit.
9353    Drop,
9354}
9355
9356/// An option in `COPY` statement.
9357///
9358/// <https://www.postgresql.org/docs/14/sql-copy.html>
9359#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9360#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9361#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9362pub enum CopyOption {
9363    /// FORMAT format_name
9364    Format(Ident),
9365    /// FREEZE \[ boolean \]
9366    Freeze(bool),
9367    /// DELIMITER 'delimiter_character'
9368    Delimiter(char),
9369    /// NULL 'null_string'
9370    Null(String),
9371    /// HEADER \[ boolean \]
9372    Header(bool),
9373    /// QUOTE 'quote_character'
9374    Quote(char),
9375    /// ESCAPE 'escape_character'
9376    Escape(char),
9377    /// FORCE_QUOTE { ( column_name [, ...] ) | * }
9378    ForceQuote(Vec<Ident>),
9379    /// FORCE_NOT_NULL ( column_name [, ...] )
9380    ForceNotNull(Vec<Ident>),
9381    /// FORCE_NULL ( column_name [, ...] )
9382    ForceNull(Vec<Ident>),
9383    /// ENCODING 'encoding_name'
9384    Encoding(String),
9385}
9386
9387impl fmt::Display for CopyOption {
9388    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9389        use CopyOption::*;
9390        match self {
9391            Format(name) => write!(f, "FORMAT {name}"),
9392            Freeze(true) => write!(f, "FREEZE"),
9393            Freeze(false) => write!(f, "FREEZE FALSE"),
9394            Delimiter(char) => write!(f, "DELIMITER '{char}'"),
9395            Null(string) => write!(f, "NULL '{}'", value::escape_single_quote_string(string)),
9396            Header(true) => write!(f, "HEADER"),
9397            Header(false) => write!(f, "HEADER FALSE"),
9398            Quote(char) => write!(f, "QUOTE '{char}'"),
9399            Escape(char) => write!(f, "ESCAPE '{char}'"),
9400            ForceQuote(columns) => write!(f, "FORCE_QUOTE ({})", display_comma_separated(columns)),
9401            ForceNotNull(columns) => {
9402                write!(f, "FORCE_NOT_NULL ({})", display_comma_separated(columns))
9403            }
9404            ForceNull(columns) => write!(f, "FORCE_NULL ({})", display_comma_separated(columns)),
9405            Encoding(name) => write!(f, "ENCODING '{}'", value::escape_single_quote_string(name)),
9406        }
9407    }
9408}
9409
9410/// An option in `COPY` statement before PostgreSQL version 9.0.
9411///
9412/// [PostgreSQL](https://www.postgresql.org/docs/8.4/sql-copy.html)
9413/// [Redshift](https://docs.aws.amazon.com/redshift/latest/dg/r_COPY-alphabetical-parm-list.html)
9414#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9415#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9416#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9417pub enum CopyLegacyOption {
9418    /// ACCEPTANYDATE
9419    AcceptAnyDate,
9420    /// ACCEPTINVCHARS
9421    AcceptInvChars(Option<String>),
9422    /// ADDQUOTES
9423    AddQuotes,
9424    /// ALLOWOVERWRITE
9425    AllowOverwrite,
9426    /// BINARY
9427    Binary,
9428    /// BLANKSASNULL
9429    BlankAsNull,
9430    /// BZIP2
9431    Bzip2,
9432    /// CLEANPATH
9433    CleanPath,
9434    /// COMPUPDATE [ PRESET | { ON | TRUE } | { OFF | FALSE } ]
9435    CompUpdate {
9436        /// Whether the COMPUPDATE PRESET option was used.
9437        preset: bool,
9438        /// Optional enabled flag for COMPUPDATE.
9439        enabled: Option<bool>,
9440    },
9441    /// CSV ...
9442    Csv(Vec<CopyLegacyCsvOption>),
9443    /// DATEFORMAT \[ AS \] {'dateformat_string' | 'auto' }
9444    DateFormat(Option<String>),
9445    /// DELIMITER \[ AS \] 'delimiter_character'
9446    Delimiter(char),
9447    /// EMPTYASNULL
9448    EmptyAsNull,
9449    /// `ENCRYPTED \[ AUTO \]`
9450    Encrypted {
9451        /// Whether `AUTO` was specified for encryption.
9452        auto: bool,
9453    },
9454    /// ESCAPE
9455    Escape,
9456    /// EXTENSION 'extension-name'
9457    Extension(String),
9458    /// FIXEDWIDTH \[ AS \] 'fixedwidth-spec'
9459    FixedWidth(String),
9460    /// GZIP
9461    Gzip,
9462    /// HEADER
9463    Header,
9464    /// IAM_ROLE { DEFAULT | 'arn:aws:iam::123456789:role/role1' }
9465    IamRole(IamRoleKind),
9466    /// IGNOREHEADER \[ AS \] number_rows
9467    IgnoreHeader(u64),
9468    /// JSON \[ AS \] 'json_option'
9469    Json(Option<String>),
9470    /// MANIFEST \[ VERBOSE \]
9471    Manifest {
9472        /// Whether the MANIFEST is verbose.
9473        verbose: bool,
9474    },
9475    /// MAXFILESIZE \[ AS \] max-size \[ MB | GB \]
9476    MaxFileSize(FileSize),
9477    /// `NULL \[ AS \] 'null_string'`
9478    Null(String),
9479    /// `PARALLEL [ { ON | TRUE } | { OFF | FALSE } ]`
9480    Parallel(Option<bool>),
9481    /// PARQUET
9482    Parquet,
9483    /// PARTITION BY ( column_name [, ... ] ) \[ INCLUDE \]
9484    PartitionBy(UnloadPartitionBy),
9485    /// REGION \[ AS \] 'aws-region' }
9486    Region(String),
9487    /// REMOVEQUOTES
9488    RemoveQuotes,
9489    /// ROWGROUPSIZE \[ AS \] size \[ MB | GB \]
9490    RowGroupSize(FileSize),
9491    /// STATUPDATE [ { ON | TRUE } | { OFF | FALSE } ]
9492    StatUpdate(Option<bool>),
9493    /// TIMEFORMAT \[ AS \] {'timeformat_string' | 'auto' | 'epochsecs' | 'epochmillisecs' }
9494    TimeFormat(Option<String>),
9495    /// TRUNCATECOLUMNS
9496    TruncateColumns,
9497    /// ZSTD
9498    Zstd,
9499    /// Redshift `CREDENTIALS 'auth-args'`
9500    /// <https://docs.aws.amazon.com/redshift/latest/dg/copy-parameters-authorization.html>
9501    Credentials(String),
9502}
9503
9504impl fmt::Display for CopyLegacyOption {
9505    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9506        use CopyLegacyOption::*;
9507        match self {
9508            AcceptAnyDate => write!(f, "ACCEPTANYDATE"),
9509            AcceptInvChars(ch) => {
9510                write!(f, "ACCEPTINVCHARS")?;
9511                if let Some(ch) = ch {
9512                    write!(f, " '{}'", value::escape_single_quote_string(ch))?;
9513                }
9514                Ok(())
9515            }
9516            AddQuotes => write!(f, "ADDQUOTES"),
9517            AllowOverwrite => write!(f, "ALLOWOVERWRITE"),
9518            Binary => write!(f, "BINARY"),
9519            BlankAsNull => write!(f, "BLANKSASNULL"),
9520            Bzip2 => write!(f, "BZIP2"),
9521            CleanPath => write!(f, "CLEANPATH"),
9522            CompUpdate { preset, enabled } => {
9523                write!(f, "COMPUPDATE")?;
9524                if *preset {
9525                    write!(f, " PRESET")?;
9526                } else if let Some(enabled) = enabled {
9527                    write!(
9528                        f,
9529                        "{}",
9530                        match enabled {
9531                            true => " TRUE",
9532                            false => " FALSE",
9533                        }
9534                    )?;
9535                }
9536                Ok(())
9537            }
9538            Csv(opts) => {
9539                write!(f, "CSV")?;
9540                if !opts.is_empty() {
9541                    write!(f, " {}", display_separated(opts, " "))?;
9542                }
9543                Ok(())
9544            }
9545            DateFormat(fmt) => {
9546                write!(f, "DATEFORMAT")?;
9547                if let Some(fmt) = fmt {
9548                    write!(f, " '{}'", value::escape_single_quote_string(fmt))?;
9549                }
9550                Ok(())
9551            }
9552            Delimiter(char) => write!(f, "DELIMITER '{char}'"),
9553            EmptyAsNull => write!(f, "EMPTYASNULL"),
9554            Encrypted { auto } => write!(f, "ENCRYPTED{}", if *auto { " AUTO" } else { "" }),
9555            Escape => write!(f, "ESCAPE"),
9556            Extension(ext) => write!(f, "EXTENSION '{}'", value::escape_single_quote_string(ext)),
9557            FixedWidth(spec) => write!(
9558                f,
9559                "FIXEDWIDTH '{}'",
9560                value::escape_single_quote_string(spec)
9561            ),
9562            Gzip => write!(f, "GZIP"),
9563            Header => write!(f, "HEADER"),
9564            IamRole(role) => write!(f, "IAM_ROLE {role}"),
9565            IgnoreHeader(num_rows) => write!(f, "IGNOREHEADER {num_rows}"),
9566            Json(opt) => {
9567                write!(f, "JSON")?;
9568                if let Some(opt) = opt {
9569                    write!(f, " AS '{}'", value::escape_single_quote_string(opt))?;
9570                }
9571                Ok(())
9572            }
9573            Manifest { verbose } => write!(f, "MANIFEST{}", if *verbose { " VERBOSE" } else { "" }),
9574            MaxFileSize(file_size) => write!(f, "MAXFILESIZE {file_size}"),
9575            Null(string) => write!(f, "NULL '{}'", value::escape_single_quote_string(string)),
9576            Parallel(enabled) => {
9577                write!(
9578                    f,
9579                    "PARALLEL{}",
9580                    match enabled {
9581                        Some(true) => " TRUE",
9582                        Some(false) => " FALSE",
9583                        _ => "",
9584                    }
9585                )
9586            }
9587            Parquet => write!(f, "PARQUET"),
9588            PartitionBy(p) => write!(f, "{p}"),
9589            Region(region) => write!(f, "REGION '{}'", value::escape_single_quote_string(region)),
9590            RemoveQuotes => write!(f, "REMOVEQUOTES"),
9591            RowGroupSize(file_size) => write!(f, "ROWGROUPSIZE {file_size}"),
9592            StatUpdate(enabled) => {
9593                write!(
9594                    f,
9595                    "STATUPDATE{}",
9596                    match enabled {
9597                        Some(true) => " TRUE",
9598                        Some(false) => " FALSE",
9599                        _ => "",
9600                    }
9601                )
9602            }
9603            TimeFormat(fmt) => {
9604                write!(f, "TIMEFORMAT")?;
9605                if let Some(fmt) = fmt {
9606                    write!(f, " '{}'", value::escape_single_quote_string(fmt))?;
9607                }
9608                Ok(())
9609            }
9610            TruncateColumns => write!(f, "TRUNCATECOLUMNS"),
9611            Zstd => write!(f, "ZSTD"),
9612            Credentials(s) => write!(f, "CREDENTIALS '{}'", value::escape_single_quote_string(s)),
9613        }
9614    }
9615}
9616
9617/// ```sql
9618/// SIZE \[ MB | GB \]
9619/// ```
9620#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9621#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9622#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9623pub struct FileSize {
9624    /// Numeric size value.
9625    pub size: ValueWithSpan,
9626    /// Optional unit for the size (MB or GB).
9627    pub unit: Option<FileSizeUnit>,
9628}
9629
9630impl fmt::Display for FileSize {
9631    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9632        write!(f, "{}", self.size)?;
9633        if let Some(unit) = &self.unit {
9634            write!(f, " {unit}")?;
9635        }
9636        Ok(())
9637    }
9638}
9639
9640/// Units for `FileSize` (MB or GB).
9641#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9642#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9643#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9644pub enum FileSizeUnit {
9645    /// Megabytes.
9646    MB,
9647    /// Gigabytes.
9648    GB,
9649}
9650
9651impl fmt::Display for FileSizeUnit {
9652    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9653        match self {
9654            FileSizeUnit::MB => write!(f, "MB"),
9655            FileSizeUnit::GB => write!(f, "GB"),
9656        }
9657    }
9658}
9659
9660/// Specifies the partition keys for the unload operation
9661///
9662/// ```sql
9663/// PARTITION BY ( column_name [, ... ] ) [ INCLUDE ]
9664/// ```
9665#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9666#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9667#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9668pub struct UnloadPartitionBy {
9669    /// Columns used to partition the unload output.
9670    pub columns: Vec<Ident>,
9671    /// Whether to include the partition in the output.
9672    pub include: bool,
9673}
9674
9675impl fmt::Display for UnloadPartitionBy {
9676    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9677        write!(
9678            f,
9679            "PARTITION BY ({}){}",
9680            display_comma_separated(&self.columns),
9681            if self.include { " INCLUDE" } else { "" }
9682        )
9683    }
9684}
9685
9686/// An `IAM_ROLE` option in the AWS ecosystem
9687///
9688/// [Redshift COPY](https://docs.aws.amazon.com/redshift/latest/dg/copy-parameters-authorization.html#copy-iam-role)
9689#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9690#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9691#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9692pub enum IamRoleKind {
9693    /// Default role
9694    Default,
9695    /// Specific role ARN, for example: `arn:aws:iam::123456789:role/role1`
9696    Arn(String),
9697}
9698
9699impl fmt::Display for IamRoleKind {
9700    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9701        match self {
9702            IamRoleKind::Default => write!(f, "DEFAULT"),
9703            IamRoleKind::Arn(arn) => write!(f, "'{arn}'"),
9704        }
9705    }
9706}
9707
9708/// A `CSV` option in `COPY` statement before PostgreSQL version 9.0.
9709///
9710/// <https://www.postgresql.org/docs/8.4/sql-copy.html>
9711#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9712#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9713#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9714pub enum CopyLegacyCsvOption {
9715    /// HEADER
9716    Header,
9717    /// QUOTE \[ AS \] 'quote_character'
9718    Quote(char),
9719    /// ESCAPE \[ AS \] 'escape_character'
9720    Escape(char),
9721    /// FORCE QUOTE { column_name [, ...] | * }
9722    ForceQuote(Vec<Ident>),
9723    /// FORCE NOT NULL column_name [, ...]
9724    ForceNotNull(Vec<Ident>),
9725}
9726
9727impl fmt::Display for CopyLegacyCsvOption {
9728    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9729        use CopyLegacyCsvOption::*;
9730        match self {
9731            Header => write!(f, "HEADER"),
9732            Quote(char) => write!(f, "QUOTE '{char}'"),
9733            Escape(char) => write!(f, "ESCAPE '{char}'"),
9734            ForceQuote(columns) => write!(f, "FORCE QUOTE {}", display_comma_separated(columns)),
9735            ForceNotNull(columns) => {
9736                write!(f, "FORCE NOT NULL {}", display_comma_separated(columns))
9737            }
9738        }
9739    }
9740}
9741
9742/// Objects that can be discarded with `DISCARD`.
9743#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9744#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9745#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9746pub enum DiscardObject {
9747    /// Discard all session state.
9748    ALL,
9749    /// Discard cached plans.
9750    PLANS,
9751    /// Discard sequence values.
9752    SEQUENCES,
9753    /// Discard temporary objects.
9754    TEMP,
9755}
9756
9757impl fmt::Display for DiscardObject {
9758    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9759        match self {
9760            DiscardObject::ALL => f.write_str("ALL"),
9761            DiscardObject::PLANS => f.write_str("PLANS"),
9762            DiscardObject::SEQUENCES => f.write_str("SEQUENCES"),
9763            DiscardObject::TEMP => f.write_str("TEMP"),
9764        }
9765    }
9766}
9767
9768/// Types of flush operations supported by `FLUSH`.
9769#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9770#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9771#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9772pub enum FlushType {
9773    /// Flush binary logs.
9774    BinaryLogs,
9775    /// Flush engine logs.
9776    EngineLogs,
9777    /// Flush error logs.
9778    ErrorLogs,
9779    /// Flush general logs.
9780    GeneralLogs,
9781    /// Flush hosts information.
9782    Hosts,
9783    /// Flush logs.
9784    Logs,
9785    /// Flush privileges.
9786    Privileges,
9787    /// Flush optimizer costs.
9788    OptimizerCosts,
9789    /// Flush relay logs.
9790    RelayLogs,
9791    /// Flush slow logs.
9792    SlowLogs,
9793    /// Flush status.
9794    Status,
9795    /// Flush user resources.
9796    UserResources,
9797    /// Flush table data.
9798    Tables,
9799}
9800
9801impl fmt::Display for FlushType {
9802    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9803        match self {
9804            FlushType::BinaryLogs => f.write_str("BINARY LOGS"),
9805            FlushType::EngineLogs => f.write_str("ENGINE LOGS"),
9806            FlushType::ErrorLogs => f.write_str("ERROR LOGS"),
9807            FlushType::GeneralLogs => f.write_str("GENERAL LOGS"),
9808            FlushType::Hosts => f.write_str("HOSTS"),
9809            FlushType::Logs => f.write_str("LOGS"),
9810            FlushType::Privileges => f.write_str("PRIVILEGES"),
9811            FlushType::OptimizerCosts => f.write_str("OPTIMIZER_COSTS"),
9812            FlushType::RelayLogs => f.write_str("RELAY LOGS"),
9813            FlushType::SlowLogs => f.write_str("SLOW LOGS"),
9814            FlushType::Status => f.write_str("STATUS"),
9815            FlushType::UserResources => f.write_str("USER_RESOURCES"),
9816            FlushType::Tables => f.write_str("TABLES"),
9817        }
9818    }
9819}
9820
9821/// Location modifier for flush commands.
9822#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9823#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9824#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9825pub enum FlushLocation {
9826    /// Do not write changes to the binary log.
9827    NoWriteToBinlog,
9828    /// Apply flush locally.
9829    Local,
9830}
9831
9832impl fmt::Display for FlushLocation {
9833    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9834        match self {
9835            FlushLocation::NoWriteToBinlog => f.write_str("NO_WRITE_TO_BINLOG"),
9836            FlushLocation::Local => f.write_str("LOCAL"),
9837        }
9838    }
9839}
9840
9841/// Optional context modifier for statements that can be or `LOCAL`, `GLOBAL`, or `SESSION`.
9842#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9843#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9844#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9845pub enum ContextModifier {
9846    /// `LOCAL` identifier, usually related to transactional states.
9847    Local,
9848    /// `SESSION` identifier
9849    Session,
9850    /// `GLOBAL` identifier
9851    Global,
9852}
9853
9854impl fmt::Display for ContextModifier {
9855    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9856        match self {
9857            Self::Local => {
9858                write!(f, "LOCAL ")
9859            }
9860            Self::Session => {
9861                write!(f, "SESSION ")
9862            }
9863            Self::Global => {
9864                write!(f, "GLOBAL ")
9865            }
9866        }
9867    }
9868}
9869
9870/// Function describe in DROP FUNCTION.
9871#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9872#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9873pub enum DropFunctionOption {
9874    /// `RESTRICT` option for DROP FUNCTION.
9875    Restrict,
9876    /// `CASCADE` option for DROP FUNCTION.
9877    Cascade,
9878}
9879
9880impl fmt::Display for DropFunctionOption {
9881    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9882        match self {
9883            DropFunctionOption::Restrict => write!(f, "RESTRICT "),
9884            DropFunctionOption::Cascade => write!(f, "CASCADE  "),
9885        }
9886    }
9887}
9888
9889/// Generic function description for DROP FUNCTION and CREATE TRIGGER.
9890#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9891#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9892#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9893pub struct FunctionDesc {
9894    /// The function name.
9895    pub name: ObjectName,
9896    /// Optional list of function arguments.
9897    pub args: Option<Vec<OperateFunctionArg>>,
9898}
9899
9900impl fmt::Display for FunctionDesc {
9901    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9902        write!(f, "{}", self.name)?;
9903        if let Some(args) = &self.args {
9904            write!(f, "({})", display_comma_separated(args))?;
9905        }
9906        Ok(())
9907    }
9908}
9909
9910/// Function argument in CREATE OR DROP FUNCTION.
9911#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9912#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9913#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9914pub struct OperateFunctionArg {
9915    /// Optional argument mode (`IN`, `OUT`, `INOUT`).
9916    pub mode: Option<ArgMode>,
9917    /// Optional argument identifier/name.
9918    pub name: Option<Ident>,
9919    /// The data type of the argument.
9920    pub data_type: DataType,
9921    /// Optional default expression for the argument.
9922    pub default_expr: Option<Expr>,
9923}
9924
9925impl OperateFunctionArg {
9926    /// Returns an unnamed argument.
9927    pub fn unnamed(data_type: DataType) -> Self {
9928        Self {
9929            mode: None,
9930            name: None,
9931            data_type,
9932            default_expr: None,
9933        }
9934    }
9935
9936    /// Returns an argument with name.
9937    pub fn with_name(name: &str, data_type: DataType) -> Self {
9938        Self {
9939            mode: None,
9940            name: Some(name.into()),
9941            data_type,
9942            default_expr: None,
9943        }
9944    }
9945}
9946
9947impl fmt::Display for OperateFunctionArg {
9948    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9949        if let Some(mode) = &self.mode {
9950            write!(f, "{mode} ")?;
9951        }
9952        if let Some(name) = &self.name {
9953            write!(f, "{name} ")?;
9954        }
9955        write!(f, "{}", self.data_type)?;
9956        if let Some(default_expr) = &self.default_expr {
9957            write!(f, " = {default_expr}")?;
9958        }
9959        Ok(())
9960    }
9961}
9962
9963/// The mode of an argument in CREATE FUNCTION.
9964#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9965#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9966#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9967pub enum ArgMode {
9968    /// `IN` mode.
9969    In,
9970    /// `OUT` mode.
9971    Out,
9972    /// `INOUT` mode.
9973    InOut,
9974    /// `VARIADIC` mode.
9975    Variadic,
9976}
9977
9978impl fmt::Display for ArgMode {
9979    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9980        match self {
9981            ArgMode::In => write!(f, "IN"),
9982            ArgMode::Out => write!(f, "OUT"),
9983            ArgMode::InOut => write!(f, "INOUT"),
9984            ArgMode::Variadic => write!(f, "VARIADIC"),
9985        }
9986    }
9987}
9988
9989/// These attributes inform the query optimizer about the behavior of the function.
9990#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9991#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9992#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9993pub enum FunctionBehavior {
9994    /// Function is immutable.
9995    Immutable,
9996    /// Function is stable.
9997    Stable,
9998    /// Function is volatile.
9999    Volatile,
10000}
10001
10002impl fmt::Display for FunctionBehavior {
10003    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10004        match self {
10005            FunctionBehavior::Immutable => write!(f, "IMMUTABLE"),
10006            FunctionBehavior::Stable => write!(f, "STABLE"),
10007            FunctionBehavior::Volatile => write!(f, "VOLATILE"),
10008        }
10009    }
10010}
10011
10012/// Security attribute for functions: SECURITY DEFINER or SECURITY INVOKER.
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 enum FunctionSecurity {
10019    /// Execute the function with the privileges of the user who defined it.
10020    Definer,
10021    /// Execute the function with the privileges of the user who invokes it.
10022    Invoker,
10023}
10024
10025impl fmt::Display for FunctionSecurity {
10026    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10027        match self {
10028            FunctionSecurity::Definer => write!(f, "SECURITY DEFINER"),
10029            FunctionSecurity::Invoker => write!(f, "SECURITY INVOKER"),
10030        }
10031    }
10032}
10033
10034/// Value for a SET configuration parameter in a CREATE FUNCTION statement.
10035///
10036/// [PostgreSQL](https://www.postgresql.org/docs/current/sql-createfunction.html)
10037#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10038#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10039#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10040pub enum FunctionSetValue {
10041    /// SET param = DEFAULT / SET param TO DEFAULT
10042    Default,
10043    /// SET param = value1, value2, ...
10044    Values(Vec<Expr>),
10045    /// SET param FROM CURRENT
10046    FromCurrent,
10047}
10048
10049/// A SET configuration_parameter clause in a CREATE FUNCTION statement.
10050///
10051/// [PostgreSQL](https://www.postgresql.org/docs/current/sql-createfunction.html)
10052#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10053#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10054#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10055pub struct FunctionDefinitionSetParam {
10056    /// The name of the configuration parameter.
10057    pub name: ObjectName,
10058    /// The value to set for the parameter.
10059    pub value: FunctionSetValue,
10060}
10061
10062impl fmt::Display for FunctionDefinitionSetParam {
10063    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10064        write!(f, "SET {} ", self.name)?;
10065        match &self.value {
10066            FunctionSetValue::Default => write!(f, "= DEFAULT"),
10067            FunctionSetValue::Values(values) => {
10068                write!(f, "= {}", display_comma_separated(values))
10069            }
10070            FunctionSetValue::FromCurrent => write!(f, "FROM CURRENT"),
10071        }
10072    }
10073}
10074
10075/// These attributes describe the behavior of the function when called with a null argument.
10076#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10077#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10078#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10079pub enum FunctionCalledOnNull {
10080    /// Function is called even when inputs are null.
10081    CalledOnNullInput,
10082    /// Function returns null when any input is null.
10083    ReturnsNullOnNullInput,
10084    /// Function is strict about null inputs.
10085    Strict,
10086}
10087
10088impl fmt::Display for FunctionCalledOnNull {
10089    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10090        match self {
10091            FunctionCalledOnNull::CalledOnNullInput => write!(f, "CALLED ON NULL INPUT"),
10092            FunctionCalledOnNull::ReturnsNullOnNullInput => write!(f, "RETURNS NULL ON NULL INPUT"),
10093            FunctionCalledOnNull::Strict => write!(f, "STRICT"),
10094        }
10095    }
10096}
10097
10098/// If it is safe for PostgreSQL to call the function from multiple threads at once
10099#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10100#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10101#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10102pub enum FunctionParallel {
10103    /// The function is not safe to run in parallel.
10104    Unsafe,
10105    /// The function is restricted for parallel execution.
10106    Restricted,
10107    /// The function is safe to run in parallel.
10108    Safe,
10109}
10110
10111impl fmt::Display for FunctionParallel {
10112    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10113        match self {
10114            FunctionParallel::Unsafe => write!(f, "PARALLEL UNSAFE"),
10115            FunctionParallel::Restricted => write!(f, "PARALLEL RESTRICTED"),
10116            FunctionParallel::Safe => write!(f, "PARALLEL SAFE"),
10117        }
10118    }
10119}
10120
10121/// [BigQuery] Determinism specifier used in a UDF definition.
10122///
10123/// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#syntax_11
10124#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10125#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10126#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10127pub enum FunctionDeterminismSpecifier {
10128    /// Function is deterministic.
10129    Deterministic,
10130    /// Function is not deterministic.
10131    NotDeterministic,
10132}
10133
10134impl fmt::Display for FunctionDeterminismSpecifier {
10135    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10136        match self {
10137            FunctionDeterminismSpecifier::Deterministic => {
10138                write!(f, "DETERMINISTIC")
10139            }
10140            FunctionDeterminismSpecifier::NotDeterministic => {
10141                write!(f, "NOT DETERMINISTIC")
10142            }
10143        }
10144    }
10145}
10146
10147/// Represent the expression body of a `CREATE FUNCTION` statement as well as
10148/// where within the statement, the body shows up.
10149///
10150/// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#syntax_11
10151/// [PostgreSQL]: https://www.postgresql.org/docs/15/sql-createfunction.html
10152/// [MsSql]: https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql
10153#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10154#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10155#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10156pub enum CreateFunctionBody {
10157    /// A function body expression using the 'AS' keyword and shows up
10158    /// before any `OPTIONS` clause.
10159    ///
10160    /// Example:
10161    /// ```sql
10162    /// CREATE FUNCTION myfunc(x FLOAT64, y FLOAT64) RETURNS FLOAT64
10163    /// AS (x * y)
10164    /// OPTIONS(description="desc");
10165    /// ```
10166    ///
10167    /// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#syntax_11
10168    /// [PostgreSQL]: https://www.postgresql.org/docs/current/sql-createfunction.html
10169    AsBeforeOptions {
10170        /// The primary expression.
10171        body: Expr,
10172        /// Link symbol if the primary expression contains the name of shared library file.
10173        ///
10174        /// Example:
10175        /// ```sql
10176        /// CREATE FUNCTION cas_in(input cstring) RETURNS cas
10177        /// AS 'MODULE_PATHNAME', 'cas_in_wrapper'
10178        /// ```
10179        /// [PostgreSQL]: https://www.postgresql.org/docs/current/sql-createfunction.html
10180        link_symbol: Option<Expr>,
10181    },
10182    /// A function body expression using the 'AS' keyword and shows up
10183    /// after any `OPTIONS` clause.
10184    ///
10185    /// Example:
10186    /// ```sql
10187    /// CREATE FUNCTION myfunc(x FLOAT64, y FLOAT64) RETURNS FLOAT64
10188    /// OPTIONS(description="desc")
10189    /// AS (x * y);
10190    /// ```
10191    ///
10192    /// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#syntax_11
10193    AsAfterOptions(Expr),
10194    /// Function body with statements before the `RETURN` keyword.
10195    ///
10196    /// Example:
10197    /// ```sql
10198    /// CREATE FUNCTION my_scalar_udf(a INT, b INT)
10199    /// RETURNS INT
10200    /// AS
10201    /// BEGIN
10202    ///     DECLARE c INT;
10203    ///     SET c = a + b;
10204    ///     RETURN c;
10205    /// END
10206    /// ```
10207    ///
10208    /// [MsSql]: https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql
10209    AsBeginEnd(BeginEndStatements),
10210    /// Function body expression using the 'RETURN' keyword.
10211    ///
10212    /// Example:
10213    /// ```sql
10214    /// CREATE FUNCTION myfunc(a INTEGER, IN b INTEGER = 1) RETURNS INTEGER
10215    /// LANGUAGE SQL
10216    /// RETURN a + b;
10217    /// ```
10218    ///
10219    /// [PostgreSQL]: https://www.postgresql.org/docs/current/sql-createfunction.html
10220    Return(Expr),
10221
10222    /// Function body expression using the 'AS RETURN' keywords
10223    ///
10224    /// Example:
10225    /// ```sql
10226    /// CREATE FUNCTION myfunc(a INT, b INT)
10227    /// RETURNS TABLE
10228    /// AS RETURN (SELECT a + b AS sum);
10229    /// ```
10230    ///
10231    /// [MsSql]: https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql
10232    AsReturnExpr(Expr),
10233
10234    /// Function body expression using the 'AS RETURN' keywords, with an un-parenthesized SELECT query
10235    ///
10236    /// Example:
10237    /// ```sql
10238    /// CREATE FUNCTION myfunc(a INT, b INT)
10239    /// RETURNS TABLE
10240    /// AS RETURN SELECT a + b AS sum;
10241    /// ```
10242    ///
10243    /// [MsSql]: https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql?view=sql-server-ver16#select_stmt
10244    AsReturnSelect(Select),
10245}
10246
10247#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10248#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10249#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10250/// `USING` clause options for `CREATE FUNCTION` (e.g., JAR, FILE, ARCHIVE).
10251pub enum CreateFunctionUsing {
10252    /// Use a JAR file located at the given URI.
10253    Jar(String),
10254    /// Use a file located at the given URI.
10255    File(String),
10256    /// Use an archive located at the given URI.
10257    Archive(String),
10258}
10259
10260impl fmt::Display for CreateFunctionUsing {
10261    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10262        write!(f, "USING ")?;
10263        match self {
10264            CreateFunctionUsing::Jar(uri) => write!(f, "JAR '{uri}'"),
10265            CreateFunctionUsing::File(uri) => write!(f, "FILE '{uri}'"),
10266            CreateFunctionUsing::Archive(uri) => write!(f, "ARCHIVE '{uri}'"),
10267        }
10268    }
10269}
10270
10271/// `NAME = <EXPR>` arguments for DuckDB macros
10272///
10273/// See [Create Macro - DuckDB](https://duckdb.org/docs/sql/statements/create_macro)
10274/// for more details
10275#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10276#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10277#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10278pub struct MacroArg {
10279    /// The argument name.
10280    pub name: Ident,
10281    /// Optional default expression for the argument.
10282    pub default_expr: Option<Expr>,
10283}
10284
10285impl MacroArg {
10286    /// Returns an argument with name.
10287    pub fn new(name: &str) -> Self {
10288        Self {
10289            name: name.into(),
10290            default_expr: None,
10291        }
10292    }
10293}
10294
10295impl fmt::Display for MacroArg {
10296    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10297        write!(f, "{}", self.name)?;
10298        if let Some(default_expr) = &self.default_expr {
10299            write!(f, " := {default_expr}")?;
10300        }
10301        Ok(())
10302    }
10303}
10304
10305#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10306#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10307#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10308/// Definition for a DuckDB macro: either an expression or a table-producing query.
10309pub enum MacroDefinition {
10310    /// The macro is defined as an expression.
10311    Expr(Expr),
10312    /// The macro is defined as a table (query).
10313    Table(Box<Query>),
10314}
10315
10316impl fmt::Display for MacroDefinition {
10317    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10318        match self {
10319            MacroDefinition::Expr(expr) => write!(f, "{expr}")?,
10320            MacroDefinition::Table(query) => write!(f, "{query}")?,
10321        }
10322        Ok(())
10323    }
10324}
10325
10326/// Schema possible naming variants ([1]).
10327///
10328/// [1]: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#schema-definition
10329#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10330#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10331#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10332pub enum SchemaName {
10333    /// Only schema name specified: `<schema name>`.
10334    Simple(ObjectName),
10335    /// Only authorization identifier specified: `AUTHORIZATION <schema authorization identifier>`.
10336    UnnamedAuthorization(Ident),
10337    /// Both schema name and authorization identifier specified: `<schema name>  AUTHORIZATION <schema authorization identifier>`.
10338    NamedAuthorization(ObjectName, Ident),
10339}
10340
10341impl fmt::Display for SchemaName {
10342    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10343        match self {
10344            SchemaName::Simple(name) => {
10345                write!(f, "{name}")
10346            }
10347            SchemaName::UnnamedAuthorization(authorization) => {
10348                write!(f, "AUTHORIZATION {authorization}")
10349            }
10350            SchemaName::NamedAuthorization(name, authorization) => {
10351                write!(f, "{name} AUTHORIZATION {authorization}")
10352            }
10353        }
10354    }
10355}
10356
10357/// Fulltext search modifiers ([1]).
10358///
10359/// [1]: https://dev.mysql.com/doc/refman/8.0/en/fulltext-search.html#function_match
10360#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10361#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10362#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10363pub enum SearchModifier {
10364    /// `IN NATURAL LANGUAGE MODE`.
10365    InNaturalLanguageMode,
10366    /// `IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION`.
10367    InNaturalLanguageModeWithQueryExpansion,
10368    ///`IN BOOLEAN MODE`.
10369    InBooleanMode,
10370    ///`WITH QUERY EXPANSION`.
10371    WithQueryExpansion,
10372}
10373
10374impl fmt::Display for SearchModifier {
10375    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10376        match self {
10377            Self::InNaturalLanguageMode => {
10378                write!(f, "IN NATURAL LANGUAGE MODE")?;
10379            }
10380            Self::InNaturalLanguageModeWithQueryExpansion => {
10381                write!(f, "IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION")?;
10382            }
10383            Self::InBooleanMode => {
10384                write!(f, "IN BOOLEAN MODE")?;
10385            }
10386            Self::WithQueryExpansion => {
10387                write!(f, "WITH QUERY EXPANSION")?;
10388            }
10389        }
10390
10391        Ok(())
10392    }
10393}
10394
10395/// Represents a `LOCK TABLE` clause with optional alias and lock type.
10396#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10397#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10398#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10399pub struct LockTable {
10400    /// The table identifier to lock.
10401    pub table: Ident,
10402    /// Optional alias for the table.
10403    pub alias: Option<Ident>,
10404    /// The type of lock to apply to the table.
10405    pub lock_type: LockTableType,
10406}
10407
10408impl fmt::Display for LockTable {
10409    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10410        let Self {
10411            table: tbl_name,
10412            alias,
10413            lock_type,
10414        } = self;
10415
10416        write!(f, "{tbl_name} ")?;
10417        if let Some(alias) = alias {
10418            write!(f, "AS {alias} ")?;
10419        }
10420        write!(f, "{lock_type}")?;
10421        Ok(())
10422    }
10423}
10424
10425#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10426#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10427#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10428/// The type of lock used in `LOCK TABLE` statements.
10429pub enum LockTableType {
10430    /// Shared/read lock. If `local` is true, it's a local read lock.
10431    Read {
10432        /// Whether the read lock is local.
10433        local: bool,
10434    },
10435    /// Exclusive/write lock. If `low_priority` is true, the write is low priority.
10436    Write {
10437        /// Whether the write lock is low priority.
10438        low_priority: bool,
10439    },
10440}
10441
10442impl fmt::Display for LockTableType {
10443    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10444        match self {
10445            Self::Read { local } => {
10446                write!(f, "READ")?;
10447                if *local {
10448                    write!(f, " LOCAL")?;
10449                }
10450            }
10451            Self::Write { low_priority } => {
10452                if *low_priority {
10453                    write!(f, "LOW_PRIORITY ")?;
10454                }
10455                write!(f, "WRITE")?;
10456            }
10457        }
10458
10459        Ok(())
10460    }
10461}
10462
10463#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10464#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10465#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10466/// Hive-specific `SET LOCATION` helper used in some `LOAD DATA` statements.
10467pub struct HiveSetLocation {
10468    /// Whether the `SET` keyword was present.
10469    pub has_set: bool,
10470    /// The location identifier.
10471    pub location: Ident,
10472}
10473
10474impl fmt::Display for HiveSetLocation {
10475    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10476        if self.has_set {
10477            write!(f, "SET ")?;
10478        }
10479        write!(f, "LOCATION {}", self.location)
10480    }
10481}
10482
10483/// MySQL `ALTER TABLE` only  [FIRST | AFTER column_name]
10484#[allow(clippy::large_enum_variant)]
10485#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10486#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10487#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10488/// MySQL `ALTER TABLE` column position specifier: `FIRST` or `AFTER <column>`.
10489pub enum MySQLColumnPosition {
10490    /// Place the column first in the table.
10491    First,
10492    /// Place the column after the specified identifier.
10493    After(Ident),
10494}
10495
10496impl Display for MySQLColumnPosition {
10497    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10498        match self {
10499            MySQLColumnPosition::First => write!(f, "FIRST"),
10500            MySQLColumnPosition::After(ident) => {
10501                let column_name = &ident.value;
10502                write!(f, "AFTER {column_name}")
10503            }
10504        }
10505    }
10506}
10507
10508/// MySQL `CREATE VIEW` algorithm parameter: [ALGORITHM = {UNDEFINED | MERGE | TEMPTABLE}]
10509#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10510#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10511#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10512/// MySQL `CREATE VIEW` algorithm options.
10513pub enum CreateViewAlgorithm {
10514    /// `UNDEFINED` algorithm.
10515    Undefined,
10516    /// `MERGE` algorithm.
10517    Merge,
10518    /// `TEMPTABLE` algorithm.
10519    TempTable,
10520}
10521
10522impl Display for CreateViewAlgorithm {
10523    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10524        match self {
10525            CreateViewAlgorithm::Undefined => write!(f, "UNDEFINED"),
10526            CreateViewAlgorithm::Merge => write!(f, "MERGE"),
10527            CreateViewAlgorithm::TempTable => write!(f, "TEMPTABLE"),
10528        }
10529    }
10530}
10531/// MySQL `CREATE VIEW` security parameter: [SQL SECURITY { DEFINER | INVOKER }]
10532#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10533#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10534#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10535/// MySQL `CREATE VIEW` SQL SECURITY options.
10536pub enum CreateViewSecurity {
10537    /// The view runs with the privileges of the definer.
10538    Definer,
10539    /// The view runs with the privileges of the invoker.
10540    Invoker,
10541}
10542
10543impl Display for CreateViewSecurity {
10544    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10545        match self {
10546            CreateViewSecurity::Definer => write!(f, "DEFINER"),
10547            CreateViewSecurity::Invoker => write!(f, "INVOKER"),
10548        }
10549    }
10550}
10551
10552/// [MySQL] `CREATE VIEW` additional parameters
10553///
10554/// [MySQL]: https://dev.mysql.com/doc/refman/9.1/en/create-view.html
10555#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10556#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10557#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10558pub struct CreateViewParams {
10559    /// Optional view algorithm (e.g., MERGE, TEMPTABLE).
10560    pub algorithm: Option<CreateViewAlgorithm>,
10561    /// Optional definer (the security principal that will own the view).
10562    pub definer: Option<GranteeName>,
10563    /// Optional SQL SECURITY setting for the view.
10564    pub security: Option<CreateViewSecurity>,
10565}
10566
10567impl Display for CreateViewParams {
10568    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10569        let CreateViewParams {
10570            algorithm,
10571            definer,
10572            security,
10573        } = self;
10574        if let Some(algorithm) = algorithm {
10575            write!(f, "ALGORITHM = {algorithm} ")?;
10576        }
10577        if let Some(definers) = definer {
10578            write!(f, "DEFINER = {definers} ")?;
10579        }
10580        if let Some(security) = security {
10581            write!(f, "SQL SECURITY {security} ")?;
10582        }
10583        Ok(())
10584    }
10585}
10586
10587#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10588#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10589#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10590/// Key/Value, where the value is a (optionally named) list of identifiers
10591///
10592/// ```sql
10593/// UNION = (tbl_name[,tbl_name]...)
10594/// ENGINE = ReplicatedMergeTree('/table_name','{replica}', ver)
10595/// ENGINE = SummingMergeTree([columns])
10596/// ```
10597pub struct NamedParenthesizedList {
10598    /// The option key (identifier) for this named list.
10599    pub key: Ident,
10600    /// Optional secondary name associated with the key.
10601    pub name: Option<Ident>,
10602    /// The list of identifier values for the key.
10603    pub values: Vec<Ident>,
10604}
10605
10606/// Snowflake `WITH ROW ACCESS POLICY policy_name ON (identifier, ...)`
10607///
10608/// <https://docs.snowflake.com/en/sql-reference/sql/create-table>
10609/// <https://docs.snowflake.com/en/user-guide/security-row-intro>
10610#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10611#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10612#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10613pub struct RowAccessPolicy {
10614    /// The fully-qualified policy object name.
10615    pub policy: ObjectName,
10616    /// Identifiers for the columns or objects the policy applies to.
10617    pub on: Vec<Ident>,
10618}
10619
10620impl RowAccessPolicy {
10621    /// Create a new `RowAccessPolicy` for the given `policy` and `on` identifiers.
10622    pub fn new(policy: ObjectName, on: Vec<Ident>) -> Self {
10623        Self { policy, on }
10624    }
10625}
10626
10627impl Display for RowAccessPolicy {
10628    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10629        write!(
10630            f,
10631            "WITH ROW ACCESS POLICY {} ON ({})",
10632            self.policy,
10633            display_comma_separated(self.on.as_slice())
10634        )
10635    }
10636}
10637
10638/// Snowflake `[ WITH ] STORAGE LIFECYCLE POLICY <policy_name> ON ( <col_name> [ , ... ] )`
10639///
10640/// <https://docs.snowflake.com/en/sql-reference/sql/create-table>
10641#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10642#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10643#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10644pub struct StorageLifecyclePolicy {
10645    /// The fully-qualified policy object name.
10646    pub policy: ObjectName,
10647    /// Column names the policy applies to.
10648    pub on: Vec<Ident>,
10649}
10650
10651impl Display for StorageLifecyclePolicy {
10652    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10653        write!(
10654            f,
10655            "WITH STORAGE LIFECYCLE POLICY {} ON ({})",
10656            self.policy,
10657            display_comma_separated(self.on.as_slice())
10658        )
10659    }
10660}
10661
10662/// Snowflake `WITH TAG ( tag_name = '<tag_value>', ...)`
10663///
10664/// <https://docs.snowflake.com/en/sql-reference/sql/create-table>
10665#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10666#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10667#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10668pub struct Tag {
10669    /// The tag key (can be qualified).
10670    pub key: ObjectName,
10671    /// The tag value as a string.
10672    pub value: String,
10673}
10674
10675impl Tag {
10676    /// Create a new `Tag` with the given key and value.
10677    pub fn new(key: ObjectName, value: String) -> Self {
10678        Self { key, value }
10679    }
10680}
10681
10682impl Display for Tag {
10683    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10684        write!(f, "{}='{}'", self.key, self.value)
10685    }
10686}
10687
10688/// Snowflake `WITH CONTACT ( purpose = contact [ , purpose = contact ...] )`
10689///
10690/// <https://docs.snowflake.com/en/sql-reference/sql/create-database>
10691#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10692#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10693#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10694pub struct ContactEntry {
10695    /// The purpose label for the contact entry.
10696    pub purpose: String,
10697    /// The contact information associated with the purpose.
10698    pub contact: String,
10699}
10700
10701impl Display for ContactEntry {
10702    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10703        write!(f, "{} = {}", self.purpose, self.contact)
10704    }
10705}
10706
10707/// Helper to indicate if a comment includes the `=` in the display form
10708#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10709#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10710#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10711pub enum CommentDef {
10712    /// Includes `=` when printing the comment, as `COMMENT = 'comment'`
10713    /// Does not include `=` when printing the comment, as `COMMENT 'comment'`
10714    WithEq(String),
10715    /// Comment variant that omits the `=` when displayed.
10716    WithoutEq(String),
10717}
10718
10719impl Display for CommentDef {
10720    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10721        match self {
10722            CommentDef::WithEq(comment) | CommentDef::WithoutEq(comment) => write!(f, "{comment}"),
10723        }
10724    }
10725}
10726
10727/// Helper to indicate if a collection should be wrapped by a symbol in the display form
10728///
10729/// [`Display`] is implemented for every [`Vec<T>`] where `T: Display`.
10730/// The string output is a comma separated list for the vec items
10731///
10732/// # Examples
10733/// ```
10734/// # use sqlparser::ast::WrappedCollection;
10735/// let items = WrappedCollection::Parentheses(vec!["one", "two", "three"]);
10736/// assert_eq!("(one, two, three)", items.to_string());
10737///
10738/// let items = WrappedCollection::NoWrapping(vec!["one", "two", "three"]);
10739/// assert_eq!("one, two, three", items.to_string());
10740/// ```
10741#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10742#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10743#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10744pub enum WrappedCollection<T> {
10745    /// Print the collection without wrapping symbols, as `item, item, item`
10746    NoWrapping(T),
10747    /// Wraps the collection in Parentheses, as `(item, item, item)`
10748    Parentheses(T),
10749}
10750
10751impl<T> Display for WrappedCollection<Vec<T>>
10752where
10753    T: Display,
10754{
10755    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10756        match self {
10757            WrappedCollection::NoWrapping(inner) => {
10758                write!(f, "{}", display_comma_separated(inner.as_slice()))
10759            }
10760            WrappedCollection::Parentheses(inner) => {
10761                write!(f, "({})", display_comma_separated(inner.as_slice()))
10762            }
10763        }
10764    }
10765}
10766
10767/// Represents a single PostgreSQL utility option.
10768///
10769/// A utility option is a key-value pair where the key is an identifier (IDENT) and the value
10770/// can be one of the following:
10771/// - A number with an optional sign (`+` or `-`). Example: `+10`, `-10.2`, `3`
10772/// - A non-keyword string. Example: `option1`, `'option2'`, `"option3"`
10773/// - keyword: `TRUE`, `FALSE`, `ON` (`off` is also accept).
10774/// - Empty. Example: `ANALYZE` (identifier only)
10775///
10776/// Utility options are used in various PostgreSQL DDL statements, including statements such as
10777/// `CLUSTER`, `EXPLAIN`, `VACUUM`, and `REINDEX`. These statements format options as `( option [, ...] )`.
10778///
10779/// [CLUSTER](https://www.postgresql.org/docs/current/sql-cluster.html)
10780/// [EXPLAIN](https://www.postgresql.org/docs/current/sql-explain.html)
10781/// [VACUUM](https://www.postgresql.org/docs/current/sql-vacuum.html)
10782/// [REINDEX](https://www.postgresql.org/docs/current/sql-reindex.html)
10783///
10784/// For example, the `EXPLAIN` AND `VACUUM` statements with options might look like this:
10785/// ```sql
10786/// EXPLAIN (ANALYZE, VERBOSE TRUE, FORMAT TEXT) SELECT * FROM my_table;
10787///
10788/// VACUUM (VERBOSE, ANALYZE ON, PARALLEL 10) my_table;
10789/// ```
10790#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10791#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10792#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10793pub struct UtilityOption {
10794    /// The option name (identifier).
10795    pub name: Ident,
10796    /// Optional argument for the option (number, string, keyword, etc.).
10797    pub arg: Option<Expr>,
10798}
10799
10800impl Display for UtilityOption {
10801    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10802        if let Some(ref arg) = self.arg {
10803            write!(f, "{} {}", self.name, arg)
10804        } else {
10805            write!(f, "{}", self.name)
10806        }
10807    }
10808}
10809
10810/// Represents the different options available for `SHOW`
10811/// statements to filter the results. Example from Snowflake:
10812/// <https://docs.snowflake.com/en/sql-reference/sql/show-tables>
10813#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10814#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10815#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10816pub struct ShowStatementOptions {
10817    /// Optional scope to show in (for example: TABLE, SCHEMA).
10818    pub show_in: Option<ShowStatementIn>,
10819    /// Optional `STARTS WITH` filter value.
10820    pub starts_with: Option<ValueWithSpan>,
10821    /// Optional `LIMIT` expression.
10822    pub limit: Option<Expr>,
10823    /// Optional `FROM` value used with `LIMIT`.
10824    pub limit_from: Option<ValueWithSpan>,
10825    /// Optional filter position (infix or suffix) for `LIKE`/`FILTER`.
10826    pub filter_position: Option<ShowStatementFilterPosition>,
10827}
10828
10829impl Display for ShowStatementOptions {
10830    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10831        let (like_in_infix, like_in_suffix) = match &self.filter_position {
10832            Some(ShowStatementFilterPosition::Infix(filter)) => {
10833                (format!(" {filter}"), "".to_string())
10834            }
10835            Some(ShowStatementFilterPosition::Suffix(filter)) => {
10836                ("".to_string(), format!(" {filter}"))
10837            }
10838            None => ("".to_string(), "".to_string()),
10839        };
10840        write!(
10841            f,
10842            "{like_in_infix}{show_in}{starts_with}{limit}{from}{like_in_suffix}",
10843            show_in = match &self.show_in {
10844                Some(i) => format!(" {i}"),
10845                None => String::new(),
10846            },
10847            starts_with = match &self.starts_with {
10848                Some(s) => format!(" STARTS WITH {s}"),
10849                None => String::new(),
10850            },
10851            limit = match &self.limit {
10852                Some(l) => format!(" LIMIT {l}"),
10853                None => String::new(),
10854            },
10855            from = match &self.limit_from {
10856                Some(f) => format!(" FROM {f}"),
10857                None => String::new(),
10858            }
10859        )?;
10860        Ok(())
10861    }
10862}
10863
10864#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10865#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10866#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10867/// Where a `SHOW` filter appears relative to the main clause.
10868pub enum ShowStatementFilterPosition {
10869    /// Put the filter in an infix position (e.g. `SHOW COLUMNS LIKE '%name%' IN TABLE tbl`).
10870    Infix(ShowStatementFilter), // For example: SHOW COLUMNS LIKE '%name%' IN TABLE tbl
10871    /// Put the filter in a suffix position (e.g. `SHOW COLUMNS IN tbl LIKE '%name%'`).
10872    Suffix(ShowStatementFilter), // For example: SHOW COLUMNS IN tbl LIKE '%name%'
10873}
10874
10875#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10876#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10877#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10878/// Parent object types usable with `SHOW ... IN <parent>` clauses.
10879pub enum ShowStatementInParentType {
10880    /// ACCOUNT parent type for SHOW statements.
10881    Account,
10882    /// DATABASE parent type for SHOW statements.
10883    Database,
10884    /// SCHEMA parent type for SHOW statements.
10885    Schema,
10886    /// TABLE parent type for SHOW statements.
10887    Table,
10888    /// VIEW parent type for SHOW statements.
10889    View,
10890}
10891
10892impl fmt::Display for ShowStatementInParentType {
10893    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10894        match self {
10895            ShowStatementInParentType::Account => write!(f, "ACCOUNT"),
10896            ShowStatementInParentType::Database => write!(f, "DATABASE"),
10897            ShowStatementInParentType::Schema => write!(f, "SCHEMA"),
10898            ShowStatementInParentType::Table => write!(f, "TABLE"),
10899            ShowStatementInParentType::View => write!(f, "VIEW"),
10900        }
10901    }
10902}
10903
10904#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10905#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10906#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10907/// Represents a `SHOW ... IN` clause with optional parent qualifier and name.
10908pub struct ShowStatementIn {
10909    /// The clause that specifies what to show (e.g. COLUMNS, TABLES).
10910    pub clause: ShowStatementInClause,
10911    /// Optional parent type qualifier (ACCOUNT/DATABASE/...).
10912    pub parent_type: Option<ShowStatementInParentType>,
10913    /// Optional parent object name for the SHOW clause.
10914    #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
10915    pub parent_name: Option<ObjectName>,
10916}
10917
10918impl fmt::Display for ShowStatementIn {
10919    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10920        write!(f, "{}", self.clause)?;
10921        if let Some(parent_type) = &self.parent_type {
10922            write!(f, " {parent_type}")?;
10923        }
10924        if let Some(parent_name) = &self.parent_name {
10925            write!(f, " {parent_name}")?;
10926        }
10927        Ok(())
10928    }
10929}
10930
10931/// A Show Charset statement
10932#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10933#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10934#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10935pub struct ShowCharset {
10936    /// The statement can be written as `SHOW CHARSET` or `SHOW CHARACTER SET`
10937    /// true means CHARSET was used and false means CHARACTER SET was used
10938    pub is_shorthand: bool,
10939    /// Optional `LIKE`/`WHERE`-style filter for the statement.
10940    pub filter: Option<ShowStatementFilter>,
10941}
10942
10943impl fmt::Display for ShowCharset {
10944    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10945        write!(f, "SHOW")?;
10946        if self.is_shorthand {
10947            write!(f, " CHARSET")?;
10948        } else {
10949            write!(f, " CHARACTER SET")?;
10950        }
10951        if let Some(filter) = &self.filter {
10952            write!(f, " {filter}")?;
10953        }
10954        Ok(())
10955    }
10956}
10957
10958#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10959#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10960#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10961/// Options for a `SHOW OBJECTS` statement.
10962pub struct ShowObjects {
10963    /// Whether to show terse output.
10964    pub terse: bool,
10965    /// Additional options controlling the SHOW output.
10966    pub show_options: ShowStatementOptions,
10967}
10968
10969/// MSSQL's json null clause
10970///
10971/// ```plaintext
10972/// <json_null_clause> ::=
10973///       NULL ON NULL
10974///     | ABSENT ON NULL
10975/// ```
10976///
10977/// <https://learn.microsoft.com/en-us/sql/t-sql/functions/json-object-transact-sql?view=sql-server-ver16#json_null_clause>
10978#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10979#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10980#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10981pub enum JsonNullClause {
10982    /// `NULL ON NULL` behavior for JSON functions.
10983    NullOnNull,
10984    /// `ABSENT ON NULL` behavior for JSON functions.
10985    AbsentOnNull,
10986}
10987
10988impl Display for JsonNullClause {
10989    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10990        match self {
10991            JsonNullClause::NullOnNull => write!(f, "NULL ON NULL"),
10992            JsonNullClause::AbsentOnNull => write!(f, "ABSENT ON NULL"),
10993        }
10994    }
10995}
10996
10997/// PostgreSQL JSON function RETURNING clause
10998///
10999/// Example:
11000/// ```sql
11001/// JSON_OBJECT('a': 1 RETURNING jsonb)
11002/// ```
11003#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11004#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11005#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11006pub struct JsonReturningClause {
11007    /// The data type to return from the JSON function (e.g. JSON/JSONB).
11008    pub data_type: DataType,
11009}
11010
11011impl Display for JsonReturningClause {
11012    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
11013        write!(f, "RETURNING {}", self.data_type)
11014    }
11015}
11016
11017/// rename object definition
11018#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11019#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11020#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11021pub struct RenameTable {
11022    /// The current name of the object to rename.
11023    pub old_name: ObjectName,
11024    /// The new name for the object.
11025    pub new_name: ObjectName,
11026}
11027
11028impl fmt::Display for RenameTable {
11029    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11030        write!(f, "{} TO {}", self.old_name, self.new_name)?;
11031        Ok(())
11032    }
11033}
11034
11035/// Represents the referenced table in an `INSERT INTO` statement
11036#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11037#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11038#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11039pub enum TableObject {
11040    /// Table specified by name.
11041    /// Example:
11042    /// ```sql
11043    /// INSERT INTO my_table
11044    /// ```
11045    TableName(#[cfg_attr(feature = "visitor", visit(with = "visit_relation"))] ObjectName),
11046
11047    /// Table specified as a function.
11048    /// Example:
11049    /// ```sql
11050    /// INSERT INTO TABLE FUNCTION remote('localhost', default.simple_table)
11051    /// ```
11052    /// [Clickhouse](https://clickhouse.com/docs/en/sql-reference/table-functions)
11053    TableFunction(Function),
11054
11055    /// Table specified through a sub-query
11056    /// Example:
11057    /// ```sql
11058    /// INSERT INTO
11059    /// (SELECT employee_id, last_name, email, hire_date, job_id,  salary, commission_pct FROM employees)
11060    /// VALUES (207, 'Gregory', 'pgregory@example.com', sysdate, 'PU_CLERK', 1.2E3, NULL);
11061    /// ```
11062    /// [Oracle](https://docs.oracle.com/en/database/oracle/oracle-database/21/sqlrf/INSERT.html#GUID-903F8043-0254-4EE9-ACC1-CB8AC0AF3423__I2126242)
11063    TableQuery(Box<Query>),
11064}
11065
11066impl fmt::Display for TableObject {
11067    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11068        match self {
11069            Self::TableName(table_name) => write!(f, "{table_name}"),
11070            Self::TableFunction(func) => write!(f, "FUNCTION {func}"),
11071            Self::TableQuery(table_query) => write!(f, "({table_query})"),
11072        }
11073    }
11074}
11075
11076/// Represents a SET SESSION AUTHORIZATION statement
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))]
11080pub struct SetSessionAuthorizationParam {
11081    /// The scope for the `SET SESSION AUTHORIZATION` (e.g., GLOBAL/SESSION).
11082    pub scope: ContextModifier,
11083    /// The specific authorization parameter kind.
11084    pub kind: SetSessionAuthorizationParamKind,
11085}
11086
11087impl fmt::Display for SetSessionAuthorizationParam {
11088    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11089        write!(f, "{}", self.kind)
11090    }
11091}
11092
11093/// Represents the parameter kind for SET SESSION AUTHORIZATION
11094#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11095#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11096#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11097pub enum SetSessionAuthorizationParamKind {
11098    /// Default authorization
11099    Default,
11100
11101    /// User name
11102    User(Ident),
11103}
11104
11105impl fmt::Display for SetSessionAuthorizationParamKind {
11106    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11107        match self {
11108            SetSessionAuthorizationParamKind::Default => write!(f, "DEFAULT"),
11109            SetSessionAuthorizationParamKind::User(name) => write!(f, "{}", name),
11110        }
11111    }
11112}
11113
11114#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11115#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11116#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11117/// Kind of session parameter being set by `SET SESSION`.
11118pub enum SetSessionParamKind {
11119    /// Generic session parameter (name/value pair).
11120    Generic(SetSessionParamGeneric),
11121    /// Identity insert related parameter.
11122    IdentityInsert(SetSessionParamIdentityInsert),
11123    /// Offsets-related parameter.
11124    Offsets(SetSessionParamOffsets),
11125    /// Statistics-related parameter.
11126    Statistics(SetSessionParamStatistics),
11127}
11128
11129impl fmt::Display for SetSessionParamKind {
11130    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11131        match self {
11132            SetSessionParamKind::Generic(x) => write!(f, "{x}"),
11133            SetSessionParamKind::IdentityInsert(x) => write!(f, "{x}"),
11134            SetSessionParamKind::Offsets(x) => write!(f, "{x}"),
11135            SetSessionParamKind::Statistics(x) => write!(f, "{x}"),
11136        }
11137    }
11138}
11139
11140#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11141#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11142#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11143/// Generic `SET SESSION` parameter represented as name(s) and value.
11144pub struct SetSessionParamGeneric {
11145    /// Names of the session parameters being set.
11146    pub names: Vec<String>,
11147    /// The value to assign to the parameter(s).
11148    pub value: String,
11149}
11150
11151impl fmt::Display for SetSessionParamGeneric {
11152    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11153        write!(f, "{} {}", display_comma_separated(&self.names), self.value)
11154    }
11155}
11156
11157#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11158#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11159#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11160/// `IDENTITY_INSERT` session parameter for a specific object.
11161pub struct SetSessionParamIdentityInsert {
11162    /// Object name targeted by `IDENTITY_INSERT`.
11163    pub obj: ObjectName,
11164    /// Value (ON/OFF) for the identity insert setting.
11165    pub value: SessionParamValue,
11166}
11167
11168impl fmt::Display for SetSessionParamIdentityInsert {
11169    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11170        write!(f, "IDENTITY_INSERT {} {}", self.obj, self.value)
11171    }
11172}
11173
11174#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11175#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11176#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11177/// Offsets-related session parameter with keywords and a value.
11178pub struct SetSessionParamOffsets {
11179    /// Keywords specifying which offsets to modify.
11180    pub keywords: Vec<String>,
11181    /// Value (ON/OFF) for the offsets setting.
11182    pub value: SessionParamValue,
11183}
11184
11185impl fmt::Display for SetSessionParamOffsets {
11186    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11187        write!(
11188            f,
11189            "OFFSETS {} {}",
11190            display_comma_separated(&self.keywords),
11191            self.value
11192        )
11193    }
11194}
11195
11196#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11197#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11198#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11199/// Statistics-related session parameter specifying topic and value.
11200pub struct SetSessionParamStatistics {
11201    /// Statistics topic to set (IO/PROFILE/TIME/XML).
11202    pub topic: SessionParamStatsTopic,
11203    /// Value (ON/OFF) for the statistics topic.
11204    pub value: SessionParamValue,
11205}
11206
11207impl fmt::Display for SetSessionParamStatistics {
11208    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11209        write!(f, "STATISTICS {} {}", self.topic, self.value)
11210    }
11211}
11212
11213#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11214#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11215#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11216/// Topics available for session statistics configuration.
11217pub enum SessionParamStatsTopic {
11218    /// Input/output statistics.
11219    IO,
11220    /// Profile statistics.
11221    Profile,
11222    /// Time statistics.
11223    Time,
11224    /// XML-related statistics.
11225    Xml,
11226}
11227
11228impl fmt::Display for SessionParamStatsTopic {
11229    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11230        match self {
11231            SessionParamStatsTopic::IO => write!(f, "IO"),
11232            SessionParamStatsTopic::Profile => write!(f, "PROFILE"),
11233            SessionParamStatsTopic::Time => write!(f, "TIME"),
11234            SessionParamStatsTopic::Xml => write!(f, "XML"),
11235        }
11236    }
11237}
11238
11239#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11240#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11241#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11242/// Value for a session boolean-like parameter (ON/OFF).
11243pub enum SessionParamValue {
11244    /// Session parameter enabled.
11245    On,
11246    /// Session parameter disabled.
11247    Off,
11248}
11249
11250impl fmt::Display for SessionParamValue {
11251    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11252        match self {
11253            SessionParamValue::On => write!(f, "ON"),
11254            SessionParamValue::Off => write!(f, "OFF"),
11255        }
11256    }
11257}
11258
11259/// Snowflake StorageSerializationPolicy for Iceberg Tables
11260/// ```sql
11261/// [ STORAGE_SERIALIZATION_POLICY = { COMPATIBLE | OPTIMIZED } ]
11262/// ```
11263///
11264/// <https://docs.snowflake.com/en/sql-reference/sql/create-iceberg-table>
11265#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11266#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11267#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11268pub enum StorageSerializationPolicy {
11269    /// Use compatible serialization mode.
11270    Compatible,
11271    /// Use optimized serialization mode.
11272    Optimized,
11273}
11274
11275impl Display for StorageSerializationPolicy {
11276    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
11277        match self {
11278            StorageSerializationPolicy::Compatible => write!(f, "COMPATIBLE"),
11279            StorageSerializationPolicy::Optimized => write!(f, "OPTIMIZED"),
11280        }
11281    }
11282}
11283
11284/// Snowflake CatalogSyncNamespaceMode
11285/// ```sql
11286/// [ CATALOG_SYNC_NAMESPACE_MODE = { NEST | FLATTEN } ]
11287/// ```
11288///
11289/// <https://docs.snowflake.com/en/sql-reference/sql/create-database>
11290#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11291#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11292#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11293pub enum CatalogSyncNamespaceMode {
11294    /// Nest namespaces when syncing catalog.
11295    Nest,
11296    /// Flatten namespaces when syncing catalog.
11297    Flatten,
11298}
11299
11300impl Display for CatalogSyncNamespaceMode {
11301    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
11302        match self {
11303            CatalogSyncNamespaceMode::Nest => write!(f, "NEST"),
11304            CatalogSyncNamespaceMode::Flatten => write!(f, "FLATTEN"),
11305        }
11306    }
11307}
11308
11309/// Variants of the Snowflake `COPY INTO` statement
11310#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11311#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11312#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11313pub enum CopyIntoSnowflakeKind {
11314    /// Loads data from files to a table
11315    /// See: <https://docs.snowflake.com/en/sql-reference/sql/copy-into-table>
11316    Table,
11317    /// Unloads data from a table or query to external files
11318    /// See: <https://docs.snowflake.com/en/sql-reference/sql/copy-into-location>
11319    Location,
11320}
11321
11322#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11323#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11324#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11325/// `PRINT` statement for producing debug/output messages.
11326pub struct PrintStatement {
11327    /// The expression producing the message to print.
11328    pub message: Box<Expr>,
11329}
11330
11331impl fmt::Display for PrintStatement {
11332    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11333        write!(f, "PRINT {}", self.message)
11334    }
11335}
11336
11337/// The type of `WAITFOR` statement (MSSQL).
11338///
11339/// See: <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/waitfor-transact-sql>
11340#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11341#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11342#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11343pub enum WaitForType {
11344    /// `WAITFOR DELAY 'time_to_pass'`
11345    Delay,
11346    /// `WAITFOR TIME 'time_to_execute'`
11347    Time,
11348}
11349
11350impl fmt::Display for WaitForType {
11351    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11352        match self {
11353            WaitForType::Delay => write!(f, "DELAY"),
11354            WaitForType::Time => write!(f, "TIME"),
11355        }
11356    }
11357}
11358
11359/// MSSQL `WAITFOR` statement.
11360///
11361/// See: <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/waitfor-transact-sql>
11362#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11363#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11364#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11365pub struct WaitForStatement {
11366    /// `DELAY` or `TIME`.
11367    pub wait_type: WaitForType,
11368    /// The time expression.
11369    pub expr: Expr,
11370}
11371
11372impl fmt::Display for WaitForStatement {
11373    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11374        write!(f, "WAITFOR {} {}", self.wait_type, self.expr)
11375    }
11376}
11377
11378/// Represents a `Return` statement.
11379///
11380/// [MsSql triggers](https://learn.microsoft.com/en-us/sql/t-sql/statements/create-trigger-transact-sql)
11381/// [MsSql functions](https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql)
11382#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11383#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11384#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11385pub struct ReturnStatement {
11386    /// Optional return value expression.
11387    pub value: Option<ReturnStatementValue>,
11388}
11389
11390impl fmt::Display for ReturnStatement {
11391    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11392        match &self.value {
11393            Some(ReturnStatementValue::Expr(expr)) => write!(f, "RETURN {expr}"),
11394            None => write!(f, "RETURN"),
11395        }
11396    }
11397}
11398
11399/// Variants of a `RETURN` statement
11400#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11401#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11402#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11403pub enum ReturnStatementValue {
11404    /// Return an expression from a function or trigger.
11405    Expr(Expr),
11406}
11407
11408/// Represents an `OPEN` statement.
11409#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11410#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11411#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11412pub struct OpenStatement {
11413    /// Cursor name
11414    pub cursor_name: Ident,
11415}
11416
11417impl fmt::Display for OpenStatement {
11418    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11419        write!(f, "OPEN {}", self.cursor_name)
11420    }
11421}
11422
11423/// Specifies Include / Exclude NULL within UNPIVOT command.
11424/// For example
11425/// `UNPIVOT (column1 FOR new_column IN (col3, col4, col5, col6))`
11426#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11427#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11428#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11429pub enum NullInclusion {
11430    /// Include NULL values in the UNPIVOT output.
11431    IncludeNulls,
11432    /// Exclude NULL values from the UNPIVOT output.
11433    ExcludeNulls,
11434}
11435
11436impl fmt::Display for NullInclusion {
11437    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11438        match self {
11439            NullInclusion::IncludeNulls => write!(f, "INCLUDE NULLS"),
11440            NullInclusion::ExcludeNulls => write!(f, "EXCLUDE NULLS"),
11441        }
11442    }
11443}
11444
11445/// Checks membership of a value in a JSON array
11446///
11447/// Syntax:
11448/// ```sql
11449/// <value> MEMBER OF(<array>)
11450/// ```
11451/// [MySQL](https://dev.mysql.com/doc/refman/8.4/en/json-search-functions.html#operator_member-of)
11452#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11453#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11454#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11455pub struct MemberOf {
11456    /// The value to check for membership.
11457    pub value: Box<Expr>,
11458    /// The JSON array expression to check against.
11459    pub array: Box<Expr>,
11460}
11461
11462impl fmt::Display for MemberOf {
11463    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11464        write!(f, "{} MEMBER OF({})", self.value, self.array)
11465    }
11466}
11467
11468#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11469#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11470#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11471/// Represents an `EXPORT DATA` statement.
11472pub struct ExportData {
11473    /// Options for the export operation.
11474    pub options: Vec<SqlOption>,
11475    /// The query producing the data to export.
11476    pub query: Box<Query>,
11477    /// Optional named connection to use for export.
11478    pub connection: Option<ObjectName>,
11479}
11480
11481impl fmt::Display for ExportData {
11482    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11483        if let Some(connection) = &self.connection {
11484            write!(
11485                f,
11486                "EXPORT DATA WITH CONNECTION {connection} OPTIONS({}) AS {}",
11487                display_comma_separated(&self.options),
11488                self.query
11489            )
11490        } else {
11491            write!(
11492                f,
11493                "EXPORT DATA OPTIONS({}) AS {}",
11494                display_comma_separated(&self.options),
11495                self.query
11496            )
11497        }
11498    }
11499}
11500/// Creates a user
11501///
11502/// Syntax:
11503/// ```sql
11504/// CREATE [OR REPLACE] USER [IF NOT EXISTS] <name> [OPTIONS]
11505/// ```
11506///
11507/// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-user)
11508#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11509#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11510#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11511pub struct CreateUser {
11512    /// Replace existing user if present.
11513    pub or_replace: bool,
11514    /// Only create the user if it does not already exist.
11515    pub if_not_exists: bool,
11516    /// The name of the user to create.
11517    pub name: Ident,
11518    /// Key/value options for user creation.
11519    pub options: KeyValueOptions,
11520    /// Whether tags are specified using `WITH TAG`.
11521    pub with_tags: bool,
11522    /// Tags for the user.
11523    pub tags: KeyValueOptions,
11524}
11525
11526impl fmt::Display for CreateUser {
11527    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11528        write!(f, "CREATE")?;
11529        if self.or_replace {
11530            write!(f, " OR REPLACE")?;
11531        }
11532        write!(f, " USER")?;
11533        if self.if_not_exists {
11534            write!(f, " IF NOT EXISTS")?;
11535        }
11536        write!(f, " {}", self.name)?;
11537        if !self.options.options.is_empty() {
11538            write!(f, " {}", self.options)?;
11539        }
11540        if !self.tags.options.is_empty() {
11541            if self.with_tags {
11542                write!(f, " WITH")?;
11543            }
11544            write!(f, " TAG ({})", self.tags)?;
11545        }
11546        Ok(())
11547    }
11548}
11549
11550/// Modifies the properties of a user
11551///
11552/// [Snowflake Syntax:](https://docs.snowflake.com/en/sql-reference/sql/alter-user)
11553/// ```sql
11554/// ALTER USER [ IF EXISTS ] [ <name> ] [ OPTIONS ]
11555/// ```
11556///
11557/// [PostgreSQL Syntax:](https://www.postgresql.org/docs/current/sql-alteruser.html)
11558/// ```sql
11559/// ALTER USER <role_specification> [ WITH ] option [ ... ]
11560/// ```
11561#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11562#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11563#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11564pub struct AlterUser {
11565    /// Whether to only alter the user if it exists.
11566    pub if_exists: bool,
11567    /// The name of the user to alter.
11568    pub name: Ident,
11569    /// Optional new name for the user (Snowflake-specific).
11570    /// See: <https://docs.snowflake.com/en/sql-reference/sql/alter-user#syntax>
11571    pub rename_to: Option<Ident>,
11572    /// Reset the user's password.
11573    pub reset_password: bool,
11574    /// Abort all running queries for the user.
11575    pub abort_all_queries: bool,
11576    /// Optionally add a delegated role authorization.
11577    pub add_role_delegation: Option<AlterUserAddRoleDelegation>,
11578    /// Optionally remove a delegated role authorization.
11579    pub remove_role_delegation: Option<AlterUserRemoveRoleDelegation>,
11580    /// Enroll the user in MFA.
11581    pub enroll_mfa: bool,
11582    /// Set the default MFA method for the user.
11583    pub set_default_mfa_method: Option<MfaMethodKind>,
11584    /// Remove the user's default MFA method.
11585    pub remove_mfa_method: Option<MfaMethodKind>,
11586    /// Modify an MFA method for the user.
11587    pub modify_mfa_method: Option<AlterUserModifyMfaMethod>,
11588    /// Add an MFA OTP method with optional count.
11589    pub add_mfa_method_otp: Option<AlterUserAddMfaMethodOtp>,
11590    /// Set a user policy.
11591    pub set_policy: Option<AlterUserSetPolicy>,
11592    /// Unset a user policy.
11593    pub unset_policy: Option<UserPolicyKind>,
11594    /// Key/value tag options to set on the user.
11595    pub set_tag: KeyValueOptions,
11596    /// Tags to unset on the user.
11597    pub unset_tag: Vec<String>,
11598    /// Key/value properties to set on the user.
11599    pub set_props: KeyValueOptions,
11600    /// Properties to unset on the user.
11601    pub unset_props: Vec<String>,
11602    /// The following options are PostgreSQL-specific: <https://www.postgresql.org/docs/current/sql-alteruser.html>
11603    pub password: Option<AlterUserPassword>,
11604}
11605
11606/// ```sql
11607/// ALTER USER [ IF EXISTS ] [ <name> ] ADD DELEGATED AUTHORIZATION OF ROLE <role_name> TO SECURITY INTEGRATION <integration_name>
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 AlterUserAddRoleDelegation {
11613    /// Role name to delegate.
11614    pub role: Ident,
11615    /// Security integration receiving the delegation.
11616    pub integration: Ident,
11617}
11618
11619/// ```sql
11620/// ALTER USER [ IF EXISTS ] [ <name> ] REMOVE DELEGATED { AUTHORIZATION OF ROLE <role_name> | AUTHORIZATIONS } FROM SECURITY INTEGRATION <integration_name>
11621/// ```
11622#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11623#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11624#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11625pub struct AlterUserRemoveRoleDelegation {
11626    /// Optional role name to remove delegation for.
11627    pub role: Option<Ident>,
11628    /// Security integration from which to remove delegation.
11629    pub integration: Ident,
11630}
11631
11632/// ```sql
11633/// ADD MFA METHOD OTP [ COUNT = number ]
11634/// ```
11635#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11636#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11637#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11638pub struct AlterUserAddMfaMethodOtp {
11639    /// Optional OTP count parameter.
11640    pub count: Option<ValueWithSpan>,
11641}
11642
11643/// ```sql
11644/// ALTER USER [ IF EXISTS ] [ <name> ] MODIFY MFA METHOD <mfa_method> SET COMMENT = '<string>'
11645/// ```
11646#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11647#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11648#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11649pub struct AlterUserModifyMfaMethod {
11650    /// The MFA method being modified.
11651    pub method: MfaMethodKind,
11652    /// The new comment for the MFA method.
11653    pub comment: String,
11654}
11655
11656/// Types of MFA methods
11657#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11658#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11659#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11660pub enum MfaMethodKind {
11661    /// PassKey (hardware or platform passkey) MFA method.
11662    PassKey,
11663    /// Time-based One-Time Password (TOTP) MFA method.
11664    Totp,
11665    /// Duo Security MFA method.
11666    Duo,
11667}
11668
11669impl fmt::Display for MfaMethodKind {
11670    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11671        match self {
11672            MfaMethodKind::PassKey => write!(f, "PASSKEY"),
11673            MfaMethodKind::Totp => write!(f, "TOTP"),
11674            MfaMethodKind::Duo => write!(f, "DUO"),
11675        }
11676    }
11677}
11678
11679/// ```sql
11680/// ALTER USER [ IF EXISTS ] [ <name> ] SET { AUTHENTICATION | PASSWORD | SESSION } POLICY <policy_name>
11681/// ```
11682#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11683#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11684#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11685pub struct AlterUserSetPolicy {
11686    /// The kind of user policy being set (authentication/password/session).
11687    pub policy_kind: UserPolicyKind,
11688    /// The identifier of the policy to apply.
11689    pub policy: Ident,
11690}
11691
11692/// Types of user-based policies
11693#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11694#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11695#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11696pub enum UserPolicyKind {
11697    /// Authentication policy.
11698    Authentication,
11699    /// Password policy.
11700    Password,
11701    /// Session policy.
11702    Session,
11703}
11704
11705impl fmt::Display for UserPolicyKind {
11706    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11707        match self {
11708            UserPolicyKind::Authentication => write!(f, "AUTHENTICATION"),
11709            UserPolicyKind::Password => write!(f, "PASSWORD"),
11710            UserPolicyKind::Session => write!(f, "SESSION"),
11711        }
11712    }
11713}
11714
11715impl fmt::Display for AlterUser {
11716    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11717        write!(f, "ALTER")?;
11718        write!(f, " USER")?;
11719        if self.if_exists {
11720            write!(f, " IF EXISTS")?;
11721        }
11722        write!(f, " {}", self.name)?;
11723        if let Some(new_name) = &self.rename_to {
11724            write!(f, " RENAME TO {new_name}")?;
11725        }
11726        if self.reset_password {
11727            write!(f, " RESET PASSWORD")?;
11728        }
11729        if self.abort_all_queries {
11730            write!(f, " ABORT ALL QUERIES")?;
11731        }
11732        if let Some(role_delegation) = &self.add_role_delegation {
11733            let role = &role_delegation.role;
11734            let integration = &role_delegation.integration;
11735            write!(
11736                f,
11737                " ADD DELEGATED AUTHORIZATION OF ROLE {role} TO SECURITY INTEGRATION {integration}"
11738            )?;
11739        }
11740        if let Some(role_delegation) = &self.remove_role_delegation {
11741            write!(f, " REMOVE DELEGATED")?;
11742            match &role_delegation.role {
11743                Some(role) => write!(f, " AUTHORIZATION OF ROLE {role}")?,
11744                None => write!(f, " AUTHORIZATIONS")?,
11745            }
11746            let integration = &role_delegation.integration;
11747            write!(f, " FROM SECURITY INTEGRATION {integration}")?;
11748        }
11749        if self.enroll_mfa {
11750            write!(f, " ENROLL MFA")?;
11751        }
11752        if let Some(method) = &self.set_default_mfa_method {
11753            write!(f, " SET DEFAULT_MFA_METHOD {method}")?
11754        }
11755        if let Some(method) = &self.remove_mfa_method {
11756            write!(f, " REMOVE MFA METHOD {method}")?;
11757        }
11758        if let Some(modify) = &self.modify_mfa_method {
11759            let method = &modify.method;
11760            let comment = &modify.comment;
11761            write!(
11762                f,
11763                " MODIFY MFA METHOD {method} SET COMMENT '{}'",
11764                value::escape_single_quote_string(comment)
11765            )?;
11766        }
11767        if let Some(add_mfa_method_otp) = &self.add_mfa_method_otp {
11768            write!(f, " ADD MFA METHOD OTP")?;
11769            if let Some(count) = &add_mfa_method_otp.count {
11770                write!(f, " COUNT = {count}")?;
11771            }
11772        }
11773        if let Some(policy) = &self.set_policy {
11774            let policy_kind = &policy.policy_kind;
11775            let name = &policy.policy;
11776            write!(f, " SET {policy_kind} POLICY {name}")?;
11777        }
11778        if let Some(policy_kind) = &self.unset_policy {
11779            write!(f, " UNSET {policy_kind} POLICY")?;
11780        }
11781        if !self.set_tag.options.is_empty() {
11782            write!(f, " SET TAG {}", self.set_tag)?;
11783        }
11784        if !self.unset_tag.is_empty() {
11785            write!(f, " UNSET TAG {}", display_comma_separated(&self.unset_tag))?;
11786        }
11787        let has_props = !self.set_props.options.is_empty();
11788        if has_props {
11789            write!(f, " SET")?;
11790            write!(f, " {}", &self.set_props)?;
11791        }
11792        if !self.unset_props.is_empty() {
11793            write!(f, " UNSET {}", display_comma_separated(&self.unset_props))?;
11794        }
11795        if let Some(password) = &self.password {
11796            write!(f, " {}", password)?;
11797        }
11798        Ok(())
11799    }
11800}
11801
11802/// ```sql
11803/// ALTER USER <role_specification> [ WITH ] PASSWORD { 'password' | NULL }``
11804/// ```
11805#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11806#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11807#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11808pub struct AlterUserPassword {
11809    /// Whether the password is encrypted.
11810    pub encrypted: bool,
11811    /// The password string, or `None` for `NULL`.
11812    pub password: Option<String>,
11813}
11814
11815impl Display for AlterUserPassword {
11816    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11817        if self.encrypted {
11818            write!(f, "ENCRYPTED ")?;
11819        }
11820        write!(f, "PASSWORD")?;
11821        match &self.password {
11822            None => write!(f, " NULL")?,
11823            Some(password) => write!(f, " '{}'", value::escape_single_quote_string(password))?,
11824        }
11825        Ok(())
11826    }
11827}
11828
11829/// Specifies how to create a new table based on an existing table's schema.
11830/// '''sql
11831/// CREATE TABLE new LIKE old ...
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))]
11836pub enum CreateTableLikeKind {
11837    /// '''sql
11838    /// CREATE TABLE new (LIKE old ...)
11839    /// '''
11840    /// [Redshift](https://docs.aws.amazon.com/redshift/latest/dg/r_CREATE_TABLE_NEW.html)
11841    Parenthesized(CreateTableLike),
11842    /// '''sql
11843    /// CREATE TABLE new LIKE old ...
11844    /// '''
11845    /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-table#label-create-table-like)
11846    /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_table_like)
11847    Plain(CreateTableLike),
11848}
11849
11850#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11851#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11852#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11853/// Controls whether defaults are included when creating a table FROM/LILE another.
11854pub enum CreateTableLikeDefaults {
11855    /// Include default values from the source table.
11856    Including,
11857    /// Exclude default values from the source table.
11858    Excluding,
11859}
11860
11861impl fmt::Display for CreateTableLikeDefaults {
11862    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11863        match self {
11864            CreateTableLikeDefaults::Including => write!(f, "INCLUDING DEFAULTS"),
11865            CreateTableLikeDefaults::Excluding => write!(f, "EXCLUDING DEFAULTS"),
11866        }
11867    }
11868}
11869
11870#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11871#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11872#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11873/// Represents the `LIKE` clause of a `CREATE TABLE` statement.
11874pub struct CreateTableLike {
11875    /// The source table name to copy the schema from.
11876    pub name: ObjectName,
11877    /// Optional behavior controlling whether defaults are copied.
11878    pub defaults: Option<CreateTableLikeDefaults>,
11879}
11880
11881impl fmt::Display for CreateTableLike {
11882    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11883        write!(f, "LIKE {}", self.name)?;
11884        if let Some(defaults) = &self.defaults {
11885            write!(f, " {defaults}")?;
11886        }
11887        Ok(())
11888    }
11889}
11890
11891/// Specifies the refresh mode for the dynamic table.
11892///
11893/// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-dynamic-table)
11894#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11895#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11896#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11897pub enum RefreshModeKind {
11898    /// Automatic refresh mode (`AUTO`).
11899    Auto,
11900    /// Full refresh mode (`FULL`).
11901    Full,
11902    /// Incremental refresh mode (`INCREMENTAL`).
11903    Incremental,
11904}
11905
11906impl fmt::Display for RefreshModeKind {
11907    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11908        match self {
11909            RefreshModeKind::Auto => write!(f, "AUTO"),
11910            RefreshModeKind::Full => write!(f, "FULL"),
11911            RefreshModeKind::Incremental => write!(f, "INCREMENTAL"),
11912        }
11913    }
11914}
11915
11916/// Specifies the behavior of the initial refresh of the dynamic table.
11917///
11918/// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-dynamic-table)
11919#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11920#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11921#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11922pub enum InitializeKind {
11923    /// Initialize on creation (`ON CREATE`).
11924    OnCreate,
11925    /// Initialize on schedule (`ON SCHEDULE`).
11926    OnSchedule,
11927}
11928
11929impl fmt::Display for InitializeKind {
11930    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11931        match self {
11932            InitializeKind::OnCreate => write!(f, "ON_CREATE"),
11933            InitializeKind::OnSchedule => write!(f, "ON_SCHEDULE"),
11934        }
11935    }
11936}
11937
11938/// Re-sorts rows and reclaims space in either a specified table or all tables in the current database
11939///
11940/// '''sql
11941/// VACUUM [ FULL | SORT ONLY | DELETE ONLY | REINDEX | RECLUSTER ] [ \[ table_name \] [ TO threshold PERCENT ] \[ BOOST \] ]
11942/// '''
11943/// [Redshift](https://docs.aws.amazon.com/redshift/latest/dg/r_VACUUM_command.html)
11944#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11945#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11946#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11947pub struct VacuumStatement {
11948    /// Whether `FULL` was specified.
11949    pub full: bool,
11950    /// Whether `SORT ONLY` was specified.
11951    pub sort_only: bool,
11952    /// Whether `DELETE ONLY` was specified.
11953    pub delete_only: bool,
11954    /// Whether `REINDEX` was specified.
11955    pub reindex: bool,
11956    /// Whether `RECLUSTER` was specified.
11957    pub recluster: bool,
11958    /// Optional table to run `VACUUM` on.
11959    pub table_name: Option<ObjectName>,
11960    /// Optional threshold value (percent) for `TO threshold PERCENT`.
11961    pub threshold: Option<ValueWithSpan>,
11962    /// Whether `BOOST` was specified.
11963    pub boost: bool,
11964}
11965
11966impl fmt::Display for VacuumStatement {
11967    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11968        write!(
11969            f,
11970            "VACUUM{}{}{}{}{}",
11971            if self.full { " FULL" } else { "" },
11972            if self.sort_only { " SORT ONLY" } else { "" },
11973            if self.delete_only { " DELETE ONLY" } else { "" },
11974            if self.reindex { " REINDEX" } else { "" },
11975            if self.recluster { " RECLUSTER" } else { "" },
11976        )?;
11977        if let Some(table_name) = &self.table_name {
11978            write!(f, " {table_name}")?;
11979        }
11980        if let Some(threshold) = &self.threshold {
11981            write!(f, " TO {threshold} PERCENT")?;
11982        }
11983        if self.boost {
11984            write!(f, " BOOST")?;
11985        }
11986        Ok(())
11987    }
11988}
11989
11990/// Variants of the RESET statement
11991#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11992#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11993#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11994pub enum Reset {
11995    /// Resets all session parameters to their default values.
11996    ALL,
11997
11998    /// Resets a specific session parameter to its default value.
11999    ConfigurationParameter(ObjectName),
12000}
12001
12002/// Resets a session parameter to its default value.
12003/// ```sql
12004/// RESET { ALL | <configuration_parameter> }
12005/// ```
12006#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
12007#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
12008#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
12009pub struct ResetStatement {
12010    /// The reset action to perform (either `ALL` or a specific configuration parameter).
12011    pub reset: Reset,
12012}
12013
12014/// Query optimizer hints are optionally supported comments after the
12015/// `SELECT`, `INSERT`, `UPDATE`, `REPLACE`, `MERGE`, and `DELETE` keywords in
12016/// the corresponding statements.
12017///
12018/// See [Select::optimizer_hints]
12019#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
12020#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
12021#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
12022pub struct OptimizerHint {
12023    /// An optional prefix between the comment marker and `+`.
12024    ///
12025    /// Standard optimizer hints like `/*+ ... */` have an empty prefix,
12026    /// while system-specific hints like `/*abc+ ... */` have `prefix = "abc"`.
12027    /// The prefix is any sequence of ASCII alphanumeric characters
12028    /// immediately before the `+` marker.
12029    pub prefix: String,
12030    /// the raw text of the optimizer hint without its markers
12031    pub text: String,
12032    /// the style of the comment which `text` was extracted from,
12033    /// e.g. `/*+...*/` or `--+...`
12034    ///
12035    /// Not all dialects support all styles, though.
12036    pub style: OptimizerHintStyle,
12037}
12038
12039/// The commentary style of an [optimizer hint](OptimizerHint)
12040#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
12041#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
12042#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
12043pub enum OptimizerHintStyle {
12044    /// A hint corresponding to a single line comment,
12045    /// e.g. `--+ LEADING(v.e v.d t)`
12046    SingleLine {
12047        /// the comment prefix, e.g. `--`
12048        prefix: String,
12049    },
12050    /// A hint corresponding to a multi line comment,
12051    /// e.g. `/*+ LEADING(v.e v.d t) */`
12052    MultiLine,
12053}
12054
12055impl fmt::Display for OptimizerHint {
12056    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
12057        match &self.style {
12058            OptimizerHintStyle::SingleLine { prefix } => {
12059                f.write_str(prefix)?;
12060                f.write_str(&self.prefix)?;
12061                f.write_str("+")?;
12062                f.write_str(&self.text)
12063            }
12064            OptimizerHintStyle::MultiLine => {
12065                f.write_str("/*")?;
12066                f.write_str(&self.prefix)?;
12067                f.write_str("+")?;
12068                f.write_str(&self.text)?;
12069                f.write_str("*/")
12070            }
12071        }
12072    }
12073}
12074
12075impl fmt::Display for ResetStatement {
12076    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
12077        match &self.reset {
12078            Reset::ALL => write!(f, "RESET ALL"),
12079            Reset::ConfigurationParameter(param) => write!(f, "RESET {}", param),
12080        }
12081    }
12082}
12083
12084impl From<Set> for Statement {
12085    fn from(s: Set) -> Self {
12086        Self::Set(s)
12087    }
12088}
12089
12090impl From<Query> for Statement {
12091    fn from(q: Query) -> Self {
12092        Box::new(q).into()
12093    }
12094}
12095
12096impl From<Box<Query>> for Statement {
12097    fn from(q: Box<Query>) -> Self {
12098        Self::Query(q)
12099    }
12100}
12101
12102impl From<Insert> for Statement {
12103    fn from(i: Insert) -> Self {
12104        Self::Insert(i)
12105    }
12106}
12107
12108impl From<Update> for Statement {
12109    fn from(u: Update) -> Self {
12110        Self::Update(u)
12111    }
12112}
12113
12114impl From<CreateView> for Statement {
12115    fn from(cv: CreateView) -> Self {
12116        Self::CreateView(cv)
12117    }
12118}
12119
12120impl From<CreateRole> for Statement {
12121    fn from(cr: CreateRole) -> Self {
12122        Self::CreateRole(cr)
12123    }
12124}
12125
12126impl From<AlterTable> for Statement {
12127    fn from(at: AlterTable) -> Self {
12128        Self::AlterTable(at)
12129    }
12130}
12131
12132impl From<DropFunction> for Statement {
12133    fn from(df: DropFunction) -> Self {
12134        Self::DropFunction(df)
12135    }
12136}
12137
12138impl From<CreateExtension> for Statement {
12139    fn from(ce: CreateExtension) -> Self {
12140        Self::CreateExtension(ce)
12141    }
12142}
12143
12144impl From<CreateCollation> for Statement {
12145    fn from(c: CreateCollation) -> Self {
12146        Self::CreateCollation(c)
12147    }
12148}
12149
12150impl From<DropExtension> for Statement {
12151    fn from(de: DropExtension) -> Self {
12152        Self::DropExtension(de)
12153    }
12154}
12155
12156impl From<CaseStatement> for Statement {
12157    fn from(c: CaseStatement) -> Self {
12158        Self::Case(c)
12159    }
12160}
12161
12162impl From<IfStatement> for Statement {
12163    fn from(i: IfStatement) -> Self {
12164        Self::If(i)
12165    }
12166}
12167
12168impl From<WhileStatement> for Statement {
12169    fn from(w: WhileStatement) -> Self {
12170        Self::While(w)
12171    }
12172}
12173
12174impl From<RaiseStatement> for Statement {
12175    fn from(r: RaiseStatement) -> Self {
12176        Self::Raise(r)
12177    }
12178}
12179
12180impl From<ThrowStatement> for Statement {
12181    fn from(t: ThrowStatement) -> Self {
12182        Self::Throw(t)
12183    }
12184}
12185
12186impl From<Function> for Statement {
12187    fn from(f: Function) -> Self {
12188        Self::Call(f)
12189    }
12190}
12191
12192impl From<OpenStatement> for Statement {
12193    fn from(o: OpenStatement) -> Self {
12194        Self::Open(o)
12195    }
12196}
12197
12198impl From<Delete> for Statement {
12199    fn from(d: Delete) -> Self {
12200        Self::Delete(d)
12201    }
12202}
12203
12204impl From<CreateTable> for Statement {
12205    fn from(c: CreateTable) -> Self {
12206        Self::CreateTable(c)
12207    }
12208}
12209
12210impl From<CreateIndex> for Statement {
12211    fn from(c: CreateIndex) -> Self {
12212        Self::CreateIndex(c)
12213    }
12214}
12215
12216impl From<CreateServerStatement> for Statement {
12217    fn from(c: CreateServerStatement) -> Self {
12218        Self::CreateServer(c)
12219    }
12220}
12221
12222impl From<CreateConnector> for Statement {
12223    fn from(c: CreateConnector) -> Self {
12224        Self::CreateConnector(c)
12225    }
12226}
12227
12228impl From<CreateOperator> for Statement {
12229    fn from(c: CreateOperator) -> Self {
12230        Self::CreateOperator(c)
12231    }
12232}
12233
12234impl From<CreateOperatorFamily> for Statement {
12235    fn from(c: CreateOperatorFamily) -> Self {
12236        Self::CreateOperatorFamily(c)
12237    }
12238}
12239
12240impl From<CreateOperatorClass> for Statement {
12241    fn from(c: CreateOperatorClass) -> Self {
12242        Self::CreateOperatorClass(c)
12243    }
12244}
12245
12246impl From<AlterSchema> for Statement {
12247    fn from(a: AlterSchema) -> Self {
12248        Self::AlterSchema(a)
12249    }
12250}
12251
12252impl From<AlterFunction> for Statement {
12253    fn from(a: AlterFunction) -> Self {
12254        Self::AlterFunction(a)
12255    }
12256}
12257
12258impl From<AlterType> for Statement {
12259    fn from(a: AlterType) -> Self {
12260        Self::AlterType(a)
12261    }
12262}
12263
12264impl From<AlterCollation> for Statement {
12265    fn from(a: AlterCollation) -> Self {
12266        Self::AlterCollation(a)
12267    }
12268}
12269
12270impl From<AlterOperator> for Statement {
12271    fn from(a: AlterOperator) -> Self {
12272        Self::AlterOperator(a)
12273    }
12274}
12275
12276impl From<AlterOperatorFamily> for Statement {
12277    fn from(a: AlterOperatorFamily) -> Self {
12278        Self::AlterOperatorFamily(a)
12279    }
12280}
12281
12282impl From<AlterOperatorClass> for Statement {
12283    fn from(a: AlterOperatorClass) -> Self {
12284        Self::AlterOperatorClass(a)
12285    }
12286}
12287
12288impl From<Merge> for Statement {
12289    fn from(m: Merge) -> Self {
12290        Self::Merge(m)
12291    }
12292}
12293
12294impl From<AlterUser> for Statement {
12295    fn from(a: AlterUser) -> Self {
12296        Self::AlterUser(a)
12297    }
12298}
12299
12300impl From<DropDomain> for Statement {
12301    fn from(d: DropDomain) -> Self {
12302        Self::DropDomain(d)
12303    }
12304}
12305
12306impl From<ShowCharset> for Statement {
12307    fn from(s: ShowCharset) -> Self {
12308        Self::ShowCharset(s)
12309    }
12310}
12311
12312impl From<ShowObjects> for Statement {
12313    fn from(s: ShowObjects) -> Self {
12314        Self::ShowObjects(s)
12315    }
12316}
12317
12318impl From<Use> for Statement {
12319    fn from(u: Use) -> Self {
12320        Self::Use(u)
12321    }
12322}
12323
12324impl From<CreateFunction> for Statement {
12325    fn from(c: CreateFunction) -> Self {
12326        Self::CreateFunction(c)
12327    }
12328}
12329
12330impl From<CreateTrigger> for Statement {
12331    fn from(c: CreateTrigger) -> Self {
12332        Self::CreateTrigger(c)
12333    }
12334}
12335
12336impl From<DropTrigger> for Statement {
12337    fn from(d: DropTrigger) -> Self {
12338        Self::DropTrigger(d)
12339    }
12340}
12341
12342impl From<DropOperator> for Statement {
12343    fn from(d: DropOperator) -> Self {
12344        Self::DropOperator(d)
12345    }
12346}
12347
12348impl From<DropOperatorFamily> for Statement {
12349    fn from(d: DropOperatorFamily) -> Self {
12350        Self::DropOperatorFamily(d)
12351    }
12352}
12353
12354impl From<DropOperatorClass> for Statement {
12355    fn from(d: DropOperatorClass) -> Self {
12356        Self::DropOperatorClass(d)
12357    }
12358}
12359
12360impl From<DenyStatement> for Statement {
12361    fn from(d: DenyStatement) -> Self {
12362        Self::Deny(d)
12363    }
12364}
12365
12366impl From<CreateDomain> for Statement {
12367    fn from(c: CreateDomain) -> Self {
12368        Self::CreateDomain(c)
12369    }
12370}
12371
12372impl From<RenameTable> for Statement {
12373    fn from(r: RenameTable) -> Self {
12374        vec![r].into()
12375    }
12376}
12377
12378impl From<Vec<RenameTable>> for Statement {
12379    fn from(r: Vec<RenameTable>) -> Self {
12380        Self::RenameTable(r)
12381    }
12382}
12383
12384impl From<PrintStatement> for Statement {
12385    fn from(p: PrintStatement) -> Self {
12386        Self::Print(p)
12387    }
12388}
12389
12390impl From<ReturnStatement> for Statement {
12391    fn from(r: ReturnStatement) -> Self {
12392        Self::Return(r)
12393    }
12394}
12395
12396impl From<ExportData> for Statement {
12397    fn from(e: ExportData) -> Self {
12398        Self::ExportData(e)
12399    }
12400}
12401
12402impl From<CreateUser> for Statement {
12403    fn from(c: CreateUser) -> Self {
12404        Self::CreateUser(c)
12405    }
12406}
12407
12408impl From<VacuumStatement> for Statement {
12409    fn from(v: VacuumStatement) -> Self {
12410        Self::Vacuum(v)
12411    }
12412}
12413
12414impl From<ResetStatement> for Statement {
12415    fn from(r: ResetStatement) -> Self {
12416        Self::Reset(r)
12417    }
12418}
12419
12420#[cfg(test)]
12421mod tests {
12422    use crate::tokenizer::Location;
12423
12424    use super::*;
12425
12426    #[test]
12427    fn test_window_frame_default() {
12428        let window_frame = WindowFrame::default();
12429        assert_eq!(WindowFrameBound::Preceding(None), window_frame.start_bound);
12430    }
12431
12432    #[test]
12433    fn test_grouping_sets_display() {
12434        // a and b in different group
12435        let grouping_sets = Expr::GroupingSets(vec![
12436            vec![Expr::Identifier(Ident::new("a"))],
12437            vec![Expr::Identifier(Ident::new("b"))],
12438        ]);
12439        assert_eq!("GROUPING SETS ((a), (b))", format!("{grouping_sets}"));
12440
12441        // a and b in the same group
12442        let grouping_sets = Expr::GroupingSets(vec![vec![
12443            Expr::Identifier(Ident::new("a")),
12444            Expr::Identifier(Ident::new("b")),
12445        ]]);
12446        assert_eq!("GROUPING SETS ((a, b))", format!("{grouping_sets}"));
12447
12448        // (a, b) and (c, d) in different group
12449        let grouping_sets = Expr::GroupingSets(vec![
12450            vec![
12451                Expr::Identifier(Ident::new("a")),
12452                Expr::Identifier(Ident::new("b")),
12453            ],
12454            vec![
12455                Expr::Identifier(Ident::new("c")),
12456                Expr::Identifier(Ident::new("d")),
12457            ],
12458        ]);
12459        assert_eq!("GROUPING SETS ((a, b), (c, d))", format!("{grouping_sets}"));
12460    }
12461
12462    #[test]
12463    fn test_rollup_display() {
12464        let rollup = Expr::Rollup(vec![vec![Expr::Identifier(Ident::new("a"))]]);
12465        assert_eq!("ROLLUP (a)", format!("{rollup}"));
12466
12467        let rollup = Expr::Rollup(vec![vec![
12468            Expr::Identifier(Ident::new("a")),
12469            Expr::Identifier(Ident::new("b")),
12470        ]]);
12471        assert_eq!("ROLLUP ((a, b))", format!("{rollup}"));
12472
12473        let rollup = Expr::Rollup(vec![
12474            vec![Expr::Identifier(Ident::new("a"))],
12475            vec![Expr::Identifier(Ident::new("b"))],
12476        ]);
12477        assert_eq!("ROLLUP (a, b)", format!("{rollup}"));
12478
12479        let rollup = Expr::Rollup(vec![
12480            vec![Expr::Identifier(Ident::new("a"))],
12481            vec![
12482                Expr::Identifier(Ident::new("b")),
12483                Expr::Identifier(Ident::new("c")),
12484            ],
12485            vec![Expr::Identifier(Ident::new("d"))],
12486        ]);
12487        assert_eq!("ROLLUP (a, (b, c), d)", format!("{rollup}"));
12488    }
12489
12490    #[test]
12491    fn test_cube_display() {
12492        let cube = Expr::Cube(vec![vec![Expr::Identifier(Ident::new("a"))]]);
12493        assert_eq!("CUBE (a)", format!("{cube}"));
12494
12495        let cube = Expr::Cube(vec![vec![
12496            Expr::Identifier(Ident::new("a")),
12497            Expr::Identifier(Ident::new("b")),
12498        ]]);
12499        assert_eq!("CUBE ((a, b))", format!("{cube}"));
12500
12501        let cube = Expr::Cube(vec![
12502            vec![Expr::Identifier(Ident::new("a"))],
12503            vec![Expr::Identifier(Ident::new("b"))],
12504        ]);
12505        assert_eq!("CUBE (a, b)", format!("{cube}"));
12506
12507        let cube = Expr::Cube(vec![
12508            vec![Expr::Identifier(Ident::new("a"))],
12509            vec![
12510                Expr::Identifier(Ident::new("b")),
12511                Expr::Identifier(Ident::new("c")),
12512            ],
12513            vec![Expr::Identifier(Ident::new("d"))],
12514        ]);
12515        assert_eq!("CUBE (a, (b, c), d)", format!("{cube}"));
12516    }
12517
12518    #[test]
12519    fn test_interval_display() {
12520        let interval = Expr::Interval(Interval {
12521            value: Box::new(Expr::Value(
12522                Value::SingleQuotedString(String::from("123:45.67")).with_empty_span(),
12523            )),
12524            leading_field: Some(DateTimeField::Minute),
12525            leading_precision: Some(10),
12526            last_field: Some(DateTimeField::Second),
12527            fractional_seconds_precision: Some(9),
12528        });
12529        assert_eq!(
12530            "INTERVAL '123:45.67' MINUTE (10) TO SECOND (9)",
12531            format!("{interval}"),
12532        );
12533
12534        let interval = Expr::Interval(Interval {
12535            value: Box::new(Expr::Value(
12536                Value::SingleQuotedString(String::from("5")).with_empty_span(),
12537            )),
12538            leading_field: Some(DateTimeField::Second),
12539            leading_precision: Some(1),
12540            last_field: None,
12541            fractional_seconds_precision: Some(3),
12542        });
12543        assert_eq!("INTERVAL '5' SECOND (1, 3)", format!("{interval}"));
12544    }
12545
12546    #[test]
12547    fn test_one_or_many_with_parens_deref() {
12548        use core::ops::Index;
12549
12550        let one = OneOrManyWithParens::One("a");
12551
12552        assert_eq!(one.deref(), &["a"]);
12553        assert_eq!(<OneOrManyWithParens<_> as Deref>::deref(&one), &["a"]);
12554
12555        assert_eq!(one[0], "a");
12556        assert_eq!(one.index(0), &"a");
12557        assert_eq!(
12558            <<OneOrManyWithParens<_> as Deref>::Target as Index<usize>>::index(&one, 0),
12559            &"a"
12560        );
12561
12562        assert_eq!(one.len(), 1);
12563        assert_eq!(<OneOrManyWithParens<_> as Deref>::Target::len(&one), 1);
12564
12565        let many1 = OneOrManyWithParens::Many(vec!["b"]);
12566
12567        assert_eq!(many1.deref(), &["b"]);
12568        assert_eq!(<OneOrManyWithParens<_> as Deref>::deref(&many1), &["b"]);
12569
12570        assert_eq!(many1[0], "b");
12571        assert_eq!(many1.index(0), &"b");
12572        assert_eq!(
12573            <<OneOrManyWithParens<_> as Deref>::Target as Index<usize>>::index(&many1, 0),
12574            &"b"
12575        );
12576
12577        assert_eq!(many1.len(), 1);
12578        assert_eq!(<OneOrManyWithParens<_> as Deref>::Target::len(&many1), 1);
12579
12580        let many2 = OneOrManyWithParens::Many(vec!["c", "d"]);
12581
12582        assert_eq!(many2.deref(), &["c", "d"]);
12583        assert_eq!(
12584            <OneOrManyWithParens<_> as Deref>::deref(&many2),
12585            &["c", "d"]
12586        );
12587
12588        assert_eq!(many2[0], "c");
12589        assert_eq!(many2.index(0), &"c");
12590        assert_eq!(
12591            <<OneOrManyWithParens<_> as Deref>::Target as Index<usize>>::index(&many2, 0),
12592            &"c"
12593        );
12594
12595        assert_eq!(many2[1], "d");
12596        assert_eq!(many2.index(1), &"d");
12597        assert_eq!(
12598            <<OneOrManyWithParens<_> as Deref>::Target as Index<usize>>::index(&many2, 1),
12599            &"d"
12600        );
12601
12602        assert_eq!(many2.len(), 2);
12603        assert_eq!(<OneOrManyWithParens<_> as Deref>::Target::len(&many2), 2);
12604    }
12605
12606    #[test]
12607    fn test_one_or_many_with_parens_as_ref() {
12608        let one = OneOrManyWithParens::One("a");
12609
12610        assert_eq!(one.as_ref(), &["a"]);
12611        assert_eq!(<OneOrManyWithParens<_> as AsRef<_>>::as_ref(&one), &["a"]);
12612
12613        let many1 = OneOrManyWithParens::Many(vec!["b"]);
12614
12615        assert_eq!(many1.as_ref(), &["b"]);
12616        assert_eq!(<OneOrManyWithParens<_> as AsRef<_>>::as_ref(&many1), &["b"]);
12617
12618        let many2 = OneOrManyWithParens::Many(vec!["c", "d"]);
12619
12620        assert_eq!(many2.as_ref(), &["c", "d"]);
12621        assert_eq!(
12622            <OneOrManyWithParens<_> as AsRef<_>>::as_ref(&many2),
12623            &["c", "d"]
12624        );
12625    }
12626
12627    #[test]
12628    fn test_one_or_many_with_parens_ref_into_iter() {
12629        let one = OneOrManyWithParens::One("a");
12630
12631        assert_eq!(Vec::from_iter(&one), vec![&"a"]);
12632
12633        let many1 = OneOrManyWithParens::Many(vec!["b"]);
12634
12635        assert_eq!(Vec::from_iter(&many1), vec![&"b"]);
12636
12637        let many2 = OneOrManyWithParens::Many(vec!["c", "d"]);
12638
12639        assert_eq!(Vec::from_iter(&many2), vec![&"c", &"d"]);
12640    }
12641
12642    #[test]
12643    fn test_one_or_many_with_parens_value_into_iter() {
12644        use core::iter::once;
12645
12646        //tests that our iterator implemented methods behaves exactly as it's inner iterator, at every step up to n calls to next/next_back
12647        fn test_steps<I>(ours: OneOrManyWithParens<usize>, inner: I, n: usize)
12648        where
12649            I: IntoIterator<Item = usize, IntoIter: DoubleEndedIterator + Clone> + Clone,
12650        {
12651            fn checks<I>(ours: OneOrManyWithParensIntoIter<usize>, inner: I)
12652            where
12653                I: Iterator<Item = usize> + Clone + DoubleEndedIterator,
12654            {
12655                assert_eq!(ours.size_hint(), inner.size_hint());
12656                assert_eq!(ours.clone().count(), inner.clone().count());
12657
12658                assert_eq!(
12659                    ours.clone().fold(1, |a, v| a + v),
12660                    inner.clone().fold(1, |a, v| a + v)
12661                );
12662
12663                assert_eq!(Vec::from_iter(ours.clone()), Vec::from_iter(inner.clone()));
12664                assert_eq!(
12665                    Vec::from_iter(ours.clone().rev()),
12666                    Vec::from_iter(inner.clone().rev())
12667                );
12668            }
12669
12670            let mut ours_next = ours.clone().into_iter();
12671            let mut inner_next = inner.clone().into_iter();
12672
12673            for _ in 0..n {
12674                checks(ours_next.clone(), inner_next.clone());
12675
12676                assert_eq!(ours_next.next(), inner_next.next());
12677            }
12678
12679            let mut ours_next_back = ours.clone().into_iter();
12680            let mut inner_next_back = inner.clone().into_iter();
12681
12682            for _ in 0..n {
12683                checks(ours_next_back.clone(), inner_next_back.clone());
12684
12685                assert_eq!(ours_next_back.next_back(), inner_next_back.next_back());
12686            }
12687
12688            let mut ours_mixed = ours.clone().into_iter();
12689            let mut inner_mixed = inner.clone().into_iter();
12690
12691            for i in 0..n {
12692                checks(ours_mixed.clone(), inner_mixed.clone());
12693
12694                if i % 2 == 0 {
12695                    assert_eq!(ours_mixed.next_back(), inner_mixed.next_back());
12696                } else {
12697                    assert_eq!(ours_mixed.next(), inner_mixed.next());
12698                }
12699            }
12700
12701            let mut ours_mixed2 = ours.into_iter();
12702            let mut inner_mixed2 = inner.into_iter();
12703
12704            for i in 0..n {
12705                checks(ours_mixed2.clone(), inner_mixed2.clone());
12706
12707                if i % 2 == 0 {
12708                    assert_eq!(ours_mixed2.next(), inner_mixed2.next());
12709                } else {
12710                    assert_eq!(ours_mixed2.next_back(), inner_mixed2.next_back());
12711                }
12712            }
12713        }
12714
12715        test_steps(OneOrManyWithParens::One(1), once(1), 3);
12716        test_steps(OneOrManyWithParens::Many(vec![2]), vec![2], 3);
12717        test_steps(OneOrManyWithParens::Many(vec![3, 4]), vec![3, 4], 4);
12718    }
12719
12720    // Tests that the position in the code of an `Ident` does not affect its
12721    // ordering.
12722    #[test]
12723    fn test_ident_ord() {
12724        let mut a = Ident::with_span(Span::new(Location::new(1, 1), Location::new(1, 1)), "a");
12725        let mut b = Ident::with_span(Span::new(Location::new(2, 2), Location::new(2, 2)), "b");
12726
12727        assert!(a < b);
12728        std::mem::swap(&mut a.span, &mut b.span);
12729        assert!(a < b);
12730    }
12731}