mod.rs - source

sqlparser/ast/

mod.rs

1// Licensed to the Apache Software Foundation (ASF) under one
2// or more contributor license agreements.  See the NOTICE file
3// distributed with this work for additional information
4// regarding copyright ownership.  The ASF licenses this file
5// to you under the Apache License, Version 2.0 (the
6// "License"); you may not use this file except in compliance
7// with the License.  You may obtain a copy of the License at
8//
9//   http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing,
12// software distributed under the License is distributed on an
13// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14// KIND, either express or implied.  See the License for the
15// specific language governing permissions and limitations
16// under the License.
17
18//! SQL Abstract Syntax Tree (AST) types
19#[cfg(not(feature = "std"))]
20use alloc::{
21    boxed::Box,
22    format,
23    string::{String, ToString},
24    vec,
25    vec::Vec,
26};
27use helpers::{
28    attached_token::AttachedToken,
29    stmt_data_loading::{FileStagingCommand, StageLoadSelectItemKind},
30};
31
32use core::cmp::Ordering;
33use core::ops::Deref;
34use core::{
35    fmt::{self, Display},
36    hash,
37};
38
39#[cfg(feature = "serde")]
40use serde::{Deserialize, Serialize};
41
42#[cfg(feature = "visitor")]
43use sqlparser_derive::{Visit, VisitMut};
44
45use crate::{
46    display_utils::SpaceOrNewline,
47    tokenizer::{Span, Token},
48};
49use crate::{
50    display_utils::{Indent, NewLine},
51    keywords::Keyword,
52};
53
54pub use self::data_type::{
55    ArrayElemTypeDef, BinaryLength, CharLengthUnits, CharacterLength, DataType, EnumMember,
56    ExactNumberInfo, IntervalFields, StructBracketKind, TimezoneInfo,
57};
58pub use self::dcl::{
59    AlterRoleOperation, CreateRole, Grant, ResetConfig, Revoke, RoleOption, SecondaryRoles,
60    SetConfigValue, Use,
61};
62pub use self::ddl::{
63    Alignment, AlterColumnOperation, AlterConnectorOwner, AlterIndexOperation, AlterOperator,
64    AlterOperatorClass, AlterOperatorClassOperation, AlterOperatorFamily,
65    AlterOperatorFamilyOperation, AlterOperatorOperation, AlterPolicy, AlterPolicyOperation,
66    AlterSchema, AlterSchemaOperation, AlterTable, AlterTableAlgorithm, AlterTableLock,
67    AlterTableOperation, AlterTableType, AlterType, AlterTypeAddValue, AlterTypeAddValuePosition,
68    AlterTypeOperation, AlterTypeRename, AlterTypeRenameValue, ClusteredBy, ColumnDef,
69    ColumnOption, ColumnOptionDef, ColumnOptions, ColumnPolicy, ColumnPolicyProperty,
70    ConstraintCharacteristics, CreateConnector, CreateDomain, CreateExtension, CreateFunction,
71    CreateIndex, CreateOperator, CreateOperatorClass, CreateOperatorFamily, CreatePolicy,
72    CreatePolicyCommand, CreatePolicyType, CreateTable, CreateTrigger, CreateView, Deduplicate,
73    DeferrableInitial, DropBehavior, DropExtension, DropFunction, DropOperator, DropOperatorClass,
74    DropOperatorFamily, DropOperatorSignature, DropPolicy, DropTrigger, ForValues, GeneratedAs,
75    GeneratedExpressionMode, IdentityParameters, IdentityProperty, IdentityPropertyFormatKind,
76    IdentityPropertyKind, IdentityPropertyOrder, IndexColumn, IndexOption, IndexType,
77    KeyOrIndexDisplay, Msck, NullsDistinctOption, OperatorArgTypes, OperatorClassItem,
78    OperatorFamilyDropItem, OperatorFamilyItem, OperatorOption, OperatorPurpose, Owner, Partition,
79    PartitionBoundValue, ProcedureParam, ReferentialAction, RenameTableNameKind, ReplicaIdentity,
80    TagsColumnOption, TriggerObjectKind, Truncate, UserDefinedTypeCompositeAttributeDef,
81    UserDefinedTypeInternalLength, UserDefinedTypeRangeOption, UserDefinedTypeRepresentation,
82    UserDefinedTypeSqlDefinitionOption, UserDefinedTypeStorage, ViewColumnDef,
83};
84pub use self::dml::{
85    Delete, Insert, Merge, MergeAction, MergeClause, MergeClauseKind, MergeInsertExpr,
86    MergeInsertKind, MergeUpdateExpr, OutputClause, Update,
87};
88pub use self::operator::{BinaryOperator, UnaryOperator};
89pub use self::query::{
90    AfterMatchSkip, ConnectByKind, Cte, CteAsMaterialized, Distinct, EmptyMatchesMode,
91    ExceptSelectItem, ExcludeSelectItem, ExprWithAlias, ExprWithAliasAndOrderBy, Fetch, ForClause,
92    ForJson, ForXml, FormatClause, GroupByExpr, GroupByWithModifier, IdentWithAlias,
93    IlikeSelectItem, InputFormatClause, Interpolate, InterpolateExpr, Join, JoinConstraint,
94    JoinOperator, JsonTableColumn, JsonTableColumnErrorHandling, JsonTableNamedColumn,
95    JsonTableNestedColumn, LateralView, LimitClause, LockClause, LockType, MatchRecognizePattern,
96    MatchRecognizeSymbol, Measure, NamedWindowDefinition, NamedWindowExpr, NonBlock, Offset,
97    OffsetRows, OpenJsonTableColumn, OrderBy, OrderByExpr, OrderByKind, OrderByOptions,
98    PipeOperator, PivotValueSource, ProjectionSelect, Query, RenameSelectItem,
99    RepetitionQuantifier, ReplaceSelectElement, ReplaceSelectItem, RowsPerMatch, Select,
100    SelectFlavor, SelectInto, SelectItem, SelectItemQualifiedWildcardKind, SelectModifiers,
101    SetExpr, SetOperator, SetQuantifier, Setting, SymbolDefinition, Table, TableAlias,
102    TableAliasColumnDef, TableFactor, TableFunctionArgs, TableIndexHintForClause,
103    TableIndexHintType, TableIndexHints, TableIndexType, TableSample, TableSampleBucket,
104    TableSampleKind, TableSampleMethod, TableSampleModifier, TableSampleQuantity, TableSampleSeed,
105    TableSampleSeedModifier, TableSampleUnit, TableVersion, TableWithJoins, Top, TopQuantity,
106    UpdateTableFromKind, ValueTableMode, Values, WildcardAdditionalOptions, With, WithFill,
107    XmlNamespaceDefinition, XmlPassingArgument, XmlPassingClause, XmlTableColumn,
108    XmlTableColumnOption,
109};
110
111pub use self::trigger::{
112    TriggerEvent, TriggerExecBody, TriggerExecBodyType, TriggerObject, TriggerPeriod,
113    TriggerReferencing, TriggerReferencingType,
114};
115
116pub use self::value::{
117    escape_double_quote_string, escape_quoted_string, DateTimeField, DollarQuotedString,
118    NormalizationForm, QuoteDelimitedString, TrimWhereField, Value, ValueWithSpan,
119};
120
121use crate::ast::helpers::key_value_options::KeyValueOptions;
122use crate::ast::helpers::stmt_data_loading::StageParamsObject;
123
124#[cfg(feature = "visitor")]
125pub use visitor::*;
126
127pub use self::data_type::GeometricTypeKind;
128
129mod data_type;
130mod dcl;
131mod ddl;
132mod dml;
133/// Helper modules for building and manipulating AST nodes.
134pub mod helpers;
135pub mod table_constraints;
136pub use table_constraints::{
137    CheckConstraint, ForeignKeyConstraint, FullTextOrSpatialConstraint, IndexConstraint,
138    PrimaryKeyConstraint, TableConstraint, UniqueConstraint,
139};
140mod operator;
141mod query;
142mod spans;
143pub use spans::Spanned;
144
145pub mod comments;
146mod trigger;
147mod value;
148
149#[cfg(feature = "visitor")]
150mod visitor;
151
152/// Helper used to format a slice using a separator string (e.g., `", "`).
153pub struct DisplaySeparated<'a, T>
154where
155    T: fmt::Display,
156{
157    slice: &'a [T],
158    sep: &'static str,
159}
160
161impl<T> fmt::Display for DisplaySeparated<'_, T>
162where
163    T: fmt::Display,
164{
165    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
166        let mut delim = "";
167        for t in self.slice {
168            f.write_str(delim)?;
169            delim = self.sep;
170            t.fmt(f)?;
171        }
172        Ok(())
173    }
174}
175
176pub(crate) fn display_separated<'a, T>(slice: &'a [T], sep: &'static str) -> DisplaySeparated<'a, T>
177where
178    T: fmt::Display,
179{
180    DisplaySeparated { slice, sep }
181}
182
183pub(crate) fn display_comma_separated<T>(slice: &[T]) -> DisplaySeparated<'_, T>
184where
185    T: fmt::Display,
186{
187    DisplaySeparated { slice, sep: ", " }
188}
189
190/// Writes the given statements to the formatter, each ending with
191/// a semicolon and space separated.
192fn format_statement_list(f: &mut fmt::Formatter, statements: &[Statement]) -> fmt::Result {
193    write!(f, "{}", display_separated(statements, "; "))?;
194    // We manually insert semicolon for the last statement,
195    // since display_separated doesn't handle that case.
196    write!(f, ";")
197}
198
199/// An identifier, decomposed into its value or character data and the quote style.
200#[derive(Debug, Clone)]
201#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
202#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
203pub struct Ident {
204    /// The value of the identifier without quotes.
205    pub value: String,
206    /// The starting quote if any. Valid quote characters are the single quote,
207    /// double quote, backtick, and opening square bracket.
208    pub quote_style: Option<char>,
209    /// The span of the identifier in the original SQL string.
210    pub span: Span,
211}
212
213impl PartialEq for Ident {
214    fn eq(&self, other: &Self) -> bool {
215        let Ident {
216            value,
217            quote_style,
218            // exhaustiveness check; we ignore spans in comparisons
219            span: _,
220        } = self;
221
222        value == &other.value && quote_style == &other.quote_style
223    }
224}
225
226impl core::hash::Hash for Ident {
227    fn hash<H: hash::Hasher>(&self, state: &mut H) {
228        let Ident {
229            value,
230            quote_style,
231            // exhaustiveness check; we ignore spans in hashes
232            span: _,
233        } = self;
234
235        value.hash(state);
236        quote_style.hash(state);
237    }
238}
239
240impl Eq for Ident {}
241
242impl PartialOrd for Ident {
243    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
244        Some(self.cmp(other))
245    }
246}
247
248impl Ord for Ident {
249    fn cmp(&self, other: &Self) -> Ordering {
250        let Ident {
251            value,
252            quote_style,
253            // exhaustiveness check; we ignore spans in ordering
254            span: _,
255        } = self;
256
257        let Ident {
258            value: other_value,
259            quote_style: other_quote_style,
260            // exhaustiveness check; we ignore spans in ordering
261            span: _,
262        } = other;
263
264        // First compare by value, then by quote_style
265        value
266            .cmp(other_value)
267            .then_with(|| quote_style.cmp(other_quote_style))
268    }
269}
270
271impl Ident {
272    /// Create a new identifier with the given value and no quotes and an empty span.
273    pub fn new<S>(value: S) -> Self
274    where
275        S: Into<String>,
276    {
277        Ident {
278            value: value.into(),
279            quote_style: None,
280            span: Span::empty(),
281        }
282    }
283
284    /// Create a new quoted identifier with the given quote and value. This function
285    /// panics if the given quote is not a valid quote character.
286    pub fn with_quote<S>(quote: char, value: S) -> Self
287    where
288        S: Into<String>,
289    {
290        assert!(quote == '\'' || quote == '"' || quote == '`' || quote == '[');
291        Ident {
292            value: value.into(),
293            quote_style: Some(quote),
294            span: Span::empty(),
295        }
296    }
297
298    /// Create an `Ident` with the given `span` and `value` (unquoted).
299    pub fn with_span<S>(span: Span, value: S) -> Self
300    where
301        S: Into<String>,
302    {
303        Ident {
304            value: value.into(),
305            quote_style: None,
306            span,
307        }
308    }
309
310    /// Create a quoted `Ident` with the given `quote` and `span`.
311    pub fn with_quote_and_span<S>(quote: char, span: Span, value: S) -> Self
312    where
313        S: Into<String>,
314    {
315        assert!(quote == '\'' || quote == '"' || quote == '`' || quote == '[');
316        Ident {
317            value: value.into(),
318            quote_style: Some(quote),
319            span,
320        }
321    }
322}
323
324impl From<&str> for Ident {
325    fn from(value: &str) -> Self {
326        Ident {
327            value: value.to_string(),
328            quote_style: None,
329            span: Span::empty(),
330        }
331    }
332}
333
334impl fmt::Display for Ident {
335    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
336        match self.quote_style {
337            Some(q) if q == '"' || q == '\'' || q == '`' => {
338                let escaped = value::escape_quoted_string(&self.value, q);
339                write!(f, "{q}{escaped}{q}")
340            }
341            Some('[') => write!(f, "[{}]", self.value),
342            None => f.write_str(&self.value),
343            _ => panic!("unexpected quote style"),
344        }
345    }
346}
347
348/// A name of a table, view, custom type, etc., possibly multi-part, i.e. db.schema.obj
349#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
350#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
351#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
352pub struct ObjectName(pub Vec<ObjectNamePart>);
353
354impl From<Vec<Ident>> for ObjectName {
355    fn from(idents: Vec<Ident>) -> Self {
356        ObjectName(idents.into_iter().map(ObjectNamePart::Identifier).collect())
357    }
358}
359
360impl From<Ident> for ObjectName {
361    fn from(ident: Ident) -> Self {
362        ObjectName(vec![ObjectNamePart::Identifier(ident)])
363    }
364}
365
366impl fmt::Display for ObjectName {
367    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
368        write!(f, "{}", display_separated(&self.0, "."))
369    }
370}
371
372/// A single part of an ObjectName
373#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
374#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
375#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
376pub enum ObjectNamePart {
377    /// A single identifier part, e.g. `schema` or `table`.
378    Identifier(Ident),
379    /// A function that returns an identifier (dialect-specific).
380    Function(ObjectNamePartFunction),
381}
382
383impl ObjectNamePart {
384    /// Return the identifier if this is an `Identifier` variant.
385    pub fn as_ident(&self) -> Option<&Ident> {
386        match self {
387            ObjectNamePart::Identifier(ident) => Some(ident),
388            ObjectNamePart::Function(_) => None,
389        }
390    }
391}
392
393impl fmt::Display for ObjectNamePart {
394    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
395        match self {
396            ObjectNamePart::Identifier(ident) => write!(f, "{ident}"),
397            ObjectNamePart::Function(func) => write!(f, "{func}"),
398        }
399    }
400}
401
402/// An object name part that consists of a function that dynamically
403/// constructs identifiers.
404///
405/// - [Snowflake](https://docs.snowflake.com/en/sql-reference/identifier-literal)
406#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
407#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
408#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
409pub struct ObjectNamePartFunction {
410    /// The function name that produces the object name part.
411    pub name: Ident,
412    /// Function arguments used to compute the identifier.
413    pub args: Vec<FunctionArg>,
414}
415
416impl fmt::Display for ObjectNamePartFunction {
417    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
418        write!(f, "{}(", self.name)?;
419        write!(f, "{})", display_comma_separated(&self.args))
420    }
421}
422
423/// Represents an Array Expression, either
424/// `ARRAY[..]`, or `[..]`
425#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
426#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
427#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
428pub struct Array {
429    /// The list of expressions between brackets
430    pub elem: Vec<Expr>,
431
432    /// `true` for  `ARRAY[..]`, `false` for `[..]`
433    pub named: bool,
434}
435
436impl fmt::Display for Array {
437    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
438        write!(
439            f,
440            "{}[{}]",
441            if self.named { "ARRAY" } else { "" },
442            display_comma_separated(&self.elem)
443        )
444    }
445}
446
447/// Represents an INTERVAL expression, roughly in the following format:
448/// `INTERVAL '<value>' [ <leading_field> [ (<leading_precision>) ] ]
449/// [ TO <last_field> [ (<fractional_seconds_precision>) ] ]`,
450/// e.g. `INTERVAL '123:45.67' MINUTE(3) TO SECOND(2)`.
451///
452/// The parser does not validate the `<value>`, nor does it ensure
453/// that the `<leading_field>` units >= the units in `<last_field>`,
454/// so the user will have to reject intervals like `HOUR TO YEAR`.
455#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
456#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
457#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
458pub struct Interval {
459    /// The interval value expression (commonly a string literal).
460    pub value: Box<Expr>,
461    /// Optional leading time unit (e.g., `HOUR`, `MINUTE`).
462    pub leading_field: Option<DateTimeField>,
463    /// Optional leading precision for the leading field.
464    pub leading_precision: Option<u64>,
465    /// Optional trailing time unit for a range (e.g., `SECOND`).
466    pub last_field: Option<DateTimeField>,
467    /// The fractional seconds precision, when specified.
468    ///
469    /// See SQL `SECOND(n)` or `SECOND(m, n)` forms.
470    pub fractional_seconds_precision: Option<u64>,
471}
472
473impl fmt::Display for Interval {
474    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
475        let value = self.value.as_ref();
476        match (
477            &self.leading_field,
478            self.leading_precision,
479            self.fractional_seconds_precision,
480        ) {
481            (
482                Some(DateTimeField::Second),
483                Some(leading_precision),
484                Some(fractional_seconds_precision),
485            ) => {
486                // When the leading field is SECOND, the parser guarantees that
487                // the last field is None.
488                assert!(self.last_field.is_none());
489                write!(
490                    f,
491                    "INTERVAL {value} SECOND ({leading_precision}, {fractional_seconds_precision})"
492                )
493            }
494            _ => {
495                write!(f, "INTERVAL {value}")?;
496                if let Some(leading_field) = &self.leading_field {
497                    write!(f, " {leading_field}")?;
498                }
499                if let Some(leading_precision) = self.leading_precision {
500                    write!(f, " ({leading_precision})")?;
501                }
502                if let Some(last_field) = &self.last_field {
503                    write!(f, " TO {last_field}")?;
504                }
505                if let Some(fractional_seconds_precision) = self.fractional_seconds_precision {
506                    write!(f, " ({fractional_seconds_precision})")?;
507                }
508                Ok(())
509            }
510        }
511    }
512}
513
514/// A field definition within a struct
515///
516/// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-types#struct_type
517#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
518#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
519#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
520pub struct StructField {
521    /// Optional name of the struct field.
522    pub field_name: Option<Ident>,
523    /// The field data type.
524    pub field_type: DataType,
525    /// Struct field options (e.g., `OPTIONS(...)` on BigQuery).
526    /// See [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#column_name_and_column_schema)
527    pub options: Option<Vec<SqlOption>>,
528}
529
530impl fmt::Display for StructField {
531    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
532        if let Some(name) = &self.field_name {
533            write!(f, "{name} {}", self.field_type)?;
534        } else {
535            write!(f, "{}", self.field_type)?;
536        }
537        if let Some(options) = &self.options {
538            write!(f, " OPTIONS({})", display_separated(options, ", "))
539        } else {
540            Ok(())
541        }
542    }
543}
544
545/// A field definition within a union
546///
547/// [DuckDB]: https://duckdb.org/docs/sql/data_types/union.html
548#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
549#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
550#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
551pub struct UnionField {
552    /// Name of the union field.
553    pub field_name: Ident,
554    /// Type of the union field.
555    pub field_type: DataType,
556}
557
558impl fmt::Display for UnionField {
559    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
560        write!(f, "{} {}", self.field_name, self.field_type)
561    }
562}
563
564/// A dictionary field within a dictionary.
565///
566/// [DuckDB]: https://duckdb.org/docs/sql/data_types/struct#creating-structs
567#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
568#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
569#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
570pub struct DictionaryField {
571    /// Dictionary key identifier.
572    pub key: Ident,
573    /// Value expression for the dictionary entry.
574    pub value: Box<Expr>,
575}
576
577impl fmt::Display for DictionaryField {
578    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
579        write!(f, "{}: {}", self.key, self.value)
580    }
581}
582
583/// Represents a Map expression.
584#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
585#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
586#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
587pub struct Map {
588    /// Entries of the map as key/value pairs.
589    pub entries: Vec<MapEntry>,
590}
591
592impl Display for Map {
593    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
594        write!(f, "MAP {{{}}}", display_comma_separated(&self.entries))
595    }
596}
597
598/// A map field within a map.
599///
600/// [DuckDB]: https://duckdb.org/docs/sql/data_types/map.html#creating-maps
601#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
602#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
603#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
604pub struct MapEntry {
605    /// Key expression of the map entry.
606    pub key: Box<Expr>,
607    /// Value expression of the map entry.
608    pub value: Box<Expr>,
609}
610
611impl fmt::Display for MapEntry {
612    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
613        write!(f, "{}: {}", self.key, self.value)
614    }
615}
616
617/// Options for `CAST` / `TRY_CAST`
618/// BigQuery: <https://cloud.google.com/bigquery/docs/reference/standard-sql/format-elements#formatting_syntax>
619#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
620#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
621#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
622pub enum CastFormat {
623    /// A simple cast format specified by a `Value`.
624    Value(Value),
625    /// A cast format with an explicit time zone: `(format, timezone)`.
626    ValueAtTimeZone(Value, Value),
627}
628
629/// An element of a JSON path.
630#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
631#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
632#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
633pub enum JsonPathElem {
634    /// Accesses an object field using dot notation, e.g. `obj:foo.bar.baz`.
635    ///
636    /// See <https://docs.snowflake.com/en/user-guide/querying-semistructured#dot-notation>.
637    Dot {
638        /// The object key text (without quotes).
639        key: String,
640        /// `true` when the key was quoted in the source.
641        quoted: bool,
642    },
643    /// Accesses an object field or array element using bracket notation,
644    /// e.g. `obj['foo']`.
645    ///
646    /// See <https://docs.snowflake.com/en/user-guide/querying-semistructured#bracket-notation>.
647    Bracket {
648        /// The expression used as the bracket key (string or numeric expression).
649        key: Expr,
650    },
651}
652
653/// A JSON path.
654///
655/// See <https://docs.snowflake.com/en/user-guide/querying-semistructured>.
656/// See <https://docs.databricks.com/en/sql/language-manual/sql-ref-json-path-expression.html>.
657#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
658#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
659#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
660pub struct JsonPath {
661    /// Sequence of path elements that form the JSON path.
662    pub path: Vec<JsonPathElem>,
663}
664
665impl fmt::Display for JsonPath {
666    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
667        for (i, elem) in self.path.iter().enumerate() {
668            match elem {
669                JsonPathElem::Dot { key, quoted } => {
670                    if i == 0 {
671                        write!(f, ":")?;
672                    } else {
673                        write!(f, ".")?;
674                    }
675
676                    if *quoted {
677                        write!(f, "\"{}\"", escape_double_quote_string(key))?;
678                    } else {
679                        write!(f, "{key}")?;
680                    }
681                }
682                JsonPathElem::Bracket { key } => {
683                    write!(f, "[{key}]")?;
684                }
685            }
686        }
687        Ok(())
688    }
689}
690
691/// The syntax used for in a cast expression.
692#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
693#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
694#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
695pub enum CastKind {
696    /// The standard SQL cast syntax, e.g. `CAST(<expr> as <datatype>)`
697    Cast,
698    /// A cast that returns `NULL` on failure, e.g. `TRY_CAST(<expr> as <datatype>)`.
699    ///
700    /// See <https://docs.snowflake.com/en/sql-reference/functions/try_cast>.
701    /// See <https://learn.microsoft.com/en-us/sql/t-sql/functions/try-cast-transact-sql>.
702    TryCast,
703    /// A cast that returns `NULL` on failure, bigQuery-specific ,  e.g. `SAFE_CAST(<expr> as <datatype>)`.
704    ///
705    /// See <https://cloud.google.com/bigquery/docs/reference/standard-sql/functions-and-operators#safe_casting>.
706    SafeCast,
707    /// `<expr> :: <datatype>`
708    DoubleColon,
709}
710
711/// `MATCH` type for constraint references
712///
713/// See: <https://www.postgresql.org/docs/current/sql-createtable.html#SQL-CREATETABLE-PARMS-REFERENCES>
714#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
715#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
716#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
717pub enum ConstraintReferenceMatchKind {
718    /// `MATCH FULL`
719    Full,
720    /// `MATCH PARTIAL`
721    Partial,
722    /// `MATCH SIMPLE`
723    Simple,
724}
725
726impl fmt::Display for ConstraintReferenceMatchKind {
727    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
728        match self {
729            Self::Full => write!(f, "MATCH FULL"),
730            Self::Partial => write!(f, "MATCH PARTIAL"),
731            Self::Simple => write!(f, "MATCH SIMPLE"),
732        }
733    }
734}
735
736/// `EXTRACT` syntax variants.
737///
738/// In Snowflake dialect, the `EXTRACT` expression can support either the `from` syntax
739/// or the comma syntax.
740///
741/// See <https://docs.snowflake.com/en/sql-reference/functions/extract>
742#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
743#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
744#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
745pub enum ExtractSyntax {
746    /// `EXTRACT( <date_or_time_part> FROM <date_or_time_expr> )`
747    From,
748    /// `EXTRACT( <date_or_time_part> , <date_or_timestamp_expr> )`
749    Comma,
750}
751
752/// The syntax used in a CEIL or FLOOR expression.
753///
754/// The `CEIL/FLOOR(<datetime value expression> TO <time unit>)` is an Amazon Kinesis Data Analytics extension.
755/// See <https://docs.aws.amazon.com/kinesisanalytics/latest/sqlref/sql-reference-ceil.html> for
756/// details.
757///
758/// Other dialects either support `CEIL/FLOOR( <expr> [, <scale>])` format or just
759/// `CEIL/FLOOR(<expr>)`.
760#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
761#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
762#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
763pub enum CeilFloorKind {
764    /// `CEIL( <expr> TO <DateTimeField>)`
765    DateTimeField(DateTimeField),
766    /// `CEIL( <expr> [, <scale>])`
767    Scale(Value),
768}
769
770/// A WHEN clause in a CASE expression containing both
771/// the condition and its corresponding result
772#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
773#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
774#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
775pub struct CaseWhen {
776    /// The `WHEN` condition expression.
777    pub condition: Expr,
778    /// The expression returned when `condition` matches.
779    pub result: Expr,
780}
781
782impl fmt::Display for CaseWhen {
783    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
784        f.write_str("WHEN ")?;
785        self.condition.fmt(f)?;
786        f.write_str(" THEN")?;
787        SpaceOrNewline.fmt(f)?;
788        Indent(&self.result).fmt(f)?;
789        Ok(())
790    }
791}
792
793/// An SQL expression of any type.
794///
795/// # Semantics / Type Checking
796///
797/// The parser does not distinguish between expressions of different types
798/// (e.g. boolean vs string). The caller is responsible for detecting and
799/// validating types as necessary (for example  `WHERE 1` vs `SELECT 1=1`)
800/// See the [README.md] for more details.
801///
802/// [README.md]: https://github.com/apache/datafusion-sqlparser-rs/blob/main/README.md#syntax-vs-semantics
803///
804/// # Equality and Hashing Does not Include Source Locations
805///
806/// The `Expr` type implements `PartialEq` and `Eq` based on the semantic value
807/// of the expression (not bitwise comparison). This means that `Expr` instances
808/// that are semantically equivalent but have different spans (locations in the
809/// source tree) will compare as equal.
810#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
811#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
812#[cfg_attr(
813    feature = "visitor",
814    derive(Visit, VisitMut),
815    visit(with = "visit_expr")
816)]
817pub enum Expr {
818    /// Identifier e.g. table name or column name
819    Identifier(Ident),
820    /// Multi-part identifier, e.g. `table_alias.column` or `schema.table.col`
821    CompoundIdentifier(Vec<Ident>),
822    /// Multi-part expression access.
823    ///
824    /// This structure represents an access chain in structured / nested types
825    /// such as maps, arrays, and lists:
826    /// - Array
827    ///     - A 1-dim array `a[1]` will be represented like:
828    ///       `CompoundFieldAccess(Ident('a'), vec![Subscript(1)]`
829    ///     - A 2-dim array `a[1][2]` will be represented like:
830    ///       `CompoundFieldAccess(Ident('a'), vec![Subscript(1), Subscript(2)]`
831    /// - Map or Struct (Bracket-style)
832    ///     - A map `a['field1']` will be represented like:
833    ///       `CompoundFieldAccess(Ident('a'), vec![Subscript('field')]`
834    ///     - A 2-dim map `a['field1']['field2']` will be represented like:
835    ///       `CompoundFieldAccess(Ident('a'), vec![Subscript('field1'), Subscript('field2')]`
836    /// - Struct (Dot-style) (only effect when the chain contains both subscript and expr)
837    ///     - A struct access `a[field1].field2` will be represented like:
838    ///       `CompoundFieldAccess(Ident('a'), vec![Subscript('field1'), Ident('field2')]`
839    /// - If a struct access likes `a.field1.field2`, it will be represented by CompoundIdentifier([a, field1, field2])
840    CompoundFieldAccess {
841        /// The base expression being accessed.
842        root: Box<Expr>,
843        /// Sequence of access operations (subscript or identifier accesses).
844        access_chain: Vec<AccessExpr>,
845    },
846    /// Access data nested in a value containing semi-structured data, such as
847    /// the `VARIANT` type on Snowflake. for example `src:customer[0].name`.
848    ///
849    /// See <https://docs.snowflake.com/en/user-guide/querying-semistructured>.
850    /// See <https://docs.databricks.com/en/sql/language-manual/functions/colonsign.html>.
851    JsonAccess {
852        /// The value being queried.
853        value: Box<Expr>,
854        /// The path to the data to extract.
855        path: JsonPath,
856    },
857    /// `IS FALSE` operator
858    IsFalse(Box<Expr>),
859    /// `IS NOT FALSE` operator
860    IsNotFalse(Box<Expr>),
861    /// `IS TRUE` operator
862    IsTrue(Box<Expr>),
863    /// `IS NOT TRUE` operator
864    IsNotTrue(Box<Expr>),
865    /// `IS NULL` operator
866    IsNull(Box<Expr>),
867    /// `IS NOT NULL` operator
868    IsNotNull(Box<Expr>),
869    /// `IS UNKNOWN` operator
870    IsUnknown(Box<Expr>),
871    /// `IS NOT UNKNOWN` operator
872    IsNotUnknown(Box<Expr>),
873    /// `IS DISTINCT FROM` operator
874    IsDistinctFrom(Box<Expr>, Box<Expr>),
875    /// `IS NOT DISTINCT FROM` operator
876    IsNotDistinctFrom(Box<Expr>, Box<Expr>),
877    /// `<expr> IS [ NOT ] [ form ] NORMALIZED`
878    IsNormalized {
879        /// Expression being tested.
880        expr: Box<Expr>,
881        /// Optional normalization `form` (e.g., NFC, NFD).
882        form: Option<NormalizationForm>,
883        /// `true` when `NOT` is present.
884        negated: bool,
885    },
886    /// `[ NOT ] IN (val1, val2, ...)`
887    InList {
888        /// Left-hand expression to test for membership.
889        expr: Box<Expr>,
890        /// Literal list of expressions to check against.
891        list: Vec<Expr>,
892        /// `true` when the `NOT` modifier is present.
893        negated: bool,
894    },
895    /// `[ NOT ] IN (SELECT ...)`
896    InSubquery {
897        /// Left-hand expression to test for membership.
898        expr: Box<Expr>,
899        /// The subquery providing the candidate values.
900        subquery: Box<Query>,
901        /// `true` when the `NOT` modifier is present.
902        negated: bool,
903    },
904    /// `[ NOT ] IN UNNEST(array_expression)`
905    InUnnest {
906        /// Left-hand expression to test for membership.
907        expr: Box<Expr>,
908        /// Array expression being unnested.
909        array_expr: Box<Expr>,
910        /// `true` when the `NOT` modifier is present.
911        negated: bool,
912    },
913    /// `<expr> [ NOT ] BETWEEN <low> AND <high>`
914    Between {
915        /// Expression being compared.
916        expr: Box<Expr>,
917        /// `true` when the `NOT` modifier is present.
918        negated: bool,
919        /// Lower bound.
920        low: Box<Expr>,
921        /// Upper bound.
922        high: Box<Expr>,
923    },
924    /// Binary operation e.g. `1 + 1` or `foo > bar`
925    BinaryOp {
926        /// Left operand.
927        left: Box<Expr>,
928        /// Operator between operands.
929        op: BinaryOperator,
930        /// Right operand.
931        right: Box<Expr>,
932    },
933    /// `[NOT] LIKE <pattern> [ESCAPE <escape_character>]`
934    Like {
935        /// `true` when `NOT` is present.
936        negated: bool,
937        /// Snowflake supports the ANY keyword to match against a list of patterns
938        /// <https://docs.snowflake.com/en/sql-reference/functions/like_any>
939        any: bool,
940        /// Expression to match.
941        expr: Box<Expr>,
942        /// Pattern expression.
943        pattern: Box<Expr>,
944        /// Optional escape character.
945        escape_char: Option<Value>,
946    },
947    /// `ILIKE` (case-insensitive `LIKE`)
948    ILike {
949        /// `true` when `NOT` is present.
950        negated: bool,
951        /// Snowflake supports the ANY keyword to match against a list of patterns
952        /// <https://docs.snowflake.com/en/sql-reference/functions/like_any>
953        any: bool,
954        /// Expression to match.
955        expr: Box<Expr>,
956        /// Pattern expression.
957        pattern: Box<Expr>,
958        /// Optional escape character.
959        escape_char: Option<Value>,
960    },
961    /// `SIMILAR TO` regex
962    SimilarTo {
963        /// `true` when `NOT` is present.
964        negated: bool,
965        /// Expression to test.
966        expr: Box<Expr>,
967        /// Pattern expression.
968        pattern: Box<Expr>,
969        /// Optional escape character.
970        escape_char: Option<Value>,
971    },
972    /// MySQL: `RLIKE` regex or `REGEXP` regex
973    RLike {
974        /// `true` when `NOT` is present.
975        negated: bool,
976        /// Expression to test.
977        expr: Box<Expr>,
978        /// Pattern expression.
979        pattern: Box<Expr>,
980        /// true for REGEXP, false for RLIKE (no difference in semantics)
981        regexp: bool,
982    },
983    /// `ANY` operation e.g. `foo > ANY(bar)`, comparison operator is one of `[=, >, <, =>, =<, !=]`
984    /// <https://docs.snowflake.com/en/sql-reference/operators-subquery#all-any>
985    AnyOp {
986        /// Left operand.
987        left: Box<Expr>,
988        /// Comparison operator.
989        compare_op: BinaryOperator,
990        /// Right-hand subquery expression.
991        right: Box<Expr>,
992        /// ANY and SOME are synonymous: <https://docs.cloudera.com/cdw-runtime/cloud/using-hiveql/topics/hive_comparison_predicates.html>
993        is_some: bool,
994    },
995    /// `ALL` operation e.g. `foo > ALL(bar)`, comparison operator is one of `[=, >, <, =>, =<, !=]`
996    /// <https://docs.snowflake.com/en/sql-reference/operators-subquery#all-any>
997    AllOp {
998        /// Left operand.
999        left: Box<Expr>,
1000        /// Comparison operator.
1001        compare_op: BinaryOperator,
1002        /// Right-hand subquery expression.
1003        right: Box<Expr>,
1004    },
1005
1006    /// Unary operation e.g. `NOT foo`
1007    UnaryOp {
1008        /// The unary operator (e.g., `NOT`, `-`).
1009        op: UnaryOperator,
1010        /// Operand expression.
1011        expr: Box<Expr>,
1012    },
1013    /// CONVERT a value to a different data type or character encoding. e.g. `CONVERT(foo USING utf8mb4)`
1014    Convert {
1015        /// CONVERT (false) or TRY_CONVERT (true)
1016        /// <https://learn.microsoft.com/en-us/sql/t-sql/functions/try-convert-transact-sql?view=sql-server-ver16>
1017        is_try: bool,
1018        /// The expression to convert.
1019        expr: Box<Expr>,
1020        /// The target data type, if provided.
1021        data_type: Option<DataType>,
1022        /// Optional target character encoding (e.g., `utf8mb4`).
1023        charset: Option<ObjectName>,
1024        /// `true` when target precedes the value (MSSQL syntax).
1025        target_before_value: bool,
1026        /// How to translate the expression.
1027        ///
1028        /// [MSSQL]: https://learn.microsoft.com/en-us/sql/t-sql/functions/cast-and-convert-transact-sql?view=sql-server-ver16#style
1029        styles: Vec<Expr>,
1030    },
1031    /// `CAST` an expression to a different data type e.g. `CAST(foo AS VARCHAR(123))`
1032    Cast {
1033        /// The cast kind (e.g., `CAST`, `TRY_CAST`).
1034        kind: CastKind,
1035        /// Expression being cast.
1036        expr: Box<Expr>,
1037        /// Target data type.
1038        data_type: DataType,
1039        /// [MySQL] allows CAST(... AS type ARRAY) in functional index definitions for InnoDB
1040        /// multi-valued indices. It's not really a datatype, and is only allowed in `CAST` in key
1041        /// specifications, so it's a flag here.
1042        ///
1043        /// [MySQL]: https://dev.mysql.com/doc/refman/8.4/en/cast-functions.html#function_cast
1044        array: bool,
1045        /// Optional CAST(string_expression AS type FORMAT format_string_expression) as used by [BigQuery]
1046        ///
1047        /// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/format-elements#formatting_syntax
1048        format: Option<CastFormat>,
1049    },
1050    /// AT a timestamp to a different timezone e.g. `FROM_UNIXTIME(0) AT TIME ZONE 'UTC-06:00'`
1051    AtTimeZone {
1052        /// Timestamp expression to shift.
1053        timestamp: Box<Expr>,
1054        /// Time zone expression to apply.
1055        time_zone: Box<Expr>,
1056    },
1057    /// Extract a field from a timestamp e.g. `EXTRACT(MONTH FROM foo)`
1058    /// Or `EXTRACT(MONTH, foo)`
1059    ///
1060    /// Syntax:
1061    /// ```sql
1062    /// EXTRACT(DateTimeField FROM <expr>) | EXTRACT(DateTimeField, <expr>)
1063    /// ```
1064    Extract {
1065        /// Which datetime field is being extracted.
1066        field: DateTimeField,
1067        /// Syntax variant used (`From` or `Comma`).
1068        syntax: ExtractSyntax,
1069        /// Expression to extract from.
1070        expr: Box<Expr>,
1071    },
1072    /// ```sql
1073    /// CEIL(<expr> [TO DateTimeField])
1074    /// ```
1075    /// ```sql
1076    /// CEIL( <input_expr> [, <scale_expr> ] )
1077    /// ```
1078    Ceil {
1079        /// Expression to ceil.
1080        expr: Box<Expr>,
1081        /// The CEIL/FLOOR kind (datetime field or scale).
1082        field: CeilFloorKind,
1083    },
1084    /// ```sql
1085    /// FLOOR(<expr> [TO DateTimeField])
1086    /// ```
1087    /// ```sql
1088    /// FLOOR( <input_expr> [, <scale_expr> ] )
1089    ///
1090    Floor {
1091        /// Expression to floor.
1092        expr: Box<Expr>,
1093        /// The CEIL/FLOOR kind (datetime field or scale).
1094        field: CeilFloorKind,
1095    },
1096    /// ```sql
1097    /// POSITION(<expr> in <expr>)
1098    /// ```
1099    Position {
1100        /// Expression to search for.
1101        expr: Box<Expr>,
1102        /// Expression to search in.
1103        r#in: Box<Expr>,
1104    },
1105    /// ```sql
1106    /// SUBSTRING(<expr> [FROM <expr>] [FOR <expr>])
1107    /// ```
1108    /// or
1109    /// ```sql
1110    /// SUBSTRING(<expr>, <expr>, <expr>)
1111    /// ```
1112    Substring {
1113        /// Source expression.
1114        expr: Box<Expr>,
1115        /// Optional `FROM` expression.
1116        substring_from: Option<Box<Expr>>,
1117        /// Optional `FOR` expression.
1118        substring_for: Option<Box<Expr>>,
1119
1120        /// false if the expression is represented using the `SUBSTRING(expr [FROM start] [FOR len])` syntax
1121        /// true if the expression is represented using the `SUBSTRING(expr, start, len)` syntax
1122        /// This flag is used for formatting.
1123        special: bool,
1124
1125        /// true if the expression is represented using the `SUBSTR` shorthand
1126        /// This flag is used for formatting.
1127        shorthand: bool,
1128    },
1129    /// ```sql
1130    /// TRIM([BOTH | LEADING | TRAILING] [<expr> FROM] <expr>)
1131    /// TRIM(<expr>)
1132    /// TRIM(<expr>, [, characters]) -- only Snowflake or Bigquery
1133    /// ```
1134    Trim {
1135        /// The expression to trim from.
1136        expr: Box<Expr>,
1137        /// Which side to trim: `BOTH`, `LEADING`, or `TRAILING`.
1138        trim_where: Option<TrimWhereField>,
1139        /// Optional expression specifying what to trim from the value.
1140        trim_what: Option<Box<Expr>>,
1141        /// Optional list of characters to trim (dialect-specific).
1142        trim_characters: Option<Vec<Expr>>,
1143    },
1144    /// ```sql
1145    /// OVERLAY(<expr> PLACING <expr> FROM <expr>[ FOR <expr> ]
1146    /// ```
1147    Overlay {
1148        /// The target expression being overlayed.
1149        expr: Box<Expr>,
1150        /// The expression to place into the target.
1151        overlay_what: Box<Expr>,
1152        /// The `FROM` position expression indicating where to start overlay.
1153        overlay_from: Box<Expr>,
1154        /// Optional `FOR` length expression limiting the overlay span.
1155        overlay_for: Option<Box<Expr>>,
1156    },
1157    /// `expr COLLATE collation`
1158    Collate {
1159        /// The expression being collated.
1160        expr: Box<Expr>,
1161        /// The collation name to apply to the expression.
1162        collation: ObjectName,
1163    },
1164    /// Nested expression e.g. `(foo > bar)` or `(1)`
1165    Nested(Box<Expr>),
1166    /// A literal value, such as string, number, date or NULL
1167    Value(ValueWithSpan),
1168    /// Prefixed expression, e.g. introducer strings, projection prefix
1169    /// <https://dev.mysql.com/doc/refman/8.0/en/charset-introducer.html>
1170    /// <https://docs.snowflake.com/en/sql-reference/constructs/connect-by>
1171    Prefixed {
1172        /// The prefix identifier (introducer or projection prefix).
1173        prefix: Ident,
1174        /// The value expression being prefixed.
1175        /// Hint: you can unwrap the string value using `value.into_string()`.
1176        value: Box<Expr>,
1177    },
1178    /// A constant of form `<data_type> 'value'`.
1179    /// This can represent ANSI SQL `DATE`, `TIME`, and `TIMESTAMP` literals (such as `DATE '2020-01-01'`),
1180    /// as well as constants of other types (a non-standard PostgreSQL extension).
1181    TypedString(TypedString),
1182    /// Scalar function call e.g. `LEFT(foo, 5)`
1183    Function(Function),
1184    /// `CASE [<operand>] WHEN <condition> THEN <result> ... [ELSE <result>] END`
1185    ///
1186    /// Note we only recognize a complete single expression as `<condition>`,
1187    /// not `< 0` nor `1, 2, 3` as allowed in a `<simple when clause>` per
1188    /// <https://jakewheat.github.io/sql-overview/sql-2011-foundation-grammar.html#simple-when-clause>
1189    Case {
1190        /// The attached `CASE` token (keeps original spacing/comments).
1191        case_token: AttachedToken,
1192        /// The attached `END` token (keeps original spacing/comments).
1193        end_token: AttachedToken,
1194        /// Optional operand expression after `CASE` (for simple CASE).
1195        operand: Option<Box<Expr>>,
1196        /// The `WHEN ... THEN` conditions and results.
1197        conditions: Vec<CaseWhen>,
1198        /// Optional `ELSE` result expression.
1199        else_result: Option<Box<Expr>>,
1200    },
1201    /// An exists expression `[ NOT ] EXISTS(SELECT ...)`, used in expressions like
1202    /// `WHERE [ NOT ] EXISTS (SELECT ...)`.
1203    Exists {
1204        /// The subquery checked by `EXISTS`.
1205        subquery: Box<Query>,
1206        /// Whether the `EXISTS` is negated (`NOT EXISTS`).
1207        negated: bool,
1208    },
1209    /// A parenthesized subquery `(SELECT ...)`, used in expression like
1210    /// `SELECT (subquery) AS x` or `WHERE (subquery) = x`
1211    Subquery(Box<Query>),
1212    /// The `GROUPING SETS` expr.
1213    GroupingSets(Vec<Vec<Expr>>),
1214    /// The `CUBE` expr.
1215    Cube(Vec<Vec<Expr>>),
1216    /// The `ROLLUP` expr.
1217    Rollup(Vec<Vec<Expr>>),
1218    /// ROW / TUPLE a single value, such as `SELECT (1, 2)`
1219    Tuple(Vec<Expr>),
1220    /// `Struct` literal expression
1221    /// Syntax:
1222    /// ```sql
1223    /// STRUCT<[field_name] field_type, ...>( expr1 [, ... ])
1224    ///
1225    /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-types#struct_type)
1226    /// [Databricks](https://docs.databricks.com/en/sql/language-manual/functions/struct.html)
1227    /// ```
1228    Struct {
1229        /// Struct values.
1230        values: Vec<Expr>,
1231        /// Struct field definitions.
1232        fields: Vec<StructField>,
1233    },
1234    /// `BigQuery` specific: An named expression in a typeless struct [1]
1235    ///
1236    /// Syntax
1237    /// ```sql
1238    /// 1 AS A
1239    /// ```
1240    /// [1]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-types#struct_type
1241    Named {
1242        /// The expression being named.
1243        expr: Box<Expr>,
1244        /// The assigned identifier name for the expression.
1245        name: Ident,
1246    },
1247    /// `DuckDB` specific `Struct` literal expression [1]
1248    ///
1249    /// Syntax:
1250    /// ```sql
1251    /// syntax: {'field_name': expr1[, ... ]}
1252    /// ```
1253    /// [1]: https://duckdb.org/docs/sql/data_types/struct#creating-structs
1254    Dictionary(Vec<DictionaryField>),
1255    /// `DuckDB` specific `Map` literal expression [1]
1256    ///
1257    /// Syntax:
1258    /// ```sql
1259    /// syntax: Map {key1: value1[, ... ]}
1260    /// ```
1261    /// [1]: https://duckdb.org/docs/sql/data_types/map#creating-maps
1262    Map(Map),
1263    /// An array expression e.g. `ARRAY[1, 2]`
1264    Array(Array),
1265    /// An interval expression e.g. `INTERVAL '1' YEAR`
1266    Interval(Interval),
1267    /// `MySQL` specific text search function [(1)].
1268    ///
1269    /// Syntax:
1270    /// ```sql
1271    /// MATCH (<col>, <col>, ...) AGAINST (<expr> [<search modifier>])
1272    ///
1273    /// <col> = CompoundIdentifier
1274    /// <expr> = String literal
1275    /// ```
1276    /// [(1)]: https://dev.mysql.com/doc/refman/8.0/en/fulltext-search.html#function_match
1277    MatchAgainst {
1278        /// `(<col>, <col>, ...)`.
1279        columns: Vec<ObjectName>,
1280        /// `<expr>`.
1281        match_value: Value,
1282        /// `<search modifier>`
1283        opt_search_modifier: Option<SearchModifier>,
1284    },
1285    /// An unqualified `*` wildcard token (e.g. `*`).
1286    Wildcard(AttachedToken),
1287    /// Qualified wildcard, e.g. `alias.*` or `schema.table.*`.
1288    /// (Same caveats apply to `QualifiedWildcard` as to `Wildcard`.)
1289    QualifiedWildcard(ObjectName, AttachedToken),
1290    /// Some dialects support an older syntax for outer joins where columns are
1291    /// marked with the `(+)` operator in the WHERE clause, for example:
1292    ///
1293    /// ```sql
1294    /// SELECT t1.c1, t2.c2 FROM t1, t2 WHERE t1.c1 = t2.c2 (+)
1295    /// ```
1296    ///
1297    /// which is equivalent to
1298    ///
1299    /// ```sql
1300    /// SELECT t1.c1, t2.c2 FROM t1 LEFT OUTER JOIN t2 ON t1.c1 = t2.c2
1301    /// ```
1302    ///
1303    /// See <https://docs.snowflake.com/en/sql-reference/constructs/where#joins-in-the-where-clause>.
1304    OuterJoin(Box<Expr>),
1305    /// A reference to the prior level in a CONNECT BY clause.
1306    Prior(Box<Expr>),
1307    /// A lambda function.
1308    ///
1309    /// Syntax:
1310    /// ```plaintext
1311    /// param -> expr | (param1, ...) -> expr
1312    /// ```
1313    ///
1314    /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/functions#higher-order-functions---operator-and-lambdaparams-expr-function)
1315    /// [Databricks](https://docs.databricks.com/en/sql/language-manual/sql-ref-lambda-functions.html)
1316    /// [DuckDB](https://duckdb.org/docs/stable/sql/functions/lambda)
1317    Lambda(LambdaFunction),
1318    /// Checks membership of a value in a JSON array
1319    MemberOf(MemberOf),
1320}
1321
1322impl Expr {
1323    /// Creates a new [`Expr::Value`]
1324    pub fn value(value: impl Into<ValueWithSpan>) -> Self {
1325        Expr::Value(value.into())
1326    }
1327}
1328
1329/// The contents inside the `[` and `]` in a subscript expression.
1330#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1331#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1332#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1333pub enum Subscript {
1334    /// Accesses the element of the array at the given index.
1335    Index {
1336        /// The index expression used to access the array element.
1337        index: Expr,
1338    },
1339
1340    /// Accesses a slice of an array on PostgreSQL, e.g.
1341    ///
1342    /// ```plaintext
1343    /// => select (array[1,2,3,4,5,6])[2:5];
1344    /// -----------
1345    /// {2,3,4,5}
1346    /// ```
1347    ///
1348    /// The lower and/or upper bound can be omitted to slice from the start or
1349    /// end of the array respectively.
1350    ///
1351    /// See <https://www.postgresql.org/docs/current/arrays.html#ARRAYS-ACCESSING>.
1352    ///
1353    /// Also supports an optional "stride" as the last element (this is not
1354    /// supported by postgres), e.g.
1355    ///
1356    /// ```plaintext
1357    /// => select (array[1,2,3,4,5,6])[1:6:2];
1358    /// -----------
1359    /// {1,3,5}
1360    /// ```
1361    Slice {
1362        /// Optional lower bound for the slice (inclusive).
1363        lower_bound: Option<Expr>,
1364        /// Optional upper bound for the slice (inclusive).
1365        upper_bound: Option<Expr>,
1366        /// Optional stride for the slice (step size).
1367        stride: Option<Expr>,
1368    },
1369}
1370
1371impl fmt::Display for Subscript {
1372    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1373        match self {
1374            Subscript::Index { index } => write!(f, "{index}"),
1375            Subscript::Slice {
1376                lower_bound,
1377                upper_bound,
1378                stride,
1379            } => {
1380                if let Some(lower) = lower_bound {
1381                    write!(f, "{lower}")?;
1382                }
1383                write!(f, ":")?;
1384                if let Some(upper) = upper_bound {
1385                    write!(f, "{upper}")?;
1386                }
1387                if let Some(stride) = stride {
1388                    write!(f, ":")?;
1389                    write!(f, "{stride}")?;
1390                }
1391                Ok(())
1392            }
1393        }
1394    }
1395}
1396
1397/// An element of a [`Expr::CompoundFieldAccess`].
1398/// It can be an expression or a subscript.
1399#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1400#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1401#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1402pub enum AccessExpr {
1403    /// Accesses a field using dot notation, e.g. `foo.bar.baz`.
1404    Dot(Expr),
1405    /// Accesses a field or array element using bracket notation, e.g. `foo['bar']`.
1406    Subscript(Subscript),
1407}
1408
1409impl fmt::Display for AccessExpr {
1410    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1411        match self {
1412            AccessExpr::Dot(expr) => write!(f, ".{expr}"),
1413            AccessExpr::Subscript(subscript) => write!(f, "[{subscript}]"),
1414        }
1415    }
1416}
1417
1418/// A lambda function.
1419#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1420#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1421#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1422pub struct LambdaFunction {
1423    /// The parameters to the lambda function.
1424    pub params: OneOrManyWithParens<Ident>,
1425    /// The body of the lambda function.
1426    pub body: Box<Expr>,
1427    /// The syntax style used to write the lambda function.
1428    pub syntax: LambdaSyntax,
1429}
1430
1431impl fmt::Display for LambdaFunction {
1432    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1433        match self.syntax {
1434            LambdaSyntax::Arrow => write!(f, "{} -> {}", self.params, self.body),
1435            LambdaSyntax::LambdaKeyword => {
1436                // For lambda keyword syntax, display params without parentheses
1437                // e.g., `lambda x, y : expr` not `lambda (x, y) : expr`
1438                write!(f, "lambda ")?;
1439                match &self.params {
1440                    OneOrManyWithParens::One(p) => write!(f, "{p}")?,
1441                    OneOrManyWithParens::Many(ps) => write!(f, "{}", display_comma_separated(ps))?,
1442                };
1443                write!(f, " : {}", self.body)
1444            }
1445        }
1446    }
1447}
1448
1449/// The syntax style for a lambda function.
1450#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Copy)]
1451#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1452#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1453pub enum LambdaSyntax {
1454    /// Arrow syntax: `param -> expr` or `(param1, param2) -> expr`
1455    ///
1456    /// <https://docs.databricks.com/aws/en/sql/language-manual/sql-ref-lambda-functions>
1457    ///
1458    /// Supported, but deprecated in DuckDB:
1459    /// <https://duckdb.org/docs/stable/sql/functions/lambda>
1460    Arrow,
1461    /// Lambda keyword syntax: `lambda param : expr` or `lambda param1, param2 : expr`
1462    ///
1463    /// Recommended in DuckDB:
1464    /// <https://duckdb.org/docs/stable/sql/functions/lambda>
1465    LambdaKeyword,
1466}
1467
1468/// Encapsulates the common pattern in SQL where either one unparenthesized item
1469/// such as an identifier or expression is permitted, or multiple of the same
1470/// item in a parenthesized list. For accessing items regardless of the form,
1471/// `OneOrManyWithParens` implements `Deref<Target = [T]>` and `IntoIterator`,
1472/// so you can call slice methods on it and iterate over items
1473/// # Examples
1474/// Accessing as a slice:
1475/// ```
1476/// # use sqlparser::ast::OneOrManyWithParens;
1477/// let one = OneOrManyWithParens::One("a");
1478///
1479/// assert_eq!(one[0], "a");
1480/// assert_eq!(one.len(), 1);
1481/// ```
1482/// Iterating:
1483/// ```
1484/// # use sqlparser::ast::OneOrManyWithParens;
1485/// let one = OneOrManyWithParens::One("a");
1486/// let many = OneOrManyWithParens::Many(vec!["a", "b"]);
1487///
1488/// assert_eq!(one.into_iter().chain(many).collect::<Vec<_>>(), vec!["a", "a", "b"] );
1489/// ```
1490#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1491#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1492#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1493pub enum OneOrManyWithParens<T> {
1494    /// A single `T`, unparenthesized.
1495    One(T),
1496    /// One or more `T`s, parenthesized.
1497    Many(Vec<T>),
1498}
1499
1500impl<T> Deref for OneOrManyWithParens<T> {
1501    type Target = [T];
1502
1503    fn deref(&self) -> &[T] {
1504        match self {
1505            OneOrManyWithParens::One(one) => core::slice::from_ref(one),
1506            OneOrManyWithParens::Many(many) => many,
1507        }
1508    }
1509}
1510
1511impl<T> AsRef<[T]> for OneOrManyWithParens<T> {
1512    fn as_ref(&self) -> &[T] {
1513        self
1514    }
1515}
1516
1517impl<'a, T> IntoIterator for &'a OneOrManyWithParens<T> {
1518    type Item = &'a T;
1519    type IntoIter = core::slice::Iter<'a, T>;
1520
1521    fn into_iter(self) -> Self::IntoIter {
1522        self.iter()
1523    }
1524}
1525
1526/// Owned iterator implementation of `OneOrManyWithParens`
1527#[derive(Debug, Clone)]
1528pub struct OneOrManyWithParensIntoIter<T> {
1529    inner: OneOrManyWithParensIntoIterInner<T>,
1530}
1531
1532#[derive(Debug, Clone)]
1533enum OneOrManyWithParensIntoIterInner<T> {
1534    One(core::iter::Once<T>),
1535    Many(<Vec<T> as IntoIterator>::IntoIter),
1536}
1537
1538impl<T> core::iter::FusedIterator for OneOrManyWithParensIntoIter<T>
1539where
1540    core::iter::Once<T>: core::iter::FusedIterator,
1541    <Vec<T> as IntoIterator>::IntoIter: core::iter::FusedIterator,
1542{
1543}
1544
1545impl<T> core::iter::ExactSizeIterator for OneOrManyWithParensIntoIter<T>
1546where
1547    core::iter::Once<T>: core::iter::ExactSizeIterator,
1548    <Vec<T> as IntoIterator>::IntoIter: core::iter::ExactSizeIterator,
1549{
1550}
1551
1552impl<T> core::iter::Iterator for OneOrManyWithParensIntoIter<T> {
1553    type Item = T;
1554
1555    fn next(&mut self) -> Option<Self::Item> {
1556        match &mut self.inner {
1557            OneOrManyWithParensIntoIterInner::One(one) => one.next(),
1558            OneOrManyWithParensIntoIterInner::Many(many) => many.next(),
1559        }
1560    }
1561
1562    fn size_hint(&self) -> (usize, Option<usize>) {
1563        match &self.inner {
1564            OneOrManyWithParensIntoIterInner::One(one) => one.size_hint(),
1565            OneOrManyWithParensIntoIterInner::Many(many) => many.size_hint(),
1566        }
1567    }
1568
1569    fn count(self) -> usize
1570    where
1571        Self: Sized,
1572    {
1573        match self.inner {
1574            OneOrManyWithParensIntoIterInner::One(one) => one.count(),
1575            OneOrManyWithParensIntoIterInner::Many(many) => many.count(),
1576        }
1577    }
1578
1579    fn fold<B, F>(mut self, init: B, f: F) -> B
1580    where
1581        Self: Sized,
1582        F: FnMut(B, Self::Item) -> B,
1583    {
1584        match &mut self.inner {
1585            OneOrManyWithParensIntoIterInner::One(one) => one.fold(init, f),
1586            OneOrManyWithParensIntoIterInner::Many(many) => many.fold(init, f),
1587        }
1588    }
1589}
1590
1591impl<T> core::iter::DoubleEndedIterator for OneOrManyWithParensIntoIter<T> {
1592    fn next_back(&mut self) -> Option<Self::Item> {
1593        match &mut self.inner {
1594            OneOrManyWithParensIntoIterInner::One(one) => one.next_back(),
1595            OneOrManyWithParensIntoIterInner::Many(many) => many.next_back(),
1596        }
1597    }
1598}
1599
1600impl<T> IntoIterator for OneOrManyWithParens<T> {
1601    type Item = T;
1602
1603    type IntoIter = OneOrManyWithParensIntoIter<T>;
1604
1605    fn into_iter(self) -> Self::IntoIter {
1606        let inner = match self {
1607            OneOrManyWithParens::One(one) => {
1608                OneOrManyWithParensIntoIterInner::One(core::iter::once(one))
1609            }
1610            OneOrManyWithParens::Many(many) => {
1611                OneOrManyWithParensIntoIterInner::Many(many.into_iter())
1612            }
1613        };
1614
1615        OneOrManyWithParensIntoIter { inner }
1616    }
1617}
1618
1619impl<T> fmt::Display for OneOrManyWithParens<T>
1620where
1621    T: fmt::Display,
1622{
1623    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1624        match self {
1625            OneOrManyWithParens::One(value) => write!(f, "{value}"),
1626            OneOrManyWithParens::Many(values) => {
1627                write!(f, "({})", display_comma_separated(values))
1628            }
1629        }
1630    }
1631}
1632
1633impl fmt::Display for CastFormat {
1634    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1635        match self {
1636            CastFormat::Value(v) => write!(f, "{v}"),
1637            CastFormat::ValueAtTimeZone(v, tz) => write!(f, "{v} AT TIME ZONE {tz}"),
1638        }
1639    }
1640}
1641
1642impl fmt::Display for Expr {
1643    #[cfg_attr(feature = "recursive-protection", recursive::recursive)]
1644    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1645        match self {
1646            Expr::Identifier(s) => write!(f, "{s}"),
1647            Expr::Wildcard(_) => f.write_str("*"),
1648            Expr::QualifiedWildcard(prefix, _) => write!(f, "{prefix}.*"),
1649            Expr::CompoundIdentifier(s) => write!(f, "{}", display_separated(s, ".")),
1650            Expr::CompoundFieldAccess { root, access_chain } => {
1651                write!(f, "{root}")?;
1652                for field in access_chain {
1653                    write!(f, "{field}")?;
1654                }
1655                Ok(())
1656            }
1657            Expr::IsTrue(ast) => write!(f, "{ast} IS TRUE"),
1658            Expr::IsNotTrue(ast) => write!(f, "{ast} IS NOT TRUE"),
1659            Expr::IsFalse(ast) => write!(f, "{ast} IS FALSE"),
1660            Expr::IsNotFalse(ast) => write!(f, "{ast} IS NOT FALSE"),
1661            Expr::IsNull(ast) => write!(f, "{ast} IS NULL"),
1662            Expr::IsNotNull(ast) => write!(f, "{ast} IS NOT NULL"),
1663            Expr::IsUnknown(ast) => write!(f, "{ast} IS UNKNOWN"),
1664            Expr::IsNotUnknown(ast) => write!(f, "{ast} IS NOT UNKNOWN"),
1665            Expr::InList {
1666                expr,
1667                list,
1668                negated,
1669            } => write!(
1670                f,
1671                "{} {}IN ({})",
1672                expr,
1673                if *negated { "NOT " } else { "" },
1674                display_comma_separated(list)
1675            ),
1676            Expr::InSubquery {
1677                expr,
1678                subquery,
1679                negated,
1680            } => write!(
1681                f,
1682                "{} {}IN ({})",
1683                expr,
1684                if *negated { "NOT " } else { "" },
1685                subquery
1686            ),
1687            Expr::InUnnest {
1688                expr,
1689                array_expr,
1690                negated,
1691            } => write!(
1692                f,
1693                "{} {}IN UNNEST({})",
1694                expr,
1695                if *negated { "NOT " } else { "" },
1696                array_expr
1697            ),
1698            Expr::Between {
1699                expr,
1700                negated,
1701                low,
1702                high,
1703            } => write!(
1704                f,
1705                "{} {}BETWEEN {} AND {}",
1706                expr,
1707                if *negated { "NOT " } else { "" },
1708                low,
1709                high
1710            ),
1711            Expr::BinaryOp { left, op, right } => write!(f, "{left} {op} {right}"),
1712            Expr::Like {
1713                negated,
1714                expr,
1715                pattern,
1716                escape_char,
1717                any,
1718            } => match escape_char {
1719                Some(ch) => write!(
1720                    f,
1721                    "{} {}LIKE {}{} ESCAPE {}",
1722                    expr,
1723                    if *negated { "NOT " } else { "" },
1724                    if *any { "ANY " } else { "" },
1725                    pattern,
1726                    ch
1727                ),
1728                _ => write!(
1729                    f,
1730                    "{} {}LIKE {}{}",
1731                    expr,
1732                    if *negated { "NOT " } else { "" },
1733                    if *any { "ANY " } else { "" },
1734                    pattern
1735                ),
1736            },
1737            Expr::ILike {
1738                negated,
1739                expr,
1740                pattern,
1741                escape_char,
1742                any,
1743            } => match escape_char {
1744                Some(ch) => write!(
1745                    f,
1746                    "{} {}ILIKE {}{} ESCAPE {}",
1747                    expr,
1748                    if *negated { "NOT " } else { "" },
1749                    if *any { "ANY" } else { "" },
1750                    pattern,
1751                    ch
1752                ),
1753                _ => write!(
1754                    f,
1755                    "{} {}ILIKE {}{}",
1756                    expr,
1757                    if *negated { "NOT " } else { "" },
1758                    if *any { "ANY " } else { "" },
1759                    pattern
1760                ),
1761            },
1762            Expr::RLike {
1763                negated,
1764                expr,
1765                pattern,
1766                regexp,
1767            } => write!(
1768                f,
1769                "{} {}{} {}",
1770                expr,
1771                if *negated { "NOT " } else { "" },
1772                if *regexp { "REGEXP" } else { "RLIKE" },
1773                pattern
1774            ),
1775            Expr::IsNormalized {
1776                expr,
1777                form,
1778                negated,
1779            } => {
1780                let not_ = if *negated { "NOT " } else { "" };
1781                if form.is_none() {
1782                    write!(f, "{expr} IS {not_}NORMALIZED")
1783                } else {
1784                    write!(
1785                        f,
1786                        "{} IS {}{} NORMALIZED",
1787                        expr,
1788                        not_,
1789                        form.as_ref().unwrap()
1790                    )
1791                }
1792            }
1793            Expr::SimilarTo {
1794                negated,
1795                expr,
1796                pattern,
1797                escape_char,
1798            } => match escape_char {
1799                Some(ch) => write!(
1800                    f,
1801                    "{} {}SIMILAR TO {} ESCAPE {}",
1802                    expr,
1803                    if *negated { "NOT " } else { "" },
1804                    pattern,
1805                    ch
1806                ),
1807                _ => write!(
1808                    f,
1809                    "{} {}SIMILAR TO {}",
1810                    expr,
1811                    if *negated { "NOT " } else { "" },
1812                    pattern
1813                ),
1814            },
1815            Expr::AnyOp {
1816                left,
1817                compare_op,
1818                right,
1819                is_some,
1820            } => {
1821                let add_parens = !matches!(right.as_ref(), Expr::Subquery(_));
1822                write!(
1823                    f,
1824                    "{left} {compare_op} {}{}{right}{}",
1825                    if *is_some { "SOME" } else { "ANY" },
1826                    if add_parens { "(" } else { "" },
1827                    if add_parens { ")" } else { "" },
1828                )
1829            }
1830            Expr::AllOp {
1831                left,
1832                compare_op,
1833                right,
1834            } => {
1835                let add_parens = !matches!(right.as_ref(), Expr::Subquery(_));
1836                write!(
1837                    f,
1838                    "{left} {compare_op} ALL{}{right}{}",
1839                    if add_parens { "(" } else { "" },
1840                    if add_parens { ")" } else { "" },
1841                )
1842            }
1843            Expr::UnaryOp { op, expr } => {
1844                if op == &UnaryOperator::PGPostfixFactorial {
1845                    write!(f, "{expr}{op}")
1846                } else if matches!(
1847                    op,
1848                    UnaryOperator::Not
1849                        | UnaryOperator::Hash
1850                        | UnaryOperator::AtDashAt
1851                        | UnaryOperator::DoubleAt
1852                        | UnaryOperator::QuestionDash
1853                        | UnaryOperator::QuestionPipe
1854                ) {
1855                    write!(f, "{op} {expr}")
1856                } else {
1857                    write!(f, "{op}{expr}")
1858                }
1859            }
1860            Expr::Convert {
1861                is_try,
1862                expr,
1863                target_before_value,
1864                data_type,
1865                charset,
1866                styles,
1867            } => {
1868                write!(f, "{}CONVERT(", if *is_try { "TRY_" } else { "" })?;
1869                if let Some(data_type) = data_type {
1870                    if let Some(charset) = charset {
1871                        write!(f, "{expr}, {data_type} CHARACTER SET {charset}")
1872                    } else if *target_before_value {
1873                        write!(f, "{data_type}, {expr}")
1874                    } else {
1875                        write!(f, "{expr}, {data_type}")
1876                    }
1877                } else if let Some(charset) = charset {
1878                    write!(f, "{expr} USING {charset}")
1879                } else {
1880                    write!(f, "{expr}") // This should never happen
1881                }?;
1882                if !styles.is_empty() {
1883                    write!(f, ", {}", display_comma_separated(styles))?;
1884                }
1885                write!(f, ")")
1886            }
1887            Expr::Cast {
1888                kind,
1889                expr,
1890                data_type,
1891                array,
1892                format,
1893            } => match kind {
1894                CastKind::Cast => {
1895                    write!(f, "CAST({expr} AS {data_type}")?;
1896                    if *array {
1897                        write!(f, " ARRAY")?;
1898                    }
1899                    if let Some(format) = format {
1900                        write!(f, " FORMAT {format}")?;
1901                    }
1902                    write!(f, ")")
1903                }
1904                CastKind::TryCast => {
1905                    if let Some(format) = format {
1906                        write!(f, "TRY_CAST({expr} AS {data_type} FORMAT {format})")
1907                    } else {
1908                        write!(f, "TRY_CAST({expr} AS {data_type})")
1909                    }
1910                }
1911                CastKind::SafeCast => {
1912                    if let Some(format) = format {
1913                        write!(f, "SAFE_CAST({expr} AS {data_type} FORMAT {format})")
1914                    } else {
1915                        write!(f, "SAFE_CAST({expr} AS {data_type})")
1916                    }
1917                }
1918                CastKind::DoubleColon => {
1919                    write!(f, "{expr}::{data_type}")
1920                }
1921            },
1922            Expr::Extract {
1923                field,
1924                syntax,
1925                expr,
1926            } => match syntax {
1927                ExtractSyntax::From => write!(f, "EXTRACT({field} FROM {expr})"),
1928                ExtractSyntax::Comma => write!(f, "EXTRACT({field}, {expr})"),
1929            },
1930            Expr::Ceil { expr, field } => match field {
1931                CeilFloorKind::DateTimeField(DateTimeField::NoDateTime) => {
1932                    write!(f, "CEIL({expr})")
1933                }
1934                CeilFloorKind::DateTimeField(dt_field) => write!(f, "CEIL({expr} TO {dt_field})"),
1935                CeilFloorKind::Scale(s) => write!(f, "CEIL({expr}, {s})"),
1936            },
1937            Expr::Floor { expr, field } => match field {
1938                CeilFloorKind::DateTimeField(DateTimeField::NoDateTime) => {
1939                    write!(f, "FLOOR({expr})")
1940                }
1941                CeilFloorKind::DateTimeField(dt_field) => write!(f, "FLOOR({expr} TO {dt_field})"),
1942                CeilFloorKind::Scale(s) => write!(f, "FLOOR({expr}, {s})"),
1943            },
1944            Expr::Position { expr, r#in } => write!(f, "POSITION({expr} IN {in})"),
1945            Expr::Collate { expr, collation } => write!(f, "{expr} COLLATE {collation}"),
1946            Expr::Nested(ast) => write!(f, "({ast})"),
1947            Expr::Value(v) => write!(f, "{v}"),
1948            Expr::Prefixed { prefix, value } => write!(f, "{prefix} {value}"),
1949            Expr::TypedString(ts) => ts.fmt(f),
1950            Expr::Function(fun) => fun.fmt(f),
1951            Expr::Case {
1952                case_token: _,
1953                end_token: _,
1954                operand,
1955                conditions,
1956                else_result,
1957            } => {
1958                f.write_str("CASE")?;
1959                if let Some(operand) = operand {
1960                    f.write_str(" ")?;
1961                    operand.fmt(f)?;
1962                }
1963                for when in conditions {
1964                    SpaceOrNewline.fmt(f)?;
1965                    Indent(when).fmt(f)?;
1966                }
1967                if let Some(else_result) = else_result {
1968                    SpaceOrNewline.fmt(f)?;
1969                    Indent("ELSE").fmt(f)?;
1970                    SpaceOrNewline.fmt(f)?;
1971                    Indent(Indent(else_result)).fmt(f)?;
1972                }
1973                SpaceOrNewline.fmt(f)?;
1974                f.write_str("END")
1975            }
1976            Expr::Exists { subquery, negated } => write!(
1977                f,
1978                "{}EXISTS ({})",
1979                if *negated { "NOT " } else { "" },
1980                subquery
1981            ),
1982            Expr::Subquery(s) => write!(f, "({s})"),
1983            Expr::GroupingSets(sets) => {
1984                write!(f, "GROUPING SETS (")?;
1985                let mut sep = "";
1986                for set in sets {
1987                    write!(f, "{sep}")?;
1988                    sep = ", ";
1989                    write!(f, "({})", display_comma_separated(set))?;
1990                }
1991                write!(f, ")")
1992            }
1993            Expr::Cube(sets) => {
1994                write!(f, "CUBE (")?;
1995                let mut sep = "";
1996                for set in sets {
1997                    write!(f, "{sep}")?;
1998                    sep = ", ";
1999                    if set.len() == 1 {
2000                        write!(f, "{}", set[0])?;
2001                    } else {
2002                        write!(f, "({})", display_comma_separated(set))?;
2003                    }
2004                }
2005                write!(f, ")")
2006            }
2007            Expr::Rollup(sets) => {
2008                write!(f, "ROLLUP (")?;
2009                let mut sep = "";
2010                for set in sets {
2011                    write!(f, "{sep}")?;
2012                    sep = ", ";
2013                    if set.len() == 1 {
2014                        write!(f, "{}", set[0])?;
2015                    } else {
2016                        write!(f, "({})", display_comma_separated(set))?;
2017                    }
2018                }
2019                write!(f, ")")
2020            }
2021            Expr::Substring {
2022                expr,
2023                substring_from,
2024                substring_for,
2025                special,
2026                shorthand,
2027            } => {
2028                f.write_str("SUBSTR")?;
2029                if !*shorthand {
2030                    f.write_str("ING")?;
2031                }
2032                write!(f, "({expr}")?;
2033                if let Some(from_part) = substring_from {
2034                    if *special {
2035                        write!(f, ", {from_part}")?;
2036                    } else {
2037                        write!(f, " FROM {from_part}")?;
2038                    }
2039                }
2040                if let Some(for_part) = substring_for {
2041                    if *special {
2042                        write!(f, ", {for_part}")?;
2043                    } else {
2044                        write!(f, " FOR {for_part}")?;
2045                    }
2046                }
2047
2048                write!(f, ")")
2049            }
2050            Expr::Overlay {
2051                expr,
2052                overlay_what,
2053                overlay_from,
2054                overlay_for,
2055            } => {
2056                write!(
2057                    f,
2058                    "OVERLAY({expr} PLACING {overlay_what} FROM {overlay_from}"
2059                )?;
2060                if let Some(for_part) = overlay_for {
2061                    write!(f, " FOR {for_part}")?;
2062                }
2063
2064                write!(f, ")")
2065            }
2066            Expr::IsDistinctFrom(a, b) => write!(f, "{a} IS DISTINCT FROM {b}"),
2067            Expr::IsNotDistinctFrom(a, b) => write!(f, "{a} IS NOT DISTINCT FROM {b}"),
2068            Expr::Trim {
2069                expr,
2070                trim_where,
2071                trim_what,
2072                trim_characters,
2073            } => {
2074                write!(f, "TRIM(")?;
2075                if let Some(ident) = trim_where {
2076                    write!(f, "{ident} ")?;
2077                }
2078                if let Some(trim_char) = trim_what {
2079                    write!(f, "{trim_char} FROM {expr}")?;
2080                } else {
2081                    write!(f, "{expr}")?;
2082                }
2083                if let Some(characters) = trim_characters {
2084                    write!(f, ", {}", display_comma_separated(characters))?;
2085                }
2086
2087                write!(f, ")")
2088            }
2089            Expr::Tuple(exprs) => {
2090                write!(f, "({})", display_comma_separated(exprs))
2091            }
2092            Expr::Struct { values, fields } => {
2093                if !fields.is_empty() {
2094                    write!(
2095                        f,
2096                        "STRUCT<{}>({})",
2097                        display_comma_separated(fields),
2098                        display_comma_separated(values)
2099                    )
2100                } else {
2101                    write!(f, "STRUCT({})", display_comma_separated(values))
2102                }
2103            }
2104            Expr::Named { expr, name } => {
2105                write!(f, "{expr} AS {name}")
2106            }
2107            Expr::Dictionary(fields) => {
2108                write!(f, "{{{}}}", display_comma_separated(fields))
2109            }
2110            Expr::Map(map) => {
2111                write!(f, "{map}")
2112            }
2113            Expr::Array(set) => {
2114                write!(f, "{set}")
2115            }
2116            Expr::JsonAccess { value, path } => {
2117                write!(f, "{value}{path}")
2118            }
2119            Expr::AtTimeZone {
2120                timestamp,
2121                time_zone,
2122            } => {
2123                write!(f, "{timestamp} AT TIME ZONE {time_zone}")
2124            }
2125            Expr::Interval(interval) => {
2126                write!(f, "{interval}")
2127            }
2128            Expr::MatchAgainst {
2129                columns,
2130                match_value: match_expr,
2131                opt_search_modifier,
2132            } => {
2133                write!(f, "MATCH ({}) AGAINST ", display_comma_separated(columns),)?;
2134
2135                if let Some(search_modifier) = opt_search_modifier {
2136                    write!(f, "({match_expr} {search_modifier})")?;
2137                } else {
2138                    write!(f, "({match_expr})")?;
2139                }
2140
2141                Ok(())
2142            }
2143            Expr::OuterJoin(expr) => {
2144                write!(f, "{expr} (+)")
2145            }
2146            Expr::Prior(expr) => write!(f, "PRIOR {expr}"),
2147            Expr::Lambda(lambda) => write!(f, "{lambda}"),
2148            Expr::MemberOf(member_of) => write!(f, "{member_of}"),
2149        }
2150    }
2151}
2152
2153/// The type of a window used in `OVER` clauses.
2154///
2155/// A window can be either an inline specification (`WindowSpec`) or a
2156/// reference to a previously defined named window.
2157///
2158/// - `WindowSpec(WindowSpec)`: An inline window specification, e.g.
2159///   `OVER (PARTITION BY ... ORDER BY ...)`.
2160/// - `NamedWindow(Ident)`: A reference to a named window declared elsewhere.
2161#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2162#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2163#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2164pub enum WindowType {
2165    /// An inline window specification.
2166    WindowSpec(WindowSpec),
2167    /// A reference to a previously defined named window.
2168    NamedWindow(Ident),
2169}
2170
2171impl Display for WindowType {
2172    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2173        match self {
2174            WindowType::WindowSpec(spec) => {
2175                f.write_str("(")?;
2176                NewLine.fmt(f)?;
2177                Indent(spec).fmt(f)?;
2178                NewLine.fmt(f)?;
2179                f.write_str(")")
2180            }
2181            WindowType::NamedWindow(name) => name.fmt(f),
2182        }
2183    }
2184}
2185
2186/// A window specification (i.e. `OVER ([window_name] PARTITION BY .. ORDER BY .. etc.)`)
2187#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2188#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2189#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2190pub struct WindowSpec {
2191    /// Optional window name.
2192    ///
2193    /// You can find it at least in [MySQL][1], [BigQuery][2], [PostgreSQL][3]
2194    ///
2195    /// [1]: https://dev.mysql.com/doc/refman/8.0/en/window-functions-named-windows.html
2196    /// [2]: https://cloud.google.com/bigquery/docs/reference/standard-sql/window-function-calls
2197    /// [3]: https://www.postgresql.org/docs/current/sql-expressions.html#SYNTAX-WINDOW-FUNCTIONS
2198    pub window_name: Option<Ident>,
2199    /// `OVER (PARTITION BY ...)`
2200    pub partition_by: Vec<Expr>,
2201    /// `OVER (ORDER BY ...)`
2202    pub order_by: Vec<OrderByExpr>,
2203    /// `OVER (window frame)`
2204    pub window_frame: Option<WindowFrame>,
2205}
2206
2207impl fmt::Display for WindowSpec {
2208    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2209        let mut is_first = true;
2210        if let Some(window_name) = &self.window_name {
2211            if !is_first {
2212                SpaceOrNewline.fmt(f)?;
2213            }
2214            is_first = false;
2215            write!(f, "{window_name}")?;
2216        }
2217        if !self.partition_by.is_empty() {
2218            if !is_first {
2219                SpaceOrNewline.fmt(f)?;
2220            }
2221            is_first = false;
2222            write!(
2223                f,
2224                "PARTITION BY {}",
2225                display_comma_separated(&self.partition_by)
2226            )?;
2227        }
2228        if !self.order_by.is_empty() {
2229            if !is_first {
2230                SpaceOrNewline.fmt(f)?;
2231            }
2232            is_first = false;
2233            write!(f, "ORDER BY {}", display_comma_separated(&self.order_by))?;
2234        }
2235        if let Some(window_frame) = &self.window_frame {
2236            if !is_first {
2237                SpaceOrNewline.fmt(f)?;
2238            }
2239            if let Some(end_bound) = &window_frame.end_bound {
2240                write!(
2241                    f,
2242                    "{} BETWEEN {} AND {}",
2243                    window_frame.units, window_frame.start_bound, end_bound
2244                )?;
2245            } else {
2246                write!(f, "{} {}", window_frame.units, window_frame.start_bound)?;
2247            }
2248        }
2249        Ok(())
2250    }
2251}
2252
2253/// Specifies the data processed by a window function, e.g.
2254/// `RANGE UNBOUNDED PRECEDING` or `ROWS BETWEEN 5 PRECEDING AND CURRENT ROW`.
2255///
2256/// Note: The parser does not validate the specified bounds; the caller should
2257/// reject invalid bounds like `ROWS UNBOUNDED FOLLOWING` before execution.
2258#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2259#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2260#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2261pub struct WindowFrame {
2262    /// Units for the frame (e.g. `ROWS`, `RANGE`, `GROUPS`).
2263    pub units: WindowFrameUnits,
2264    /// The start bound of the window frame.
2265    pub start_bound: WindowFrameBound,
2266    /// The right bound of the `BETWEEN .. AND` clause. The end bound of `None`
2267    /// indicates the shorthand form (e.g. `ROWS 1 PRECEDING`), which must
2268    /// behave the same as `end_bound = WindowFrameBound::CurrentRow`.
2269    pub end_bound: Option<WindowFrameBound>,
2270    // TBD: EXCLUDE
2271}
2272
2273impl Default for WindowFrame {
2274    /// Returns default value for window frame
2275    ///
2276    /// See [this page](https://www.sqlite.org/windowfunctions.html#frame_specifications) for more details.
2277    fn default() -> Self {
2278        Self {
2279            units: WindowFrameUnits::Range,
2280            start_bound: WindowFrameBound::Preceding(None),
2281            end_bound: None,
2282        }
2283    }
2284}
2285
2286#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2287#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2288#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2289/// Units used to describe the window frame scope.
2290pub enum WindowFrameUnits {
2291    /// `ROWS` unit.
2292    Rows,
2293    /// `RANGE` unit.
2294    Range,
2295    /// `GROUPS` unit.
2296    Groups,
2297}
2298
2299impl fmt::Display for WindowFrameUnits {
2300    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2301        f.write_str(match self {
2302            WindowFrameUnits::Rows => "ROWS",
2303            WindowFrameUnits::Range => "RANGE",
2304            WindowFrameUnits::Groups => "GROUPS",
2305        })
2306    }
2307}
2308
2309/// Specifies Ignore / Respect NULL within window functions.
2310/// For example
2311/// `FIRST_VALUE(column2) IGNORE NULLS OVER (PARTITION BY column1)`
2312#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2313#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2314#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2315/// How NULL values are treated in certain window functions.
2316pub enum NullTreatment {
2317    /// Ignore NULL values (e.g. `IGNORE NULLS`).
2318    IgnoreNulls,
2319    /// Respect NULL values (e.g. `RESPECT NULLS`).
2320    RespectNulls,
2321}
2322
2323impl fmt::Display for NullTreatment {
2324    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2325        f.write_str(match self {
2326            NullTreatment::IgnoreNulls => "IGNORE NULLS",
2327            NullTreatment::RespectNulls => "RESPECT NULLS",
2328        })
2329    }
2330}
2331
2332/// Specifies [WindowFrame]'s `start_bound` and `end_bound`
2333#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2334#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2335#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2336pub enum WindowFrameBound {
2337    /// `CURRENT ROW`
2338    CurrentRow,
2339    /// `<N> PRECEDING` or `UNBOUNDED PRECEDING`
2340    Preceding(Option<Box<Expr>>),
2341    /// `<N> FOLLOWING` or `UNBOUNDED FOLLOWING`.
2342    Following(Option<Box<Expr>>),
2343}
2344
2345impl fmt::Display for WindowFrameBound {
2346    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2347        match self {
2348            WindowFrameBound::CurrentRow => f.write_str("CURRENT ROW"),
2349            WindowFrameBound::Preceding(None) => f.write_str("UNBOUNDED PRECEDING"),
2350            WindowFrameBound::Following(None) => f.write_str("UNBOUNDED FOLLOWING"),
2351            WindowFrameBound::Preceding(Some(n)) => write!(f, "{n} PRECEDING"),
2352            WindowFrameBound::Following(Some(n)) => write!(f, "{n} FOLLOWING"),
2353        }
2354    }
2355}
2356
2357#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2358#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2359#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2360/// Indicates partition operation type for partition management statements.
2361pub enum AddDropSync {
2362    /// Add partitions.
2363    ADD,
2364    /// Drop partitions.
2365    DROP,
2366    /// Sync partitions.
2367    SYNC,
2368}
2369
2370impl fmt::Display for AddDropSync {
2371    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2372        match self {
2373            AddDropSync::SYNC => f.write_str("SYNC PARTITIONS"),
2374            AddDropSync::DROP => f.write_str("DROP PARTITIONS"),
2375            AddDropSync::ADD => f.write_str("ADD PARTITIONS"),
2376        }
2377    }
2378}
2379
2380#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2381#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2382#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2383/// Object kinds supported by `SHOW CREATE` statements.
2384pub enum ShowCreateObject {
2385    /// An event object for `SHOW CREATE EVENT`.
2386    Event,
2387    /// A function object for `SHOW CREATE FUNCTION`.
2388    Function,
2389    /// A procedure object for `SHOW CREATE PROCEDURE`.
2390    Procedure,
2391    /// A table object for `SHOW CREATE TABLE`.
2392    Table,
2393    /// A trigger object for `SHOW CREATE TRIGGER`.
2394    Trigger,
2395    /// A view object for `SHOW CREATE VIEW`.
2396    View,
2397}
2398
2399impl fmt::Display for ShowCreateObject {
2400    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2401        match self {
2402            ShowCreateObject::Event => f.write_str("EVENT"),
2403            ShowCreateObject::Function => f.write_str("FUNCTION"),
2404            ShowCreateObject::Procedure => f.write_str("PROCEDURE"),
2405            ShowCreateObject::Table => f.write_str("TABLE"),
2406            ShowCreateObject::Trigger => f.write_str("TRIGGER"),
2407            ShowCreateObject::View => f.write_str("VIEW"),
2408        }
2409    }
2410}
2411
2412#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2413#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2414#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2415/// Objects that can be targeted by a `COMMENT` statement.
2416pub enum CommentObject {
2417    /// A table column.
2418    Column,
2419    /// A table.
2420    Table,
2421    /// An extension.
2422    Extension,
2423    /// A schema.
2424    Schema,
2425    /// A database.
2426    Database,
2427    /// A user.
2428    User,
2429    /// A role.
2430    Role,
2431}
2432
2433impl fmt::Display for CommentObject {
2434    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2435        match self {
2436            CommentObject::Column => f.write_str("COLUMN"),
2437            CommentObject::Table => f.write_str("TABLE"),
2438            CommentObject::Extension => f.write_str("EXTENSION"),
2439            CommentObject::Schema => f.write_str("SCHEMA"),
2440            CommentObject::Database => f.write_str("DATABASE"),
2441            CommentObject::User => f.write_str("USER"),
2442            CommentObject::Role => f.write_str("ROLE"),
2443        }
2444    }
2445}
2446
2447#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2448#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2449#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2450/// Password specification variants used in user-related statements.
2451pub enum Password {
2452    /// A concrete password expression.
2453    Password(Expr),
2454    /// Represents a `NULL` password.
2455    NullPassword,
2456}
2457
2458/// A `CASE` statement.
2459///
2460/// Examples:
2461/// ```sql
2462/// CASE
2463///     WHEN EXISTS(SELECT 1)
2464///         THEN SELECT 1 FROM T;
2465///     WHEN EXISTS(SELECT 2)
2466///         THEN SELECT 1 FROM U;
2467///     ELSE
2468///         SELECT 1 FROM V;
2469/// END CASE;
2470/// ```
2471///
2472/// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#case_search_expression)
2473/// [Snowflake](https://docs.snowflake.com/en/sql-reference/snowflake-scripting/case)
2474#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2475#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2476#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2477pub struct CaseStatement {
2478    /// The `CASE` token that starts the statement.
2479    pub case_token: AttachedToken,
2480    /// Optional expression to match against in `CASE ... WHEN`.
2481    pub match_expr: Option<Expr>,
2482    /// The `WHEN ... THEN` blocks of the `CASE` statement.
2483    pub when_blocks: Vec<ConditionalStatementBlock>,
2484    /// Optional `ELSE` block for the `CASE` statement.
2485    pub else_block: Option<ConditionalStatementBlock>,
2486    /// The last token of the statement (`END` or `CASE`).
2487    pub end_case_token: AttachedToken,
2488}
2489
2490impl fmt::Display for CaseStatement {
2491    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2492        let CaseStatement {
2493            case_token: _,
2494            match_expr,
2495            when_blocks,
2496            else_block,
2497            end_case_token: AttachedToken(end),
2498        } = self;
2499
2500        write!(f, "CASE")?;
2501
2502        if let Some(expr) = match_expr {
2503            write!(f, " {expr}")?;
2504        }
2505
2506        if !when_blocks.is_empty() {
2507            write!(f, " {}", display_separated(when_blocks, " "))?;
2508        }
2509
2510        if let Some(else_block) = else_block {
2511            write!(f, " {else_block}")?;
2512        }
2513
2514        write!(f, " END")?;
2515
2516        if let Token::Word(w) = &end.token {
2517            if w.keyword == Keyword::CASE {
2518                write!(f, " CASE")?;
2519            }
2520        }
2521
2522        Ok(())
2523    }
2524}
2525
2526/// An `IF` statement.
2527///
2528/// Example (BigQuery or Snowflake):
2529/// ```sql
2530/// IF TRUE THEN
2531///     SELECT 1;
2532///     SELECT 2;
2533/// ELSEIF TRUE THEN
2534///     SELECT 3;
2535/// ELSE
2536///     SELECT 4;
2537/// END IF
2538/// ```
2539/// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#if)
2540/// [Snowflake](https://docs.snowflake.com/en/sql-reference/snowflake-scripting/if)
2541///
2542/// Example (MSSQL):
2543/// ```sql
2544/// IF 1=1 SELECT 1 ELSE SELECT 2
2545/// ```
2546/// [MSSQL](https://learn.microsoft.com/en-us/sql/t-sql/language-elements/if-else-transact-sql?view=sql-server-ver16)
2547#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2548#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2549#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2550pub struct IfStatement {
2551    /// The initial `IF` block containing the condition and statements.
2552    pub if_block: ConditionalStatementBlock,
2553    /// Additional `ELSEIF` blocks.
2554    pub elseif_blocks: Vec<ConditionalStatementBlock>,
2555    /// Optional `ELSE` block.
2556    pub else_block: Option<ConditionalStatementBlock>,
2557    /// Optional trailing `END` token for the `IF` statement.
2558    pub end_token: Option<AttachedToken>,
2559}
2560
2561impl fmt::Display for IfStatement {
2562    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2563        let IfStatement {
2564            if_block,
2565            elseif_blocks,
2566            else_block,
2567            end_token,
2568        } = self;
2569
2570        write!(f, "{if_block}")?;
2571
2572        for elseif_block in elseif_blocks {
2573            write!(f, " {elseif_block}")?;
2574        }
2575
2576        if let Some(else_block) = else_block {
2577            write!(f, " {else_block}")?;
2578        }
2579
2580        if let Some(AttachedToken(end_token)) = end_token {
2581            write!(f, " END {end_token}")?;
2582        }
2583
2584        Ok(())
2585    }
2586}
2587
2588/// A `WHILE` statement.
2589///
2590/// Example:
2591/// ```sql
2592/// WHILE @@FETCH_STATUS = 0
2593/// BEGIN
2594///    FETCH NEXT FROM c1 INTO @var1, @var2;
2595/// END
2596/// ```
2597///
2598/// [MsSql](https://learn.microsoft.com/en-us/sql/t-sql/language-elements/while-transact-sql)
2599#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2600#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2601#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2602pub struct WhileStatement {
2603    /// Block executed while the condition holds.
2604    pub while_block: ConditionalStatementBlock,
2605}
2606
2607impl fmt::Display for WhileStatement {
2608    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2609        let WhileStatement { while_block } = self;
2610        write!(f, "{while_block}")?;
2611        Ok(())
2612    }
2613}
2614
2615/// A block within a [Statement::Case] or [Statement::If] or [Statement::While]-like statement
2616///
2617/// Example 1:
2618/// ```sql
2619/// WHEN EXISTS(SELECT 1) THEN SELECT 1;
2620/// ```
2621///
2622/// Example 2:
2623/// ```sql
2624/// IF TRUE THEN SELECT 1; SELECT 2;
2625/// ```
2626///
2627/// Example 3:
2628/// ```sql
2629/// ELSE SELECT 1; SELECT 2;
2630/// ```
2631///
2632/// Example 4:
2633/// ```sql
2634/// WHILE @@FETCH_STATUS = 0
2635/// BEGIN
2636///    FETCH NEXT FROM c1 INTO @var1, @var2;
2637/// END
2638/// ```
2639#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2640#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2641#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2642pub struct ConditionalStatementBlock {
2643    /// Token representing the start of the block (e.g., WHEN/IF/WHILE).
2644    pub start_token: AttachedToken,
2645    /// Optional condition expression for the block.
2646    pub condition: Option<Expr>,
2647    /// Optional token for the `THEN` keyword.
2648    pub then_token: Option<AttachedToken>,
2649    /// The statements contained in this conditional block.
2650    pub conditional_statements: ConditionalStatements,
2651}
2652
2653impl ConditionalStatementBlock {
2654    /// Get the statements in this conditional block.
2655    pub fn statements(&self) -> &Vec<Statement> {
2656        self.conditional_statements.statements()
2657    }
2658}
2659
2660impl fmt::Display for ConditionalStatementBlock {
2661    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2662        let ConditionalStatementBlock {
2663            start_token: AttachedToken(start_token),
2664            condition,
2665            then_token,
2666            conditional_statements,
2667        } = self;
2668
2669        write!(f, "{start_token}")?;
2670
2671        if let Some(condition) = condition {
2672            write!(f, " {condition}")?;
2673        }
2674
2675        if then_token.is_some() {
2676            write!(f, " THEN")?;
2677        }
2678
2679        if !conditional_statements.statements().is_empty() {
2680            write!(f, " {conditional_statements}")?;
2681        }
2682
2683        Ok(())
2684    }
2685}
2686
2687/// A list of statements in a [ConditionalStatementBlock].
2688#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2689#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2690#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2691/// Statements used inside conditional blocks (`IF`, `WHEN`, `WHILE`).
2692pub enum ConditionalStatements {
2693    /// Simple sequence of statements (no `BEGIN`/`END`).
2694    Sequence {
2695        /// The statements in the sequence.
2696        statements: Vec<Statement>,
2697    },
2698    /// Block enclosed by `BEGIN` and `END`.
2699    BeginEnd(BeginEndStatements),
2700}
2701
2702impl ConditionalStatements {
2703    /// Get the statements in this conditional statements block.
2704    pub fn statements(&self) -> &Vec<Statement> {
2705        match self {
2706            ConditionalStatements::Sequence { statements } => statements,
2707            ConditionalStatements::BeginEnd(bes) => &bes.statements,
2708        }
2709    }
2710}
2711
2712impl fmt::Display for ConditionalStatements {
2713    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2714        match self {
2715            ConditionalStatements::Sequence { statements } => {
2716                if !statements.is_empty() {
2717                    format_statement_list(f, statements)?;
2718                }
2719                Ok(())
2720            }
2721            ConditionalStatements::BeginEnd(bes) => write!(f, "{bes}"),
2722        }
2723    }
2724}
2725
2726/// Represents a list of statements enclosed within `BEGIN` and `END` keywords.
2727/// Example:
2728/// ```sql
2729/// BEGIN
2730///     SELECT 1;
2731///     SELECT 2;
2732/// END
2733/// ```
2734#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2735#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2736#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2737pub struct BeginEndStatements {
2738    /// Token representing the `BEGIN` keyword (may include span info).
2739    pub begin_token: AttachedToken,
2740    /// Statements contained within the block.
2741    pub statements: Vec<Statement>,
2742    /// Token representing the `END` keyword (may include span info).
2743    pub end_token: AttachedToken,
2744}
2745
2746impl fmt::Display for BeginEndStatements {
2747    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2748        let BeginEndStatements {
2749            begin_token: AttachedToken(begin_token),
2750            statements,
2751            end_token: AttachedToken(end_token),
2752        } = self;
2753
2754        if begin_token.token != Token::EOF {
2755            write!(f, "{begin_token} ")?;
2756        }
2757        if !statements.is_empty() {
2758            format_statement_list(f, statements)?;
2759        }
2760        if end_token.token != Token::EOF {
2761            write!(f, " {end_token}")?;
2762        }
2763        Ok(())
2764    }
2765}
2766
2767/// A `RAISE` statement.
2768///
2769/// Examples:
2770/// ```sql
2771/// RAISE USING MESSAGE = 'error';
2772///
2773/// RAISE myerror;
2774/// ```
2775///
2776/// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#raise)
2777/// [Snowflake](https://docs.snowflake.com/en/sql-reference/snowflake-scripting/raise)
2778#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2779#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2780#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2781pub struct RaiseStatement {
2782    /// Optional value provided to the RAISE statement.
2783    pub value: Option<RaiseStatementValue>,
2784}
2785
2786impl fmt::Display for RaiseStatement {
2787    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2788        let RaiseStatement { value } = self;
2789
2790        write!(f, "RAISE")?;
2791        if let Some(value) = value {
2792            write!(f, " {value}")?;
2793        }
2794
2795        Ok(())
2796    }
2797}
2798
2799/// Represents the error value of a [RaiseStatement].
2800#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2801#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2802#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2803pub enum RaiseStatementValue {
2804    /// `RAISE USING MESSAGE = 'error'`
2805    UsingMessage(Expr),
2806    /// `RAISE myerror`
2807    Expr(Expr),
2808}
2809
2810impl fmt::Display for RaiseStatementValue {
2811    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2812        match self {
2813            RaiseStatementValue::Expr(expr) => write!(f, "{expr}"),
2814            RaiseStatementValue::UsingMessage(expr) => write!(f, "USING MESSAGE = {expr}"),
2815        }
2816    }
2817}
2818
2819/// Represents an expression assignment within a variable `DECLARE` statement.
2820///
2821/// Examples:
2822/// ```sql
2823/// DECLARE variable_name := 42
2824/// DECLARE variable_name DEFAULT 42
2825/// ```
2826#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2827#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2828#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2829pub enum DeclareAssignment {
2830    /// Plain expression specified.
2831    Expr(Box<Expr>),
2832
2833    /// Expression assigned via the `DEFAULT` keyword
2834    Default(Box<Expr>),
2835
2836    /// Expression assigned via the `:=` syntax
2837    ///
2838    /// Example:
2839    /// ```sql
2840    /// DECLARE variable_name := 42;
2841    /// ```
2842    DuckAssignment(Box<Expr>),
2843
2844    /// Expression via the `FOR` keyword
2845    ///
2846    /// Example:
2847    /// ```sql
2848    /// DECLARE c1 CURSOR FOR res
2849    /// ```
2850    For(Box<Expr>),
2851
2852    /// Expression via the `=` syntax.
2853    ///
2854    /// Example:
2855    /// ```sql
2856    /// DECLARE @variable AS INT = 100
2857    /// ```
2858    MsSqlAssignment(Box<Expr>),
2859}
2860
2861impl fmt::Display for DeclareAssignment {
2862    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2863        match self {
2864            DeclareAssignment::Expr(expr) => {
2865                write!(f, "{expr}")
2866            }
2867            DeclareAssignment::Default(expr) => {
2868                write!(f, "DEFAULT {expr}")
2869            }
2870            DeclareAssignment::DuckAssignment(expr) => {
2871                write!(f, ":= {expr}")
2872            }
2873            DeclareAssignment::MsSqlAssignment(expr) => {
2874                write!(f, "= {expr}")
2875            }
2876            DeclareAssignment::For(expr) => {
2877                write!(f, "FOR {expr}")
2878            }
2879        }
2880    }
2881}
2882
2883/// Represents the type of a `DECLARE` statement.
2884#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2885#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2886#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2887pub enum DeclareType {
2888    /// Cursor variable type. e.g. [Snowflake] [PostgreSQL] [MsSql]
2889    ///
2890    /// [Snowflake]: https://docs.snowflake.com/en/developer-guide/snowflake-scripting/cursors#declaring-a-cursor
2891    /// [PostgreSQL]: https://www.postgresql.org/docs/current/plpgsql-cursors.html
2892    /// [MsSql]: https://learn.microsoft.com/en-us/sql/t-sql/language-elements/declare-cursor-transact-sql
2893    Cursor,
2894
2895    /// Result set variable type. [Snowflake]
2896    ///
2897    /// Syntax:
2898    /// ```text
2899    /// <resultset_name> RESULTSET [ { DEFAULT | := } ( <query> ) ] ;
2900    /// ```
2901    /// [Snowflake]: https://docs.snowflake.com/en/sql-reference/snowflake-scripting/declare#resultset-declaration-syntax
2902    ResultSet,
2903
2904    /// Exception declaration syntax. [Snowflake]
2905    ///
2906    /// Syntax:
2907    /// ```text
2908    /// <exception_name> EXCEPTION [ ( <exception_number> , '<exception_message>' ) ] ;
2909    /// ```
2910    /// [Snowflake]: https://docs.snowflake.com/en/sql-reference/snowflake-scripting/declare#exception-declaration-syntax
2911    Exception,
2912}
2913
2914impl fmt::Display for DeclareType {
2915    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2916        match self {
2917            DeclareType::Cursor => {
2918                write!(f, "CURSOR")
2919            }
2920            DeclareType::ResultSet => {
2921                write!(f, "RESULTSET")
2922            }
2923            DeclareType::Exception => {
2924                write!(f, "EXCEPTION")
2925            }
2926        }
2927    }
2928}
2929
2930/// A `DECLARE` statement.
2931/// [PostgreSQL] [Snowflake] [BigQuery]
2932///
2933/// Examples:
2934/// ```sql
2935/// DECLARE variable_name := 42
2936/// DECLARE liahona CURSOR FOR SELECT * FROM films;
2937/// ```
2938///
2939/// [PostgreSQL]: https://www.postgresql.org/docs/current/sql-declare.html
2940/// [Snowflake]: https://docs.snowflake.com/en/sql-reference/snowflake-scripting/declare
2941/// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#declare
2942#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2943#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2944#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2945pub struct Declare {
2946    /// The name(s) being declared.
2947    /// Example: `DECLARE a, b, c DEFAULT 42;
2948    pub names: Vec<Ident>,
2949    /// Data-type assigned to the declared variable.
2950    /// Example: `DECLARE x INT64 DEFAULT 42;
2951    pub data_type: Option<DataType>,
2952    /// Expression being assigned to the declared variable.
2953    pub assignment: Option<DeclareAssignment>,
2954    /// Represents the type of the declared variable.
2955    pub declare_type: Option<DeclareType>,
2956    /// Causes the cursor to return data in binary rather than in text format.
2957    pub binary: Option<bool>,
2958    /// None = Not specified
2959    /// Some(true) = INSENSITIVE
2960    /// Some(false) = ASENSITIVE
2961    pub sensitive: Option<bool>,
2962    /// None = Not specified
2963    /// Some(true) = SCROLL
2964    /// Some(false) = NO SCROLL
2965    pub scroll: Option<bool>,
2966    /// None = Not specified
2967    /// Some(true) = WITH HOLD, specifies that the cursor can continue to be used after the transaction that created it successfully commits
2968    /// Some(false) = WITHOUT HOLD, specifies that the cursor cannot be used outside of the transaction that created it
2969    pub hold: Option<bool>,
2970    /// `FOR <query>` clause in a CURSOR declaration.
2971    pub for_query: Option<Box<Query>>,
2972}
2973
2974impl fmt::Display for Declare {
2975    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2976        let Declare {
2977            names,
2978            data_type,
2979            assignment,
2980            declare_type,
2981            binary,
2982            sensitive,
2983            scroll,
2984            hold,
2985            for_query,
2986        } = self;
2987        write!(f, "{}", display_comma_separated(names))?;
2988
2989        if let Some(true) = binary {
2990            write!(f, " BINARY")?;
2991        }
2992
2993        if let Some(sensitive) = sensitive {
2994            if *sensitive {
2995                write!(f, " INSENSITIVE")?;
2996            } else {
2997                write!(f, " ASENSITIVE")?;
2998            }
2999        }
3000
3001        if let Some(scroll) = scroll {
3002            if *scroll {
3003                write!(f, " SCROLL")?;
3004            } else {
3005                write!(f, " NO SCROLL")?;
3006            }
3007        }
3008
3009        if let Some(declare_type) = declare_type {
3010            write!(f, " {declare_type}")?;
3011        }
3012
3013        if let Some(hold) = hold {
3014            if *hold {
3015                write!(f, " WITH HOLD")?;
3016            } else {
3017                write!(f, " WITHOUT HOLD")?;
3018            }
3019        }
3020
3021        if let Some(query) = for_query {
3022            write!(f, " FOR {query}")?;
3023        }
3024
3025        if let Some(data_type) = data_type {
3026            write!(f, " {data_type}")?;
3027        }
3028
3029        if let Some(expr) = assignment {
3030            write!(f, " {expr}")?;
3031        }
3032        Ok(())
3033    }
3034}
3035
3036/// Sql options of a `CREATE TABLE` statement.
3037#[derive(Debug, Default, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3038#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3039#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3040/// Options allowed within a `CREATE TABLE` statement.
3041pub enum CreateTableOptions {
3042    /// No options specified.
3043    #[default]
3044    None,
3045    /// Options specified using the `WITH` keyword, e.g. `WITH (k = v)`.
3046    With(Vec<SqlOption>),
3047    /// Options specified using the `OPTIONS(...)` clause.
3048    Options(Vec<SqlOption>),
3049    /// Plain space-separated options.
3050    Plain(Vec<SqlOption>),
3051    /// Table properties (e.g., TBLPROPERTIES / storage properties).
3052    TableProperties(Vec<SqlOption>),
3053}
3054
3055impl fmt::Display for CreateTableOptions {
3056    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3057        match self {
3058            CreateTableOptions::With(with_options) => {
3059                write!(f, "WITH ({})", display_comma_separated(with_options))
3060            }
3061            CreateTableOptions::Options(options) => {
3062                write!(f, "OPTIONS({})", display_comma_separated(options))
3063            }
3064            CreateTableOptions::TableProperties(options) => {
3065                write!(f, "TBLPROPERTIES ({})", display_comma_separated(options))
3066            }
3067            CreateTableOptions::Plain(options) => {
3068                write!(f, "{}", display_separated(options, " "))
3069            }
3070            CreateTableOptions::None => Ok(()),
3071        }
3072    }
3073}
3074
3075/// A `FROM` clause within a `DELETE` statement.
3076///
3077/// Syntax
3078/// ```sql
3079/// [FROM] table
3080/// ```
3081#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3082#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3083#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3084pub enum FromTable {
3085    /// An explicit `FROM` keyword was specified.
3086    WithFromKeyword(Vec<TableWithJoins>),
3087    /// BigQuery: `FROM` keyword was omitted.
3088    /// <https://cloud.google.com/bigquery/docs/reference/standard-sql/dml-syntax#delete_statement>
3089    WithoutKeyword(Vec<TableWithJoins>),
3090}
3091impl Display for FromTable {
3092    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3093        match self {
3094            FromTable::WithFromKeyword(tables) => {
3095                write!(f, "FROM {}", display_comma_separated(tables))
3096            }
3097            FromTable::WithoutKeyword(tables) => {
3098                write!(f, "{}", display_comma_separated(tables))
3099            }
3100        }
3101    }
3102}
3103
3104#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3105#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3106#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3107/// Variants for the `SET` family of statements.
3108pub enum Set {
3109    /// SQL Standard-style
3110    /// SET a = 1;
3111    /// `SET var = value` (standard SQL-style assignment).
3112    SingleAssignment {
3113        /// Optional scope modifier (`SESSION` / `LOCAL`).
3114        scope: Option<ContextModifier>,
3115        /// Whether this is a Hive-style `HIVEVAR:` assignment.
3116        hivevar: bool,
3117        /// Variable name to assign.
3118        variable: ObjectName,
3119        /// Values assigned to the variable.
3120        values: Vec<Expr>,
3121    },
3122    /// Snowflake-style
3123    /// SET (a, b, ..) = (1, 2, ..);
3124    /// `SET (a, b) = (1, 2)` (tuple assignment syntax).
3125    ParenthesizedAssignments {
3126        /// Variables being assigned in tuple form.
3127        variables: Vec<ObjectName>,
3128        /// Corresponding values for the variables.
3129        values: Vec<Expr>,
3130    },
3131    /// MySQL-style
3132    /// SET a = 1, b = 2, ..;
3133    /// `SET a = 1, b = 2` (MySQL-style comma-separated assignments).
3134    MultipleAssignments {
3135        /// List of `SET` assignments (MySQL-style comma-separated).
3136        assignments: Vec<SetAssignment>,
3137    },
3138    /// Session authorization for Postgres/Redshift
3139    ///
3140    /// ```sql
3141    /// SET SESSION AUTHORIZATION { user_name | DEFAULT }
3142    /// ```
3143    ///
3144    /// See <https://www.postgresql.org/docs/current/sql-set-session-authorization.html>
3145    /// See <https://docs.aws.amazon.com/redshift/latest/dg/r_SET_SESSION_AUTHORIZATION.html>
3146    SetSessionAuthorization(SetSessionAuthorizationParam),
3147    /// MS-SQL session
3148    ///
3149    /// See <https://learn.microsoft.com/en-us/sql/t-sql/statements/set-statements-transact-sql>
3150    SetSessionParam(SetSessionParamKind),
3151    /// ```sql
3152    /// SET [ SESSION | LOCAL ] ROLE role_name
3153    /// ```
3154    ///
3155    /// Sets session state. Examples: [ANSI][1], [Postgresql][2], [MySQL][3], and [Oracle][4]
3156    ///
3157    /// [1]: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#set-role-statement
3158    /// [2]: https://www.postgresql.org/docs/14/sql-set-role.html
3159    /// [3]: https://dev.mysql.com/doc/refman/8.0/en/set-role.html
3160    /// [4]: https://docs.oracle.com/cd/B19306_01/server.102/b14200/statements_10004.htm
3161    SetRole {
3162        /// Non-ANSI optional identifier to inform if the role is defined inside the current session (`SESSION`) or transaction (`LOCAL`).
3163        context_modifier: Option<ContextModifier>,
3164        /// Role name. If NONE is specified, then the current role name is removed.
3165        role_name: Option<Ident>,
3166    },
3167    /// ```sql
3168    /// SET TIME ZONE <value>
3169    /// ```
3170    ///
3171    /// Note: this is a PostgreSQL-specific statements
3172    /// `SET TIME ZONE <value>` is an alias for `SET timezone TO <value>` in PostgreSQL
3173    /// However, we allow it for all dialects.
3174    /// `SET TIME ZONE` statement. `local` indicates the `LOCAL` keyword.
3175    /// `SET TIME ZONE <value>` statement.
3176    SetTimeZone {
3177        /// Whether the `LOCAL` keyword was specified.
3178        local: bool,
3179        /// Time zone expression value.
3180        value: Expr,
3181    },
3182    /// ```sql
3183    /// SET NAMES 'charset_name' [COLLATE 'collation_name']
3184    /// ```
3185    SetNames {
3186        /// Character set name to set.
3187        charset_name: Ident,
3188        /// Optional collation name.
3189        collation_name: Option<String>,
3190    },
3191    /// ```sql
3192    /// SET NAMES DEFAULT
3193    /// ```
3194    ///
3195    /// Note: this is a MySQL-specific statement.
3196    SetNamesDefault {},
3197    /// ```sql
3198    /// SET TRANSACTION ...
3199    /// ```
3200    SetTransaction {
3201        /// Transaction modes (e.g., ISOLATION LEVEL, READ ONLY).
3202        modes: Vec<TransactionMode>,
3203        /// Optional snapshot value for transaction snapshot control.
3204        snapshot: Option<Value>,
3205        /// `true` when the `SESSION` keyword was used.
3206        session: bool,
3207    },
3208}
3209
3210impl Display for Set {
3211    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3212        match self {
3213            Self::ParenthesizedAssignments { variables, values } => write!(
3214                f,
3215                "SET ({}) = ({})",
3216                display_comma_separated(variables),
3217                display_comma_separated(values)
3218            ),
3219            Self::MultipleAssignments { assignments } => {
3220                write!(f, "SET {}", display_comma_separated(assignments))
3221            }
3222            Self::SetRole {
3223                context_modifier,
3224                role_name,
3225            } => {
3226                let role_name = role_name.clone().unwrap_or_else(|| Ident::new("NONE"));
3227                write!(
3228                    f,
3229                    "SET {modifier}ROLE {role_name}",
3230                    modifier = context_modifier.map(|m| format!("{m}")).unwrap_or_default()
3231                )
3232            }
3233            Self::SetSessionAuthorization(kind) => write!(f, "SET SESSION AUTHORIZATION {kind}"),
3234            Self::SetSessionParam(kind) => write!(f, "SET {kind}"),
3235            Self::SetTransaction {
3236                modes,
3237                snapshot,
3238                session,
3239            } => {
3240                if *session {
3241                    write!(f, "SET SESSION CHARACTERISTICS AS TRANSACTION")?;
3242                } else {
3243                    write!(f, "SET TRANSACTION")?;
3244                }
3245                if !modes.is_empty() {
3246                    write!(f, " {}", display_comma_separated(modes))?;
3247                }
3248                if let Some(snapshot_id) = snapshot {
3249                    write!(f, " SNAPSHOT {snapshot_id}")?;
3250                }
3251                Ok(())
3252            }
3253            Self::SetTimeZone { local, value } => {
3254                f.write_str("SET ")?;
3255                if *local {
3256                    f.write_str("LOCAL ")?;
3257                }
3258                write!(f, "TIME ZONE {value}")
3259            }
3260            Self::SetNames {
3261                charset_name,
3262                collation_name,
3263            } => {
3264                write!(f, "SET NAMES {charset_name}")?;
3265
3266                if let Some(collation) = collation_name {
3267                    f.write_str(" COLLATE ")?;
3268                    f.write_str(collation)?;
3269                };
3270
3271                Ok(())
3272            }
3273            Self::SetNamesDefault {} => {
3274                f.write_str("SET NAMES DEFAULT")?;
3275
3276                Ok(())
3277            }
3278            Set::SingleAssignment {
3279                scope,
3280                hivevar,
3281                variable,
3282                values,
3283            } => {
3284                write!(
3285                    f,
3286                    "SET {}{}{} = {}",
3287                    scope.map(|s| format!("{s}")).unwrap_or_default(),
3288                    if *hivevar { "HIVEVAR:" } else { "" },
3289                    variable,
3290                    display_comma_separated(values)
3291                )
3292            }
3293        }
3294    }
3295}
3296
3297/// A representation of a `WHEN` arm with all the identifiers catched and the statements to execute
3298/// for the arm.
3299///
3300/// Snowflake: <https://docs.snowflake.com/en/sql-reference/snowflake-scripting/exception>
3301/// BigQuery: <https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#beginexceptionend>
3302#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3303#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3304#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3305pub struct ExceptionWhen {
3306    /// Identifiers that trigger this branch (error conditions).
3307    pub idents: Vec<Ident>,
3308    /// Statements to execute when the condition matches.
3309    pub statements: Vec<Statement>,
3310}
3311
3312impl Display for ExceptionWhen {
3313    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3314        write!(
3315            f,
3316            "WHEN {idents} THEN",
3317            idents = display_separated(&self.idents, " OR ")
3318        )?;
3319
3320        if !self.statements.is_empty() {
3321            write!(f, " ")?;
3322            format_statement_list(f, &self.statements)?;
3323        }
3324
3325        Ok(())
3326    }
3327}
3328
3329/// ANALYZE statement
3330///
3331/// Supported syntax varies by dialect:
3332/// - Hive: `ANALYZE TABLE t [PARTITION (...)] COMPUTE STATISTICS [NOSCAN] [FOR COLUMNS [col1, ...]] [CACHE METADATA]`
3333/// - PostgreSQL: `ANALYZE [VERBOSE] [t [(col1, ...)]]` See <https://www.postgresql.org/docs/current/sql-analyze.html>
3334/// - General: `ANALYZE [TABLE] t`
3335#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3336#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3337#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3338pub struct Analyze {
3339    #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
3340    /// Name of the table to analyze. `None` for bare `ANALYZE`.
3341    pub table_name: Option<ObjectName>,
3342    /// Optional partition expressions to restrict the analysis.
3343    pub partitions: Option<Vec<Expr>>,
3344    /// `true` when analyzing specific columns (Hive `FOR COLUMNS` syntax).
3345    pub for_columns: bool,
3346    /// Columns to analyze.
3347    pub columns: Vec<Ident>,
3348    /// Whether to cache metadata before analyzing.
3349    pub cache_metadata: bool,
3350    /// Whether to skip scanning the table.
3351    pub noscan: bool,
3352    /// Whether to compute statistics during analysis.
3353    pub compute_statistics: bool,
3354    /// Whether the `TABLE` keyword was present.
3355    pub has_table_keyword: bool,
3356}
3357
3358impl fmt::Display for Analyze {
3359    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3360        write!(f, "ANALYZE")?;
3361        if let Some(ref table_name) = self.table_name {
3362            if self.has_table_keyword {
3363                write!(f, " TABLE")?;
3364            }
3365            write!(f, " {table_name}")?;
3366        }
3367        if !self.for_columns && !self.columns.is_empty() {
3368            write!(f, " ({})", display_comma_separated(&self.columns))?;
3369        }
3370        if let Some(ref parts) = self.partitions {
3371            if !parts.is_empty() {
3372                write!(f, " PARTITION ({})", display_comma_separated(parts))?;
3373            }
3374        }
3375        if self.compute_statistics {
3376            write!(f, " COMPUTE STATISTICS")?;
3377        }
3378        if self.noscan {
3379            write!(f, " NOSCAN")?;
3380        }
3381        if self.cache_metadata {
3382            write!(f, " CACHE METADATA")?;
3383        }
3384        if self.for_columns {
3385            write!(f, " FOR COLUMNS")?;
3386            if !self.columns.is_empty() {
3387                write!(f, " {}", display_comma_separated(&self.columns))?;
3388            }
3389        }
3390        Ok(())
3391    }
3392}
3393
3394/// A top-level statement (SELECT, INSERT, CREATE, etc.)
3395#[allow(clippy::large_enum_variant)]
3396#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3397#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3398#[cfg_attr(
3399    feature = "visitor",
3400    derive(Visit, VisitMut),
3401    visit(with = "visit_statement")
3402)]
3403pub enum Statement {
3404    /// ```sql
3405    /// ANALYZE
3406    /// ```
3407    /// Analyze (Hive)
3408    Analyze(Analyze),
3409    /// `SET` statements (session, transaction, timezone, etc.).
3410    Set(Set),
3411    /// ```sql
3412    /// TRUNCATE
3413    /// ```
3414    /// Truncate (Hive)
3415    Truncate(Truncate),
3416    /// ```sql
3417    /// MSCK
3418    /// ```
3419    /// Msck (Hive)
3420    Msck(Msck),
3421    /// ```sql
3422    /// SELECT
3423    /// ```
3424    Query(Box<Query>),
3425    /// ```sql
3426    /// INSERT
3427    /// ```
3428    Insert(Insert),
3429    /// ```sql
3430    /// INSTALL
3431    /// ```
3432    Install {
3433        /// Only for DuckDB
3434        extension_name: Ident,
3435    },
3436    /// ```sql
3437    /// LOAD
3438    /// ```
3439    Load {
3440        /// Only for DuckDB
3441        extension_name: Ident,
3442    },
3443    // TODO: Support ROW FORMAT
3444    /// LOAD DATA from a directory or query source.
3445    Directory {
3446        /// Whether to overwrite existing files.
3447        overwrite: bool,
3448        /// Whether the directory is local to the server.
3449        local: bool,
3450        /// Path to the directory or files.
3451        path: String,
3452        /// Optional file format for the data.
3453        file_format: Option<FileFormat>,
3454        /// Source query providing data to load.
3455        source: Box<Query>,
3456    },
3457    /// A `CASE` statement.
3458    Case(CaseStatement),
3459    /// An `IF` statement.
3460    If(IfStatement),
3461    /// A `WHILE` statement.
3462    While(WhileStatement),
3463    /// A `RAISE` statement.
3464    Raise(RaiseStatement),
3465    /// ```sql
3466    /// CALL <function>
3467    /// ```
3468    Call(Function),
3469    /// ```sql
3470    /// COPY [TO | FROM] ...
3471    /// ```
3472    Copy {
3473        /// The source of 'COPY TO', or the target of 'COPY FROM'
3474        source: CopySource,
3475        /// If true, is a 'COPY TO' statement. If false is a 'COPY FROM'
3476        to: bool,
3477        /// The target of 'COPY TO', or the source of 'COPY FROM'
3478        target: CopyTarget,
3479        /// WITH options (from PostgreSQL version 9.0)
3480        options: Vec<CopyOption>,
3481        /// WITH options (before PostgreSQL version 9.0)
3482        legacy_options: Vec<CopyLegacyOption>,
3483        /// VALUES a vector of values to be copied
3484        values: Vec<Option<String>>,
3485    },
3486    /// ```sql
3487    /// COPY INTO <table> | <location>
3488    /// ```
3489    /// See:
3490    /// <https://docs.snowflake.com/en/sql-reference/sql/copy-into-table>
3491    /// <https://docs.snowflake.com/en/sql-reference/sql/copy-into-location>
3492    ///
3493    /// Copy Into syntax available for Snowflake is different than the one implemented in
3494    /// Postgres. Although they share common prefix, it is reasonable to implement them
3495    /// in different enums. This can be refactored later once custom dialects
3496    /// are allowed to have custom Statements.
3497    CopyIntoSnowflake {
3498        /// Kind of COPY INTO operation (table or location).
3499        kind: CopyIntoSnowflakeKind,
3500        /// Target object for the COPY INTO operation.
3501        into: ObjectName,
3502        /// Optional list of target columns.
3503        into_columns: Option<Vec<Ident>>,
3504        /// Optional source object name (staged data).
3505        from_obj: Option<ObjectName>,
3506        /// Optional alias for the source object.
3507        from_obj_alias: Option<Ident>,
3508        /// Stage-specific parameters (e.g., credentials, path).
3509        stage_params: StageParamsObject,
3510        /// Optional list of transformations applied when loading.
3511        from_transformations: Option<Vec<StageLoadSelectItemKind>>,
3512        /// Optional source query instead of a staged object.
3513        from_query: Option<Box<Query>>,
3514        /// Optional list of specific file names to load.
3515        files: Option<Vec<String>>,
3516        /// Optional filename matching pattern.
3517        pattern: Option<String>,
3518        /// File format options.
3519        file_format: KeyValueOptions,
3520        /// Additional copy options.
3521        copy_options: KeyValueOptions,
3522        /// Optional validation mode string.
3523        validation_mode: Option<String>,
3524        /// Optional partition expression for loading.
3525        partition: Option<Box<Expr>>,
3526    },
3527    /// ```sql
3528    /// OPEN cursor_name
3529    /// ```
3530    /// Opens a cursor.
3531    Open(OpenStatement),
3532    /// ```sql
3533    /// CLOSE
3534    /// ```
3535    /// Closes the portal underlying an open cursor.
3536    Close {
3537        /// Cursor name
3538        cursor: CloseCursor,
3539    },
3540    /// ```sql
3541    /// UPDATE
3542    /// ```
3543    Update(Update),
3544    /// ```sql
3545    /// DELETE
3546    /// ```
3547    Delete(Delete),
3548    /// ```sql
3549    /// CREATE VIEW
3550    /// ```
3551    CreateView(CreateView),
3552    /// ```sql
3553    /// CREATE TABLE
3554    /// ```
3555    CreateTable(CreateTable),
3556    /// ```sql
3557    /// CREATE VIRTUAL TABLE .. USING <module_name> (<module_args>)`
3558    /// ```
3559    /// Sqlite specific statement
3560    CreateVirtualTable {
3561        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
3562        /// Name of the virtual table module instance.
3563        name: ObjectName,
3564        /// `true` when `IF NOT EXISTS` was specified.
3565        if_not_exists: bool,
3566        /// Module name used by the virtual table.
3567        module_name: Ident,
3568        /// Arguments passed to the module.
3569        module_args: Vec<Ident>,
3570    },
3571    /// ```sql
3572    /// `CREATE INDEX`
3573    /// ```
3574    CreateIndex(CreateIndex),
3575    /// ```sql
3576    /// CREATE ROLE
3577    /// ```
3578    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createrole.html)
3579    CreateRole(CreateRole),
3580    /// ```sql
3581    /// CREATE SECRET
3582    /// ```
3583    /// See [DuckDB](https://duckdb.org/docs/sql/statements/create_secret.html)
3584    CreateSecret {
3585        /// `true` when `OR REPLACE` was specified.
3586        or_replace: bool,
3587        /// Optional `TEMPORARY` flag.
3588        temporary: Option<bool>,
3589        /// `true` when `IF NOT EXISTS` was present.
3590        if_not_exists: bool,
3591        /// Optional secret name.
3592        name: Option<Ident>,
3593        /// Optional storage specifier identifier.
3594        storage_specifier: Option<Ident>,
3595        /// The secret type identifier.
3596        secret_type: Ident,
3597        /// Additional secret options.
3598        options: Vec<SecretOption>,
3599    },
3600    /// A `CREATE SERVER` statement.
3601    CreateServer(CreateServerStatement),
3602    /// ```sql
3603    /// CREATE POLICY
3604    /// ```
3605    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createpolicy.html)
3606    CreatePolicy(CreatePolicy),
3607    /// ```sql
3608    /// CREATE CONNECTOR
3609    /// ```
3610    /// See [Hive](https://cwiki.apache.org/confluence/pages/viewpage.action?pageId=27362034#LanguageManualDDL-CreateDataConnectorCreateConnector)
3611    CreateConnector(CreateConnector),
3612    /// ```sql
3613    /// CREATE OPERATOR
3614    /// ```
3615    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createoperator.html)
3616    CreateOperator(CreateOperator),
3617    /// ```sql
3618    /// CREATE OPERATOR FAMILY
3619    /// ```
3620    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createopfamily.html)
3621    CreateOperatorFamily(CreateOperatorFamily),
3622    /// ```sql
3623    /// CREATE OPERATOR CLASS
3624    /// ```
3625    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createopclass.html)
3626    CreateOperatorClass(CreateOperatorClass),
3627    /// ```sql
3628    /// ALTER TABLE
3629    /// ```
3630    AlterTable(AlterTable),
3631    /// ```sql
3632    /// ALTER SCHEMA
3633    /// ```
3634    /// See [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#alter_schema_collate_statement)
3635    AlterSchema(AlterSchema),
3636    /// ```sql
3637    /// ALTER INDEX
3638    /// ```
3639    AlterIndex {
3640        /// Name of the index to alter.
3641        name: ObjectName,
3642        /// The operation to perform on the index.
3643        operation: AlterIndexOperation,
3644    },
3645    /// ```sql
3646    /// ALTER VIEW
3647    /// ```
3648    AlterView {
3649        /// View name being altered.
3650        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
3651        name: ObjectName,
3652        /// Optional new column list for the view.
3653        columns: Vec<Ident>,
3654        /// Replacement query for the view definition.
3655        query: Box<Query>,
3656        /// Additional WITH options for the view.
3657        with_options: Vec<SqlOption>,
3658    },
3659    /// ```sql
3660    /// ALTER TYPE
3661    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-altertype.html)
3662    /// ```
3663    AlterType(AlterType),
3664    /// ```sql
3665    /// ALTER OPERATOR
3666    /// ```
3667    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-alteroperator.html)
3668    AlterOperator(AlterOperator),
3669    /// ```sql
3670    /// ALTER OPERATOR FAMILY
3671    /// ```
3672    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-alteropfamily.html)
3673    AlterOperatorFamily(AlterOperatorFamily),
3674    /// ```sql
3675    /// ALTER OPERATOR CLASS
3676    /// ```
3677    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-alteropclass.html)
3678    AlterOperatorClass(AlterOperatorClass),
3679    /// ```sql
3680    /// ALTER ROLE
3681    /// ```
3682    AlterRole {
3683        /// Role name being altered.
3684        name: Ident,
3685        /// Operation to perform on the role.
3686        operation: AlterRoleOperation,
3687    },
3688    /// ```sql
3689    /// ALTER POLICY <NAME> ON <TABLE NAME> [<OPERATION>]
3690    /// ```
3691    /// (Postgresql-specific)
3692    AlterPolicy(AlterPolicy),
3693    /// ```sql
3694    /// ALTER CONNECTOR connector_name SET DCPROPERTIES(property_name=property_value, ...);
3695    /// or
3696    /// ALTER CONNECTOR connector_name SET URL new_url;
3697    /// or
3698    /// ALTER CONNECTOR connector_name SET OWNER [USER|ROLE] user_or_role;
3699    /// ```
3700    /// (Hive-specific)
3701    AlterConnector {
3702        /// Name of the connector to alter.
3703        name: Ident,
3704        /// Optional connector properties to set.
3705        properties: Option<Vec<SqlOption>>,
3706        /// Optional new URL for the connector.
3707        url: Option<String>,
3708        /// Optional new owner specification.
3709        owner: Option<ddl::AlterConnectorOwner>,
3710    },
3711    /// ```sql
3712    /// ALTER SESSION SET sessionParam
3713    /// ALTER SESSION UNSET <param_name> [ , <param_name> , ... ]
3714    /// ```
3715    /// See <https://docs.snowflake.com/en/sql-reference/sql/alter-session>
3716    AlterSession {
3717        /// true is to set for the session parameters, false is to unset
3718        set: bool,
3719        /// The session parameters to set or unset
3720        session_params: KeyValueOptions,
3721    },
3722    /// ```sql
3723    /// ATTACH DATABASE 'path/to/file' AS alias
3724    /// ```
3725    /// (SQLite-specific)
3726    AttachDatabase {
3727        /// The name to bind to the newly attached database
3728        schema_name: Ident,
3729        /// An expression that indicates the path to the database file
3730        database_file_name: Expr,
3731        /// true if the syntax is 'ATTACH DATABASE', false if it's just 'ATTACH'
3732        database: bool,
3733    },
3734    /// (DuckDB-specific)
3735    /// ```sql
3736    /// ATTACH 'sqlite_file.db' AS sqlite_db (READ_ONLY, TYPE SQLITE);
3737    /// ```
3738    /// See <https://duckdb.org/docs/sql/statements/attach.html>
3739    AttachDuckDBDatabase {
3740        /// `true` when `IF NOT EXISTS` was present.
3741        if_not_exists: bool,
3742        /// `true` if the syntax used `ATTACH DATABASE` rather than `ATTACH`.
3743        database: bool,
3744        /// The path identifier to the database file being attached.
3745        database_path: Ident,
3746        /// Optional alias assigned to the attached database.
3747        database_alias: Option<Ident>,
3748        /// Dialect-specific attach options (e.g., `READ_ONLY`).
3749        attach_options: Vec<AttachDuckDBDatabaseOption>,
3750    },
3751    /// (DuckDB-specific)
3752    /// ```sql
3753    /// DETACH db_alias;
3754    /// ```
3755    /// See <https://duckdb.org/docs/sql/statements/attach.html>
3756    DetachDuckDBDatabase {
3757        /// `true` when `IF EXISTS` was present.
3758        if_exists: bool,
3759        /// `true` if the syntax used `DETACH DATABASE` rather than `DETACH`.
3760        database: bool,
3761        /// Alias of the database to detach.
3762        database_alias: Ident,
3763    },
3764    /// ```sql
3765    /// DROP [TABLE, VIEW, ...]
3766    /// ```
3767    Drop {
3768        /// The type of the object to drop: TABLE, VIEW, etc.
3769        object_type: ObjectType,
3770        /// An optional `IF EXISTS` clause. (Non-standard.)
3771        if_exists: bool,
3772        /// One or more objects to drop. (ANSI SQL requires exactly one.)
3773        names: Vec<ObjectName>,
3774        /// Whether `CASCADE` was specified. This will be `false` when
3775        /// `RESTRICT` or no drop behavior at all was specified.
3776        cascade: bool,
3777        /// Whether `RESTRICT` was specified. This will be `false` when
3778        /// `CASCADE` or no drop behavior at all was specified.
3779        restrict: bool,
3780        /// Hive allows you specify whether the table's stored data will be
3781        /// deleted along with the dropped table
3782        purge: bool,
3783        /// MySQL-specific "TEMPORARY" keyword
3784        temporary: bool,
3785        /// MySQL-specific drop index syntax, which requires table specification
3786        /// See <https://dev.mysql.com/doc/refman/8.4/en/drop-index.html>
3787        table: Option<ObjectName>,
3788    },
3789    /// ```sql
3790    /// DROP FUNCTION
3791    /// ```
3792    DropFunction(DropFunction),
3793    /// ```sql
3794    /// DROP DOMAIN
3795    /// ```
3796    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-dropdomain.html)
3797    ///
3798    /// DROP DOMAIN [ IF EXISTS ] name [, ...] [ CASCADE | RESTRICT ]
3799    ///
3800    DropDomain(DropDomain),
3801    /// ```sql
3802    /// DROP PROCEDURE
3803    /// ```
3804    DropProcedure {
3805        /// `true` when `IF EXISTS` was present.
3806        if_exists: bool,
3807        /// One or more functions/procedures to drop.
3808        proc_desc: Vec<FunctionDesc>,
3809        /// Optional drop behavior (`CASCADE` or `RESTRICT`).
3810        drop_behavior: Option<DropBehavior>,
3811    },
3812    /// ```sql
3813    /// DROP SECRET
3814    /// ```
3815    DropSecret {
3816        /// `true` when `IF EXISTS` was present.
3817        if_exists: bool,
3818        /// Optional `TEMPORARY` marker.
3819        temporary: Option<bool>,
3820        /// Name of the secret to drop.
3821        name: Ident,
3822        /// Optional storage specifier identifier.
3823        storage_specifier: Option<Ident>,
3824    },
3825    ///```sql
3826    /// DROP POLICY
3827    /// ```
3828    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-droppolicy.html)
3829    DropPolicy(DropPolicy),
3830    /// ```sql
3831    /// DROP CONNECTOR
3832    /// ```
3833    /// See [Hive](https://cwiki.apache.org/confluence/pages/viewpage.action?pageId=27362034#LanguageManualDDL-DropConnector)
3834    DropConnector {
3835        /// `true` when `IF EXISTS` was present.
3836        if_exists: bool,
3837        /// Name of the connector to drop.
3838        name: Ident,
3839    },
3840    /// ```sql
3841    /// DECLARE
3842    /// ```
3843    /// Declare Cursor Variables
3844    ///
3845    /// Note: this is a PostgreSQL-specific statement,
3846    /// but may also compatible with other SQL.
3847    Declare {
3848        /// Cursor declaration statements collected by `DECLARE`.
3849        stmts: Vec<Declare>,
3850    },
3851    /// ```sql
3852    /// CREATE EXTENSION [ IF NOT EXISTS ] extension_name
3853    ///     [ WITH ] [ SCHEMA schema_name ]
3854    ///              [ VERSION version ]
3855    ///              [ CASCADE ]
3856    /// ```
3857    ///
3858    /// Note: this is a PostgreSQL-specific statement,
3859    CreateExtension(CreateExtension),
3860    /// ```sql
3861    /// DROP EXTENSION [ IF EXISTS ] name [, ...] [ CASCADE | RESTRICT ]
3862    /// ```
3863    /// Note: this is a PostgreSQL-specific statement.
3864    /// <https://www.postgresql.org/docs/current/sql-dropextension.html>
3865    DropExtension(DropExtension),
3866    /// ```sql
3867    /// DROP OPERATOR [ IF EXISTS ] name ( { left_type | NONE } , right_type ) [, ...] [ CASCADE | RESTRICT ]
3868    /// ```
3869    /// Note: this is a PostgreSQL-specific statement.
3870    /// <https://www.postgresql.org/docs/current/sql-dropoperator.html>
3871    DropOperator(DropOperator),
3872    /// ```sql
3873    /// DROP OPERATOR FAMILY [ IF EXISTS ] name USING index_method [ CASCADE | RESTRICT ]
3874    /// ```
3875    /// Note: this is a PostgreSQL-specific statement.
3876    /// <https://www.postgresql.org/docs/current/sql-dropopfamily.html>
3877    DropOperatorFamily(DropOperatorFamily),
3878    /// ```sql
3879    /// DROP OPERATOR CLASS [ IF EXISTS ] name USING index_method [ CASCADE | RESTRICT ]
3880    /// ```
3881    /// Note: this is a PostgreSQL-specific statement.
3882    /// <https://www.postgresql.org/docs/current/sql-dropopclass.html>
3883    DropOperatorClass(DropOperatorClass),
3884    /// ```sql
3885    /// FETCH
3886    /// ```
3887    /// Retrieve rows from a query using a cursor
3888    ///
3889    /// Note: this is a PostgreSQL-specific statement,
3890    /// but may also compatible with other SQL.
3891    Fetch {
3892        /// Cursor name
3893        name: Ident,
3894        /// The fetch direction (e.g., `FORWARD`, `BACKWARD`).
3895        direction: FetchDirection,
3896        /// The fetch position (e.g., `ALL`, `NEXT`, `ABSOLUTE`).
3897        position: FetchPosition,
3898        /// Optional target table to fetch rows into.
3899        into: Option<ObjectName>,
3900    },
3901    /// ```sql
3902    /// FLUSH [NO_WRITE_TO_BINLOG | LOCAL] flush_option [, flush_option] ... | tables_option
3903    /// ```
3904    ///
3905    /// Note: this is a Mysql-specific statement,
3906    /// but may also compatible with other SQL.
3907    Flush {
3908        /// The specific flush option or object to flush.
3909        object_type: FlushType,
3910        /// Optional flush location (dialect-specific).
3911        location: Option<FlushLocation>,
3912        /// Optional channel name used for flush operations.
3913        channel: Option<String>,
3914        /// Whether a read lock was requested.
3915        read_lock: bool,
3916        /// Whether this is an export flush operation.
3917        export: bool,
3918        /// Optional list of tables involved in the flush.
3919        tables: Vec<ObjectName>,
3920    },
3921    /// ```sql
3922    /// DISCARD [ ALL | PLANS | SEQUENCES | TEMPORARY | TEMP ]
3923    /// ```
3924    ///
3925    /// Note: this is a PostgreSQL-specific statement,
3926    /// but may also compatible with other SQL.
3927    Discard {
3928        /// The kind of object(s) to discard (ALL, PLANS, etc.).
3929        object_type: DiscardObject,
3930    },
3931    /// `SHOW FUNCTIONS`
3932    ///
3933    /// Note: this is a Presto-specific statement.
3934    ShowFunctions {
3935        /// Optional filter for which functions to display.
3936        filter: Option<ShowStatementFilter>,
3937    },
3938    /// ```sql
3939    /// SHOW <variable>
3940    /// ```
3941    ///
3942    /// Note: this is a PostgreSQL-specific statement.
3943    ShowVariable {
3944        /// Variable name as one or more identifiers.
3945        variable: Vec<Ident>,
3946    },
3947    /// ```sql
3948    /// SHOW [GLOBAL | SESSION] STATUS [LIKE 'pattern' | WHERE expr]
3949    /// ```
3950    ///
3951    /// Note: this is a MySQL-specific statement.
3952    ShowStatus {
3953        /// Optional filter for which status entries to display.
3954        filter: Option<ShowStatementFilter>,
3955        /// `true` when `GLOBAL` scope was requested.
3956        global: bool,
3957        /// `true` when `SESSION` scope was requested.
3958        session: bool,
3959    },
3960    /// ```sql
3961    /// SHOW VARIABLES
3962    /// ```
3963    ///
3964    /// Note: this is a MySQL-specific statement.
3965    ShowVariables {
3966        /// Optional filter for which variables to display.
3967        filter: Option<ShowStatementFilter>,
3968        /// `true` when `GLOBAL` scope was requested.
3969        global: bool,
3970        /// `true` when `SESSION` scope was requested.
3971        session: bool,
3972    },
3973    /// ```sql
3974    /// SHOW CREATE TABLE
3975    /// ```
3976    ///
3977    /// Note: this is a MySQL-specific statement.
3978    ShowCreate {
3979        /// The kind of object being shown (TABLE, VIEW, etc.).
3980        obj_type: ShowCreateObject,
3981        /// The name of the object to show create statement for.
3982        obj_name: ObjectName,
3983    },
3984    /// ```sql
3985    /// SHOW COLUMNS
3986    /// ```
3987    ShowColumns {
3988        /// `true` when extended column information was requested.
3989        extended: bool,
3990        /// `true` when full column details were requested.
3991        full: bool,
3992        /// Additional options for `SHOW COLUMNS`.
3993        show_options: ShowStatementOptions,
3994    },
3995    /// ```sql
3996    /// SHOW DATABASES
3997    /// ```
3998    ShowDatabases {
3999        /// `true` when terse output format was requested.
4000        terse: bool,
4001        /// `true` when history information was requested.
4002        history: bool,
4003        /// Additional options for `SHOW DATABASES`.
4004        show_options: ShowStatementOptions,
4005    },
4006    /// ```sql
4007    /// SHOW SCHEMAS
4008    /// ```
4009    ShowSchemas {
4010        /// `true` when terse (compact) output was requested.
4011        terse: bool,
4012        /// `true` when history information was requested.
4013        history: bool,
4014        /// Additional options for `SHOW SCHEMAS`.
4015        show_options: ShowStatementOptions,
4016    },
4017    // ```sql
4018    // SHOW {CHARACTER SET | CHARSET}
4019    // ```
4020    // [MySQL]:
4021    // <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>
4022    /// Show the available character sets (alias `CHARSET`).
4023    ShowCharset(ShowCharset),
4024    /// ```sql
4025    /// SHOW OBJECTS LIKE 'line%' IN mydb.public
4026    /// ```
4027    /// Snowflake-specific statement
4028    /// <https://docs.snowflake.com/en/sql-reference/sql/show-objects>
4029    ShowObjects(ShowObjects),
4030    /// ```sql
4031    /// SHOW TABLES
4032    /// ```
4033    ShowTables {
4034        /// `true` when terse output format was requested (compact listing).
4035        terse: bool,
4036        /// `true` when history rows are requested.
4037        history: bool,
4038        /// `true` when extended information should be shown.
4039        extended: bool,
4040        /// `true` when a full listing was requested.
4041        full: bool,
4042        /// `true` when external tables should be included.
4043        external: bool,
4044        /// Additional options for `SHOW` statements.
4045        show_options: ShowStatementOptions,
4046    },
4047    /// ```sql
4048    /// SHOW VIEWS
4049    /// ```
4050    ShowViews {
4051        /// `true` when terse output format was requested.
4052        terse: bool,
4053        /// `true` when materialized views should be included.
4054        materialized: bool,
4055        /// Additional options for `SHOW` statements.
4056        show_options: ShowStatementOptions,
4057    },
4058    /// ```sql
4059    /// SHOW COLLATION
4060    /// ```
4061    ///
4062    /// Note: this is a MySQL-specific statement.
4063    ShowCollation {
4064        /// Optional filter for which collations to display.
4065        filter: Option<ShowStatementFilter>,
4066    },
4067    /// ```sql
4068    /// `USE ...`
4069    /// ```
4070    Use(Use),
4071    /// ```sql
4072    /// START  [ TRANSACTION | WORK ] | START TRANSACTION } ...
4073    /// ```
4074    /// If `begin` is false.
4075    ///
4076    /// ```sql
4077    /// `BEGIN  [ TRANSACTION | WORK ] | START TRANSACTION } ...`
4078    /// ```
4079    /// If `begin` is true
4080    StartTransaction {
4081        /// Transaction modes such as `ISOLATION LEVEL` or `READ WRITE`.
4082        modes: Vec<TransactionMode>,
4083        /// `true` when this was parsed as `BEGIN` instead of `START`.
4084        begin: bool,
4085        /// Optional specific keyword used: `TRANSACTION` or `WORK`.
4086        transaction: Option<BeginTransactionKind>,
4087        /// Optional transaction modifier (e.g., `AND NO CHAIN`).
4088        modifier: Option<TransactionModifier>,
4089        /// List of statements belonging to the `BEGIN` block.
4090        /// Example:
4091        /// ```sql
4092        /// BEGIN
4093        ///     SELECT 1;
4094        ///     SELECT 2;
4095        /// END;
4096        /// ```
4097        statements: Vec<Statement>,
4098        /// Exception handling with exception clauses.
4099        /// Example:
4100        /// ```sql
4101        /// EXCEPTION
4102        ///     WHEN EXCEPTION_1 THEN
4103        ///         SELECT 2;
4104        ///     WHEN EXCEPTION_2 OR EXCEPTION_3 THEN
4105        ///         SELECT 3;
4106        ///     WHEN OTHER THEN
4107        ///         SELECT 4;
4108        /// ```
4109        /// <https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#beginexceptionend>
4110        /// <https://docs.snowflake.com/en/sql-reference/snowflake-scripting/exception>
4111        exception: Option<Vec<ExceptionWhen>>,
4112        /// TRUE if the statement has an `END` keyword.
4113        has_end_keyword: bool,
4114    },
4115    /// ```sql
4116    /// COMMENT ON ...
4117    /// ```
4118    ///
4119    /// Note: this is a PostgreSQL-specific statement.
4120    Comment {
4121        /// Type of object being commented (table, column, etc.).
4122        object_type: CommentObject,
4123        /// Name of the object the comment applies to.
4124        object_name: ObjectName,
4125        /// Optional comment text (None to remove comment).
4126        comment: Option<String>,
4127        /// An optional `IF EXISTS` clause. (Non-standard.)
4128        /// See <https://docs.snowflake.com/en/sql-reference/sql/comment>
4129        if_exists: bool,
4130    },
4131    /// ```sql
4132    /// COMMIT [ TRANSACTION | WORK ] [ AND [ NO ] CHAIN ]
4133    /// ```
4134    /// If `end` is false
4135    ///
4136    /// ```sql
4137    /// END [ TRY | CATCH ]
4138    /// ```
4139    /// If `end` is true
4140    Commit {
4141        /// `true` when `AND [ NO ] CHAIN` was present.
4142        chain: bool,
4143        /// `true` when this `COMMIT` was parsed as an `END` block terminator.
4144        end: bool,
4145        /// Optional transaction modifier for commit semantics.
4146        modifier: Option<TransactionModifier>,
4147    },
4148    /// ```sql
4149    /// ROLLBACK [ TRANSACTION | WORK ] [ AND [ NO ] CHAIN ] [ TO [ SAVEPOINT ] savepoint_name ]
4150    /// ```
4151    Rollback {
4152        /// `true` when `AND [ NO ] CHAIN` was present.
4153        chain: bool,
4154        /// Optional savepoint name to roll back to.
4155        savepoint: Option<Ident>,
4156    },
4157    /// ```sql
4158    /// CREATE SCHEMA
4159    /// ```
4160    CreateSchema {
4161        /// `<schema name> | AUTHORIZATION <schema authorization identifier>  | <schema name>  AUTHORIZATION <schema authorization identifier>`
4162        schema_name: SchemaName,
4163        /// `true` when `IF NOT EXISTS` was present.
4164        if_not_exists: bool,
4165        /// Schema properties.
4166        ///
4167        /// ```sql
4168        /// CREATE SCHEMA myschema WITH (key1='value1');
4169        /// ```
4170        ///
4171        /// [Trino](https://trino.io/docs/current/sql/create-schema.html)
4172        with: Option<Vec<SqlOption>>,
4173        /// Schema options.
4174        ///
4175        /// ```sql
4176        /// CREATE SCHEMA myschema OPTIONS(key1='value1');
4177        /// ```
4178        ///
4179        /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_schema_statement)
4180        options: Option<Vec<SqlOption>>,
4181        /// Default collation specification for the schema.
4182        ///
4183        /// ```sql
4184        /// CREATE SCHEMA myschema DEFAULT COLLATE 'und:ci';
4185        /// ```
4186        ///
4187        /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_schema_statement)
4188        default_collate_spec: Option<Expr>,
4189        /// Clones a schema
4190        ///
4191        /// ```sql
4192        /// CREATE SCHEMA myschema CLONE otherschema
4193        /// ```
4194        ///
4195        /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-clone#databases-schemas)
4196        clone: Option<ObjectName>,
4197    },
4198    /// ```sql
4199    /// CREATE DATABASE
4200    /// ```
4201    /// See:
4202    /// <https://docs.snowflake.com/en/sql-reference/sql/create-database>
4203    CreateDatabase {
4204        /// Database name.
4205        db_name: ObjectName,
4206        /// `IF NOT EXISTS` flag.
4207        if_not_exists: bool,
4208        /// Optional location URI.
4209        location: Option<String>,
4210        /// Optional managed location.
4211        managed_location: Option<String>,
4212        /// `OR REPLACE` flag.
4213        or_replace: bool,
4214        /// `TRANSIENT` flag.
4215        transient: bool,
4216        /// Optional clone source.
4217        clone: Option<ObjectName>,
4218        /// Optional data retention time in days.
4219        data_retention_time_in_days: Option<u64>,
4220        /// Optional maximum data extension time in days.
4221        max_data_extension_time_in_days: Option<u64>,
4222        /// Optional external volume identifier.
4223        external_volume: Option<String>,
4224        /// Optional catalog name.
4225        catalog: Option<String>,
4226        /// Whether to replace invalid characters.
4227        replace_invalid_characters: Option<bool>,
4228        /// Default DDL collation string.
4229        default_ddl_collation: Option<String>,
4230        /// Storage serialization policy.
4231        storage_serialization_policy: Option<StorageSerializationPolicy>,
4232        /// Optional comment.
4233        comment: Option<String>,
4234        /// Optional default character set (MySQL).
4235        default_charset: Option<String>,
4236        /// Optional default collation (MySQL).
4237        default_collation: Option<String>,
4238        /// Optional catalog sync identifier.
4239        catalog_sync: Option<String>,
4240        /// Catalog sync namespace mode.
4241        catalog_sync_namespace_mode: Option<CatalogSyncNamespaceMode>,
4242        /// Optional flatten delimiter for namespace sync.
4243        catalog_sync_namespace_flatten_delimiter: Option<String>,
4244        /// Optional tags for the database.
4245        with_tags: Option<Vec<Tag>>,
4246        /// Optional contact entries for the database.
4247        with_contacts: Option<Vec<ContactEntry>>,
4248    },
4249    /// ```sql
4250    /// CREATE FUNCTION
4251    /// ```
4252    ///
4253    /// Supported variants:
4254    /// 1. [Hive](https://cwiki.apache.org/confluence/display/hive/languagemanual+ddl#LanguageManualDDL-Create/Drop/ReloadFunction)
4255    /// 2. [PostgreSQL](https://www.postgresql.org/docs/15/sql-createfunction.html)
4256    /// 3. [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_function_statement)
4257    /// 4. [MsSql](https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql)
4258    CreateFunction(CreateFunction),
4259    /// CREATE TRIGGER statement. See struct [CreateTrigger] for details.
4260    CreateTrigger(CreateTrigger),
4261    /// DROP TRIGGER statement. See struct [DropTrigger] for details.
4262    DropTrigger(DropTrigger),
4263    /// ```sql
4264    /// CREATE PROCEDURE
4265    /// ```
4266    CreateProcedure {
4267        /// `OR ALTER` flag.
4268        or_alter: bool,
4269        /// Procedure name.
4270        name: ObjectName,
4271        /// Optional procedure parameters.
4272        params: Option<Vec<ProcedureParam>>,
4273        /// Optional language identifier.
4274        language: Option<Ident>,
4275        /// Procedure body statements.
4276        body: ConditionalStatements,
4277    },
4278    /// ```sql
4279    /// CREATE MACRO
4280    /// ```
4281    ///
4282    /// Supported variants:
4283    /// 1. [DuckDB](https://duckdb.org/docs/sql/statements/create_macro)
4284    CreateMacro {
4285        /// `OR REPLACE` flag.
4286        or_replace: bool,
4287        /// Whether macro is temporary.
4288        temporary: bool,
4289        /// Macro name.
4290        name: ObjectName,
4291        /// Optional macro arguments.
4292        args: Option<Vec<MacroArg>>,
4293        /// Macro definition body.
4294        definition: MacroDefinition,
4295    },
4296    /// ```sql
4297    /// CREATE STAGE
4298    /// ```
4299    /// See <https://docs.snowflake.com/en/sql-reference/sql/create-stage>
4300    CreateStage {
4301        /// `OR REPLACE` flag for stage.
4302        or_replace: bool,
4303        /// Whether stage is temporary.
4304        temporary: bool,
4305        /// `IF NOT EXISTS` flag.
4306        if_not_exists: bool,
4307        /// Stage name.
4308        name: ObjectName,
4309        /// Stage parameters.
4310        stage_params: StageParamsObject,
4311        /// Directory table parameters.
4312        directory_table_params: KeyValueOptions,
4313        /// File format options.
4314        file_format: KeyValueOptions,
4315        /// Copy options for stage.
4316        copy_options: KeyValueOptions,
4317        /// Optional comment.
4318        comment: Option<String>,
4319    },
4320    /// ```sql
4321    /// ASSERT <condition> [AS <message>]
4322    /// ```
4323    Assert {
4324        /// Assertion condition expression.
4325        condition: Expr,
4326        /// Optional message expression.
4327        message: Option<Expr>,
4328    },
4329    /// ```sql
4330    /// GRANT privileges ON objects TO grantees
4331    /// ```
4332    Grant(Grant),
4333    /// ```sql
4334    /// DENY privileges ON object TO grantees
4335    /// ```
4336    Deny(DenyStatement),
4337    /// ```sql
4338    /// REVOKE privileges ON objects FROM grantees
4339    /// ```
4340    Revoke(Revoke),
4341    /// ```sql
4342    /// DEALLOCATE [ PREPARE ] { name | ALL }
4343    /// ```
4344    ///
4345    /// Note: this is a PostgreSQL-specific statement.
4346    Deallocate {
4347        /// Name to deallocate (or `ALL`).
4348        name: Ident,
4349        /// Whether `PREPARE` keyword was present.
4350        prepare: bool,
4351    },
4352    /// ```sql
4353    /// An `EXECUTE` statement
4354    /// ```
4355    ///
4356    /// Postgres: <https://www.postgresql.org/docs/current/sql-execute.html>
4357    /// MSSQL: <https://learn.microsoft.com/en-us/sql/relational-databases/stored-procedures/execute-a-stored-procedure>
4358    /// BigQuery: <https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#execute_immediate>
4359    /// Snowflake: <https://docs.snowflake.com/en/sql-reference/sql/execute-immediate>
4360    Execute {
4361        /// Optional function/procedure name.
4362        name: Option<ObjectName>,
4363        /// Parameter expressions passed to execute.
4364        parameters: Vec<Expr>,
4365        /// Whether parentheses were present.
4366        has_parentheses: bool,
4367        /// Is this an `EXECUTE IMMEDIATE`.
4368        immediate: bool,
4369        /// Identifiers to capture results into.
4370        into: Vec<Ident>,
4371        /// `USING` expressions with optional aliases.
4372        using: Vec<ExprWithAlias>,
4373        /// Whether the last parameter is the return value of the procedure
4374        /// MSSQL: <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/execute-transact-sql?view=sql-server-ver17#output>
4375        output: bool,
4376        /// Whether to invoke the procedure with the default parameter values
4377        /// MSSQL: <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/execute-transact-sql?view=sql-server-ver17#default>
4378        default: bool,
4379    },
4380    /// ```sql
4381    /// PREPARE name [ ( data_type [, ...] ) ] AS statement
4382    /// ```
4383    ///
4384    /// Note: this is a PostgreSQL-specific statement.
4385    Prepare {
4386        /// Name of the prepared statement.
4387        name: Ident,
4388        /// Optional data types for parameters.
4389        data_types: Vec<DataType>,
4390        /// Statement being prepared.
4391        statement: Box<Statement>,
4392    },
4393    /// ```sql
4394    /// KILL [CONNECTION | QUERY | MUTATION]
4395    /// ```
4396    ///
4397    /// See <https://clickhouse.com/docs/en/sql-reference/statements/kill/>
4398    /// See <https://dev.mysql.com/doc/refman/8.0/en/kill.html>
4399    Kill {
4400        /// Optional kill modifier (CONNECTION, QUERY, MUTATION).
4401        modifier: Option<KillType>,
4402        // processlist_id
4403        /// The id of the process to kill.
4404        id: u64,
4405    },
4406    /// ```sql
4407    /// [EXPLAIN | DESC | DESCRIBE] TABLE
4408    /// ```
4409    /// Note: this is a MySQL-specific statement. See <https://dev.mysql.com/doc/refman/8.0/en/explain.html>
4410    ExplainTable {
4411        /// `EXPLAIN | DESC | DESCRIBE`
4412        describe_alias: DescribeAlias,
4413        /// Hive style `FORMATTED | EXTENDED`
4414        hive_format: Option<HiveDescribeFormat>,
4415        /// Snowflake and ClickHouse support `DESC|DESCRIBE TABLE <table_name>` syntax
4416        ///
4417        /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/desc-table.html)
4418        /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/describe-table)
4419        has_table_keyword: bool,
4420        /// Table name
4421        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
4422        table_name: ObjectName,
4423    },
4424    /// ```sql
4425    /// [EXPLAIN | DESC | DESCRIBE]  <statement>
4426    /// ```
4427    Explain {
4428        /// `EXPLAIN | DESC | DESCRIBE`
4429        describe_alias: DescribeAlias,
4430        /// Carry out the command and show actual run times and other statistics.
4431        analyze: bool,
4432        /// Display additional information regarding the plan.
4433        verbose: bool,
4434        /// `EXPLAIN QUERY PLAN`
4435        /// Display the query plan without running the query.
4436        ///
4437        /// [SQLite](https://sqlite.org/lang_explain.html)
4438        query_plan: bool,
4439        /// `EXPLAIN ESTIMATE`
4440        /// [Clickhouse](https://clickhouse.com/docs/en/sql-reference/statements/explain#explain-estimate)
4441        estimate: bool,
4442        /// A SQL query that specifies what to explain
4443        statement: Box<Statement>,
4444        /// Optional output format of explain
4445        format: Option<AnalyzeFormatKind>,
4446        /// Postgres style utility options, `(analyze, verbose true)`
4447        options: Option<Vec<UtilityOption>>,
4448    },
4449    /// ```sql
4450    /// SAVEPOINT
4451    /// ```
4452    /// Define a new savepoint within the current transaction
4453    Savepoint {
4454        /// Name of the savepoint being defined.
4455        name: Ident,
4456    },
4457    /// ```sql
4458    /// RELEASE [ SAVEPOINT ] savepoint_name
4459    /// ```
4460    ReleaseSavepoint {
4461        /// Name of the savepoint to release.
4462        name: Ident,
4463    },
4464    /// A `MERGE` statement.
4465    ///
4466    /// ```sql
4467    /// MERGE INTO <target_table> USING <source> ON <join_expr> { matchedClause | notMatchedClause } [ ... ]
4468    /// ```
4469    /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/merge)
4470    /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/dml-syntax#merge_statement)
4471    /// [MSSQL](https://learn.microsoft.com/en-us/sql/t-sql/statements/merge-transact-sql?view=sql-server-ver16)
4472    Merge(Merge),
4473    /// ```sql
4474    /// CACHE [ FLAG ] TABLE <table_name> [ OPTIONS('K1' = 'V1', 'K2' = V2) ] [ AS ] [ <query> ]
4475    /// ```
4476    ///
4477    /// See [Spark SQL docs] for more details.
4478    ///
4479    /// [Spark SQL docs]: https://docs.databricks.com/spark/latest/spark-sql/language-manual/sql-ref-syntax-aux-cache-cache-table.html
4480    Cache {
4481        /// Table flag
4482        table_flag: Option<ObjectName>,
4483        /// Table name
4484        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
4485        table_name: ObjectName,
4486        /// `true` if `AS` keyword was present before the query.
4487        has_as: bool,
4488        /// Table confs
4489        options: Vec<SqlOption>,
4490        /// Cache table as a Query
4491        query: Option<Box<Query>>,
4492    },
4493    /// ```sql
4494    /// UNCACHE TABLE [ IF EXISTS ]  <table_name>
4495    /// ```
4496    UNCache {
4497        /// Table name
4498        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
4499        table_name: ObjectName,
4500        /// `true` when `IF EXISTS` was present.
4501        if_exists: bool,
4502    },
4503    /// ```sql
4504    /// CREATE [ { TEMPORARY | TEMP } ] SEQUENCE [ IF NOT EXISTS ] <sequence_name>
4505    /// ```
4506    /// Define a new sequence:
4507    CreateSequence {
4508        /// Whether the sequence is temporary.
4509        temporary: bool,
4510        /// `IF NOT EXISTS` flag.
4511        if_not_exists: bool,
4512        /// Sequence name.
4513        name: ObjectName,
4514        /// Optional data type for the sequence.
4515        data_type: Option<DataType>,
4516        /// Sequence options (INCREMENT, MINVALUE, etc.).
4517        sequence_options: Vec<SequenceOptions>,
4518        /// Optional `OWNED BY` target.
4519        owned_by: Option<ObjectName>,
4520    },
4521    /// A `CREATE DOMAIN` statement.
4522    CreateDomain(CreateDomain),
4523    /// ```sql
4524    /// CREATE TYPE <name>
4525    /// ```
4526    CreateType {
4527        /// Type name to create.
4528        name: ObjectName,
4529        /// Optional type representation details.
4530        representation: Option<UserDefinedTypeRepresentation>,
4531    },
4532    /// ```sql
4533    /// PRAGMA <schema-name>.<pragma-name> = <pragma-value>
4534    /// ```
4535    Pragma {
4536        /// Pragma name (possibly qualified).
4537        name: ObjectName,
4538        /// Optional pragma value.
4539        value: Option<Value>,
4540        /// Whether the pragma used `=`.
4541        is_eq: bool,
4542    },
4543    /// ```sql
4544    /// LOCK TABLES <table_name> [READ [LOCAL] | [LOW_PRIORITY] WRITE]
4545    /// ```
4546    /// Note: this is a MySQL-specific statement. See <https://dev.mysql.com/doc/refman/8.0/en/lock-tables.html>
4547    LockTables {
4548        /// List of tables to lock with modes.
4549        tables: Vec<LockTable>,
4550    },
4551    /// ```sql
4552    /// UNLOCK TABLES
4553    /// ```
4554    /// Note: this is a MySQL-specific statement. See <https://dev.mysql.com/doc/refman/8.0/en/lock-tables.html>
4555    UnlockTables,
4556    /// Unloads the result of a query to file
4557    ///
4558    /// [Athena](https://docs.aws.amazon.com/athena/latest/ug/unload.html):
4559    /// ```sql
4560    /// UNLOAD(statement) TO <destination> [ WITH options ]
4561    /// ```
4562    ///
4563    /// [Redshift](https://docs.aws.amazon.com/redshift/latest/dg/r_UNLOAD.html):
4564    /// ```sql
4565    /// UNLOAD('statement') TO <destination> [ OPTIONS ]
4566    /// ```
4567    Unload {
4568        /// Optional query AST to unload.
4569        query: Option<Box<Query>>,
4570        /// Optional original query text.
4571        query_text: Option<String>,
4572        /// Destination identifier.
4573        to: Ident,
4574        /// Optional IAM role/auth information.
4575        auth: Option<IamRoleKind>,
4576        /// Additional `WITH` options.
4577        with: Vec<SqlOption>,
4578        /// Legacy copy-style options.
4579        options: Vec<CopyLegacyOption>,
4580    },
4581    /// ```sql
4582    /// OPTIMIZE TABLE [db.]name [ON CLUSTER cluster] [PARTITION partition | PARTITION ID 'partition_id'] [FINAL] [DEDUPLICATE [BY expression]]
4583    /// ```
4584    ///
4585    /// See ClickHouse <https://clickhouse.com/docs/en/sql-reference/statements/optimize>
4586    OptimizeTable {
4587        /// Table name to optimize.
4588        name: ObjectName,
4589        /// Optional cluster identifier.
4590        on_cluster: Option<Ident>,
4591        /// Optional partition spec.
4592        partition: Option<Partition>,
4593        /// Whether `FINAL` was specified.
4594        include_final: bool,
4595        /// Optional deduplication settings.
4596        deduplicate: Option<Deduplicate>,
4597    },
4598    /// ```sql
4599    /// LISTEN
4600    /// ```
4601    /// listen for a notification channel
4602    ///
4603    /// See Postgres <https://www.postgresql.org/docs/current/sql-listen.html>
4604    LISTEN {
4605        /// Notification channel identifier.
4606        channel: Ident,
4607    },
4608    /// ```sql
4609    /// UNLISTEN
4610    /// ```
4611    /// stop listening for a notification
4612    ///
4613    /// See Postgres <https://www.postgresql.org/docs/current/sql-unlisten.html>
4614    UNLISTEN {
4615        /// Notification channel identifier.
4616        channel: Ident,
4617    },
4618    /// ```sql
4619    /// NOTIFY channel [ , payload ]
4620    /// ```
4621    /// send a notification event together with an optional "payload" string to channel
4622    ///
4623    /// See Postgres <https://www.postgresql.org/docs/current/sql-notify.html>
4624    NOTIFY {
4625        /// Notification channel identifier.
4626        channel: Ident,
4627        /// Optional payload string.
4628        payload: Option<String>,
4629    },
4630    /// ```sql
4631    /// LOAD DATA [LOCAL] INPATH 'filepath' [OVERWRITE] INTO TABLE tablename
4632    /// [PARTITION (partcol1=val1, partcol2=val2 ...)]
4633    /// [INPUTFORMAT 'inputformat' SERDE 'serde']
4634    /// ```
4635    /// Loading files into tables
4636    ///
4637    /// See Hive <https://cwiki.apache.org/confluence/pages/viewpage.action?pageId=27362036#LanguageManualDML-Loadingfilesintotables>
4638    LoadData {
4639        /// Whether `LOCAL` is present.
4640        local: bool,
4641        /// Input path for files to load.
4642        inpath: String,
4643        /// Whether `OVERWRITE` was specified.
4644        overwrite: bool,
4645        /// Target table name to load into.
4646        table_name: ObjectName,
4647        /// Optional partition specification.
4648        partitioned: Option<Vec<Expr>>,
4649        /// Optional table format information.
4650        table_format: Option<HiveLoadDataFormat>,
4651    },
4652    /// ```sql
4653    /// Rename TABLE tbl_name TO new_tbl_name[, tbl_name2 TO new_tbl_name2] ...
4654    /// ```
4655    /// Renames one or more tables
4656    ///
4657    /// See Mysql <https://dev.mysql.com/doc/refman/9.1/en/rename-table.html>
4658    RenameTable(Vec<RenameTable>),
4659    /// Snowflake `LIST`
4660    /// See: <https://docs.snowflake.com/en/sql-reference/sql/list>
4661    List(FileStagingCommand),
4662    /// Snowflake `REMOVE`
4663    /// See: <https://docs.snowflake.com/en/sql-reference/sql/remove>
4664    Remove(FileStagingCommand),
4665    /// RaiseError (MSSQL)
4666    /// RAISERROR ( { msg_id | msg_str | @local_variable }
4667    /// { , severity , state }
4668    /// [ , argument [ , ...n ] ] )
4669    /// [ WITH option [ , ...n ] ]
4670    /// See <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/raiserror-transact-sql?view=sql-server-ver16>
4671    RaisError {
4672        /// Error message expression or identifier.
4673        message: Box<Expr>,
4674        /// Severity expression.
4675        severity: Box<Expr>,
4676        /// State expression.
4677        state: Box<Expr>,
4678        /// Substitution arguments for the message.
4679        arguments: Vec<Expr>,
4680        /// Additional `WITH` options for RAISERROR.
4681        options: Vec<RaisErrorOption>,
4682    },
4683    /// ```sql
4684    /// PRINT msg_str | @local_variable | string_expr
4685    /// ```
4686    ///
4687    /// See: <https://learn.microsoft.com/en-us/sql/t-sql/statements/print-transact-sql>
4688    Print(PrintStatement),
4689    /// ```sql
4690    /// RETURN [ expression ]
4691    /// ```
4692    ///
4693    /// See [ReturnStatement]
4694    Return(ReturnStatement),
4695    /// Export data statement
4696    ///
4697    /// Example:
4698    /// ```sql
4699    /// EXPORT DATA OPTIONS(uri='gs://bucket/folder/*', format='PARQUET', overwrite=true) AS
4700    /// SELECT field1, field2 FROM mydataset.table1 ORDER BY field1 LIMIT 10
4701    /// ```
4702    /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/export-statements)
4703    ExportData(ExportData),
4704    /// ```sql
4705    /// CREATE [OR REPLACE] USER <user> [IF NOT EXISTS]
4706    /// ```
4707    /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-user)
4708    CreateUser(CreateUser),
4709    /// ```sql
4710    /// ALTER USER \[ IF EXISTS \] \[ <name> \]
4711    /// ```
4712    /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/alter-user)
4713    AlterUser(AlterUser),
4714    /// Re-sorts rows and reclaims space in either a specified table or all tables in the current database
4715    ///
4716    /// ```sql
4717    /// VACUUM tbl
4718    /// ```
4719    /// [Redshift](https://docs.aws.amazon.com/redshift/latest/dg/r_VACUUM_command.html)
4720    Vacuum(VacuumStatement),
4721    /// Restore the value of a run-time parameter to the default value.
4722    ///
4723    /// ```sql
4724    /// RESET configuration_parameter;
4725    /// RESET ALL;
4726    /// ```
4727    /// [PostgreSQL](https://www.postgresql.org/docs/current/sql-reset.html)
4728    Reset(ResetStatement),
4729}
4730
4731impl From<Analyze> for Statement {
4732    fn from(analyze: Analyze) -> Self {
4733        Statement::Analyze(analyze)
4734    }
4735}
4736
4737impl From<ddl::Truncate> for Statement {
4738    fn from(truncate: ddl::Truncate) -> Self {
4739        Statement::Truncate(truncate)
4740    }
4741}
4742
4743impl From<ddl::Msck> for Statement {
4744    fn from(msck: ddl::Msck) -> Self {
4745        Statement::Msck(msck)
4746    }
4747}
4748
4749/// ```sql
4750/// {COPY | REVOKE} CURRENT GRANTS
4751/// ```
4752///
4753/// - [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/grant-ownership#optional-parameters)
4754#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
4755#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4756#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
4757pub enum CurrentGrantsKind {
4758    /// `COPY CURRENT GRANTS` (copy current grants to target).
4759    CopyCurrentGrants,
4760    /// `REVOKE CURRENT GRANTS` (revoke current grants from target).
4761    RevokeCurrentGrants,
4762}
4763
4764impl fmt::Display for CurrentGrantsKind {
4765    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
4766        match self {
4767            CurrentGrantsKind::CopyCurrentGrants => write!(f, "COPY CURRENT GRANTS"),
4768            CurrentGrantsKind::RevokeCurrentGrants => write!(f, "REVOKE CURRENT GRANTS"),
4769        }
4770    }
4771}
4772
4773#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
4774#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4775#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
4776/// `RAISERROR` options
4777/// See <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/raiserror-transact-sql?view=sql-server-ver16#options>
4778pub enum RaisErrorOption {
4779    /// Log the error.
4780    Log,
4781    /// Do not wait for completion.
4782    NoWait,
4783    /// Set the error state.
4784    SetError,
4785}
4786
4787impl fmt::Display for RaisErrorOption {
4788    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
4789        match self {
4790            RaisErrorOption::Log => write!(f, "LOG"),
4791            RaisErrorOption::NoWait => write!(f, "NOWAIT"),
4792            RaisErrorOption::SetError => write!(f, "SETERROR"),
4793        }
4794    }
4795}
4796
4797impl fmt::Display for Statement {
4798    /// Formats a SQL statement with support for pretty printing.
4799    ///
4800    /// When using the alternate flag (`{:#}`), the statement will be formatted with proper
4801    /// indentation and line breaks. For example:
4802    ///
4803    /// ```
4804    /// # use sqlparser::dialect::GenericDialect;
4805    /// # use sqlparser::parser::Parser;
4806    /// let sql = "SELECT a, b FROM table_1";
4807    /// let ast = Parser::parse_sql(&GenericDialect, sql).unwrap();
4808    ///
4809    /// // Regular formatting
4810    /// assert_eq!(format!("{}", ast[0]), "SELECT a, b FROM table_1");
4811    ///
4812    /// // Pretty printing
4813    /// assert_eq!(format!("{:#}", ast[0]),
4814    /// r#"SELECT
4815    ///   a,
4816    ///   b
4817    /// FROM
4818    ///   table_1"#);
4819    /// ```
4820    // Clippy thinks this function is too complicated, but it is painful to
4821    // split up without extracting structs for each `Statement` variant.
4822    #[allow(clippy::cognitive_complexity)]
4823    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
4824        match self {
4825            Statement::Flush {
4826                object_type,
4827                location,
4828                channel,
4829                read_lock,
4830                export,
4831                tables,
4832            } => {
4833                write!(f, "FLUSH")?;
4834                if let Some(location) = location {
4835                    f.write_str(" ")?;
4836                    location.fmt(f)?;
4837                }
4838                write!(f, " {object_type}")?;
4839
4840                if let Some(channel) = channel {
4841                    write!(f, " FOR CHANNEL {channel}")?;
4842                }
4843
4844                write!(
4845                    f,
4846                    "{tables}{read}{export}",
4847                    tables = if !tables.is_empty() {
4848                        format!(" {}", display_comma_separated(tables))
4849                    } else {
4850                        String::new()
4851                    },
4852                    export = if *export { " FOR EXPORT" } else { "" },
4853                    read = if *read_lock { " WITH READ LOCK" } else { "" }
4854                )
4855            }
4856            Statement::Kill { modifier, id } => {
4857                write!(f, "KILL ")?;
4858
4859                if let Some(m) = modifier {
4860                    write!(f, "{m} ")?;
4861                }
4862
4863                write!(f, "{id}")
4864            }
4865            Statement::ExplainTable {
4866                describe_alias,
4867                hive_format,
4868                has_table_keyword,
4869                table_name,
4870            } => {
4871                write!(f, "{describe_alias} ")?;
4872
4873                if let Some(format) = hive_format {
4874                    write!(f, "{format} ")?;
4875                }
4876                if *has_table_keyword {
4877                    write!(f, "TABLE ")?;
4878                }
4879
4880                write!(f, "{table_name}")
4881            }
4882            Statement::Explain {
4883                describe_alias,
4884                verbose,
4885                analyze,
4886                query_plan,
4887                estimate,
4888                statement,
4889                format,
4890                options,
4891            } => {
4892                write!(f, "{describe_alias} ")?;
4893
4894                if *query_plan {
4895                    write!(f, "QUERY PLAN ")?;
4896                }
4897                if *analyze {
4898                    write!(f, "ANALYZE ")?;
4899                }
4900                if *estimate {
4901                    write!(f, "ESTIMATE ")?;
4902                }
4903
4904                if *verbose {
4905                    write!(f, "VERBOSE ")?;
4906                }
4907
4908                if let Some(format) = format {
4909                    write!(f, "{format} ")?;
4910                }
4911
4912                if let Some(options) = options {
4913                    write!(f, "({}) ", display_comma_separated(options))?;
4914                }
4915
4916                write!(f, "{statement}")
4917            }
4918            Statement::Query(s) => s.fmt(f),
4919            Statement::Declare { stmts } => {
4920                write!(f, "DECLARE ")?;
4921                write!(f, "{}", display_separated(stmts, "; "))
4922            }
4923            Statement::Fetch {
4924                name,
4925                direction,
4926                position,
4927                into,
4928            } => {
4929                write!(f, "FETCH {direction} {position} {name}")?;
4930
4931                if let Some(into) = into {
4932                    write!(f, " INTO {into}")?;
4933                }
4934
4935                Ok(())
4936            }
4937            Statement::Directory {
4938                overwrite,
4939                local,
4940                path,
4941                file_format,
4942                source,
4943            } => {
4944                write!(
4945                    f,
4946                    "INSERT{overwrite}{local} DIRECTORY '{path}'",
4947                    overwrite = if *overwrite { " OVERWRITE" } else { "" },
4948                    local = if *local { " LOCAL" } else { "" },
4949                    path = path
4950                )?;
4951                if let Some(ref ff) = file_format {
4952                    write!(f, " STORED AS {ff}")?
4953                }
4954                write!(f, " {source}")
4955            }
4956            Statement::Msck(msck) => msck.fmt(f),
4957            Statement::Truncate(truncate) => truncate.fmt(f),
4958            Statement::Case(stmt) => {
4959                write!(f, "{stmt}")
4960            }
4961            Statement::If(stmt) => {
4962                write!(f, "{stmt}")
4963            }
4964            Statement::While(stmt) => {
4965                write!(f, "{stmt}")
4966            }
4967            Statement::Raise(stmt) => {
4968                write!(f, "{stmt}")
4969            }
4970            Statement::AttachDatabase {
4971                schema_name,
4972                database_file_name,
4973                database,
4974            } => {
4975                let keyword = if *database { "DATABASE " } else { "" };
4976                write!(f, "ATTACH {keyword}{database_file_name} AS {schema_name}")
4977            }
4978            Statement::AttachDuckDBDatabase {
4979                if_not_exists,
4980                database,
4981                database_path,
4982                database_alias,
4983                attach_options,
4984            } => {
4985                write!(
4986                    f,
4987                    "ATTACH{database}{if_not_exists} {database_path}",
4988                    database = if *database { " DATABASE" } else { "" },
4989                    if_not_exists = if *if_not_exists { " IF NOT EXISTS" } else { "" },
4990                )?;
4991                if let Some(alias) = database_alias {
4992                    write!(f, " AS {alias}")?;
4993                }
4994                if !attach_options.is_empty() {
4995                    write!(f, " ({})", display_comma_separated(attach_options))?;
4996                }
4997                Ok(())
4998            }
4999            Statement::DetachDuckDBDatabase {
5000                if_exists,
5001                database,
5002                database_alias,
5003            } => {
5004                write!(
5005                    f,
5006                    "DETACH{database}{if_exists} {database_alias}",
5007                    database = if *database { " DATABASE" } else { "" },
5008                    if_exists = if *if_exists { " IF EXISTS" } else { "" },
5009                )?;
5010                Ok(())
5011            }
5012            Statement::Analyze(analyze) => analyze.fmt(f),
5013            Statement::Insert(insert) => insert.fmt(f),
5014            Statement::Install {
5015                extension_name: name,
5016            } => write!(f, "INSTALL {name}"),
5017
5018            Statement::Load {
5019                extension_name: name,
5020            } => write!(f, "LOAD {name}"),
5021
5022            Statement::Call(function) => write!(f, "CALL {function}"),
5023
5024            Statement::Copy {
5025                source,
5026                to,
5027                target,
5028                options,
5029                legacy_options,
5030                values,
5031            } => {
5032                write!(f, "COPY")?;
5033                match source {
5034                    CopySource::Query(query) => write!(f, " ({query})")?,
5035                    CopySource::Table {
5036                        table_name,
5037                        columns,
5038                    } => {
5039                        write!(f, " {table_name}")?;
5040                        if !columns.is_empty() {
5041                            write!(f, " ({})", display_comma_separated(columns))?;
5042                        }
5043                    }
5044                }
5045                write!(f, " {} {}", if *to { "TO" } else { "FROM" }, target)?;
5046                if !options.is_empty() {
5047                    write!(f, " ({})", display_comma_separated(options))?;
5048                }
5049                if !legacy_options.is_empty() {
5050                    write!(f, " {}", display_separated(legacy_options, " "))?;
5051                }
5052                if !values.is_empty() {
5053                    writeln!(f, ";")?;
5054                    let mut delim = "";
5055                    for v in values {
5056                        write!(f, "{delim}")?;
5057                        delim = "\t";
5058                        if let Some(v) = v {
5059                            write!(f, "{v}")?;
5060                        } else {
5061                            write!(f, "\\N")?;
5062                        }
5063                    }
5064                    write!(f, "\n\\.")?;
5065                }
5066                Ok(())
5067            }
5068            Statement::Update(update) => update.fmt(f),
5069            Statement::Delete(delete) => delete.fmt(f),
5070            Statement::Open(open) => open.fmt(f),
5071            Statement::Close { cursor } => {
5072                write!(f, "CLOSE {cursor}")?;
5073
5074                Ok(())
5075            }
5076            Statement::CreateDatabase {
5077                db_name,
5078                if_not_exists,
5079                location,
5080                managed_location,
5081                or_replace,
5082                transient,
5083                clone,
5084                data_retention_time_in_days,
5085                max_data_extension_time_in_days,
5086                external_volume,
5087                catalog,
5088                replace_invalid_characters,
5089                default_ddl_collation,
5090                storage_serialization_policy,
5091                comment,
5092                default_charset,
5093                default_collation,
5094                catalog_sync,
5095                catalog_sync_namespace_mode,
5096                catalog_sync_namespace_flatten_delimiter,
5097                with_tags,
5098                with_contacts,
5099            } => {
5100                write!(
5101                    f,
5102                    "CREATE {or_replace}{transient}DATABASE {if_not_exists}{name}",
5103                    or_replace = if *or_replace { "OR REPLACE " } else { "" },
5104                    transient = if *transient { "TRANSIENT " } else { "" },
5105                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
5106                    name = db_name,
5107                )?;
5108
5109                if let Some(l) = location {
5110                    write!(f, " LOCATION '{l}'")?;
5111                }
5112                if let Some(ml) = managed_location {
5113                    write!(f, " MANAGEDLOCATION '{ml}'")?;
5114                }
5115                if let Some(clone) = clone {
5116                    write!(f, " CLONE {clone}")?;
5117                }
5118
5119                if let Some(value) = data_retention_time_in_days {
5120                    write!(f, " DATA_RETENTION_TIME_IN_DAYS = {value}")?;
5121                }
5122
5123                if let Some(value) = max_data_extension_time_in_days {
5124                    write!(f, " MAX_DATA_EXTENSION_TIME_IN_DAYS = {value}")?;
5125                }
5126
5127                if let Some(vol) = external_volume {
5128                    write!(f, " EXTERNAL_VOLUME = '{vol}'")?;
5129                }
5130
5131                if let Some(cat) = catalog {
5132                    write!(f, " CATALOG = '{cat}'")?;
5133                }
5134
5135                if let Some(true) = replace_invalid_characters {
5136                    write!(f, " REPLACE_INVALID_CHARACTERS = TRUE")?;
5137                } else if let Some(false) = replace_invalid_characters {
5138                    write!(f, " REPLACE_INVALID_CHARACTERS = FALSE")?;
5139                }
5140
5141                if let Some(collation) = default_ddl_collation {
5142                    write!(f, " DEFAULT_DDL_COLLATION = '{collation}'")?;
5143                }
5144
5145                if let Some(policy) = storage_serialization_policy {
5146                    write!(f, " STORAGE_SERIALIZATION_POLICY = {policy}")?;
5147                }
5148
5149                if let Some(comment) = comment {
5150                    write!(f, " COMMENT = '{comment}'")?;
5151                }
5152
5153                if let Some(charset) = default_charset {
5154                    write!(f, " DEFAULT CHARACTER SET {charset}")?;
5155                }
5156
5157                if let Some(collation) = default_collation {
5158                    write!(f, " DEFAULT COLLATE {collation}")?;
5159                }
5160
5161                if let Some(sync) = catalog_sync {
5162                    write!(f, " CATALOG_SYNC = '{sync}'")?;
5163                }
5164
5165                if let Some(mode) = catalog_sync_namespace_mode {
5166                    write!(f, " CATALOG_SYNC_NAMESPACE_MODE = {mode}")?;
5167                }
5168
5169                if let Some(delim) = catalog_sync_namespace_flatten_delimiter {
5170                    write!(f, " CATALOG_SYNC_NAMESPACE_FLATTEN_DELIMITER = '{delim}'")?;
5171                }
5172
5173                if let Some(tags) = with_tags {
5174                    write!(f, " WITH TAG ({})", display_comma_separated(tags))?;
5175                }
5176
5177                if let Some(contacts) = with_contacts {
5178                    write!(f, " WITH CONTACT ({})", display_comma_separated(contacts))?;
5179                }
5180                Ok(())
5181            }
5182            Statement::CreateFunction(create_function) => create_function.fmt(f),
5183            Statement::CreateDomain(create_domain) => create_domain.fmt(f),
5184            Statement::CreateTrigger(create_trigger) => create_trigger.fmt(f),
5185            Statement::DropTrigger(drop_trigger) => drop_trigger.fmt(f),
5186            Statement::CreateProcedure {
5187                name,
5188                or_alter,
5189                params,
5190                language,
5191                body,
5192            } => {
5193                write!(
5194                    f,
5195                    "CREATE {or_alter}PROCEDURE {name}",
5196                    or_alter = if *or_alter { "OR ALTER " } else { "" },
5197                    name = name
5198                )?;
5199
5200                if let Some(p) = params {
5201                    if !p.is_empty() {
5202                        write!(f, " ({})", display_comma_separated(p))?;
5203                    }
5204                }
5205
5206                if let Some(language) = language {
5207                    write!(f, " LANGUAGE {language}")?;
5208                }
5209
5210                write!(f, " AS {body}")
5211            }
5212            Statement::CreateMacro {
5213                or_replace,
5214                temporary,
5215                name,
5216                args,
5217                definition,
5218            } => {
5219                write!(
5220                    f,
5221                    "CREATE {or_replace}{temp}MACRO {name}",
5222                    temp = if *temporary { "TEMPORARY " } else { "" },
5223                    or_replace = if *or_replace { "OR REPLACE " } else { "" },
5224                )?;
5225                if let Some(args) = args {
5226                    write!(f, "({})", display_comma_separated(args))?;
5227                }
5228                match definition {
5229                    MacroDefinition::Expr(expr) => write!(f, " AS {expr}")?,
5230                    MacroDefinition::Table(query) => write!(f, " AS TABLE {query}")?,
5231                }
5232                Ok(())
5233            }
5234            Statement::CreateView(create_view) => create_view.fmt(f),
5235            Statement::CreateTable(create_table) => create_table.fmt(f),
5236            Statement::LoadData {
5237                local,
5238                inpath,
5239                overwrite,
5240                table_name,
5241                partitioned,
5242                table_format,
5243            } => {
5244                write!(
5245                    f,
5246                    "LOAD DATA {local}INPATH '{inpath}' {overwrite}INTO TABLE {table_name}",
5247                    local = if *local { "LOCAL " } else { "" },
5248                    inpath = inpath,
5249                    overwrite = if *overwrite { "OVERWRITE " } else { "" },
5250                    table_name = table_name,
5251                )?;
5252                if let Some(ref parts) = &partitioned {
5253                    if !parts.is_empty() {
5254                        write!(f, " PARTITION ({})", display_comma_separated(parts))?;
5255                    }
5256                }
5257                if let Some(HiveLoadDataFormat {
5258                    serde,
5259                    input_format,
5260                }) = &table_format
5261                {
5262                    write!(f, " INPUTFORMAT {input_format} SERDE {serde}")?;
5263                }
5264                Ok(())
5265            }
5266            Statement::CreateVirtualTable {
5267                name,
5268                if_not_exists,
5269                module_name,
5270                module_args,
5271            } => {
5272                write!(
5273                    f,
5274                    "CREATE VIRTUAL TABLE {if_not_exists}{name} USING {module_name}",
5275                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
5276                    name = name,
5277                    module_name = module_name
5278                )?;
5279                if !module_args.is_empty() {
5280                    write!(f, " ({})", display_comma_separated(module_args))?;
5281                }
5282                Ok(())
5283            }
5284            Statement::CreateIndex(create_index) => create_index.fmt(f),
5285            Statement::CreateExtension(create_extension) => write!(f, "{create_extension}"),
5286            Statement::DropExtension(drop_extension) => write!(f, "{drop_extension}"),
5287            Statement::DropOperator(drop_operator) => write!(f, "{drop_operator}"),
5288            Statement::DropOperatorFamily(drop_operator_family) => {
5289                write!(f, "{drop_operator_family}")
5290            }
5291            Statement::DropOperatorClass(drop_operator_class) => {
5292                write!(f, "{drop_operator_class}")
5293            }
5294            Statement::CreateRole(create_role) => write!(f, "{create_role}"),
5295            Statement::CreateSecret {
5296                or_replace,
5297                temporary,
5298                if_not_exists,
5299                name,
5300                storage_specifier,
5301                secret_type,
5302                options,
5303            } => {
5304                write!(
5305                    f,
5306                    "CREATE {or_replace}",
5307                    or_replace = if *or_replace { "OR REPLACE " } else { "" },
5308                )?;
5309                if let Some(t) = temporary {
5310                    write!(f, "{}", if *t { "TEMPORARY " } else { "PERSISTENT " })?;
5311                }
5312                write!(
5313                    f,
5314                    "SECRET {if_not_exists}",
5315                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
5316                )?;
5317                if let Some(n) = name {
5318                    write!(f, "{n} ")?;
5319                };
5320                if let Some(s) = storage_specifier {
5321                    write!(f, "IN {s} ")?;
5322                }
5323                write!(f, "( TYPE {secret_type}",)?;
5324                if !options.is_empty() {
5325                    write!(f, ", {o}", o = display_comma_separated(options))?;
5326                }
5327                write!(f, " )")?;
5328                Ok(())
5329            }
5330            Statement::CreateServer(stmt) => {
5331                write!(f, "{stmt}")
5332            }
5333            Statement::CreatePolicy(policy) => write!(f, "{policy}"),
5334            Statement::CreateConnector(create_connector) => create_connector.fmt(f),
5335            Statement::CreateOperator(create_operator) => create_operator.fmt(f),
5336            Statement::CreateOperatorFamily(create_operator_family) => {
5337                create_operator_family.fmt(f)
5338            }
5339            Statement::CreateOperatorClass(create_operator_class) => create_operator_class.fmt(f),
5340            Statement::AlterTable(alter_table) => write!(f, "{alter_table}"),
5341            Statement::AlterIndex { name, operation } => {
5342                write!(f, "ALTER INDEX {name} {operation}")
5343            }
5344            Statement::AlterView {
5345                name,
5346                columns,
5347                query,
5348                with_options,
5349            } => {
5350                write!(f, "ALTER VIEW {name}")?;
5351                if !with_options.is_empty() {
5352                    write!(f, " WITH ({})", display_comma_separated(with_options))?;
5353                }
5354                if !columns.is_empty() {
5355                    write!(f, " ({})", display_comma_separated(columns))?;
5356                }
5357                write!(f, " AS {query}")
5358            }
5359            Statement::AlterType(AlterType { name, operation }) => {
5360                write!(f, "ALTER TYPE {name} {operation}")
5361            }
5362            Statement::AlterOperator(alter_operator) => write!(f, "{alter_operator}"),
5363            Statement::AlterOperatorFamily(alter_operator_family) => {
5364                write!(f, "{alter_operator_family}")
5365            }
5366            Statement::AlterOperatorClass(alter_operator_class) => {
5367                write!(f, "{alter_operator_class}")
5368            }
5369            Statement::AlterRole { name, operation } => {
5370                write!(f, "ALTER ROLE {name} {operation}")
5371            }
5372            Statement::AlterPolicy(alter_policy) => write!(f, "{alter_policy}"),
5373            Statement::AlterConnector {
5374                name,
5375                properties,
5376                url,
5377                owner,
5378            } => {
5379                write!(f, "ALTER CONNECTOR {name}")?;
5380                if let Some(properties) = properties {
5381                    write!(
5382                        f,
5383                        " SET DCPROPERTIES({})",
5384                        display_comma_separated(properties)
5385                    )?;
5386                }
5387                if let Some(url) = url {
5388                    write!(f, " SET URL '{url}'")?;
5389                }
5390                if let Some(owner) = owner {
5391                    write!(f, " SET OWNER {owner}")?;
5392                }
5393                Ok(())
5394            }
5395            Statement::AlterSession {
5396                set,
5397                session_params,
5398            } => {
5399                write!(
5400                    f,
5401                    "ALTER SESSION {set}",
5402                    set = if *set { "SET" } else { "UNSET" }
5403                )?;
5404                if !session_params.options.is_empty() {
5405                    if *set {
5406                        write!(f, " {session_params}")?;
5407                    } else {
5408                        let options = session_params
5409                            .options
5410                            .iter()
5411                            .map(|p| p.option_name.clone())
5412                            .collect::<Vec<_>>();
5413                        write!(f, " {}", display_separated(&options, ", "))?;
5414                    }
5415                }
5416                Ok(())
5417            }
5418            Statement::Drop {
5419                object_type,
5420                if_exists,
5421                names,
5422                cascade,
5423                restrict,
5424                purge,
5425                temporary,
5426                table,
5427            } => {
5428                write!(
5429                    f,
5430                    "DROP {}{}{} {}{}{}{}",
5431                    if *temporary { "TEMPORARY " } else { "" },
5432                    object_type,
5433                    if *if_exists { " IF EXISTS" } else { "" },
5434                    display_comma_separated(names),
5435                    if *cascade { " CASCADE" } else { "" },
5436                    if *restrict { " RESTRICT" } else { "" },
5437                    if *purge { " PURGE" } else { "" },
5438                )?;
5439                if let Some(table_name) = table.as_ref() {
5440                    write!(f, " ON {table_name}")?;
5441                };
5442                Ok(())
5443            }
5444            Statement::DropFunction(drop_function) => write!(f, "{drop_function}"),
5445            Statement::DropDomain(DropDomain {
5446                if_exists,
5447                name,
5448                drop_behavior,
5449            }) => {
5450                write!(
5451                    f,
5452                    "DROP DOMAIN{} {name}",
5453                    if *if_exists { " IF EXISTS" } else { "" },
5454                )?;
5455                if let Some(op) = drop_behavior {
5456                    write!(f, " {op}")?;
5457                }
5458                Ok(())
5459            }
5460            Statement::DropProcedure {
5461                if_exists,
5462                proc_desc,
5463                drop_behavior,
5464            } => {
5465                write!(
5466                    f,
5467                    "DROP PROCEDURE{} {}",
5468                    if *if_exists { " IF EXISTS" } else { "" },
5469                    display_comma_separated(proc_desc),
5470                )?;
5471                if let Some(op) = drop_behavior {
5472                    write!(f, " {op}")?;
5473                }
5474                Ok(())
5475            }
5476            Statement::DropSecret {
5477                if_exists,
5478                temporary,
5479                name,
5480                storage_specifier,
5481            } => {
5482                write!(f, "DROP ")?;
5483                if let Some(t) = temporary {
5484                    write!(f, "{}", if *t { "TEMPORARY " } else { "PERSISTENT " })?;
5485                }
5486                write!(
5487                    f,
5488                    "SECRET {if_exists}{name}",
5489                    if_exists = if *if_exists { "IF EXISTS " } else { "" },
5490                )?;
5491                if let Some(s) = storage_specifier {
5492                    write!(f, " FROM {s}")?;
5493                }
5494                Ok(())
5495            }
5496            Statement::DropPolicy(policy) => write!(f, "{policy}"),
5497            Statement::DropConnector { if_exists, name } => {
5498                write!(
5499                    f,
5500                    "DROP CONNECTOR {if_exists}{name}",
5501                    if_exists = if *if_exists { "IF EXISTS " } else { "" }
5502                )?;
5503                Ok(())
5504            }
5505            Statement::Discard { object_type } => {
5506                write!(f, "DISCARD {object_type}")?;
5507                Ok(())
5508            }
5509            Self::Set(set) => write!(f, "{set}"),
5510            Statement::ShowVariable { variable } => {
5511                write!(f, "SHOW")?;
5512                if !variable.is_empty() {
5513                    write!(f, " {}", display_separated(variable, " "))?;
5514                }
5515                Ok(())
5516            }
5517            Statement::ShowStatus {
5518                filter,
5519                global,
5520                session,
5521            } => {
5522                write!(f, "SHOW")?;
5523                if *global {
5524                    write!(f, " GLOBAL")?;
5525                }
5526                if *session {
5527                    write!(f, " SESSION")?;
5528                }
5529                write!(f, " STATUS")?;
5530                if filter.is_some() {
5531                    write!(f, " {}", filter.as_ref().unwrap())?;
5532                }
5533                Ok(())
5534            }
5535            Statement::ShowVariables {
5536                filter,
5537                global,
5538                session,
5539            } => {
5540                write!(f, "SHOW")?;
5541                if *global {
5542                    write!(f, " GLOBAL")?;
5543                }
5544                if *session {
5545                    write!(f, " SESSION")?;
5546                }
5547                write!(f, " VARIABLES")?;
5548                if filter.is_some() {
5549                    write!(f, " {}", filter.as_ref().unwrap())?;
5550                }
5551                Ok(())
5552            }
5553            Statement::ShowCreate { obj_type, obj_name } => {
5554                write!(f, "SHOW CREATE {obj_type} {obj_name}",)?;
5555                Ok(())
5556            }
5557            Statement::ShowColumns {
5558                extended,
5559                full,
5560                show_options,
5561            } => {
5562                write!(
5563                    f,
5564                    "SHOW {extended}{full}COLUMNS{show_options}",
5565                    extended = if *extended { "EXTENDED " } else { "" },
5566                    full = if *full { "FULL " } else { "" },
5567                )?;
5568                Ok(())
5569            }
5570            Statement::ShowDatabases {
5571                terse,
5572                history,
5573                show_options,
5574            } => {
5575                write!(
5576                    f,
5577                    "SHOW {terse}DATABASES{history}{show_options}",
5578                    terse = if *terse { "TERSE " } else { "" },
5579                    history = if *history { " HISTORY" } else { "" },
5580                )?;
5581                Ok(())
5582            }
5583            Statement::ShowSchemas {
5584                terse,
5585                history,
5586                show_options,
5587            } => {
5588                write!(
5589                    f,
5590                    "SHOW {terse}SCHEMAS{history}{show_options}",
5591                    terse = if *terse { "TERSE " } else { "" },
5592                    history = if *history { " HISTORY" } else { "" },
5593                )?;
5594                Ok(())
5595            }
5596            Statement::ShowObjects(ShowObjects {
5597                terse,
5598                show_options,
5599            }) => {
5600                write!(
5601                    f,
5602                    "SHOW {terse}OBJECTS{show_options}",
5603                    terse = if *terse { "TERSE " } else { "" },
5604                )?;
5605                Ok(())
5606            }
5607            Statement::ShowTables {
5608                terse,
5609                history,
5610                extended,
5611                full,
5612                external,
5613                show_options,
5614            } => {
5615                write!(
5616                    f,
5617                    "SHOW {terse}{extended}{full}{external}TABLES{history}{show_options}",
5618                    terse = if *terse { "TERSE " } else { "" },
5619                    extended = if *extended { "EXTENDED " } else { "" },
5620                    full = if *full { "FULL " } else { "" },
5621                    external = if *external { "EXTERNAL " } else { "" },
5622                    history = if *history { " HISTORY" } else { "" },
5623                )?;
5624                Ok(())
5625            }
5626            Statement::ShowViews {
5627                terse,
5628                materialized,
5629                show_options,
5630            } => {
5631                write!(
5632                    f,
5633                    "SHOW {terse}{materialized}VIEWS{show_options}",
5634                    terse = if *terse { "TERSE " } else { "" },
5635                    materialized = if *materialized { "MATERIALIZED " } else { "" }
5636                )?;
5637                Ok(())
5638            }
5639            Statement::ShowFunctions { filter } => {
5640                write!(f, "SHOW FUNCTIONS")?;
5641                if let Some(filter) = filter {
5642                    write!(f, " {filter}")?;
5643                }
5644                Ok(())
5645            }
5646            Statement::Use(use_expr) => use_expr.fmt(f),
5647            Statement::ShowCollation { filter } => {
5648                write!(f, "SHOW COLLATION")?;
5649                if let Some(filter) = filter {
5650                    write!(f, " {filter}")?;
5651                }
5652                Ok(())
5653            }
5654            Statement::ShowCharset(show_stm) => show_stm.fmt(f),
5655            Statement::StartTransaction {
5656                modes,
5657                begin: syntax_begin,
5658                transaction,
5659                modifier,
5660                statements,
5661                exception,
5662                has_end_keyword,
5663            } => {
5664                if *syntax_begin {
5665                    if let Some(modifier) = *modifier {
5666                        write!(f, "BEGIN {modifier}")?;
5667                    } else {
5668                        write!(f, "BEGIN")?;
5669                    }
5670                } else {
5671                    write!(f, "START")?;
5672                }
5673                if let Some(transaction) = transaction {
5674                    write!(f, " {transaction}")?;
5675                }
5676                if !modes.is_empty() {
5677                    write!(f, " {}", display_comma_separated(modes))?;
5678                }
5679                if !statements.is_empty() {
5680                    write!(f, " ")?;
5681                    format_statement_list(f, statements)?;
5682                }
5683                if let Some(exception_when) = exception {
5684                    write!(f, " EXCEPTION")?;
5685                    for when in exception_when {
5686                        write!(f, " {when}")?;
5687                    }
5688                }
5689                if *has_end_keyword {
5690                    write!(f, " END")?;
5691                }
5692                Ok(())
5693            }
5694            Statement::Commit {
5695                chain,
5696                end: end_syntax,
5697                modifier,
5698            } => {
5699                if *end_syntax {
5700                    write!(f, "END")?;
5701                    if let Some(modifier) = *modifier {
5702                        write!(f, " {modifier}")?;
5703                    }
5704                    if *chain {
5705                        write!(f, " AND CHAIN")?;
5706                    }
5707                } else {
5708                    write!(f, "COMMIT{}", if *chain { " AND CHAIN" } else { "" })?;
5709                }
5710                Ok(())
5711            }
5712            Statement::Rollback { chain, savepoint } => {
5713                write!(f, "ROLLBACK")?;
5714
5715                if *chain {
5716                    write!(f, " AND CHAIN")?;
5717                }
5718
5719                if let Some(savepoint) = savepoint {
5720                    write!(f, " TO SAVEPOINT {savepoint}")?;
5721                }
5722
5723                Ok(())
5724            }
5725            Statement::CreateSchema {
5726                schema_name,
5727                if_not_exists,
5728                with,
5729                options,
5730                default_collate_spec,
5731                clone,
5732            } => {
5733                write!(
5734                    f,
5735                    "CREATE SCHEMA {if_not_exists}{name}",
5736                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
5737                    name = schema_name
5738                )?;
5739
5740                if let Some(collate) = default_collate_spec {
5741                    write!(f, " DEFAULT COLLATE {collate}")?;
5742                }
5743
5744                if let Some(with) = with {
5745                    write!(f, " WITH ({})", display_comma_separated(with))?;
5746                }
5747
5748                if let Some(options) = options {
5749                    write!(f, " OPTIONS({})", display_comma_separated(options))?;
5750                }
5751
5752                if let Some(clone) = clone {
5753                    write!(f, " CLONE {clone}")?;
5754                }
5755                Ok(())
5756            }
5757            Statement::Assert { condition, message } => {
5758                write!(f, "ASSERT {condition}")?;
5759                if let Some(m) = message {
5760                    write!(f, " AS {m}")?;
5761                }
5762                Ok(())
5763            }
5764            Statement::Grant(grant) => write!(f, "{grant}"),
5765            Statement::Deny(s) => write!(f, "{s}"),
5766            Statement::Revoke(revoke) => write!(f, "{revoke}"),
5767            Statement::Deallocate { name, prepare } => write!(
5768                f,
5769                "DEALLOCATE {prepare}{name}",
5770                prepare = if *prepare { "PREPARE " } else { "" },
5771                name = name,
5772            ),
5773            Statement::Execute {
5774                name,
5775                parameters,
5776                has_parentheses,
5777                immediate,
5778                into,
5779                using,
5780                output,
5781                default,
5782            } => {
5783                let (open, close) = if *has_parentheses {
5784                    ("(", ")")
5785                } else {
5786                    (if parameters.is_empty() { "" } else { " " }, "")
5787                };
5788                write!(f, "EXECUTE")?;
5789                if *immediate {
5790                    write!(f, " IMMEDIATE")?;
5791                }
5792                if let Some(name) = name {
5793                    write!(f, " {name}")?;
5794                }
5795                write!(f, "{open}{}{close}", display_comma_separated(parameters),)?;
5796                if !into.is_empty() {
5797                    write!(f, " INTO {}", display_comma_separated(into))?;
5798                }
5799                if !using.is_empty() {
5800                    write!(f, " USING {}", display_comma_separated(using))?;
5801                };
5802                if *output {
5803                    write!(f, " OUTPUT")?;
5804                }
5805                if *default {
5806                    write!(f, " DEFAULT")?;
5807                }
5808                Ok(())
5809            }
5810            Statement::Prepare {
5811                name,
5812                data_types,
5813                statement,
5814            } => {
5815                write!(f, "PREPARE {name} ")?;
5816                if !data_types.is_empty() {
5817                    write!(f, "({}) ", display_comma_separated(data_types))?;
5818                }
5819                write!(f, "AS {statement}")
5820            }
5821            Statement::Comment {
5822                object_type,
5823                object_name,
5824                comment,
5825                if_exists,
5826            } => {
5827                write!(f, "COMMENT ")?;
5828                if *if_exists {
5829                    write!(f, "IF EXISTS ")?
5830                };
5831                write!(f, "ON {object_type} {object_name} IS ")?;
5832                if let Some(c) = comment {
5833                    write!(f, "'{c}'")
5834                } else {
5835                    write!(f, "NULL")
5836                }
5837            }
5838            Statement::Savepoint { name } => {
5839                write!(f, "SAVEPOINT ")?;
5840                write!(f, "{name}")
5841            }
5842            Statement::ReleaseSavepoint { name } => {
5843                write!(f, "RELEASE SAVEPOINT {name}")
5844            }
5845            Statement::Merge(merge) => merge.fmt(f),
5846            Statement::Cache {
5847                table_name,
5848                table_flag,
5849                has_as,
5850                options,
5851                query,
5852            } => {
5853                if let Some(table_flag) = table_flag {
5854                    write!(f, "CACHE {table_flag} TABLE {table_name}")?;
5855                } else {
5856                    write!(f, "CACHE TABLE {table_name}")?;
5857                }
5858
5859                if !options.is_empty() {
5860                    write!(f, " OPTIONS({})", display_comma_separated(options))?;
5861                }
5862
5863                match (*has_as, query) {
5864                    (true, Some(query)) => write!(f, " AS {query}"),
5865                    (true, None) => f.write_str(" AS"),
5866                    (false, Some(query)) => write!(f, " {query}"),
5867                    (false, None) => Ok(()),
5868                }
5869            }
5870            Statement::UNCache {
5871                table_name,
5872                if_exists,
5873            } => {
5874                if *if_exists {
5875                    write!(f, "UNCACHE TABLE IF EXISTS {table_name}")
5876                } else {
5877                    write!(f, "UNCACHE TABLE {table_name}")
5878                }
5879            }
5880            Statement::CreateSequence {
5881                temporary,
5882                if_not_exists,
5883                name,
5884                data_type,
5885                sequence_options,
5886                owned_by,
5887            } => {
5888                let as_type: String = if let Some(dt) = data_type.as_ref() {
5889                    //Cannot use format!(" AS {}", dt), due to format! is not available in --target thumbv6m-none-eabi
5890                    // " AS ".to_owned() + &dt.to_string()
5891                    [" AS ", &dt.to_string()].concat()
5892                } else {
5893                    "".to_string()
5894                };
5895                write!(
5896                    f,
5897                    "CREATE {temporary}SEQUENCE {if_not_exists}{name}{as_type}",
5898                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
5899                    temporary = if *temporary { "TEMPORARY " } else { "" },
5900                    name = name,
5901                    as_type = as_type
5902                )?;
5903                for sequence_option in sequence_options {
5904                    write!(f, "{sequence_option}")?;
5905                }
5906                if let Some(ob) = owned_by.as_ref() {
5907                    write!(f, " OWNED BY {ob}")?;
5908                }
5909                write!(f, "")
5910            }
5911            Statement::CreateStage {
5912                or_replace,
5913                temporary,
5914                if_not_exists,
5915                name,
5916                stage_params,
5917                directory_table_params,
5918                file_format,
5919                copy_options,
5920                comment,
5921                ..
5922            } => {
5923                write!(
5924                    f,
5925                    "CREATE {or_replace}{temp}STAGE {if_not_exists}{name}{stage_params}",
5926                    temp = if *temporary { "TEMPORARY " } else { "" },
5927                    or_replace = if *or_replace { "OR REPLACE " } else { "" },
5928                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
5929                )?;
5930                if !directory_table_params.options.is_empty() {
5931                    write!(f, " DIRECTORY=({directory_table_params})")?;
5932                }
5933                if !file_format.options.is_empty() {
5934                    write!(f, " FILE_FORMAT=({file_format})")?;
5935                }
5936                if !copy_options.options.is_empty() {
5937                    write!(f, " COPY_OPTIONS=({copy_options})")?;
5938                }
5939                if comment.is_some() {
5940                    write!(f, " COMMENT='{}'", comment.as_ref().unwrap())?;
5941                }
5942                Ok(())
5943            }
5944            Statement::CopyIntoSnowflake {
5945                kind,
5946                into,
5947                into_columns,
5948                from_obj,
5949                from_obj_alias,
5950                stage_params,
5951                from_transformations,
5952                from_query,
5953                files,
5954                pattern,
5955                file_format,
5956                copy_options,
5957                validation_mode,
5958                partition,
5959            } => {
5960                write!(f, "COPY INTO {into}")?;
5961                if let Some(into_columns) = into_columns {
5962                    write!(f, " ({})", display_comma_separated(into_columns))?;
5963                }
5964                if let Some(from_transformations) = from_transformations {
5965                    // Data load with transformation
5966                    if let Some(from_stage) = from_obj {
5967                        write!(
5968                            f,
5969                            " FROM (SELECT {} FROM {}{}",
5970                            display_separated(from_transformations, ", "),
5971                            from_stage,
5972                            stage_params
5973                        )?;
5974                    }
5975                    if let Some(from_obj_alias) = from_obj_alias {
5976                        write!(f, " AS {from_obj_alias}")?;
5977                    }
5978                    write!(f, ")")?;
5979                } else if let Some(from_obj) = from_obj {
5980                    // Standard data load
5981                    write!(f, " FROM {from_obj}{stage_params}")?;
5982                    if let Some(from_obj_alias) = from_obj_alias {
5983                        write!(f, " AS {from_obj_alias}")?;
5984                    }
5985                } else if let Some(from_query) = from_query {
5986                    // Data unload from query
5987                    write!(f, " FROM ({from_query})")?;
5988                }
5989
5990                if let Some(files) = files {
5991                    write!(f, " FILES = ('{}')", display_separated(files, "', '"))?;
5992                }
5993                if let Some(pattern) = pattern {
5994                    write!(f, " PATTERN = '{pattern}'")?;
5995                }
5996                if let Some(partition) = partition {
5997                    write!(f, " PARTITION BY {partition}")?;
5998                }
5999                if !file_format.options.is_empty() {
6000                    write!(f, " FILE_FORMAT=({file_format})")?;
6001                }
6002                if !copy_options.options.is_empty() {
6003                    match kind {
6004                        CopyIntoSnowflakeKind::Table => {
6005                            write!(f, " COPY_OPTIONS=({copy_options})")?
6006                        }
6007                        CopyIntoSnowflakeKind::Location => write!(f, " {copy_options}")?,
6008                    }
6009                }
6010                if let Some(validation_mode) = validation_mode {
6011                    write!(f, " VALIDATION_MODE = {validation_mode}")?;
6012                }
6013                Ok(())
6014            }
6015            Statement::CreateType {
6016                name,
6017                representation,
6018            } => {
6019                write!(f, "CREATE TYPE {name}")?;
6020                if let Some(repr) = representation {
6021                    write!(f, " {repr}")?;
6022                }
6023                Ok(())
6024            }
6025            Statement::Pragma { name, value, is_eq } => {
6026                write!(f, "PRAGMA {name}")?;
6027                if value.is_some() {
6028                    let val = value.as_ref().unwrap();
6029                    if *is_eq {
6030                        write!(f, " = {val}")?;
6031                    } else {
6032                        write!(f, "({val})")?;
6033                    }
6034                }
6035                Ok(())
6036            }
6037            Statement::LockTables { tables } => {
6038                write!(f, "LOCK TABLES {}", display_comma_separated(tables))
6039            }
6040            Statement::UnlockTables => {
6041                write!(f, "UNLOCK TABLES")
6042            }
6043            Statement::Unload {
6044                query,
6045                query_text,
6046                to,
6047                auth,
6048                with,
6049                options,
6050            } => {
6051                write!(f, "UNLOAD(")?;
6052                if let Some(query) = query {
6053                    write!(f, "{query}")?;
6054                }
6055                if let Some(query_text) = query_text {
6056                    write!(f, "'{query_text}'")?;
6057                }
6058                write!(f, ") TO {to}")?;
6059                if let Some(auth) = auth {
6060                    write!(f, " IAM_ROLE {auth}")?;
6061                }
6062                if !with.is_empty() {
6063                    write!(f, " WITH ({})", display_comma_separated(with))?;
6064                }
6065                if !options.is_empty() {
6066                    write!(f, " {}", display_separated(options, " "))?;
6067                }
6068                Ok(())
6069            }
6070            Statement::OptimizeTable {
6071                name,
6072                on_cluster,
6073                partition,
6074                include_final,
6075                deduplicate,
6076            } => {
6077                write!(f, "OPTIMIZE TABLE {name}")?;
6078                if let Some(on_cluster) = on_cluster {
6079                    write!(f, " ON CLUSTER {on_cluster}")?;
6080                }
6081                if let Some(partition) = partition {
6082                    write!(f, " {partition}")?;
6083                }
6084                if *include_final {
6085                    write!(f, " FINAL")?;
6086                }
6087                if let Some(deduplicate) = deduplicate {
6088                    write!(f, " {deduplicate}")?;
6089                }
6090                Ok(())
6091            }
6092            Statement::LISTEN { channel } => {
6093                write!(f, "LISTEN {channel}")?;
6094                Ok(())
6095            }
6096            Statement::UNLISTEN { channel } => {
6097                write!(f, "UNLISTEN {channel}")?;
6098                Ok(())
6099            }
6100            Statement::NOTIFY { channel, payload } => {
6101                write!(f, "NOTIFY {channel}")?;
6102                if let Some(payload) = payload {
6103                    write!(f, ", '{payload}'")?;
6104                }
6105                Ok(())
6106            }
6107            Statement::RenameTable(rename_tables) => {
6108                write!(f, "RENAME TABLE {}", display_comma_separated(rename_tables))
6109            }
6110            Statement::RaisError {
6111                message,
6112                severity,
6113                state,
6114                arguments,
6115                options,
6116            } => {
6117                write!(f, "RAISERROR({message}, {severity}, {state}")?;
6118                if !arguments.is_empty() {
6119                    write!(f, ", {}", display_comma_separated(arguments))?;
6120                }
6121                write!(f, ")")?;
6122                if !options.is_empty() {
6123                    write!(f, " WITH {}", display_comma_separated(options))?;
6124                }
6125                Ok(())
6126            }
6127            Statement::Print(s) => write!(f, "{s}"),
6128            Statement::Return(r) => write!(f, "{r}"),
6129            Statement::List(command) => write!(f, "LIST {command}"),
6130            Statement::Remove(command) => write!(f, "REMOVE {command}"),
6131            Statement::ExportData(e) => write!(f, "{e}"),
6132            Statement::CreateUser(s) => write!(f, "{s}"),
6133            Statement::AlterSchema(s) => write!(f, "{s}"),
6134            Statement::Vacuum(s) => write!(f, "{s}"),
6135            Statement::AlterUser(s) => write!(f, "{s}"),
6136            Statement::Reset(s) => write!(f, "{s}"),
6137        }
6138    }
6139}
6140
6141/// Can use to describe options in create sequence or table column type identity
6142/// ```sql
6143/// [ INCREMENT [ BY ] increment ]
6144///     [ MINVALUE minvalue | NO MINVALUE ] [ MAXVALUE maxvalue | NO MAXVALUE ]
6145///     [ START [ WITH ] start ] [ CACHE cache ] [ [ NO ] CYCLE ]
6146/// ```
6147#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6148#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6149#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6150pub enum SequenceOptions {
6151    /// `INCREMENT [BY] <expr>` option; second value indicates presence of `BY` keyword.
6152    IncrementBy(Expr, bool),
6153    /// `MINVALUE <expr>` or `NO MINVALUE`.
6154    MinValue(Option<Expr>),
6155    /// `MAXVALUE <expr>` or `NO MAXVALUE`.
6156    MaxValue(Option<Expr>),
6157    /// `START [WITH] <expr>`; second value indicates presence of `WITH`.
6158    StartWith(Expr, bool),
6159    /// `CACHE <expr>` option.
6160    Cache(Expr),
6161    /// `CYCLE` or `NO CYCLE` option.
6162    Cycle(bool),
6163}
6164
6165impl fmt::Display for SequenceOptions {
6166    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6167        match self {
6168            SequenceOptions::IncrementBy(increment, by) => {
6169                write!(
6170                    f,
6171                    " INCREMENT{by} {increment}",
6172                    by = if *by { " BY" } else { "" },
6173                    increment = increment
6174                )
6175            }
6176            SequenceOptions::MinValue(Some(expr)) => {
6177                write!(f, " MINVALUE {expr}")
6178            }
6179            SequenceOptions::MinValue(None) => {
6180                write!(f, " NO MINVALUE")
6181            }
6182            SequenceOptions::MaxValue(Some(expr)) => {
6183                write!(f, " MAXVALUE {expr}")
6184            }
6185            SequenceOptions::MaxValue(None) => {
6186                write!(f, " NO MAXVALUE")
6187            }
6188            SequenceOptions::StartWith(start, with) => {
6189                write!(
6190                    f,
6191                    " START{with} {start}",
6192                    with = if *with { " WITH" } else { "" },
6193                    start = start
6194                )
6195            }
6196            SequenceOptions::Cache(cache) => {
6197                write!(f, " CACHE {}", *cache)
6198            }
6199            SequenceOptions::Cycle(no) => {
6200                write!(f, " {}CYCLE", if *no { "NO " } else { "" })
6201            }
6202        }
6203    }
6204}
6205
6206/// Assignment for a `SET` statement (name [=|TO] value)
6207#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6208#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6209#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6210pub struct SetAssignment {
6211    /// Optional context scope (e.g., SESSION or LOCAL).
6212    pub scope: Option<ContextModifier>,
6213    /// Assignment target name.
6214    pub name: ObjectName,
6215    /// Assigned expression value.
6216    pub value: Expr,
6217}
6218
6219impl fmt::Display for SetAssignment {
6220    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6221        write!(
6222            f,
6223            "{}{} = {}",
6224            self.scope.map(|s| format!("{s}")).unwrap_or_default(),
6225            self.name,
6226            self.value
6227        )
6228    }
6229}
6230
6231/// Target of a `TRUNCATE TABLE` command
6232///
6233/// Note this is its own struct because `visit_relation` requires an `ObjectName` (not a `Vec<ObjectName>`)
6234#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6235#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6236#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6237pub struct TruncateTableTarget {
6238    /// name of the table being truncated
6239    #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
6240    pub name: ObjectName,
6241    /// Postgres-specific option: explicitly exclude descendants (also default without ONLY)
6242    /// ```sql
6243    /// TRUNCATE TABLE ONLY name
6244    /// ```
6245    /// <https://www.postgresql.org/docs/current/sql-truncate.html>
6246    pub only: bool,
6247    /// Postgres-specific option: asterisk after table name to explicitly indicate descendants
6248    /// ```sql
6249    /// TRUNCATE TABLE name [ * ]
6250    /// ```
6251    /// <https://www.postgresql.org/docs/current/sql-truncate.html>
6252    pub has_asterisk: bool,
6253}
6254
6255impl fmt::Display for TruncateTableTarget {
6256    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6257        if self.only {
6258            write!(f, "ONLY ")?;
6259        };
6260        write!(f, "{}", self.name)?;
6261        if self.has_asterisk {
6262            write!(f, " *")?;
6263        };
6264        Ok(())
6265    }
6266}
6267
6268/// PostgreSQL identity option for TRUNCATE table
6269/// [ RESTART IDENTITY | CONTINUE IDENTITY ]
6270#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6271#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6272#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6273pub enum TruncateIdentityOption {
6274    /// Restart identity values (RESTART IDENTITY).
6275    Restart,
6276    /// Continue identity values (CONTINUE IDENTITY).
6277    Continue,
6278}
6279
6280/// Cascade/restrict option for Postgres TRUNCATE table, MySQL GRANT/REVOKE, etc.
6281/// [ CASCADE | RESTRICT ]
6282#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6283#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6284#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6285pub enum CascadeOption {
6286    /// Apply cascading action (e.g., CASCADE).
6287    Cascade,
6288    /// Restrict the action (e.g., RESTRICT).
6289    Restrict,
6290}
6291
6292impl Display for CascadeOption {
6293    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6294        match self {
6295            CascadeOption::Cascade => write!(f, "CASCADE"),
6296            CascadeOption::Restrict => write!(f, "RESTRICT"),
6297        }
6298    }
6299}
6300
6301/// Transaction started with [ TRANSACTION | WORK ]
6302#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6303#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6304#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6305pub enum BeginTransactionKind {
6306    /// Standard `TRANSACTION` keyword.
6307    Transaction,
6308    /// Alternate `WORK` keyword.
6309    Work,
6310}
6311
6312impl Display for BeginTransactionKind {
6313    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6314        match self {
6315            BeginTransactionKind::Transaction => write!(f, "TRANSACTION"),
6316            BeginTransactionKind::Work => write!(f, "WORK"),
6317        }
6318    }
6319}
6320
6321/// Can use to describe options in  create sequence or table column type identity
6322/// [ MINVALUE minvalue | NO MINVALUE ] [ MAXVALUE maxvalue | NO MAXVALUE ]
6323#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6324#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6325#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6326pub enum MinMaxValue {
6327    /// Clause is not specified.
6328    Empty,
6329    /// NO MINVALUE / NO MAXVALUE.
6330    None,
6331    /// `MINVALUE <expr>` / `MAXVALUE <expr>`.
6332    Some(Expr),
6333}
6334
6335#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6336#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6337#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6338#[non_exhaustive]
6339/// Behavior to apply for `INSERT` when a conflict occurs.
6340pub enum OnInsert {
6341    /// ON DUPLICATE KEY UPDATE (MySQL when the key already exists, then execute an update instead)
6342    DuplicateKeyUpdate(Vec<Assignment>),
6343    /// ON CONFLICT is a PostgreSQL and Sqlite extension
6344    OnConflict(OnConflict),
6345}
6346
6347#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6348#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6349#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6350/// Optional aliases for `INSERT` targets: row alias and optional column aliases.
6351pub struct InsertAliases {
6352    /// Row alias (table-style alias) for the inserted values.
6353    pub row_alias: ObjectName,
6354    /// Optional list of column aliases for the inserted values.
6355    pub col_aliases: Option<Vec<Ident>>,
6356}
6357
6358#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6359#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6360#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6361/// `ON CONFLICT` clause representation.
6362pub struct OnConflict {
6363    /// Optional conflict target specifying columns or constraint.
6364    pub conflict_target: Option<ConflictTarget>,
6365    /// Action to take when a conflict occurs.
6366    pub action: OnConflictAction,
6367}
6368#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6369#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6370#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6371/// Target specification for an `ON CONFLICT` clause.
6372pub enum ConflictTarget {
6373    /// Target specified as a list of columns.
6374    Columns(Vec<Ident>),
6375    /// Target specified as a named constraint.
6376    OnConstraint(ObjectName),
6377}
6378#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6379#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6380#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6381/// Action to perform when an `ON CONFLICT` target is matched.
6382pub enum OnConflictAction {
6383    /// Do nothing on conflict.
6384    DoNothing,
6385    /// Perform an update on conflict.
6386    DoUpdate(DoUpdate),
6387}
6388
6389#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6390#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6391#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6392/// Details for `DO UPDATE` action of an `ON CONFLICT` clause.
6393pub struct DoUpdate {
6394    /// Column assignments to perform on update.
6395    pub assignments: Vec<Assignment>,
6396    /// Optional WHERE clause limiting the update.
6397    pub selection: Option<Expr>,
6398}
6399
6400impl fmt::Display for OnInsert {
6401    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6402        match self {
6403            Self::DuplicateKeyUpdate(expr) => write!(
6404                f,
6405                " ON DUPLICATE KEY UPDATE {}",
6406                display_comma_separated(expr)
6407            ),
6408            Self::OnConflict(o) => write!(f, "{o}"),
6409        }
6410    }
6411}
6412impl fmt::Display for OnConflict {
6413    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6414        write!(f, " ON CONFLICT")?;
6415        if let Some(target) = &self.conflict_target {
6416            write!(f, "{target}")?;
6417        }
6418        write!(f, " {}", self.action)
6419    }
6420}
6421impl fmt::Display for ConflictTarget {
6422    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6423        match self {
6424            ConflictTarget::Columns(cols) => write!(f, "({})", display_comma_separated(cols)),
6425            ConflictTarget::OnConstraint(name) => write!(f, " ON CONSTRAINT {name}"),
6426        }
6427    }
6428}
6429impl fmt::Display for OnConflictAction {
6430    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6431        match self {
6432            Self::DoNothing => write!(f, "DO NOTHING"),
6433            Self::DoUpdate(do_update) => {
6434                write!(f, "DO UPDATE")?;
6435                if !do_update.assignments.is_empty() {
6436                    write!(
6437                        f,
6438                        " SET {}",
6439                        display_comma_separated(&do_update.assignments)
6440                    )?;
6441                }
6442                if let Some(selection) = &do_update.selection {
6443                    write!(f, " WHERE {selection}")?;
6444                }
6445                Ok(())
6446            }
6447        }
6448    }
6449}
6450
6451/// Privileges granted in a GRANT statement or revoked in a REVOKE statement.
6452#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6453#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6454#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6455pub enum Privileges {
6456    /// All privileges applicable to the object type
6457    All {
6458        /// Optional keyword from the spec, ignored in practice
6459        with_privileges_keyword: bool,
6460    },
6461    /// Specific privileges (e.g. `SELECT`, `INSERT`)
6462    Actions(Vec<Action>),
6463}
6464
6465impl fmt::Display for Privileges {
6466    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6467        match self {
6468            Privileges::All {
6469                with_privileges_keyword,
6470            } => {
6471                write!(
6472                    f,
6473                    "ALL{}",
6474                    if *with_privileges_keyword {
6475                        " PRIVILEGES"
6476                    } else {
6477                        ""
6478                    }
6479                )
6480            }
6481            Privileges::Actions(actions) => {
6482                write!(f, "{}", display_comma_separated(actions))
6483            }
6484        }
6485    }
6486}
6487
6488/// Specific direction for FETCH statement
6489#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6490#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6491#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6492pub enum FetchDirection {
6493    /// Fetch a specific count of rows.
6494    Count {
6495        /// The limit value for the count.
6496        limit: Value,
6497    },
6498    /// Fetch the next row.
6499    Next,
6500    /// Fetch the prior row.
6501    Prior,
6502    /// Fetch the first row.
6503    First,
6504    /// Fetch the last row.
6505    Last,
6506    /// Fetch an absolute row by index.
6507    Absolute {
6508        /// The absolute index value.
6509        limit: Value,
6510    },
6511    /// Fetch a row relative to the current position.
6512    Relative {
6513        /// The relative offset value.
6514        limit: Value,
6515    },
6516    /// Fetch all rows.
6517    All,
6518    // FORWARD
6519    // FORWARD count
6520    /// Fetch forward by an optional limit.
6521    Forward {
6522        /// Optional forward limit.
6523        limit: Option<Value>,
6524    },
6525    /// Fetch all forward rows.
6526    ForwardAll,
6527    // BACKWARD
6528    // BACKWARD count
6529    /// Fetch backward by an optional limit.
6530    Backward {
6531        /// Optional backward limit.
6532        limit: Option<Value>,
6533    },
6534    /// Fetch all backward rows.
6535    BackwardAll,
6536}
6537
6538impl fmt::Display for FetchDirection {
6539    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6540        match self {
6541            FetchDirection::Count { limit } => f.write_str(&limit.to_string())?,
6542            FetchDirection::Next => f.write_str("NEXT")?,
6543            FetchDirection::Prior => f.write_str("PRIOR")?,
6544            FetchDirection::First => f.write_str("FIRST")?,
6545            FetchDirection::Last => f.write_str("LAST")?,
6546            FetchDirection::Absolute { limit } => {
6547                f.write_str("ABSOLUTE ")?;
6548                f.write_str(&limit.to_string())?;
6549            }
6550            FetchDirection::Relative { limit } => {
6551                f.write_str("RELATIVE ")?;
6552                f.write_str(&limit.to_string())?;
6553            }
6554            FetchDirection::All => f.write_str("ALL")?,
6555            FetchDirection::Forward { limit } => {
6556                f.write_str("FORWARD")?;
6557
6558                if let Some(l) = limit {
6559                    f.write_str(" ")?;
6560                    f.write_str(&l.to_string())?;
6561                }
6562            }
6563            FetchDirection::ForwardAll => f.write_str("FORWARD ALL")?,
6564            FetchDirection::Backward { limit } => {
6565                f.write_str("BACKWARD")?;
6566
6567                if let Some(l) = limit {
6568                    f.write_str(" ")?;
6569                    f.write_str(&l.to_string())?;
6570                }
6571            }
6572            FetchDirection::BackwardAll => f.write_str("BACKWARD ALL")?,
6573        };
6574
6575        Ok(())
6576    }
6577}
6578
6579/// The "position" for a FETCH statement.
6580///
6581/// [MsSql](https://learn.microsoft.com/en-us/sql/t-sql/language-elements/fetch-transact-sql)
6582#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6583#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6584#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6585pub enum FetchPosition {
6586    /// Use `FROM <pos>` position specifier.
6587    From,
6588    /// Use `IN <pos>` position specifier.
6589    In,
6590}
6591
6592impl fmt::Display for FetchPosition {
6593    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6594        match self {
6595            FetchPosition::From => f.write_str("FROM")?,
6596            FetchPosition::In => f.write_str("IN")?,
6597        };
6598
6599        Ok(())
6600    }
6601}
6602
6603/// A privilege on a database object (table, sequence, etc.).
6604#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6605#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6606#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6607pub enum Action {
6608    /// Add a search optimization.
6609    AddSearchOptimization,
6610    /// Apply an `APPLY` operation with a specific type.
6611    Apply {
6612        /// The type of apply operation.
6613        apply_type: ActionApplyType,
6614    },
6615    /// Apply a budget operation.
6616    ApplyBudget,
6617    /// Attach a listing.
6618    AttachListing,
6619    /// Attach a policy.
6620    AttachPolicy,
6621    /// Audit operation.
6622    Audit,
6623    /// Bind a service endpoint.
6624    BindServiceEndpoint,
6625    /// Connect permission.
6626    Connect,
6627    /// Create action, optionally specifying an object type.
6628    Create {
6629        /// Optional object type to create.
6630        obj_type: Option<ActionCreateObjectType>,
6631    },
6632    /// Actions related to database roles.
6633    DatabaseRole {
6634        /// The role name.
6635        role: ObjectName,
6636    },
6637    /// Delete permission.
6638    Delete,
6639    /// Drop permission.
6640    Drop,
6641    /// Evolve schema permission.
6642    EvolveSchema,
6643    /// Exec action (execute) with optional object type.
6644    Exec {
6645        /// Optional execute object type.
6646        obj_type: Option<ActionExecuteObjectType>,
6647    },
6648    /// Execute action with optional object type.
6649    Execute {
6650        /// Optional execute object type.
6651        obj_type: Option<ActionExecuteObjectType>,
6652    },
6653    /// Failover operation.
6654    Failover,
6655    /// Use imported privileges.
6656    ImportedPrivileges,
6657    /// Import a share.
6658    ImportShare,
6659    /// Insert rows with optional column list.
6660    Insert {
6661        /// Optional list of target columns for insert.
6662        columns: Option<Vec<Ident>>,
6663    },
6664    /// Manage operation with a specific manage type.
6665    Manage {
6666        /// The specific manage sub-type.
6667        manage_type: ActionManageType,
6668    },
6669    /// Manage releases.
6670    ManageReleases,
6671    /// Manage versions.
6672    ManageVersions,
6673    /// Modify operation with an optional modify type.
6674    Modify {
6675        /// The optional modify sub-type.
6676        modify_type: Option<ActionModifyType>,
6677    },
6678    /// Monitor operation with an optional monitor type.
6679    Monitor {
6680        /// The optional monitor sub-type.
6681        monitor_type: Option<ActionMonitorType>,
6682    },
6683    /// Operate permission.
6684    Operate,
6685    /// Override share restrictions.
6686    OverrideShareRestrictions,
6687    /// Ownership permission.
6688    Ownership,
6689    /// Purchase a data exchange listing.
6690    PurchaseDataExchangeListing,
6691
6692    /// Read access.
6693    Read,
6694    /// Read session-level access.
6695    ReadSession,
6696    /// References with optional column list.
6697    References {
6698        /// Optional list of referenced column identifiers.
6699        columns: Option<Vec<Ident>>,
6700    },
6701    /// Replication permission.
6702    Replicate,
6703    /// Resolve all references.
6704    ResolveAll,
6705    /// Role-related permission with target role name.
6706    Role {
6707        /// The target role name.
6708        role: ObjectName,
6709    },
6710    /// Select permission with optional column list.
6711    Select {
6712        /// Optional list of selected columns.
6713        columns: Option<Vec<Ident>>,
6714    },
6715    /// Temporary object permission.
6716    Temporary,
6717    /// Trigger-related permission.
6718    Trigger,
6719    /// Truncate permission.
6720    Truncate,
6721    /// Update permission with optional affected columns.
6722    Update {
6723        /// Optional list of columns affected by update.
6724        columns: Option<Vec<Ident>>,
6725    },
6726    /// Usage permission.
6727    Usage,
6728}
6729
6730impl fmt::Display for Action {
6731    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6732        match self {
6733            Action::AddSearchOptimization => f.write_str("ADD SEARCH OPTIMIZATION")?,
6734            Action::Apply { apply_type } => write!(f, "APPLY {apply_type}")?,
6735            Action::ApplyBudget => f.write_str("APPLYBUDGET")?,
6736            Action::AttachListing => f.write_str("ATTACH LISTING")?,
6737            Action::AttachPolicy => f.write_str("ATTACH POLICY")?,
6738            Action::Audit => f.write_str("AUDIT")?,
6739            Action::BindServiceEndpoint => f.write_str("BIND SERVICE ENDPOINT")?,
6740            Action::Connect => f.write_str("CONNECT")?,
6741            Action::Create { obj_type } => {
6742                f.write_str("CREATE")?;
6743                if let Some(obj_type) = obj_type {
6744                    write!(f, " {obj_type}")?
6745                }
6746            }
6747            Action::DatabaseRole { role } => write!(f, "DATABASE ROLE {role}")?,
6748            Action::Delete => f.write_str("DELETE")?,
6749            Action::Drop => f.write_str("DROP")?,
6750            Action::EvolveSchema => f.write_str("EVOLVE SCHEMA")?,
6751            Action::Exec { obj_type } => {
6752                f.write_str("EXEC")?;
6753                if let Some(obj_type) = obj_type {
6754                    write!(f, " {obj_type}")?
6755                }
6756            }
6757            Action::Execute { obj_type } => {
6758                f.write_str("EXECUTE")?;
6759                if let Some(obj_type) = obj_type {
6760                    write!(f, " {obj_type}")?
6761                }
6762            }
6763            Action::Failover => f.write_str("FAILOVER")?,
6764            Action::ImportedPrivileges => f.write_str("IMPORTED PRIVILEGES")?,
6765            Action::ImportShare => f.write_str("IMPORT SHARE")?,
6766            Action::Insert { .. } => f.write_str("INSERT")?,
6767            Action::Manage { manage_type } => write!(f, "MANAGE {manage_type}")?,
6768            Action::ManageReleases => f.write_str("MANAGE RELEASES")?,
6769            Action::ManageVersions => f.write_str("MANAGE VERSIONS")?,
6770            Action::Modify { modify_type } => {
6771                write!(f, "MODIFY")?;
6772                if let Some(modify_type) = modify_type {
6773                    write!(f, " {modify_type}")?;
6774                }
6775            }
6776            Action::Monitor { monitor_type } => {
6777                write!(f, "MONITOR")?;
6778                if let Some(monitor_type) = monitor_type {
6779                    write!(f, " {monitor_type}")?
6780                }
6781            }
6782            Action::Operate => f.write_str("OPERATE")?,
6783            Action::OverrideShareRestrictions => f.write_str("OVERRIDE SHARE RESTRICTIONS")?,
6784            Action::Ownership => f.write_str("OWNERSHIP")?,
6785            Action::PurchaseDataExchangeListing => f.write_str("PURCHASE DATA EXCHANGE LISTING")?,
6786            Action::Read => f.write_str("READ")?,
6787            Action::ReadSession => f.write_str("READ SESSION")?,
6788            Action::References { .. } => f.write_str("REFERENCES")?,
6789            Action::Replicate => f.write_str("REPLICATE")?,
6790            Action::ResolveAll => f.write_str("RESOLVE ALL")?,
6791            Action::Role { role } => write!(f, "ROLE {role}")?,
6792            Action::Select { .. } => f.write_str("SELECT")?,
6793            Action::Temporary => f.write_str("TEMPORARY")?,
6794            Action::Trigger => f.write_str("TRIGGER")?,
6795            Action::Truncate => f.write_str("TRUNCATE")?,
6796            Action::Update { .. } => f.write_str("UPDATE")?,
6797            Action::Usage => f.write_str("USAGE")?,
6798        };
6799        match self {
6800            Action::Insert { columns }
6801            | Action::References { columns }
6802            | Action::Select { columns }
6803            | Action::Update { columns } => {
6804                if let Some(columns) = columns {
6805                    write!(f, " ({})", display_comma_separated(columns))?;
6806                }
6807            }
6808            _ => (),
6809        };
6810        Ok(())
6811    }
6812}
6813
6814#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6815#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6816#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6817/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
6818/// under `globalPrivileges` in the `CREATE` privilege.
6819pub enum ActionCreateObjectType {
6820    /// An account-level object.
6821    Account,
6822    /// An application object.
6823    Application,
6824    /// An application package object.
6825    ApplicationPackage,
6826    /// A compute pool object.
6827    ComputePool,
6828    /// A data exchange listing.
6829    DataExchangeListing,
6830    /// A database object.
6831    Database,
6832    /// An external volume object.
6833    ExternalVolume,
6834    /// A failover group object.
6835    FailoverGroup,
6836    /// An integration object.
6837    Integration,
6838    /// A network policy object.
6839    NetworkPolicy,
6840    /// An organization listing.
6841    OrganiationListing,
6842    /// A replication group object.
6843    ReplicationGroup,
6844    /// A role object.
6845    Role,
6846    /// A schema object.
6847    Schema,
6848    /// A share object.
6849    Share,
6850    /// A user object.
6851    User,
6852    /// A warehouse object.
6853    Warehouse,
6854}
6855
6856impl fmt::Display for ActionCreateObjectType {
6857    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6858        match self {
6859            ActionCreateObjectType::Account => write!(f, "ACCOUNT"),
6860            ActionCreateObjectType::Application => write!(f, "APPLICATION"),
6861            ActionCreateObjectType::ApplicationPackage => write!(f, "APPLICATION PACKAGE"),
6862            ActionCreateObjectType::ComputePool => write!(f, "COMPUTE POOL"),
6863            ActionCreateObjectType::DataExchangeListing => write!(f, "DATA EXCHANGE LISTING"),
6864            ActionCreateObjectType::Database => write!(f, "DATABASE"),
6865            ActionCreateObjectType::ExternalVolume => write!(f, "EXTERNAL VOLUME"),
6866            ActionCreateObjectType::FailoverGroup => write!(f, "FAILOVER GROUP"),
6867            ActionCreateObjectType::Integration => write!(f, "INTEGRATION"),
6868            ActionCreateObjectType::NetworkPolicy => write!(f, "NETWORK POLICY"),
6869            ActionCreateObjectType::OrganiationListing => write!(f, "ORGANIZATION LISTING"),
6870            ActionCreateObjectType::ReplicationGroup => write!(f, "REPLICATION GROUP"),
6871            ActionCreateObjectType::Role => write!(f, "ROLE"),
6872            ActionCreateObjectType::Schema => write!(f, "SCHEMA"),
6873            ActionCreateObjectType::Share => write!(f, "SHARE"),
6874            ActionCreateObjectType::User => write!(f, "USER"),
6875            ActionCreateObjectType::Warehouse => write!(f, "WAREHOUSE"),
6876        }
6877    }
6878}
6879
6880#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6881#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6882#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6883/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
6884/// under `globalPrivileges` in the `APPLY` privilege.
6885pub enum ActionApplyType {
6886    /// Apply an aggregation policy.
6887    AggregationPolicy,
6888    /// Apply an authentication policy.
6889    AuthenticationPolicy,
6890    /// Apply a join policy.
6891    JoinPolicy,
6892    /// Apply a masking policy.
6893    MaskingPolicy,
6894    /// Apply a packages policy.
6895    PackagesPolicy,
6896    /// Apply a password policy.
6897    PasswordPolicy,
6898    /// Apply a projection policy.
6899    ProjectionPolicy,
6900    /// Apply a row access policy.
6901    RowAccessPolicy,
6902    /// Apply a session policy.
6903    SessionPolicy,
6904    /// Apply a tag.
6905    Tag,
6906}
6907
6908impl fmt::Display for ActionApplyType {
6909    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6910        match self {
6911            ActionApplyType::AggregationPolicy => write!(f, "AGGREGATION POLICY"),
6912            ActionApplyType::AuthenticationPolicy => write!(f, "AUTHENTICATION POLICY"),
6913            ActionApplyType::JoinPolicy => write!(f, "JOIN POLICY"),
6914            ActionApplyType::MaskingPolicy => write!(f, "MASKING POLICY"),
6915            ActionApplyType::PackagesPolicy => write!(f, "PACKAGES POLICY"),
6916            ActionApplyType::PasswordPolicy => write!(f, "PASSWORD POLICY"),
6917            ActionApplyType::ProjectionPolicy => write!(f, "PROJECTION POLICY"),
6918            ActionApplyType::RowAccessPolicy => write!(f, "ROW ACCESS POLICY"),
6919            ActionApplyType::SessionPolicy => write!(f, "SESSION POLICY"),
6920            ActionApplyType::Tag => write!(f, "TAG"),
6921        }
6922    }
6923}
6924
6925#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6926#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6927#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6928/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
6929/// under `globalPrivileges` in the `EXECUTE` privilege.
6930pub enum ActionExecuteObjectType {
6931    /// Alert object.
6932    Alert,
6933    /// Data metric function object.
6934    DataMetricFunction,
6935    /// Managed alert object.
6936    ManagedAlert,
6937    /// Managed task object.
6938    ManagedTask,
6939    /// Task object.
6940    Task,
6941}
6942
6943impl fmt::Display for ActionExecuteObjectType {
6944    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6945        match self {
6946            ActionExecuteObjectType::Alert => write!(f, "ALERT"),
6947            ActionExecuteObjectType::DataMetricFunction => write!(f, "DATA METRIC FUNCTION"),
6948            ActionExecuteObjectType::ManagedAlert => write!(f, "MANAGED ALERT"),
6949            ActionExecuteObjectType::ManagedTask => write!(f, "MANAGED TASK"),
6950            ActionExecuteObjectType::Task => write!(f, "TASK"),
6951        }
6952    }
6953}
6954
6955#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6956#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6957#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6958/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
6959/// under `globalPrivileges` in the `MANAGE` privilege.
6960pub enum ActionManageType {
6961    /// Account support cases management.
6962    AccountSupportCases,
6963    /// Event sharing management.
6964    EventSharing,
6965    /// Grants management.
6966    Grants,
6967    /// Listing auto-fulfillment management.
6968    ListingAutoFulfillment,
6969    /// Organization support cases management.
6970    OrganizationSupportCases,
6971    /// User support cases management.
6972    UserSupportCases,
6973    /// Warehouses management.
6974    Warehouses,
6975}
6976
6977impl fmt::Display for ActionManageType {
6978    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6979        match self {
6980            ActionManageType::AccountSupportCases => write!(f, "ACCOUNT SUPPORT CASES"),
6981            ActionManageType::EventSharing => write!(f, "EVENT SHARING"),
6982            ActionManageType::Grants => write!(f, "GRANTS"),
6983            ActionManageType::ListingAutoFulfillment => write!(f, "LISTING AUTO FULFILLMENT"),
6984            ActionManageType::OrganizationSupportCases => write!(f, "ORGANIZATION SUPPORT CASES"),
6985            ActionManageType::UserSupportCases => write!(f, "USER SUPPORT CASES"),
6986            ActionManageType::Warehouses => write!(f, "WAREHOUSES"),
6987        }
6988    }
6989}
6990
6991#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6992#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6993#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6994/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
6995/// under `globalPrivileges` in the `MODIFY` privilege.
6996pub enum ActionModifyType {
6997    /// Modify log level.
6998    LogLevel,
6999    /// Modify trace level.
7000    TraceLevel,
7001    /// Modify session log level.
7002    SessionLogLevel,
7003    /// Modify session trace level.
7004    SessionTraceLevel,
7005}
7006
7007impl fmt::Display for ActionModifyType {
7008    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7009        match self {
7010            ActionModifyType::LogLevel => write!(f, "LOG LEVEL"),
7011            ActionModifyType::TraceLevel => write!(f, "TRACE LEVEL"),
7012            ActionModifyType::SessionLogLevel => write!(f, "SESSION LOG LEVEL"),
7013            ActionModifyType::SessionTraceLevel => write!(f, "SESSION TRACE LEVEL"),
7014        }
7015    }
7016}
7017
7018#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7019#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7020#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7021/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
7022/// under `globalPrivileges` in the `MONITOR` privilege.
7023pub enum ActionMonitorType {
7024    /// Monitor execution.
7025    Execution,
7026    /// Monitor security.
7027    Security,
7028    /// Monitor usage.
7029    Usage,
7030}
7031
7032impl fmt::Display for ActionMonitorType {
7033    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7034        match self {
7035            ActionMonitorType::Execution => write!(f, "EXECUTION"),
7036            ActionMonitorType::Security => write!(f, "SECURITY"),
7037            ActionMonitorType::Usage => write!(f, "USAGE"),
7038        }
7039    }
7040}
7041
7042/// The principal that receives the privileges
7043#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7044#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7045#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7046pub struct Grantee {
7047    /// The category/type of grantee (role, user, share, etc.).
7048    pub grantee_type: GranteesType,
7049    /// Optional name of the grantee (identifier or user@host).
7050    pub name: Option<GranteeName>,
7051}
7052
7053impl fmt::Display for Grantee {
7054    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7055        match self.grantee_type {
7056            GranteesType::Role => {
7057                write!(f, "ROLE ")?;
7058            }
7059            GranteesType::Share => {
7060                write!(f, "SHARE ")?;
7061            }
7062            GranteesType::User => {
7063                write!(f, "USER ")?;
7064            }
7065            GranteesType::Group => {
7066                write!(f, "GROUP ")?;
7067            }
7068            GranteesType::Public => {
7069                write!(f, "PUBLIC ")?;
7070            }
7071            GranteesType::DatabaseRole => {
7072                write!(f, "DATABASE ROLE ")?;
7073            }
7074            GranteesType::Application => {
7075                write!(f, "APPLICATION ")?;
7076            }
7077            GranteesType::ApplicationRole => {
7078                write!(f, "APPLICATION ROLE ")?;
7079            }
7080            GranteesType::None => (),
7081        }
7082        if let Some(ref name) = self.name {
7083            name.fmt(f)?;
7084        }
7085        Ok(())
7086    }
7087}
7088
7089#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7090#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7091#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7092/// The kind of principal receiving privileges.
7093pub enum GranteesType {
7094    /// A role principal.
7095    Role,
7096    /// A share principal.
7097    Share,
7098    /// A user principal.
7099    User,
7100    /// A group principal.
7101    Group,
7102    /// The public principal.
7103    Public,
7104    /// A database role principal.
7105    DatabaseRole,
7106    /// An application principal.
7107    Application,
7108    /// An application role principal.
7109    ApplicationRole,
7110    /// No specific principal (e.g. `NONE`).
7111    None,
7112}
7113
7114/// Users/roles designated in a GRANT/REVOKE
7115#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7116#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7117#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7118pub enum GranteeName {
7119    /// A bare identifier
7120    ObjectName(ObjectName),
7121    /// A MySQL user/host pair such as 'root'@'%'
7122    UserHost {
7123        /// The user identifier portion.
7124        user: Ident,
7125        /// The host identifier portion.
7126        host: Ident,
7127    },
7128}
7129
7130impl fmt::Display for GranteeName {
7131    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7132        match self {
7133            GranteeName::ObjectName(name) => name.fmt(f),
7134            GranteeName::UserHost { user, host } => {
7135                write!(f, "{user}@{host}")
7136            }
7137        }
7138    }
7139}
7140
7141/// Objects on which privileges are granted in a GRANT statement.
7142#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7143#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7144#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7145pub enum GrantObjects {
7146    /// Grant privileges on `ALL SEQUENCES IN SCHEMA <schema_name> [, ...]`
7147    AllSequencesInSchema {
7148        /// The target schema names.
7149        schemas: Vec<ObjectName>,
7150    },
7151    /// Grant privileges on `ALL TABLES IN SCHEMA <schema_name> [, ...]`
7152    AllTablesInSchema {
7153        /// The target schema names.
7154        schemas: Vec<ObjectName>,
7155    },
7156    /// Grant privileges on `ALL VIEWS IN SCHEMA <schema_name> [, ...]`
7157    AllViewsInSchema {
7158        /// The target schema names.
7159        schemas: Vec<ObjectName>,
7160    },
7161    /// Grant privileges on `ALL MATERIALIZED VIEWS IN SCHEMA <schema_name> [, ...]`
7162    AllMaterializedViewsInSchema {
7163        /// The target schema names.
7164        schemas: Vec<ObjectName>,
7165    },
7166    /// Grant privileges on `ALL EXTERNAL TABLES IN SCHEMA <schema_name> [, ...]`
7167    AllExternalTablesInSchema {
7168        /// The target schema names.
7169        schemas: Vec<ObjectName>,
7170    },
7171    /// Grant privileges on `ALL FUNCTIONS IN SCHEMA <schema_name> [, ...]`
7172    AllFunctionsInSchema {
7173        /// The target schema names.
7174        schemas: Vec<ObjectName>,
7175    },
7176    /// Grant privileges on `FUTURE SCHEMAS IN DATABASE <database_name> [, ...]`
7177    FutureSchemasInDatabase {
7178        /// The target database names.
7179        databases: Vec<ObjectName>,
7180    },
7181    /// Grant privileges on `FUTURE TABLES IN SCHEMA <schema_name> [, ...]`
7182    FutureTablesInSchema {
7183        /// The target schema names.
7184        schemas: Vec<ObjectName>,
7185    },
7186    /// Grant privileges on `FUTURE VIEWS IN SCHEMA <schema_name> [, ...]`
7187    FutureViewsInSchema {
7188        /// The target schema names.
7189        schemas: Vec<ObjectName>,
7190    },
7191    /// Grant privileges on `FUTURE EXTERNAL TABLES IN SCHEMA <schema_name> [, ...]`
7192    FutureExternalTablesInSchema {
7193        /// The target schema names.
7194        schemas: Vec<ObjectName>,
7195    },
7196    /// Grant privileges on `FUTURE MATERIALIZED VIEWS IN SCHEMA <schema_name> [, ...]`
7197    FutureMaterializedViewsInSchema {
7198        /// The target schema names.
7199        schemas: Vec<ObjectName>,
7200    },
7201    /// Grant privileges on `FUTURE SEQUENCES IN SCHEMA <schema_name> [, ...]`
7202    FutureSequencesInSchema {
7203        /// The target schema names.
7204        schemas: Vec<ObjectName>,
7205    },
7206    /// Grant privileges on specific databases
7207    Databases(Vec<ObjectName>),
7208    /// Grant privileges on specific schemas
7209    Schemas(Vec<ObjectName>),
7210    /// Grant privileges on specific sequences
7211    Sequences(Vec<ObjectName>),
7212    /// Grant privileges on specific tables
7213    Tables(Vec<ObjectName>),
7214    /// Grant privileges on specific views
7215    Views(Vec<ObjectName>),
7216    /// Grant privileges on specific warehouses
7217    Warehouses(Vec<ObjectName>),
7218    /// Grant privileges on specific integrations
7219    Integrations(Vec<ObjectName>),
7220    /// Grant privileges on resource monitors
7221    ResourceMonitors(Vec<ObjectName>),
7222    /// Grant privileges on users
7223    Users(Vec<ObjectName>),
7224    /// Grant privileges on compute pools
7225    ComputePools(Vec<ObjectName>),
7226    /// Grant privileges on connections
7227    Connections(Vec<ObjectName>),
7228    /// Grant privileges on failover groups
7229    FailoverGroup(Vec<ObjectName>),
7230    /// Grant privileges on replication group
7231    ReplicationGroup(Vec<ObjectName>),
7232    /// Grant privileges on external volumes
7233    ExternalVolumes(Vec<ObjectName>),
7234    /// Grant privileges on a procedure. In dialects that
7235    /// support overloading, the argument types must be specified.
7236    ///
7237    /// For example:
7238    /// `GRANT USAGE ON PROCEDURE foo(varchar) TO ROLE role1`
7239    Procedure {
7240        /// The procedure name.
7241        name: ObjectName,
7242        /// Optional argument types for overloaded procedures.
7243        arg_types: Vec<DataType>,
7244    },
7245
7246    /// Grant privileges on a function. In dialects that
7247    /// support overloading, the argument types must be specified.
7248    ///
7249    /// For example:
7250    /// `GRANT USAGE ON FUNCTION foo(varchar) TO ROLE role1`
7251    Function {
7252        /// The function name.
7253        name: ObjectName,
7254        /// Optional argument types for overloaded functions.
7255        arg_types: Vec<DataType>,
7256    },
7257}
7258
7259impl fmt::Display for GrantObjects {
7260    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7261        match self {
7262            GrantObjects::Sequences(sequences) => {
7263                write!(f, "SEQUENCE {}", display_comma_separated(sequences))
7264            }
7265            GrantObjects::Databases(databases) => {
7266                write!(f, "DATABASE {}", display_comma_separated(databases))
7267            }
7268            GrantObjects::Schemas(schemas) => {
7269                write!(f, "SCHEMA {}", display_comma_separated(schemas))
7270            }
7271            GrantObjects::Tables(tables) => {
7272                write!(f, "{}", display_comma_separated(tables))
7273            }
7274            GrantObjects::Views(views) => {
7275                write!(f, "VIEW {}", display_comma_separated(views))
7276            }
7277            GrantObjects::Warehouses(warehouses) => {
7278                write!(f, "WAREHOUSE {}", display_comma_separated(warehouses))
7279            }
7280            GrantObjects::Integrations(integrations) => {
7281                write!(f, "INTEGRATION {}", display_comma_separated(integrations))
7282            }
7283            GrantObjects::AllSequencesInSchema { schemas } => {
7284                write!(
7285                    f,
7286                    "ALL SEQUENCES IN SCHEMA {}",
7287                    display_comma_separated(schemas)
7288                )
7289            }
7290            GrantObjects::AllTablesInSchema { schemas } => {
7291                write!(
7292                    f,
7293                    "ALL TABLES IN SCHEMA {}",
7294                    display_comma_separated(schemas)
7295                )
7296            }
7297            GrantObjects::AllExternalTablesInSchema { schemas } => {
7298                write!(
7299                    f,
7300                    "ALL EXTERNAL TABLES IN SCHEMA {}",
7301                    display_comma_separated(schemas)
7302                )
7303            }
7304            GrantObjects::AllViewsInSchema { schemas } => {
7305                write!(
7306                    f,
7307                    "ALL VIEWS IN SCHEMA {}",
7308                    display_comma_separated(schemas)
7309                )
7310            }
7311            GrantObjects::AllMaterializedViewsInSchema { schemas } => {
7312                write!(
7313                    f,
7314                    "ALL MATERIALIZED VIEWS IN SCHEMA {}",
7315                    display_comma_separated(schemas)
7316                )
7317            }
7318            GrantObjects::AllFunctionsInSchema { schemas } => {
7319                write!(
7320                    f,
7321                    "ALL FUNCTIONS IN SCHEMA {}",
7322                    display_comma_separated(schemas)
7323                )
7324            }
7325            GrantObjects::FutureSchemasInDatabase { databases } => {
7326                write!(
7327                    f,
7328                    "FUTURE SCHEMAS IN DATABASE {}",
7329                    display_comma_separated(databases)
7330                )
7331            }
7332            GrantObjects::FutureTablesInSchema { schemas } => {
7333                write!(
7334                    f,
7335                    "FUTURE TABLES IN SCHEMA {}",
7336                    display_comma_separated(schemas)
7337                )
7338            }
7339            GrantObjects::FutureExternalTablesInSchema { schemas } => {
7340                write!(
7341                    f,
7342                    "FUTURE EXTERNAL TABLES IN SCHEMA {}",
7343                    display_comma_separated(schemas)
7344                )
7345            }
7346            GrantObjects::FutureViewsInSchema { schemas } => {
7347                write!(
7348                    f,
7349                    "FUTURE VIEWS IN SCHEMA {}",
7350                    display_comma_separated(schemas)
7351                )
7352            }
7353            GrantObjects::FutureMaterializedViewsInSchema { schemas } => {
7354                write!(
7355                    f,
7356                    "FUTURE MATERIALIZED VIEWS IN SCHEMA {}",
7357                    display_comma_separated(schemas)
7358                )
7359            }
7360            GrantObjects::FutureSequencesInSchema { schemas } => {
7361                write!(
7362                    f,
7363                    "FUTURE SEQUENCES IN SCHEMA {}",
7364                    display_comma_separated(schemas)
7365                )
7366            }
7367            GrantObjects::ResourceMonitors(objects) => {
7368                write!(f, "RESOURCE MONITOR {}", display_comma_separated(objects))
7369            }
7370            GrantObjects::Users(objects) => {
7371                write!(f, "USER {}", display_comma_separated(objects))
7372            }
7373            GrantObjects::ComputePools(objects) => {
7374                write!(f, "COMPUTE POOL {}", display_comma_separated(objects))
7375            }
7376            GrantObjects::Connections(objects) => {
7377                write!(f, "CONNECTION {}", display_comma_separated(objects))
7378            }
7379            GrantObjects::FailoverGroup(objects) => {
7380                write!(f, "FAILOVER GROUP {}", display_comma_separated(objects))
7381            }
7382            GrantObjects::ReplicationGroup(objects) => {
7383                write!(f, "REPLICATION GROUP {}", display_comma_separated(objects))
7384            }
7385            GrantObjects::ExternalVolumes(objects) => {
7386                write!(f, "EXTERNAL VOLUME {}", display_comma_separated(objects))
7387            }
7388            GrantObjects::Procedure { name, arg_types } => {
7389                write!(f, "PROCEDURE {name}")?;
7390                if !arg_types.is_empty() {
7391                    write!(f, "({})", display_comma_separated(arg_types))?;
7392                }
7393                Ok(())
7394            }
7395            GrantObjects::Function { name, arg_types } => {
7396                write!(f, "FUNCTION {name}")?;
7397                if !arg_types.is_empty() {
7398                    write!(f, "({})", display_comma_separated(arg_types))?;
7399                }
7400                Ok(())
7401            }
7402        }
7403    }
7404}
7405
7406/// A `DENY` statement
7407///
7408/// [MsSql](https://learn.microsoft.com/en-us/sql/t-sql/statements/deny-transact-sql)
7409#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7410#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7411#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7412pub struct DenyStatement {
7413    /// The privileges to deny.
7414    pub privileges: Privileges,
7415    /// The objects the privileges apply to.
7416    pub objects: GrantObjects,
7417    /// The grantees (users/roles) to whom the denial applies.
7418    pub grantees: Vec<Grantee>,
7419    /// Optional identifier of the principal that performed the grant.
7420    pub granted_by: Option<Ident>,
7421    /// Optional cascade option controlling dependent objects.
7422    pub cascade: Option<CascadeOption>,
7423}
7424
7425impl fmt::Display for DenyStatement {
7426    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7427        write!(f, "DENY {}", self.privileges)?;
7428        write!(f, " ON {}", self.objects)?;
7429        if !self.grantees.is_empty() {
7430            write!(f, " TO {}", display_comma_separated(&self.grantees))?;
7431        }
7432        if let Some(cascade) = &self.cascade {
7433            write!(f, " {cascade}")?;
7434        }
7435        if let Some(granted_by) = &self.granted_by {
7436            write!(f, " AS {granted_by}")?;
7437        }
7438        Ok(())
7439    }
7440}
7441
7442/// SQL assignment `foo = expr` as used in SQLUpdate
7443#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7444#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7445#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7446pub struct Assignment {
7447    /// The left-hand side of the assignment.
7448    pub target: AssignmentTarget,
7449    /// The expression assigned to the target.
7450    pub value: Expr,
7451}
7452
7453impl fmt::Display for Assignment {
7454    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7455        write!(f, "{} = {}", self.target, self.value)
7456    }
7457}
7458
7459/// Left-hand side of an assignment in an UPDATE statement,
7460/// e.g. `foo` in `foo = 5` (ColumnName assignment) or
7461/// `(a, b)` in `(a, b) = (1, 2)` (Tuple assignment).
7462#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7463#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7464#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7465pub enum AssignmentTarget {
7466    /// A single column
7467    ColumnName(ObjectName),
7468    /// A tuple of columns
7469    Tuple(Vec<ObjectName>),
7470}
7471
7472impl fmt::Display for AssignmentTarget {
7473    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7474        match self {
7475            AssignmentTarget::ColumnName(column) => write!(f, "{column}"),
7476            AssignmentTarget::Tuple(columns) => write!(f, "({})", display_comma_separated(columns)),
7477        }
7478    }
7479}
7480
7481#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7482#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7483#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7484/// Expression forms allowed as a function argument.
7485pub enum FunctionArgExpr {
7486    /// A normal expression argument.
7487    Expr(Expr),
7488    /// Qualified wildcard, e.g. `alias.*` or `schema.table.*`.
7489    QualifiedWildcard(ObjectName),
7490    /// An unqualified `*` wildcard.
7491    Wildcard,
7492}
7493
7494impl From<Expr> for FunctionArgExpr {
7495    fn from(wildcard_expr: Expr) -> Self {
7496        match wildcard_expr {
7497            Expr::QualifiedWildcard(prefix, _) => Self::QualifiedWildcard(prefix),
7498            Expr::Wildcard(_) => Self::Wildcard,
7499            expr => Self::Expr(expr),
7500        }
7501    }
7502}
7503
7504impl fmt::Display for FunctionArgExpr {
7505    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7506        match self {
7507            FunctionArgExpr::Expr(expr) => write!(f, "{expr}"),
7508            FunctionArgExpr::QualifiedWildcard(prefix) => write!(f, "{prefix}.*"),
7509            FunctionArgExpr::Wildcard => f.write_str("*"),
7510        }
7511    }
7512}
7513
7514#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7515#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7516#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7517/// Operator used to separate function arguments
7518pub enum FunctionArgOperator {
7519    /// function(arg1 = value1)
7520    Equals,
7521    /// function(arg1 => value1)
7522    RightArrow,
7523    /// function(arg1 := value1)
7524    Assignment,
7525    /// function(arg1 : value1)
7526    Colon,
7527    /// function(arg1 VALUE value1)
7528    Value,
7529}
7530
7531impl fmt::Display for FunctionArgOperator {
7532    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7533        match self {
7534            FunctionArgOperator::Equals => f.write_str("="),
7535            FunctionArgOperator::RightArrow => f.write_str("=>"),
7536            FunctionArgOperator::Assignment => f.write_str(":="),
7537            FunctionArgOperator::Colon => f.write_str(":"),
7538            FunctionArgOperator::Value => f.write_str("VALUE"),
7539        }
7540    }
7541}
7542
7543#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7544#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7545#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7546/// Forms of function arguments (named, expression-named, or positional).
7547pub enum FunctionArg {
7548    /// `name` is identifier
7549    ///
7550    /// Enabled when `Dialect::supports_named_fn_args_with_expr_name` returns 'false'
7551    Named {
7552        /// The identifier name of the argument.
7553        name: Ident,
7554        /// The argument expression or wildcard form.
7555        arg: FunctionArgExpr,
7556        /// The operator separating name and value.
7557        operator: FunctionArgOperator,
7558    },
7559    /// `name` is arbitrary expression
7560    ///
7561    /// Enabled when `Dialect::supports_named_fn_args_with_expr_name` returns 'true'
7562    ExprNamed {
7563        /// The expression used as the argument name.
7564        name: Expr,
7565        /// The argument expression or wildcard form.
7566        arg: FunctionArgExpr,
7567        /// The operator separating name and value.
7568        operator: FunctionArgOperator,
7569    },
7570    /// An unnamed argument (positional), given by expression or wildcard.
7571    Unnamed(FunctionArgExpr),
7572}
7573
7574impl fmt::Display for FunctionArg {
7575    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7576        match self {
7577            FunctionArg::Named {
7578                name,
7579                arg,
7580                operator,
7581            } => write!(f, "{name} {operator} {arg}"),
7582            FunctionArg::ExprNamed {
7583                name,
7584                arg,
7585                operator,
7586            } => write!(f, "{name} {operator} {arg}"),
7587            FunctionArg::Unnamed(unnamed_arg) => write!(f, "{unnamed_arg}"),
7588        }
7589    }
7590}
7591
7592#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7593#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7594#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7595/// Which cursor(s) to close.
7596pub enum CloseCursor {
7597    /// Close all cursors.
7598    All,
7599    /// Close a specific cursor by name.
7600    Specific {
7601        /// The name of the cursor to close.
7602        name: Ident,
7603    },
7604}
7605
7606impl fmt::Display for CloseCursor {
7607    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7608        match self {
7609            CloseCursor::All => write!(f, "ALL"),
7610            CloseCursor::Specific { name } => write!(f, "{name}"),
7611        }
7612    }
7613}
7614
7615/// A Drop Domain statement
7616#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7617#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7618#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7619pub struct DropDomain {
7620    /// Whether to drop the domain if it exists
7621    pub if_exists: bool,
7622    /// The name of the domain to drop
7623    pub name: ObjectName,
7624    /// The behavior to apply when dropping the domain
7625    pub drop_behavior: Option<DropBehavior>,
7626}
7627
7628/// A constant of form `<data_type> 'value'`.
7629/// This can represent ANSI SQL `DATE`, `TIME`, and `TIMESTAMP` literals (such as `DATE '2020-01-01'`),
7630/// as well as constants of other types (a non-standard PostgreSQL extension).
7631#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7632#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7633#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7634pub struct TypedString {
7635    /// The data type of the typed string (e.g. DATE, TIME, TIMESTAMP).
7636    pub data_type: DataType,
7637    /// The value of the constant.
7638    /// Hint: you can unwrap the string value using `value.into_string()`.
7639    pub value: ValueWithSpan,
7640    /// Flags whether this TypedString uses the [ODBC syntax].
7641    ///
7642    /// Example:
7643    /// ```sql
7644    /// -- An ODBC date literal:
7645    /// SELECT {d '2025-07-16'}
7646    /// -- This is equivalent to the standard ANSI SQL literal:
7647    /// SELECT DATE '2025-07-16'
7648    ///
7649    /// [ODBC syntax]: https://learn.microsoft.com/en-us/sql/odbc/reference/develop-app/date-time-and-timestamp-literals?view=sql-server-2017
7650    pub uses_odbc_syntax: bool,
7651}
7652
7653impl fmt::Display for TypedString {
7654    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7655        let data_type = &self.data_type;
7656        let value = &self.value;
7657        match self.uses_odbc_syntax {
7658            false => {
7659                write!(f, "{data_type}")?;
7660                write!(f, " {value}")
7661            }
7662            true => {
7663                let prefix = match data_type {
7664                    DataType::Date => "d",
7665                    DataType::Time(..) => "t",
7666                    DataType::Timestamp(..) => "ts",
7667                    _ => "?",
7668                };
7669                write!(f, "{{{prefix} {value}}}")
7670            }
7671        }
7672    }
7673}
7674
7675/// A function call
7676#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7677#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7678#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7679pub struct Function {
7680    /// The function name (may be qualified).
7681    pub name: ObjectName,
7682    /// Flags whether this function call uses the [ODBC syntax].
7683    ///
7684    /// Example:
7685    /// ```sql
7686    /// SELECT {fn CONCAT('foo', 'bar')}
7687    /// ```
7688    ///
7689    /// [ODBC syntax]: https://learn.microsoft.com/en-us/sql/odbc/reference/develop-app/scalar-function-calls?view=sql-server-2017
7690    pub uses_odbc_syntax: bool,
7691    /// The parameters to the function, including any options specified within the
7692    /// delimiting parentheses.
7693    ///
7694    /// Example:
7695    /// ```plaintext
7696    /// HISTOGRAM(0.5, 0.6)(x, y)
7697    /// ```
7698    ///
7699    /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/aggregate-functions/parametric-functions)
7700    pub parameters: FunctionArguments,
7701    /// The arguments to the function, including any options specified within the
7702    /// delimiting parentheses.
7703    pub args: FunctionArguments,
7704    /// e.g. `x > 5` in `COUNT(x) FILTER (WHERE x > 5)`
7705    pub filter: Option<Box<Expr>>,
7706    /// Indicates how `NULL`s should be handled in the calculation.
7707    ///
7708    /// Example:
7709    /// ```plaintext
7710    /// FIRST_VALUE( <expr> ) [ { IGNORE | RESPECT } NULLS ] OVER ...
7711    /// ```
7712    ///
7713    /// [Snowflake](https://docs.snowflake.com/en/sql-reference/functions/first_value)
7714    pub null_treatment: Option<NullTreatment>,
7715    /// The `OVER` clause, indicating a window function call.
7716    pub over: Option<WindowType>,
7717    /// A clause used with certain aggregate functions to control the ordering
7718    /// within grouped sets before the function is applied.
7719    ///
7720    /// Syntax:
7721    /// ```plaintext
7722    /// <aggregate_function>(expression) WITHIN GROUP (ORDER BY key [ASC | DESC], ...)
7723    /// ```
7724    pub within_group: Vec<OrderByExpr>,
7725}
7726
7727impl fmt::Display for Function {
7728    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7729        if self.uses_odbc_syntax {
7730            write!(f, "{{fn ")?;
7731        }
7732
7733        write!(f, "{}{}{}", self.name, self.parameters, self.args)?;
7734
7735        if !self.within_group.is_empty() {
7736            write!(
7737                f,
7738                " WITHIN GROUP (ORDER BY {})",
7739                display_comma_separated(&self.within_group)
7740            )?;
7741        }
7742
7743        if let Some(filter_cond) = &self.filter {
7744            write!(f, " FILTER (WHERE {filter_cond})")?;
7745        }
7746
7747        if let Some(null_treatment) = &self.null_treatment {
7748            write!(f, " {null_treatment}")?;
7749        }
7750
7751        if let Some(o) = &self.over {
7752            f.write_str(" OVER ")?;
7753            o.fmt(f)?;
7754        }
7755
7756        if self.uses_odbc_syntax {
7757            write!(f, "}}")?;
7758        }
7759
7760        Ok(())
7761    }
7762}
7763
7764/// The arguments passed to a function call.
7765#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7766#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7767#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7768pub enum FunctionArguments {
7769    /// Used for special functions like `CURRENT_TIMESTAMP` that are invoked
7770    /// without parentheses.
7771    None,
7772    /// On some dialects, a subquery can be passed without surrounding
7773    /// parentheses if it's the sole argument to the function.
7774    Subquery(Box<Query>),
7775    /// A normal function argument list, including any clauses within it such as
7776    /// `DISTINCT` or `ORDER BY`.
7777    List(FunctionArgumentList),
7778}
7779
7780impl fmt::Display for FunctionArguments {
7781    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
7782        match self {
7783            FunctionArguments::None => Ok(()),
7784            FunctionArguments::Subquery(query) => write!(f, "({query})"),
7785            FunctionArguments::List(args) => write!(f, "({args})"),
7786        }
7787    }
7788}
7789
7790/// This represents everything inside the parentheses when calling a function.
7791#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7792#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7793#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7794pub struct FunctionArgumentList {
7795    /// `[ ALL | DISTINCT ]`
7796    pub duplicate_treatment: Option<DuplicateTreatment>,
7797    /// The function arguments.
7798    pub args: Vec<FunctionArg>,
7799    /// Additional clauses specified within the argument list.
7800    pub clauses: Vec<FunctionArgumentClause>,
7801}
7802
7803impl fmt::Display for FunctionArgumentList {
7804    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7805        if let Some(duplicate_treatment) = self.duplicate_treatment {
7806            write!(f, "{duplicate_treatment} ")?;
7807        }
7808        write!(f, "{}", display_comma_separated(&self.args))?;
7809        if !self.clauses.is_empty() {
7810            if !self.args.is_empty() {
7811                write!(f, " ")?;
7812            }
7813            write!(f, "{}", display_separated(&self.clauses, " "))?;
7814        }
7815        Ok(())
7816    }
7817}
7818
7819#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7820#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7821#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7822/// Clauses that can appear inside a function argument list.
7823pub enum FunctionArgumentClause {
7824    /// Indicates how `NULL`s should be handled in the calculation, e.g. in `FIRST_VALUE` on [BigQuery].
7825    ///
7826    /// Syntax:
7827    /// ```plaintext
7828    /// { IGNORE | RESPECT } NULLS ]
7829    /// ```
7830    ///
7831    /// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/navigation_functions#first_value
7832    IgnoreOrRespectNulls(NullTreatment),
7833    /// Specifies the the ordering for some ordered set aggregates, e.g. `ARRAY_AGG` on [BigQuery].
7834    ///
7835    /// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/aggregate_functions#array_agg
7836    OrderBy(Vec<OrderByExpr>),
7837    /// Specifies a limit for the `ARRAY_AGG` and `ARRAY_CONCAT_AGG` functions on BigQuery.
7838    Limit(Expr),
7839    /// Specifies the behavior on overflow of the `LISTAGG` function.
7840    ///
7841    /// See <https://trino.io/docs/current/functions/aggregate.html>.
7842    OnOverflow(ListAggOnOverflow),
7843    /// Specifies a minimum or maximum bound on the input to [`ANY_VALUE`] on BigQuery.
7844    ///
7845    /// Syntax:
7846    /// ```plaintext
7847    /// HAVING { MAX | MIN } expression
7848    /// ```
7849    ///
7850    /// [`ANY_VALUE`]: https://cloud.google.com/bigquery/docs/reference/standard-sql/aggregate_functions#any_value
7851    Having(HavingBound),
7852    /// The `SEPARATOR` clause to the [`GROUP_CONCAT`] function in MySQL.
7853    ///
7854    /// [`GROUP_CONCAT`]: https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html#function_group-concat
7855    Separator(Value),
7856    /// The `ON NULL` clause for some JSON functions.
7857    ///
7858    /// [MSSQL `JSON_ARRAY`](https://learn.microsoft.com/en-us/sql/t-sql/functions/json-array-transact-sql?view=sql-server-ver16)
7859    /// [MSSQL `JSON_OBJECT`](https://learn.microsoft.com/en-us/sql/t-sql/functions/json-object-transact-sql?view=sql-server-ver16>)
7860    /// [PostgreSQL JSON functions](https://www.postgresql.org/docs/current/functions-json.html#FUNCTIONS-JSON-PROCESSING)
7861    JsonNullClause(JsonNullClause),
7862    /// The `RETURNING` clause for some JSON functions in PostgreSQL
7863    ///
7864    /// [`JSON_OBJECT`](https://www.postgresql.org/docs/current/functions-json.html#:~:text=json_object)
7865    JsonReturningClause(JsonReturningClause),
7866}
7867
7868impl fmt::Display for FunctionArgumentClause {
7869    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
7870        match self {
7871            FunctionArgumentClause::IgnoreOrRespectNulls(null_treatment) => {
7872                write!(f, "{null_treatment}")
7873            }
7874            FunctionArgumentClause::OrderBy(order_by) => {
7875                write!(f, "ORDER BY {}", display_comma_separated(order_by))
7876            }
7877            FunctionArgumentClause::Limit(limit) => write!(f, "LIMIT {limit}"),
7878            FunctionArgumentClause::OnOverflow(on_overflow) => write!(f, "{on_overflow}"),
7879            FunctionArgumentClause::Having(bound) => write!(f, "{bound}"),
7880            FunctionArgumentClause::Separator(sep) => write!(f, "SEPARATOR {sep}"),
7881            FunctionArgumentClause::JsonNullClause(null_clause) => write!(f, "{null_clause}"),
7882            FunctionArgumentClause::JsonReturningClause(returning_clause) => {
7883                write!(f, "{returning_clause}")
7884            }
7885        }
7886    }
7887}
7888
7889/// A method call
7890#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7891#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7892#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7893pub struct Method {
7894    /// The expression on which the method is invoked.
7895    pub expr: Box<Expr>,
7896    // always non-empty
7897    /// The sequence of chained method calls.
7898    pub method_chain: Vec<Function>,
7899}
7900
7901impl fmt::Display for Method {
7902    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7903        write!(
7904            f,
7905            "{}.{}",
7906            self.expr,
7907            display_separated(&self.method_chain, ".")
7908        )
7909    }
7910}
7911
7912#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7913#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7914#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7915/// How duplicate values are treated inside function argument lists.
7916pub enum DuplicateTreatment {
7917    /// Consider only unique values.
7918    Distinct,
7919    /// Retain all duplicate values (the default).
7920    All,
7921}
7922
7923impl fmt::Display for DuplicateTreatment {
7924    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
7925        match self {
7926            DuplicateTreatment::Distinct => write!(f, "DISTINCT"),
7927            DuplicateTreatment::All => write!(f, "ALL"),
7928        }
7929    }
7930}
7931
7932#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7933#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7934#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7935/// How the `ANALYZE`/`EXPLAIN ANALYZE` format is specified.
7936pub enum AnalyzeFormatKind {
7937    /// Format provided as a keyword, e.g. `FORMAT JSON`.
7938    Keyword(AnalyzeFormat),
7939    /// Format provided as an assignment, e.g. `FORMAT=JSON`.
7940    Assignment(AnalyzeFormat),
7941}
7942
7943impl fmt::Display for AnalyzeFormatKind {
7944    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
7945        match self {
7946            AnalyzeFormatKind::Keyword(format) => write!(f, "FORMAT {format}"),
7947            AnalyzeFormatKind::Assignment(format) => write!(f, "FORMAT={format}"),
7948        }
7949    }
7950}
7951
7952#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7953#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7954#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7955/// Output formats supported for `ANALYZE`/`EXPLAIN ANALYZE`.
7956pub enum AnalyzeFormat {
7957    /// Plain text format.
7958    TEXT,
7959    /// Graphviz DOT format.
7960    GRAPHVIZ,
7961    /// JSON format.
7962    JSON,
7963    /// Traditional explain output.
7964    TRADITIONAL,
7965    /// Tree-style explain output.
7966    TREE,
7967}
7968
7969impl fmt::Display for AnalyzeFormat {
7970    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
7971        f.write_str(match self {
7972            AnalyzeFormat::TEXT => "TEXT",
7973            AnalyzeFormat::GRAPHVIZ => "GRAPHVIZ",
7974            AnalyzeFormat::JSON => "JSON",
7975            AnalyzeFormat::TRADITIONAL => "TRADITIONAL",
7976            AnalyzeFormat::TREE => "TREE",
7977        })
7978    }
7979}
7980
7981/// External table's available file format
7982#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7983#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7984#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7985pub enum FileFormat {
7986    /// Text file format.
7987    TEXTFILE,
7988    /// Sequence file format.
7989    SEQUENCEFILE,
7990    /// ORC file format.
7991    ORC,
7992    /// Parquet file format.
7993    PARQUET,
7994    /// Avro file format.
7995    AVRO,
7996    /// RCFile format.
7997    RCFILE,
7998    /// JSON file format.
7999    JSONFILE,
8000}
8001
8002impl fmt::Display for FileFormat {
8003    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8004        use self::FileFormat::*;
8005        f.write_str(match self {
8006            TEXTFILE => "TEXTFILE",
8007            SEQUENCEFILE => "SEQUENCEFILE",
8008            ORC => "ORC",
8009            PARQUET => "PARQUET",
8010            AVRO => "AVRO",
8011            RCFILE => "RCFILE",
8012            JSONFILE => "JSONFILE",
8013        })
8014    }
8015}
8016
8017/// The `ON OVERFLOW` clause of a LISTAGG invocation
8018#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8019#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8020#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8021pub enum ListAggOnOverflow {
8022    /// `ON OVERFLOW ERROR`
8023    Error,
8024
8025    /// `ON OVERFLOW TRUNCATE [ <filler> ] WITH[OUT] COUNT`
8026    Truncate {
8027        /// Optional filler expression used when truncating.
8028        filler: Option<Box<Expr>>,
8029        /// Whether to include a count when truncating.
8030        with_count: bool,
8031    },
8032}
8033
8034impl fmt::Display for ListAggOnOverflow {
8035    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8036        write!(f, "ON OVERFLOW")?;
8037        match self {
8038            ListAggOnOverflow::Error => write!(f, " ERROR"),
8039            ListAggOnOverflow::Truncate { filler, with_count } => {
8040                write!(f, " TRUNCATE")?;
8041                if let Some(filler) = filler {
8042                    write!(f, " {filler}")?;
8043                }
8044                if *with_count {
8045                    write!(f, " WITH")?;
8046                } else {
8047                    write!(f, " WITHOUT")?;
8048                }
8049                write!(f, " COUNT")
8050            }
8051        }
8052    }
8053}
8054
8055/// The `HAVING` clause in a call to `ANY_VALUE` on BigQuery.
8056#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8057#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8058#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8059pub struct HavingBound(pub HavingBoundKind, pub Expr);
8060
8061impl fmt::Display for HavingBound {
8062    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8063        write!(f, "HAVING {} {}", self.0, self.1)
8064    }
8065}
8066
8067#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8068#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8069#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8070/// Which bound is used in a HAVING clause for ANY_VALUE on BigQuery.
8071pub enum HavingBoundKind {
8072    /// The minimum bound.
8073    Min,
8074    /// The maximum bound.
8075    Max,
8076}
8077
8078impl fmt::Display for HavingBoundKind {
8079    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8080        match self {
8081            HavingBoundKind::Min => write!(f, "MIN"),
8082            HavingBoundKind::Max => write!(f, "MAX"),
8083        }
8084    }
8085}
8086
8087#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8088#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8089#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8090/// Types of database objects referenced by DDL statements.
8091pub enum ObjectType {
8092    /// A table.
8093    Table,
8094    /// A view.
8095    View,
8096    /// A materialized view.
8097    MaterializedView,
8098    /// An index.
8099    Index,
8100    /// A schema.
8101    Schema,
8102    /// A database.
8103    Database,
8104    /// A role.
8105    Role,
8106    /// A sequence.
8107    Sequence,
8108    /// A stage.
8109    Stage,
8110    /// A type definition.
8111    Type,
8112    /// A user.
8113    User,
8114    /// A stream.
8115    Stream,
8116}
8117
8118impl fmt::Display for ObjectType {
8119    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8120        f.write_str(match self {
8121            ObjectType::Table => "TABLE",
8122            ObjectType::View => "VIEW",
8123            ObjectType::MaterializedView => "MATERIALIZED VIEW",
8124            ObjectType::Index => "INDEX",
8125            ObjectType::Schema => "SCHEMA",
8126            ObjectType::Database => "DATABASE",
8127            ObjectType::Role => "ROLE",
8128            ObjectType::Sequence => "SEQUENCE",
8129            ObjectType::Stage => "STAGE",
8130            ObjectType::Type => "TYPE",
8131            ObjectType::User => "USER",
8132            ObjectType::Stream => "STREAM",
8133        })
8134    }
8135}
8136
8137#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8138#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8139#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8140/// Types supported by `KILL` statements.
8141pub enum KillType {
8142    /// Kill a connection.
8143    Connection,
8144    /// Kill a running query.
8145    Query,
8146    /// Kill a mutation (ClickHouse).
8147    Mutation,
8148}
8149
8150impl fmt::Display for KillType {
8151    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8152        f.write_str(match self {
8153            // MySQL
8154            KillType::Connection => "CONNECTION",
8155            KillType::Query => "QUERY",
8156            // Clickhouse supports Mutation
8157            KillType::Mutation => "MUTATION",
8158        })
8159    }
8160}
8161
8162#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8163#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8164#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8165/// Distribution style options for Hive tables.
8166pub enum HiveDistributionStyle {
8167    /// Partitioned distribution with the given columns.
8168    PARTITIONED {
8169        /// Columns used for partitioning.
8170        columns: Vec<ColumnDef>,
8171    },
8172    /// Skewed distribution definition.
8173    SKEWED {
8174        /// Columns participating in the skew definition.
8175        columns: Vec<ColumnDef>,
8176        /// Columns listed in the `ON` clause for skewing.
8177        on: Vec<ColumnDef>,
8178        /// Whether skewed data is stored as directories.
8179        stored_as_directories: bool,
8180    },
8181    /// No distribution style specified.
8182    NONE,
8183}
8184
8185#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8186#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8187#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8188/// Row format specification for Hive tables (SERDE or DELIMITED).
8189pub enum HiveRowFormat {
8190    /// SerDe class specification with the implementing class name.
8191    SERDE {
8192        /// The SerDe implementation class name.
8193        class: String,
8194    },
8195    /// Delimited row format with one or more delimiter specifications.
8196    DELIMITED {
8197        /// The list of delimiters used for delimiting fields/lines.
8198        delimiters: Vec<HiveRowDelimiter>,
8199    },
8200}
8201
8202#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8203#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8204#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8205/// Format specification for `LOAD DATA` Hive operations.
8206pub struct HiveLoadDataFormat {
8207    /// SerDe expression used for the table.
8208    pub serde: Expr,
8209    /// Input format expression.
8210    pub input_format: Expr,
8211}
8212
8213#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8214#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8215#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8216/// A single row delimiter specification for Hive `ROW FORMAT`.
8217pub struct HiveRowDelimiter {
8218    /// The delimiter kind (fields/lines/etc.).
8219    pub delimiter: HiveDelimiter,
8220    /// The delimiter character identifier.
8221    pub char: Ident,
8222}
8223
8224impl fmt::Display for HiveRowDelimiter {
8225    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8226        write!(f, "{} ", self.delimiter)?;
8227        write!(f, "{}", self.char)
8228    }
8229}
8230
8231#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8232#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8233#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8234/// Kind of delimiter used in Hive `ROW FORMAT` definitions.
8235pub enum HiveDelimiter {
8236    /// Fields terminated by a delimiter.
8237    FieldsTerminatedBy,
8238    /// Fields escaped by a character.
8239    FieldsEscapedBy,
8240    /// Collection items terminated by a delimiter.
8241    CollectionItemsTerminatedBy,
8242    /// Map keys terminated by a delimiter.
8243    MapKeysTerminatedBy,
8244    /// Lines terminated by a delimiter.
8245    LinesTerminatedBy,
8246    /// Null represented by a specific token.
8247    NullDefinedAs,
8248}
8249
8250impl fmt::Display for HiveDelimiter {
8251    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8252        use HiveDelimiter::*;
8253        f.write_str(match self {
8254            FieldsTerminatedBy => "FIELDS TERMINATED BY",
8255            FieldsEscapedBy => "ESCAPED BY",
8256            CollectionItemsTerminatedBy => "COLLECTION ITEMS TERMINATED BY",
8257            MapKeysTerminatedBy => "MAP KEYS TERMINATED BY",
8258            LinesTerminatedBy => "LINES TERMINATED BY",
8259            NullDefinedAs => "NULL DEFINED AS",
8260        })
8261    }
8262}
8263
8264#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8265#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8266#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8267/// Describe output format options for Hive `DESCRIBE`/`EXPLAIN`.
8268pub enum HiveDescribeFormat {
8269    /// Extended describe output.
8270    Extended,
8271    /// Formatted describe output.
8272    Formatted,
8273}
8274
8275impl fmt::Display for HiveDescribeFormat {
8276    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8277        use HiveDescribeFormat::*;
8278        f.write_str(match self {
8279            Extended => "EXTENDED",
8280            Formatted => "FORMATTED",
8281        })
8282    }
8283}
8284
8285#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8286#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8287#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8288/// Aliases accepted for describe-style commands.
8289pub enum DescribeAlias {
8290    /// `DESCRIBE` alias.
8291    Describe,
8292    /// `EXPLAIN` alias.
8293    Explain,
8294    /// `DESC` alias.
8295    Desc,
8296}
8297
8298impl fmt::Display for DescribeAlias {
8299    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8300        use DescribeAlias::*;
8301        f.write_str(match self {
8302            Describe => "DESCRIBE",
8303            Explain => "EXPLAIN",
8304            Desc => "DESC",
8305        })
8306    }
8307}
8308
8309#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8310#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8311#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8312#[allow(clippy::large_enum_variant)]
8313/// Hive input/output format specification used in `CREATE TABLE`.
8314pub enum HiveIOFormat {
8315    /// Generic IO format with separate input and output expressions.
8316    IOF {
8317        /// Expression for the input format.
8318        input_format: Expr,
8319        /// Expression for the output format.
8320        output_format: Expr,
8321    },
8322    /// File format wrapper referencing a `FileFormat` variant.
8323    FileFormat {
8324        /// The file format used for storage.
8325        format: FileFormat,
8326    },
8327}
8328
8329#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Default)]
8330#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8331#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8332/// Hive table format and storage-related options.
8333pub struct HiveFormat {
8334    /// Optional row format specification.
8335    pub row_format: Option<HiveRowFormat>,
8336    /// Optional SerDe properties expressed as SQL options.
8337    pub serde_properties: Option<Vec<SqlOption>>,
8338    /// Optional input/output storage format details.
8339    pub storage: Option<HiveIOFormat>,
8340    /// Optional location (URI or path) for table data.
8341    pub location: Option<String>,
8342}
8343
8344#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8345#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8346#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8347/// A clustered index column specification.
8348pub struct ClusteredIndex {
8349    /// Column identifier for the clustered index entry.
8350    pub name: Ident,
8351    /// Optional sort direction: `Some(true)` for ASC, `Some(false)` for DESC, `None` for unspecified.
8352    pub asc: Option<bool>,
8353}
8354
8355impl fmt::Display for ClusteredIndex {
8356    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8357        write!(f, "{}", self.name)?;
8358        match self.asc {
8359            Some(true) => write!(f, " ASC"),
8360            Some(false) => write!(f, " DESC"),
8361            _ => Ok(()),
8362        }
8363    }
8364}
8365
8366#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8367#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8368#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8369/// Clustered options used for `CREATE TABLE` clustered/indexed storage.
8370pub enum TableOptionsClustered {
8371    /// Use a columnstore index.
8372    ColumnstoreIndex,
8373    /// Columnstore index with an explicit ordering of columns.
8374    ColumnstoreIndexOrder(Vec<Ident>),
8375    /// A named clustered index with one or more columns.
8376    Index(Vec<ClusteredIndex>),
8377}
8378
8379impl fmt::Display for TableOptionsClustered {
8380    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8381        match self {
8382            TableOptionsClustered::ColumnstoreIndex => {
8383                write!(f, "CLUSTERED COLUMNSTORE INDEX")
8384            }
8385            TableOptionsClustered::ColumnstoreIndexOrder(values) => {
8386                write!(
8387                    f,
8388                    "CLUSTERED COLUMNSTORE INDEX ORDER ({})",
8389                    display_comma_separated(values)
8390                )
8391            }
8392            TableOptionsClustered::Index(values) => {
8393                write!(f, "CLUSTERED INDEX ({})", display_comma_separated(values))
8394            }
8395        }
8396    }
8397}
8398
8399/// Specifies which partition the boundary values on table partitioning belongs to.
8400#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash)]
8401#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8402#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8403pub enum PartitionRangeDirection {
8404    /// LEFT range direction.
8405    Left,
8406    /// RIGHT range direction.
8407    Right,
8408}
8409
8410#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8411#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8412#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8413/// SQL option syntax used in table and server definitions.
8414pub enum SqlOption {
8415    /// Clustered represents the clustered version of table storage for MSSQL.
8416    ///
8417    /// <https://learn.microsoft.com/en-us/sql/t-sql/statements/create-table-azure-sql-data-warehouse?view=aps-pdw-2016-au7#TableOptions>
8418    Clustered(TableOptionsClustered),
8419    /// Single identifier options, e.g. `HEAP` for MSSQL.
8420    ///
8421    /// <https://learn.microsoft.com/en-us/sql/t-sql/statements/create-table-azure-sql-data-warehouse?view=aps-pdw-2016-au7#TableOptions>
8422    Ident(Ident),
8423    /// Any option that consists of a key value pair where the value is an expression. e.g.
8424    ///
8425    ///   WITH(DISTRIBUTION = ROUND_ROBIN)
8426    KeyValue {
8427        /// The option key identifier.
8428        key: Ident,
8429        /// The expression value for the option.
8430        value: Expr,
8431    },
8432    /// One or more table partitions and represents which partition the boundary values belong to,
8433    /// e.g.
8434    ///
8435    ///   PARTITION (id RANGE LEFT FOR VALUES (10, 20, 30, 40))
8436    ///
8437    /// <https://learn.microsoft.com/en-us/sql/t-sql/statements/create-table-azure-sql-data-warehouse?view=aps-pdw-2016-au7#TablePartitionOptions>
8438    Partition {
8439        /// The partition column name.
8440        column_name: Ident,
8441        /// Optional direction for the partition range (LEFT/RIGHT).
8442        range_direction: Option<PartitionRangeDirection>,
8443        /// Values that define the partition boundaries.
8444        for_values: Vec<Expr>,
8445    },
8446    /// Comment parameter (supports `=` and no `=` syntax)
8447    Comment(CommentDef),
8448    /// MySQL TableSpace option
8449    /// <https://dev.mysql.com/doc/refman/8.4/en/create-table.html>
8450    TableSpace(TablespaceOption),
8451    /// An option representing a key value pair, where the value is a parenthesized list and with an optional name
8452    /// e.g.
8453    ///
8454    ///   UNION  = (tbl_name\[,tbl_name\]...) <https://dev.mysql.com/doc/refman/8.4/en/create-table.html>
8455    ///   ENGINE = ReplicatedMergeTree('/table_name','{replica}', ver) <https://clickhouse.com/docs/engines/table-engines/mergetree-family/replication>
8456    ///   ENGINE = SummingMergeTree(\[columns\]) <https://clickhouse.com/docs/engines/table-engines/mergetree-family/summingmergetree>
8457    NamedParenthesizedList(NamedParenthesizedList),
8458}
8459
8460impl fmt::Display for SqlOption {
8461    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8462        match self {
8463            SqlOption::Clustered(c) => write!(f, "{c}"),
8464            SqlOption::Ident(ident) => {
8465                write!(f, "{ident}")
8466            }
8467            SqlOption::KeyValue { key: name, value } => {
8468                write!(f, "{name} = {value}")
8469            }
8470            SqlOption::Partition {
8471                column_name,
8472                range_direction,
8473                for_values,
8474            } => {
8475                let direction = match range_direction {
8476                    Some(PartitionRangeDirection::Left) => " LEFT",
8477                    Some(PartitionRangeDirection::Right) => " RIGHT",
8478                    None => "",
8479                };
8480
8481                write!(
8482                    f,
8483                    "PARTITION ({} RANGE{} FOR VALUES ({}))",
8484                    column_name,
8485                    direction,
8486                    display_comma_separated(for_values)
8487                )
8488            }
8489            SqlOption::TableSpace(tablespace_option) => {
8490                write!(f, "TABLESPACE {}", tablespace_option.name)?;
8491                match tablespace_option.storage {
8492                    Some(StorageType::Disk) => write!(f, " STORAGE DISK"),
8493                    Some(StorageType::Memory) => write!(f, " STORAGE MEMORY"),
8494                    None => Ok(()),
8495                }
8496            }
8497            SqlOption::Comment(comment) => match comment {
8498                CommentDef::WithEq(comment) => {
8499                    write!(f, "COMMENT = '{comment}'")
8500                }
8501                CommentDef::WithoutEq(comment) => {
8502                    write!(f, "COMMENT '{comment}'")
8503                }
8504            },
8505            SqlOption::NamedParenthesizedList(value) => {
8506                write!(f, "{} = ", value.key)?;
8507                if let Some(key) = &value.name {
8508                    write!(f, "{key}")?;
8509                }
8510                if !value.values.is_empty() {
8511                    write!(f, "({})", display_comma_separated(&value.values))?
8512                }
8513                Ok(())
8514            }
8515        }
8516    }
8517}
8518
8519#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
8520#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8521#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8522/// Storage type options for a tablespace.
8523pub enum StorageType {
8524    /// Store on disk.
8525    Disk,
8526    /// Store in memory.
8527    Memory,
8528}
8529
8530#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
8531#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8532#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8533/// MySql TableSpace option
8534/// <https://dev.mysql.com/doc/refman/8.4/en/create-table.html>
8535pub struct TablespaceOption {
8536    /// Name of the tablespace.
8537    pub name: String,
8538    /// Optional storage type for the tablespace.
8539    pub storage: Option<StorageType>,
8540}
8541
8542#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8543#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8544#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8545/// A key/value identifier pair used for secret or key-based options.
8546pub struct SecretOption {
8547    /// The option key identifier.
8548    pub key: Ident,
8549    /// The option value identifier.
8550    pub value: Ident,
8551}
8552
8553impl fmt::Display for SecretOption {
8554    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8555        write!(f, "{} {}", self.key, self.value)
8556    }
8557}
8558
8559/// A `CREATE SERVER` statement.
8560///
8561/// [PostgreSQL Documentation](https://www.postgresql.org/docs/current/sql-createserver.html)
8562#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8563#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8564#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8565pub struct CreateServerStatement {
8566    /// The server name.
8567    pub name: ObjectName,
8568    /// Whether `IF NOT EXISTS` was specified.
8569    pub if_not_exists: bool,
8570    /// Optional server type identifier.
8571    pub server_type: Option<Ident>,
8572    /// Optional server version identifier.
8573    pub version: Option<Ident>,
8574    /// Foreign-data wrapper object name.
8575    pub foreign_data_wrapper: ObjectName,
8576    /// Optional list of server options.
8577    pub options: Option<Vec<CreateServerOption>>,
8578}
8579
8580impl fmt::Display for CreateServerStatement {
8581    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8582        let CreateServerStatement {
8583            name,
8584            if_not_exists,
8585            server_type,
8586            version,
8587            foreign_data_wrapper,
8588            options,
8589        } = self;
8590
8591        write!(
8592            f,
8593            "CREATE SERVER {if_not_exists}{name} ",
8594            if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
8595        )?;
8596
8597        if let Some(st) = server_type {
8598            write!(f, "TYPE {st} ")?;
8599        }
8600
8601        if let Some(v) = version {
8602            write!(f, "VERSION {v} ")?;
8603        }
8604
8605        write!(f, "FOREIGN DATA WRAPPER {foreign_data_wrapper}")?;
8606
8607        if let Some(o) = options {
8608            write!(f, " OPTIONS ({o})", o = display_comma_separated(o))?;
8609        }
8610
8611        Ok(())
8612    }
8613}
8614
8615/// A key/value option for `CREATE SERVER`.
8616#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8617#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8618#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8619pub struct CreateServerOption {
8620    /// Option key identifier.
8621    pub key: Ident,
8622    /// Option value identifier.
8623    pub value: Ident,
8624}
8625
8626impl fmt::Display for CreateServerOption {
8627    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8628        write!(f, "{} {}", self.key, self.value)
8629    }
8630}
8631
8632#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8633#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8634#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8635/// Options supported by DuckDB for `ATTACH DATABASE`.
8636pub enum AttachDuckDBDatabaseOption {
8637    /// READ_ONLY option, optional boolean value.
8638    ReadOnly(Option<bool>),
8639    /// TYPE option specifying a database type identifier.
8640    Type(Ident),
8641}
8642
8643impl fmt::Display for AttachDuckDBDatabaseOption {
8644    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8645        match self {
8646            AttachDuckDBDatabaseOption::ReadOnly(Some(true)) => write!(f, "READ_ONLY true"),
8647            AttachDuckDBDatabaseOption::ReadOnly(Some(false)) => write!(f, "READ_ONLY false"),
8648            AttachDuckDBDatabaseOption::ReadOnly(None) => write!(f, "READ_ONLY"),
8649            AttachDuckDBDatabaseOption::Type(t) => write!(f, "TYPE {t}"),
8650        }
8651    }
8652}
8653
8654#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8655#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8656#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8657/// Mode for transactions: access mode or isolation level.
8658pub enum TransactionMode {
8659    /// Access mode for a transaction (e.g. `READ ONLY` / `READ WRITE`).
8660    AccessMode(TransactionAccessMode),
8661    /// Isolation level for a transaction (e.g. `SERIALIZABLE`).
8662    IsolationLevel(TransactionIsolationLevel),
8663}
8664
8665impl fmt::Display for TransactionMode {
8666    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8667        use TransactionMode::*;
8668        match self {
8669            AccessMode(access_mode) => write!(f, "{access_mode}"),
8670            IsolationLevel(iso_level) => write!(f, "ISOLATION LEVEL {iso_level}"),
8671        }
8672    }
8673}
8674
8675#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8676#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8677#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8678/// Transaction access mode (READ ONLY / READ WRITE).
8679pub enum TransactionAccessMode {
8680    /// READ ONLY access mode.
8681    ReadOnly,
8682    /// READ WRITE access mode.
8683    ReadWrite,
8684}
8685
8686impl fmt::Display for TransactionAccessMode {
8687    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8688        use TransactionAccessMode::*;
8689        f.write_str(match self {
8690            ReadOnly => "READ ONLY",
8691            ReadWrite => "READ WRITE",
8692        })
8693    }
8694}
8695
8696#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8697#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8698#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8699/// Transaction isolation levels.
8700pub enum TransactionIsolationLevel {
8701    /// READ UNCOMMITTED isolation level.
8702    ReadUncommitted,
8703    /// READ COMMITTED isolation level.
8704    ReadCommitted,
8705    /// REPEATABLE READ isolation level.
8706    RepeatableRead,
8707    /// SERIALIZABLE isolation level.
8708    Serializable,
8709    /// SNAPSHOT isolation level.
8710    Snapshot,
8711}
8712
8713impl fmt::Display for TransactionIsolationLevel {
8714    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8715        use TransactionIsolationLevel::*;
8716        f.write_str(match self {
8717            ReadUncommitted => "READ UNCOMMITTED",
8718            ReadCommitted => "READ COMMITTED",
8719            RepeatableRead => "REPEATABLE READ",
8720            Serializable => "SERIALIZABLE",
8721            Snapshot => "SNAPSHOT",
8722        })
8723    }
8724}
8725
8726/// Modifier for the transaction in the `BEGIN` syntax
8727///
8728/// SQLite: <https://sqlite.org/lang_transaction.html>
8729/// MS-SQL: <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/try-catch-transact-sql>
8730#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8731#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8732#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8733pub enum TransactionModifier {
8734    /// DEFERRED transaction modifier.
8735    Deferred,
8736    /// IMMEDIATE transaction modifier.
8737    Immediate,
8738    /// EXCLUSIVE transaction modifier.
8739    Exclusive,
8740    /// TRY block modifier (MS-SQL style TRY/CATCH).
8741    Try,
8742    /// CATCH block modifier (MS-SQL style TRY/CATCH).
8743    Catch,
8744}
8745
8746impl fmt::Display for TransactionModifier {
8747    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8748        use TransactionModifier::*;
8749        f.write_str(match self {
8750            Deferred => "DEFERRED",
8751            Immediate => "IMMEDIATE",
8752            Exclusive => "EXCLUSIVE",
8753            Try => "TRY",
8754            Catch => "CATCH",
8755        })
8756    }
8757}
8758
8759#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8760#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8761#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8762/// Filter forms usable in SHOW statements.
8763pub enum ShowStatementFilter {
8764    /// Filter using LIKE pattern.
8765    Like(String),
8766    /// Filter using ILIKE pattern.
8767    ILike(String),
8768    /// Filter using a WHERE expression.
8769    Where(Expr),
8770    /// Filter provided without a keyword (raw string).
8771    NoKeyword(String),
8772}
8773
8774impl fmt::Display for ShowStatementFilter {
8775    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8776        use ShowStatementFilter::*;
8777        match self {
8778            Like(pattern) => write!(f, "LIKE '{}'", value::escape_single_quote_string(pattern)),
8779            ILike(pattern) => write!(f, "ILIKE {}", value::escape_single_quote_string(pattern)),
8780            Where(expr) => write!(f, "WHERE {expr}"),
8781            NoKeyword(pattern) => write!(f, "'{}'", value::escape_single_quote_string(pattern)),
8782        }
8783    }
8784}
8785
8786#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8787#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8788#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8789/// Clause types used with SHOW ... IN/FROM.
8790pub enum ShowStatementInClause {
8791    /// Use the `IN` clause.
8792    IN,
8793    /// Use the `FROM` clause.
8794    FROM,
8795}
8796
8797impl fmt::Display for ShowStatementInClause {
8798    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8799        use ShowStatementInClause::*;
8800        match self {
8801            FROM => write!(f, "FROM"),
8802            IN => write!(f, "IN"),
8803        }
8804    }
8805}
8806
8807/// Sqlite specific syntax
8808///
8809/// See [Sqlite documentation](https://sqlite.org/lang_conflict.html)
8810/// for more details.
8811#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8812#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8813#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8814pub enum SqliteOnConflict {
8815    /// Use ROLLBACK on conflict.
8816    Rollback,
8817    /// Use ABORT on conflict.
8818    Abort,
8819    /// Use FAIL on conflict.
8820    Fail,
8821    /// Use IGNORE on conflict.
8822    Ignore,
8823    /// Use REPLACE on conflict.
8824    Replace,
8825}
8826
8827impl fmt::Display for SqliteOnConflict {
8828    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8829        use SqliteOnConflict::*;
8830        match self {
8831            Rollback => write!(f, "OR ROLLBACK"),
8832            Abort => write!(f, "OR ABORT"),
8833            Fail => write!(f, "OR FAIL"),
8834            Ignore => write!(f, "OR IGNORE"),
8835            Replace => write!(f, "OR REPLACE"),
8836        }
8837    }
8838}
8839
8840/// Mysql specific syntax
8841///
8842/// See [Mysql documentation](https://dev.mysql.com/doc/refman/8.0/en/replace.html)
8843/// See [Mysql documentation](https://dev.mysql.com/doc/refman/8.0/en/insert.html)
8844/// for more details.
8845#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8846#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8847#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8848pub enum MysqlInsertPriority {
8849    /// LOW_PRIORITY modifier for INSERT/REPLACE.
8850    LowPriority,
8851    /// DELAYED modifier for INSERT/REPLACE.
8852    Delayed,
8853    /// HIGH_PRIORITY modifier for INSERT/REPLACE.
8854    HighPriority,
8855}
8856
8857impl fmt::Display for crate::ast::MysqlInsertPriority {
8858    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8859        use MysqlInsertPriority::*;
8860        match self {
8861            LowPriority => write!(f, "LOW_PRIORITY"),
8862            Delayed => write!(f, "DELAYED"),
8863            HighPriority => write!(f, "HIGH_PRIORITY"),
8864        }
8865    }
8866}
8867
8868#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8869#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8870#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8871/// Source for the `COPY` command: a table or a query.
8872pub enum CopySource {
8873    /// Copy from a table with optional column list.
8874    Table {
8875        /// The name of the table to copy from.
8876        table_name: ObjectName,
8877        /// A list of column names to copy. Empty list means that all columns
8878        /// are copied.
8879        columns: Vec<Ident>,
8880    },
8881    /// Copy from the results of a query.
8882    Query(Box<Query>),
8883}
8884
8885#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8886#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8887#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8888/// Target for the `COPY` command: STDIN, STDOUT, a file, or a program.
8889pub enum CopyTarget {
8890    /// Use standard input as the source.
8891    Stdin,
8892    /// Use standard output as the target.
8893    Stdout,
8894    /// Read from or write to a file.
8895    File {
8896        /// The path name of the input or output file.
8897        filename: String,
8898    },
8899    /// Use a program as the source or target (shell command).
8900    Program {
8901        /// A command to execute
8902        command: String,
8903    },
8904}
8905
8906impl fmt::Display for CopyTarget {
8907    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8908        use CopyTarget::*;
8909        match self {
8910            Stdin => write!(f, "STDIN"),
8911            Stdout => write!(f, "STDOUT"),
8912            File { filename } => write!(f, "'{}'", value::escape_single_quote_string(filename)),
8913            Program { command } => write!(
8914                f,
8915                "PROGRAM '{}'",
8916                value::escape_single_quote_string(command)
8917            ),
8918        }
8919    }
8920}
8921
8922#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8923#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8924#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8925/// Action to take `ON COMMIT` for temporary tables.
8926pub enum OnCommit {
8927    /// Delete rows on commit.
8928    DeleteRows,
8929    /// Preserve rows on commit.
8930    PreserveRows,
8931    /// Drop the table on commit.
8932    Drop,
8933}
8934
8935/// An option in `COPY` statement.
8936///
8937/// <https://www.postgresql.org/docs/14/sql-copy.html>
8938#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8939#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8940#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8941pub enum CopyOption {
8942    /// FORMAT format_name
8943    Format(Ident),
8944    /// FREEZE \[ boolean \]
8945    Freeze(bool),
8946    /// DELIMITER 'delimiter_character'
8947    Delimiter(char),
8948    /// NULL 'null_string'
8949    Null(String),
8950    /// HEADER \[ boolean \]
8951    Header(bool),
8952    /// QUOTE 'quote_character'
8953    Quote(char),
8954    /// ESCAPE 'escape_character'
8955    Escape(char),
8956    /// FORCE_QUOTE { ( column_name [, ...] ) | * }
8957    ForceQuote(Vec<Ident>),
8958    /// FORCE_NOT_NULL ( column_name [, ...] )
8959    ForceNotNull(Vec<Ident>),
8960    /// FORCE_NULL ( column_name [, ...] )
8961    ForceNull(Vec<Ident>),
8962    /// ENCODING 'encoding_name'
8963    Encoding(String),
8964}
8965
8966impl fmt::Display for CopyOption {
8967    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8968        use CopyOption::*;
8969        match self {
8970            Format(name) => write!(f, "FORMAT {name}"),
8971            Freeze(true) => write!(f, "FREEZE"),
8972            Freeze(false) => write!(f, "FREEZE FALSE"),
8973            Delimiter(char) => write!(f, "DELIMITER '{char}'"),
8974            Null(string) => write!(f, "NULL '{}'", value::escape_single_quote_string(string)),
8975            Header(true) => write!(f, "HEADER"),
8976            Header(false) => write!(f, "HEADER FALSE"),
8977            Quote(char) => write!(f, "QUOTE '{char}'"),
8978            Escape(char) => write!(f, "ESCAPE '{char}'"),
8979            ForceQuote(columns) => write!(f, "FORCE_QUOTE ({})", display_comma_separated(columns)),
8980            ForceNotNull(columns) => {
8981                write!(f, "FORCE_NOT_NULL ({})", display_comma_separated(columns))
8982            }
8983            ForceNull(columns) => write!(f, "FORCE_NULL ({})", display_comma_separated(columns)),
8984            Encoding(name) => write!(f, "ENCODING '{}'", value::escape_single_quote_string(name)),
8985        }
8986    }
8987}
8988
8989/// An option in `COPY` statement before PostgreSQL version 9.0.
8990///
8991/// [PostgreSQL](https://www.postgresql.org/docs/8.4/sql-copy.html)
8992/// [Redshift](https://docs.aws.amazon.com/redshift/latest/dg/r_COPY-alphabetical-parm-list.html)
8993#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8994#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8995#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8996pub enum CopyLegacyOption {
8997    /// ACCEPTANYDATE
8998    AcceptAnyDate,
8999    /// ACCEPTINVCHARS
9000    AcceptInvChars(Option<String>),
9001    /// ADDQUOTES
9002    AddQuotes,
9003    /// ALLOWOVERWRITE
9004    AllowOverwrite,
9005    /// BINARY
9006    Binary,
9007    /// BLANKSASNULL
9008    BlankAsNull,
9009    /// BZIP2
9010    Bzip2,
9011    /// CLEANPATH
9012    CleanPath,
9013    /// COMPUPDATE [ PRESET | { ON | TRUE } | { OFF | FALSE } ]
9014    CompUpdate {
9015        /// Whether the COMPUPDATE PRESET option was used.
9016        preset: bool,
9017        /// Optional enabled flag for COMPUPDATE.
9018        enabled: Option<bool>,
9019    },
9020    /// CSV ...
9021    Csv(Vec<CopyLegacyCsvOption>),
9022    /// DATEFORMAT \[ AS \] {'dateformat_string' | 'auto' }
9023    DateFormat(Option<String>),
9024    /// DELIMITER \[ AS \] 'delimiter_character'
9025    Delimiter(char),
9026    /// EMPTYASNULL
9027    EmptyAsNull,
9028    /// `ENCRYPTED \[ AUTO \]`
9029    Encrypted {
9030        /// Whether `AUTO` was specified for encryption.
9031        auto: bool,
9032    },
9033    /// ESCAPE
9034    Escape,
9035    /// EXTENSION 'extension-name'
9036    Extension(String),
9037    /// FIXEDWIDTH \[ AS \] 'fixedwidth-spec'
9038    FixedWidth(String),
9039    /// GZIP
9040    Gzip,
9041    /// HEADER
9042    Header,
9043    /// IAM_ROLE { DEFAULT | 'arn:aws:iam::123456789:role/role1' }
9044    IamRole(IamRoleKind),
9045    /// IGNOREHEADER \[ AS \] number_rows
9046    IgnoreHeader(u64),
9047    /// JSON \[ AS \] 'json_option'
9048    Json(Option<String>),
9049    /// MANIFEST \[ VERBOSE \]
9050    Manifest {
9051        /// Whether the MANIFEST is verbose.
9052        verbose: bool,
9053    },
9054    /// MAXFILESIZE \[ AS \] max-size \[ MB | GB \]
9055    MaxFileSize(FileSize),
9056    /// `NULL \[ AS \] 'null_string'`
9057    Null(String),
9058    /// `PARALLEL [ { ON | TRUE } | { OFF | FALSE } ]`
9059    Parallel(Option<bool>),
9060    /// PARQUET
9061    Parquet,
9062    /// PARTITION BY ( column_name [, ... ] ) \[ INCLUDE \]
9063    PartitionBy(UnloadPartitionBy),
9064    /// REGION \[ AS \] 'aws-region' }
9065    Region(String),
9066    /// REMOVEQUOTES
9067    RemoveQuotes,
9068    /// ROWGROUPSIZE \[ AS \] size \[ MB | GB \]
9069    RowGroupSize(FileSize),
9070    /// STATUPDATE [ { ON | TRUE } | { OFF | FALSE } ]
9071    StatUpdate(Option<bool>),
9072    /// TIMEFORMAT \[ AS \] {'timeformat_string' | 'auto' | 'epochsecs' | 'epochmillisecs' }
9073    TimeFormat(Option<String>),
9074    /// TRUNCATECOLUMNS
9075    TruncateColumns,
9076    /// ZSTD
9077    Zstd,
9078}
9079
9080impl fmt::Display for CopyLegacyOption {
9081    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9082        use CopyLegacyOption::*;
9083        match self {
9084            AcceptAnyDate => write!(f, "ACCEPTANYDATE"),
9085            AcceptInvChars(ch) => {
9086                write!(f, "ACCEPTINVCHARS")?;
9087                if let Some(ch) = ch {
9088                    write!(f, " '{}'", value::escape_single_quote_string(ch))?;
9089                }
9090                Ok(())
9091            }
9092            AddQuotes => write!(f, "ADDQUOTES"),
9093            AllowOverwrite => write!(f, "ALLOWOVERWRITE"),
9094            Binary => write!(f, "BINARY"),
9095            BlankAsNull => write!(f, "BLANKSASNULL"),
9096            Bzip2 => write!(f, "BZIP2"),
9097            CleanPath => write!(f, "CLEANPATH"),
9098            CompUpdate { preset, enabled } => {
9099                write!(f, "COMPUPDATE")?;
9100                if *preset {
9101                    write!(f, " PRESET")?;
9102                } else if let Some(enabled) = enabled {
9103                    write!(
9104                        f,
9105                        "{}",
9106                        match enabled {
9107                            true => " TRUE",
9108                            false => " FALSE",
9109                        }
9110                    )?;
9111                }
9112                Ok(())
9113            }
9114            Csv(opts) => {
9115                write!(f, "CSV")?;
9116                if !opts.is_empty() {
9117                    write!(f, " {}", display_separated(opts, " "))?;
9118                }
9119                Ok(())
9120            }
9121            DateFormat(fmt) => {
9122                write!(f, "DATEFORMAT")?;
9123                if let Some(fmt) = fmt {
9124                    write!(f, " '{}'", value::escape_single_quote_string(fmt))?;
9125                }
9126                Ok(())
9127            }
9128            Delimiter(char) => write!(f, "DELIMITER '{char}'"),
9129            EmptyAsNull => write!(f, "EMPTYASNULL"),
9130            Encrypted { auto } => write!(f, "ENCRYPTED{}", if *auto { " AUTO" } else { "" }),
9131            Escape => write!(f, "ESCAPE"),
9132            Extension(ext) => write!(f, "EXTENSION '{}'", value::escape_single_quote_string(ext)),
9133            FixedWidth(spec) => write!(
9134                f,
9135                "FIXEDWIDTH '{}'",
9136                value::escape_single_quote_string(spec)
9137            ),
9138            Gzip => write!(f, "GZIP"),
9139            Header => write!(f, "HEADER"),
9140            IamRole(role) => write!(f, "IAM_ROLE {role}"),
9141            IgnoreHeader(num_rows) => write!(f, "IGNOREHEADER {num_rows}"),
9142            Json(opt) => {
9143                write!(f, "JSON")?;
9144                if let Some(opt) = opt {
9145                    write!(f, " AS '{}'", value::escape_single_quote_string(opt))?;
9146                }
9147                Ok(())
9148            }
9149            Manifest { verbose } => write!(f, "MANIFEST{}", if *verbose { " VERBOSE" } else { "" }),
9150            MaxFileSize(file_size) => write!(f, "MAXFILESIZE {file_size}"),
9151            Null(string) => write!(f, "NULL '{}'", value::escape_single_quote_string(string)),
9152            Parallel(enabled) => {
9153                write!(
9154                    f,
9155                    "PARALLEL{}",
9156                    match enabled {
9157                        Some(true) => " TRUE",
9158                        Some(false) => " FALSE",
9159                        _ => "",
9160                    }
9161                )
9162            }
9163            Parquet => write!(f, "PARQUET"),
9164            PartitionBy(p) => write!(f, "{p}"),
9165            Region(region) => write!(f, "REGION '{}'", value::escape_single_quote_string(region)),
9166            RemoveQuotes => write!(f, "REMOVEQUOTES"),
9167            RowGroupSize(file_size) => write!(f, "ROWGROUPSIZE {file_size}"),
9168            StatUpdate(enabled) => {
9169                write!(
9170                    f,
9171                    "STATUPDATE{}",
9172                    match enabled {
9173                        Some(true) => " TRUE",
9174                        Some(false) => " FALSE",
9175                        _ => "",
9176                    }
9177                )
9178            }
9179            TimeFormat(fmt) => {
9180                write!(f, "TIMEFORMAT")?;
9181                if let Some(fmt) = fmt {
9182                    write!(f, " '{}'", value::escape_single_quote_string(fmt))?;
9183                }
9184                Ok(())
9185            }
9186            TruncateColumns => write!(f, "TRUNCATECOLUMNS"),
9187            Zstd => write!(f, "ZSTD"),
9188        }
9189    }
9190}
9191
9192/// ```sql
9193/// SIZE \[ MB | GB \]
9194/// ```
9195#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9196#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9197#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9198pub struct FileSize {
9199    /// Numeric size value.
9200    pub size: Value,
9201    /// Optional unit for the size (MB or GB).
9202    pub unit: Option<FileSizeUnit>,
9203}
9204
9205impl fmt::Display for FileSize {
9206    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9207        write!(f, "{}", self.size)?;
9208        if let Some(unit) = &self.unit {
9209            write!(f, " {unit}")?;
9210        }
9211        Ok(())
9212    }
9213}
9214
9215/// Units for `FileSize` (MB or GB).
9216#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9217#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9218#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9219pub enum FileSizeUnit {
9220    /// Megabytes.
9221    MB,
9222    /// Gigabytes.
9223    GB,
9224}
9225
9226impl fmt::Display for FileSizeUnit {
9227    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9228        match self {
9229            FileSizeUnit::MB => write!(f, "MB"),
9230            FileSizeUnit::GB => write!(f, "GB"),
9231        }
9232    }
9233}
9234
9235/// Specifies the partition keys for the unload operation
9236///
9237/// ```sql
9238/// PARTITION BY ( column_name [, ... ] ) [ INCLUDE ]
9239/// ```
9240#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9241#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9242#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9243pub struct UnloadPartitionBy {
9244    /// Columns used to partition the unload output.
9245    pub columns: Vec<Ident>,
9246    /// Whether to include the partition in the output.
9247    pub include: bool,
9248}
9249
9250impl fmt::Display for UnloadPartitionBy {
9251    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9252        write!(
9253            f,
9254            "PARTITION BY ({}){}",
9255            display_comma_separated(&self.columns),
9256            if self.include { " INCLUDE" } else { "" }
9257        )
9258    }
9259}
9260
9261/// An `IAM_ROLE` option in the AWS ecosystem
9262///
9263/// [Redshift COPY](https://docs.aws.amazon.com/redshift/latest/dg/copy-parameters-authorization.html#copy-iam-role)
9264#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9265#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9266#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9267pub enum IamRoleKind {
9268    /// Default role
9269    Default,
9270    /// Specific role ARN, for example: `arn:aws:iam::123456789:role/role1`
9271    Arn(String),
9272}
9273
9274impl fmt::Display for IamRoleKind {
9275    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9276        match self {
9277            IamRoleKind::Default => write!(f, "DEFAULT"),
9278            IamRoleKind::Arn(arn) => write!(f, "'{arn}'"),
9279        }
9280    }
9281}
9282
9283/// A `CSV` option in `COPY` statement before PostgreSQL version 9.0.
9284///
9285/// <https://www.postgresql.org/docs/8.4/sql-copy.html>
9286#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9287#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9288#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9289pub enum CopyLegacyCsvOption {
9290    /// HEADER
9291    Header,
9292    /// QUOTE \[ AS \] 'quote_character'
9293    Quote(char),
9294    /// ESCAPE \[ AS \] 'escape_character'
9295    Escape(char),
9296    /// FORCE QUOTE { column_name [, ...] | * }
9297    ForceQuote(Vec<Ident>),
9298    /// FORCE NOT NULL column_name [, ...]
9299    ForceNotNull(Vec<Ident>),
9300}
9301
9302impl fmt::Display for CopyLegacyCsvOption {
9303    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9304        use CopyLegacyCsvOption::*;
9305        match self {
9306            Header => write!(f, "HEADER"),
9307            Quote(char) => write!(f, "QUOTE '{char}'"),
9308            Escape(char) => write!(f, "ESCAPE '{char}'"),
9309            ForceQuote(columns) => write!(f, "FORCE QUOTE {}", display_comma_separated(columns)),
9310            ForceNotNull(columns) => {
9311                write!(f, "FORCE NOT NULL {}", display_comma_separated(columns))
9312            }
9313        }
9314    }
9315}
9316
9317/// Objects that can be discarded with `DISCARD`.
9318#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9319#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9320#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9321pub enum DiscardObject {
9322    /// Discard all session state.
9323    ALL,
9324    /// Discard cached plans.
9325    PLANS,
9326    /// Discard sequence values.
9327    SEQUENCES,
9328    /// Discard temporary objects.
9329    TEMP,
9330}
9331
9332impl fmt::Display for DiscardObject {
9333    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9334        match self {
9335            DiscardObject::ALL => f.write_str("ALL"),
9336            DiscardObject::PLANS => f.write_str("PLANS"),
9337            DiscardObject::SEQUENCES => f.write_str("SEQUENCES"),
9338            DiscardObject::TEMP => f.write_str("TEMP"),
9339        }
9340    }
9341}
9342
9343/// Types of flush operations supported by `FLUSH`.
9344#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9345#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9346#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9347pub enum FlushType {
9348    /// Flush binary logs.
9349    BinaryLogs,
9350    /// Flush engine logs.
9351    EngineLogs,
9352    /// Flush error logs.
9353    ErrorLogs,
9354    /// Flush general logs.
9355    GeneralLogs,
9356    /// Flush hosts information.
9357    Hosts,
9358    /// Flush logs.
9359    Logs,
9360    /// Flush privileges.
9361    Privileges,
9362    /// Flush optimizer costs.
9363    OptimizerCosts,
9364    /// Flush relay logs.
9365    RelayLogs,
9366    /// Flush slow logs.
9367    SlowLogs,
9368    /// Flush status.
9369    Status,
9370    /// Flush user resources.
9371    UserResources,
9372    /// Flush table data.
9373    Tables,
9374}
9375
9376impl fmt::Display for FlushType {
9377    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9378        match self {
9379            FlushType::BinaryLogs => f.write_str("BINARY LOGS"),
9380            FlushType::EngineLogs => f.write_str("ENGINE LOGS"),
9381            FlushType::ErrorLogs => f.write_str("ERROR LOGS"),
9382            FlushType::GeneralLogs => f.write_str("GENERAL LOGS"),
9383            FlushType::Hosts => f.write_str("HOSTS"),
9384            FlushType::Logs => f.write_str("LOGS"),
9385            FlushType::Privileges => f.write_str("PRIVILEGES"),
9386            FlushType::OptimizerCosts => f.write_str("OPTIMIZER_COSTS"),
9387            FlushType::RelayLogs => f.write_str("RELAY LOGS"),
9388            FlushType::SlowLogs => f.write_str("SLOW LOGS"),
9389            FlushType::Status => f.write_str("STATUS"),
9390            FlushType::UserResources => f.write_str("USER_RESOURCES"),
9391            FlushType::Tables => f.write_str("TABLES"),
9392        }
9393    }
9394}
9395
9396/// Location modifier for flush commands.
9397#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9398#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9399#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9400pub enum FlushLocation {
9401    /// Do not write changes to the binary log.
9402    NoWriteToBinlog,
9403    /// Apply flush locally.
9404    Local,
9405}
9406
9407impl fmt::Display for FlushLocation {
9408    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9409        match self {
9410            FlushLocation::NoWriteToBinlog => f.write_str("NO_WRITE_TO_BINLOG"),
9411            FlushLocation::Local => f.write_str("LOCAL"),
9412        }
9413    }
9414}
9415
9416/// Optional context modifier for statements that can be or `LOCAL`, `GLOBAL`, or `SESSION`.
9417#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9418#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9419#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9420pub enum ContextModifier {
9421    /// `LOCAL` identifier, usually related to transactional states.
9422    Local,
9423    /// `SESSION` identifier
9424    Session,
9425    /// `GLOBAL` identifier
9426    Global,
9427}
9428
9429impl fmt::Display for ContextModifier {
9430    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9431        match self {
9432            Self::Local => {
9433                write!(f, "LOCAL ")
9434            }
9435            Self::Session => {
9436                write!(f, "SESSION ")
9437            }
9438            Self::Global => {
9439                write!(f, "GLOBAL ")
9440            }
9441        }
9442    }
9443}
9444
9445/// Function describe in DROP FUNCTION.
9446#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9447#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9448pub enum DropFunctionOption {
9449    /// `RESTRICT` option for DROP FUNCTION.
9450    Restrict,
9451    /// `CASCADE` option for DROP FUNCTION.
9452    Cascade,
9453}
9454
9455impl fmt::Display for DropFunctionOption {
9456    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9457        match self {
9458            DropFunctionOption::Restrict => write!(f, "RESTRICT "),
9459            DropFunctionOption::Cascade => write!(f, "CASCADE  "),
9460        }
9461    }
9462}
9463
9464/// Generic function description for DROP FUNCTION and CREATE TRIGGER.
9465#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9466#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9467#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9468pub struct FunctionDesc {
9469    /// The function name.
9470    pub name: ObjectName,
9471    /// Optional list of function arguments.
9472    pub args: Option<Vec<OperateFunctionArg>>,
9473}
9474
9475impl fmt::Display for FunctionDesc {
9476    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9477        write!(f, "{}", self.name)?;
9478        if let Some(args) = &self.args {
9479            write!(f, "({})", display_comma_separated(args))?;
9480        }
9481        Ok(())
9482    }
9483}
9484
9485/// Function argument in CREATE OR DROP FUNCTION.
9486#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9487#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9488#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9489pub struct OperateFunctionArg {
9490    /// Optional argument mode (`IN`, `OUT`, `INOUT`).
9491    pub mode: Option<ArgMode>,
9492    /// Optional argument identifier/name.
9493    pub name: Option<Ident>,
9494    /// The data type of the argument.
9495    pub data_type: DataType,
9496    /// Optional default expression for the argument.
9497    pub default_expr: Option<Expr>,
9498}
9499
9500impl OperateFunctionArg {
9501    /// Returns an unnamed argument.
9502    pub fn unnamed(data_type: DataType) -> Self {
9503        Self {
9504            mode: None,
9505            name: None,
9506            data_type,
9507            default_expr: None,
9508        }
9509    }
9510
9511    /// Returns an argument with name.
9512    pub fn with_name(name: &str, data_type: DataType) -> Self {
9513        Self {
9514            mode: None,
9515            name: Some(name.into()),
9516            data_type,
9517            default_expr: None,
9518        }
9519    }
9520}
9521
9522impl fmt::Display for OperateFunctionArg {
9523    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9524        if let Some(mode) = &self.mode {
9525            write!(f, "{mode} ")?;
9526        }
9527        if let Some(name) = &self.name {
9528            write!(f, "{name} ")?;
9529        }
9530        write!(f, "{}", self.data_type)?;
9531        if let Some(default_expr) = &self.default_expr {
9532            write!(f, " = {default_expr}")?;
9533        }
9534        Ok(())
9535    }
9536}
9537
9538/// The mode of an argument in CREATE FUNCTION.
9539#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9540#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9541#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9542pub enum ArgMode {
9543    /// `IN` mode.
9544    In,
9545    /// `OUT` mode.
9546    Out,
9547    /// `INOUT` mode.
9548    InOut,
9549}
9550
9551impl fmt::Display for ArgMode {
9552    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9553        match self {
9554            ArgMode::In => write!(f, "IN"),
9555            ArgMode::Out => write!(f, "OUT"),
9556            ArgMode::InOut => write!(f, "INOUT"),
9557        }
9558    }
9559}
9560
9561/// These attributes inform the query optimizer about the behavior of the function.
9562#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9563#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9564#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9565pub enum FunctionBehavior {
9566    /// Function is immutable.
9567    Immutable,
9568    /// Function is stable.
9569    Stable,
9570    /// Function is volatile.
9571    Volatile,
9572}
9573
9574impl fmt::Display for FunctionBehavior {
9575    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9576        match self {
9577            FunctionBehavior::Immutable => write!(f, "IMMUTABLE"),
9578            FunctionBehavior::Stable => write!(f, "STABLE"),
9579            FunctionBehavior::Volatile => write!(f, "VOLATILE"),
9580        }
9581    }
9582}
9583
9584/// Security attribute for functions: SECURITY DEFINER or SECURITY INVOKER.
9585///
9586/// [PostgreSQL](https://www.postgresql.org/docs/current/sql-createfunction.html)
9587#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9588#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9589#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9590pub enum FunctionSecurity {
9591    /// Execute the function with the privileges of the user who defined it.
9592    Definer,
9593    /// Execute the function with the privileges of the user who invokes it.
9594    Invoker,
9595}
9596
9597impl fmt::Display for FunctionSecurity {
9598    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9599        match self {
9600            FunctionSecurity::Definer => write!(f, "SECURITY DEFINER"),
9601            FunctionSecurity::Invoker => write!(f, "SECURITY INVOKER"),
9602        }
9603    }
9604}
9605
9606/// Value for a SET configuration parameter in a CREATE FUNCTION statement.
9607///
9608/// [PostgreSQL](https://www.postgresql.org/docs/current/sql-createfunction.html)
9609#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9610#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9611#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9612pub enum FunctionSetValue {
9613    /// SET param = value1, value2, ...
9614    Values(Vec<Expr>),
9615    /// SET param FROM CURRENT
9616    FromCurrent,
9617}
9618
9619/// A SET configuration_parameter clause in a CREATE FUNCTION statement.
9620///
9621/// [PostgreSQL](https://www.postgresql.org/docs/current/sql-createfunction.html)
9622#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9623#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9624#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9625pub struct FunctionDefinitionSetParam {
9626    /// The name of the configuration parameter.
9627    pub name: Ident,
9628    /// The value to set for the parameter.
9629    pub value: FunctionSetValue,
9630}
9631
9632impl fmt::Display for FunctionDefinitionSetParam {
9633    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9634        write!(f, "SET {} ", self.name)?;
9635        match &self.value {
9636            FunctionSetValue::Values(values) => {
9637                write!(f, "= {}", display_comma_separated(values))
9638            }
9639            FunctionSetValue::FromCurrent => write!(f, "FROM CURRENT"),
9640        }
9641    }
9642}
9643
9644/// These attributes describe the behavior of the function when called with a null argument.
9645#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9646#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9647#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9648pub enum FunctionCalledOnNull {
9649    /// Function is called even when inputs are null.
9650    CalledOnNullInput,
9651    /// Function returns null when any input is null.
9652    ReturnsNullOnNullInput,
9653    /// Function is strict about null inputs.
9654    Strict,
9655}
9656
9657impl fmt::Display for FunctionCalledOnNull {
9658    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9659        match self {
9660            FunctionCalledOnNull::CalledOnNullInput => write!(f, "CALLED ON NULL INPUT"),
9661            FunctionCalledOnNull::ReturnsNullOnNullInput => write!(f, "RETURNS NULL ON NULL INPUT"),
9662            FunctionCalledOnNull::Strict => write!(f, "STRICT"),
9663        }
9664    }
9665}
9666
9667/// If it is safe for PostgreSQL to call the function from multiple threads at once
9668#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9669#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9670#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9671pub enum FunctionParallel {
9672    /// The function is not safe to run in parallel.
9673    Unsafe,
9674    /// The function is restricted for parallel execution.
9675    Restricted,
9676    /// The function is safe to run in parallel.
9677    Safe,
9678}
9679
9680impl fmt::Display for FunctionParallel {
9681    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9682        match self {
9683            FunctionParallel::Unsafe => write!(f, "PARALLEL UNSAFE"),
9684            FunctionParallel::Restricted => write!(f, "PARALLEL RESTRICTED"),
9685            FunctionParallel::Safe => write!(f, "PARALLEL SAFE"),
9686        }
9687    }
9688}
9689
9690/// [BigQuery] Determinism specifier used in a UDF definition.
9691///
9692/// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#syntax_11
9693#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9694#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9695#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9696pub enum FunctionDeterminismSpecifier {
9697    /// Function is deterministic.
9698    Deterministic,
9699    /// Function is not deterministic.
9700    NotDeterministic,
9701}
9702
9703impl fmt::Display for FunctionDeterminismSpecifier {
9704    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9705        match self {
9706            FunctionDeterminismSpecifier::Deterministic => {
9707                write!(f, "DETERMINISTIC")
9708            }
9709            FunctionDeterminismSpecifier::NotDeterministic => {
9710                write!(f, "NOT DETERMINISTIC")
9711            }
9712        }
9713    }
9714}
9715
9716/// Represent the expression body of a `CREATE FUNCTION` statement as well as
9717/// where within the statement, the body shows up.
9718///
9719/// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#syntax_11
9720/// [PostgreSQL]: https://www.postgresql.org/docs/15/sql-createfunction.html
9721/// [MsSql]: https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql
9722#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9723#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9724#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9725pub enum CreateFunctionBody {
9726    /// A function body expression using the 'AS' keyword and shows up
9727    /// before any `OPTIONS` clause.
9728    ///
9729    /// Example:
9730    /// ```sql
9731    /// CREATE FUNCTION myfunc(x FLOAT64, y FLOAT64) RETURNS FLOAT64
9732    /// AS (x * y)
9733    /// OPTIONS(description="desc");
9734    /// ```
9735    ///
9736    /// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#syntax_11
9737    /// [PostgreSQL]: https://www.postgresql.org/docs/current/sql-createfunction.html
9738    AsBeforeOptions {
9739        /// The primary expression.
9740        body: Expr,
9741        /// Link symbol if the primary expression contains the name of shared library file.
9742        ///
9743        /// Example:
9744        /// ```sql
9745        /// CREATE FUNCTION cas_in(input cstring) RETURNS cas
9746        /// AS 'MODULE_PATHNAME', 'cas_in_wrapper'
9747        /// ```
9748        /// [PostgreSQL]: https://www.postgresql.org/docs/current/sql-createfunction.html
9749        link_symbol: Option<Expr>,
9750    },
9751    /// A function body expression using the 'AS' keyword and shows up
9752    /// after any `OPTIONS` clause.
9753    ///
9754    /// Example:
9755    /// ```sql
9756    /// CREATE FUNCTION myfunc(x FLOAT64, y FLOAT64) RETURNS FLOAT64
9757    /// OPTIONS(description="desc")
9758    /// AS (x * y);
9759    /// ```
9760    ///
9761    /// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#syntax_11
9762    AsAfterOptions(Expr),
9763    /// Function body with statements before the `RETURN` keyword.
9764    ///
9765    /// Example:
9766    /// ```sql
9767    /// CREATE FUNCTION my_scalar_udf(a INT, b INT)
9768    /// RETURNS INT
9769    /// AS
9770    /// BEGIN
9771    ///     DECLARE c INT;
9772    ///     SET c = a + b;
9773    ///     RETURN c;
9774    /// END
9775    /// ```
9776    ///
9777    /// [MsSql]: https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql
9778    AsBeginEnd(BeginEndStatements),
9779    /// Function body expression using the 'RETURN' keyword.
9780    ///
9781    /// Example:
9782    /// ```sql
9783    /// CREATE FUNCTION myfunc(a INTEGER, IN b INTEGER = 1) RETURNS INTEGER
9784    /// LANGUAGE SQL
9785    /// RETURN a + b;
9786    /// ```
9787    ///
9788    /// [PostgreSQL]: https://www.postgresql.org/docs/current/sql-createfunction.html
9789    Return(Expr),
9790
9791    /// Function body expression using the 'AS RETURN' keywords
9792    ///
9793    /// Example:
9794    /// ```sql
9795    /// CREATE FUNCTION myfunc(a INT, b INT)
9796    /// RETURNS TABLE
9797    /// AS RETURN (SELECT a + b AS sum);
9798    /// ```
9799    ///
9800    /// [MsSql]: https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql
9801    AsReturnExpr(Expr),
9802
9803    /// Function body expression using the 'AS RETURN' keywords, with an un-parenthesized SELECT query
9804    ///
9805    /// Example:
9806    /// ```sql
9807    /// CREATE FUNCTION myfunc(a INT, b INT)
9808    /// RETURNS TABLE
9809    /// AS RETURN SELECT a + b AS sum;
9810    /// ```
9811    ///
9812    /// [MsSql]: https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql?view=sql-server-ver16#select_stmt
9813    AsReturnSelect(Select),
9814}
9815
9816#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9817#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9818#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9819/// `USING` clause options for `CREATE FUNCTION` (e.g., JAR, FILE, ARCHIVE).
9820pub enum CreateFunctionUsing {
9821    /// Use a JAR file located at the given URI.
9822    Jar(String),
9823    /// Use a file located at the given URI.
9824    File(String),
9825    /// Use an archive located at the given URI.
9826    Archive(String),
9827}
9828
9829impl fmt::Display for CreateFunctionUsing {
9830    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9831        write!(f, "USING ")?;
9832        match self {
9833            CreateFunctionUsing::Jar(uri) => write!(f, "JAR '{uri}'"),
9834            CreateFunctionUsing::File(uri) => write!(f, "FILE '{uri}'"),
9835            CreateFunctionUsing::Archive(uri) => write!(f, "ARCHIVE '{uri}'"),
9836        }
9837    }
9838}
9839
9840/// `NAME = <EXPR>` arguments for DuckDB macros
9841///
9842/// See [Create Macro - DuckDB](https://duckdb.org/docs/sql/statements/create_macro)
9843/// for more details
9844#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9845#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9846#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9847pub struct MacroArg {
9848    /// The argument name.
9849    pub name: Ident,
9850    /// Optional default expression for the argument.
9851    pub default_expr: Option<Expr>,
9852}
9853
9854impl MacroArg {
9855    /// Returns an argument with name.
9856    pub fn new(name: &str) -> Self {
9857        Self {
9858            name: name.into(),
9859            default_expr: None,
9860        }
9861    }
9862}
9863
9864impl fmt::Display for MacroArg {
9865    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9866        write!(f, "{}", self.name)?;
9867        if let Some(default_expr) = &self.default_expr {
9868            write!(f, " := {default_expr}")?;
9869        }
9870        Ok(())
9871    }
9872}
9873
9874#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9875#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9876#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9877/// Definition for a DuckDB macro: either an expression or a table-producing query.
9878pub enum MacroDefinition {
9879    /// The macro is defined as an expression.
9880    Expr(Expr),
9881    /// The macro is defined as a table (query).
9882    Table(Box<Query>),
9883}
9884
9885impl fmt::Display for MacroDefinition {
9886    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9887        match self {
9888            MacroDefinition::Expr(expr) => write!(f, "{expr}")?,
9889            MacroDefinition::Table(query) => write!(f, "{query}")?,
9890        }
9891        Ok(())
9892    }
9893}
9894
9895/// Schema possible naming variants ([1]).
9896///
9897/// [1]: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#schema-definition
9898#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9899#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9900#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9901pub enum SchemaName {
9902    /// Only schema name specified: `<schema name>`.
9903    Simple(ObjectName),
9904    /// Only authorization identifier specified: `AUTHORIZATION <schema authorization identifier>`.
9905    UnnamedAuthorization(Ident),
9906    /// Both schema name and authorization identifier specified: `<schema name>  AUTHORIZATION <schema authorization identifier>`.
9907    NamedAuthorization(ObjectName, Ident),
9908}
9909
9910impl fmt::Display for SchemaName {
9911    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
9912        match self {
9913            SchemaName::Simple(name) => {
9914                write!(f, "{name}")
9915            }
9916            SchemaName::UnnamedAuthorization(authorization) => {
9917                write!(f, "AUTHORIZATION {authorization}")
9918            }
9919            SchemaName::NamedAuthorization(name, authorization) => {
9920                write!(f, "{name} AUTHORIZATION {authorization}")
9921            }
9922        }
9923    }
9924}
9925
9926/// Fulltext search modifiers ([1]).
9927///
9928/// [1]: https://dev.mysql.com/doc/refman/8.0/en/fulltext-search.html#function_match
9929#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9930#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9931#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9932pub enum SearchModifier {
9933    /// `IN NATURAL LANGUAGE MODE`.
9934    InNaturalLanguageMode,
9935    /// `IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION`.
9936    InNaturalLanguageModeWithQueryExpansion,
9937    ///`IN BOOLEAN MODE`.
9938    InBooleanMode,
9939    ///`WITH QUERY EXPANSION`.
9940    WithQueryExpansion,
9941}
9942
9943impl fmt::Display for SearchModifier {
9944    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
9945        match self {
9946            Self::InNaturalLanguageMode => {
9947                write!(f, "IN NATURAL LANGUAGE MODE")?;
9948            }
9949            Self::InNaturalLanguageModeWithQueryExpansion => {
9950                write!(f, "IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION")?;
9951            }
9952            Self::InBooleanMode => {
9953                write!(f, "IN BOOLEAN MODE")?;
9954            }
9955            Self::WithQueryExpansion => {
9956                write!(f, "WITH QUERY EXPANSION")?;
9957            }
9958        }
9959
9960        Ok(())
9961    }
9962}
9963
9964/// Represents a `LOCK TABLE` clause with optional alias and lock type.
9965#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9966#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9967#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9968pub struct LockTable {
9969    /// The table identifier to lock.
9970    pub table: Ident,
9971    /// Optional alias for the table.
9972    pub alias: Option<Ident>,
9973    /// The type of lock to apply to the table.
9974    pub lock_type: LockTableType,
9975}
9976
9977impl fmt::Display for LockTable {
9978    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
9979        let Self {
9980            table: tbl_name,
9981            alias,
9982            lock_type,
9983        } = self;
9984
9985        write!(f, "{tbl_name} ")?;
9986        if let Some(alias) = alias {
9987            write!(f, "AS {alias} ")?;
9988        }
9989        write!(f, "{lock_type}")?;
9990        Ok(())
9991    }
9992}
9993
9994#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9995#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9996#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9997/// The type of lock used in `LOCK TABLE` statements.
9998pub enum LockTableType {
9999    /// Shared/read lock. If `local` is true, it's a local read lock.
10000    Read {
10001        /// Whether the read lock is local.
10002        local: bool,
10003    },
10004    /// Exclusive/write lock. If `low_priority` is true, the write is low priority.
10005    Write {
10006        /// Whether the write lock is low priority.
10007        low_priority: bool,
10008    },
10009}
10010
10011impl fmt::Display for LockTableType {
10012    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10013        match self {
10014            Self::Read { local } => {
10015                write!(f, "READ")?;
10016                if *local {
10017                    write!(f, " LOCAL")?;
10018                }
10019            }
10020            Self::Write { low_priority } => {
10021                if *low_priority {
10022                    write!(f, "LOW_PRIORITY ")?;
10023                }
10024                write!(f, "WRITE")?;
10025            }
10026        }
10027
10028        Ok(())
10029    }
10030}
10031
10032#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10033#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10034#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10035/// Hive-specific `SET LOCATION` helper used in some `LOAD DATA` statements.
10036pub struct HiveSetLocation {
10037    /// Whether the `SET` keyword was present.
10038    pub has_set: bool,
10039    /// The location identifier.
10040    pub location: Ident,
10041}
10042
10043impl fmt::Display for HiveSetLocation {
10044    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10045        if self.has_set {
10046            write!(f, "SET ")?;
10047        }
10048        write!(f, "LOCATION {}", self.location)
10049    }
10050}
10051
10052/// MySQL `ALTER TABLE` only  [FIRST | AFTER column_name]
10053#[allow(clippy::large_enum_variant)]
10054#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10055#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10056#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10057/// MySQL `ALTER TABLE` column position specifier: `FIRST` or `AFTER <column>`.
10058pub enum MySQLColumnPosition {
10059    /// Place the column first in the table.
10060    First,
10061    /// Place the column after the specified identifier.
10062    After(Ident),
10063}
10064
10065impl Display for MySQLColumnPosition {
10066    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10067        match self {
10068            MySQLColumnPosition::First => write!(f, "FIRST"),
10069            MySQLColumnPosition::After(ident) => {
10070                let column_name = &ident.value;
10071                write!(f, "AFTER {column_name}")
10072            }
10073        }
10074    }
10075}
10076
10077/// MySQL `CREATE VIEW` algorithm parameter: [ALGORITHM = {UNDEFINED | MERGE | TEMPTABLE}]
10078#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10079#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10080#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10081/// MySQL `CREATE VIEW` algorithm options.
10082pub enum CreateViewAlgorithm {
10083    /// `UNDEFINED` algorithm.
10084    Undefined,
10085    /// `MERGE` algorithm.
10086    Merge,
10087    /// `TEMPTABLE` algorithm.
10088    TempTable,
10089}
10090
10091impl Display for CreateViewAlgorithm {
10092    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10093        match self {
10094            CreateViewAlgorithm::Undefined => write!(f, "UNDEFINED"),
10095            CreateViewAlgorithm::Merge => write!(f, "MERGE"),
10096            CreateViewAlgorithm::TempTable => write!(f, "TEMPTABLE"),
10097        }
10098    }
10099}
10100/// MySQL `CREATE VIEW` security parameter: [SQL SECURITY { DEFINER | INVOKER }]
10101#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10102#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10103#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10104/// MySQL `CREATE VIEW` SQL SECURITY options.
10105pub enum CreateViewSecurity {
10106    /// The view runs with the privileges of the definer.
10107    Definer,
10108    /// The view runs with the privileges of the invoker.
10109    Invoker,
10110}
10111
10112impl Display for CreateViewSecurity {
10113    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10114        match self {
10115            CreateViewSecurity::Definer => write!(f, "DEFINER"),
10116            CreateViewSecurity::Invoker => write!(f, "INVOKER"),
10117        }
10118    }
10119}
10120
10121/// [MySQL] `CREATE VIEW` additional parameters
10122///
10123/// [MySQL]: https://dev.mysql.com/doc/refman/9.1/en/create-view.html
10124#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10125#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10126#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10127pub struct CreateViewParams {
10128    /// Optional view algorithm (e.g., MERGE, TEMPTABLE).
10129    pub algorithm: Option<CreateViewAlgorithm>,
10130    /// Optional definer (the security principal that will own the view).
10131    pub definer: Option<GranteeName>,
10132    /// Optional SQL SECURITY setting for the view.
10133    pub security: Option<CreateViewSecurity>,
10134}
10135
10136impl Display for CreateViewParams {
10137    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10138        let CreateViewParams {
10139            algorithm,
10140            definer,
10141            security,
10142        } = self;
10143        if let Some(algorithm) = algorithm {
10144            write!(f, "ALGORITHM = {algorithm} ")?;
10145        }
10146        if let Some(definers) = definer {
10147            write!(f, "DEFINER = {definers} ")?;
10148        }
10149        if let Some(security) = security {
10150            write!(f, "SQL SECURITY {security} ")?;
10151        }
10152        Ok(())
10153    }
10154}
10155
10156#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10157#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10158#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10159/// Key/Value, where the value is a (optionally named) list of identifiers
10160///
10161/// ```sql
10162/// UNION = (tbl_name[,tbl_name]...)
10163/// ENGINE = ReplicatedMergeTree('/table_name','{replica}', ver)
10164/// ENGINE = SummingMergeTree([columns])
10165/// ```
10166pub struct NamedParenthesizedList {
10167    /// The option key (identifier) for this named list.
10168    pub key: Ident,
10169    /// Optional secondary name associated with the key.
10170    pub name: Option<Ident>,
10171    /// The list of identifier values for the key.
10172    pub values: Vec<Ident>,
10173}
10174
10175/// Snowflake `WITH ROW ACCESS POLICY policy_name ON (identifier, ...)`
10176///
10177/// <https://docs.snowflake.com/en/sql-reference/sql/create-table>
10178/// <https://docs.snowflake.com/en/user-guide/security-row-intro>
10179#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10180#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10181#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10182pub struct RowAccessPolicy {
10183    /// The fully-qualified policy object name.
10184    pub policy: ObjectName,
10185    /// Identifiers for the columns or objects the policy applies to.
10186    pub on: Vec<Ident>,
10187}
10188
10189impl RowAccessPolicy {
10190    /// Create a new `RowAccessPolicy` for the given `policy` and `on` identifiers.
10191    pub fn new(policy: ObjectName, on: Vec<Ident>) -> Self {
10192        Self { policy, on }
10193    }
10194}
10195
10196impl Display for RowAccessPolicy {
10197    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10198        write!(
10199            f,
10200            "WITH ROW ACCESS POLICY {} ON ({})",
10201            self.policy,
10202            display_comma_separated(self.on.as_slice())
10203        )
10204    }
10205}
10206
10207/// Snowflake `WITH TAG ( tag_name = '<tag_value>', ...)`
10208///
10209/// <https://docs.snowflake.com/en/sql-reference/sql/create-table>
10210#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10211#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10212#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10213pub struct Tag {
10214    /// The tag key (can be qualified).
10215    pub key: ObjectName,
10216    /// The tag value as a string.
10217    pub value: String,
10218}
10219
10220impl Tag {
10221    /// Create a new `Tag` with the given key and value.
10222    pub fn new(key: ObjectName, value: String) -> Self {
10223        Self { key, value }
10224    }
10225}
10226
10227impl Display for Tag {
10228    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10229        write!(f, "{}='{}'", self.key, self.value)
10230    }
10231}
10232
10233/// Snowflake `WITH CONTACT ( purpose = contact [ , purpose = contact ...] )`
10234///
10235/// <https://docs.snowflake.com/en/sql-reference/sql/create-database>
10236#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10237#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10238#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10239pub struct ContactEntry {
10240    /// The purpose label for the contact entry.
10241    pub purpose: String,
10242    /// The contact information associated with the purpose.
10243    pub contact: String,
10244}
10245
10246impl Display for ContactEntry {
10247    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10248        write!(f, "{} = {}", self.purpose, self.contact)
10249    }
10250}
10251
10252/// Helper to indicate if a comment includes the `=` in the display form
10253#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10254#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10255#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10256pub enum CommentDef {
10257    /// Includes `=` when printing the comment, as `COMMENT = 'comment'`
10258    /// Does not include `=` when printing the comment, as `COMMENT 'comment'`
10259    WithEq(String),
10260    /// Comment variant that omits the `=` when displayed.
10261    WithoutEq(String),
10262}
10263
10264impl Display for CommentDef {
10265    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10266        match self {
10267            CommentDef::WithEq(comment) | CommentDef::WithoutEq(comment) => write!(f, "{comment}"),
10268        }
10269    }
10270}
10271
10272/// Helper to indicate if a collection should be wrapped by a symbol in the display form
10273///
10274/// [`Display`] is implemented for every [`Vec<T>`] where `T: Display`.
10275/// The string output is a comma separated list for the vec items
10276///
10277/// # Examples
10278/// ```
10279/// # use sqlparser::ast::WrappedCollection;
10280/// let items = WrappedCollection::Parentheses(vec!["one", "two", "three"]);
10281/// assert_eq!("(one, two, three)", items.to_string());
10282///
10283/// let items = WrappedCollection::NoWrapping(vec!["one", "two", "three"]);
10284/// assert_eq!("one, two, three", items.to_string());
10285/// ```
10286#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10287#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10288#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10289pub enum WrappedCollection<T> {
10290    /// Print the collection without wrapping symbols, as `item, item, item`
10291    NoWrapping(T),
10292    /// Wraps the collection in Parentheses, as `(item, item, item)`
10293    Parentheses(T),
10294}
10295
10296impl<T> Display for WrappedCollection<Vec<T>>
10297where
10298    T: Display,
10299{
10300    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10301        match self {
10302            WrappedCollection::NoWrapping(inner) => {
10303                write!(f, "{}", display_comma_separated(inner.as_slice()))
10304            }
10305            WrappedCollection::Parentheses(inner) => {
10306                write!(f, "({})", display_comma_separated(inner.as_slice()))
10307            }
10308        }
10309    }
10310}
10311
10312/// Represents a single PostgreSQL utility option.
10313///
10314/// A utility option is a key-value pair where the key is an identifier (IDENT) and the value
10315/// can be one of the following:
10316/// - A number with an optional sign (`+` or `-`). Example: `+10`, `-10.2`, `3`
10317/// - A non-keyword string. Example: `option1`, `'option2'`, `"option3"`
10318/// - keyword: `TRUE`, `FALSE`, `ON` (`off` is also accept).
10319/// - Empty. Example: `ANALYZE` (identifier only)
10320///
10321/// Utility options are used in various PostgreSQL DDL statements, including statements such as
10322/// `CLUSTER`, `EXPLAIN`, `VACUUM`, and `REINDEX`. These statements format options as `( option [, ...] )`.
10323///
10324/// [CLUSTER](https://www.postgresql.org/docs/current/sql-cluster.html)
10325/// [EXPLAIN](https://www.postgresql.org/docs/current/sql-explain.html)
10326/// [VACUUM](https://www.postgresql.org/docs/current/sql-vacuum.html)
10327/// [REINDEX](https://www.postgresql.org/docs/current/sql-reindex.html)
10328///
10329/// For example, the `EXPLAIN` AND `VACUUM` statements with options might look like this:
10330/// ```sql
10331/// EXPLAIN (ANALYZE, VERBOSE TRUE, FORMAT TEXT) SELECT * FROM my_table;
10332///
10333/// VACUUM (VERBOSE, ANALYZE ON, PARALLEL 10) my_table;
10334/// ```
10335#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10336#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10337#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10338pub struct UtilityOption {
10339    /// The option name (identifier).
10340    pub name: Ident,
10341    /// Optional argument for the option (number, string, keyword, etc.).
10342    pub arg: Option<Expr>,
10343}
10344
10345impl Display for UtilityOption {
10346    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10347        if let Some(ref arg) = self.arg {
10348            write!(f, "{} {}", self.name, arg)
10349        } else {
10350            write!(f, "{}", self.name)
10351        }
10352    }
10353}
10354
10355/// Represents the different options available for `SHOW`
10356/// statements to filter the results. Example from Snowflake:
10357/// <https://docs.snowflake.com/en/sql-reference/sql/show-tables>
10358#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10359#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10360#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10361pub struct ShowStatementOptions {
10362    /// Optional scope to show in (for example: TABLE, SCHEMA).
10363    pub show_in: Option<ShowStatementIn>,
10364    /// Optional `STARTS WITH` filter value.
10365    pub starts_with: Option<Value>,
10366    /// Optional `LIMIT` expression.
10367    pub limit: Option<Expr>,
10368    /// Optional `FROM` value used with `LIMIT`.
10369    pub limit_from: Option<Value>,
10370    /// Optional filter position (infix or suffix) for `LIKE`/`FILTER`.
10371    pub filter_position: Option<ShowStatementFilterPosition>,
10372}
10373
10374impl Display for ShowStatementOptions {
10375    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10376        let (like_in_infix, like_in_suffix) = match &self.filter_position {
10377            Some(ShowStatementFilterPosition::Infix(filter)) => {
10378                (format!(" {filter}"), "".to_string())
10379            }
10380            Some(ShowStatementFilterPosition::Suffix(filter)) => {
10381                ("".to_string(), format!(" {filter}"))
10382            }
10383            None => ("".to_string(), "".to_string()),
10384        };
10385        write!(
10386            f,
10387            "{like_in_infix}{show_in}{starts_with}{limit}{from}{like_in_suffix}",
10388            show_in = match &self.show_in {
10389                Some(i) => format!(" {i}"),
10390                None => String::new(),
10391            },
10392            starts_with = match &self.starts_with {
10393                Some(s) => format!(" STARTS WITH {s}"),
10394                None => String::new(),
10395            },
10396            limit = match &self.limit {
10397                Some(l) => format!(" LIMIT {l}"),
10398                None => String::new(),
10399            },
10400            from = match &self.limit_from {
10401                Some(f) => format!(" FROM {f}"),
10402                None => String::new(),
10403            }
10404        )?;
10405        Ok(())
10406    }
10407}
10408
10409#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10410#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10411#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10412/// Where a `SHOW` filter appears relative to the main clause.
10413pub enum ShowStatementFilterPosition {
10414    /// Put the filter in an infix position (e.g. `SHOW COLUMNS LIKE '%name%' IN TABLE tbl`).
10415    Infix(ShowStatementFilter), // For example: SHOW COLUMNS LIKE '%name%' IN TABLE tbl
10416    /// Put the filter in a suffix position (e.g. `SHOW COLUMNS IN tbl LIKE '%name%'`).
10417    Suffix(ShowStatementFilter), // For example: SHOW COLUMNS IN tbl LIKE '%name%'
10418}
10419
10420#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10421#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10422#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10423/// Parent object types usable with `SHOW ... IN <parent>` clauses.
10424pub enum ShowStatementInParentType {
10425    /// ACCOUNT parent type for SHOW statements.
10426    Account,
10427    /// DATABASE parent type for SHOW statements.
10428    Database,
10429    /// SCHEMA parent type for SHOW statements.
10430    Schema,
10431    /// TABLE parent type for SHOW statements.
10432    Table,
10433    /// VIEW parent type for SHOW statements.
10434    View,
10435}
10436
10437impl fmt::Display for ShowStatementInParentType {
10438    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10439        match self {
10440            ShowStatementInParentType::Account => write!(f, "ACCOUNT"),
10441            ShowStatementInParentType::Database => write!(f, "DATABASE"),
10442            ShowStatementInParentType::Schema => write!(f, "SCHEMA"),
10443            ShowStatementInParentType::Table => write!(f, "TABLE"),
10444            ShowStatementInParentType::View => write!(f, "VIEW"),
10445        }
10446    }
10447}
10448
10449#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10450#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10451#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10452/// Represents a `SHOW ... IN` clause with optional parent qualifier and name.
10453pub struct ShowStatementIn {
10454    /// The clause that specifies what to show (e.g. COLUMNS, TABLES).
10455    pub clause: ShowStatementInClause,
10456    /// Optional parent type qualifier (ACCOUNT/DATABASE/...).
10457    pub parent_type: Option<ShowStatementInParentType>,
10458    /// Optional parent object name for the SHOW clause.
10459    #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
10460    pub parent_name: Option<ObjectName>,
10461}
10462
10463impl fmt::Display for ShowStatementIn {
10464    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10465        write!(f, "{}", self.clause)?;
10466        if let Some(parent_type) = &self.parent_type {
10467            write!(f, " {parent_type}")?;
10468        }
10469        if let Some(parent_name) = &self.parent_name {
10470            write!(f, " {parent_name}")?;
10471        }
10472        Ok(())
10473    }
10474}
10475
10476/// A Show Charset statement
10477#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10478#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10479#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10480pub struct ShowCharset {
10481    /// The statement can be written as `SHOW CHARSET` or `SHOW CHARACTER SET`
10482    /// true means CHARSET was used and false means CHARACTER SET was used
10483    pub is_shorthand: bool,
10484    /// Optional `LIKE`/`WHERE`-style filter for the statement.
10485    pub filter: Option<ShowStatementFilter>,
10486}
10487
10488impl fmt::Display for ShowCharset {
10489    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10490        write!(f, "SHOW")?;
10491        if self.is_shorthand {
10492            write!(f, " CHARSET")?;
10493        } else {
10494            write!(f, " CHARACTER SET")?;
10495        }
10496        if let Some(filter) = &self.filter {
10497            write!(f, " {filter}")?;
10498        }
10499        Ok(())
10500    }
10501}
10502
10503#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10504#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10505#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10506/// Options for a `SHOW OBJECTS` statement.
10507pub struct ShowObjects {
10508    /// Whether to show terse output.
10509    pub terse: bool,
10510    /// Additional options controlling the SHOW output.
10511    pub show_options: ShowStatementOptions,
10512}
10513
10514/// MSSQL's json null clause
10515///
10516/// ```plaintext
10517/// <json_null_clause> ::=
10518///       NULL ON NULL
10519///     | ABSENT ON NULL
10520/// ```
10521///
10522/// <https://learn.microsoft.com/en-us/sql/t-sql/functions/json-object-transact-sql?view=sql-server-ver16#json_null_clause>
10523#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10524#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10525#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10526pub enum JsonNullClause {
10527    /// `NULL ON NULL` behavior for JSON functions.
10528    NullOnNull,
10529    /// `ABSENT ON NULL` behavior for JSON functions.
10530    AbsentOnNull,
10531}
10532
10533impl Display for JsonNullClause {
10534    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10535        match self {
10536            JsonNullClause::NullOnNull => write!(f, "NULL ON NULL"),
10537            JsonNullClause::AbsentOnNull => write!(f, "ABSENT ON NULL"),
10538        }
10539    }
10540}
10541
10542/// PostgreSQL JSON function RETURNING clause
10543///
10544/// Example:
10545/// ```sql
10546/// JSON_OBJECT('a': 1 RETURNING jsonb)
10547/// ```
10548#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10549#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10550#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10551pub struct JsonReturningClause {
10552    /// The data type to return from the JSON function (e.g. JSON/JSONB).
10553    pub data_type: DataType,
10554}
10555
10556impl Display for JsonReturningClause {
10557    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10558        write!(f, "RETURNING {}", self.data_type)
10559    }
10560}
10561
10562/// rename object definition
10563#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10564#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10565#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10566pub struct RenameTable {
10567    /// The current name of the object to rename.
10568    pub old_name: ObjectName,
10569    /// The new name for the object.
10570    pub new_name: ObjectName,
10571}
10572
10573impl fmt::Display for RenameTable {
10574    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10575        write!(f, "{} TO {}", self.old_name, self.new_name)?;
10576        Ok(())
10577    }
10578}
10579
10580/// Represents the referenced table in an `INSERT INTO` statement
10581#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10582#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10583#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10584pub enum TableObject {
10585    /// Table specified by name.
10586    /// Example:
10587    /// ```sql
10588    /// INSERT INTO my_table
10589    /// ```
10590    TableName(#[cfg_attr(feature = "visitor", visit(with = "visit_relation"))] ObjectName),
10591
10592    /// Table specified as a function.
10593    /// Example:
10594    /// ```sql
10595    /// INSERT INTO TABLE FUNCTION remote('localhost', default.simple_table)
10596    /// ```
10597    /// [Clickhouse](https://clickhouse.com/docs/en/sql-reference/table-functions)
10598    TableFunction(Function),
10599}
10600
10601impl fmt::Display for TableObject {
10602    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10603        match self {
10604            Self::TableName(table_name) => write!(f, "{table_name}"),
10605            Self::TableFunction(func) => write!(f, "FUNCTION {func}"),
10606        }
10607    }
10608}
10609
10610/// Represents a SET SESSION AUTHORIZATION statement
10611#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10612#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10613#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10614pub struct SetSessionAuthorizationParam {
10615    /// The scope for the `SET SESSION AUTHORIZATION` (e.g., GLOBAL/SESSION).
10616    pub scope: ContextModifier,
10617    /// The specific authorization parameter kind.
10618    pub kind: SetSessionAuthorizationParamKind,
10619}
10620
10621impl fmt::Display for SetSessionAuthorizationParam {
10622    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10623        write!(f, "{}", self.kind)
10624    }
10625}
10626
10627/// Represents the parameter kind for SET SESSION AUTHORIZATION
10628#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10629#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10630#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10631pub enum SetSessionAuthorizationParamKind {
10632    /// Default authorization
10633    Default,
10634
10635    /// User name
10636    User(Ident),
10637}
10638
10639impl fmt::Display for SetSessionAuthorizationParamKind {
10640    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10641        match self {
10642            SetSessionAuthorizationParamKind::Default => write!(f, "DEFAULT"),
10643            SetSessionAuthorizationParamKind::User(name) => write!(f, "{}", name),
10644        }
10645    }
10646}
10647
10648#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10649#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10650#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10651/// Kind of session parameter being set by `SET SESSION`.
10652pub enum SetSessionParamKind {
10653    /// Generic session parameter (name/value pair).
10654    Generic(SetSessionParamGeneric),
10655    /// Identity insert related parameter.
10656    IdentityInsert(SetSessionParamIdentityInsert),
10657    /// Offsets-related parameter.
10658    Offsets(SetSessionParamOffsets),
10659    /// Statistics-related parameter.
10660    Statistics(SetSessionParamStatistics),
10661}
10662
10663impl fmt::Display for SetSessionParamKind {
10664    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10665        match self {
10666            SetSessionParamKind::Generic(x) => write!(f, "{x}"),
10667            SetSessionParamKind::IdentityInsert(x) => write!(f, "{x}"),
10668            SetSessionParamKind::Offsets(x) => write!(f, "{x}"),
10669            SetSessionParamKind::Statistics(x) => write!(f, "{x}"),
10670        }
10671    }
10672}
10673
10674#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10675#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10676#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10677/// Generic `SET SESSION` parameter represented as name(s) and value.
10678pub struct SetSessionParamGeneric {
10679    /// Names of the session parameters being set.
10680    pub names: Vec<String>,
10681    /// The value to assign to the parameter(s).
10682    pub value: String,
10683}
10684
10685impl fmt::Display for SetSessionParamGeneric {
10686    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10687        write!(f, "{} {}", display_comma_separated(&self.names), self.value)
10688    }
10689}
10690
10691#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10692#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10693#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10694/// `IDENTITY_INSERT` session parameter for a specific object.
10695pub struct SetSessionParamIdentityInsert {
10696    /// Object name targeted by `IDENTITY_INSERT`.
10697    pub obj: ObjectName,
10698    /// Value (ON/OFF) for the identity insert setting.
10699    pub value: SessionParamValue,
10700}
10701
10702impl fmt::Display for SetSessionParamIdentityInsert {
10703    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10704        write!(f, "IDENTITY_INSERT {} {}", self.obj, self.value)
10705    }
10706}
10707
10708#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10709#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10710#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10711/// Offsets-related session parameter with keywords and a value.
10712pub struct SetSessionParamOffsets {
10713    /// Keywords specifying which offsets to modify.
10714    pub keywords: Vec<String>,
10715    /// Value (ON/OFF) for the offsets setting.
10716    pub value: SessionParamValue,
10717}
10718
10719impl fmt::Display for SetSessionParamOffsets {
10720    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10721        write!(
10722            f,
10723            "OFFSETS {} {}",
10724            display_comma_separated(&self.keywords),
10725            self.value
10726        )
10727    }
10728}
10729
10730#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10731#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10732#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10733/// Statistics-related session parameter specifying topic and value.
10734pub struct SetSessionParamStatistics {
10735    /// Statistics topic to set (IO/PROFILE/TIME/XML).
10736    pub topic: SessionParamStatsTopic,
10737    /// Value (ON/OFF) for the statistics topic.
10738    pub value: SessionParamValue,
10739}
10740
10741impl fmt::Display for SetSessionParamStatistics {
10742    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10743        write!(f, "STATISTICS {} {}", self.topic, self.value)
10744    }
10745}
10746
10747#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10748#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10749#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10750/// Topics available for session statistics configuration.
10751pub enum SessionParamStatsTopic {
10752    /// Input/output statistics.
10753    IO,
10754    /// Profile statistics.
10755    Profile,
10756    /// Time statistics.
10757    Time,
10758    /// XML-related statistics.
10759    Xml,
10760}
10761
10762impl fmt::Display for SessionParamStatsTopic {
10763    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10764        match self {
10765            SessionParamStatsTopic::IO => write!(f, "IO"),
10766            SessionParamStatsTopic::Profile => write!(f, "PROFILE"),
10767            SessionParamStatsTopic::Time => write!(f, "TIME"),
10768            SessionParamStatsTopic::Xml => write!(f, "XML"),
10769        }
10770    }
10771}
10772
10773#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10774#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10775#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10776/// Value for a session boolean-like parameter (ON/OFF).
10777pub enum SessionParamValue {
10778    /// Session parameter enabled.
10779    On,
10780    /// Session parameter disabled.
10781    Off,
10782}
10783
10784impl fmt::Display for SessionParamValue {
10785    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10786        match self {
10787            SessionParamValue::On => write!(f, "ON"),
10788            SessionParamValue::Off => write!(f, "OFF"),
10789        }
10790    }
10791}
10792
10793/// Snowflake StorageSerializationPolicy for Iceberg Tables
10794/// ```sql
10795/// [ STORAGE_SERIALIZATION_POLICY = { COMPATIBLE | OPTIMIZED } ]
10796/// ```
10797///
10798/// <https://docs.snowflake.com/en/sql-reference/sql/create-iceberg-table>
10799#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10800#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10801#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10802pub enum StorageSerializationPolicy {
10803    /// Use compatible serialization mode.
10804    Compatible,
10805    /// Use optimized serialization mode.
10806    Optimized,
10807}
10808
10809impl Display for StorageSerializationPolicy {
10810    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10811        match self {
10812            StorageSerializationPolicy::Compatible => write!(f, "COMPATIBLE"),
10813            StorageSerializationPolicy::Optimized => write!(f, "OPTIMIZED"),
10814        }
10815    }
10816}
10817
10818/// Snowflake CatalogSyncNamespaceMode
10819/// ```sql
10820/// [ CATALOG_SYNC_NAMESPACE_MODE = { NEST | FLATTEN } ]
10821/// ```
10822///
10823/// <https://docs.snowflake.com/en/sql-reference/sql/create-database>
10824#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10825#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10826#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10827pub enum CatalogSyncNamespaceMode {
10828    /// Nest namespaces when syncing catalog.
10829    Nest,
10830    /// Flatten namespaces when syncing catalog.
10831    Flatten,
10832}
10833
10834impl Display for CatalogSyncNamespaceMode {
10835    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10836        match self {
10837            CatalogSyncNamespaceMode::Nest => write!(f, "NEST"),
10838            CatalogSyncNamespaceMode::Flatten => write!(f, "FLATTEN"),
10839        }
10840    }
10841}
10842
10843/// Variants of the Snowflake `COPY INTO` statement
10844#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10845#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10846#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10847pub enum CopyIntoSnowflakeKind {
10848    /// Loads data from files to a table
10849    /// See: <https://docs.snowflake.com/en/sql-reference/sql/copy-into-table>
10850    Table,
10851    /// Unloads data from a table or query to external files
10852    /// See: <https://docs.snowflake.com/en/sql-reference/sql/copy-into-location>
10853    Location,
10854}
10855
10856#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10857#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10858#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10859/// `PRINT` statement for producing debug/output messages.
10860pub struct PrintStatement {
10861    /// The expression producing the message to print.
10862    pub message: Box<Expr>,
10863}
10864
10865impl fmt::Display for PrintStatement {
10866    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10867        write!(f, "PRINT {}", self.message)
10868    }
10869}
10870
10871/// Represents a `Return` statement.
10872///
10873/// [MsSql triggers](https://learn.microsoft.com/en-us/sql/t-sql/statements/create-trigger-transact-sql)
10874/// [MsSql functions](https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql)
10875#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10876#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10877#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10878pub struct ReturnStatement {
10879    /// Optional return value expression.
10880    pub value: Option<ReturnStatementValue>,
10881}
10882
10883impl fmt::Display for ReturnStatement {
10884    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10885        match &self.value {
10886            Some(ReturnStatementValue::Expr(expr)) => write!(f, "RETURN {expr}"),
10887            None => write!(f, "RETURN"),
10888        }
10889    }
10890}
10891
10892/// Variants of a `RETURN` statement
10893#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10894#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10895#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10896pub enum ReturnStatementValue {
10897    /// Return an expression from a function or trigger.
10898    Expr(Expr),
10899}
10900
10901/// Represents an `OPEN` statement.
10902#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10903#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10904#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10905pub struct OpenStatement {
10906    /// Cursor name
10907    pub cursor_name: Ident,
10908}
10909
10910impl fmt::Display for OpenStatement {
10911    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10912        write!(f, "OPEN {}", self.cursor_name)
10913    }
10914}
10915
10916/// Specifies Include / Exclude NULL within UNPIVOT command.
10917/// For example
10918/// `UNPIVOT (column1 FOR new_column IN (col3, col4, col5, col6))`
10919#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10920#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10921#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10922pub enum NullInclusion {
10923    /// Include NULL values in the UNPIVOT output.
10924    IncludeNulls,
10925    /// Exclude NULL values from the UNPIVOT output.
10926    ExcludeNulls,
10927}
10928
10929impl fmt::Display for NullInclusion {
10930    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10931        match self {
10932            NullInclusion::IncludeNulls => write!(f, "INCLUDE NULLS"),
10933            NullInclusion::ExcludeNulls => write!(f, "EXCLUDE NULLS"),
10934        }
10935    }
10936}
10937
10938/// Checks membership of a value in a JSON array
10939///
10940/// Syntax:
10941/// ```sql
10942/// <value> MEMBER OF(<array>)
10943/// ```
10944/// [MySQL](https://dev.mysql.com/doc/refman/8.4/en/json-search-functions.html#operator_member-of)
10945#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10946#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10947#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10948pub struct MemberOf {
10949    /// The value to check for membership.
10950    pub value: Box<Expr>,
10951    /// The JSON array expression to check against.
10952    pub array: Box<Expr>,
10953}
10954
10955impl fmt::Display for MemberOf {
10956    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10957        write!(f, "{} MEMBER OF({})", self.value, self.array)
10958    }
10959}
10960
10961#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10962#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10963#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10964/// Represents an `EXPORT DATA` statement.
10965pub struct ExportData {
10966    /// Options for the export operation.
10967    pub options: Vec<SqlOption>,
10968    /// The query producing the data to export.
10969    pub query: Box<Query>,
10970    /// Optional named connection to use for export.
10971    pub connection: Option<ObjectName>,
10972}
10973
10974impl fmt::Display for ExportData {
10975    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10976        if let Some(connection) = &self.connection {
10977            write!(
10978                f,
10979                "EXPORT DATA WITH CONNECTION {connection} OPTIONS({}) AS {}",
10980                display_comma_separated(&self.options),
10981                self.query
10982            )
10983        } else {
10984            write!(
10985                f,
10986                "EXPORT DATA OPTIONS({}) AS {}",
10987                display_comma_separated(&self.options),
10988                self.query
10989            )
10990        }
10991    }
10992}
10993/// Creates a user
10994///
10995/// Syntax:
10996/// ```sql
10997/// CREATE [OR REPLACE] USER [IF NOT EXISTS] <name> [OPTIONS]
10998/// ```
10999///
11000/// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-user)
11001#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11002#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11003#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11004pub struct CreateUser {
11005    /// Replace existing user if present.
11006    pub or_replace: bool,
11007    /// Only create the user if it does not already exist.
11008    pub if_not_exists: bool,
11009    /// The name of the user to create.
11010    pub name: Ident,
11011    /// Key/value options for user creation.
11012    pub options: KeyValueOptions,
11013    /// Whether tags are specified using `WITH TAG`.
11014    pub with_tags: bool,
11015    /// Tags for the user.
11016    pub tags: KeyValueOptions,
11017}
11018
11019impl fmt::Display for CreateUser {
11020    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11021        write!(f, "CREATE")?;
11022        if self.or_replace {
11023            write!(f, " OR REPLACE")?;
11024        }
11025        write!(f, " USER")?;
11026        if self.if_not_exists {
11027            write!(f, " IF NOT EXISTS")?;
11028        }
11029        write!(f, " {}", self.name)?;
11030        if !self.options.options.is_empty() {
11031            write!(f, " {}", self.options)?;
11032        }
11033        if !self.tags.options.is_empty() {
11034            if self.with_tags {
11035                write!(f, " WITH")?;
11036            }
11037            write!(f, " TAG ({})", self.tags)?;
11038        }
11039        Ok(())
11040    }
11041}
11042
11043/// Modifies the properties of a user
11044///
11045/// [Snowflake Syntax:](https://docs.snowflake.com/en/sql-reference/sql/alter-user)
11046/// ```sql
11047/// ALTER USER [ IF EXISTS ] [ <name> ] [ OPTIONS ]
11048/// ```
11049///
11050/// [PostgreSQL Syntax:](https://www.postgresql.org/docs/current/sql-alteruser.html)
11051/// ```sql
11052/// ALTER USER <role_specification> [ WITH ] option [ ... ]
11053/// ```
11054#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11055#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11056#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11057pub struct AlterUser {
11058    /// Whether to only alter the user if it exists.
11059    pub if_exists: bool,
11060    /// The name of the user to alter.
11061    pub name: Ident,
11062    /// Optional new name for the user (Snowflake-specific).
11063    /// See: <https://docs.snowflake.com/en/sql-reference/sql/alter-user#syntax>
11064    pub rename_to: Option<Ident>,
11065    /// Reset the user's password.
11066    pub reset_password: bool,
11067    /// Abort all running queries for the user.
11068    pub abort_all_queries: bool,
11069    /// Optionally add a delegated role authorization.
11070    pub add_role_delegation: Option<AlterUserAddRoleDelegation>,
11071    /// Optionally remove a delegated role authorization.
11072    pub remove_role_delegation: Option<AlterUserRemoveRoleDelegation>,
11073    /// Enroll the user in MFA.
11074    pub enroll_mfa: bool,
11075    /// Set the default MFA method for the user.
11076    pub set_default_mfa_method: Option<MfaMethodKind>,
11077    /// Remove the user's default MFA method.
11078    pub remove_mfa_method: Option<MfaMethodKind>,
11079    /// Modify an MFA method for the user.
11080    pub modify_mfa_method: Option<AlterUserModifyMfaMethod>,
11081    /// Add an MFA OTP method with optional count.
11082    pub add_mfa_method_otp: Option<AlterUserAddMfaMethodOtp>,
11083    /// Set a user policy.
11084    pub set_policy: Option<AlterUserSetPolicy>,
11085    /// Unset a user policy.
11086    pub unset_policy: Option<UserPolicyKind>,
11087    /// Key/value tag options to set on the user.
11088    pub set_tag: KeyValueOptions,
11089    /// Tags to unset on the user.
11090    pub unset_tag: Vec<String>,
11091    /// Key/value properties to set on the user.
11092    pub set_props: KeyValueOptions,
11093    /// Properties to unset on the user.
11094    pub unset_props: Vec<String>,
11095    /// The following options are PostgreSQL-specific: <https://www.postgresql.org/docs/current/sql-alteruser.html>
11096    pub password: Option<AlterUserPassword>,
11097}
11098
11099/// ```sql
11100/// ALTER USER [ IF EXISTS ] [ <name> ] ADD DELEGATED AUTHORIZATION OF ROLE <role_name> TO SECURITY INTEGRATION <integration_name>
11101/// ```
11102#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11103#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11104#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11105pub struct AlterUserAddRoleDelegation {
11106    /// Role name to delegate.
11107    pub role: Ident,
11108    /// Security integration receiving the delegation.
11109    pub integration: Ident,
11110}
11111
11112/// ```sql
11113/// ALTER USER [ IF EXISTS ] [ <name> ] REMOVE DELEGATED { AUTHORIZATION OF ROLE <role_name> | AUTHORIZATIONS } FROM SECURITY INTEGRATION <integration_name>
11114/// ```
11115#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11116#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11117#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11118pub struct AlterUserRemoveRoleDelegation {
11119    /// Optional role name to remove delegation for.
11120    pub role: Option<Ident>,
11121    /// Security integration from which to remove delegation.
11122    pub integration: Ident,
11123}
11124
11125/// ```sql
11126/// ADD MFA METHOD OTP [ COUNT = number ]
11127/// ```
11128#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11129#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11130#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11131pub struct AlterUserAddMfaMethodOtp {
11132    /// Optional OTP count parameter.
11133    pub count: Option<Value>,
11134}
11135
11136/// ```sql
11137/// ALTER USER [ IF EXISTS ] [ <name> ] MODIFY MFA METHOD <mfa_method> SET COMMENT = '<string>'
11138/// ```
11139#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11140#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11141#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11142pub struct AlterUserModifyMfaMethod {
11143    /// The MFA method being modified.
11144    pub method: MfaMethodKind,
11145    /// The new comment for the MFA method.
11146    pub comment: String,
11147}
11148
11149/// Types of MFA methods
11150#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11151#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11152#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11153pub enum MfaMethodKind {
11154    /// PassKey (hardware or platform passkey) MFA method.
11155    PassKey,
11156    /// Time-based One-Time Password (TOTP) MFA method.
11157    Totp,
11158    /// Duo Security MFA method.
11159    Duo,
11160}
11161
11162impl fmt::Display for MfaMethodKind {
11163    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11164        match self {
11165            MfaMethodKind::PassKey => write!(f, "PASSKEY"),
11166            MfaMethodKind::Totp => write!(f, "TOTP"),
11167            MfaMethodKind::Duo => write!(f, "DUO"),
11168        }
11169    }
11170}
11171
11172/// ```sql
11173/// ALTER USER [ IF EXISTS ] [ <name> ] SET { AUTHENTICATION | PASSWORD | SESSION } POLICY <policy_name>
11174/// ```
11175#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11176#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11177#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11178pub struct AlterUserSetPolicy {
11179    /// The kind of user policy being set (authentication/password/session).
11180    pub policy_kind: UserPolicyKind,
11181    /// The identifier of the policy to apply.
11182    pub policy: Ident,
11183}
11184
11185/// Types of user-based policies
11186#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11187#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11188#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11189pub enum UserPolicyKind {
11190    /// Authentication policy.
11191    Authentication,
11192    /// Password policy.
11193    Password,
11194    /// Session policy.
11195    Session,
11196}
11197
11198impl fmt::Display for UserPolicyKind {
11199    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11200        match self {
11201            UserPolicyKind::Authentication => write!(f, "AUTHENTICATION"),
11202            UserPolicyKind::Password => write!(f, "PASSWORD"),
11203            UserPolicyKind::Session => write!(f, "SESSION"),
11204        }
11205    }
11206}
11207
11208impl fmt::Display for AlterUser {
11209    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11210        write!(f, "ALTER")?;
11211        write!(f, " USER")?;
11212        if self.if_exists {
11213            write!(f, " IF EXISTS")?;
11214        }
11215        write!(f, " {}", self.name)?;
11216        if let Some(new_name) = &self.rename_to {
11217            write!(f, " RENAME TO {new_name}")?;
11218        }
11219        if self.reset_password {
11220            write!(f, " RESET PASSWORD")?;
11221        }
11222        if self.abort_all_queries {
11223            write!(f, " ABORT ALL QUERIES")?;
11224        }
11225        if let Some(role_delegation) = &self.add_role_delegation {
11226            let role = &role_delegation.role;
11227            let integration = &role_delegation.integration;
11228            write!(
11229                f,
11230                " ADD DELEGATED AUTHORIZATION OF ROLE {role} TO SECURITY INTEGRATION {integration}"
11231            )?;
11232        }
11233        if let Some(role_delegation) = &self.remove_role_delegation {
11234            write!(f, " REMOVE DELEGATED")?;
11235            match &role_delegation.role {
11236                Some(role) => write!(f, " AUTHORIZATION OF ROLE {role}")?,
11237                None => write!(f, " AUTHORIZATIONS")?,
11238            }
11239            let integration = &role_delegation.integration;
11240            write!(f, " FROM SECURITY INTEGRATION {integration}")?;
11241        }
11242        if self.enroll_mfa {
11243            write!(f, " ENROLL MFA")?;
11244        }
11245        if let Some(method) = &self.set_default_mfa_method {
11246            write!(f, " SET DEFAULT_MFA_METHOD {method}")?
11247        }
11248        if let Some(method) = &self.remove_mfa_method {
11249            write!(f, " REMOVE MFA METHOD {method}")?;
11250        }
11251        if let Some(modify) = &self.modify_mfa_method {
11252            let method = &modify.method;
11253            let comment = &modify.comment;
11254            write!(
11255                f,
11256                " MODIFY MFA METHOD {method} SET COMMENT '{}'",
11257                value::escape_single_quote_string(comment)
11258            )?;
11259        }
11260        if let Some(add_mfa_method_otp) = &self.add_mfa_method_otp {
11261            write!(f, " ADD MFA METHOD OTP")?;
11262            if let Some(count) = &add_mfa_method_otp.count {
11263                write!(f, " COUNT = {count}")?;
11264            }
11265        }
11266        if let Some(policy) = &self.set_policy {
11267            let policy_kind = &policy.policy_kind;
11268            let name = &policy.policy;
11269            write!(f, " SET {policy_kind} POLICY {name}")?;
11270        }
11271        if let Some(policy_kind) = &self.unset_policy {
11272            write!(f, " UNSET {policy_kind} POLICY")?;
11273        }
11274        if !self.set_tag.options.is_empty() {
11275            write!(f, " SET TAG {}", self.set_tag)?;
11276        }
11277        if !self.unset_tag.is_empty() {
11278            write!(f, " UNSET TAG {}", display_comma_separated(&self.unset_tag))?;
11279        }
11280        let has_props = !self.set_props.options.is_empty();
11281        if has_props {
11282            write!(f, " SET")?;
11283            write!(f, " {}", &self.set_props)?;
11284        }
11285        if !self.unset_props.is_empty() {
11286            write!(f, " UNSET {}", display_comma_separated(&self.unset_props))?;
11287        }
11288        if let Some(password) = &self.password {
11289            write!(f, " {}", password)?;
11290        }
11291        Ok(())
11292    }
11293}
11294
11295/// ```sql
11296/// ALTER USER <role_specification> [ WITH ] PASSWORD { 'password' | NULL }``
11297/// ```
11298#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11299#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11300#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11301pub struct AlterUserPassword {
11302    /// Whether the password is encrypted.
11303    pub encrypted: bool,
11304    /// The password string, or `None` for `NULL`.
11305    pub password: Option<String>,
11306}
11307
11308impl Display for AlterUserPassword {
11309    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11310        if self.encrypted {
11311            write!(f, "ENCRYPTED ")?;
11312        }
11313        write!(f, "PASSWORD")?;
11314        match &self.password {
11315            None => write!(f, " NULL")?,
11316            Some(password) => write!(f, " '{}'", value::escape_single_quote_string(password))?,
11317        }
11318        Ok(())
11319    }
11320}
11321
11322/// Specifies how to create a new table based on an existing table's schema.
11323/// '''sql
11324/// CREATE TABLE new LIKE old ...
11325/// '''
11326#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11327#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11328#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11329pub enum CreateTableLikeKind {
11330    /// '''sql
11331    /// CREATE TABLE new (LIKE old ...)
11332    /// '''
11333    /// [Redshift](https://docs.aws.amazon.com/redshift/latest/dg/r_CREATE_TABLE_NEW.html)
11334    Parenthesized(CreateTableLike),
11335    /// '''sql
11336    /// CREATE TABLE new LIKE old ...
11337    /// '''
11338    /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-table#label-create-table-like)
11339    /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_table_like)
11340    Plain(CreateTableLike),
11341}
11342
11343#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11344#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11345#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11346/// Controls whether defaults are included when creating a table FROM/LILE another.
11347pub enum CreateTableLikeDefaults {
11348    /// Include default values from the source table.
11349    Including,
11350    /// Exclude default values from the source table.
11351    Excluding,
11352}
11353
11354impl fmt::Display for CreateTableLikeDefaults {
11355    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11356        match self {
11357            CreateTableLikeDefaults::Including => write!(f, "INCLUDING DEFAULTS"),
11358            CreateTableLikeDefaults::Excluding => write!(f, "EXCLUDING DEFAULTS"),
11359        }
11360    }
11361}
11362
11363#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11364#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11365#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11366/// Represents the `LIKE` clause of a `CREATE TABLE` statement.
11367pub struct CreateTableLike {
11368    /// The source table name to copy the schema from.
11369    pub name: ObjectName,
11370    /// Optional behavior controlling whether defaults are copied.
11371    pub defaults: Option<CreateTableLikeDefaults>,
11372}
11373
11374impl fmt::Display for CreateTableLike {
11375    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11376        write!(f, "LIKE {}", self.name)?;
11377        if let Some(defaults) = &self.defaults {
11378            write!(f, " {defaults}")?;
11379        }
11380        Ok(())
11381    }
11382}
11383
11384/// Specifies the refresh mode for the dynamic table.
11385///
11386/// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-dynamic-table)
11387#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11388#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11389#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11390pub enum RefreshModeKind {
11391    /// Automatic refresh mode (`AUTO`).
11392    Auto,
11393    /// Full refresh mode (`FULL`).
11394    Full,
11395    /// Incremental refresh mode (`INCREMENTAL`).
11396    Incremental,
11397}
11398
11399impl fmt::Display for RefreshModeKind {
11400    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11401        match self {
11402            RefreshModeKind::Auto => write!(f, "AUTO"),
11403            RefreshModeKind::Full => write!(f, "FULL"),
11404            RefreshModeKind::Incremental => write!(f, "INCREMENTAL"),
11405        }
11406    }
11407}
11408
11409/// Specifies the behavior of the initial refresh of the dynamic table.
11410///
11411/// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-dynamic-table)
11412#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11413#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11414#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11415pub enum InitializeKind {
11416    /// Initialize on creation (`ON CREATE`).
11417    OnCreate,
11418    /// Initialize on schedule (`ON SCHEDULE`).
11419    OnSchedule,
11420}
11421
11422impl fmt::Display for InitializeKind {
11423    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11424        match self {
11425            InitializeKind::OnCreate => write!(f, "ON_CREATE"),
11426            InitializeKind::OnSchedule => write!(f, "ON_SCHEDULE"),
11427        }
11428    }
11429}
11430
11431/// Re-sorts rows and reclaims space in either a specified table or all tables in the current database
11432///
11433/// '''sql
11434/// VACUUM [ FULL | SORT ONLY | DELETE ONLY | REINDEX | RECLUSTER ] [ \[ table_name \] [ TO threshold PERCENT ] \[ BOOST \] ]
11435/// '''
11436/// [Redshift](https://docs.aws.amazon.com/redshift/latest/dg/r_VACUUM_command.html)
11437#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11438#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11439#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11440pub struct VacuumStatement {
11441    /// Whether `FULL` was specified.
11442    pub full: bool,
11443    /// Whether `SORT ONLY` was specified.
11444    pub sort_only: bool,
11445    /// Whether `DELETE ONLY` was specified.
11446    pub delete_only: bool,
11447    /// Whether `REINDEX` was specified.
11448    pub reindex: bool,
11449    /// Whether `RECLUSTER` was specified.
11450    pub recluster: bool,
11451    /// Optional table to run `VACUUM` on.
11452    pub table_name: Option<ObjectName>,
11453    /// Optional threshold value (percent) for `TO threshold PERCENT`.
11454    pub threshold: Option<Value>,
11455    /// Whether `BOOST` was specified.
11456    pub boost: bool,
11457}
11458
11459impl fmt::Display for VacuumStatement {
11460    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11461        write!(
11462            f,
11463            "VACUUM{}{}{}{}{}",
11464            if self.full { " FULL" } else { "" },
11465            if self.sort_only { " SORT ONLY" } else { "" },
11466            if self.delete_only { " DELETE ONLY" } else { "" },
11467            if self.reindex { " REINDEX" } else { "" },
11468            if self.recluster { " RECLUSTER" } else { "" },
11469        )?;
11470        if let Some(table_name) = &self.table_name {
11471            write!(f, " {table_name}")?;
11472        }
11473        if let Some(threshold) = &self.threshold {
11474            write!(f, " TO {threshold} PERCENT")?;
11475        }
11476        if self.boost {
11477            write!(f, " BOOST")?;
11478        }
11479        Ok(())
11480    }
11481}
11482
11483/// Variants of the RESET statement
11484#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11485#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11486#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11487pub enum Reset {
11488    /// Resets all session parameters to their default values.
11489    ALL,
11490
11491    /// Resets a specific session parameter to its default value.
11492    ConfigurationParameter(ObjectName),
11493}
11494
11495/// Resets a session parameter to its default value.
11496/// ```sql
11497/// RESET { ALL | <configuration_parameter> }
11498/// ```
11499#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11500#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11501#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11502pub struct ResetStatement {
11503    /// The reset action to perform (either `ALL` or a specific configuration parameter).
11504    pub reset: Reset,
11505}
11506
11507/// Query optimizer hints are optionally supported comments after the
11508/// `SELECT`, `INSERT`, `UPDATE`, `REPLACE`, `MERGE`, and `DELETE` keywords in
11509/// the corresponding statements.
11510///
11511/// See [Select::optimizer_hint]
11512#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11513#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11514#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11515pub struct OptimizerHint {
11516    /// the raw test of the optimizer hint without its markers
11517    pub text: String,
11518    /// the style of the comment which `text` was extracted from,
11519    /// e.g. `/*+...*/` or `--+...`
11520    ///
11521    /// Not all dialects support all styles, though.
11522    pub style: OptimizerHintStyle,
11523}
11524
11525/// The commentary style of an [optimizer hint](OptimizerHint)
11526#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11527#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11528#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11529pub enum OptimizerHintStyle {
11530    /// A hint corresponding to a single line comment,
11531    /// e.g. `--+ LEADING(v.e v.d t)`
11532    SingleLine {
11533        /// the comment prefix, e.g. `--`
11534        prefix: String,
11535    },
11536    /// A hint corresponding to a multi line comment,
11537    /// e.g. `/*+ LEADING(v.e v.d t) */`
11538    MultiLine,
11539}
11540
11541impl fmt::Display for OptimizerHint {
11542    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
11543        match &self.style {
11544            OptimizerHintStyle::SingleLine { prefix } => {
11545                f.write_str(prefix)?;
11546                f.write_str("+")?;
11547                f.write_str(&self.text)
11548            }
11549            OptimizerHintStyle::MultiLine => {
11550                f.write_str("/*+")?;
11551                f.write_str(&self.text)?;
11552                f.write_str("*/")
11553            }
11554        }
11555    }
11556}
11557
11558impl fmt::Display for ResetStatement {
11559    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11560        match &self.reset {
11561            Reset::ALL => write!(f, "RESET ALL"),
11562            Reset::ConfigurationParameter(param) => write!(f, "RESET {}", param),
11563        }
11564    }
11565}
11566
11567impl From<Set> for Statement {
11568    fn from(s: Set) -> Self {
11569        Self::Set(s)
11570    }
11571}
11572
11573impl From<Query> for Statement {
11574    fn from(q: Query) -> Self {
11575        Box::new(q).into()
11576    }
11577}
11578
11579impl From<Box<Query>> for Statement {
11580    fn from(q: Box<Query>) -> Self {
11581        Self::Query(q)
11582    }
11583}
11584
11585impl From<Insert> for Statement {
11586    fn from(i: Insert) -> Self {
11587        Self::Insert(i)
11588    }
11589}
11590
11591impl From<Update> for Statement {
11592    fn from(u: Update) -> Self {
11593        Self::Update(u)
11594    }
11595}
11596
11597impl From<CreateView> for Statement {
11598    fn from(cv: CreateView) -> Self {
11599        Self::CreateView(cv)
11600    }
11601}
11602
11603impl From<CreateRole> for Statement {
11604    fn from(cr: CreateRole) -> Self {
11605        Self::CreateRole(cr)
11606    }
11607}
11608
11609impl From<AlterTable> for Statement {
11610    fn from(at: AlterTable) -> Self {
11611        Self::AlterTable(at)
11612    }
11613}
11614
11615impl From<DropFunction> for Statement {
11616    fn from(df: DropFunction) -> Self {
11617        Self::DropFunction(df)
11618    }
11619}
11620
11621impl From<CreateExtension> for Statement {
11622    fn from(ce: CreateExtension) -> Self {
11623        Self::CreateExtension(ce)
11624    }
11625}
11626
11627impl From<DropExtension> for Statement {
11628    fn from(de: DropExtension) -> Self {
11629        Self::DropExtension(de)
11630    }
11631}
11632
11633impl From<CaseStatement> for Statement {
11634    fn from(c: CaseStatement) -> Self {
11635        Self::Case(c)
11636    }
11637}
11638
11639impl From<IfStatement> for Statement {
11640    fn from(i: IfStatement) -> Self {
11641        Self::If(i)
11642    }
11643}
11644
11645impl From<WhileStatement> for Statement {
11646    fn from(w: WhileStatement) -> Self {
11647        Self::While(w)
11648    }
11649}
11650
11651impl From<RaiseStatement> for Statement {
11652    fn from(r: RaiseStatement) -> Self {
11653        Self::Raise(r)
11654    }
11655}
11656
11657impl From<Function> for Statement {
11658    fn from(f: Function) -> Self {
11659        Self::Call(f)
11660    }
11661}
11662
11663impl From<OpenStatement> for Statement {
11664    fn from(o: OpenStatement) -> Self {
11665        Self::Open(o)
11666    }
11667}
11668
11669impl From<Delete> for Statement {
11670    fn from(d: Delete) -> Self {
11671        Self::Delete(d)
11672    }
11673}
11674
11675impl From<CreateTable> for Statement {
11676    fn from(c: CreateTable) -> Self {
11677        Self::CreateTable(c)
11678    }
11679}
11680
11681impl From<CreateIndex> for Statement {
11682    fn from(c: CreateIndex) -> Self {
11683        Self::CreateIndex(c)
11684    }
11685}
11686
11687impl From<CreateServerStatement> for Statement {
11688    fn from(c: CreateServerStatement) -> Self {
11689        Self::CreateServer(c)
11690    }
11691}
11692
11693impl From<CreateConnector> for Statement {
11694    fn from(c: CreateConnector) -> Self {
11695        Self::CreateConnector(c)
11696    }
11697}
11698
11699impl From<CreateOperator> for Statement {
11700    fn from(c: CreateOperator) -> Self {
11701        Self::CreateOperator(c)
11702    }
11703}
11704
11705impl From<CreateOperatorFamily> for Statement {
11706    fn from(c: CreateOperatorFamily) -> Self {
11707        Self::CreateOperatorFamily(c)
11708    }
11709}
11710
11711impl From<CreateOperatorClass> for Statement {
11712    fn from(c: CreateOperatorClass) -> Self {
11713        Self::CreateOperatorClass(c)
11714    }
11715}
11716
11717impl From<AlterSchema> for Statement {
11718    fn from(a: AlterSchema) -> Self {
11719        Self::AlterSchema(a)
11720    }
11721}
11722
11723impl From<AlterType> for Statement {
11724    fn from(a: AlterType) -> Self {
11725        Self::AlterType(a)
11726    }
11727}
11728
11729impl From<AlterOperator> for Statement {
11730    fn from(a: AlterOperator) -> Self {
11731        Self::AlterOperator(a)
11732    }
11733}
11734
11735impl From<AlterOperatorFamily> for Statement {
11736    fn from(a: AlterOperatorFamily) -> Self {
11737        Self::AlterOperatorFamily(a)
11738    }
11739}
11740
11741impl From<AlterOperatorClass> for Statement {
11742    fn from(a: AlterOperatorClass) -> Self {
11743        Self::AlterOperatorClass(a)
11744    }
11745}
11746
11747impl From<Merge> for Statement {
11748    fn from(m: Merge) -> Self {
11749        Self::Merge(m)
11750    }
11751}
11752
11753impl From<AlterUser> for Statement {
11754    fn from(a: AlterUser) -> Self {
11755        Self::AlterUser(a)
11756    }
11757}
11758
11759impl From<DropDomain> for Statement {
11760    fn from(d: DropDomain) -> Self {
11761        Self::DropDomain(d)
11762    }
11763}
11764
11765impl From<ShowCharset> for Statement {
11766    fn from(s: ShowCharset) -> Self {
11767        Self::ShowCharset(s)
11768    }
11769}
11770
11771impl From<ShowObjects> for Statement {
11772    fn from(s: ShowObjects) -> Self {
11773        Self::ShowObjects(s)
11774    }
11775}
11776
11777impl From<Use> for Statement {
11778    fn from(u: Use) -> Self {
11779        Self::Use(u)
11780    }
11781}
11782
11783impl From<CreateFunction> for Statement {
11784    fn from(c: CreateFunction) -> Self {
11785        Self::CreateFunction(c)
11786    }
11787}
11788
11789impl From<CreateTrigger> for Statement {
11790    fn from(c: CreateTrigger) -> Self {
11791        Self::CreateTrigger(c)
11792    }
11793}
11794
11795impl From<DropTrigger> for Statement {
11796    fn from(d: DropTrigger) -> Self {
11797        Self::DropTrigger(d)
11798    }
11799}
11800
11801impl From<DropOperator> for Statement {
11802    fn from(d: DropOperator) -> Self {
11803        Self::DropOperator(d)
11804    }
11805}
11806
11807impl From<DropOperatorFamily> for Statement {
11808    fn from(d: DropOperatorFamily) -> Self {
11809        Self::DropOperatorFamily(d)
11810    }
11811}
11812
11813impl From<DropOperatorClass> for Statement {
11814    fn from(d: DropOperatorClass) -> Self {
11815        Self::DropOperatorClass(d)
11816    }
11817}
11818
11819impl From<DenyStatement> for Statement {
11820    fn from(d: DenyStatement) -> Self {
11821        Self::Deny(d)
11822    }
11823}
11824
11825impl From<CreateDomain> for Statement {
11826    fn from(c: CreateDomain) -> Self {
11827        Self::CreateDomain(c)
11828    }
11829}
11830
11831impl From<RenameTable> for Statement {
11832    fn from(r: RenameTable) -> Self {
11833        vec![r].into()
11834    }
11835}
11836
11837impl From<Vec<RenameTable>> for Statement {
11838    fn from(r: Vec<RenameTable>) -> Self {
11839        Self::RenameTable(r)
11840    }
11841}
11842
11843impl From<PrintStatement> for Statement {
11844    fn from(p: PrintStatement) -> Self {
11845        Self::Print(p)
11846    }
11847}
11848
11849impl From<ReturnStatement> for Statement {
11850    fn from(r: ReturnStatement) -> Self {
11851        Self::Return(r)
11852    }
11853}
11854
11855impl From<ExportData> for Statement {
11856    fn from(e: ExportData) -> Self {
11857        Self::ExportData(e)
11858    }
11859}
11860
11861impl From<CreateUser> for Statement {
11862    fn from(c: CreateUser) -> Self {
11863        Self::CreateUser(c)
11864    }
11865}
11866
11867impl From<VacuumStatement> for Statement {
11868    fn from(v: VacuumStatement) -> Self {
11869        Self::Vacuum(v)
11870    }
11871}
11872
11873impl From<ResetStatement> for Statement {
11874    fn from(r: ResetStatement) -> Self {
11875        Self::Reset(r)
11876    }
11877}
11878
11879#[cfg(test)]
11880mod tests {
11881    use crate::tokenizer::Location;
11882
11883    use super::*;
11884
11885    #[test]
11886    fn test_window_frame_default() {
11887        let window_frame = WindowFrame::default();
11888        assert_eq!(WindowFrameBound::Preceding(None), window_frame.start_bound);
11889    }
11890
11891    #[test]
11892    fn test_grouping_sets_display() {
11893        // a and b in different group
11894        let grouping_sets = Expr::GroupingSets(vec![
11895            vec![Expr::Identifier(Ident::new("a"))],
11896            vec![Expr::Identifier(Ident::new("b"))],
11897        ]);
11898        assert_eq!("GROUPING SETS ((a), (b))", format!("{grouping_sets}"));
11899
11900        // a and b in the same group
11901        let grouping_sets = Expr::GroupingSets(vec![vec![
11902            Expr::Identifier(Ident::new("a")),
11903            Expr::Identifier(Ident::new("b")),
11904        ]]);
11905        assert_eq!("GROUPING SETS ((a, b))", format!("{grouping_sets}"));
11906
11907        // (a, b) and (c, d) in different group
11908        let grouping_sets = Expr::GroupingSets(vec![
11909            vec![
11910                Expr::Identifier(Ident::new("a")),
11911                Expr::Identifier(Ident::new("b")),
11912            ],
11913            vec![
11914                Expr::Identifier(Ident::new("c")),
11915                Expr::Identifier(Ident::new("d")),
11916            ],
11917        ]);
11918        assert_eq!("GROUPING SETS ((a, b), (c, d))", format!("{grouping_sets}"));
11919    }
11920
11921    #[test]
11922    fn test_rollup_display() {
11923        let rollup = Expr::Rollup(vec![vec![Expr::Identifier(Ident::new("a"))]]);
11924        assert_eq!("ROLLUP (a)", format!("{rollup}"));
11925
11926        let rollup = Expr::Rollup(vec![vec![
11927            Expr::Identifier(Ident::new("a")),
11928            Expr::Identifier(Ident::new("b")),
11929        ]]);
11930        assert_eq!("ROLLUP ((a, b))", format!("{rollup}"));
11931
11932        let rollup = Expr::Rollup(vec![
11933            vec![Expr::Identifier(Ident::new("a"))],
11934            vec![Expr::Identifier(Ident::new("b"))],
11935        ]);
11936        assert_eq!("ROLLUP (a, b)", format!("{rollup}"));
11937
11938        let rollup = Expr::Rollup(vec![
11939            vec![Expr::Identifier(Ident::new("a"))],
11940            vec![
11941                Expr::Identifier(Ident::new("b")),
11942                Expr::Identifier(Ident::new("c")),
11943            ],
11944            vec![Expr::Identifier(Ident::new("d"))],
11945        ]);
11946        assert_eq!("ROLLUP (a, (b, c), d)", format!("{rollup}"));
11947    }
11948
11949    #[test]
11950    fn test_cube_display() {
11951        let cube = Expr::Cube(vec![vec![Expr::Identifier(Ident::new("a"))]]);
11952        assert_eq!("CUBE (a)", format!("{cube}"));
11953
11954        let cube = Expr::Cube(vec![vec![
11955            Expr::Identifier(Ident::new("a")),
11956            Expr::Identifier(Ident::new("b")),
11957        ]]);
11958        assert_eq!("CUBE ((a, b))", format!("{cube}"));
11959
11960        let cube = Expr::Cube(vec![
11961            vec![Expr::Identifier(Ident::new("a"))],
11962            vec![Expr::Identifier(Ident::new("b"))],
11963        ]);
11964        assert_eq!("CUBE (a, b)", format!("{cube}"));
11965
11966        let cube = Expr::Cube(vec![
11967            vec![Expr::Identifier(Ident::new("a"))],
11968            vec![
11969                Expr::Identifier(Ident::new("b")),
11970                Expr::Identifier(Ident::new("c")),
11971            ],
11972            vec![Expr::Identifier(Ident::new("d"))],
11973        ]);
11974        assert_eq!("CUBE (a, (b, c), d)", format!("{cube}"));
11975    }
11976
11977    #[test]
11978    fn test_interval_display() {
11979        let interval = Expr::Interval(Interval {
11980            value: Box::new(Expr::Value(
11981                Value::SingleQuotedString(String::from("123:45.67")).with_empty_span(),
11982            )),
11983            leading_field: Some(DateTimeField::Minute),
11984            leading_precision: Some(10),
11985            last_field: Some(DateTimeField::Second),
11986            fractional_seconds_precision: Some(9),
11987        });
11988        assert_eq!(
11989            "INTERVAL '123:45.67' MINUTE (10) TO SECOND (9)",
11990            format!("{interval}"),
11991        );
11992
11993        let interval = Expr::Interval(Interval {
11994            value: Box::new(Expr::Value(
11995                Value::SingleQuotedString(String::from("5")).with_empty_span(),
11996            )),
11997            leading_field: Some(DateTimeField::Second),
11998            leading_precision: Some(1),
11999            last_field: None,
12000            fractional_seconds_precision: Some(3),
12001        });
12002        assert_eq!("INTERVAL '5' SECOND (1, 3)", format!("{interval}"));
12003    }
12004
12005    #[test]
12006    fn test_one_or_many_with_parens_deref() {
12007        use core::ops::Index;
12008
12009        let one = OneOrManyWithParens::One("a");
12010
12011        assert_eq!(one.deref(), &["a"]);
12012        assert_eq!(<OneOrManyWithParens<_> as Deref>::deref(&one), &["a"]);
12013
12014        assert_eq!(one[0], "a");
12015        assert_eq!(one.index(0), &"a");
12016        assert_eq!(
12017            <<OneOrManyWithParens<_> as Deref>::Target as Index<usize>>::index(&one, 0),
12018            &"a"
12019        );
12020
12021        assert_eq!(one.len(), 1);
12022        assert_eq!(<OneOrManyWithParens<_> as Deref>::Target::len(&one), 1);
12023
12024        let many1 = OneOrManyWithParens::Many(vec!["b"]);
12025
12026        assert_eq!(many1.deref(), &["b"]);
12027        assert_eq!(<OneOrManyWithParens<_> as Deref>::deref(&many1), &["b"]);
12028
12029        assert_eq!(many1[0], "b");
12030        assert_eq!(many1.index(0), &"b");
12031        assert_eq!(
12032            <<OneOrManyWithParens<_> as Deref>::Target as Index<usize>>::index(&many1, 0),
12033            &"b"
12034        );
12035
12036        assert_eq!(many1.len(), 1);
12037        assert_eq!(<OneOrManyWithParens<_> as Deref>::Target::len(&many1), 1);
12038
12039        let many2 = OneOrManyWithParens::Many(vec!["c", "d"]);
12040
12041        assert_eq!(many2.deref(), &["c", "d"]);
12042        assert_eq!(
12043            <OneOrManyWithParens<_> as Deref>::deref(&many2),
12044            &["c", "d"]
12045        );
12046
12047        assert_eq!(many2[0], "c");
12048        assert_eq!(many2.index(0), &"c");
12049        assert_eq!(
12050            <<OneOrManyWithParens<_> as Deref>::Target as Index<usize>>::index(&many2, 0),
12051            &"c"
12052        );
12053
12054        assert_eq!(many2[1], "d");
12055        assert_eq!(many2.index(1), &"d");
12056        assert_eq!(
12057            <<OneOrManyWithParens<_> as Deref>::Target as Index<usize>>::index(&many2, 1),
12058            &"d"
12059        );
12060
12061        assert_eq!(many2.len(), 2);
12062        assert_eq!(<OneOrManyWithParens<_> as Deref>::Target::len(&many2), 2);
12063    }
12064
12065    #[test]
12066    fn test_one_or_many_with_parens_as_ref() {
12067        let one = OneOrManyWithParens::One("a");
12068
12069        assert_eq!(one.as_ref(), &["a"]);
12070        assert_eq!(<OneOrManyWithParens<_> as AsRef<_>>::as_ref(&one), &["a"]);
12071
12072        let many1 = OneOrManyWithParens::Many(vec!["b"]);
12073
12074        assert_eq!(many1.as_ref(), &["b"]);
12075        assert_eq!(<OneOrManyWithParens<_> as AsRef<_>>::as_ref(&many1), &["b"]);
12076
12077        let many2 = OneOrManyWithParens::Many(vec!["c", "d"]);
12078
12079        assert_eq!(many2.as_ref(), &["c", "d"]);
12080        assert_eq!(
12081            <OneOrManyWithParens<_> as AsRef<_>>::as_ref(&many2),
12082            &["c", "d"]
12083        );
12084    }
12085
12086    #[test]
12087    fn test_one_or_many_with_parens_ref_into_iter() {
12088        let one = OneOrManyWithParens::One("a");
12089
12090        assert_eq!(Vec::from_iter(&one), vec![&"a"]);
12091
12092        let many1 = OneOrManyWithParens::Many(vec!["b"]);
12093
12094        assert_eq!(Vec::from_iter(&many1), vec![&"b"]);
12095
12096        let many2 = OneOrManyWithParens::Many(vec!["c", "d"]);
12097
12098        assert_eq!(Vec::from_iter(&many2), vec![&"c", &"d"]);
12099    }
12100
12101    #[test]
12102    fn test_one_or_many_with_parens_value_into_iter() {
12103        use core::iter::once;
12104
12105        //tests that our iterator implemented methods behaves exactly as it's inner iterator, at every step up to n calls to next/next_back
12106        fn test_steps<I>(ours: OneOrManyWithParens<usize>, inner: I, n: usize)
12107        where
12108            I: IntoIterator<Item = usize, IntoIter: DoubleEndedIterator + Clone> + Clone,
12109        {
12110            fn checks<I>(ours: OneOrManyWithParensIntoIter<usize>, inner: I)
12111            where
12112                I: Iterator<Item = usize> + Clone + DoubleEndedIterator,
12113            {
12114                assert_eq!(ours.size_hint(), inner.size_hint());
12115                assert_eq!(ours.clone().count(), inner.clone().count());
12116
12117                assert_eq!(
12118                    ours.clone().fold(1, |a, v| a + v),
12119                    inner.clone().fold(1, |a, v| a + v)
12120                );
12121
12122                assert_eq!(Vec::from_iter(ours.clone()), Vec::from_iter(inner.clone()));
12123                assert_eq!(
12124                    Vec::from_iter(ours.clone().rev()),
12125                    Vec::from_iter(inner.clone().rev())
12126                );
12127            }
12128
12129            let mut ours_next = ours.clone().into_iter();
12130            let mut inner_next = inner.clone().into_iter();
12131
12132            for _ in 0..n {
12133                checks(ours_next.clone(), inner_next.clone());
12134
12135                assert_eq!(ours_next.next(), inner_next.next());
12136            }
12137
12138            let mut ours_next_back = ours.clone().into_iter();
12139            let mut inner_next_back = inner.clone().into_iter();
12140
12141            for _ in 0..n {
12142                checks(ours_next_back.clone(), inner_next_back.clone());
12143
12144                assert_eq!(ours_next_back.next_back(), inner_next_back.next_back());
12145            }
12146
12147            let mut ours_mixed = ours.clone().into_iter();
12148            let mut inner_mixed = inner.clone().into_iter();
12149
12150            for i in 0..n {
12151                checks(ours_mixed.clone(), inner_mixed.clone());
12152
12153                if i % 2 == 0 {
12154                    assert_eq!(ours_mixed.next_back(), inner_mixed.next_back());
12155                } else {
12156                    assert_eq!(ours_mixed.next(), inner_mixed.next());
12157                }
12158            }
12159
12160            let mut ours_mixed2 = ours.into_iter();
12161            let mut inner_mixed2 = inner.into_iter();
12162
12163            for i in 0..n {
12164                checks(ours_mixed2.clone(), inner_mixed2.clone());
12165
12166                if i % 2 == 0 {
12167                    assert_eq!(ours_mixed2.next(), inner_mixed2.next());
12168                } else {
12169                    assert_eq!(ours_mixed2.next_back(), inner_mixed2.next_back());
12170                }
12171            }
12172        }
12173
12174        test_steps(OneOrManyWithParens::One(1), once(1), 3);
12175        test_steps(OneOrManyWithParens::Many(vec![2]), vec![2], 3);
12176        test_steps(OneOrManyWithParens::Many(vec![3, 4]), vec![3, 4], 4);
12177    }
12178
12179    // Tests that the position in the code of an `Ident` does not affect its
12180    // ordering.
12181    #[test]
12182    fn test_ident_ord() {
12183        let mut a = Ident::with_span(Span::new(Location::new(1, 1), Location::new(1, 1)), "a");
12184        let mut b = Ident::with_span(Span::new(Location::new(2, 2), Location::new(2, 2)), "b");
12185
12186        assert!(a < b);
12187        std::mem::swap(&mut a.span, &mut b.span);
12188        assert!(a < b);
12189    }
12190}