Skip to main content

sqlparser/ast/
mod.rs

1// Licensed to the Apache Software Foundation (ASF) under one
2// or more contributor license agreements.  See the NOTICE file
3// distributed with this work for additional information
4// regarding copyright ownership.  The ASF licenses this file
5// to you under the Apache License, Version 2.0 (the
6// "License"); you may not use this file except in compliance
7// with the License.  You may obtain a copy of the License at
8//
9//   http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing,
12// software distributed under the License is distributed on an
13// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14// KIND, either express or implied.  See the License for the
15// specific language governing permissions and limitations
16// under the License.
17
18//! SQL Abstract Syntax Tree (AST) types
19#[cfg(not(feature = "std"))]
20use alloc::{
21    boxed::Box,
22    format,
23    string::{String, ToString},
24    vec,
25    vec::Vec,
26};
27use helpers::{
28    attached_token::AttachedToken,
29    stmt_data_loading::{FileStagingCommand, StageLoadSelectItemKind},
30};
31
32use core::cmp::Ordering;
33use core::ops::Deref;
34use core::{
35    fmt::{self, Display},
36    hash,
37};
38
39#[cfg(feature = "serde")]
40use serde::{Deserialize, Serialize};
41
42#[cfg(feature = "visitor")]
43use sqlparser_derive::{Visit, VisitMut};
44
45use crate::{
46    display_utils::SpaceOrNewline,
47    tokenizer::{Span, Token},
48};
49use crate::{
50    display_utils::{Indent, NewLine},
51    keywords::Keyword,
52};
53
54pub use self::data_type::{
55    ArrayElemTypeDef, BinaryLength, CharLengthUnits, CharacterLength, DataType, EnumMember,
56    ExactNumberInfo, IntervalFields, StructBracketKind, TimezoneInfo,
57};
58pub use self::dcl::{
59    AlterRoleOperation, CreateRole, Grant, ResetConfig, Revoke, RoleOption, SecondaryRoles,
60    SetConfigValue, Use,
61};
62pub use self::ddl::{
63    Alignment, AlterCollation, AlterCollationOperation, AlterColumnOperation, AlterConnectorOwner,
64    AlterFunction, AlterFunctionAction, AlterFunctionKind, AlterFunctionOperation,
65    AlterIndexOperation, AlterOperator, AlterOperatorClass, AlterOperatorClassOperation,
66    AlterOperatorFamily, AlterOperatorFamilyOperation, AlterOperatorOperation, AlterPolicy,
67    AlterPolicyOperation, AlterSchema, AlterSchemaOperation, AlterTable, AlterTableAlgorithm,
68    AlterTableLock, AlterTableOperation, AlterTableType, AlterType, AlterTypeAddValue,
69    AlterTypeAddValuePosition, AlterTypeOperation, AlterTypeRename, AlterTypeRenameValue,
70    ClusteredBy, ColumnDef, ColumnOption, ColumnOptionDef, ColumnOptions, ColumnPolicy,
71    ColumnPolicyProperty, ConstraintCharacteristics, CreateCollation, CreateCollationDefinition,
72    CreateConnector, CreateDomain, CreateExtension, CreateFunction, CreateIndex, CreateOperator,
73    CreateOperatorClass, CreateOperatorFamily, CreatePolicy, CreatePolicyCommand, CreatePolicyType,
74    CreateTable, CreateTrigger, CreateView, Deduplicate, DeferrableInitial, DistStyle,
75    DropBehavior, DropExtension, DropFunction, DropOperator, DropOperatorClass, DropOperatorFamily,
76    DropOperatorSignature, DropPolicy, DropTrigger, ForValues, FunctionReturnType, GeneratedAs,
77    GeneratedExpressionMode, IdentityParameters, IdentityProperty, IdentityPropertyFormatKind,
78    IdentityPropertyKind, IdentityPropertyOrder, IndexColumn, IndexOption, IndexType,
79    KeyOrIndexDisplay, Msck, NullsDistinctOption, OperatorArgTypes, OperatorClassItem,
80    OperatorFamilyDropItem, OperatorFamilyItem, OperatorOption, OperatorPurpose, Owner, Partition,
81    PartitionBoundValue, ProcedureParam, ReferentialAction, RenameTableNameKind, ReplicaIdentity,
82    TagsColumnOption, TriggerObjectKind, Truncate, UserDefinedTypeCompositeAttributeDef,
83    UserDefinedTypeInternalLength, UserDefinedTypeRangeOption, UserDefinedTypeRepresentation,
84    UserDefinedTypeSqlDefinitionOption, UserDefinedTypeStorage, ViewColumnDef,
85};
86pub use self::dml::{
87    Delete, Insert, Merge, MergeAction, MergeClause, MergeClauseKind, MergeInsertExpr,
88    MergeInsertKind, MergeUpdateExpr, MultiTableInsertIntoClause, MultiTableInsertType,
89    MultiTableInsertValue, MultiTableInsertValues, MultiTableInsertWhenClause, OutputClause,
90    Update,
91};
92pub use self::operator::{BinaryOperator, UnaryOperator};
93pub use self::query::{
94    AfterMatchSkip, ConnectByKind, Cte, CteAsMaterialized, Distinct, EmptyMatchesMode,
95    ExceptSelectItem, ExcludeSelectItem, ExprWithAlias, ExprWithAliasAndOrderBy, Fetch, ForClause,
96    ForJson, ForXml, FormatClause, GroupByExpr, GroupByWithModifier, IdentWithAlias,
97    IlikeSelectItem, InputFormatClause, Interpolate, InterpolateExpr, Join, JoinConstraint,
98    JoinOperator, JsonTableColumn, JsonTableColumnErrorHandling, JsonTableNamedColumn,
99    JsonTableNestedColumn, LateralView, LimitClause, LockClause, LockType, MatchRecognizePattern,
100    MatchRecognizeSymbol, Measure, NamedWindowDefinition, NamedWindowExpr, NonBlock, Offset,
101    OffsetRows, OpenJsonTableColumn, OrderBy, OrderByExpr, OrderByKind, OrderByOptions,
102    PipeOperator, PivotValueSource, ProjectionSelect, Query, RenameSelectItem,
103    RepetitionQuantifier, ReplaceSelectElement, ReplaceSelectItem, RowsPerMatch, Select,
104    SelectFlavor, SelectInto, SelectItem, SelectItemQualifiedWildcardKind, SelectModifiers,
105    SetExpr, SetOperator, SetQuantifier, Setting, SymbolDefinition, Table, TableAlias,
106    TableAliasColumnDef, TableFactor, TableFunctionArgs, TableIndexHintForClause,
107    TableIndexHintType, TableIndexHints, TableIndexType, TableSample, TableSampleBucket,
108    TableSampleKind, TableSampleMethod, TableSampleModifier, TableSampleQuantity, TableSampleSeed,
109    TableSampleSeedModifier, TableSampleUnit, TableVersion, TableWithJoins, Top, TopQuantity,
110    UpdateTableFromKind, ValueTableMode, Values, WildcardAdditionalOptions, With, WithFill,
111    XmlNamespaceDefinition, XmlPassingArgument, XmlPassingClause, XmlTableColumn,
112    XmlTableColumnOption,
113};
114
115pub use self::trigger::{
116    TriggerEvent, TriggerExecBody, TriggerExecBodyType, TriggerObject, TriggerPeriod,
117    TriggerReferencing, TriggerReferencingType,
118};
119
120pub use self::value::{
121    escape_double_quote_string, escape_quoted_string, DateTimeField, DollarQuotedString,
122    NormalizationForm, QuoteDelimitedString, TrimWhereField, Value, ValueWithSpan,
123};
124
125use crate::ast::helpers::key_value_options::KeyValueOptions;
126use crate::ast::helpers::stmt_data_loading::StageParamsObject;
127
128#[cfg(feature = "visitor")]
129pub use visitor::*;
130
131pub use self::data_type::GeometricTypeKind;
132
133mod data_type;
134mod dcl;
135mod ddl;
136mod dml;
137/// Helper modules for building and manipulating AST nodes.
138pub mod helpers;
139pub mod table_constraints;
140pub use table_constraints::{
141    CheckConstraint, ConstraintUsingIndex, ExclusionConstraint, ExclusionElement,
142    ForeignKeyConstraint, FullTextOrSpatialConstraint, IndexConstraint, PrimaryKeyConstraint,
143    TableConstraint, UniqueConstraint,
144};
145mod operator;
146mod query;
147mod spans;
148pub use spans::Spanned;
149
150pub mod comments;
151mod trigger;
152mod value;
153
154#[cfg(feature = "visitor")]
155mod visitor;
156
157/// Helper used to format a slice using a separator string (e.g., `", "`).
158pub struct DisplaySeparated<'a, T>
159where
160    T: fmt::Display,
161{
162    slice: &'a [T],
163    sep: &'static str,
164}
165
166impl<T> fmt::Display for DisplaySeparated<'_, T>
167where
168    T: fmt::Display,
169{
170    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
171        let mut delim = "";
172        for t in self.slice {
173            f.write_str(delim)?;
174            delim = self.sep;
175            t.fmt(f)?;
176        }
177        Ok(())
178    }
179}
180
181pub(crate) fn display_separated<'a, T>(slice: &'a [T], sep: &'static str) -> DisplaySeparated<'a, T>
182where
183    T: fmt::Display,
184{
185    DisplaySeparated { slice, sep }
186}
187
188pub(crate) fn display_comma_separated<T>(slice: &[T]) -> DisplaySeparated<'_, T>
189where
190    T: fmt::Display,
191{
192    DisplaySeparated { slice, sep: ", " }
193}
194
195/// Writes the given statements to the formatter, each ending with
196/// a semicolon and space separated.
197fn format_statement_list(f: &mut fmt::Formatter, statements: &[Statement]) -> fmt::Result {
198    write!(f, "{}", display_separated(statements, "; "))?;
199    // We manually insert semicolon for the last statement,
200    // since display_separated doesn't handle that case.
201    write!(f, ";")
202}
203
204/// An identifier, decomposed into its value or character data and the quote style.
205#[derive(Debug, Clone)]
206#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
207#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
208pub struct Ident {
209    /// The value of the identifier without quotes.
210    pub value: String,
211    /// The starting quote if any. Valid quote characters are the single quote,
212    /// double quote, backtick, and opening square bracket.
213    pub quote_style: Option<char>,
214    /// The span of the identifier in the original SQL string.
215    pub span: Span,
216}
217
218impl PartialEq for Ident {
219    fn eq(&self, other: &Self) -> bool {
220        let Ident {
221            value,
222            quote_style,
223            // exhaustiveness check; we ignore spans in comparisons
224            span: _,
225        } = self;
226
227        value == &other.value && quote_style == &other.quote_style
228    }
229}
230
231impl core::hash::Hash for Ident {
232    fn hash<H: hash::Hasher>(&self, state: &mut H) {
233        let Ident {
234            value,
235            quote_style,
236            // exhaustiveness check; we ignore spans in hashes
237            span: _,
238        } = self;
239
240        value.hash(state);
241        quote_style.hash(state);
242    }
243}
244
245impl Eq for Ident {}
246
247impl PartialOrd for Ident {
248    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
249        Some(self.cmp(other))
250    }
251}
252
253impl Ord for Ident {
254    fn cmp(&self, other: &Self) -> Ordering {
255        let Ident {
256            value,
257            quote_style,
258            // exhaustiveness check; we ignore spans in ordering
259            span: _,
260        } = self;
261
262        let Ident {
263            value: other_value,
264            quote_style: other_quote_style,
265            // exhaustiveness check; we ignore spans in ordering
266            span: _,
267        } = other;
268
269        // First compare by value, then by quote_style
270        value
271            .cmp(other_value)
272            .then_with(|| quote_style.cmp(other_quote_style))
273    }
274}
275
276impl Ident {
277    /// Create a new identifier with the given value and no quotes and an empty span.
278    pub fn new<S>(value: S) -> Self
279    where
280        S: Into<String>,
281    {
282        Ident {
283            value: value.into(),
284            quote_style: None,
285            span: Span::empty(),
286        }
287    }
288
289    /// Create a new quoted identifier with the given quote and value. This function
290    /// panics if the given quote is not a valid quote character.
291    pub fn with_quote<S>(quote: char, value: S) -> Self
292    where
293        S: Into<String>,
294    {
295        assert!(quote == '\'' || quote == '"' || quote == '`' || quote == '[');
296        Ident {
297            value: value.into(),
298            quote_style: Some(quote),
299            span: Span::empty(),
300        }
301    }
302
303    /// Create an `Ident` with the given `span` and `value` (unquoted).
304    pub fn with_span<S>(span: Span, value: S) -> Self
305    where
306        S: Into<String>,
307    {
308        Ident {
309            value: value.into(),
310            quote_style: None,
311            span,
312        }
313    }
314
315    /// Create a quoted `Ident` with the given `quote` and `span`.
316    pub fn with_quote_and_span<S>(quote: char, span: Span, value: S) -> Self
317    where
318        S: Into<String>,
319    {
320        assert!(quote == '\'' || quote == '"' || quote == '`' || quote == '[');
321        Ident {
322            value: value.into(),
323            quote_style: Some(quote),
324            span,
325        }
326    }
327}
328
329impl From<&str> for Ident {
330    fn from(value: &str) -> Self {
331        Ident {
332            value: value.to_string(),
333            quote_style: None,
334            span: Span::empty(),
335        }
336    }
337}
338
339impl fmt::Display for Ident {
340    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
341        match self.quote_style {
342            Some(q) if q == '"' || q == '\'' || q == '`' => {
343                let escaped = value::escape_quoted_string(&self.value, q);
344                write!(f, "{q}{escaped}{q}")
345            }
346            Some('[') => write!(f, "[{}]", self.value),
347            None => f.write_str(&self.value),
348            _ => panic!("unexpected quote style"),
349        }
350    }
351}
352
353/// A name of a table, view, custom type, etc., possibly multi-part, i.e. db.schema.obj
354#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
355#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
356#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
357pub struct ObjectName(pub Vec<ObjectNamePart>);
358
359impl From<Vec<Ident>> for ObjectName {
360    fn from(idents: Vec<Ident>) -> Self {
361        ObjectName(idents.into_iter().map(ObjectNamePart::Identifier).collect())
362    }
363}
364
365impl From<Ident> for ObjectName {
366    fn from(ident: Ident) -> Self {
367        ObjectName(vec![ObjectNamePart::Identifier(ident)])
368    }
369}
370
371impl fmt::Display for ObjectName {
372    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
373        write!(f, "{}", display_separated(&self.0, "."))
374    }
375}
376
377/// A single part of an ObjectName
378#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
379#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
380#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
381pub enum ObjectNamePart {
382    /// A single identifier part, e.g. `schema` or `table`.
383    Identifier(Ident),
384    /// A function that returns an identifier (dialect-specific).
385    Function(ObjectNamePartFunction),
386}
387
388impl ObjectNamePart {
389    /// Return the identifier if this is an `Identifier` variant.
390    pub fn as_ident(&self) -> Option<&Ident> {
391        match self {
392            ObjectNamePart::Identifier(ident) => Some(ident),
393            ObjectNamePart::Function(_) => None,
394        }
395    }
396}
397
398impl fmt::Display for ObjectNamePart {
399    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
400        match self {
401            ObjectNamePart::Identifier(ident) => write!(f, "{ident}"),
402            ObjectNamePart::Function(func) => write!(f, "{func}"),
403        }
404    }
405}
406
407/// An object name part that consists of a function that dynamically
408/// constructs identifiers.
409///
410/// - [Snowflake](https://docs.snowflake.com/en/sql-reference/identifier-literal)
411#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
412#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
413#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
414pub struct ObjectNamePartFunction {
415    /// The function name that produces the object name part.
416    pub name: Ident,
417    /// Function arguments used to compute the identifier.
418    pub args: Vec<FunctionArg>,
419}
420
421impl fmt::Display for ObjectNamePartFunction {
422    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
423        write!(f, "{}(", self.name)?;
424        write!(f, "{})", display_comma_separated(&self.args))
425    }
426}
427
428/// Represents an Array Expression, either
429/// `ARRAY[..]`, or `[..]`
430#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
431#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
432#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
433pub struct Array {
434    /// The list of expressions between brackets
435    pub elem: Vec<Expr>,
436
437    /// `true` for  `ARRAY[..]`, `false` for `[..]`
438    pub named: bool,
439}
440
441impl fmt::Display for Array {
442    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
443        write!(
444            f,
445            "{}[{}]",
446            if self.named { "ARRAY" } else { "" },
447            display_comma_separated(&self.elem)
448        )
449    }
450}
451
452/// Represents an INTERVAL expression, roughly in the following format:
453/// `INTERVAL '<value>' [ <leading_field> [ (<leading_precision>) ] ]
454/// [ TO <last_field> [ (<fractional_seconds_precision>) ] ]`,
455/// e.g. `INTERVAL '123:45.67' MINUTE(3) TO SECOND(2)`.
456///
457/// The parser does not validate the `<value>`, nor does it ensure
458/// that the `<leading_field>` units >= the units in `<last_field>`,
459/// so the user will have to reject intervals like `HOUR TO YEAR`.
460#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
461#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
462#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
463pub struct Interval {
464    /// The interval value expression (commonly a string literal).
465    pub value: Box<Expr>,
466    /// Optional leading time unit (e.g., `HOUR`, `MINUTE`).
467    pub leading_field: Option<DateTimeField>,
468    /// Optional leading precision for the leading field.
469    pub leading_precision: Option<u64>,
470    /// Optional trailing time unit for a range (e.g., `SECOND`).
471    pub last_field: Option<DateTimeField>,
472    /// The fractional seconds precision, when specified.
473    ///
474    /// See SQL `SECOND(n)` or `SECOND(m, n)` forms.
475    pub fractional_seconds_precision: Option<u64>,
476}
477
478impl fmt::Display for Interval {
479    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
480        let value = self.value.as_ref();
481        match (
482            &self.leading_field,
483            self.leading_precision,
484            self.fractional_seconds_precision,
485        ) {
486            (
487                Some(DateTimeField::Second),
488                Some(leading_precision),
489                Some(fractional_seconds_precision),
490            ) => {
491                // When the leading field is SECOND, the parser guarantees that
492                // the last field is None.
493                assert!(self.last_field.is_none());
494                write!(
495                    f,
496                    "INTERVAL {value} SECOND ({leading_precision}, {fractional_seconds_precision})"
497                )
498            }
499            _ => {
500                write!(f, "INTERVAL {value}")?;
501                if let Some(leading_field) = &self.leading_field {
502                    write!(f, " {leading_field}")?;
503                }
504                if let Some(leading_precision) = self.leading_precision {
505                    write!(f, " ({leading_precision})")?;
506                }
507                if let Some(last_field) = &self.last_field {
508                    write!(f, " TO {last_field}")?;
509                }
510                if let Some(fractional_seconds_precision) = self.fractional_seconds_precision {
511                    write!(f, " ({fractional_seconds_precision})")?;
512                }
513                Ok(())
514            }
515        }
516    }
517}
518
519/// A field definition within a struct
520///
521/// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-types#struct_type
522#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
523#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
524#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
525pub struct StructField {
526    /// Optional name of the struct field.
527    pub field_name: Option<Ident>,
528    /// The field data type.
529    pub field_type: DataType,
530    /// Struct field options (e.g., `OPTIONS(...)` on BigQuery).
531    /// See [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#column_name_and_column_schema)
532    pub options: Option<Vec<SqlOption>>,
533}
534
535impl fmt::Display for StructField {
536    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
537        if let Some(name) = &self.field_name {
538            write!(f, "{name} {}", self.field_type)?;
539        } else {
540            write!(f, "{}", self.field_type)?;
541        }
542        if let Some(options) = &self.options {
543            write!(f, " OPTIONS({})", display_separated(options, ", "))
544        } else {
545            Ok(())
546        }
547    }
548}
549
550/// A field definition within a union
551///
552/// [DuckDB]: https://duckdb.org/docs/sql/data_types/union.html
553#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
554#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
555#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
556pub struct UnionField {
557    /// Name of the union field.
558    pub field_name: Ident,
559    /// Type of the union field.
560    pub field_type: DataType,
561}
562
563impl fmt::Display for UnionField {
564    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
565        write!(f, "{} {}", self.field_name, self.field_type)
566    }
567}
568
569/// A dictionary field within a dictionary.
570///
571/// [DuckDB]: https://duckdb.org/docs/sql/data_types/struct#creating-structs
572#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
573#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
574#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
575pub struct DictionaryField {
576    /// Dictionary key identifier.
577    pub key: Ident,
578    /// Value expression for the dictionary entry.
579    pub value: Box<Expr>,
580}
581
582impl fmt::Display for DictionaryField {
583    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
584        write!(f, "{}: {}", self.key, self.value)
585    }
586}
587
588/// Represents a Map expression.
589#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
590#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
591#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
592pub struct Map {
593    /// Entries of the map as key/value pairs.
594    pub entries: Vec<MapEntry>,
595}
596
597impl Display for Map {
598    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
599        write!(f, "MAP {{{}}}", display_comma_separated(&self.entries))
600    }
601}
602
603/// A map field within a map.
604///
605/// [DuckDB]: https://duckdb.org/docs/sql/data_types/map.html#creating-maps
606#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
607#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
608#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
609pub struct MapEntry {
610    /// Key expression of the map entry.
611    pub key: Box<Expr>,
612    /// Value expression of the map entry.
613    pub value: Box<Expr>,
614}
615
616impl fmt::Display for MapEntry {
617    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
618        write!(f, "{}: {}", self.key, self.value)
619    }
620}
621
622/// Options for `CAST` / `TRY_CAST`
623/// BigQuery: <https://cloud.google.com/bigquery/docs/reference/standard-sql/format-elements#formatting_syntax>
624#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
625#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
626#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
627pub enum CastFormat {
628    /// A simple cast format specified by a `Value`.
629    Value(ValueWithSpan),
630    /// A cast format with an explicit time zone: `(format, timezone)`.
631    ValueAtTimeZone(ValueWithSpan, ValueWithSpan),
632}
633
634/// An element of a JSON path.
635#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
636#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
637#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
638pub enum JsonPathElem {
639    /// Accesses an object field using dot notation, e.g. `obj:foo.bar.baz`.
640    ///
641    /// See <https://docs.snowflake.com/en/user-guide/querying-semistructured#dot-notation>.
642    Dot {
643        /// The object key text (without quotes).
644        key: String,
645        /// `true` when the key was quoted in the source.
646        quoted: bool,
647    },
648    /// Accesses an object field or array element using bracket notation,
649    /// e.g. `obj['foo']`.
650    ///
651    /// See <https://docs.snowflake.com/en/user-guide/querying-semistructured#bracket-notation>.
652    Bracket {
653        /// The expression used as the bracket key (string or numeric expression).
654        key: Expr,
655    },
656    /// Access an object field using colon bracket notation
657    /// e.g. `obj:['foo']`
658    ///
659    /// See <https://docs.databricks.com/en/sql/language-manual/functions/colonsign.html>
660    ColonBracket {
661        /// The expression used as the bracket key (string or numeric expression).
662        key: Expr,
663    },
664}
665
666/// A JSON path.
667///
668/// See <https://docs.snowflake.com/en/user-guide/querying-semistructured>.
669/// See <https://docs.databricks.com/en/sql/language-manual/sql-ref-json-path-expression.html>.
670#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
671#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
672#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
673pub struct JsonPath {
674    /// Sequence of path elements that form the JSON path.
675    pub path: Vec<JsonPathElem>,
676}
677
678impl fmt::Display for JsonPath {
679    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
680        for (i, elem) in self.path.iter().enumerate() {
681            match elem {
682                JsonPathElem::Dot { key, quoted } => {
683                    if i == 0 {
684                        write!(f, ":")?;
685                    } else {
686                        write!(f, ".")?;
687                    }
688
689                    if *quoted {
690                        write!(f, "\"{}\"", escape_double_quote_string(key))?;
691                    } else {
692                        write!(f, "{key}")?;
693                    }
694                }
695                JsonPathElem::Bracket { key } => {
696                    write!(f, "[{key}]")?;
697                }
698                JsonPathElem::ColonBracket { key } => {
699                    write!(f, ":[{key}]")?;
700                }
701            }
702        }
703        Ok(())
704    }
705}
706
707/// The syntax used for in a cast expression.
708#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
709#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
710#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
711pub enum CastKind {
712    /// The standard SQL cast syntax, e.g. `CAST(<expr> as <datatype>)`
713    Cast,
714    /// A cast that returns `NULL` on failure, e.g. `TRY_CAST(<expr> as <datatype>)`.
715    ///
716    /// See <https://docs.snowflake.com/en/sql-reference/functions/try_cast>.
717    /// See <https://learn.microsoft.com/en-us/sql/t-sql/functions/try-cast-transact-sql>.
718    TryCast,
719    /// A cast that returns `NULL` on failure, bigQuery-specific ,  e.g. `SAFE_CAST(<expr> as <datatype>)`.
720    ///
721    /// See <https://cloud.google.com/bigquery/docs/reference/standard-sql/functions-and-operators#safe_casting>.
722    SafeCast,
723    /// `<expr> :: <datatype>`
724    DoubleColon,
725}
726
727/// `MATCH` type for constraint references
728///
729/// See: <https://www.postgresql.org/docs/current/sql-createtable.html#SQL-CREATETABLE-PARMS-REFERENCES>
730#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
731#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
732#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
733pub enum ConstraintReferenceMatchKind {
734    /// `MATCH FULL`
735    Full,
736    /// `MATCH PARTIAL`
737    Partial,
738    /// `MATCH SIMPLE`
739    Simple,
740}
741
742impl fmt::Display for ConstraintReferenceMatchKind {
743    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
744        match self {
745            Self::Full => write!(f, "MATCH FULL"),
746            Self::Partial => write!(f, "MATCH PARTIAL"),
747            Self::Simple => write!(f, "MATCH SIMPLE"),
748        }
749    }
750}
751
752/// `EXTRACT` syntax variants.
753///
754/// In Snowflake dialect, the `EXTRACT` expression can support either the `from` syntax
755/// or the comma syntax.
756///
757/// See <https://docs.snowflake.com/en/sql-reference/functions/extract>
758#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
759#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
760#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
761pub enum ExtractSyntax {
762    /// `EXTRACT( <date_or_time_part> FROM <date_or_time_expr> )`
763    From,
764    /// `EXTRACT( <date_or_time_part> , <date_or_timestamp_expr> )`
765    Comma,
766}
767
768/// The syntax used in a CEIL or FLOOR expression.
769///
770/// The `CEIL/FLOOR(<datetime value expression> TO <time unit>)` is an Amazon Kinesis Data Analytics extension.
771/// See <https://docs.aws.amazon.com/kinesisanalytics/latest/sqlref/sql-reference-ceil.html> for
772/// details.
773///
774/// Other dialects either support `CEIL/FLOOR( <expr> [, <scale>])` format or just
775/// `CEIL/FLOOR(<expr>)`.
776#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
777#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
778#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
779pub enum CeilFloorKind {
780    /// `CEIL( <expr> TO <DateTimeField>)`
781    DateTimeField(DateTimeField),
782    /// `CEIL( <expr> [, <scale>])`
783    Scale(ValueWithSpan),
784}
785
786/// A WHEN clause in a CASE expression containing both
787/// the condition and its corresponding result
788#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
789#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
790#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
791pub struct CaseWhen {
792    /// The `WHEN` condition expression.
793    pub condition: Expr,
794    /// The expression returned when `condition` matches.
795    pub result: Expr,
796}
797
798impl fmt::Display for CaseWhen {
799    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
800        f.write_str("WHEN ")?;
801        self.condition.fmt(f)?;
802        f.write_str(" THEN")?;
803        SpaceOrNewline.fmt(f)?;
804        Indent(&self.result).fmt(f)?;
805        Ok(())
806    }
807}
808
809/// An SQL expression of any type.
810///
811/// # Semantics / Type Checking
812///
813/// The parser does not distinguish between expressions of different types
814/// (e.g. boolean vs string). The caller is responsible for detecting and
815/// validating types as necessary (for example  `WHERE 1` vs `SELECT 1=1`)
816/// See the [README.md] for more details.
817///
818/// [README.md]: https://github.com/apache/datafusion-sqlparser-rs/blob/main/README.md#syntax-vs-semantics
819///
820/// # Equality and Hashing Does not Include Source Locations
821///
822/// The `Expr` type implements `PartialEq` and `Eq` based on the semantic value
823/// of the expression (not bitwise comparison). This means that `Expr` instances
824/// that are semantically equivalent but have different spans (locations in the
825/// source tree) will compare as equal.
826#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
827#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
828#[cfg_attr(
829    feature = "visitor",
830    derive(Visit, VisitMut),
831    visit(with = "visit_expr")
832)]
833pub enum Expr {
834    /// Identifier e.g. table name or column name
835    Identifier(Ident),
836    /// Multi-part identifier, e.g. `table_alias.column` or `schema.table.col`
837    CompoundIdentifier(Vec<Ident>),
838    /// Multi-part expression access.
839    ///
840    /// This structure represents an access chain in structured / nested types
841    /// such as maps, arrays, and lists:
842    /// - Array
843    ///     - A 1-dim array `a[1]` will be represented like:
844    ///       `CompoundFieldAccess(Ident('a'), vec![Subscript(1)]`
845    ///     - A 2-dim array `a[1][2]` will be represented like:
846    ///       `CompoundFieldAccess(Ident('a'), vec![Subscript(1), Subscript(2)]`
847    /// - Map or Struct (Bracket-style)
848    ///     - A map `a['field1']` will be represented like:
849    ///       `CompoundFieldAccess(Ident('a'), vec![Subscript('field')]`
850    ///     - A 2-dim map `a['field1']['field2']` will be represented like:
851    ///       `CompoundFieldAccess(Ident('a'), vec![Subscript('field1'), Subscript('field2')]`
852    /// - Struct (Dot-style) (only effect when the chain contains both subscript and expr)
853    ///     - A struct access `a[field1].field2` will be represented like:
854    ///       `CompoundFieldAccess(Ident('a'), vec![Subscript('field1'), Ident('field2')]`
855    /// - If a struct access likes `a.field1.field2`, it will be represented by CompoundIdentifier([a, field1, field2])
856    CompoundFieldAccess {
857        /// The base expression being accessed.
858        root: Box<Expr>,
859        /// Sequence of access operations (subscript or identifier accesses).
860        access_chain: Vec<AccessExpr>,
861    },
862    /// Access data nested in a value containing semi-structured data, such as
863    /// the `VARIANT` type on Snowflake. for example `src:customer[0].name`.
864    ///
865    /// See <https://docs.snowflake.com/en/user-guide/querying-semistructured>.
866    /// See <https://docs.databricks.com/en/sql/language-manual/functions/colonsign.html>.
867    JsonAccess {
868        /// The value being queried.
869        value: Box<Expr>,
870        /// The path to the data to extract.
871        path: JsonPath,
872    },
873    /// `IS FALSE` operator
874    IsFalse(Box<Expr>),
875    /// `IS NOT FALSE` operator
876    IsNotFalse(Box<Expr>),
877    /// `IS TRUE` operator
878    IsTrue(Box<Expr>),
879    /// `IS NOT TRUE` operator
880    IsNotTrue(Box<Expr>),
881    /// `IS NULL` operator
882    IsNull(Box<Expr>),
883    /// `IS NOT NULL` operator
884    IsNotNull(Box<Expr>),
885    /// `IS UNKNOWN` operator
886    IsUnknown(Box<Expr>),
887    /// `IS NOT UNKNOWN` operator
888    IsNotUnknown(Box<Expr>),
889    /// `IS DISTINCT FROM` operator
890    IsDistinctFrom(Box<Expr>, Box<Expr>),
891    /// `IS NOT DISTINCT FROM` operator
892    IsNotDistinctFrom(Box<Expr>, Box<Expr>),
893    /// `<expr> IS [ NOT ] [ form ] NORMALIZED`
894    IsNormalized {
895        /// Expression being tested.
896        expr: Box<Expr>,
897        /// Optional normalization `form` (e.g., NFC, NFD).
898        form: Option<NormalizationForm>,
899        /// `true` when `NOT` is present.
900        negated: bool,
901    },
902    /// `[ NOT ] IN (val1, val2, ...)`
903    InList {
904        /// Left-hand expression to test for membership.
905        expr: Box<Expr>,
906        /// Literal list of expressions to check against.
907        list: Vec<Expr>,
908        /// `true` when the `NOT` modifier is present.
909        negated: bool,
910    },
911    /// `[ NOT ] IN (SELECT ...)`
912    InSubquery {
913        /// Left-hand expression to test for membership.
914        expr: Box<Expr>,
915        /// The subquery providing the candidate values.
916        subquery: Box<Query>,
917        /// `true` when the `NOT` modifier is present.
918        negated: bool,
919    },
920    /// `[ NOT ] IN UNNEST(array_expression)`
921    InUnnest {
922        /// Left-hand expression to test for membership.
923        expr: Box<Expr>,
924        /// Array expression being unnested.
925        array_expr: Box<Expr>,
926        /// `true` when the `NOT` modifier is present.
927        negated: bool,
928    },
929    /// `<expr> [ NOT ] BETWEEN <low> AND <high>`
930    Between {
931        /// Expression being compared.
932        expr: Box<Expr>,
933        /// `true` when the `NOT` modifier is present.
934        negated: bool,
935        /// Lower bound.
936        low: Box<Expr>,
937        /// Upper bound.
938        high: Box<Expr>,
939    },
940    /// Binary operation e.g. `1 + 1` or `foo > bar`
941    BinaryOp {
942        /// Left operand.
943        left: Box<Expr>,
944        /// Operator between operands.
945        op: BinaryOperator,
946        /// Right operand.
947        right: Box<Expr>,
948    },
949    /// `[NOT] LIKE <pattern> [ESCAPE <escape_character>]`
950    Like {
951        /// `true` when `NOT` is present.
952        negated: bool,
953        /// Snowflake supports the ANY keyword to match against a list of patterns
954        /// <https://docs.snowflake.com/en/sql-reference/functions/like_any>
955        any: bool,
956        /// Expression to match.
957        expr: Box<Expr>,
958        /// Pattern expression.
959        pattern: Box<Expr>,
960        /// Optional escape character.
961        escape_char: Option<ValueWithSpan>,
962    },
963    /// `ILIKE` (case-insensitive `LIKE`)
964    ILike {
965        /// `true` when `NOT` is present.
966        negated: bool,
967        /// Snowflake supports the ANY keyword to match against a list of patterns
968        /// <https://docs.snowflake.com/en/sql-reference/functions/like_any>
969        any: bool,
970        /// Expression to match.
971        expr: Box<Expr>,
972        /// Pattern expression.
973        pattern: Box<Expr>,
974        /// Optional escape character.
975        escape_char: Option<ValueWithSpan>,
976    },
977    /// `SIMILAR TO` regex
978    SimilarTo {
979        /// `true` when `NOT` is present.
980        negated: bool,
981        /// Expression to test.
982        expr: Box<Expr>,
983        /// Pattern expression.
984        pattern: Box<Expr>,
985        /// Optional escape character.
986        escape_char: Option<ValueWithSpan>,
987    },
988    /// MySQL: `RLIKE` regex or `REGEXP` regex
989    RLike {
990        /// `true` when `NOT` is present.
991        negated: bool,
992        /// Expression to test.
993        expr: Box<Expr>,
994        /// Pattern expression.
995        pattern: Box<Expr>,
996        /// true for REGEXP, false for RLIKE (no difference in semantics)
997        regexp: bool,
998    },
999    /// `ANY` operation e.g. `foo > ANY(bar)`, comparison operator is one of `[=, >, <, =>, =<, !=]`
1000    /// <https://docs.snowflake.com/en/sql-reference/operators-subquery#all-any>
1001    AnyOp {
1002        /// Left operand.
1003        left: Box<Expr>,
1004        /// Comparison operator.
1005        compare_op: BinaryOperator,
1006        /// Right-hand subquery expression.
1007        right: Box<Expr>,
1008        /// ANY and SOME are synonymous: <https://docs.cloudera.com/cdw-runtime/cloud/using-hiveql/topics/hive_comparison_predicates.html>
1009        is_some: bool,
1010    },
1011    /// `ALL` operation e.g. `foo > ALL(bar)`, comparison operator is one of `[=, >, <, =>, =<, !=]`
1012    /// <https://docs.snowflake.com/en/sql-reference/operators-subquery#all-any>
1013    AllOp {
1014        /// Left operand.
1015        left: Box<Expr>,
1016        /// Comparison operator.
1017        compare_op: BinaryOperator,
1018        /// Right-hand subquery expression.
1019        right: Box<Expr>,
1020    },
1021
1022    /// Unary operation e.g. `NOT foo`
1023    UnaryOp {
1024        /// The unary operator (e.g., `NOT`, `-`).
1025        op: UnaryOperator,
1026        /// Operand expression.
1027        expr: Box<Expr>,
1028    },
1029    /// CONVERT a value to a different data type or character encoding. e.g. `CONVERT(foo USING utf8mb4)`
1030    Convert {
1031        /// CONVERT (false) or TRY_CONVERT (true)
1032        /// <https://learn.microsoft.com/en-us/sql/t-sql/functions/try-convert-transact-sql?view=sql-server-ver16>
1033        is_try: bool,
1034        /// The expression to convert.
1035        expr: Box<Expr>,
1036        /// The target data type, if provided.
1037        data_type: Option<DataType>,
1038        /// Optional target character encoding (e.g., `utf8mb4`).
1039        charset: Option<ObjectName>,
1040        /// `true` when target precedes the value (MSSQL syntax).
1041        target_before_value: bool,
1042        /// How to translate the expression.
1043        ///
1044        /// [MSSQL]: https://learn.microsoft.com/en-us/sql/t-sql/functions/cast-and-convert-transact-sql?view=sql-server-ver16#style
1045        styles: Vec<Expr>,
1046    },
1047    /// `CAST` an expression to a different data type e.g. `CAST(foo AS VARCHAR(123))`
1048    Cast {
1049        /// The cast kind (e.g., `CAST`, `TRY_CAST`).
1050        kind: CastKind,
1051        /// Expression being cast.
1052        expr: Box<Expr>,
1053        /// Target data type.
1054        data_type: DataType,
1055        /// [MySQL] allows CAST(... AS type ARRAY) in functional index definitions for InnoDB
1056        /// multi-valued indices. It's not really a datatype, and is only allowed in `CAST` in key
1057        /// specifications, so it's a flag here.
1058        ///
1059        /// [MySQL]: https://dev.mysql.com/doc/refman/8.4/en/cast-functions.html#function_cast
1060        array: bool,
1061        /// Optional CAST(string_expression AS type FORMAT format_string_expression) as used by [BigQuery]
1062        ///
1063        /// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/format-elements#formatting_syntax
1064        format: Option<CastFormat>,
1065    },
1066    /// AT a timestamp to a different timezone e.g. `FROM_UNIXTIME(0) AT TIME ZONE 'UTC-06:00'`
1067    AtTimeZone {
1068        /// Timestamp expression to shift.
1069        timestamp: Box<Expr>,
1070        /// Time zone expression to apply.
1071        time_zone: Box<Expr>,
1072    },
1073    /// Extract a field from a timestamp e.g. `EXTRACT(MONTH FROM foo)`
1074    /// Or `EXTRACT(MONTH, foo)`
1075    ///
1076    /// Syntax:
1077    /// ```sql
1078    /// EXTRACT(DateTimeField FROM <expr>) | EXTRACT(DateTimeField, <expr>)
1079    /// ```
1080    Extract {
1081        /// Which datetime field is being extracted.
1082        field: DateTimeField,
1083        /// Syntax variant used (`From` or `Comma`).
1084        syntax: ExtractSyntax,
1085        /// Expression to extract from.
1086        expr: Box<Expr>,
1087    },
1088    /// ```sql
1089    /// CEIL(<expr> [TO DateTimeField])
1090    /// ```
1091    /// ```sql
1092    /// CEIL( <input_expr> [, <scale_expr> ] )
1093    /// ```
1094    Ceil {
1095        /// Expression to ceil.
1096        expr: Box<Expr>,
1097        /// The CEIL/FLOOR kind (datetime field or scale).
1098        field: CeilFloorKind,
1099    },
1100    /// ```sql
1101    /// FLOOR(<expr> [TO DateTimeField])
1102    /// ```
1103    /// ```sql
1104    /// FLOOR( <input_expr> [, <scale_expr> ] )
1105    ///
1106    Floor {
1107        /// Expression to floor.
1108        expr: Box<Expr>,
1109        /// The CEIL/FLOOR kind (datetime field or scale).
1110        field: CeilFloorKind,
1111    },
1112    /// ```sql
1113    /// POSITION(<expr> in <expr>)
1114    /// ```
1115    Position {
1116        /// Expression to search for.
1117        expr: Box<Expr>,
1118        /// Expression to search in.
1119        r#in: Box<Expr>,
1120    },
1121    /// ```sql
1122    /// SUBSTRING(<expr> [FROM <expr>] [FOR <expr>])
1123    /// ```
1124    /// or
1125    /// ```sql
1126    /// SUBSTRING(<expr>, <expr>, <expr>)
1127    /// ```
1128    Substring {
1129        /// Source expression.
1130        expr: Box<Expr>,
1131        /// Optional `FROM` expression.
1132        substring_from: Option<Box<Expr>>,
1133        /// Optional `FOR` expression.
1134        substring_for: Option<Box<Expr>>,
1135
1136        /// false if the expression is represented using the `SUBSTRING(expr [FROM start] [FOR len])` syntax
1137        /// true if the expression is represented using the `SUBSTRING(expr, start, len)` syntax
1138        /// This flag is used for formatting.
1139        special: bool,
1140
1141        /// true if the expression is represented using the `SUBSTR` shorthand
1142        /// This flag is used for formatting.
1143        shorthand: bool,
1144    },
1145    /// ```sql
1146    /// TRIM([BOTH | LEADING | TRAILING] [<expr> FROM] <expr>)
1147    /// TRIM(<expr>)
1148    /// TRIM(<expr>, [, characters]) -- PostgreSQL, DuckDB, Snowflake, BigQuery, Generic
1149    /// ```
1150    Trim {
1151        /// Which side to trim: `BOTH`, `LEADING`, or `TRAILING`.
1152        trim_where: Option<TrimWhereField>,
1153        /// Optional expression specifying what to trim from the value `expr`.
1154        trim_what: Option<Box<Expr>>,
1155        /// The expression to trim from.
1156        expr: Box<Expr>,
1157        /// Optional list of characters to trim (dialect-specific).
1158        trim_characters: Option<Vec<Expr>>,
1159    },
1160    /// ```sql
1161    /// OVERLAY(<expr> PLACING <expr> FROM <expr>[ FOR <expr> ]
1162    /// ```
1163    Overlay {
1164        /// The target expression being overlayed.
1165        expr: Box<Expr>,
1166        /// The expression to place into the target.
1167        overlay_what: Box<Expr>,
1168        /// The `FROM` position expression indicating where to start overlay.
1169        overlay_from: Box<Expr>,
1170        /// Optional `FOR` length expression limiting the overlay span.
1171        overlay_for: Option<Box<Expr>>,
1172    },
1173    /// `expr COLLATE collation`
1174    Collate {
1175        /// The expression being collated.
1176        expr: Box<Expr>,
1177        /// The collation name to apply to the expression.
1178        collation: ObjectName,
1179    },
1180    /// Nested expression e.g. `(foo > bar)` or `(1)`
1181    Nested(Box<Expr>),
1182    /// A literal value, such as string, number, date or NULL
1183    Value(ValueWithSpan),
1184    /// Prefixed expression, e.g. introducer strings, projection prefix
1185    /// <https://dev.mysql.com/doc/refman/8.0/en/charset-introducer.html>
1186    /// <https://docs.snowflake.com/en/sql-reference/constructs/connect-by>
1187    Prefixed {
1188        /// The prefix identifier (introducer or projection prefix).
1189        prefix: Ident,
1190        /// The value expression being prefixed.
1191        /// Hint: you can unwrap the string value using `value.into_string()`.
1192        value: Box<Expr>,
1193    },
1194    /// A constant of form `<data_type> 'value'`.
1195    /// This can represent ANSI SQL `DATE`, `TIME`, and `TIMESTAMP` literals (such as `DATE '2020-01-01'`),
1196    /// as well as constants of other types (a non-standard PostgreSQL extension).
1197    TypedString(TypedString),
1198    /// Scalar function call e.g. `LEFT(foo, 5)`
1199    Function(Function),
1200    /// `CASE [<operand>] WHEN <condition> THEN <result> ... [ELSE <result>] END`
1201    ///
1202    /// Note we only recognize a complete single expression as `<condition>`,
1203    /// not `< 0` nor `1, 2, 3` as allowed in a `<simple when clause>` per
1204    /// <https://jakewheat.github.io/sql-overview/sql-2011-foundation-grammar.html#simple-when-clause>
1205    Case {
1206        /// The attached `CASE` token (keeps original spacing/comments).
1207        case_token: AttachedToken,
1208        /// The attached `END` token (keeps original spacing/comments).
1209        end_token: AttachedToken,
1210        /// Optional operand expression after `CASE` (for simple CASE).
1211        operand: Option<Box<Expr>>,
1212        /// The `WHEN ... THEN` conditions and results.
1213        conditions: Vec<CaseWhen>,
1214        /// Optional `ELSE` result expression.
1215        else_result: Option<Box<Expr>>,
1216    },
1217    /// An exists expression `[ NOT ] EXISTS(SELECT ...)`, used in expressions like
1218    /// `WHERE [ NOT ] EXISTS (SELECT ...)`.
1219    Exists {
1220        /// The subquery checked by `EXISTS`.
1221        subquery: Box<Query>,
1222        /// Whether the `EXISTS` is negated (`NOT EXISTS`).
1223        negated: bool,
1224    },
1225    /// A parenthesized subquery `(SELECT ...)`, used in expression like
1226    /// `SELECT (subquery) AS x` or `WHERE (subquery) = x`
1227    Subquery(Box<Query>),
1228    /// The `GROUPING SETS` expr.
1229    GroupingSets(Vec<Vec<Expr>>),
1230    /// The `CUBE` expr.
1231    Cube(Vec<Vec<Expr>>),
1232    /// The `ROLLUP` expr.
1233    Rollup(Vec<Vec<Expr>>),
1234    /// ROW / TUPLE a single value, such as `SELECT (1, 2)`
1235    Tuple(Vec<Expr>),
1236    /// `Struct` literal expression
1237    /// Syntax:
1238    /// ```sql
1239    /// STRUCT<[field_name] field_type, ...>( expr1 [, ... ])
1240    ///
1241    /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-types#struct_type)
1242    /// [Databricks](https://docs.databricks.com/en/sql/language-manual/functions/struct.html)
1243    /// ```
1244    Struct {
1245        /// Struct values.
1246        values: Vec<Expr>,
1247        /// Struct field definitions.
1248        fields: Vec<StructField>,
1249    },
1250    /// `BigQuery` specific: An named expression in a typeless struct [1]
1251    ///
1252    /// Syntax
1253    /// ```sql
1254    /// 1 AS A
1255    /// ```
1256    /// [1]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-types#struct_type
1257    Named {
1258        /// The expression being named.
1259        expr: Box<Expr>,
1260        /// The assigned identifier name for the expression.
1261        name: Ident,
1262    },
1263    /// `DuckDB` specific `Struct` literal expression [1]
1264    ///
1265    /// Syntax:
1266    /// ```sql
1267    /// syntax: {'field_name': expr1[, ... ]}
1268    /// ```
1269    /// [1]: https://duckdb.org/docs/sql/data_types/struct#creating-structs
1270    Dictionary(Vec<DictionaryField>),
1271    /// `DuckDB` specific `Map` literal expression [1]
1272    ///
1273    /// Syntax:
1274    /// ```sql
1275    /// syntax: Map {key1: value1[, ... ]}
1276    /// ```
1277    /// [1]: https://duckdb.org/docs/sql/data_types/map#creating-maps
1278    Map(Map),
1279    /// An array expression e.g. `ARRAY[1, 2]`
1280    Array(Array),
1281    /// An interval expression e.g. `INTERVAL '1' YEAR`
1282    Interval(Interval),
1283    /// `MySQL` specific text search function [(1)].
1284    ///
1285    /// Syntax:
1286    /// ```sql
1287    /// MATCH (<col>, <col>, ...) AGAINST (<expr> [<search modifier>])
1288    ///
1289    /// <col> = CompoundIdentifier
1290    /// <expr> = String literal
1291    /// ```
1292    /// [(1)]: https://dev.mysql.com/doc/refman/8.0/en/fulltext-search.html#function_match
1293    MatchAgainst {
1294        /// `(<col>, <col>, ...)`.
1295        columns: Vec<ObjectName>,
1296        /// `<expr>`.
1297        match_value: ValueWithSpan,
1298        /// `<search modifier>`
1299        opt_search_modifier: Option<SearchModifier>,
1300    },
1301    /// An unqualified `*` wildcard token (e.g. `*`).
1302    Wildcard(AttachedToken),
1303    /// Qualified wildcard, e.g. `alias.*` or `schema.table.*`.
1304    /// (Same caveats apply to `QualifiedWildcard` as to `Wildcard`.)
1305    QualifiedWildcard(ObjectName, AttachedToken),
1306    /// Some dialects support an older syntax for outer joins where columns are
1307    /// marked with the `(+)` operator in the WHERE clause, for example:
1308    ///
1309    /// ```sql
1310    /// SELECT t1.c1, t2.c2 FROM t1, t2 WHERE t1.c1 = t2.c2 (+)
1311    /// ```
1312    ///
1313    /// which is equivalent to
1314    ///
1315    /// ```sql
1316    /// SELECT t1.c1, t2.c2 FROM t1 LEFT OUTER JOIN t2 ON t1.c1 = t2.c2
1317    /// ```
1318    ///
1319    /// See <https://docs.snowflake.com/en/sql-reference/constructs/where#joins-in-the-where-clause>.
1320    OuterJoin(Box<Expr>),
1321    /// A reference to the prior level in a CONNECT BY clause.
1322    Prior(Box<Expr>),
1323    /// A lambda function.
1324    ///
1325    /// Syntax:
1326    /// ```plaintext
1327    /// param -> expr | (param1, ...) -> expr
1328    /// ```
1329    ///
1330    /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/functions#higher-order-functions---operator-and-lambdaparams-expr-function)
1331    /// [Databricks](https://docs.databricks.com/en/sql/language-manual/sql-ref-lambda-functions.html)
1332    /// [DuckDB](https://duckdb.org/docs/stable/sql/functions/lambda)
1333    Lambda(LambdaFunction),
1334    /// Checks membership of a value in a JSON array
1335    MemberOf(MemberOf),
1336}
1337
1338impl Expr {
1339    /// Creates a new [`Expr::Value`]
1340    pub fn value(value: impl Into<ValueWithSpan>) -> Self {
1341        Expr::Value(value.into())
1342    }
1343}
1344
1345/// The contents inside the `[` and `]` in a subscript expression.
1346#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1347#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1348#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1349pub enum Subscript {
1350    /// Accesses the element of the array at the given index.
1351    Index {
1352        /// The index expression used to access the array element.
1353        index: Expr,
1354    },
1355
1356    /// Accesses a slice of an array on PostgreSQL, e.g.
1357    ///
1358    /// ```plaintext
1359    /// => select (array[1,2,3,4,5,6])[2:5];
1360    /// -----------
1361    /// {2,3,4,5}
1362    /// ```
1363    ///
1364    /// The lower and/or upper bound can be omitted to slice from the start or
1365    /// end of the array respectively.
1366    ///
1367    /// See <https://www.postgresql.org/docs/current/arrays.html#ARRAYS-ACCESSING>.
1368    ///
1369    /// Also supports an optional "stride" as the last element (this is not
1370    /// supported by postgres), e.g.
1371    ///
1372    /// ```plaintext
1373    /// => select (array[1,2,3,4,5,6])[1:6:2];
1374    /// -----------
1375    /// {1,3,5}
1376    /// ```
1377    Slice {
1378        /// Optional lower bound for the slice (inclusive).
1379        lower_bound: Option<Expr>,
1380        /// Optional upper bound for the slice (inclusive).
1381        upper_bound: Option<Expr>,
1382        /// Optional stride for the slice (step size).
1383        stride: Option<Expr>,
1384    },
1385}
1386
1387impl fmt::Display for Subscript {
1388    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1389        match self {
1390            Subscript::Index { index } => write!(f, "{index}"),
1391            Subscript::Slice {
1392                lower_bound,
1393                upper_bound,
1394                stride,
1395            } => {
1396                if let Some(lower) = lower_bound {
1397                    write!(f, "{lower}")?;
1398                }
1399                write!(f, ":")?;
1400                if let Some(upper) = upper_bound {
1401                    write!(f, "{upper}")?;
1402                }
1403                if let Some(stride) = stride {
1404                    write!(f, ":")?;
1405                    write!(f, "{stride}")?;
1406                }
1407                Ok(())
1408            }
1409        }
1410    }
1411}
1412
1413/// An element of a [`Expr::CompoundFieldAccess`].
1414/// It can be an expression or a subscript.
1415#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1416#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1417#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1418pub enum AccessExpr {
1419    /// Accesses a field using dot notation, e.g. `foo.bar.baz`.
1420    Dot(Expr),
1421    /// Accesses a field or array element using bracket notation, e.g. `foo['bar']`.
1422    Subscript(Subscript),
1423}
1424
1425impl fmt::Display for AccessExpr {
1426    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1427        match self {
1428            AccessExpr::Dot(expr) => write!(f, ".{expr}"),
1429            AccessExpr::Subscript(subscript) => write!(f, "[{subscript}]"),
1430        }
1431    }
1432}
1433
1434/// A lambda function.
1435#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1436#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1437#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1438pub struct LambdaFunction {
1439    /// The parameters to the lambda function.
1440    pub params: OneOrManyWithParens<LambdaFunctionParameter>,
1441    /// The body of the lambda function.
1442    pub body: Box<Expr>,
1443    /// The syntax style used to write the lambda function.
1444    pub syntax: LambdaSyntax,
1445}
1446
1447impl fmt::Display for LambdaFunction {
1448    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1449        match self.syntax {
1450            LambdaSyntax::Arrow => write!(f, "{} -> {}", self.params, self.body),
1451            LambdaSyntax::LambdaKeyword => {
1452                // For lambda keyword syntax, display params without parentheses
1453                // e.g., `lambda x, y : expr` not `lambda (x, y) : expr`
1454                write!(f, "lambda ")?;
1455                match &self.params {
1456                    OneOrManyWithParens::One(p) => write!(f, "{p}")?,
1457                    OneOrManyWithParens::Many(ps) => write!(f, "{}", display_comma_separated(ps))?,
1458                };
1459                write!(f, " : {}", self.body)
1460            }
1461        }
1462    }
1463}
1464
1465/// A parameter to a lambda function, optionally with a data type.
1466#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1467#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1468#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1469pub struct LambdaFunctionParameter {
1470    /// The name of the parameter
1471    pub name: Ident,
1472    /// The optional data type of the parameter
1473    /// [Snowflake Syntax](https://docs.snowflake.com/en/sql-reference/functions/filter#arguments)
1474    pub data_type: Option<DataType>,
1475}
1476
1477impl fmt::Display for LambdaFunctionParameter {
1478    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1479        match &self.data_type {
1480            Some(dt) => write!(f, "{} {}", self.name, dt),
1481            None => write!(f, "{}", self.name),
1482        }
1483    }
1484}
1485
1486/// The syntax style for a lambda function.
1487#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Copy)]
1488#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1489#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1490pub enum LambdaSyntax {
1491    /// Arrow syntax: `param -> expr` or `(param1, param2) -> expr`
1492    ///
1493    /// <https://docs.databricks.com/aws/en/sql/language-manual/sql-ref-lambda-functions>
1494    ///
1495    /// Supported, but deprecated in DuckDB:
1496    /// <https://duckdb.org/docs/stable/sql/functions/lambda>
1497    Arrow,
1498    /// Lambda keyword syntax: `lambda param : expr` or `lambda param1, param2 : expr`
1499    ///
1500    /// Recommended in DuckDB:
1501    /// <https://duckdb.org/docs/stable/sql/functions/lambda>
1502    LambdaKeyword,
1503}
1504
1505/// Encapsulates the common pattern in SQL where either one unparenthesized item
1506/// such as an identifier or expression is permitted, or multiple of the same
1507/// item in a parenthesized list. For accessing items regardless of the form,
1508/// `OneOrManyWithParens` implements `Deref<Target = [T]>` and `IntoIterator`,
1509/// so you can call slice methods on it and iterate over items
1510/// # Examples
1511/// Accessing as a slice:
1512/// ```
1513/// # use sqlparser::ast::OneOrManyWithParens;
1514/// let one = OneOrManyWithParens::One("a");
1515///
1516/// assert_eq!(one[0], "a");
1517/// assert_eq!(one.len(), 1);
1518/// ```
1519/// Iterating:
1520/// ```
1521/// # use sqlparser::ast::OneOrManyWithParens;
1522/// let one = OneOrManyWithParens::One("a");
1523/// let many = OneOrManyWithParens::Many(vec!["a", "b"]);
1524///
1525/// assert_eq!(one.into_iter().chain(many).collect::<Vec<_>>(), vec!["a", "a", "b"] );
1526/// ```
1527#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1528#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1529#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1530pub enum OneOrManyWithParens<T> {
1531    /// A single `T`, unparenthesized.
1532    One(T),
1533    /// One or more `T`s, parenthesized.
1534    Many(Vec<T>),
1535}
1536
1537impl<T> Deref for OneOrManyWithParens<T> {
1538    type Target = [T];
1539
1540    fn deref(&self) -> &[T] {
1541        match self {
1542            OneOrManyWithParens::One(one) => core::slice::from_ref(one),
1543            OneOrManyWithParens::Many(many) => many,
1544        }
1545    }
1546}
1547
1548impl<T> AsRef<[T]> for OneOrManyWithParens<T> {
1549    fn as_ref(&self) -> &[T] {
1550        self
1551    }
1552}
1553
1554impl<'a, T> IntoIterator for &'a OneOrManyWithParens<T> {
1555    type Item = &'a T;
1556    type IntoIter = core::slice::Iter<'a, T>;
1557
1558    fn into_iter(self) -> Self::IntoIter {
1559        self.iter()
1560    }
1561}
1562
1563/// Owned iterator implementation of `OneOrManyWithParens`
1564#[derive(Debug, Clone)]
1565pub struct OneOrManyWithParensIntoIter<T> {
1566    inner: OneOrManyWithParensIntoIterInner<T>,
1567}
1568
1569#[derive(Debug, Clone)]
1570enum OneOrManyWithParensIntoIterInner<T> {
1571    One(core::iter::Once<T>),
1572    Many(<Vec<T> as IntoIterator>::IntoIter),
1573}
1574
1575impl<T> core::iter::FusedIterator for OneOrManyWithParensIntoIter<T>
1576where
1577    core::iter::Once<T>: core::iter::FusedIterator,
1578    <Vec<T> as IntoIterator>::IntoIter: core::iter::FusedIterator,
1579{
1580}
1581
1582impl<T> core::iter::ExactSizeIterator for OneOrManyWithParensIntoIter<T>
1583where
1584    core::iter::Once<T>: core::iter::ExactSizeIterator,
1585    <Vec<T> as IntoIterator>::IntoIter: core::iter::ExactSizeIterator,
1586{
1587}
1588
1589impl<T> core::iter::Iterator for OneOrManyWithParensIntoIter<T> {
1590    type Item = T;
1591
1592    fn next(&mut self) -> Option<Self::Item> {
1593        match &mut self.inner {
1594            OneOrManyWithParensIntoIterInner::One(one) => one.next(),
1595            OneOrManyWithParensIntoIterInner::Many(many) => many.next(),
1596        }
1597    }
1598
1599    fn size_hint(&self) -> (usize, Option<usize>) {
1600        match &self.inner {
1601            OneOrManyWithParensIntoIterInner::One(one) => one.size_hint(),
1602            OneOrManyWithParensIntoIterInner::Many(many) => many.size_hint(),
1603        }
1604    }
1605
1606    fn count(self) -> usize
1607    where
1608        Self: Sized,
1609    {
1610        match self.inner {
1611            OneOrManyWithParensIntoIterInner::One(one) => one.count(),
1612            OneOrManyWithParensIntoIterInner::Many(many) => many.count(),
1613        }
1614    }
1615
1616    fn fold<B, F>(mut self, init: B, f: F) -> B
1617    where
1618        Self: Sized,
1619        F: FnMut(B, Self::Item) -> B,
1620    {
1621        match &mut self.inner {
1622            OneOrManyWithParensIntoIterInner::One(one) => one.fold(init, f),
1623            OneOrManyWithParensIntoIterInner::Many(many) => many.fold(init, f),
1624        }
1625    }
1626}
1627
1628impl<T> core::iter::DoubleEndedIterator for OneOrManyWithParensIntoIter<T> {
1629    fn next_back(&mut self) -> Option<Self::Item> {
1630        match &mut self.inner {
1631            OneOrManyWithParensIntoIterInner::One(one) => one.next_back(),
1632            OneOrManyWithParensIntoIterInner::Many(many) => many.next_back(),
1633        }
1634    }
1635}
1636
1637impl<T> IntoIterator for OneOrManyWithParens<T> {
1638    type Item = T;
1639
1640    type IntoIter = OneOrManyWithParensIntoIter<T>;
1641
1642    fn into_iter(self) -> Self::IntoIter {
1643        let inner = match self {
1644            OneOrManyWithParens::One(one) => {
1645                OneOrManyWithParensIntoIterInner::One(core::iter::once(one))
1646            }
1647            OneOrManyWithParens::Many(many) => {
1648                OneOrManyWithParensIntoIterInner::Many(many.into_iter())
1649            }
1650        };
1651
1652        OneOrManyWithParensIntoIter { inner }
1653    }
1654}
1655
1656impl<T> fmt::Display for OneOrManyWithParens<T>
1657where
1658    T: fmt::Display,
1659{
1660    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1661        match self {
1662            OneOrManyWithParens::One(value) => write!(f, "{value}"),
1663            OneOrManyWithParens::Many(values) => {
1664                write!(f, "({})", display_comma_separated(values))
1665            }
1666        }
1667    }
1668}
1669
1670impl fmt::Display for CastFormat {
1671    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1672        match self {
1673            CastFormat::Value(v) => write!(f, "{v}"),
1674            CastFormat::ValueAtTimeZone(v, tz) => write!(f, "{v} AT TIME ZONE {tz}"),
1675        }
1676    }
1677}
1678
1679impl fmt::Display for Expr {
1680    #[cfg_attr(feature = "recursive-protection", recursive::recursive)]
1681    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1682        match self {
1683            Expr::Identifier(s) => write!(f, "{s}"),
1684            Expr::Wildcard(_) => f.write_str("*"),
1685            Expr::QualifiedWildcard(prefix, _) => write!(f, "{prefix}.*"),
1686            Expr::CompoundIdentifier(s) => write!(f, "{}", display_separated(s, ".")),
1687            Expr::CompoundFieldAccess { root, access_chain } => {
1688                write!(f, "{root}")?;
1689                for field in access_chain {
1690                    write!(f, "{field}")?;
1691                }
1692                Ok(())
1693            }
1694            Expr::IsTrue(ast) => write!(f, "{ast} IS TRUE"),
1695            Expr::IsNotTrue(ast) => write!(f, "{ast} IS NOT TRUE"),
1696            Expr::IsFalse(ast) => write!(f, "{ast} IS FALSE"),
1697            Expr::IsNotFalse(ast) => write!(f, "{ast} IS NOT FALSE"),
1698            Expr::IsNull(ast) => write!(f, "{ast} IS NULL"),
1699            Expr::IsNotNull(ast) => write!(f, "{ast} IS NOT NULL"),
1700            Expr::IsUnknown(ast) => write!(f, "{ast} IS UNKNOWN"),
1701            Expr::IsNotUnknown(ast) => write!(f, "{ast} IS NOT UNKNOWN"),
1702            Expr::InList {
1703                expr,
1704                list,
1705                negated,
1706            } => write!(
1707                f,
1708                "{} {}IN ({})",
1709                expr,
1710                if *negated { "NOT " } else { "" },
1711                display_comma_separated(list)
1712            ),
1713            Expr::InSubquery {
1714                expr,
1715                subquery,
1716                negated,
1717            } => write!(
1718                f,
1719                "{} {}IN ({})",
1720                expr,
1721                if *negated { "NOT " } else { "" },
1722                subquery
1723            ),
1724            Expr::InUnnest {
1725                expr,
1726                array_expr,
1727                negated,
1728            } => write!(
1729                f,
1730                "{} {}IN UNNEST({})",
1731                expr,
1732                if *negated { "NOT " } else { "" },
1733                array_expr
1734            ),
1735            Expr::Between {
1736                expr,
1737                negated,
1738                low,
1739                high,
1740            } => write!(
1741                f,
1742                "{} {}BETWEEN {} AND {}",
1743                expr,
1744                if *negated { "NOT " } else { "" },
1745                low,
1746                high
1747            ),
1748            Expr::BinaryOp { left, op, right } => write!(f, "{left} {op} {right}"),
1749            Expr::Like {
1750                negated,
1751                expr,
1752                pattern,
1753                escape_char,
1754                any,
1755            } => match escape_char {
1756                Some(ch) => write!(
1757                    f,
1758                    "{} {}LIKE {}{} ESCAPE {}",
1759                    expr,
1760                    if *negated { "NOT " } else { "" },
1761                    if *any { "ANY " } else { "" },
1762                    pattern,
1763                    ch
1764                ),
1765                _ => write!(
1766                    f,
1767                    "{} {}LIKE {}{}",
1768                    expr,
1769                    if *negated { "NOT " } else { "" },
1770                    if *any { "ANY " } else { "" },
1771                    pattern
1772                ),
1773            },
1774            Expr::ILike {
1775                negated,
1776                expr,
1777                pattern,
1778                escape_char,
1779                any,
1780            } => match escape_char {
1781                Some(ch) => write!(
1782                    f,
1783                    "{} {}ILIKE {}{} ESCAPE {}",
1784                    expr,
1785                    if *negated { "NOT " } else { "" },
1786                    if *any { "ANY" } else { "" },
1787                    pattern,
1788                    ch
1789                ),
1790                _ => write!(
1791                    f,
1792                    "{} {}ILIKE {}{}",
1793                    expr,
1794                    if *negated { "NOT " } else { "" },
1795                    if *any { "ANY " } else { "" },
1796                    pattern
1797                ),
1798            },
1799            Expr::RLike {
1800                negated,
1801                expr,
1802                pattern,
1803                regexp,
1804            } => write!(
1805                f,
1806                "{} {}{} {}",
1807                expr,
1808                if *negated { "NOT " } else { "" },
1809                if *regexp { "REGEXP" } else { "RLIKE" },
1810                pattern
1811            ),
1812            Expr::IsNormalized {
1813                expr,
1814                form,
1815                negated,
1816            } => {
1817                let not_ = if *negated { "NOT " } else { "" };
1818                if form.is_none() {
1819                    write!(f, "{expr} IS {not_}NORMALIZED")
1820                } else {
1821                    write!(
1822                        f,
1823                        "{} IS {}{} NORMALIZED",
1824                        expr,
1825                        not_,
1826                        form.as_ref().unwrap()
1827                    )
1828                }
1829            }
1830            Expr::SimilarTo {
1831                negated,
1832                expr,
1833                pattern,
1834                escape_char,
1835            } => match escape_char {
1836                Some(ch) => write!(
1837                    f,
1838                    "{} {}SIMILAR TO {} ESCAPE {}",
1839                    expr,
1840                    if *negated { "NOT " } else { "" },
1841                    pattern,
1842                    ch
1843                ),
1844                _ => write!(
1845                    f,
1846                    "{} {}SIMILAR TO {}",
1847                    expr,
1848                    if *negated { "NOT " } else { "" },
1849                    pattern
1850                ),
1851            },
1852            Expr::AnyOp {
1853                left,
1854                compare_op,
1855                right,
1856                is_some,
1857            } => {
1858                let add_parens = !matches!(right.as_ref(), Expr::Subquery(_));
1859                write!(
1860                    f,
1861                    "{left} {compare_op} {}{}{right}{}",
1862                    if *is_some { "SOME" } else { "ANY" },
1863                    if add_parens { "(" } else { "" },
1864                    if add_parens { ")" } else { "" },
1865                )
1866            }
1867            Expr::AllOp {
1868                left,
1869                compare_op,
1870                right,
1871            } => {
1872                let add_parens = !matches!(right.as_ref(), Expr::Subquery(_));
1873                write!(
1874                    f,
1875                    "{left} {compare_op} ALL{}{right}{}",
1876                    if add_parens { "(" } else { "" },
1877                    if add_parens { ")" } else { "" },
1878                )
1879            }
1880            Expr::UnaryOp { op, expr } => {
1881                if op == &UnaryOperator::PGPostfixFactorial {
1882                    write!(f, "{expr}{op}")
1883                } else if matches!(
1884                    op,
1885                    UnaryOperator::Not
1886                        | UnaryOperator::Hash
1887                        | UnaryOperator::AtDashAt
1888                        | UnaryOperator::DoubleAt
1889                        | UnaryOperator::QuestionDash
1890                        | UnaryOperator::QuestionPipe
1891                ) {
1892                    write!(f, "{op} {expr}")
1893                } else {
1894                    write!(f, "{op}{expr}")
1895                }
1896            }
1897            Expr::Convert {
1898                is_try,
1899                expr,
1900                target_before_value,
1901                data_type,
1902                charset,
1903                styles,
1904            } => {
1905                write!(f, "{}CONVERT(", if *is_try { "TRY_" } else { "" })?;
1906                if let Some(data_type) = data_type {
1907                    if let Some(charset) = charset {
1908                        write!(f, "{expr}, {data_type} CHARACTER SET {charset}")
1909                    } else if *target_before_value {
1910                        write!(f, "{data_type}, {expr}")
1911                    } else {
1912                        write!(f, "{expr}, {data_type}")
1913                    }
1914                } else if let Some(charset) = charset {
1915                    write!(f, "{expr} USING {charset}")
1916                } else {
1917                    write!(f, "{expr}") // This should never happen
1918                }?;
1919                if !styles.is_empty() {
1920                    write!(f, ", {}", display_comma_separated(styles))?;
1921                }
1922                write!(f, ")")
1923            }
1924            Expr::Cast {
1925                kind,
1926                expr,
1927                data_type,
1928                array,
1929                format,
1930            } => match kind {
1931                CastKind::Cast => {
1932                    write!(f, "CAST({expr} AS {data_type}")?;
1933                    if *array {
1934                        write!(f, " ARRAY")?;
1935                    }
1936                    if let Some(format) = format {
1937                        write!(f, " FORMAT {format}")?;
1938                    }
1939                    write!(f, ")")
1940                }
1941                CastKind::TryCast => {
1942                    if let Some(format) = format {
1943                        write!(f, "TRY_CAST({expr} AS {data_type} FORMAT {format})")
1944                    } else {
1945                        write!(f, "TRY_CAST({expr} AS {data_type})")
1946                    }
1947                }
1948                CastKind::SafeCast => {
1949                    if let Some(format) = format {
1950                        write!(f, "SAFE_CAST({expr} AS {data_type} FORMAT {format})")
1951                    } else {
1952                        write!(f, "SAFE_CAST({expr} AS {data_type})")
1953                    }
1954                }
1955                CastKind::DoubleColon => {
1956                    write!(f, "{expr}::{data_type}")
1957                }
1958            },
1959            Expr::Extract {
1960                field,
1961                syntax,
1962                expr,
1963            } => match syntax {
1964                ExtractSyntax::From => write!(f, "EXTRACT({field} FROM {expr})"),
1965                ExtractSyntax::Comma => write!(f, "EXTRACT({field}, {expr})"),
1966            },
1967            Expr::Ceil { expr, field } => match field {
1968                CeilFloorKind::DateTimeField(DateTimeField::NoDateTime) => {
1969                    write!(f, "CEIL({expr})")
1970                }
1971                CeilFloorKind::DateTimeField(dt_field) => write!(f, "CEIL({expr} TO {dt_field})"),
1972                CeilFloorKind::Scale(s) => write!(f, "CEIL({expr}, {s})"),
1973            },
1974            Expr::Floor { expr, field } => match field {
1975                CeilFloorKind::DateTimeField(DateTimeField::NoDateTime) => {
1976                    write!(f, "FLOOR({expr})")
1977                }
1978                CeilFloorKind::DateTimeField(dt_field) => write!(f, "FLOOR({expr} TO {dt_field})"),
1979                CeilFloorKind::Scale(s) => write!(f, "FLOOR({expr}, {s})"),
1980            },
1981            Expr::Position { expr, r#in } => write!(f, "POSITION({expr} IN {in})"),
1982            Expr::Collate { expr, collation } => write!(f, "{expr} COLLATE {collation}"),
1983            Expr::Nested(ast) => write!(f, "({ast})"),
1984            Expr::Value(v) => write!(f, "{v}"),
1985            Expr::Prefixed { prefix, value } => write!(f, "{prefix} {value}"),
1986            Expr::TypedString(ts) => ts.fmt(f),
1987            Expr::Function(fun) => fun.fmt(f),
1988            Expr::Case {
1989                case_token: _,
1990                end_token: _,
1991                operand,
1992                conditions,
1993                else_result,
1994            } => {
1995                f.write_str("CASE")?;
1996                if let Some(operand) = operand {
1997                    f.write_str(" ")?;
1998                    operand.fmt(f)?;
1999                }
2000                for when in conditions {
2001                    SpaceOrNewline.fmt(f)?;
2002                    Indent(when).fmt(f)?;
2003                }
2004                if let Some(else_result) = else_result {
2005                    SpaceOrNewline.fmt(f)?;
2006                    Indent("ELSE").fmt(f)?;
2007                    SpaceOrNewline.fmt(f)?;
2008                    Indent(Indent(else_result)).fmt(f)?;
2009                }
2010                SpaceOrNewline.fmt(f)?;
2011                f.write_str("END")
2012            }
2013            Expr::Exists { subquery, negated } => write!(
2014                f,
2015                "{}EXISTS ({})",
2016                if *negated { "NOT " } else { "" },
2017                subquery
2018            ),
2019            Expr::Subquery(s) => write!(f, "({s})"),
2020            Expr::GroupingSets(sets) => {
2021                write!(f, "GROUPING SETS (")?;
2022                let mut sep = "";
2023                for set in sets {
2024                    write!(f, "{sep}")?;
2025                    sep = ", ";
2026                    write!(f, "({})", display_comma_separated(set))?;
2027                }
2028                write!(f, ")")
2029            }
2030            Expr::Cube(sets) => {
2031                write!(f, "CUBE (")?;
2032                let mut sep = "";
2033                for set in sets {
2034                    write!(f, "{sep}")?;
2035                    sep = ", ";
2036                    if set.len() == 1 {
2037                        write!(f, "{}", set[0])?;
2038                    } else {
2039                        write!(f, "({})", display_comma_separated(set))?;
2040                    }
2041                }
2042                write!(f, ")")
2043            }
2044            Expr::Rollup(sets) => {
2045                write!(f, "ROLLUP (")?;
2046                let mut sep = "";
2047                for set in sets {
2048                    write!(f, "{sep}")?;
2049                    sep = ", ";
2050                    if set.len() == 1 {
2051                        write!(f, "{}", set[0])?;
2052                    } else {
2053                        write!(f, "({})", display_comma_separated(set))?;
2054                    }
2055                }
2056                write!(f, ")")
2057            }
2058            Expr::Substring {
2059                expr,
2060                substring_from,
2061                substring_for,
2062                special,
2063                shorthand,
2064            } => {
2065                f.write_str("SUBSTR")?;
2066                if !*shorthand {
2067                    f.write_str("ING")?;
2068                }
2069                write!(f, "({expr}")?;
2070                if let Some(from_part) = substring_from {
2071                    if *special {
2072                        write!(f, ", {from_part}")?;
2073                    } else {
2074                        write!(f, " FROM {from_part}")?;
2075                    }
2076                }
2077                if let Some(for_part) = substring_for {
2078                    if *special {
2079                        write!(f, ", {for_part}")?;
2080                    } else {
2081                        write!(f, " FOR {for_part}")?;
2082                    }
2083                }
2084
2085                write!(f, ")")
2086            }
2087            Expr::Overlay {
2088                expr,
2089                overlay_what,
2090                overlay_from,
2091                overlay_for,
2092            } => {
2093                write!(
2094                    f,
2095                    "OVERLAY({expr} PLACING {overlay_what} FROM {overlay_from}"
2096                )?;
2097                if let Some(for_part) = overlay_for {
2098                    write!(f, " FOR {for_part}")?;
2099                }
2100
2101                write!(f, ")")
2102            }
2103            Expr::IsDistinctFrom(a, b) => write!(f, "{a} IS DISTINCT FROM {b}"),
2104            Expr::IsNotDistinctFrom(a, b) => write!(f, "{a} IS NOT DISTINCT FROM {b}"),
2105            Expr::Trim {
2106                expr,
2107                trim_where,
2108                trim_what,
2109                trim_characters,
2110            } => {
2111                write!(f, "TRIM(")?;
2112                if let Some(ident) = trim_where {
2113                    write!(f, "{ident} ")?;
2114                }
2115                if let Some(trim_char) = trim_what {
2116                    write!(f, "{trim_char} FROM {expr}")?;
2117                } else {
2118                    write!(f, "{expr}")?;
2119                }
2120                if let Some(characters) = trim_characters {
2121                    write!(f, ", {}", display_comma_separated(characters))?;
2122                }
2123
2124                write!(f, ")")
2125            }
2126            Expr::Tuple(exprs) => {
2127                write!(f, "({})", display_comma_separated(exprs))
2128            }
2129            Expr::Struct { values, fields } => {
2130                if !fields.is_empty() {
2131                    write!(
2132                        f,
2133                        "STRUCT<{}>({})",
2134                        display_comma_separated(fields),
2135                        display_comma_separated(values)
2136                    )
2137                } else {
2138                    write!(f, "STRUCT({})", display_comma_separated(values))
2139                }
2140            }
2141            Expr::Named { expr, name } => {
2142                write!(f, "{expr} AS {name}")
2143            }
2144            Expr::Dictionary(fields) => {
2145                write!(f, "{{{}}}", display_comma_separated(fields))
2146            }
2147            Expr::Map(map) => {
2148                write!(f, "{map}")
2149            }
2150            Expr::Array(set) => {
2151                write!(f, "{set}")
2152            }
2153            Expr::JsonAccess { value, path } => {
2154                write!(f, "{value}{path}")
2155            }
2156            Expr::AtTimeZone {
2157                timestamp,
2158                time_zone,
2159            } => {
2160                write!(f, "{timestamp} AT TIME ZONE {time_zone}")
2161            }
2162            Expr::Interval(interval) => {
2163                write!(f, "{interval}")
2164            }
2165            Expr::MatchAgainst {
2166                columns,
2167                match_value: match_expr,
2168                opt_search_modifier,
2169            } => {
2170                write!(f, "MATCH ({}) AGAINST ", display_comma_separated(columns),)?;
2171
2172                if let Some(search_modifier) = opt_search_modifier {
2173                    write!(f, "({match_expr} {search_modifier})")?;
2174                } else {
2175                    write!(f, "({match_expr})")?;
2176                }
2177
2178                Ok(())
2179            }
2180            Expr::OuterJoin(expr) => {
2181                write!(f, "{expr} (+)")
2182            }
2183            Expr::Prior(expr) => write!(f, "PRIOR {expr}"),
2184            Expr::Lambda(lambda) => write!(f, "{lambda}"),
2185            Expr::MemberOf(member_of) => write!(f, "{member_of}"),
2186        }
2187    }
2188}
2189
2190/// The type of a window used in `OVER` clauses.
2191///
2192/// A window can be either an inline specification (`WindowSpec`) or a
2193/// reference to a previously defined named window.
2194///
2195/// - `WindowSpec(WindowSpec)`: An inline window specification, e.g.
2196///   `OVER (PARTITION BY ... ORDER BY ...)`.
2197/// - `NamedWindow(Ident)`: A reference to a named window declared elsewhere.
2198#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2199#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2200#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2201pub enum WindowType {
2202    /// An inline window specification.
2203    WindowSpec(WindowSpec),
2204    /// A reference to a previously defined named window.
2205    NamedWindow(Ident),
2206}
2207
2208impl Display for WindowType {
2209    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2210        match self {
2211            WindowType::WindowSpec(spec) => {
2212                f.write_str("(")?;
2213                NewLine.fmt(f)?;
2214                Indent(spec).fmt(f)?;
2215                NewLine.fmt(f)?;
2216                f.write_str(")")
2217            }
2218            WindowType::NamedWindow(name) => name.fmt(f),
2219        }
2220    }
2221}
2222
2223/// A window specification (i.e. `OVER ([window_name] PARTITION BY .. ORDER BY .. etc.)`)
2224#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2225#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2226#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2227pub struct WindowSpec {
2228    /// Optional window name.
2229    ///
2230    /// You can find it at least in [MySQL][1], [BigQuery][2], [PostgreSQL][3]
2231    ///
2232    /// [1]: https://dev.mysql.com/doc/refman/8.0/en/window-functions-named-windows.html
2233    /// [2]: https://cloud.google.com/bigquery/docs/reference/standard-sql/window-function-calls
2234    /// [3]: https://www.postgresql.org/docs/current/sql-expressions.html#SYNTAX-WINDOW-FUNCTIONS
2235    pub window_name: Option<Ident>,
2236    /// `OVER (PARTITION BY ...)`
2237    pub partition_by: Vec<Expr>,
2238    /// `OVER (ORDER BY ...)`
2239    pub order_by: Vec<OrderByExpr>,
2240    /// `OVER (window frame)`
2241    pub window_frame: Option<WindowFrame>,
2242}
2243
2244impl fmt::Display for WindowSpec {
2245    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2246        let mut is_first = true;
2247        if let Some(window_name) = &self.window_name {
2248            if !is_first {
2249                SpaceOrNewline.fmt(f)?;
2250            }
2251            is_first = false;
2252            write!(f, "{window_name}")?;
2253        }
2254        if !self.partition_by.is_empty() {
2255            if !is_first {
2256                SpaceOrNewline.fmt(f)?;
2257            }
2258            is_first = false;
2259            write!(
2260                f,
2261                "PARTITION BY {}",
2262                display_comma_separated(&self.partition_by)
2263            )?;
2264        }
2265        if !self.order_by.is_empty() {
2266            if !is_first {
2267                SpaceOrNewline.fmt(f)?;
2268            }
2269            is_first = false;
2270            write!(f, "ORDER BY {}", display_comma_separated(&self.order_by))?;
2271        }
2272        if let Some(window_frame) = &self.window_frame {
2273            if !is_first {
2274                SpaceOrNewline.fmt(f)?;
2275            }
2276            if let Some(end_bound) = &window_frame.end_bound {
2277                write!(
2278                    f,
2279                    "{} BETWEEN {} AND {}",
2280                    window_frame.units, window_frame.start_bound, end_bound
2281                )?;
2282            } else {
2283                write!(f, "{} {}", window_frame.units, window_frame.start_bound)?;
2284            }
2285        }
2286        Ok(())
2287    }
2288}
2289
2290/// Specifies the data processed by a window function, e.g.
2291/// `RANGE UNBOUNDED PRECEDING` or `ROWS BETWEEN 5 PRECEDING AND CURRENT ROW`.
2292///
2293/// Note: The parser does not validate the specified bounds; the caller should
2294/// reject invalid bounds like `ROWS UNBOUNDED FOLLOWING` before execution.
2295#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2296#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2297#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2298pub struct WindowFrame {
2299    /// Units for the frame (e.g. `ROWS`, `RANGE`, `GROUPS`).
2300    pub units: WindowFrameUnits,
2301    /// The start bound of the window frame.
2302    pub start_bound: WindowFrameBound,
2303    /// The right bound of the `BETWEEN .. AND` clause. The end bound of `None`
2304    /// indicates the shorthand form (e.g. `ROWS 1 PRECEDING`), which must
2305    /// behave the same as `end_bound = WindowFrameBound::CurrentRow`.
2306    pub end_bound: Option<WindowFrameBound>,
2307    // TBD: EXCLUDE
2308}
2309
2310impl Default for WindowFrame {
2311    /// Returns default value for window frame
2312    ///
2313    /// See [this page](https://www.sqlite.org/windowfunctions.html#frame_specifications) for more details.
2314    fn default() -> Self {
2315        Self {
2316            units: WindowFrameUnits::Range,
2317            start_bound: WindowFrameBound::Preceding(None),
2318            end_bound: None,
2319        }
2320    }
2321}
2322
2323#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2324#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2325#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2326/// Units used to describe the window frame scope.
2327pub enum WindowFrameUnits {
2328    /// `ROWS` unit.
2329    Rows,
2330    /// `RANGE` unit.
2331    Range,
2332    /// `GROUPS` unit.
2333    Groups,
2334}
2335
2336impl fmt::Display for WindowFrameUnits {
2337    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2338        f.write_str(match self {
2339            WindowFrameUnits::Rows => "ROWS",
2340            WindowFrameUnits::Range => "RANGE",
2341            WindowFrameUnits::Groups => "GROUPS",
2342        })
2343    }
2344}
2345
2346/// Specifies Ignore / Respect NULL within window functions.
2347/// For example
2348/// `FIRST_VALUE(column2) IGNORE NULLS OVER (PARTITION BY column1)`
2349#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2350#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2351#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2352/// How NULL values are treated in certain window functions.
2353pub enum NullTreatment {
2354    /// Ignore NULL values (e.g. `IGNORE NULLS`).
2355    IgnoreNulls,
2356    /// Respect NULL values (e.g. `RESPECT NULLS`).
2357    RespectNulls,
2358}
2359
2360impl fmt::Display for NullTreatment {
2361    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2362        f.write_str(match self {
2363            NullTreatment::IgnoreNulls => "IGNORE NULLS",
2364            NullTreatment::RespectNulls => "RESPECT NULLS",
2365        })
2366    }
2367}
2368
2369/// Specifies [WindowFrame]'s `start_bound` and `end_bound`
2370#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2371#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2372#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2373pub enum WindowFrameBound {
2374    /// `CURRENT ROW`
2375    CurrentRow,
2376    /// `<N> PRECEDING` or `UNBOUNDED PRECEDING`
2377    Preceding(Option<Box<Expr>>),
2378    /// `<N> FOLLOWING` or `UNBOUNDED FOLLOWING`.
2379    Following(Option<Box<Expr>>),
2380}
2381
2382impl fmt::Display for WindowFrameBound {
2383    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2384        match self {
2385            WindowFrameBound::CurrentRow => f.write_str("CURRENT ROW"),
2386            WindowFrameBound::Preceding(None) => f.write_str("UNBOUNDED PRECEDING"),
2387            WindowFrameBound::Following(None) => f.write_str("UNBOUNDED FOLLOWING"),
2388            WindowFrameBound::Preceding(Some(n)) => write!(f, "{n} PRECEDING"),
2389            WindowFrameBound::Following(Some(n)) => write!(f, "{n} FOLLOWING"),
2390        }
2391    }
2392}
2393
2394#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2395#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2396#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2397/// Indicates partition operation type for partition management statements.
2398pub enum AddDropSync {
2399    /// Add partitions.
2400    ADD,
2401    /// Drop partitions.
2402    DROP,
2403    /// Sync partitions.
2404    SYNC,
2405}
2406
2407impl fmt::Display for AddDropSync {
2408    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2409        match self {
2410            AddDropSync::SYNC => f.write_str("SYNC PARTITIONS"),
2411            AddDropSync::DROP => f.write_str("DROP PARTITIONS"),
2412            AddDropSync::ADD => f.write_str("ADD PARTITIONS"),
2413        }
2414    }
2415}
2416
2417#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2418#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2419#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2420/// Object kinds supported by `SHOW CREATE` statements.
2421pub enum ShowCreateObject {
2422    /// An event object for `SHOW CREATE EVENT`.
2423    Event,
2424    /// A function object for `SHOW CREATE FUNCTION`.
2425    Function,
2426    /// A procedure object for `SHOW CREATE PROCEDURE`.
2427    Procedure,
2428    /// A table object for `SHOW CREATE TABLE`.
2429    Table,
2430    /// A trigger object for `SHOW CREATE TRIGGER`.
2431    Trigger,
2432    /// A view object for `SHOW CREATE VIEW`.
2433    View,
2434}
2435
2436impl fmt::Display for ShowCreateObject {
2437    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2438        match self {
2439            ShowCreateObject::Event => f.write_str("EVENT"),
2440            ShowCreateObject::Function => f.write_str("FUNCTION"),
2441            ShowCreateObject::Procedure => f.write_str("PROCEDURE"),
2442            ShowCreateObject::Table => f.write_str("TABLE"),
2443            ShowCreateObject::Trigger => f.write_str("TRIGGER"),
2444            ShowCreateObject::View => f.write_str("VIEW"),
2445        }
2446    }
2447}
2448
2449#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2450#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2451#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2452/// Objects that can be targeted by a `COMMENT` statement.
2453pub enum CommentObject {
2454    /// A collation.
2455    Collation,
2456    /// A table column.
2457    Column,
2458    /// A database.
2459    Database,
2460    /// A domain.
2461    Domain,
2462    /// An extension.
2463    Extension,
2464    /// A function.
2465    Function,
2466    /// An index.
2467    Index,
2468    /// A materialized view.
2469    MaterializedView,
2470    /// A procedure.
2471    Procedure,
2472    /// A role.
2473    Role,
2474    /// A schema.
2475    Schema,
2476    /// A sequence.
2477    Sequence,
2478    /// A table.
2479    Table,
2480    /// A type.
2481    Type,
2482    /// A user.
2483    User,
2484    /// A view.
2485    View,
2486}
2487
2488impl fmt::Display for CommentObject {
2489    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2490        match self {
2491            CommentObject::Collation => f.write_str("COLLATION"),
2492            CommentObject::Column => f.write_str("COLUMN"),
2493            CommentObject::Database => f.write_str("DATABASE"),
2494            CommentObject::Domain => f.write_str("DOMAIN"),
2495            CommentObject::Extension => f.write_str("EXTENSION"),
2496            CommentObject::Function => f.write_str("FUNCTION"),
2497            CommentObject::Index => f.write_str("INDEX"),
2498            CommentObject::MaterializedView => f.write_str("MATERIALIZED VIEW"),
2499            CommentObject::Procedure => f.write_str("PROCEDURE"),
2500            CommentObject::Role => f.write_str("ROLE"),
2501            CommentObject::Schema => f.write_str("SCHEMA"),
2502            CommentObject::Sequence => f.write_str("SEQUENCE"),
2503            CommentObject::Table => f.write_str("TABLE"),
2504            CommentObject::Type => f.write_str("TYPE"),
2505            CommentObject::User => f.write_str("USER"),
2506            CommentObject::View => f.write_str("VIEW"),
2507        }
2508    }
2509}
2510
2511#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2512#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2513#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2514/// Password specification variants used in user-related statements.
2515pub enum Password {
2516    /// A concrete password expression.
2517    Password(Expr),
2518    /// Represents a `NULL` password.
2519    NullPassword,
2520}
2521
2522/// A `CASE` statement.
2523///
2524/// Examples:
2525/// ```sql
2526/// CASE
2527///     WHEN EXISTS(SELECT 1)
2528///         THEN SELECT 1 FROM T;
2529///     WHEN EXISTS(SELECT 2)
2530///         THEN SELECT 1 FROM U;
2531///     ELSE
2532///         SELECT 1 FROM V;
2533/// END CASE;
2534/// ```
2535///
2536/// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#case_search_expression)
2537/// [Snowflake](https://docs.snowflake.com/en/sql-reference/snowflake-scripting/case)
2538#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2539#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2540#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2541pub struct CaseStatement {
2542    /// The `CASE` token that starts the statement.
2543    pub case_token: AttachedToken,
2544    /// Optional expression to match against in `CASE ... WHEN`.
2545    pub match_expr: Option<Expr>,
2546    /// The `WHEN ... THEN` blocks of the `CASE` statement.
2547    pub when_blocks: Vec<ConditionalStatementBlock>,
2548    /// Optional `ELSE` block for the `CASE` statement.
2549    pub else_block: Option<ConditionalStatementBlock>,
2550    /// The last token of the statement (`END` or `CASE`).
2551    pub end_case_token: AttachedToken,
2552}
2553
2554impl fmt::Display for CaseStatement {
2555    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2556        let CaseStatement {
2557            case_token: _,
2558            match_expr,
2559            when_blocks,
2560            else_block,
2561            end_case_token: AttachedToken(end),
2562        } = self;
2563
2564        write!(f, "CASE")?;
2565
2566        if let Some(expr) = match_expr {
2567            write!(f, " {expr}")?;
2568        }
2569
2570        if !when_blocks.is_empty() {
2571            write!(f, " {}", display_separated(when_blocks, " "))?;
2572        }
2573
2574        if let Some(else_block) = else_block {
2575            write!(f, " {else_block}")?;
2576        }
2577
2578        write!(f, " END")?;
2579
2580        if let Token::Word(w) = &end.token {
2581            if w.keyword == Keyword::CASE {
2582                write!(f, " CASE")?;
2583            }
2584        }
2585
2586        Ok(())
2587    }
2588}
2589
2590/// An `IF` statement.
2591///
2592/// Example (BigQuery or Snowflake):
2593/// ```sql
2594/// IF TRUE THEN
2595///     SELECT 1;
2596///     SELECT 2;
2597/// ELSEIF TRUE THEN
2598///     SELECT 3;
2599/// ELSE
2600///     SELECT 4;
2601/// END IF
2602/// ```
2603/// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#if)
2604/// [Snowflake](https://docs.snowflake.com/en/sql-reference/snowflake-scripting/if)
2605///
2606/// Example (MSSQL):
2607/// ```sql
2608/// IF 1=1 SELECT 1 ELSE SELECT 2
2609/// ```
2610/// [MSSQL](https://learn.microsoft.com/en-us/sql/t-sql/language-elements/if-else-transact-sql?view=sql-server-ver16)
2611#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2612#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2613#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2614pub struct IfStatement {
2615    /// The initial `IF` block containing the condition and statements.
2616    pub if_block: ConditionalStatementBlock,
2617    /// Additional `ELSEIF` blocks.
2618    pub elseif_blocks: Vec<ConditionalStatementBlock>,
2619    /// Optional `ELSE` block.
2620    pub else_block: Option<ConditionalStatementBlock>,
2621    /// Optional trailing `END` token for the `IF` statement.
2622    pub end_token: Option<AttachedToken>,
2623}
2624
2625impl fmt::Display for IfStatement {
2626    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2627        let IfStatement {
2628            if_block,
2629            elseif_blocks,
2630            else_block,
2631            end_token,
2632        } = self;
2633
2634        write!(f, "{if_block}")?;
2635
2636        for elseif_block in elseif_blocks {
2637            write!(f, " {elseif_block}")?;
2638        }
2639
2640        if let Some(else_block) = else_block {
2641            write!(f, " {else_block}")?;
2642        }
2643
2644        if let Some(AttachedToken(end_token)) = end_token {
2645            write!(f, " END {end_token}")?;
2646        }
2647
2648        Ok(())
2649    }
2650}
2651
2652/// A `WHILE` statement.
2653///
2654/// Example:
2655/// ```sql
2656/// WHILE @@FETCH_STATUS = 0
2657/// BEGIN
2658///    FETCH NEXT FROM c1 INTO @var1, @var2;
2659/// END
2660/// ```
2661///
2662/// [MsSql](https://learn.microsoft.com/en-us/sql/t-sql/language-elements/while-transact-sql)
2663#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2664#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2665#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2666pub struct WhileStatement {
2667    /// Block executed while the condition holds.
2668    pub while_block: ConditionalStatementBlock,
2669}
2670
2671impl fmt::Display for WhileStatement {
2672    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2673        let WhileStatement { while_block } = self;
2674        write!(f, "{while_block}")?;
2675        Ok(())
2676    }
2677}
2678
2679/// A block within a [Statement::Case] or [Statement::If] or [Statement::While]-like statement
2680///
2681/// Example 1:
2682/// ```sql
2683/// WHEN EXISTS(SELECT 1) THEN SELECT 1;
2684/// ```
2685///
2686/// Example 2:
2687/// ```sql
2688/// IF TRUE THEN SELECT 1; SELECT 2;
2689/// ```
2690///
2691/// Example 3:
2692/// ```sql
2693/// ELSE SELECT 1; SELECT 2;
2694/// ```
2695///
2696/// Example 4:
2697/// ```sql
2698/// WHILE @@FETCH_STATUS = 0
2699/// BEGIN
2700///    FETCH NEXT FROM c1 INTO @var1, @var2;
2701/// END
2702/// ```
2703#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2704#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2705#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2706pub struct ConditionalStatementBlock {
2707    /// Token representing the start of the block (e.g., WHEN/IF/WHILE).
2708    pub start_token: AttachedToken,
2709    /// Optional condition expression for the block.
2710    pub condition: Option<Expr>,
2711    /// Optional token for the `THEN` keyword.
2712    pub then_token: Option<AttachedToken>,
2713    /// The statements contained in this conditional block.
2714    pub conditional_statements: ConditionalStatements,
2715}
2716
2717impl ConditionalStatementBlock {
2718    /// Get the statements in this conditional block.
2719    pub fn statements(&self) -> &Vec<Statement> {
2720        self.conditional_statements.statements()
2721    }
2722}
2723
2724impl fmt::Display for ConditionalStatementBlock {
2725    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2726        let ConditionalStatementBlock {
2727            start_token: AttachedToken(start_token),
2728            condition,
2729            then_token,
2730            conditional_statements,
2731        } = self;
2732
2733        write!(f, "{start_token}")?;
2734
2735        if let Some(condition) = condition {
2736            write!(f, " {condition}")?;
2737        }
2738
2739        if then_token.is_some() {
2740            write!(f, " THEN")?;
2741        }
2742
2743        if !conditional_statements.statements().is_empty() {
2744            write!(f, " {conditional_statements}")?;
2745        }
2746
2747        Ok(())
2748    }
2749}
2750
2751/// A list of statements in a [ConditionalStatementBlock].
2752#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2753#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2754#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2755/// Statements used inside conditional blocks (`IF`, `WHEN`, `WHILE`).
2756pub enum ConditionalStatements {
2757    /// Simple sequence of statements (no `BEGIN`/`END`).
2758    Sequence {
2759        /// The statements in the sequence.
2760        statements: Vec<Statement>,
2761    },
2762    /// Block enclosed by `BEGIN` and `END`.
2763    BeginEnd(BeginEndStatements),
2764}
2765
2766impl ConditionalStatements {
2767    /// Get the statements in this conditional statements block.
2768    pub fn statements(&self) -> &Vec<Statement> {
2769        match self {
2770            ConditionalStatements::Sequence { statements } => statements,
2771            ConditionalStatements::BeginEnd(bes) => &bes.statements,
2772        }
2773    }
2774}
2775
2776impl fmt::Display for ConditionalStatements {
2777    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2778        match self {
2779            ConditionalStatements::Sequence { statements } => {
2780                if !statements.is_empty() {
2781                    format_statement_list(f, statements)?;
2782                }
2783                Ok(())
2784            }
2785            ConditionalStatements::BeginEnd(bes) => write!(f, "{bes}"),
2786        }
2787    }
2788}
2789
2790/// Represents a list of statements enclosed within `BEGIN` and `END` keywords.
2791/// Example:
2792/// ```sql
2793/// BEGIN
2794///     SELECT 1;
2795///     SELECT 2;
2796/// END
2797/// ```
2798#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2799#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2800#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2801pub struct BeginEndStatements {
2802    /// Token representing the `BEGIN` keyword (may include span info).
2803    pub begin_token: AttachedToken,
2804    /// Statements contained within the block.
2805    pub statements: Vec<Statement>,
2806    /// Token representing the `END` keyword (may include span info).
2807    pub end_token: AttachedToken,
2808}
2809
2810impl fmt::Display for BeginEndStatements {
2811    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2812        let BeginEndStatements {
2813            begin_token: AttachedToken(begin_token),
2814            statements,
2815            end_token: AttachedToken(end_token),
2816        } = self;
2817
2818        if begin_token.token != Token::EOF {
2819            write!(f, "{begin_token} ")?;
2820        }
2821        if !statements.is_empty() {
2822            format_statement_list(f, statements)?;
2823        }
2824        if end_token.token != Token::EOF {
2825            write!(f, " {end_token}")?;
2826        }
2827        Ok(())
2828    }
2829}
2830
2831/// A `RAISE` statement.
2832///
2833/// Examples:
2834/// ```sql
2835/// RAISE USING MESSAGE = 'error';
2836///
2837/// RAISE myerror;
2838/// ```
2839///
2840/// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#raise)
2841/// [Snowflake](https://docs.snowflake.com/en/sql-reference/snowflake-scripting/raise)
2842#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2843#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2844#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2845pub struct RaiseStatement {
2846    /// Optional value provided to the RAISE statement.
2847    pub value: Option<RaiseStatementValue>,
2848}
2849
2850impl fmt::Display for RaiseStatement {
2851    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2852        let RaiseStatement { value } = self;
2853
2854        write!(f, "RAISE")?;
2855        if let Some(value) = value {
2856            write!(f, " {value}")?;
2857        }
2858
2859        Ok(())
2860    }
2861}
2862
2863/// Represents the error value of a [RaiseStatement].
2864#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2865#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2866#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2867pub enum RaiseStatementValue {
2868    /// `RAISE USING MESSAGE = 'error'`
2869    UsingMessage(Expr),
2870    /// `RAISE myerror`
2871    Expr(Expr),
2872}
2873
2874impl fmt::Display for RaiseStatementValue {
2875    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2876        match self {
2877            RaiseStatementValue::Expr(expr) => write!(f, "{expr}"),
2878            RaiseStatementValue::UsingMessage(expr) => write!(f, "USING MESSAGE = {expr}"),
2879        }
2880    }
2881}
2882
2883/// A MSSQL `THROW` statement.
2884///
2885/// ```sql
2886/// THROW [ error_number, message, state ]
2887/// ```
2888///
2889/// [MSSQL](https://learn.microsoft.com/en-us/sql/t-sql/language-elements/throw-transact-sql)
2890#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2891#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2892#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2893pub struct ThrowStatement {
2894    /// Error number expression.
2895    pub error_number: Option<Box<Expr>>,
2896    /// Error message expression.
2897    pub message: Option<Box<Expr>>,
2898    /// State expression.
2899    pub state: Option<Box<Expr>>,
2900}
2901
2902impl fmt::Display for ThrowStatement {
2903    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2904        let ThrowStatement {
2905            error_number,
2906            message,
2907            state,
2908        } = self;
2909
2910        write!(f, "THROW")?;
2911        if let (Some(error_number), Some(message), Some(state)) = (error_number, message, state) {
2912            write!(f, " {error_number}, {message}, {state}")?;
2913        }
2914        Ok(())
2915    }
2916}
2917
2918/// Represents an expression assignment within a variable `DECLARE` statement.
2919///
2920/// Examples:
2921/// ```sql
2922/// DECLARE variable_name := 42
2923/// DECLARE variable_name DEFAULT 42
2924/// ```
2925#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2926#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2927#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2928pub enum DeclareAssignment {
2929    /// Plain expression specified.
2930    Expr(Box<Expr>),
2931
2932    /// Expression assigned via the `DEFAULT` keyword
2933    Default(Box<Expr>),
2934
2935    /// Expression assigned via the `:=` syntax
2936    ///
2937    /// Example:
2938    /// ```sql
2939    /// DECLARE variable_name := 42;
2940    /// ```
2941    DuckAssignment(Box<Expr>),
2942
2943    /// Expression via the `FOR` keyword
2944    ///
2945    /// Example:
2946    /// ```sql
2947    /// DECLARE c1 CURSOR FOR res
2948    /// ```
2949    For(Box<Expr>),
2950
2951    /// Expression via the `=` syntax.
2952    ///
2953    /// Example:
2954    /// ```sql
2955    /// DECLARE @variable AS INT = 100
2956    /// ```
2957    MsSqlAssignment(Box<Expr>),
2958}
2959
2960impl fmt::Display for DeclareAssignment {
2961    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2962        match self {
2963            DeclareAssignment::Expr(expr) => {
2964                write!(f, "{expr}")
2965            }
2966            DeclareAssignment::Default(expr) => {
2967                write!(f, "DEFAULT {expr}")
2968            }
2969            DeclareAssignment::DuckAssignment(expr) => {
2970                write!(f, ":= {expr}")
2971            }
2972            DeclareAssignment::MsSqlAssignment(expr) => {
2973                write!(f, "= {expr}")
2974            }
2975            DeclareAssignment::For(expr) => {
2976                write!(f, "FOR {expr}")
2977            }
2978        }
2979    }
2980}
2981
2982/// Represents the type of a `DECLARE` statement.
2983#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2984#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2985#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2986pub enum DeclareType {
2987    /// Cursor variable type. e.g. [Snowflake] [PostgreSQL] [MsSql]
2988    ///
2989    /// [Snowflake]: https://docs.snowflake.com/en/developer-guide/snowflake-scripting/cursors#declaring-a-cursor
2990    /// [PostgreSQL]: https://www.postgresql.org/docs/current/plpgsql-cursors.html
2991    /// [MsSql]: https://learn.microsoft.com/en-us/sql/t-sql/language-elements/declare-cursor-transact-sql
2992    Cursor,
2993
2994    /// Result set variable type. [Snowflake]
2995    ///
2996    /// Syntax:
2997    /// ```text
2998    /// <resultset_name> RESULTSET [ { DEFAULT | := } ( <query> ) ] ;
2999    /// ```
3000    /// [Snowflake]: https://docs.snowflake.com/en/sql-reference/snowflake-scripting/declare#resultset-declaration-syntax
3001    ResultSet,
3002
3003    /// Exception declaration syntax. [Snowflake]
3004    ///
3005    /// Syntax:
3006    /// ```text
3007    /// <exception_name> EXCEPTION [ ( <exception_number> , '<exception_message>' ) ] ;
3008    /// ```
3009    /// [Snowflake]: https://docs.snowflake.com/en/sql-reference/snowflake-scripting/declare#exception-declaration-syntax
3010    Exception,
3011}
3012
3013impl fmt::Display for DeclareType {
3014    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3015        match self {
3016            DeclareType::Cursor => {
3017                write!(f, "CURSOR")
3018            }
3019            DeclareType::ResultSet => {
3020                write!(f, "RESULTSET")
3021            }
3022            DeclareType::Exception => {
3023                write!(f, "EXCEPTION")
3024            }
3025        }
3026    }
3027}
3028
3029/// A `DECLARE` statement.
3030/// [PostgreSQL] [Snowflake] [BigQuery]
3031///
3032/// Examples:
3033/// ```sql
3034/// DECLARE variable_name := 42
3035/// DECLARE liahona CURSOR FOR SELECT * FROM films;
3036/// ```
3037///
3038/// [PostgreSQL]: https://www.postgresql.org/docs/current/sql-declare.html
3039/// [Snowflake]: https://docs.snowflake.com/en/sql-reference/snowflake-scripting/declare
3040/// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#declare
3041#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3042#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3043#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3044pub struct Declare {
3045    /// The name(s) being declared.
3046    /// Example: `DECLARE a, b, c DEFAULT 42;
3047    pub names: Vec<Ident>,
3048    /// Data-type assigned to the declared variable.
3049    /// Example: `DECLARE x INT64 DEFAULT 42;
3050    pub data_type: Option<DataType>,
3051    /// Expression being assigned to the declared variable.
3052    pub assignment: Option<DeclareAssignment>,
3053    /// Represents the type of the declared variable.
3054    pub declare_type: Option<DeclareType>,
3055    /// Causes the cursor to return data in binary rather than in text format.
3056    pub binary: Option<bool>,
3057    /// None = Not specified
3058    /// Some(true) = INSENSITIVE
3059    /// Some(false) = ASENSITIVE
3060    pub sensitive: Option<bool>,
3061    /// None = Not specified
3062    /// Some(true) = SCROLL
3063    /// Some(false) = NO SCROLL
3064    pub scroll: Option<bool>,
3065    /// None = Not specified
3066    /// Some(true) = WITH HOLD, specifies that the cursor can continue to be used after the transaction that created it successfully commits
3067    /// Some(false) = WITHOUT HOLD, specifies that the cursor cannot be used outside of the transaction that created it
3068    pub hold: Option<bool>,
3069    /// `FOR <query>` clause in a CURSOR declaration.
3070    pub for_query: Option<Box<Query>>,
3071}
3072
3073impl fmt::Display for Declare {
3074    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3075        let Declare {
3076            names,
3077            data_type,
3078            assignment,
3079            declare_type,
3080            binary,
3081            sensitive,
3082            scroll,
3083            hold,
3084            for_query,
3085        } = self;
3086        write!(f, "{}", display_comma_separated(names))?;
3087
3088        if let Some(true) = binary {
3089            write!(f, " BINARY")?;
3090        }
3091
3092        if let Some(sensitive) = sensitive {
3093            if *sensitive {
3094                write!(f, " INSENSITIVE")?;
3095            } else {
3096                write!(f, " ASENSITIVE")?;
3097            }
3098        }
3099
3100        if let Some(scroll) = scroll {
3101            if *scroll {
3102                write!(f, " SCROLL")?;
3103            } else {
3104                write!(f, " NO SCROLL")?;
3105            }
3106        }
3107
3108        if let Some(declare_type) = declare_type {
3109            write!(f, " {declare_type}")?;
3110        }
3111
3112        if let Some(hold) = hold {
3113            if *hold {
3114                write!(f, " WITH HOLD")?;
3115            } else {
3116                write!(f, " WITHOUT HOLD")?;
3117            }
3118        }
3119
3120        if let Some(query) = for_query {
3121            write!(f, " FOR {query}")?;
3122        }
3123
3124        if let Some(data_type) = data_type {
3125            write!(f, " {data_type}")?;
3126        }
3127
3128        if let Some(expr) = assignment {
3129            write!(f, " {expr}")?;
3130        }
3131        Ok(())
3132    }
3133}
3134
3135/// Sql options of a `CREATE TABLE` statement.
3136#[derive(Debug, Default, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3137#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3138#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3139/// Options allowed within a `CREATE TABLE` statement.
3140pub enum CreateTableOptions {
3141    /// No options specified.
3142    #[default]
3143    None,
3144    /// Options specified using the `WITH` keyword, e.g. `WITH (k = v)`.
3145    With(Vec<SqlOption>),
3146    /// Options specified using the `OPTIONS(...)` clause.
3147    Options(Vec<SqlOption>),
3148    /// Plain space-separated options.
3149    Plain(Vec<SqlOption>),
3150    /// Table properties (e.g., TBLPROPERTIES / storage properties).
3151    TableProperties(Vec<SqlOption>),
3152}
3153
3154impl fmt::Display for CreateTableOptions {
3155    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3156        match self {
3157            CreateTableOptions::With(with_options) => {
3158                write!(f, "WITH ({})", display_comma_separated(with_options))
3159            }
3160            CreateTableOptions::Options(options) => {
3161                write!(f, "OPTIONS({})", display_comma_separated(options))
3162            }
3163            CreateTableOptions::TableProperties(options) => {
3164                write!(f, "TBLPROPERTIES ({})", display_comma_separated(options))
3165            }
3166            CreateTableOptions::Plain(options) => {
3167                write!(f, "{}", display_separated(options, " "))
3168            }
3169            CreateTableOptions::None => Ok(()),
3170        }
3171    }
3172}
3173
3174/// A `FROM` clause within a `DELETE` statement.
3175///
3176/// Syntax
3177/// ```sql
3178/// [FROM] table
3179/// ```
3180#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3181#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3182#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3183pub enum FromTable {
3184    /// An explicit `FROM` keyword was specified.
3185    WithFromKeyword(Vec<TableWithJoins>),
3186    /// BigQuery: `FROM` keyword was omitted.
3187    /// <https://cloud.google.com/bigquery/docs/reference/standard-sql/dml-syntax#delete_statement>
3188    WithoutKeyword(Vec<TableWithJoins>),
3189}
3190impl Display for FromTable {
3191    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3192        match self {
3193            FromTable::WithFromKeyword(tables) => {
3194                write!(f, "FROM {}", display_comma_separated(tables))
3195            }
3196            FromTable::WithoutKeyword(tables) => {
3197                write!(f, "{}", display_comma_separated(tables))
3198            }
3199        }
3200    }
3201}
3202
3203#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3204#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3205#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3206/// Variants for the `SET` family of statements.
3207pub enum Set {
3208    /// SQL Standard-style
3209    /// SET a = 1;
3210    /// `SET var = value` (standard SQL-style assignment).
3211    SingleAssignment {
3212        /// Optional scope modifier (`SESSION` / `LOCAL`).
3213        scope: Option<ContextModifier>,
3214        /// Whether this is a Hive-style `HIVEVAR:` assignment.
3215        hivevar: bool,
3216        /// Variable name to assign.
3217        variable: ObjectName,
3218        /// Values assigned to the variable.
3219        values: Vec<Expr>,
3220    },
3221    /// Snowflake-style
3222    /// SET (a, b, ..) = (1, 2, ..);
3223    /// `SET (a, b) = (1, 2)` (tuple assignment syntax).
3224    ParenthesizedAssignments {
3225        /// Variables being assigned in tuple form.
3226        variables: Vec<ObjectName>,
3227        /// Corresponding values for the variables.
3228        values: Vec<Expr>,
3229    },
3230    /// MySQL-style
3231    /// SET a = 1, b = 2, ..;
3232    /// `SET a = 1, b = 2` (MySQL-style comma-separated assignments).
3233    MultipleAssignments {
3234        /// List of `SET` assignments (MySQL-style comma-separated).
3235        assignments: Vec<SetAssignment>,
3236    },
3237    /// Session authorization for Postgres/Redshift
3238    ///
3239    /// ```sql
3240    /// SET SESSION AUTHORIZATION { user_name | DEFAULT }
3241    /// ```
3242    ///
3243    /// See <https://www.postgresql.org/docs/current/sql-set-session-authorization.html>
3244    /// See <https://docs.aws.amazon.com/redshift/latest/dg/r_SET_SESSION_AUTHORIZATION.html>
3245    SetSessionAuthorization(SetSessionAuthorizationParam),
3246    /// MS-SQL session
3247    ///
3248    /// See <https://learn.microsoft.com/en-us/sql/t-sql/statements/set-statements-transact-sql>
3249    SetSessionParam(SetSessionParamKind),
3250    /// ```sql
3251    /// SET [ SESSION | LOCAL ] ROLE role_name
3252    /// ```
3253    ///
3254    /// Sets session state. Examples: [ANSI][1], [Postgresql][2], [MySQL][3], and [Oracle][4]
3255    ///
3256    /// [1]: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#set-role-statement
3257    /// [2]: https://www.postgresql.org/docs/14/sql-set-role.html
3258    /// [3]: https://dev.mysql.com/doc/refman/8.0/en/set-role.html
3259    /// [4]: https://docs.oracle.com/cd/B19306_01/server.102/b14200/statements_10004.htm
3260    SetRole {
3261        /// Non-ANSI optional identifier to inform if the role is defined inside the current session (`SESSION`) or transaction (`LOCAL`).
3262        context_modifier: Option<ContextModifier>,
3263        /// Role name. If NONE is specified, then the current role name is removed.
3264        role_name: Option<Ident>,
3265    },
3266    /// ```sql
3267    /// SET TIME ZONE <value>
3268    /// ```
3269    ///
3270    /// Note: this is a PostgreSQL-specific statements
3271    /// `SET TIME ZONE <value>` is an alias for `SET timezone TO <value>` in PostgreSQL
3272    /// However, we allow it for all dialects.
3273    /// `SET TIME ZONE` statement. `local` indicates the `LOCAL` keyword.
3274    /// `SET TIME ZONE <value>` statement.
3275    SetTimeZone {
3276        /// Whether the `LOCAL` keyword was specified.
3277        local: bool,
3278        /// Time zone expression value.
3279        value: Expr,
3280    },
3281    /// ```sql
3282    /// SET NAMES 'charset_name' [COLLATE 'collation_name']
3283    /// ```
3284    SetNames {
3285        /// Character set name to set.
3286        charset_name: Ident,
3287        /// Optional collation name.
3288        collation_name: Option<String>,
3289    },
3290    /// ```sql
3291    /// SET NAMES DEFAULT
3292    /// ```
3293    ///
3294    /// Note: this is a MySQL-specific statement.
3295    SetNamesDefault {},
3296    /// ```sql
3297    /// SET TRANSACTION ...
3298    /// ```
3299    SetTransaction {
3300        /// Transaction modes (e.g., ISOLATION LEVEL, READ ONLY).
3301        modes: Vec<TransactionMode>,
3302        /// Optional snapshot value for transaction snapshot control.
3303        snapshot: Option<ValueWithSpan>,
3304        /// `true` when the `SESSION` keyword was used.
3305        session: bool,
3306    },
3307}
3308
3309impl Display for Set {
3310    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3311        match self {
3312            Self::ParenthesizedAssignments { variables, values } => write!(
3313                f,
3314                "SET ({}) = ({})",
3315                display_comma_separated(variables),
3316                display_comma_separated(values)
3317            ),
3318            Self::MultipleAssignments { assignments } => {
3319                write!(f, "SET {}", display_comma_separated(assignments))
3320            }
3321            Self::SetRole {
3322                context_modifier,
3323                role_name,
3324            } => {
3325                let role_name = role_name.clone().unwrap_or_else(|| Ident::new("NONE"));
3326                write!(
3327                    f,
3328                    "SET {modifier}ROLE {role_name}",
3329                    modifier = context_modifier.map(|m| format!("{m}")).unwrap_or_default()
3330                )
3331            }
3332            Self::SetSessionAuthorization(kind) => write!(f, "SET SESSION AUTHORIZATION {kind}"),
3333            Self::SetSessionParam(kind) => write!(f, "SET {kind}"),
3334            Self::SetTransaction {
3335                modes,
3336                snapshot,
3337                session,
3338            } => {
3339                if *session {
3340                    write!(f, "SET SESSION CHARACTERISTICS AS TRANSACTION")?;
3341                } else {
3342                    write!(f, "SET TRANSACTION")?;
3343                }
3344                if !modes.is_empty() {
3345                    write!(f, " {}", display_comma_separated(modes))?;
3346                }
3347                if let Some(snapshot_id) = snapshot {
3348                    write!(f, " SNAPSHOT {snapshot_id}")?;
3349                }
3350                Ok(())
3351            }
3352            Self::SetTimeZone { local, value } => {
3353                f.write_str("SET ")?;
3354                if *local {
3355                    f.write_str("LOCAL ")?;
3356                }
3357                write!(f, "TIME ZONE {value}")
3358            }
3359            Self::SetNames {
3360                charset_name,
3361                collation_name,
3362            } => {
3363                write!(f, "SET NAMES {charset_name}")?;
3364
3365                if let Some(collation) = collation_name {
3366                    f.write_str(" COLLATE ")?;
3367                    f.write_str(collation)?;
3368                };
3369
3370                Ok(())
3371            }
3372            Self::SetNamesDefault {} => {
3373                f.write_str("SET NAMES DEFAULT")?;
3374
3375                Ok(())
3376            }
3377            Set::SingleAssignment {
3378                scope,
3379                hivevar,
3380                variable,
3381                values,
3382            } => {
3383                write!(
3384                    f,
3385                    "SET {}{}{} = {}",
3386                    scope.map(|s| format!("{s}")).unwrap_or_default(),
3387                    if *hivevar { "HIVEVAR:" } else { "" },
3388                    variable,
3389                    display_comma_separated(values)
3390                )
3391            }
3392        }
3393    }
3394}
3395
3396/// A representation of a `WHEN` arm with all the identifiers catched and the statements to execute
3397/// for the arm.
3398///
3399/// Snowflake: <https://docs.snowflake.com/en/sql-reference/snowflake-scripting/exception>
3400/// BigQuery: <https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#beginexceptionend>
3401#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3402#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3403#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3404pub struct ExceptionWhen {
3405    /// Identifiers that trigger this branch (error conditions).
3406    pub idents: Vec<Ident>,
3407    /// Statements to execute when the condition matches.
3408    pub statements: Vec<Statement>,
3409}
3410
3411impl Display for ExceptionWhen {
3412    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3413        write!(
3414            f,
3415            "WHEN {idents} THEN",
3416            idents = display_separated(&self.idents, " OR ")
3417        )?;
3418
3419        if !self.statements.is_empty() {
3420            write!(f, " ")?;
3421            format_statement_list(f, &self.statements)?;
3422        }
3423
3424        Ok(())
3425    }
3426}
3427
3428/// ANALYZE statement
3429///
3430/// Supported syntax varies by dialect:
3431/// - Hive: `ANALYZE TABLE t [PARTITION (...)] COMPUTE STATISTICS [NOSCAN] [FOR COLUMNS [col1, ...]] [CACHE METADATA]`
3432/// - PostgreSQL: `ANALYZE [VERBOSE] [t [(col1, ...)]]` See <https://www.postgresql.org/docs/current/sql-analyze.html>
3433/// - General: `ANALYZE [TABLE] t`
3434#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3435#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3436#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3437pub struct Analyze {
3438    #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
3439    /// Name of the table to analyze. `None` for bare `ANALYZE`.
3440    pub table_name: Option<ObjectName>,
3441    /// Optional partition expressions to restrict the analysis.
3442    pub partitions: Option<Vec<Expr>>,
3443    /// `true` when analyzing specific columns (Hive `FOR COLUMNS` syntax).
3444    pub for_columns: bool,
3445    /// Columns to analyze.
3446    pub columns: Vec<Ident>,
3447    /// Whether to cache metadata before analyzing.
3448    pub cache_metadata: bool,
3449    /// Whether to skip scanning the table.
3450    pub noscan: bool,
3451    /// Whether to compute statistics during analysis.
3452    pub compute_statistics: bool,
3453    /// Whether the `TABLE` keyword was present.
3454    pub has_table_keyword: bool,
3455}
3456
3457impl fmt::Display for Analyze {
3458    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3459        write!(f, "ANALYZE")?;
3460        if let Some(ref table_name) = self.table_name {
3461            if self.has_table_keyword {
3462                write!(f, " TABLE")?;
3463            }
3464            write!(f, " {table_name}")?;
3465        }
3466        if !self.for_columns && !self.columns.is_empty() {
3467            write!(f, " ({})", display_comma_separated(&self.columns))?;
3468        }
3469        if let Some(ref parts) = self.partitions {
3470            if !parts.is_empty() {
3471                write!(f, " PARTITION ({})", display_comma_separated(parts))?;
3472            }
3473        }
3474        if self.compute_statistics {
3475            write!(f, " COMPUTE STATISTICS")?;
3476        }
3477        if self.noscan {
3478            write!(f, " NOSCAN")?;
3479        }
3480        if self.cache_metadata {
3481            write!(f, " CACHE METADATA")?;
3482        }
3483        if self.for_columns {
3484            write!(f, " FOR COLUMNS")?;
3485            if !self.columns.is_empty() {
3486                write!(f, " {}", display_comma_separated(&self.columns))?;
3487            }
3488        }
3489        Ok(())
3490    }
3491}
3492
3493/// A top-level statement (SELECT, INSERT, CREATE, etc.)
3494#[allow(clippy::large_enum_variant)]
3495#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3496#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3497#[cfg_attr(
3498    feature = "visitor",
3499    derive(Visit, VisitMut),
3500    visit(with = "visit_statement")
3501)]
3502pub enum Statement {
3503    /// ```sql
3504    /// ANALYZE
3505    /// ```
3506    /// Analyze (Hive)
3507    Analyze(Analyze),
3508    /// `SET` statements (session, transaction, timezone, etc.).
3509    Set(Set),
3510    /// ```sql
3511    /// TRUNCATE
3512    /// ```
3513    /// Truncate (Hive)
3514    Truncate(Truncate),
3515    /// ```sql
3516    /// MSCK
3517    /// ```
3518    /// Msck (Hive)
3519    Msck(Msck),
3520    /// ```sql
3521    /// SELECT
3522    /// ```
3523    Query(Box<Query>),
3524    /// ```sql
3525    /// INSERT
3526    /// ```
3527    Insert(Insert),
3528    /// ```sql
3529    /// INSTALL
3530    /// ```
3531    Install {
3532        /// Only for DuckDB
3533        extension_name: Ident,
3534    },
3535    /// ```sql
3536    /// LOAD
3537    /// ```
3538    Load {
3539        /// Only for DuckDB
3540        extension_name: Ident,
3541    },
3542    // TODO: Support ROW FORMAT
3543    /// LOAD DATA from a directory or query source.
3544    Directory {
3545        /// Whether to overwrite existing files.
3546        overwrite: bool,
3547        /// Whether the directory is local to the server.
3548        local: bool,
3549        /// Path to the directory or files.
3550        path: String,
3551        /// Optional file format for the data.
3552        file_format: Option<FileFormat>,
3553        /// Source query providing data to load.
3554        source: Box<Query>,
3555    },
3556    /// A `CASE` statement.
3557    Case(CaseStatement),
3558    /// An `IF` statement.
3559    If(IfStatement),
3560    /// A `WHILE` statement.
3561    While(WhileStatement),
3562    /// A `RAISE` statement.
3563    Raise(RaiseStatement),
3564    /// ```sql
3565    /// CALL <function>
3566    /// ```
3567    Call(Function),
3568    /// ```sql
3569    /// COPY [TO | FROM] ...
3570    /// ```
3571    Copy {
3572        /// The source of 'COPY TO', or the target of 'COPY FROM'
3573        source: CopySource,
3574        /// If true, is a 'COPY TO' statement. If false is a 'COPY FROM'
3575        to: bool,
3576        /// The target of 'COPY TO', or the source of 'COPY FROM'
3577        target: CopyTarget,
3578        /// WITH options (from PostgreSQL version 9.0)
3579        options: Vec<CopyOption>,
3580        /// WITH options (before PostgreSQL version 9.0)
3581        legacy_options: Vec<CopyLegacyOption>,
3582        /// VALUES a vector of values to be copied
3583        values: Vec<Option<String>>,
3584    },
3585    /// ```sql
3586    /// COPY INTO <table> | <location>
3587    /// ```
3588    /// See:
3589    /// <https://docs.snowflake.com/en/sql-reference/sql/copy-into-table>
3590    /// <https://docs.snowflake.com/en/sql-reference/sql/copy-into-location>
3591    ///
3592    /// Copy Into syntax available for Snowflake is different than the one implemented in
3593    /// Postgres. Although they share common prefix, it is reasonable to implement them
3594    /// in different enums. This can be refactored later once custom dialects
3595    /// are allowed to have custom Statements.
3596    CopyIntoSnowflake {
3597        /// Kind of COPY INTO operation (table or location).
3598        kind: CopyIntoSnowflakeKind,
3599        /// Target object for the COPY INTO operation.
3600        into: ObjectName,
3601        /// Optional list of target columns.
3602        into_columns: Option<Vec<Ident>>,
3603        /// Optional source object name (staged data).
3604        from_obj: Option<ObjectName>,
3605        /// Optional alias for the source object.
3606        from_obj_alias: Option<Ident>,
3607        /// Stage-specific parameters (e.g., credentials, path).
3608        stage_params: StageParamsObject,
3609        /// Optional list of transformations applied when loading.
3610        from_transformations: Option<Vec<StageLoadSelectItemKind>>,
3611        /// Optional source query instead of a staged object.
3612        from_query: Option<Box<Query>>,
3613        /// Optional list of specific file names to load.
3614        files: Option<Vec<String>>,
3615        /// Optional filename matching pattern.
3616        pattern: Option<String>,
3617        /// File format options.
3618        file_format: KeyValueOptions,
3619        /// Additional copy options.
3620        copy_options: KeyValueOptions,
3621        /// Optional validation mode string.
3622        validation_mode: Option<String>,
3623        /// Optional partition expression for loading.
3624        partition: Option<Box<Expr>>,
3625    },
3626    /// ```sql
3627    /// OPEN cursor_name
3628    /// ```
3629    /// Opens a cursor.
3630    Open(OpenStatement),
3631    /// ```sql
3632    /// CLOSE
3633    /// ```
3634    /// Closes the portal underlying an open cursor.
3635    Close {
3636        /// Cursor name
3637        cursor: CloseCursor,
3638    },
3639    /// ```sql
3640    /// UPDATE
3641    /// ```
3642    Update(Update),
3643    /// ```sql
3644    /// DELETE
3645    /// ```
3646    Delete(Delete),
3647    /// ```sql
3648    /// CREATE VIEW
3649    /// ```
3650    CreateView(CreateView),
3651    /// ```sql
3652    /// CREATE TABLE
3653    /// ```
3654    CreateTable(CreateTable),
3655    /// ```sql
3656    /// CREATE VIRTUAL TABLE .. USING <module_name> (<module_args>)`
3657    /// ```
3658    /// Sqlite specific statement
3659    CreateVirtualTable {
3660        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
3661        /// Name of the virtual table module instance.
3662        name: ObjectName,
3663        /// `true` when `IF NOT EXISTS` was specified.
3664        if_not_exists: bool,
3665        /// Module name used by the virtual table.
3666        module_name: Ident,
3667        /// Arguments passed to the module.
3668        module_args: Vec<Ident>,
3669    },
3670    /// ```sql
3671    /// `CREATE INDEX`
3672    /// ```
3673    CreateIndex(CreateIndex),
3674    /// ```sql
3675    /// CREATE ROLE
3676    /// ```
3677    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createrole.html)
3678    CreateRole(CreateRole),
3679    /// ```sql
3680    /// CREATE SECRET
3681    /// ```
3682    /// See [DuckDB](https://duckdb.org/docs/sql/statements/create_secret.html)
3683    CreateSecret {
3684        /// `true` when `OR REPLACE` was specified.
3685        or_replace: bool,
3686        /// Optional `TEMPORARY` flag.
3687        temporary: Option<bool>,
3688        /// `true` when `IF NOT EXISTS` was present.
3689        if_not_exists: bool,
3690        /// Optional secret name.
3691        name: Option<Ident>,
3692        /// Optional storage specifier identifier.
3693        storage_specifier: Option<Ident>,
3694        /// The secret type identifier.
3695        secret_type: Ident,
3696        /// Additional secret options.
3697        options: Vec<SecretOption>,
3698    },
3699    /// A `CREATE SERVER` statement.
3700    CreateServer(CreateServerStatement),
3701    /// ```sql
3702    /// CREATE POLICY
3703    /// ```
3704    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createpolicy.html)
3705    CreatePolicy(CreatePolicy),
3706    /// ```sql
3707    /// CREATE CONNECTOR
3708    /// ```
3709    /// See [Hive](https://cwiki.apache.org/confluence/pages/viewpage.action?pageId=27362034#LanguageManualDDL-CreateDataConnectorCreateConnector)
3710    CreateConnector(CreateConnector),
3711    /// ```sql
3712    /// CREATE OPERATOR
3713    /// ```
3714    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createoperator.html)
3715    CreateOperator(CreateOperator),
3716    /// ```sql
3717    /// CREATE OPERATOR FAMILY
3718    /// ```
3719    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createopfamily.html)
3720    CreateOperatorFamily(CreateOperatorFamily),
3721    /// ```sql
3722    /// CREATE OPERATOR CLASS
3723    /// ```
3724    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createopclass.html)
3725    CreateOperatorClass(CreateOperatorClass),
3726    /// ```sql
3727    /// ALTER TABLE
3728    /// ```
3729    AlterTable(AlterTable),
3730    /// ```sql
3731    /// ALTER SCHEMA
3732    /// ```
3733    /// See [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#alter_schema_collate_statement)
3734    AlterSchema(AlterSchema),
3735    /// ```sql
3736    /// ALTER INDEX
3737    /// ```
3738    AlterIndex {
3739        /// Name of the index to alter.
3740        name: ObjectName,
3741        /// The operation to perform on the index.
3742        operation: AlterIndexOperation,
3743    },
3744    /// ```sql
3745    /// ALTER VIEW
3746    /// ```
3747    AlterView {
3748        /// View name being altered.
3749        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
3750        name: ObjectName,
3751        /// Optional new column list for the view.
3752        columns: Vec<Ident>,
3753        /// Replacement query for the view definition.
3754        query: Box<Query>,
3755        /// Additional WITH options for the view.
3756        with_options: Vec<SqlOption>,
3757    },
3758    /// ```sql
3759    /// ALTER FUNCTION
3760    /// ALTER AGGREGATE
3761    /// ```
3762    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-alterfunction.html)
3763    /// and [PostgreSQL](https://www.postgresql.org/docs/current/sql-alteraggregate.html)
3764    AlterFunction(AlterFunction),
3765    /// ```sql
3766    /// ALTER TYPE
3767    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-altertype.html)
3768    /// ```
3769    AlterType(AlterType),
3770    /// ```sql
3771    /// ALTER COLLATION
3772    /// ```
3773    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-altercollation.html)
3774    AlterCollation(AlterCollation),
3775    /// ```sql
3776    /// ALTER OPERATOR
3777    /// ```
3778    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-alteroperator.html)
3779    AlterOperator(AlterOperator),
3780    /// ```sql
3781    /// ALTER OPERATOR FAMILY
3782    /// ```
3783    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-alteropfamily.html)
3784    AlterOperatorFamily(AlterOperatorFamily),
3785    /// ```sql
3786    /// ALTER OPERATOR CLASS
3787    /// ```
3788    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-alteropclass.html)
3789    AlterOperatorClass(AlterOperatorClass),
3790    /// ```sql
3791    /// ALTER ROLE
3792    /// ```
3793    AlterRole {
3794        /// Role name being altered.
3795        name: Ident,
3796        /// Operation to perform on the role.
3797        operation: AlterRoleOperation,
3798    },
3799    /// ```sql
3800    /// ALTER POLICY <NAME> ON <TABLE NAME> [<OPERATION>]
3801    /// ```
3802    /// (Postgresql-specific)
3803    AlterPolicy(AlterPolicy),
3804    /// ```sql
3805    /// ALTER CONNECTOR connector_name SET DCPROPERTIES(property_name=property_value, ...);
3806    /// or
3807    /// ALTER CONNECTOR connector_name SET URL new_url;
3808    /// or
3809    /// ALTER CONNECTOR connector_name SET OWNER [USER|ROLE] user_or_role;
3810    /// ```
3811    /// (Hive-specific)
3812    AlterConnector {
3813        /// Name of the connector to alter.
3814        name: Ident,
3815        /// Optional connector properties to set.
3816        properties: Option<Vec<SqlOption>>,
3817        /// Optional new URL for the connector.
3818        url: Option<String>,
3819        /// Optional new owner specification.
3820        owner: Option<ddl::AlterConnectorOwner>,
3821    },
3822    /// ```sql
3823    /// ALTER SESSION SET sessionParam
3824    /// ALTER SESSION UNSET <param_name> [ , <param_name> , ... ]
3825    /// ```
3826    /// See <https://docs.snowflake.com/en/sql-reference/sql/alter-session>
3827    AlterSession {
3828        /// true is to set for the session parameters, false is to unset
3829        set: bool,
3830        /// The session parameters to set or unset
3831        session_params: KeyValueOptions,
3832    },
3833    /// ```sql
3834    /// ATTACH DATABASE 'path/to/file' AS alias
3835    /// ```
3836    /// (SQLite-specific)
3837    AttachDatabase {
3838        /// The name to bind to the newly attached database
3839        schema_name: Ident,
3840        /// An expression that indicates the path to the database file
3841        database_file_name: Expr,
3842        /// true if the syntax is 'ATTACH DATABASE', false if it's just 'ATTACH'
3843        database: bool,
3844    },
3845    /// (DuckDB-specific)
3846    /// ```sql
3847    /// ATTACH 'sqlite_file.db' AS sqlite_db (READ_ONLY, TYPE SQLITE);
3848    /// ```
3849    /// See <https://duckdb.org/docs/sql/statements/attach.html>
3850    AttachDuckDBDatabase {
3851        /// `true` when `IF NOT EXISTS` was present.
3852        if_not_exists: bool,
3853        /// `true` if the syntax used `ATTACH DATABASE` rather than `ATTACH`.
3854        database: bool,
3855        /// The path identifier to the database file being attached.
3856        database_path: Ident,
3857        /// Optional alias assigned to the attached database.
3858        database_alias: Option<Ident>,
3859        /// Dialect-specific attach options (e.g., `READ_ONLY`).
3860        attach_options: Vec<AttachDuckDBDatabaseOption>,
3861    },
3862    /// (DuckDB-specific)
3863    /// ```sql
3864    /// DETACH db_alias;
3865    /// ```
3866    /// See <https://duckdb.org/docs/sql/statements/attach.html>
3867    DetachDuckDBDatabase {
3868        /// `true` when `IF EXISTS` was present.
3869        if_exists: bool,
3870        /// `true` if the syntax used `DETACH DATABASE` rather than `DETACH`.
3871        database: bool,
3872        /// Alias of the database to detach.
3873        database_alias: Ident,
3874    },
3875    /// ```sql
3876    /// DROP [TABLE, VIEW, ...]
3877    /// ```
3878    Drop {
3879        /// The type of the object to drop: TABLE, VIEW, etc.
3880        object_type: ObjectType,
3881        /// An optional `IF EXISTS` clause. (Non-standard.)
3882        if_exists: bool,
3883        /// One or more objects to drop. (ANSI SQL requires exactly one.)
3884        names: Vec<ObjectName>,
3885        /// Whether `CASCADE` was specified. This will be `false` when
3886        /// `RESTRICT` or no drop behavior at all was specified.
3887        cascade: bool,
3888        /// Whether `RESTRICT` was specified. This will be `false` when
3889        /// `CASCADE` or no drop behavior at all was specified.
3890        restrict: bool,
3891        /// Hive allows you specify whether the table's stored data will be
3892        /// deleted along with the dropped table
3893        purge: bool,
3894        /// MySQL-specific "TEMPORARY" keyword
3895        temporary: bool,
3896        /// MySQL-specific drop index syntax, which requires table specification
3897        /// See <https://dev.mysql.com/doc/refman/8.4/en/drop-index.html>
3898        table: Option<ObjectName>,
3899    },
3900    /// ```sql
3901    /// DROP FUNCTION
3902    /// ```
3903    DropFunction(DropFunction),
3904    /// ```sql
3905    /// DROP DOMAIN
3906    /// ```
3907    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-dropdomain.html)
3908    ///
3909    /// DROP DOMAIN [ IF EXISTS ] name [, ...] [ CASCADE | RESTRICT ]
3910    ///
3911    DropDomain(DropDomain),
3912    /// ```sql
3913    /// DROP PROCEDURE
3914    /// ```
3915    DropProcedure {
3916        /// `true` when `IF EXISTS` was present.
3917        if_exists: bool,
3918        /// One or more functions/procedures to drop.
3919        proc_desc: Vec<FunctionDesc>,
3920        /// Optional drop behavior (`CASCADE` or `RESTRICT`).
3921        drop_behavior: Option<DropBehavior>,
3922    },
3923    /// ```sql
3924    /// DROP SECRET
3925    /// ```
3926    DropSecret {
3927        /// `true` when `IF EXISTS` was present.
3928        if_exists: bool,
3929        /// Optional `TEMPORARY` marker.
3930        temporary: Option<bool>,
3931        /// Name of the secret to drop.
3932        name: Ident,
3933        /// Optional storage specifier identifier.
3934        storage_specifier: Option<Ident>,
3935    },
3936    ///```sql
3937    /// DROP POLICY
3938    /// ```
3939    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-droppolicy.html)
3940    DropPolicy(DropPolicy),
3941    /// ```sql
3942    /// DROP CONNECTOR
3943    /// ```
3944    /// See [Hive](https://cwiki.apache.org/confluence/pages/viewpage.action?pageId=27362034#LanguageManualDDL-DropConnector)
3945    DropConnector {
3946        /// `true` when `IF EXISTS` was present.
3947        if_exists: bool,
3948        /// Name of the connector to drop.
3949        name: Ident,
3950    },
3951    /// ```sql
3952    /// DECLARE
3953    /// ```
3954    /// Declare Cursor Variables
3955    ///
3956    /// Note: this is a PostgreSQL-specific statement,
3957    /// but may also compatible with other SQL.
3958    Declare {
3959        /// Cursor declaration statements collected by `DECLARE`.
3960        stmts: Vec<Declare>,
3961    },
3962    /// ```sql
3963    /// CREATE EXTENSION [ IF NOT EXISTS ] extension_name
3964    ///     [ WITH ] [ SCHEMA schema_name ]
3965    ///              [ VERSION version ]
3966    ///              [ CASCADE ]
3967    /// ```
3968    ///
3969    /// Note: this is a PostgreSQL-specific statement,
3970    CreateExtension(CreateExtension),
3971    /// ```sql
3972    /// CREATE COLLATION
3973    /// ```
3974    /// Note: this is a PostgreSQL-specific statement.
3975    /// <https://www.postgresql.org/docs/current/sql-createcollation.html>
3976    CreateCollation(CreateCollation),
3977    /// ```sql
3978    /// DROP EXTENSION [ IF EXISTS ] name [, ...] [ CASCADE | RESTRICT ]
3979    /// ```
3980    /// Note: this is a PostgreSQL-specific statement.
3981    /// <https://www.postgresql.org/docs/current/sql-dropextension.html>
3982    DropExtension(DropExtension),
3983    /// ```sql
3984    /// DROP OPERATOR [ IF EXISTS ] name ( { left_type | NONE } , right_type ) [, ...] [ CASCADE | RESTRICT ]
3985    /// ```
3986    /// Note: this is a PostgreSQL-specific statement.
3987    /// <https://www.postgresql.org/docs/current/sql-dropoperator.html>
3988    DropOperator(DropOperator),
3989    /// ```sql
3990    /// DROP OPERATOR FAMILY [ IF EXISTS ] name USING index_method [ CASCADE | RESTRICT ]
3991    /// ```
3992    /// Note: this is a PostgreSQL-specific statement.
3993    /// <https://www.postgresql.org/docs/current/sql-dropopfamily.html>
3994    DropOperatorFamily(DropOperatorFamily),
3995    /// ```sql
3996    /// DROP OPERATOR CLASS [ IF EXISTS ] name USING index_method [ CASCADE | RESTRICT ]
3997    /// ```
3998    /// Note: this is a PostgreSQL-specific statement.
3999    /// <https://www.postgresql.org/docs/current/sql-dropopclass.html>
4000    DropOperatorClass(DropOperatorClass),
4001    /// ```sql
4002    /// FETCH
4003    /// ```
4004    /// Retrieve rows from a query using a cursor
4005    ///
4006    /// Note: this is a PostgreSQL-specific statement,
4007    /// but may also compatible with other SQL.
4008    Fetch {
4009        /// Cursor name
4010        name: Ident,
4011        /// The fetch direction (e.g., `FORWARD`, `BACKWARD`).
4012        direction: FetchDirection,
4013        /// The fetch position (e.g., `ALL`, `NEXT`, `ABSOLUTE`).
4014        position: FetchPosition,
4015        /// Optional target table to fetch rows into.
4016        into: Option<ObjectName>,
4017    },
4018    /// ```sql
4019    /// FLUSH [NO_WRITE_TO_BINLOG | LOCAL] flush_option [, flush_option] ... | tables_option
4020    /// ```
4021    ///
4022    /// Note: this is a Mysql-specific statement,
4023    /// but may also compatible with other SQL.
4024    Flush {
4025        /// The specific flush option or object to flush.
4026        object_type: FlushType,
4027        /// Optional flush location (dialect-specific).
4028        location: Option<FlushLocation>,
4029        /// Optional channel name used for flush operations.
4030        channel: Option<String>,
4031        /// Whether a read lock was requested.
4032        read_lock: bool,
4033        /// Whether this is an export flush operation.
4034        export: bool,
4035        /// Optional list of tables involved in the flush.
4036        tables: Vec<ObjectName>,
4037    },
4038    /// ```sql
4039    /// DISCARD [ ALL | PLANS | SEQUENCES | TEMPORARY | TEMP ]
4040    /// ```
4041    ///
4042    /// Note: this is a PostgreSQL-specific statement,
4043    /// but may also compatible with other SQL.
4044    Discard {
4045        /// The kind of object(s) to discard (ALL, PLANS, etc.).
4046        object_type: DiscardObject,
4047    },
4048    /// `SHOW FUNCTIONS`
4049    ///
4050    /// Note: this is a Presto-specific statement.
4051    ShowFunctions {
4052        /// Optional filter for which functions to display.
4053        filter: Option<ShowStatementFilter>,
4054    },
4055    /// ```sql
4056    /// SHOW <variable>
4057    /// ```
4058    ///
4059    /// Note: this is a PostgreSQL-specific statement.
4060    ShowVariable {
4061        /// Variable name as one or more identifiers.
4062        variable: Vec<Ident>,
4063    },
4064    /// ```sql
4065    /// SHOW [GLOBAL | SESSION] STATUS [LIKE 'pattern' | WHERE expr]
4066    /// ```
4067    ///
4068    /// Note: this is a MySQL-specific statement.
4069    ShowStatus {
4070        /// Optional filter for which status entries to display.
4071        filter: Option<ShowStatementFilter>,
4072        /// `true` when `GLOBAL` scope was requested.
4073        global: bool,
4074        /// `true` when `SESSION` scope was requested.
4075        session: bool,
4076    },
4077    /// ```sql
4078    /// SHOW VARIABLES
4079    /// ```
4080    ///
4081    /// Note: this is a MySQL-specific statement.
4082    ShowVariables {
4083        /// Optional filter for which variables to display.
4084        filter: Option<ShowStatementFilter>,
4085        /// `true` when `GLOBAL` scope was requested.
4086        global: bool,
4087        /// `true` when `SESSION` scope was requested.
4088        session: bool,
4089    },
4090    /// ```sql
4091    /// SHOW CREATE TABLE
4092    /// ```
4093    ///
4094    /// Note: this is a MySQL-specific statement.
4095    ShowCreate {
4096        /// The kind of object being shown (TABLE, VIEW, etc.).
4097        obj_type: ShowCreateObject,
4098        /// The name of the object to show create statement for.
4099        obj_name: ObjectName,
4100    },
4101    /// ```sql
4102    /// SHOW COLUMNS
4103    /// ```
4104    ShowColumns {
4105        /// `true` when extended column information was requested.
4106        extended: bool,
4107        /// `true` when full column details were requested.
4108        full: bool,
4109        /// Additional options for `SHOW COLUMNS`.
4110        show_options: ShowStatementOptions,
4111    },
4112    /// ```sql
4113    /// SHOW CATALOGS
4114    /// ```
4115    ShowCatalogs {
4116        /// `true` when terse output format was requested.
4117        terse: bool,
4118        /// `true` when history information was requested.
4119        history: bool,
4120        /// Additional options for `SHOW CATALOGS`.
4121        show_options: ShowStatementOptions,
4122    },
4123    /// ```sql
4124    /// SHOW DATABASES
4125    /// ```
4126    ShowDatabases {
4127        /// `true` when terse output format was requested.
4128        terse: bool,
4129        /// `true` when history information was requested.
4130        history: bool,
4131        /// Additional options for `SHOW DATABASES`.
4132        show_options: ShowStatementOptions,
4133    },
4134    /// ```sql
4135    /// SHOW [FULL] PROCESSLIST
4136    /// ```
4137    ///
4138    /// Note: this is a MySQL-specific statement.
4139    ShowProcessList {
4140        /// `true` when full process information was requested.
4141        full: bool,
4142    },
4143    /// ```sql
4144    /// SHOW SCHEMAS
4145    /// ```
4146    ShowSchemas {
4147        /// `true` when terse (compact) output was requested.
4148        terse: bool,
4149        /// `true` when history information was requested.
4150        history: bool,
4151        /// Additional options for `SHOW SCHEMAS`.
4152        show_options: ShowStatementOptions,
4153    },
4154    // ```sql
4155    // SHOW {CHARACTER SET | CHARSET}
4156    // ```
4157    // [MySQL]:
4158    // <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>
4159    /// Show the available character sets (alias `CHARSET`).
4160    ShowCharset(ShowCharset),
4161    /// ```sql
4162    /// SHOW OBJECTS LIKE 'line%' IN mydb.public
4163    /// ```
4164    /// Snowflake-specific statement
4165    /// <https://docs.snowflake.com/en/sql-reference/sql/show-objects>
4166    ShowObjects(ShowObjects),
4167    /// ```sql
4168    /// SHOW TABLES
4169    /// ```
4170    ShowTables {
4171        /// `true` when terse output format was requested (compact listing).
4172        terse: bool,
4173        /// `true` when history rows are requested.
4174        history: bool,
4175        /// `true` when extended information should be shown.
4176        extended: bool,
4177        /// `true` when a full listing was requested.
4178        full: bool,
4179        /// `true` when external tables should be included.
4180        external: bool,
4181        /// Additional options for `SHOW` statements.
4182        show_options: ShowStatementOptions,
4183    },
4184    /// ```sql
4185    /// SHOW VIEWS
4186    /// ```
4187    ShowViews {
4188        /// `true` when terse output format was requested.
4189        terse: bool,
4190        /// `true` when materialized views should be included.
4191        materialized: bool,
4192        /// Additional options for `SHOW` statements.
4193        show_options: ShowStatementOptions,
4194    },
4195    /// ```sql
4196    /// SHOW COLLATION
4197    /// ```
4198    ///
4199    /// Note: this is a MySQL-specific statement.
4200    ShowCollation {
4201        /// Optional filter for which collations to display.
4202        filter: Option<ShowStatementFilter>,
4203    },
4204    /// ```sql
4205    /// `USE ...`
4206    /// ```
4207    Use(Use),
4208    /// ```sql
4209    /// START  [ TRANSACTION | WORK ] | START TRANSACTION } ...
4210    /// ```
4211    /// If `begin` is false.
4212    ///
4213    /// ```sql
4214    /// `BEGIN  [ TRANSACTION | WORK ] | START TRANSACTION } ...`
4215    /// ```
4216    /// If `begin` is true
4217    StartTransaction {
4218        /// Transaction modes such as `ISOLATION LEVEL` or `READ WRITE`.
4219        modes: Vec<TransactionMode>,
4220        /// `true` when this was parsed as `BEGIN` instead of `START`.
4221        begin: bool,
4222        /// Optional specific keyword used: `TRANSACTION` or `WORK`.
4223        transaction: Option<BeginTransactionKind>,
4224        /// Optional transaction modifier (e.g., `AND NO CHAIN`).
4225        modifier: Option<TransactionModifier>,
4226        /// List of statements belonging to the `BEGIN` block.
4227        /// Example:
4228        /// ```sql
4229        /// BEGIN
4230        ///     SELECT 1;
4231        ///     SELECT 2;
4232        /// END;
4233        /// ```
4234        statements: Vec<Statement>,
4235        /// Exception handling with exception clauses.
4236        /// Example:
4237        /// ```sql
4238        /// EXCEPTION
4239        ///     WHEN EXCEPTION_1 THEN
4240        ///         SELECT 2;
4241        ///     WHEN EXCEPTION_2 OR EXCEPTION_3 THEN
4242        ///         SELECT 3;
4243        ///     WHEN OTHER THEN
4244        ///         SELECT 4;
4245        /// ```
4246        /// <https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#beginexceptionend>
4247        /// <https://docs.snowflake.com/en/sql-reference/snowflake-scripting/exception>
4248        exception: Option<Vec<ExceptionWhen>>,
4249        /// TRUE if the statement has an `END` keyword.
4250        has_end_keyword: bool,
4251    },
4252    /// ```sql
4253    /// COMMENT ON ...
4254    /// ```
4255    ///
4256    /// Note: this is a PostgreSQL-specific statement.
4257    Comment {
4258        /// Type of object being commented (table, column, etc.).
4259        object_type: CommentObject,
4260        /// Name of the object the comment applies to.
4261        object_name: ObjectName,
4262        /// Optional comment text (None to remove comment).
4263        comment: Option<String>,
4264        /// An optional `IF EXISTS` clause. (Non-standard.)
4265        /// See <https://docs.snowflake.com/en/sql-reference/sql/comment>
4266        if_exists: bool,
4267    },
4268    /// ```sql
4269    /// COMMIT [ TRANSACTION | WORK ] [ AND [ NO ] CHAIN ]
4270    /// ```
4271    /// If `end` is false
4272    ///
4273    /// ```sql
4274    /// END [ TRY | CATCH ]
4275    /// ```
4276    /// If `end` is true
4277    Commit {
4278        /// `true` when `AND [ NO ] CHAIN` was present.
4279        chain: bool,
4280        /// `true` when this `COMMIT` was parsed as an `END` block terminator.
4281        end: bool,
4282        /// Optional transaction modifier for commit semantics.
4283        modifier: Option<TransactionModifier>,
4284    },
4285    /// ```sql
4286    /// ROLLBACK [ TRANSACTION | WORK ] [ AND [ NO ] CHAIN ] [ TO [ SAVEPOINT ] savepoint_name ]
4287    /// ```
4288    Rollback {
4289        /// `true` when `AND [ NO ] CHAIN` was present.
4290        chain: bool,
4291        /// Optional savepoint name to roll back to.
4292        savepoint: Option<Ident>,
4293    },
4294    /// ```sql
4295    /// CREATE SCHEMA
4296    /// ```
4297    CreateSchema {
4298        /// `<schema name> | AUTHORIZATION <schema authorization identifier>  | <schema name>  AUTHORIZATION <schema authorization identifier>`
4299        schema_name: SchemaName,
4300        /// `true` when `IF NOT EXISTS` was present.
4301        if_not_exists: bool,
4302        /// Schema properties.
4303        ///
4304        /// ```sql
4305        /// CREATE SCHEMA myschema WITH (key1='value1');
4306        /// ```
4307        ///
4308        /// [Trino](https://trino.io/docs/current/sql/create-schema.html)
4309        with: Option<Vec<SqlOption>>,
4310        /// Schema options.
4311        ///
4312        /// ```sql
4313        /// CREATE SCHEMA myschema OPTIONS(key1='value1');
4314        /// ```
4315        ///
4316        /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_schema_statement)
4317        options: Option<Vec<SqlOption>>,
4318        /// Default collation specification for the schema.
4319        ///
4320        /// ```sql
4321        /// CREATE SCHEMA myschema DEFAULT COLLATE 'und:ci';
4322        /// ```
4323        ///
4324        /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_schema_statement)
4325        default_collate_spec: Option<Expr>,
4326        /// Clones a schema
4327        ///
4328        /// ```sql
4329        /// CREATE SCHEMA myschema CLONE otherschema
4330        /// ```
4331        ///
4332        /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-clone#databases-schemas)
4333        clone: Option<ObjectName>,
4334    },
4335    /// ```sql
4336    /// CREATE DATABASE
4337    /// ```
4338    /// See:
4339    /// <https://docs.snowflake.com/en/sql-reference/sql/create-database>
4340    CreateDatabase {
4341        /// Database name.
4342        db_name: ObjectName,
4343        /// `IF NOT EXISTS` flag.
4344        if_not_exists: bool,
4345        /// Optional location URI.
4346        location: Option<String>,
4347        /// Optional managed location.
4348        managed_location: Option<String>,
4349        /// `OR REPLACE` flag.
4350        or_replace: bool,
4351        /// `TRANSIENT` flag.
4352        transient: bool,
4353        /// Optional clone source.
4354        clone: Option<ObjectName>,
4355        /// Optional data retention time in days.
4356        data_retention_time_in_days: Option<u64>,
4357        /// Optional maximum data extension time in days.
4358        max_data_extension_time_in_days: Option<u64>,
4359        /// Optional external volume identifier.
4360        external_volume: Option<String>,
4361        /// Optional catalog name.
4362        catalog: Option<String>,
4363        /// Whether to replace invalid characters.
4364        replace_invalid_characters: Option<bool>,
4365        /// Default DDL collation string.
4366        default_ddl_collation: Option<String>,
4367        /// Storage serialization policy.
4368        storage_serialization_policy: Option<StorageSerializationPolicy>,
4369        /// Optional comment.
4370        comment: Option<String>,
4371        /// Optional default character set (MySQL).
4372        default_charset: Option<String>,
4373        /// Optional default collation (MySQL).
4374        default_collation: Option<String>,
4375        /// Optional catalog sync identifier.
4376        catalog_sync: Option<String>,
4377        /// Catalog sync namespace mode.
4378        catalog_sync_namespace_mode: Option<CatalogSyncNamespaceMode>,
4379        /// Optional flatten delimiter for namespace sync.
4380        catalog_sync_namespace_flatten_delimiter: Option<String>,
4381        /// Optional tags for the database.
4382        with_tags: Option<Vec<Tag>>,
4383        /// Optional contact entries for the database.
4384        with_contacts: Option<Vec<ContactEntry>>,
4385    },
4386    /// ```sql
4387    /// CREATE FUNCTION
4388    /// ```
4389    ///
4390    /// Supported variants:
4391    /// 1. [Hive](https://cwiki.apache.org/confluence/display/hive/languagemanual+ddl#LanguageManualDDL-Create/Drop/ReloadFunction)
4392    /// 2. [PostgreSQL](https://www.postgresql.org/docs/15/sql-createfunction.html)
4393    /// 3. [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_function_statement)
4394    /// 4. [MsSql](https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql)
4395    CreateFunction(CreateFunction),
4396    /// CREATE TRIGGER statement. See struct [CreateTrigger] for details.
4397    CreateTrigger(CreateTrigger),
4398    /// DROP TRIGGER statement. See struct [DropTrigger] for details.
4399    DropTrigger(DropTrigger),
4400    /// ```sql
4401    /// CREATE PROCEDURE
4402    /// ```
4403    CreateProcedure {
4404        /// `OR ALTER` flag.
4405        or_alter: bool,
4406        /// Procedure name.
4407        name: ObjectName,
4408        /// Optional procedure parameters.
4409        params: Option<Vec<ProcedureParam>>,
4410        /// Optional language identifier.
4411        language: Option<Ident>,
4412        /// Procedure body statements.
4413        body: ConditionalStatements,
4414    },
4415    /// ```sql
4416    /// CREATE MACRO
4417    /// ```
4418    ///
4419    /// Supported variants:
4420    /// 1. [DuckDB](https://duckdb.org/docs/sql/statements/create_macro)
4421    CreateMacro {
4422        /// `OR REPLACE` flag.
4423        or_replace: bool,
4424        /// Whether macro is temporary.
4425        temporary: bool,
4426        /// Macro name.
4427        name: ObjectName,
4428        /// Optional macro arguments.
4429        args: Option<Vec<MacroArg>>,
4430        /// Macro definition body.
4431        definition: MacroDefinition,
4432    },
4433    /// ```sql
4434    /// CREATE STAGE
4435    /// ```
4436    /// See <https://docs.snowflake.com/en/sql-reference/sql/create-stage>
4437    CreateStage {
4438        /// `OR REPLACE` flag for stage.
4439        or_replace: bool,
4440        /// Whether stage is temporary.
4441        temporary: bool,
4442        /// `IF NOT EXISTS` flag.
4443        if_not_exists: bool,
4444        /// Stage name.
4445        name: ObjectName,
4446        /// Stage parameters.
4447        stage_params: StageParamsObject,
4448        /// Directory table parameters.
4449        directory_table_params: KeyValueOptions,
4450        /// File format options.
4451        file_format: KeyValueOptions,
4452        /// Copy options for stage.
4453        copy_options: KeyValueOptions,
4454        /// Optional comment.
4455        comment: Option<String>,
4456    },
4457    /// ```sql
4458    /// ASSERT <condition> [AS <message>]
4459    /// ```
4460    Assert {
4461        /// Assertion condition expression.
4462        condition: Expr,
4463        /// Optional message expression.
4464        message: Option<Expr>,
4465    },
4466    /// ```sql
4467    /// GRANT privileges ON objects TO grantees
4468    /// ```
4469    Grant(Grant),
4470    /// ```sql
4471    /// DENY privileges ON object TO grantees
4472    /// ```
4473    Deny(DenyStatement),
4474    /// ```sql
4475    /// REVOKE privileges ON objects FROM grantees
4476    /// ```
4477    Revoke(Revoke),
4478    /// ```sql
4479    /// DEALLOCATE [ PREPARE ] { name | ALL }
4480    /// ```
4481    ///
4482    /// Note: this is a PostgreSQL-specific statement.
4483    Deallocate {
4484        /// Name to deallocate (or `ALL`).
4485        name: Ident,
4486        /// Whether `PREPARE` keyword was present.
4487        prepare: bool,
4488    },
4489    /// ```sql
4490    /// An `EXECUTE` statement
4491    /// ```
4492    ///
4493    /// Postgres: <https://www.postgresql.org/docs/current/sql-execute.html>
4494    /// MSSQL: <https://learn.microsoft.com/en-us/sql/relational-databases/stored-procedures/execute-a-stored-procedure>
4495    /// BigQuery: <https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#execute_immediate>
4496    /// Snowflake: <https://docs.snowflake.com/en/sql-reference/sql/execute-immediate>
4497    Execute {
4498        /// Optional function/procedure name.
4499        name: Option<ObjectName>,
4500        /// Parameter expressions passed to execute.
4501        parameters: Vec<Expr>,
4502        /// Whether parentheses were present around `parameters`.
4503        has_parentheses: bool,
4504        /// Is this an `EXECUTE IMMEDIATE`.
4505        immediate: bool,
4506        /// Identifiers to capture results into.
4507        into: Vec<Ident>,
4508        /// `USING` expressions with optional aliases.
4509        using: Vec<ExprWithAlias>,
4510        /// Whether the last parameter is the return value of the procedure
4511        /// MSSQL: <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/execute-transact-sql?view=sql-server-ver17#output>
4512        output: bool,
4513        /// Whether to invoke the procedure with the default parameter values
4514        /// MSSQL: <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/execute-transact-sql?view=sql-server-ver17#default>
4515        default: bool,
4516    },
4517    /// ```sql
4518    /// PREPARE name [ ( data_type [, ...] ) ] AS statement
4519    /// ```
4520    ///
4521    /// Note: this is a PostgreSQL-specific statement.
4522    Prepare {
4523        /// Name of the prepared statement.
4524        name: Ident,
4525        /// Optional data types for parameters.
4526        data_types: Vec<DataType>,
4527        /// Statement being prepared.
4528        statement: Box<Statement>,
4529    },
4530    /// ```sql
4531    /// KILL [CONNECTION | QUERY | MUTATION]
4532    /// ```
4533    ///
4534    /// See <https://clickhouse.com/docs/en/sql-reference/statements/kill/>
4535    /// See <https://dev.mysql.com/doc/refman/8.0/en/kill.html>
4536    Kill {
4537        /// Optional kill modifier (CONNECTION, QUERY, MUTATION).
4538        modifier: Option<KillType>,
4539        // processlist_id
4540        /// The id of the process to kill.
4541        id: u64,
4542    },
4543    /// ```sql
4544    /// [EXPLAIN | DESC | DESCRIBE] TABLE
4545    /// ```
4546    /// Note: this is a MySQL-specific statement. See <https://dev.mysql.com/doc/refman/8.0/en/explain.html>
4547    ExplainTable {
4548        /// `EXPLAIN | DESC | DESCRIBE`
4549        describe_alias: DescribeAlias,
4550        /// Hive style `FORMATTED | EXTENDED`
4551        hive_format: Option<HiveDescribeFormat>,
4552        /// Snowflake and ClickHouse support `DESC|DESCRIBE TABLE <table_name>` syntax
4553        ///
4554        /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/desc-table.html)
4555        /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/describe-table)
4556        has_table_keyword: bool,
4557        /// Table name
4558        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
4559        table_name: ObjectName,
4560    },
4561    /// ```sql
4562    /// [EXPLAIN | DESC | DESCRIBE]  <statement>
4563    /// ```
4564    Explain {
4565        /// `EXPLAIN | DESC | DESCRIBE`
4566        describe_alias: DescribeAlias,
4567        /// Carry out the command and show actual run times and other statistics.
4568        analyze: bool,
4569        /// Display additional information regarding the plan.
4570        verbose: bool,
4571        /// `EXPLAIN QUERY PLAN`
4572        /// Display the query plan without running the query.
4573        ///
4574        /// [SQLite](https://sqlite.org/lang_explain.html)
4575        query_plan: bool,
4576        /// `EXPLAIN ESTIMATE`
4577        /// [Clickhouse](https://clickhouse.com/docs/en/sql-reference/statements/explain#explain-estimate)
4578        estimate: bool,
4579        /// A SQL query that specifies what to explain
4580        statement: Box<Statement>,
4581        /// Optional output format of explain
4582        format: Option<AnalyzeFormatKind>,
4583        /// Postgres style utility options, `(analyze, verbose true)`
4584        options: Option<Vec<UtilityOption>>,
4585    },
4586    /// ```sql
4587    /// SAVEPOINT
4588    /// ```
4589    /// Define a new savepoint within the current transaction
4590    Savepoint {
4591        /// Name of the savepoint being defined.
4592        name: Ident,
4593    },
4594    /// ```sql
4595    /// RELEASE [ SAVEPOINT ] savepoint_name
4596    /// ```
4597    ReleaseSavepoint {
4598        /// Name of the savepoint to release.
4599        name: Ident,
4600    },
4601    /// A `MERGE` statement.
4602    ///
4603    /// ```sql
4604    /// MERGE INTO <target_table> USING <source> ON <join_expr> { matchedClause | notMatchedClause } [ ... ]
4605    /// ```
4606    /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/merge)
4607    /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/dml-syntax#merge_statement)
4608    /// [MSSQL](https://learn.microsoft.com/en-us/sql/t-sql/statements/merge-transact-sql?view=sql-server-ver16)
4609    Merge(Merge),
4610    /// ```sql
4611    /// CACHE [ FLAG ] TABLE <table_name> [ OPTIONS('K1' = 'V1', 'K2' = V2) ] [ AS ] [ <query> ]
4612    /// ```
4613    ///
4614    /// See [Spark SQL docs] for more details.
4615    ///
4616    /// [Spark SQL docs]: https://docs.databricks.com/spark/latest/spark-sql/language-manual/sql-ref-syntax-aux-cache-cache-table.html
4617    Cache {
4618        /// Table flag
4619        table_flag: Option<ObjectName>,
4620        /// Table name
4621        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
4622        table_name: ObjectName,
4623        /// `true` if `AS` keyword was present before the query.
4624        has_as: bool,
4625        /// Table confs
4626        options: Vec<SqlOption>,
4627        /// Cache table as a Query
4628        query: Option<Box<Query>>,
4629    },
4630    /// ```sql
4631    /// UNCACHE TABLE [ IF EXISTS ]  <table_name>
4632    /// ```
4633    UNCache {
4634        /// Table name
4635        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
4636        table_name: ObjectName,
4637        /// `true` when `IF EXISTS` was present.
4638        if_exists: bool,
4639    },
4640    /// ```sql
4641    /// CREATE [ { TEMPORARY | TEMP } ] SEQUENCE [ IF NOT EXISTS ] <sequence_name>
4642    /// ```
4643    /// Define a new sequence:
4644    CreateSequence {
4645        /// Whether the sequence is temporary.
4646        temporary: bool,
4647        /// `IF NOT EXISTS` flag.
4648        if_not_exists: bool,
4649        /// Sequence name.
4650        name: ObjectName,
4651        /// Optional data type for the sequence.
4652        data_type: Option<DataType>,
4653        /// Sequence options (INCREMENT, MINVALUE, etc.).
4654        sequence_options: Vec<SequenceOptions>,
4655        /// Optional `OWNED BY` target.
4656        owned_by: Option<ObjectName>,
4657    },
4658    /// A `CREATE DOMAIN` statement.
4659    CreateDomain(CreateDomain),
4660    /// ```sql
4661    /// CREATE TYPE <name>
4662    /// ```
4663    CreateType {
4664        /// Type name to create.
4665        name: ObjectName,
4666        /// Optional type representation details.
4667        representation: Option<UserDefinedTypeRepresentation>,
4668    },
4669    /// ```sql
4670    /// PRAGMA <schema-name>.<pragma-name> = <pragma-value>
4671    /// ```
4672    Pragma {
4673        /// Pragma name (possibly qualified).
4674        name: ObjectName,
4675        /// Optional pragma value.
4676        value: Option<ValueWithSpan>,
4677        /// Whether the pragma used `=`.
4678        is_eq: bool,
4679    },
4680    /// ```sql
4681    /// LOCK [ TABLE ] [ ONLY ] name [ * ] [, ...] [ IN lockmode MODE ] [ NOWAIT ]
4682    /// ```
4683    ///
4684    /// See <https://www.postgresql.org/docs/current/sql-lock.html>
4685    Lock(Lock),
4686    /// ```sql
4687    /// LOCK TABLES <table_name> [READ [LOCAL] | [LOW_PRIORITY] WRITE]
4688    /// ```
4689    /// Note: this is a MySQL-specific statement. See <https://dev.mysql.com/doc/refman/8.0/en/lock-tables.html>
4690    LockTables {
4691        /// List of tables to lock with modes.
4692        tables: Vec<LockTable>,
4693    },
4694    /// ```sql
4695    /// UNLOCK TABLES
4696    /// ```
4697    /// Note: this is a MySQL-specific statement. See <https://dev.mysql.com/doc/refman/8.0/en/lock-tables.html>
4698    UnlockTables,
4699    /// Unloads the result of a query to file
4700    ///
4701    /// [Athena](https://docs.aws.amazon.com/athena/latest/ug/unload.html):
4702    /// ```sql
4703    /// UNLOAD(statement) TO <destination> [ WITH options ]
4704    /// ```
4705    ///
4706    /// [Redshift](https://docs.aws.amazon.com/redshift/latest/dg/r_UNLOAD.html):
4707    /// ```sql
4708    /// UNLOAD('statement') TO <destination> [ OPTIONS ]
4709    /// ```
4710    Unload {
4711        /// Optional query AST to unload.
4712        query: Option<Box<Query>>,
4713        /// Optional original query text.
4714        query_text: Option<String>,
4715        /// Destination identifier.
4716        to: Ident,
4717        /// Optional IAM role/auth information.
4718        auth: Option<IamRoleKind>,
4719        /// Additional `WITH` options.
4720        with: Vec<SqlOption>,
4721        /// Legacy copy-style options.
4722        options: Vec<CopyLegacyOption>,
4723    },
4724    /// ClickHouse:
4725    /// ```sql
4726    /// OPTIMIZE TABLE [db.]name [ON CLUSTER cluster] [PARTITION partition | PARTITION ID 'partition_id'] [FINAL] [DEDUPLICATE [BY expression]]
4727    /// ```
4728    /// See ClickHouse <https://clickhouse.com/docs/en/sql-reference/statements/optimize>
4729    ///
4730    /// Databricks:
4731    /// ```sql
4732    /// OPTIMIZE table_name [WHERE predicate] [ZORDER BY (col_name1 [, ...])]
4733    /// ```
4734    /// See Databricks <https://docs.databricks.com/en/sql/language-manual/delta-optimize.html>
4735    OptimizeTable {
4736        /// Table name to optimize.
4737        name: ObjectName,
4738        /// Whether the `TABLE` keyword was present (ClickHouse uses `OPTIMIZE TABLE`, Databricks uses `OPTIMIZE`).
4739        has_table_keyword: bool,
4740        /// Optional cluster identifier.
4741        /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/optimize)
4742        on_cluster: Option<Ident>,
4743        /// Optional partition spec.
4744        /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/optimize)
4745        partition: Option<Partition>,
4746        /// Whether `FINAL` was specified.
4747        /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/optimize)
4748        include_final: bool,
4749        /// Optional deduplication settings.
4750        /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/optimize)
4751        deduplicate: Option<Deduplicate>,
4752        /// Optional WHERE predicate.
4753        /// [Databricks](https://docs.databricks.com/en/sql/language-manual/delta-optimize.html)
4754        predicate: Option<Expr>,
4755        /// Optional ZORDER BY columns.
4756        /// [Databricks](https://docs.databricks.com/en/sql/language-manual/delta-optimize.html)
4757        zorder: Option<Vec<Expr>>,
4758    },
4759    /// ```sql
4760    /// LISTEN
4761    /// ```
4762    /// listen for a notification channel
4763    ///
4764    /// See Postgres <https://www.postgresql.org/docs/current/sql-listen.html>
4765    LISTEN {
4766        /// Notification channel identifier.
4767        channel: Ident,
4768    },
4769    /// ```sql
4770    /// UNLISTEN
4771    /// ```
4772    /// stop listening for a notification
4773    ///
4774    /// See Postgres <https://www.postgresql.org/docs/current/sql-unlisten.html>
4775    UNLISTEN {
4776        /// Notification channel identifier.
4777        channel: Ident,
4778    },
4779    /// ```sql
4780    /// NOTIFY channel [ , payload ]
4781    /// ```
4782    /// send a notification event together with an optional "payload" string to channel
4783    ///
4784    /// See Postgres <https://www.postgresql.org/docs/current/sql-notify.html>
4785    NOTIFY {
4786        /// Notification channel identifier.
4787        channel: Ident,
4788        /// Optional payload string.
4789        payload: Option<String>,
4790    },
4791    /// ```sql
4792    /// LOAD DATA [LOCAL] INPATH 'filepath' [OVERWRITE] INTO TABLE tablename
4793    /// [PARTITION (partcol1=val1, partcol2=val2 ...)]
4794    /// [INPUTFORMAT 'inputformat' SERDE 'serde']
4795    /// ```
4796    /// Loading files into tables
4797    ///
4798    /// See Hive <https://cwiki.apache.org/confluence/pages/viewpage.action?pageId=27362036#LanguageManualDML-Loadingfilesintotables>
4799    LoadData {
4800        /// Whether `LOCAL` is present.
4801        local: bool,
4802        /// Input path for files to load.
4803        inpath: String,
4804        /// Whether `OVERWRITE` was specified.
4805        overwrite: bool,
4806        /// Target table name to load into.
4807        table_name: ObjectName,
4808        /// Optional partition specification.
4809        partitioned: Option<Vec<Expr>>,
4810        /// Optional table format information.
4811        table_format: Option<HiveLoadDataFormat>,
4812    },
4813    /// ```sql
4814    /// Rename TABLE tbl_name TO new_tbl_name[, tbl_name2 TO new_tbl_name2] ...
4815    /// ```
4816    /// Renames one or more tables
4817    ///
4818    /// See Mysql <https://dev.mysql.com/doc/refman/9.1/en/rename-table.html>
4819    RenameTable(Vec<RenameTable>),
4820    /// Snowflake `LIST`
4821    /// See: <https://docs.snowflake.com/en/sql-reference/sql/list>
4822    List(FileStagingCommand),
4823    /// Snowflake `REMOVE`
4824    /// See: <https://docs.snowflake.com/en/sql-reference/sql/remove>
4825    Remove(FileStagingCommand),
4826    /// RaiseError (MSSQL)
4827    /// RAISERROR ( { msg_id | msg_str | @local_variable }
4828    /// { , severity , state }
4829    /// [ , argument [ , ...n ] ] )
4830    /// [ WITH option [ , ...n ] ]
4831    /// See <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/raiserror-transact-sql?view=sql-server-ver16>
4832    RaisError {
4833        /// Error message expression or identifier.
4834        message: Box<Expr>,
4835        /// Severity expression.
4836        severity: Box<Expr>,
4837        /// State expression.
4838        state: Box<Expr>,
4839        /// Substitution arguments for the message.
4840        arguments: Vec<Expr>,
4841        /// Additional `WITH` options for RAISERROR.
4842        options: Vec<RaisErrorOption>,
4843    },
4844    /// A MSSQL `THROW` statement.
4845    Throw(ThrowStatement),
4846    /// ```sql
4847    /// PRINT msg_str | @local_variable | string_expr
4848    /// ```
4849    ///
4850    /// See: <https://learn.microsoft.com/en-us/sql/t-sql/statements/print-transact-sql>
4851    Print(PrintStatement),
4852    /// MSSQL `WAITFOR` statement.
4853    ///
4854    /// See: <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/waitfor-transact-sql>
4855    WaitFor(WaitForStatement),
4856    /// ```sql
4857    /// RETURN [ expression ]
4858    /// ```
4859    ///
4860    /// See [ReturnStatement]
4861    Return(ReturnStatement),
4862    /// Export data statement
4863    ///
4864    /// Example:
4865    /// ```sql
4866    /// EXPORT DATA OPTIONS(uri='gs://bucket/folder/*', format='PARQUET', overwrite=true) AS
4867    /// SELECT field1, field2 FROM mydataset.table1 ORDER BY field1 LIMIT 10
4868    /// ```
4869    /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/export-statements)
4870    ExportData(ExportData),
4871    /// ```sql
4872    /// CREATE [OR REPLACE] USER <user> [IF NOT EXISTS]
4873    /// ```
4874    /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-user)
4875    CreateUser(CreateUser),
4876    /// ```sql
4877    /// ALTER USER \[ IF EXISTS \] \[ <name> \]
4878    /// ```
4879    /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/alter-user)
4880    AlterUser(AlterUser),
4881    /// Re-sorts rows and reclaims space in either a specified table or all tables in the current database
4882    ///
4883    /// ```sql
4884    /// VACUUM tbl
4885    /// ```
4886    /// [Redshift](https://docs.aws.amazon.com/redshift/latest/dg/r_VACUUM_command.html)
4887    Vacuum(VacuumStatement),
4888    /// Restore the value of a run-time parameter to the default value.
4889    ///
4890    /// ```sql
4891    /// RESET configuration_parameter;
4892    /// RESET ALL;
4893    /// ```
4894    /// [PostgreSQL](https://www.postgresql.org/docs/current/sql-reset.html)
4895    Reset(ResetStatement),
4896}
4897
4898impl From<Analyze> for Statement {
4899    fn from(analyze: Analyze) -> Self {
4900        Statement::Analyze(analyze)
4901    }
4902}
4903
4904impl From<ddl::Truncate> for Statement {
4905    fn from(truncate: ddl::Truncate) -> Self {
4906        Statement::Truncate(truncate)
4907    }
4908}
4909
4910impl From<Lock> for Statement {
4911    fn from(lock: Lock) -> Self {
4912        Statement::Lock(lock)
4913    }
4914}
4915
4916impl From<ddl::Msck> for Statement {
4917    fn from(msck: ddl::Msck) -> Self {
4918        Statement::Msck(msck)
4919    }
4920}
4921
4922/// ```sql
4923/// {COPY | REVOKE} CURRENT GRANTS
4924/// ```
4925///
4926/// - [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/grant-ownership#optional-parameters)
4927#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
4928#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4929#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
4930pub enum CurrentGrantsKind {
4931    /// `COPY CURRENT GRANTS` (copy current grants to target).
4932    CopyCurrentGrants,
4933    /// `REVOKE CURRENT GRANTS` (revoke current grants from target).
4934    RevokeCurrentGrants,
4935}
4936
4937impl fmt::Display for CurrentGrantsKind {
4938    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
4939        match self {
4940            CurrentGrantsKind::CopyCurrentGrants => write!(f, "COPY CURRENT GRANTS"),
4941            CurrentGrantsKind::RevokeCurrentGrants => write!(f, "REVOKE CURRENT GRANTS"),
4942        }
4943    }
4944}
4945
4946#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
4947#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4948#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
4949/// `RAISERROR` options
4950/// See <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/raiserror-transact-sql?view=sql-server-ver16#options>
4951pub enum RaisErrorOption {
4952    /// Log the error.
4953    Log,
4954    /// Do not wait for completion.
4955    NoWait,
4956    /// Set the error state.
4957    SetError,
4958}
4959
4960impl fmt::Display for RaisErrorOption {
4961    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
4962        match self {
4963            RaisErrorOption::Log => write!(f, "LOG"),
4964            RaisErrorOption::NoWait => write!(f, "NOWAIT"),
4965            RaisErrorOption::SetError => write!(f, "SETERROR"),
4966        }
4967    }
4968}
4969
4970impl fmt::Display for Statement {
4971    /// Formats a SQL statement with support for pretty printing.
4972    ///
4973    /// When using the alternate flag (`{:#}`), the statement will be formatted with proper
4974    /// indentation and line breaks. For example:
4975    ///
4976    /// ```
4977    /// # use sqlparser::dialect::GenericDialect;
4978    /// # use sqlparser::parser::Parser;
4979    /// let sql = "SELECT a, b FROM table_1";
4980    /// let ast = Parser::parse_sql(&GenericDialect, sql).unwrap();
4981    ///
4982    /// // Regular formatting
4983    /// assert_eq!(format!("{}", ast[0]), "SELECT a, b FROM table_1");
4984    ///
4985    /// // Pretty printing
4986    /// assert_eq!(format!("{:#}", ast[0]),
4987    /// r#"SELECT
4988    ///   a,
4989    ///   b
4990    /// FROM
4991    ///   table_1"#);
4992    /// ```
4993    // Clippy thinks this function is too complicated, but it is painful to
4994    // split up without extracting structs for each `Statement` variant.
4995    #[allow(clippy::cognitive_complexity)]
4996    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
4997        match self {
4998            Statement::Flush {
4999                object_type,
5000                location,
5001                channel,
5002                read_lock,
5003                export,
5004                tables,
5005            } => {
5006                write!(f, "FLUSH")?;
5007                if let Some(location) = location {
5008                    f.write_str(" ")?;
5009                    location.fmt(f)?;
5010                }
5011                write!(f, " {object_type}")?;
5012
5013                if let Some(channel) = channel {
5014                    write!(f, " FOR CHANNEL {channel}")?;
5015                }
5016
5017                write!(
5018                    f,
5019                    "{tables}{read}{export}",
5020                    tables = if !tables.is_empty() {
5021                        format!(" {}", display_comma_separated(tables))
5022                    } else {
5023                        String::new()
5024                    },
5025                    export = if *export { " FOR EXPORT" } else { "" },
5026                    read = if *read_lock { " WITH READ LOCK" } else { "" }
5027                )
5028            }
5029            Statement::Kill { modifier, id } => {
5030                write!(f, "KILL ")?;
5031
5032                if let Some(m) = modifier {
5033                    write!(f, "{m} ")?;
5034                }
5035
5036                write!(f, "{id}")
5037            }
5038            Statement::ExplainTable {
5039                describe_alias,
5040                hive_format,
5041                has_table_keyword,
5042                table_name,
5043            } => {
5044                write!(f, "{describe_alias} ")?;
5045
5046                if let Some(format) = hive_format {
5047                    write!(f, "{format} ")?;
5048                }
5049                if *has_table_keyword {
5050                    write!(f, "TABLE ")?;
5051                }
5052
5053                write!(f, "{table_name}")
5054            }
5055            Statement::Explain {
5056                describe_alias,
5057                verbose,
5058                analyze,
5059                query_plan,
5060                estimate,
5061                statement,
5062                format,
5063                options,
5064            } => {
5065                write!(f, "{describe_alias} ")?;
5066
5067                if *query_plan {
5068                    write!(f, "QUERY PLAN ")?;
5069                }
5070                if *analyze {
5071                    write!(f, "ANALYZE ")?;
5072                }
5073                if *estimate {
5074                    write!(f, "ESTIMATE ")?;
5075                }
5076
5077                if *verbose {
5078                    write!(f, "VERBOSE ")?;
5079                }
5080
5081                if let Some(format) = format {
5082                    write!(f, "{format} ")?;
5083                }
5084
5085                if let Some(options) = options {
5086                    write!(f, "({}) ", display_comma_separated(options))?;
5087                }
5088
5089                write!(f, "{statement}")
5090            }
5091            Statement::Query(s) => s.fmt(f),
5092            Statement::Declare { stmts } => {
5093                write!(f, "DECLARE ")?;
5094                write!(f, "{}", display_separated(stmts, "; "))
5095            }
5096            Statement::Fetch {
5097                name,
5098                direction,
5099                position,
5100                into,
5101            } => {
5102                write!(f, "FETCH {direction} {position} {name}")?;
5103
5104                if let Some(into) = into {
5105                    write!(f, " INTO {into}")?;
5106                }
5107
5108                Ok(())
5109            }
5110            Statement::Directory {
5111                overwrite,
5112                local,
5113                path,
5114                file_format,
5115                source,
5116            } => {
5117                write!(
5118                    f,
5119                    "INSERT{overwrite}{local} DIRECTORY '{path}'",
5120                    overwrite = if *overwrite { " OVERWRITE" } else { "" },
5121                    local = if *local { " LOCAL" } else { "" },
5122                    path = path
5123                )?;
5124                if let Some(ref ff) = file_format {
5125                    write!(f, " STORED AS {ff}")?
5126                }
5127                write!(f, " {source}")
5128            }
5129            Statement::Msck(msck) => msck.fmt(f),
5130            Statement::Truncate(truncate) => truncate.fmt(f),
5131            Statement::Case(stmt) => {
5132                write!(f, "{stmt}")
5133            }
5134            Statement::If(stmt) => {
5135                write!(f, "{stmt}")
5136            }
5137            Statement::While(stmt) => {
5138                write!(f, "{stmt}")
5139            }
5140            Statement::Raise(stmt) => {
5141                write!(f, "{stmt}")
5142            }
5143            Statement::AttachDatabase {
5144                schema_name,
5145                database_file_name,
5146                database,
5147            } => {
5148                let keyword = if *database { "DATABASE " } else { "" };
5149                write!(f, "ATTACH {keyword}{database_file_name} AS {schema_name}")
5150            }
5151            Statement::AttachDuckDBDatabase {
5152                if_not_exists,
5153                database,
5154                database_path,
5155                database_alias,
5156                attach_options,
5157            } => {
5158                write!(
5159                    f,
5160                    "ATTACH{database}{if_not_exists} {database_path}",
5161                    database = if *database { " DATABASE" } else { "" },
5162                    if_not_exists = if *if_not_exists { " IF NOT EXISTS" } else { "" },
5163                )?;
5164                if let Some(alias) = database_alias {
5165                    write!(f, " AS {alias}")?;
5166                }
5167                if !attach_options.is_empty() {
5168                    write!(f, " ({})", display_comma_separated(attach_options))?;
5169                }
5170                Ok(())
5171            }
5172            Statement::DetachDuckDBDatabase {
5173                if_exists,
5174                database,
5175                database_alias,
5176            } => {
5177                write!(
5178                    f,
5179                    "DETACH{database}{if_exists} {database_alias}",
5180                    database = if *database { " DATABASE" } else { "" },
5181                    if_exists = if *if_exists { " IF EXISTS" } else { "" },
5182                )?;
5183                Ok(())
5184            }
5185            Statement::Analyze(analyze) => analyze.fmt(f),
5186            Statement::Insert(insert) => insert.fmt(f),
5187            Statement::Install {
5188                extension_name: name,
5189            } => write!(f, "INSTALL {name}"),
5190
5191            Statement::Load {
5192                extension_name: name,
5193            } => write!(f, "LOAD {name}"),
5194
5195            Statement::Call(function) => write!(f, "CALL {function}"),
5196
5197            Statement::Copy {
5198                source,
5199                to,
5200                target,
5201                options,
5202                legacy_options,
5203                values,
5204            } => {
5205                write!(f, "COPY")?;
5206                match source {
5207                    CopySource::Query(query) => write!(f, " ({query})")?,
5208                    CopySource::Table {
5209                        table_name,
5210                        columns,
5211                    } => {
5212                        write!(f, " {table_name}")?;
5213                        if !columns.is_empty() {
5214                            write!(f, " ({})", display_comma_separated(columns))?;
5215                        }
5216                    }
5217                }
5218                write!(f, " {} {}", if *to { "TO" } else { "FROM" }, target)?;
5219                if !options.is_empty() {
5220                    write!(f, " ({})", display_comma_separated(options))?;
5221                }
5222                if !legacy_options.is_empty() {
5223                    write!(f, " {}", display_separated(legacy_options, " "))?;
5224                }
5225                if !values.is_empty() {
5226                    writeln!(f, ";")?;
5227                    let mut delim = "";
5228                    for v in values {
5229                        write!(f, "{delim}")?;
5230                        delim = "\t";
5231                        if let Some(v) = v {
5232                            write!(f, "{v}")?;
5233                        } else {
5234                            write!(f, "\\N")?;
5235                        }
5236                    }
5237                    write!(f, "\n\\.")?;
5238                }
5239                Ok(())
5240            }
5241            Statement::Update(update) => update.fmt(f),
5242            Statement::Delete(delete) => delete.fmt(f),
5243            Statement::Open(open) => open.fmt(f),
5244            Statement::Close { cursor } => {
5245                write!(f, "CLOSE {cursor}")?;
5246
5247                Ok(())
5248            }
5249            Statement::CreateDatabase {
5250                db_name,
5251                if_not_exists,
5252                location,
5253                managed_location,
5254                or_replace,
5255                transient,
5256                clone,
5257                data_retention_time_in_days,
5258                max_data_extension_time_in_days,
5259                external_volume,
5260                catalog,
5261                replace_invalid_characters,
5262                default_ddl_collation,
5263                storage_serialization_policy,
5264                comment,
5265                default_charset,
5266                default_collation,
5267                catalog_sync,
5268                catalog_sync_namespace_mode,
5269                catalog_sync_namespace_flatten_delimiter,
5270                with_tags,
5271                with_contacts,
5272            } => {
5273                write!(
5274                    f,
5275                    "CREATE {or_replace}{transient}DATABASE {if_not_exists}{name}",
5276                    or_replace = if *or_replace { "OR REPLACE " } else { "" },
5277                    transient = if *transient { "TRANSIENT " } else { "" },
5278                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
5279                    name = db_name,
5280                )?;
5281
5282                if let Some(l) = location {
5283                    write!(f, " LOCATION '{l}'")?;
5284                }
5285                if let Some(ml) = managed_location {
5286                    write!(f, " MANAGEDLOCATION '{ml}'")?;
5287                }
5288                if let Some(clone) = clone {
5289                    write!(f, " CLONE {clone}")?;
5290                }
5291
5292                if let Some(value) = data_retention_time_in_days {
5293                    write!(f, " DATA_RETENTION_TIME_IN_DAYS = {value}")?;
5294                }
5295
5296                if let Some(value) = max_data_extension_time_in_days {
5297                    write!(f, " MAX_DATA_EXTENSION_TIME_IN_DAYS = {value}")?;
5298                }
5299
5300                if let Some(vol) = external_volume {
5301                    write!(f, " EXTERNAL_VOLUME = '{vol}'")?;
5302                }
5303
5304                if let Some(cat) = catalog {
5305                    write!(f, " CATALOG = '{cat}'")?;
5306                }
5307
5308                if let Some(true) = replace_invalid_characters {
5309                    write!(f, " REPLACE_INVALID_CHARACTERS = TRUE")?;
5310                } else if let Some(false) = replace_invalid_characters {
5311                    write!(f, " REPLACE_INVALID_CHARACTERS = FALSE")?;
5312                }
5313
5314                if let Some(collation) = default_ddl_collation {
5315                    write!(f, " DEFAULT_DDL_COLLATION = '{collation}'")?;
5316                }
5317
5318                if let Some(policy) = storage_serialization_policy {
5319                    write!(f, " STORAGE_SERIALIZATION_POLICY = {policy}")?;
5320                }
5321
5322                if let Some(comment) = comment {
5323                    write!(f, " COMMENT = '{comment}'")?;
5324                }
5325
5326                if let Some(charset) = default_charset {
5327                    write!(f, " DEFAULT CHARACTER SET {charset}")?;
5328                }
5329
5330                if let Some(collation) = default_collation {
5331                    write!(f, " DEFAULT COLLATE {collation}")?;
5332                }
5333
5334                if let Some(sync) = catalog_sync {
5335                    write!(f, " CATALOG_SYNC = '{sync}'")?;
5336                }
5337
5338                if let Some(mode) = catalog_sync_namespace_mode {
5339                    write!(f, " CATALOG_SYNC_NAMESPACE_MODE = {mode}")?;
5340                }
5341
5342                if let Some(delim) = catalog_sync_namespace_flatten_delimiter {
5343                    write!(f, " CATALOG_SYNC_NAMESPACE_FLATTEN_DELIMITER = '{delim}'")?;
5344                }
5345
5346                if let Some(tags) = with_tags {
5347                    write!(f, " WITH TAG ({})", display_comma_separated(tags))?;
5348                }
5349
5350                if let Some(contacts) = with_contacts {
5351                    write!(f, " WITH CONTACT ({})", display_comma_separated(contacts))?;
5352                }
5353                Ok(())
5354            }
5355            Statement::CreateFunction(create_function) => create_function.fmt(f),
5356            Statement::CreateDomain(create_domain) => create_domain.fmt(f),
5357            Statement::CreateTrigger(create_trigger) => create_trigger.fmt(f),
5358            Statement::DropTrigger(drop_trigger) => drop_trigger.fmt(f),
5359            Statement::CreateProcedure {
5360                name,
5361                or_alter,
5362                params,
5363                language,
5364                body,
5365            } => {
5366                write!(
5367                    f,
5368                    "CREATE {or_alter}PROCEDURE {name}",
5369                    or_alter = if *or_alter { "OR ALTER " } else { "" },
5370                    name = name
5371                )?;
5372
5373                if let Some(p) = params {
5374                    if !p.is_empty() {
5375                        write!(f, " ({})", display_comma_separated(p))?;
5376                    }
5377                }
5378
5379                if let Some(language) = language {
5380                    write!(f, " LANGUAGE {language}")?;
5381                }
5382
5383                write!(f, " AS {body}")
5384            }
5385            Statement::CreateMacro {
5386                or_replace,
5387                temporary,
5388                name,
5389                args,
5390                definition,
5391            } => {
5392                write!(
5393                    f,
5394                    "CREATE {or_replace}{temp}MACRO {name}",
5395                    temp = if *temporary { "TEMPORARY " } else { "" },
5396                    or_replace = if *or_replace { "OR REPLACE " } else { "" },
5397                )?;
5398                if let Some(args) = args {
5399                    write!(f, "({})", display_comma_separated(args))?;
5400                }
5401                match definition {
5402                    MacroDefinition::Expr(expr) => write!(f, " AS {expr}")?,
5403                    MacroDefinition::Table(query) => write!(f, " AS TABLE {query}")?,
5404                }
5405                Ok(())
5406            }
5407            Statement::CreateView(create_view) => create_view.fmt(f),
5408            Statement::CreateTable(create_table) => create_table.fmt(f),
5409            Statement::LoadData {
5410                local,
5411                inpath,
5412                overwrite,
5413                table_name,
5414                partitioned,
5415                table_format,
5416            } => {
5417                write!(
5418                    f,
5419                    "LOAD DATA {local}INPATH '{inpath}' {overwrite}INTO TABLE {table_name}",
5420                    local = if *local { "LOCAL " } else { "" },
5421                    inpath = inpath,
5422                    overwrite = if *overwrite { "OVERWRITE " } else { "" },
5423                    table_name = table_name,
5424                )?;
5425                if let Some(ref parts) = &partitioned {
5426                    if !parts.is_empty() {
5427                        write!(f, " PARTITION ({})", display_comma_separated(parts))?;
5428                    }
5429                }
5430                if let Some(HiveLoadDataFormat {
5431                    serde,
5432                    input_format,
5433                }) = &table_format
5434                {
5435                    write!(f, " INPUTFORMAT {input_format} SERDE {serde}")?;
5436                }
5437                Ok(())
5438            }
5439            Statement::CreateVirtualTable {
5440                name,
5441                if_not_exists,
5442                module_name,
5443                module_args,
5444            } => {
5445                write!(
5446                    f,
5447                    "CREATE VIRTUAL TABLE {if_not_exists}{name} USING {module_name}",
5448                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
5449                    name = name,
5450                    module_name = module_name
5451                )?;
5452                if !module_args.is_empty() {
5453                    write!(f, " ({})", display_comma_separated(module_args))?;
5454                }
5455                Ok(())
5456            }
5457            Statement::CreateIndex(create_index) => create_index.fmt(f),
5458            Statement::CreateExtension(create_extension) => write!(f, "{create_extension}"),
5459            Statement::CreateCollation(create_collation) => write!(f, "{create_collation}"),
5460            Statement::DropExtension(drop_extension) => write!(f, "{drop_extension}"),
5461            Statement::DropOperator(drop_operator) => write!(f, "{drop_operator}"),
5462            Statement::DropOperatorFamily(drop_operator_family) => {
5463                write!(f, "{drop_operator_family}")
5464            }
5465            Statement::DropOperatorClass(drop_operator_class) => {
5466                write!(f, "{drop_operator_class}")
5467            }
5468            Statement::CreateRole(create_role) => write!(f, "{create_role}"),
5469            Statement::CreateSecret {
5470                or_replace,
5471                temporary,
5472                if_not_exists,
5473                name,
5474                storage_specifier,
5475                secret_type,
5476                options,
5477            } => {
5478                write!(
5479                    f,
5480                    "CREATE {or_replace}",
5481                    or_replace = if *or_replace { "OR REPLACE " } else { "" },
5482                )?;
5483                if let Some(t) = temporary {
5484                    write!(f, "{}", if *t { "TEMPORARY " } else { "PERSISTENT " })?;
5485                }
5486                write!(
5487                    f,
5488                    "SECRET {if_not_exists}",
5489                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
5490                )?;
5491                if let Some(n) = name {
5492                    write!(f, "{n} ")?;
5493                };
5494                if let Some(s) = storage_specifier {
5495                    write!(f, "IN {s} ")?;
5496                }
5497                write!(f, "( TYPE {secret_type}",)?;
5498                if !options.is_empty() {
5499                    write!(f, ", {o}", o = display_comma_separated(options))?;
5500                }
5501                write!(f, " )")?;
5502                Ok(())
5503            }
5504            Statement::CreateServer(stmt) => {
5505                write!(f, "{stmt}")
5506            }
5507            Statement::CreatePolicy(policy) => write!(f, "{policy}"),
5508            Statement::CreateConnector(create_connector) => create_connector.fmt(f),
5509            Statement::CreateOperator(create_operator) => create_operator.fmt(f),
5510            Statement::CreateOperatorFamily(create_operator_family) => {
5511                create_operator_family.fmt(f)
5512            }
5513            Statement::CreateOperatorClass(create_operator_class) => create_operator_class.fmt(f),
5514            Statement::AlterTable(alter_table) => write!(f, "{alter_table}"),
5515            Statement::AlterIndex { name, operation } => {
5516                write!(f, "ALTER INDEX {name} {operation}")
5517            }
5518            Statement::AlterView {
5519                name,
5520                columns,
5521                query,
5522                with_options,
5523            } => {
5524                write!(f, "ALTER VIEW {name}")?;
5525                if !with_options.is_empty() {
5526                    write!(f, " WITH ({})", display_comma_separated(with_options))?;
5527                }
5528                if !columns.is_empty() {
5529                    write!(f, " ({})", display_comma_separated(columns))?;
5530                }
5531                write!(f, " AS {query}")
5532            }
5533            Statement::AlterFunction(alter_function) => write!(f, "{alter_function}"),
5534            Statement::AlterType(AlterType { name, operation }) => {
5535                write!(f, "ALTER TYPE {name} {operation}")
5536            }
5537            Statement::AlterCollation(alter_collation) => write!(f, "{alter_collation}"),
5538            Statement::AlterOperator(alter_operator) => write!(f, "{alter_operator}"),
5539            Statement::AlterOperatorFamily(alter_operator_family) => {
5540                write!(f, "{alter_operator_family}")
5541            }
5542            Statement::AlterOperatorClass(alter_operator_class) => {
5543                write!(f, "{alter_operator_class}")
5544            }
5545            Statement::AlterRole { name, operation } => {
5546                write!(f, "ALTER ROLE {name} {operation}")
5547            }
5548            Statement::AlterPolicy(alter_policy) => write!(f, "{alter_policy}"),
5549            Statement::AlterConnector {
5550                name,
5551                properties,
5552                url,
5553                owner,
5554            } => {
5555                write!(f, "ALTER CONNECTOR {name}")?;
5556                if let Some(properties) = properties {
5557                    write!(
5558                        f,
5559                        " SET DCPROPERTIES({})",
5560                        display_comma_separated(properties)
5561                    )?;
5562                }
5563                if let Some(url) = url {
5564                    write!(f, " SET URL '{url}'")?;
5565                }
5566                if let Some(owner) = owner {
5567                    write!(f, " SET OWNER {owner}")?;
5568                }
5569                Ok(())
5570            }
5571            Statement::AlterSession {
5572                set,
5573                session_params,
5574            } => {
5575                write!(
5576                    f,
5577                    "ALTER SESSION {set}",
5578                    set = if *set { "SET" } else { "UNSET" }
5579                )?;
5580                if !session_params.options.is_empty() {
5581                    if *set {
5582                        write!(f, " {session_params}")?;
5583                    } else {
5584                        let options = session_params
5585                            .options
5586                            .iter()
5587                            .map(|p| p.option_name.clone())
5588                            .collect::<Vec<_>>();
5589                        write!(f, " {}", display_separated(&options, ", "))?;
5590                    }
5591                }
5592                Ok(())
5593            }
5594            Statement::Drop {
5595                object_type,
5596                if_exists,
5597                names,
5598                cascade,
5599                restrict,
5600                purge,
5601                temporary,
5602                table,
5603            } => {
5604                write!(
5605                    f,
5606                    "DROP {}{}{} {}{}{}{}",
5607                    if *temporary { "TEMPORARY " } else { "" },
5608                    object_type,
5609                    if *if_exists { " IF EXISTS" } else { "" },
5610                    display_comma_separated(names),
5611                    if *cascade { " CASCADE" } else { "" },
5612                    if *restrict { " RESTRICT" } else { "" },
5613                    if *purge { " PURGE" } else { "" },
5614                )?;
5615                if let Some(table_name) = table.as_ref() {
5616                    write!(f, " ON {table_name}")?;
5617                };
5618                Ok(())
5619            }
5620            Statement::DropFunction(drop_function) => write!(f, "{drop_function}"),
5621            Statement::DropDomain(DropDomain {
5622                if_exists,
5623                name,
5624                drop_behavior,
5625            }) => {
5626                write!(
5627                    f,
5628                    "DROP DOMAIN{} {name}",
5629                    if *if_exists { " IF EXISTS" } else { "" },
5630                )?;
5631                if let Some(op) = drop_behavior {
5632                    write!(f, " {op}")?;
5633                }
5634                Ok(())
5635            }
5636            Statement::DropProcedure {
5637                if_exists,
5638                proc_desc,
5639                drop_behavior,
5640            } => {
5641                write!(
5642                    f,
5643                    "DROP PROCEDURE{} {}",
5644                    if *if_exists { " IF EXISTS" } else { "" },
5645                    display_comma_separated(proc_desc),
5646                )?;
5647                if let Some(op) = drop_behavior {
5648                    write!(f, " {op}")?;
5649                }
5650                Ok(())
5651            }
5652            Statement::DropSecret {
5653                if_exists,
5654                temporary,
5655                name,
5656                storage_specifier,
5657            } => {
5658                write!(f, "DROP ")?;
5659                if let Some(t) = temporary {
5660                    write!(f, "{}", if *t { "TEMPORARY " } else { "PERSISTENT " })?;
5661                }
5662                write!(
5663                    f,
5664                    "SECRET {if_exists}{name}",
5665                    if_exists = if *if_exists { "IF EXISTS " } else { "" },
5666                )?;
5667                if let Some(s) = storage_specifier {
5668                    write!(f, " FROM {s}")?;
5669                }
5670                Ok(())
5671            }
5672            Statement::DropPolicy(policy) => write!(f, "{policy}"),
5673            Statement::DropConnector { if_exists, name } => {
5674                write!(
5675                    f,
5676                    "DROP CONNECTOR {if_exists}{name}",
5677                    if_exists = if *if_exists { "IF EXISTS " } else { "" }
5678                )?;
5679                Ok(())
5680            }
5681            Statement::Discard { object_type } => {
5682                write!(f, "DISCARD {object_type}")?;
5683                Ok(())
5684            }
5685            Self::Set(set) => write!(f, "{set}"),
5686            Statement::ShowVariable { variable } => {
5687                write!(f, "SHOW")?;
5688                if !variable.is_empty() {
5689                    write!(f, " {}", display_separated(variable, " "))?;
5690                }
5691                Ok(())
5692            }
5693            Statement::ShowStatus {
5694                filter,
5695                global,
5696                session,
5697            } => {
5698                write!(f, "SHOW")?;
5699                if *global {
5700                    write!(f, " GLOBAL")?;
5701                }
5702                if *session {
5703                    write!(f, " SESSION")?;
5704                }
5705                write!(f, " STATUS")?;
5706                if filter.is_some() {
5707                    write!(f, " {}", filter.as_ref().unwrap())?;
5708                }
5709                Ok(())
5710            }
5711            Statement::ShowVariables {
5712                filter,
5713                global,
5714                session,
5715            } => {
5716                write!(f, "SHOW")?;
5717                if *global {
5718                    write!(f, " GLOBAL")?;
5719                }
5720                if *session {
5721                    write!(f, " SESSION")?;
5722                }
5723                write!(f, " VARIABLES")?;
5724                if filter.is_some() {
5725                    write!(f, " {}", filter.as_ref().unwrap())?;
5726                }
5727                Ok(())
5728            }
5729            Statement::ShowCreate { obj_type, obj_name } => {
5730                write!(f, "SHOW CREATE {obj_type} {obj_name}",)?;
5731                Ok(())
5732            }
5733            Statement::ShowColumns {
5734                extended,
5735                full,
5736                show_options,
5737            } => {
5738                write!(
5739                    f,
5740                    "SHOW {extended}{full}COLUMNS{show_options}",
5741                    extended = if *extended { "EXTENDED " } else { "" },
5742                    full = if *full { "FULL " } else { "" },
5743                )?;
5744                Ok(())
5745            }
5746            Statement::ShowDatabases {
5747                terse,
5748                history,
5749                show_options,
5750            } => {
5751                write!(
5752                    f,
5753                    "SHOW {terse}DATABASES{history}{show_options}",
5754                    terse = if *terse { "TERSE " } else { "" },
5755                    history = if *history { " HISTORY" } else { "" },
5756                )?;
5757                Ok(())
5758            }
5759            Statement::ShowCatalogs {
5760                terse,
5761                history,
5762                show_options,
5763            } => {
5764                write!(
5765                    f,
5766                    "SHOW {terse}CATALOGS{history}{show_options}",
5767                    terse = if *terse { "TERSE " } else { "" },
5768                    history = if *history { " HISTORY" } else { "" },
5769                )?;
5770                Ok(())
5771            }
5772            Statement::ShowProcessList { full } => {
5773                write!(
5774                    f,
5775                    "SHOW {full}PROCESSLIST",
5776                    full = if *full { "FULL " } else { "" },
5777                )?;
5778                Ok(())
5779            }
5780            Statement::ShowSchemas {
5781                terse,
5782                history,
5783                show_options,
5784            } => {
5785                write!(
5786                    f,
5787                    "SHOW {terse}SCHEMAS{history}{show_options}",
5788                    terse = if *terse { "TERSE " } else { "" },
5789                    history = if *history { " HISTORY" } else { "" },
5790                )?;
5791                Ok(())
5792            }
5793            Statement::ShowObjects(ShowObjects {
5794                terse,
5795                show_options,
5796            }) => {
5797                write!(
5798                    f,
5799                    "SHOW {terse}OBJECTS{show_options}",
5800                    terse = if *terse { "TERSE " } else { "" },
5801                )?;
5802                Ok(())
5803            }
5804            Statement::ShowTables {
5805                terse,
5806                history,
5807                extended,
5808                full,
5809                external,
5810                show_options,
5811            } => {
5812                write!(
5813                    f,
5814                    "SHOW {terse}{extended}{full}{external}TABLES{history}{show_options}",
5815                    terse = if *terse { "TERSE " } else { "" },
5816                    extended = if *extended { "EXTENDED " } else { "" },
5817                    full = if *full { "FULL " } else { "" },
5818                    external = if *external { "EXTERNAL " } else { "" },
5819                    history = if *history { " HISTORY" } else { "" },
5820                )?;
5821                Ok(())
5822            }
5823            Statement::ShowViews {
5824                terse,
5825                materialized,
5826                show_options,
5827            } => {
5828                write!(
5829                    f,
5830                    "SHOW {terse}{materialized}VIEWS{show_options}",
5831                    terse = if *terse { "TERSE " } else { "" },
5832                    materialized = if *materialized { "MATERIALIZED " } else { "" }
5833                )?;
5834                Ok(())
5835            }
5836            Statement::ShowFunctions { filter } => {
5837                write!(f, "SHOW FUNCTIONS")?;
5838                if let Some(filter) = filter {
5839                    write!(f, " {filter}")?;
5840                }
5841                Ok(())
5842            }
5843            Statement::Use(use_expr) => use_expr.fmt(f),
5844            Statement::ShowCollation { filter } => {
5845                write!(f, "SHOW COLLATION")?;
5846                if let Some(filter) = filter {
5847                    write!(f, " {filter}")?;
5848                }
5849                Ok(())
5850            }
5851            Statement::ShowCharset(show_stm) => show_stm.fmt(f),
5852            Statement::StartTransaction {
5853                modes,
5854                begin: syntax_begin,
5855                transaction,
5856                modifier,
5857                statements,
5858                exception,
5859                has_end_keyword,
5860            } => {
5861                if *syntax_begin {
5862                    if let Some(modifier) = *modifier {
5863                        write!(f, "BEGIN {modifier}")?;
5864                    } else {
5865                        write!(f, "BEGIN")?;
5866                    }
5867                } else {
5868                    write!(f, "START")?;
5869                }
5870                if let Some(transaction) = transaction {
5871                    write!(f, " {transaction}")?;
5872                }
5873                if !modes.is_empty() {
5874                    write!(f, " {}", display_comma_separated(modes))?;
5875                }
5876                if !statements.is_empty() {
5877                    write!(f, " ")?;
5878                    format_statement_list(f, statements)?;
5879                }
5880                if let Some(exception_when) = exception {
5881                    write!(f, " EXCEPTION")?;
5882                    for when in exception_when {
5883                        write!(f, " {when}")?;
5884                    }
5885                }
5886                if *has_end_keyword {
5887                    write!(f, " END")?;
5888                }
5889                Ok(())
5890            }
5891            Statement::Commit {
5892                chain,
5893                end: end_syntax,
5894                modifier,
5895            } => {
5896                if *end_syntax {
5897                    write!(f, "END")?;
5898                    if let Some(modifier) = *modifier {
5899                        write!(f, " {modifier}")?;
5900                    }
5901                    if *chain {
5902                        write!(f, " AND CHAIN")?;
5903                    }
5904                } else {
5905                    write!(f, "COMMIT{}", if *chain { " AND CHAIN" } else { "" })?;
5906                }
5907                Ok(())
5908            }
5909            Statement::Rollback { chain, savepoint } => {
5910                write!(f, "ROLLBACK")?;
5911
5912                if *chain {
5913                    write!(f, " AND CHAIN")?;
5914                }
5915
5916                if let Some(savepoint) = savepoint {
5917                    write!(f, " TO SAVEPOINT {savepoint}")?;
5918                }
5919
5920                Ok(())
5921            }
5922            Statement::CreateSchema {
5923                schema_name,
5924                if_not_exists,
5925                with,
5926                options,
5927                default_collate_spec,
5928                clone,
5929            } => {
5930                write!(
5931                    f,
5932                    "CREATE SCHEMA {if_not_exists}{name}",
5933                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
5934                    name = schema_name
5935                )?;
5936
5937                if let Some(collate) = default_collate_spec {
5938                    write!(f, " DEFAULT COLLATE {collate}")?;
5939                }
5940
5941                if let Some(with) = with {
5942                    write!(f, " WITH ({})", display_comma_separated(with))?;
5943                }
5944
5945                if let Some(options) = options {
5946                    write!(f, " OPTIONS({})", display_comma_separated(options))?;
5947                }
5948
5949                if let Some(clone) = clone {
5950                    write!(f, " CLONE {clone}")?;
5951                }
5952                Ok(())
5953            }
5954            Statement::Assert { condition, message } => {
5955                write!(f, "ASSERT {condition}")?;
5956                if let Some(m) = message {
5957                    write!(f, " AS {m}")?;
5958                }
5959                Ok(())
5960            }
5961            Statement::Grant(grant) => write!(f, "{grant}"),
5962            Statement::Deny(s) => write!(f, "{s}"),
5963            Statement::Revoke(revoke) => write!(f, "{revoke}"),
5964            Statement::Deallocate { name, prepare } => write!(
5965                f,
5966                "DEALLOCATE {prepare}{name}",
5967                prepare = if *prepare { "PREPARE " } else { "" },
5968                name = name,
5969            ),
5970            Statement::Execute {
5971                name,
5972                parameters,
5973                has_parentheses,
5974                immediate,
5975                into,
5976                using,
5977                output,
5978                default,
5979            } => {
5980                let (open, close) = if *has_parentheses {
5981                    // Space before `(` only when there is no name directly preceding it.
5982                    (if name.is_some() { "(" } else { " (" }, ")")
5983                } else {
5984                    (if parameters.is_empty() { "" } else { " " }, "")
5985                };
5986                write!(f, "EXECUTE")?;
5987                if *immediate {
5988                    write!(f, " IMMEDIATE")?;
5989                }
5990                if let Some(name) = name {
5991                    write!(f, " {name}")?;
5992                }
5993                write!(f, "{open}{}{close}", display_comma_separated(parameters),)?;
5994                if !into.is_empty() {
5995                    write!(f, " INTO {}", display_comma_separated(into))?;
5996                }
5997                if !using.is_empty() {
5998                    write!(f, " USING {}", display_comma_separated(using))?;
5999                };
6000                if *output {
6001                    write!(f, " OUTPUT")?;
6002                }
6003                if *default {
6004                    write!(f, " DEFAULT")?;
6005                }
6006                Ok(())
6007            }
6008            Statement::Prepare {
6009                name,
6010                data_types,
6011                statement,
6012            } => {
6013                write!(f, "PREPARE {name} ")?;
6014                if !data_types.is_empty() {
6015                    write!(f, "({}) ", display_comma_separated(data_types))?;
6016                }
6017                write!(f, "AS {statement}")
6018            }
6019            Statement::Comment {
6020                object_type,
6021                object_name,
6022                comment,
6023                if_exists,
6024            } => {
6025                write!(f, "COMMENT ")?;
6026                if *if_exists {
6027                    write!(f, "IF EXISTS ")?
6028                };
6029                write!(f, "ON {object_type} {object_name} IS ")?;
6030                if let Some(c) = comment {
6031                    write!(f, "'{c}'")
6032                } else {
6033                    write!(f, "NULL")
6034                }
6035            }
6036            Statement::Savepoint { name } => {
6037                write!(f, "SAVEPOINT ")?;
6038                write!(f, "{name}")
6039            }
6040            Statement::ReleaseSavepoint { name } => {
6041                write!(f, "RELEASE SAVEPOINT {name}")
6042            }
6043            Statement::Merge(merge) => merge.fmt(f),
6044            Statement::Cache {
6045                table_name,
6046                table_flag,
6047                has_as,
6048                options,
6049                query,
6050            } => {
6051                if let Some(table_flag) = table_flag {
6052                    write!(f, "CACHE {table_flag} TABLE {table_name}")?;
6053                } else {
6054                    write!(f, "CACHE TABLE {table_name}")?;
6055                }
6056
6057                if !options.is_empty() {
6058                    write!(f, " OPTIONS({})", display_comma_separated(options))?;
6059                }
6060
6061                match (*has_as, query) {
6062                    (true, Some(query)) => write!(f, " AS {query}"),
6063                    (true, None) => f.write_str(" AS"),
6064                    (false, Some(query)) => write!(f, " {query}"),
6065                    (false, None) => Ok(()),
6066                }
6067            }
6068            Statement::UNCache {
6069                table_name,
6070                if_exists,
6071            } => {
6072                if *if_exists {
6073                    write!(f, "UNCACHE TABLE IF EXISTS {table_name}")
6074                } else {
6075                    write!(f, "UNCACHE TABLE {table_name}")
6076                }
6077            }
6078            Statement::CreateSequence {
6079                temporary,
6080                if_not_exists,
6081                name,
6082                data_type,
6083                sequence_options,
6084                owned_by,
6085            } => {
6086                let as_type: String = if let Some(dt) = data_type.as_ref() {
6087                    //Cannot use format!(" AS {}", dt), due to format! is not available in --target thumbv6m-none-eabi
6088                    // " AS ".to_owned() + &dt.to_string()
6089                    [" AS ", &dt.to_string()].concat()
6090                } else {
6091                    "".to_string()
6092                };
6093                write!(
6094                    f,
6095                    "CREATE {temporary}SEQUENCE {if_not_exists}{name}{as_type}",
6096                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
6097                    temporary = if *temporary { "TEMPORARY " } else { "" },
6098                    name = name,
6099                    as_type = as_type
6100                )?;
6101                for sequence_option in sequence_options {
6102                    write!(f, "{sequence_option}")?;
6103                }
6104                if let Some(ob) = owned_by.as_ref() {
6105                    write!(f, " OWNED BY {ob}")?;
6106                }
6107                write!(f, "")
6108            }
6109            Statement::CreateStage {
6110                or_replace,
6111                temporary,
6112                if_not_exists,
6113                name,
6114                stage_params,
6115                directory_table_params,
6116                file_format,
6117                copy_options,
6118                comment,
6119                ..
6120            } => {
6121                write!(
6122                    f,
6123                    "CREATE {or_replace}{temp}STAGE {if_not_exists}{name}{stage_params}",
6124                    temp = if *temporary { "TEMPORARY " } else { "" },
6125                    or_replace = if *or_replace { "OR REPLACE " } else { "" },
6126                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
6127                )?;
6128                if !directory_table_params.options.is_empty() {
6129                    write!(f, " DIRECTORY=({directory_table_params})")?;
6130                }
6131                if !file_format.options.is_empty() {
6132                    write!(f, " FILE_FORMAT=({file_format})")?;
6133                }
6134                if !copy_options.options.is_empty() {
6135                    write!(f, " COPY_OPTIONS=({copy_options})")?;
6136                }
6137                if comment.is_some() {
6138                    write!(f, " COMMENT='{}'", comment.as_ref().unwrap())?;
6139                }
6140                Ok(())
6141            }
6142            Statement::CopyIntoSnowflake {
6143                kind,
6144                into,
6145                into_columns,
6146                from_obj,
6147                from_obj_alias,
6148                stage_params,
6149                from_transformations,
6150                from_query,
6151                files,
6152                pattern,
6153                file_format,
6154                copy_options,
6155                validation_mode,
6156                partition,
6157            } => {
6158                write!(f, "COPY INTO {into}")?;
6159                if let Some(into_columns) = into_columns {
6160                    write!(f, " ({})", display_comma_separated(into_columns))?;
6161                }
6162                if let Some(from_transformations) = from_transformations {
6163                    // Data load with transformation
6164                    if let Some(from_stage) = from_obj {
6165                        write!(
6166                            f,
6167                            " FROM (SELECT {} FROM {}{}",
6168                            display_separated(from_transformations, ", "),
6169                            from_stage,
6170                            stage_params
6171                        )?;
6172                    }
6173                    if let Some(from_obj_alias) = from_obj_alias {
6174                        write!(f, " AS {from_obj_alias}")?;
6175                    }
6176                    write!(f, ")")?;
6177                } else if let Some(from_obj) = from_obj {
6178                    // Standard data load
6179                    write!(f, " FROM {from_obj}{stage_params}")?;
6180                    if let Some(from_obj_alias) = from_obj_alias {
6181                        write!(f, " AS {from_obj_alias}")?;
6182                    }
6183                } else if let Some(from_query) = from_query {
6184                    // Data unload from query
6185                    write!(f, " FROM ({from_query})")?;
6186                }
6187
6188                if let Some(files) = files {
6189                    write!(f, " FILES = ('{}')", display_separated(files, "', '"))?;
6190                }
6191                if let Some(pattern) = pattern {
6192                    write!(f, " PATTERN = '{pattern}'")?;
6193                }
6194                if let Some(partition) = partition {
6195                    write!(f, " PARTITION BY {partition}")?;
6196                }
6197                if !file_format.options.is_empty() {
6198                    write!(f, " FILE_FORMAT=({file_format})")?;
6199                }
6200                if !copy_options.options.is_empty() {
6201                    match kind {
6202                        CopyIntoSnowflakeKind::Table => {
6203                            write!(f, " COPY_OPTIONS=({copy_options})")?
6204                        }
6205                        CopyIntoSnowflakeKind::Location => write!(f, " {copy_options}")?,
6206                    }
6207                }
6208                if let Some(validation_mode) = validation_mode {
6209                    write!(f, " VALIDATION_MODE = {validation_mode}")?;
6210                }
6211                Ok(())
6212            }
6213            Statement::CreateType {
6214                name,
6215                representation,
6216            } => {
6217                write!(f, "CREATE TYPE {name}")?;
6218                if let Some(repr) = representation {
6219                    write!(f, " {repr}")?;
6220                }
6221                Ok(())
6222            }
6223            Statement::Pragma { name, value, is_eq } => {
6224                write!(f, "PRAGMA {name}")?;
6225                if value.is_some() {
6226                    let val = value.as_ref().unwrap();
6227                    if *is_eq {
6228                        write!(f, " = {val}")?;
6229                    } else {
6230                        write!(f, "({val})")?;
6231                    }
6232                }
6233                Ok(())
6234            }
6235            Statement::Lock(lock) => lock.fmt(f),
6236            Statement::LockTables { tables } => {
6237                write!(f, "LOCK TABLES {}", display_comma_separated(tables))
6238            }
6239            Statement::UnlockTables => {
6240                write!(f, "UNLOCK TABLES")
6241            }
6242            Statement::Unload {
6243                query,
6244                query_text,
6245                to,
6246                auth,
6247                with,
6248                options,
6249            } => {
6250                write!(f, "UNLOAD(")?;
6251                if let Some(query) = query {
6252                    write!(f, "{query}")?;
6253                }
6254                if let Some(query_text) = query_text {
6255                    write!(f, "'{query_text}'")?;
6256                }
6257                write!(f, ") TO {to}")?;
6258                if let Some(auth) = auth {
6259                    write!(f, " IAM_ROLE {auth}")?;
6260                }
6261                if !with.is_empty() {
6262                    write!(f, " WITH ({})", display_comma_separated(with))?;
6263                }
6264                if !options.is_empty() {
6265                    write!(f, " {}", display_separated(options, " "))?;
6266                }
6267                Ok(())
6268            }
6269            Statement::OptimizeTable {
6270                name,
6271                has_table_keyword,
6272                on_cluster,
6273                partition,
6274                include_final,
6275                deduplicate,
6276                predicate,
6277                zorder,
6278            } => {
6279                write!(f, "OPTIMIZE")?;
6280                if *has_table_keyword {
6281                    write!(f, " TABLE")?;
6282                }
6283                write!(f, " {name}")?;
6284                if let Some(on_cluster) = on_cluster {
6285                    write!(f, " ON CLUSTER {on_cluster}")?;
6286                }
6287                if let Some(partition) = partition {
6288                    write!(f, " {partition}")?;
6289                }
6290                if *include_final {
6291                    write!(f, " FINAL")?;
6292                }
6293                if let Some(deduplicate) = deduplicate {
6294                    write!(f, " {deduplicate}")?;
6295                }
6296                if let Some(predicate) = predicate {
6297                    write!(f, " WHERE {predicate}")?;
6298                }
6299                if let Some(zorder) = zorder {
6300                    write!(f, " ZORDER BY ({})", display_comma_separated(zorder))?;
6301                }
6302                Ok(())
6303            }
6304            Statement::LISTEN { channel } => {
6305                write!(f, "LISTEN {channel}")?;
6306                Ok(())
6307            }
6308            Statement::UNLISTEN { channel } => {
6309                write!(f, "UNLISTEN {channel}")?;
6310                Ok(())
6311            }
6312            Statement::NOTIFY { channel, payload } => {
6313                write!(f, "NOTIFY {channel}")?;
6314                if let Some(payload) = payload {
6315                    write!(f, ", '{payload}'")?;
6316                }
6317                Ok(())
6318            }
6319            Statement::RenameTable(rename_tables) => {
6320                write!(f, "RENAME TABLE {}", display_comma_separated(rename_tables))
6321            }
6322            Statement::RaisError {
6323                message,
6324                severity,
6325                state,
6326                arguments,
6327                options,
6328            } => {
6329                write!(f, "RAISERROR({message}, {severity}, {state}")?;
6330                if !arguments.is_empty() {
6331                    write!(f, ", {}", display_comma_separated(arguments))?;
6332                }
6333                write!(f, ")")?;
6334                if !options.is_empty() {
6335                    write!(f, " WITH {}", display_comma_separated(options))?;
6336                }
6337                Ok(())
6338            }
6339            Statement::Throw(s) => write!(f, "{s}"),
6340            Statement::Print(s) => write!(f, "{s}"),
6341            Statement::WaitFor(s) => write!(f, "{s}"),
6342            Statement::Return(r) => write!(f, "{r}"),
6343            Statement::List(command) => write!(f, "LIST {command}"),
6344            Statement::Remove(command) => write!(f, "REMOVE {command}"),
6345            Statement::ExportData(e) => write!(f, "{e}"),
6346            Statement::CreateUser(s) => write!(f, "{s}"),
6347            Statement::AlterSchema(s) => write!(f, "{s}"),
6348            Statement::Vacuum(s) => write!(f, "{s}"),
6349            Statement::AlterUser(s) => write!(f, "{s}"),
6350            Statement::Reset(s) => write!(f, "{s}"),
6351        }
6352    }
6353}
6354
6355/// Can use to describe options in create sequence or table column type identity
6356/// ```sql
6357/// [ INCREMENT [ BY ] increment ]
6358///     [ MINVALUE minvalue | NO MINVALUE ] [ MAXVALUE maxvalue | NO MAXVALUE ]
6359///     [ START [ WITH ] start ] [ CACHE cache ] [ [ NO ] CYCLE ]
6360/// ```
6361#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6362#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6363#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6364pub enum SequenceOptions {
6365    /// `INCREMENT [BY] <expr>` option; second value indicates presence of `BY` keyword.
6366    IncrementBy(Expr, bool),
6367    /// `MINVALUE <expr>` or `NO MINVALUE`.
6368    MinValue(Option<Expr>),
6369    /// `MAXVALUE <expr>` or `NO MAXVALUE`.
6370    MaxValue(Option<Expr>),
6371    /// `START [WITH] <expr>`; second value indicates presence of `WITH`.
6372    StartWith(Expr, bool),
6373    /// `CACHE <expr>` option.
6374    Cache(Expr),
6375    /// `CYCLE` or `NO CYCLE` option.
6376    Cycle(bool),
6377}
6378
6379impl fmt::Display for SequenceOptions {
6380    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6381        match self {
6382            SequenceOptions::IncrementBy(increment, by) => {
6383                write!(
6384                    f,
6385                    " INCREMENT{by} {increment}",
6386                    by = if *by { " BY" } else { "" },
6387                    increment = increment
6388                )
6389            }
6390            SequenceOptions::MinValue(Some(expr)) => {
6391                write!(f, " MINVALUE {expr}")
6392            }
6393            SequenceOptions::MinValue(None) => {
6394                write!(f, " NO MINVALUE")
6395            }
6396            SequenceOptions::MaxValue(Some(expr)) => {
6397                write!(f, " MAXVALUE {expr}")
6398            }
6399            SequenceOptions::MaxValue(None) => {
6400                write!(f, " NO MAXVALUE")
6401            }
6402            SequenceOptions::StartWith(start, with) => {
6403                write!(
6404                    f,
6405                    " START{with} {start}",
6406                    with = if *with { " WITH" } else { "" },
6407                    start = start
6408                )
6409            }
6410            SequenceOptions::Cache(cache) => {
6411                write!(f, " CACHE {}", *cache)
6412            }
6413            SequenceOptions::Cycle(no) => {
6414                write!(f, " {}CYCLE", if *no { "NO " } else { "" })
6415            }
6416        }
6417    }
6418}
6419
6420/// Assignment for a `SET` statement (name [=|TO] value)
6421#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6422#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6423#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6424pub struct SetAssignment {
6425    /// Optional context scope (e.g., SESSION or LOCAL).
6426    pub scope: Option<ContextModifier>,
6427    /// Assignment target name.
6428    pub name: ObjectName,
6429    /// Assigned expression value.
6430    pub value: Expr,
6431}
6432
6433impl fmt::Display for SetAssignment {
6434    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6435        write!(
6436            f,
6437            "{}{} = {}",
6438            self.scope.map(|s| format!("{s}")).unwrap_or_default(),
6439            self.name,
6440            self.value
6441        )
6442    }
6443}
6444
6445/// Target of a `TRUNCATE TABLE` command
6446///
6447/// Note this is its own struct because `visit_relation` requires an `ObjectName` (not a `Vec<ObjectName>`)
6448#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6449#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6450#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6451pub struct TruncateTableTarget {
6452    /// name of the table being truncated
6453    #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
6454    pub name: ObjectName,
6455    /// Postgres-specific option: explicitly exclude descendants (also default without ONLY)
6456    /// ```sql
6457    /// TRUNCATE TABLE ONLY name
6458    /// ```
6459    /// <https://www.postgresql.org/docs/current/sql-truncate.html>
6460    pub only: bool,
6461    /// Postgres-specific option: asterisk after table name to explicitly indicate descendants
6462    /// ```sql
6463    /// TRUNCATE TABLE name [ * ]
6464    /// ```
6465    /// <https://www.postgresql.org/docs/current/sql-truncate.html>
6466    pub has_asterisk: bool,
6467}
6468
6469impl fmt::Display for TruncateTableTarget {
6470    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6471        if self.only {
6472            write!(f, "ONLY ")?;
6473        };
6474        write!(f, "{}", self.name)?;
6475        if self.has_asterisk {
6476            write!(f, " *")?;
6477        };
6478        Ok(())
6479    }
6480}
6481
6482/// A `LOCK` statement.
6483///
6484/// See <https://www.postgresql.org/docs/current/sql-lock.html>
6485#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6486#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6487#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6488pub struct Lock {
6489    /// List of tables to lock.
6490    pub tables: Vec<LockTableTarget>,
6491    /// Lock mode.
6492    pub lock_mode: Option<LockTableMode>,
6493    /// Whether `NOWAIT` was specified.
6494    pub nowait: bool,
6495}
6496
6497impl fmt::Display for Lock {
6498    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6499        write!(f, "LOCK TABLE {}", display_comma_separated(&self.tables))?;
6500        if let Some(lock_mode) = &self.lock_mode {
6501            write!(f, " IN {lock_mode} MODE")?;
6502        }
6503        if self.nowait {
6504            write!(f, " NOWAIT")?;
6505        }
6506        Ok(())
6507    }
6508}
6509
6510/// Target of a `LOCK TABLE` command
6511///
6512/// See <https://www.postgresql.org/docs/current/sql-lock.html>
6513#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6514#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6515#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6516pub struct LockTableTarget {
6517    /// Name of the table being locked.
6518    #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
6519    pub name: ObjectName,
6520    /// Whether `ONLY` was specified to exclude descendant tables.
6521    pub only: bool,
6522    /// Whether `*` was specified to explicitly include descendant tables.
6523    pub has_asterisk: bool,
6524}
6525
6526impl fmt::Display for LockTableTarget {
6527    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6528        if self.only {
6529            write!(f, "ONLY ")?;
6530        }
6531        write!(f, "{}", self.name)?;
6532        if self.has_asterisk {
6533            write!(f, " *")?;
6534        }
6535        Ok(())
6536    }
6537}
6538
6539/// PostgreSQL lock modes for `LOCK TABLE`.
6540///
6541/// See <https://www.postgresql.org/docs/current/sql-lock.html>
6542#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6543#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6544#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6545pub enum LockTableMode {
6546    /// `ACCESS SHARE`
6547    AccessShare,
6548    /// `ROW SHARE`
6549    RowShare,
6550    /// `ROW EXCLUSIVE`
6551    RowExclusive,
6552    /// `SHARE UPDATE EXCLUSIVE`
6553    ShareUpdateExclusive,
6554    /// `SHARE`
6555    Share,
6556    /// `SHARE ROW EXCLUSIVE`
6557    ShareRowExclusive,
6558    /// `EXCLUSIVE`
6559    Exclusive,
6560    /// `ACCESS EXCLUSIVE`
6561    AccessExclusive,
6562}
6563
6564impl fmt::Display for LockTableMode {
6565    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
6566        let text = match self {
6567            Self::AccessShare => "ACCESS SHARE",
6568            Self::RowShare => "ROW SHARE",
6569            Self::RowExclusive => "ROW EXCLUSIVE",
6570            Self::ShareUpdateExclusive => "SHARE UPDATE EXCLUSIVE",
6571            Self::Share => "SHARE",
6572            Self::ShareRowExclusive => "SHARE ROW EXCLUSIVE",
6573            Self::Exclusive => "EXCLUSIVE",
6574            Self::AccessExclusive => "ACCESS EXCLUSIVE",
6575        };
6576        write!(f, "{text}")
6577    }
6578}
6579
6580/// PostgreSQL identity option for TRUNCATE table
6581/// [ RESTART IDENTITY | CONTINUE IDENTITY ]
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 TruncateIdentityOption {
6586    /// Restart identity values (RESTART IDENTITY).
6587    Restart,
6588    /// Continue identity values (CONTINUE IDENTITY).
6589    Continue,
6590}
6591
6592/// Cascade/restrict option for Postgres TRUNCATE table, MySQL GRANT/REVOKE, etc.
6593/// [ CASCADE | RESTRICT ]
6594#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6595#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6596#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6597pub enum CascadeOption {
6598    /// Apply cascading action (e.g., CASCADE).
6599    Cascade,
6600    /// Restrict the action (e.g., RESTRICT).
6601    Restrict,
6602}
6603
6604impl Display for CascadeOption {
6605    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6606        match self {
6607            CascadeOption::Cascade => write!(f, "CASCADE"),
6608            CascadeOption::Restrict => write!(f, "RESTRICT"),
6609        }
6610    }
6611}
6612
6613/// Transaction started with [ TRANSACTION | WORK | TRAN ]
6614#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6615#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6616#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6617pub enum BeginTransactionKind {
6618    /// Standard `TRANSACTION` keyword.
6619    Transaction,
6620    /// Alternate `WORK` keyword.
6621    Work,
6622    /// MSSQL shorthand `TRAN` keyword.
6623    /// See <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/begin-transaction-transact-sql>
6624    Tran,
6625}
6626
6627impl Display for BeginTransactionKind {
6628    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6629        match self {
6630            BeginTransactionKind::Transaction => write!(f, "TRANSACTION"),
6631            BeginTransactionKind::Work => write!(f, "WORK"),
6632            BeginTransactionKind::Tran => write!(f, "TRAN"),
6633        }
6634    }
6635}
6636
6637/// Can use to describe options in  create sequence or table column type identity
6638/// [ MINVALUE minvalue | NO MINVALUE ] [ MAXVALUE maxvalue | NO MAXVALUE ]
6639#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6640#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6641#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6642pub enum MinMaxValue {
6643    /// Clause is not specified.
6644    Empty,
6645    /// NO MINVALUE / NO MAXVALUE.
6646    None,
6647    /// `MINVALUE <expr>` / `MAXVALUE <expr>`.
6648    Some(Expr),
6649}
6650
6651#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6652#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6653#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6654#[non_exhaustive]
6655/// Behavior to apply for `INSERT` when a conflict occurs.
6656pub enum OnInsert {
6657    /// ON DUPLICATE KEY UPDATE (MySQL when the key already exists, then execute an update instead)
6658    DuplicateKeyUpdate(Vec<Assignment>),
6659    /// ON CONFLICT is a PostgreSQL and Sqlite extension
6660    OnConflict(OnConflict),
6661}
6662
6663#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6664#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6665#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6666/// Optional aliases for `INSERT` targets: row alias and optional column aliases.
6667pub struct InsertAliases {
6668    /// Row alias (table-style alias) for the inserted values.
6669    pub row_alias: ObjectName,
6670    /// Optional list of column aliases for the inserted values.
6671    pub col_aliases: Option<Vec<Ident>>,
6672}
6673
6674#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6675#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6676#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6677/// Optional alias for an `INSERT` table; i.e. the table to be inserted into
6678pub struct TableAliasWithoutColumns {
6679    /// `true` if the aliases was explicitly introduced with the "AS" keyword
6680    pub explicit: bool,
6681    /// the alias name itself
6682    pub alias: Ident,
6683}
6684
6685#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6686#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6687#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6688/// `ON CONFLICT` clause representation.
6689pub struct OnConflict {
6690    /// Optional conflict target specifying columns or constraint.
6691    pub conflict_target: Option<ConflictTarget>,
6692    /// Action to take when a conflict occurs.
6693    pub action: OnConflictAction,
6694}
6695#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6696#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6697#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6698/// Target specification for an `ON CONFLICT` clause.
6699pub enum ConflictTarget {
6700    /// Target specified as a list of columns.
6701    Columns(Vec<Ident>),
6702    /// Target specified as a named constraint.
6703    OnConstraint(ObjectName),
6704}
6705#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6706#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6707#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6708/// Action to perform when an `ON CONFLICT` target is matched.
6709pub enum OnConflictAction {
6710    /// Do nothing on conflict.
6711    DoNothing,
6712    /// Perform an update on conflict.
6713    DoUpdate(DoUpdate),
6714}
6715
6716#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6717#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6718#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6719/// Details for `DO UPDATE` action of an `ON CONFLICT` clause.
6720pub struct DoUpdate {
6721    /// Column assignments to perform on update.
6722    pub assignments: Vec<Assignment>,
6723    /// Optional WHERE clause limiting the update.
6724    pub selection: Option<Expr>,
6725}
6726
6727impl fmt::Display for OnInsert {
6728    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6729        match self {
6730            Self::DuplicateKeyUpdate(expr) => write!(
6731                f,
6732                " ON DUPLICATE KEY UPDATE {}",
6733                display_comma_separated(expr)
6734            ),
6735            Self::OnConflict(o) => write!(f, "{o}"),
6736        }
6737    }
6738}
6739impl fmt::Display for OnConflict {
6740    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6741        write!(f, " ON CONFLICT")?;
6742        if let Some(target) = &self.conflict_target {
6743            write!(f, "{target}")?;
6744        }
6745        write!(f, " {}", self.action)
6746    }
6747}
6748impl fmt::Display for ConflictTarget {
6749    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6750        match self {
6751            ConflictTarget::Columns(cols) => write!(f, "({})", display_comma_separated(cols)),
6752            ConflictTarget::OnConstraint(name) => write!(f, " ON CONSTRAINT {name}"),
6753        }
6754    }
6755}
6756impl fmt::Display for OnConflictAction {
6757    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6758        match self {
6759            Self::DoNothing => write!(f, "DO NOTHING"),
6760            Self::DoUpdate(do_update) => {
6761                write!(f, "DO UPDATE")?;
6762                if !do_update.assignments.is_empty() {
6763                    write!(
6764                        f,
6765                        " SET {}",
6766                        display_comma_separated(&do_update.assignments)
6767                    )?;
6768                }
6769                if let Some(selection) = &do_update.selection {
6770                    write!(f, " WHERE {selection}")?;
6771                }
6772                Ok(())
6773            }
6774        }
6775    }
6776}
6777
6778/// Privileges granted in a GRANT statement or revoked in a REVOKE statement.
6779#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6780#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6781#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6782pub enum Privileges {
6783    /// All privileges applicable to the object type
6784    All {
6785        /// Optional keyword from the spec, ignored in practice
6786        with_privileges_keyword: bool,
6787    },
6788    /// Specific privileges (e.g. `SELECT`, `INSERT`)
6789    Actions(Vec<Action>),
6790}
6791
6792impl fmt::Display for Privileges {
6793    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6794        match self {
6795            Privileges::All {
6796                with_privileges_keyword,
6797            } => {
6798                write!(
6799                    f,
6800                    "ALL{}",
6801                    if *with_privileges_keyword {
6802                        " PRIVILEGES"
6803                    } else {
6804                        ""
6805                    }
6806                )
6807            }
6808            Privileges::Actions(actions) => {
6809                write!(f, "{}", display_comma_separated(actions))
6810            }
6811        }
6812    }
6813}
6814
6815/// Specific direction for FETCH statement
6816#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6817#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6818#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6819pub enum FetchDirection {
6820    /// Fetch a specific count of rows.
6821    Count {
6822        /// The limit value for the count.
6823        limit: ValueWithSpan,
6824    },
6825    /// Fetch the next row.
6826    Next,
6827    /// Fetch the prior row.
6828    Prior,
6829    /// Fetch the first row.
6830    First,
6831    /// Fetch the last row.
6832    Last,
6833    /// Fetch an absolute row by index.
6834    Absolute {
6835        /// The absolute index value.
6836        limit: ValueWithSpan,
6837    },
6838    /// Fetch a row relative to the current position.
6839    Relative {
6840        /// The relative offset value.
6841        limit: ValueWithSpan,
6842    },
6843    /// Fetch all rows.
6844    All,
6845    // FORWARD
6846    // FORWARD count
6847    /// Fetch forward by an optional limit.
6848    Forward {
6849        /// Optional forward limit.
6850        limit: Option<ValueWithSpan>,
6851    },
6852    /// Fetch all forward rows.
6853    ForwardAll,
6854    // BACKWARD
6855    // BACKWARD count
6856    /// Fetch backward by an optional limit.
6857    Backward {
6858        /// Optional backward limit.
6859        limit: Option<ValueWithSpan>,
6860    },
6861    /// Fetch all backward rows.
6862    BackwardAll,
6863}
6864
6865impl fmt::Display for FetchDirection {
6866    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6867        match self {
6868            FetchDirection::Count { limit } => f.write_str(&limit.to_string())?,
6869            FetchDirection::Next => f.write_str("NEXT")?,
6870            FetchDirection::Prior => f.write_str("PRIOR")?,
6871            FetchDirection::First => f.write_str("FIRST")?,
6872            FetchDirection::Last => f.write_str("LAST")?,
6873            FetchDirection::Absolute { limit } => {
6874                f.write_str("ABSOLUTE ")?;
6875                f.write_str(&limit.to_string())?;
6876            }
6877            FetchDirection::Relative { limit } => {
6878                f.write_str("RELATIVE ")?;
6879                f.write_str(&limit.to_string())?;
6880            }
6881            FetchDirection::All => f.write_str("ALL")?,
6882            FetchDirection::Forward { limit } => {
6883                f.write_str("FORWARD")?;
6884
6885                if let Some(l) = limit {
6886                    f.write_str(" ")?;
6887                    f.write_str(&l.to_string())?;
6888                }
6889            }
6890            FetchDirection::ForwardAll => f.write_str("FORWARD ALL")?,
6891            FetchDirection::Backward { limit } => {
6892                f.write_str("BACKWARD")?;
6893
6894                if let Some(l) = limit {
6895                    f.write_str(" ")?;
6896                    f.write_str(&l.to_string())?;
6897                }
6898            }
6899            FetchDirection::BackwardAll => f.write_str("BACKWARD ALL")?,
6900        };
6901
6902        Ok(())
6903    }
6904}
6905
6906/// The "position" for a FETCH statement.
6907///
6908/// [MsSql](https://learn.microsoft.com/en-us/sql/t-sql/language-elements/fetch-transact-sql)
6909#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6910#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6911#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6912pub enum FetchPosition {
6913    /// Use `FROM <pos>` position specifier.
6914    From,
6915    /// Use `IN <pos>` position specifier.
6916    In,
6917}
6918
6919impl fmt::Display for FetchPosition {
6920    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6921        match self {
6922            FetchPosition::From => f.write_str("FROM")?,
6923            FetchPosition::In => f.write_str("IN")?,
6924        };
6925
6926        Ok(())
6927    }
6928}
6929
6930/// A privilege on a database object (table, sequence, etc.).
6931#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6932#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6933#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6934pub enum Action {
6935    /// Add a search optimization.
6936    AddSearchOptimization,
6937    /// Apply an `APPLY` operation with a specific type.
6938    Apply {
6939        /// The type of apply operation.
6940        apply_type: ActionApplyType,
6941    },
6942    /// Apply a budget operation.
6943    ApplyBudget,
6944    /// Attach a listing.
6945    AttachListing,
6946    /// Attach a policy.
6947    AttachPolicy,
6948    /// Audit operation.
6949    Audit,
6950    /// Bind a service endpoint.
6951    BindServiceEndpoint,
6952    /// Connect permission.
6953    Connect,
6954    /// Create action, optionally specifying an object type.
6955    Create {
6956        /// Optional object type to create.
6957        obj_type: Option<ActionCreateObjectType>,
6958    },
6959    /// Actions related to database roles.
6960    DatabaseRole {
6961        /// The role name.
6962        role: ObjectName,
6963    },
6964    /// Delete permission.
6965    Delete,
6966    /// Drop permission.
6967    Drop,
6968    /// Evolve schema permission.
6969    EvolveSchema,
6970    /// Exec action (execute) with optional object type.
6971    Exec {
6972        /// Optional execute object type.
6973        obj_type: Option<ActionExecuteObjectType>,
6974    },
6975    /// Execute action with optional object type.
6976    Execute {
6977        /// Optional execute object type.
6978        obj_type: Option<ActionExecuteObjectType>,
6979    },
6980    /// Failover operation.
6981    Failover,
6982    /// Use imported privileges.
6983    ImportedPrivileges,
6984    /// Import a share.
6985    ImportShare,
6986    /// Insert rows with optional column list.
6987    Insert {
6988        /// Optional list of target columns for insert.
6989        columns: Option<Vec<Ident>>,
6990    },
6991    /// Manage operation with a specific manage type.
6992    Manage {
6993        /// The specific manage sub-type.
6994        manage_type: ActionManageType,
6995    },
6996    /// Manage releases.
6997    ManageReleases,
6998    /// Manage versions.
6999    ManageVersions,
7000    /// Modify operation with an optional modify type.
7001    Modify {
7002        /// The optional modify sub-type.
7003        modify_type: Option<ActionModifyType>,
7004    },
7005    /// Monitor operation with an optional monitor type.
7006    Monitor {
7007        /// The optional monitor sub-type.
7008        monitor_type: Option<ActionMonitorType>,
7009    },
7010    /// Operate permission.
7011    Operate,
7012    /// Override share restrictions.
7013    OverrideShareRestrictions,
7014    /// Ownership permission.
7015    Ownership,
7016    /// Purchase a data exchange listing.
7017    PurchaseDataExchangeListing,
7018
7019    /// Read access.
7020    Read,
7021    /// Read session-level access.
7022    ReadSession,
7023    /// References with optional column list.
7024    References {
7025        /// Optional list of referenced column identifiers.
7026        columns: Option<Vec<Ident>>,
7027    },
7028    /// Replication permission.
7029    Replicate,
7030    /// Resolve all references.
7031    ResolveAll,
7032    /// Role-related permission with target role name.
7033    Role {
7034        /// The target role name.
7035        role: ObjectName,
7036    },
7037    /// Select permission with optional column list.
7038    Select {
7039        /// Optional list of selected columns.
7040        columns: Option<Vec<Ident>>,
7041    },
7042    /// Temporary object permission.
7043    Temporary,
7044    /// Trigger-related permission.
7045    Trigger,
7046    /// Truncate permission.
7047    Truncate,
7048    /// Update permission with optional affected columns.
7049    Update {
7050        /// Optional list of columns affected by update.
7051        columns: Option<Vec<Ident>>,
7052    },
7053    /// Usage permission.
7054    Usage,
7055}
7056
7057impl fmt::Display for Action {
7058    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7059        match self {
7060            Action::AddSearchOptimization => f.write_str("ADD SEARCH OPTIMIZATION")?,
7061            Action::Apply { apply_type } => write!(f, "APPLY {apply_type}")?,
7062            Action::ApplyBudget => f.write_str("APPLYBUDGET")?,
7063            Action::AttachListing => f.write_str("ATTACH LISTING")?,
7064            Action::AttachPolicy => f.write_str("ATTACH POLICY")?,
7065            Action::Audit => f.write_str("AUDIT")?,
7066            Action::BindServiceEndpoint => f.write_str("BIND SERVICE ENDPOINT")?,
7067            Action::Connect => f.write_str("CONNECT")?,
7068            Action::Create { obj_type } => {
7069                f.write_str("CREATE")?;
7070                if let Some(obj_type) = obj_type {
7071                    write!(f, " {obj_type}")?
7072                }
7073            }
7074            Action::DatabaseRole { role } => write!(f, "DATABASE ROLE {role}")?,
7075            Action::Delete => f.write_str("DELETE")?,
7076            Action::Drop => f.write_str("DROP")?,
7077            Action::EvolveSchema => f.write_str("EVOLVE SCHEMA")?,
7078            Action::Exec { obj_type } => {
7079                f.write_str("EXEC")?;
7080                if let Some(obj_type) = obj_type {
7081                    write!(f, " {obj_type}")?
7082                }
7083            }
7084            Action::Execute { obj_type } => {
7085                f.write_str("EXECUTE")?;
7086                if let Some(obj_type) = obj_type {
7087                    write!(f, " {obj_type}")?
7088                }
7089            }
7090            Action::Failover => f.write_str("FAILOVER")?,
7091            Action::ImportedPrivileges => f.write_str("IMPORTED PRIVILEGES")?,
7092            Action::ImportShare => f.write_str("IMPORT SHARE")?,
7093            Action::Insert { .. } => f.write_str("INSERT")?,
7094            Action::Manage { manage_type } => write!(f, "MANAGE {manage_type}")?,
7095            Action::ManageReleases => f.write_str("MANAGE RELEASES")?,
7096            Action::ManageVersions => f.write_str("MANAGE VERSIONS")?,
7097            Action::Modify { modify_type } => {
7098                write!(f, "MODIFY")?;
7099                if let Some(modify_type) = modify_type {
7100                    write!(f, " {modify_type}")?;
7101                }
7102            }
7103            Action::Monitor { monitor_type } => {
7104                write!(f, "MONITOR")?;
7105                if let Some(monitor_type) = monitor_type {
7106                    write!(f, " {monitor_type}")?
7107                }
7108            }
7109            Action::Operate => f.write_str("OPERATE")?,
7110            Action::OverrideShareRestrictions => f.write_str("OVERRIDE SHARE RESTRICTIONS")?,
7111            Action::Ownership => f.write_str("OWNERSHIP")?,
7112            Action::PurchaseDataExchangeListing => f.write_str("PURCHASE DATA EXCHANGE LISTING")?,
7113            Action::Read => f.write_str("READ")?,
7114            Action::ReadSession => f.write_str("READ SESSION")?,
7115            Action::References { .. } => f.write_str("REFERENCES")?,
7116            Action::Replicate => f.write_str("REPLICATE")?,
7117            Action::ResolveAll => f.write_str("RESOLVE ALL")?,
7118            Action::Role { role } => write!(f, "ROLE {role}")?,
7119            Action::Select { .. } => f.write_str("SELECT")?,
7120            Action::Temporary => f.write_str("TEMPORARY")?,
7121            Action::Trigger => f.write_str("TRIGGER")?,
7122            Action::Truncate => f.write_str("TRUNCATE")?,
7123            Action::Update { .. } => f.write_str("UPDATE")?,
7124            Action::Usage => f.write_str("USAGE")?,
7125        };
7126        match self {
7127            Action::Insert { columns }
7128            | Action::References { columns }
7129            | Action::Select { columns }
7130            | Action::Update { columns } => {
7131                if let Some(columns) = columns {
7132                    write!(f, " ({})", display_comma_separated(columns))?;
7133                }
7134            }
7135            _ => (),
7136        };
7137        Ok(())
7138    }
7139}
7140
7141#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7142#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7143#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7144/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
7145/// under `globalPrivileges` in the `CREATE` privilege.
7146pub enum ActionCreateObjectType {
7147    /// An account-level object.
7148    Account,
7149    /// An application object.
7150    Application,
7151    /// An application package object.
7152    ApplicationPackage,
7153    /// A compute pool object.
7154    ComputePool,
7155    /// A data exchange listing.
7156    DataExchangeListing,
7157    /// A database object.
7158    Database,
7159    /// An external volume object.
7160    ExternalVolume,
7161    /// A failover group object.
7162    FailoverGroup,
7163    /// An integration object.
7164    Integration,
7165    /// A network policy object.
7166    NetworkPolicy,
7167    /// An organization listing.
7168    OrganiationListing,
7169    /// A replication group object.
7170    ReplicationGroup,
7171    /// A role object.
7172    Role,
7173    /// A schema object.
7174    Schema,
7175    /// A share object.
7176    Share,
7177    /// A user object.
7178    User,
7179    /// A warehouse object.
7180    Warehouse,
7181}
7182
7183impl fmt::Display for ActionCreateObjectType {
7184    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7185        match self {
7186            ActionCreateObjectType::Account => write!(f, "ACCOUNT"),
7187            ActionCreateObjectType::Application => write!(f, "APPLICATION"),
7188            ActionCreateObjectType::ApplicationPackage => write!(f, "APPLICATION PACKAGE"),
7189            ActionCreateObjectType::ComputePool => write!(f, "COMPUTE POOL"),
7190            ActionCreateObjectType::DataExchangeListing => write!(f, "DATA EXCHANGE LISTING"),
7191            ActionCreateObjectType::Database => write!(f, "DATABASE"),
7192            ActionCreateObjectType::ExternalVolume => write!(f, "EXTERNAL VOLUME"),
7193            ActionCreateObjectType::FailoverGroup => write!(f, "FAILOVER GROUP"),
7194            ActionCreateObjectType::Integration => write!(f, "INTEGRATION"),
7195            ActionCreateObjectType::NetworkPolicy => write!(f, "NETWORK POLICY"),
7196            ActionCreateObjectType::OrganiationListing => write!(f, "ORGANIZATION LISTING"),
7197            ActionCreateObjectType::ReplicationGroup => write!(f, "REPLICATION GROUP"),
7198            ActionCreateObjectType::Role => write!(f, "ROLE"),
7199            ActionCreateObjectType::Schema => write!(f, "SCHEMA"),
7200            ActionCreateObjectType::Share => write!(f, "SHARE"),
7201            ActionCreateObjectType::User => write!(f, "USER"),
7202            ActionCreateObjectType::Warehouse => write!(f, "WAREHOUSE"),
7203        }
7204    }
7205}
7206
7207#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7208#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7209#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7210/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
7211/// under `globalPrivileges` in the `APPLY` privilege.
7212pub enum ActionApplyType {
7213    /// Apply an aggregation policy.
7214    AggregationPolicy,
7215    /// Apply an authentication policy.
7216    AuthenticationPolicy,
7217    /// Apply a join policy.
7218    JoinPolicy,
7219    /// Apply a masking policy.
7220    MaskingPolicy,
7221    /// Apply a packages policy.
7222    PackagesPolicy,
7223    /// Apply a password policy.
7224    PasswordPolicy,
7225    /// Apply a projection policy.
7226    ProjectionPolicy,
7227    /// Apply a row access policy.
7228    RowAccessPolicy,
7229    /// Apply a session policy.
7230    SessionPolicy,
7231    /// Apply a tag.
7232    Tag,
7233}
7234
7235impl fmt::Display for ActionApplyType {
7236    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7237        match self {
7238            ActionApplyType::AggregationPolicy => write!(f, "AGGREGATION POLICY"),
7239            ActionApplyType::AuthenticationPolicy => write!(f, "AUTHENTICATION POLICY"),
7240            ActionApplyType::JoinPolicy => write!(f, "JOIN POLICY"),
7241            ActionApplyType::MaskingPolicy => write!(f, "MASKING POLICY"),
7242            ActionApplyType::PackagesPolicy => write!(f, "PACKAGES POLICY"),
7243            ActionApplyType::PasswordPolicy => write!(f, "PASSWORD POLICY"),
7244            ActionApplyType::ProjectionPolicy => write!(f, "PROJECTION POLICY"),
7245            ActionApplyType::RowAccessPolicy => write!(f, "ROW ACCESS POLICY"),
7246            ActionApplyType::SessionPolicy => write!(f, "SESSION POLICY"),
7247            ActionApplyType::Tag => write!(f, "TAG"),
7248        }
7249    }
7250}
7251
7252#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7253#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7254#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7255/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
7256/// under `globalPrivileges` in the `EXECUTE` privilege.
7257pub enum ActionExecuteObjectType {
7258    /// Alert object.
7259    Alert,
7260    /// Data metric function object.
7261    DataMetricFunction,
7262    /// Managed alert object.
7263    ManagedAlert,
7264    /// Managed task object.
7265    ManagedTask,
7266    /// Task object.
7267    Task,
7268}
7269
7270impl fmt::Display for ActionExecuteObjectType {
7271    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7272        match self {
7273            ActionExecuteObjectType::Alert => write!(f, "ALERT"),
7274            ActionExecuteObjectType::DataMetricFunction => write!(f, "DATA METRIC FUNCTION"),
7275            ActionExecuteObjectType::ManagedAlert => write!(f, "MANAGED ALERT"),
7276            ActionExecuteObjectType::ManagedTask => write!(f, "MANAGED TASK"),
7277            ActionExecuteObjectType::Task => write!(f, "TASK"),
7278        }
7279    }
7280}
7281
7282#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7283#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7284#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7285/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
7286/// under `globalPrivileges` in the `MANAGE` privilege.
7287pub enum ActionManageType {
7288    /// Account support cases management.
7289    AccountSupportCases,
7290    /// Event sharing management.
7291    EventSharing,
7292    /// Grants management.
7293    Grants,
7294    /// Listing auto-fulfillment management.
7295    ListingAutoFulfillment,
7296    /// Organization support cases management.
7297    OrganizationSupportCases,
7298    /// User support cases management.
7299    UserSupportCases,
7300    /// Warehouses management.
7301    Warehouses,
7302}
7303
7304impl fmt::Display for ActionManageType {
7305    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7306        match self {
7307            ActionManageType::AccountSupportCases => write!(f, "ACCOUNT SUPPORT CASES"),
7308            ActionManageType::EventSharing => write!(f, "EVENT SHARING"),
7309            ActionManageType::Grants => write!(f, "GRANTS"),
7310            ActionManageType::ListingAutoFulfillment => write!(f, "LISTING AUTO FULFILLMENT"),
7311            ActionManageType::OrganizationSupportCases => write!(f, "ORGANIZATION SUPPORT CASES"),
7312            ActionManageType::UserSupportCases => write!(f, "USER SUPPORT CASES"),
7313            ActionManageType::Warehouses => write!(f, "WAREHOUSES"),
7314        }
7315    }
7316}
7317
7318#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7319#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7320#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7321/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
7322/// under `globalPrivileges` in the `MODIFY` privilege.
7323pub enum ActionModifyType {
7324    /// Modify log level.
7325    LogLevel,
7326    /// Modify trace level.
7327    TraceLevel,
7328    /// Modify session log level.
7329    SessionLogLevel,
7330    /// Modify session trace level.
7331    SessionTraceLevel,
7332}
7333
7334impl fmt::Display for ActionModifyType {
7335    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7336        match self {
7337            ActionModifyType::LogLevel => write!(f, "LOG LEVEL"),
7338            ActionModifyType::TraceLevel => write!(f, "TRACE LEVEL"),
7339            ActionModifyType::SessionLogLevel => write!(f, "SESSION LOG LEVEL"),
7340            ActionModifyType::SessionTraceLevel => write!(f, "SESSION TRACE LEVEL"),
7341        }
7342    }
7343}
7344
7345#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7346#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7347#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7348/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
7349/// under `globalPrivileges` in the `MONITOR` privilege.
7350pub enum ActionMonitorType {
7351    /// Monitor execution.
7352    Execution,
7353    /// Monitor security.
7354    Security,
7355    /// Monitor usage.
7356    Usage,
7357}
7358
7359impl fmt::Display for ActionMonitorType {
7360    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7361        match self {
7362            ActionMonitorType::Execution => write!(f, "EXECUTION"),
7363            ActionMonitorType::Security => write!(f, "SECURITY"),
7364            ActionMonitorType::Usage => write!(f, "USAGE"),
7365        }
7366    }
7367}
7368
7369/// The principal that receives the privileges
7370#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7371#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7372#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7373pub struct Grantee {
7374    /// The category/type of grantee (role, user, share, etc.).
7375    pub grantee_type: GranteesType,
7376    /// Optional name of the grantee (identifier or user@host).
7377    pub name: Option<GranteeName>,
7378}
7379
7380impl fmt::Display for Grantee {
7381    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7382        match self.grantee_type {
7383            GranteesType::Role => {
7384                write!(f, "ROLE ")?;
7385            }
7386            GranteesType::Share => {
7387                write!(f, "SHARE ")?;
7388            }
7389            GranteesType::User => {
7390                write!(f, "USER ")?;
7391            }
7392            GranteesType::Group => {
7393                write!(f, "GROUP ")?;
7394            }
7395            GranteesType::Public => {
7396                write!(f, "PUBLIC ")?;
7397            }
7398            GranteesType::DatabaseRole => {
7399                write!(f, "DATABASE ROLE ")?;
7400            }
7401            GranteesType::Application => {
7402                write!(f, "APPLICATION ")?;
7403            }
7404            GranteesType::ApplicationRole => {
7405                write!(f, "APPLICATION ROLE ")?;
7406            }
7407            GranteesType::None => (),
7408        }
7409        if let Some(ref name) = self.name {
7410            name.fmt(f)?;
7411        }
7412        Ok(())
7413    }
7414}
7415
7416#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7417#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7418#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7419/// The kind of principal receiving privileges.
7420pub enum GranteesType {
7421    /// A role principal.
7422    Role,
7423    /// A share principal.
7424    Share,
7425    /// A user principal.
7426    User,
7427    /// A group principal.
7428    Group,
7429    /// The public principal.
7430    Public,
7431    /// A database role principal.
7432    DatabaseRole,
7433    /// An application principal.
7434    Application,
7435    /// An application role principal.
7436    ApplicationRole,
7437    /// No specific principal (e.g. `NONE`).
7438    None,
7439}
7440
7441/// Users/roles designated in a GRANT/REVOKE
7442#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7443#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7444#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7445pub enum GranteeName {
7446    /// A bare identifier
7447    ObjectName(ObjectName),
7448    /// A MySQL user/host pair such as 'root'@'%'
7449    UserHost {
7450        /// The user identifier portion.
7451        user: Ident,
7452        /// The host identifier portion.
7453        host: Ident,
7454    },
7455}
7456
7457impl fmt::Display for GranteeName {
7458    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7459        match self {
7460            GranteeName::ObjectName(name) => name.fmt(f),
7461            GranteeName::UserHost { user, host } => {
7462                write!(f, "{user}@{host}")
7463            }
7464        }
7465    }
7466}
7467
7468/// Objects on which privileges are granted in a GRANT statement.
7469#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7470#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7471#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7472pub enum GrantObjects {
7473    /// Grant privileges on `ALL SEQUENCES IN SCHEMA <schema_name> [, ...]`
7474    AllSequencesInSchema {
7475        /// The target schema names.
7476        schemas: Vec<ObjectName>,
7477    },
7478    /// Grant privileges on `ALL TABLES IN SCHEMA <schema_name> [, ...]`
7479    AllTablesInSchema {
7480        /// The target schema names.
7481        schemas: Vec<ObjectName>,
7482    },
7483    /// Grant privileges on `ALL VIEWS IN SCHEMA <schema_name> [, ...]`
7484    AllViewsInSchema {
7485        /// The target schema names.
7486        schemas: Vec<ObjectName>,
7487    },
7488    /// Grant privileges on `ALL MATERIALIZED VIEWS IN SCHEMA <schema_name> [, ...]`
7489    AllMaterializedViewsInSchema {
7490        /// The target schema names.
7491        schemas: Vec<ObjectName>,
7492    },
7493    /// Grant privileges on `ALL EXTERNAL TABLES IN SCHEMA <schema_name> [, ...]`
7494    AllExternalTablesInSchema {
7495        /// The target schema names.
7496        schemas: Vec<ObjectName>,
7497    },
7498    /// Grant privileges on `ALL FUNCTIONS IN SCHEMA <schema_name> [, ...]`
7499    AllFunctionsInSchema {
7500        /// The target schema names.
7501        schemas: Vec<ObjectName>,
7502    },
7503    /// Grant privileges on `FUTURE SCHEMAS IN DATABASE <database_name> [, ...]`
7504    FutureSchemasInDatabase {
7505        /// The target database names.
7506        databases: Vec<ObjectName>,
7507    },
7508    /// Grant privileges on `FUTURE TABLES IN SCHEMA <schema_name> [, ...]`
7509    FutureTablesInSchema {
7510        /// The target schema names.
7511        schemas: Vec<ObjectName>,
7512    },
7513    /// Grant privileges on `FUTURE VIEWS IN SCHEMA <schema_name> [, ...]`
7514    FutureViewsInSchema {
7515        /// The target schema names.
7516        schemas: Vec<ObjectName>,
7517    },
7518    /// Grant privileges on `FUTURE EXTERNAL TABLES IN SCHEMA <schema_name> [, ...]`
7519    FutureExternalTablesInSchema {
7520        /// The target schema names.
7521        schemas: Vec<ObjectName>,
7522    },
7523    /// Grant privileges on `FUTURE MATERIALIZED VIEWS IN SCHEMA <schema_name> [, ...]`
7524    FutureMaterializedViewsInSchema {
7525        /// The target schema names.
7526        schemas: Vec<ObjectName>,
7527    },
7528    /// Grant privileges on `FUTURE SEQUENCES IN SCHEMA <schema_name> [, ...]`
7529    FutureSequencesInSchema {
7530        /// The target schema names.
7531        schemas: Vec<ObjectName>,
7532    },
7533    /// Grant privileges on specific databases
7534    Databases(Vec<ObjectName>),
7535    /// Grant privileges on specific schemas
7536    Schemas(Vec<ObjectName>),
7537    /// Grant privileges on specific sequences
7538    Sequences(Vec<ObjectName>),
7539    /// Grant privileges on specific tables
7540    Tables(Vec<ObjectName>),
7541    /// Grant privileges on specific views
7542    Views(Vec<ObjectName>),
7543    /// Grant privileges on specific warehouses
7544    Warehouses(Vec<ObjectName>),
7545    /// Grant privileges on specific integrations
7546    Integrations(Vec<ObjectName>),
7547    /// Grant privileges on resource monitors
7548    ResourceMonitors(Vec<ObjectName>),
7549    /// Grant privileges on users
7550    Users(Vec<ObjectName>),
7551    /// Grant privileges on compute pools
7552    ComputePools(Vec<ObjectName>),
7553    /// Grant privileges on connections
7554    Connections(Vec<ObjectName>),
7555    /// Grant privileges on failover groups
7556    FailoverGroup(Vec<ObjectName>),
7557    /// Grant privileges on replication group
7558    ReplicationGroup(Vec<ObjectName>),
7559    /// Grant privileges on external volumes
7560    ExternalVolumes(Vec<ObjectName>),
7561    /// Grant privileges on a procedure. In dialects that
7562    /// support overloading, the argument types must be specified.
7563    ///
7564    /// For example:
7565    /// `GRANT USAGE ON PROCEDURE foo(varchar) TO ROLE role1`
7566    Procedure {
7567        /// The procedure name.
7568        name: ObjectName,
7569        /// Optional argument types for overloaded procedures.
7570        arg_types: Vec<DataType>,
7571    },
7572
7573    /// Grant privileges on a function. In dialects that
7574    /// support overloading, the argument types must be specified.
7575    ///
7576    /// For example:
7577    /// `GRANT USAGE ON FUNCTION foo(varchar) TO ROLE role1`
7578    Function {
7579        /// The function name.
7580        name: ObjectName,
7581        /// Optional argument types for overloaded functions.
7582        arg_types: Vec<DataType>,
7583    },
7584}
7585
7586impl fmt::Display for GrantObjects {
7587    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7588        match self {
7589            GrantObjects::Sequences(sequences) => {
7590                write!(f, "SEQUENCE {}", display_comma_separated(sequences))
7591            }
7592            GrantObjects::Databases(databases) => {
7593                write!(f, "DATABASE {}", display_comma_separated(databases))
7594            }
7595            GrantObjects::Schemas(schemas) => {
7596                write!(f, "SCHEMA {}", display_comma_separated(schemas))
7597            }
7598            GrantObjects::Tables(tables) => {
7599                write!(f, "{}", display_comma_separated(tables))
7600            }
7601            GrantObjects::Views(views) => {
7602                write!(f, "VIEW {}", display_comma_separated(views))
7603            }
7604            GrantObjects::Warehouses(warehouses) => {
7605                write!(f, "WAREHOUSE {}", display_comma_separated(warehouses))
7606            }
7607            GrantObjects::Integrations(integrations) => {
7608                write!(f, "INTEGRATION {}", display_comma_separated(integrations))
7609            }
7610            GrantObjects::AllSequencesInSchema { schemas } => {
7611                write!(
7612                    f,
7613                    "ALL SEQUENCES IN SCHEMA {}",
7614                    display_comma_separated(schemas)
7615                )
7616            }
7617            GrantObjects::AllTablesInSchema { schemas } => {
7618                write!(
7619                    f,
7620                    "ALL TABLES IN SCHEMA {}",
7621                    display_comma_separated(schemas)
7622                )
7623            }
7624            GrantObjects::AllExternalTablesInSchema { schemas } => {
7625                write!(
7626                    f,
7627                    "ALL EXTERNAL TABLES IN SCHEMA {}",
7628                    display_comma_separated(schemas)
7629                )
7630            }
7631            GrantObjects::AllViewsInSchema { schemas } => {
7632                write!(
7633                    f,
7634                    "ALL VIEWS IN SCHEMA {}",
7635                    display_comma_separated(schemas)
7636                )
7637            }
7638            GrantObjects::AllMaterializedViewsInSchema { schemas } => {
7639                write!(
7640                    f,
7641                    "ALL MATERIALIZED VIEWS IN SCHEMA {}",
7642                    display_comma_separated(schemas)
7643                )
7644            }
7645            GrantObjects::AllFunctionsInSchema { schemas } => {
7646                write!(
7647                    f,
7648                    "ALL FUNCTIONS IN SCHEMA {}",
7649                    display_comma_separated(schemas)
7650                )
7651            }
7652            GrantObjects::FutureSchemasInDatabase { databases } => {
7653                write!(
7654                    f,
7655                    "FUTURE SCHEMAS IN DATABASE {}",
7656                    display_comma_separated(databases)
7657                )
7658            }
7659            GrantObjects::FutureTablesInSchema { schemas } => {
7660                write!(
7661                    f,
7662                    "FUTURE TABLES IN SCHEMA {}",
7663                    display_comma_separated(schemas)
7664                )
7665            }
7666            GrantObjects::FutureExternalTablesInSchema { schemas } => {
7667                write!(
7668                    f,
7669                    "FUTURE EXTERNAL TABLES IN SCHEMA {}",
7670                    display_comma_separated(schemas)
7671                )
7672            }
7673            GrantObjects::FutureViewsInSchema { schemas } => {
7674                write!(
7675                    f,
7676                    "FUTURE VIEWS IN SCHEMA {}",
7677                    display_comma_separated(schemas)
7678                )
7679            }
7680            GrantObjects::FutureMaterializedViewsInSchema { schemas } => {
7681                write!(
7682                    f,
7683                    "FUTURE MATERIALIZED VIEWS IN SCHEMA {}",
7684                    display_comma_separated(schemas)
7685                )
7686            }
7687            GrantObjects::FutureSequencesInSchema { schemas } => {
7688                write!(
7689                    f,
7690                    "FUTURE SEQUENCES IN SCHEMA {}",
7691                    display_comma_separated(schemas)
7692                )
7693            }
7694            GrantObjects::ResourceMonitors(objects) => {
7695                write!(f, "RESOURCE MONITOR {}", display_comma_separated(objects))
7696            }
7697            GrantObjects::Users(objects) => {
7698                write!(f, "USER {}", display_comma_separated(objects))
7699            }
7700            GrantObjects::ComputePools(objects) => {
7701                write!(f, "COMPUTE POOL {}", display_comma_separated(objects))
7702            }
7703            GrantObjects::Connections(objects) => {
7704                write!(f, "CONNECTION {}", display_comma_separated(objects))
7705            }
7706            GrantObjects::FailoverGroup(objects) => {
7707                write!(f, "FAILOVER GROUP {}", display_comma_separated(objects))
7708            }
7709            GrantObjects::ReplicationGroup(objects) => {
7710                write!(f, "REPLICATION GROUP {}", display_comma_separated(objects))
7711            }
7712            GrantObjects::ExternalVolumes(objects) => {
7713                write!(f, "EXTERNAL VOLUME {}", display_comma_separated(objects))
7714            }
7715            GrantObjects::Procedure { name, arg_types } => {
7716                write!(f, "PROCEDURE {name}")?;
7717                if !arg_types.is_empty() {
7718                    write!(f, "({})", display_comma_separated(arg_types))?;
7719                }
7720                Ok(())
7721            }
7722            GrantObjects::Function { name, arg_types } => {
7723                write!(f, "FUNCTION {name}")?;
7724                if !arg_types.is_empty() {
7725                    write!(f, "({})", display_comma_separated(arg_types))?;
7726                }
7727                Ok(())
7728            }
7729        }
7730    }
7731}
7732
7733/// A `DENY` statement
7734///
7735/// [MsSql](https://learn.microsoft.com/en-us/sql/t-sql/statements/deny-transact-sql)
7736#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7737#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7738#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7739pub struct DenyStatement {
7740    /// The privileges to deny.
7741    pub privileges: Privileges,
7742    /// The objects the privileges apply to.
7743    pub objects: GrantObjects,
7744    /// The grantees (users/roles) to whom the denial applies.
7745    pub grantees: Vec<Grantee>,
7746    /// Optional identifier of the principal that performed the grant.
7747    pub granted_by: Option<Ident>,
7748    /// Optional cascade option controlling dependent objects.
7749    pub cascade: Option<CascadeOption>,
7750}
7751
7752impl fmt::Display for DenyStatement {
7753    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7754        write!(f, "DENY {}", self.privileges)?;
7755        write!(f, " ON {}", self.objects)?;
7756        if !self.grantees.is_empty() {
7757            write!(f, " TO {}", display_comma_separated(&self.grantees))?;
7758        }
7759        if let Some(cascade) = &self.cascade {
7760            write!(f, " {cascade}")?;
7761        }
7762        if let Some(granted_by) = &self.granted_by {
7763            write!(f, " AS {granted_by}")?;
7764        }
7765        Ok(())
7766    }
7767}
7768
7769/// SQL assignment `foo = expr` as used in SQLUpdate
7770#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7771#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7772#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7773pub struct Assignment {
7774    /// The left-hand side of the assignment.
7775    pub target: AssignmentTarget,
7776    /// The expression assigned to the target.
7777    pub value: Expr,
7778}
7779
7780impl fmt::Display for Assignment {
7781    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7782        write!(f, "{} = {}", self.target, self.value)
7783    }
7784}
7785
7786/// Left-hand side of an assignment in an UPDATE statement,
7787/// e.g. `foo` in `foo = 5` (ColumnName assignment) or
7788/// `(a, b)` in `(a, b) = (1, 2)` (Tuple assignment).
7789#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7790#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7791#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7792pub enum AssignmentTarget {
7793    /// A single column
7794    ColumnName(ObjectName),
7795    /// A tuple of columns
7796    Tuple(Vec<ObjectName>),
7797}
7798
7799impl fmt::Display for AssignmentTarget {
7800    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7801        match self {
7802            AssignmentTarget::ColumnName(column) => write!(f, "{column}"),
7803            AssignmentTarget::Tuple(columns) => write!(f, "({})", display_comma_separated(columns)),
7804        }
7805    }
7806}
7807
7808#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7809#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7810#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7811/// Expression forms allowed as a function argument.
7812pub enum FunctionArgExpr {
7813    /// A normal expression argument.
7814    Expr(Expr),
7815    /// Qualified wildcard, e.g. `alias.*` or `schema.table.*`.
7816    QualifiedWildcard(ObjectName),
7817    /// An unqualified `*` wildcard.
7818    Wildcard,
7819    /// An unqualified `*` wildcard with additional options, e.g. `* EXCLUDE(col)`.
7820    ///
7821    /// Used in Snowflake to support expressions like `HASH(* EXCLUDE(col))`.
7822    WildcardWithOptions(WildcardAdditionalOptions),
7823}
7824
7825impl From<Expr> for FunctionArgExpr {
7826    fn from(wildcard_expr: Expr) -> Self {
7827        match wildcard_expr {
7828            Expr::QualifiedWildcard(prefix, _) => Self::QualifiedWildcard(prefix),
7829            Expr::Wildcard(_) => Self::Wildcard,
7830            expr => Self::Expr(expr),
7831        }
7832    }
7833}
7834
7835impl fmt::Display for FunctionArgExpr {
7836    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7837        match self {
7838            FunctionArgExpr::Expr(expr) => write!(f, "{expr}"),
7839            FunctionArgExpr::QualifiedWildcard(prefix) => write!(f, "{prefix}.*"),
7840            FunctionArgExpr::Wildcard => f.write_str("*"),
7841            FunctionArgExpr::WildcardWithOptions(opts) => write!(f, "*{opts}"),
7842        }
7843    }
7844}
7845
7846#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7847#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7848#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7849/// Operator used to separate function arguments
7850pub enum FunctionArgOperator {
7851    /// function(arg1 = value1)
7852    Equals,
7853    /// function(arg1 => value1)
7854    RightArrow,
7855    /// function(arg1 := value1)
7856    Assignment,
7857    /// function(arg1 : value1)
7858    Colon,
7859    /// function(arg1 VALUE value1)
7860    Value,
7861}
7862
7863impl fmt::Display for FunctionArgOperator {
7864    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7865        match self {
7866            FunctionArgOperator::Equals => f.write_str("="),
7867            FunctionArgOperator::RightArrow => f.write_str("=>"),
7868            FunctionArgOperator::Assignment => f.write_str(":="),
7869            FunctionArgOperator::Colon => f.write_str(":"),
7870            FunctionArgOperator::Value => f.write_str("VALUE"),
7871        }
7872    }
7873}
7874
7875#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7876#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7877#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7878/// Forms of function arguments (named, expression-named, or positional).
7879pub enum FunctionArg {
7880    /// `name` is identifier
7881    ///
7882    /// Enabled when `Dialect::supports_named_fn_args_with_expr_name` returns 'false'
7883    Named {
7884        /// The identifier name of the argument.
7885        name: Ident,
7886        /// The argument expression or wildcard form.
7887        arg: FunctionArgExpr,
7888        /// The operator separating name and value.
7889        operator: FunctionArgOperator,
7890    },
7891    /// `name` is arbitrary expression
7892    ///
7893    /// Enabled when `Dialect::supports_named_fn_args_with_expr_name` returns 'true'
7894    ExprNamed {
7895        /// The expression used as the argument name.
7896        name: Expr,
7897        /// The argument expression or wildcard form.
7898        arg: FunctionArgExpr,
7899        /// The operator separating name and value.
7900        operator: FunctionArgOperator,
7901    },
7902    /// An unnamed argument (positional), given by expression or wildcard.
7903    Unnamed(FunctionArgExpr),
7904}
7905
7906impl fmt::Display for FunctionArg {
7907    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7908        match self {
7909            FunctionArg::Named {
7910                name,
7911                arg,
7912                operator,
7913            } => write!(f, "{name} {operator} {arg}"),
7914            FunctionArg::ExprNamed {
7915                name,
7916                arg,
7917                operator,
7918            } => write!(f, "{name} {operator} {arg}"),
7919            FunctionArg::Unnamed(unnamed_arg) => write!(f, "{unnamed_arg}"),
7920        }
7921    }
7922}
7923
7924#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7925#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7926#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7927/// Which cursor(s) to close.
7928pub enum CloseCursor {
7929    /// Close all cursors.
7930    All,
7931    /// Close a specific cursor by name.
7932    Specific {
7933        /// The name of the cursor to close.
7934        name: Ident,
7935    },
7936}
7937
7938impl fmt::Display for CloseCursor {
7939    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7940        match self {
7941            CloseCursor::All => write!(f, "ALL"),
7942            CloseCursor::Specific { name } => write!(f, "{name}"),
7943        }
7944    }
7945}
7946
7947/// A Drop Domain statement
7948#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7949#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7950#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7951pub struct DropDomain {
7952    /// Whether to drop the domain if it exists
7953    pub if_exists: bool,
7954    /// The name of the domain to drop
7955    pub name: ObjectName,
7956    /// The behavior to apply when dropping the domain
7957    pub drop_behavior: Option<DropBehavior>,
7958}
7959
7960/// A constant of form `<data_type> 'value'`.
7961/// This can represent ANSI SQL `DATE`, `TIME`, and `TIMESTAMP` literals (such as `DATE '2020-01-01'`),
7962/// as well as constants of other types (a non-standard PostgreSQL extension).
7963#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7964#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7965#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7966pub struct TypedString {
7967    /// The data type of the typed string (e.g. DATE, TIME, TIMESTAMP).
7968    pub data_type: DataType,
7969    /// The value of the constant.
7970    /// Hint: you can unwrap the string value using `value.into_string()`.
7971    pub value: ValueWithSpan,
7972    /// Flags whether this TypedString uses the [ODBC syntax].
7973    ///
7974    /// Example:
7975    /// ```sql
7976    /// -- An ODBC date literal:
7977    /// SELECT {d '2025-07-16'}
7978    /// -- This is equivalent to the standard ANSI SQL literal:
7979    /// SELECT DATE '2025-07-16'
7980    ///
7981    /// [ODBC syntax]: https://learn.microsoft.com/en-us/sql/odbc/reference/develop-app/date-time-and-timestamp-literals?view=sql-server-2017
7982    pub uses_odbc_syntax: bool,
7983}
7984
7985impl fmt::Display for TypedString {
7986    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7987        let data_type = &self.data_type;
7988        let value = &self.value;
7989        match self.uses_odbc_syntax {
7990            false => {
7991                write!(f, "{data_type}")?;
7992                write!(f, " {value}")
7993            }
7994            true => {
7995                let prefix = match data_type {
7996                    DataType::Date => "d",
7997                    DataType::Time(..) => "t",
7998                    DataType::Timestamp(..) => "ts",
7999                    _ => "?",
8000                };
8001                write!(f, "{{{prefix} {value}}}")
8002            }
8003        }
8004    }
8005}
8006
8007/// A function call
8008#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8009#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8010#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8011pub struct Function {
8012    /// The function name (may be qualified).
8013    pub name: ObjectName,
8014    /// Flags whether this function call uses the [ODBC syntax].
8015    ///
8016    /// Example:
8017    /// ```sql
8018    /// SELECT {fn CONCAT('foo', 'bar')}
8019    /// ```
8020    ///
8021    /// [ODBC syntax]: https://learn.microsoft.com/en-us/sql/odbc/reference/develop-app/scalar-function-calls?view=sql-server-2017
8022    pub uses_odbc_syntax: bool,
8023    /// The parameters to the function, including any options specified within the
8024    /// delimiting parentheses.
8025    ///
8026    /// Example:
8027    /// ```plaintext
8028    /// HISTOGRAM(0.5, 0.6)(x, y)
8029    /// ```
8030    ///
8031    /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/aggregate-functions/parametric-functions)
8032    pub parameters: FunctionArguments,
8033    /// The arguments to the function, including any options specified within the
8034    /// delimiting parentheses.
8035    pub args: FunctionArguments,
8036    /// e.g. `x > 5` in `COUNT(x) FILTER (WHERE x > 5)`
8037    pub filter: Option<Box<Expr>>,
8038    /// Indicates how `NULL`s should be handled in the calculation.
8039    ///
8040    /// Example:
8041    /// ```plaintext
8042    /// FIRST_VALUE( <expr> ) [ { IGNORE | RESPECT } NULLS ] OVER ...
8043    /// ```
8044    ///
8045    /// [Snowflake](https://docs.snowflake.com/en/sql-reference/functions/first_value)
8046    pub null_treatment: Option<NullTreatment>,
8047    /// The `OVER` clause, indicating a window function call.
8048    pub over: Option<WindowType>,
8049    /// A clause used with certain aggregate functions to control the ordering
8050    /// within grouped sets before the function is applied.
8051    ///
8052    /// Syntax:
8053    /// ```plaintext
8054    /// <aggregate_function>(expression) WITHIN GROUP (ORDER BY key [ASC | DESC], ...)
8055    /// ```
8056    pub within_group: Vec<OrderByExpr>,
8057}
8058
8059impl fmt::Display for Function {
8060    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8061        if self.uses_odbc_syntax {
8062            write!(f, "{{fn ")?;
8063        }
8064
8065        write!(f, "{}{}{}", self.name, self.parameters, self.args)?;
8066
8067        if !self.within_group.is_empty() {
8068            write!(
8069                f,
8070                " WITHIN GROUP (ORDER BY {})",
8071                display_comma_separated(&self.within_group)
8072            )?;
8073        }
8074
8075        if let Some(filter_cond) = &self.filter {
8076            write!(f, " FILTER (WHERE {filter_cond})")?;
8077        }
8078
8079        if let Some(null_treatment) = &self.null_treatment {
8080            write!(f, " {null_treatment}")?;
8081        }
8082
8083        if let Some(o) = &self.over {
8084            f.write_str(" OVER ")?;
8085            o.fmt(f)?;
8086        }
8087
8088        if self.uses_odbc_syntax {
8089            write!(f, "}}")?;
8090        }
8091
8092        Ok(())
8093    }
8094}
8095
8096/// The arguments passed to a function call.
8097#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8098#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8099#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8100pub enum FunctionArguments {
8101    /// Used for special functions like `CURRENT_TIMESTAMP` that are invoked
8102    /// without parentheses.
8103    None,
8104    /// On some dialects, a subquery can be passed without surrounding
8105    /// parentheses if it's the sole argument to the function.
8106    Subquery(Box<Query>),
8107    /// A normal function argument list, including any clauses within it such as
8108    /// `DISTINCT` or `ORDER BY`.
8109    List(FunctionArgumentList),
8110}
8111
8112impl fmt::Display for FunctionArguments {
8113    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8114        match self {
8115            FunctionArguments::None => Ok(()),
8116            FunctionArguments::Subquery(query) => write!(f, "({query})"),
8117            FunctionArguments::List(args) => write!(f, "({args})"),
8118        }
8119    }
8120}
8121
8122/// This represents everything inside the parentheses when calling a function.
8123#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8124#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8125#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8126pub struct FunctionArgumentList {
8127    /// `[ ALL | DISTINCT ]`
8128    pub duplicate_treatment: Option<DuplicateTreatment>,
8129    /// The function arguments.
8130    pub args: Vec<FunctionArg>,
8131    /// Additional clauses specified within the argument list.
8132    pub clauses: Vec<FunctionArgumentClause>,
8133}
8134
8135impl fmt::Display for FunctionArgumentList {
8136    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8137        if let Some(duplicate_treatment) = self.duplicate_treatment {
8138            write!(f, "{duplicate_treatment} ")?;
8139        }
8140        write!(f, "{}", display_comma_separated(&self.args))?;
8141        if !self.clauses.is_empty() {
8142            if !self.args.is_empty() {
8143                write!(f, " ")?;
8144            }
8145            write!(f, "{}", display_separated(&self.clauses, " "))?;
8146        }
8147        Ok(())
8148    }
8149}
8150
8151#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8152#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8153#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8154/// Clauses that can appear inside a function argument list.
8155pub enum FunctionArgumentClause {
8156    /// Indicates how `NULL`s should be handled in the calculation, e.g. in `FIRST_VALUE` on [BigQuery].
8157    ///
8158    /// Syntax:
8159    /// ```plaintext
8160    /// { IGNORE | RESPECT } NULLS ]
8161    /// ```
8162    ///
8163    /// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/navigation_functions#first_value
8164    IgnoreOrRespectNulls(NullTreatment),
8165    /// Specifies the the ordering for some ordered set aggregates, e.g. `ARRAY_AGG` on [BigQuery].
8166    ///
8167    /// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/aggregate_functions#array_agg
8168    OrderBy(Vec<OrderByExpr>),
8169    /// Specifies a limit for the `ARRAY_AGG` and `ARRAY_CONCAT_AGG` functions on BigQuery.
8170    Limit(Expr),
8171    /// Specifies the behavior on overflow of the `LISTAGG` function.
8172    ///
8173    /// See <https://trino.io/docs/current/functions/aggregate.html>.
8174    OnOverflow(ListAggOnOverflow),
8175    /// Specifies a minimum or maximum bound on the input to [`ANY_VALUE`] on BigQuery.
8176    ///
8177    /// Syntax:
8178    /// ```plaintext
8179    /// HAVING { MAX | MIN } expression
8180    /// ```
8181    ///
8182    /// [`ANY_VALUE`]: https://cloud.google.com/bigquery/docs/reference/standard-sql/aggregate_functions#any_value
8183    Having(HavingBound),
8184    /// The `SEPARATOR` clause to the [`GROUP_CONCAT`] function in MySQL.
8185    ///
8186    /// [`GROUP_CONCAT`]: https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html#function_group-concat
8187    Separator(ValueWithSpan),
8188    /// The `ON NULL` clause for some JSON functions.
8189    ///
8190    /// [MSSQL `JSON_ARRAY`](https://learn.microsoft.com/en-us/sql/t-sql/functions/json-array-transact-sql?view=sql-server-ver16)
8191    /// [MSSQL `JSON_OBJECT`](https://learn.microsoft.com/en-us/sql/t-sql/functions/json-object-transact-sql?view=sql-server-ver16>)
8192    /// [PostgreSQL JSON functions](https://www.postgresql.org/docs/current/functions-json.html#FUNCTIONS-JSON-PROCESSING)
8193    JsonNullClause(JsonNullClause),
8194    /// The `RETURNING` clause for some JSON functions in PostgreSQL
8195    ///
8196    /// [`JSON_OBJECT`](https://www.postgresql.org/docs/current/functions-json.html#:~:text=json_object)
8197    JsonReturningClause(JsonReturningClause),
8198}
8199
8200impl fmt::Display for FunctionArgumentClause {
8201    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8202        match self {
8203            FunctionArgumentClause::IgnoreOrRespectNulls(null_treatment) => {
8204                write!(f, "{null_treatment}")
8205            }
8206            FunctionArgumentClause::OrderBy(order_by) => {
8207                write!(f, "ORDER BY {}", display_comma_separated(order_by))
8208            }
8209            FunctionArgumentClause::Limit(limit) => write!(f, "LIMIT {limit}"),
8210            FunctionArgumentClause::OnOverflow(on_overflow) => write!(f, "{on_overflow}"),
8211            FunctionArgumentClause::Having(bound) => write!(f, "{bound}"),
8212            FunctionArgumentClause::Separator(sep) => write!(f, "SEPARATOR {sep}"),
8213            FunctionArgumentClause::JsonNullClause(null_clause) => write!(f, "{null_clause}"),
8214            FunctionArgumentClause::JsonReturningClause(returning_clause) => {
8215                write!(f, "{returning_clause}")
8216            }
8217        }
8218    }
8219}
8220
8221/// A method call
8222#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8223#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8224#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8225pub struct Method {
8226    /// The expression on which the method is invoked.
8227    pub expr: Box<Expr>,
8228    // always non-empty
8229    /// The sequence of chained method calls.
8230    pub method_chain: Vec<Function>,
8231}
8232
8233impl fmt::Display for Method {
8234    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8235        write!(
8236            f,
8237            "{}.{}",
8238            self.expr,
8239            display_separated(&self.method_chain, ".")
8240        )
8241    }
8242}
8243
8244#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8245#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8246#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8247/// How duplicate values are treated inside function argument lists.
8248pub enum DuplicateTreatment {
8249    /// Consider only unique values.
8250    Distinct,
8251    /// Retain all duplicate values (the default).
8252    All,
8253}
8254
8255impl fmt::Display for DuplicateTreatment {
8256    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8257        match self {
8258            DuplicateTreatment::Distinct => write!(f, "DISTINCT"),
8259            DuplicateTreatment::All => write!(f, "ALL"),
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/// How the `ANALYZE`/`EXPLAIN ANALYZE` format is specified.
8268pub enum AnalyzeFormatKind {
8269    /// Format provided as a keyword, e.g. `FORMAT JSON`.
8270    Keyword(AnalyzeFormat),
8271    /// Format provided as an assignment, e.g. `FORMAT=JSON`.
8272    Assignment(AnalyzeFormat),
8273}
8274
8275impl fmt::Display for AnalyzeFormatKind {
8276    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
8277        match self {
8278            AnalyzeFormatKind::Keyword(format) => write!(f, "FORMAT {format}"),
8279            AnalyzeFormatKind::Assignment(format) => write!(f, "FORMAT={format}"),
8280        }
8281    }
8282}
8283
8284#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8285#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8286#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8287/// Output formats supported for `ANALYZE`/`EXPLAIN ANALYZE`.
8288pub enum AnalyzeFormat {
8289    /// Plain text format.
8290    TEXT,
8291    /// Graphviz DOT format.
8292    GRAPHVIZ,
8293    /// JSON format.
8294    JSON,
8295    /// Traditional explain output.
8296    TRADITIONAL,
8297    /// Tree-style explain output.
8298    TREE,
8299}
8300
8301impl fmt::Display for AnalyzeFormat {
8302    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
8303        f.write_str(match self {
8304            AnalyzeFormat::TEXT => "TEXT",
8305            AnalyzeFormat::GRAPHVIZ => "GRAPHVIZ",
8306            AnalyzeFormat::JSON => "JSON",
8307            AnalyzeFormat::TRADITIONAL => "TRADITIONAL",
8308            AnalyzeFormat::TREE => "TREE",
8309        })
8310    }
8311}
8312
8313/// External table's available file format
8314#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8315#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8316#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8317pub enum FileFormat {
8318    /// Text file format.
8319    TEXTFILE,
8320    /// Sequence file format.
8321    SEQUENCEFILE,
8322    /// ORC file format.
8323    ORC,
8324    /// Parquet file format.
8325    PARQUET,
8326    /// Avro file format.
8327    AVRO,
8328    /// RCFile format.
8329    RCFILE,
8330    /// JSON file format.
8331    JSONFILE,
8332}
8333
8334impl fmt::Display for FileFormat {
8335    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8336        use self::FileFormat::*;
8337        f.write_str(match self {
8338            TEXTFILE => "TEXTFILE",
8339            SEQUENCEFILE => "SEQUENCEFILE",
8340            ORC => "ORC",
8341            PARQUET => "PARQUET",
8342            AVRO => "AVRO",
8343            RCFILE => "RCFILE",
8344            JSONFILE => "JSONFILE",
8345        })
8346    }
8347}
8348
8349/// The `ON OVERFLOW` clause of a LISTAGG invocation
8350#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8351#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8352#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8353pub enum ListAggOnOverflow {
8354    /// `ON OVERFLOW ERROR`
8355    Error,
8356
8357    /// `ON OVERFLOW TRUNCATE [ <filler> ] WITH[OUT] COUNT`
8358    Truncate {
8359        /// Optional filler expression used when truncating.
8360        filler: Option<Box<Expr>>,
8361        /// Whether to include a count when truncating.
8362        with_count: bool,
8363    },
8364}
8365
8366impl fmt::Display for ListAggOnOverflow {
8367    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8368        write!(f, "ON OVERFLOW")?;
8369        match self {
8370            ListAggOnOverflow::Error => write!(f, " ERROR"),
8371            ListAggOnOverflow::Truncate { filler, with_count } => {
8372                write!(f, " TRUNCATE")?;
8373                if let Some(filler) = filler {
8374                    write!(f, " {filler}")?;
8375                }
8376                if *with_count {
8377                    write!(f, " WITH")?;
8378                } else {
8379                    write!(f, " WITHOUT")?;
8380                }
8381                write!(f, " COUNT")
8382            }
8383        }
8384    }
8385}
8386
8387/// The `HAVING` clause in a call to `ANY_VALUE` on BigQuery.
8388#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8389#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8390#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8391pub struct HavingBound(pub HavingBoundKind, pub Expr);
8392
8393impl fmt::Display for HavingBound {
8394    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8395        write!(f, "HAVING {} {}", self.0, self.1)
8396    }
8397}
8398
8399#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8400#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8401#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8402/// Which bound is used in a HAVING clause for ANY_VALUE on BigQuery.
8403pub enum HavingBoundKind {
8404    /// The minimum bound.
8405    Min,
8406    /// The maximum bound.
8407    Max,
8408}
8409
8410impl fmt::Display for HavingBoundKind {
8411    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8412        match self {
8413            HavingBoundKind::Min => write!(f, "MIN"),
8414            HavingBoundKind::Max => write!(f, "MAX"),
8415        }
8416    }
8417}
8418
8419#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8420#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8421#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8422/// Types of database objects referenced by DDL statements.
8423pub enum ObjectType {
8424    /// A collation.
8425    Collation,
8426    /// A table.
8427    Table,
8428    /// A view.
8429    View,
8430    /// A materialized view.
8431    MaterializedView,
8432    /// An index.
8433    Index,
8434    /// A schema.
8435    Schema,
8436    /// A database.
8437    Database,
8438    /// A role.
8439    Role,
8440    /// A sequence.
8441    Sequence,
8442    /// A stage.
8443    Stage,
8444    /// A type definition.
8445    Type,
8446    /// A user.
8447    User,
8448    /// A stream.
8449    Stream,
8450}
8451
8452impl fmt::Display for ObjectType {
8453    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8454        f.write_str(match self {
8455            ObjectType::Collation => "COLLATION",
8456            ObjectType::Table => "TABLE",
8457            ObjectType::View => "VIEW",
8458            ObjectType::MaterializedView => "MATERIALIZED VIEW",
8459            ObjectType::Index => "INDEX",
8460            ObjectType::Schema => "SCHEMA",
8461            ObjectType::Database => "DATABASE",
8462            ObjectType::Role => "ROLE",
8463            ObjectType::Sequence => "SEQUENCE",
8464            ObjectType::Stage => "STAGE",
8465            ObjectType::Type => "TYPE",
8466            ObjectType::User => "USER",
8467            ObjectType::Stream => "STREAM",
8468        })
8469    }
8470}
8471
8472#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8473#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8474#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8475/// Types supported by `KILL` statements.
8476pub enum KillType {
8477    /// Kill a connection.
8478    Connection,
8479    /// Kill a running query.
8480    Query,
8481    /// Kill a mutation (ClickHouse).
8482    Mutation,
8483}
8484
8485impl fmt::Display for KillType {
8486    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8487        f.write_str(match self {
8488            // MySQL
8489            KillType::Connection => "CONNECTION",
8490            KillType::Query => "QUERY",
8491            // Clickhouse supports Mutation
8492            KillType::Mutation => "MUTATION",
8493        })
8494    }
8495}
8496
8497#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8498#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8499#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8500/// Distribution style options for Hive tables.
8501pub enum HiveDistributionStyle {
8502    /// Partitioned distribution with the given columns.
8503    PARTITIONED {
8504        /// Columns used for partitioning.
8505        columns: Vec<ColumnDef>,
8506    },
8507    /// Skewed distribution definition.
8508    SKEWED {
8509        /// Columns participating in the skew definition.
8510        columns: Vec<ColumnDef>,
8511        /// Columns listed in the `ON` clause for skewing.
8512        on: Vec<ColumnDef>,
8513        /// Whether skewed data is stored as directories.
8514        stored_as_directories: bool,
8515    },
8516    /// No distribution style specified.
8517    NONE,
8518}
8519
8520#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8521#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8522#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8523/// Row format specification for Hive tables (SERDE or DELIMITED).
8524pub enum HiveRowFormat {
8525    /// SerDe class specification with the implementing class name.
8526    SERDE {
8527        /// The SerDe implementation class name.
8528        class: String,
8529    },
8530    /// Delimited row format with one or more delimiter specifications.
8531    DELIMITED {
8532        /// The list of delimiters used for delimiting fields/lines.
8533        delimiters: Vec<HiveRowDelimiter>,
8534    },
8535}
8536
8537#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8538#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8539#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8540/// Format specification for `LOAD DATA` Hive operations.
8541pub struct HiveLoadDataFormat {
8542    /// SerDe expression used for the table.
8543    pub serde: Expr,
8544    /// Input format expression.
8545    pub input_format: Expr,
8546}
8547
8548#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8549#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8550#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8551/// A single row delimiter specification for Hive `ROW FORMAT`.
8552pub struct HiveRowDelimiter {
8553    /// The delimiter kind (fields/lines/etc.).
8554    pub delimiter: HiveDelimiter,
8555    /// The delimiter character identifier.
8556    pub char: Ident,
8557}
8558
8559impl fmt::Display for HiveRowDelimiter {
8560    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8561        write!(f, "{} ", self.delimiter)?;
8562        write!(f, "{}", self.char)
8563    }
8564}
8565
8566#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8567#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8568#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8569/// Kind of delimiter used in Hive `ROW FORMAT` definitions.
8570pub enum HiveDelimiter {
8571    /// Fields terminated by a delimiter.
8572    FieldsTerminatedBy,
8573    /// Fields escaped by a character.
8574    FieldsEscapedBy,
8575    /// Collection items terminated by a delimiter.
8576    CollectionItemsTerminatedBy,
8577    /// Map keys terminated by a delimiter.
8578    MapKeysTerminatedBy,
8579    /// Lines terminated by a delimiter.
8580    LinesTerminatedBy,
8581    /// Null represented by a specific token.
8582    NullDefinedAs,
8583}
8584
8585impl fmt::Display for HiveDelimiter {
8586    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8587        use HiveDelimiter::*;
8588        f.write_str(match self {
8589            FieldsTerminatedBy => "FIELDS TERMINATED BY",
8590            FieldsEscapedBy => "ESCAPED BY",
8591            CollectionItemsTerminatedBy => "COLLECTION ITEMS TERMINATED BY",
8592            MapKeysTerminatedBy => "MAP KEYS TERMINATED BY",
8593            LinesTerminatedBy => "LINES TERMINATED BY",
8594            NullDefinedAs => "NULL DEFINED AS",
8595        })
8596    }
8597}
8598
8599#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8600#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8601#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8602/// Describe output format options for Hive `DESCRIBE`/`EXPLAIN`.
8603pub enum HiveDescribeFormat {
8604    /// Extended describe output.
8605    Extended,
8606    /// Formatted describe output.
8607    Formatted,
8608}
8609
8610impl fmt::Display for HiveDescribeFormat {
8611    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8612        use HiveDescribeFormat::*;
8613        f.write_str(match self {
8614            Extended => "EXTENDED",
8615            Formatted => "FORMATTED",
8616        })
8617    }
8618}
8619
8620#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8621#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8622#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8623/// Aliases accepted for describe-style commands.
8624pub enum DescribeAlias {
8625    /// `DESCRIBE` alias.
8626    Describe,
8627    /// `EXPLAIN` alias.
8628    Explain,
8629    /// `DESC` alias.
8630    Desc,
8631}
8632
8633impl fmt::Display for DescribeAlias {
8634    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8635        use DescribeAlias::*;
8636        f.write_str(match self {
8637            Describe => "DESCRIBE",
8638            Explain => "EXPLAIN",
8639            Desc => "DESC",
8640        })
8641    }
8642}
8643
8644#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8645#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8646#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8647#[allow(clippy::large_enum_variant)]
8648/// Hive input/output format specification used in `CREATE TABLE`.
8649pub enum HiveIOFormat {
8650    /// Generic IO format with separate input and output expressions.
8651    IOF {
8652        /// Expression for the input format.
8653        input_format: Expr,
8654        /// Expression for the output format.
8655        output_format: Expr,
8656    },
8657    /// File format wrapper referencing a `FileFormat` variant.
8658    FileFormat {
8659        /// The file format used for storage.
8660        format: FileFormat,
8661    },
8662}
8663
8664#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Default)]
8665#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8666#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8667/// Hive table format and storage-related options.
8668pub struct HiveFormat {
8669    /// Optional row format specification.
8670    pub row_format: Option<HiveRowFormat>,
8671    /// Optional SerDe properties expressed as SQL options.
8672    pub serde_properties: Option<Vec<SqlOption>>,
8673    /// Optional input/output storage format details.
8674    pub storage: Option<HiveIOFormat>,
8675    /// Optional location (URI or path) for table data.
8676    pub location: Option<String>,
8677}
8678
8679#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8680#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8681#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8682/// A clustered index column specification.
8683pub struct ClusteredIndex {
8684    /// Column identifier for the clustered index entry.
8685    pub name: Ident,
8686    /// Optional sort direction: `Some(true)` for ASC, `Some(false)` for DESC, `None` for unspecified.
8687    pub asc: Option<bool>,
8688}
8689
8690impl fmt::Display for ClusteredIndex {
8691    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8692        write!(f, "{}", self.name)?;
8693        match self.asc {
8694            Some(true) => write!(f, " ASC"),
8695            Some(false) => write!(f, " DESC"),
8696            _ => Ok(()),
8697        }
8698    }
8699}
8700
8701#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8702#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8703#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8704/// Clustered options used for `CREATE TABLE` clustered/indexed storage.
8705pub enum TableOptionsClustered {
8706    /// Use a columnstore index.
8707    ColumnstoreIndex,
8708    /// Columnstore index with an explicit ordering of columns.
8709    ColumnstoreIndexOrder(Vec<Ident>),
8710    /// A named clustered index with one or more columns.
8711    Index(Vec<ClusteredIndex>),
8712}
8713
8714impl fmt::Display for TableOptionsClustered {
8715    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8716        match self {
8717            TableOptionsClustered::ColumnstoreIndex => {
8718                write!(f, "CLUSTERED COLUMNSTORE INDEX")
8719            }
8720            TableOptionsClustered::ColumnstoreIndexOrder(values) => {
8721                write!(
8722                    f,
8723                    "CLUSTERED COLUMNSTORE INDEX ORDER ({})",
8724                    display_comma_separated(values)
8725                )
8726            }
8727            TableOptionsClustered::Index(values) => {
8728                write!(f, "CLUSTERED INDEX ({})", display_comma_separated(values))
8729            }
8730        }
8731    }
8732}
8733
8734/// Specifies which partition the boundary values on table partitioning belongs to.
8735#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash)]
8736#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8737#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8738pub enum PartitionRangeDirection {
8739    /// LEFT range direction.
8740    Left,
8741    /// RIGHT range direction.
8742    Right,
8743}
8744
8745#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8746#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8747#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8748/// SQL option syntax used in table and server definitions.
8749pub enum SqlOption {
8750    /// Clustered represents the clustered version of table storage for MSSQL.
8751    ///
8752    /// <https://learn.microsoft.com/en-us/sql/t-sql/statements/create-table-azure-sql-data-warehouse?view=aps-pdw-2016-au7#TableOptions>
8753    Clustered(TableOptionsClustered),
8754    /// Single identifier options, e.g. `HEAP` for MSSQL.
8755    ///
8756    /// <https://learn.microsoft.com/en-us/sql/t-sql/statements/create-table-azure-sql-data-warehouse?view=aps-pdw-2016-au7#TableOptions>
8757    Ident(Ident),
8758    /// Any option that consists of a key value pair where the value is an expression. e.g.
8759    ///
8760    ///   WITH(DISTRIBUTION = ROUND_ROBIN)
8761    KeyValue {
8762        /// The option key identifier.
8763        key: Ident,
8764        /// The expression value for the option.
8765        value: Expr,
8766    },
8767    /// One or more table partitions and represents which partition the boundary values belong to,
8768    /// e.g.
8769    ///
8770    ///   PARTITION (id RANGE LEFT FOR VALUES (10, 20, 30, 40))
8771    ///
8772    /// <https://learn.microsoft.com/en-us/sql/t-sql/statements/create-table-azure-sql-data-warehouse?view=aps-pdw-2016-au7#TablePartitionOptions>
8773    Partition {
8774        /// The partition column name.
8775        column_name: Ident,
8776        /// Optional direction for the partition range (LEFT/RIGHT).
8777        range_direction: Option<PartitionRangeDirection>,
8778        /// Values that define the partition boundaries.
8779        for_values: Vec<Expr>,
8780    },
8781    /// Comment parameter (supports `=` and no `=` syntax)
8782    Comment(CommentDef),
8783    /// MySQL TableSpace option
8784    /// <https://dev.mysql.com/doc/refman/8.4/en/create-table.html>
8785    TableSpace(TablespaceOption),
8786    /// An option representing a key value pair, where the value is a parenthesized list and with an optional name
8787    /// e.g.
8788    ///
8789    ///   UNION  = (tbl_name\[,tbl_name\]...) <https://dev.mysql.com/doc/refman/8.4/en/create-table.html>
8790    ///   ENGINE = ReplicatedMergeTree('/table_name','{replica}', ver) <https://clickhouse.com/docs/engines/table-engines/mergetree-family/replication>
8791    ///   ENGINE = SummingMergeTree(\[columns\]) <https://clickhouse.com/docs/engines/table-engines/mergetree-family/summingmergetree>
8792    NamedParenthesizedList(NamedParenthesizedList),
8793}
8794
8795impl fmt::Display for SqlOption {
8796    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8797        match self {
8798            SqlOption::Clustered(c) => write!(f, "{c}"),
8799            SqlOption::Ident(ident) => {
8800                write!(f, "{ident}")
8801            }
8802            SqlOption::KeyValue { key: name, value } => {
8803                write!(f, "{name} = {value}")
8804            }
8805            SqlOption::Partition {
8806                column_name,
8807                range_direction,
8808                for_values,
8809            } => {
8810                let direction = match range_direction {
8811                    Some(PartitionRangeDirection::Left) => " LEFT",
8812                    Some(PartitionRangeDirection::Right) => " RIGHT",
8813                    None => "",
8814                };
8815
8816                write!(
8817                    f,
8818                    "PARTITION ({} RANGE{} FOR VALUES ({}))",
8819                    column_name,
8820                    direction,
8821                    display_comma_separated(for_values)
8822                )
8823            }
8824            SqlOption::TableSpace(tablespace_option) => {
8825                write!(f, "TABLESPACE {}", tablespace_option.name)?;
8826                match tablespace_option.storage {
8827                    Some(StorageType::Disk) => write!(f, " STORAGE DISK"),
8828                    Some(StorageType::Memory) => write!(f, " STORAGE MEMORY"),
8829                    None => Ok(()),
8830                }
8831            }
8832            SqlOption::Comment(comment) => match comment {
8833                CommentDef::WithEq(comment) => {
8834                    write!(f, "COMMENT = '{comment}'")
8835                }
8836                CommentDef::WithoutEq(comment) => {
8837                    write!(f, "COMMENT '{comment}'")
8838                }
8839            },
8840            SqlOption::NamedParenthesizedList(value) => {
8841                write!(f, "{} = ", value.key)?;
8842                if let Some(key) = &value.name {
8843                    write!(f, "{key}")?;
8844                }
8845                if !value.values.is_empty() {
8846                    write!(f, "({})", display_comma_separated(&value.values))?
8847                }
8848                Ok(())
8849            }
8850        }
8851    }
8852}
8853
8854#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
8855#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8856#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8857/// Storage type options for a tablespace.
8858pub enum StorageType {
8859    /// Store on disk.
8860    Disk,
8861    /// Store in memory.
8862    Memory,
8863}
8864
8865#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
8866#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8867#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8868/// MySql TableSpace option
8869/// <https://dev.mysql.com/doc/refman/8.4/en/create-table.html>
8870pub struct TablespaceOption {
8871    /// Name of the tablespace.
8872    pub name: String,
8873    /// Optional storage type for the tablespace.
8874    pub storage: Option<StorageType>,
8875}
8876
8877#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8878#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8879#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8880/// A key/value identifier pair used for secret or key-based options.
8881pub struct SecretOption {
8882    /// The option key identifier.
8883    pub key: Ident,
8884    /// The option value identifier.
8885    pub value: Ident,
8886}
8887
8888impl fmt::Display for SecretOption {
8889    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8890        write!(f, "{} {}", self.key, self.value)
8891    }
8892}
8893
8894/// A `CREATE SERVER` statement.
8895///
8896/// [PostgreSQL Documentation](https://www.postgresql.org/docs/current/sql-createserver.html)
8897#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8898#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8899#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8900pub struct CreateServerStatement {
8901    /// The server name.
8902    pub name: ObjectName,
8903    /// Whether `IF NOT EXISTS` was specified.
8904    pub if_not_exists: bool,
8905    /// Optional server type identifier.
8906    pub server_type: Option<Ident>,
8907    /// Optional server version identifier.
8908    pub version: Option<Ident>,
8909    /// Foreign-data wrapper object name.
8910    pub foreign_data_wrapper: ObjectName,
8911    /// Optional list of server options.
8912    pub options: Option<Vec<CreateServerOption>>,
8913}
8914
8915impl fmt::Display for CreateServerStatement {
8916    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8917        let CreateServerStatement {
8918            name,
8919            if_not_exists,
8920            server_type,
8921            version,
8922            foreign_data_wrapper,
8923            options,
8924        } = self;
8925
8926        write!(
8927            f,
8928            "CREATE SERVER {if_not_exists}{name} ",
8929            if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
8930        )?;
8931
8932        if let Some(st) = server_type {
8933            write!(f, "TYPE {st} ")?;
8934        }
8935
8936        if let Some(v) = version {
8937            write!(f, "VERSION {v} ")?;
8938        }
8939
8940        write!(f, "FOREIGN DATA WRAPPER {foreign_data_wrapper}")?;
8941
8942        if let Some(o) = options {
8943            write!(f, " OPTIONS ({o})", o = display_comma_separated(o))?;
8944        }
8945
8946        Ok(())
8947    }
8948}
8949
8950/// A key/value option for `CREATE SERVER`.
8951#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8952#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8953#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8954pub struct CreateServerOption {
8955    /// Option key identifier.
8956    pub key: Ident,
8957    /// Option value identifier.
8958    pub value: Ident,
8959}
8960
8961impl fmt::Display for CreateServerOption {
8962    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8963        write!(f, "{} {}", self.key, self.value)
8964    }
8965}
8966
8967#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8968#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8969#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8970/// Options supported by DuckDB for `ATTACH DATABASE`.
8971pub enum AttachDuckDBDatabaseOption {
8972    /// READ_ONLY option, optional boolean value.
8973    ReadOnly(Option<bool>),
8974    /// TYPE option specifying a database type identifier.
8975    Type(Ident),
8976}
8977
8978impl fmt::Display for AttachDuckDBDatabaseOption {
8979    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8980        match self {
8981            AttachDuckDBDatabaseOption::ReadOnly(Some(true)) => write!(f, "READ_ONLY true"),
8982            AttachDuckDBDatabaseOption::ReadOnly(Some(false)) => write!(f, "READ_ONLY false"),
8983            AttachDuckDBDatabaseOption::ReadOnly(None) => write!(f, "READ_ONLY"),
8984            AttachDuckDBDatabaseOption::Type(t) => write!(f, "TYPE {t}"),
8985        }
8986    }
8987}
8988
8989#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8990#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8991#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8992/// Mode for transactions: access mode or isolation level.
8993pub enum TransactionMode {
8994    /// Access mode for a transaction (e.g. `READ ONLY` / `READ WRITE`).
8995    AccessMode(TransactionAccessMode),
8996    /// Isolation level for a transaction (e.g. `SERIALIZABLE`).
8997    IsolationLevel(TransactionIsolationLevel),
8998}
8999
9000impl fmt::Display for TransactionMode {
9001    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9002        use TransactionMode::*;
9003        match self {
9004            AccessMode(access_mode) => write!(f, "{access_mode}"),
9005            IsolationLevel(iso_level) => write!(f, "ISOLATION LEVEL {iso_level}"),
9006        }
9007    }
9008}
9009
9010#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9011#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9012#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9013/// Transaction access mode (READ ONLY / READ WRITE).
9014pub enum TransactionAccessMode {
9015    /// READ ONLY access mode.
9016    ReadOnly,
9017    /// READ WRITE access mode.
9018    ReadWrite,
9019}
9020
9021impl fmt::Display for TransactionAccessMode {
9022    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9023        use TransactionAccessMode::*;
9024        f.write_str(match self {
9025            ReadOnly => "READ ONLY",
9026            ReadWrite => "READ WRITE",
9027        })
9028    }
9029}
9030
9031#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9032#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9033#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9034/// Transaction isolation levels.
9035pub enum TransactionIsolationLevel {
9036    /// READ UNCOMMITTED isolation level.
9037    ReadUncommitted,
9038    /// READ COMMITTED isolation level.
9039    ReadCommitted,
9040    /// REPEATABLE READ isolation level.
9041    RepeatableRead,
9042    /// SERIALIZABLE isolation level.
9043    Serializable,
9044    /// SNAPSHOT isolation level.
9045    Snapshot,
9046}
9047
9048impl fmt::Display for TransactionIsolationLevel {
9049    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9050        use TransactionIsolationLevel::*;
9051        f.write_str(match self {
9052            ReadUncommitted => "READ UNCOMMITTED",
9053            ReadCommitted => "READ COMMITTED",
9054            RepeatableRead => "REPEATABLE READ",
9055            Serializable => "SERIALIZABLE",
9056            Snapshot => "SNAPSHOT",
9057        })
9058    }
9059}
9060
9061/// Modifier for the transaction in the `BEGIN` syntax
9062///
9063/// SQLite: <https://sqlite.org/lang_transaction.html>
9064/// MS-SQL: <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/try-catch-transact-sql>
9065#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9066#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9067#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9068pub enum TransactionModifier {
9069    /// DEFERRED transaction modifier.
9070    Deferred,
9071    /// IMMEDIATE transaction modifier.
9072    Immediate,
9073    /// EXCLUSIVE transaction modifier.
9074    Exclusive,
9075    /// TRY block modifier (MS-SQL style TRY/CATCH).
9076    Try,
9077    /// CATCH block modifier (MS-SQL style TRY/CATCH).
9078    Catch,
9079}
9080
9081impl fmt::Display for TransactionModifier {
9082    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9083        use TransactionModifier::*;
9084        f.write_str(match self {
9085            Deferred => "DEFERRED",
9086            Immediate => "IMMEDIATE",
9087            Exclusive => "EXCLUSIVE",
9088            Try => "TRY",
9089            Catch => "CATCH",
9090        })
9091    }
9092}
9093
9094#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9095#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9096#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9097/// Filter forms usable in SHOW statements.
9098pub enum ShowStatementFilter {
9099    /// Filter using LIKE pattern.
9100    Like(String),
9101    /// Filter using ILIKE pattern.
9102    ILike(String),
9103    /// Filter using a WHERE expression.
9104    Where(Expr),
9105    /// Filter provided without a keyword (raw string).
9106    NoKeyword(String),
9107}
9108
9109impl fmt::Display for ShowStatementFilter {
9110    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9111        use ShowStatementFilter::*;
9112        match self {
9113            Like(pattern) => write!(f, "LIKE '{}'", value::escape_single_quote_string(pattern)),
9114            ILike(pattern) => write!(f, "ILIKE {}", value::escape_single_quote_string(pattern)),
9115            Where(expr) => write!(f, "WHERE {expr}"),
9116            NoKeyword(pattern) => write!(f, "'{}'", value::escape_single_quote_string(pattern)),
9117        }
9118    }
9119}
9120
9121#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9122#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9123#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9124/// Clause types used with SHOW ... IN/FROM.
9125pub enum ShowStatementInClause {
9126    /// Use the `IN` clause.
9127    IN,
9128    /// Use the `FROM` clause.
9129    FROM,
9130}
9131
9132impl fmt::Display for ShowStatementInClause {
9133    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9134        use ShowStatementInClause::*;
9135        match self {
9136            FROM => write!(f, "FROM"),
9137            IN => write!(f, "IN"),
9138        }
9139    }
9140}
9141
9142/// Sqlite specific syntax
9143///
9144/// See [Sqlite documentation](https://sqlite.org/lang_conflict.html)
9145/// for more details.
9146#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9147#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9148#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9149pub enum SqliteOnConflict {
9150    /// Use ROLLBACK on conflict.
9151    Rollback,
9152    /// Use ABORT on conflict.
9153    Abort,
9154    /// Use FAIL on conflict.
9155    Fail,
9156    /// Use IGNORE on conflict.
9157    Ignore,
9158    /// Use REPLACE on conflict.
9159    Replace,
9160}
9161
9162impl fmt::Display for SqliteOnConflict {
9163    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9164        use SqliteOnConflict::*;
9165        match self {
9166            Rollback => write!(f, "OR ROLLBACK"),
9167            Abort => write!(f, "OR ABORT"),
9168            Fail => write!(f, "OR FAIL"),
9169            Ignore => write!(f, "OR IGNORE"),
9170            Replace => write!(f, "OR REPLACE"),
9171        }
9172    }
9173}
9174
9175/// Mysql specific syntax
9176///
9177/// See [Mysql documentation](https://dev.mysql.com/doc/refman/8.0/en/replace.html)
9178/// See [Mysql documentation](https://dev.mysql.com/doc/refman/8.0/en/insert.html)
9179/// for more details.
9180#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9181#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9182#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9183pub enum MysqlInsertPriority {
9184    /// LOW_PRIORITY modifier for INSERT/REPLACE.
9185    LowPriority,
9186    /// DELAYED modifier for INSERT/REPLACE.
9187    Delayed,
9188    /// HIGH_PRIORITY modifier for INSERT/REPLACE.
9189    HighPriority,
9190}
9191
9192impl fmt::Display for crate::ast::MysqlInsertPriority {
9193    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9194        use MysqlInsertPriority::*;
9195        match self {
9196            LowPriority => write!(f, "LOW_PRIORITY"),
9197            Delayed => write!(f, "DELAYED"),
9198            HighPriority => write!(f, "HIGH_PRIORITY"),
9199        }
9200    }
9201}
9202
9203#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9204#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9205#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9206/// Source for the `COPY` command: a table or a query.
9207pub enum CopySource {
9208    /// Copy from a table with optional column list.
9209    Table {
9210        /// The name of the table to copy from.
9211        table_name: ObjectName,
9212        /// A list of column names to copy. Empty list means that all columns
9213        /// are copied.
9214        columns: Vec<Ident>,
9215    },
9216    /// Copy from the results of a query.
9217    Query(Box<Query>),
9218}
9219
9220#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9221#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9222#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9223/// Target for the `COPY` command: STDIN, STDOUT, a file, or a program.
9224pub enum CopyTarget {
9225    /// Use standard input as the source.
9226    Stdin,
9227    /// Use standard output as the target.
9228    Stdout,
9229    /// Read from or write to a file.
9230    File {
9231        /// The path name of the input or output file.
9232        filename: String,
9233    },
9234    /// Use a program as the source or target (shell command).
9235    Program {
9236        /// A command to execute
9237        command: String,
9238    },
9239}
9240
9241impl fmt::Display for CopyTarget {
9242    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9243        use CopyTarget::*;
9244        match self {
9245            Stdin => write!(f, "STDIN"),
9246            Stdout => write!(f, "STDOUT"),
9247            File { filename } => write!(f, "'{}'", value::escape_single_quote_string(filename)),
9248            Program { command } => write!(
9249                f,
9250                "PROGRAM '{}'",
9251                value::escape_single_quote_string(command)
9252            ),
9253        }
9254    }
9255}
9256
9257#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9258#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9259#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9260/// Action to take `ON COMMIT` for temporary tables.
9261pub enum OnCommit {
9262    /// Delete rows on commit.
9263    DeleteRows,
9264    /// Preserve rows on commit.
9265    PreserveRows,
9266    /// Drop the table on commit.
9267    Drop,
9268}
9269
9270/// An option in `COPY` statement.
9271///
9272/// <https://www.postgresql.org/docs/14/sql-copy.html>
9273#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9274#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9275#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9276pub enum CopyOption {
9277    /// FORMAT format_name
9278    Format(Ident),
9279    /// FREEZE \[ boolean \]
9280    Freeze(bool),
9281    /// DELIMITER 'delimiter_character'
9282    Delimiter(char),
9283    /// NULL 'null_string'
9284    Null(String),
9285    /// HEADER \[ boolean \]
9286    Header(bool),
9287    /// QUOTE 'quote_character'
9288    Quote(char),
9289    /// ESCAPE 'escape_character'
9290    Escape(char),
9291    /// FORCE_QUOTE { ( column_name [, ...] ) | * }
9292    ForceQuote(Vec<Ident>),
9293    /// FORCE_NOT_NULL ( column_name [, ...] )
9294    ForceNotNull(Vec<Ident>),
9295    /// FORCE_NULL ( column_name [, ...] )
9296    ForceNull(Vec<Ident>),
9297    /// ENCODING 'encoding_name'
9298    Encoding(String),
9299}
9300
9301impl fmt::Display for CopyOption {
9302    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9303        use CopyOption::*;
9304        match self {
9305            Format(name) => write!(f, "FORMAT {name}"),
9306            Freeze(true) => write!(f, "FREEZE"),
9307            Freeze(false) => write!(f, "FREEZE FALSE"),
9308            Delimiter(char) => write!(f, "DELIMITER '{char}'"),
9309            Null(string) => write!(f, "NULL '{}'", value::escape_single_quote_string(string)),
9310            Header(true) => write!(f, "HEADER"),
9311            Header(false) => write!(f, "HEADER FALSE"),
9312            Quote(char) => write!(f, "QUOTE '{char}'"),
9313            Escape(char) => write!(f, "ESCAPE '{char}'"),
9314            ForceQuote(columns) => write!(f, "FORCE_QUOTE ({})", display_comma_separated(columns)),
9315            ForceNotNull(columns) => {
9316                write!(f, "FORCE_NOT_NULL ({})", display_comma_separated(columns))
9317            }
9318            ForceNull(columns) => write!(f, "FORCE_NULL ({})", display_comma_separated(columns)),
9319            Encoding(name) => write!(f, "ENCODING '{}'", value::escape_single_quote_string(name)),
9320        }
9321    }
9322}
9323
9324/// An option in `COPY` statement before PostgreSQL version 9.0.
9325///
9326/// [PostgreSQL](https://www.postgresql.org/docs/8.4/sql-copy.html)
9327/// [Redshift](https://docs.aws.amazon.com/redshift/latest/dg/r_COPY-alphabetical-parm-list.html)
9328#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9329#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9330#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9331pub enum CopyLegacyOption {
9332    /// ACCEPTANYDATE
9333    AcceptAnyDate,
9334    /// ACCEPTINVCHARS
9335    AcceptInvChars(Option<String>),
9336    /// ADDQUOTES
9337    AddQuotes,
9338    /// ALLOWOVERWRITE
9339    AllowOverwrite,
9340    /// BINARY
9341    Binary,
9342    /// BLANKSASNULL
9343    BlankAsNull,
9344    /// BZIP2
9345    Bzip2,
9346    /// CLEANPATH
9347    CleanPath,
9348    /// COMPUPDATE [ PRESET | { ON | TRUE } | { OFF | FALSE } ]
9349    CompUpdate {
9350        /// Whether the COMPUPDATE PRESET option was used.
9351        preset: bool,
9352        /// Optional enabled flag for COMPUPDATE.
9353        enabled: Option<bool>,
9354    },
9355    /// CSV ...
9356    Csv(Vec<CopyLegacyCsvOption>),
9357    /// DATEFORMAT \[ AS \] {'dateformat_string' | 'auto' }
9358    DateFormat(Option<String>),
9359    /// DELIMITER \[ AS \] 'delimiter_character'
9360    Delimiter(char),
9361    /// EMPTYASNULL
9362    EmptyAsNull,
9363    /// `ENCRYPTED \[ AUTO \]`
9364    Encrypted {
9365        /// Whether `AUTO` was specified for encryption.
9366        auto: bool,
9367    },
9368    /// ESCAPE
9369    Escape,
9370    /// EXTENSION 'extension-name'
9371    Extension(String),
9372    /// FIXEDWIDTH \[ AS \] 'fixedwidth-spec'
9373    FixedWidth(String),
9374    /// GZIP
9375    Gzip,
9376    /// HEADER
9377    Header,
9378    /// IAM_ROLE { DEFAULT | 'arn:aws:iam::123456789:role/role1' }
9379    IamRole(IamRoleKind),
9380    /// IGNOREHEADER \[ AS \] number_rows
9381    IgnoreHeader(u64),
9382    /// JSON \[ AS \] 'json_option'
9383    Json(Option<String>),
9384    /// MANIFEST \[ VERBOSE \]
9385    Manifest {
9386        /// Whether the MANIFEST is verbose.
9387        verbose: bool,
9388    },
9389    /// MAXFILESIZE \[ AS \] max-size \[ MB | GB \]
9390    MaxFileSize(FileSize),
9391    /// `NULL \[ AS \] 'null_string'`
9392    Null(String),
9393    /// `PARALLEL [ { ON | TRUE } | { OFF | FALSE } ]`
9394    Parallel(Option<bool>),
9395    /// PARQUET
9396    Parquet,
9397    /// PARTITION BY ( column_name [, ... ] ) \[ INCLUDE \]
9398    PartitionBy(UnloadPartitionBy),
9399    /// REGION \[ AS \] 'aws-region' }
9400    Region(String),
9401    /// REMOVEQUOTES
9402    RemoveQuotes,
9403    /// ROWGROUPSIZE \[ AS \] size \[ MB | GB \]
9404    RowGroupSize(FileSize),
9405    /// STATUPDATE [ { ON | TRUE } | { OFF | FALSE } ]
9406    StatUpdate(Option<bool>),
9407    /// TIMEFORMAT \[ AS \] {'timeformat_string' | 'auto' | 'epochsecs' | 'epochmillisecs' }
9408    TimeFormat(Option<String>),
9409    /// TRUNCATECOLUMNS
9410    TruncateColumns,
9411    /// ZSTD
9412    Zstd,
9413    /// Redshift `CREDENTIALS 'auth-args'`
9414    /// <https://docs.aws.amazon.com/redshift/latest/dg/copy-parameters-authorization.html>
9415    Credentials(String),
9416}
9417
9418impl fmt::Display for CopyLegacyOption {
9419    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9420        use CopyLegacyOption::*;
9421        match self {
9422            AcceptAnyDate => write!(f, "ACCEPTANYDATE"),
9423            AcceptInvChars(ch) => {
9424                write!(f, "ACCEPTINVCHARS")?;
9425                if let Some(ch) = ch {
9426                    write!(f, " '{}'", value::escape_single_quote_string(ch))?;
9427                }
9428                Ok(())
9429            }
9430            AddQuotes => write!(f, "ADDQUOTES"),
9431            AllowOverwrite => write!(f, "ALLOWOVERWRITE"),
9432            Binary => write!(f, "BINARY"),
9433            BlankAsNull => write!(f, "BLANKSASNULL"),
9434            Bzip2 => write!(f, "BZIP2"),
9435            CleanPath => write!(f, "CLEANPATH"),
9436            CompUpdate { preset, enabled } => {
9437                write!(f, "COMPUPDATE")?;
9438                if *preset {
9439                    write!(f, " PRESET")?;
9440                } else if let Some(enabled) = enabled {
9441                    write!(
9442                        f,
9443                        "{}",
9444                        match enabled {
9445                            true => " TRUE",
9446                            false => " FALSE",
9447                        }
9448                    )?;
9449                }
9450                Ok(())
9451            }
9452            Csv(opts) => {
9453                write!(f, "CSV")?;
9454                if !opts.is_empty() {
9455                    write!(f, " {}", display_separated(opts, " "))?;
9456                }
9457                Ok(())
9458            }
9459            DateFormat(fmt) => {
9460                write!(f, "DATEFORMAT")?;
9461                if let Some(fmt) = fmt {
9462                    write!(f, " '{}'", value::escape_single_quote_string(fmt))?;
9463                }
9464                Ok(())
9465            }
9466            Delimiter(char) => write!(f, "DELIMITER '{char}'"),
9467            EmptyAsNull => write!(f, "EMPTYASNULL"),
9468            Encrypted { auto } => write!(f, "ENCRYPTED{}", if *auto { " AUTO" } else { "" }),
9469            Escape => write!(f, "ESCAPE"),
9470            Extension(ext) => write!(f, "EXTENSION '{}'", value::escape_single_quote_string(ext)),
9471            FixedWidth(spec) => write!(
9472                f,
9473                "FIXEDWIDTH '{}'",
9474                value::escape_single_quote_string(spec)
9475            ),
9476            Gzip => write!(f, "GZIP"),
9477            Header => write!(f, "HEADER"),
9478            IamRole(role) => write!(f, "IAM_ROLE {role}"),
9479            IgnoreHeader(num_rows) => write!(f, "IGNOREHEADER {num_rows}"),
9480            Json(opt) => {
9481                write!(f, "JSON")?;
9482                if let Some(opt) = opt {
9483                    write!(f, " AS '{}'", value::escape_single_quote_string(opt))?;
9484                }
9485                Ok(())
9486            }
9487            Manifest { verbose } => write!(f, "MANIFEST{}", if *verbose { " VERBOSE" } else { "" }),
9488            MaxFileSize(file_size) => write!(f, "MAXFILESIZE {file_size}"),
9489            Null(string) => write!(f, "NULL '{}'", value::escape_single_quote_string(string)),
9490            Parallel(enabled) => {
9491                write!(
9492                    f,
9493                    "PARALLEL{}",
9494                    match enabled {
9495                        Some(true) => " TRUE",
9496                        Some(false) => " FALSE",
9497                        _ => "",
9498                    }
9499                )
9500            }
9501            Parquet => write!(f, "PARQUET"),
9502            PartitionBy(p) => write!(f, "{p}"),
9503            Region(region) => write!(f, "REGION '{}'", value::escape_single_quote_string(region)),
9504            RemoveQuotes => write!(f, "REMOVEQUOTES"),
9505            RowGroupSize(file_size) => write!(f, "ROWGROUPSIZE {file_size}"),
9506            StatUpdate(enabled) => {
9507                write!(
9508                    f,
9509                    "STATUPDATE{}",
9510                    match enabled {
9511                        Some(true) => " TRUE",
9512                        Some(false) => " FALSE",
9513                        _ => "",
9514                    }
9515                )
9516            }
9517            TimeFormat(fmt) => {
9518                write!(f, "TIMEFORMAT")?;
9519                if let Some(fmt) = fmt {
9520                    write!(f, " '{}'", value::escape_single_quote_string(fmt))?;
9521                }
9522                Ok(())
9523            }
9524            TruncateColumns => write!(f, "TRUNCATECOLUMNS"),
9525            Zstd => write!(f, "ZSTD"),
9526            Credentials(s) => write!(f, "CREDENTIALS '{}'", value::escape_single_quote_string(s)),
9527        }
9528    }
9529}
9530
9531/// ```sql
9532/// SIZE \[ MB | GB \]
9533/// ```
9534#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9535#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9536#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9537pub struct FileSize {
9538    /// Numeric size value.
9539    pub size: ValueWithSpan,
9540    /// Optional unit for the size (MB or GB).
9541    pub unit: Option<FileSizeUnit>,
9542}
9543
9544impl fmt::Display for FileSize {
9545    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9546        write!(f, "{}", self.size)?;
9547        if let Some(unit) = &self.unit {
9548            write!(f, " {unit}")?;
9549        }
9550        Ok(())
9551    }
9552}
9553
9554/// Units for `FileSize` (MB or GB).
9555#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9556#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9557#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9558pub enum FileSizeUnit {
9559    /// Megabytes.
9560    MB,
9561    /// Gigabytes.
9562    GB,
9563}
9564
9565impl fmt::Display for FileSizeUnit {
9566    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9567        match self {
9568            FileSizeUnit::MB => write!(f, "MB"),
9569            FileSizeUnit::GB => write!(f, "GB"),
9570        }
9571    }
9572}
9573
9574/// Specifies the partition keys for the unload operation
9575///
9576/// ```sql
9577/// PARTITION BY ( column_name [, ... ] ) [ INCLUDE ]
9578/// ```
9579#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9580#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9581#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9582pub struct UnloadPartitionBy {
9583    /// Columns used to partition the unload output.
9584    pub columns: Vec<Ident>,
9585    /// Whether to include the partition in the output.
9586    pub include: bool,
9587}
9588
9589impl fmt::Display for UnloadPartitionBy {
9590    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9591        write!(
9592            f,
9593            "PARTITION BY ({}){}",
9594            display_comma_separated(&self.columns),
9595            if self.include { " INCLUDE" } else { "" }
9596        )
9597    }
9598}
9599
9600/// An `IAM_ROLE` option in the AWS ecosystem
9601///
9602/// [Redshift COPY](https://docs.aws.amazon.com/redshift/latest/dg/copy-parameters-authorization.html#copy-iam-role)
9603#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9604#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9605#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9606pub enum IamRoleKind {
9607    /// Default role
9608    Default,
9609    /// Specific role ARN, for example: `arn:aws:iam::123456789:role/role1`
9610    Arn(String),
9611}
9612
9613impl fmt::Display for IamRoleKind {
9614    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9615        match self {
9616            IamRoleKind::Default => write!(f, "DEFAULT"),
9617            IamRoleKind::Arn(arn) => write!(f, "'{arn}'"),
9618        }
9619    }
9620}
9621
9622/// A `CSV` option in `COPY` statement before PostgreSQL version 9.0.
9623///
9624/// <https://www.postgresql.org/docs/8.4/sql-copy.html>
9625#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9626#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9627#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9628pub enum CopyLegacyCsvOption {
9629    /// HEADER
9630    Header,
9631    /// QUOTE \[ AS \] 'quote_character'
9632    Quote(char),
9633    /// ESCAPE \[ AS \] 'escape_character'
9634    Escape(char),
9635    /// FORCE QUOTE { column_name [, ...] | * }
9636    ForceQuote(Vec<Ident>),
9637    /// FORCE NOT NULL column_name [, ...]
9638    ForceNotNull(Vec<Ident>),
9639}
9640
9641impl fmt::Display for CopyLegacyCsvOption {
9642    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9643        use CopyLegacyCsvOption::*;
9644        match self {
9645            Header => write!(f, "HEADER"),
9646            Quote(char) => write!(f, "QUOTE '{char}'"),
9647            Escape(char) => write!(f, "ESCAPE '{char}'"),
9648            ForceQuote(columns) => write!(f, "FORCE QUOTE {}", display_comma_separated(columns)),
9649            ForceNotNull(columns) => {
9650                write!(f, "FORCE NOT NULL {}", display_comma_separated(columns))
9651            }
9652        }
9653    }
9654}
9655
9656/// Objects that can be discarded with `DISCARD`.
9657#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9658#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9659#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9660pub enum DiscardObject {
9661    /// Discard all session state.
9662    ALL,
9663    /// Discard cached plans.
9664    PLANS,
9665    /// Discard sequence values.
9666    SEQUENCES,
9667    /// Discard temporary objects.
9668    TEMP,
9669}
9670
9671impl fmt::Display for DiscardObject {
9672    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9673        match self {
9674            DiscardObject::ALL => f.write_str("ALL"),
9675            DiscardObject::PLANS => f.write_str("PLANS"),
9676            DiscardObject::SEQUENCES => f.write_str("SEQUENCES"),
9677            DiscardObject::TEMP => f.write_str("TEMP"),
9678        }
9679    }
9680}
9681
9682/// Types of flush operations supported by `FLUSH`.
9683#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9684#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9685#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9686pub enum FlushType {
9687    /// Flush binary logs.
9688    BinaryLogs,
9689    /// Flush engine logs.
9690    EngineLogs,
9691    /// Flush error logs.
9692    ErrorLogs,
9693    /// Flush general logs.
9694    GeneralLogs,
9695    /// Flush hosts information.
9696    Hosts,
9697    /// Flush logs.
9698    Logs,
9699    /// Flush privileges.
9700    Privileges,
9701    /// Flush optimizer costs.
9702    OptimizerCosts,
9703    /// Flush relay logs.
9704    RelayLogs,
9705    /// Flush slow logs.
9706    SlowLogs,
9707    /// Flush status.
9708    Status,
9709    /// Flush user resources.
9710    UserResources,
9711    /// Flush table data.
9712    Tables,
9713}
9714
9715impl fmt::Display for FlushType {
9716    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9717        match self {
9718            FlushType::BinaryLogs => f.write_str("BINARY LOGS"),
9719            FlushType::EngineLogs => f.write_str("ENGINE LOGS"),
9720            FlushType::ErrorLogs => f.write_str("ERROR LOGS"),
9721            FlushType::GeneralLogs => f.write_str("GENERAL LOGS"),
9722            FlushType::Hosts => f.write_str("HOSTS"),
9723            FlushType::Logs => f.write_str("LOGS"),
9724            FlushType::Privileges => f.write_str("PRIVILEGES"),
9725            FlushType::OptimizerCosts => f.write_str("OPTIMIZER_COSTS"),
9726            FlushType::RelayLogs => f.write_str("RELAY LOGS"),
9727            FlushType::SlowLogs => f.write_str("SLOW LOGS"),
9728            FlushType::Status => f.write_str("STATUS"),
9729            FlushType::UserResources => f.write_str("USER_RESOURCES"),
9730            FlushType::Tables => f.write_str("TABLES"),
9731        }
9732    }
9733}
9734
9735/// Location modifier for flush commands.
9736#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9737#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9738#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9739pub enum FlushLocation {
9740    /// Do not write changes to the binary log.
9741    NoWriteToBinlog,
9742    /// Apply flush locally.
9743    Local,
9744}
9745
9746impl fmt::Display for FlushLocation {
9747    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9748        match self {
9749            FlushLocation::NoWriteToBinlog => f.write_str("NO_WRITE_TO_BINLOG"),
9750            FlushLocation::Local => f.write_str("LOCAL"),
9751        }
9752    }
9753}
9754
9755/// Optional context modifier for statements that can be or `LOCAL`, `GLOBAL`, or `SESSION`.
9756#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9757#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9758#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9759pub enum ContextModifier {
9760    /// `LOCAL` identifier, usually related to transactional states.
9761    Local,
9762    /// `SESSION` identifier
9763    Session,
9764    /// `GLOBAL` identifier
9765    Global,
9766}
9767
9768impl fmt::Display for ContextModifier {
9769    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9770        match self {
9771            Self::Local => {
9772                write!(f, "LOCAL ")
9773            }
9774            Self::Session => {
9775                write!(f, "SESSION ")
9776            }
9777            Self::Global => {
9778                write!(f, "GLOBAL ")
9779            }
9780        }
9781    }
9782}
9783
9784/// Function describe in DROP FUNCTION.
9785#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9786#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9787pub enum DropFunctionOption {
9788    /// `RESTRICT` option for DROP FUNCTION.
9789    Restrict,
9790    /// `CASCADE` option for DROP FUNCTION.
9791    Cascade,
9792}
9793
9794impl fmt::Display for DropFunctionOption {
9795    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9796        match self {
9797            DropFunctionOption::Restrict => write!(f, "RESTRICT "),
9798            DropFunctionOption::Cascade => write!(f, "CASCADE  "),
9799        }
9800    }
9801}
9802
9803/// Generic function description for DROP FUNCTION and CREATE TRIGGER.
9804#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9805#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9806#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9807pub struct FunctionDesc {
9808    /// The function name.
9809    pub name: ObjectName,
9810    /// Optional list of function arguments.
9811    pub args: Option<Vec<OperateFunctionArg>>,
9812}
9813
9814impl fmt::Display for FunctionDesc {
9815    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9816        write!(f, "{}", self.name)?;
9817        if let Some(args) = &self.args {
9818            write!(f, "({})", display_comma_separated(args))?;
9819        }
9820        Ok(())
9821    }
9822}
9823
9824/// Function argument in CREATE OR DROP FUNCTION.
9825#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9826#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9827#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9828pub struct OperateFunctionArg {
9829    /// Optional argument mode (`IN`, `OUT`, `INOUT`).
9830    pub mode: Option<ArgMode>,
9831    /// Optional argument identifier/name.
9832    pub name: Option<Ident>,
9833    /// The data type of the argument.
9834    pub data_type: DataType,
9835    /// Optional default expression for the argument.
9836    pub default_expr: Option<Expr>,
9837}
9838
9839impl OperateFunctionArg {
9840    /// Returns an unnamed argument.
9841    pub fn unnamed(data_type: DataType) -> Self {
9842        Self {
9843            mode: None,
9844            name: None,
9845            data_type,
9846            default_expr: None,
9847        }
9848    }
9849
9850    /// Returns an argument with name.
9851    pub fn with_name(name: &str, data_type: DataType) -> Self {
9852        Self {
9853            mode: None,
9854            name: Some(name.into()),
9855            data_type,
9856            default_expr: None,
9857        }
9858    }
9859}
9860
9861impl fmt::Display for OperateFunctionArg {
9862    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9863        if let Some(mode) = &self.mode {
9864            write!(f, "{mode} ")?;
9865        }
9866        if let Some(name) = &self.name {
9867            write!(f, "{name} ")?;
9868        }
9869        write!(f, "{}", self.data_type)?;
9870        if let Some(default_expr) = &self.default_expr {
9871            write!(f, " = {default_expr}")?;
9872        }
9873        Ok(())
9874    }
9875}
9876
9877/// The mode of an argument in CREATE FUNCTION.
9878#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9879#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9880#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9881pub enum ArgMode {
9882    /// `IN` mode.
9883    In,
9884    /// `OUT` mode.
9885    Out,
9886    /// `INOUT` mode.
9887    InOut,
9888    /// `VARIADIC` mode.
9889    Variadic,
9890}
9891
9892impl fmt::Display for ArgMode {
9893    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9894        match self {
9895            ArgMode::In => write!(f, "IN"),
9896            ArgMode::Out => write!(f, "OUT"),
9897            ArgMode::InOut => write!(f, "INOUT"),
9898            ArgMode::Variadic => write!(f, "VARIADIC"),
9899        }
9900    }
9901}
9902
9903/// These attributes inform the query optimizer about the behavior of the function.
9904#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9905#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9906#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9907pub enum FunctionBehavior {
9908    /// Function is immutable.
9909    Immutable,
9910    /// Function is stable.
9911    Stable,
9912    /// Function is volatile.
9913    Volatile,
9914}
9915
9916impl fmt::Display for FunctionBehavior {
9917    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9918        match self {
9919            FunctionBehavior::Immutable => write!(f, "IMMUTABLE"),
9920            FunctionBehavior::Stable => write!(f, "STABLE"),
9921            FunctionBehavior::Volatile => write!(f, "VOLATILE"),
9922        }
9923    }
9924}
9925
9926/// Security attribute for functions: SECURITY DEFINER or SECURITY INVOKER.
9927///
9928/// [PostgreSQL](https://www.postgresql.org/docs/current/sql-createfunction.html)
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 FunctionSecurity {
9933    /// Execute the function with the privileges of the user who defined it.
9934    Definer,
9935    /// Execute the function with the privileges of the user who invokes it.
9936    Invoker,
9937}
9938
9939impl fmt::Display for FunctionSecurity {
9940    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9941        match self {
9942            FunctionSecurity::Definer => write!(f, "SECURITY DEFINER"),
9943            FunctionSecurity::Invoker => write!(f, "SECURITY INVOKER"),
9944        }
9945    }
9946}
9947
9948/// Value for a SET configuration parameter in a CREATE FUNCTION statement.
9949///
9950/// [PostgreSQL](https://www.postgresql.org/docs/current/sql-createfunction.html)
9951#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9952#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9953#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9954pub enum FunctionSetValue {
9955    /// SET param = DEFAULT / SET param TO DEFAULT
9956    Default,
9957    /// SET param = value1, value2, ...
9958    Values(Vec<Expr>),
9959    /// SET param FROM CURRENT
9960    FromCurrent,
9961}
9962
9963/// A SET configuration_parameter clause in a CREATE FUNCTION statement.
9964///
9965/// [PostgreSQL](https://www.postgresql.org/docs/current/sql-createfunction.html)
9966#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9967#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9968#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9969pub struct FunctionDefinitionSetParam {
9970    /// The name of the configuration parameter.
9971    pub name: ObjectName,
9972    /// The value to set for the parameter.
9973    pub value: FunctionSetValue,
9974}
9975
9976impl fmt::Display for FunctionDefinitionSetParam {
9977    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9978        write!(f, "SET {} ", self.name)?;
9979        match &self.value {
9980            FunctionSetValue::Default => write!(f, "= DEFAULT"),
9981            FunctionSetValue::Values(values) => {
9982                write!(f, "= {}", display_comma_separated(values))
9983            }
9984            FunctionSetValue::FromCurrent => write!(f, "FROM CURRENT"),
9985        }
9986    }
9987}
9988
9989/// These attributes describe the behavior of the function when called with a null argument.
9990#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9991#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9992#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9993pub enum FunctionCalledOnNull {
9994    /// Function is called even when inputs are null.
9995    CalledOnNullInput,
9996    /// Function returns null when any input is null.
9997    ReturnsNullOnNullInput,
9998    /// Function is strict about null inputs.
9999    Strict,
10000}
10001
10002impl fmt::Display for FunctionCalledOnNull {
10003    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10004        match self {
10005            FunctionCalledOnNull::CalledOnNullInput => write!(f, "CALLED ON NULL INPUT"),
10006            FunctionCalledOnNull::ReturnsNullOnNullInput => write!(f, "RETURNS NULL ON NULL INPUT"),
10007            FunctionCalledOnNull::Strict => write!(f, "STRICT"),
10008        }
10009    }
10010}
10011
10012/// If it is safe for PostgreSQL to call the function from multiple threads at once
10013#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10014#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10015#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10016pub enum FunctionParallel {
10017    /// The function is not safe to run in parallel.
10018    Unsafe,
10019    /// The function is restricted for parallel execution.
10020    Restricted,
10021    /// The function is safe to run in parallel.
10022    Safe,
10023}
10024
10025impl fmt::Display for FunctionParallel {
10026    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10027        match self {
10028            FunctionParallel::Unsafe => write!(f, "PARALLEL UNSAFE"),
10029            FunctionParallel::Restricted => write!(f, "PARALLEL RESTRICTED"),
10030            FunctionParallel::Safe => write!(f, "PARALLEL SAFE"),
10031        }
10032    }
10033}
10034
10035/// [BigQuery] Determinism specifier used in a UDF definition.
10036///
10037/// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#syntax_11
10038#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10039#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10040#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10041pub enum FunctionDeterminismSpecifier {
10042    /// Function is deterministic.
10043    Deterministic,
10044    /// Function is not deterministic.
10045    NotDeterministic,
10046}
10047
10048impl fmt::Display for FunctionDeterminismSpecifier {
10049    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10050        match self {
10051            FunctionDeterminismSpecifier::Deterministic => {
10052                write!(f, "DETERMINISTIC")
10053            }
10054            FunctionDeterminismSpecifier::NotDeterministic => {
10055                write!(f, "NOT DETERMINISTIC")
10056            }
10057        }
10058    }
10059}
10060
10061/// Represent the expression body of a `CREATE FUNCTION` statement as well as
10062/// where within the statement, the body shows up.
10063///
10064/// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#syntax_11
10065/// [PostgreSQL]: https://www.postgresql.org/docs/15/sql-createfunction.html
10066/// [MsSql]: https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql
10067#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10068#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10069#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10070pub enum CreateFunctionBody {
10071    /// A function body expression using the 'AS' keyword and shows up
10072    /// before any `OPTIONS` clause.
10073    ///
10074    /// Example:
10075    /// ```sql
10076    /// CREATE FUNCTION myfunc(x FLOAT64, y FLOAT64) RETURNS FLOAT64
10077    /// AS (x * y)
10078    /// OPTIONS(description="desc");
10079    /// ```
10080    ///
10081    /// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#syntax_11
10082    /// [PostgreSQL]: https://www.postgresql.org/docs/current/sql-createfunction.html
10083    AsBeforeOptions {
10084        /// The primary expression.
10085        body: Expr,
10086        /// Link symbol if the primary expression contains the name of shared library file.
10087        ///
10088        /// Example:
10089        /// ```sql
10090        /// CREATE FUNCTION cas_in(input cstring) RETURNS cas
10091        /// AS 'MODULE_PATHNAME', 'cas_in_wrapper'
10092        /// ```
10093        /// [PostgreSQL]: https://www.postgresql.org/docs/current/sql-createfunction.html
10094        link_symbol: Option<Expr>,
10095    },
10096    /// A function body expression using the 'AS' keyword and shows up
10097    /// after any `OPTIONS` clause.
10098    ///
10099    /// Example:
10100    /// ```sql
10101    /// CREATE FUNCTION myfunc(x FLOAT64, y FLOAT64) RETURNS FLOAT64
10102    /// OPTIONS(description="desc")
10103    /// AS (x * y);
10104    /// ```
10105    ///
10106    /// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#syntax_11
10107    AsAfterOptions(Expr),
10108    /// Function body with statements before the `RETURN` keyword.
10109    ///
10110    /// Example:
10111    /// ```sql
10112    /// CREATE FUNCTION my_scalar_udf(a INT, b INT)
10113    /// RETURNS INT
10114    /// AS
10115    /// BEGIN
10116    ///     DECLARE c INT;
10117    ///     SET c = a + b;
10118    ///     RETURN c;
10119    /// END
10120    /// ```
10121    ///
10122    /// [MsSql]: https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql
10123    AsBeginEnd(BeginEndStatements),
10124    /// Function body expression using the 'RETURN' keyword.
10125    ///
10126    /// Example:
10127    /// ```sql
10128    /// CREATE FUNCTION myfunc(a INTEGER, IN b INTEGER = 1) RETURNS INTEGER
10129    /// LANGUAGE SQL
10130    /// RETURN a + b;
10131    /// ```
10132    ///
10133    /// [PostgreSQL]: https://www.postgresql.org/docs/current/sql-createfunction.html
10134    Return(Expr),
10135
10136    /// Function body expression using the 'AS RETURN' keywords
10137    ///
10138    /// Example:
10139    /// ```sql
10140    /// CREATE FUNCTION myfunc(a INT, b INT)
10141    /// RETURNS TABLE
10142    /// AS RETURN (SELECT a + b AS sum);
10143    /// ```
10144    ///
10145    /// [MsSql]: https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql
10146    AsReturnExpr(Expr),
10147
10148    /// Function body expression using the 'AS RETURN' keywords, with an un-parenthesized SELECT query
10149    ///
10150    /// Example:
10151    /// ```sql
10152    /// CREATE FUNCTION myfunc(a INT, b INT)
10153    /// RETURNS TABLE
10154    /// AS RETURN SELECT a + b AS sum;
10155    /// ```
10156    ///
10157    /// [MsSql]: https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql?view=sql-server-ver16#select_stmt
10158    AsReturnSelect(Select),
10159}
10160
10161#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10162#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10163#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10164/// `USING` clause options for `CREATE FUNCTION` (e.g., JAR, FILE, ARCHIVE).
10165pub enum CreateFunctionUsing {
10166    /// Use a JAR file located at the given URI.
10167    Jar(String),
10168    /// Use a file located at the given URI.
10169    File(String),
10170    /// Use an archive located at the given URI.
10171    Archive(String),
10172}
10173
10174impl fmt::Display for CreateFunctionUsing {
10175    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10176        write!(f, "USING ")?;
10177        match self {
10178            CreateFunctionUsing::Jar(uri) => write!(f, "JAR '{uri}'"),
10179            CreateFunctionUsing::File(uri) => write!(f, "FILE '{uri}'"),
10180            CreateFunctionUsing::Archive(uri) => write!(f, "ARCHIVE '{uri}'"),
10181        }
10182    }
10183}
10184
10185/// `NAME = <EXPR>` arguments for DuckDB macros
10186///
10187/// See [Create Macro - DuckDB](https://duckdb.org/docs/sql/statements/create_macro)
10188/// for more details
10189#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10190#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10191#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10192pub struct MacroArg {
10193    /// The argument name.
10194    pub name: Ident,
10195    /// Optional default expression for the argument.
10196    pub default_expr: Option<Expr>,
10197}
10198
10199impl MacroArg {
10200    /// Returns an argument with name.
10201    pub fn new(name: &str) -> Self {
10202        Self {
10203            name: name.into(),
10204            default_expr: None,
10205        }
10206    }
10207}
10208
10209impl fmt::Display for MacroArg {
10210    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10211        write!(f, "{}", self.name)?;
10212        if let Some(default_expr) = &self.default_expr {
10213            write!(f, " := {default_expr}")?;
10214        }
10215        Ok(())
10216    }
10217}
10218
10219#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10220#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10221#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10222/// Definition for a DuckDB macro: either an expression or a table-producing query.
10223pub enum MacroDefinition {
10224    /// The macro is defined as an expression.
10225    Expr(Expr),
10226    /// The macro is defined as a table (query).
10227    Table(Box<Query>),
10228}
10229
10230impl fmt::Display for MacroDefinition {
10231    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10232        match self {
10233            MacroDefinition::Expr(expr) => write!(f, "{expr}")?,
10234            MacroDefinition::Table(query) => write!(f, "{query}")?,
10235        }
10236        Ok(())
10237    }
10238}
10239
10240/// Schema possible naming variants ([1]).
10241///
10242/// [1]: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#schema-definition
10243#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10244#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10245#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10246pub enum SchemaName {
10247    /// Only schema name specified: `<schema name>`.
10248    Simple(ObjectName),
10249    /// Only authorization identifier specified: `AUTHORIZATION <schema authorization identifier>`.
10250    UnnamedAuthorization(Ident),
10251    /// Both schema name and authorization identifier specified: `<schema name>  AUTHORIZATION <schema authorization identifier>`.
10252    NamedAuthorization(ObjectName, Ident),
10253}
10254
10255impl fmt::Display for SchemaName {
10256    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10257        match self {
10258            SchemaName::Simple(name) => {
10259                write!(f, "{name}")
10260            }
10261            SchemaName::UnnamedAuthorization(authorization) => {
10262                write!(f, "AUTHORIZATION {authorization}")
10263            }
10264            SchemaName::NamedAuthorization(name, authorization) => {
10265                write!(f, "{name} AUTHORIZATION {authorization}")
10266            }
10267        }
10268    }
10269}
10270
10271/// Fulltext search modifiers ([1]).
10272///
10273/// [1]: https://dev.mysql.com/doc/refman/8.0/en/fulltext-search.html#function_match
10274#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10275#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10276#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10277pub enum SearchModifier {
10278    /// `IN NATURAL LANGUAGE MODE`.
10279    InNaturalLanguageMode,
10280    /// `IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION`.
10281    InNaturalLanguageModeWithQueryExpansion,
10282    ///`IN BOOLEAN MODE`.
10283    InBooleanMode,
10284    ///`WITH QUERY EXPANSION`.
10285    WithQueryExpansion,
10286}
10287
10288impl fmt::Display for SearchModifier {
10289    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10290        match self {
10291            Self::InNaturalLanguageMode => {
10292                write!(f, "IN NATURAL LANGUAGE MODE")?;
10293            }
10294            Self::InNaturalLanguageModeWithQueryExpansion => {
10295                write!(f, "IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION")?;
10296            }
10297            Self::InBooleanMode => {
10298                write!(f, "IN BOOLEAN MODE")?;
10299            }
10300            Self::WithQueryExpansion => {
10301                write!(f, "WITH QUERY EXPANSION")?;
10302            }
10303        }
10304
10305        Ok(())
10306    }
10307}
10308
10309/// Represents a `LOCK TABLE` clause with optional alias and lock type.
10310#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10311#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10312#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10313pub struct LockTable {
10314    /// The table identifier to lock.
10315    pub table: Ident,
10316    /// Optional alias for the table.
10317    pub alias: Option<Ident>,
10318    /// The type of lock to apply to the table.
10319    pub lock_type: LockTableType,
10320}
10321
10322impl fmt::Display for LockTable {
10323    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10324        let Self {
10325            table: tbl_name,
10326            alias,
10327            lock_type,
10328        } = self;
10329
10330        write!(f, "{tbl_name} ")?;
10331        if let Some(alias) = alias {
10332            write!(f, "AS {alias} ")?;
10333        }
10334        write!(f, "{lock_type}")?;
10335        Ok(())
10336    }
10337}
10338
10339#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10340#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10341#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10342/// The type of lock used in `LOCK TABLE` statements.
10343pub enum LockTableType {
10344    /// Shared/read lock. If `local` is true, it's a local read lock.
10345    Read {
10346        /// Whether the read lock is local.
10347        local: bool,
10348    },
10349    /// Exclusive/write lock. If `low_priority` is true, the write is low priority.
10350    Write {
10351        /// Whether the write lock is low priority.
10352        low_priority: bool,
10353    },
10354}
10355
10356impl fmt::Display for LockTableType {
10357    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10358        match self {
10359            Self::Read { local } => {
10360                write!(f, "READ")?;
10361                if *local {
10362                    write!(f, " LOCAL")?;
10363                }
10364            }
10365            Self::Write { low_priority } => {
10366                if *low_priority {
10367                    write!(f, "LOW_PRIORITY ")?;
10368                }
10369                write!(f, "WRITE")?;
10370            }
10371        }
10372
10373        Ok(())
10374    }
10375}
10376
10377#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10378#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10379#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10380/// Hive-specific `SET LOCATION` helper used in some `LOAD DATA` statements.
10381pub struct HiveSetLocation {
10382    /// Whether the `SET` keyword was present.
10383    pub has_set: bool,
10384    /// The location identifier.
10385    pub location: Ident,
10386}
10387
10388impl fmt::Display for HiveSetLocation {
10389    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10390        if self.has_set {
10391            write!(f, "SET ")?;
10392        }
10393        write!(f, "LOCATION {}", self.location)
10394    }
10395}
10396
10397/// MySQL `ALTER TABLE` only  [FIRST | AFTER column_name]
10398#[allow(clippy::large_enum_variant)]
10399#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10400#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10401#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10402/// MySQL `ALTER TABLE` column position specifier: `FIRST` or `AFTER <column>`.
10403pub enum MySQLColumnPosition {
10404    /// Place the column first in the table.
10405    First,
10406    /// Place the column after the specified identifier.
10407    After(Ident),
10408}
10409
10410impl Display for MySQLColumnPosition {
10411    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10412        match self {
10413            MySQLColumnPosition::First => write!(f, "FIRST"),
10414            MySQLColumnPosition::After(ident) => {
10415                let column_name = &ident.value;
10416                write!(f, "AFTER {column_name}")
10417            }
10418        }
10419    }
10420}
10421
10422/// MySQL `CREATE VIEW` algorithm parameter: [ALGORITHM = {UNDEFINED | MERGE | TEMPTABLE}]
10423#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10424#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10425#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10426/// MySQL `CREATE VIEW` algorithm options.
10427pub enum CreateViewAlgorithm {
10428    /// `UNDEFINED` algorithm.
10429    Undefined,
10430    /// `MERGE` algorithm.
10431    Merge,
10432    /// `TEMPTABLE` algorithm.
10433    TempTable,
10434}
10435
10436impl Display for CreateViewAlgorithm {
10437    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10438        match self {
10439            CreateViewAlgorithm::Undefined => write!(f, "UNDEFINED"),
10440            CreateViewAlgorithm::Merge => write!(f, "MERGE"),
10441            CreateViewAlgorithm::TempTable => write!(f, "TEMPTABLE"),
10442        }
10443    }
10444}
10445/// MySQL `CREATE VIEW` security parameter: [SQL SECURITY { DEFINER | INVOKER }]
10446#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10447#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10448#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10449/// MySQL `CREATE VIEW` SQL SECURITY options.
10450pub enum CreateViewSecurity {
10451    /// The view runs with the privileges of the definer.
10452    Definer,
10453    /// The view runs with the privileges of the invoker.
10454    Invoker,
10455}
10456
10457impl Display for CreateViewSecurity {
10458    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10459        match self {
10460            CreateViewSecurity::Definer => write!(f, "DEFINER"),
10461            CreateViewSecurity::Invoker => write!(f, "INVOKER"),
10462        }
10463    }
10464}
10465
10466/// [MySQL] `CREATE VIEW` additional parameters
10467///
10468/// [MySQL]: https://dev.mysql.com/doc/refman/9.1/en/create-view.html
10469#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10470#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10471#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10472pub struct CreateViewParams {
10473    /// Optional view algorithm (e.g., MERGE, TEMPTABLE).
10474    pub algorithm: Option<CreateViewAlgorithm>,
10475    /// Optional definer (the security principal that will own the view).
10476    pub definer: Option<GranteeName>,
10477    /// Optional SQL SECURITY setting for the view.
10478    pub security: Option<CreateViewSecurity>,
10479}
10480
10481impl Display for CreateViewParams {
10482    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10483        let CreateViewParams {
10484            algorithm,
10485            definer,
10486            security,
10487        } = self;
10488        if let Some(algorithm) = algorithm {
10489            write!(f, "ALGORITHM = {algorithm} ")?;
10490        }
10491        if let Some(definers) = definer {
10492            write!(f, "DEFINER = {definers} ")?;
10493        }
10494        if let Some(security) = security {
10495            write!(f, "SQL SECURITY {security} ")?;
10496        }
10497        Ok(())
10498    }
10499}
10500
10501#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10502#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10503#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10504/// Key/Value, where the value is a (optionally named) list of identifiers
10505///
10506/// ```sql
10507/// UNION = (tbl_name[,tbl_name]...)
10508/// ENGINE = ReplicatedMergeTree('/table_name','{replica}', ver)
10509/// ENGINE = SummingMergeTree([columns])
10510/// ```
10511pub struct NamedParenthesizedList {
10512    /// The option key (identifier) for this named list.
10513    pub key: Ident,
10514    /// Optional secondary name associated with the key.
10515    pub name: Option<Ident>,
10516    /// The list of identifier values for the key.
10517    pub values: Vec<Ident>,
10518}
10519
10520/// Snowflake `WITH ROW ACCESS POLICY policy_name ON (identifier, ...)`
10521///
10522/// <https://docs.snowflake.com/en/sql-reference/sql/create-table>
10523/// <https://docs.snowflake.com/en/user-guide/security-row-intro>
10524#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10525#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10526#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10527pub struct RowAccessPolicy {
10528    /// The fully-qualified policy object name.
10529    pub policy: ObjectName,
10530    /// Identifiers for the columns or objects the policy applies to.
10531    pub on: Vec<Ident>,
10532}
10533
10534impl RowAccessPolicy {
10535    /// Create a new `RowAccessPolicy` for the given `policy` and `on` identifiers.
10536    pub fn new(policy: ObjectName, on: Vec<Ident>) -> Self {
10537        Self { policy, on }
10538    }
10539}
10540
10541impl Display for RowAccessPolicy {
10542    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10543        write!(
10544            f,
10545            "WITH ROW ACCESS POLICY {} ON ({})",
10546            self.policy,
10547            display_comma_separated(self.on.as_slice())
10548        )
10549    }
10550}
10551
10552/// Snowflake `[ WITH ] STORAGE LIFECYCLE POLICY <policy_name> ON ( <col_name> [ , ... ] )`
10553///
10554/// <https://docs.snowflake.com/en/sql-reference/sql/create-table>
10555#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10556#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10557#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10558pub struct StorageLifecyclePolicy {
10559    /// The fully-qualified policy object name.
10560    pub policy: ObjectName,
10561    /// Column names the policy applies to.
10562    pub on: Vec<Ident>,
10563}
10564
10565impl Display for StorageLifecyclePolicy {
10566    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10567        write!(
10568            f,
10569            "WITH STORAGE LIFECYCLE POLICY {} ON ({})",
10570            self.policy,
10571            display_comma_separated(self.on.as_slice())
10572        )
10573    }
10574}
10575
10576/// Snowflake `WITH TAG ( tag_name = '<tag_value>', ...)`
10577///
10578/// <https://docs.snowflake.com/en/sql-reference/sql/create-table>
10579#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10580#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10581#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10582pub struct Tag {
10583    /// The tag key (can be qualified).
10584    pub key: ObjectName,
10585    /// The tag value as a string.
10586    pub value: String,
10587}
10588
10589impl Tag {
10590    /// Create a new `Tag` with the given key and value.
10591    pub fn new(key: ObjectName, value: String) -> Self {
10592        Self { key, value }
10593    }
10594}
10595
10596impl Display for Tag {
10597    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10598        write!(f, "{}='{}'", self.key, self.value)
10599    }
10600}
10601
10602/// Snowflake `WITH CONTACT ( purpose = contact [ , purpose = contact ...] )`
10603///
10604/// <https://docs.snowflake.com/en/sql-reference/sql/create-database>
10605#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10606#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10607#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10608pub struct ContactEntry {
10609    /// The purpose label for the contact entry.
10610    pub purpose: String,
10611    /// The contact information associated with the purpose.
10612    pub contact: String,
10613}
10614
10615impl Display for ContactEntry {
10616    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10617        write!(f, "{} = {}", self.purpose, self.contact)
10618    }
10619}
10620
10621/// Helper to indicate if a comment includes the `=` in the display form
10622#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10623#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10624#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10625pub enum CommentDef {
10626    /// Includes `=` when printing the comment, as `COMMENT = 'comment'`
10627    /// Does not include `=` when printing the comment, as `COMMENT 'comment'`
10628    WithEq(String),
10629    /// Comment variant that omits the `=` when displayed.
10630    WithoutEq(String),
10631}
10632
10633impl Display for CommentDef {
10634    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10635        match self {
10636            CommentDef::WithEq(comment) | CommentDef::WithoutEq(comment) => write!(f, "{comment}"),
10637        }
10638    }
10639}
10640
10641/// Helper to indicate if a collection should be wrapped by a symbol in the display form
10642///
10643/// [`Display`] is implemented for every [`Vec<T>`] where `T: Display`.
10644/// The string output is a comma separated list for the vec items
10645///
10646/// # Examples
10647/// ```
10648/// # use sqlparser::ast::WrappedCollection;
10649/// let items = WrappedCollection::Parentheses(vec!["one", "two", "three"]);
10650/// assert_eq!("(one, two, three)", items.to_string());
10651///
10652/// let items = WrappedCollection::NoWrapping(vec!["one", "two", "three"]);
10653/// assert_eq!("one, two, three", items.to_string());
10654/// ```
10655#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10656#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10657#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10658pub enum WrappedCollection<T> {
10659    /// Print the collection without wrapping symbols, as `item, item, item`
10660    NoWrapping(T),
10661    /// Wraps the collection in Parentheses, as `(item, item, item)`
10662    Parentheses(T),
10663}
10664
10665impl<T> Display for WrappedCollection<Vec<T>>
10666where
10667    T: Display,
10668{
10669    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10670        match self {
10671            WrappedCollection::NoWrapping(inner) => {
10672                write!(f, "{}", display_comma_separated(inner.as_slice()))
10673            }
10674            WrappedCollection::Parentheses(inner) => {
10675                write!(f, "({})", display_comma_separated(inner.as_slice()))
10676            }
10677        }
10678    }
10679}
10680
10681/// Represents a single PostgreSQL utility option.
10682///
10683/// A utility option is a key-value pair where the key is an identifier (IDENT) and the value
10684/// can be one of the following:
10685/// - A number with an optional sign (`+` or `-`). Example: `+10`, `-10.2`, `3`
10686/// - A non-keyword string. Example: `option1`, `'option2'`, `"option3"`
10687/// - keyword: `TRUE`, `FALSE`, `ON` (`off` is also accept).
10688/// - Empty. Example: `ANALYZE` (identifier only)
10689///
10690/// Utility options are used in various PostgreSQL DDL statements, including statements such as
10691/// `CLUSTER`, `EXPLAIN`, `VACUUM`, and `REINDEX`. These statements format options as `( option [, ...] )`.
10692///
10693/// [CLUSTER](https://www.postgresql.org/docs/current/sql-cluster.html)
10694/// [EXPLAIN](https://www.postgresql.org/docs/current/sql-explain.html)
10695/// [VACUUM](https://www.postgresql.org/docs/current/sql-vacuum.html)
10696/// [REINDEX](https://www.postgresql.org/docs/current/sql-reindex.html)
10697///
10698/// For example, the `EXPLAIN` AND `VACUUM` statements with options might look like this:
10699/// ```sql
10700/// EXPLAIN (ANALYZE, VERBOSE TRUE, FORMAT TEXT) SELECT * FROM my_table;
10701///
10702/// VACUUM (VERBOSE, ANALYZE ON, PARALLEL 10) my_table;
10703/// ```
10704#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10705#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10706#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10707pub struct UtilityOption {
10708    /// The option name (identifier).
10709    pub name: Ident,
10710    /// Optional argument for the option (number, string, keyword, etc.).
10711    pub arg: Option<Expr>,
10712}
10713
10714impl Display for UtilityOption {
10715    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10716        if let Some(ref arg) = self.arg {
10717            write!(f, "{} {}", self.name, arg)
10718        } else {
10719            write!(f, "{}", self.name)
10720        }
10721    }
10722}
10723
10724/// Represents the different options available for `SHOW`
10725/// statements to filter the results. Example from Snowflake:
10726/// <https://docs.snowflake.com/en/sql-reference/sql/show-tables>
10727#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10728#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10729#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10730pub struct ShowStatementOptions {
10731    /// Optional scope to show in (for example: TABLE, SCHEMA).
10732    pub show_in: Option<ShowStatementIn>,
10733    /// Optional `STARTS WITH` filter value.
10734    pub starts_with: Option<ValueWithSpan>,
10735    /// Optional `LIMIT` expression.
10736    pub limit: Option<Expr>,
10737    /// Optional `FROM` value used with `LIMIT`.
10738    pub limit_from: Option<ValueWithSpan>,
10739    /// Optional filter position (infix or suffix) for `LIKE`/`FILTER`.
10740    pub filter_position: Option<ShowStatementFilterPosition>,
10741}
10742
10743impl Display for ShowStatementOptions {
10744    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10745        let (like_in_infix, like_in_suffix) = match &self.filter_position {
10746            Some(ShowStatementFilterPosition::Infix(filter)) => {
10747                (format!(" {filter}"), "".to_string())
10748            }
10749            Some(ShowStatementFilterPosition::Suffix(filter)) => {
10750                ("".to_string(), format!(" {filter}"))
10751            }
10752            None => ("".to_string(), "".to_string()),
10753        };
10754        write!(
10755            f,
10756            "{like_in_infix}{show_in}{starts_with}{limit}{from}{like_in_suffix}",
10757            show_in = match &self.show_in {
10758                Some(i) => format!(" {i}"),
10759                None => String::new(),
10760            },
10761            starts_with = match &self.starts_with {
10762                Some(s) => format!(" STARTS WITH {s}"),
10763                None => String::new(),
10764            },
10765            limit = match &self.limit {
10766                Some(l) => format!(" LIMIT {l}"),
10767                None => String::new(),
10768            },
10769            from = match &self.limit_from {
10770                Some(f) => format!(" FROM {f}"),
10771                None => String::new(),
10772            }
10773        )?;
10774        Ok(())
10775    }
10776}
10777
10778#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10779#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10780#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10781/// Where a `SHOW` filter appears relative to the main clause.
10782pub enum ShowStatementFilterPosition {
10783    /// Put the filter in an infix position (e.g. `SHOW COLUMNS LIKE '%name%' IN TABLE tbl`).
10784    Infix(ShowStatementFilter), // For example: SHOW COLUMNS LIKE '%name%' IN TABLE tbl
10785    /// Put the filter in a suffix position (e.g. `SHOW COLUMNS IN tbl LIKE '%name%'`).
10786    Suffix(ShowStatementFilter), // For example: SHOW COLUMNS IN tbl LIKE '%name%'
10787}
10788
10789#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10790#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10791#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10792/// Parent object types usable with `SHOW ... IN <parent>` clauses.
10793pub enum ShowStatementInParentType {
10794    /// ACCOUNT parent type for SHOW statements.
10795    Account,
10796    /// DATABASE parent type for SHOW statements.
10797    Database,
10798    /// SCHEMA parent type for SHOW statements.
10799    Schema,
10800    /// TABLE parent type for SHOW statements.
10801    Table,
10802    /// VIEW parent type for SHOW statements.
10803    View,
10804}
10805
10806impl fmt::Display for ShowStatementInParentType {
10807    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10808        match self {
10809            ShowStatementInParentType::Account => write!(f, "ACCOUNT"),
10810            ShowStatementInParentType::Database => write!(f, "DATABASE"),
10811            ShowStatementInParentType::Schema => write!(f, "SCHEMA"),
10812            ShowStatementInParentType::Table => write!(f, "TABLE"),
10813            ShowStatementInParentType::View => write!(f, "VIEW"),
10814        }
10815    }
10816}
10817
10818#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10819#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10820#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10821/// Represents a `SHOW ... IN` clause with optional parent qualifier and name.
10822pub struct ShowStatementIn {
10823    /// The clause that specifies what to show (e.g. COLUMNS, TABLES).
10824    pub clause: ShowStatementInClause,
10825    /// Optional parent type qualifier (ACCOUNT/DATABASE/...).
10826    pub parent_type: Option<ShowStatementInParentType>,
10827    /// Optional parent object name for the SHOW clause.
10828    #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
10829    pub parent_name: Option<ObjectName>,
10830}
10831
10832impl fmt::Display for ShowStatementIn {
10833    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10834        write!(f, "{}", self.clause)?;
10835        if let Some(parent_type) = &self.parent_type {
10836            write!(f, " {parent_type}")?;
10837        }
10838        if let Some(parent_name) = &self.parent_name {
10839            write!(f, " {parent_name}")?;
10840        }
10841        Ok(())
10842    }
10843}
10844
10845/// A Show Charset statement
10846#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10847#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10848#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10849pub struct ShowCharset {
10850    /// The statement can be written as `SHOW CHARSET` or `SHOW CHARACTER SET`
10851    /// true means CHARSET was used and false means CHARACTER SET was used
10852    pub is_shorthand: bool,
10853    /// Optional `LIKE`/`WHERE`-style filter for the statement.
10854    pub filter: Option<ShowStatementFilter>,
10855}
10856
10857impl fmt::Display for ShowCharset {
10858    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10859        write!(f, "SHOW")?;
10860        if self.is_shorthand {
10861            write!(f, " CHARSET")?;
10862        } else {
10863            write!(f, " CHARACTER SET")?;
10864        }
10865        if let Some(filter) = &self.filter {
10866            write!(f, " {filter}")?;
10867        }
10868        Ok(())
10869    }
10870}
10871
10872#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10873#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10874#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10875/// Options for a `SHOW OBJECTS` statement.
10876pub struct ShowObjects {
10877    /// Whether to show terse output.
10878    pub terse: bool,
10879    /// Additional options controlling the SHOW output.
10880    pub show_options: ShowStatementOptions,
10881}
10882
10883/// MSSQL's json null clause
10884///
10885/// ```plaintext
10886/// <json_null_clause> ::=
10887///       NULL ON NULL
10888///     | ABSENT ON NULL
10889/// ```
10890///
10891/// <https://learn.microsoft.com/en-us/sql/t-sql/functions/json-object-transact-sql?view=sql-server-ver16#json_null_clause>
10892#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10893#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10894#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10895pub enum JsonNullClause {
10896    /// `NULL ON NULL` behavior for JSON functions.
10897    NullOnNull,
10898    /// `ABSENT ON NULL` behavior for JSON functions.
10899    AbsentOnNull,
10900}
10901
10902impl Display for JsonNullClause {
10903    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10904        match self {
10905            JsonNullClause::NullOnNull => write!(f, "NULL ON NULL"),
10906            JsonNullClause::AbsentOnNull => write!(f, "ABSENT ON NULL"),
10907        }
10908    }
10909}
10910
10911/// PostgreSQL JSON function RETURNING clause
10912///
10913/// Example:
10914/// ```sql
10915/// JSON_OBJECT('a': 1 RETURNING jsonb)
10916/// ```
10917#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10918#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10919#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10920pub struct JsonReturningClause {
10921    /// The data type to return from the JSON function (e.g. JSON/JSONB).
10922    pub data_type: DataType,
10923}
10924
10925impl Display for JsonReturningClause {
10926    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10927        write!(f, "RETURNING {}", self.data_type)
10928    }
10929}
10930
10931/// rename object definition
10932#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10933#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10934#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10935pub struct RenameTable {
10936    /// The current name of the object to rename.
10937    pub old_name: ObjectName,
10938    /// The new name for the object.
10939    pub new_name: ObjectName,
10940}
10941
10942impl fmt::Display for RenameTable {
10943    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10944        write!(f, "{} TO {}", self.old_name, self.new_name)?;
10945        Ok(())
10946    }
10947}
10948
10949/// Represents the referenced table in an `INSERT INTO` statement
10950#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10951#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10952#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10953pub enum TableObject {
10954    /// Table specified by name.
10955    /// Example:
10956    /// ```sql
10957    /// INSERT INTO my_table
10958    /// ```
10959    TableName(#[cfg_attr(feature = "visitor", visit(with = "visit_relation"))] ObjectName),
10960
10961    /// Table specified as a function.
10962    /// Example:
10963    /// ```sql
10964    /// INSERT INTO TABLE FUNCTION remote('localhost', default.simple_table)
10965    /// ```
10966    /// [Clickhouse](https://clickhouse.com/docs/en/sql-reference/table-functions)
10967    TableFunction(Function),
10968
10969    /// Table specified through a sub-query
10970    /// Example:
10971    /// ```sql
10972    /// INSERT INTO
10973    /// (SELECT employee_id, last_name, email, hire_date, job_id,  salary, commission_pct FROM employees)
10974    /// VALUES (207, 'Gregory', 'pgregory@example.com', sysdate, 'PU_CLERK', 1.2E3, NULL);
10975    /// ```
10976    /// [Oracle](https://docs.oracle.com/en/database/oracle/oracle-database/21/sqlrf/INSERT.html#GUID-903F8043-0254-4EE9-ACC1-CB8AC0AF3423__I2126242)
10977    TableQuery(Box<Query>),
10978}
10979
10980impl fmt::Display for TableObject {
10981    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10982        match self {
10983            Self::TableName(table_name) => write!(f, "{table_name}"),
10984            Self::TableFunction(func) => write!(f, "FUNCTION {func}"),
10985            Self::TableQuery(table_query) => write!(f, "({table_query})"),
10986        }
10987    }
10988}
10989
10990/// Represents a SET SESSION AUTHORIZATION statement
10991#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10992#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10993#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10994pub struct SetSessionAuthorizationParam {
10995    /// The scope for the `SET SESSION AUTHORIZATION` (e.g., GLOBAL/SESSION).
10996    pub scope: ContextModifier,
10997    /// The specific authorization parameter kind.
10998    pub kind: SetSessionAuthorizationParamKind,
10999}
11000
11001impl fmt::Display for SetSessionAuthorizationParam {
11002    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11003        write!(f, "{}", self.kind)
11004    }
11005}
11006
11007/// Represents the parameter kind for SET SESSION AUTHORIZATION
11008#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11009#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11010#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11011pub enum SetSessionAuthorizationParamKind {
11012    /// Default authorization
11013    Default,
11014
11015    /// User name
11016    User(Ident),
11017}
11018
11019impl fmt::Display for SetSessionAuthorizationParamKind {
11020    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11021        match self {
11022            SetSessionAuthorizationParamKind::Default => write!(f, "DEFAULT"),
11023            SetSessionAuthorizationParamKind::User(name) => write!(f, "{}", name),
11024        }
11025    }
11026}
11027
11028#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11029#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11030#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11031/// Kind of session parameter being set by `SET SESSION`.
11032pub enum SetSessionParamKind {
11033    /// Generic session parameter (name/value pair).
11034    Generic(SetSessionParamGeneric),
11035    /// Identity insert related parameter.
11036    IdentityInsert(SetSessionParamIdentityInsert),
11037    /// Offsets-related parameter.
11038    Offsets(SetSessionParamOffsets),
11039    /// Statistics-related parameter.
11040    Statistics(SetSessionParamStatistics),
11041}
11042
11043impl fmt::Display for SetSessionParamKind {
11044    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11045        match self {
11046            SetSessionParamKind::Generic(x) => write!(f, "{x}"),
11047            SetSessionParamKind::IdentityInsert(x) => write!(f, "{x}"),
11048            SetSessionParamKind::Offsets(x) => write!(f, "{x}"),
11049            SetSessionParamKind::Statistics(x) => write!(f, "{x}"),
11050        }
11051    }
11052}
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))]
11057/// Generic `SET SESSION` parameter represented as name(s) and value.
11058pub struct SetSessionParamGeneric {
11059    /// Names of the session parameters being set.
11060    pub names: Vec<String>,
11061    /// The value to assign to the parameter(s).
11062    pub value: String,
11063}
11064
11065impl fmt::Display for SetSessionParamGeneric {
11066    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11067        write!(f, "{} {}", display_comma_separated(&self.names), self.value)
11068    }
11069}
11070
11071#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11072#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11073#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11074/// `IDENTITY_INSERT` session parameter for a specific object.
11075pub struct SetSessionParamIdentityInsert {
11076    /// Object name targeted by `IDENTITY_INSERT`.
11077    pub obj: ObjectName,
11078    /// Value (ON/OFF) for the identity insert setting.
11079    pub value: SessionParamValue,
11080}
11081
11082impl fmt::Display for SetSessionParamIdentityInsert {
11083    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11084        write!(f, "IDENTITY_INSERT {} {}", self.obj, self.value)
11085    }
11086}
11087
11088#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11089#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11090#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11091/// Offsets-related session parameter with keywords and a value.
11092pub struct SetSessionParamOffsets {
11093    /// Keywords specifying which offsets to modify.
11094    pub keywords: Vec<String>,
11095    /// Value (ON/OFF) for the offsets setting.
11096    pub value: SessionParamValue,
11097}
11098
11099impl fmt::Display for SetSessionParamOffsets {
11100    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11101        write!(
11102            f,
11103            "OFFSETS {} {}",
11104            display_comma_separated(&self.keywords),
11105            self.value
11106        )
11107    }
11108}
11109
11110#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11111#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11112#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11113/// Statistics-related session parameter specifying topic and value.
11114pub struct SetSessionParamStatistics {
11115    /// Statistics topic to set (IO/PROFILE/TIME/XML).
11116    pub topic: SessionParamStatsTopic,
11117    /// Value (ON/OFF) for the statistics topic.
11118    pub value: SessionParamValue,
11119}
11120
11121impl fmt::Display for SetSessionParamStatistics {
11122    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11123        write!(f, "STATISTICS {} {}", self.topic, self.value)
11124    }
11125}
11126
11127#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11128#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11129#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11130/// Topics available for session statistics configuration.
11131pub enum SessionParamStatsTopic {
11132    /// Input/output statistics.
11133    IO,
11134    /// Profile statistics.
11135    Profile,
11136    /// Time statistics.
11137    Time,
11138    /// XML-related statistics.
11139    Xml,
11140}
11141
11142impl fmt::Display for SessionParamStatsTopic {
11143    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11144        match self {
11145            SessionParamStatsTopic::IO => write!(f, "IO"),
11146            SessionParamStatsTopic::Profile => write!(f, "PROFILE"),
11147            SessionParamStatsTopic::Time => write!(f, "TIME"),
11148            SessionParamStatsTopic::Xml => write!(f, "XML"),
11149        }
11150    }
11151}
11152
11153#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11154#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11155#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11156/// Value for a session boolean-like parameter (ON/OFF).
11157pub enum SessionParamValue {
11158    /// Session parameter enabled.
11159    On,
11160    /// Session parameter disabled.
11161    Off,
11162}
11163
11164impl fmt::Display for SessionParamValue {
11165    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11166        match self {
11167            SessionParamValue::On => write!(f, "ON"),
11168            SessionParamValue::Off => write!(f, "OFF"),
11169        }
11170    }
11171}
11172
11173/// Snowflake StorageSerializationPolicy for Iceberg Tables
11174/// ```sql
11175/// [ STORAGE_SERIALIZATION_POLICY = { COMPATIBLE | OPTIMIZED } ]
11176/// ```
11177///
11178/// <https://docs.snowflake.com/en/sql-reference/sql/create-iceberg-table>
11179#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11180#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11181#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11182pub enum StorageSerializationPolicy {
11183    /// Use compatible serialization mode.
11184    Compatible,
11185    /// Use optimized serialization mode.
11186    Optimized,
11187}
11188
11189impl Display for StorageSerializationPolicy {
11190    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
11191        match self {
11192            StorageSerializationPolicy::Compatible => write!(f, "COMPATIBLE"),
11193            StorageSerializationPolicy::Optimized => write!(f, "OPTIMIZED"),
11194        }
11195    }
11196}
11197
11198/// Snowflake CatalogSyncNamespaceMode
11199/// ```sql
11200/// [ CATALOG_SYNC_NAMESPACE_MODE = { NEST | FLATTEN } ]
11201/// ```
11202///
11203/// <https://docs.snowflake.com/en/sql-reference/sql/create-database>
11204#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11205#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11206#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11207pub enum CatalogSyncNamespaceMode {
11208    /// Nest namespaces when syncing catalog.
11209    Nest,
11210    /// Flatten namespaces when syncing catalog.
11211    Flatten,
11212}
11213
11214impl Display for CatalogSyncNamespaceMode {
11215    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
11216        match self {
11217            CatalogSyncNamespaceMode::Nest => write!(f, "NEST"),
11218            CatalogSyncNamespaceMode::Flatten => write!(f, "FLATTEN"),
11219        }
11220    }
11221}
11222
11223/// Variants of the Snowflake `COPY INTO` statement
11224#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11225#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11226#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11227pub enum CopyIntoSnowflakeKind {
11228    /// Loads data from files to a table
11229    /// See: <https://docs.snowflake.com/en/sql-reference/sql/copy-into-table>
11230    Table,
11231    /// Unloads data from a table or query to external files
11232    /// See: <https://docs.snowflake.com/en/sql-reference/sql/copy-into-location>
11233    Location,
11234}
11235
11236#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11237#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11238#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11239/// `PRINT` statement for producing debug/output messages.
11240pub struct PrintStatement {
11241    /// The expression producing the message to print.
11242    pub message: Box<Expr>,
11243}
11244
11245impl fmt::Display for PrintStatement {
11246    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11247        write!(f, "PRINT {}", self.message)
11248    }
11249}
11250
11251/// The type of `WAITFOR` statement (MSSQL).
11252///
11253/// See: <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/waitfor-transact-sql>
11254#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11255#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11256#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11257pub enum WaitForType {
11258    /// `WAITFOR DELAY 'time_to_pass'`
11259    Delay,
11260    /// `WAITFOR TIME 'time_to_execute'`
11261    Time,
11262}
11263
11264impl fmt::Display for WaitForType {
11265    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11266        match self {
11267            WaitForType::Delay => write!(f, "DELAY"),
11268            WaitForType::Time => write!(f, "TIME"),
11269        }
11270    }
11271}
11272
11273/// MSSQL `WAITFOR` statement.
11274///
11275/// See: <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/waitfor-transact-sql>
11276#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11277#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11278#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11279pub struct WaitForStatement {
11280    /// `DELAY` or `TIME`.
11281    pub wait_type: WaitForType,
11282    /// The time expression.
11283    pub expr: Expr,
11284}
11285
11286impl fmt::Display for WaitForStatement {
11287    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11288        write!(f, "WAITFOR {} {}", self.wait_type, self.expr)
11289    }
11290}
11291
11292/// Represents a `Return` statement.
11293///
11294/// [MsSql triggers](https://learn.microsoft.com/en-us/sql/t-sql/statements/create-trigger-transact-sql)
11295/// [MsSql functions](https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql)
11296#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11297#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11298#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11299pub struct ReturnStatement {
11300    /// Optional return value expression.
11301    pub value: Option<ReturnStatementValue>,
11302}
11303
11304impl fmt::Display for ReturnStatement {
11305    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11306        match &self.value {
11307            Some(ReturnStatementValue::Expr(expr)) => write!(f, "RETURN {expr}"),
11308            None => write!(f, "RETURN"),
11309        }
11310    }
11311}
11312
11313/// Variants of a `RETURN` statement
11314#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11315#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11316#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11317pub enum ReturnStatementValue {
11318    /// Return an expression from a function or trigger.
11319    Expr(Expr),
11320}
11321
11322/// Represents an `OPEN` statement.
11323#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11324#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11325#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11326pub struct OpenStatement {
11327    /// Cursor name
11328    pub cursor_name: Ident,
11329}
11330
11331impl fmt::Display for OpenStatement {
11332    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11333        write!(f, "OPEN {}", self.cursor_name)
11334    }
11335}
11336
11337/// Specifies Include / Exclude NULL within UNPIVOT command.
11338/// For example
11339/// `UNPIVOT (column1 FOR new_column IN (col3, col4, col5, col6))`
11340#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11341#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11342#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11343pub enum NullInclusion {
11344    /// Include NULL values in the UNPIVOT output.
11345    IncludeNulls,
11346    /// Exclude NULL values from the UNPIVOT output.
11347    ExcludeNulls,
11348}
11349
11350impl fmt::Display for NullInclusion {
11351    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11352        match self {
11353            NullInclusion::IncludeNulls => write!(f, "INCLUDE NULLS"),
11354            NullInclusion::ExcludeNulls => write!(f, "EXCLUDE NULLS"),
11355        }
11356    }
11357}
11358
11359/// Checks membership of a value in a JSON array
11360///
11361/// Syntax:
11362/// ```sql
11363/// <value> MEMBER OF(<array>)
11364/// ```
11365/// [MySQL](https://dev.mysql.com/doc/refman/8.4/en/json-search-functions.html#operator_member-of)
11366#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11367#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11368#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11369pub struct MemberOf {
11370    /// The value to check for membership.
11371    pub value: Box<Expr>,
11372    /// The JSON array expression to check against.
11373    pub array: Box<Expr>,
11374}
11375
11376impl fmt::Display for MemberOf {
11377    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11378        write!(f, "{} MEMBER OF({})", self.value, self.array)
11379    }
11380}
11381
11382#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11383#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11384#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11385/// Represents an `EXPORT DATA` statement.
11386pub struct ExportData {
11387    /// Options for the export operation.
11388    pub options: Vec<SqlOption>,
11389    /// The query producing the data to export.
11390    pub query: Box<Query>,
11391    /// Optional named connection to use for export.
11392    pub connection: Option<ObjectName>,
11393}
11394
11395impl fmt::Display for ExportData {
11396    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11397        if let Some(connection) = &self.connection {
11398            write!(
11399                f,
11400                "EXPORT DATA WITH CONNECTION {connection} OPTIONS({}) AS {}",
11401                display_comma_separated(&self.options),
11402                self.query
11403            )
11404        } else {
11405            write!(
11406                f,
11407                "EXPORT DATA OPTIONS({}) AS {}",
11408                display_comma_separated(&self.options),
11409                self.query
11410            )
11411        }
11412    }
11413}
11414/// Creates a user
11415///
11416/// Syntax:
11417/// ```sql
11418/// CREATE [OR REPLACE] USER [IF NOT EXISTS] <name> [OPTIONS]
11419/// ```
11420///
11421/// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-user)
11422#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11423#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11424#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11425pub struct CreateUser {
11426    /// Replace existing user if present.
11427    pub or_replace: bool,
11428    /// Only create the user if it does not already exist.
11429    pub if_not_exists: bool,
11430    /// The name of the user to create.
11431    pub name: Ident,
11432    /// Key/value options for user creation.
11433    pub options: KeyValueOptions,
11434    /// Whether tags are specified using `WITH TAG`.
11435    pub with_tags: bool,
11436    /// Tags for the user.
11437    pub tags: KeyValueOptions,
11438}
11439
11440impl fmt::Display for CreateUser {
11441    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11442        write!(f, "CREATE")?;
11443        if self.or_replace {
11444            write!(f, " OR REPLACE")?;
11445        }
11446        write!(f, " USER")?;
11447        if self.if_not_exists {
11448            write!(f, " IF NOT EXISTS")?;
11449        }
11450        write!(f, " {}", self.name)?;
11451        if !self.options.options.is_empty() {
11452            write!(f, " {}", self.options)?;
11453        }
11454        if !self.tags.options.is_empty() {
11455            if self.with_tags {
11456                write!(f, " WITH")?;
11457            }
11458            write!(f, " TAG ({})", self.tags)?;
11459        }
11460        Ok(())
11461    }
11462}
11463
11464/// Modifies the properties of a user
11465///
11466/// [Snowflake Syntax:](https://docs.snowflake.com/en/sql-reference/sql/alter-user)
11467/// ```sql
11468/// ALTER USER [ IF EXISTS ] [ <name> ] [ OPTIONS ]
11469/// ```
11470///
11471/// [PostgreSQL Syntax:](https://www.postgresql.org/docs/current/sql-alteruser.html)
11472/// ```sql
11473/// ALTER USER <role_specification> [ WITH ] option [ ... ]
11474/// ```
11475#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11476#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11477#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11478pub struct AlterUser {
11479    /// Whether to only alter the user if it exists.
11480    pub if_exists: bool,
11481    /// The name of the user to alter.
11482    pub name: Ident,
11483    /// Optional new name for the user (Snowflake-specific).
11484    /// See: <https://docs.snowflake.com/en/sql-reference/sql/alter-user#syntax>
11485    pub rename_to: Option<Ident>,
11486    /// Reset the user's password.
11487    pub reset_password: bool,
11488    /// Abort all running queries for the user.
11489    pub abort_all_queries: bool,
11490    /// Optionally add a delegated role authorization.
11491    pub add_role_delegation: Option<AlterUserAddRoleDelegation>,
11492    /// Optionally remove a delegated role authorization.
11493    pub remove_role_delegation: Option<AlterUserRemoveRoleDelegation>,
11494    /// Enroll the user in MFA.
11495    pub enroll_mfa: bool,
11496    /// Set the default MFA method for the user.
11497    pub set_default_mfa_method: Option<MfaMethodKind>,
11498    /// Remove the user's default MFA method.
11499    pub remove_mfa_method: Option<MfaMethodKind>,
11500    /// Modify an MFA method for the user.
11501    pub modify_mfa_method: Option<AlterUserModifyMfaMethod>,
11502    /// Add an MFA OTP method with optional count.
11503    pub add_mfa_method_otp: Option<AlterUserAddMfaMethodOtp>,
11504    /// Set a user policy.
11505    pub set_policy: Option<AlterUserSetPolicy>,
11506    /// Unset a user policy.
11507    pub unset_policy: Option<UserPolicyKind>,
11508    /// Key/value tag options to set on the user.
11509    pub set_tag: KeyValueOptions,
11510    /// Tags to unset on the user.
11511    pub unset_tag: Vec<String>,
11512    /// Key/value properties to set on the user.
11513    pub set_props: KeyValueOptions,
11514    /// Properties to unset on the user.
11515    pub unset_props: Vec<String>,
11516    /// The following options are PostgreSQL-specific: <https://www.postgresql.org/docs/current/sql-alteruser.html>
11517    pub password: Option<AlterUserPassword>,
11518}
11519
11520/// ```sql
11521/// ALTER USER [ IF EXISTS ] [ <name> ] ADD DELEGATED AUTHORIZATION OF ROLE <role_name> TO SECURITY INTEGRATION <integration_name>
11522/// ```
11523#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11524#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11525#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11526pub struct AlterUserAddRoleDelegation {
11527    /// Role name to delegate.
11528    pub role: Ident,
11529    /// Security integration receiving the delegation.
11530    pub integration: Ident,
11531}
11532
11533/// ```sql
11534/// ALTER USER [ IF EXISTS ] [ <name> ] REMOVE DELEGATED { AUTHORIZATION OF ROLE <role_name> | AUTHORIZATIONS } FROM SECURITY INTEGRATION <integration_name>
11535/// ```
11536#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11537#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11538#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11539pub struct AlterUserRemoveRoleDelegation {
11540    /// Optional role name to remove delegation for.
11541    pub role: Option<Ident>,
11542    /// Security integration from which to remove delegation.
11543    pub integration: Ident,
11544}
11545
11546/// ```sql
11547/// ADD MFA METHOD OTP [ COUNT = number ]
11548/// ```
11549#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11550#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11551#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11552pub struct AlterUserAddMfaMethodOtp {
11553    /// Optional OTP count parameter.
11554    pub count: Option<ValueWithSpan>,
11555}
11556
11557/// ```sql
11558/// ALTER USER [ IF EXISTS ] [ <name> ] MODIFY MFA METHOD <mfa_method> SET COMMENT = '<string>'
11559/// ```
11560#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11561#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11562#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11563pub struct AlterUserModifyMfaMethod {
11564    /// The MFA method being modified.
11565    pub method: MfaMethodKind,
11566    /// The new comment for the MFA method.
11567    pub comment: String,
11568}
11569
11570/// Types of MFA methods
11571#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11572#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11573#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11574pub enum MfaMethodKind {
11575    /// PassKey (hardware or platform passkey) MFA method.
11576    PassKey,
11577    /// Time-based One-Time Password (TOTP) MFA method.
11578    Totp,
11579    /// Duo Security MFA method.
11580    Duo,
11581}
11582
11583impl fmt::Display for MfaMethodKind {
11584    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11585        match self {
11586            MfaMethodKind::PassKey => write!(f, "PASSKEY"),
11587            MfaMethodKind::Totp => write!(f, "TOTP"),
11588            MfaMethodKind::Duo => write!(f, "DUO"),
11589        }
11590    }
11591}
11592
11593/// ```sql
11594/// ALTER USER [ IF EXISTS ] [ <name> ] SET { AUTHENTICATION | PASSWORD | SESSION } POLICY <policy_name>
11595/// ```
11596#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11597#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11598#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11599pub struct AlterUserSetPolicy {
11600    /// The kind of user policy being set (authentication/password/session).
11601    pub policy_kind: UserPolicyKind,
11602    /// The identifier of the policy to apply.
11603    pub policy: Ident,
11604}
11605
11606/// Types of user-based policies
11607#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11608#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11609#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11610pub enum UserPolicyKind {
11611    /// Authentication policy.
11612    Authentication,
11613    /// Password policy.
11614    Password,
11615    /// Session policy.
11616    Session,
11617}
11618
11619impl fmt::Display for UserPolicyKind {
11620    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11621        match self {
11622            UserPolicyKind::Authentication => write!(f, "AUTHENTICATION"),
11623            UserPolicyKind::Password => write!(f, "PASSWORD"),
11624            UserPolicyKind::Session => write!(f, "SESSION"),
11625        }
11626    }
11627}
11628
11629impl fmt::Display for AlterUser {
11630    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11631        write!(f, "ALTER")?;
11632        write!(f, " USER")?;
11633        if self.if_exists {
11634            write!(f, " IF EXISTS")?;
11635        }
11636        write!(f, " {}", self.name)?;
11637        if let Some(new_name) = &self.rename_to {
11638            write!(f, " RENAME TO {new_name}")?;
11639        }
11640        if self.reset_password {
11641            write!(f, " RESET PASSWORD")?;
11642        }
11643        if self.abort_all_queries {
11644            write!(f, " ABORT ALL QUERIES")?;
11645        }
11646        if let Some(role_delegation) = &self.add_role_delegation {
11647            let role = &role_delegation.role;
11648            let integration = &role_delegation.integration;
11649            write!(
11650                f,
11651                " ADD DELEGATED AUTHORIZATION OF ROLE {role} TO SECURITY INTEGRATION {integration}"
11652            )?;
11653        }
11654        if let Some(role_delegation) = &self.remove_role_delegation {
11655            write!(f, " REMOVE DELEGATED")?;
11656            match &role_delegation.role {
11657                Some(role) => write!(f, " AUTHORIZATION OF ROLE {role}")?,
11658                None => write!(f, " AUTHORIZATIONS")?,
11659            }
11660            let integration = &role_delegation.integration;
11661            write!(f, " FROM SECURITY INTEGRATION {integration}")?;
11662        }
11663        if self.enroll_mfa {
11664            write!(f, " ENROLL MFA")?;
11665        }
11666        if let Some(method) = &self.set_default_mfa_method {
11667            write!(f, " SET DEFAULT_MFA_METHOD {method}")?
11668        }
11669        if let Some(method) = &self.remove_mfa_method {
11670            write!(f, " REMOVE MFA METHOD {method}")?;
11671        }
11672        if let Some(modify) = &self.modify_mfa_method {
11673            let method = &modify.method;
11674            let comment = &modify.comment;
11675            write!(
11676                f,
11677                " MODIFY MFA METHOD {method} SET COMMENT '{}'",
11678                value::escape_single_quote_string(comment)
11679            )?;
11680        }
11681        if let Some(add_mfa_method_otp) = &self.add_mfa_method_otp {
11682            write!(f, " ADD MFA METHOD OTP")?;
11683            if let Some(count) = &add_mfa_method_otp.count {
11684                write!(f, " COUNT = {count}")?;
11685            }
11686        }
11687        if let Some(policy) = &self.set_policy {
11688            let policy_kind = &policy.policy_kind;
11689            let name = &policy.policy;
11690            write!(f, " SET {policy_kind} POLICY {name}")?;
11691        }
11692        if let Some(policy_kind) = &self.unset_policy {
11693            write!(f, " UNSET {policy_kind} POLICY")?;
11694        }
11695        if !self.set_tag.options.is_empty() {
11696            write!(f, " SET TAG {}", self.set_tag)?;
11697        }
11698        if !self.unset_tag.is_empty() {
11699            write!(f, " UNSET TAG {}", display_comma_separated(&self.unset_tag))?;
11700        }
11701        let has_props = !self.set_props.options.is_empty();
11702        if has_props {
11703            write!(f, " SET")?;
11704            write!(f, " {}", &self.set_props)?;
11705        }
11706        if !self.unset_props.is_empty() {
11707            write!(f, " UNSET {}", display_comma_separated(&self.unset_props))?;
11708        }
11709        if let Some(password) = &self.password {
11710            write!(f, " {}", password)?;
11711        }
11712        Ok(())
11713    }
11714}
11715
11716/// ```sql
11717/// ALTER USER <role_specification> [ WITH ] PASSWORD { 'password' | NULL }``
11718/// ```
11719#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11720#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11721#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11722pub struct AlterUserPassword {
11723    /// Whether the password is encrypted.
11724    pub encrypted: bool,
11725    /// The password string, or `None` for `NULL`.
11726    pub password: Option<String>,
11727}
11728
11729impl Display for AlterUserPassword {
11730    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11731        if self.encrypted {
11732            write!(f, "ENCRYPTED ")?;
11733        }
11734        write!(f, "PASSWORD")?;
11735        match &self.password {
11736            None => write!(f, " NULL")?,
11737            Some(password) => write!(f, " '{}'", value::escape_single_quote_string(password))?,
11738        }
11739        Ok(())
11740    }
11741}
11742
11743/// Specifies how to create a new table based on an existing table's schema.
11744/// '''sql
11745/// CREATE TABLE new LIKE old ...
11746/// '''
11747#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11748#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11749#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11750pub enum CreateTableLikeKind {
11751    /// '''sql
11752    /// CREATE TABLE new (LIKE old ...)
11753    /// '''
11754    /// [Redshift](https://docs.aws.amazon.com/redshift/latest/dg/r_CREATE_TABLE_NEW.html)
11755    Parenthesized(CreateTableLike),
11756    /// '''sql
11757    /// CREATE TABLE new LIKE old ...
11758    /// '''
11759    /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-table#label-create-table-like)
11760    /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_table_like)
11761    Plain(CreateTableLike),
11762}
11763
11764#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11765#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11766#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11767/// Controls whether defaults are included when creating a table FROM/LILE another.
11768pub enum CreateTableLikeDefaults {
11769    /// Include default values from the source table.
11770    Including,
11771    /// Exclude default values from the source table.
11772    Excluding,
11773}
11774
11775impl fmt::Display for CreateTableLikeDefaults {
11776    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11777        match self {
11778            CreateTableLikeDefaults::Including => write!(f, "INCLUDING DEFAULTS"),
11779            CreateTableLikeDefaults::Excluding => write!(f, "EXCLUDING DEFAULTS"),
11780        }
11781    }
11782}
11783
11784#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11785#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11786#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11787/// Represents the `LIKE` clause of a `CREATE TABLE` statement.
11788pub struct CreateTableLike {
11789    /// The source table name to copy the schema from.
11790    pub name: ObjectName,
11791    /// Optional behavior controlling whether defaults are copied.
11792    pub defaults: Option<CreateTableLikeDefaults>,
11793}
11794
11795impl fmt::Display for CreateTableLike {
11796    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11797        write!(f, "LIKE {}", self.name)?;
11798        if let Some(defaults) = &self.defaults {
11799            write!(f, " {defaults}")?;
11800        }
11801        Ok(())
11802    }
11803}
11804
11805/// Specifies the refresh mode for the dynamic table.
11806///
11807/// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-dynamic-table)
11808#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11809#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11810#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11811pub enum RefreshModeKind {
11812    /// Automatic refresh mode (`AUTO`).
11813    Auto,
11814    /// Full refresh mode (`FULL`).
11815    Full,
11816    /// Incremental refresh mode (`INCREMENTAL`).
11817    Incremental,
11818}
11819
11820impl fmt::Display for RefreshModeKind {
11821    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11822        match self {
11823            RefreshModeKind::Auto => write!(f, "AUTO"),
11824            RefreshModeKind::Full => write!(f, "FULL"),
11825            RefreshModeKind::Incremental => write!(f, "INCREMENTAL"),
11826        }
11827    }
11828}
11829
11830/// Specifies the behavior of the initial refresh of the dynamic table.
11831///
11832/// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-dynamic-table)
11833#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11834#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11835#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11836pub enum InitializeKind {
11837    /// Initialize on creation (`ON CREATE`).
11838    OnCreate,
11839    /// Initialize on schedule (`ON SCHEDULE`).
11840    OnSchedule,
11841}
11842
11843impl fmt::Display for InitializeKind {
11844    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11845        match self {
11846            InitializeKind::OnCreate => write!(f, "ON_CREATE"),
11847            InitializeKind::OnSchedule => write!(f, "ON_SCHEDULE"),
11848        }
11849    }
11850}
11851
11852/// Re-sorts rows and reclaims space in either a specified table or all tables in the current database
11853///
11854/// '''sql
11855/// VACUUM [ FULL | SORT ONLY | DELETE ONLY | REINDEX | RECLUSTER ] [ \[ table_name \] [ TO threshold PERCENT ] \[ BOOST \] ]
11856/// '''
11857/// [Redshift](https://docs.aws.amazon.com/redshift/latest/dg/r_VACUUM_command.html)
11858#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11859#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11860#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11861pub struct VacuumStatement {
11862    /// Whether `FULL` was specified.
11863    pub full: bool,
11864    /// Whether `SORT ONLY` was specified.
11865    pub sort_only: bool,
11866    /// Whether `DELETE ONLY` was specified.
11867    pub delete_only: bool,
11868    /// Whether `REINDEX` was specified.
11869    pub reindex: bool,
11870    /// Whether `RECLUSTER` was specified.
11871    pub recluster: bool,
11872    /// Optional table to run `VACUUM` on.
11873    pub table_name: Option<ObjectName>,
11874    /// Optional threshold value (percent) for `TO threshold PERCENT`.
11875    pub threshold: Option<ValueWithSpan>,
11876    /// Whether `BOOST` was specified.
11877    pub boost: bool,
11878}
11879
11880impl fmt::Display for VacuumStatement {
11881    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11882        write!(
11883            f,
11884            "VACUUM{}{}{}{}{}",
11885            if self.full { " FULL" } else { "" },
11886            if self.sort_only { " SORT ONLY" } else { "" },
11887            if self.delete_only { " DELETE ONLY" } else { "" },
11888            if self.reindex { " REINDEX" } else { "" },
11889            if self.recluster { " RECLUSTER" } else { "" },
11890        )?;
11891        if let Some(table_name) = &self.table_name {
11892            write!(f, " {table_name}")?;
11893        }
11894        if let Some(threshold) = &self.threshold {
11895            write!(f, " TO {threshold} PERCENT")?;
11896        }
11897        if self.boost {
11898            write!(f, " BOOST")?;
11899        }
11900        Ok(())
11901    }
11902}
11903
11904/// Variants of the RESET statement
11905#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11906#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11907#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11908pub enum Reset {
11909    /// Resets all session parameters to their default values.
11910    ALL,
11911
11912    /// Resets a specific session parameter to its default value.
11913    ConfigurationParameter(ObjectName),
11914}
11915
11916/// Resets a session parameter to its default value.
11917/// ```sql
11918/// RESET { ALL | <configuration_parameter> }
11919/// ```
11920#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11921#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11922#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11923pub struct ResetStatement {
11924    /// The reset action to perform (either `ALL` or a specific configuration parameter).
11925    pub reset: Reset,
11926}
11927
11928/// Query optimizer hints are optionally supported comments after the
11929/// `SELECT`, `INSERT`, `UPDATE`, `REPLACE`, `MERGE`, and `DELETE` keywords in
11930/// the corresponding statements.
11931///
11932/// See [Select::optimizer_hints]
11933#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11934#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11935#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11936pub struct OptimizerHint {
11937    /// An optional prefix between the comment marker and `+`.
11938    ///
11939    /// Standard optimizer hints like `/*+ ... */` have an empty prefix,
11940    /// while system-specific hints like `/*abc+ ... */` have `prefix = "abc"`.
11941    /// The prefix is any sequence of ASCII alphanumeric characters
11942    /// immediately before the `+` marker.
11943    pub prefix: String,
11944    /// the raw text of the optimizer hint without its markers
11945    pub text: String,
11946    /// the style of the comment which `text` was extracted from,
11947    /// e.g. `/*+...*/` or `--+...`
11948    ///
11949    /// Not all dialects support all styles, though.
11950    pub style: OptimizerHintStyle,
11951}
11952
11953/// The commentary style of an [optimizer hint](OptimizerHint)
11954#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11955#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11956#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11957pub enum OptimizerHintStyle {
11958    /// A hint corresponding to a single line comment,
11959    /// e.g. `--+ LEADING(v.e v.d t)`
11960    SingleLine {
11961        /// the comment prefix, e.g. `--`
11962        prefix: String,
11963    },
11964    /// A hint corresponding to a multi line comment,
11965    /// e.g. `/*+ LEADING(v.e v.d t) */`
11966    MultiLine,
11967}
11968
11969impl fmt::Display for OptimizerHint {
11970    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
11971        match &self.style {
11972            OptimizerHintStyle::SingleLine { prefix } => {
11973                f.write_str(prefix)?;
11974                f.write_str(&self.prefix)?;
11975                f.write_str("+")?;
11976                f.write_str(&self.text)
11977            }
11978            OptimizerHintStyle::MultiLine => {
11979                f.write_str("/*")?;
11980                f.write_str(&self.prefix)?;
11981                f.write_str("+")?;
11982                f.write_str(&self.text)?;
11983                f.write_str("*/")
11984            }
11985        }
11986    }
11987}
11988
11989impl fmt::Display for ResetStatement {
11990    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11991        match &self.reset {
11992            Reset::ALL => write!(f, "RESET ALL"),
11993            Reset::ConfigurationParameter(param) => write!(f, "RESET {}", param),
11994        }
11995    }
11996}
11997
11998impl From<Set> for Statement {
11999    fn from(s: Set) -> Self {
12000        Self::Set(s)
12001    }
12002}
12003
12004impl From<Query> for Statement {
12005    fn from(q: Query) -> Self {
12006        Box::new(q).into()
12007    }
12008}
12009
12010impl From<Box<Query>> for Statement {
12011    fn from(q: Box<Query>) -> Self {
12012        Self::Query(q)
12013    }
12014}
12015
12016impl From<Insert> for Statement {
12017    fn from(i: Insert) -> Self {
12018        Self::Insert(i)
12019    }
12020}
12021
12022impl From<Update> for Statement {
12023    fn from(u: Update) -> Self {
12024        Self::Update(u)
12025    }
12026}
12027
12028impl From<CreateView> for Statement {
12029    fn from(cv: CreateView) -> Self {
12030        Self::CreateView(cv)
12031    }
12032}
12033
12034impl From<CreateRole> for Statement {
12035    fn from(cr: CreateRole) -> Self {
12036        Self::CreateRole(cr)
12037    }
12038}
12039
12040impl From<AlterTable> for Statement {
12041    fn from(at: AlterTable) -> Self {
12042        Self::AlterTable(at)
12043    }
12044}
12045
12046impl From<DropFunction> for Statement {
12047    fn from(df: DropFunction) -> Self {
12048        Self::DropFunction(df)
12049    }
12050}
12051
12052impl From<CreateExtension> for Statement {
12053    fn from(ce: CreateExtension) -> Self {
12054        Self::CreateExtension(ce)
12055    }
12056}
12057
12058impl From<CreateCollation> for Statement {
12059    fn from(c: CreateCollation) -> Self {
12060        Self::CreateCollation(c)
12061    }
12062}
12063
12064impl From<DropExtension> for Statement {
12065    fn from(de: DropExtension) -> Self {
12066        Self::DropExtension(de)
12067    }
12068}
12069
12070impl From<CaseStatement> for Statement {
12071    fn from(c: CaseStatement) -> Self {
12072        Self::Case(c)
12073    }
12074}
12075
12076impl From<IfStatement> for Statement {
12077    fn from(i: IfStatement) -> Self {
12078        Self::If(i)
12079    }
12080}
12081
12082impl From<WhileStatement> for Statement {
12083    fn from(w: WhileStatement) -> Self {
12084        Self::While(w)
12085    }
12086}
12087
12088impl From<RaiseStatement> for Statement {
12089    fn from(r: RaiseStatement) -> Self {
12090        Self::Raise(r)
12091    }
12092}
12093
12094impl From<ThrowStatement> for Statement {
12095    fn from(t: ThrowStatement) -> Self {
12096        Self::Throw(t)
12097    }
12098}
12099
12100impl From<Function> for Statement {
12101    fn from(f: Function) -> Self {
12102        Self::Call(f)
12103    }
12104}
12105
12106impl From<OpenStatement> for Statement {
12107    fn from(o: OpenStatement) -> Self {
12108        Self::Open(o)
12109    }
12110}
12111
12112impl From<Delete> for Statement {
12113    fn from(d: Delete) -> Self {
12114        Self::Delete(d)
12115    }
12116}
12117
12118impl From<CreateTable> for Statement {
12119    fn from(c: CreateTable) -> Self {
12120        Self::CreateTable(c)
12121    }
12122}
12123
12124impl From<CreateIndex> for Statement {
12125    fn from(c: CreateIndex) -> Self {
12126        Self::CreateIndex(c)
12127    }
12128}
12129
12130impl From<CreateServerStatement> for Statement {
12131    fn from(c: CreateServerStatement) -> Self {
12132        Self::CreateServer(c)
12133    }
12134}
12135
12136impl From<CreateConnector> for Statement {
12137    fn from(c: CreateConnector) -> Self {
12138        Self::CreateConnector(c)
12139    }
12140}
12141
12142impl From<CreateOperator> for Statement {
12143    fn from(c: CreateOperator) -> Self {
12144        Self::CreateOperator(c)
12145    }
12146}
12147
12148impl From<CreateOperatorFamily> for Statement {
12149    fn from(c: CreateOperatorFamily) -> Self {
12150        Self::CreateOperatorFamily(c)
12151    }
12152}
12153
12154impl From<CreateOperatorClass> for Statement {
12155    fn from(c: CreateOperatorClass) -> Self {
12156        Self::CreateOperatorClass(c)
12157    }
12158}
12159
12160impl From<AlterSchema> for Statement {
12161    fn from(a: AlterSchema) -> Self {
12162        Self::AlterSchema(a)
12163    }
12164}
12165
12166impl From<AlterFunction> for Statement {
12167    fn from(a: AlterFunction) -> Self {
12168        Self::AlterFunction(a)
12169    }
12170}
12171
12172impl From<AlterType> for Statement {
12173    fn from(a: AlterType) -> Self {
12174        Self::AlterType(a)
12175    }
12176}
12177
12178impl From<AlterCollation> for Statement {
12179    fn from(a: AlterCollation) -> Self {
12180        Self::AlterCollation(a)
12181    }
12182}
12183
12184impl From<AlterOperator> for Statement {
12185    fn from(a: AlterOperator) -> Self {
12186        Self::AlterOperator(a)
12187    }
12188}
12189
12190impl From<AlterOperatorFamily> for Statement {
12191    fn from(a: AlterOperatorFamily) -> Self {
12192        Self::AlterOperatorFamily(a)
12193    }
12194}
12195
12196impl From<AlterOperatorClass> for Statement {
12197    fn from(a: AlterOperatorClass) -> Self {
12198        Self::AlterOperatorClass(a)
12199    }
12200}
12201
12202impl From<Merge> for Statement {
12203    fn from(m: Merge) -> Self {
12204        Self::Merge(m)
12205    }
12206}
12207
12208impl From<AlterUser> for Statement {
12209    fn from(a: AlterUser) -> Self {
12210        Self::AlterUser(a)
12211    }
12212}
12213
12214impl From<DropDomain> for Statement {
12215    fn from(d: DropDomain) -> Self {
12216        Self::DropDomain(d)
12217    }
12218}
12219
12220impl From<ShowCharset> for Statement {
12221    fn from(s: ShowCharset) -> Self {
12222        Self::ShowCharset(s)
12223    }
12224}
12225
12226impl From<ShowObjects> for Statement {
12227    fn from(s: ShowObjects) -> Self {
12228        Self::ShowObjects(s)
12229    }
12230}
12231
12232impl From<Use> for Statement {
12233    fn from(u: Use) -> Self {
12234        Self::Use(u)
12235    }
12236}
12237
12238impl From<CreateFunction> for Statement {
12239    fn from(c: CreateFunction) -> Self {
12240        Self::CreateFunction(c)
12241    }
12242}
12243
12244impl From<CreateTrigger> for Statement {
12245    fn from(c: CreateTrigger) -> Self {
12246        Self::CreateTrigger(c)
12247    }
12248}
12249
12250impl From<DropTrigger> for Statement {
12251    fn from(d: DropTrigger) -> Self {
12252        Self::DropTrigger(d)
12253    }
12254}
12255
12256impl From<DropOperator> for Statement {
12257    fn from(d: DropOperator) -> Self {
12258        Self::DropOperator(d)
12259    }
12260}
12261
12262impl From<DropOperatorFamily> for Statement {
12263    fn from(d: DropOperatorFamily) -> Self {
12264        Self::DropOperatorFamily(d)
12265    }
12266}
12267
12268impl From<DropOperatorClass> for Statement {
12269    fn from(d: DropOperatorClass) -> Self {
12270        Self::DropOperatorClass(d)
12271    }
12272}
12273
12274impl From<DenyStatement> for Statement {
12275    fn from(d: DenyStatement) -> Self {
12276        Self::Deny(d)
12277    }
12278}
12279
12280impl From<CreateDomain> for Statement {
12281    fn from(c: CreateDomain) -> Self {
12282        Self::CreateDomain(c)
12283    }
12284}
12285
12286impl From<RenameTable> for Statement {
12287    fn from(r: RenameTable) -> Self {
12288        vec![r].into()
12289    }
12290}
12291
12292impl From<Vec<RenameTable>> for Statement {
12293    fn from(r: Vec<RenameTable>) -> Self {
12294        Self::RenameTable(r)
12295    }
12296}
12297
12298impl From<PrintStatement> for Statement {
12299    fn from(p: PrintStatement) -> Self {
12300        Self::Print(p)
12301    }
12302}
12303
12304impl From<ReturnStatement> for Statement {
12305    fn from(r: ReturnStatement) -> Self {
12306        Self::Return(r)
12307    }
12308}
12309
12310impl From<ExportData> for Statement {
12311    fn from(e: ExportData) -> Self {
12312        Self::ExportData(e)
12313    }
12314}
12315
12316impl From<CreateUser> for Statement {
12317    fn from(c: CreateUser) -> Self {
12318        Self::CreateUser(c)
12319    }
12320}
12321
12322impl From<VacuumStatement> for Statement {
12323    fn from(v: VacuumStatement) -> Self {
12324        Self::Vacuum(v)
12325    }
12326}
12327
12328impl From<ResetStatement> for Statement {
12329    fn from(r: ResetStatement) -> Self {
12330        Self::Reset(r)
12331    }
12332}
12333
12334#[cfg(test)]
12335mod tests {
12336    use crate::tokenizer::Location;
12337
12338    use super::*;
12339
12340    #[test]
12341    fn test_window_frame_default() {
12342        let window_frame = WindowFrame::default();
12343        assert_eq!(WindowFrameBound::Preceding(None), window_frame.start_bound);
12344    }
12345
12346    #[test]
12347    fn test_grouping_sets_display() {
12348        // a and b in different group
12349        let grouping_sets = Expr::GroupingSets(vec![
12350            vec![Expr::Identifier(Ident::new("a"))],
12351            vec![Expr::Identifier(Ident::new("b"))],
12352        ]);
12353        assert_eq!("GROUPING SETS ((a), (b))", format!("{grouping_sets}"));
12354
12355        // a and b in the same group
12356        let grouping_sets = Expr::GroupingSets(vec![vec![
12357            Expr::Identifier(Ident::new("a")),
12358            Expr::Identifier(Ident::new("b")),
12359        ]]);
12360        assert_eq!("GROUPING SETS ((a, b))", format!("{grouping_sets}"));
12361
12362        // (a, b) and (c, d) in different group
12363        let grouping_sets = Expr::GroupingSets(vec![
12364            vec![
12365                Expr::Identifier(Ident::new("a")),
12366                Expr::Identifier(Ident::new("b")),
12367            ],
12368            vec![
12369                Expr::Identifier(Ident::new("c")),
12370                Expr::Identifier(Ident::new("d")),
12371            ],
12372        ]);
12373        assert_eq!("GROUPING SETS ((a, b), (c, d))", format!("{grouping_sets}"));
12374    }
12375
12376    #[test]
12377    fn test_rollup_display() {
12378        let rollup = Expr::Rollup(vec![vec![Expr::Identifier(Ident::new("a"))]]);
12379        assert_eq!("ROLLUP (a)", format!("{rollup}"));
12380
12381        let rollup = Expr::Rollup(vec![vec![
12382            Expr::Identifier(Ident::new("a")),
12383            Expr::Identifier(Ident::new("b")),
12384        ]]);
12385        assert_eq!("ROLLUP ((a, b))", format!("{rollup}"));
12386
12387        let rollup = Expr::Rollup(vec![
12388            vec![Expr::Identifier(Ident::new("a"))],
12389            vec![Expr::Identifier(Ident::new("b"))],
12390        ]);
12391        assert_eq!("ROLLUP (a, b)", format!("{rollup}"));
12392
12393        let rollup = Expr::Rollup(vec![
12394            vec![Expr::Identifier(Ident::new("a"))],
12395            vec![
12396                Expr::Identifier(Ident::new("b")),
12397                Expr::Identifier(Ident::new("c")),
12398            ],
12399            vec![Expr::Identifier(Ident::new("d"))],
12400        ]);
12401        assert_eq!("ROLLUP (a, (b, c), d)", format!("{rollup}"));
12402    }
12403
12404    #[test]
12405    fn test_cube_display() {
12406        let cube = Expr::Cube(vec![vec![Expr::Identifier(Ident::new("a"))]]);
12407        assert_eq!("CUBE (a)", format!("{cube}"));
12408
12409        let cube = Expr::Cube(vec![vec![
12410            Expr::Identifier(Ident::new("a")),
12411            Expr::Identifier(Ident::new("b")),
12412        ]]);
12413        assert_eq!("CUBE ((a, b))", format!("{cube}"));
12414
12415        let cube = Expr::Cube(vec![
12416            vec![Expr::Identifier(Ident::new("a"))],
12417            vec![Expr::Identifier(Ident::new("b"))],
12418        ]);
12419        assert_eq!("CUBE (a, b)", format!("{cube}"));
12420
12421        let cube = Expr::Cube(vec![
12422            vec![Expr::Identifier(Ident::new("a"))],
12423            vec![
12424                Expr::Identifier(Ident::new("b")),
12425                Expr::Identifier(Ident::new("c")),
12426            ],
12427            vec![Expr::Identifier(Ident::new("d"))],
12428        ]);
12429        assert_eq!("CUBE (a, (b, c), d)", format!("{cube}"));
12430    }
12431
12432    #[test]
12433    fn test_interval_display() {
12434        let interval = Expr::Interval(Interval {
12435            value: Box::new(Expr::Value(
12436                Value::SingleQuotedString(String::from("123:45.67")).with_empty_span(),
12437            )),
12438            leading_field: Some(DateTimeField::Minute),
12439            leading_precision: Some(10),
12440            last_field: Some(DateTimeField::Second),
12441            fractional_seconds_precision: Some(9),
12442        });
12443        assert_eq!(
12444            "INTERVAL '123:45.67' MINUTE (10) TO SECOND (9)",
12445            format!("{interval}"),
12446        );
12447
12448        let interval = Expr::Interval(Interval {
12449            value: Box::new(Expr::Value(
12450                Value::SingleQuotedString(String::from("5")).with_empty_span(),
12451            )),
12452            leading_field: Some(DateTimeField::Second),
12453            leading_precision: Some(1),
12454            last_field: None,
12455            fractional_seconds_precision: Some(3),
12456        });
12457        assert_eq!("INTERVAL '5' SECOND (1, 3)", format!("{interval}"));
12458    }
12459
12460    #[test]
12461    fn test_one_or_many_with_parens_deref() {
12462        use core::ops::Index;
12463
12464        let one = OneOrManyWithParens::One("a");
12465
12466        assert_eq!(one.deref(), &["a"]);
12467        assert_eq!(<OneOrManyWithParens<_> as Deref>::deref(&one), &["a"]);
12468
12469        assert_eq!(one[0], "a");
12470        assert_eq!(one.index(0), &"a");
12471        assert_eq!(
12472            <<OneOrManyWithParens<_> as Deref>::Target as Index<usize>>::index(&one, 0),
12473            &"a"
12474        );
12475
12476        assert_eq!(one.len(), 1);
12477        assert_eq!(<OneOrManyWithParens<_> as Deref>::Target::len(&one), 1);
12478
12479        let many1 = OneOrManyWithParens::Many(vec!["b"]);
12480
12481        assert_eq!(many1.deref(), &["b"]);
12482        assert_eq!(<OneOrManyWithParens<_> as Deref>::deref(&many1), &["b"]);
12483
12484        assert_eq!(many1[0], "b");
12485        assert_eq!(many1.index(0), &"b");
12486        assert_eq!(
12487            <<OneOrManyWithParens<_> as Deref>::Target as Index<usize>>::index(&many1, 0),
12488            &"b"
12489        );
12490
12491        assert_eq!(many1.len(), 1);
12492        assert_eq!(<OneOrManyWithParens<_> as Deref>::Target::len(&many1), 1);
12493
12494        let many2 = OneOrManyWithParens::Many(vec!["c", "d"]);
12495
12496        assert_eq!(many2.deref(), &["c", "d"]);
12497        assert_eq!(
12498            <OneOrManyWithParens<_> as Deref>::deref(&many2),
12499            &["c", "d"]
12500        );
12501
12502        assert_eq!(many2[0], "c");
12503        assert_eq!(many2.index(0), &"c");
12504        assert_eq!(
12505            <<OneOrManyWithParens<_> as Deref>::Target as Index<usize>>::index(&many2, 0),
12506            &"c"
12507        );
12508
12509        assert_eq!(many2[1], "d");
12510        assert_eq!(many2.index(1), &"d");
12511        assert_eq!(
12512            <<OneOrManyWithParens<_> as Deref>::Target as Index<usize>>::index(&many2, 1),
12513            &"d"
12514        );
12515
12516        assert_eq!(many2.len(), 2);
12517        assert_eq!(<OneOrManyWithParens<_> as Deref>::Target::len(&many2), 2);
12518    }
12519
12520    #[test]
12521    fn test_one_or_many_with_parens_as_ref() {
12522        let one = OneOrManyWithParens::One("a");
12523
12524        assert_eq!(one.as_ref(), &["a"]);
12525        assert_eq!(<OneOrManyWithParens<_> as AsRef<_>>::as_ref(&one), &["a"]);
12526
12527        let many1 = OneOrManyWithParens::Many(vec!["b"]);
12528
12529        assert_eq!(many1.as_ref(), &["b"]);
12530        assert_eq!(<OneOrManyWithParens<_> as AsRef<_>>::as_ref(&many1), &["b"]);
12531
12532        let many2 = OneOrManyWithParens::Many(vec!["c", "d"]);
12533
12534        assert_eq!(many2.as_ref(), &["c", "d"]);
12535        assert_eq!(
12536            <OneOrManyWithParens<_> as AsRef<_>>::as_ref(&many2),
12537            &["c", "d"]
12538        );
12539    }
12540
12541    #[test]
12542    fn test_one_or_many_with_parens_ref_into_iter() {
12543        let one = OneOrManyWithParens::One("a");
12544
12545        assert_eq!(Vec::from_iter(&one), vec![&"a"]);
12546
12547        let many1 = OneOrManyWithParens::Many(vec!["b"]);
12548
12549        assert_eq!(Vec::from_iter(&many1), vec![&"b"]);
12550
12551        let many2 = OneOrManyWithParens::Many(vec!["c", "d"]);
12552
12553        assert_eq!(Vec::from_iter(&many2), vec![&"c", &"d"]);
12554    }
12555
12556    #[test]
12557    fn test_one_or_many_with_parens_value_into_iter() {
12558        use core::iter::once;
12559
12560        //tests that our iterator implemented methods behaves exactly as it's inner iterator, at every step up to n calls to next/next_back
12561        fn test_steps<I>(ours: OneOrManyWithParens<usize>, inner: I, n: usize)
12562        where
12563            I: IntoIterator<Item = usize, IntoIter: DoubleEndedIterator + Clone> + Clone,
12564        {
12565            fn checks<I>(ours: OneOrManyWithParensIntoIter<usize>, inner: I)
12566            where
12567                I: Iterator<Item = usize> + Clone + DoubleEndedIterator,
12568            {
12569                assert_eq!(ours.size_hint(), inner.size_hint());
12570                assert_eq!(ours.clone().count(), inner.clone().count());
12571
12572                assert_eq!(
12573                    ours.clone().fold(1, |a, v| a + v),
12574                    inner.clone().fold(1, |a, v| a + v)
12575                );
12576
12577                assert_eq!(Vec::from_iter(ours.clone()), Vec::from_iter(inner.clone()));
12578                assert_eq!(
12579                    Vec::from_iter(ours.clone().rev()),
12580                    Vec::from_iter(inner.clone().rev())
12581                );
12582            }
12583
12584            let mut ours_next = ours.clone().into_iter();
12585            let mut inner_next = inner.clone().into_iter();
12586
12587            for _ in 0..n {
12588                checks(ours_next.clone(), inner_next.clone());
12589
12590                assert_eq!(ours_next.next(), inner_next.next());
12591            }
12592
12593            let mut ours_next_back = ours.clone().into_iter();
12594            let mut inner_next_back = inner.clone().into_iter();
12595
12596            for _ in 0..n {
12597                checks(ours_next_back.clone(), inner_next_back.clone());
12598
12599                assert_eq!(ours_next_back.next_back(), inner_next_back.next_back());
12600            }
12601
12602            let mut ours_mixed = ours.clone().into_iter();
12603            let mut inner_mixed = inner.clone().into_iter();
12604
12605            for i in 0..n {
12606                checks(ours_mixed.clone(), inner_mixed.clone());
12607
12608                if i % 2 == 0 {
12609                    assert_eq!(ours_mixed.next_back(), inner_mixed.next_back());
12610                } else {
12611                    assert_eq!(ours_mixed.next(), inner_mixed.next());
12612                }
12613            }
12614
12615            let mut ours_mixed2 = ours.into_iter();
12616            let mut inner_mixed2 = inner.into_iter();
12617
12618            for i in 0..n {
12619                checks(ours_mixed2.clone(), inner_mixed2.clone());
12620
12621                if i % 2 == 0 {
12622                    assert_eq!(ours_mixed2.next(), inner_mixed2.next());
12623                } else {
12624                    assert_eq!(ours_mixed2.next_back(), inner_mixed2.next_back());
12625                }
12626            }
12627        }
12628
12629        test_steps(OneOrManyWithParens::One(1), once(1), 3);
12630        test_steps(OneOrManyWithParens::Many(vec![2]), vec![2], 3);
12631        test_steps(OneOrManyWithParens::Many(vec![3, 4]), vec![3, 4], 4);
12632    }
12633
12634    // Tests that the position in the code of an `Ident` does not affect its
12635    // ordering.
12636    #[test]
12637    fn test_ident_ord() {
12638        let mut a = Ident::with_span(Span::new(Location::new(1, 1), Location::new(1, 1)), "a");
12639        let mut b = Ident::with_span(Span::new(Location::new(2, 2), Location::new(2, 2)), "b");
12640
12641        assert!(a < b);
12642        std::mem::swap(&mut a.span, &mut b.span);
12643        assert!(a < b);
12644    }
12645}