Skip to main content

sqlparser/ast/
mod.rs

1// Licensed to the Apache Software Foundation (ASF) under one
2// or more contributor license agreements.  See the NOTICE file
3// distributed with this work for additional information
4// regarding copyright ownership.  The ASF licenses this file
5// to you under the Apache License, Version 2.0 (the
6// "License"); you may not use this file except in compliance
7// with the License.  You may obtain a copy of the License at
8//
9//   http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing,
12// software distributed under the License is distributed on an
13// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14// KIND, either express or implied.  See the License for the
15// specific language governing permissions and limitations
16// under the License.
17
18//! SQL Abstract Syntax Tree (AST) types
19#[cfg(not(feature = "std"))]
20use alloc::{
21    boxed::Box,
22    format,
23    string::{String, ToString},
24    vec,
25    vec::Vec,
26};
27use helpers::{
28    attached_token::AttachedToken,
29    stmt_data_loading::{FileStagingCommand, StageLoadSelectItemKind},
30};
31
32use core::cmp::Ordering;
33use core::ops::{Deref, DerefMut};
34use core::{
35    fmt::{self, Display},
36    hash,
37};
38
39#[cfg(feature = "serde")]
40use serde::{Deserialize, Serialize};
41
42#[cfg(feature = "visitor")]
43use sqlparser_derive::{Visit, VisitMut};
44
45use crate::{
46    display_utils::SpaceOrNewline,
47    tokenizer::{Span, Token},
48};
49use crate::{
50    display_utils::{Indent, NewLine},
51    keywords::Keyword,
52};
53
54pub use self::data_type::{
55    ArrayElemTypeDef, BinaryLength, CharLengthUnits, CharacterLength, DataType, EnumMember,
56    ExactNumberInfo, IntervalFields, StructBracketKind, TimezoneInfo,
57};
58pub use self::dcl::{
59    AlterRoleOperation, CreateRole, Grant, ResetConfig, Revoke, RoleOption, SecondaryRoles,
60    SetConfigValue, Use,
61};
62pub use self::ddl::{
63    Alignment, AlterCollation, AlterCollationOperation, AlterColumnOperation, AlterColumnStorage,
64    AlterConnectorOwner, AlterFunction, AlterFunctionAction, AlterFunctionKind,
65    AlterFunctionOperation, AlterIndexOperation, AlterOperator, AlterOperatorClass,
66    AlterOperatorClassOperation, AlterOperatorFamily, AlterOperatorFamilyOperation,
67    AlterOperatorOperation, AlterPolicy, AlterPolicyOperation, AlterSchema, AlterSchemaOperation,
68    AlterTable, AlterTableAlgorithm, AlterTableLock, AlterTableOperation, AlterTableType,
69    AlterType, AlterTypeAddValue, AlterTypeAddValuePosition, AlterTypeOperation, AlterTypeRename,
70    AlterTypeRenameValue, ClusteredBy, ColumnDef, ColumnOption, ColumnOptionDef, ColumnOptions,
71    ColumnPolicy, ColumnPolicyProperty, ConstraintCharacteristics, CreateCollation,
72    CreateCollationDefinition, CreateConnector, CreateDomain, CreateExtension, CreateFunction,
73    CreateIndex, CreateOperator, CreateOperatorClass, CreateOperatorFamily, CreatePolicy,
74    CreatePolicyCommand, CreatePolicyType, CreateTable, CreateTrigger, CreateView, Deduplicate,
75    DeferrableInitial, DistStyle, DropBehavior, DropExtension, DropFunction, DropOperator,
76    DropOperatorClass, DropOperatorFamily, DropOperatorSignature, DropPolicy, DropTrigger,
77    ForValues, FunctionReturnType, GeneratedAs, GeneratedExpressionMode, IdentityParameters,
78    IdentityProperty, IdentityPropertyFormatKind, IdentityPropertyKind, IdentityPropertyOrder,
79    IndexColumn, IndexOption, IndexType, KeyOrIndexDisplay, Msck, NullsDistinctOption,
80    OperatorArgTypes, OperatorClassItem, OperatorFamilyDropItem, OperatorFamilyItem,
81    OperatorOption, OperatorPurpose, Owner, Partition, PartitionBoundValue, ProcedureParam,
82    ReferentialAction, RenameTableNameKind, ReplicaIdentity, TagsColumnOption, TriggerObjectKind,
83    Truncate, UserDefinedTypeCompositeAttributeDef, UserDefinedTypeInternalLength,
84    UserDefinedTypeRangeOption, UserDefinedTypeRepresentation, UserDefinedTypeSqlDefinitionOption,
85    UserDefinedTypeStorage, ViewColumnDef, WithData,
86};
87pub use self::dml::{
88    Delete, Insert, Merge, MergeAction, MergeClause, MergeClauseKind, MergeInsertExpr,
89    MergeInsertKind, MergeUpdateExpr, MergeUpdateKind, MultiTableInsertIntoClause,
90    MultiTableInsertType, MultiTableInsertValue, MultiTableInsertValues,
91    MultiTableInsertWhenClause, OutputClause, Update,
92};
93pub use self::operator::{BinaryOperator, UnaryOperator};
94pub use self::query::{
95    AfterMatchSkip, ConnectByKind, Cte, CteAsMaterialized, Distinct, EmptyMatchesMode,
96    ExceptSelectItem, ExcludeSelectItem, ExprWithAlias, ExprWithAliasAndOrderBy, Fetch, ForClause,
97    ForJson, ForXml, FormatClause, GroupByExpr, GroupByWithModifier, IdentWithAlias,
98    IlikeSelectItem, InputFormatClause, Interpolate, InterpolateExpr, Join, JoinConstraint,
99    JoinOperator, JsonTableColumn, JsonTableColumnErrorHandling, JsonTableNamedColumn,
100    JsonTableNestedColumn, LateralView, LimitClause, LockClause, LockType, MatchRecognizePattern,
101    MatchRecognizeSymbol, Measure, NamedWindowDefinition, NamedWindowExpr, NonBlock, Offset,
102    OffsetRows, OpenJsonTableColumn, OrderBy, OrderByExpr, OrderByKind, OrderByOptions,
103    OrderBySort, PipeOperator, PivotValueSource, ProjectionSelect, Query, RenameSelectItem,
104    RepetitionQuantifier, ReplaceSelectElement, ReplaceSelectItem, RowsPerMatch, Select,
105    SelectFlavor, SelectInto, SelectItem, SelectItemQualifiedWildcardKind, SelectModifiers,
106    SetExpr, SetOperator, SetQuantifier, Setting, SymbolDefinition, Table, TableAlias,
107    TableAliasColumnDef, TableFactor, TableFunctionArgs, TableIndexHintForClause,
108    TableIndexHintType, TableIndexHints, TableIndexType, TableSample, TableSampleBucket,
109    TableSampleKind, TableSampleMethod, TableSampleModifier, TableSampleQuantity, TableSampleSeed,
110    TableSampleSeedModifier, TableSampleUnit, TableVersion, TableWithJoins, Top, TopQuantity,
111    UpdateTableFromKind, ValueTableMode, Values, WildcardAdditionalOptions, With, WithFill,
112    XmlNamespaceDefinition, XmlPassingArgument, XmlPassingClause, XmlTableColumn,
113    XmlTableColumnOption,
114};
115
116pub use self::trigger::{
117    TriggerEvent, TriggerExecBody, TriggerExecBodyType, TriggerObject, TriggerPeriod,
118    TriggerReferencing, TriggerReferencingType,
119};
120
121pub use self::value::{
122    escape_double_quote_string, escape_quoted_string, DateTimeField, DollarQuotedString,
123    NormalizationForm, QuoteDelimitedString, TrimWhereField, Value, ValueWithSpan,
124};
125
126use crate::ast::helpers::key_value_options::KeyValueOptions;
127use crate::ast::helpers::stmt_data_loading::StageParamsObject;
128
129#[cfg(feature = "visitor")]
130pub use visitor::*;
131
132pub use self::data_type::GeometricTypeKind;
133
134mod data_type;
135mod dcl;
136mod ddl;
137mod dml;
138/// Helper modules for building and manipulating AST nodes.
139pub mod helpers;
140pub mod table_constraints;
141pub use table_constraints::{
142    CheckConstraint, ConstraintUsingIndex, ForeignKeyConstraint, FullTextOrSpatialConstraint,
143    IndexConstraint, PrimaryKeyConstraint, TableConstraint, UniqueConstraint,
144};
145mod operator;
146mod query;
147mod spans;
148pub use spans::Spanned;
149
150pub mod comments;
151mod trigger;
152mod value;
153
154#[cfg(feature = "visitor")]
155mod visitor;
156
157/// Helper used to format a slice using a separator string (e.g., `", "`).
158pub struct DisplaySeparated<'a, T>
159where
160    T: fmt::Display,
161{
162    slice: &'a [T],
163    sep: &'static str,
164}
165
166impl<T> fmt::Display for DisplaySeparated<'_, T>
167where
168    T: fmt::Display,
169{
170    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
171        let mut delim = "";
172        for t in self.slice {
173            f.write_str(delim)?;
174            delim = self.sep;
175            t.fmt(f)?;
176        }
177        Ok(())
178    }
179}
180
181pub(crate) fn display_separated<'a, T>(slice: &'a [T], sep: &'static str) -> DisplaySeparated<'a, T>
182where
183    T: fmt::Display,
184{
185    DisplaySeparated { slice, sep }
186}
187
188pub(crate) fn display_comma_separated<T>(slice: &[T]) -> DisplaySeparated<'_, T>
189where
190    T: fmt::Display,
191{
192    DisplaySeparated { slice, sep: ", " }
193}
194
195/// Writes the given statements to the formatter, each ending with
196/// a semicolon and space separated.
197fn format_statement_list(f: &mut fmt::Formatter, statements: &[Statement]) -> fmt::Result {
198    write!(f, "{}", display_separated(statements, "; "))?;
199    // We manually insert semicolon for the last statement,
200    // since display_separated doesn't handle that case.
201    write!(f, ";")
202}
203
204/// A item `T` enclosed in a pair of parentheses
205#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
206#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
207#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
208pub struct Parens<T> {
209    /// the opening parenthesis token, i.e. `(`
210    pub opening_token: AttachedToken,
211    /// content enclosed in parentheses
212    pub content: T,
213    /// the closing parenthesis token, i.e. `)`
214    pub closing_token: AttachedToken,
215}
216
217impl<T> Parens<T> {
218    /// Constructor wrapping `content` into `Parens` with an empty span;
219    /// useful for testing purposes.
220    pub fn with_empty_span(content: T) -> Self {
221        Self {
222            opening_token: AttachedToken::empty(),
223            content,
224            closing_token: AttachedToken::empty(),
225        }
226    }
227}
228
229impl<T> Deref for Parens<T> {
230    type Target = T;
231
232    fn deref(&self) -> &Self::Target {
233        &self.content
234    }
235}
236
237impl<T> DerefMut for Parens<T> {
238    fn deref_mut(&mut self) -> &mut Self::Target {
239        &mut self.content
240    }
241}
242
243/// An identifier, decomposed into its value or character data and the quote style.
244#[derive(Debug, Clone)]
245#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
246#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
247pub struct Ident {
248    /// The value of the identifier without quotes.
249    pub value: String,
250    /// The starting quote if any. Valid quote characters are the single quote,
251    /// double quote, backtick, and opening square bracket.
252    pub quote_style: Option<char>,
253    /// The span of the identifier in the original SQL string.
254    pub span: Span,
255}
256
257impl PartialEq for Ident {
258    fn eq(&self, other: &Self) -> bool {
259        let Ident {
260            value,
261            quote_style,
262            // exhaustiveness check; we ignore spans in comparisons
263            span: _,
264        } = self;
265
266        value == &other.value && quote_style == &other.quote_style
267    }
268}
269
270impl core::hash::Hash for Ident {
271    fn hash<H: hash::Hasher>(&self, state: &mut H) {
272        let Ident {
273            value,
274            quote_style,
275            // exhaustiveness check; we ignore spans in hashes
276            span: _,
277        } = self;
278
279        value.hash(state);
280        quote_style.hash(state);
281    }
282}
283
284impl Eq for Ident {}
285
286impl PartialOrd for Ident {
287    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
288        Some(self.cmp(other))
289    }
290}
291
292impl Ord for Ident {
293    fn cmp(&self, other: &Self) -> Ordering {
294        let Ident {
295            value,
296            quote_style,
297            // exhaustiveness check; we ignore spans in ordering
298            span: _,
299        } = self;
300
301        let Ident {
302            value: other_value,
303            quote_style: other_quote_style,
304            // exhaustiveness check; we ignore spans in ordering
305            span: _,
306        } = other;
307
308        // First compare by value, then by quote_style
309        value
310            .cmp(other_value)
311            .then_with(|| quote_style.cmp(other_quote_style))
312    }
313}
314
315impl Ident {
316    /// Create a new identifier with the given value and no quotes and an empty span.
317    pub fn new<S>(value: S) -> Self
318    where
319        S: Into<String>,
320    {
321        Ident {
322            value: value.into(),
323            quote_style: None,
324            span: Span::empty(),
325        }
326    }
327
328    /// Create a new quoted identifier with the given quote and value. This function
329    /// panics if the given quote is not a valid quote character.
330    pub fn with_quote<S>(quote: char, value: S) -> Self
331    where
332        S: Into<String>,
333    {
334        assert!(quote == '\'' || quote == '"' || quote == '`' || quote == '[');
335        Ident {
336            value: value.into(),
337            quote_style: Some(quote),
338            span: Span::empty(),
339        }
340    }
341
342    /// Create an `Ident` with the given `span` and `value` (unquoted).
343    pub fn with_span<S>(span: Span, value: S) -> Self
344    where
345        S: Into<String>,
346    {
347        Ident {
348            value: value.into(),
349            quote_style: None,
350            span,
351        }
352    }
353
354    /// Create a quoted `Ident` with the given `quote` and `span`.
355    pub fn with_quote_and_span<S>(quote: char, span: Span, value: S) -> Self
356    where
357        S: Into<String>,
358    {
359        assert!(quote == '\'' || quote == '"' || quote == '`' || quote == '[');
360        Ident {
361            value: value.into(),
362            quote_style: Some(quote),
363            span,
364        }
365    }
366}
367
368impl From<&str> for Ident {
369    fn from(value: &str) -> Self {
370        Ident {
371            value: value.to_string(),
372            quote_style: None,
373            span: Span::empty(),
374        }
375    }
376}
377
378impl fmt::Display for Ident {
379    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
380        match self.quote_style {
381            Some(q) if q == '"' || q == '\'' || q == '`' => {
382                let escaped = value::escape_quoted_string(&self.value, q);
383                write!(f, "{q}{escaped}{q}")
384            }
385            Some('[') => write!(f, "[{}]", self.value),
386            None => f.write_str(&self.value),
387            _ => panic!("unexpected quote style"),
388        }
389    }
390}
391
392/// A name of a table, view, custom type, etc., possibly multi-part, i.e. db.schema.obj
393#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
394#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
395#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
396pub struct ObjectName(pub Vec<ObjectNamePart>);
397
398impl From<Vec<Ident>> for ObjectName {
399    fn from(idents: Vec<Ident>) -> Self {
400        ObjectName(idents.into_iter().map(ObjectNamePart::Identifier).collect())
401    }
402}
403
404impl From<Ident> for ObjectName {
405    fn from(ident: Ident) -> Self {
406        ObjectName(vec![ObjectNamePart::Identifier(ident)])
407    }
408}
409
410impl fmt::Display for ObjectName {
411    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
412        write!(f, "{}", display_separated(&self.0, "."))
413    }
414}
415
416/// A single part of an ObjectName
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 enum ObjectNamePart {
421    /// A single identifier part, e.g. `schema` or `table`.
422    Identifier(Ident),
423    /// A function that returns an identifier (dialect-specific).
424    Function(ObjectNamePartFunction),
425}
426
427impl ObjectNamePart {
428    /// Return the identifier if this is an `Identifier` variant.
429    pub fn as_ident(&self) -> Option<&Ident> {
430        match self {
431            ObjectNamePart::Identifier(ident) => Some(ident),
432            ObjectNamePart::Function(_) => None,
433        }
434    }
435}
436
437impl fmt::Display for ObjectNamePart {
438    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
439        match self {
440            ObjectNamePart::Identifier(ident) => write!(f, "{ident}"),
441            ObjectNamePart::Function(func) => write!(f, "{func}"),
442        }
443    }
444}
445
446/// An object name part that consists of a function that dynamically
447/// constructs identifiers.
448///
449/// - [Snowflake](https://docs.snowflake.com/en/sql-reference/identifier-literal)
450#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
451#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
452#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
453pub struct ObjectNamePartFunction {
454    /// The function name that produces the object name part.
455    pub name: Ident,
456    /// Function arguments used to compute the identifier.
457    pub args: Vec<FunctionArg>,
458}
459
460impl fmt::Display for ObjectNamePartFunction {
461    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
462        write!(f, "{}(", self.name)?;
463        write!(f, "{})", display_comma_separated(&self.args))
464    }
465}
466
467/// Represents an Array Expression, either
468/// `ARRAY[..]`, or `[..]`
469#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
470#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
471#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
472pub struct Array {
473    /// The list of expressions between brackets
474    pub elem: Vec<Expr>,
475
476    /// `true` for  `ARRAY[..]`, `false` for `[..]`
477    pub named: bool,
478}
479
480impl fmt::Display for Array {
481    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
482        write!(
483            f,
484            "{}[{}]",
485            if self.named { "ARRAY" } else { "" },
486            display_comma_separated(&self.elem)
487        )
488    }
489}
490
491/// Represents an INTERVAL expression, roughly in the following format:
492/// `INTERVAL '<value>' [ <leading_field> [ (<leading_precision>) ] ]
493/// [ TO <last_field> [ (<fractional_seconds_precision>) ] ]`,
494/// e.g. `INTERVAL '123:45.67' MINUTE(3) TO SECOND(2)`.
495///
496/// The parser does not validate the `<value>`, nor does it ensure
497/// that the `<leading_field>` units >= the units in `<last_field>`,
498/// so the user will have to reject intervals like `HOUR TO YEAR`.
499#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
500#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
501#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
502pub struct Interval {
503    /// The interval value expression (commonly a string literal).
504    pub value: Box<Expr>,
505    /// Optional leading time unit (e.g., `HOUR`, `MINUTE`).
506    pub leading_field: Option<DateTimeField>,
507    /// Optional leading precision for the leading field.
508    pub leading_precision: Option<u64>,
509    /// Optional trailing time unit for a range (e.g., `SECOND`).
510    pub last_field: Option<DateTimeField>,
511    /// The fractional seconds precision, when specified.
512    ///
513    /// See SQL `SECOND(n)` or `SECOND(m, n)` forms.
514    pub fractional_seconds_precision: Option<u64>,
515}
516
517impl fmt::Display for Interval {
518    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
519        let value = self.value.as_ref();
520        match (
521            &self.leading_field,
522            self.leading_precision,
523            self.fractional_seconds_precision,
524        ) {
525            (
526                Some(DateTimeField::Second),
527                Some(leading_precision),
528                Some(fractional_seconds_precision),
529            ) => {
530                // When the leading field is SECOND, the parser guarantees that
531                // the last field is None.
532                assert!(self.last_field.is_none());
533                write!(
534                    f,
535                    "INTERVAL {value} SECOND ({leading_precision}, {fractional_seconds_precision})"
536                )
537            }
538            _ => {
539                write!(f, "INTERVAL {value}")?;
540                if let Some(leading_field) = &self.leading_field {
541                    write!(f, " {leading_field}")?;
542                }
543                if let Some(leading_precision) = self.leading_precision {
544                    write!(f, " ({leading_precision})")?;
545                }
546                if let Some(last_field) = &self.last_field {
547                    write!(f, " TO {last_field}")?;
548                }
549                if let Some(fractional_seconds_precision) = self.fractional_seconds_precision {
550                    write!(f, " ({fractional_seconds_precision})")?;
551                }
552                Ok(())
553            }
554        }
555    }
556}
557
558/// A field definition within a struct
559///
560/// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-types#struct_type
561#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
562#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
563#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
564pub struct StructField {
565    /// Optional name of the struct field.
566    pub field_name: Option<Ident>,
567    /// The field data type.
568    pub field_type: DataType,
569    /// Struct field options (e.g., `OPTIONS(...)` on BigQuery).
570    /// See [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#column_name_and_column_schema)
571    pub options: Option<Vec<SqlOption>>,
572}
573
574impl fmt::Display for StructField {
575    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
576        if let Some(name) = &self.field_name {
577            write!(f, "{name} {}", self.field_type)?;
578        } else {
579            write!(f, "{}", self.field_type)?;
580        }
581        if let Some(options) = &self.options {
582            write!(f, " OPTIONS({})", display_separated(options, ", "))
583        } else {
584            Ok(())
585        }
586    }
587}
588
589/// A field definition within a union
590///
591/// [DuckDB]: https://duckdb.org/docs/sql/data_types/union.html
592#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
593#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
594#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
595pub struct UnionField {
596    /// Name of the union field.
597    pub field_name: Ident,
598    /// Type of the union field.
599    pub field_type: DataType,
600}
601
602impl fmt::Display for UnionField {
603    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
604        write!(f, "{} {}", self.field_name, self.field_type)
605    }
606}
607
608/// A dictionary field within a dictionary.
609///
610/// [DuckDB]: https://duckdb.org/docs/sql/data_types/struct#creating-structs
611#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
612#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
613#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
614pub struct DictionaryField {
615    /// Dictionary key identifier.
616    pub key: Ident,
617    /// Value expression for the dictionary entry.
618    pub value: Box<Expr>,
619}
620
621impl fmt::Display for DictionaryField {
622    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
623        write!(f, "{}: {}", self.key, self.value)
624    }
625}
626
627/// Represents a Map expression.
628#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
629#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
630#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
631pub struct Map {
632    /// Entries of the map as key/value pairs.
633    pub entries: Vec<MapEntry>,
634}
635
636impl Display for Map {
637    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
638        write!(f, "MAP {{{}}}", display_comma_separated(&self.entries))
639    }
640}
641
642/// A map field within a map.
643///
644/// [DuckDB]: https://duckdb.org/docs/sql/data_types/map.html#creating-maps
645#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
646#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
647#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
648pub struct MapEntry {
649    /// Key expression of the map entry.
650    pub key: Box<Expr>,
651    /// Value expression of the map entry.
652    pub value: Box<Expr>,
653}
654
655impl fmt::Display for MapEntry {
656    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
657        write!(f, "{}: {}", self.key, self.value)
658    }
659}
660
661/// Options for `CAST` / `TRY_CAST`
662/// BigQuery: <https://cloud.google.com/bigquery/docs/reference/standard-sql/format-elements#formatting_syntax>
663#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
664#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
665#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
666pub enum CastFormat {
667    /// A simple cast format specified by a `Value`.
668    Value(ValueWithSpan),
669    /// A cast format with an explicit time zone: `(format, timezone)`.
670    ValueAtTimeZone(ValueWithSpan, ValueWithSpan),
671}
672
673/// An element of a JSON path.
674#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
675#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
676#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
677pub enum JsonPathElem {
678    /// Accesses an object field using dot notation, e.g. `obj:foo.bar.baz`.
679    ///
680    /// See <https://docs.snowflake.com/en/user-guide/querying-semistructured#dot-notation>.
681    Dot {
682        /// The object key text (without quotes).
683        key: String,
684        /// `true` when the key was quoted in the source.
685        quoted: bool,
686    },
687    /// Accesses an object field or array element using bracket notation,
688    /// e.g. `obj['foo']`.
689    ///
690    /// See <https://docs.snowflake.com/en/user-guide/querying-semistructured#bracket-notation>.
691    Bracket {
692        /// The expression used as the bracket key (string or numeric expression).
693        key: Expr,
694    },
695    /// Access an object field using colon bracket notation
696    /// e.g. `obj:['foo']`
697    ///
698    /// See <https://docs.databricks.com/en/sql/language-manual/functions/colonsign.html>
699    ColonBracket {
700        /// The expression used as the bracket key (string or numeric expression).
701        key: Expr,
702    },
703}
704
705/// A JSON path.
706///
707/// See <https://docs.snowflake.com/en/user-guide/querying-semistructured>.
708/// See <https://docs.databricks.com/en/sql/language-manual/sql-ref-json-path-expression.html>.
709#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
710#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
711#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
712pub struct JsonPath {
713    /// Sequence of path elements that form the JSON path.
714    pub path: Vec<JsonPathElem>,
715}
716
717impl fmt::Display for JsonPath {
718    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
719        for (i, elem) in self.path.iter().enumerate() {
720            match elem {
721                JsonPathElem::Dot { key, quoted } => {
722                    if i == 0 {
723                        write!(f, ":")?;
724                    } else {
725                        write!(f, ".")?;
726                    }
727
728                    if *quoted {
729                        write!(f, "\"{}\"", escape_double_quote_string(key))?;
730                    } else {
731                        write!(f, "{key}")?;
732                    }
733                }
734                JsonPathElem::Bracket { key } => {
735                    write!(f, "[{key}]")?;
736                }
737                JsonPathElem::ColonBracket { key } => {
738                    write!(f, ":[{key}]")?;
739                }
740            }
741        }
742        Ok(())
743    }
744}
745
746/// The syntax used for in a cast expression.
747#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
748#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
749#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
750pub enum CastKind {
751    /// The standard SQL cast syntax, e.g. `CAST(<expr> as <datatype>)`
752    Cast,
753    /// A cast that returns `NULL` on failure, e.g. `TRY_CAST(<expr> as <datatype>)`.
754    ///
755    /// See <https://docs.snowflake.com/en/sql-reference/functions/try_cast>.
756    /// See <https://learn.microsoft.com/en-us/sql/t-sql/functions/try-cast-transact-sql>.
757    TryCast,
758    /// A cast that returns `NULL` on failure, bigQuery-specific ,  e.g. `SAFE_CAST(<expr> as <datatype>)`.
759    ///
760    /// See <https://cloud.google.com/bigquery/docs/reference/standard-sql/functions-and-operators#safe_casting>.
761    SafeCast,
762    /// `<expr> :: <datatype>`
763    DoubleColon,
764}
765
766/// `MATCH` type for constraint references
767///
768/// See: <https://www.postgresql.org/docs/current/sql-createtable.html#SQL-CREATETABLE-PARMS-REFERENCES>
769#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
770#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
771#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
772pub enum ConstraintReferenceMatchKind {
773    /// `MATCH FULL`
774    Full,
775    /// `MATCH PARTIAL`
776    Partial,
777    /// `MATCH SIMPLE`
778    Simple,
779}
780
781impl fmt::Display for ConstraintReferenceMatchKind {
782    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
783        match self {
784            Self::Full => write!(f, "MATCH FULL"),
785            Self::Partial => write!(f, "MATCH PARTIAL"),
786            Self::Simple => write!(f, "MATCH SIMPLE"),
787        }
788    }
789}
790
791/// `EXTRACT` syntax variants.
792///
793/// In Snowflake dialect, the `EXTRACT` expression can support either the `from` syntax
794/// or the comma syntax.
795///
796/// See <https://docs.snowflake.com/en/sql-reference/functions/extract>
797#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
798#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
799#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
800pub enum ExtractSyntax {
801    /// `EXTRACT( <date_or_time_part> FROM <date_or_time_expr> )`
802    From,
803    /// `EXTRACT( <date_or_time_part> , <date_or_timestamp_expr> )`
804    Comma,
805}
806
807/// The syntax used in a CEIL or FLOOR expression.
808///
809/// The `CEIL/FLOOR(<datetime value expression> TO <time unit>)` is an Amazon Kinesis Data Analytics extension.
810/// See <https://docs.aws.amazon.com/kinesisanalytics/latest/sqlref/sql-reference-ceil.html> for
811/// details.
812///
813/// Other dialects either support `CEIL/FLOOR( <expr> [, <scale>])` format or just
814/// `CEIL/FLOOR(<expr>)`.
815#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
816#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
817#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
818pub enum CeilFloorKind {
819    /// `CEIL( <expr> TO <DateTimeField>)`
820    DateTimeField(DateTimeField),
821    /// `CEIL( <expr> [, <scale>])`
822    Scale(ValueWithSpan),
823}
824
825/// A WHEN clause in a CASE expression containing both
826/// the condition and its corresponding result
827#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
828#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
829#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
830pub struct CaseWhen {
831    /// The `WHEN` condition expression.
832    pub condition: Expr,
833    /// The expression returned when `condition` matches.
834    pub result: Expr,
835}
836
837impl fmt::Display for CaseWhen {
838    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
839        f.write_str("WHEN ")?;
840        self.condition.fmt(f)?;
841        f.write_str(" THEN")?;
842        SpaceOrNewline.fmt(f)?;
843        Indent(&self.result).fmt(f)?;
844        Ok(())
845    }
846}
847
848/// An SQL expression of any type.
849///
850/// # Semantics / Type Checking
851///
852/// The parser does not distinguish between expressions of different types
853/// (e.g. boolean vs string). The caller is responsible for detecting and
854/// validating types as necessary (for example  `WHERE 1` vs `SELECT 1=1`)
855/// See the [README.md] for more details.
856///
857/// [README.md]: https://github.com/apache/datafusion-sqlparser-rs/blob/main/README.md#syntax-vs-semantics
858///
859/// # Equality and Hashing Does not Include Source Locations
860///
861/// The `Expr` type implements `PartialEq` and `Eq` based on the semantic value
862/// of the expression (not bitwise comparison). This means that `Expr` instances
863/// that are semantically equivalent but have different spans (locations in the
864/// source tree) will compare as equal.
865#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
866#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
867#[cfg_attr(
868    feature = "visitor",
869    derive(Visit, VisitMut),
870    visit(with = "visit_expr")
871)]
872pub enum Expr {
873    /// Identifier e.g. table name or column name
874    Identifier(Ident),
875    /// Multi-part identifier, e.g. `table_alias.column` or `schema.table.col`
876    CompoundIdentifier(Vec<Ident>),
877    /// Multi-part expression access.
878    ///
879    /// This structure represents an access chain in structured / nested types
880    /// such as maps, arrays, and lists:
881    /// - Array
882    ///     - A 1-dim array `a[1]` will be represented like:
883    ///       `CompoundFieldAccess(Ident('a'), vec![Subscript(1)]`
884    ///     - A 2-dim array `a[1][2]` will be represented like:
885    ///       `CompoundFieldAccess(Ident('a'), vec![Subscript(1), Subscript(2)]`
886    /// - Map or Struct (Bracket-style)
887    ///     - A map `a['field1']` will be represented like:
888    ///       `CompoundFieldAccess(Ident('a'), vec![Subscript('field')]`
889    ///     - A 2-dim map `a['field1']['field2']` will be represented like:
890    ///       `CompoundFieldAccess(Ident('a'), vec![Subscript('field1'), Subscript('field2')]`
891    /// - Struct (Dot-style) (only effect when the chain contains both subscript and expr)
892    ///     - A struct access `a[field1].field2` will be represented like:
893    ///       `CompoundFieldAccess(Ident('a'), vec![Subscript('field1'), Ident('field2')]`
894    /// - If a struct access likes `a.field1.field2`, it will be represented by CompoundIdentifier([a, field1, field2])
895    CompoundFieldAccess {
896        /// The base expression being accessed.
897        root: Box<Expr>,
898        /// Sequence of access operations (subscript or identifier accesses).
899        access_chain: Vec<AccessExpr>,
900    },
901    /// Access data nested in a value containing semi-structured data, such as
902    /// the `VARIANT` type on Snowflake. for example `src:customer[0].name`.
903    ///
904    /// See <https://docs.snowflake.com/en/user-guide/querying-semistructured>.
905    /// See <https://docs.databricks.com/en/sql/language-manual/functions/colonsign.html>.
906    JsonAccess {
907        /// The value being queried.
908        value: Box<Expr>,
909        /// The path to the data to extract.
910        path: JsonPath,
911    },
912    /// `IS FALSE` operator
913    IsFalse(Box<Expr>),
914    /// `IS NOT FALSE` operator
915    IsNotFalse(Box<Expr>),
916    /// `IS TRUE` operator
917    IsTrue(Box<Expr>),
918    /// `IS NOT TRUE` operator
919    IsNotTrue(Box<Expr>),
920    /// `IS NULL` operator
921    IsNull(Box<Expr>),
922    /// `IS NOT NULL` operator
923    IsNotNull(Box<Expr>),
924    /// `IS UNKNOWN` operator
925    IsUnknown(Box<Expr>),
926    /// `IS NOT UNKNOWN` operator
927    IsNotUnknown(Box<Expr>),
928    /// `IS DISTINCT FROM` operator
929    IsDistinctFrom(Box<Expr>, Box<Expr>),
930    /// `IS NOT DISTINCT FROM` operator
931    IsNotDistinctFrom(Box<Expr>, Box<Expr>),
932    /// `<expr> IS [ NOT ] [ form ] NORMALIZED`
933    IsNormalized {
934        /// Expression being tested.
935        expr: Box<Expr>,
936        /// Optional normalization `form` (e.g., NFC, NFD).
937        form: Option<NormalizationForm>,
938        /// `true` when `NOT` is present.
939        negated: bool,
940    },
941    /// `[ NOT ] IN (val1, val2, ...)`
942    InList {
943        /// Left-hand expression to test for membership.
944        expr: Box<Expr>,
945        /// Literal list of expressions to check against.
946        list: Vec<Expr>,
947        /// `true` when the `NOT` modifier is present.
948        negated: bool,
949    },
950    /// `[ NOT ] IN (SELECT ...)`
951    InSubquery {
952        /// Left-hand expression to test for membership.
953        expr: Box<Expr>,
954        /// The subquery providing the candidate values.
955        subquery: Box<Query>,
956        /// `true` when the `NOT` modifier is present.
957        negated: bool,
958    },
959    /// `[ NOT ] IN UNNEST(array_expression)`
960    InUnnest {
961        /// Left-hand expression to test for membership.
962        expr: Box<Expr>,
963        /// Array expression being unnested.
964        array_expr: Box<Expr>,
965        /// `true` when the `NOT` modifier is present.
966        negated: bool,
967    },
968    /// `<expr> [ NOT ] BETWEEN <low> AND <high>`
969    Between {
970        /// Expression being compared.
971        expr: Box<Expr>,
972        /// `true` when the `NOT` modifier is present.
973        negated: bool,
974        /// Lower bound.
975        low: Box<Expr>,
976        /// Upper bound.
977        high: Box<Expr>,
978    },
979    /// Binary operation e.g. `1 + 1` or `foo > bar`
980    BinaryOp {
981        /// Left operand.
982        left: Box<Expr>,
983        /// Operator between operands.
984        op: BinaryOperator,
985        /// Right operand.
986        right: Box<Expr>,
987    },
988    /// `[NOT] LIKE <pattern> [ESCAPE <escape_character>]`
989    Like {
990        /// `true` when `NOT` is present.
991        negated: bool,
992        /// Snowflake supports the ANY keyword to match against a list of patterns
993        /// <https://docs.snowflake.com/en/sql-reference/functions/like_any>
994        any: bool,
995        /// Expression to match.
996        expr: Box<Expr>,
997        /// Pattern expression.
998        pattern: Box<Expr>,
999        /// Optional escape character.
1000        escape_char: Option<ValueWithSpan>,
1001    },
1002    /// `ILIKE` (case-insensitive `LIKE`)
1003    ILike {
1004        /// `true` when `NOT` is present.
1005        negated: bool,
1006        /// Snowflake supports the ANY keyword to match against a list of patterns
1007        /// <https://docs.snowflake.com/en/sql-reference/functions/like_any>
1008        any: bool,
1009        /// Expression to match.
1010        expr: Box<Expr>,
1011        /// Pattern expression.
1012        pattern: Box<Expr>,
1013        /// Optional escape character.
1014        escape_char: Option<ValueWithSpan>,
1015    },
1016    /// `SIMILAR TO` regex
1017    SimilarTo {
1018        /// `true` when `NOT` is present.
1019        negated: bool,
1020        /// Expression to test.
1021        expr: Box<Expr>,
1022        /// Pattern expression.
1023        pattern: Box<Expr>,
1024        /// Optional escape character.
1025        escape_char: Option<ValueWithSpan>,
1026    },
1027    /// MySQL: `RLIKE` regex or `REGEXP` regex
1028    RLike {
1029        /// `true` when `NOT` is present.
1030        negated: bool,
1031        /// Expression to test.
1032        expr: Box<Expr>,
1033        /// Pattern expression.
1034        pattern: Box<Expr>,
1035        /// true for REGEXP, false for RLIKE (no difference in semantics)
1036        regexp: bool,
1037    },
1038    /// `ANY` operation e.g. `foo > ANY(bar)`, comparison operator is one of `[=, >, <, =>, =<, !=]`
1039    /// <https://docs.snowflake.com/en/sql-reference/operators-subquery#all-any>
1040    AnyOp {
1041        /// Left operand.
1042        left: Box<Expr>,
1043        /// Comparison operator.
1044        compare_op: BinaryOperator,
1045        /// Right-hand subquery expression.
1046        right: Box<Expr>,
1047        /// ANY and SOME are synonymous: <https://docs.cloudera.com/cdw-runtime/cloud/using-hiveql/topics/hive_comparison_predicates.html>
1048        is_some: bool,
1049    },
1050    /// `ALL` operation e.g. `foo > ALL(bar)`, comparison operator is one of `[=, >, <, =>, =<, !=]`
1051    /// <https://docs.snowflake.com/en/sql-reference/operators-subquery#all-any>
1052    AllOp {
1053        /// Left operand.
1054        left: Box<Expr>,
1055        /// Comparison operator.
1056        compare_op: BinaryOperator,
1057        /// Right-hand subquery expression.
1058        right: Box<Expr>,
1059    },
1060
1061    /// Unary operation e.g. `NOT foo`
1062    UnaryOp {
1063        /// The unary operator (e.g., `NOT`, `-`).
1064        op: UnaryOperator,
1065        /// Operand expression.
1066        expr: Box<Expr>,
1067    },
1068    /// CONVERT a value to a different data type or character encoding. e.g. `CONVERT(foo USING utf8mb4)`
1069    Convert {
1070        /// CONVERT (false) or TRY_CONVERT (true)
1071        /// <https://learn.microsoft.com/en-us/sql/t-sql/functions/try-convert-transact-sql?view=sql-server-ver16>
1072        is_try: bool,
1073        /// The expression to convert.
1074        expr: Box<Expr>,
1075        /// The target data type, if provided.
1076        data_type: Option<DataType>,
1077        /// Optional target character encoding (e.g., `utf8mb4`).
1078        charset: Option<ObjectName>,
1079        /// `true` when target precedes the value (MSSQL syntax).
1080        target_before_value: bool,
1081        /// How to translate the expression.
1082        ///
1083        /// [MSSQL]: https://learn.microsoft.com/en-us/sql/t-sql/functions/cast-and-convert-transact-sql?view=sql-server-ver16#style
1084        styles: Vec<Expr>,
1085    },
1086    /// `CAST` an expression to a different data type e.g. `CAST(foo AS VARCHAR(123))`
1087    Cast {
1088        /// The cast kind (e.g., `CAST`, `TRY_CAST`).
1089        kind: CastKind,
1090        /// Expression being cast.
1091        expr: Box<Expr>,
1092        /// Target data type.
1093        data_type: DataType,
1094        /// [MySQL] allows CAST(... AS type ARRAY) in functional index definitions for InnoDB
1095        /// multi-valued indices. It's not really a datatype, and is only allowed in `CAST` in key
1096        /// specifications, so it's a flag here.
1097        ///
1098        /// [MySQL]: https://dev.mysql.com/doc/refman/8.4/en/cast-functions.html#function_cast
1099        array: bool,
1100        /// Optional CAST(string_expression AS type FORMAT format_string_expression) as used by [BigQuery]
1101        ///
1102        /// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/format-elements#formatting_syntax
1103        format: Option<CastFormat>,
1104    },
1105    /// AT a timestamp to a different timezone e.g. `FROM_UNIXTIME(0) AT TIME ZONE 'UTC-06:00'`
1106    AtTimeZone {
1107        /// Timestamp expression to shift.
1108        timestamp: Box<Expr>,
1109        /// Time zone expression to apply.
1110        time_zone: Box<Expr>,
1111    },
1112    /// Extract a field from a timestamp e.g. `EXTRACT(MONTH FROM foo)`
1113    /// Or `EXTRACT(MONTH, foo)`
1114    ///
1115    /// Syntax:
1116    /// ```sql
1117    /// EXTRACT(DateTimeField FROM <expr>) | EXTRACT(DateTimeField, <expr>)
1118    /// ```
1119    Extract {
1120        /// Which datetime field is being extracted.
1121        field: DateTimeField,
1122        /// Syntax variant used (`From` or `Comma`).
1123        syntax: ExtractSyntax,
1124        /// Expression to extract from.
1125        expr: Box<Expr>,
1126    },
1127    /// ```sql
1128    /// CEIL(<expr> [TO DateTimeField])
1129    /// ```
1130    /// ```sql
1131    /// CEIL( <input_expr> [, <scale_expr> ] )
1132    /// ```
1133    Ceil {
1134        /// Expression to ceil.
1135        expr: Box<Expr>,
1136        /// The CEIL/FLOOR kind (datetime field or scale).
1137        field: CeilFloorKind,
1138    },
1139    /// ```sql
1140    /// FLOOR(<expr> [TO DateTimeField])
1141    /// ```
1142    /// ```sql
1143    /// FLOOR( <input_expr> [, <scale_expr> ] )
1144    ///
1145    Floor {
1146        /// Expression to floor.
1147        expr: Box<Expr>,
1148        /// The CEIL/FLOOR kind (datetime field or scale).
1149        field: CeilFloorKind,
1150    },
1151    /// ```sql
1152    /// POSITION(<expr> in <expr>)
1153    /// ```
1154    Position {
1155        /// Expression to search for.
1156        expr: Box<Expr>,
1157        /// Expression to search in.
1158        r#in: Box<Expr>,
1159    },
1160    /// ```sql
1161    /// SUBSTRING(<expr> [FROM <expr>] [FOR <expr>])
1162    /// ```
1163    /// or
1164    /// ```sql
1165    /// SUBSTRING(<expr>, <expr>, <expr>)
1166    /// ```
1167    Substring {
1168        /// Source expression.
1169        expr: Box<Expr>,
1170        /// Optional `FROM` expression.
1171        substring_from: Option<Box<Expr>>,
1172        /// Optional `FOR` expression.
1173        substring_for: Option<Box<Expr>>,
1174
1175        /// false if the expression is represented using the `SUBSTRING(expr [FROM start] [FOR len])` syntax
1176        /// true if the expression is represented using the `SUBSTRING(expr, start, len)` syntax
1177        /// This flag is used for formatting.
1178        special: bool,
1179
1180        /// true if the expression is represented using the `SUBSTR` shorthand
1181        /// This flag is used for formatting.
1182        shorthand: bool,
1183    },
1184    /// ```sql
1185    /// TRIM([BOTH | LEADING | TRAILING] [<expr> FROM] <expr>)
1186    /// TRIM(<expr>)
1187    /// TRIM(<expr>, [, characters]) -- PostgreSQL, DuckDB, Snowflake, BigQuery, Generic
1188    /// ```
1189    Trim {
1190        /// Which side to trim: `BOTH`, `LEADING`, or `TRAILING`.
1191        trim_where: Option<TrimWhereField>,
1192        /// Optional expression specifying what to trim from the value `expr`.
1193        trim_what: Option<Box<Expr>>,
1194        /// The expression to trim from.
1195        expr: Box<Expr>,
1196        /// Optional list of characters to trim (dialect-specific).
1197        trim_characters: Option<Vec<Expr>>,
1198    },
1199    /// ```sql
1200    /// OVERLAY(<expr> PLACING <expr> FROM <expr>[ FOR <expr> ]
1201    /// ```
1202    Overlay {
1203        /// The target expression being overlayed.
1204        expr: Box<Expr>,
1205        /// The expression to place into the target.
1206        overlay_what: Box<Expr>,
1207        /// The `FROM` position expression indicating where to start overlay.
1208        overlay_from: Box<Expr>,
1209        /// Optional `FOR` length expression limiting the overlay span.
1210        overlay_for: Option<Box<Expr>>,
1211    },
1212    /// `expr COLLATE collation`
1213    Collate {
1214        /// The expression being collated.
1215        expr: Box<Expr>,
1216        /// The collation name to apply to the expression.
1217        collation: ObjectName,
1218    },
1219    /// Nested expression e.g. `(foo > bar)` or `(1)`
1220    Nested(Box<Expr>),
1221    /// A literal value, such as string, number, date or NULL
1222    Value(ValueWithSpan),
1223    /// Prefixed expression, e.g. introducer strings, projection prefix
1224    /// <https://dev.mysql.com/doc/refman/8.0/en/charset-introducer.html>
1225    /// <https://docs.snowflake.com/en/sql-reference/constructs/connect-by>
1226    Prefixed {
1227        /// The prefix identifier (introducer or projection prefix).
1228        prefix: Ident,
1229        /// The value expression being prefixed.
1230        /// Hint: you can unwrap the string value using `value.into_string()`.
1231        value: Box<Expr>,
1232    },
1233    /// A constant of form `<data_type> 'value'`.
1234    /// This can represent ANSI SQL `DATE`, `TIME`, and `TIMESTAMP` literals (such as `DATE '2020-01-01'`),
1235    /// as well as constants of other types (a non-standard PostgreSQL extension).
1236    TypedString(TypedString),
1237    /// Scalar function call e.g. `LEFT(foo, 5)`
1238    Function(Function),
1239    /// `CASE [<operand>] WHEN <condition> THEN <result> ... [ELSE <result>] END`
1240    ///
1241    /// Note we only recognize a complete single expression as `<condition>`,
1242    /// not `< 0` nor `1, 2, 3` as allowed in a `<simple when clause>` per
1243    /// <https://jakewheat.github.io/sql-overview/sql-2011-foundation-grammar.html#simple-when-clause>
1244    Case {
1245        /// The attached `CASE` token (keeps original spacing/comments).
1246        case_token: AttachedToken,
1247        /// The attached `END` token (keeps original spacing/comments).
1248        end_token: AttachedToken,
1249        /// Optional operand expression after `CASE` (for simple CASE).
1250        operand: Option<Box<Expr>>,
1251        /// The `WHEN ... THEN` conditions and results.
1252        conditions: Vec<CaseWhen>,
1253        /// Optional `ELSE` result expression.
1254        else_result: Option<Box<Expr>>,
1255    },
1256    /// An exists expression `[ NOT ] EXISTS(SELECT ...)`, used in expressions like
1257    /// `WHERE [ NOT ] EXISTS (SELECT ...)`.
1258    Exists {
1259        /// The subquery checked by `EXISTS`.
1260        subquery: Box<Query>,
1261        /// Whether the `EXISTS` is negated (`NOT EXISTS`).
1262        negated: bool,
1263    },
1264    /// A parenthesized subquery `(SELECT ...)`, used in expression like
1265    /// `SELECT (subquery) AS x` or `WHERE (subquery) = x`
1266    Subquery(Box<Query>),
1267    /// The `GROUPING SETS` expr.
1268    GroupingSets(Vec<Vec<Expr>>),
1269    /// The `CUBE` expr.
1270    Cube(Vec<Vec<Expr>>),
1271    /// The `ROLLUP` expr.
1272    Rollup(Vec<Vec<Expr>>),
1273    /// ROW / TUPLE a single value, such as `SELECT (1, 2)`
1274    Tuple(Vec<Expr>),
1275    /// `Struct` literal expression
1276    /// Syntax:
1277    /// ```sql
1278    /// STRUCT<[field_name] field_type, ...>( expr1 [, ... ])
1279    ///
1280    /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-types#struct_type)
1281    /// [Databricks](https://docs.databricks.com/en/sql/language-manual/functions/struct.html)
1282    /// ```
1283    Struct {
1284        /// Struct values.
1285        values: Vec<Expr>,
1286        /// Struct field definitions.
1287        fields: Vec<StructField>,
1288    },
1289    /// `BigQuery` specific: An named expression in a typeless struct [1]
1290    ///
1291    /// Syntax
1292    /// ```sql
1293    /// 1 AS A
1294    /// ```
1295    /// [1]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-types#struct_type
1296    Named {
1297        /// The expression being named.
1298        expr: Box<Expr>,
1299        /// The assigned identifier name for the expression.
1300        name: Ident,
1301    },
1302    /// `DuckDB` specific `Struct` literal expression [1]
1303    ///
1304    /// Syntax:
1305    /// ```sql
1306    /// syntax: {'field_name': expr1[, ... ]}
1307    /// ```
1308    /// [1]: https://duckdb.org/docs/sql/data_types/struct#creating-structs
1309    Dictionary(Vec<DictionaryField>),
1310    /// `DuckDB` specific `Map` literal expression [1]
1311    ///
1312    /// Syntax:
1313    /// ```sql
1314    /// syntax: Map {key1: value1[, ... ]}
1315    /// ```
1316    /// [1]: https://duckdb.org/docs/sql/data_types/map#creating-maps
1317    Map(Map),
1318    /// An array expression e.g. `ARRAY[1, 2]`
1319    Array(Array),
1320    /// An interval expression e.g. `INTERVAL '1' YEAR`
1321    Interval(Interval),
1322    /// `MySQL` specific text search function [(1)].
1323    ///
1324    /// Syntax:
1325    /// ```sql
1326    /// MATCH (<col>, <col>, ...) AGAINST (<expr> [<search modifier>])
1327    ///
1328    /// <col> = CompoundIdentifier
1329    /// <expr> = String literal
1330    /// ```
1331    /// [(1)]: https://dev.mysql.com/doc/refman/8.0/en/fulltext-search.html#function_match
1332    MatchAgainst {
1333        /// `(<col>, <col>, ...)`.
1334        columns: Vec<ObjectName>,
1335        /// `<expr>`.
1336        match_value: ValueWithSpan,
1337        /// `<search modifier>`
1338        opt_search_modifier: Option<SearchModifier>,
1339    },
1340    /// An unqualified `*` wildcard token (e.g. `*`).
1341    Wildcard(AttachedToken),
1342    /// Qualified wildcard, e.g. `alias.*` or `schema.table.*`.
1343    /// (Same caveats apply to `QualifiedWildcard` as to `Wildcard`.)
1344    QualifiedWildcard(ObjectName, AttachedToken),
1345    /// Some dialects support an older syntax for outer joins where columns are
1346    /// marked with the `(+)` operator in the WHERE clause, for example:
1347    ///
1348    /// ```sql
1349    /// SELECT t1.c1, t2.c2 FROM t1, t2 WHERE t1.c1 = t2.c2 (+)
1350    /// ```
1351    ///
1352    /// which is equivalent to
1353    ///
1354    /// ```sql
1355    /// SELECT t1.c1, t2.c2 FROM t1 LEFT OUTER JOIN t2 ON t1.c1 = t2.c2
1356    /// ```
1357    ///
1358    /// See <https://docs.snowflake.com/en/sql-reference/constructs/where#joins-in-the-where-clause>.
1359    OuterJoin(Box<Expr>),
1360    /// A reference to the prior level in a CONNECT BY clause.
1361    Prior(Box<Expr>),
1362    /// A lambda function.
1363    ///
1364    /// Syntax:
1365    /// ```plaintext
1366    /// param -> expr | (param1, ...) -> expr
1367    /// ```
1368    ///
1369    /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/functions#higher-order-functions---operator-and-lambdaparams-expr-function)
1370    /// [Databricks](https://docs.databricks.com/en/sql/language-manual/sql-ref-lambda-functions.html)
1371    /// [DuckDB](https://duckdb.org/docs/stable/sql/functions/lambda)
1372    Lambda(LambdaFunction),
1373    /// Checks membership of a value in a JSON array
1374    MemberOf(MemberOf),
1375}
1376
1377impl Expr {
1378    /// Creates a new [`Expr::Value`]
1379    pub fn value(value: impl Into<ValueWithSpan>) -> Self {
1380        Expr::Value(value.into())
1381    }
1382}
1383
1384/// The contents inside the `[` and `]` in a subscript expression.
1385#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1386#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1387#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1388pub enum Subscript {
1389    /// Accesses the element of the array at the given index.
1390    Index {
1391        /// The index expression used to access the array element.
1392        index: Expr,
1393    },
1394
1395    /// Accesses a slice of an array on PostgreSQL, e.g.
1396    ///
1397    /// ```plaintext
1398    /// => select (array[1,2,3,4,5,6])[2:5];
1399    /// -----------
1400    /// {2,3,4,5}
1401    /// ```
1402    ///
1403    /// The lower and/or upper bound can be omitted to slice from the start or
1404    /// end of the array respectively.
1405    ///
1406    /// See <https://www.postgresql.org/docs/current/arrays.html#ARRAYS-ACCESSING>.
1407    ///
1408    /// Also supports an optional "stride" as the last element (this is not
1409    /// supported by postgres), e.g.
1410    ///
1411    /// ```plaintext
1412    /// => select (array[1,2,3,4,5,6])[1:6:2];
1413    /// -----------
1414    /// {1,3,5}
1415    /// ```
1416    Slice {
1417        /// Optional lower bound for the slice (inclusive).
1418        lower_bound: Option<Expr>,
1419        /// Optional upper bound for the slice (inclusive).
1420        upper_bound: Option<Expr>,
1421        /// Optional stride for the slice (step size).
1422        stride: Option<Expr>,
1423    },
1424}
1425
1426impl fmt::Display for Subscript {
1427    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1428        match self {
1429            Subscript::Index { index } => write!(f, "{index}"),
1430            Subscript::Slice {
1431                lower_bound,
1432                upper_bound,
1433                stride,
1434            } => {
1435                if let Some(lower) = lower_bound {
1436                    write!(f, "{lower}")?;
1437                }
1438                write!(f, ":")?;
1439                if let Some(upper) = upper_bound {
1440                    write!(f, "{upper}")?;
1441                }
1442                if let Some(stride) = stride {
1443                    write!(f, ":")?;
1444                    write!(f, "{stride}")?;
1445                }
1446                Ok(())
1447            }
1448        }
1449    }
1450}
1451
1452/// An element of a [`Expr::CompoundFieldAccess`].
1453/// It can be an expression or a subscript.
1454#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1455#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1456#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1457pub enum AccessExpr {
1458    /// Accesses a field using dot notation, e.g. `foo.bar.baz`.
1459    Dot(Expr),
1460    /// Accesses a field or array element using bracket notation, e.g. `foo['bar']`.
1461    Subscript(Subscript),
1462}
1463
1464impl fmt::Display for AccessExpr {
1465    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1466        match self {
1467            AccessExpr::Dot(expr) => write!(f, ".{expr}"),
1468            AccessExpr::Subscript(subscript) => write!(f, "[{subscript}]"),
1469        }
1470    }
1471}
1472
1473/// A lambda function.
1474#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1475#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1476#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1477pub struct LambdaFunction {
1478    /// The parameters to the lambda function.
1479    pub params: OneOrManyWithParens<LambdaFunctionParameter>,
1480    /// The body of the lambda function.
1481    pub body: Box<Expr>,
1482    /// The syntax style used to write the lambda function.
1483    pub syntax: LambdaSyntax,
1484}
1485
1486impl fmt::Display for LambdaFunction {
1487    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1488        match self.syntax {
1489            LambdaSyntax::Arrow => write!(f, "{} -> {}", self.params, self.body),
1490            LambdaSyntax::LambdaKeyword => {
1491                // For lambda keyword syntax, display params without parentheses
1492                // e.g., `lambda x, y : expr` not `lambda (x, y) : expr`
1493                write!(f, "lambda ")?;
1494                match &self.params {
1495                    OneOrManyWithParens::One(p) => write!(f, "{p}")?,
1496                    OneOrManyWithParens::Many(ps) => write!(f, "{}", display_comma_separated(ps))?,
1497                };
1498                write!(f, " : {}", self.body)
1499            }
1500        }
1501    }
1502}
1503
1504/// A parameter to a lambda function, optionally with a data type.
1505#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1506#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1507#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1508pub struct LambdaFunctionParameter {
1509    /// The name of the parameter
1510    pub name: Ident,
1511    /// The optional data type of the parameter
1512    /// [Snowflake Syntax](https://docs.snowflake.com/en/sql-reference/functions/filter#arguments)
1513    pub data_type: Option<DataType>,
1514}
1515
1516impl fmt::Display for LambdaFunctionParameter {
1517    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1518        match &self.data_type {
1519            Some(dt) => write!(f, "{} {}", self.name, dt),
1520            None => write!(f, "{}", self.name),
1521        }
1522    }
1523}
1524
1525/// The syntax style for a lambda function.
1526#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Copy)]
1527#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1528#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1529pub enum LambdaSyntax {
1530    /// Arrow syntax: `param -> expr` or `(param1, param2) -> expr`
1531    ///
1532    /// <https://docs.databricks.com/aws/en/sql/language-manual/sql-ref-lambda-functions>
1533    ///
1534    /// Supported, but deprecated in DuckDB:
1535    /// <https://duckdb.org/docs/stable/sql/functions/lambda>
1536    Arrow,
1537    /// Lambda keyword syntax: `lambda param : expr` or `lambda param1, param2 : expr`
1538    ///
1539    /// Recommended in DuckDB:
1540    /// <https://duckdb.org/docs/stable/sql/functions/lambda>
1541    LambdaKeyword,
1542}
1543
1544/// Encapsulates the common pattern in SQL where either one unparenthesized item
1545/// such as an identifier or expression is permitted, or multiple of the same
1546/// item in a parenthesized list. For accessing items regardless of the form,
1547/// `OneOrManyWithParens` implements `Deref<Target = [T]>` and `IntoIterator`,
1548/// so you can call slice methods on it and iterate over items
1549/// # Examples
1550/// Accessing as a slice:
1551/// ```
1552/// # use sqlparser::ast::OneOrManyWithParens;
1553/// let one = OneOrManyWithParens::One("a");
1554///
1555/// assert_eq!(one[0], "a");
1556/// assert_eq!(one.len(), 1);
1557/// ```
1558/// Iterating:
1559/// ```
1560/// # use sqlparser::ast::OneOrManyWithParens;
1561/// let one = OneOrManyWithParens::One("a");
1562/// let many = OneOrManyWithParens::Many(vec!["a", "b"]);
1563///
1564/// assert_eq!(one.into_iter().chain(many).collect::<Vec<_>>(), vec!["a", "a", "b"] );
1565/// ```
1566#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1567#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1568#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1569pub enum OneOrManyWithParens<T> {
1570    /// A single `T`, unparenthesized.
1571    One(T),
1572    /// One or more `T`s, parenthesized.
1573    Many(Vec<T>),
1574}
1575
1576impl<T> Deref for OneOrManyWithParens<T> {
1577    type Target = [T];
1578
1579    fn deref(&self) -> &[T] {
1580        match self {
1581            OneOrManyWithParens::One(one) => core::slice::from_ref(one),
1582            OneOrManyWithParens::Many(many) => many,
1583        }
1584    }
1585}
1586
1587impl<T> AsRef<[T]> for OneOrManyWithParens<T> {
1588    fn as_ref(&self) -> &[T] {
1589        self
1590    }
1591}
1592
1593impl<'a, T> IntoIterator for &'a OneOrManyWithParens<T> {
1594    type Item = &'a T;
1595    type IntoIter = core::slice::Iter<'a, T>;
1596
1597    fn into_iter(self) -> Self::IntoIter {
1598        self.iter()
1599    }
1600}
1601
1602/// Owned iterator implementation of `OneOrManyWithParens`
1603#[derive(Debug, Clone)]
1604pub struct OneOrManyWithParensIntoIter<T> {
1605    inner: OneOrManyWithParensIntoIterInner<T>,
1606}
1607
1608#[derive(Debug, Clone)]
1609enum OneOrManyWithParensIntoIterInner<T> {
1610    One(core::iter::Once<T>),
1611    Many(<Vec<T> as IntoIterator>::IntoIter),
1612}
1613
1614impl<T> core::iter::FusedIterator for OneOrManyWithParensIntoIter<T>
1615where
1616    core::iter::Once<T>: core::iter::FusedIterator,
1617    <Vec<T> as IntoIterator>::IntoIter: core::iter::FusedIterator,
1618{
1619}
1620
1621impl<T> core::iter::ExactSizeIterator for OneOrManyWithParensIntoIter<T>
1622where
1623    core::iter::Once<T>: core::iter::ExactSizeIterator,
1624    <Vec<T> as IntoIterator>::IntoIter: core::iter::ExactSizeIterator,
1625{
1626}
1627
1628impl<T> core::iter::Iterator for OneOrManyWithParensIntoIter<T> {
1629    type Item = T;
1630
1631    fn next(&mut self) -> Option<Self::Item> {
1632        match &mut self.inner {
1633            OneOrManyWithParensIntoIterInner::One(one) => one.next(),
1634            OneOrManyWithParensIntoIterInner::Many(many) => many.next(),
1635        }
1636    }
1637
1638    fn size_hint(&self) -> (usize, Option<usize>) {
1639        match &self.inner {
1640            OneOrManyWithParensIntoIterInner::One(one) => one.size_hint(),
1641            OneOrManyWithParensIntoIterInner::Many(many) => many.size_hint(),
1642        }
1643    }
1644
1645    fn count(self) -> usize
1646    where
1647        Self: Sized,
1648    {
1649        match self.inner {
1650            OneOrManyWithParensIntoIterInner::One(one) => one.count(),
1651            OneOrManyWithParensIntoIterInner::Many(many) => many.count(),
1652        }
1653    }
1654
1655    fn fold<B, F>(mut self, init: B, f: F) -> B
1656    where
1657        Self: Sized,
1658        F: FnMut(B, Self::Item) -> B,
1659    {
1660        match &mut self.inner {
1661            OneOrManyWithParensIntoIterInner::One(one) => one.fold(init, f),
1662            OneOrManyWithParensIntoIterInner::Many(many) => many.fold(init, f),
1663        }
1664    }
1665}
1666
1667impl<T> core::iter::DoubleEndedIterator for OneOrManyWithParensIntoIter<T> {
1668    fn next_back(&mut self) -> Option<Self::Item> {
1669        match &mut self.inner {
1670            OneOrManyWithParensIntoIterInner::One(one) => one.next_back(),
1671            OneOrManyWithParensIntoIterInner::Many(many) => many.next_back(),
1672        }
1673    }
1674}
1675
1676impl<T> IntoIterator for OneOrManyWithParens<T> {
1677    type Item = T;
1678
1679    type IntoIter = OneOrManyWithParensIntoIter<T>;
1680
1681    fn into_iter(self) -> Self::IntoIter {
1682        let inner = match self {
1683            OneOrManyWithParens::One(one) => {
1684                OneOrManyWithParensIntoIterInner::One(core::iter::once(one))
1685            }
1686            OneOrManyWithParens::Many(many) => {
1687                OneOrManyWithParensIntoIterInner::Many(many.into_iter())
1688            }
1689        };
1690
1691        OneOrManyWithParensIntoIter { inner }
1692    }
1693}
1694
1695impl<T> fmt::Display for OneOrManyWithParens<T>
1696where
1697    T: fmt::Display,
1698{
1699    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1700        match self {
1701            OneOrManyWithParens::One(value) => write!(f, "{value}"),
1702            OneOrManyWithParens::Many(values) => {
1703                write!(f, "({})", display_comma_separated(values))
1704            }
1705        }
1706    }
1707}
1708
1709impl fmt::Display for CastFormat {
1710    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1711        match self {
1712            CastFormat::Value(v) => write!(f, "{v}"),
1713            CastFormat::ValueAtTimeZone(v, tz) => write!(f, "{v} AT TIME ZONE {tz}"),
1714        }
1715    }
1716}
1717
1718impl fmt::Display for Expr {
1719    #[cfg_attr(feature = "recursive-protection", recursive::recursive)]
1720    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1721        match self {
1722            Expr::Identifier(s) => write!(f, "{s}"),
1723            Expr::Wildcard(_) => f.write_str("*"),
1724            Expr::QualifiedWildcard(prefix, _) => write!(f, "{prefix}.*"),
1725            Expr::CompoundIdentifier(s) => write!(f, "{}", display_separated(s, ".")),
1726            Expr::CompoundFieldAccess { root, access_chain } => {
1727                write!(f, "{root}")?;
1728                for field in access_chain {
1729                    write!(f, "{field}")?;
1730                }
1731                Ok(())
1732            }
1733            Expr::IsTrue(ast) => write!(f, "{ast} IS TRUE"),
1734            Expr::IsNotTrue(ast) => write!(f, "{ast} IS NOT TRUE"),
1735            Expr::IsFalse(ast) => write!(f, "{ast} IS FALSE"),
1736            Expr::IsNotFalse(ast) => write!(f, "{ast} IS NOT FALSE"),
1737            Expr::IsNull(ast) => write!(f, "{ast} IS NULL"),
1738            Expr::IsNotNull(ast) => write!(f, "{ast} IS NOT NULL"),
1739            Expr::IsUnknown(ast) => write!(f, "{ast} IS UNKNOWN"),
1740            Expr::IsNotUnknown(ast) => write!(f, "{ast} IS NOT UNKNOWN"),
1741            Expr::InList {
1742                expr,
1743                list,
1744                negated,
1745            } => write!(
1746                f,
1747                "{} {}IN ({})",
1748                expr,
1749                if *negated { "NOT " } else { "" },
1750                display_comma_separated(list)
1751            ),
1752            Expr::InSubquery {
1753                expr,
1754                subquery,
1755                negated,
1756            } => write!(
1757                f,
1758                "{} {}IN ({})",
1759                expr,
1760                if *negated { "NOT " } else { "" },
1761                subquery
1762            ),
1763            Expr::InUnnest {
1764                expr,
1765                array_expr,
1766                negated,
1767            } => write!(
1768                f,
1769                "{} {}IN UNNEST({})",
1770                expr,
1771                if *negated { "NOT " } else { "" },
1772                array_expr
1773            ),
1774            Expr::Between {
1775                expr,
1776                negated,
1777                low,
1778                high,
1779            } => write!(
1780                f,
1781                "{} {}BETWEEN {} AND {}",
1782                expr,
1783                if *negated { "NOT " } else { "" },
1784                low,
1785                high
1786            ),
1787            Expr::BinaryOp { left, op, right } => write!(f, "{left} {op} {right}"),
1788            Expr::Like {
1789                negated,
1790                expr,
1791                pattern,
1792                escape_char,
1793                any,
1794            } => match escape_char {
1795                Some(ch) => write!(
1796                    f,
1797                    "{} {}LIKE {}{} ESCAPE {}",
1798                    expr,
1799                    if *negated { "NOT " } else { "" },
1800                    if *any { "ANY " } else { "" },
1801                    pattern,
1802                    ch
1803                ),
1804                _ => write!(
1805                    f,
1806                    "{} {}LIKE {}{}",
1807                    expr,
1808                    if *negated { "NOT " } else { "" },
1809                    if *any { "ANY " } else { "" },
1810                    pattern
1811                ),
1812            },
1813            Expr::ILike {
1814                negated,
1815                expr,
1816                pattern,
1817                escape_char,
1818                any,
1819            } => match escape_char {
1820                Some(ch) => write!(
1821                    f,
1822                    "{} {}ILIKE {}{} ESCAPE {}",
1823                    expr,
1824                    if *negated { "NOT " } else { "" },
1825                    if *any { "ANY" } else { "" },
1826                    pattern,
1827                    ch
1828                ),
1829                _ => write!(
1830                    f,
1831                    "{} {}ILIKE {}{}",
1832                    expr,
1833                    if *negated { "NOT " } else { "" },
1834                    if *any { "ANY " } else { "" },
1835                    pattern
1836                ),
1837            },
1838            Expr::RLike {
1839                negated,
1840                expr,
1841                pattern,
1842                regexp,
1843            } => write!(
1844                f,
1845                "{} {}{} {}",
1846                expr,
1847                if *negated { "NOT " } else { "" },
1848                if *regexp { "REGEXP" } else { "RLIKE" },
1849                pattern
1850            ),
1851            Expr::IsNormalized {
1852                expr,
1853                form,
1854                negated,
1855            } => {
1856                let not_ = if *negated { "NOT " } else { "" };
1857                if let Some(form) = form {
1858                    write!(f, "{} IS {}{} NORMALIZED", expr, not_, form)
1859                } else {
1860                    write!(f, "{expr} IS {not_}NORMALIZED")
1861                }
1862            }
1863            Expr::SimilarTo {
1864                negated,
1865                expr,
1866                pattern,
1867                escape_char,
1868            } => match escape_char {
1869                Some(ch) => write!(
1870                    f,
1871                    "{} {}SIMILAR TO {} ESCAPE {}",
1872                    expr,
1873                    if *negated { "NOT " } else { "" },
1874                    pattern,
1875                    ch
1876                ),
1877                _ => write!(
1878                    f,
1879                    "{} {}SIMILAR TO {}",
1880                    expr,
1881                    if *negated { "NOT " } else { "" },
1882                    pattern
1883                ),
1884            },
1885            Expr::AnyOp {
1886                left,
1887                compare_op,
1888                right,
1889                is_some,
1890            } => {
1891                let add_parens = !matches!(right.as_ref(), Expr::Subquery(_));
1892                write!(
1893                    f,
1894                    "{left} {compare_op} {}{}{right}{}",
1895                    if *is_some { "SOME" } else { "ANY" },
1896                    if add_parens { "(" } else { "" },
1897                    if add_parens { ")" } else { "" },
1898                )
1899            }
1900            Expr::AllOp {
1901                left,
1902                compare_op,
1903                right,
1904            } => {
1905                let add_parens = !matches!(right.as_ref(), Expr::Subquery(_));
1906                write!(
1907                    f,
1908                    "{left} {compare_op} ALL{}{right}{}",
1909                    if add_parens { "(" } else { "" },
1910                    if add_parens { ")" } else { "" },
1911                )
1912            }
1913            Expr::UnaryOp { op, expr } => {
1914                if op == &UnaryOperator::PGPostfixFactorial {
1915                    write!(f, "{expr}{op}")
1916                } else if matches!(
1917                    op,
1918                    UnaryOperator::Not
1919                        | UnaryOperator::Hash
1920                        | UnaryOperator::AtDashAt
1921                        | UnaryOperator::DoubleAt
1922                        | UnaryOperator::QuestionDash
1923                        | UnaryOperator::QuestionPipe
1924                ) {
1925                    write!(f, "{op} {expr}")
1926                } else {
1927                    write!(f, "{op}{expr}")
1928                }
1929            }
1930            Expr::Convert {
1931                is_try,
1932                expr,
1933                target_before_value,
1934                data_type,
1935                charset,
1936                styles,
1937            } => {
1938                write!(f, "{}CONVERT(", if *is_try { "TRY_" } else { "" })?;
1939                if let Some(data_type) = data_type {
1940                    if let Some(charset) = charset {
1941                        write!(f, "{expr}, {data_type} CHARACTER SET {charset}")
1942                    } else if *target_before_value {
1943                        write!(f, "{data_type}, {expr}")
1944                    } else {
1945                        write!(f, "{expr}, {data_type}")
1946                    }
1947                } else if let Some(charset) = charset {
1948                    write!(f, "{expr} USING {charset}")
1949                } else {
1950                    write!(f, "{expr}") // This should never happen
1951                }?;
1952                if !styles.is_empty() {
1953                    write!(f, ", {}", display_comma_separated(styles))?;
1954                }
1955                write!(f, ")")
1956            }
1957            Expr::Cast {
1958                kind,
1959                expr,
1960                data_type,
1961                array,
1962                format,
1963            } => match kind {
1964                CastKind::Cast => {
1965                    write!(f, "CAST({expr} AS {data_type}")?;
1966                    if *array {
1967                        write!(f, " ARRAY")?;
1968                    }
1969                    if let Some(format) = format {
1970                        write!(f, " FORMAT {format}")?;
1971                    }
1972                    write!(f, ")")
1973                }
1974                CastKind::TryCast => {
1975                    if let Some(format) = format {
1976                        write!(f, "TRY_CAST({expr} AS {data_type} FORMAT {format})")
1977                    } else {
1978                        write!(f, "TRY_CAST({expr} AS {data_type})")
1979                    }
1980                }
1981                CastKind::SafeCast => {
1982                    if let Some(format) = format {
1983                        write!(f, "SAFE_CAST({expr} AS {data_type} FORMAT {format})")
1984                    } else {
1985                        write!(f, "SAFE_CAST({expr} AS {data_type})")
1986                    }
1987                }
1988                CastKind::DoubleColon => {
1989                    write!(f, "{expr}::{data_type}")
1990                }
1991            },
1992            Expr::Extract {
1993                field,
1994                syntax,
1995                expr,
1996            } => match syntax {
1997                ExtractSyntax::From => write!(f, "EXTRACT({field} FROM {expr})"),
1998                ExtractSyntax::Comma => write!(f, "EXTRACT({field}, {expr})"),
1999            },
2000            Expr::Ceil { expr, field } => match field {
2001                CeilFloorKind::DateTimeField(DateTimeField::NoDateTime) => {
2002                    write!(f, "CEIL({expr})")
2003                }
2004                CeilFloorKind::DateTimeField(dt_field) => write!(f, "CEIL({expr} TO {dt_field})"),
2005                CeilFloorKind::Scale(s) => write!(f, "CEIL({expr}, {s})"),
2006            },
2007            Expr::Floor { expr, field } => match field {
2008                CeilFloorKind::DateTimeField(DateTimeField::NoDateTime) => {
2009                    write!(f, "FLOOR({expr})")
2010                }
2011                CeilFloorKind::DateTimeField(dt_field) => write!(f, "FLOOR({expr} TO {dt_field})"),
2012                CeilFloorKind::Scale(s) => write!(f, "FLOOR({expr}, {s})"),
2013            },
2014            Expr::Position { expr, r#in } => write!(f, "POSITION({expr} IN {in})"),
2015            Expr::Collate { expr, collation } => write!(f, "{expr} COLLATE {collation}"),
2016            Expr::Nested(ast) => write!(f, "({ast})"),
2017            Expr::Value(v) => write!(f, "{v}"),
2018            Expr::Prefixed { prefix, value } => write!(f, "{prefix} {value}"),
2019            Expr::TypedString(ts) => ts.fmt(f),
2020            Expr::Function(fun) => fun.fmt(f),
2021            Expr::Case {
2022                case_token: _,
2023                end_token: _,
2024                operand,
2025                conditions,
2026                else_result,
2027            } => {
2028                f.write_str("CASE")?;
2029                if let Some(operand) = operand {
2030                    f.write_str(" ")?;
2031                    operand.fmt(f)?;
2032                }
2033                for when in conditions {
2034                    SpaceOrNewline.fmt(f)?;
2035                    Indent(when).fmt(f)?;
2036                }
2037                if let Some(else_result) = else_result {
2038                    SpaceOrNewline.fmt(f)?;
2039                    Indent("ELSE").fmt(f)?;
2040                    SpaceOrNewline.fmt(f)?;
2041                    Indent(Indent(else_result)).fmt(f)?;
2042                }
2043                SpaceOrNewline.fmt(f)?;
2044                f.write_str("END")
2045            }
2046            Expr::Exists { subquery, negated } => write!(
2047                f,
2048                "{}EXISTS ({})",
2049                if *negated { "NOT " } else { "" },
2050                subquery
2051            ),
2052            Expr::Subquery(s) => write!(f, "({s})"),
2053            Expr::GroupingSets(sets) => {
2054                write!(f, "GROUPING SETS (")?;
2055                let mut sep = "";
2056                for set in sets {
2057                    write!(f, "{sep}")?;
2058                    sep = ", ";
2059                    write!(f, "({})", display_comma_separated(set))?;
2060                }
2061                write!(f, ")")
2062            }
2063            Expr::Cube(sets) => {
2064                write!(f, "CUBE (")?;
2065                let mut sep = "";
2066                for set in sets {
2067                    write!(f, "{sep}")?;
2068                    sep = ", ";
2069                    if set.len() == 1 {
2070                        write!(f, "{}", set[0])?;
2071                    } else {
2072                        write!(f, "({})", display_comma_separated(set))?;
2073                    }
2074                }
2075                write!(f, ")")
2076            }
2077            Expr::Rollup(sets) => {
2078                write!(f, "ROLLUP (")?;
2079                let mut sep = "";
2080                for set in sets {
2081                    write!(f, "{sep}")?;
2082                    sep = ", ";
2083                    if set.len() == 1 {
2084                        write!(f, "{}", set[0])?;
2085                    } else {
2086                        write!(f, "({})", display_comma_separated(set))?;
2087                    }
2088                }
2089                write!(f, ")")
2090            }
2091            Expr::Substring {
2092                expr,
2093                substring_from,
2094                substring_for,
2095                special,
2096                shorthand,
2097            } => {
2098                f.write_str("SUBSTR")?;
2099                if !*shorthand {
2100                    f.write_str("ING")?;
2101                }
2102                write!(f, "({expr}")?;
2103                if let Some(from_part) = substring_from {
2104                    if *special {
2105                        write!(f, ", {from_part}")?;
2106                    } else {
2107                        write!(f, " FROM {from_part}")?;
2108                    }
2109                }
2110                if let Some(for_part) = substring_for {
2111                    if *special {
2112                        write!(f, ", {for_part}")?;
2113                    } else {
2114                        write!(f, " FOR {for_part}")?;
2115                    }
2116                }
2117
2118                write!(f, ")")
2119            }
2120            Expr::Overlay {
2121                expr,
2122                overlay_what,
2123                overlay_from,
2124                overlay_for,
2125            } => {
2126                write!(
2127                    f,
2128                    "OVERLAY({expr} PLACING {overlay_what} FROM {overlay_from}"
2129                )?;
2130                if let Some(for_part) = overlay_for {
2131                    write!(f, " FOR {for_part}")?;
2132                }
2133
2134                write!(f, ")")
2135            }
2136            Expr::IsDistinctFrom(a, b) => write!(f, "{a} IS DISTINCT FROM {b}"),
2137            Expr::IsNotDistinctFrom(a, b) => write!(f, "{a} IS NOT DISTINCT FROM {b}"),
2138            Expr::Trim {
2139                expr,
2140                trim_where,
2141                trim_what,
2142                trim_characters,
2143            } => {
2144                write!(f, "TRIM(")?;
2145                if let Some(ident) = trim_where {
2146                    write!(f, "{ident} ")?;
2147                }
2148                if let Some(trim_char) = trim_what {
2149                    write!(f, "{trim_char} FROM {expr}")?;
2150                } else {
2151                    write!(f, "{expr}")?;
2152                }
2153                if let Some(characters) = trim_characters {
2154                    write!(f, ", {}", display_comma_separated(characters))?;
2155                }
2156
2157                write!(f, ")")
2158            }
2159            Expr::Tuple(exprs) => {
2160                write!(f, "({})", display_comma_separated(exprs))
2161            }
2162            Expr::Struct { values, fields } => {
2163                if !fields.is_empty() {
2164                    write!(
2165                        f,
2166                        "STRUCT<{}>({})",
2167                        display_comma_separated(fields),
2168                        display_comma_separated(values)
2169                    )
2170                } else {
2171                    write!(f, "STRUCT({})", display_comma_separated(values))
2172                }
2173            }
2174            Expr::Named { expr, name } => {
2175                write!(f, "{expr} AS {name}")
2176            }
2177            Expr::Dictionary(fields) => {
2178                write!(f, "{{{}}}", display_comma_separated(fields))
2179            }
2180            Expr::Map(map) => {
2181                write!(f, "{map}")
2182            }
2183            Expr::Array(set) => {
2184                write!(f, "{set}")
2185            }
2186            Expr::JsonAccess { value, path } => {
2187                write!(f, "{value}{path}")
2188            }
2189            Expr::AtTimeZone {
2190                timestamp,
2191                time_zone,
2192            } => {
2193                write!(f, "{timestamp} AT TIME ZONE {time_zone}")
2194            }
2195            Expr::Interval(interval) => {
2196                write!(f, "{interval}")
2197            }
2198            Expr::MatchAgainst {
2199                columns,
2200                match_value: match_expr,
2201                opt_search_modifier,
2202            } => {
2203                write!(f, "MATCH ({}) AGAINST ", display_comma_separated(columns),)?;
2204
2205                if let Some(search_modifier) = opt_search_modifier {
2206                    write!(f, "({match_expr} {search_modifier})")?;
2207                } else {
2208                    write!(f, "({match_expr})")?;
2209                }
2210
2211                Ok(())
2212            }
2213            Expr::OuterJoin(expr) => {
2214                write!(f, "{expr} (+)")
2215            }
2216            Expr::Prior(expr) => write!(f, "PRIOR {expr}"),
2217            Expr::Lambda(lambda) => write!(f, "{lambda}"),
2218            Expr::MemberOf(member_of) => write!(f, "{member_of}"),
2219        }
2220    }
2221}
2222
2223/// The type of a window used in `OVER` clauses.
2224///
2225/// A window can be either an inline specification (`WindowSpec`) or a
2226/// reference to a previously defined named window.
2227///
2228/// - `WindowSpec(WindowSpec)`: An inline window specification, e.g.
2229///   `OVER (PARTITION BY ... ORDER BY ...)`.
2230/// - `NamedWindow(Ident)`: A reference to a named window declared elsewhere.
2231#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2232#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2233#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2234pub enum WindowType {
2235    /// An inline window specification.
2236    WindowSpec(WindowSpec),
2237    /// A reference to a previously defined named window.
2238    NamedWindow(Ident),
2239}
2240
2241impl Display for WindowType {
2242    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2243        match self {
2244            WindowType::WindowSpec(spec) => {
2245                f.write_str("(")?;
2246                NewLine.fmt(f)?;
2247                Indent(spec).fmt(f)?;
2248                NewLine.fmt(f)?;
2249                f.write_str(")")
2250            }
2251            WindowType::NamedWindow(name) => name.fmt(f),
2252        }
2253    }
2254}
2255
2256/// A window specification (i.e. `OVER ([window_name] PARTITION BY .. ORDER BY .. etc.)`)
2257#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2258#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2259#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2260pub struct WindowSpec {
2261    /// Optional window name.
2262    ///
2263    /// You can find it at least in [MySQL][1], [BigQuery][2], [PostgreSQL][3]
2264    ///
2265    /// [1]: https://dev.mysql.com/doc/refman/8.0/en/window-functions-named-windows.html
2266    /// [2]: https://cloud.google.com/bigquery/docs/reference/standard-sql/window-function-calls
2267    /// [3]: https://www.postgresql.org/docs/current/sql-expressions.html#SYNTAX-WINDOW-FUNCTIONS
2268    pub window_name: Option<Ident>,
2269    /// `OVER (PARTITION BY ...)`
2270    pub partition_by: Vec<Expr>,
2271    /// `OVER (ORDER BY ...)`
2272    pub order_by: Vec<OrderByExpr>,
2273    /// `OVER (window frame)`
2274    pub window_frame: Option<WindowFrame>,
2275}
2276
2277impl fmt::Display for WindowSpec {
2278    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2279        let mut is_first = true;
2280        if let Some(window_name) = &self.window_name {
2281            if !is_first {
2282                SpaceOrNewline.fmt(f)?;
2283            }
2284            is_first = false;
2285            write!(f, "{window_name}")?;
2286        }
2287        if !self.partition_by.is_empty() {
2288            if !is_first {
2289                SpaceOrNewline.fmt(f)?;
2290            }
2291            is_first = false;
2292            write!(
2293                f,
2294                "PARTITION BY {}",
2295                display_comma_separated(&self.partition_by)
2296            )?;
2297        }
2298        if !self.order_by.is_empty() {
2299            if !is_first {
2300                SpaceOrNewline.fmt(f)?;
2301            }
2302            is_first = false;
2303            write!(f, "ORDER BY {}", display_comma_separated(&self.order_by))?;
2304        }
2305        if let Some(window_frame) = &self.window_frame {
2306            if !is_first {
2307                SpaceOrNewline.fmt(f)?;
2308            }
2309            if let Some(end_bound) = &window_frame.end_bound {
2310                write!(
2311                    f,
2312                    "{} BETWEEN {} AND {}",
2313                    window_frame.units, window_frame.start_bound, end_bound
2314                )?;
2315            } else {
2316                write!(f, "{} {}", window_frame.units, window_frame.start_bound)?;
2317            }
2318        }
2319        Ok(())
2320    }
2321}
2322
2323/// Specifies the data processed by a window function, e.g.
2324/// `RANGE UNBOUNDED PRECEDING` or `ROWS BETWEEN 5 PRECEDING AND CURRENT ROW`.
2325///
2326/// Note: The parser does not validate the specified bounds; the caller should
2327/// reject invalid bounds like `ROWS UNBOUNDED FOLLOWING` before execution.
2328#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2329#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2330#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2331pub struct WindowFrame {
2332    /// Units for the frame (e.g. `ROWS`, `RANGE`, `GROUPS`).
2333    pub units: WindowFrameUnits,
2334    /// The start bound of the window frame.
2335    pub start_bound: WindowFrameBound,
2336    /// The right bound of the `BETWEEN .. AND` clause. The end bound of `None`
2337    /// indicates the shorthand form (e.g. `ROWS 1 PRECEDING`), which must
2338    /// behave the same as `end_bound = WindowFrameBound::CurrentRow`.
2339    pub end_bound: Option<WindowFrameBound>,
2340    // TBD: EXCLUDE
2341}
2342
2343impl Default for WindowFrame {
2344    /// Returns default value for window frame
2345    ///
2346    /// See [this page](https://www.sqlite.org/windowfunctions.html#frame_specifications) for more details.
2347    fn default() -> Self {
2348        Self {
2349            units: WindowFrameUnits::Range,
2350            start_bound: WindowFrameBound::Preceding(None),
2351            end_bound: None,
2352        }
2353    }
2354}
2355
2356#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2357#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2358#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2359/// Units used to describe the window frame scope.
2360pub enum WindowFrameUnits {
2361    /// `ROWS` unit.
2362    Rows,
2363    /// `RANGE` unit.
2364    Range,
2365    /// `GROUPS` unit.
2366    Groups,
2367}
2368
2369impl fmt::Display for WindowFrameUnits {
2370    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2371        f.write_str(match self {
2372            WindowFrameUnits::Rows => "ROWS",
2373            WindowFrameUnits::Range => "RANGE",
2374            WindowFrameUnits::Groups => "GROUPS",
2375        })
2376    }
2377}
2378
2379/// Specifies Ignore / Respect NULL within window functions.
2380/// For example
2381/// `FIRST_VALUE(column2) IGNORE NULLS OVER (PARTITION BY column1)`
2382#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2383#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2384#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2385/// How NULL values are treated in certain window functions.
2386pub enum NullTreatment {
2387    /// Ignore NULL values (e.g. `IGNORE NULLS`).
2388    IgnoreNulls,
2389    /// Respect NULL values (e.g. `RESPECT NULLS`).
2390    RespectNulls,
2391}
2392
2393impl fmt::Display for NullTreatment {
2394    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2395        f.write_str(match self {
2396            NullTreatment::IgnoreNulls => "IGNORE NULLS",
2397            NullTreatment::RespectNulls => "RESPECT NULLS",
2398        })
2399    }
2400}
2401
2402/// Specifies [WindowFrame]'s `start_bound` and `end_bound`
2403#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2404#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2405#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2406pub enum WindowFrameBound {
2407    /// `CURRENT ROW`
2408    CurrentRow,
2409    /// `<N> PRECEDING` or `UNBOUNDED PRECEDING`
2410    Preceding(Option<Box<Expr>>),
2411    /// `<N> FOLLOWING` or `UNBOUNDED FOLLOWING`.
2412    Following(Option<Box<Expr>>),
2413}
2414
2415impl fmt::Display for WindowFrameBound {
2416    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2417        match self {
2418            WindowFrameBound::CurrentRow => f.write_str("CURRENT ROW"),
2419            WindowFrameBound::Preceding(None) => f.write_str("UNBOUNDED PRECEDING"),
2420            WindowFrameBound::Following(None) => f.write_str("UNBOUNDED FOLLOWING"),
2421            WindowFrameBound::Preceding(Some(n)) => write!(f, "{n} PRECEDING"),
2422            WindowFrameBound::Following(Some(n)) => write!(f, "{n} FOLLOWING"),
2423        }
2424    }
2425}
2426
2427#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2428#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2429#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2430/// Indicates partition operation type for partition management statements.
2431pub enum AddDropSync {
2432    /// Add partitions.
2433    ADD,
2434    /// Drop partitions.
2435    DROP,
2436    /// Sync partitions.
2437    SYNC,
2438}
2439
2440impl fmt::Display for AddDropSync {
2441    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2442        match self {
2443            AddDropSync::SYNC => f.write_str("SYNC PARTITIONS"),
2444            AddDropSync::DROP => f.write_str("DROP PARTITIONS"),
2445            AddDropSync::ADD => f.write_str("ADD PARTITIONS"),
2446        }
2447    }
2448}
2449
2450#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2451#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2452#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2453/// Object kinds supported by `SHOW CREATE` statements.
2454pub enum ShowCreateObject {
2455    /// An event object for `SHOW CREATE EVENT`.
2456    Event,
2457    /// A function object for `SHOW CREATE FUNCTION`.
2458    Function,
2459    /// A procedure object for `SHOW CREATE PROCEDURE`.
2460    Procedure,
2461    /// A table object for `SHOW CREATE TABLE`.
2462    Table,
2463    /// A trigger object for `SHOW CREATE TRIGGER`.
2464    Trigger,
2465    /// A view object for `SHOW CREATE VIEW`.
2466    View,
2467}
2468
2469impl fmt::Display for ShowCreateObject {
2470    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2471        match self {
2472            ShowCreateObject::Event => f.write_str("EVENT"),
2473            ShowCreateObject::Function => f.write_str("FUNCTION"),
2474            ShowCreateObject::Procedure => f.write_str("PROCEDURE"),
2475            ShowCreateObject::Table => f.write_str("TABLE"),
2476            ShowCreateObject::Trigger => f.write_str("TRIGGER"),
2477            ShowCreateObject::View => f.write_str("VIEW"),
2478        }
2479    }
2480}
2481
2482#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2483#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2484#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2485/// Objects that can be targeted by a `COMMENT` statement.
2486pub enum CommentObject {
2487    /// A collation.
2488    Collation,
2489    /// A table column.
2490    Column,
2491    /// A database.
2492    Database,
2493    /// A domain.
2494    Domain,
2495    /// An extension.
2496    Extension,
2497    /// A function.
2498    Function,
2499    /// An index.
2500    Index,
2501    /// A materialized view.
2502    MaterializedView,
2503    /// A procedure.
2504    Procedure,
2505    /// A role.
2506    Role,
2507    /// A schema.
2508    Schema,
2509    /// A sequence.
2510    Sequence,
2511    /// A table.
2512    Table,
2513    /// A type.
2514    Type,
2515    /// A user.
2516    User,
2517    /// A view.
2518    View,
2519}
2520
2521impl fmt::Display for CommentObject {
2522    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2523        match self {
2524            CommentObject::Collation => f.write_str("COLLATION"),
2525            CommentObject::Column => f.write_str("COLUMN"),
2526            CommentObject::Database => f.write_str("DATABASE"),
2527            CommentObject::Domain => f.write_str("DOMAIN"),
2528            CommentObject::Extension => f.write_str("EXTENSION"),
2529            CommentObject::Function => f.write_str("FUNCTION"),
2530            CommentObject::Index => f.write_str("INDEX"),
2531            CommentObject::MaterializedView => f.write_str("MATERIALIZED VIEW"),
2532            CommentObject::Procedure => f.write_str("PROCEDURE"),
2533            CommentObject::Role => f.write_str("ROLE"),
2534            CommentObject::Schema => f.write_str("SCHEMA"),
2535            CommentObject::Sequence => f.write_str("SEQUENCE"),
2536            CommentObject::Table => f.write_str("TABLE"),
2537            CommentObject::Type => f.write_str("TYPE"),
2538            CommentObject::User => f.write_str("USER"),
2539            CommentObject::View => f.write_str("VIEW"),
2540        }
2541    }
2542}
2543
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))]
2547/// Password specification variants used in user-related statements.
2548pub enum Password {
2549    /// A concrete password expression.
2550    Password(Expr),
2551    /// Represents a `NULL` password.
2552    NullPassword,
2553}
2554
2555/// A `CASE` statement.
2556///
2557/// Examples:
2558/// ```sql
2559/// CASE
2560///     WHEN EXISTS(SELECT 1)
2561///         THEN SELECT 1 FROM T;
2562///     WHEN EXISTS(SELECT 2)
2563///         THEN SELECT 1 FROM U;
2564///     ELSE
2565///         SELECT 1 FROM V;
2566/// END CASE;
2567/// ```
2568///
2569/// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#case_search_expression)
2570/// [Snowflake](https://docs.snowflake.com/en/sql-reference/snowflake-scripting/case)
2571#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2572#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2573#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2574pub struct CaseStatement {
2575    /// The `CASE` token that starts the statement.
2576    pub case_token: AttachedToken,
2577    /// Optional expression to match against in `CASE ... WHEN`.
2578    pub match_expr: Option<Expr>,
2579    /// The `WHEN ... THEN` blocks of the `CASE` statement.
2580    pub when_blocks: Vec<ConditionalStatementBlock>,
2581    /// Optional `ELSE` block for the `CASE` statement.
2582    pub else_block: Option<ConditionalStatementBlock>,
2583    /// The last token of the statement (`END` or `CASE`).
2584    pub end_case_token: AttachedToken,
2585}
2586
2587impl fmt::Display for CaseStatement {
2588    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2589        let CaseStatement {
2590            case_token: _,
2591            match_expr,
2592            when_blocks,
2593            else_block,
2594            end_case_token: AttachedToken(end),
2595        } = self;
2596
2597        write!(f, "CASE")?;
2598
2599        if let Some(expr) = match_expr {
2600            write!(f, " {expr}")?;
2601        }
2602
2603        if !when_blocks.is_empty() {
2604            write!(f, " {}", display_separated(when_blocks, " "))?;
2605        }
2606
2607        if let Some(else_block) = else_block {
2608            write!(f, " {else_block}")?;
2609        }
2610
2611        write!(f, " END")?;
2612
2613        if let Token::Word(w) = &end.token {
2614            if w.keyword == Keyword::CASE {
2615                write!(f, " CASE")?;
2616            }
2617        }
2618
2619        Ok(())
2620    }
2621}
2622
2623/// An `IF` statement.
2624///
2625/// Example (BigQuery or Snowflake):
2626/// ```sql
2627/// IF TRUE THEN
2628///     SELECT 1;
2629///     SELECT 2;
2630/// ELSEIF TRUE THEN
2631///     SELECT 3;
2632/// ELSE
2633///     SELECT 4;
2634/// END IF
2635/// ```
2636/// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#if)
2637/// [Snowflake](https://docs.snowflake.com/en/sql-reference/snowflake-scripting/if)
2638///
2639/// Example (MSSQL):
2640/// ```sql
2641/// IF 1=1 SELECT 1 ELSE SELECT 2
2642/// ```
2643/// [MSSQL](https://learn.microsoft.com/en-us/sql/t-sql/language-elements/if-else-transact-sql?view=sql-server-ver16)
2644#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2645#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2646#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2647pub struct IfStatement {
2648    /// The initial `IF` block containing the condition and statements.
2649    pub if_block: ConditionalStatementBlock,
2650    /// Additional `ELSEIF` blocks.
2651    pub elseif_blocks: Vec<ConditionalStatementBlock>,
2652    /// Optional `ELSE` block.
2653    pub else_block: Option<ConditionalStatementBlock>,
2654    /// Optional trailing `END` token for the `IF` statement.
2655    pub end_token: Option<AttachedToken>,
2656}
2657
2658impl fmt::Display for IfStatement {
2659    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2660        let IfStatement {
2661            if_block,
2662            elseif_blocks,
2663            else_block,
2664            end_token,
2665        } = self;
2666
2667        write!(f, "{if_block}")?;
2668
2669        for elseif_block in elseif_blocks {
2670            write!(f, " {elseif_block}")?;
2671        }
2672
2673        if let Some(else_block) = else_block {
2674            write!(f, " {else_block}")?;
2675        }
2676
2677        if let Some(AttachedToken(end_token)) = end_token {
2678            write!(f, " END {end_token}")?;
2679        }
2680
2681        Ok(())
2682    }
2683}
2684
2685/// A `WHILE` statement.
2686///
2687/// Example:
2688/// ```sql
2689/// WHILE @@FETCH_STATUS = 0
2690/// BEGIN
2691///    FETCH NEXT FROM c1 INTO @var1, @var2;
2692/// END
2693/// ```
2694///
2695/// [MsSql](https://learn.microsoft.com/en-us/sql/t-sql/language-elements/while-transact-sql)
2696#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2697#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2698#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2699pub struct WhileStatement {
2700    /// Block executed while the condition holds.
2701    pub while_block: ConditionalStatementBlock,
2702}
2703
2704impl fmt::Display for WhileStatement {
2705    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2706        let WhileStatement { while_block } = self;
2707        write!(f, "{while_block}")?;
2708        Ok(())
2709    }
2710}
2711
2712/// A block within a [Statement::Case] or [Statement::If] or [Statement::While]-like statement
2713///
2714/// Example 1:
2715/// ```sql
2716/// WHEN EXISTS(SELECT 1) THEN SELECT 1;
2717/// ```
2718///
2719/// Example 2:
2720/// ```sql
2721/// IF TRUE THEN SELECT 1; SELECT 2;
2722/// ```
2723///
2724/// Example 3:
2725/// ```sql
2726/// ELSE SELECT 1; SELECT 2;
2727/// ```
2728///
2729/// Example 4:
2730/// ```sql
2731/// WHILE @@FETCH_STATUS = 0
2732/// BEGIN
2733///    FETCH NEXT FROM c1 INTO @var1, @var2;
2734/// END
2735/// ```
2736#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2737#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2738#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2739pub struct ConditionalStatementBlock {
2740    /// Token representing the start of the block (e.g., WHEN/IF/WHILE).
2741    pub start_token: AttachedToken,
2742    /// Optional condition expression for the block.
2743    pub condition: Option<Expr>,
2744    /// Optional token for the `THEN` keyword.
2745    pub then_token: Option<AttachedToken>,
2746    /// The statements contained in this conditional block.
2747    pub conditional_statements: ConditionalStatements,
2748}
2749
2750impl ConditionalStatementBlock {
2751    /// Get the statements in this conditional block.
2752    pub fn statements(&self) -> &Vec<Statement> {
2753        self.conditional_statements.statements()
2754    }
2755}
2756
2757impl fmt::Display for ConditionalStatementBlock {
2758    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2759        let ConditionalStatementBlock {
2760            start_token: AttachedToken(start_token),
2761            condition,
2762            then_token,
2763            conditional_statements,
2764        } = self;
2765
2766        write!(f, "{start_token}")?;
2767
2768        if let Some(condition) = condition {
2769            write!(f, " {condition}")?;
2770        }
2771
2772        if then_token.is_some() {
2773            write!(f, " THEN")?;
2774        }
2775
2776        if !conditional_statements.statements().is_empty() {
2777            write!(f, " {conditional_statements}")?;
2778        }
2779
2780        Ok(())
2781    }
2782}
2783
2784/// A list of statements in a [ConditionalStatementBlock].
2785#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2786#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2787#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2788/// Statements used inside conditional blocks (`IF`, `WHEN`, `WHILE`).
2789pub enum ConditionalStatements {
2790    /// Simple sequence of statements (no `BEGIN`/`END`).
2791    Sequence {
2792        /// The statements in the sequence.
2793        statements: Vec<Statement>,
2794    },
2795    /// Block enclosed by `BEGIN` and `END`.
2796    BeginEnd(BeginEndStatements),
2797}
2798
2799impl ConditionalStatements {
2800    /// Get the statements in this conditional statements block.
2801    pub fn statements(&self) -> &Vec<Statement> {
2802        match self {
2803            ConditionalStatements::Sequence { statements } => statements,
2804            ConditionalStatements::BeginEnd(bes) => &bes.statements,
2805        }
2806    }
2807}
2808
2809impl fmt::Display for ConditionalStatements {
2810    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2811        match self {
2812            ConditionalStatements::Sequence { statements } => {
2813                if !statements.is_empty() {
2814                    format_statement_list(f, statements)?;
2815                }
2816                Ok(())
2817            }
2818            ConditionalStatements::BeginEnd(bes) => write!(f, "{bes}"),
2819        }
2820    }
2821}
2822
2823/// Represents a list of statements enclosed within `BEGIN` and `END` keywords.
2824/// Example:
2825/// ```sql
2826/// BEGIN
2827///     SELECT 1;
2828///     SELECT 2;
2829/// END
2830/// ```
2831#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2832#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2833#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2834pub struct BeginEndStatements {
2835    /// Token representing the `BEGIN` keyword (may include span info).
2836    pub begin_token: AttachedToken,
2837    /// Statements contained within the block.
2838    pub statements: Vec<Statement>,
2839    /// Token representing the `END` keyword (may include span info).
2840    pub end_token: AttachedToken,
2841}
2842
2843impl fmt::Display for BeginEndStatements {
2844    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2845        let BeginEndStatements {
2846            begin_token: AttachedToken(begin_token),
2847            statements,
2848            end_token: AttachedToken(end_token),
2849        } = self;
2850
2851        if begin_token.token != Token::EOF {
2852            write!(f, "{begin_token} ")?;
2853        }
2854        if !statements.is_empty() {
2855            format_statement_list(f, statements)?;
2856        }
2857        if end_token.token != Token::EOF {
2858            write!(f, " {end_token}")?;
2859        }
2860        Ok(())
2861    }
2862}
2863
2864/// A `RAISE` statement.
2865///
2866/// Examples:
2867/// ```sql
2868/// RAISE USING MESSAGE = 'error';
2869///
2870/// RAISE myerror;
2871/// ```
2872///
2873/// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#raise)
2874/// [Snowflake](https://docs.snowflake.com/en/sql-reference/snowflake-scripting/raise)
2875#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2876#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2877#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2878pub struct RaiseStatement {
2879    /// Optional value provided to the RAISE statement.
2880    pub value: Option<RaiseStatementValue>,
2881}
2882
2883impl fmt::Display for RaiseStatement {
2884    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2885        let RaiseStatement { value } = self;
2886
2887        write!(f, "RAISE")?;
2888        if let Some(value) = value {
2889            write!(f, " {value}")?;
2890        }
2891
2892        Ok(())
2893    }
2894}
2895
2896/// Represents the error value of a [RaiseStatement].
2897#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2898#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2899#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2900pub enum RaiseStatementValue {
2901    /// `RAISE USING MESSAGE = 'error'`
2902    UsingMessage(Expr),
2903    /// `RAISE myerror`
2904    Expr(Expr),
2905}
2906
2907impl fmt::Display for RaiseStatementValue {
2908    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2909        match self {
2910            RaiseStatementValue::Expr(expr) => write!(f, "{expr}"),
2911            RaiseStatementValue::UsingMessage(expr) => write!(f, "USING MESSAGE = {expr}"),
2912        }
2913    }
2914}
2915
2916/// A MSSQL `THROW` statement.
2917///
2918/// ```sql
2919/// THROW [ error_number, message, state ]
2920/// ```
2921///
2922/// [MSSQL](https://learn.microsoft.com/en-us/sql/t-sql/language-elements/throw-transact-sql)
2923#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2924#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2925#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2926pub struct ThrowStatement {
2927    /// Error number expression.
2928    pub error_number: Option<Box<Expr>>,
2929    /// Error message expression.
2930    pub message: Option<Box<Expr>>,
2931    /// State expression.
2932    pub state: Option<Box<Expr>>,
2933}
2934
2935impl fmt::Display for ThrowStatement {
2936    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2937        let ThrowStatement {
2938            error_number,
2939            message,
2940            state,
2941        } = self;
2942
2943        write!(f, "THROW")?;
2944        if let (Some(error_number), Some(message), Some(state)) = (error_number, message, state) {
2945            write!(f, " {error_number}, {message}, {state}")?;
2946        }
2947        Ok(())
2948    }
2949}
2950
2951/// Represents an expression assignment within a variable `DECLARE` statement.
2952///
2953/// Examples:
2954/// ```sql
2955/// DECLARE variable_name := 42
2956/// DECLARE variable_name DEFAULT 42
2957/// ```
2958#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2959#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2960#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2961pub enum DeclareAssignment {
2962    /// Plain expression specified.
2963    Expr(Box<Expr>),
2964
2965    /// Expression assigned via the `DEFAULT` keyword
2966    Default(Box<Expr>),
2967
2968    /// Expression assigned via the `:=` syntax
2969    ///
2970    /// Example:
2971    /// ```sql
2972    /// DECLARE variable_name := 42;
2973    /// ```
2974    DuckAssignment(Box<Expr>),
2975
2976    /// Expression via the `FOR` keyword
2977    ///
2978    /// Example:
2979    /// ```sql
2980    /// DECLARE c1 CURSOR FOR res
2981    /// ```
2982    For(Box<Expr>),
2983
2984    /// Expression via the `=` syntax.
2985    ///
2986    /// Example:
2987    /// ```sql
2988    /// DECLARE @variable AS INT = 100
2989    /// ```
2990    MsSqlAssignment(Box<Expr>),
2991}
2992
2993impl fmt::Display for DeclareAssignment {
2994    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2995        match self {
2996            DeclareAssignment::Expr(expr) => {
2997                write!(f, "{expr}")
2998            }
2999            DeclareAssignment::Default(expr) => {
3000                write!(f, "DEFAULT {expr}")
3001            }
3002            DeclareAssignment::DuckAssignment(expr) => {
3003                write!(f, ":= {expr}")
3004            }
3005            DeclareAssignment::MsSqlAssignment(expr) => {
3006                write!(f, "= {expr}")
3007            }
3008            DeclareAssignment::For(expr) => {
3009                write!(f, "FOR {expr}")
3010            }
3011        }
3012    }
3013}
3014
3015/// Represents the type of a `DECLARE` statement.
3016#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3017#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3018#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3019pub enum DeclareType {
3020    /// Cursor variable type. e.g. [Snowflake] [PostgreSQL] [MsSql]
3021    ///
3022    /// [Snowflake]: https://docs.snowflake.com/en/developer-guide/snowflake-scripting/cursors#declaring-a-cursor
3023    /// [PostgreSQL]: https://www.postgresql.org/docs/current/plpgsql-cursors.html
3024    /// [MsSql]: https://learn.microsoft.com/en-us/sql/t-sql/language-elements/declare-cursor-transact-sql
3025    Cursor,
3026
3027    /// Result set variable type. [Snowflake]
3028    ///
3029    /// Syntax:
3030    /// ```text
3031    /// <resultset_name> RESULTSET [ { DEFAULT | := } ( <query> ) ] ;
3032    /// ```
3033    /// [Snowflake]: https://docs.snowflake.com/en/sql-reference/snowflake-scripting/declare#resultset-declaration-syntax
3034    ResultSet,
3035
3036    /// Exception declaration syntax. [Snowflake]
3037    ///
3038    /// Syntax:
3039    /// ```text
3040    /// <exception_name> EXCEPTION [ ( <exception_number> , '<exception_message>' ) ] ;
3041    /// ```
3042    /// [Snowflake]: https://docs.snowflake.com/en/sql-reference/snowflake-scripting/declare#exception-declaration-syntax
3043    Exception,
3044}
3045
3046impl fmt::Display for DeclareType {
3047    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3048        match self {
3049            DeclareType::Cursor => {
3050                write!(f, "CURSOR")
3051            }
3052            DeclareType::ResultSet => {
3053                write!(f, "RESULTSET")
3054            }
3055            DeclareType::Exception => {
3056                write!(f, "EXCEPTION")
3057            }
3058        }
3059    }
3060}
3061
3062/// A `DECLARE` statement.
3063/// [PostgreSQL] [Snowflake] [BigQuery]
3064///
3065/// Examples:
3066/// ```sql
3067/// DECLARE variable_name := 42
3068/// DECLARE liahona CURSOR FOR SELECT * FROM films;
3069/// ```
3070///
3071/// [PostgreSQL]: https://www.postgresql.org/docs/current/sql-declare.html
3072/// [Snowflake]: https://docs.snowflake.com/en/sql-reference/snowflake-scripting/declare
3073/// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#declare
3074#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3075#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3076#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3077pub struct Declare {
3078    /// The name(s) being declared.
3079    /// Example: `DECLARE a, b, c DEFAULT 42;
3080    pub names: Vec<Ident>,
3081    /// Data-type assigned to the declared variable.
3082    /// Example: `DECLARE x INT64 DEFAULT 42;
3083    pub data_type: Option<DataType>,
3084    /// Expression being assigned to the declared variable.
3085    pub assignment: Option<DeclareAssignment>,
3086    /// Represents the type of the declared variable.
3087    pub declare_type: Option<DeclareType>,
3088    /// Causes the cursor to return data in binary rather than in text format.
3089    pub binary: Option<bool>,
3090    /// None = Not specified
3091    /// Some(true) = INSENSITIVE
3092    /// Some(false) = ASENSITIVE
3093    pub sensitive: Option<bool>,
3094    /// None = Not specified
3095    /// Some(true) = SCROLL
3096    /// Some(false) = NO SCROLL
3097    pub scroll: Option<bool>,
3098    /// None = Not specified
3099    /// Some(true) = WITH HOLD, specifies that the cursor can continue to be used after the transaction that created it successfully commits
3100    /// Some(false) = WITHOUT HOLD, specifies that the cursor cannot be used outside of the transaction that created it
3101    pub hold: Option<bool>,
3102    /// `FOR <query>` clause in a CURSOR declaration.
3103    pub for_query: Option<Box<Query>>,
3104}
3105
3106impl fmt::Display for Declare {
3107    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3108        let Declare {
3109            names,
3110            data_type,
3111            assignment,
3112            declare_type,
3113            binary,
3114            sensitive,
3115            scroll,
3116            hold,
3117            for_query,
3118        } = self;
3119        write!(f, "{}", display_comma_separated(names))?;
3120
3121        if let Some(true) = binary {
3122            write!(f, " BINARY")?;
3123        }
3124
3125        if let Some(sensitive) = sensitive {
3126            if *sensitive {
3127                write!(f, " INSENSITIVE")?;
3128            } else {
3129                write!(f, " ASENSITIVE")?;
3130            }
3131        }
3132
3133        if let Some(scroll) = scroll {
3134            if *scroll {
3135                write!(f, " SCROLL")?;
3136            } else {
3137                write!(f, " NO SCROLL")?;
3138            }
3139        }
3140
3141        if let Some(declare_type) = declare_type {
3142            write!(f, " {declare_type}")?;
3143        }
3144
3145        if let Some(hold) = hold {
3146            if *hold {
3147                write!(f, " WITH HOLD")?;
3148            } else {
3149                write!(f, " WITHOUT HOLD")?;
3150            }
3151        }
3152
3153        if let Some(query) = for_query {
3154            write!(f, " FOR {query}")?;
3155        }
3156
3157        if let Some(data_type) = data_type {
3158            write!(f, " {data_type}")?;
3159        }
3160
3161        if let Some(expr) = assignment {
3162            write!(f, " {expr}")?;
3163        }
3164        Ok(())
3165    }
3166}
3167
3168/// Sql options of a `CREATE TABLE` statement.
3169#[derive(Debug, Default, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3170#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3171#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3172/// Options allowed within a `CREATE TABLE` statement.
3173pub enum CreateTableOptions {
3174    /// No options specified.
3175    #[default]
3176    None,
3177    /// Options specified using the `WITH` keyword, e.g. `WITH (k = v)`.
3178    With(Vec<SqlOption>),
3179    /// Options specified using the `OPTIONS(...)` clause.
3180    Options(Vec<SqlOption>),
3181    /// Plain space-separated options.
3182    Plain(Vec<SqlOption>),
3183    /// Table properties (e.g., TBLPROPERTIES / storage properties).
3184    TableProperties(Vec<SqlOption>),
3185}
3186
3187impl fmt::Display for CreateTableOptions {
3188    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3189        match self {
3190            CreateTableOptions::With(with_options) => {
3191                write!(f, "WITH ({})", display_comma_separated(with_options))
3192            }
3193            CreateTableOptions::Options(options) => {
3194                write!(f, "OPTIONS({})", display_comma_separated(options))
3195            }
3196            CreateTableOptions::TableProperties(options) => {
3197                write!(f, "TBLPROPERTIES ({})", display_comma_separated(options))
3198            }
3199            CreateTableOptions::Plain(options) => {
3200                write!(f, "{}", display_separated(options, " "))
3201            }
3202            CreateTableOptions::None => Ok(()),
3203        }
3204    }
3205}
3206
3207/// A `FROM` clause within a `DELETE` statement.
3208///
3209/// Syntax
3210/// ```sql
3211/// [FROM] table
3212/// ```
3213#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3214#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3215#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3216pub enum FromTable {
3217    /// An explicit `FROM` keyword was specified.
3218    WithFromKeyword(Vec<TableWithJoins>),
3219    /// BigQuery: `FROM` keyword was omitted.
3220    /// <https://cloud.google.com/bigquery/docs/reference/standard-sql/dml-syntax#delete_statement>
3221    WithoutKeyword(Vec<TableWithJoins>),
3222}
3223impl Display for FromTable {
3224    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3225        match self {
3226            FromTable::WithFromKeyword(tables) => {
3227                write!(f, "FROM {}", display_comma_separated(tables))
3228            }
3229            FromTable::WithoutKeyword(tables) => {
3230                write!(f, "{}", display_comma_separated(tables))
3231            }
3232        }
3233    }
3234}
3235
3236#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3237#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3238#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3239/// Variants for the `SET` family of statements.
3240pub enum Set {
3241    /// SQL Standard-style
3242    /// SET a = 1;
3243    /// `SET var = value` (standard SQL-style assignment).
3244    SingleAssignment {
3245        /// Optional scope modifier (`SESSION` / `LOCAL`).
3246        scope: Option<ContextModifier>,
3247        /// Whether this is a Hive-style `HIVEVAR:` assignment.
3248        hivevar: bool,
3249        /// Variable name to assign.
3250        variable: ObjectName,
3251        /// Values assigned to the variable.
3252        values: Vec<Expr>,
3253    },
3254    /// Snowflake-style
3255    /// SET (a, b, ..) = (1, 2, ..);
3256    /// `SET (a, b) = (1, 2)` (tuple assignment syntax).
3257    ParenthesizedAssignments {
3258        /// Variables being assigned in tuple form.
3259        variables: Vec<ObjectName>,
3260        /// Corresponding values for the variables.
3261        values: Vec<Expr>,
3262    },
3263    /// MySQL-style
3264    /// SET a = 1, b = 2, ..;
3265    /// `SET a = 1, b = 2` (MySQL-style comma-separated assignments).
3266    MultipleAssignments {
3267        /// List of `SET` assignments (MySQL-style comma-separated).
3268        assignments: Vec<SetAssignment>,
3269    },
3270    /// Session authorization for Postgres/Redshift
3271    ///
3272    /// ```sql
3273    /// SET SESSION AUTHORIZATION { user_name | DEFAULT }
3274    /// ```
3275    ///
3276    /// See <https://www.postgresql.org/docs/current/sql-set-session-authorization.html>
3277    /// See <https://docs.aws.amazon.com/redshift/latest/dg/r_SET_SESSION_AUTHORIZATION.html>
3278    SetSessionAuthorization(SetSessionAuthorizationParam),
3279    /// MS-SQL session
3280    ///
3281    /// See <https://learn.microsoft.com/en-us/sql/t-sql/statements/set-statements-transact-sql>
3282    SetSessionParam(SetSessionParamKind),
3283    /// ```sql
3284    /// SET [ SESSION | LOCAL ] ROLE role_name
3285    /// ```
3286    ///
3287    /// Sets session state. Examples: [ANSI][1], [Postgresql][2], [MySQL][3], and [Oracle][4]
3288    ///
3289    /// [1]: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#set-role-statement
3290    /// [2]: https://www.postgresql.org/docs/14/sql-set-role.html
3291    /// [3]: https://dev.mysql.com/doc/refman/8.0/en/set-role.html
3292    /// [4]: https://docs.oracle.com/cd/B19306_01/server.102/b14200/statements_10004.htm
3293    SetRole {
3294        /// Non-ANSI optional identifier to inform if the role is defined inside the current session (`SESSION`) or transaction (`LOCAL`).
3295        context_modifier: Option<ContextModifier>,
3296        /// Role name. If NONE is specified, then the current role name is removed.
3297        role_name: Option<Ident>,
3298    },
3299    /// ```sql
3300    /// SET TIME ZONE <value>
3301    /// ```
3302    ///
3303    /// Note: this is a PostgreSQL-specific statements
3304    /// `SET TIME ZONE <value>` is an alias for `SET timezone TO <value>` in PostgreSQL
3305    /// However, we allow it for all dialects.
3306    /// `SET TIME ZONE` statement. `local` indicates the `LOCAL` keyword.
3307    /// `SET TIME ZONE <value>` statement.
3308    SetTimeZone {
3309        /// Whether the `LOCAL` keyword was specified.
3310        local: bool,
3311        /// Time zone expression value.
3312        value: Expr,
3313    },
3314    /// ```sql
3315    /// SET NAMES 'charset_name' [COLLATE 'collation_name']
3316    /// ```
3317    SetNames {
3318        /// Character set name to set.
3319        charset_name: Ident,
3320        /// Optional collation name.
3321        collation_name: Option<String>,
3322    },
3323    /// ```sql
3324    /// SET NAMES DEFAULT
3325    /// ```
3326    ///
3327    /// Note: this is a MySQL-specific statement.
3328    SetNamesDefault {},
3329    /// ```sql
3330    /// SET TRANSACTION ...
3331    /// ```
3332    SetTransaction {
3333        /// Transaction modes (e.g., ISOLATION LEVEL, READ ONLY).
3334        modes: Vec<TransactionMode>,
3335        /// Optional snapshot value for transaction snapshot control.
3336        snapshot: Option<ValueWithSpan>,
3337        /// `true` when the `SESSION` keyword was used.
3338        session: bool,
3339    },
3340}
3341
3342impl Display for Set {
3343    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3344        match self {
3345            Self::ParenthesizedAssignments { variables, values } => write!(
3346                f,
3347                "SET ({}) = ({})",
3348                display_comma_separated(variables),
3349                display_comma_separated(values)
3350            ),
3351            Self::MultipleAssignments { assignments } => {
3352                write!(f, "SET {}", display_comma_separated(assignments))
3353            }
3354            Self::SetRole {
3355                context_modifier,
3356                role_name,
3357            } => {
3358                let role_name = role_name.clone().unwrap_or_else(|| Ident::new("NONE"));
3359                write!(
3360                    f,
3361                    "SET {modifier}ROLE {role_name}",
3362                    modifier = context_modifier.map(|m| format!("{m}")).unwrap_or_default()
3363                )
3364            }
3365            Self::SetSessionAuthorization(kind) => write!(f, "SET SESSION AUTHORIZATION {kind}"),
3366            Self::SetSessionParam(kind) => write!(f, "SET {kind}"),
3367            Self::SetTransaction {
3368                modes,
3369                snapshot,
3370                session,
3371            } => {
3372                if *session {
3373                    write!(f, "SET SESSION CHARACTERISTICS AS TRANSACTION")?;
3374                } else {
3375                    write!(f, "SET TRANSACTION")?;
3376                }
3377                if !modes.is_empty() {
3378                    write!(f, " {}", display_comma_separated(modes))?;
3379                }
3380                if let Some(snapshot_id) = snapshot {
3381                    write!(f, " SNAPSHOT {snapshot_id}")?;
3382                }
3383                Ok(())
3384            }
3385            Self::SetTimeZone { local, value } => {
3386                f.write_str("SET ")?;
3387                if *local {
3388                    f.write_str("LOCAL ")?;
3389                }
3390                write!(f, "TIME ZONE {value}")
3391            }
3392            Self::SetNames {
3393                charset_name,
3394                collation_name,
3395            } => {
3396                write!(f, "SET NAMES {charset_name}")?;
3397
3398                if let Some(collation) = collation_name {
3399                    f.write_str(" COLLATE ")?;
3400                    f.write_str(collation)?;
3401                };
3402
3403                Ok(())
3404            }
3405            Self::SetNamesDefault {} => {
3406                f.write_str("SET NAMES DEFAULT")?;
3407
3408                Ok(())
3409            }
3410            Set::SingleAssignment {
3411                scope,
3412                hivevar,
3413                variable,
3414                values,
3415            } => {
3416                write!(
3417                    f,
3418                    "SET {}{}{} = {}",
3419                    scope.map(|s| format!("{s}")).unwrap_or_default(),
3420                    if *hivevar { "HIVEVAR:" } else { "" },
3421                    variable,
3422                    display_comma_separated(values)
3423                )
3424            }
3425        }
3426    }
3427}
3428
3429/// A representation of a `WHEN` arm with all the identifiers catched and the statements to execute
3430/// for the arm.
3431///
3432/// Snowflake: <https://docs.snowflake.com/en/sql-reference/snowflake-scripting/exception>
3433/// BigQuery: <https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#beginexceptionend>
3434#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3435#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3436#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3437pub struct ExceptionWhen {
3438    /// Identifiers that trigger this branch (error conditions).
3439    pub idents: Vec<Ident>,
3440    /// Statements to execute when the condition matches.
3441    pub statements: Vec<Statement>,
3442}
3443
3444impl Display for ExceptionWhen {
3445    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3446        write!(
3447            f,
3448            "WHEN {idents} THEN",
3449            idents = display_separated(&self.idents, " OR ")
3450        )?;
3451
3452        if !self.statements.is_empty() {
3453            write!(f, " ")?;
3454            format_statement_list(f, &self.statements)?;
3455        }
3456
3457        Ok(())
3458    }
3459}
3460
3461/// ANALYZE statement
3462///
3463/// Supported syntax varies by dialect:
3464/// - Hive: `ANALYZE TABLE t [PARTITION (...)] COMPUTE STATISTICS [NOSCAN] [FOR COLUMNS [col1, ...]] [CACHE METADATA]`
3465/// - PostgreSQL: `ANALYZE [VERBOSE] [t [(col1, ...)]]` See <https://www.postgresql.org/docs/current/sql-analyze.html>
3466/// - General: `ANALYZE [TABLE] t`
3467#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3468#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3469#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3470pub struct Analyze {
3471    #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
3472    /// Name of the table to analyze. `None` for bare `ANALYZE`.
3473    pub table_name: Option<ObjectName>,
3474    /// Optional partition expressions to restrict the analysis.
3475    pub partitions: Option<Vec<Expr>>,
3476    /// `true` when analyzing specific columns (Hive `FOR COLUMNS` syntax).
3477    pub for_columns: bool,
3478    /// Columns to analyze.
3479    pub columns: Vec<Ident>,
3480    /// Whether to cache metadata before analyzing.
3481    pub cache_metadata: bool,
3482    /// Whether to skip scanning the table.
3483    pub noscan: bool,
3484    /// Whether to compute statistics during analysis.
3485    pub compute_statistics: bool,
3486    /// Whether the `TABLE` keyword was present.
3487    pub has_table_keyword: bool,
3488}
3489
3490impl fmt::Display for Analyze {
3491    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3492        write!(f, "ANALYZE")?;
3493        if let Some(ref table_name) = self.table_name {
3494            if self.has_table_keyword {
3495                write!(f, " TABLE")?;
3496            }
3497            write!(f, " {table_name}")?;
3498        }
3499        if !self.for_columns && !self.columns.is_empty() {
3500            write!(f, " ({})", display_comma_separated(&self.columns))?;
3501        }
3502        if let Some(ref parts) = self.partitions {
3503            if !parts.is_empty() {
3504                write!(f, " PARTITION ({})", display_comma_separated(parts))?;
3505            }
3506        }
3507        if self.compute_statistics {
3508            write!(f, " COMPUTE STATISTICS")?;
3509        }
3510        if self.noscan {
3511            write!(f, " NOSCAN")?;
3512        }
3513        if self.cache_metadata {
3514            write!(f, " CACHE METADATA")?;
3515        }
3516        if self.for_columns {
3517            write!(f, " FOR COLUMNS")?;
3518            if !self.columns.is_empty() {
3519                write!(f, " {}", display_comma_separated(&self.columns))?;
3520            }
3521        }
3522        Ok(())
3523    }
3524}
3525
3526/// A top-level statement (SELECT, INSERT, CREATE, etc.)
3527#[allow(clippy::large_enum_variant)]
3528#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3529#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3530#[cfg_attr(
3531    feature = "visitor",
3532    derive(Visit, VisitMut),
3533    visit(with = "visit_statement")
3534)]
3535pub enum Statement {
3536    /// ```sql
3537    /// ANALYZE
3538    /// ```
3539    /// Analyze (Hive)
3540    Analyze(Analyze),
3541    /// `SET` statements (session, transaction, timezone, etc.).
3542    Set(Set),
3543    /// ```sql
3544    /// TRUNCATE
3545    /// ```
3546    /// Truncate (Hive)
3547    Truncate(Truncate),
3548    /// ```sql
3549    /// MSCK
3550    /// ```
3551    /// Msck (Hive)
3552    Msck(Msck),
3553    /// ```sql
3554    /// SELECT
3555    /// ```
3556    Query(Box<Query>),
3557    /// ```sql
3558    /// INSERT
3559    /// ```
3560    Insert(Insert),
3561    /// ```sql
3562    /// INSTALL
3563    /// ```
3564    Install {
3565        /// Only for DuckDB
3566        extension_name: Ident,
3567    },
3568    /// ```sql
3569    /// LOAD
3570    /// ```
3571    Load {
3572        /// Only for DuckDB
3573        extension_name: Ident,
3574    },
3575    // TODO: Support ROW FORMAT
3576    /// LOAD DATA from a directory or query source.
3577    Directory {
3578        /// Whether to overwrite existing files.
3579        overwrite: bool,
3580        /// Whether the directory is local to the server.
3581        local: bool,
3582        /// Path to the directory or files.
3583        path: String,
3584        /// Optional file format for the data.
3585        file_format: Option<FileFormat>,
3586        /// Source query providing data to load.
3587        source: Box<Query>,
3588    },
3589    /// A `CASE` statement.
3590    Case(CaseStatement),
3591    /// An `IF` statement.
3592    If(IfStatement),
3593    /// A `WHILE` statement.
3594    While(WhileStatement),
3595    /// A `RAISE` statement.
3596    Raise(RaiseStatement),
3597    /// ```sql
3598    /// CALL <function>
3599    /// ```
3600    Call(Function),
3601    /// ```sql
3602    /// COPY [TO | FROM] ...
3603    /// ```
3604    Copy {
3605        /// The source of 'COPY TO', or the target of 'COPY FROM'
3606        source: CopySource,
3607        /// If true, is a 'COPY TO' statement. If false is a 'COPY FROM'
3608        to: bool,
3609        /// The target of 'COPY TO', or the source of 'COPY FROM'
3610        target: CopyTarget,
3611        /// WITH options (from PostgreSQL version 9.0)
3612        options: Vec<CopyOption>,
3613        /// WITH options (before PostgreSQL version 9.0)
3614        legacy_options: Vec<CopyLegacyOption>,
3615        /// VALUES a vector of values to be copied
3616        values: Vec<Option<String>>,
3617    },
3618    /// ```sql
3619    /// COPY INTO <table> | <location>
3620    /// ```
3621    /// See:
3622    /// <https://docs.snowflake.com/en/sql-reference/sql/copy-into-table>
3623    /// <https://docs.snowflake.com/en/sql-reference/sql/copy-into-location>
3624    ///
3625    /// Copy Into syntax available for Snowflake is different than the one implemented in
3626    /// Postgres. Although they share common prefix, it is reasonable to implement them
3627    /// in different enums. This can be refactored later once custom dialects
3628    /// are allowed to have custom Statements.
3629    CopyIntoSnowflake {
3630        /// Kind of COPY INTO operation (table or location).
3631        kind: CopyIntoSnowflakeKind,
3632        /// Target object for the COPY INTO operation.
3633        into: ObjectName,
3634        /// Optional list of target columns.
3635        into_columns: Option<Vec<Ident>>,
3636        /// Optional source object name (staged data).
3637        from_obj: Option<ObjectName>,
3638        /// Optional alias for the source object.
3639        from_obj_alias: Option<Ident>,
3640        /// Stage-specific parameters (e.g., credentials, path).
3641        stage_params: StageParamsObject,
3642        /// Optional list of transformations applied when loading.
3643        from_transformations: Option<Vec<StageLoadSelectItemKind>>,
3644        /// Optional source query instead of a staged object.
3645        from_query: Option<Box<Query>>,
3646        /// Optional list of specific file names to load.
3647        files: Option<Vec<String>>,
3648        /// Optional filename matching pattern.
3649        pattern: Option<String>,
3650        /// File format options.
3651        file_format: KeyValueOptions,
3652        /// Additional copy options.
3653        copy_options: KeyValueOptions,
3654        /// Optional validation mode string.
3655        validation_mode: Option<String>,
3656        /// Optional partition expression for loading.
3657        partition: Option<Box<Expr>>,
3658    },
3659    /// ```sql
3660    /// OPEN cursor_name
3661    /// ```
3662    /// Opens a cursor.
3663    Open(OpenStatement),
3664    /// ```sql
3665    /// CLOSE
3666    /// ```
3667    /// Closes the portal underlying an open cursor.
3668    Close {
3669        /// Cursor name
3670        cursor: CloseCursor,
3671    },
3672    /// ```sql
3673    /// UPDATE
3674    /// ```
3675    Update(Update),
3676    /// ```sql
3677    /// DELETE
3678    /// ```
3679    Delete(Delete),
3680    /// ```sql
3681    /// CREATE VIEW
3682    /// ```
3683    CreateView(CreateView),
3684    /// ```sql
3685    /// CREATE TABLE
3686    /// ```
3687    CreateTable(CreateTable),
3688    /// ```sql
3689    /// CREATE VIRTUAL TABLE .. USING <module_name> (<module_args>)`
3690    /// ```
3691    /// Sqlite specific statement
3692    CreateVirtualTable {
3693        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
3694        /// Name of the virtual table module instance.
3695        name: ObjectName,
3696        /// `true` when `IF NOT EXISTS` was specified.
3697        if_not_exists: bool,
3698        /// Module name used by the virtual table.
3699        module_name: Ident,
3700        /// Arguments passed to the module.
3701        module_args: Vec<Ident>,
3702    },
3703    /// ```sql
3704    /// `CREATE INDEX`
3705    /// ```
3706    CreateIndex(CreateIndex),
3707    /// ```sql
3708    /// CREATE ROLE
3709    /// ```
3710    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createrole.html)
3711    CreateRole(CreateRole),
3712    /// ```sql
3713    /// CREATE SECRET
3714    /// ```
3715    /// See [DuckDB](https://duckdb.org/docs/sql/statements/create_secret.html)
3716    CreateSecret {
3717        /// `true` when `OR REPLACE` was specified.
3718        or_replace: bool,
3719        /// Optional `TEMPORARY` flag.
3720        temporary: Option<bool>,
3721        /// `true` when `IF NOT EXISTS` was present.
3722        if_not_exists: bool,
3723        /// Optional secret name.
3724        name: Option<Ident>,
3725        /// Optional storage specifier identifier.
3726        storage_specifier: Option<Ident>,
3727        /// The secret type identifier.
3728        secret_type: Ident,
3729        /// Additional secret options.
3730        options: Vec<SecretOption>,
3731    },
3732    /// A `CREATE SERVER` statement.
3733    CreateServer(CreateServerStatement),
3734    /// ```sql
3735    /// CREATE POLICY
3736    /// ```
3737    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createpolicy.html)
3738    CreatePolicy(CreatePolicy),
3739    /// ```sql
3740    /// CREATE CONNECTOR
3741    /// ```
3742    /// See [Hive](https://cwiki.apache.org/confluence/pages/viewpage.action?pageId=27362034#LanguageManualDDL-CreateDataConnectorCreateConnector)
3743    CreateConnector(CreateConnector),
3744    /// ```sql
3745    /// CREATE OPERATOR
3746    /// ```
3747    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createoperator.html)
3748    CreateOperator(CreateOperator),
3749    /// ```sql
3750    /// CREATE OPERATOR FAMILY
3751    /// ```
3752    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createopfamily.html)
3753    CreateOperatorFamily(CreateOperatorFamily),
3754    /// ```sql
3755    /// CREATE OPERATOR CLASS
3756    /// ```
3757    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createopclass.html)
3758    CreateOperatorClass(CreateOperatorClass),
3759    /// ```sql
3760    /// ALTER TABLE
3761    /// ```
3762    AlterTable(AlterTable),
3763    /// ```sql
3764    /// ALTER SCHEMA
3765    /// ```
3766    /// See [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#alter_schema_collate_statement)
3767    AlterSchema(AlterSchema),
3768    /// ```sql
3769    /// ALTER INDEX
3770    /// ```
3771    AlterIndex {
3772        /// Name of the index to alter.
3773        name: ObjectName,
3774        /// The operation to perform on the index.
3775        operation: AlterIndexOperation,
3776    },
3777    /// ```sql
3778    /// ALTER VIEW
3779    /// ```
3780    AlterView {
3781        /// View name being altered.
3782        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
3783        name: ObjectName,
3784        /// Optional new column list for the view.
3785        columns: Vec<Ident>,
3786        /// Replacement query for the view definition.
3787        query: Box<Query>,
3788        /// Additional WITH options for the view.
3789        with_options: Vec<SqlOption>,
3790    },
3791    /// ```sql
3792    /// ALTER FUNCTION
3793    /// ALTER AGGREGATE
3794    /// ```
3795    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-alterfunction.html)
3796    /// and [PostgreSQL](https://www.postgresql.org/docs/current/sql-alteraggregate.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 COLLATION
3805    /// ```
3806    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-altercollation.html)
3807    AlterCollation(AlterCollation),
3808    /// ```sql
3809    /// ALTER OPERATOR
3810    /// ```
3811    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-alteroperator.html)
3812    AlterOperator(AlterOperator),
3813    /// ```sql
3814    /// ALTER OPERATOR FAMILY
3815    /// ```
3816    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-alteropfamily.html)
3817    AlterOperatorFamily(AlterOperatorFamily),
3818    /// ```sql
3819    /// ALTER OPERATOR CLASS
3820    /// ```
3821    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-alteropclass.html)
3822    AlterOperatorClass(AlterOperatorClass),
3823    /// ```sql
3824    /// ALTER ROLE
3825    /// ```
3826    AlterRole {
3827        /// Role name being altered.
3828        name: Ident,
3829        /// Operation to perform on the role.
3830        operation: AlterRoleOperation,
3831    },
3832    /// ```sql
3833    /// ALTER POLICY <NAME> ON <TABLE NAME> [<OPERATION>]
3834    /// ```
3835    /// (Postgresql-specific)
3836    AlterPolicy(AlterPolicy),
3837    /// ```sql
3838    /// ALTER CONNECTOR connector_name SET DCPROPERTIES(property_name=property_value, ...);
3839    /// or
3840    /// ALTER CONNECTOR connector_name SET URL new_url;
3841    /// or
3842    /// ALTER CONNECTOR connector_name SET OWNER [USER|ROLE] user_or_role;
3843    /// ```
3844    /// (Hive-specific)
3845    AlterConnector {
3846        /// Name of the connector to alter.
3847        name: Ident,
3848        /// Optional connector properties to set.
3849        properties: Option<Vec<SqlOption>>,
3850        /// Optional new URL for the connector.
3851        url: Option<String>,
3852        /// Optional new owner specification.
3853        owner: Option<ddl::AlterConnectorOwner>,
3854    },
3855    /// ```sql
3856    /// ALTER SESSION SET sessionParam
3857    /// ALTER SESSION UNSET <param_name> [ , <param_name> , ... ]
3858    /// ```
3859    /// See <https://docs.snowflake.com/en/sql-reference/sql/alter-session>
3860    AlterSession {
3861        /// true is to set for the session parameters, false is to unset
3862        set: bool,
3863        /// The session parameters to set or unset
3864        session_params: KeyValueOptions,
3865    },
3866    /// ```sql
3867    /// ATTACH DATABASE 'path/to/file' AS alias
3868    /// ```
3869    /// (SQLite-specific)
3870    AttachDatabase {
3871        /// The name to bind to the newly attached database
3872        schema_name: Ident,
3873        /// An expression that indicates the path to the database file
3874        database_file_name: Expr,
3875        /// true if the syntax is 'ATTACH DATABASE', false if it's just 'ATTACH'
3876        database: bool,
3877    },
3878    /// (DuckDB-specific)
3879    /// ```sql
3880    /// ATTACH 'sqlite_file.db' AS sqlite_db (READ_ONLY, TYPE SQLITE);
3881    /// ```
3882    /// See <https://duckdb.org/docs/sql/statements/attach.html>
3883    AttachDuckDBDatabase {
3884        /// `true` when `IF NOT EXISTS` was present.
3885        if_not_exists: bool,
3886        /// `true` if the syntax used `ATTACH DATABASE` rather than `ATTACH`.
3887        database: bool,
3888        /// The path identifier to the database file being attached.
3889        database_path: Ident,
3890        /// Optional alias assigned to the attached database.
3891        database_alias: Option<Ident>,
3892        /// Dialect-specific attach options (e.g., `READ_ONLY`).
3893        attach_options: Vec<AttachDuckDBDatabaseOption>,
3894    },
3895    /// (DuckDB-specific)
3896    /// ```sql
3897    /// DETACH db_alias;
3898    /// ```
3899    /// See <https://duckdb.org/docs/sql/statements/attach.html>
3900    DetachDuckDBDatabase {
3901        /// `true` when `IF EXISTS` was present.
3902        if_exists: bool,
3903        /// `true` if the syntax used `DETACH DATABASE` rather than `DETACH`.
3904        database: bool,
3905        /// Alias of the database to detach.
3906        database_alias: Ident,
3907    },
3908    /// ```sql
3909    /// DROP [TABLE, VIEW, ...]
3910    /// ```
3911    Drop {
3912        /// The type of the object to drop: TABLE, VIEW, etc.
3913        object_type: ObjectType,
3914        /// An optional `IF EXISTS` clause. (Non-standard.)
3915        if_exists: bool,
3916        /// One or more objects to drop. (ANSI SQL requires exactly one.)
3917        names: Vec<ObjectName>,
3918        /// Whether `CASCADE` was specified. This will be `false` when
3919        /// `RESTRICT` or no drop behavior at all was specified.
3920        cascade: bool,
3921        /// Whether `RESTRICT` was specified. This will be `false` when
3922        /// `CASCADE` or no drop behavior at all was specified.
3923        restrict: bool,
3924        /// Hive allows you specify whether the table's stored data will be
3925        /// deleted along with the dropped table
3926        purge: bool,
3927        /// MySQL-specific "TEMPORARY" keyword
3928        temporary: bool,
3929        /// MySQL-specific drop index syntax, which requires table specification
3930        /// See <https://dev.mysql.com/doc/refman/8.4/en/drop-index.html>
3931        table: Option<ObjectName>,
3932    },
3933    /// ```sql
3934    /// DROP FUNCTION
3935    /// ```
3936    DropFunction(DropFunction),
3937    /// ```sql
3938    /// DROP DOMAIN
3939    /// ```
3940    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-dropdomain.html)
3941    ///
3942    /// DROP DOMAIN [ IF EXISTS ] name [, ...] [ CASCADE | RESTRICT ]
3943    ///
3944    DropDomain(DropDomain),
3945    /// ```sql
3946    /// DROP PROCEDURE
3947    /// ```
3948    DropProcedure {
3949        /// `true` when `IF EXISTS` was present.
3950        if_exists: bool,
3951        /// One or more functions/procedures to drop.
3952        proc_desc: Vec<FunctionDesc>,
3953        /// Optional drop behavior (`CASCADE` or `RESTRICT`).
3954        drop_behavior: Option<DropBehavior>,
3955    },
3956    /// ```sql
3957    /// DROP SECRET
3958    /// ```
3959    DropSecret {
3960        /// `true` when `IF EXISTS` was present.
3961        if_exists: bool,
3962        /// Optional `TEMPORARY` marker.
3963        temporary: Option<bool>,
3964        /// Name of the secret to drop.
3965        name: Ident,
3966        /// Optional storage specifier identifier.
3967        storage_specifier: Option<Ident>,
3968    },
3969    ///```sql
3970    /// DROP POLICY
3971    /// ```
3972    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-droppolicy.html)
3973    DropPolicy(DropPolicy),
3974    /// ```sql
3975    /// DROP CONNECTOR
3976    /// ```
3977    /// See [Hive](https://cwiki.apache.org/confluence/pages/viewpage.action?pageId=27362034#LanguageManualDDL-DropConnector)
3978    DropConnector {
3979        /// `true` when `IF EXISTS` was present.
3980        if_exists: bool,
3981        /// Name of the connector to drop.
3982        name: Ident,
3983    },
3984    /// ```sql
3985    /// DECLARE
3986    /// ```
3987    /// Declare Cursor Variables
3988    ///
3989    /// Note: this is a PostgreSQL-specific statement,
3990    /// but may also compatible with other SQL.
3991    Declare {
3992        /// Cursor declaration statements collected by `DECLARE`.
3993        stmts: Vec<Declare>,
3994    },
3995    /// ```sql
3996    /// CREATE EXTENSION [ IF NOT EXISTS ] extension_name
3997    ///     [ WITH ] [ SCHEMA schema_name ]
3998    ///              [ VERSION version ]
3999    ///              [ CASCADE ]
4000    /// ```
4001    ///
4002    /// Note: this is a PostgreSQL-specific statement,
4003    CreateExtension(CreateExtension),
4004    /// ```sql
4005    /// CREATE COLLATION
4006    /// ```
4007    /// Note: this is a PostgreSQL-specific statement.
4008    /// <https://www.postgresql.org/docs/current/sql-createcollation.html>
4009    CreateCollation(CreateCollation),
4010    /// ```sql
4011    /// DROP EXTENSION [ IF EXISTS ] name [, ...] [ CASCADE | RESTRICT ]
4012    /// ```
4013    /// Note: this is a PostgreSQL-specific statement.
4014    /// <https://www.postgresql.org/docs/current/sql-dropextension.html>
4015    DropExtension(DropExtension),
4016    /// ```sql
4017    /// DROP OPERATOR [ IF EXISTS ] name ( { left_type | NONE } , right_type ) [, ...] [ CASCADE | RESTRICT ]
4018    /// ```
4019    /// Note: this is a PostgreSQL-specific statement.
4020    /// <https://www.postgresql.org/docs/current/sql-dropoperator.html>
4021    DropOperator(DropOperator),
4022    /// ```sql
4023    /// DROP OPERATOR FAMILY [ IF EXISTS ] name USING index_method [ CASCADE | RESTRICT ]
4024    /// ```
4025    /// Note: this is a PostgreSQL-specific statement.
4026    /// <https://www.postgresql.org/docs/current/sql-dropopfamily.html>
4027    DropOperatorFamily(DropOperatorFamily),
4028    /// ```sql
4029    /// DROP OPERATOR CLASS [ IF EXISTS ] name USING index_method [ CASCADE | RESTRICT ]
4030    /// ```
4031    /// Note: this is a PostgreSQL-specific statement.
4032    /// <https://www.postgresql.org/docs/current/sql-dropopclass.html>
4033    DropOperatorClass(DropOperatorClass),
4034    /// ```sql
4035    /// FETCH
4036    /// ```
4037    /// Retrieve rows from a query using a cursor
4038    ///
4039    /// Note: this is a PostgreSQL-specific statement,
4040    /// but may also compatible with other SQL.
4041    Fetch {
4042        /// Cursor name
4043        name: Ident,
4044        /// The fetch direction (e.g., `FORWARD`, `BACKWARD`).
4045        direction: FetchDirection,
4046        /// The fetch position (e.g., `ALL`, `NEXT`, `ABSOLUTE`).
4047        position: FetchPosition,
4048        /// Optional target table to fetch rows into.
4049        into: Option<ObjectName>,
4050    },
4051    /// ```sql
4052    /// FLUSH [NO_WRITE_TO_BINLOG | LOCAL] flush_option [, flush_option] ... | tables_option
4053    /// ```
4054    ///
4055    /// Note: this is a Mysql-specific statement,
4056    /// but may also compatible with other SQL.
4057    Flush {
4058        /// The specific flush option or object to flush.
4059        object_type: FlushType,
4060        /// Optional flush location (dialect-specific).
4061        location: Option<FlushLocation>,
4062        /// Optional channel name used for flush operations.
4063        channel: Option<String>,
4064        /// Whether a read lock was requested.
4065        read_lock: bool,
4066        /// Whether this is an export flush operation.
4067        export: bool,
4068        /// Optional list of tables involved in the flush.
4069        tables: Vec<ObjectName>,
4070    },
4071    /// ```sql
4072    /// DISCARD [ ALL | PLANS | SEQUENCES | TEMPORARY | TEMP ]
4073    /// ```
4074    ///
4075    /// Note: this is a PostgreSQL-specific statement,
4076    /// but may also compatible with other SQL.
4077    Discard {
4078        /// The kind of object(s) to discard (ALL, PLANS, etc.).
4079        object_type: DiscardObject,
4080    },
4081    /// `SHOW FUNCTIONS`
4082    ///
4083    /// Note: this is a Presto-specific statement.
4084    ShowFunctions {
4085        /// Optional filter for which functions to display.
4086        filter: Option<ShowStatementFilter>,
4087    },
4088    /// ```sql
4089    /// SHOW <variable>
4090    /// ```
4091    ///
4092    /// Note: this is a PostgreSQL-specific statement.
4093    ShowVariable {
4094        /// Variable name as one or more identifiers.
4095        variable: Vec<Ident>,
4096    },
4097    /// ```sql
4098    /// SHOW [GLOBAL | SESSION] STATUS [LIKE 'pattern' | WHERE expr]
4099    /// ```
4100    ///
4101    /// Note: this is a MySQL-specific statement.
4102    ShowStatus {
4103        /// Optional filter for which status entries to display.
4104        filter: Option<ShowStatementFilter>,
4105        /// `true` when `GLOBAL` scope was requested.
4106        global: bool,
4107        /// `true` when `SESSION` scope was requested.
4108        session: bool,
4109    },
4110    /// ```sql
4111    /// SHOW VARIABLES
4112    /// ```
4113    ///
4114    /// Note: this is a MySQL-specific statement.
4115    ShowVariables {
4116        /// Optional filter for which variables to display.
4117        filter: Option<ShowStatementFilter>,
4118        /// `true` when `GLOBAL` scope was requested.
4119        global: bool,
4120        /// `true` when `SESSION` scope was requested.
4121        session: bool,
4122    },
4123    /// ```sql
4124    /// SHOW CREATE TABLE
4125    /// ```
4126    ///
4127    /// Note: this is a MySQL-specific statement.
4128    ShowCreate {
4129        /// The kind of object being shown (TABLE, VIEW, etc.).
4130        obj_type: ShowCreateObject,
4131        /// The name of the object to show create statement for.
4132        obj_name: ObjectName,
4133    },
4134    /// ```sql
4135    /// SHOW COLUMNS
4136    /// ```
4137    ShowColumns {
4138        /// `true` when extended column information was requested.
4139        extended: bool,
4140        /// `true` when full column details were requested.
4141        full: bool,
4142        /// Additional options for `SHOW COLUMNS`.
4143        show_options: ShowStatementOptions,
4144    },
4145    /// ```sql
4146    /// SHOW CATALOGS
4147    /// ```
4148    ShowCatalogs {
4149        /// `true` when terse output format was requested.
4150        terse: bool,
4151        /// `true` when history information was requested.
4152        history: bool,
4153        /// Additional options for `SHOW CATALOGS`.
4154        show_options: ShowStatementOptions,
4155    },
4156    /// ```sql
4157    /// SHOW DATABASES
4158    /// ```
4159    ShowDatabases {
4160        /// `true` when terse output format was requested.
4161        terse: bool,
4162        /// `true` when history information was requested.
4163        history: bool,
4164        /// Additional options for `SHOW DATABASES`.
4165        show_options: ShowStatementOptions,
4166    },
4167    /// ```sql
4168    /// SHOW [FULL] PROCESSLIST
4169    /// ```
4170    ///
4171    /// Note: this is a MySQL-specific statement.
4172    ShowProcessList {
4173        /// `true` when full process information was requested.
4174        full: bool,
4175    },
4176    /// ```sql
4177    /// SHOW SCHEMAS
4178    /// ```
4179    ShowSchemas {
4180        /// `true` when terse (compact) output was requested.
4181        terse: bool,
4182        /// `true` when history information was requested.
4183        history: bool,
4184        /// Additional options for `SHOW SCHEMAS`.
4185        show_options: ShowStatementOptions,
4186    },
4187    // ```sql
4188    // SHOW {CHARACTER SET | CHARSET}
4189    // ```
4190    // [MySQL]:
4191    // <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>
4192    /// Show the available character sets (alias `CHARSET`).
4193    ShowCharset(ShowCharset),
4194    /// ```sql
4195    /// SHOW OBJECTS LIKE 'line%' IN mydb.public
4196    /// ```
4197    /// Snowflake-specific statement
4198    /// <https://docs.snowflake.com/en/sql-reference/sql/show-objects>
4199    ShowObjects(ShowObjects),
4200    /// ```sql
4201    /// SHOW TABLES
4202    /// ```
4203    ShowTables {
4204        /// `true` when terse output format was requested (compact listing).
4205        terse: bool,
4206        /// `true` when history rows are requested.
4207        history: bool,
4208        /// `true` when extended information should be shown.
4209        extended: bool,
4210        /// `true` when a full listing was requested.
4211        full: bool,
4212        /// `true` when external tables should be included.
4213        external: bool,
4214        /// Additional options for `SHOW` statements.
4215        show_options: ShowStatementOptions,
4216    },
4217    /// ```sql
4218    /// SHOW VIEWS
4219    /// ```
4220    ShowViews {
4221        /// `true` when terse output format was requested.
4222        terse: bool,
4223        /// `true` when materialized views should be included.
4224        materialized: bool,
4225        /// Additional options for `SHOW` statements.
4226        show_options: ShowStatementOptions,
4227    },
4228    /// ```sql
4229    /// SHOW COLLATION
4230    /// ```
4231    ///
4232    /// Note: this is a MySQL-specific statement.
4233    ShowCollation {
4234        /// Optional filter for which collations to display.
4235        filter: Option<ShowStatementFilter>,
4236    },
4237    /// ```sql
4238    /// `USE ...`
4239    /// ```
4240    Use(Use),
4241    /// ```sql
4242    /// START  [ TRANSACTION | WORK ] | START TRANSACTION } ...
4243    /// ```
4244    /// If `begin` is false.
4245    ///
4246    /// ```sql
4247    /// `BEGIN  [ TRANSACTION | WORK ] | START TRANSACTION } ...`
4248    /// ```
4249    /// If `begin` is true
4250    StartTransaction {
4251        /// Transaction modes such as `ISOLATION LEVEL` or `READ WRITE`.
4252        modes: Vec<TransactionMode>,
4253        /// `true` when this was parsed as `BEGIN` instead of `START`.
4254        begin: bool,
4255        /// Optional specific keyword used: `TRANSACTION` or `WORK`.
4256        transaction: Option<BeginTransactionKind>,
4257        /// Optional transaction modifier (e.g., `AND NO CHAIN`).
4258        modifier: Option<TransactionModifier>,
4259        /// List of statements belonging to the `BEGIN` block.
4260        /// Example:
4261        /// ```sql
4262        /// BEGIN
4263        ///     SELECT 1;
4264        ///     SELECT 2;
4265        /// END;
4266        /// ```
4267        statements: Vec<Statement>,
4268        /// Exception handling with exception clauses.
4269        /// Example:
4270        /// ```sql
4271        /// EXCEPTION
4272        ///     WHEN EXCEPTION_1 THEN
4273        ///         SELECT 2;
4274        ///     WHEN EXCEPTION_2 OR EXCEPTION_3 THEN
4275        ///         SELECT 3;
4276        ///     WHEN OTHER THEN
4277        ///         SELECT 4;
4278        /// ```
4279        /// <https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#beginexceptionend>
4280        /// <https://docs.snowflake.com/en/sql-reference/snowflake-scripting/exception>
4281        exception: Option<Vec<ExceptionWhen>>,
4282        /// TRUE if the statement has an `END` keyword.
4283        has_end_keyword: bool,
4284    },
4285    /// ```sql
4286    /// COMMENT ON ...
4287    /// ```
4288    ///
4289    /// Note: this is a PostgreSQL-specific statement.
4290    Comment {
4291        /// Type of object being commented (table, column, etc.).
4292        object_type: CommentObject,
4293        /// Name of the object the comment applies to.
4294        object_name: ObjectName,
4295        /// Optional comment text (None to remove comment).
4296        comment: Option<String>,
4297        /// An optional `IF EXISTS` clause. (Non-standard.)
4298        /// See <https://docs.snowflake.com/en/sql-reference/sql/comment>
4299        if_exists: bool,
4300    },
4301    /// ```sql
4302    /// COMMIT [ TRANSACTION | WORK ] [ AND [ NO ] CHAIN ]
4303    /// ```
4304    /// If `end` is false
4305    ///
4306    /// ```sql
4307    /// END [ TRY | CATCH ]
4308    /// ```
4309    /// If `end` is true
4310    Commit {
4311        /// `true` when `AND [ NO ] CHAIN` was present.
4312        chain: bool,
4313        /// `true` when this `COMMIT` was parsed as an `END` block terminator.
4314        end: bool,
4315        /// Optional transaction modifier for commit semantics.
4316        modifier: Option<TransactionModifier>,
4317    },
4318    /// ```sql
4319    /// ROLLBACK [ TRANSACTION | WORK ] [ AND [ NO ] CHAIN ] [ TO [ SAVEPOINT ] savepoint_name ]
4320    /// ```
4321    Rollback {
4322        /// `true` when `AND [ NO ] CHAIN` was present.
4323        chain: bool,
4324        /// Optional savepoint name to roll back to.
4325        savepoint: Option<Ident>,
4326    },
4327    /// ```sql
4328    /// CREATE SCHEMA
4329    /// ```
4330    CreateSchema {
4331        /// `<schema name> | AUTHORIZATION <schema authorization identifier>  | <schema name>  AUTHORIZATION <schema authorization identifier>`
4332        schema_name: SchemaName,
4333        /// `true` when `IF NOT EXISTS` was present.
4334        if_not_exists: bool,
4335        /// Schema properties.
4336        ///
4337        /// ```sql
4338        /// CREATE SCHEMA myschema WITH (key1='value1');
4339        /// ```
4340        ///
4341        /// [Trino](https://trino.io/docs/current/sql/create-schema.html)
4342        with: Option<Vec<SqlOption>>,
4343        /// Schema options.
4344        ///
4345        /// ```sql
4346        /// CREATE SCHEMA myschema OPTIONS(key1='value1');
4347        /// ```
4348        ///
4349        /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_schema_statement)
4350        options: Option<Vec<SqlOption>>,
4351        /// Default collation specification for the schema.
4352        ///
4353        /// ```sql
4354        /// CREATE SCHEMA myschema DEFAULT COLLATE 'und:ci';
4355        /// ```
4356        ///
4357        /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_schema_statement)
4358        default_collate_spec: Option<Expr>,
4359        /// Clones a schema
4360        ///
4361        /// ```sql
4362        /// CREATE SCHEMA myschema CLONE otherschema
4363        /// ```
4364        ///
4365        /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-clone#databases-schemas)
4366        clone: Option<ObjectName>,
4367    },
4368    /// ```sql
4369    /// CREATE DATABASE
4370    /// ```
4371    /// See:
4372    /// <https://docs.snowflake.com/en/sql-reference/sql/create-database>
4373    CreateDatabase {
4374        /// Database name.
4375        db_name: ObjectName,
4376        /// `IF NOT EXISTS` flag.
4377        if_not_exists: bool,
4378        /// Optional location URI.
4379        location: Option<String>,
4380        /// Optional managed location.
4381        managed_location: Option<String>,
4382        /// `OR REPLACE` flag.
4383        or_replace: bool,
4384        /// `TRANSIENT` flag.
4385        transient: bool,
4386        /// Optional clone source.
4387        clone: Option<ObjectName>,
4388        /// Optional data retention time in days.
4389        data_retention_time_in_days: Option<u64>,
4390        /// Optional maximum data extension time in days.
4391        max_data_extension_time_in_days: Option<u64>,
4392        /// Optional external volume identifier.
4393        external_volume: Option<String>,
4394        /// Optional catalog name.
4395        catalog: Option<String>,
4396        /// Whether to replace invalid characters.
4397        replace_invalid_characters: Option<bool>,
4398        /// Default DDL collation string.
4399        default_ddl_collation: Option<String>,
4400        /// Storage serialization policy.
4401        storage_serialization_policy: Option<StorageSerializationPolicy>,
4402        /// Optional comment.
4403        comment: Option<String>,
4404        /// Optional default character set (MySQL).
4405        default_charset: Option<String>,
4406        /// Optional default collation (MySQL).
4407        default_collation: Option<String>,
4408        /// Optional catalog sync identifier.
4409        catalog_sync: Option<String>,
4410        /// Catalog sync namespace mode.
4411        catalog_sync_namespace_mode: Option<CatalogSyncNamespaceMode>,
4412        /// Optional flatten delimiter for namespace sync.
4413        catalog_sync_namespace_flatten_delimiter: Option<String>,
4414        /// Optional tags for the database.
4415        with_tags: Option<Vec<Tag>>,
4416        /// Optional contact entries for the database.
4417        with_contacts: Option<Vec<ContactEntry>>,
4418    },
4419    /// ```sql
4420    /// CREATE FUNCTION
4421    /// ```
4422    ///
4423    /// Supported variants:
4424    /// 1. [Hive](https://cwiki.apache.org/confluence/display/hive/languagemanual+ddl#LanguageManualDDL-Create/Drop/ReloadFunction)
4425    /// 2. [PostgreSQL](https://www.postgresql.org/docs/15/sql-createfunction.html)
4426    /// 3. [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_function_statement)
4427    /// 4. [MsSql](https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql)
4428    CreateFunction(CreateFunction),
4429    /// CREATE TRIGGER statement. See struct [CreateTrigger] for details.
4430    CreateTrigger(CreateTrigger),
4431    /// DROP TRIGGER statement. See struct [DropTrigger] for details.
4432    DropTrigger(DropTrigger),
4433    /// ```sql
4434    /// CREATE PROCEDURE
4435    /// ```
4436    CreateProcedure {
4437        /// `OR ALTER` flag.
4438        or_alter: bool,
4439        /// Procedure name.
4440        name: ObjectName,
4441        /// Optional procedure parameters.
4442        params: Option<Vec<ProcedureParam>>,
4443        /// Optional language identifier.
4444        language: Option<Ident>,
4445        /// Procedure body statements.
4446        body: ConditionalStatements,
4447    },
4448    /// ```sql
4449    /// CREATE MACRO
4450    /// ```
4451    ///
4452    /// Supported variants:
4453    /// 1. [DuckDB](https://duckdb.org/docs/sql/statements/create_macro)
4454    CreateMacro {
4455        /// `OR REPLACE` flag.
4456        or_replace: bool,
4457        /// Whether macro is temporary.
4458        temporary: bool,
4459        /// Macro name.
4460        name: ObjectName,
4461        /// Optional macro arguments.
4462        args: Option<Vec<MacroArg>>,
4463        /// Macro definition body.
4464        definition: MacroDefinition,
4465    },
4466    /// ```sql
4467    /// CREATE STAGE
4468    /// ```
4469    /// See <https://docs.snowflake.com/en/sql-reference/sql/create-stage>
4470    CreateStage {
4471        /// `OR REPLACE` flag for stage.
4472        or_replace: bool,
4473        /// Whether stage is temporary.
4474        temporary: bool,
4475        /// `IF NOT EXISTS` flag.
4476        if_not_exists: bool,
4477        /// Stage name.
4478        name: ObjectName,
4479        /// Stage parameters.
4480        stage_params: StageParamsObject,
4481        /// Directory table parameters.
4482        directory_table_params: KeyValueOptions,
4483        /// File format options.
4484        file_format: KeyValueOptions,
4485        /// Copy options for stage.
4486        copy_options: KeyValueOptions,
4487        /// Optional comment.
4488        comment: Option<String>,
4489    },
4490    /// ```sql
4491    /// ASSERT <condition> [AS <message>]
4492    /// ```
4493    Assert {
4494        /// Assertion condition expression.
4495        condition: Expr,
4496        /// Optional message expression.
4497        message: Option<Expr>,
4498    },
4499    /// ```sql
4500    /// GRANT privileges ON objects TO grantees
4501    /// ```
4502    Grant(Grant),
4503    /// ```sql
4504    /// DENY privileges ON object TO grantees
4505    /// ```
4506    Deny(DenyStatement),
4507    /// ```sql
4508    /// REVOKE privileges ON objects FROM grantees
4509    /// ```
4510    Revoke(Revoke),
4511    /// ```sql
4512    /// DEALLOCATE [ PREPARE ] { name | ALL }
4513    /// ```
4514    ///
4515    /// Note: this is a PostgreSQL-specific statement.
4516    Deallocate {
4517        /// Name to deallocate (or `ALL`).
4518        name: Ident,
4519        /// Whether `PREPARE` keyword was present.
4520        prepare: bool,
4521    },
4522    /// ```sql
4523    /// An `EXECUTE` statement
4524    /// ```
4525    ///
4526    /// Postgres: <https://www.postgresql.org/docs/current/sql-execute.html>
4527    /// MSSQL: <https://learn.microsoft.com/en-us/sql/relational-databases/stored-procedures/execute-a-stored-procedure>
4528    /// BigQuery: <https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#execute_immediate>
4529    /// Snowflake: <https://docs.snowflake.com/en/sql-reference/sql/execute-immediate>
4530    Execute {
4531        /// Optional function/procedure name.
4532        name: Option<ObjectName>,
4533        /// Parameter expressions passed to execute.
4534        parameters: Vec<Expr>,
4535        /// Whether parentheses were present around `parameters`.
4536        has_parentheses: bool,
4537        /// Is this an `EXECUTE IMMEDIATE`.
4538        immediate: bool,
4539        /// Identifiers to capture results into.
4540        into: Vec<Ident>,
4541        /// `USING` expressions with optional aliases.
4542        using: Vec<ExprWithAlias>,
4543        /// Whether the last parameter is the return value of the procedure
4544        /// MSSQL: <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/execute-transact-sql?view=sql-server-ver17#output>
4545        output: bool,
4546        /// Whether to invoke the procedure with the default parameter values
4547        /// MSSQL: <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/execute-transact-sql?view=sql-server-ver17#default>
4548        default: bool,
4549    },
4550    /// ```sql
4551    /// PREPARE name [ ( data_type [, ...] ) ] AS statement
4552    /// ```
4553    ///
4554    /// Note: this is a PostgreSQL-specific statement.
4555    Prepare {
4556        /// Name of the prepared statement.
4557        name: Ident,
4558        /// Optional data types for parameters.
4559        data_types: Vec<DataType>,
4560        /// Statement being prepared.
4561        statement: Box<Statement>,
4562    },
4563    /// ```sql
4564    /// KILL [CONNECTION | QUERY | MUTATION]
4565    /// ```
4566    ///
4567    /// See <https://clickhouse.com/docs/en/sql-reference/statements/kill/>
4568    /// See <https://dev.mysql.com/doc/refman/8.0/en/kill.html>
4569    Kill {
4570        /// Optional kill modifier (CONNECTION, QUERY, MUTATION).
4571        modifier: Option<KillType>,
4572        // processlist_id
4573        /// The id of the process to kill.
4574        id: u64,
4575    },
4576    /// ```sql
4577    /// [EXPLAIN | DESC | DESCRIBE] TABLE
4578    /// ```
4579    /// Note: this is a MySQL-specific statement. See <https://dev.mysql.com/doc/refman/8.0/en/explain.html>
4580    ExplainTable {
4581        /// `EXPLAIN | DESC | DESCRIBE`
4582        describe_alias: DescribeAlias,
4583        /// Hive style `FORMATTED | EXTENDED`
4584        hive_format: Option<HiveDescribeFormat>,
4585        /// Snowflake and ClickHouse support `DESC|DESCRIBE TABLE <table_name>` syntax
4586        ///
4587        /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/desc-table.html)
4588        /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/describe-table)
4589        has_table_keyword: bool,
4590        /// Table name
4591        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
4592        table_name: ObjectName,
4593    },
4594    /// ```sql
4595    /// [EXPLAIN | DESC | DESCRIBE]  <statement>
4596    /// ```
4597    Explain {
4598        /// `EXPLAIN | DESC | DESCRIBE`
4599        describe_alias: DescribeAlias,
4600        /// Carry out the command and show actual run times and other statistics.
4601        analyze: bool,
4602        /// Display additional information regarding the plan.
4603        verbose: bool,
4604        /// `EXPLAIN QUERY PLAN`
4605        /// Display the query plan without running the query.
4606        ///
4607        /// [SQLite](https://sqlite.org/lang_explain.html)
4608        query_plan: bool,
4609        /// `EXPLAIN ESTIMATE`
4610        /// [Clickhouse](https://clickhouse.com/docs/en/sql-reference/statements/explain#explain-estimate)
4611        estimate: bool,
4612        /// A SQL query that specifies what to explain
4613        statement: Box<Statement>,
4614        /// Optional output format of explain
4615        format: Option<AnalyzeFormatKind>,
4616        /// Postgres style utility options, `(analyze, verbose true)`
4617        options: Option<Vec<UtilityOption>>,
4618    },
4619    /// ```sql
4620    /// SAVEPOINT
4621    /// ```
4622    /// Define a new savepoint within the current transaction
4623    Savepoint {
4624        /// Name of the savepoint being defined.
4625        name: Ident,
4626    },
4627    /// ```sql
4628    /// RELEASE [ SAVEPOINT ] savepoint_name
4629    /// ```
4630    ReleaseSavepoint {
4631        /// Name of the savepoint to release.
4632        name: Ident,
4633    },
4634    /// A `MERGE` statement.
4635    ///
4636    /// ```sql
4637    /// MERGE INTO <target_table> USING <source> ON <join_expr> { matchedClause | notMatchedClause } [ ... ]
4638    /// ```
4639    /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/merge)
4640    /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/dml-syntax#merge_statement)
4641    /// [MSSQL](https://learn.microsoft.com/en-us/sql/t-sql/statements/merge-transact-sql?view=sql-server-ver16)
4642    Merge(Merge),
4643    /// ```sql
4644    /// CACHE [ FLAG ] TABLE <table_name> [ OPTIONS('K1' = 'V1', 'K2' = V2) ] [ AS ] [ <query> ]
4645    /// ```
4646    ///
4647    /// See [Spark SQL docs] for more details.
4648    ///
4649    /// [Spark SQL docs]: https://docs.databricks.com/spark/latest/spark-sql/language-manual/sql-ref-syntax-aux-cache-cache-table.html
4650    Cache {
4651        /// Table flag
4652        table_flag: Option<ObjectName>,
4653        /// Table name
4654        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
4655        table_name: ObjectName,
4656        /// `true` if `AS` keyword was present before the query.
4657        has_as: bool,
4658        /// Table confs
4659        options: Vec<SqlOption>,
4660        /// Cache table as a Query
4661        query: Option<Box<Query>>,
4662    },
4663    /// ```sql
4664    /// UNCACHE TABLE [ IF EXISTS ]  <table_name>
4665    /// ```
4666    UNCache {
4667        /// Table name
4668        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
4669        table_name: ObjectName,
4670        /// `true` when `IF EXISTS` was present.
4671        if_exists: bool,
4672    },
4673    /// ```sql
4674    /// CREATE [ { TEMPORARY | TEMP } ] SEQUENCE [ IF NOT EXISTS ] <sequence_name>
4675    /// ```
4676    /// Define a new sequence:
4677    ///
4678    /// Note: PostgreSQL allows the option clauses (`INCREMENT`, `MINVALUE`,
4679    /// `START`, etc.) to appear in any order.
4680    /// See <https://www.postgresql.org/docs/current/sql-createsequence.html>
4681    CreateSequence {
4682        /// Whether the sequence is temporary.
4683        temporary: bool,
4684        /// `IF NOT EXISTS` flag.
4685        if_not_exists: bool,
4686        /// Sequence name.
4687        name: ObjectName,
4688        /// Optional data type for the sequence.
4689        data_type: Option<DataType>,
4690        /// Sequence options (INCREMENT, MINVALUE, etc.).
4691        sequence_options: Vec<SequenceOptions>,
4692        /// Optional `OWNED BY` target.
4693        owned_by: Option<ObjectName>,
4694    },
4695    /// A `CREATE DOMAIN` statement.
4696    CreateDomain(CreateDomain),
4697    /// ```sql
4698    /// CREATE TYPE <name>
4699    /// ```
4700    CreateType {
4701        /// Type name to create.
4702        name: ObjectName,
4703        /// Optional type representation details.
4704        representation: Option<UserDefinedTypeRepresentation>,
4705    },
4706    /// ```sql
4707    /// PRAGMA <schema-name>.<pragma-name> = <pragma-value>
4708    /// ```
4709    Pragma {
4710        /// Pragma name (possibly qualified).
4711        name: ObjectName,
4712        /// Optional pragma value.
4713        value: Option<ValueWithSpan>,
4714        /// Whether the pragma used `=`.
4715        is_eq: bool,
4716    },
4717    /// ```sql
4718    /// LOCK [ TABLE ] [ ONLY ] name [ * ] [, ...] [ IN lockmode MODE ] [ NOWAIT ]
4719    /// ```
4720    ///
4721    /// See <https://www.postgresql.org/docs/current/sql-lock.html>
4722    Lock(Lock),
4723    /// ```sql
4724    /// LOCK TABLES <table_name> [READ [LOCAL] | [LOW_PRIORITY] WRITE]
4725    /// ```
4726    /// Note: this is a MySQL-specific statement. See <https://dev.mysql.com/doc/refman/8.0/en/lock-tables.html>
4727    LockTables {
4728        /// List of tables to lock with modes.
4729        tables: Vec<LockTable>,
4730    },
4731    /// ```sql
4732    /// UNLOCK TABLES
4733    /// ```
4734    /// Note: this is a MySQL-specific statement. See <https://dev.mysql.com/doc/refman/8.0/en/lock-tables.html>
4735    UnlockTables,
4736    /// Unloads the result of a query to file
4737    ///
4738    /// [Athena](https://docs.aws.amazon.com/athena/latest/ug/unload.html):
4739    /// ```sql
4740    /// UNLOAD(statement) TO <destination> [ WITH options ]
4741    /// ```
4742    ///
4743    /// [Redshift](https://docs.aws.amazon.com/redshift/latest/dg/r_UNLOAD.html):
4744    /// ```sql
4745    /// UNLOAD('statement') TO <destination> [ OPTIONS ]
4746    /// ```
4747    Unload {
4748        /// Optional query AST to unload.
4749        query: Option<Box<Query>>,
4750        /// Optional original query text.
4751        query_text: Option<String>,
4752        /// Destination identifier.
4753        to: Ident,
4754        /// Optional IAM role/auth information.
4755        auth: Option<IamRoleKind>,
4756        /// Additional `WITH` options.
4757        with: Vec<SqlOption>,
4758        /// Legacy copy-style options.
4759        options: Vec<CopyLegacyOption>,
4760    },
4761    /// ClickHouse:
4762    /// ```sql
4763    /// OPTIMIZE TABLE [db.]name [ON CLUSTER cluster] [PARTITION partition | PARTITION ID 'partition_id'] [FINAL] [DEDUPLICATE [BY expression]]
4764    /// ```
4765    /// See ClickHouse <https://clickhouse.com/docs/en/sql-reference/statements/optimize>
4766    ///
4767    /// Databricks:
4768    /// ```sql
4769    /// OPTIMIZE table_name [WHERE predicate] [ZORDER BY (col_name1 [, ...])]
4770    /// ```
4771    /// See Databricks <https://docs.databricks.com/en/sql/language-manual/delta-optimize.html>
4772    OptimizeTable {
4773        /// Table name to optimize.
4774        name: ObjectName,
4775        /// Whether the `TABLE` keyword was present (ClickHouse uses `OPTIMIZE TABLE`, Databricks uses `OPTIMIZE`).
4776        has_table_keyword: bool,
4777        /// Optional cluster identifier.
4778        /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/optimize)
4779        on_cluster: Option<Ident>,
4780        /// Optional partition spec.
4781        /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/optimize)
4782        partition: Option<Partition>,
4783        /// Whether `FINAL` was specified.
4784        /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/optimize)
4785        include_final: bool,
4786        /// Optional deduplication settings.
4787        /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/optimize)
4788        deduplicate: Option<Deduplicate>,
4789        /// Optional WHERE predicate.
4790        /// [Databricks](https://docs.databricks.com/en/sql/language-manual/delta-optimize.html)
4791        predicate: Option<Expr>,
4792        /// Optional ZORDER BY columns.
4793        /// [Databricks](https://docs.databricks.com/en/sql/language-manual/delta-optimize.html)
4794        zorder: Option<Vec<Expr>>,
4795    },
4796    /// ```sql
4797    /// LISTEN
4798    /// ```
4799    /// listen for a notification channel
4800    ///
4801    /// See Postgres <https://www.postgresql.org/docs/current/sql-listen.html>
4802    LISTEN {
4803        /// Notification channel identifier.
4804        channel: Ident,
4805    },
4806    /// ```sql
4807    /// UNLISTEN
4808    /// ```
4809    /// stop listening for a notification
4810    ///
4811    /// See Postgres <https://www.postgresql.org/docs/current/sql-unlisten.html>
4812    UNLISTEN {
4813        /// Notification channel identifier.
4814        channel: Ident,
4815    },
4816    /// ```sql
4817    /// NOTIFY channel [ , payload ]
4818    /// ```
4819    /// send a notification event together with an optional "payload" string to channel
4820    ///
4821    /// See Postgres <https://www.postgresql.org/docs/current/sql-notify.html>
4822    NOTIFY {
4823        /// Notification channel identifier.
4824        channel: Ident,
4825        /// Optional payload string.
4826        payload: Option<String>,
4827    },
4828    /// ```sql
4829    /// LOAD DATA [LOCAL] INPATH 'filepath' [OVERWRITE] INTO TABLE tablename
4830    /// [PARTITION (partcol1=val1, partcol2=val2 ...)]
4831    /// [INPUTFORMAT 'inputformat' SERDE 'serde']
4832    /// ```
4833    /// Loading files into tables
4834    ///
4835    /// See Hive <https://cwiki.apache.org/confluence/pages/viewpage.action?pageId=27362036#LanguageManualDML-Loadingfilesintotables>
4836    LoadData {
4837        /// Whether `LOCAL` is present.
4838        local: bool,
4839        /// Input path for files to load.
4840        inpath: String,
4841        /// Whether `OVERWRITE` was specified.
4842        overwrite: bool,
4843        /// Target table name to load into.
4844        table_name: ObjectName,
4845        /// Optional partition specification.
4846        partitioned: Option<Vec<Expr>>,
4847        /// Optional table format information.
4848        table_format: Option<HiveLoadDataFormat>,
4849    },
4850    /// ```sql
4851    /// Rename TABLE tbl_name TO new_tbl_name[, tbl_name2 TO new_tbl_name2] ...
4852    /// ```
4853    /// Renames one or more tables
4854    ///
4855    /// See Mysql <https://dev.mysql.com/doc/refman/9.1/en/rename-table.html>
4856    RenameTable(Vec<RenameTable>),
4857    /// Snowflake `LIST`
4858    /// See: <https://docs.snowflake.com/en/sql-reference/sql/list>
4859    List(FileStagingCommand),
4860    /// Snowflake `REMOVE`
4861    /// See: <https://docs.snowflake.com/en/sql-reference/sql/remove>
4862    Remove(FileStagingCommand),
4863    /// RaiseError (MSSQL)
4864    /// RAISERROR ( { msg_id | msg_str | @local_variable }
4865    /// { , severity , state }
4866    /// [ , argument [ , ...n ] ] )
4867    /// [ WITH option [ , ...n ] ]
4868    /// See <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/raiserror-transact-sql?view=sql-server-ver16>
4869    RaisError {
4870        /// Error message expression or identifier.
4871        message: Box<Expr>,
4872        /// Severity expression.
4873        severity: Box<Expr>,
4874        /// State expression.
4875        state: Box<Expr>,
4876        /// Substitution arguments for the message.
4877        arguments: Vec<Expr>,
4878        /// Additional `WITH` options for RAISERROR.
4879        options: Vec<RaisErrorOption>,
4880    },
4881    /// A MSSQL `THROW` statement.
4882    Throw(ThrowStatement),
4883    /// ```sql
4884    /// PRINT msg_str | @local_variable | string_expr
4885    /// ```
4886    ///
4887    /// See: <https://learn.microsoft.com/en-us/sql/t-sql/statements/print-transact-sql>
4888    Print(PrintStatement),
4889    /// MSSQL `WAITFOR` statement.
4890    ///
4891    /// See: <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/waitfor-transact-sql>
4892    WaitFor(WaitForStatement),
4893    /// ```sql
4894    /// RETURN [ expression ]
4895    /// ```
4896    ///
4897    /// See [ReturnStatement]
4898    Return(ReturnStatement),
4899    /// Export data statement
4900    ///
4901    /// Example:
4902    /// ```sql
4903    /// EXPORT DATA OPTIONS(uri='gs://bucket/folder/*', format='PARQUET', overwrite=true) AS
4904    /// SELECT field1, field2 FROM mydataset.table1 ORDER BY field1 LIMIT 10
4905    /// ```
4906    /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/export-statements)
4907    ExportData(ExportData),
4908    /// ```sql
4909    /// CREATE [OR REPLACE] USER <user> [IF NOT EXISTS]
4910    /// ```
4911    /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-user)
4912    CreateUser(CreateUser),
4913    /// ```sql
4914    /// ALTER USER \[ IF EXISTS \] \[ <name> \]
4915    /// ```
4916    /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/alter-user)
4917    AlterUser(AlterUser),
4918    /// Re-sorts rows and reclaims space in either a specified table or all tables in the current database
4919    ///
4920    /// ```sql
4921    /// VACUUM tbl
4922    /// ```
4923    /// [Redshift](https://docs.aws.amazon.com/redshift/latest/dg/r_VACUUM_command.html)
4924    Vacuum(VacuumStatement),
4925    /// Restore the value of a run-time parameter to the default value.
4926    ///
4927    /// ```sql
4928    /// RESET configuration_parameter;
4929    /// RESET ALL;
4930    /// ```
4931    /// [PostgreSQL](https://www.postgresql.org/docs/current/sql-reset.html)
4932    Reset(ResetStatement),
4933}
4934
4935impl From<Analyze> for Statement {
4936    fn from(analyze: Analyze) -> Self {
4937        Statement::Analyze(analyze)
4938    }
4939}
4940
4941impl From<ddl::Truncate> for Statement {
4942    fn from(truncate: ddl::Truncate) -> Self {
4943        Statement::Truncate(truncate)
4944    }
4945}
4946
4947impl From<Lock> for Statement {
4948    fn from(lock: Lock) -> Self {
4949        Statement::Lock(lock)
4950    }
4951}
4952
4953impl From<ddl::Msck> for Statement {
4954    fn from(msck: ddl::Msck) -> Self {
4955        Statement::Msck(msck)
4956    }
4957}
4958
4959/// ```sql
4960/// {COPY | REVOKE} CURRENT GRANTS
4961/// ```
4962///
4963/// - [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/grant-ownership#optional-parameters)
4964#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
4965#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4966#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
4967pub enum CurrentGrantsKind {
4968    /// `COPY CURRENT GRANTS` (copy current grants to target).
4969    CopyCurrentGrants,
4970    /// `REVOKE CURRENT GRANTS` (revoke current grants from target).
4971    RevokeCurrentGrants,
4972}
4973
4974impl fmt::Display for CurrentGrantsKind {
4975    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
4976        match self {
4977            CurrentGrantsKind::CopyCurrentGrants => write!(f, "COPY CURRENT GRANTS"),
4978            CurrentGrantsKind::RevokeCurrentGrants => write!(f, "REVOKE CURRENT GRANTS"),
4979        }
4980    }
4981}
4982
4983#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
4984#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4985#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
4986/// `RAISERROR` options
4987/// See <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/raiserror-transact-sql?view=sql-server-ver16#options>
4988pub enum RaisErrorOption {
4989    /// Log the error.
4990    Log,
4991    /// Do not wait for completion.
4992    NoWait,
4993    /// Set the error state.
4994    SetError,
4995}
4996
4997impl fmt::Display for RaisErrorOption {
4998    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
4999        match self {
5000            RaisErrorOption::Log => write!(f, "LOG"),
5001            RaisErrorOption::NoWait => write!(f, "NOWAIT"),
5002            RaisErrorOption::SetError => write!(f, "SETERROR"),
5003        }
5004    }
5005}
5006
5007impl fmt::Display for Statement {
5008    /// Formats a SQL statement with support for pretty printing.
5009    ///
5010    /// When using the alternate flag (`{:#}`), the statement will be formatted with proper
5011    /// indentation and line breaks. For example:
5012    ///
5013    /// ```
5014    /// # use sqlparser::dialect::GenericDialect;
5015    /// # use sqlparser::parser::Parser;
5016    /// let sql = "SELECT a, b FROM table_1";
5017    /// let ast = Parser::parse_sql(&GenericDialect, sql).unwrap();
5018    ///
5019    /// // Regular formatting
5020    /// assert_eq!(format!("{}", ast[0]), "SELECT a, b FROM table_1");
5021    ///
5022    /// // Pretty printing
5023    /// assert_eq!(format!("{:#}", ast[0]),
5024    /// r#"SELECT
5025    ///   a,
5026    ///   b
5027    /// FROM
5028    ///   table_1"#);
5029    /// ```
5030    // Clippy thinks this function is too complicated, but it is painful to
5031    // split up without extracting structs for each `Statement` variant.
5032    #[allow(clippy::cognitive_complexity)]
5033    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
5034        match self {
5035            Statement::Flush {
5036                object_type,
5037                location,
5038                channel,
5039                read_lock,
5040                export,
5041                tables,
5042            } => {
5043                write!(f, "FLUSH")?;
5044                if let Some(location) = location {
5045                    f.write_str(" ")?;
5046                    location.fmt(f)?;
5047                }
5048                write!(f, " {object_type}")?;
5049
5050                if let Some(channel) = channel {
5051                    write!(f, " FOR CHANNEL {channel}")?;
5052                }
5053
5054                write!(
5055                    f,
5056                    "{tables}{read}{export}",
5057                    tables = if !tables.is_empty() {
5058                        format!(" {}", display_comma_separated(tables))
5059                    } else {
5060                        String::new()
5061                    },
5062                    export = if *export { " FOR EXPORT" } else { "" },
5063                    read = if *read_lock { " WITH READ LOCK" } else { "" }
5064                )
5065            }
5066            Statement::Kill { modifier, id } => {
5067                write!(f, "KILL ")?;
5068
5069                if let Some(m) = modifier {
5070                    write!(f, "{m} ")?;
5071                }
5072
5073                write!(f, "{id}")
5074            }
5075            Statement::ExplainTable {
5076                describe_alias,
5077                hive_format,
5078                has_table_keyword,
5079                table_name,
5080            } => {
5081                write!(f, "{describe_alias} ")?;
5082
5083                if let Some(format) = hive_format {
5084                    write!(f, "{format} ")?;
5085                }
5086                if *has_table_keyword {
5087                    write!(f, "TABLE ")?;
5088                }
5089
5090                write!(f, "{table_name}")
5091            }
5092            Statement::Explain {
5093                describe_alias,
5094                verbose,
5095                analyze,
5096                query_plan,
5097                estimate,
5098                statement,
5099                format,
5100                options,
5101            } => {
5102                write!(f, "{describe_alias} ")?;
5103
5104                if *query_plan {
5105                    write!(f, "QUERY PLAN ")?;
5106                }
5107                if *analyze {
5108                    write!(f, "ANALYZE ")?;
5109                }
5110                if *estimate {
5111                    write!(f, "ESTIMATE ")?;
5112                }
5113
5114                if *verbose {
5115                    write!(f, "VERBOSE ")?;
5116                }
5117
5118                if let Some(format) = format {
5119                    write!(f, "{format} ")?;
5120                }
5121
5122                if let Some(options) = options {
5123                    write!(f, "({}) ", display_comma_separated(options))?;
5124                }
5125
5126                write!(f, "{statement}")
5127            }
5128            Statement::Query(s) => s.fmt(f),
5129            Statement::Declare { stmts } => {
5130                write!(f, "DECLARE ")?;
5131                write!(f, "{}", display_separated(stmts, "; "))
5132            }
5133            Statement::Fetch {
5134                name,
5135                direction,
5136                position,
5137                into,
5138            } => {
5139                write!(f, "FETCH {direction} {position} {name}")?;
5140
5141                if let Some(into) = into {
5142                    write!(f, " INTO {into}")?;
5143                }
5144
5145                Ok(())
5146            }
5147            Statement::Directory {
5148                overwrite,
5149                local,
5150                path,
5151                file_format,
5152                source,
5153            } => {
5154                write!(
5155                    f,
5156                    "INSERT{overwrite}{local} DIRECTORY '{path}'",
5157                    overwrite = if *overwrite { " OVERWRITE" } else { "" },
5158                    local = if *local { " LOCAL" } else { "" },
5159                    path = path
5160                )?;
5161                if let Some(ref ff) = file_format {
5162                    write!(f, " STORED AS {ff}")?
5163                }
5164                write!(f, " {source}")
5165            }
5166            Statement::Msck(msck) => msck.fmt(f),
5167            Statement::Truncate(truncate) => truncate.fmt(f),
5168            Statement::Case(stmt) => {
5169                write!(f, "{stmt}")
5170            }
5171            Statement::If(stmt) => {
5172                write!(f, "{stmt}")
5173            }
5174            Statement::While(stmt) => {
5175                write!(f, "{stmt}")
5176            }
5177            Statement::Raise(stmt) => {
5178                write!(f, "{stmt}")
5179            }
5180            Statement::AttachDatabase {
5181                schema_name,
5182                database_file_name,
5183                database,
5184            } => {
5185                let keyword = if *database { "DATABASE " } else { "" };
5186                write!(f, "ATTACH {keyword}{database_file_name} AS {schema_name}")
5187            }
5188            Statement::AttachDuckDBDatabase {
5189                if_not_exists,
5190                database,
5191                database_path,
5192                database_alias,
5193                attach_options,
5194            } => {
5195                write!(
5196                    f,
5197                    "ATTACH{database}{if_not_exists} {database_path}",
5198                    database = if *database { " DATABASE" } else { "" },
5199                    if_not_exists = if *if_not_exists { " IF NOT EXISTS" } else { "" },
5200                )?;
5201                if let Some(alias) = database_alias {
5202                    write!(f, " AS {alias}")?;
5203                }
5204                if !attach_options.is_empty() {
5205                    write!(f, " ({})", display_comma_separated(attach_options))?;
5206                }
5207                Ok(())
5208            }
5209            Statement::DetachDuckDBDatabase {
5210                if_exists,
5211                database,
5212                database_alias,
5213            } => {
5214                write!(
5215                    f,
5216                    "DETACH{database}{if_exists} {database_alias}",
5217                    database = if *database { " DATABASE" } else { "" },
5218                    if_exists = if *if_exists { " IF EXISTS" } else { "" },
5219                )?;
5220                Ok(())
5221            }
5222            Statement::Analyze(analyze) => analyze.fmt(f),
5223            Statement::Insert(insert) => insert.fmt(f),
5224            Statement::Install {
5225                extension_name: name,
5226            } => write!(f, "INSTALL {name}"),
5227
5228            Statement::Load {
5229                extension_name: name,
5230            } => write!(f, "LOAD {name}"),
5231
5232            Statement::Call(function) => write!(f, "CALL {function}"),
5233
5234            Statement::Copy {
5235                source,
5236                to,
5237                target,
5238                options,
5239                legacy_options,
5240                values,
5241            } => {
5242                write!(f, "COPY")?;
5243                match source {
5244                    CopySource::Query(query) => write!(f, " ({query})")?,
5245                    CopySource::Table {
5246                        table_name,
5247                        columns,
5248                    } => {
5249                        write!(f, " {table_name}")?;
5250                        if !columns.is_empty() {
5251                            write!(f, " ({})", display_comma_separated(columns))?;
5252                        }
5253                    }
5254                }
5255                write!(f, " {} {}", if *to { "TO" } else { "FROM" }, target)?;
5256                if !options.is_empty() {
5257                    write!(f, " ({})", display_comma_separated(options))?;
5258                }
5259                if !legacy_options.is_empty() {
5260                    write!(f, " {}", display_separated(legacy_options, " "))?;
5261                }
5262                if !values.is_empty() {
5263                    writeln!(f, ";")?;
5264                    let mut delim = "";
5265                    for v in values {
5266                        write!(f, "{delim}")?;
5267                        delim = "\t";
5268                        if let Some(v) = v {
5269                            write!(f, "{v}")?;
5270                        } else {
5271                            write!(f, "\\N")?;
5272                        }
5273                    }
5274                    write!(f, "\n\\.")?;
5275                }
5276                Ok(())
5277            }
5278            Statement::Update(update) => update.fmt(f),
5279            Statement::Delete(delete) => delete.fmt(f),
5280            Statement::Open(open) => open.fmt(f),
5281            Statement::Close { cursor } => {
5282                write!(f, "CLOSE {cursor}")?;
5283
5284                Ok(())
5285            }
5286            Statement::CreateDatabase {
5287                db_name,
5288                if_not_exists,
5289                location,
5290                managed_location,
5291                or_replace,
5292                transient,
5293                clone,
5294                data_retention_time_in_days,
5295                max_data_extension_time_in_days,
5296                external_volume,
5297                catalog,
5298                replace_invalid_characters,
5299                default_ddl_collation,
5300                storage_serialization_policy,
5301                comment,
5302                default_charset,
5303                default_collation,
5304                catalog_sync,
5305                catalog_sync_namespace_mode,
5306                catalog_sync_namespace_flatten_delimiter,
5307                with_tags,
5308                with_contacts,
5309            } => {
5310                write!(
5311                    f,
5312                    "CREATE {or_replace}{transient}DATABASE {if_not_exists}{name}",
5313                    or_replace = if *or_replace { "OR REPLACE " } else { "" },
5314                    transient = if *transient { "TRANSIENT " } else { "" },
5315                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
5316                    name = db_name,
5317                )?;
5318
5319                if let Some(l) = location {
5320                    write!(f, " LOCATION '{l}'")?;
5321                }
5322                if let Some(ml) = managed_location {
5323                    write!(f, " MANAGEDLOCATION '{ml}'")?;
5324                }
5325                if let Some(clone) = clone {
5326                    write!(f, " CLONE {clone}")?;
5327                }
5328
5329                if let Some(value) = data_retention_time_in_days {
5330                    write!(f, " DATA_RETENTION_TIME_IN_DAYS = {value}")?;
5331                }
5332
5333                if let Some(value) = max_data_extension_time_in_days {
5334                    write!(f, " MAX_DATA_EXTENSION_TIME_IN_DAYS = {value}")?;
5335                }
5336
5337                if let Some(vol) = external_volume {
5338                    write!(f, " EXTERNAL_VOLUME = '{vol}'")?;
5339                }
5340
5341                if let Some(cat) = catalog {
5342                    write!(f, " CATALOG = '{cat}'")?;
5343                }
5344
5345                if let Some(true) = replace_invalid_characters {
5346                    write!(f, " REPLACE_INVALID_CHARACTERS = TRUE")?;
5347                } else if let Some(false) = replace_invalid_characters {
5348                    write!(f, " REPLACE_INVALID_CHARACTERS = FALSE")?;
5349                }
5350
5351                if let Some(collation) = default_ddl_collation {
5352                    write!(f, " DEFAULT_DDL_COLLATION = '{collation}'")?;
5353                }
5354
5355                if let Some(policy) = storage_serialization_policy {
5356                    write!(f, " STORAGE_SERIALIZATION_POLICY = {policy}")?;
5357                }
5358
5359                if let Some(comment) = comment {
5360                    write!(f, " COMMENT = '{comment}'")?;
5361                }
5362
5363                if let Some(charset) = default_charset {
5364                    write!(f, " DEFAULT CHARACTER SET {charset}")?;
5365                }
5366
5367                if let Some(collation) = default_collation {
5368                    write!(f, " DEFAULT COLLATE {collation}")?;
5369                }
5370
5371                if let Some(sync) = catalog_sync {
5372                    write!(f, " CATALOG_SYNC = '{sync}'")?;
5373                }
5374
5375                if let Some(mode) = catalog_sync_namespace_mode {
5376                    write!(f, " CATALOG_SYNC_NAMESPACE_MODE = {mode}")?;
5377                }
5378
5379                if let Some(delim) = catalog_sync_namespace_flatten_delimiter {
5380                    write!(f, " CATALOG_SYNC_NAMESPACE_FLATTEN_DELIMITER = '{delim}'")?;
5381                }
5382
5383                if let Some(tags) = with_tags {
5384                    write!(f, " WITH TAG ({})", display_comma_separated(tags))?;
5385                }
5386
5387                if let Some(contacts) = with_contacts {
5388                    write!(f, " WITH CONTACT ({})", display_comma_separated(contacts))?;
5389                }
5390                Ok(())
5391            }
5392            Statement::CreateFunction(create_function) => create_function.fmt(f),
5393            Statement::CreateDomain(create_domain) => create_domain.fmt(f),
5394            Statement::CreateTrigger(create_trigger) => create_trigger.fmt(f),
5395            Statement::DropTrigger(drop_trigger) => drop_trigger.fmt(f),
5396            Statement::CreateProcedure {
5397                name,
5398                or_alter,
5399                params,
5400                language,
5401                body,
5402            } => {
5403                write!(
5404                    f,
5405                    "CREATE {or_alter}PROCEDURE {name}",
5406                    or_alter = if *or_alter { "OR ALTER " } else { "" },
5407                    name = name
5408                )?;
5409
5410                if let Some(p) = params {
5411                    if !p.is_empty() {
5412                        write!(f, " ({})", display_comma_separated(p))?;
5413                    }
5414                }
5415
5416                if let Some(language) = language {
5417                    write!(f, " LANGUAGE {language}")?;
5418                }
5419
5420                write!(f, " AS {body}")
5421            }
5422            Statement::CreateMacro {
5423                or_replace,
5424                temporary,
5425                name,
5426                args,
5427                definition,
5428            } => {
5429                write!(
5430                    f,
5431                    "CREATE {or_replace}{temp}MACRO {name}",
5432                    temp = if *temporary { "TEMPORARY " } else { "" },
5433                    or_replace = if *or_replace { "OR REPLACE " } else { "" },
5434                )?;
5435                if let Some(args) = args {
5436                    write!(f, "({})", display_comma_separated(args))?;
5437                }
5438                match definition {
5439                    MacroDefinition::Expr(expr) => write!(f, " AS {expr}")?,
5440                    MacroDefinition::Table(query) => write!(f, " AS TABLE {query}")?,
5441                }
5442                Ok(())
5443            }
5444            Statement::CreateView(create_view) => create_view.fmt(f),
5445            Statement::CreateTable(create_table) => create_table.fmt(f),
5446            Statement::LoadData {
5447                local,
5448                inpath,
5449                overwrite,
5450                table_name,
5451                partitioned,
5452                table_format,
5453            } => {
5454                write!(
5455                    f,
5456                    "LOAD DATA {local}INPATH '{inpath}' {overwrite}INTO TABLE {table_name}",
5457                    local = if *local { "LOCAL " } else { "" },
5458                    inpath = inpath,
5459                    overwrite = if *overwrite { "OVERWRITE " } else { "" },
5460                    table_name = table_name,
5461                )?;
5462                if let Some(ref parts) = &partitioned {
5463                    if !parts.is_empty() {
5464                        write!(f, " PARTITION ({})", display_comma_separated(parts))?;
5465                    }
5466                }
5467                if let Some(HiveLoadDataFormat {
5468                    serde,
5469                    input_format,
5470                }) = &table_format
5471                {
5472                    write!(f, " INPUTFORMAT {input_format} SERDE {serde}")?;
5473                }
5474                Ok(())
5475            }
5476            Statement::CreateVirtualTable {
5477                name,
5478                if_not_exists,
5479                module_name,
5480                module_args,
5481            } => {
5482                write!(
5483                    f,
5484                    "CREATE VIRTUAL TABLE {if_not_exists}{name} USING {module_name}",
5485                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
5486                    name = name,
5487                    module_name = module_name
5488                )?;
5489                if !module_args.is_empty() {
5490                    write!(f, " ({})", display_comma_separated(module_args))?;
5491                }
5492                Ok(())
5493            }
5494            Statement::CreateIndex(create_index) => create_index.fmt(f),
5495            Statement::CreateExtension(create_extension) => write!(f, "{create_extension}"),
5496            Statement::CreateCollation(create_collation) => write!(f, "{create_collation}"),
5497            Statement::DropExtension(drop_extension) => write!(f, "{drop_extension}"),
5498            Statement::DropOperator(drop_operator) => write!(f, "{drop_operator}"),
5499            Statement::DropOperatorFamily(drop_operator_family) => {
5500                write!(f, "{drop_operator_family}")
5501            }
5502            Statement::DropOperatorClass(drop_operator_class) => {
5503                write!(f, "{drop_operator_class}")
5504            }
5505            Statement::CreateRole(create_role) => write!(f, "{create_role}"),
5506            Statement::CreateSecret {
5507                or_replace,
5508                temporary,
5509                if_not_exists,
5510                name,
5511                storage_specifier,
5512                secret_type,
5513                options,
5514            } => {
5515                write!(
5516                    f,
5517                    "CREATE {or_replace}",
5518                    or_replace = if *or_replace { "OR REPLACE " } else { "" },
5519                )?;
5520                if let Some(t) = temporary {
5521                    write!(f, "{}", if *t { "TEMPORARY " } else { "PERSISTENT " })?;
5522                }
5523                write!(
5524                    f,
5525                    "SECRET {if_not_exists}",
5526                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
5527                )?;
5528                if let Some(n) = name {
5529                    write!(f, "{n} ")?;
5530                };
5531                if let Some(s) = storage_specifier {
5532                    write!(f, "IN {s} ")?;
5533                }
5534                write!(f, "( TYPE {secret_type}",)?;
5535                if !options.is_empty() {
5536                    write!(f, ", {o}", o = display_comma_separated(options))?;
5537                }
5538                write!(f, " )")?;
5539                Ok(())
5540            }
5541            Statement::CreateServer(stmt) => {
5542                write!(f, "{stmt}")
5543            }
5544            Statement::CreatePolicy(policy) => write!(f, "{policy}"),
5545            Statement::CreateConnector(create_connector) => create_connector.fmt(f),
5546            Statement::CreateOperator(create_operator) => create_operator.fmt(f),
5547            Statement::CreateOperatorFamily(create_operator_family) => {
5548                create_operator_family.fmt(f)
5549            }
5550            Statement::CreateOperatorClass(create_operator_class) => create_operator_class.fmt(f),
5551            Statement::AlterTable(alter_table) => write!(f, "{alter_table}"),
5552            Statement::AlterIndex { name, operation } => {
5553                write!(f, "ALTER INDEX {name} {operation}")
5554            }
5555            Statement::AlterView {
5556                name,
5557                columns,
5558                query,
5559                with_options,
5560            } => {
5561                write!(f, "ALTER VIEW {name}")?;
5562                if !with_options.is_empty() {
5563                    write!(f, " WITH ({})", display_comma_separated(with_options))?;
5564                }
5565                if !columns.is_empty() {
5566                    write!(f, " ({})", display_comma_separated(columns))?;
5567                }
5568                write!(f, " AS {query}")
5569            }
5570            Statement::AlterFunction(alter_function) => write!(f, "{alter_function}"),
5571            Statement::AlterType(AlterType { name, operation }) => {
5572                write!(f, "ALTER TYPE {name} {operation}")
5573            }
5574            Statement::AlterCollation(alter_collation) => write!(f, "{alter_collation}"),
5575            Statement::AlterOperator(alter_operator) => write!(f, "{alter_operator}"),
5576            Statement::AlterOperatorFamily(alter_operator_family) => {
5577                write!(f, "{alter_operator_family}")
5578            }
5579            Statement::AlterOperatorClass(alter_operator_class) => {
5580                write!(f, "{alter_operator_class}")
5581            }
5582            Statement::AlterRole { name, operation } => {
5583                write!(f, "ALTER ROLE {name} {operation}")
5584            }
5585            Statement::AlterPolicy(alter_policy) => write!(f, "{alter_policy}"),
5586            Statement::AlterConnector {
5587                name,
5588                properties,
5589                url,
5590                owner,
5591            } => {
5592                write!(f, "ALTER CONNECTOR {name}")?;
5593                if let Some(properties) = properties {
5594                    write!(
5595                        f,
5596                        " SET DCPROPERTIES({})",
5597                        display_comma_separated(properties)
5598                    )?;
5599                }
5600                if let Some(url) = url {
5601                    write!(f, " SET URL '{url}'")?;
5602                }
5603                if let Some(owner) = owner {
5604                    write!(f, " SET OWNER {owner}")?;
5605                }
5606                Ok(())
5607            }
5608            Statement::AlterSession {
5609                set,
5610                session_params,
5611            } => {
5612                write!(
5613                    f,
5614                    "ALTER SESSION {set}",
5615                    set = if *set { "SET" } else { "UNSET" }
5616                )?;
5617                if !session_params.options.is_empty() {
5618                    if *set {
5619                        write!(f, " {session_params}")?;
5620                    } else {
5621                        let options = session_params
5622                            .options
5623                            .iter()
5624                            .map(|p| p.option_name.clone())
5625                            .collect::<Vec<_>>();
5626                        write!(f, " {}", display_separated(&options, ", "))?;
5627                    }
5628                }
5629                Ok(())
5630            }
5631            Statement::Drop {
5632                object_type,
5633                if_exists,
5634                names,
5635                cascade,
5636                restrict,
5637                purge,
5638                temporary,
5639                table,
5640            } => {
5641                write!(
5642                    f,
5643                    "DROP {}{}{} {}{}{}{}",
5644                    if *temporary { "TEMPORARY " } else { "" },
5645                    object_type,
5646                    if *if_exists { " IF EXISTS" } else { "" },
5647                    display_comma_separated(names),
5648                    if *cascade { " CASCADE" } else { "" },
5649                    if *restrict { " RESTRICT" } else { "" },
5650                    if *purge { " PURGE" } else { "" },
5651                )?;
5652                if let Some(table_name) = table.as_ref() {
5653                    write!(f, " ON {table_name}")?;
5654                };
5655                Ok(())
5656            }
5657            Statement::DropFunction(drop_function) => write!(f, "{drop_function}"),
5658            Statement::DropDomain(DropDomain {
5659                if_exists,
5660                name,
5661                drop_behavior,
5662            }) => {
5663                write!(
5664                    f,
5665                    "DROP DOMAIN{} {name}",
5666                    if *if_exists { " IF EXISTS" } else { "" },
5667                )?;
5668                if let Some(op) = drop_behavior {
5669                    write!(f, " {op}")?;
5670                }
5671                Ok(())
5672            }
5673            Statement::DropProcedure {
5674                if_exists,
5675                proc_desc,
5676                drop_behavior,
5677            } => {
5678                write!(
5679                    f,
5680                    "DROP PROCEDURE{} {}",
5681                    if *if_exists { " IF EXISTS" } else { "" },
5682                    display_comma_separated(proc_desc),
5683                )?;
5684                if let Some(op) = drop_behavior {
5685                    write!(f, " {op}")?;
5686                }
5687                Ok(())
5688            }
5689            Statement::DropSecret {
5690                if_exists,
5691                temporary,
5692                name,
5693                storage_specifier,
5694            } => {
5695                write!(f, "DROP ")?;
5696                if let Some(t) = temporary {
5697                    write!(f, "{}", if *t { "TEMPORARY " } else { "PERSISTENT " })?;
5698                }
5699                write!(
5700                    f,
5701                    "SECRET {if_exists}{name}",
5702                    if_exists = if *if_exists { "IF EXISTS " } else { "" },
5703                )?;
5704                if let Some(s) = storage_specifier {
5705                    write!(f, " FROM {s}")?;
5706                }
5707                Ok(())
5708            }
5709            Statement::DropPolicy(policy) => write!(f, "{policy}"),
5710            Statement::DropConnector { if_exists, name } => {
5711                write!(
5712                    f,
5713                    "DROP CONNECTOR {if_exists}{name}",
5714                    if_exists = if *if_exists { "IF EXISTS " } else { "" }
5715                )?;
5716                Ok(())
5717            }
5718            Statement::Discard { object_type } => {
5719                write!(f, "DISCARD {object_type}")?;
5720                Ok(())
5721            }
5722            Self::Set(set) => write!(f, "{set}"),
5723            Statement::ShowVariable { variable } => {
5724                write!(f, "SHOW")?;
5725                if !variable.is_empty() {
5726                    write!(f, " {}", display_separated(variable, " "))?;
5727                }
5728                Ok(())
5729            }
5730            Statement::ShowStatus {
5731                filter,
5732                global,
5733                session,
5734            } => {
5735                write!(f, "SHOW")?;
5736                if *global {
5737                    write!(f, " GLOBAL")?;
5738                }
5739                if *session {
5740                    write!(f, " SESSION")?;
5741                }
5742                write!(f, " STATUS")?;
5743                if let Some(filter) = filter {
5744                    write!(f, " {}", filter)?;
5745                }
5746                Ok(())
5747            }
5748            Statement::ShowVariables {
5749                filter,
5750                global,
5751                session,
5752            } => {
5753                write!(f, "SHOW")?;
5754                if *global {
5755                    write!(f, " GLOBAL")?;
5756                }
5757                if *session {
5758                    write!(f, " SESSION")?;
5759                }
5760                write!(f, " VARIABLES")?;
5761                if let Some(filter) = filter {
5762                    write!(f, " {}", filter)?;
5763                }
5764                Ok(())
5765            }
5766            Statement::ShowCreate { obj_type, obj_name } => {
5767                write!(f, "SHOW CREATE {obj_type} {obj_name}",)?;
5768                Ok(())
5769            }
5770            Statement::ShowColumns {
5771                extended,
5772                full,
5773                show_options,
5774            } => {
5775                write!(
5776                    f,
5777                    "SHOW {extended}{full}COLUMNS{show_options}",
5778                    extended = if *extended { "EXTENDED " } else { "" },
5779                    full = if *full { "FULL " } else { "" },
5780                )?;
5781                Ok(())
5782            }
5783            Statement::ShowDatabases {
5784                terse,
5785                history,
5786                show_options,
5787            } => {
5788                write!(
5789                    f,
5790                    "SHOW {terse}DATABASES{history}{show_options}",
5791                    terse = if *terse { "TERSE " } else { "" },
5792                    history = if *history { " HISTORY" } else { "" },
5793                )?;
5794                Ok(())
5795            }
5796            Statement::ShowCatalogs {
5797                terse,
5798                history,
5799                show_options,
5800            } => {
5801                write!(
5802                    f,
5803                    "SHOW {terse}CATALOGS{history}{show_options}",
5804                    terse = if *terse { "TERSE " } else { "" },
5805                    history = if *history { " HISTORY" } else { "" },
5806                )?;
5807                Ok(())
5808            }
5809            Statement::ShowProcessList { full } => {
5810                write!(
5811                    f,
5812                    "SHOW {full}PROCESSLIST",
5813                    full = if *full { "FULL " } else { "" },
5814                )?;
5815                Ok(())
5816            }
5817            Statement::ShowSchemas {
5818                terse,
5819                history,
5820                show_options,
5821            } => {
5822                write!(
5823                    f,
5824                    "SHOW {terse}SCHEMAS{history}{show_options}",
5825                    terse = if *terse { "TERSE " } else { "" },
5826                    history = if *history { " HISTORY" } else { "" },
5827                )?;
5828                Ok(())
5829            }
5830            Statement::ShowObjects(ShowObjects {
5831                terse,
5832                show_options,
5833            }) => {
5834                write!(
5835                    f,
5836                    "SHOW {terse}OBJECTS{show_options}",
5837                    terse = if *terse { "TERSE " } else { "" },
5838                )?;
5839                Ok(())
5840            }
5841            Statement::ShowTables {
5842                terse,
5843                history,
5844                extended,
5845                full,
5846                external,
5847                show_options,
5848            } => {
5849                write!(
5850                    f,
5851                    "SHOW {terse}{extended}{full}{external}TABLES{history}{show_options}",
5852                    terse = if *terse { "TERSE " } else { "" },
5853                    extended = if *extended { "EXTENDED " } else { "" },
5854                    full = if *full { "FULL " } else { "" },
5855                    external = if *external { "EXTERNAL " } else { "" },
5856                    history = if *history { " HISTORY" } else { "" },
5857                )?;
5858                Ok(())
5859            }
5860            Statement::ShowViews {
5861                terse,
5862                materialized,
5863                show_options,
5864            } => {
5865                write!(
5866                    f,
5867                    "SHOW {terse}{materialized}VIEWS{show_options}",
5868                    terse = if *terse { "TERSE " } else { "" },
5869                    materialized = if *materialized { "MATERIALIZED " } else { "" }
5870                )?;
5871                Ok(())
5872            }
5873            Statement::ShowFunctions { filter } => {
5874                write!(f, "SHOW FUNCTIONS")?;
5875                if let Some(filter) = filter {
5876                    write!(f, " {filter}")?;
5877                }
5878                Ok(())
5879            }
5880            Statement::Use(use_expr) => use_expr.fmt(f),
5881            Statement::ShowCollation { filter } => {
5882                write!(f, "SHOW COLLATION")?;
5883                if let Some(filter) = filter {
5884                    write!(f, " {filter}")?;
5885                }
5886                Ok(())
5887            }
5888            Statement::ShowCharset(show_stm) => show_stm.fmt(f),
5889            Statement::StartTransaction {
5890                modes,
5891                begin: syntax_begin,
5892                transaction,
5893                modifier,
5894                statements,
5895                exception,
5896                has_end_keyword,
5897            } => {
5898                if *syntax_begin {
5899                    if let Some(modifier) = *modifier {
5900                        write!(f, "BEGIN {modifier}")?;
5901                    } else {
5902                        write!(f, "BEGIN")?;
5903                    }
5904                } else {
5905                    write!(f, "START")?;
5906                }
5907                if let Some(transaction) = transaction {
5908                    write!(f, " {transaction}")?;
5909                }
5910                if !modes.is_empty() {
5911                    write!(f, " {}", display_comma_separated(modes))?;
5912                }
5913                if !statements.is_empty() {
5914                    write!(f, " ")?;
5915                    format_statement_list(f, statements)?;
5916                }
5917                if let Some(exception_when) = exception {
5918                    write!(f, " EXCEPTION")?;
5919                    for when in exception_when {
5920                        write!(f, " {when}")?;
5921                    }
5922                }
5923                if *has_end_keyword {
5924                    write!(f, " END")?;
5925                }
5926                Ok(())
5927            }
5928            Statement::Commit {
5929                chain,
5930                end: end_syntax,
5931                modifier,
5932            } => {
5933                if *end_syntax {
5934                    write!(f, "END")?;
5935                    if let Some(modifier) = *modifier {
5936                        write!(f, " {modifier}")?;
5937                    }
5938                    if *chain {
5939                        write!(f, " AND CHAIN")?;
5940                    }
5941                } else {
5942                    write!(f, "COMMIT{}", if *chain { " AND CHAIN" } else { "" })?;
5943                }
5944                Ok(())
5945            }
5946            Statement::Rollback { chain, savepoint } => {
5947                write!(f, "ROLLBACK")?;
5948
5949                if *chain {
5950                    write!(f, " AND CHAIN")?;
5951                }
5952
5953                if let Some(savepoint) = savepoint {
5954                    write!(f, " TO SAVEPOINT {savepoint}")?;
5955                }
5956
5957                Ok(())
5958            }
5959            Statement::CreateSchema {
5960                schema_name,
5961                if_not_exists,
5962                with,
5963                options,
5964                default_collate_spec,
5965                clone,
5966            } => {
5967                write!(
5968                    f,
5969                    "CREATE SCHEMA {if_not_exists}{name}",
5970                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
5971                    name = schema_name
5972                )?;
5973
5974                if let Some(collate) = default_collate_spec {
5975                    write!(f, " DEFAULT COLLATE {collate}")?;
5976                }
5977
5978                if let Some(with) = with {
5979                    write!(f, " WITH ({})", display_comma_separated(with))?;
5980                }
5981
5982                if let Some(options) = options {
5983                    write!(f, " OPTIONS({})", display_comma_separated(options))?;
5984                }
5985
5986                if let Some(clone) = clone {
5987                    write!(f, " CLONE {clone}")?;
5988                }
5989                Ok(())
5990            }
5991            Statement::Assert { condition, message } => {
5992                write!(f, "ASSERT {condition}")?;
5993                if let Some(m) = message {
5994                    write!(f, " AS {m}")?;
5995                }
5996                Ok(())
5997            }
5998            Statement::Grant(grant) => write!(f, "{grant}"),
5999            Statement::Deny(s) => write!(f, "{s}"),
6000            Statement::Revoke(revoke) => write!(f, "{revoke}"),
6001            Statement::Deallocate { name, prepare } => write!(
6002                f,
6003                "DEALLOCATE {prepare}{name}",
6004                prepare = if *prepare { "PREPARE " } else { "" },
6005                name = name,
6006            ),
6007            Statement::Execute {
6008                name,
6009                parameters,
6010                has_parentheses,
6011                immediate,
6012                into,
6013                using,
6014                output,
6015                default,
6016            } => {
6017                let (open, close) = if *has_parentheses {
6018                    // Space before `(` only when there is no name directly preceding it.
6019                    (if name.is_some() { "(" } else { " (" }, ")")
6020                } else {
6021                    (if parameters.is_empty() { "" } else { " " }, "")
6022                };
6023                write!(f, "EXECUTE")?;
6024                if *immediate {
6025                    write!(f, " IMMEDIATE")?;
6026                }
6027                if let Some(name) = name {
6028                    write!(f, " {name}")?;
6029                }
6030                write!(f, "{open}{}{close}", display_comma_separated(parameters),)?;
6031                if !into.is_empty() {
6032                    write!(f, " INTO {}", display_comma_separated(into))?;
6033                }
6034                if !using.is_empty() {
6035                    write!(f, " USING {}", display_comma_separated(using))?;
6036                };
6037                if *output {
6038                    write!(f, " OUTPUT")?;
6039                }
6040                if *default {
6041                    write!(f, " DEFAULT")?;
6042                }
6043                Ok(())
6044            }
6045            Statement::Prepare {
6046                name,
6047                data_types,
6048                statement,
6049            } => {
6050                write!(f, "PREPARE {name} ")?;
6051                if !data_types.is_empty() {
6052                    write!(f, "({}) ", display_comma_separated(data_types))?;
6053                }
6054                write!(f, "AS {statement}")
6055            }
6056            Statement::Comment {
6057                object_type,
6058                object_name,
6059                comment,
6060                if_exists,
6061            } => {
6062                write!(f, "COMMENT ")?;
6063                if *if_exists {
6064                    write!(f, "IF EXISTS ")?
6065                };
6066                write!(f, "ON {object_type} {object_name} IS ")?;
6067                if let Some(c) = comment {
6068                    write!(f, "'{c}'")
6069                } else {
6070                    write!(f, "NULL")
6071                }
6072            }
6073            Statement::Savepoint { name } => {
6074                write!(f, "SAVEPOINT ")?;
6075                write!(f, "{name}")
6076            }
6077            Statement::ReleaseSavepoint { name } => {
6078                write!(f, "RELEASE SAVEPOINT {name}")
6079            }
6080            Statement::Merge(merge) => merge.fmt(f),
6081            Statement::Cache {
6082                table_name,
6083                table_flag,
6084                has_as,
6085                options,
6086                query,
6087            } => {
6088                if let Some(table_flag) = table_flag {
6089                    write!(f, "CACHE {table_flag} TABLE {table_name}")?;
6090                } else {
6091                    write!(f, "CACHE TABLE {table_name}")?;
6092                }
6093
6094                if !options.is_empty() {
6095                    write!(f, " OPTIONS({})", display_comma_separated(options))?;
6096                }
6097
6098                match (*has_as, query) {
6099                    (true, Some(query)) => write!(f, " AS {query}"),
6100                    (true, None) => f.write_str(" AS"),
6101                    (false, Some(query)) => write!(f, " {query}"),
6102                    (false, None) => Ok(()),
6103                }
6104            }
6105            Statement::UNCache {
6106                table_name,
6107                if_exists,
6108            } => {
6109                if *if_exists {
6110                    write!(f, "UNCACHE TABLE IF EXISTS {table_name}")
6111                } else {
6112                    write!(f, "UNCACHE TABLE {table_name}")
6113                }
6114            }
6115            Statement::CreateSequence {
6116                temporary,
6117                if_not_exists,
6118                name,
6119                data_type,
6120                sequence_options,
6121                owned_by,
6122            } => {
6123                let as_type: String = if let Some(dt) = data_type.as_ref() {
6124                    //Cannot use format!(" AS {}", dt), due to format! is not available in --target thumbv6m-none-eabi
6125                    // " AS ".to_owned() + &dt.to_string()
6126                    [" AS ", &dt.to_string()].concat()
6127                } else {
6128                    "".to_string()
6129                };
6130                write!(
6131                    f,
6132                    "CREATE {temporary}SEQUENCE {if_not_exists}{name}{as_type}",
6133                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
6134                    temporary = if *temporary { "TEMPORARY " } else { "" },
6135                    name = name,
6136                    as_type = as_type
6137                )?;
6138                for sequence_option in sequence_options {
6139                    write!(f, "{sequence_option}")?;
6140                }
6141                if let Some(ob) = owned_by.as_ref() {
6142                    write!(f, " OWNED BY {ob}")?;
6143                }
6144                write!(f, "")
6145            }
6146            Statement::CreateStage {
6147                or_replace,
6148                temporary,
6149                if_not_exists,
6150                name,
6151                stage_params,
6152                directory_table_params,
6153                file_format,
6154                copy_options,
6155                comment,
6156                ..
6157            } => {
6158                write!(
6159                    f,
6160                    "CREATE {or_replace}{temp}STAGE {if_not_exists}{name}{stage_params}",
6161                    temp = if *temporary { "TEMPORARY " } else { "" },
6162                    or_replace = if *or_replace { "OR REPLACE " } else { "" },
6163                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
6164                )?;
6165                if !directory_table_params.options.is_empty() {
6166                    write!(f, " DIRECTORY=({directory_table_params})")?;
6167                }
6168                if !file_format.options.is_empty() {
6169                    write!(f, " FILE_FORMAT=({file_format})")?;
6170                }
6171                if !copy_options.options.is_empty() {
6172                    write!(f, " COPY_OPTIONS=({copy_options})")?;
6173                }
6174                if let Some(comment) = comment {
6175                    write!(f, " COMMENT='{}'", comment)?;
6176                }
6177                Ok(())
6178            }
6179            Statement::CopyIntoSnowflake {
6180                kind,
6181                into,
6182                into_columns,
6183                from_obj,
6184                from_obj_alias,
6185                stage_params,
6186                from_transformations,
6187                from_query,
6188                files,
6189                pattern,
6190                file_format,
6191                copy_options,
6192                validation_mode,
6193                partition,
6194            } => {
6195                write!(f, "COPY INTO {into}")?;
6196                if let Some(into_columns) = into_columns {
6197                    write!(f, " ({})", display_comma_separated(into_columns))?;
6198                }
6199                if let Some(from_transformations) = from_transformations {
6200                    // Data load with transformation
6201                    if let Some(from_stage) = from_obj {
6202                        write!(
6203                            f,
6204                            " FROM (SELECT {} FROM {}{}",
6205                            display_separated(from_transformations, ", "),
6206                            from_stage,
6207                            stage_params
6208                        )?;
6209                    }
6210                    if let Some(from_obj_alias) = from_obj_alias {
6211                        write!(f, " AS {from_obj_alias}")?;
6212                    }
6213                    write!(f, ")")?;
6214                } else if let Some(from_obj) = from_obj {
6215                    // Standard data load
6216                    write!(f, " FROM {from_obj}{stage_params}")?;
6217                    if let Some(from_obj_alias) = from_obj_alias {
6218                        write!(f, " AS {from_obj_alias}")?;
6219                    }
6220                } else if let Some(from_query) = from_query {
6221                    // Data unload from query
6222                    write!(f, " FROM ({from_query})")?;
6223                }
6224
6225                if let Some(files) = files {
6226                    write!(f, " FILES = ('{}')", display_separated(files, "', '"))?;
6227                }
6228                if let Some(pattern) = pattern {
6229                    write!(f, " PATTERN = '{pattern}'")?;
6230                }
6231                if let Some(partition) = partition {
6232                    write!(f, " PARTITION BY {partition}")?;
6233                }
6234                if !file_format.options.is_empty() {
6235                    write!(f, " FILE_FORMAT=({file_format})")?;
6236                }
6237                if !copy_options.options.is_empty() {
6238                    match kind {
6239                        CopyIntoSnowflakeKind::Table => {
6240                            write!(f, " COPY_OPTIONS=({copy_options})")?
6241                        }
6242                        CopyIntoSnowflakeKind::Location => write!(f, " {copy_options}")?,
6243                    }
6244                }
6245                if let Some(validation_mode) = validation_mode {
6246                    write!(f, " VALIDATION_MODE = {validation_mode}")?;
6247                }
6248                Ok(())
6249            }
6250            Statement::CreateType {
6251                name,
6252                representation,
6253            } => {
6254                write!(f, "CREATE TYPE {name}")?;
6255                if let Some(repr) = representation {
6256                    write!(f, " {repr}")?;
6257                }
6258                Ok(())
6259            }
6260            Statement::Pragma { name, value, is_eq } => {
6261                write!(f, "PRAGMA {name}")?;
6262                if let Some(value) = value {
6263                    if *is_eq {
6264                        write!(f, " = {value}")?;
6265                    } else {
6266                        write!(f, "({value})")?;
6267                    }
6268                }
6269                Ok(())
6270            }
6271            Statement::Lock(lock) => lock.fmt(f),
6272            Statement::LockTables { tables } => {
6273                write!(f, "LOCK TABLES {}", display_comma_separated(tables))
6274            }
6275            Statement::UnlockTables => {
6276                write!(f, "UNLOCK TABLES")
6277            }
6278            Statement::Unload {
6279                query,
6280                query_text,
6281                to,
6282                auth,
6283                with,
6284                options,
6285            } => {
6286                write!(f, "UNLOAD(")?;
6287                if let Some(query) = query {
6288                    write!(f, "{query}")?;
6289                }
6290                if let Some(query_text) = query_text {
6291                    write!(f, "'{query_text}'")?;
6292                }
6293                write!(f, ") TO {to}")?;
6294                if let Some(auth) = auth {
6295                    write!(f, " IAM_ROLE {auth}")?;
6296                }
6297                if !with.is_empty() {
6298                    write!(f, " WITH ({})", display_comma_separated(with))?;
6299                }
6300                if !options.is_empty() {
6301                    write!(f, " {}", display_separated(options, " "))?;
6302                }
6303                Ok(())
6304            }
6305            Statement::OptimizeTable {
6306                name,
6307                has_table_keyword,
6308                on_cluster,
6309                partition,
6310                include_final,
6311                deduplicate,
6312                predicate,
6313                zorder,
6314            } => {
6315                write!(f, "OPTIMIZE")?;
6316                if *has_table_keyword {
6317                    write!(f, " TABLE")?;
6318                }
6319                write!(f, " {name}")?;
6320                if let Some(on_cluster) = on_cluster {
6321                    write!(f, " ON CLUSTER {on_cluster}")?;
6322                }
6323                if let Some(partition) = partition {
6324                    write!(f, " {partition}")?;
6325                }
6326                if *include_final {
6327                    write!(f, " FINAL")?;
6328                }
6329                if let Some(deduplicate) = deduplicate {
6330                    write!(f, " {deduplicate}")?;
6331                }
6332                if let Some(predicate) = predicate {
6333                    write!(f, " WHERE {predicate}")?;
6334                }
6335                if let Some(zorder) = zorder {
6336                    write!(f, " ZORDER BY ({})", display_comma_separated(zorder))?;
6337                }
6338                Ok(())
6339            }
6340            Statement::LISTEN { channel } => {
6341                write!(f, "LISTEN {channel}")?;
6342                Ok(())
6343            }
6344            Statement::UNLISTEN { channel } => {
6345                write!(f, "UNLISTEN {channel}")?;
6346                Ok(())
6347            }
6348            Statement::NOTIFY { channel, payload } => {
6349                write!(f, "NOTIFY {channel}")?;
6350                if let Some(payload) = payload {
6351                    write!(f, ", '{payload}'")?;
6352                }
6353                Ok(())
6354            }
6355            Statement::RenameTable(rename_tables) => {
6356                write!(f, "RENAME TABLE {}", display_comma_separated(rename_tables))
6357            }
6358            Statement::RaisError {
6359                message,
6360                severity,
6361                state,
6362                arguments,
6363                options,
6364            } => {
6365                write!(f, "RAISERROR({message}, {severity}, {state}")?;
6366                if !arguments.is_empty() {
6367                    write!(f, ", {}", display_comma_separated(arguments))?;
6368                }
6369                write!(f, ")")?;
6370                if !options.is_empty() {
6371                    write!(f, " WITH {}", display_comma_separated(options))?;
6372                }
6373                Ok(())
6374            }
6375            Statement::Throw(s) => write!(f, "{s}"),
6376            Statement::Print(s) => write!(f, "{s}"),
6377            Statement::WaitFor(s) => write!(f, "{s}"),
6378            Statement::Return(r) => write!(f, "{r}"),
6379            Statement::List(command) => write!(f, "LIST {command}"),
6380            Statement::Remove(command) => write!(f, "REMOVE {command}"),
6381            Statement::ExportData(e) => write!(f, "{e}"),
6382            Statement::CreateUser(s) => write!(f, "{s}"),
6383            Statement::AlterSchema(s) => write!(f, "{s}"),
6384            Statement::Vacuum(s) => write!(f, "{s}"),
6385            Statement::AlterUser(s) => write!(f, "{s}"),
6386            Statement::Reset(s) => write!(f, "{s}"),
6387        }
6388    }
6389}
6390
6391/// Can use to describe options in create sequence or table column type identity
6392/// ```sql
6393/// [ INCREMENT [ BY ] increment ]
6394///     [ MINVALUE minvalue | NO MINVALUE ] [ MAXVALUE maxvalue | NO MAXVALUE ]
6395///     [ START [ WITH ] start ] [ CACHE cache ] [ [ NO ] CYCLE ]
6396/// ```
6397#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6398#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6399#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6400pub enum SequenceOptions {
6401    /// `INCREMENT [BY] <expr>` option; second value indicates presence of `BY` keyword.
6402    IncrementBy(Expr, bool),
6403    /// `MINVALUE <expr>` or `NO MINVALUE`.
6404    MinValue(Option<Expr>),
6405    /// `MAXVALUE <expr>` or `NO MAXVALUE`.
6406    MaxValue(Option<Expr>),
6407    /// `START [WITH] <expr>`; second value indicates presence of `WITH`.
6408    StartWith(Expr, bool),
6409    /// `CACHE <expr>` option.
6410    Cache(Expr),
6411    /// `CYCLE` or `NO CYCLE` option.
6412    Cycle(bool),
6413}
6414
6415impl fmt::Display for SequenceOptions {
6416    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6417        match self {
6418            SequenceOptions::IncrementBy(increment, by) => {
6419                write!(
6420                    f,
6421                    " INCREMENT{by} {increment}",
6422                    by = if *by { " BY" } else { "" },
6423                    increment = increment
6424                )
6425            }
6426            SequenceOptions::MinValue(Some(expr)) => {
6427                write!(f, " MINVALUE {expr}")
6428            }
6429            SequenceOptions::MinValue(None) => {
6430                write!(f, " NO MINVALUE")
6431            }
6432            SequenceOptions::MaxValue(Some(expr)) => {
6433                write!(f, " MAXVALUE {expr}")
6434            }
6435            SequenceOptions::MaxValue(None) => {
6436                write!(f, " NO MAXVALUE")
6437            }
6438            SequenceOptions::StartWith(start, with) => {
6439                write!(
6440                    f,
6441                    " START{with} {start}",
6442                    with = if *with { " WITH" } else { "" },
6443                    start = start
6444                )
6445            }
6446            SequenceOptions::Cache(cache) => {
6447                write!(f, " CACHE {}", *cache)
6448            }
6449            SequenceOptions::Cycle(no) => {
6450                write!(f, " {}CYCLE", if *no { "NO " } else { "" })
6451            }
6452        }
6453    }
6454}
6455
6456/// Assignment for a `SET` statement (name [=|TO] value)
6457#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6458#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6459#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6460pub struct SetAssignment {
6461    /// Optional context scope (e.g., SESSION or LOCAL).
6462    pub scope: Option<ContextModifier>,
6463    /// Assignment target name.
6464    pub name: ObjectName,
6465    /// Assigned expression value.
6466    pub value: Expr,
6467}
6468
6469impl fmt::Display for SetAssignment {
6470    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6471        write!(
6472            f,
6473            "{}{} = {}",
6474            self.scope.map(|s| format!("{s}")).unwrap_or_default(),
6475            self.name,
6476            self.value
6477        )
6478    }
6479}
6480
6481/// Target of a `TRUNCATE TABLE` command
6482///
6483/// Note this is its own struct because `visit_relation` requires an `ObjectName` (not a `Vec<ObjectName>`)
6484#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6485#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6486#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6487pub struct TruncateTableTarget {
6488    /// name of the table being truncated
6489    #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
6490    pub name: ObjectName,
6491    /// Postgres-specific option: explicitly exclude descendants (also default without ONLY)
6492    /// ```sql
6493    /// TRUNCATE TABLE ONLY name
6494    /// ```
6495    /// <https://www.postgresql.org/docs/current/sql-truncate.html>
6496    pub only: bool,
6497    /// Postgres-specific option: asterisk after table name to explicitly indicate descendants
6498    /// ```sql
6499    /// TRUNCATE TABLE name [ * ]
6500    /// ```
6501    /// <https://www.postgresql.org/docs/current/sql-truncate.html>
6502    pub has_asterisk: bool,
6503}
6504
6505impl fmt::Display for TruncateTableTarget {
6506    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6507        if self.only {
6508            write!(f, "ONLY ")?;
6509        };
6510        write!(f, "{}", self.name)?;
6511        if self.has_asterisk {
6512            write!(f, " *")?;
6513        };
6514        Ok(())
6515    }
6516}
6517
6518/// A `LOCK` statement.
6519///
6520/// See <https://www.postgresql.org/docs/current/sql-lock.html>
6521#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6522#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6523#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6524pub struct Lock {
6525    /// List of tables to lock.
6526    pub tables: Vec<LockTableTarget>,
6527    /// Lock mode.
6528    pub lock_mode: Option<LockTableMode>,
6529    /// Whether `NOWAIT` was specified.
6530    pub nowait: bool,
6531}
6532
6533impl fmt::Display for Lock {
6534    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6535        write!(f, "LOCK TABLE {}", display_comma_separated(&self.tables))?;
6536        if let Some(lock_mode) = &self.lock_mode {
6537            write!(f, " IN {lock_mode} MODE")?;
6538        }
6539        if self.nowait {
6540            write!(f, " NOWAIT")?;
6541        }
6542        Ok(())
6543    }
6544}
6545
6546/// Target of a `LOCK TABLE` command
6547///
6548/// See <https://www.postgresql.org/docs/current/sql-lock.html>
6549#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6550#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6551#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6552pub struct LockTableTarget {
6553    /// Name of the table being locked.
6554    #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
6555    pub name: ObjectName,
6556    /// Whether `ONLY` was specified to exclude descendant tables.
6557    pub only: bool,
6558    /// Whether `*` was specified to explicitly include descendant tables.
6559    pub has_asterisk: bool,
6560}
6561
6562impl fmt::Display for LockTableTarget {
6563    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6564        if self.only {
6565            write!(f, "ONLY ")?;
6566        }
6567        write!(f, "{}", self.name)?;
6568        if self.has_asterisk {
6569            write!(f, " *")?;
6570        }
6571        Ok(())
6572    }
6573}
6574
6575/// PostgreSQL lock modes for `LOCK TABLE`.
6576///
6577/// See <https://www.postgresql.org/docs/current/sql-lock.html>
6578#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6579#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6580#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6581pub enum LockTableMode {
6582    /// `ACCESS SHARE`
6583    AccessShare,
6584    /// `ROW SHARE`
6585    RowShare,
6586    /// `ROW EXCLUSIVE`
6587    RowExclusive,
6588    /// `SHARE UPDATE EXCLUSIVE`
6589    ShareUpdateExclusive,
6590    /// `SHARE`
6591    Share,
6592    /// `SHARE ROW EXCLUSIVE`
6593    ShareRowExclusive,
6594    /// `EXCLUSIVE`
6595    Exclusive,
6596    /// `ACCESS EXCLUSIVE`
6597    AccessExclusive,
6598}
6599
6600impl fmt::Display for LockTableMode {
6601    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
6602        let text = match self {
6603            Self::AccessShare => "ACCESS SHARE",
6604            Self::RowShare => "ROW SHARE",
6605            Self::RowExclusive => "ROW EXCLUSIVE",
6606            Self::ShareUpdateExclusive => "SHARE UPDATE EXCLUSIVE",
6607            Self::Share => "SHARE",
6608            Self::ShareRowExclusive => "SHARE ROW EXCLUSIVE",
6609            Self::Exclusive => "EXCLUSIVE",
6610            Self::AccessExclusive => "ACCESS EXCLUSIVE",
6611        };
6612        write!(f, "{text}")
6613    }
6614}
6615
6616/// PostgreSQL identity option for TRUNCATE table
6617/// [ RESTART IDENTITY | CONTINUE IDENTITY ]
6618#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6619#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6620#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6621pub enum TruncateIdentityOption {
6622    /// Restart identity values (RESTART IDENTITY).
6623    Restart,
6624    /// Continue identity values (CONTINUE IDENTITY).
6625    Continue,
6626}
6627
6628/// Cascade/restrict option for Postgres TRUNCATE table, MySQL GRANT/REVOKE, etc.
6629/// [ CASCADE | RESTRICT ]
6630#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6631#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6632#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6633pub enum CascadeOption {
6634    /// Apply cascading action (e.g., CASCADE).
6635    Cascade,
6636    /// Restrict the action (e.g., RESTRICT).
6637    Restrict,
6638}
6639
6640impl Display for CascadeOption {
6641    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6642        match self {
6643            CascadeOption::Cascade => write!(f, "CASCADE"),
6644            CascadeOption::Restrict => write!(f, "RESTRICT"),
6645        }
6646    }
6647}
6648
6649/// Transaction started with [ TRANSACTION | WORK | TRAN ]
6650#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6651#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6652#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6653pub enum BeginTransactionKind {
6654    /// Standard `TRANSACTION` keyword.
6655    Transaction,
6656    /// Alternate `WORK` keyword.
6657    Work,
6658    /// MSSQL shorthand `TRAN` keyword.
6659    /// See <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/begin-transaction-transact-sql>
6660    Tran,
6661}
6662
6663impl Display for BeginTransactionKind {
6664    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6665        match self {
6666            BeginTransactionKind::Transaction => write!(f, "TRANSACTION"),
6667            BeginTransactionKind::Work => write!(f, "WORK"),
6668            BeginTransactionKind::Tran => write!(f, "TRAN"),
6669        }
6670    }
6671}
6672
6673/// Can use to describe options in  create sequence or table column type identity
6674/// [ MINVALUE minvalue | NO MINVALUE ] [ MAXVALUE maxvalue | NO MAXVALUE ]
6675#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6676#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6677#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6678pub enum MinMaxValue {
6679    /// Clause is not specified.
6680    Empty,
6681    /// NO MINVALUE / NO MAXVALUE.
6682    None,
6683    /// `MINVALUE <expr>` / `MAXVALUE <expr>`.
6684    Some(Expr),
6685}
6686
6687#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6688#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6689#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6690#[non_exhaustive]
6691/// Behavior to apply for `INSERT` when a conflict occurs.
6692pub enum OnInsert {
6693    /// ON DUPLICATE KEY UPDATE (MySQL when the key already exists, then execute an update instead)
6694    DuplicateKeyUpdate(Vec<Assignment>),
6695    /// ON CONFLICT is a PostgreSQL and Sqlite extension
6696    OnConflict(OnConflict),
6697}
6698
6699#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6700#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6701#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6702/// Optional aliases for `INSERT` targets: row alias and optional column aliases.
6703pub struct InsertAliases {
6704    /// Row alias (table-style alias) for the inserted values.
6705    pub row_alias: ObjectName,
6706    /// Optional list of column aliases for the inserted values.
6707    pub col_aliases: Option<Vec<Ident>>,
6708}
6709
6710#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6711#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6712#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6713/// Optional alias for an `INSERT` table; i.e. the table to be inserted into
6714pub struct TableAliasWithoutColumns {
6715    /// `true` if the aliases was explicitly introduced with the "AS" keyword
6716    pub explicit: bool,
6717    /// the alias name itself
6718    pub alias: Ident,
6719}
6720
6721#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6722#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6723#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6724/// `ON CONFLICT` clause representation.
6725pub struct OnConflict {
6726    /// Optional conflict target specifying columns or constraint.
6727    pub conflict_target: Option<ConflictTarget>,
6728    /// Action to take when a conflict occurs.
6729    pub action: OnConflictAction,
6730}
6731#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6732#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6733#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6734/// Target specification for an `ON CONFLICT` clause.
6735pub enum ConflictTarget {
6736    /// Target specified as a list of columns.
6737    Columns(Vec<Ident>),
6738    /// Target specified as a named constraint.
6739    OnConstraint(ObjectName),
6740}
6741#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6742#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6743#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6744/// Action to perform when an `ON CONFLICT` target is matched.
6745pub enum OnConflictAction {
6746    /// Do nothing on conflict.
6747    DoNothing,
6748    /// Perform an update on conflict.
6749    DoUpdate(DoUpdate),
6750}
6751
6752#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6753#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6754#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6755/// Details for `DO UPDATE` action of an `ON CONFLICT` clause.
6756pub struct DoUpdate {
6757    /// Column assignments to perform on update.
6758    pub assignments: Vec<Assignment>,
6759    /// Optional WHERE clause limiting the update.
6760    pub selection: Option<Expr>,
6761}
6762
6763impl fmt::Display for OnInsert {
6764    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6765        match self {
6766            Self::DuplicateKeyUpdate(expr) => write!(
6767                f,
6768                " ON DUPLICATE KEY UPDATE {}",
6769                display_comma_separated(expr)
6770            ),
6771            Self::OnConflict(o) => write!(f, "{o}"),
6772        }
6773    }
6774}
6775impl fmt::Display for OnConflict {
6776    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6777        write!(f, " ON CONFLICT")?;
6778        if let Some(target) = &self.conflict_target {
6779            write!(f, "{target}")?;
6780        }
6781        write!(f, " {}", self.action)
6782    }
6783}
6784impl fmt::Display for ConflictTarget {
6785    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6786        match self {
6787            ConflictTarget::Columns(cols) => write!(f, "({})", display_comma_separated(cols)),
6788            ConflictTarget::OnConstraint(name) => write!(f, " ON CONSTRAINT {name}"),
6789        }
6790    }
6791}
6792impl fmt::Display for OnConflictAction {
6793    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6794        match self {
6795            Self::DoNothing => write!(f, "DO NOTHING"),
6796            Self::DoUpdate(do_update) => {
6797                write!(f, "DO UPDATE")?;
6798                if !do_update.assignments.is_empty() {
6799                    write!(
6800                        f,
6801                        " SET {}",
6802                        display_comma_separated(&do_update.assignments)
6803                    )?;
6804                }
6805                if let Some(selection) = &do_update.selection {
6806                    write!(f, " WHERE {selection}")?;
6807                }
6808                Ok(())
6809            }
6810        }
6811    }
6812}
6813
6814/// Privileges granted in a GRANT statement or revoked in a REVOKE statement.
6815#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6816#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6817#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6818pub enum Privileges {
6819    /// All privileges applicable to the object type
6820    All {
6821        /// Optional keyword from the spec, ignored in practice
6822        with_privileges_keyword: bool,
6823    },
6824    /// Specific privileges (e.g. `SELECT`, `INSERT`)
6825    Actions(Vec<Action>),
6826}
6827
6828impl fmt::Display for Privileges {
6829    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6830        match self {
6831            Privileges::All {
6832                with_privileges_keyword,
6833            } => {
6834                write!(
6835                    f,
6836                    "ALL{}",
6837                    if *with_privileges_keyword {
6838                        " PRIVILEGES"
6839                    } else {
6840                        ""
6841                    }
6842                )
6843            }
6844            Privileges::Actions(actions) => {
6845                write!(f, "{}", display_comma_separated(actions))
6846            }
6847        }
6848    }
6849}
6850
6851/// Specific direction for FETCH statement
6852#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6853#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6854#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6855pub enum FetchDirection {
6856    /// Fetch a specific count of rows.
6857    Count {
6858        /// The limit value for the count.
6859        limit: ValueWithSpan,
6860    },
6861    /// Fetch the next row.
6862    Next,
6863    /// Fetch the prior row.
6864    Prior,
6865    /// Fetch the first row.
6866    First,
6867    /// Fetch the last row.
6868    Last,
6869    /// Fetch an absolute row by index.
6870    Absolute {
6871        /// The absolute index value.
6872        limit: ValueWithSpan,
6873    },
6874    /// Fetch a row relative to the current position.
6875    Relative {
6876        /// The relative offset value.
6877        limit: ValueWithSpan,
6878    },
6879    /// Fetch all rows.
6880    All,
6881    // FORWARD
6882    // FORWARD count
6883    /// Fetch forward by an optional limit.
6884    Forward {
6885        /// Optional forward limit.
6886        limit: Option<ValueWithSpan>,
6887    },
6888    /// Fetch all forward rows.
6889    ForwardAll,
6890    // BACKWARD
6891    // BACKWARD count
6892    /// Fetch backward by an optional limit.
6893    Backward {
6894        /// Optional backward limit.
6895        limit: Option<ValueWithSpan>,
6896    },
6897    /// Fetch all backward rows.
6898    BackwardAll,
6899}
6900
6901impl fmt::Display for FetchDirection {
6902    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6903        match self {
6904            FetchDirection::Count { limit } => f.write_str(&limit.to_string())?,
6905            FetchDirection::Next => f.write_str("NEXT")?,
6906            FetchDirection::Prior => f.write_str("PRIOR")?,
6907            FetchDirection::First => f.write_str("FIRST")?,
6908            FetchDirection::Last => f.write_str("LAST")?,
6909            FetchDirection::Absolute { limit } => {
6910                f.write_str("ABSOLUTE ")?;
6911                f.write_str(&limit.to_string())?;
6912            }
6913            FetchDirection::Relative { limit } => {
6914                f.write_str("RELATIVE ")?;
6915                f.write_str(&limit.to_string())?;
6916            }
6917            FetchDirection::All => f.write_str("ALL")?,
6918            FetchDirection::Forward { limit } => {
6919                f.write_str("FORWARD")?;
6920
6921                if let Some(l) = limit {
6922                    f.write_str(" ")?;
6923                    f.write_str(&l.to_string())?;
6924                }
6925            }
6926            FetchDirection::ForwardAll => f.write_str("FORWARD ALL")?,
6927            FetchDirection::Backward { limit } => {
6928                f.write_str("BACKWARD")?;
6929
6930                if let Some(l) = limit {
6931                    f.write_str(" ")?;
6932                    f.write_str(&l.to_string())?;
6933                }
6934            }
6935            FetchDirection::BackwardAll => f.write_str("BACKWARD ALL")?,
6936        };
6937
6938        Ok(())
6939    }
6940}
6941
6942/// The "position" for a FETCH statement.
6943///
6944/// [MsSql](https://learn.microsoft.com/en-us/sql/t-sql/language-elements/fetch-transact-sql)
6945#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6946#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6947#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6948pub enum FetchPosition {
6949    /// Use `FROM <pos>` position specifier.
6950    From,
6951    /// Use `IN <pos>` position specifier.
6952    In,
6953}
6954
6955impl fmt::Display for FetchPosition {
6956    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6957        match self {
6958            FetchPosition::From => f.write_str("FROM")?,
6959            FetchPosition::In => f.write_str("IN")?,
6960        };
6961
6962        Ok(())
6963    }
6964}
6965
6966/// A privilege on a database object (table, sequence, etc.).
6967#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6968#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6969#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6970pub enum Action {
6971    /// Add a search optimization.
6972    AddSearchOptimization,
6973    /// Apply an `APPLY` operation with a specific type.
6974    Apply {
6975        /// The type of apply operation.
6976        apply_type: ActionApplyType,
6977    },
6978    /// Apply a budget operation.
6979    ApplyBudget,
6980    /// Attach a listing.
6981    AttachListing,
6982    /// Attach a policy.
6983    AttachPolicy,
6984    /// Audit operation.
6985    Audit,
6986    /// Bind a service endpoint.
6987    BindServiceEndpoint,
6988    /// Connect permission.
6989    Connect,
6990    /// Create action, optionally specifying an object type.
6991    Create {
6992        /// Optional object type to create.
6993        obj_type: Option<ActionCreateObjectType>,
6994    },
6995    /// Actions related to database roles.
6996    DatabaseRole {
6997        /// The role name.
6998        role: ObjectName,
6999    },
7000    /// Delete permission.
7001    Delete,
7002    /// Drop permission.
7003    Drop,
7004    /// Evolve schema permission.
7005    EvolveSchema,
7006    /// Exec action (execute) with optional object type.
7007    Exec {
7008        /// Optional execute object type.
7009        obj_type: Option<ActionExecuteObjectType>,
7010    },
7011    /// Execute action with optional object type.
7012    Execute {
7013        /// Optional execute object type.
7014        obj_type: Option<ActionExecuteObjectType>,
7015    },
7016    /// Failover operation.
7017    Failover,
7018    /// Use imported privileges.
7019    ImportedPrivileges,
7020    /// Import a share.
7021    ImportShare,
7022    /// Insert rows with optional column list.
7023    Insert {
7024        /// Optional list of target columns for insert.
7025        columns: Option<Vec<Ident>>,
7026    },
7027    /// Manage operation with a specific manage type.
7028    Manage {
7029        /// The specific manage sub-type.
7030        manage_type: ActionManageType,
7031    },
7032    /// Manage releases.
7033    ManageReleases,
7034    /// Manage versions.
7035    ManageVersions,
7036    /// Modify operation with an optional modify type.
7037    Modify {
7038        /// The optional modify sub-type.
7039        modify_type: Option<ActionModifyType>,
7040    },
7041    /// Monitor operation with an optional monitor type.
7042    Monitor {
7043        /// The optional monitor sub-type.
7044        monitor_type: Option<ActionMonitorType>,
7045    },
7046    /// Operate permission.
7047    Operate,
7048    /// Override share restrictions.
7049    OverrideShareRestrictions,
7050    /// Ownership permission.
7051    Ownership,
7052    /// Purchase a data exchange listing.
7053    PurchaseDataExchangeListing,
7054
7055    /// Read access.
7056    Read,
7057    /// Read session-level access.
7058    ReadSession,
7059    /// References with optional column list.
7060    References {
7061        /// Optional list of referenced column identifiers.
7062        columns: Option<Vec<Ident>>,
7063    },
7064    /// Replication permission.
7065    Replicate,
7066    /// Resolve all references.
7067    ResolveAll,
7068    /// Role-related permission with target role name.
7069    Role {
7070        /// The target role name.
7071        role: ObjectName,
7072    },
7073    /// Select permission with optional column list.
7074    Select {
7075        /// Optional list of selected columns.
7076        columns: Option<Vec<Ident>>,
7077    },
7078    /// Temporary object permission.
7079    Temporary,
7080    /// Trigger-related permission.
7081    Trigger,
7082    /// Truncate permission.
7083    Truncate,
7084    /// Update permission with optional affected columns.
7085    Update {
7086        /// Optional list of columns affected by update.
7087        columns: Option<Vec<Ident>>,
7088    },
7089    /// Usage permission.
7090    Usage,
7091}
7092
7093impl fmt::Display for Action {
7094    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7095        match self {
7096            Action::AddSearchOptimization => f.write_str("ADD SEARCH OPTIMIZATION")?,
7097            Action::Apply { apply_type } => write!(f, "APPLY {apply_type}")?,
7098            Action::ApplyBudget => f.write_str("APPLYBUDGET")?,
7099            Action::AttachListing => f.write_str("ATTACH LISTING")?,
7100            Action::AttachPolicy => f.write_str("ATTACH POLICY")?,
7101            Action::Audit => f.write_str("AUDIT")?,
7102            Action::BindServiceEndpoint => f.write_str("BIND SERVICE ENDPOINT")?,
7103            Action::Connect => f.write_str("CONNECT")?,
7104            Action::Create { obj_type } => {
7105                f.write_str("CREATE")?;
7106                if let Some(obj_type) = obj_type {
7107                    write!(f, " {obj_type}")?
7108                }
7109            }
7110            Action::DatabaseRole { role } => write!(f, "DATABASE ROLE {role}")?,
7111            Action::Delete => f.write_str("DELETE")?,
7112            Action::Drop => f.write_str("DROP")?,
7113            Action::EvolveSchema => f.write_str("EVOLVE SCHEMA")?,
7114            Action::Exec { obj_type } => {
7115                f.write_str("EXEC")?;
7116                if let Some(obj_type) = obj_type {
7117                    write!(f, " {obj_type}")?
7118                }
7119            }
7120            Action::Execute { obj_type } => {
7121                f.write_str("EXECUTE")?;
7122                if let Some(obj_type) = obj_type {
7123                    write!(f, " {obj_type}")?
7124                }
7125            }
7126            Action::Failover => f.write_str("FAILOVER")?,
7127            Action::ImportedPrivileges => f.write_str("IMPORTED PRIVILEGES")?,
7128            Action::ImportShare => f.write_str("IMPORT SHARE")?,
7129            Action::Insert { .. } => f.write_str("INSERT")?,
7130            Action::Manage { manage_type } => write!(f, "MANAGE {manage_type}")?,
7131            Action::ManageReleases => f.write_str("MANAGE RELEASES")?,
7132            Action::ManageVersions => f.write_str("MANAGE VERSIONS")?,
7133            Action::Modify { modify_type } => {
7134                write!(f, "MODIFY")?;
7135                if let Some(modify_type) = modify_type {
7136                    write!(f, " {modify_type}")?;
7137                }
7138            }
7139            Action::Monitor { monitor_type } => {
7140                write!(f, "MONITOR")?;
7141                if let Some(monitor_type) = monitor_type {
7142                    write!(f, " {monitor_type}")?
7143                }
7144            }
7145            Action::Operate => f.write_str("OPERATE")?,
7146            Action::OverrideShareRestrictions => f.write_str("OVERRIDE SHARE RESTRICTIONS")?,
7147            Action::Ownership => f.write_str("OWNERSHIP")?,
7148            Action::PurchaseDataExchangeListing => f.write_str("PURCHASE DATA EXCHANGE LISTING")?,
7149            Action::Read => f.write_str("READ")?,
7150            Action::ReadSession => f.write_str("READ SESSION")?,
7151            Action::References { .. } => f.write_str("REFERENCES")?,
7152            Action::Replicate => f.write_str("REPLICATE")?,
7153            Action::ResolveAll => f.write_str("RESOLVE ALL")?,
7154            Action::Role { role } => write!(f, "ROLE {role}")?,
7155            Action::Select { .. } => f.write_str("SELECT")?,
7156            Action::Temporary => f.write_str("TEMPORARY")?,
7157            Action::Trigger => f.write_str("TRIGGER")?,
7158            Action::Truncate => f.write_str("TRUNCATE")?,
7159            Action::Update { .. } => f.write_str("UPDATE")?,
7160            Action::Usage => f.write_str("USAGE")?,
7161        };
7162        match self {
7163            Action::Insert { columns }
7164            | Action::References { columns }
7165            | Action::Select { columns }
7166            | Action::Update { columns } => {
7167                if let Some(columns) = columns {
7168                    write!(f, " ({})", display_comma_separated(columns))?;
7169                }
7170            }
7171            _ => (),
7172        };
7173        Ok(())
7174    }
7175}
7176
7177#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7178#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7179#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7180/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
7181/// under `globalPrivileges` in the `CREATE` privilege.
7182pub enum ActionCreateObjectType {
7183    /// An account-level object.
7184    Account,
7185    /// An application object.
7186    Application,
7187    /// An application package object.
7188    ApplicationPackage,
7189    /// A compute pool object.
7190    ComputePool,
7191    /// A data exchange listing.
7192    DataExchangeListing,
7193    /// A database object.
7194    Database,
7195    /// An external volume object.
7196    ExternalVolume,
7197    /// A failover group object.
7198    FailoverGroup,
7199    /// An integration object.
7200    Integration,
7201    /// A network policy object.
7202    NetworkPolicy,
7203    /// An organization listing.
7204    OrganiationListing,
7205    /// A replication group object.
7206    ReplicationGroup,
7207    /// A role object.
7208    Role,
7209    /// A schema object.
7210    Schema,
7211    /// A share object.
7212    Share,
7213    /// A user object.
7214    User,
7215    /// A warehouse object.
7216    Warehouse,
7217}
7218
7219impl fmt::Display for ActionCreateObjectType {
7220    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7221        match self {
7222            ActionCreateObjectType::Account => write!(f, "ACCOUNT"),
7223            ActionCreateObjectType::Application => write!(f, "APPLICATION"),
7224            ActionCreateObjectType::ApplicationPackage => write!(f, "APPLICATION PACKAGE"),
7225            ActionCreateObjectType::ComputePool => write!(f, "COMPUTE POOL"),
7226            ActionCreateObjectType::DataExchangeListing => write!(f, "DATA EXCHANGE LISTING"),
7227            ActionCreateObjectType::Database => write!(f, "DATABASE"),
7228            ActionCreateObjectType::ExternalVolume => write!(f, "EXTERNAL VOLUME"),
7229            ActionCreateObjectType::FailoverGroup => write!(f, "FAILOVER GROUP"),
7230            ActionCreateObjectType::Integration => write!(f, "INTEGRATION"),
7231            ActionCreateObjectType::NetworkPolicy => write!(f, "NETWORK POLICY"),
7232            ActionCreateObjectType::OrganiationListing => write!(f, "ORGANIZATION LISTING"),
7233            ActionCreateObjectType::ReplicationGroup => write!(f, "REPLICATION GROUP"),
7234            ActionCreateObjectType::Role => write!(f, "ROLE"),
7235            ActionCreateObjectType::Schema => write!(f, "SCHEMA"),
7236            ActionCreateObjectType::Share => write!(f, "SHARE"),
7237            ActionCreateObjectType::User => write!(f, "USER"),
7238            ActionCreateObjectType::Warehouse => write!(f, "WAREHOUSE"),
7239        }
7240    }
7241}
7242
7243#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7244#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7245#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7246/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
7247/// under `globalPrivileges` in the `APPLY` privilege.
7248pub enum ActionApplyType {
7249    /// Apply an aggregation policy.
7250    AggregationPolicy,
7251    /// Apply an authentication policy.
7252    AuthenticationPolicy,
7253    /// Apply a join policy.
7254    JoinPolicy,
7255    /// Apply a masking policy.
7256    MaskingPolicy,
7257    /// Apply a packages policy.
7258    PackagesPolicy,
7259    /// Apply a password policy.
7260    PasswordPolicy,
7261    /// Apply a projection policy.
7262    ProjectionPolicy,
7263    /// Apply a row access policy.
7264    RowAccessPolicy,
7265    /// Apply a session policy.
7266    SessionPolicy,
7267    /// Apply a tag.
7268    Tag,
7269}
7270
7271impl fmt::Display for ActionApplyType {
7272    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7273        match self {
7274            ActionApplyType::AggregationPolicy => write!(f, "AGGREGATION POLICY"),
7275            ActionApplyType::AuthenticationPolicy => write!(f, "AUTHENTICATION POLICY"),
7276            ActionApplyType::JoinPolicy => write!(f, "JOIN POLICY"),
7277            ActionApplyType::MaskingPolicy => write!(f, "MASKING POLICY"),
7278            ActionApplyType::PackagesPolicy => write!(f, "PACKAGES POLICY"),
7279            ActionApplyType::PasswordPolicy => write!(f, "PASSWORD POLICY"),
7280            ActionApplyType::ProjectionPolicy => write!(f, "PROJECTION POLICY"),
7281            ActionApplyType::RowAccessPolicy => write!(f, "ROW ACCESS POLICY"),
7282            ActionApplyType::SessionPolicy => write!(f, "SESSION POLICY"),
7283            ActionApplyType::Tag => write!(f, "TAG"),
7284        }
7285    }
7286}
7287
7288#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7289#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7290#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7291/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
7292/// under `globalPrivileges` in the `EXECUTE` privilege.
7293pub enum ActionExecuteObjectType {
7294    /// Alert object.
7295    Alert,
7296    /// Data metric function object.
7297    DataMetricFunction,
7298    /// Managed alert object.
7299    ManagedAlert,
7300    /// Managed task object.
7301    ManagedTask,
7302    /// Task object.
7303    Task,
7304}
7305
7306impl fmt::Display for ActionExecuteObjectType {
7307    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7308        match self {
7309            ActionExecuteObjectType::Alert => write!(f, "ALERT"),
7310            ActionExecuteObjectType::DataMetricFunction => write!(f, "DATA METRIC FUNCTION"),
7311            ActionExecuteObjectType::ManagedAlert => write!(f, "MANAGED ALERT"),
7312            ActionExecuteObjectType::ManagedTask => write!(f, "MANAGED TASK"),
7313            ActionExecuteObjectType::Task => write!(f, "TASK"),
7314        }
7315    }
7316}
7317
7318#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7319#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7320#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7321/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
7322/// under `globalPrivileges` in the `MANAGE` privilege.
7323pub enum ActionManageType {
7324    /// Account support cases management.
7325    AccountSupportCases,
7326    /// Event sharing management.
7327    EventSharing,
7328    /// Grants management.
7329    Grants,
7330    /// Listing auto-fulfillment management.
7331    ListingAutoFulfillment,
7332    /// Organization support cases management.
7333    OrganizationSupportCases,
7334    /// User support cases management.
7335    UserSupportCases,
7336    /// Warehouses management.
7337    Warehouses,
7338}
7339
7340impl fmt::Display for ActionManageType {
7341    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7342        match self {
7343            ActionManageType::AccountSupportCases => write!(f, "ACCOUNT SUPPORT CASES"),
7344            ActionManageType::EventSharing => write!(f, "EVENT SHARING"),
7345            ActionManageType::Grants => write!(f, "GRANTS"),
7346            ActionManageType::ListingAutoFulfillment => write!(f, "LISTING AUTO FULFILLMENT"),
7347            ActionManageType::OrganizationSupportCases => write!(f, "ORGANIZATION SUPPORT CASES"),
7348            ActionManageType::UserSupportCases => write!(f, "USER SUPPORT CASES"),
7349            ActionManageType::Warehouses => write!(f, "WAREHOUSES"),
7350        }
7351    }
7352}
7353
7354#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7355#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7356#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7357/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
7358/// under `globalPrivileges` in the `MODIFY` privilege.
7359pub enum ActionModifyType {
7360    /// Modify log level.
7361    LogLevel,
7362    /// Modify trace level.
7363    TraceLevel,
7364    /// Modify session log level.
7365    SessionLogLevel,
7366    /// Modify session trace level.
7367    SessionTraceLevel,
7368}
7369
7370impl fmt::Display for ActionModifyType {
7371    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7372        match self {
7373            ActionModifyType::LogLevel => write!(f, "LOG LEVEL"),
7374            ActionModifyType::TraceLevel => write!(f, "TRACE LEVEL"),
7375            ActionModifyType::SessionLogLevel => write!(f, "SESSION LOG LEVEL"),
7376            ActionModifyType::SessionTraceLevel => write!(f, "SESSION TRACE LEVEL"),
7377        }
7378    }
7379}
7380
7381#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7382#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7383#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7384/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
7385/// under `globalPrivileges` in the `MONITOR` privilege.
7386pub enum ActionMonitorType {
7387    /// Monitor execution.
7388    Execution,
7389    /// Monitor security.
7390    Security,
7391    /// Monitor usage.
7392    Usage,
7393}
7394
7395impl fmt::Display for ActionMonitorType {
7396    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7397        match self {
7398            ActionMonitorType::Execution => write!(f, "EXECUTION"),
7399            ActionMonitorType::Security => write!(f, "SECURITY"),
7400            ActionMonitorType::Usage => write!(f, "USAGE"),
7401        }
7402    }
7403}
7404
7405/// The principal that receives the privileges
7406#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7407#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7408#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7409pub struct Grantee {
7410    /// The category/type of grantee (role, user, share, etc.).
7411    pub grantee_type: GranteesType,
7412    /// Optional name of the grantee (identifier or user@host).
7413    pub name: Option<GranteeName>,
7414}
7415
7416impl fmt::Display for Grantee {
7417    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7418        match self.grantee_type {
7419            GranteesType::Role => {
7420                write!(f, "ROLE ")?;
7421            }
7422            GranteesType::Share => {
7423                write!(f, "SHARE ")?;
7424            }
7425            GranteesType::User => {
7426                write!(f, "USER ")?;
7427            }
7428            GranteesType::Group => {
7429                write!(f, "GROUP ")?;
7430            }
7431            GranteesType::Public => {
7432                write!(f, "PUBLIC ")?;
7433            }
7434            GranteesType::DatabaseRole => {
7435                write!(f, "DATABASE ROLE ")?;
7436            }
7437            GranteesType::Application => {
7438                write!(f, "APPLICATION ")?;
7439            }
7440            GranteesType::ApplicationRole => {
7441                write!(f, "APPLICATION ROLE ")?;
7442            }
7443            GranteesType::None => (),
7444        }
7445        if let Some(ref name) = self.name {
7446            name.fmt(f)?;
7447        }
7448        Ok(())
7449    }
7450}
7451
7452#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7453#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7454#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7455/// The kind of principal receiving privileges.
7456pub enum GranteesType {
7457    /// A role principal.
7458    Role,
7459    /// A share principal.
7460    Share,
7461    /// A user principal.
7462    User,
7463    /// A group principal.
7464    Group,
7465    /// The public principal.
7466    Public,
7467    /// A database role principal.
7468    DatabaseRole,
7469    /// An application principal.
7470    Application,
7471    /// An application role principal.
7472    ApplicationRole,
7473    /// No specific principal (e.g. `NONE`).
7474    None,
7475}
7476
7477/// Users/roles designated in a GRANT/REVOKE
7478#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7479#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7480#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7481pub enum GranteeName {
7482    /// A bare identifier
7483    ObjectName(ObjectName),
7484    /// A MySQL user/host pair such as 'root'@'%'
7485    UserHost {
7486        /// The user identifier portion.
7487        user: Ident,
7488        /// The host identifier portion.
7489        host: Ident,
7490    },
7491}
7492
7493impl fmt::Display for GranteeName {
7494    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7495        match self {
7496            GranteeName::ObjectName(name) => name.fmt(f),
7497            GranteeName::UserHost { user, host } => {
7498                write!(f, "{user}@{host}")
7499            }
7500        }
7501    }
7502}
7503
7504/// Objects on which privileges are granted in a GRANT statement.
7505#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7506#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7507#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7508pub enum GrantObjects {
7509    /// Grant privileges on `ALL SEQUENCES IN SCHEMA <schema_name> [, ...]`
7510    AllSequencesInSchema {
7511        /// The target schema names.
7512        schemas: Vec<ObjectName>,
7513    },
7514    /// Grant privileges on `ALL TABLES IN SCHEMA <schema_name> [, ...]`
7515    AllTablesInSchema {
7516        /// The target schema names.
7517        schemas: Vec<ObjectName>,
7518    },
7519    /// Grant privileges on `ALL VIEWS IN SCHEMA <schema_name> [, ...]`
7520    AllViewsInSchema {
7521        /// The target schema names.
7522        schemas: Vec<ObjectName>,
7523    },
7524    /// Grant privileges on `ALL MATERIALIZED VIEWS IN SCHEMA <schema_name> [, ...]`
7525    AllMaterializedViewsInSchema {
7526        /// The target schema names.
7527        schemas: Vec<ObjectName>,
7528    },
7529    /// Grant privileges on `ALL EXTERNAL TABLES IN SCHEMA <schema_name> [, ...]`
7530    AllExternalTablesInSchema {
7531        /// The target schema names.
7532        schemas: Vec<ObjectName>,
7533    },
7534    /// Grant privileges on `ALL FUNCTIONS IN SCHEMA <schema_name> [, ...]`
7535    AllFunctionsInSchema {
7536        /// The target schema names.
7537        schemas: Vec<ObjectName>,
7538    },
7539    /// Grant privileges on `FUTURE SCHEMAS IN DATABASE <database_name> [, ...]`
7540    FutureSchemasInDatabase {
7541        /// The target database names.
7542        databases: Vec<ObjectName>,
7543    },
7544    /// Grant privileges on `FUTURE TABLES IN SCHEMA <schema_name> [, ...]`
7545    FutureTablesInSchema {
7546        /// The target schema names.
7547        schemas: Vec<ObjectName>,
7548    },
7549    /// Grant privileges on `FUTURE VIEWS IN SCHEMA <schema_name> [, ...]`
7550    FutureViewsInSchema {
7551        /// The target schema names.
7552        schemas: Vec<ObjectName>,
7553    },
7554    /// Grant privileges on `FUTURE EXTERNAL TABLES IN SCHEMA <schema_name> [, ...]`
7555    FutureExternalTablesInSchema {
7556        /// The target schema names.
7557        schemas: Vec<ObjectName>,
7558    },
7559    /// Grant privileges on `FUTURE MATERIALIZED VIEWS IN SCHEMA <schema_name> [, ...]`
7560    FutureMaterializedViewsInSchema {
7561        /// The target schema names.
7562        schemas: Vec<ObjectName>,
7563    },
7564    /// Grant privileges on `FUTURE SEQUENCES IN SCHEMA <schema_name> [, ...]`
7565    FutureSequencesInSchema {
7566        /// The target schema names.
7567        schemas: Vec<ObjectName>,
7568    },
7569    /// Grant privileges on specific databases
7570    Databases(Vec<ObjectName>),
7571    /// Grant privileges on specific schemas
7572    Schemas(Vec<ObjectName>),
7573    /// Grant privileges on specific sequences
7574    Sequences(Vec<ObjectName>),
7575    /// Grant privileges on specific tables
7576    Tables(Vec<ObjectName>),
7577    /// Grant privileges on specific views
7578    Views(Vec<ObjectName>),
7579    /// Grant privileges on specific warehouses
7580    Warehouses(Vec<ObjectName>),
7581    /// Grant privileges on specific integrations
7582    Integrations(Vec<ObjectName>),
7583    /// Grant privileges on resource monitors
7584    ResourceMonitors(Vec<ObjectName>),
7585    /// Grant privileges on users
7586    Users(Vec<ObjectName>),
7587    /// Grant privileges on compute pools
7588    ComputePools(Vec<ObjectName>),
7589    /// Grant privileges on connections
7590    Connections(Vec<ObjectName>),
7591    /// Grant privileges on failover groups
7592    FailoverGroup(Vec<ObjectName>),
7593    /// Grant privileges on replication group
7594    ReplicationGroup(Vec<ObjectName>),
7595    /// Grant privileges on external volumes
7596    ExternalVolumes(Vec<ObjectName>),
7597    /// Grant privileges on a procedure. In dialects that
7598    /// support overloading, the argument types must be specified.
7599    ///
7600    /// For example:
7601    /// `GRANT USAGE ON PROCEDURE foo(varchar) TO ROLE role1`
7602    Procedure {
7603        /// The procedure name.
7604        name: ObjectName,
7605        /// Optional argument types for overloaded procedures.
7606        arg_types: Vec<DataType>,
7607    },
7608
7609    /// Grant privileges on a function. In dialects that
7610    /// support overloading, the argument types must be specified.
7611    ///
7612    /// For example:
7613    /// `GRANT USAGE ON FUNCTION foo(varchar) TO ROLE role1`
7614    Function {
7615        /// The function name.
7616        name: ObjectName,
7617        /// Optional argument types for overloaded functions.
7618        arg_types: Vec<DataType>,
7619    },
7620}
7621
7622impl fmt::Display for GrantObjects {
7623    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7624        match self {
7625            GrantObjects::Sequences(sequences) => {
7626                write!(f, "SEQUENCE {}", display_comma_separated(sequences))
7627            }
7628            GrantObjects::Databases(databases) => {
7629                write!(f, "DATABASE {}", display_comma_separated(databases))
7630            }
7631            GrantObjects::Schemas(schemas) => {
7632                write!(f, "SCHEMA {}", display_comma_separated(schemas))
7633            }
7634            GrantObjects::Tables(tables) => {
7635                write!(f, "{}", display_comma_separated(tables))
7636            }
7637            GrantObjects::Views(views) => {
7638                write!(f, "VIEW {}", display_comma_separated(views))
7639            }
7640            GrantObjects::Warehouses(warehouses) => {
7641                write!(f, "WAREHOUSE {}", display_comma_separated(warehouses))
7642            }
7643            GrantObjects::Integrations(integrations) => {
7644                write!(f, "INTEGRATION {}", display_comma_separated(integrations))
7645            }
7646            GrantObjects::AllSequencesInSchema { schemas } => {
7647                write!(
7648                    f,
7649                    "ALL SEQUENCES IN SCHEMA {}",
7650                    display_comma_separated(schemas)
7651                )
7652            }
7653            GrantObjects::AllTablesInSchema { schemas } => {
7654                write!(
7655                    f,
7656                    "ALL TABLES IN SCHEMA {}",
7657                    display_comma_separated(schemas)
7658                )
7659            }
7660            GrantObjects::AllExternalTablesInSchema { schemas } => {
7661                write!(
7662                    f,
7663                    "ALL EXTERNAL TABLES IN SCHEMA {}",
7664                    display_comma_separated(schemas)
7665                )
7666            }
7667            GrantObjects::AllViewsInSchema { schemas } => {
7668                write!(
7669                    f,
7670                    "ALL VIEWS IN SCHEMA {}",
7671                    display_comma_separated(schemas)
7672                )
7673            }
7674            GrantObjects::AllMaterializedViewsInSchema { schemas } => {
7675                write!(
7676                    f,
7677                    "ALL MATERIALIZED VIEWS IN SCHEMA {}",
7678                    display_comma_separated(schemas)
7679                )
7680            }
7681            GrantObjects::AllFunctionsInSchema { schemas } => {
7682                write!(
7683                    f,
7684                    "ALL FUNCTIONS IN SCHEMA {}",
7685                    display_comma_separated(schemas)
7686                )
7687            }
7688            GrantObjects::FutureSchemasInDatabase { databases } => {
7689                write!(
7690                    f,
7691                    "FUTURE SCHEMAS IN DATABASE {}",
7692                    display_comma_separated(databases)
7693                )
7694            }
7695            GrantObjects::FutureTablesInSchema { schemas } => {
7696                write!(
7697                    f,
7698                    "FUTURE TABLES IN SCHEMA {}",
7699                    display_comma_separated(schemas)
7700                )
7701            }
7702            GrantObjects::FutureExternalTablesInSchema { schemas } => {
7703                write!(
7704                    f,
7705                    "FUTURE EXTERNAL TABLES IN SCHEMA {}",
7706                    display_comma_separated(schemas)
7707                )
7708            }
7709            GrantObjects::FutureViewsInSchema { schemas } => {
7710                write!(
7711                    f,
7712                    "FUTURE VIEWS IN SCHEMA {}",
7713                    display_comma_separated(schemas)
7714                )
7715            }
7716            GrantObjects::FutureMaterializedViewsInSchema { schemas } => {
7717                write!(
7718                    f,
7719                    "FUTURE MATERIALIZED VIEWS IN SCHEMA {}",
7720                    display_comma_separated(schemas)
7721                )
7722            }
7723            GrantObjects::FutureSequencesInSchema { schemas } => {
7724                write!(
7725                    f,
7726                    "FUTURE SEQUENCES IN SCHEMA {}",
7727                    display_comma_separated(schemas)
7728                )
7729            }
7730            GrantObjects::ResourceMonitors(objects) => {
7731                write!(f, "RESOURCE MONITOR {}", display_comma_separated(objects))
7732            }
7733            GrantObjects::Users(objects) => {
7734                write!(f, "USER {}", display_comma_separated(objects))
7735            }
7736            GrantObjects::ComputePools(objects) => {
7737                write!(f, "COMPUTE POOL {}", display_comma_separated(objects))
7738            }
7739            GrantObjects::Connections(objects) => {
7740                write!(f, "CONNECTION {}", display_comma_separated(objects))
7741            }
7742            GrantObjects::FailoverGroup(objects) => {
7743                write!(f, "FAILOVER GROUP {}", display_comma_separated(objects))
7744            }
7745            GrantObjects::ReplicationGroup(objects) => {
7746                write!(f, "REPLICATION GROUP {}", display_comma_separated(objects))
7747            }
7748            GrantObjects::ExternalVolumes(objects) => {
7749                write!(f, "EXTERNAL VOLUME {}", display_comma_separated(objects))
7750            }
7751            GrantObjects::Procedure { name, arg_types } => {
7752                write!(f, "PROCEDURE {name}")?;
7753                if !arg_types.is_empty() {
7754                    write!(f, "({})", display_comma_separated(arg_types))?;
7755                }
7756                Ok(())
7757            }
7758            GrantObjects::Function { name, arg_types } => {
7759                write!(f, "FUNCTION {name}")?;
7760                if !arg_types.is_empty() {
7761                    write!(f, "({})", display_comma_separated(arg_types))?;
7762                }
7763                Ok(())
7764            }
7765        }
7766    }
7767}
7768
7769/// A `DENY` statement
7770///
7771/// [MsSql](https://learn.microsoft.com/en-us/sql/t-sql/statements/deny-transact-sql)
7772#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7773#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7774#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7775pub struct DenyStatement {
7776    /// The privileges to deny.
7777    pub privileges: Privileges,
7778    /// The objects the privileges apply to.
7779    pub objects: GrantObjects,
7780    /// The grantees (users/roles) to whom the denial applies.
7781    pub grantees: Vec<Grantee>,
7782    /// Optional identifier of the principal that performed the grant.
7783    pub granted_by: Option<Ident>,
7784    /// Optional cascade option controlling dependent objects.
7785    pub cascade: Option<CascadeOption>,
7786}
7787
7788impl fmt::Display for DenyStatement {
7789    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7790        write!(f, "DENY {}", self.privileges)?;
7791        write!(f, " ON {}", self.objects)?;
7792        if !self.grantees.is_empty() {
7793            write!(f, " TO {}", display_comma_separated(&self.grantees))?;
7794        }
7795        if let Some(cascade) = &self.cascade {
7796            write!(f, " {cascade}")?;
7797        }
7798        if let Some(granted_by) = &self.granted_by {
7799            write!(f, " AS {granted_by}")?;
7800        }
7801        Ok(())
7802    }
7803}
7804
7805/// SQL assignment `foo = expr` as used in SQLUpdate
7806#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7807#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7808#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7809pub struct Assignment {
7810    /// The left-hand side of the assignment.
7811    pub target: AssignmentTarget,
7812    /// The expression assigned to the target.
7813    pub value: Expr,
7814}
7815
7816impl fmt::Display for Assignment {
7817    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7818        write!(f, "{} = {}", self.target, self.value)
7819    }
7820}
7821
7822/// Left-hand side of an assignment in an UPDATE statement,
7823/// e.g. `foo` in `foo = 5` (ColumnName assignment) or
7824/// `(a, b)` in `(a, b) = (1, 2)` (Tuple assignment).
7825#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7826#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7827#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7828pub enum AssignmentTarget {
7829    /// A single column
7830    ColumnName(ObjectName),
7831    /// A tuple of columns
7832    Tuple(Vec<ObjectName>),
7833}
7834
7835impl fmt::Display for AssignmentTarget {
7836    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7837        match self {
7838            AssignmentTarget::ColumnName(column) => write!(f, "{column}"),
7839            AssignmentTarget::Tuple(columns) => write!(f, "({})", display_comma_separated(columns)),
7840        }
7841    }
7842}
7843
7844#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7845#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7846#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7847/// Expression forms allowed as a function argument.
7848pub enum FunctionArgExpr {
7849    /// A normal expression argument.
7850    Expr(Expr),
7851    /// Qualified wildcard, e.g. `alias.*` or `schema.table.*`.
7852    QualifiedWildcard(ObjectName),
7853    /// An unqualified `*` wildcard.
7854    Wildcard,
7855    /// An unqualified `*` wildcard with additional options, e.g. `* EXCLUDE(col)`.
7856    ///
7857    /// Used in Snowflake to support expressions like `HASH(* EXCLUDE(col))`.
7858    WildcardWithOptions(WildcardAdditionalOptions),
7859}
7860
7861impl From<Expr> for FunctionArgExpr {
7862    fn from(wildcard_expr: Expr) -> Self {
7863        match wildcard_expr {
7864            Expr::QualifiedWildcard(prefix, _) => Self::QualifiedWildcard(prefix),
7865            Expr::Wildcard(_) => Self::Wildcard,
7866            expr => Self::Expr(expr),
7867        }
7868    }
7869}
7870
7871impl fmt::Display for FunctionArgExpr {
7872    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7873        match self {
7874            FunctionArgExpr::Expr(expr) => write!(f, "{expr}"),
7875            FunctionArgExpr::QualifiedWildcard(prefix) => write!(f, "{prefix}.*"),
7876            FunctionArgExpr::Wildcard => f.write_str("*"),
7877            FunctionArgExpr::WildcardWithOptions(opts) => write!(f, "*{opts}"),
7878        }
7879    }
7880}
7881
7882#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7883#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7884#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7885/// Operator used to separate function arguments
7886pub enum FunctionArgOperator {
7887    /// function(arg1 = value1)
7888    Equals,
7889    /// function(arg1 => value1)
7890    RightArrow,
7891    /// function(arg1 := value1)
7892    Assignment,
7893    /// function(arg1 : value1)
7894    Colon,
7895    /// function(arg1 VALUE value1)
7896    Value,
7897}
7898
7899impl fmt::Display for FunctionArgOperator {
7900    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7901        match self {
7902            FunctionArgOperator::Equals => f.write_str("="),
7903            FunctionArgOperator::RightArrow => f.write_str("=>"),
7904            FunctionArgOperator::Assignment => f.write_str(":="),
7905            FunctionArgOperator::Colon => f.write_str(":"),
7906            FunctionArgOperator::Value => f.write_str("VALUE"),
7907        }
7908    }
7909}
7910
7911#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7912#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7913#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7914/// Forms of function arguments (named, expression-named, or positional).
7915pub enum FunctionArg {
7916    /// `name` is identifier
7917    ///
7918    /// Enabled when `Dialect::supports_named_fn_args_with_expr_name` returns 'false'
7919    Named {
7920        /// The identifier name of the argument.
7921        name: Ident,
7922        /// The argument expression or wildcard form.
7923        arg: FunctionArgExpr,
7924        /// The operator separating name and value.
7925        operator: FunctionArgOperator,
7926    },
7927    /// `name` is arbitrary expression
7928    ///
7929    /// Enabled when `Dialect::supports_named_fn_args_with_expr_name` returns 'true'
7930    ExprNamed {
7931        /// The expression used as the argument name.
7932        name: Expr,
7933        /// The argument expression or wildcard form.
7934        arg: FunctionArgExpr,
7935        /// The operator separating name and value.
7936        operator: FunctionArgOperator,
7937    },
7938    /// An unnamed argument (positional), given by expression or wildcard.
7939    Unnamed(FunctionArgExpr),
7940}
7941
7942impl fmt::Display for FunctionArg {
7943    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7944        match self {
7945            FunctionArg::Named {
7946                name,
7947                arg,
7948                operator,
7949            } => write!(f, "{name} {operator} {arg}"),
7950            FunctionArg::ExprNamed {
7951                name,
7952                arg,
7953                operator,
7954            } => write!(f, "{name} {operator} {arg}"),
7955            FunctionArg::Unnamed(unnamed_arg) => write!(f, "{unnamed_arg}"),
7956        }
7957    }
7958}
7959
7960#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7961#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7962#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7963/// Which cursor(s) to close.
7964pub enum CloseCursor {
7965    /// Close all cursors.
7966    All,
7967    /// Close a specific cursor by name.
7968    Specific {
7969        /// The name of the cursor to close.
7970        name: Ident,
7971    },
7972}
7973
7974impl fmt::Display for CloseCursor {
7975    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7976        match self {
7977            CloseCursor::All => write!(f, "ALL"),
7978            CloseCursor::Specific { name } => write!(f, "{name}"),
7979        }
7980    }
7981}
7982
7983/// A Drop Domain statement
7984#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7985#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7986#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7987pub struct DropDomain {
7988    /// Whether to drop the domain if it exists
7989    pub if_exists: bool,
7990    /// The name of the domain to drop
7991    pub name: ObjectName,
7992    /// The behavior to apply when dropping the domain
7993    pub drop_behavior: Option<DropBehavior>,
7994}
7995
7996/// A constant of form `<data_type> 'value'`.
7997/// This can represent ANSI SQL `DATE`, `TIME`, and `TIMESTAMP` literals (such as `DATE '2020-01-01'`),
7998/// as well as constants of other types (a non-standard PostgreSQL extension).
7999#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8000#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8001#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8002pub struct TypedString {
8003    /// The data type of the typed string (e.g. DATE, TIME, TIMESTAMP).
8004    pub data_type: DataType,
8005    /// The value of the constant.
8006    /// Hint: you can unwrap the string value using `value.into_string()`.
8007    pub value: ValueWithSpan,
8008    /// Flags whether this TypedString uses the [ODBC syntax].
8009    ///
8010    /// Example:
8011    /// ```sql
8012    /// -- An ODBC date literal:
8013    /// SELECT {d '2025-07-16'}
8014    /// -- This is equivalent to the standard ANSI SQL literal:
8015    /// SELECT DATE '2025-07-16'
8016    ///
8017    /// [ODBC syntax]: https://learn.microsoft.com/en-us/sql/odbc/reference/develop-app/date-time-and-timestamp-literals?view=sql-server-2017
8018    pub uses_odbc_syntax: bool,
8019}
8020
8021impl fmt::Display for TypedString {
8022    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8023        let data_type = &self.data_type;
8024        let value = &self.value;
8025        match self.uses_odbc_syntax {
8026            false => {
8027                write!(f, "{data_type}")?;
8028                write!(f, " {value}")
8029            }
8030            true => {
8031                let prefix = match data_type {
8032                    DataType::Date => "d",
8033                    DataType::Time(..) => "t",
8034                    DataType::Timestamp(..) => "ts",
8035                    _ => "?",
8036                };
8037                write!(f, "{{{prefix} {value}}}")
8038            }
8039        }
8040    }
8041}
8042
8043/// A function call
8044#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8045#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8046#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8047pub struct Function {
8048    /// The function name (may be qualified).
8049    pub name: ObjectName,
8050    /// Flags whether this function call uses the [ODBC syntax].
8051    ///
8052    /// Example:
8053    /// ```sql
8054    /// SELECT {fn CONCAT('foo', 'bar')}
8055    /// ```
8056    ///
8057    /// [ODBC syntax]: https://learn.microsoft.com/en-us/sql/odbc/reference/develop-app/scalar-function-calls?view=sql-server-2017
8058    pub uses_odbc_syntax: bool,
8059    /// The parameters to the function, including any options specified within the
8060    /// delimiting parentheses.
8061    ///
8062    /// Example:
8063    /// ```plaintext
8064    /// HISTOGRAM(0.5, 0.6)(x, y)
8065    /// ```
8066    ///
8067    /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/aggregate-functions/parametric-functions)
8068    pub parameters: FunctionArguments,
8069    /// The arguments to the function, including any options specified within the
8070    /// delimiting parentheses.
8071    pub args: FunctionArguments,
8072    /// e.g. `x > 5` in `COUNT(x) FILTER (WHERE x > 5)`
8073    pub filter: Option<Box<Expr>>,
8074    /// Indicates how `NULL`s should be handled in the calculation.
8075    ///
8076    /// Example:
8077    /// ```plaintext
8078    /// FIRST_VALUE( <expr> ) [ { IGNORE | RESPECT } NULLS ] OVER ...
8079    /// ```
8080    ///
8081    /// [Snowflake](https://docs.snowflake.com/en/sql-reference/functions/first_value)
8082    pub null_treatment: Option<NullTreatment>,
8083    /// The `OVER` clause, indicating a window function call.
8084    pub over: Option<WindowType>,
8085    /// A clause used with certain aggregate functions to control the ordering
8086    /// within grouped sets before the function is applied.
8087    ///
8088    /// Syntax:
8089    /// ```plaintext
8090    /// <aggregate_function>(expression) WITHIN GROUP (ORDER BY key [ASC | DESC], ...)
8091    /// ```
8092    pub within_group: Vec<OrderByExpr>,
8093}
8094
8095impl fmt::Display for Function {
8096    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8097        if self.uses_odbc_syntax {
8098            write!(f, "{{fn ")?;
8099        }
8100
8101        write!(f, "{}{}{}", self.name, self.parameters, self.args)?;
8102
8103        if !self.within_group.is_empty() {
8104            write!(
8105                f,
8106                " WITHIN GROUP (ORDER BY {})",
8107                display_comma_separated(&self.within_group)
8108            )?;
8109        }
8110
8111        if let Some(filter_cond) = &self.filter {
8112            write!(f, " FILTER (WHERE {filter_cond})")?;
8113        }
8114
8115        if let Some(null_treatment) = &self.null_treatment {
8116            write!(f, " {null_treatment}")?;
8117        }
8118
8119        if let Some(o) = &self.over {
8120            f.write_str(" OVER ")?;
8121            o.fmt(f)?;
8122        }
8123
8124        if self.uses_odbc_syntax {
8125            write!(f, "}}")?;
8126        }
8127
8128        Ok(())
8129    }
8130}
8131
8132/// The arguments passed to a function call.
8133#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8134#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8135#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8136pub enum FunctionArguments {
8137    /// Used for special functions like `CURRENT_TIMESTAMP` that are invoked
8138    /// without parentheses.
8139    None,
8140    /// On some dialects, a subquery can be passed without surrounding
8141    /// parentheses if it's the sole argument to the function.
8142    Subquery(Box<Query>),
8143    /// A normal function argument list, including any clauses within it such as
8144    /// `DISTINCT` or `ORDER BY`.
8145    List(FunctionArgumentList),
8146}
8147
8148impl fmt::Display for FunctionArguments {
8149    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8150        match self {
8151            FunctionArguments::None => Ok(()),
8152            FunctionArguments::Subquery(query) => write!(f, "({query})"),
8153            FunctionArguments::List(args) => write!(f, "({args})"),
8154        }
8155    }
8156}
8157
8158/// This represents everything inside the parentheses when calling a function.
8159#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8160#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8161#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8162pub struct FunctionArgumentList {
8163    /// `[ ALL | DISTINCT ]`
8164    pub duplicate_treatment: Option<DuplicateTreatment>,
8165    /// The function arguments.
8166    pub args: Vec<FunctionArg>,
8167    /// Additional clauses specified within the argument list.
8168    pub clauses: Vec<FunctionArgumentClause>,
8169}
8170
8171impl fmt::Display for FunctionArgumentList {
8172    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8173        if let Some(duplicate_treatment) = self.duplicate_treatment {
8174            write!(f, "{duplicate_treatment} ")?;
8175        }
8176        write!(f, "{}", display_comma_separated(&self.args))?;
8177        if !self.clauses.is_empty() {
8178            if !self.args.is_empty() {
8179                write!(f, " ")?;
8180            }
8181            write!(f, "{}", display_separated(&self.clauses, " "))?;
8182        }
8183        Ok(())
8184    }
8185}
8186
8187#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8188#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8189#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8190/// Clauses that can appear inside a function argument list.
8191pub enum FunctionArgumentClause {
8192    /// Indicates how `NULL`s should be handled in the calculation, e.g. in `FIRST_VALUE` on [BigQuery].
8193    ///
8194    /// Syntax:
8195    /// ```plaintext
8196    /// { IGNORE | RESPECT } NULLS ]
8197    /// ```
8198    ///
8199    /// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/navigation_functions#first_value
8200    IgnoreOrRespectNulls(NullTreatment),
8201    /// Specifies the the ordering for some ordered set aggregates, e.g. `ARRAY_AGG` on [BigQuery].
8202    ///
8203    /// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/aggregate_functions#array_agg
8204    OrderBy(Vec<OrderByExpr>),
8205    /// Specifies a limit for the `ARRAY_AGG` and `ARRAY_CONCAT_AGG` functions on BigQuery.
8206    Limit(Expr),
8207    /// Specifies the behavior on overflow of the `LISTAGG` function.
8208    ///
8209    /// See <https://trino.io/docs/current/functions/aggregate.html>.
8210    OnOverflow(ListAggOnOverflow),
8211    /// Specifies a minimum or maximum bound on the input to [`ANY_VALUE`] on BigQuery.
8212    ///
8213    /// Syntax:
8214    /// ```plaintext
8215    /// HAVING { MAX | MIN } expression
8216    /// ```
8217    ///
8218    /// [`ANY_VALUE`]: https://cloud.google.com/bigquery/docs/reference/standard-sql/aggregate_functions#any_value
8219    Having(HavingBound),
8220    /// The `SEPARATOR` clause to the [`GROUP_CONCAT`] function in MySQL.
8221    ///
8222    /// [`GROUP_CONCAT`]: https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html#function_group-concat
8223    Separator(ValueWithSpan),
8224    /// The `ON NULL` clause for some JSON functions.
8225    ///
8226    /// [MSSQL `JSON_ARRAY`](https://learn.microsoft.com/en-us/sql/t-sql/functions/json-array-transact-sql?view=sql-server-ver16)
8227    /// [MSSQL `JSON_OBJECT`](https://learn.microsoft.com/en-us/sql/t-sql/functions/json-object-transact-sql?view=sql-server-ver16>)
8228    /// [PostgreSQL JSON functions](https://www.postgresql.org/docs/current/functions-json.html#FUNCTIONS-JSON-PROCESSING)
8229    JsonNullClause(JsonNullClause),
8230    /// The `RETURNING` clause for some JSON functions in PostgreSQL
8231    ///
8232    /// [`JSON_OBJECT`](https://www.postgresql.org/docs/current/functions-json.html#:~:text=json_object)
8233    JsonReturningClause(JsonReturningClause),
8234}
8235
8236impl fmt::Display for FunctionArgumentClause {
8237    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8238        match self {
8239            FunctionArgumentClause::IgnoreOrRespectNulls(null_treatment) => {
8240                write!(f, "{null_treatment}")
8241            }
8242            FunctionArgumentClause::OrderBy(order_by) => {
8243                write!(f, "ORDER BY {}", display_comma_separated(order_by))
8244            }
8245            FunctionArgumentClause::Limit(limit) => write!(f, "LIMIT {limit}"),
8246            FunctionArgumentClause::OnOverflow(on_overflow) => write!(f, "{on_overflow}"),
8247            FunctionArgumentClause::Having(bound) => write!(f, "{bound}"),
8248            FunctionArgumentClause::Separator(sep) => write!(f, "SEPARATOR {sep}"),
8249            FunctionArgumentClause::JsonNullClause(null_clause) => write!(f, "{null_clause}"),
8250            FunctionArgumentClause::JsonReturningClause(returning_clause) => {
8251                write!(f, "{returning_clause}")
8252            }
8253        }
8254    }
8255}
8256
8257/// A method call
8258#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8259#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8260#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8261pub struct Method {
8262    /// The expression on which the method is invoked.
8263    pub expr: Box<Expr>,
8264    // always non-empty
8265    /// The sequence of chained method calls.
8266    pub method_chain: Vec<Function>,
8267}
8268
8269impl fmt::Display for Method {
8270    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8271        write!(
8272            f,
8273            "{}.{}",
8274            self.expr,
8275            display_separated(&self.method_chain, ".")
8276        )
8277    }
8278}
8279
8280#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8281#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8282#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8283/// How duplicate values are treated inside function argument lists.
8284pub enum DuplicateTreatment {
8285    /// Consider only unique values.
8286    Distinct,
8287    /// Retain all duplicate values (the default).
8288    All,
8289}
8290
8291impl fmt::Display for DuplicateTreatment {
8292    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8293        match self {
8294            DuplicateTreatment::Distinct => write!(f, "DISTINCT"),
8295            DuplicateTreatment::All => write!(f, "ALL"),
8296        }
8297    }
8298}
8299
8300#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8301#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8302#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8303/// How the `ANALYZE`/`EXPLAIN ANALYZE` format is specified.
8304pub enum AnalyzeFormatKind {
8305    /// Format provided as a keyword, e.g. `FORMAT JSON`.
8306    Keyword(AnalyzeFormat),
8307    /// Format provided as an assignment, e.g. `FORMAT=JSON`.
8308    Assignment(AnalyzeFormat),
8309}
8310
8311impl fmt::Display for AnalyzeFormatKind {
8312    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
8313        match self {
8314            AnalyzeFormatKind::Keyword(format) => write!(f, "FORMAT {format}"),
8315            AnalyzeFormatKind::Assignment(format) => write!(f, "FORMAT={format}"),
8316        }
8317    }
8318}
8319
8320#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8321#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8322#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8323/// Output formats supported for `ANALYZE`/`EXPLAIN ANALYZE`.
8324pub enum AnalyzeFormat {
8325    /// Plain text format.
8326    TEXT,
8327    /// Graphviz DOT format.
8328    GRAPHVIZ,
8329    /// JSON format.
8330    JSON,
8331    /// Traditional explain output.
8332    TRADITIONAL,
8333    /// Tree-style explain output.
8334    TREE,
8335}
8336
8337impl fmt::Display for AnalyzeFormat {
8338    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
8339        f.write_str(match self {
8340            AnalyzeFormat::TEXT => "TEXT",
8341            AnalyzeFormat::GRAPHVIZ => "GRAPHVIZ",
8342            AnalyzeFormat::JSON => "JSON",
8343            AnalyzeFormat::TRADITIONAL => "TRADITIONAL",
8344            AnalyzeFormat::TREE => "TREE",
8345        })
8346    }
8347}
8348
8349/// External table's available file format
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))]
8353pub enum FileFormat {
8354    /// Text file format.
8355    TEXTFILE,
8356    /// Sequence file format.
8357    SEQUENCEFILE,
8358    /// ORC file format.
8359    ORC,
8360    /// Parquet file format.
8361    PARQUET,
8362    /// Avro file format.
8363    AVRO,
8364    /// RCFile format.
8365    RCFILE,
8366    /// JSON file format.
8367    JSONFILE,
8368}
8369
8370impl fmt::Display for FileFormat {
8371    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8372        use self::FileFormat::*;
8373        f.write_str(match self {
8374            TEXTFILE => "TEXTFILE",
8375            SEQUENCEFILE => "SEQUENCEFILE",
8376            ORC => "ORC",
8377            PARQUET => "PARQUET",
8378            AVRO => "AVRO",
8379            RCFILE => "RCFILE",
8380            JSONFILE => "JSONFILE",
8381        })
8382    }
8383}
8384
8385/// The `ON OVERFLOW` clause of a LISTAGG invocation
8386#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8387#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8388#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8389pub enum ListAggOnOverflow {
8390    /// `ON OVERFLOW ERROR`
8391    Error,
8392
8393    /// `ON OVERFLOW TRUNCATE [ <filler> ] WITH[OUT] COUNT`
8394    Truncate {
8395        /// Optional filler expression used when truncating.
8396        filler: Option<Box<Expr>>,
8397        /// Whether to include a count when truncating.
8398        with_count: bool,
8399    },
8400}
8401
8402impl fmt::Display for ListAggOnOverflow {
8403    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8404        write!(f, "ON OVERFLOW")?;
8405        match self {
8406            ListAggOnOverflow::Error => write!(f, " ERROR"),
8407            ListAggOnOverflow::Truncate { filler, with_count } => {
8408                write!(f, " TRUNCATE")?;
8409                if let Some(filler) = filler {
8410                    write!(f, " {filler}")?;
8411                }
8412                if *with_count {
8413                    write!(f, " WITH")?;
8414                } else {
8415                    write!(f, " WITHOUT")?;
8416                }
8417                write!(f, " COUNT")
8418            }
8419        }
8420    }
8421}
8422
8423/// The `HAVING` clause in a call to `ANY_VALUE` on BigQuery.
8424#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8425#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8426#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8427pub struct HavingBound(pub HavingBoundKind, pub Expr);
8428
8429impl fmt::Display for HavingBound {
8430    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8431        write!(f, "HAVING {} {}", self.0, self.1)
8432    }
8433}
8434
8435#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8436#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8437#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8438/// Which bound is used in a HAVING clause for ANY_VALUE on BigQuery.
8439pub enum HavingBoundKind {
8440    /// The minimum bound.
8441    Min,
8442    /// The maximum bound.
8443    Max,
8444}
8445
8446impl fmt::Display for HavingBoundKind {
8447    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8448        match self {
8449            HavingBoundKind::Min => write!(f, "MIN"),
8450            HavingBoundKind::Max => write!(f, "MAX"),
8451        }
8452    }
8453}
8454
8455#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8456#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8457#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8458/// Types of database objects referenced by DDL statements.
8459pub enum ObjectType {
8460    /// A collation.
8461    Collation,
8462    /// A table.
8463    Table,
8464    /// A view.
8465    View,
8466    /// A materialized view.
8467    MaterializedView,
8468    /// An index.
8469    Index,
8470    /// A schema.
8471    Schema,
8472    /// A database.
8473    Database,
8474    /// A role.
8475    Role,
8476    /// A sequence.
8477    Sequence,
8478    /// A stage.
8479    Stage,
8480    /// A type definition.
8481    Type,
8482    /// A user.
8483    User,
8484    /// A stream.
8485    Stream,
8486}
8487
8488impl fmt::Display for ObjectType {
8489    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8490        f.write_str(match self {
8491            ObjectType::Collation => "COLLATION",
8492            ObjectType::Table => "TABLE",
8493            ObjectType::View => "VIEW",
8494            ObjectType::MaterializedView => "MATERIALIZED VIEW",
8495            ObjectType::Index => "INDEX",
8496            ObjectType::Schema => "SCHEMA",
8497            ObjectType::Database => "DATABASE",
8498            ObjectType::Role => "ROLE",
8499            ObjectType::Sequence => "SEQUENCE",
8500            ObjectType::Stage => "STAGE",
8501            ObjectType::Type => "TYPE",
8502            ObjectType::User => "USER",
8503            ObjectType::Stream => "STREAM",
8504        })
8505    }
8506}
8507
8508#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8509#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8510#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8511/// Types supported by `KILL` statements.
8512pub enum KillType {
8513    /// Kill a connection.
8514    Connection,
8515    /// Kill a running query.
8516    Query,
8517    /// Kill a mutation (ClickHouse).
8518    Mutation,
8519}
8520
8521impl fmt::Display for KillType {
8522    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8523        f.write_str(match self {
8524            // MySQL
8525            KillType::Connection => "CONNECTION",
8526            KillType::Query => "QUERY",
8527            // Clickhouse supports Mutation
8528            KillType::Mutation => "MUTATION",
8529        })
8530    }
8531}
8532
8533#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8534#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8535#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8536/// Distribution style options for Hive tables.
8537pub enum HiveDistributionStyle {
8538    /// Partitioned distribution with the given columns.
8539    PARTITIONED {
8540        /// Columns used for partitioning.
8541        columns: Vec<ColumnDef>,
8542    },
8543    /// Skewed distribution definition.
8544    SKEWED {
8545        /// Columns participating in the skew definition.
8546        columns: Vec<ColumnDef>,
8547        /// Columns listed in the `ON` clause for skewing.
8548        on: Vec<ColumnDef>,
8549        /// Whether skewed data is stored as directories.
8550        stored_as_directories: bool,
8551    },
8552    /// No distribution style specified.
8553    NONE,
8554}
8555
8556#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8557#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8558#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8559/// Row format specification for Hive tables (SERDE or DELIMITED).
8560pub enum HiveRowFormat {
8561    /// SerDe class specification with the implementing class name.
8562    SERDE {
8563        /// The SerDe implementation class name.
8564        class: String,
8565    },
8566    /// Delimited row format with one or more delimiter specifications.
8567    DELIMITED {
8568        /// The list of delimiters used for delimiting fields/lines.
8569        delimiters: Vec<HiveRowDelimiter>,
8570    },
8571}
8572
8573#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8574#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8575#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8576/// Format specification for `LOAD DATA` Hive operations.
8577pub struct HiveLoadDataFormat {
8578    /// SerDe expression used for the table.
8579    pub serde: Expr,
8580    /// Input format expression.
8581    pub input_format: Expr,
8582}
8583
8584#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8585#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8586#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8587/// A single row delimiter specification for Hive `ROW FORMAT`.
8588pub struct HiveRowDelimiter {
8589    /// The delimiter kind (fields/lines/etc.).
8590    pub delimiter: HiveDelimiter,
8591    /// The delimiter character identifier.
8592    pub char: Ident,
8593}
8594
8595impl fmt::Display for HiveRowDelimiter {
8596    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8597        write!(f, "{} ", self.delimiter)?;
8598        write!(f, "{}", self.char)
8599    }
8600}
8601
8602#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8603#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8604#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8605/// Kind of delimiter used in Hive `ROW FORMAT` definitions.
8606pub enum HiveDelimiter {
8607    /// Fields terminated by a delimiter.
8608    FieldsTerminatedBy,
8609    /// Fields escaped by a character.
8610    FieldsEscapedBy,
8611    /// Collection items terminated by a delimiter.
8612    CollectionItemsTerminatedBy,
8613    /// Map keys terminated by a delimiter.
8614    MapKeysTerminatedBy,
8615    /// Lines terminated by a delimiter.
8616    LinesTerminatedBy,
8617    /// Null represented by a specific token.
8618    NullDefinedAs,
8619}
8620
8621impl fmt::Display for HiveDelimiter {
8622    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8623        use HiveDelimiter::*;
8624        f.write_str(match self {
8625            FieldsTerminatedBy => "FIELDS TERMINATED BY",
8626            FieldsEscapedBy => "ESCAPED BY",
8627            CollectionItemsTerminatedBy => "COLLECTION ITEMS TERMINATED BY",
8628            MapKeysTerminatedBy => "MAP KEYS TERMINATED BY",
8629            LinesTerminatedBy => "LINES TERMINATED BY",
8630            NullDefinedAs => "NULL DEFINED AS",
8631        })
8632    }
8633}
8634
8635#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8636#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8637#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8638/// Describe output format options for Hive `DESCRIBE`/`EXPLAIN`.
8639pub enum HiveDescribeFormat {
8640    /// Extended describe output.
8641    Extended,
8642    /// Formatted describe output.
8643    Formatted,
8644}
8645
8646impl fmt::Display for HiveDescribeFormat {
8647    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8648        use HiveDescribeFormat::*;
8649        f.write_str(match self {
8650            Extended => "EXTENDED",
8651            Formatted => "FORMATTED",
8652        })
8653    }
8654}
8655
8656#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8657#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8658#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8659/// Aliases accepted for describe-style commands.
8660pub enum DescribeAlias {
8661    /// `DESCRIBE` alias.
8662    Describe,
8663    /// `EXPLAIN` alias.
8664    Explain,
8665    /// `DESC` alias.
8666    Desc,
8667}
8668
8669impl fmt::Display for DescribeAlias {
8670    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8671        use DescribeAlias::*;
8672        f.write_str(match self {
8673            Describe => "DESCRIBE",
8674            Explain => "EXPLAIN",
8675            Desc => "DESC",
8676        })
8677    }
8678}
8679
8680#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8681#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8682#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8683#[allow(clippy::large_enum_variant)]
8684/// Hive input/output format specification used in `CREATE TABLE`.
8685pub enum HiveIOFormat {
8686    /// Generic IO format with separate input and output expressions.
8687    IOF {
8688        /// Expression for the input format.
8689        input_format: Expr,
8690        /// Expression for the output format.
8691        output_format: Expr,
8692    },
8693    /// File format wrapper referencing a `FileFormat` variant.
8694    FileFormat {
8695        /// The file format used for storage.
8696        format: FileFormat,
8697    },
8698    /// `USING <format>` syntax used by Spark SQL.
8699    ///
8700    /// Example: `CREATE TABLE t (i INT) USING PARQUET`
8701    ///
8702    /// See <https://spark.apache.org/docs/latest/sql-ref-syntax-ddl-create-table-datasource.html>
8703    Using {
8704        /// The data source or format name, e.g. `parquet`, `delta`, `csv`.
8705        format: Ident,
8706    },
8707}
8708
8709#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Default)]
8710#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8711#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8712/// Hive table format and storage-related options.
8713pub struct HiveFormat {
8714    /// Optional row format specification.
8715    pub row_format: Option<HiveRowFormat>,
8716    /// Optional SerDe properties expressed as SQL options.
8717    pub serde_properties: Option<Vec<SqlOption>>,
8718    /// Optional input/output storage format details.
8719    pub storage: Option<HiveIOFormat>,
8720    /// Optional location (URI or path) for table data.
8721    pub location: Option<String>,
8722}
8723
8724#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8725#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8726#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8727/// A clustered index column specification.
8728pub struct ClusteredIndex {
8729    /// Column identifier for the clustered index entry.
8730    pub name: Ident,
8731    /// Optional sort direction: `Some(true)` for ASC, `Some(false)` for DESC, `None` for unspecified.
8732    pub asc: Option<bool>,
8733}
8734
8735impl fmt::Display for ClusteredIndex {
8736    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8737        write!(f, "{}", self.name)?;
8738        match self.asc {
8739            Some(true) => write!(f, " ASC"),
8740            Some(false) => write!(f, " DESC"),
8741            _ => Ok(()),
8742        }
8743    }
8744}
8745
8746#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8747#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8748#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8749/// Clustered options used for `CREATE TABLE` clustered/indexed storage.
8750pub enum TableOptionsClustered {
8751    /// Use a columnstore index.
8752    ColumnstoreIndex,
8753    /// Columnstore index with an explicit ordering of columns.
8754    ColumnstoreIndexOrder(Vec<Ident>),
8755    /// A named clustered index with one or more columns.
8756    Index(Vec<ClusteredIndex>),
8757}
8758
8759impl fmt::Display for TableOptionsClustered {
8760    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8761        match self {
8762            TableOptionsClustered::ColumnstoreIndex => {
8763                write!(f, "CLUSTERED COLUMNSTORE INDEX")
8764            }
8765            TableOptionsClustered::ColumnstoreIndexOrder(values) => {
8766                write!(
8767                    f,
8768                    "CLUSTERED COLUMNSTORE INDEX ORDER ({})",
8769                    display_comma_separated(values)
8770                )
8771            }
8772            TableOptionsClustered::Index(values) => {
8773                write!(f, "CLUSTERED INDEX ({})", display_comma_separated(values))
8774            }
8775        }
8776    }
8777}
8778
8779/// Specifies which partition the boundary values on table partitioning belongs to.
8780#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash)]
8781#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8782#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8783pub enum PartitionRangeDirection {
8784    /// LEFT range direction.
8785    Left,
8786    /// RIGHT range direction.
8787    Right,
8788}
8789
8790#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8791#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8792#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8793/// SQL option syntax used in table and server definitions.
8794pub enum SqlOption {
8795    /// Clustered represents the clustered version of table storage for MSSQL.
8796    ///
8797    /// <https://learn.microsoft.com/en-us/sql/t-sql/statements/create-table-azure-sql-data-warehouse?view=aps-pdw-2016-au7#TableOptions>
8798    Clustered(TableOptionsClustered),
8799    /// Single identifier options, e.g. `HEAP` for MSSQL.
8800    ///
8801    /// <https://learn.microsoft.com/en-us/sql/t-sql/statements/create-table-azure-sql-data-warehouse?view=aps-pdw-2016-au7#TableOptions>
8802    Ident(Ident),
8803    /// Any option that consists of a key value pair where the value is an expression. e.g.
8804    ///
8805    ///   WITH(DISTRIBUTION = ROUND_ROBIN)
8806    KeyValue {
8807        /// The option key identifier.
8808        key: Ident,
8809        /// The expression value for the option.
8810        value: Expr,
8811    },
8812    /// One or more table partitions and represents which partition the boundary values belong to,
8813    /// e.g.
8814    ///
8815    ///   PARTITION (id RANGE LEFT FOR VALUES (10, 20, 30, 40))
8816    ///
8817    /// <https://learn.microsoft.com/en-us/sql/t-sql/statements/create-table-azure-sql-data-warehouse?view=aps-pdw-2016-au7#TablePartitionOptions>
8818    Partition {
8819        /// The partition column name.
8820        column_name: Ident,
8821        /// Optional direction for the partition range (LEFT/RIGHT).
8822        range_direction: Option<PartitionRangeDirection>,
8823        /// Values that define the partition boundaries.
8824        for_values: Vec<Expr>,
8825    },
8826    /// Comment parameter (supports `=` and no `=` syntax)
8827    Comment(CommentDef),
8828    /// MySQL TableSpace option
8829    /// <https://dev.mysql.com/doc/refman/8.4/en/create-table.html>
8830    TableSpace(TablespaceOption),
8831    /// An option representing a key value pair, where the value is a parenthesized list and with an optional name
8832    /// e.g.
8833    ///
8834    ///   UNION  = (tbl_name\[,tbl_name\]...) <https://dev.mysql.com/doc/refman/8.4/en/create-table.html>
8835    ///   ENGINE = ReplicatedMergeTree('/table_name','{replica}', ver) <https://clickhouse.com/docs/engines/table-engines/mergetree-family/replication>
8836    ///   ENGINE = SummingMergeTree(\[columns\]) <https://clickhouse.com/docs/engines/table-engines/mergetree-family/summingmergetree>
8837    NamedParenthesizedList(NamedParenthesizedList),
8838}
8839
8840impl fmt::Display for SqlOption {
8841    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8842        match self {
8843            SqlOption::Clustered(c) => write!(f, "{c}"),
8844            SqlOption::Ident(ident) => {
8845                write!(f, "{ident}")
8846            }
8847            SqlOption::KeyValue { key: name, value } => {
8848                write!(f, "{name} = {value}")
8849            }
8850            SqlOption::Partition {
8851                column_name,
8852                range_direction,
8853                for_values,
8854            } => {
8855                let direction = match range_direction {
8856                    Some(PartitionRangeDirection::Left) => " LEFT",
8857                    Some(PartitionRangeDirection::Right) => " RIGHT",
8858                    None => "",
8859                };
8860
8861                write!(
8862                    f,
8863                    "PARTITION ({} RANGE{} FOR VALUES ({}))",
8864                    column_name,
8865                    direction,
8866                    display_comma_separated(for_values)
8867                )
8868            }
8869            SqlOption::TableSpace(tablespace_option) => {
8870                write!(f, "TABLESPACE {}", tablespace_option.name)?;
8871                match tablespace_option.storage {
8872                    Some(StorageType::Disk) => write!(f, " STORAGE DISK"),
8873                    Some(StorageType::Memory) => write!(f, " STORAGE MEMORY"),
8874                    None => Ok(()),
8875                }
8876            }
8877            SqlOption::Comment(comment) => match comment {
8878                CommentDef::WithEq(comment) => {
8879                    write!(f, "COMMENT = '{comment}'")
8880                }
8881                CommentDef::WithoutEq(comment) => {
8882                    write!(f, "COMMENT '{comment}'")
8883                }
8884            },
8885            SqlOption::NamedParenthesizedList(value) => {
8886                write!(f, "{} = ", value.key)?;
8887                if let Some(key) = &value.name {
8888                    write!(f, "{key}")?;
8889                }
8890                if !value.values.is_empty() {
8891                    write!(f, "({})", display_comma_separated(&value.values))?
8892                }
8893                Ok(())
8894            }
8895        }
8896    }
8897}
8898
8899#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
8900#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8901#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8902/// Storage type options for a tablespace.
8903pub enum StorageType {
8904    /// Store on disk.
8905    Disk,
8906    /// Store in memory.
8907    Memory,
8908}
8909
8910#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
8911#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8912#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8913/// MySql TableSpace option
8914/// <https://dev.mysql.com/doc/refman/8.4/en/create-table.html>
8915pub struct TablespaceOption {
8916    /// Name of the tablespace.
8917    pub name: String,
8918    /// Optional storage type for the tablespace.
8919    pub storage: Option<StorageType>,
8920}
8921
8922#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8923#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8924#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8925/// A key/value identifier pair used for secret or key-based options.
8926pub struct SecretOption {
8927    /// The option key identifier.
8928    pub key: Ident,
8929    /// The option value identifier.
8930    pub value: Ident,
8931}
8932
8933impl fmt::Display for SecretOption {
8934    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8935        write!(f, "{} {}", self.key, self.value)
8936    }
8937}
8938
8939/// A `CREATE SERVER` statement.
8940///
8941/// [PostgreSQL Documentation](https://www.postgresql.org/docs/current/sql-createserver.html)
8942#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8943#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8944#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8945pub struct CreateServerStatement {
8946    /// The server name.
8947    pub name: ObjectName,
8948    /// Whether `IF NOT EXISTS` was specified.
8949    pub if_not_exists: bool,
8950    /// Optional server type identifier.
8951    pub server_type: Option<Ident>,
8952    /// Optional server version identifier.
8953    pub version: Option<Ident>,
8954    /// Foreign-data wrapper object name.
8955    pub foreign_data_wrapper: ObjectName,
8956    /// Optional list of server options.
8957    pub options: Option<Vec<CreateServerOption>>,
8958}
8959
8960impl fmt::Display for CreateServerStatement {
8961    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8962        let CreateServerStatement {
8963            name,
8964            if_not_exists,
8965            server_type,
8966            version,
8967            foreign_data_wrapper,
8968            options,
8969        } = self;
8970
8971        write!(
8972            f,
8973            "CREATE SERVER {if_not_exists}{name} ",
8974            if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
8975        )?;
8976
8977        if let Some(st) = server_type {
8978            write!(f, "TYPE {st} ")?;
8979        }
8980
8981        if let Some(v) = version {
8982            write!(f, "VERSION {v} ")?;
8983        }
8984
8985        write!(f, "FOREIGN DATA WRAPPER {foreign_data_wrapper}")?;
8986
8987        if let Some(o) = options {
8988            write!(f, " OPTIONS ({o})", o = display_comma_separated(o))?;
8989        }
8990
8991        Ok(())
8992    }
8993}
8994
8995/// A key/value option for `CREATE SERVER`.
8996#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8997#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8998#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8999pub struct CreateServerOption {
9000    /// Option key identifier.
9001    pub key: Ident,
9002    /// Option value identifier.
9003    pub value: Ident,
9004}
9005
9006impl fmt::Display for CreateServerOption {
9007    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9008        write!(f, "{} {}", self.key, self.value)
9009    }
9010}
9011
9012#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9013#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9014#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9015/// Options supported by DuckDB for `ATTACH DATABASE`.
9016pub enum AttachDuckDBDatabaseOption {
9017    /// READ_ONLY option, optional boolean value.
9018    ReadOnly(Option<bool>),
9019    /// TYPE option specifying a database type identifier.
9020    Type(Ident),
9021}
9022
9023impl fmt::Display for AttachDuckDBDatabaseOption {
9024    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9025        match self {
9026            AttachDuckDBDatabaseOption::ReadOnly(Some(true)) => write!(f, "READ_ONLY true"),
9027            AttachDuckDBDatabaseOption::ReadOnly(Some(false)) => write!(f, "READ_ONLY false"),
9028            AttachDuckDBDatabaseOption::ReadOnly(None) => write!(f, "READ_ONLY"),
9029            AttachDuckDBDatabaseOption::Type(t) => write!(f, "TYPE {t}"),
9030        }
9031    }
9032}
9033
9034#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9035#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9036#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9037/// Mode for transactions: access mode or isolation level.
9038pub enum TransactionMode {
9039    /// Access mode for a transaction (e.g. `READ ONLY` / `READ WRITE`).
9040    AccessMode(TransactionAccessMode),
9041    /// Isolation level for a transaction (e.g. `SERIALIZABLE`).
9042    IsolationLevel(TransactionIsolationLevel),
9043}
9044
9045impl fmt::Display for TransactionMode {
9046    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9047        use TransactionMode::*;
9048        match self {
9049            AccessMode(access_mode) => write!(f, "{access_mode}"),
9050            IsolationLevel(iso_level) => write!(f, "ISOLATION LEVEL {iso_level}"),
9051        }
9052    }
9053}
9054
9055#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9056#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9057#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9058/// Transaction access mode (READ ONLY / READ WRITE).
9059pub enum TransactionAccessMode {
9060    /// READ ONLY access mode.
9061    ReadOnly,
9062    /// READ WRITE access mode.
9063    ReadWrite,
9064}
9065
9066impl fmt::Display for TransactionAccessMode {
9067    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9068        use TransactionAccessMode::*;
9069        f.write_str(match self {
9070            ReadOnly => "READ ONLY",
9071            ReadWrite => "READ WRITE",
9072        })
9073    }
9074}
9075
9076#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9077#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9078#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9079/// Transaction isolation levels.
9080pub enum TransactionIsolationLevel {
9081    /// READ UNCOMMITTED isolation level.
9082    ReadUncommitted,
9083    /// READ COMMITTED isolation level.
9084    ReadCommitted,
9085    /// REPEATABLE READ isolation level.
9086    RepeatableRead,
9087    /// SERIALIZABLE isolation level.
9088    Serializable,
9089    /// SNAPSHOT isolation level.
9090    Snapshot,
9091}
9092
9093impl fmt::Display for TransactionIsolationLevel {
9094    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9095        use TransactionIsolationLevel::*;
9096        f.write_str(match self {
9097            ReadUncommitted => "READ UNCOMMITTED",
9098            ReadCommitted => "READ COMMITTED",
9099            RepeatableRead => "REPEATABLE READ",
9100            Serializable => "SERIALIZABLE",
9101            Snapshot => "SNAPSHOT",
9102        })
9103    }
9104}
9105
9106/// Modifier for the transaction in the `BEGIN` syntax
9107///
9108/// SQLite: <https://sqlite.org/lang_transaction.html>
9109/// MS-SQL: <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/try-catch-transact-sql>
9110#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9111#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9112#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9113pub enum TransactionModifier {
9114    /// DEFERRED transaction modifier.
9115    Deferred,
9116    /// IMMEDIATE transaction modifier.
9117    Immediate,
9118    /// EXCLUSIVE transaction modifier.
9119    Exclusive,
9120    /// TRY block modifier (MS-SQL style TRY/CATCH).
9121    Try,
9122    /// CATCH block modifier (MS-SQL style TRY/CATCH).
9123    Catch,
9124}
9125
9126impl fmt::Display for TransactionModifier {
9127    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9128        use TransactionModifier::*;
9129        f.write_str(match self {
9130            Deferred => "DEFERRED",
9131            Immediate => "IMMEDIATE",
9132            Exclusive => "EXCLUSIVE",
9133            Try => "TRY",
9134            Catch => "CATCH",
9135        })
9136    }
9137}
9138
9139#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9140#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9141#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9142/// Filter forms usable in SHOW statements.
9143pub enum ShowStatementFilter {
9144    /// Filter using LIKE pattern.
9145    Like(String),
9146    /// Filter using ILIKE pattern.
9147    ILike(String),
9148    /// Filter using a WHERE expression.
9149    Where(Expr),
9150    /// Filter provided without a keyword (raw string).
9151    NoKeyword(String),
9152}
9153
9154impl fmt::Display for ShowStatementFilter {
9155    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9156        use ShowStatementFilter::*;
9157        match self {
9158            Like(pattern) => write!(f, "LIKE '{}'", value::escape_single_quote_string(pattern)),
9159            ILike(pattern) => write!(f, "ILIKE {}", value::escape_single_quote_string(pattern)),
9160            Where(expr) => write!(f, "WHERE {expr}"),
9161            NoKeyword(pattern) => write!(f, "'{}'", value::escape_single_quote_string(pattern)),
9162        }
9163    }
9164}
9165
9166#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9167#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9168#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9169/// Clause types used with SHOW ... IN/FROM.
9170pub enum ShowStatementInClause {
9171    /// Use the `IN` clause.
9172    IN,
9173    /// Use the `FROM` clause.
9174    FROM,
9175}
9176
9177impl fmt::Display for ShowStatementInClause {
9178    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9179        use ShowStatementInClause::*;
9180        match self {
9181            FROM => write!(f, "FROM"),
9182            IN => write!(f, "IN"),
9183        }
9184    }
9185}
9186
9187/// Sqlite specific syntax
9188///
9189/// See [Sqlite documentation](https://sqlite.org/lang_conflict.html)
9190/// for more details.
9191#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9192#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9193#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9194pub enum SqliteOnConflict {
9195    /// Use ROLLBACK on conflict.
9196    Rollback,
9197    /// Use ABORT on conflict.
9198    Abort,
9199    /// Use FAIL on conflict.
9200    Fail,
9201    /// Use IGNORE on conflict.
9202    Ignore,
9203    /// Use REPLACE on conflict.
9204    Replace,
9205}
9206
9207impl fmt::Display for SqliteOnConflict {
9208    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9209        use SqliteOnConflict::*;
9210        match self {
9211            Rollback => write!(f, "OR ROLLBACK"),
9212            Abort => write!(f, "OR ABORT"),
9213            Fail => write!(f, "OR FAIL"),
9214            Ignore => write!(f, "OR IGNORE"),
9215            Replace => write!(f, "OR REPLACE"),
9216        }
9217    }
9218}
9219
9220/// Mysql specific syntax
9221///
9222/// See [Mysql documentation](https://dev.mysql.com/doc/refman/8.0/en/replace.html)
9223/// See [Mysql documentation](https://dev.mysql.com/doc/refman/8.0/en/insert.html)
9224/// for more details.
9225#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9226#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9227#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9228pub enum MysqlInsertPriority {
9229    /// LOW_PRIORITY modifier for INSERT/REPLACE.
9230    LowPriority,
9231    /// DELAYED modifier for INSERT/REPLACE.
9232    Delayed,
9233    /// HIGH_PRIORITY modifier for INSERT/REPLACE.
9234    HighPriority,
9235}
9236
9237impl fmt::Display for crate::ast::MysqlInsertPriority {
9238    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9239        use MysqlInsertPriority::*;
9240        match self {
9241            LowPriority => write!(f, "LOW_PRIORITY"),
9242            Delayed => write!(f, "DELAYED"),
9243            HighPriority => write!(f, "HIGH_PRIORITY"),
9244        }
9245    }
9246}
9247
9248#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9249#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9250#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9251/// Source for the `COPY` command: a table or a query.
9252pub enum CopySource {
9253    /// Copy from a table with optional column list.
9254    Table {
9255        /// The name of the table to copy from.
9256        table_name: ObjectName,
9257        /// A list of column names to copy. Empty list means that all columns
9258        /// are copied.
9259        columns: Vec<Ident>,
9260    },
9261    /// Copy from the results of a query.
9262    Query(Box<Query>),
9263}
9264
9265#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9266#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9267#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9268/// Target for the `COPY` command: STDIN, STDOUT, a file, or a program.
9269pub enum CopyTarget {
9270    /// Use standard input as the source.
9271    Stdin,
9272    /// Use standard output as the target.
9273    Stdout,
9274    /// Read from or write to a file.
9275    File {
9276        /// The path name of the input or output file.
9277        filename: String,
9278    },
9279    /// Use a program as the source or target (shell command).
9280    Program {
9281        /// A command to execute
9282        command: String,
9283    },
9284}
9285
9286impl fmt::Display for CopyTarget {
9287    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9288        use CopyTarget::*;
9289        match self {
9290            Stdin => write!(f, "STDIN"),
9291            Stdout => write!(f, "STDOUT"),
9292            File { filename } => write!(f, "'{}'", value::escape_single_quote_string(filename)),
9293            Program { command } => write!(
9294                f,
9295                "PROGRAM '{}'",
9296                value::escape_single_quote_string(command)
9297            ),
9298        }
9299    }
9300}
9301
9302#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9303#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9304#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9305/// Action to take `ON COMMIT` for temporary tables.
9306pub enum OnCommit {
9307    /// Delete rows on commit.
9308    DeleteRows,
9309    /// Preserve rows on commit.
9310    PreserveRows,
9311    /// Drop the table on commit.
9312    Drop,
9313}
9314
9315/// An option in `COPY` statement.
9316///
9317/// <https://www.postgresql.org/docs/14/sql-copy.html>
9318#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9319#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9320#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9321pub enum CopyOption {
9322    /// FORMAT format_name
9323    Format(Ident),
9324    /// FREEZE \[ boolean \]
9325    Freeze(bool),
9326    /// DELIMITER 'delimiter_character'
9327    Delimiter(char),
9328    /// NULL 'null_string'
9329    Null(String),
9330    /// HEADER \[ boolean \]
9331    Header(bool),
9332    /// QUOTE 'quote_character'
9333    Quote(char),
9334    /// ESCAPE 'escape_character'
9335    Escape(char),
9336    /// FORCE_QUOTE { ( column_name [, ...] ) | * }
9337    ForceQuote(Vec<Ident>),
9338    /// FORCE_NOT_NULL ( column_name [, ...] )
9339    ForceNotNull(Vec<Ident>),
9340    /// FORCE_NULL ( column_name [, ...] )
9341    ForceNull(Vec<Ident>),
9342    /// ENCODING 'encoding_name'
9343    Encoding(String),
9344}
9345
9346impl fmt::Display for CopyOption {
9347    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9348        use CopyOption::*;
9349        match self {
9350            Format(name) => write!(f, "FORMAT {name}"),
9351            Freeze(true) => write!(f, "FREEZE"),
9352            Freeze(false) => write!(f, "FREEZE FALSE"),
9353            Delimiter(char) => write!(f, "DELIMITER '{char}'"),
9354            Null(string) => write!(f, "NULL '{}'", value::escape_single_quote_string(string)),
9355            Header(true) => write!(f, "HEADER"),
9356            Header(false) => write!(f, "HEADER FALSE"),
9357            Quote(char) => write!(f, "QUOTE '{char}'"),
9358            Escape(char) => write!(f, "ESCAPE '{char}'"),
9359            ForceQuote(columns) => write!(f, "FORCE_QUOTE ({})", display_comma_separated(columns)),
9360            ForceNotNull(columns) => {
9361                write!(f, "FORCE_NOT_NULL ({})", display_comma_separated(columns))
9362            }
9363            ForceNull(columns) => write!(f, "FORCE_NULL ({})", display_comma_separated(columns)),
9364            Encoding(name) => write!(f, "ENCODING '{}'", value::escape_single_quote_string(name)),
9365        }
9366    }
9367}
9368
9369/// An option in `COPY` statement before PostgreSQL version 9.0.
9370///
9371/// [PostgreSQL](https://www.postgresql.org/docs/8.4/sql-copy.html)
9372/// [Redshift](https://docs.aws.amazon.com/redshift/latest/dg/r_COPY-alphabetical-parm-list.html)
9373#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9374#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9375#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9376pub enum CopyLegacyOption {
9377    /// ACCEPTANYDATE
9378    AcceptAnyDate,
9379    /// ACCEPTINVCHARS
9380    AcceptInvChars(Option<String>),
9381    /// ADDQUOTES
9382    AddQuotes,
9383    /// ALLOWOVERWRITE
9384    AllowOverwrite,
9385    /// BINARY
9386    Binary,
9387    /// BLANKSASNULL
9388    BlankAsNull,
9389    /// BZIP2
9390    Bzip2,
9391    /// CLEANPATH
9392    CleanPath,
9393    /// COMPUPDATE [ PRESET | { ON | TRUE } | { OFF | FALSE } ]
9394    CompUpdate {
9395        /// Whether the COMPUPDATE PRESET option was used.
9396        preset: bool,
9397        /// Optional enabled flag for COMPUPDATE.
9398        enabled: Option<bool>,
9399    },
9400    /// CSV ...
9401    Csv(Vec<CopyLegacyCsvOption>),
9402    /// DATEFORMAT \[ AS \] {'dateformat_string' | 'auto' }
9403    DateFormat(Option<String>),
9404    /// DELIMITER \[ AS \] 'delimiter_character'
9405    Delimiter(char),
9406    /// EMPTYASNULL
9407    EmptyAsNull,
9408    /// `ENCRYPTED \[ AUTO \]`
9409    Encrypted {
9410        /// Whether `AUTO` was specified for encryption.
9411        auto: bool,
9412    },
9413    /// ESCAPE
9414    Escape,
9415    /// EXTENSION 'extension-name'
9416    Extension(String),
9417    /// FIXEDWIDTH \[ AS \] 'fixedwidth-spec'
9418    FixedWidth(String),
9419    /// GZIP
9420    Gzip,
9421    /// HEADER
9422    Header,
9423    /// IAM_ROLE { DEFAULT | 'arn:aws:iam::123456789:role/role1' }
9424    IamRole(IamRoleKind),
9425    /// IGNOREHEADER \[ AS \] number_rows
9426    IgnoreHeader(u64),
9427    /// JSON \[ AS \] 'json_option'
9428    Json(Option<String>),
9429    /// MANIFEST \[ VERBOSE \]
9430    Manifest {
9431        /// Whether the MANIFEST is verbose.
9432        verbose: bool,
9433    },
9434    /// MAXFILESIZE \[ AS \] max-size \[ MB | GB \]
9435    MaxFileSize(FileSize),
9436    /// `NULL \[ AS \] 'null_string'`
9437    Null(String),
9438    /// `PARALLEL [ { ON | TRUE } | { OFF | FALSE } ]`
9439    Parallel(Option<bool>),
9440    /// PARQUET
9441    Parquet,
9442    /// PARTITION BY ( column_name [, ... ] ) \[ INCLUDE \]
9443    PartitionBy(UnloadPartitionBy),
9444    /// REGION \[ AS \] 'aws-region' }
9445    Region(String),
9446    /// REMOVEQUOTES
9447    RemoveQuotes,
9448    /// ROWGROUPSIZE \[ AS \] size \[ MB | GB \]
9449    RowGroupSize(FileSize),
9450    /// STATUPDATE [ { ON | TRUE } | { OFF | FALSE } ]
9451    StatUpdate(Option<bool>),
9452    /// TIMEFORMAT \[ AS \] {'timeformat_string' | 'auto' | 'epochsecs' | 'epochmillisecs' }
9453    TimeFormat(Option<String>),
9454    /// TRUNCATECOLUMNS
9455    TruncateColumns,
9456    /// ZSTD
9457    Zstd,
9458    /// Redshift `CREDENTIALS 'auth-args'`
9459    /// <https://docs.aws.amazon.com/redshift/latest/dg/copy-parameters-authorization.html>
9460    Credentials(String),
9461}
9462
9463impl fmt::Display for CopyLegacyOption {
9464    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9465        use CopyLegacyOption::*;
9466        match self {
9467            AcceptAnyDate => write!(f, "ACCEPTANYDATE"),
9468            AcceptInvChars(ch) => {
9469                write!(f, "ACCEPTINVCHARS")?;
9470                if let Some(ch) = ch {
9471                    write!(f, " '{}'", value::escape_single_quote_string(ch))?;
9472                }
9473                Ok(())
9474            }
9475            AddQuotes => write!(f, "ADDQUOTES"),
9476            AllowOverwrite => write!(f, "ALLOWOVERWRITE"),
9477            Binary => write!(f, "BINARY"),
9478            BlankAsNull => write!(f, "BLANKSASNULL"),
9479            Bzip2 => write!(f, "BZIP2"),
9480            CleanPath => write!(f, "CLEANPATH"),
9481            CompUpdate { preset, enabled } => {
9482                write!(f, "COMPUPDATE")?;
9483                if *preset {
9484                    write!(f, " PRESET")?;
9485                } else if let Some(enabled) = enabled {
9486                    write!(
9487                        f,
9488                        "{}",
9489                        match enabled {
9490                            true => " TRUE",
9491                            false => " FALSE",
9492                        }
9493                    )?;
9494                }
9495                Ok(())
9496            }
9497            Csv(opts) => {
9498                write!(f, "CSV")?;
9499                if !opts.is_empty() {
9500                    write!(f, " {}", display_separated(opts, " "))?;
9501                }
9502                Ok(())
9503            }
9504            DateFormat(fmt) => {
9505                write!(f, "DATEFORMAT")?;
9506                if let Some(fmt) = fmt {
9507                    write!(f, " '{}'", value::escape_single_quote_string(fmt))?;
9508                }
9509                Ok(())
9510            }
9511            Delimiter(char) => write!(f, "DELIMITER '{char}'"),
9512            EmptyAsNull => write!(f, "EMPTYASNULL"),
9513            Encrypted { auto } => write!(f, "ENCRYPTED{}", if *auto { " AUTO" } else { "" }),
9514            Escape => write!(f, "ESCAPE"),
9515            Extension(ext) => write!(f, "EXTENSION '{}'", value::escape_single_quote_string(ext)),
9516            FixedWidth(spec) => write!(
9517                f,
9518                "FIXEDWIDTH '{}'",
9519                value::escape_single_quote_string(spec)
9520            ),
9521            Gzip => write!(f, "GZIP"),
9522            Header => write!(f, "HEADER"),
9523            IamRole(role) => write!(f, "IAM_ROLE {role}"),
9524            IgnoreHeader(num_rows) => write!(f, "IGNOREHEADER {num_rows}"),
9525            Json(opt) => {
9526                write!(f, "JSON")?;
9527                if let Some(opt) = opt {
9528                    write!(f, " AS '{}'", value::escape_single_quote_string(opt))?;
9529                }
9530                Ok(())
9531            }
9532            Manifest { verbose } => write!(f, "MANIFEST{}", if *verbose { " VERBOSE" } else { "" }),
9533            MaxFileSize(file_size) => write!(f, "MAXFILESIZE {file_size}"),
9534            Null(string) => write!(f, "NULL '{}'", value::escape_single_quote_string(string)),
9535            Parallel(enabled) => {
9536                write!(
9537                    f,
9538                    "PARALLEL{}",
9539                    match enabled {
9540                        Some(true) => " TRUE",
9541                        Some(false) => " FALSE",
9542                        _ => "",
9543                    }
9544                )
9545            }
9546            Parquet => write!(f, "PARQUET"),
9547            PartitionBy(p) => write!(f, "{p}"),
9548            Region(region) => write!(f, "REGION '{}'", value::escape_single_quote_string(region)),
9549            RemoveQuotes => write!(f, "REMOVEQUOTES"),
9550            RowGroupSize(file_size) => write!(f, "ROWGROUPSIZE {file_size}"),
9551            StatUpdate(enabled) => {
9552                write!(
9553                    f,
9554                    "STATUPDATE{}",
9555                    match enabled {
9556                        Some(true) => " TRUE",
9557                        Some(false) => " FALSE",
9558                        _ => "",
9559                    }
9560                )
9561            }
9562            TimeFormat(fmt) => {
9563                write!(f, "TIMEFORMAT")?;
9564                if let Some(fmt) = fmt {
9565                    write!(f, " '{}'", value::escape_single_quote_string(fmt))?;
9566                }
9567                Ok(())
9568            }
9569            TruncateColumns => write!(f, "TRUNCATECOLUMNS"),
9570            Zstd => write!(f, "ZSTD"),
9571            Credentials(s) => write!(f, "CREDENTIALS '{}'", value::escape_single_quote_string(s)),
9572        }
9573    }
9574}
9575
9576/// ```sql
9577/// SIZE \[ MB | GB \]
9578/// ```
9579#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9580#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9581#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9582pub struct FileSize {
9583    /// Numeric size value.
9584    pub size: ValueWithSpan,
9585    /// Optional unit for the size (MB or GB).
9586    pub unit: Option<FileSizeUnit>,
9587}
9588
9589impl fmt::Display for FileSize {
9590    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9591        write!(f, "{}", self.size)?;
9592        if let Some(unit) = &self.unit {
9593            write!(f, " {unit}")?;
9594        }
9595        Ok(())
9596    }
9597}
9598
9599/// Units for `FileSize` (MB or GB).
9600#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9601#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9602#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9603pub enum FileSizeUnit {
9604    /// Megabytes.
9605    MB,
9606    /// Gigabytes.
9607    GB,
9608}
9609
9610impl fmt::Display for FileSizeUnit {
9611    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9612        match self {
9613            FileSizeUnit::MB => write!(f, "MB"),
9614            FileSizeUnit::GB => write!(f, "GB"),
9615        }
9616    }
9617}
9618
9619/// Specifies the partition keys for the unload operation
9620///
9621/// ```sql
9622/// PARTITION BY ( column_name [, ... ] ) [ INCLUDE ]
9623/// ```
9624#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9625#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9626#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9627pub struct UnloadPartitionBy {
9628    /// Columns used to partition the unload output.
9629    pub columns: Vec<Ident>,
9630    /// Whether to include the partition in the output.
9631    pub include: bool,
9632}
9633
9634impl fmt::Display for UnloadPartitionBy {
9635    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9636        write!(
9637            f,
9638            "PARTITION BY ({}){}",
9639            display_comma_separated(&self.columns),
9640            if self.include { " INCLUDE" } else { "" }
9641        )
9642    }
9643}
9644
9645/// An `IAM_ROLE` option in the AWS ecosystem
9646///
9647/// [Redshift COPY](https://docs.aws.amazon.com/redshift/latest/dg/copy-parameters-authorization.html#copy-iam-role)
9648#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9649#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9650#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9651pub enum IamRoleKind {
9652    /// Default role
9653    Default,
9654    /// Specific role ARN, for example: `arn:aws:iam::123456789:role/role1`
9655    Arn(String),
9656}
9657
9658impl fmt::Display for IamRoleKind {
9659    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9660        match self {
9661            IamRoleKind::Default => write!(f, "DEFAULT"),
9662            IamRoleKind::Arn(arn) => write!(f, "'{arn}'"),
9663        }
9664    }
9665}
9666
9667/// A `CSV` option in `COPY` statement before PostgreSQL version 9.0.
9668///
9669/// <https://www.postgresql.org/docs/8.4/sql-copy.html>
9670#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9671#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9672#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9673pub enum CopyLegacyCsvOption {
9674    /// HEADER
9675    Header,
9676    /// QUOTE \[ AS \] 'quote_character'
9677    Quote(char),
9678    /// ESCAPE \[ AS \] 'escape_character'
9679    Escape(char),
9680    /// FORCE QUOTE { column_name [, ...] | * }
9681    ForceQuote(Vec<Ident>),
9682    /// FORCE NOT NULL column_name [, ...]
9683    ForceNotNull(Vec<Ident>),
9684}
9685
9686impl fmt::Display for CopyLegacyCsvOption {
9687    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9688        use CopyLegacyCsvOption::*;
9689        match self {
9690            Header => write!(f, "HEADER"),
9691            Quote(char) => write!(f, "QUOTE '{char}'"),
9692            Escape(char) => write!(f, "ESCAPE '{char}'"),
9693            ForceQuote(columns) => write!(f, "FORCE QUOTE {}", display_comma_separated(columns)),
9694            ForceNotNull(columns) => {
9695                write!(f, "FORCE NOT NULL {}", display_comma_separated(columns))
9696            }
9697        }
9698    }
9699}
9700
9701/// Objects that can be discarded with `DISCARD`.
9702#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9703#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9704#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9705pub enum DiscardObject {
9706    /// Discard all session state.
9707    ALL,
9708    /// Discard cached plans.
9709    PLANS,
9710    /// Discard sequence values.
9711    SEQUENCES,
9712    /// Discard temporary objects.
9713    TEMP,
9714}
9715
9716impl fmt::Display for DiscardObject {
9717    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9718        match self {
9719            DiscardObject::ALL => f.write_str("ALL"),
9720            DiscardObject::PLANS => f.write_str("PLANS"),
9721            DiscardObject::SEQUENCES => f.write_str("SEQUENCES"),
9722            DiscardObject::TEMP => f.write_str("TEMP"),
9723        }
9724    }
9725}
9726
9727/// Types of flush operations supported by `FLUSH`.
9728#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9729#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9730#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9731pub enum FlushType {
9732    /// Flush binary logs.
9733    BinaryLogs,
9734    /// Flush engine logs.
9735    EngineLogs,
9736    /// Flush error logs.
9737    ErrorLogs,
9738    /// Flush general logs.
9739    GeneralLogs,
9740    /// Flush hosts information.
9741    Hosts,
9742    /// Flush logs.
9743    Logs,
9744    /// Flush privileges.
9745    Privileges,
9746    /// Flush optimizer costs.
9747    OptimizerCosts,
9748    /// Flush relay logs.
9749    RelayLogs,
9750    /// Flush slow logs.
9751    SlowLogs,
9752    /// Flush status.
9753    Status,
9754    /// Flush user resources.
9755    UserResources,
9756    /// Flush table data.
9757    Tables,
9758}
9759
9760impl fmt::Display for FlushType {
9761    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9762        match self {
9763            FlushType::BinaryLogs => f.write_str("BINARY LOGS"),
9764            FlushType::EngineLogs => f.write_str("ENGINE LOGS"),
9765            FlushType::ErrorLogs => f.write_str("ERROR LOGS"),
9766            FlushType::GeneralLogs => f.write_str("GENERAL LOGS"),
9767            FlushType::Hosts => f.write_str("HOSTS"),
9768            FlushType::Logs => f.write_str("LOGS"),
9769            FlushType::Privileges => f.write_str("PRIVILEGES"),
9770            FlushType::OptimizerCosts => f.write_str("OPTIMIZER_COSTS"),
9771            FlushType::RelayLogs => f.write_str("RELAY LOGS"),
9772            FlushType::SlowLogs => f.write_str("SLOW LOGS"),
9773            FlushType::Status => f.write_str("STATUS"),
9774            FlushType::UserResources => f.write_str("USER_RESOURCES"),
9775            FlushType::Tables => f.write_str("TABLES"),
9776        }
9777    }
9778}
9779
9780/// Location modifier for flush commands.
9781#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9782#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9783#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9784pub enum FlushLocation {
9785    /// Do not write changes to the binary log.
9786    NoWriteToBinlog,
9787    /// Apply flush locally.
9788    Local,
9789}
9790
9791impl fmt::Display for FlushLocation {
9792    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9793        match self {
9794            FlushLocation::NoWriteToBinlog => f.write_str("NO_WRITE_TO_BINLOG"),
9795            FlushLocation::Local => f.write_str("LOCAL"),
9796        }
9797    }
9798}
9799
9800/// Optional context modifier for statements that can be or `LOCAL`, `GLOBAL`, or `SESSION`.
9801#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9802#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9803#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9804pub enum ContextModifier {
9805    /// `LOCAL` identifier, usually related to transactional states.
9806    Local,
9807    /// `SESSION` identifier
9808    Session,
9809    /// `GLOBAL` identifier
9810    Global,
9811}
9812
9813impl fmt::Display for ContextModifier {
9814    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9815        match self {
9816            Self::Local => {
9817                write!(f, "LOCAL ")
9818            }
9819            Self::Session => {
9820                write!(f, "SESSION ")
9821            }
9822            Self::Global => {
9823                write!(f, "GLOBAL ")
9824            }
9825        }
9826    }
9827}
9828
9829/// Function describe in DROP FUNCTION.
9830#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9831#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9832pub enum DropFunctionOption {
9833    /// `RESTRICT` option for DROP FUNCTION.
9834    Restrict,
9835    /// `CASCADE` option for DROP FUNCTION.
9836    Cascade,
9837}
9838
9839impl fmt::Display for DropFunctionOption {
9840    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9841        match self {
9842            DropFunctionOption::Restrict => write!(f, "RESTRICT "),
9843            DropFunctionOption::Cascade => write!(f, "CASCADE  "),
9844        }
9845    }
9846}
9847
9848/// Generic function description for DROP FUNCTION and CREATE TRIGGER.
9849#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9850#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9851#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9852pub struct FunctionDesc {
9853    /// The function name.
9854    pub name: ObjectName,
9855    /// Optional list of function arguments.
9856    pub args: Option<Vec<OperateFunctionArg>>,
9857}
9858
9859impl fmt::Display for FunctionDesc {
9860    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9861        write!(f, "{}", self.name)?;
9862        if let Some(args) = &self.args {
9863            write!(f, "({})", display_comma_separated(args))?;
9864        }
9865        Ok(())
9866    }
9867}
9868
9869/// Function argument in CREATE OR DROP FUNCTION.
9870#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9871#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9872#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9873pub struct OperateFunctionArg {
9874    /// Optional argument mode (`IN`, `OUT`, `INOUT`).
9875    pub mode: Option<ArgMode>,
9876    /// Optional argument identifier/name.
9877    pub name: Option<Ident>,
9878    /// The data type of the argument.
9879    pub data_type: DataType,
9880    /// Optional default expression for the argument.
9881    pub default_expr: Option<Expr>,
9882}
9883
9884impl OperateFunctionArg {
9885    /// Returns an unnamed argument.
9886    pub fn unnamed(data_type: DataType) -> Self {
9887        Self {
9888            mode: None,
9889            name: None,
9890            data_type,
9891            default_expr: None,
9892        }
9893    }
9894
9895    /// Returns an argument with name.
9896    pub fn with_name(name: &str, data_type: DataType) -> Self {
9897        Self {
9898            mode: None,
9899            name: Some(name.into()),
9900            data_type,
9901            default_expr: None,
9902        }
9903    }
9904}
9905
9906impl fmt::Display for OperateFunctionArg {
9907    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9908        if let Some(mode) = &self.mode {
9909            write!(f, "{mode} ")?;
9910        }
9911        if let Some(name) = &self.name {
9912            write!(f, "{name} ")?;
9913        }
9914        write!(f, "{}", self.data_type)?;
9915        if let Some(default_expr) = &self.default_expr {
9916            write!(f, " = {default_expr}")?;
9917        }
9918        Ok(())
9919    }
9920}
9921
9922/// The mode of an argument in CREATE FUNCTION.
9923#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9924#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9925#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9926pub enum ArgMode {
9927    /// `IN` mode.
9928    In,
9929    /// `OUT` mode.
9930    Out,
9931    /// `INOUT` mode.
9932    InOut,
9933    /// `VARIADIC` mode.
9934    Variadic,
9935}
9936
9937impl fmt::Display for ArgMode {
9938    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9939        match self {
9940            ArgMode::In => write!(f, "IN"),
9941            ArgMode::Out => write!(f, "OUT"),
9942            ArgMode::InOut => write!(f, "INOUT"),
9943            ArgMode::Variadic => write!(f, "VARIADIC"),
9944        }
9945    }
9946}
9947
9948/// These attributes inform the query optimizer about the behavior of the function.
9949#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9950#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9951#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9952pub enum FunctionBehavior {
9953    /// Function is immutable.
9954    Immutable,
9955    /// Function is stable.
9956    Stable,
9957    /// Function is volatile.
9958    Volatile,
9959}
9960
9961impl fmt::Display for FunctionBehavior {
9962    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9963        match self {
9964            FunctionBehavior::Immutable => write!(f, "IMMUTABLE"),
9965            FunctionBehavior::Stable => write!(f, "STABLE"),
9966            FunctionBehavior::Volatile => write!(f, "VOLATILE"),
9967        }
9968    }
9969}
9970
9971/// Security attribute for functions: SECURITY DEFINER or SECURITY INVOKER.
9972///
9973/// [PostgreSQL](https://www.postgresql.org/docs/current/sql-createfunction.html)
9974#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9975#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9976#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9977pub enum FunctionSecurity {
9978    /// Execute the function with the privileges of the user who defined it.
9979    Definer,
9980    /// Execute the function with the privileges of the user who invokes it.
9981    Invoker,
9982}
9983
9984impl fmt::Display for FunctionSecurity {
9985    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9986        match self {
9987            FunctionSecurity::Definer => write!(f, "SECURITY DEFINER"),
9988            FunctionSecurity::Invoker => write!(f, "SECURITY INVOKER"),
9989        }
9990    }
9991}
9992
9993/// Value for a SET configuration parameter in a CREATE FUNCTION statement.
9994///
9995/// [PostgreSQL](https://www.postgresql.org/docs/current/sql-createfunction.html)
9996#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9997#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9998#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9999pub enum FunctionSetValue {
10000    /// SET param = DEFAULT / SET param TO DEFAULT
10001    Default,
10002    /// SET param = value1, value2, ...
10003    Values(Vec<Expr>),
10004    /// SET param FROM CURRENT
10005    FromCurrent,
10006}
10007
10008/// A SET configuration_parameter clause in a CREATE FUNCTION statement.
10009///
10010/// [PostgreSQL](https://www.postgresql.org/docs/current/sql-createfunction.html)
10011#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10012#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10013#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10014pub struct FunctionDefinitionSetParam {
10015    /// The name of the configuration parameter.
10016    pub name: ObjectName,
10017    /// The value to set for the parameter.
10018    pub value: FunctionSetValue,
10019}
10020
10021impl fmt::Display for FunctionDefinitionSetParam {
10022    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10023        write!(f, "SET {} ", self.name)?;
10024        match &self.value {
10025            FunctionSetValue::Default => write!(f, "= DEFAULT"),
10026            FunctionSetValue::Values(values) => {
10027                write!(f, "= {}", display_comma_separated(values))
10028            }
10029            FunctionSetValue::FromCurrent => write!(f, "FROM CURRENT"),
10030        }
10031    }
10032}
10033
10034/// These attributes describe the behavior of the function when called with a null argument.
10035#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10036#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10037#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10038pub enum FunctionCalledOnNull {
10039    /// Function is called even when inputs are null.
10040    CalledOnNullInput,
10041    /// Function returns null when any input is null.
10042    ReturnsNullOnNullInput,
10043    /// Function is strict about null inputs.
10044    Strict,
10045}
10046
10047impl fmt::Display for FunctionCalledOnNull {
10048    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10049        match self {
10050            FunctionCalledOnNull::CalledOnNullInput => write!(f, "CALLED ON NULL INPUT"),
10051            FunctionCalledOnNull::ReturnsNullOnNullInput => write!(f, "RETURNS NULL ON NULL INPUT"),
10052            FunctionCalledOnNull::Strict => write!(f, "STRICT"),
10053        }
10054    }
10055}
10056
10057/// If it is safe for PostgreSQL to call the function from multiple threads at once
10058#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10059#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10060#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10061pub enum FunctionParallel {
10062    /// The function is not safe to run in parallel.
10063    Unsafe,
10064    /// The function is restricted for parallel execution.
10065    Restricted,
10066    /// The function is safe to run in parallel.
10067    Safe,
10068}
10069
10070impl fmt::Display for FunctionParallel {
10071    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10072        match self {
10073            FunctionParallel::Unsafe => write!(f, "PARALLEL UNSAFE"),
10074            FunctionParallel::Restricted => write!(f, "PARALLEL RESTRICTED"),
10075            FunctionParallel::Safe => write!(f, "PARALLEL SAFE"),
10076        }
10077    }
10078}
10079
10080/// [BigQuery] Determinism specifier used in a UDF definition.
10081///
10082/// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#syntax_11
10083#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10084#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10085#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10086pub enum FunctionDeterminismSpecifier {
10087    /// Function is deterministic.
10088    Deterministic,
10089    /// Function is not deterministic.
10090    NotDeterministic,
10091}
10092
10093impl fmt::Display for FunctionDeterminismSpecifier {
10094    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10095        match self {
10096            FunctionDeterminismSpecifier::Deterministic => {
10097                write!(f, "DETERMINISTIC")
10098            }
10099            FunctionDeterminismSpecifier::NotDeterministic => {
10100                write!(f, "NOT DETERMINISTIC")
10101            }
10102        }
10103    }
10104}
10105
10106/// Represent the expression body of a `CREATE FUNCTION` statement as well as
10107/// where within the statement, the body shows up.
10108///
10109/// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#syntax_11
10110/// [PostgreSQL]: https://www.postgresql.org/docs/15/sql-createfunction.html
10111/// [MsSql]: https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql
10112#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10113#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10114#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10115pub enum CreateFunctionBody {
10116    /// A function body expression using the 'AS' keyword and shows up
10117    /// before any `OPTIONS` clause.
10118    ///
10119    /// Example:
10120    /// ```sql
10121    /// CREATE FUNCTION myfunc(x FLOAT64, y FLOAT64) RETURNS FLOAT64
10122    /// AS (x * y)
10123    /// OPTIONS(description="desc");
10124    /// ```
10125    ///
10126    /// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#syntax_11
10127    /// [PostgreSQL]: https://www.postgresql.org/docs/current/sql-createfunction.html
10128    AsBeforeOptions {
10129        /// The primary expression.
10130        body: Expr,
10131        /// Link symbol if the primary expression contains the name of shared library file.
10132        ///
10133        /// Example:
10134        /// ```sql
10135        /// CREATE FUNCTION cas_in(input cstring) RETURNS cas
10136        /// AS 'MODULE_PATHNAME', 'cas_in_wrapper'
10137        /// ```
10138        /// [PostgreSQL]: https://www.postgresql.org/docs/current/sql-createfunction.html
10139        link_symbol: Option<Expr>,
10140    },
10141    /// A function body expression using the 'AS' keyword and shows up
10142    /// after any `OPTIONS` clause.
10143    ///
10144    /// Example:
10145    /// ```sql
10146    /// CREATE FUNCTION myfunc(x FLOAT64, y FLOAT64) RETURNS FLOAT64
10147    /// OPTIONS(description="desc")
10148    /// AS (x * y);
10149    /// ```
10150    ///
10151    /// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#syntax_11
10152    AsAfterOptions(Expr),
10153    /// Function body with statements before the `RETURN` keyword.
10154    ///
10155    /// Example:
10156    /// ```sql
10157    /// CREATE FUNCTION my_scalar_udf(a INT, b INT)
10158    /// RETURNS INT
10159    /// AS
10160    /// BEGIN
10161    ///     DECLARE c INT;
10162    ///     SET c = a + b;
10163    ///     RETURN c;
10164    /// END
10165    /// ```
10166    ///
10167    /// [MsSql]: https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql
10168    AsBeginEnd(BeginEndStatements),
10169    /// Function body expression using the 'RETURN' keyword.
10170    ///
10171    /// Example:
10172    /// ```sql
10173    /// CREATE FUNCTION myfunc(a INTEGER, IN b INTEGER = 1) RETURNS INTEGER
10174    /// LANGUAGE SQL
10175    /// RETURN a + b;
10176    /// ```
10177    ///
10178    /// [PostgreSQL]: https://www.postgresql.org/docs/current/sql-createfunction.html
10179    Return(Expr),
10180
10181    /// Function body expression using the 'AS RETURN' keywords
10182    ///
10183    /// Example:
10184    /// ```sql
10185    /// CREATE FUNCTION myfunc(a INT, b INT)
10186    /// RETURNS TABLE
10187    /// AS RETURN (SELECT a + b AS sum);
10188    /// ```
10189    ///
10190    /// [MsSql]: https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql
10191    AsReturnExpr(Expr),
10192
10193    /// Function body expression using the 'AS RETURN' keywords, with an un-parenthesized SELECT query
10194    ///
10195    /// Example:
10196    /// ```sql
10197    /// CREATE FUNCTION myfunc(a INT, b INT)
10198    /// RETURNS TABLE
10199    /// AS RETURN SELECT a + b AS sum;
10200    /// ```
10201    ///
10202    /// [MsSql]: https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql?view=sql-server-ver16#select_stmt
10203    AsReturnSelect(Select),
10204}
10205
10206#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10207#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10208#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10209/// `USING` clause options for `CREATE FUNCTION` (e.g., JAR, FILE, ARCHIVE).
10210pub enum CreateFunctionUsing {
10211    /// Use a JAR file located at the given URI.
10212    Jar(String),
10213    /// Use a file located at the given URI.
10214    File(String),
10215    /// Use an archive located at the given URI.
10216    Archive(String),
10217}
10218
10219impl fmt::Display for CreateFunctionUsing {
10220    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10221        write!(f, "USING ")?;
10222        match self {
10223            CreateFunctionUsing::Jar(uri) => write!(f, "JAR '{uri}'"),
10224            CreateFunctionUsing::File(uri) => write!(f, "FILE '{uri}'"),
10225            CreateFunctionUsing::Archive(uri) => write!(f, "ARCHIVE '{uri}'"),
10226        }
10227    }
10228}
10229
10230/// `NAME = <EXPR>` arguments for DuckDB macros
10231///
10232/// See [Create Macro - DuckDB](https://duckdb.org/docs/sql/statements/create_macro)
10233/// for more details
10234#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10235#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10236#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10237pub struct MacroArg {
10238    /// The argument name.
10239    pub name: Ident,
10240    /// Optional default expression for the argument.
10241    pub default_expr: Option<Expr>,
10242}
10243
10244impl MacroArg {
10245    /// Returns an argument with name.
10246    pub fn new(name: &str) -> Self {
10247        Self {
10248            name: name.into(),
10249            default_expr: None,
10250        }
10251    }
10252}
10253
10254impl fmt::Display for MacroArg {
10255    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10256        write!(f, "{}", self.name)?;
10257        if let Some(default_expr) = &self.default_expr {
10258            write!(f, " := {default_expr}")?;
10259        }
10260        Ok(())
10261    }
10262}
10263
10264#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10265#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10266#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10267/// Definition for a DuckDB macro: either an expression or a table-producing query.
10268pub enum MacroDefinition {
10269    /// The macro is defined as an expression.
10270    Expr(Expr),
10271    /// The macro is defined as a table (query).
10272    Table(Box<Query>),
10273}
10274
10275impl fmt::Display for MacroDefinition {
10276    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10277        match self {
10278            MacroDefinition::Expr(expr) => write!(f, "{expr}")?,
10279            MacroDefinition::Table(query) => write!(f, "{query}")?,
10280        }
10281        Ok(())
10282    }
10283}
10284
10285/// Schema possible naming variants ([1]).
10286///
10287/// [1]: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#schema-definition
10288#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10289#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10290#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10291pub enum SchemaName {
10292    /// Only schema name specified: `<schema name>`.
10293    Simple(ObjectName),
10294    /// Only authorization identifier specified: `AUTHORIZATION <schema authorization identifier>`.
10295    UnnamedAuthorization(Ident),
10296    /// Both schema name and authorization identifier specified: `<schema name>  AUTHORIZATION <schema authorization identifier>`.
10297    NamedAuthorization(ObjectName, Ident),
10298}
10299
10300impl fmt::Display for SchemaName {
10301    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10302        match self {
10303            SchemaName::Simple(name) => {
10304                write!(f, "{name}")
10305            }
10306            SchemaName::UnnamedAuthorization(authorization) => {
10307                write!(f, "AUTHORIZATION {authorization}")
10308            }
10309            SchemaName::NamedAuthorization(name, authorization) => {
10310                write!(f, "{name} AUTHORIZATION {authorization}")
10311            }
10312        }
10313    }
10314}
10315
10316/// Fulltext search modifiers ([1]).
10317///
10318/// [1]: https://dev.mysql.com/doc/refman/8.0/en/fulltext-search.html#function_match
10319#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10320#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10321#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10322pub enum SearchModifier {
10323    /// `IN NATURAL LANGUAGE MODE`.
10324    InNaturalLanguageMode,
10325    /// `IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION`.
10326    InNaturalLanguageModeWithQueryExpansion,
10327    ///`IN BOOLEAN MODE`.
10328    InBooleanMode,
10329    ///`WITH QUERY EXPANSION`.
10330    WithQueryExpansion,
10331}
10332
10333impl fmt::Display for SearchModifier {
10334    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10335        match self {
10336            Self::InNaturalLanguageMode => {
10337                write!(f, "IN NATURAL LANGUAGE MODE")?;
10338            }
10339            Self::InNaturalLanguageModeWithQueryExpansion => {
10340                write!(f, "IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION")?;
10341            }
10342            Self::InBooleanMode => {
10343                write!(f, "IN BOOLEAN MODE")?;
10344            }
10345            Self::WithQueryExpansion => {
10346                write!(f, "WITH QUERY EXPANSION")?;
10347            }
10348        }
10349
10350        Ok(())
10351    }
10352}
10353
10354/// Represents a `LOCK TABLE` clause with optional alias and lock type.
10355#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10356#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10357#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10358pub struct LockTable {
10359    /// The table identifier to lock.
10360    pub table: Ident,
10361    /// Optional alias for the table.
10362    pub alias: Option<Ident>,
10363    /// The type of lock to apply to the table.
10364    pub lock_type: LockTableType,
10365}
10366
10367impl fmt::Display for LockTable {
10368    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10369        let Self {
10370            table: tbl_name,
10371            alias,
10372            lock_type,
10373        } = self;
10374
10375        write!(f, "{tbl_name} ")?;
10376        if let Some(alias) = alias {
10377            write!(f, "AS {alias} ")?;
10378        }
10379        write!(f, "{lock_type}")?;
10380        Ok(())
10381    }
10382}
10383
10384#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10385#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10386#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10387/// The type of lock used in `LOCK TABLE` statements.
10388pub enum LockTableType {
10389    /// Shared/read lock. If `local` is true, it's a local read lock.
10390    Read {
10391        /// Whether the read lock is local.
10392        local: bool,
10393    },
10394    /// Exclusive/write lock. If `low_priority` is true, the write is low priority.
10395    Write {
10396        /// Whether the write lock is low priority.
10397        low_priority: bool,
10398    },
10399}
10400
10401impl fmt::Display for LockTableType {
10402    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10403        match self {
10404            Self::Read { local } => {
10405                write!(f, "READ")?;
10406                if *local {
10407                    write!(f, " LOCAL")?;
10408                }
10409            }
10410            Self::Write { low_priority } => {
10411                if *low_priority {
10412                    write!(f, "LOW_PRIORITY ")?;
10413                }
10414                write!(f, "WRITE")?;
10415            }
10416        }
10417
10418        Ok(())
10419    }
10420}
10421
10422#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10423#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10424#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10425/// Hive-specific `SET LOCATION` helper used in some `LOAD DATA` statements.
10426pub struct HiveSetLocation {
10427    /// Whether the `SET` keyword was present.
10428    pub has_set: bool,
10429    /// The location identifier.
10430    pub location: Ident,
10431}
10432
10433impl fmt::Display for HiveSetLocation {
10434    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10435        if self.has_set {
10436            write!(f, "SET ")?;
10437        }
10438        write!(f, "LOCATION {}", self.location)
10439    }
10440}
10441
10442/// MySQL `ALTER TABLE` only  [FIRST | AFTER column_name]
10443#[allow(clippy::large_enum_variant)]
10444#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10445#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10446#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10447/// MySQL `ALTER TABLE` column position specifier: `FIRST` or `AFTER <column>`.
10448pub enum MySQLColumnPosition {
10449    /// Place the column first in the table.
10450    First,
10451    /// Place the column after the specified identifier.
10452    After(Ident),
10453}
10454
10455impl Display for MySQLColumnPosition {
10456    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10457        match self {
10458            MySQLColumnPosition::First => write!(f, "FIRST"),
10459            MySQLColumnPosition::After(ident) => {
10460                let column_name = &ident.value;
10461                write!(f, "AFTER {column_name}")
10462            }
10463        }
10464    }
10465}
10466
10467/// MySQL `CREATE VIEW` algorithm parameter: [ALGORITHM = {UNDEFINED | MERGE | TEMPTABLE}]
10468#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10469#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10470#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10471/// MySQL `CREATE VIEW` algorithm options.
10472pub enum CreateViewAlgorithm {
10473    /// `UNDEFINED` algorithm.
10474    Undefined,
10475    /// `MERGE` algorithm.
10476    Merge,
10477    /// `TEMPTABLE` algorithm.
10478    TempTable,
10479}
10480
10481impl Display for CreateViewAlgorithm {
10482    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10483        match self {
10484            CreateViewAlgorithm::Undefined => write!(f, "UNDEFINED"),
10485            CreateViewAlgorithm::Merge => write!(f, "MERGE"),
10486            CreateViewAlgorithm::TempTable => write!(f, "TEMPTABLE"),
10487        }
10488    }
10489}
10490/// MySQL `CREATE VIEW` security parameter: [SQL SECURITY { DEFINER | INVOKER }]
10491#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10492#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10493#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10494/// MySQL `CREATE VIEW` SQL SECURITY options.
10495pub enum CreateViewSecurity {
10496    /// The view runs with the privileges of the definer.
10497    Definer,
10498    /// The view runs with the privileges of the invoker.
10499    Invoker,
10500}
10501
10502impl Display for CreateViewSecurity {
10503    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10504        match self {
10505            CreateViewSecurity::Definer => write!(f, "DEFINER"),
10506            CreateViewSecurity::Invoker => write!(f, "INVOKER"),
10507        }
10508    }
10509}
10510
10511/// [MySQL] `CREATE VIEW` additional parameters
10512///
10513/// [MySQL]: https://dev.mysql.com/doc/refman/9.1/en/create-view.html
10514#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10515#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10516#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10517pub struct CreateViewParams {
10518    /// Optional view algorithm (e.g., MERGE, TEMPTABLE).
10519    pub algorithm: Option<CreateViewAlgorithm>,
10520    /// Optional definer (the security principal that will own the view).
10521    pub definer: Option<GranteeName>,
10522    /// Optional SQL SECURITY setting for the view.
10523    pub security: Option<CreateViewSecurity>,
10524}
10525
10526impl Display for CreateViewParams {
10527    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10528        let CreateViewParams {
10529            algorithm,
10530            definer,
10531            security,
10532        } = self;
10533        if let Some(algorithm) = algorithm {
10534            write!(f, "ALGORITHM = {algorithm} ")?;
10535        }
10536        if let Some(definers) = definer {
10537            write!(f, "DEFINER = {definers} ")?;
10538        }
10539        if let Some(security) = security {
10540            write!(f, "SQL SECURITY {security} ")?;
10541        }
10542        Ok(())
10543    }
10544}
10545
10546#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10547#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10548#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10549/// Key/Value, where the value is a (optionally named) list of identifiers
10550///
10551/// ```sql
10552/// UNION = (tbl_name[,tbl_name]...)
10553/// ENGINE = ReplicatedMergeTree('/table_name','{replica}', ver)
10554/// ENGINE = SummingMergeTree([columns])
10555/// ```
10556pub struct NamedParenthesizedList {
10557    /// The option key (identifier) for this named list.
10558    pub key: Ident,
10559    /// Optional secondary name associated with the key.
10560    pub name: Option<Ident>,
10561    /// The list of identifier values for the key.
10562    pub values: Vec<Ident>,
10563}
10564
10565/// Snowflake `WITH ROW ACCESS POLICY policy_name ON (identifier, ...)`
10566///
10567/// <https://docs.snowflake.com/en/sql-reference/sql/create-table>
10568/// <https://docs.snowflake.com/en/user-guide/security-row-intro>
10569#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10570#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10571#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10572pub struct RowAccessPolicy {
10573    /// The fully-qualified policy object name.
10574    pub policy: ObjectName,
10575    /// Identifiers for the columns or objects the policy applies to.
10576    pub on: Vec<Ident>,
10577}
10578
10579impl RowAccessPolicy {
10580    /// Create a new `RowAccessPolicy` for the given `policy` and `on` identifiers.
10581    pub fn new(policy: ObjectName, on: Vec<Ident>) -> Self {
10582        Self { policy, on }
10583    }
10584}
10585
10586impl Display for RowAccessPolicy {
10587    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10588        write!(
10589            f,
10590            "WITH ROW ACCESS POLICY {} ON ({})",
10591            self.policy,
10592            display_comma_separated(self.on.as_slice())
10593        )
10594    }
10595}
10596
10597/// Snowflake `[ WITH ] STORAGE LIFECYCLE POLICY <policy_name> ON ( <col_name> [ , ... ] )`
10598///
10599/// <https://docs.snowflake.com/en/sql-reference/sql/create-table>
10600#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10601#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10602#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10603pub struct StorageLifecyclePolicy {
10604    /// The fully-qualified policy object name.
10605    pub policy: ObjectName,
10606    /// Column names the policy applies to.
10607    pub on: Vec<Ident>,
10608}
10609
10610impl Display for StorageLifecyclePolicy {
10611    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10612        write!(
10613            f,
10614            "WITH STORAGE LIFECYCLE POLICY {} ON ({})",
10615            self.policy,
10616            display_comma_separated(self.on.as_slice())
10617        )
10618    }
10619}
10620
10621/// Snowflake `WITH TAG ( tag_name = '<tag_value>', ...)`
10622///
10623/// <https://docs.snowflake.com/en/sql-reference/sql/create-table>
10624#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10625#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10626#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10627pub struct Tag {
10628    /// The tag key (can be qualified).
10629    pub key: ObjectName,
10630    /// The tag value as a string.
10631    pub value: String,
10632}
10633
10634impl Tag {
10635    /// Create a new `Tag` with the given key and value.
10636    pub fn new(key: ObjectName, value: String) -> Self {
10637        Self { key, value }
10638    }
10639}
10640
10641impl Display for Tag {
10642    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10643        write!(f, "{}='{}'", self.key, self.value)
10644    }
10645}
10646
10647/// Snowflake `WITH CONTACT ( purpose = contact [ , purpose = contact ...] )`
10648///
10649/// <https://docs.snowflake.com/en/sql-reference/sql/create-database>
10650#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10651#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10652#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10653pub struct ContactEntry {
10654    /// The purpose label for the contact entry.
10655    pub purpose: String,
10656    /// The contact information associated with the purpose.
10657    pub contact: String,
10658}
10659
10660impl Display for ContactEntry {
10661    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10662        write!(f, "{} = {}", self.purpose, self.contact)
10663    }
10664}
10665
10666/// Helper to indicate if a comment includes the `=` in the display form
10667#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10668#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10669#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10670pub enum CommentDef {
10671    /// Includes `=` when printing the comment, as `COMMENT = 'comment'`
10672    /// Does not include `=` when printing the comment, as `COMMENT 'comment'`
10673    WithEq(String),
10674    /// Comment variant that omits the `=` when displayed.
10675    WithoutEq(String),
10676}
10677
10678impl Display for CommentDef {
10679    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10680        match self {
10681            CommentDef::WithEq(comment) | CommentDef::WithoutEq(comment) => write!(f, "{comment}"),
10682        }
10683    }
10684}
10685
10686/// Helper to indicate if a collection should be wrapped by a symbol in the display form
10687///
10688/// [`Display`] is implemented for every [`Vec<T>`] where `T: Display`.
10689/// The string output is a comma separated list for the vec items
10690///
10691/// # Examples
10692/// ```
10693/// # use sqlparser::ast::WrappedCollection;
10694/// let items = WrappedCollection::Parentheses(vec!["one", "two", "three"]);
10695/// assert_eq!("(one, two, three)", items.to_string());
10696///
10697/// let items = WrappedCollection::NoWrapping(vec!["one", "two", "three"]);
10698/// assert_eq!("one, two, three", items.to_string());
10699/// ```
10700#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10701#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10702#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10703pub enum WrappedCollection<T> {
10704    /// Print the collection without wrapping symbols, as `item, item, item`
10705    NoWrapping(T),
10706    /// Wraps the collection in Parentheses, as `(item, item, item)`
10707    Parentheses(T),
10708}
10709
10710impl<T> Display for WrappedCollection<Vec<T>>
10711where
10712    T: Display,
10713{
10714    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10715        match self {
10716            WrappedCollection::NoWrapping(inner) => {
10717                write!(f, "{}", display_comma_separated(inner.as_slice()))
10718            }
10719            WrappedCollection::Parentheses(inner) => {
10720                write!(f, "({})", display_comma_separated(inner.as_slice()))
10721            }
10722        }
10723    }
10724}
10725
10726/// Represents a single PostgreSQL utility option.
10727///
10728/// A utility option is a key-value pair where the key is an identifier (IDENT) and the value
10729/// can be one of the following:
10730/// - A number with an optional sign (`+` or `-`). Example: `+10`, `-10.2`, `3`
10731/// - A non-keyword string. Example: `option1`, `'option2'`, `"option3"`
10732/// - keyword: `TRUE`, `FALSE`, `ON` (`off` is also accept).
10733/// - Empty. Example: `ANALYZE` (identifier only)
10734///
10735/// Utility options are used in various PostgreSQL DDL statements, including statements such as
10736/// `CLUSTER`, `EXPLAIN`, `VACUUM`, and `REINDEX`. These statements format options as `( option [, ...] )`.
10737///
10738/// [CLUSTER](https://www.postgresql.org/docs/current/sql-cluster.html)
10739/// [EXPLAIN](https://www.postgresql.org/docs/current/sql-explain.html)
10740/// [VACUUM](https://www.postgresql.org/docs/current/sql-vacuum.html)
10741/// [REINDEX](https://www.postgresql.org/docs/current/sql-reindex.html)
10742///
10743/// For example, the `EXPLAIN` AND `VACUUM` statements with options might look like this:
10744/// ```sql
10745/// EXPLAIN (ANALYZE, VERBOSE TRUE, FORMAT TEXT) SELECT * FROM my_table;
10746///
10747/// VACUUM (VERBOSE, ANALYZE ON, PARALLEL 10) my_table;
10748/// ```
10749#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10750#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10751#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10752pub struct UtilityOption {
10753    /// The option name (identifier).
10754    pub name: Ident,
10755    /// Optional argument for the option (number, string, keyword, etc.).
10756    pub arg: Option<Expr>,
10757}
10758
10759impl Display for UtilityOption {
10760    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10761        if let Some(ref arg) = self.arg {
10762            write!(f, "{} {}", self.name, arg)
10763        } else {
10764            write!(f, "{}", self.name)
10765        }
10766    }
10767}
10768
10769/// Represents the different options available for `SHOW`
10770/// statements to filter the results. Example from Snowflake:
10771/// <https://docs.snowflake.com/en/sql-reference/sql/show-tables>
10772#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10773#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10774#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10775pub struct ShowStatementOptions {
10776    /// Optional scope to show in (for example: TABLE, SCHEMA).
10777    pub show_in: Option<ShowStatementIn>,
10778    /// Optional `STARTS WITH` filter value.
10779    pub starts_with: Option<ValueWithSpan>,
10780    /// Optional `LIMIT` expression.
10781    pub limit: Option<Expr>,
10782    /// Optional `FROM` value used with `LIMIT`.
10783    pub limit_from: Option<ValueWithSpan>,
10784    /// Optional filter position (infix or suffix) for `LIKE`/`FILTER`.
10785    pub filter_position: Option<ShowStatementFilterPosition>,
10786}
10787
10788impl Display for ShowStatementOptions {
10789    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10790        let (like_in_infix, like_in_suffix) = match &self.filter_position {
10791            Some(ShowStatementFilterPosition::Infix(filter)) => {
10792                (format!(" {filter}"), "".to_string())
10793            }
10794            Some(ShowStatementFilterPosition::Suffix(filter)) => {
10795                ("".to_string(), format!(" {filter}"))
10796            }
10797            None => ("".to_string(), "".to_string()),
10798        };
10799        write!(
10800            f,
10801            "{like_in_infix}{show_in}{starts_with}{limit}{from}{like_in_suffix}",
10802            show_in = match &self.show_in {
10803                Some(i) => format!(" {i}"),
10804                None => String::new(),
10805            },
10806            starts_with = match &self.starts_with {
10807                Some(s) => format!(" STARTS WITH {s}"),
10808                None => String::new(),
10809            },
10810            limit = match &self.limit {
10811                Some(l) => format!(" LIMIT {l}"),
10812                None => String::new(),
10813            },
10814            from = match &self.limit_from {
10815                Some(f) => format!(" FROM {f}"),
10816                None => String::new(),
10817            }
10818        )?;
10819        Ok(())
10820    }
10821}
10822
10823#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10824#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10825#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10826/// Where a `SHOW` filter appears relative to the main clause.
10827pub enum ShowStatementFilterPosition {
10828    /// Put the filter in an infix position (e.g. `SHOW COLUMNS LIKE '%name%' IN TABLE tbl`).
10829    Infix(ShowStatementFilter), // For example: SHOW COLUMNS LIKE '%name%' IN TABLE tbl
10830    /// Put the filter in a suffix position (e.g. `SHOW COLUMNS IN tbl LIKE '%name%'`).
10831    Suffix(ShowStatementFilter), // For example: SHOW COLUMNS IN tbl LIKE '%name%'
10832}
10833
10834#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10835#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10836#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10837/// Parent object types usable with `SHOW ... IN <parent>` clauses.
10838pub enum ShowStatementInParentType {
10839    /// ACCOUNT parent type for SHOW statements.
10840    Account,
10841    /// DATABASE parent type for SHOW statements.
10842    Database,
10843    /// SCHEMA parent type for SHOW statements.
10844    Schema,
10845    /// TABLE parent type for SHOW statements.
10846    Table,
10847    /// VIEW parent type for SHOW statements.
10848    View,
10849}
10850
10851impl fmt::Display for ShowStatementInParentType {
10852    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10853        match self {
10854            ShowStatementInParentType::Account => write!(f, "ACCOUNT"),
10855            ShowStatementInParentType::Database => write!(f, "DATABASE"),
10856            ShowStatementInParentType::Schema => write!(f, "SCHEMA"),
10857            ShowStatementInParentType::Table => write!(f, "TABLE"),
10858            ShowStatementInParentType::View => write!(f, "VIEW"),
10859        }
10860    }
10861}
10862
10863#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10864#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10865#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10866/// Represents a `SHOW ... IN` clause with optional parent qualifier and name.
10867pub struct ShowStatementIn {
10868    /// The clause that specifies what to show (e.g. COLUMNS, TABLES).
10869    pub clause: ShowStatementInClause,
10870    /// Optional parent type qualifier (ACCOUNT/DATABASE/...).
10871    pub parent_type: Option<ShowStatementInParentType>,
10872    /// Optional parent object name for the SHOW clause.
10873    #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
10874    pub parent_name: Option<ObjectName>,
10875}
10876
10877impl fmt::Display for ShowStatementIn {
10878    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10879        write!(f, "{}", self.clause)?;
10880        if let Some(parent_type) = &self.parent_type {
10881            write!(f, " {parent_type}")?;
10882        }
10883        if let Some(parent_name) = &self.parent_name {
10884            write!(f, " {parent_name}")?;
10885        }
10886        Ok(())
10887    }
10888}
10889
10890/// A Show Charset statement
10891#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10892#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10893#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10894pub struct ShowCharset {
10895    /// The statement can be written as `SHOW CHARSET` or `SHOW CHARACTER SET`
10896    /// true means CHARSET was used and false means CHARACTER SET was used
10897    pub is_shorthand: bool,
10898    /// Optional `LIKE`/`WHERE`-style filter for the statement.
10899    pub filter: Option<ShowStatementFilter>,
10900}
10901
10902impl fmt::Display for ShowCharset {
10903    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10904        write!(f, "SHOW")?;
10905        if self.is_shorthand {
10906            write!(f, " CHARSET")?;
10907        } else {
10908            write!(f, " CHARACTER SET")?;
10909        }
10910        if let Some(filter) = &self.filter {
10911            write!(f, " {filter}")?;
10912        }
10913        Ok(())
10914    }
10915}
10916
10917#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10918#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10919#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10920/// Options for a `SHOW OBJECTS` statement.
10921pub struct ShowObjects {
10922    /// Whether to show terse output.
10923    pub terse: bool,
10924    /// Additional options controlling the SHOW output.
10925    pub show_options: ShowStatementOptions,
10926}
10927
10928/// MSSQL's json null clause
10929///
10930/// ```plaintext
10931/// <json_null_clause> ::=
10932///       NULL ON NULL
10933///     | ABSENT ON NULL
10934/// ```
10935///
10936/// <https://learn.microsoft.com/en-us/sql/t-sql/functions/json-object-transact-sql?view=sql-server-ver16#json_null_clause>
10937#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10938#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10939#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10940pub enum JsonNullClause {
10941    /// `NULL ON NULL` behavior for JSON functions.
10942    NullOnNull,
10943    /// `ABSENT ON NULL` behavior for JSON functions.
10944    AbsentOnNull,
10945}
10946
10947impl Display for JsonNullClause {
10948    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10949        match self {
10950            JsonNullClause::NullOnNull => write!(f, "NULL ON NULL"),
10951            JsonNullClause::AbsentOnNull => write!(f, "ABSENT ON NULL"),
10952        }
10953    }
10954}
10955
10956/// PostgreSQL JSON function RETURNING clause
10957///
10958/// Example:
10959/// ```sql
10960/// JSON_OBJECT('a': 1 RETURNING jsonb)
10961/// ```
10962#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10963#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10964#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10965pub struct JsonReturningClause {
10966    /// The data type to return from the JSON function (e.g. JSON/JSONB).
10967    pub data_type: DataType,
10968}
10969
10970impl Display for JsonReturningClause {
10971    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10972        write!(f, "RETURNING {}", self.data_type)
10973    }
10974}
10975
10976/// rename object definition
10977#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10978#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10979#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10980pub struct RenameTable {
10981    /// The current name of the object to rename.
10982    pub old_name: ObjectName,
10983    /// The new name for the object.
10984    pub new_name: ObjectName,
10985}
10986
10987impl fmt::Display for RenameTable {
10988    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10989        write!(f, "{} TO {}", self.old_name, self.new_name)?;
10990        Ok(())
10991    }
10992}
10993
10994/// Represents the referenced table in an `INSERT INTO` statement
10995#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10996#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10997#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10998pub enum TableObject {
10999    /// Table specified by name.
11000    /// Example:
11001    /// ```sql
11002    /// INSERT INTO my_table
11003    /// ```
11004    TableName(#[cfg_attr(feature = "visitor", visit(with = "visit_relation"))] ObjectName),
11005
11006    /// Table specified as a function.
11007    /// Example:
11008    /// ```sql
11009    /// INSERT INTO TABLE FUNCTION remote('localhost', default.simple_table)
11010    /// ```
11011    /// [Clickhouse](https://clickhouse.com/docs/en/sql-reference/table-functions)
11012    TableFunction(Function),
11013
11014    /// Table specified through a sub-query
11015    /// Example:
11016    /// ```sql
11017    /// INSERT INTO
11018    /// (SELECT employee_id, last_name, email, hire_date, job_id,  salary, commission_pct FROM employees)
11019    /// VALUES (207, 'Gregory', 'pgregory@example.com', sysdate, 'PU_CLERK', 1.2E3, NULL);
11020    /// ```
11021    /// [Oracle](https://docs.oracle.com/en/database/oracle/oracle-database/21/sqlrf/INSERT.html#GUID-903F8043-0254-4EE9-ACC1-CB8AC0AF3423__I2126242)
11022    TableQuery(Box<Query>),
11023}
11024
11025impl fmt::Display for TableObject {
11026    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11027        match self {
11028            Self::TableName(table_name) => write!(f, "{table_name}"),
11029            Self::TableFunction(func) => write!(f, "FUNCTION {func}"),
11030            Self::TableQuery(table_query) => write!(f, "({table_query})"),
11031        }
11032    }
11033}
11034
11035/// Represents a SET SESSION AUTHORIZATION 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 struct SetSessionAuthorizationParam {
11040    /// The scope for the `SET SESSION AUTHORIZATION` (e.g., GLOBAL/SESSION).
11041    pub scope: ContextModifier,
11042    /// The specific authorization parameter kind.
11043    pub kind: SetSessionAuthorizationParamKind,
11044}
11045
11046impl fmt::Display for SetSessionAuthorizationParam {
11047    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11048        write!(f, "{}", self.kind)
11049    }
11050}
11051
11052/// Represents the parameter kind for SET SESSION AUTHORIZATION
11053#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11054#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11055#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11056pub enum SetSessionAuthorizationParamKind {
11057    /// Default authorization
11058    Default,
11059
11060    /// User name
11061    User(Ident),
11062}
11063
11064impl fmt::Display for SetSessionAuthorizationParamKind {
11065    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11066        match self {
11067            SetSessionAuthorizationParamKind::Default => write!(f, "DEFAULT"),
11068            SetSessionAuthorizationParamKind::User(name) => write!(f, "{}", name),
11069        }
11070    }
11071}
11072
11073#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11074#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11075#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11076/// Kind of session parameter being set by `SET SESSION`.
11077pub enum SetSessionParamKind {
11078    /// Generic session parameter (name/value pair).
11079    Generic(SetSessionParamGeneric),
11080    /// Identity insert related parameter.
11081    IdentityInsert(SetSessionParamIdentityInsert),
11082    /// Offsets-related parameter.
11083    Offsets(SetSessionParamOffsets),
11084    /// Statistics-related parameter.
11085    Statistics(SetSessionParamStatistics),
11086}
11087
11088impl fmt::Display for SetSessionParamKind {
11089    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11090        match self {
11091            SetSessionParamKind::Generic(x) => write!(f, "{x}"),
11092            SetSessionParamKind::IdentityInsert(x) => write!(f, "{x}"),
11093            SetSessionParamKind::Offsets(x) => write!(f, "{x}"),
11094            SetSessionParamKind::Statistics(x) => write!(f, "{x}"),
11095        }
11096    }
11097}
11098
11099#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11100#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11101#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11102/// Generic `SET SESSION` parameter represented as name(s) and value.
11103pub struct SetSessionParamGeneric {
11104    /// Names of the session parameters being set.
11105    pub names: Vec<String>,
11106    /// The value to assign to the parameter(s).
11107    pub value: String,
11108}
11109
11110impl fmt::Display for SetSessionParamGeneric {
11111    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11112        write!(f, "{} {}", display_comma_separated(&self.names), self.value)
11113    }
11114}
11115
11116#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11117#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11118#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11119/// `IDENTITY_INSERT` session parameter for a specific object.
11120pub struct SetSessionParamIdentityInsert {
11121    /// Object name targeted by `IDENTITY_INSERT`.
11122    pub obj: ObjectName,
11123    /// Value (ON/OFF) for the identity insert setting.
11124    pub value: SessionParamValue,
11125}
11126
11127impl fmt::Display for SetSessionParamIdentityInsert {
11128    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11129        write!(f, "IDENTITY_INSERT {} {}", self.obj, self.value)
11130    }
11131}
11132
11133#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11134#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11135#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11136/// Offsets-related session parameter with keywords and a value.
11137pub struct SetSessionParamOffsets {
11138    /// Keywords specifying which offsets to modify.
11139    pub keywords: Vec<String>,
11140    /// Value (ON/OFF) for the offsets setting.
11141    pub value: SessionParamValue,
11142}
11143
11144impl fmt::Display for SetSessionParamOffsets {
11145    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11146        write!(
11147            f,
11148            "OFFSETS {} {}",
11149            display_comma_separated(&self.keywords),
11150            self.value
11151        )
11152    }
11153}
11154
11155#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11156#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11157#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11158/// Statistics-related session parameter specifying topic and value.
11159pub struct SetSessionParamStatistics {
11160    /// Statistics topic to set (IO/PROFILE/TIME/XML).
11161    pub topic: SessionParamStatsTopic,
11162    /// Value (ON/OFF) for the statistics topic.
11163    pub value: SessionParamValue,
11164}
11165
11166impl fmt::Display for SetSessionParamStatistics {
11167    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11168        write!(f, "STATISTICS {} {}", self.topic, self.value)
11169    }
11170}
11171
11172#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11173#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11174#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11175/// Topics available for session statistics configuration.
11176pub enum SessionParamStatsTopic {
11177    /// Input/output statistics.
11178    IO,
11179    /// Profile statistics.
11180    Profile,
11181    /// Time statistics.
11182    Time,
11183    /// XML-related statistics.
11184    Xml,
11185}
11186
11187impl fmt::Display for SessionParamStatsTopic {
11188    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11189        match self {
11190            SessionParamStatsTopic::IO => write!(f, "IO"),
11191            SessionParamStatsTopic::Profile => write!(f, "PROFILE"),
11192            SessionParamStatsTopic::Time => write!(f, "TIME"),
11193            SessionParamStatsTopic::Xml => write!(f, "XML"),
11194        }
11195    }
11196}
11197
11198#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11199#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11200#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11201/// Value for a session boolean-like parameter (ON/OFF).
11202pub enum SessionParamValue {
11203    /// Session parameter enabled.
11204    On,
11205    /// Session parameter disabled.
11206    Off,
11207}
11208
11209impl fmt::Display for SessionParamValue {
11210    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11211        match self {
11212            SessionParamValue::On => write!(f, "ON"),
11213            SessionParamValue::Off => write!(f, "OFF"),
11214        }
11215    }
11216}
11217
11218/// Snowflake StorageSerializationPolicy for Iceberg Tables
11219/// ```sql
11220/// [ STORAGE_SERIALIZATION_POLICY = { COMPATIBLE | OPTIMIZED } ]
11221/// ```
11222///
11223/// <https://docs.snowflake.com/en/sql-reference/sql/create-iceberg-table>
11224#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11225#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11226#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11227pub enum StorageSerializationPolicy {
11228    /// Use compatible serialization mode.
11229    Compatible,
11230    /// Use optimized serialization mode.
11231    Optimized,
11232}
11233
11234impl Display for StorageSerializationPolicy {
11235    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
11236        match self {
11237            StorageSerializationPolicy::Compatible => write!(f, "COMPATIBLE"),
11238            StorageSerializationPolicy::Optimized => write!(f, "OPTIMIZED"),
11239        }
11240    }
11241}
11242
11243/// Snowflake CatalogSyncNamespaceMode
11244/// ```sql
11245/// [ CATALOG_SYNC_NAMESPACE_MODE = { NEST | FLATTEN } ]
11246/// ```
11247///
11248/// <https://docs.snowflake.com/en/sql-reference/sql/create-database>
11249#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11250#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11251#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11252pub enum CatalogSyncNamespaceMode {
11253    /// Nest namespaces when syncing catalog.
11254    Nest,
11255    /// Flatten namespaces when syncing catalog.
11256    Flatten,
11257}
11258
11259impl Display for CatalogSyncNamespaceMode {
11260    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
11261        match self {
11262            CatalogSyncNamespaceMode::Nest => write!(f, "NEST"),
11263            CatalogSyncNamespaceMode::Flatten => write!(f, "FLATTEN"),
11264        }
11265    }
11266}
11267
11268/// Variants of the Snowflake `COPY INTO` statement
11269#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11270#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11271#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11272pub enum CopyIntoSnowflakeKind {
11273    /// Loads data from files to a table
11274    /// See: <https://docs.snowflake.com/en/sql-reference/sql/copy-into-table>
11275    Table,
11276    /// Unloads data from a table or query to external files
11277    /// See: <https://docs.snowflake.com/en/sql-reference/sql/copy-into-location>
11278    Location,
11279}
11280
11281#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11282#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11283#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11284/// `PRINT` statement for producing debug/output messages.
11285pub struct PrintStatement {
11286    /// The expression producing the message to print.
11287    pub message: Box<Expr>,
11288}
11289
11290impl fmt::Display for PrintStatement {
11291    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11292        write!(f, "PRINT {}", self.message)
11293    }
11294}
11295
11296/// The type of `WAITFOR` statement (MSSQL).
11297///
11298/// See: <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/waitfor-transact-sql>
11299#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11300#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11301#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11302pub enum WaitForType {
11303    /// `WAITFOR DELAY 'time_to_pass'`
11304    Delay,
11305    /// `WAITFOR TIME 'time_to_execute'`
11306    Time,
11307}
11308
11309impl fmt::Display for WaitForType {
11310    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11311        match self {
11312            WaitForType::Delay => write!(f, "DELAY"),
11313            WaitForType::Time => write!(f, "TIME"),
11314        }
11315    }
11316}
11317
11318/// MSSQL `WAITFOR` statement.
11319///
11320/// See: <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/waitfor-transact-sql>
11321#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11322#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11323#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11324pub struct WaitForStatement {
11325    /// `DELAY` or `TIME`.
11326    pub wait_type: WaitForType,
11327    /// The time expression.
11328    pub expr: Expr,
11329}
11330
11331impl fmt::Display for WaitForStatement {
11332    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11333        write!(f, "WAITFOR {} {}", self.wait_type, self.expr)
11334    }
11335}
11336
11337/// Represents a `Return` statement.
11338///
11339/// [MsSql triggers](https://learn.microsoft.com/en-us/sql/t-sql/statements/create-trigger-transact-sql)
11340/// [MsSql functions](https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql)
11341#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11342#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11343#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11344pub struct ReturnStatement {
11345    /// Optional return value expression.
11346    pub value: Option<ReturnStatementValue>,
11347}
11348
11349impl fmt::Display for ReturnStatement {
11350    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11351        match &self.value {
11352            Some(ReturnStatementValue::Expr(expr)) => write!(f, "RETURN {expr}"),
11353            None => write!(f, "RETURN"),
11354        }
11355    }
11356}
11357
11358/// Variants of a `RETURN` statement
11359#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11360#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11361#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11362pub enum ReturnStatementValue {
11363    /// Return an expression from a function or trigger.
11364    Expr(Expr),
11365}
11366
11367/// Represents an `OPEN` statement.
11368#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11369#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11370#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11371pub struct OpenStatement {
11372    /// Cursor name
11373    pub cursor_name: Ident,
11374}
11375
11376impl fmt::Display for OpenStatement {
11377    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11378        write!(f, "OPEN {}", self.cursor_name)
11379    }
11380}
11381
11382/// Specifies Include / Exclude NULL within UNPIVOT command.
11383/// For example
11384/// `UNPIVOT (column1 FOR new_column IN (col3, col4, col5, col6))`
11385#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11386#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11387#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11388pub enum NullInclusion {
11389    /// Include NULL values in the UNPIVOT output.
11390    IncludeNulls,
11391    /// Exclude NULL values from the UNPIVOT output.
11392    ExcludeNulls,
11393}
11394
11395impl fmt::Display for NullInclusion {
11396    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11397        match self {
11398            NullInclusion::IncludeNulls => write!(f, "INCLUDE NULLS"),
11399            NullInclusion::ExcludeNulls => write!(f, "EXCLUDE NULLS"),
11400        }
11401    }
11402}
11403
11404/// Checks membership of a value in a JSON array
11405///
11406/// Syntax:
11407/// ```sql
11408/// <value> MEMBER OF(<array>)
11409/// ```
11410/// [MySQL](https://dev.mysql.com/doc/refman/8.4/en/json-search-functions.html#operator_member-of)
11411#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11412#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11413#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11414pub struct MemberOf {
11415    /// The value to check for membership.
11416    pub value: Box<Expr>,
11417    /// The JSON array expression to check against.
11418    pub array: Box<Expr>,
11419}
11420
11421impl fmt::Display for MemberOf {
11422    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11423        write!(f, "{} MEMBER OF({})", self.value, self.array)
11424    }
11425}
11426
11427#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11428#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11429#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11430/// Represents an `EXPORT DATA` statement.
11431pub struct ExportData {
11432    /// Options for the export operation.
11433    pub options: Vec<SqlOption>,
11434    /// The query producing the data to export.
11435    pub query: Box<Query>,
11436    /// Optional named connection to use for export.
11437    pub connection: Option<ObjectName>,
11438}
11439
11440impl fmt::Display for ExportData {
11441    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11442        if let Some(connection) = &self.connection {
11443            write!(
11444                f,
11445                "EXPORT DATA WITH CONNECTION {connection} OPTIONS({}) AS {}",
11446                display_comma_separated(&self.options),
11447                self.query
11448            )
11449        } else {
11450            write!(
11451                f,
11452                "EXPORT DATA OPTIONS({}) AS {}",
11453                display_comma_separated(&self.options),
11454                self.query
11455            )
11456        }
11457    }
11458}
11459/// Creates a user
11460///
11461/// Syntax:
11462/// ```sql
11463/// CREATE [OR REPLACE] USER [IF NOT EXISTS] <name> [OPTIONS]
11464/// ```
11465///
11466/// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-user)
11467#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11468#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11469#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11470pub struct CreateUser {
11471    /// Replace existing user if present.
11472    pub or_replace: bool,
11473    /// Only create the user if it does not already exist.
11474    pub if_not_exists: bool,
11475    /// The name of the user to create.
11476    pub name: Ident,
11477    /// Key/value options for user creation.
11478    pub options: KeyValueOptions,
11479    /// Whether tags are specified using `WITH TAG`.
11480    pub with_tags: bool,
11481    /// Tags for the user.
11482    pub tags: KeyValueOptions,
11483}
11484
11485impl fmt::Display for CreateUser {
11486    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11487        write!(f, "CREATE")?;
11488        if self.or_replace {
11489            write!(f, " OR REPLACE")?;
11490        }
11491        write!(f, " USER")?;
11492        if self.if_not_exists {
11493            write!(f, " IF NOT EXISTS")?;
11494        }
11495        write!(f, " {}", self.name)?;
11496        if !self.options.options.is_empty() {
11497            write!(f, " {}", self.options)?;
11498        }
11499        if !self.tags.options.is_empty() {
11500            if self.with_tags {
11501                write!(f, " WITH")?;
11502            }
11503            write!(f, " TAG ({})", self.tags)?;
11504        }
11505        Ok(())
11506    }
11507}
11508
11509/// Modifies the properties of a user
11510///
11511/// [Snowflake Syntax:](https://docs.snowflake.com/en/sql-reference/sql/alter-user)
11512/// ```sql
11513/// ALTER USER [ IF EXISTS ] [ <name> ] [ OPTIONS ]
11514/// ```
11515///
11516/// [PostgreSQL Syntax:](https://www.postgresql.org/docs/current/sql-alteruser.html)
11517/// ```sql
11518/// ALTER USER <role_specification> [ WITH ] option [ ... ]
11519/// ```
11520#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11521#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11522#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11523pub struct AlterUser {
11524    /// Whether to only alter the user if it exists.
11525    pub if_exists: bool,
11526    /// The name of the user to alter.
11527    pub name: Ident,
11528    /// Optional new name for the user (Snowflake-specific).
11529    /// See: <https://docs.snowflake.com/en/sql-reference/sql/alter-user#syntax>
11530    pub rename_to: Option<Ident>,
11531    /// Reset the user's password.
11532    pub reset_password: bool,
11533    /// Abort all running queries for the user.
11534    pub abort_all_queries: bool,
11535    /// Optionally add a delegated role authorization.
11536    pub add_role_delegation: Option<AlterUserAddRoleDelegation>,
11537    /// Optionally remove a delegated role authorization.
11538    pub remove_role_delegation: Option<AlterUserRemoveRoleDelegation>,
11539    /// Enroll the user in MFA.
11540    pub enroll_mfa: bool,
11541    /// Set the default MFA method for the user.
11542    pub set_default_mfa_method: Option<MfaMethodKind>,
11543    /// Remove the user's default MFA method.
11544    pub remove_mfa_method: Option<MfaMethodKind>,
11545    /// Modify an MFA method for the user.
11546    pub modify_mfa_method: Option<AlterUserModifyMfaMethod>,
11547    /// Add an MFA OTP method with optional count.
11548    pub add_mfa_method_otp: Option<AlterUserAddMfaMethodOtp>,
11549    /// Set a user policy.
11550    pub set_policy: Option<AlterUserSetPolicy>,
11551    /// Unset a user policy.
11552    pub unset_policy: Option<UserPolicyKind>,
11553    /// Key/value tag options to set on the user.
11554    pub set_tag: KeyValueOptions,
11555    /// Tags to unset on the user.
11556    pub unset_tag: Vec<String>,
11557    /// Key/value properties to set on the user.
11558    pub set_props: KeyValueOptions,
11559    /// Properties to unset on the user.
11560    pub unset_props: Vec<String>,
11561    /// The following options are PostgreSQL-specific: <https://www.postgresql.org/docs/current/sql-alteruser.html>
11562    pub password: Option<AlterUserPassword>,
11563}
11564
11565/// ```sql
11566/// ALTER USER [ IF EXISTS ] [ <name> ] ADD DELEGATED AUTHORIZATION OF ROLE <role_name> TO SECURITY INTEGRATION <integration_name>
11567/// ```
11568#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11569#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11570#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11571pub struct AlterUserAddRoleDelegation {
11572    /// Role name to delegate.
11573    pub role: Ident,
11574    /// Security integration receiving the delegation.
11575    pub integration: Ident,
11576}
11577
11578/// ```sql
11579/// ALTER USER [ IF EXISTS ] [ <name> ] REMOVE DELEGATED { AUTHORIZATION OF ROLE <role_name> | AUTHORIZATIONS } FROM SECURITY INTEGRATION <integration_name>
11580/// ```
11581#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11582#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11583#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11584pub struct AlterUserRemoveRoleDelegation {
11585    /// Optional role name to remove delegation for.
11586    pub role: Option<Ident>,
11587    /// Security integration from which to remove delegation.
11588    pub integration: Ident,
11589}
11590
11591/// ```sql
11592/// ADD MFA METHOD OTP [ COUNT = number ]
11593/// ```
11594#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11595#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11596#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11597pub struct AlterUserAddMfaMethodOtp {
11598    /// Optional OTP count parameter.
11599    pub count: Option<ValueWithSpan>,
11600}
11601
11602/// ```sql
11603/// ALTER USER [ IF EXISTS ] [ <name> ] MODIFY MFA METHOD <mfa_method> SET COMMENT = '<string>'
11604/// ```
11605#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11606#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11607#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11608pub struct AlterUserModifyMfaMethod {
11609    /// The MFA method being modified.
11610    pub method: MfaMethodKind,
11611    /// The new comment for the MFA method.
11612    pub comment: String,
11613}
11614
11615/// Types of MFA methods
11616#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11617#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11618#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11619pub enum MfaMethodKind {
11620    /// PassKey (hardware or platform passkey) MFA method.
11621    PassKey,
11622    /// Time-based One-Time Password (TOTP) MFA method.
11623    Totp,
11624    /// Duo Security MFA method.
11625    Duo,
11626}
11627
11628impl fmt::Display for MfaMethodKind {
11629    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11630        match self {
11631            MfaMethodKind::PassKey => write!(f, "PASSKEY"),
11632            MfaMethodKind::Totp => write!(f, "TOTP"),
11633            MfaMethodKind::Duo => write!(f, "DUO"),
11634        }
11635    }
11636}
11637
11638/// ```sql
11639/// ALTER USER [ IF EXISTS ] [ <name> ] SET { AUTHENTICATION | PASSWORD | SESSION } POLICY <policy_name>
11640/// ```
11641#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11642#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11643#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11644pub struct AlterUserSetPolicy {
11645    /// The kind of user policy being set (authentication/password/session).
11646    pub policy_kind: UserPolicyKind,
11647    /// The identifier of the policy to apply.
11648    pub policy: Ident,
11649}
11650
11651/// Types of user-based policies
11652#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11653#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11654#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11655pub enum UserPolicyKind {
11656    /// Authentication policy.
11657    Authentication,
11658    /// Password policy.
11659    Password,
11660    /// Session policy.
11661    Session,
11662}
11663
11664impl fmt::Display for UserPolicyKind {
11665    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11666        match self {
11667            UserPolicyKind::Authentication => write!(f, "AUTHENTICATION"),
11668            UserPolicyKind::Password => write!(f, "PASSWORD"),
11669            UserPolicyKind::Session => write!(f, "SESSION"),
11670        }
11671    }
11672}
11673
11674impl fmt::Display for AlterUser {
11675    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11676        write!(f, "ALTER")?;
11677        write!(f, " USER")?;
11678        if self.if_exists {
11679            write!(f, " IF EXISTS")?;
11680        }
11681        write!(f, " {}", self.name)?;
11682        if let Some(new_name) = &self.rename_to {
11683            write!(f, " RENAME TO {new_name}")?;
11684        }
11685        if self.reset_password {
11686            write!(f, " RESET PASSWORD")?;
11687        }
11688        if self.abort_all_queries {
11689            write!(f, " ABORT ALL QUERIES")?;
11690        }
11691        if let Some(role_delegation) = &self.add_role_delegation {
11692            let role = &role_delegation.role;
11693            let integration = &role_delegation.integration;
11694            write!(
11695                f,
11696                " ADD DELEGATED AUTHORIZATION OF ROLE {role} TO SECURITY INTEGRATION {integration}"
11697            )?;
11698        }
11699        if let Some(role_delegation) = &self.remove_role_delegation {
11700            write!(f, " REMOVE DELEGATED")?;
11701            match &role_delegation.role {
11702                Some(role) => write!(f, " AUTHORIZATION OF ROLE {role}")?,
11703                None => write!(f, " AUTHORIZATIONS")?,
11704            }
11705            let integration = &role_delegation.integration;
11706            write!(f, " FROM SECURITY INTEGRATION {integration}")?;
11707        }
11708        if self.enroll_mfa {
11709            write!(f, " ENROLL MFA")?;
11710        }
11711        if let Some(method) = &self.set_default_mfa_method {
11712            write!(f, " SET DEFAULT_MFA_METHOD {method}")?
11713        }
11714        if let Some(method) = &self.remove_mfa_method {
11715            write!(f, " REMOVE MFA METHOD {method}")?;
11716        }
11717        if let Some(modify) = &self.modify_mfa_method {
11718            let method = &modify.method;
11719            let comment = &modify.comment;
11720            write!(
11721                f,
11722                " MODIFY MFA METHOD {method} SET COMMENT '{}'",
11723                value::escape_single_quote_string(comment)
11724            )?;
11725        }
11726        if let Some(add_mfa_method_otp) = &self.add_mfa_method_otp {
11727            write!(f, " ADD MFA METHOD OTP")?;
11728            if let Some(count) = &add_mfa_method_otp.count {
11729                write!(f, " COUNT = {count}")?;
11730            }
11731        }
11732        if let Some(policy) = &self.set_policy {
11733            let policy_kind = &policy.policy_kind;
11734            let name = &policy.policy;
11735            write!(f, " SET {policy_kind} POLICY {name}")?;
11736        }
11737        if let Some(policy_kind) = &self.unset_policy {
11738            write!(f, " UNSET {policy_kind} POLICY")?;
11739        }
11740        if !self.set_tag.options.is_empty() {
11741            write!(f, " SET TAG {}", self.set_tag)?;
11742        }
11743        if !self.unset_tag.is_empty() {
11744            write!(f, " UNSET TAG {}", display_comma_separated(&self.unset_tag))?;
11745        }
11746        let has_props = !self.set_props.options.is_empty();
11747        if has_props {
11748            write!(f, " SET")?;
11749            write!(f, " {}", self.set_props)?;
11750        }
11751        if !self.unset_props.is_empty() {
11752            write!(f, " UNSET {}", display_comma_separated(&self.unset_props))?;
11753        }
11754        if let Some(password) = &self.password {
11755            write!(f, " {}", password)?;
11756        }
11757        Ok(())
11758    }
11759}
11760
11761/// ```sql
11762/// ALTER USER <role_specification> [ WITH ] PASSWORD { 'password' | NULL }``
11763/// ```
11764#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11765#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11766#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11767pub struct AlterUserPassword {
11768    /// Whether the password is encrypted.
11769    pub encrypted: bool,
11770    /// The password string, or `None` for `NULL`.
11771    pub password: Option<String>,
11772}
11773
11774impl Display for AlterUserPassword {
11775    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11776        if self.encrypted {
11777            write!(f, "ENCRYPTED ")?;
11778        }
11779        write!(f, "PASSWORD")?;
11780        match &self.password {
11781            None => write!(f, " NULL")?,
11782            Some(password) => write!(f, " '{}'", value::escape_single_quote_string(password))?,
11783        }
11784        Ok(())
11785    }
11786}
11787
11788/// Specifies how to create a new table based on an existing table's schema.
11789/// '''sql
11790/// CREATE TABLE new LIKE old ...
11791/// '''
11792#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11793#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11794#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11795pub enum CreateTableLikeKind {
11796    /// '''sql
11797    /// CREATE TABLE new (LIKE old ...)
11798    /// '''
11799    /// [Redshift](https://docs.aws.amazon.com/redshift/latest/dg/r_CREATE_TABLE_NEW.html)
11800    Parenthesized(CreateTableLike),
11801    /// '''sql
11802    /// CREATE TABLE new LIKE old ...
11803    /// '''
11804    /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-table#label-create-table-like)
11805    /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_table_like)
11806    Plain(CreateTableLike),
11807}
11808
11809#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11810#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11811#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11812/// Controls whether defaults are included when creating a table FROM/LILE another.
11813pub enum CreateTableLikeDefaults {
11814    /// Include default values from the source table.
11815    Including,
11816    /// Exclude default values from the source table.
11817    Excluding,
11818}
11819
11820impl fmt::Display for CreateTableLikeDefaults {
11821    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11822        match self {
11823            CreateTableLikeDefaults::Including => write!(f, "INCLUDING DEFAULTS"),
11824            CreateTableLikeDefaults::Excluding => write!(f, "EXCLUDING DEFAULTS"),
11825        }
11826    }
11827}
11828
11829#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11830#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11831#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11832/// Represents the `LIKE` clause of a `CREATE TABLE` statement.
11833pub struct CreateTableLike {
11834    /// The source table name to copy the schema from.
11835    pub name: ObjectName,
11836    /// Optional behavior controlling whether defaults are copied.
11837    pub defaults: Option<CreateTableLikeDefaults>,
11838}
11839
11840impl fmt::Display for CreateTableLike {
11841    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11842        write!(f, "LIKE {}", self.name)?;
11843        if let Some(defaults) = &self.defaults {
11844            write!(f, " {defaults}")?;
11845        }
11846        Ok(())
11847    }
11848}
11849
11850/// Specifies the refresh mode for the dynamic table.
11851///
11852/// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-dynamic-table)
11853#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11854#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11855#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11856pub enum RefreshModeKind {
11857    /// Automatic refresh mode (`AUTO`).
11858    Auto,
11859    /// Full refresh mode (`FULL`).
11860    Full,
11861    /// Incremental refresh mode (`INCREMENTAL`).
11862    Incremental,
11863}
11864
11865impl fmt::Display for RefreshModeKind {
11866    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11867        match self {
11868            RefreshModeKind::Auto => write!(f, "AUTO"),
11869            RefreshModeKind::Full => write!(f, "FULL"),
11870            RefreshModeKind::Incremental => write!(f, "INCREMENTAL"),
11871        }
11872    }
11873}
11874
11875/// Specifies the behavior of the initial refresh of the dynamic table.
11876///
11877/// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-dynamic-table)
11878#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11879#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11880#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11881pub enum InitializeKind {
11882    /// Initialize on creation (`ON CREATE`).
11883    OnCreate,
11884    /// Initialize on schedule (`ON SCHEDULE`).
11885    OnSchedule,
11886}
11887
11888impl fmt::Display for InitializeKind {
11889    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11890        match self {
11891            InitializeKind::OnCreate => write!(f, "ON_CREATE"),
11892            InitializeKind::OnSchedule => write!(f, "ON_SCHEDULE"),
11893        }
11894    }
11895}
11896
11897/// Re-sorts rows and reclaims space in either a specified table or all tables in the current database
11898///
11899/// '''sql
11900/// VACUUM [ FULL | SORT ONLY | DELETE ONLY | REINDEX | RECLUSTER ] [ \[ table_name \] [ TO threshold PERCENT ] \[ BOOST \] ]
11901/// '''
11902/// [Redshift](https://docs.aws.amazon.com/redshift/latest/dg/r_VACUUM_command.html)
11903#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11904#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11905#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11906pub struct VacuumStatement {
11907    /// Whether `FULL` was specified.
11908    pub full: bool,
11909    /// Whether `SORT ONLY` was specified.
11910    pub sort_only: bool,
11911    /// Whether `DELETE ONLY` was specified.
11912    pub delete_only: bool,
11913    /// Whether `REINDEX` was specified.
11914    pub reindex: bool,
11915    /// Whether `RECLUSTER` was specified.
11916    pub recluster: bool,
11917    /// Optional table to run `VACUUM` on.
11918    pub table_name: Option<ObjectName>,
11919    /// Optional threshold value (percent) for `TO threshold PERCENT`.
11920    pub threshold: Option<ValueWithSpan>,
11921    /// Whether `BOOST` was specified.
11922    pub boost: bool,
11923}
11924
11925impl fmt::Display for VacuumStatement {
11926    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11927        write!(
11928            f,
11929            "VACUUM{}{}{}{}{}",
11930            if self.full { " FULL" } else { "" },
11931            if self.sort_only { " SORT ONLY" } else { "" },
11932            if self.delete_only { " DELETE ONLY" } else { "" },
11933            if self.reindex { " REINDEX" } else { "" },
11934            if self.recluster { " RECLUSTER" } else { "" },
11935        )?;
11936        if let Some(table_name) = &self.table_name {
11937            write!(f, " {table_name}")?;
11938        }
11939        if let Some(threshold) = &self.threshold {
11940            write!(f, " TO {threshold} PERCENT")?;
11941        }
11942        if self.boost {
11943            write!(f, " BOOST")?;
11944        }
11945        Ok(())
11946    }
11947}
11948
11949/// Variants of the RESET statement
11950#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11951#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11952#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11953pub enum Reset {
11954    /// Resets all session parameters to their default values.
11955    ALL,
11956
11957    /// Resets a specific session parameter to its default value.
11958    ConfigurationParameter(ObjectName),
11959}
11960
11961/// Resets a session parameter to its default value.
11962/// ```sql
11963/// RESET { ALL | <configuration_parameter> }
11964/// ```
11965#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11966#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11967#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11968pub struct ResetStatement {
11969    /// The reset action to perform (either `ALL` or a specific configuration parameter).
11970    pub reset: Reset,
11971}
11972
11973/// Query optimizer hints are optionally supported comments after the
11974/// `SELECT`, `INSERT`, `UPDATE`, `REPLACE`, `MERGE`, and `DELETE` keywords in
11975/// the corresponding statements.
11976///
11977/// See [Select::optimizer_hints]
11978#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11979#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11980#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11981pub struct OptimizerHint {
11982    /// An optional prefix between the comment marker and `+`.
11983    ///
11984    /// Standard optimizer hints like `/*+ ... */` have an empty prefix,
11985    /// while system-specific hints like `/*abc+ ... */` have `prefix = "abc"`.
11986    /// The prefix is any sequence of ASCII alphanumeric characters
11987    /// immediately before the `+` marker.
11988    pub prefix: String,
11989    /// the raw text of the optimizer hint without its markers
11990    pub text: String,
11991    /// the style of the comment which `text` was extracted from,
11992    /// e.g. `/*+...*/` or `--+...`
11993    ///
11994    /// Not all dialects support all styles, though.
11995    pub style: OptimizerHintStyle,
11996}
11997
11998/// The commentary style of an [optimizer hint](OptimizerHint)
11999#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
12000#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
12001#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
12002pub enum OptimizerHintStyle {
12003    /// A hint corresponding to a single line comment,
12004    /// e.g. `--+ LEADING(v.e v.d t)`
12005    SingleLine {
12006        /// the comment prefix, e.g. `--`
12007        prefix: String,
12008    },
12009    /// A hint corresponding to a multi line comment,
12010    /// e.g. `/*+ LEADING(v.e v.d t) */`
12011    MultiLine,
12012}
12013
12014impl fmt::Display for OptimizerHint {
12015    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
12016        match &self.style {
12017            OptimizerHintStyle::SingleLine { prefix } => {
12018                f.write_str(prefix)?;
12019                f.write_str(&self.prefix)?;
12020                f.write_str("+")?;
12021                f.write_str(&self.text)
12022            }
12023            OptimizerHintStyle::MultiLine => {
12024                f.write_str("/*")?;
12025                f.write_str(&self.prefix)?;
12026                f.write_str("+")?;
12027                f.write_str(&self.text)?;
12028                f.write_str("*/")
12029            }
12030        }
12031    }
12032}
12033
12034impl fmt::Display for ResetStatement {
12035    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
12036        match &self.reset {
12037            Reset::ALL => write!(f, "RESET ALL"),
12038            Reset::ConfigurationParameter(param) => write!(f, "RESET {}", param),
12039        }
12040    }
12041}
12042
12043impl From<Set> for Statement {
12044    fn from(s: Set) -> Self {
12045        Self::Set(s)
12046    }
12047}
12048
12049impl From<Query> for Statement {
12050    fn from(q: Query) -> Self {
12051        Box::new(q).into()
12052    }
12053}
12054
12055impl From<Box<Query>> for Statement {
12056    fn from(q: Box<Query>) -> Self {
12057        Self::Query(q)
12058    }
12059}
12060
12061impl From<Insert> for Statement {
12062    fn from(i: Insert) -> Self {
12063        Self::Insert(i)
12064    }
12065}
12066
12067impl From<Update> for Statement {
12068    fn from(u: Update) -> Self {
12069        Self::Update(u)
12070    }
12071}
12072
12073impl From<CreateView> for Statement {
12074    fn from(cv: CreateView) -> Self {
12075        Self::CreateView(cv)
12076    }
12077}
12078
12079impl From<CreateRole> for Statement {
12080    fn from(cr: CreateRole) -> Self {
12081        Self::CreateRole(cr)
12082    }
12083}
12084
12085impl From<AlterTable> for Statement {
12086    fn from(at: AlterTable) -> Self {
12087        Self::AlterTable(at)
12088    }
12089}
12090
12091impl From<DropFunction> for Statement {
12092    fn from(df: DropFunction) -> Self {
12093        Self::DropFunction(df)
12094    }
12095}
12096
12097impl From<CreateExtension> for Statement {
12098    fn from(ce: CreateExtension) -> Self {
12099        Self::CreateExtension(ce)
12100    }
12101}
12102
12103impl From<CreateCollation> for Statement {
12104    fn from(c: CreateCollation) -> Self {
12105        Self::CreateCollation(c)
12106    }
12107}
12108
12109impl From<DropExtension> for Statement {
12110    fn from(de: DropExtension) -> Self {
12111        Self::DropExtension(de)
12112    }
12113}
12114
12115impl From<CaseStatement> for Statement {
12116    fn from(c: CaseStatement) -> Self {
12117        Self::Case(c)
12118    }
12119}
12120
12121impl From<IfStatement> for Statement {
12122    fn from(i: IfStatement) -> Self {
12123        Self::If(i)
12124    }
12125}
12126
12127impl From<WhileStatement> for Statement {
12128    fn from(w: WhileStatement) -> Self {
12129        Self::While(w)
12130    }
12131}
12132
12133impl From<RaiseStatement> for Statement {
12134    fn from(r: RaiseStatement) -> Self {
12135        Self::Raise(r)
12136    }
12137}
12138
12139impl From<ThrowStatement> for Statement {
12140    fn from(t: ThrowStatement) -> Self {
12141        Self::Throw(t)
12142    }
12143}
12144
12145impl From<Function> for Statement {
12146    fn from(f: Function) -> Self {
12147        Self::Call(f)
12148    }
12149}
12150
12151impl From<OpenStatement> for Statement {
12152    fn from(o: OpenStatement) -> Self {
12153        Self::Open(o)
12154    }
12155}
12156
12157impl From<Delete> for Statement {
12158    fn from(d: Delete) -> Self {
12159        Self::Delete(d)
12160    }
12161}
12162
12163impl From<CreateTable> for Statement {
12164    fn from(c: CreateTable) -> Self {
12165        Self::CreateTable(c)
12166    }
12167}
12168
12169impl From<CreateIndex> for Statement {
12170    fn from(c: CreateIndex) -> Self {
12171        Self::CreateIndex(c)
12172    }
12173}
12174
12175impl From<CreateServerStatement> for Statement {
12176    fn from(c: CreateServerStatement) -> Self {
12177        Self::CreateServer(c)
12178    }
12179}
12180
12181impl From<CreateConnector> for Statement {
12182    fn from(c: CreateConnector) -> Self {
12183        Self::CreateConnector(c)
12184    }
12185}
12186
12187impl From<CreateOperator> for Statement {
12188    fn from(c: CreateOperator) -> Self {
12189        Self::CreateOperator(c)
12190    }
12191}
12192
12193impl From<CreateOperatorFamily> for Statement {
12194    fn from(c: CreateOperatorFamily) -> Self {
12195        Self::CreateOperatorFamily(c)
12196    }
12197}
12198
12199impl From<CreateOperatorClass> for Statement {
12200    fn from(c: CreateOperatorClass) -> Self {
12201        Self::CreateOperatorClass(c)
12202    }
12203}
12204
12205impl From<AlterSchema> for Statement {
12206    fn from(a: AlterSchema) -> Self {
12207        Self::AlterSchema(a)
12208    }
12209}
12210
12211impl From<AlterFunction> for Statement {
12212    fn from(a: AlterFunction) -> Self {
12213        Self::AlterFunction(a)
12214    }
12215}
12216
12217impl From<AlterType> for Statement {
12218    fn from(a: AlterType) -> Self {
12219        Self::AlterType(a)
12220    }
12221}
12222
12223impl From<AlterCollation> for Statement {
12224    fn from(a: AlterCollation) -> Self {
12225        Self::AlterCollation(a)
12226    }
12227}
12228
12229impl From<AlterOperator> for Statement {
12230    fn from(a: AlterOperator) -> Self {
12231        Self::AlterOperator(a)
12232    }
12233}
12234
12235impl From<AlterOperatorFamily> for Statement {
12236    fn from(a: AlterOperatorFamily) -> Self {
12237        Self::AlterOperatorFamily(a)
12238    }
12239}
12240
12241impl From<AlterOperatorClass> for Statement {
12242    fn from(a: AlterOperatorClass) -> Self {
12243        Self::AlterOperatorClass(a)
12244    }
12245}
12246
12247impl From<Merge> for Statement {
12248    fn from(m: Merge) -> Self {
12249        Self::Merge(m)
12250    }
12251}
12252
12253impl From<AlterUser> for Statement {
12254    fn from(a: AlterUser) -> Self {
12255        Self::AlterUser(a)
12256    }
12257}
12258
12259impl From<DropDomain> for Statement {
12260    fn from(d: DropDomain) -> Self {
12261        Self::DropDomain(d)
12262    }
12263}
12264
12265impl From<ShowCharset> for Statement {
12266    fn from(s: ShowCharset) -> Self {
12267        Self::ShowCharset(s)
12268    }
12269}
12270
12271impl From<ShowObjects> for Statement {
12272    fn from(s: ShowObjects) -> Self {
12273        Self::ShowObjects(s)
12274    }
12275}
12276
12277impl From<Use> for Statement {
12278    fn from(u: Use) -> Self {
12279        Self::Use(u)
12280    }
12281}
12282
12283impl From<CreateFunction> for Statement {
12284    fn from(c: CreateFunction) -> Self {
12285        Self::CreateFunction(c)
12286    }
12287}
12288
12289impl From<CreateTrigger> for Statement {
12290    fn from(c: CreateTrigger) -> Self {
12291        Self::CreateTrigger(c)
12292    }
12293}
12294
12295impl From<DropTrigger> for Statement {
12296    fn from(d: DropTrigger) -> Self {
12297        Self::DropTrigger(d)
12298    }
12299}
12300
12301impl From<DropOperator> for Statement {
12302    fn from(d: DropOperator) -> Self {
12303        Self::DropOperator(d)
12304    }
12305}
12306
12307impl From<DropOperatorFamily> for Statement {
12308    fn from(d: DropOperatorFamily) -> Self {
12309        Self::DropOperatorFamily(d)
12310    }
12311}
12312
12313impl From<DropOperatorClass> for Statement {
12314    fn from(d: DropOperatorClass) -> Self {
12315        Self::DropOperatorClass(d)
12316    }
12317}
12318
12319impl From<DenyStatement> for Statement {
12320    fn from(d: DenyStatement) -> Self {
12321        Self::Deny(d)
12322    }
12323}
12324
12325impl From<CreateDomain> for Statement {
12326    fn from(c: CreateDomain) -> Self {
12327        Self::CreateDomain(c)
12328    }
12329}
12330
12331impl From<RenameTable> for Statement {
12332    fn from(r: RenameTable) -> Self {
12333        vec![r].into()
12334    }
12335}
12336
12337impl From<Vec<RenameTable>> for Statement {
12338    fn from(r: Vec<RenameTable>) -> Self {
12339        Self::RenameTable(r)
12340    }
12341}
12342
12343impl From<PrintStatement> for Statement {
12344    fn from(p: PrintStatement) -> Self {
12345        Self::Print(p)
12346    }
12347}
12348
12349impl From<ReturnStatement> for Statement {
12350    fn from(r: ReturnStatement) -> Self {
12351        Self::Return(r)
12352    }
12353}
12354
12355impl From<ExportData> for Statement {
12356    fn from(e: ExportData) -> Self {
12357        Self::ExportData(e)
12358    }
12359}
12360
12361impl From<CreateUser> for Statement {
12362    fn from(c: CreateUser) -> Self {
12363        Self::CreateUser(c)
12364    }
12365}
12366
12367impl From<VacuumStatement> for Statement {
12368    fn from(v: VacuumStatement) -> Self {
12369        Self::Vacuum(v)
12370    }
12371}
12372
12373impl From<ResetStatement> for Statement {
12374    fn from(r: ResetStatement) -> Self {
12375        Self::Reset(r)
12376    }
12377}
12378
12379#[cfg(test)]
12380mod tests {
12381    use crate::tokenizer::Location;
12382
12383    use super::*;
12384
12385    #[test]
12386    fn test_window_frame_default() {
12387        let window_frame = WindowFrame::default();
12388        assert_eq!(WindowFrameBound::Preceding(None), window_frame.start_bound);
12389    }
12390
12391    #[test]
12392    fn test_grouping_sets_display() {
12393        // a and b in different group
12394        let grouping_sets = Expr::GroupingSets(vec![
12395            vec![Expr::Identifier(Ident::new("a"))],
12396            vec![Expr::Identifier(Ident::new("b"))],
12397        ]);
12398        assert_eq!("GROUPING SETS ((a), (b))", format!("{grouping_sets}"));
12399
12400        // a and b in the same group
12401        let grouping_sets = Expr::GroupingSets(vec![vec![
12402            Expr::Identifier(Ident::new("a")),
12403            Expr::Identifier(Ident::new("b")),
12404        ]]);
12405        assert_eq!("GROUPING SETS ((a, b))", format!("{grouping_sets}"));
12406
12407        // (a, b) and (c, d) in different group
12408        let grouping_sets = Expr::GroupingSets(vec![
12409            vec![
12410                Expr::Identifier(Ident::new("a")),
12411                Expr::Identifier(Ident::new("b")),
12412            ],
12413            vec![
12414                Expr::Identifier(Ident::new("c")),
12415                Expr::Identifier(Ident::new("d")),
12416            ],
12417        ]);
12418        assert_eq!("GROUPING SETS ((a, b), (c, d))", format!("{grouping_sets}"));
12419    }
12420
12421    #[test]
12422    fn test_rollup_display() {
12423        let rollup = Expr::Rollup(vec![vec![Expr::Identifier(Ident::new("a"))]]);
12424        assert_eq!("ROLLUP (a)", format!("{rollup}"));
12425
12426        let rollup = Expr::Rollup(vec![vec![
12427            Expr::Identifier(Ident::new("a")),
12428            Expr::Identifier(Ident::new("b")),
12429        ]]);
12430        assert_eq!("ROLLUP ((a, b))", format!("{rollup}"));
12431
12432        let rollup = Expr::Rollup(vec![
12433            vec![Expr::Identifier(Ident::new("a"))],
12434            vec![Expr::Identifier(Ident::new("b"))],
12435        ]);
12436        assert_eq!("ROLLUP (a, b)", format!("{rollup}"));
12437
12438        let rollup = Expr::Rollup(vec![
12439            vec![Expr::Identifier(Ident::new("a"))],
12440            vec![
12441                Expr::Identifier(Ident::new("b")),
12442                Expr::Identifier(Ident::new("c")),
12443            ],
12444            vec![Expr::Identifier(Ident::new("d"))],
12445        ]);
12446        assert_eq!("ROLLUP (a, (b, c), d)", format!("{rollup}"));
12447    }
12448
12449    #[test]
12450    fn test_cube_display() {
12451        let cube = Expr::Cube(vec![vec![Expr::Identifier(Ident::new("a"))]]);
12452        assert_eq!("CUBE (a)", format!("{cube}"));
12453
12454        let cube = Expr::Cube(vec![vec![
12455            Expr::Identifier(Ident::new("a")),
12456            Expr::Identifier(Ident::new("b")),
12457        ]]);
12458        assert_eq!("CUBE ((a, b))", format!("{cube}"));
12459
12460        let cube = Expr::Cube(vec![
12461            vec![Expr::Identifier(Ident::new("a"))],
12462            vec![Expr::Identifier(Ident::new("b"))],
12463        ]);
12464        assert_eq!("CUBE (a, b)", format!("{cube}"));
12465
12466        let cube = Expr::Cube(vec![
12467            vec![Expr::Identifier(Ident::new("a"))],
12468            vec![
12469                Expr::Identifier(Ident::new("b")),
12470                Expr::Identifier(Ident::new("c")),
12471            ],
12472            vec![Expr::Identifier(Ident::new("d"))],
12473        ]);
12474        assert_eq!("CUBE (a, (b, c), d)", format!("{cube}"));
12475    }
12476
12477    #[test]
12478    fn test_interval_display() {
12479        let interval = Expr::Interval(Interval {
12480            value: Box::new(Expr::Value(
12481                Value::SingleQuotedString(String::from("123:45.67")).with_empty_span(),
12482            )),
12483            leading_field: Some(DateTimeField::Minute),
12484            leading_precision: Some(10),
12485            last_field: Some(DateTimeField::Second),
12486            fractional_seconds_precision: Some(9),
12487        });
12488        assert_eq!(
12489            "INTERVAL '123:45.67' MINUTE (10) TO SECOND (9)",
12490            format!("{interval}"),
12491        );
12492
12493        let interval = Expr::Interval(Interval {
12494            value: Box::new(Expr::Value(
12495                Value::SingleQuotedString(String::from("5")).with_empty_span(),
12496            )),
12497            leading_field: Some(DateTimeField::Second),
12498            leading_precision: Some(1),
12499            last_field: None,
12500            fractional_seconds_precision: Some(3),
12501        });
12502        assert_eq!("INTERVAL '5' SECOND (1, 3)", format!("{interval}"));
12503    }
12504
12505    #[test]
12506    fn test_one_or_many_with_parens_deref() {
12507        use core::ops::Index;
12508
12509        let one = OneOrManyWithParens::One("a");
12510
12511        assert_eq!(one.deref(), &["a"]);
12512        assert_eq!(<OneOrManyWithParens<_> as Deref>::deref(&one), &["a"]);
12513
12514        assert_eq!(one[0], "a");
12515        assert_eq!(one.index(0), &"a");
12516        assert_eq!(
12517            <<OneOrManyWithParens<_> as Deref>::Target as Index<usize>>::index(&one, 0),
12518            &"a"
12519        );
12520
12521        assert_eq!(one.len(), 1);
12522        assert_eq!(<OneOrManyWithParens<_> as Deref>::Target::len(&one), 1);
12523
12524        let many1 = OneOrManyWithParens::Many(vec!["b"]);
12525
12526        assert_eq!(many1.deref(), &["b"]);
12527        assert_eq!(<OneOrManyWithParens<_> as Deref>::deref(&many1), &["b"]);
12528
12529        assert_eq!(many1[0], "b");
12530        assert_eq!(many1.index(0), &"b");
12531        assert_eq!(
12532            <<OneOrManyWithParens<_> as Deref>::Target as Index<usize>>::index(&many1, 0),
12533            &"b"
12534        );
12535
12536        assert_eq!(many1.len(), 1);
12537        assert_eq!(<OneOrManyWithParens<_> as Deref>::Target::len(&many1), 1);
12538
12539        let many2 = OneOrManyWithParens::Many(vec!["c", "d"]);
12540
12541        assert_eq!(many2.deref(), &["c", "d"]);
12542        assert_eq!(
12543            <OneOrManyWithParens<_> as Deref>::deref(&many2),
12544            &["c", "d"]
12545        );
12546
12547        assert_eq!(many2[0], "c");
12548        assert_eq!(many2.index(0), &"c");
12549        assert_eq!(
12550            <<OneOrManyWithParens<_> as Deref>::Target as Index<usize>>::index(&many2, 0),
12551            &"c"
12552        );
12553
12554        assert_eq!(many2[1], "d");
12555        assert_eq!(many2.index(1), &"d");
12556        assert_eq!(
12557            <<OneOrManyWithParens<_> as Deref>::Target as Index<usize>>::index(&many2, 1),
12558            &"d"
12559        );
12560
12561        assert_eq!(many2.len(), 2);
12562        assert_eq!(<OneOrManyWithParens<_> as Deref>::Target::len(&many2), 2);
12563    }
12564
12565    #[test]
12566    fn test_one_or_many_with_parens_as_ref() {
12567        let one = OneOrManyWithParens::One("a");
12568
12569        assert_eq!(one.as_ref(), &["a"]);
12570        assert_eq!(<OneOrManyWithParens<_> as AsRef<_>>::as_ref(&one), &["a"]);
12571
12572        let many1 = OneOrManyWithParens::Many(vec!["b"]);
12573
12574        assert_eq!(many1.as_ref(), &["b"]);
12575        assert_eq!(<OneOrManyWithParens<_> as AsRef<_>>::as_ref(&many1), &["b"]);
12576
12577        let many2 = OneOrManyWithParens::Many(vec!["c", "d"]);
12578
12579        assert_eq!(many2.as_ref(), &["c", "d"]);
12580        assert_eq!(
12581            <OneOrManyWithParens<_> as AsRef<_>>::as_ref(&many2),
12582            &["c", "d"]
12583        );
12584    }
12585
12586    #[test]
12587    fn test_one_or_many_with_parens_ref_into_iter() {
12588        let one = OneOrManyWithParens::One("a");
12589
12590        assert_eq!(Vec::from_iter(&one), vec![&"a"]);
12591
12592        let many1 = OneOrManyWithParens::Many(vec!["b"]);
12593
12594        assert_eq!(Vec::from_iter(&many1), vec![&"b"]);
12595
12596        let many2 = OneOrManyWithParens::Many(vec!["c", "d"]);
12597
12598        assert_eq!(Vec::from_iter(&many2), vec![&"c", &"d"]);
12599    }
12600
12601    #[test]
12602    fn test_one_or_many_with_parens_value_into_iter() {
12603        use core::iter::once;
12604
12605        //tests that our iterator implemented methods behaves exactly as it's inner iterator, at every step up to n calls to next/next_back
12606        fn test_steps<I>(ours: OneOrManyWithParens<usize>, inner: I, n: usize)
12607        where
12608            I: IntoIterator<Item = usize, IntoIter: DoubleEndedIterator + Clone> + Clone,
12609        {
12610            fn checks<I>(ours: OneOrManyWithParensIntoIter<usize>, inner: I)
12611            where
12612                I: Iterator<Item = usize> + Clone + DoubleEndedIterator,
12613            {
12614                assert_eq!(ours.size_hint(), inner.size_hint());
12615                assert_eq!(ours.clone().count(), inner.clone().count());
12616
12617                assert_eq!(
12618                    ours.clone().fold(1, |a, v| a + v),
12619                    inner.clone().fold(1, |a, v| a + v)
12620                );
12621
12622                assert_eq!(Vec::from_iter(ours.clone()), Vec::from_iter(inner.clone()));
12623                assert_eq!(
12624                    Vec::from_iter(ours.clone().rev()),
12625                    Vec::from_iter(inner.clone().rev())
12626                );
12627            }
12628
12629            let mut ours_next = ours.clone().into_iter();
12630            let mut inner_next = inner.clone().into_iter();
12631
12632            for _ in 0..n {
12633                checks(ours_next.clone(), inner_next.clone());
12634
12635                assert_eq!(ours_next.next(), inner_next.next());
12636            }
12637
12638            let mut ours_next_back = ours.clone().into_iter();
12639            let mut inner_next_back = inner.clone().into_iter();
12640
12641            for _ in 0..n {
12642                checks(ours_next_back.clone(), inner_next_back.clone());
12643
12644                assert_eq!(ours_next_back.next_back(), inner_next_back.next_back());
12645            }
12646
12647            let mut ours_mixed = ours.clone().into_iter();
12648            let mut inner_mixed = inner.clone().into_iter();
12649
12650            for i in 0..n {
12651                checks(ours_mixed.clone(), inner_mixed.clone());
12652
12653                if i % 2 == 0 {
12654                    assert_eq!(ours_mixed.next_back(), inner_mixed.next_back());
12655                } else {
12656                    assert_eq!(ours_mixed.next(), inner_mixed.next());
12657                }
12658            }
12659
12660            let mut ours_mixed2 = ours.into_iter();
12661            let mut inner_mixed2 = inner.into_iter();
12662
12663            for i in 0..n {
12664                checks(ours_mixed2.clone(), inner_mixed2.clone());
12665
12666                if i % 2 == 0 {
12667                    assert_eq!(ours_mixed2.next(), inner_mixed2.next());
12668                } else {
12669                    assert_eq!(ours_mixed2.next_back(), inner_mixed2.next_back());
12670                }
12671            }
12672        }
12673
12674        test_steps(OneOrManyWithParens::One(1), once(1), 3);
12675        test_steps(OneOrManyWithParens::Many(vec![2]), vec![2], 3);
12676        test_steps(OneOrManyWithParens::Many(vec![3, 4]), vec![3, 4], 4);
12677    }
12678
12679    // Tests that the position in the code of an `Ident` does not affect its
12680    // ordering.
12681    #[test]
12682    fn test_ident_ord() {
12683        let mut a = Ident::with_span(Span::new(Location::new(1, 1), Location::new(1, 1)), "a");
12684        let mut b = Ident::with_span(Span::new(Location::new(2, 2), Location::new(2, 2)), "b");
12685
12686        assert!(a < b);
12687        std::mem::swap(&mut a.span, &mut b.span);
12688        assert!(a < b);
12689    }
12690}