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    AlterDefaultPrivileges, AlterDefaultPrivilegesAction, AlterDefaultPrivilegesObjectType,
60    AlterRoleOperation, CreateRole, Grant, ResetConfig, Revoke, RoleOption, SecondaryRoles,
61    SetConfigValue, Use,
62};
63pub use self::ddl::{
64    AccessMethodType, AggregateModifyKind, Alignment, AlterCollation, AlterCollationOperation,
65    AlterColumnOperation, AlterConnectorOwner, AlterDomain, AlterDomainOperation, AlterExtension,
66    AlterExtensionOperation, AlterFunction, AlterFunctionAction, AlterFunctionKind,
67    AlterFunctionOperation, AlterIndexOperation, AlterOperator, AlterOperatorClass,
68    AlterOperatorClassOperation, AlterOperatorFamily, AlterOperatorFamilyOperation,
69    AlterOperatorOperation, AlterPolicy, AlterPolicyOperation, AlterSchema, AlterSchemaOperation,
70    AlterTable, AlterTableAlgorithm, AlterTableLock, AlterTableOperation, AlterTableType,
71    AlterTrigger, AlterTriggerOperation, AlterType, AlterTypeAddValue, AlterTypeAddValuePosition,
72    AlterTypeOperation, AlterTypeRename, AlterTypeRenameValue, CastContext, CastFunctionKind,
73    ClusteredBy, ColumnDef, ColumnOption, ColumnOptionDef, ColumnOptions, ColumnPolicy,
74    ColumnPolicyProperty, ConstraintCharacteristics, CreateAccessMethod, CreateAggregate,
75    CreateAggregateOption, CreateCast, CreateCollation, CreateCollationDefinition, CreateConnector,
76    CreateConversion, CreateDomain, CreateEventTrigger, CreateExtension, CreateForeignDataWrapper,
77    CreateForeignTable, CreateFunction, CreateIndex, CreateLanguage, CreateOperator,
78    CreateOperatorClass, CreateOperatorFamily, CreatePolicy, CreatePolicyCommand, CreatePolicyType,
79    CreatePublication, CreateRule, CreateStatistics, CreateSubscription, CreateTable,
80    CreateTablespace, CreateTextSearchConfiguration, CreateTextSearchDictionary,
81    CreateTextSearchParser, CreateTextSearchTemplate, CreateTransform, CreateTrigger,
82    CreateUserMapping, CreateView, Deduplicate, DeferrableInitial, DistStyle, DropBehavior,
83    DropExtension, DropFunction, DropOperator, DropOperatorClass, DropOperatorFamily,
84    DropOperatorSignature, DropPolicy, DropTrigger, EventTriggerEvent, FdwRoutineClause, ForValues,
85    FunctionReturnType, GeneratedAs, GeneratedExpressionMode, IdentityParameters, IdentityProperty,
86    IdentityPropertyFormatKind, IdentityPropertyKind, IdentityPropertyOrder, IndexColumn,
87    IndexOption, IndexType, KeyOrIndexDisplay, Msck, NullsDistinctOption, OperatorArgTypes,
88    OperatorClassItem, OperatorFamilyDropItem, OperatorFamilyItem, OperatorOption, OperatorPurpose,
89    Owner, Partition, PartitionBoundValue, ProcedureParam, PublicationTarget, ReferentialAction,
90    RenameTableNameKind, ReplicaIdentity, RuleAction, RuleEvent, SecurityLabel,
91    SecurityLabelObjectKind, StatisticsKind, TagsColumnOption, TransformElement, TriggerObjectKind,
92    Truncate, UserDefinedTypeCompositeAttributeDef, UserDefinedTypeInternalLength,
93    UserDefinedTypeRangeOption, UserDefinedTypeRepresentation, UserDefinedTypeSqlDefinitionOption,
94    UserDefinedTypeStorage, UserMappingUser, ViewColumnDef,
95};
96pub use self::dml::{
97    Delete, Insert, Merge, MergeAction, MergeClause, MergeClauseKind, MergeInsertExpr,
98    MergeInsertKind, MergeUpdateExpr, MultiTableInsertIntoClause, MultiTableInsertType,
99    MultiTableInsertValue, MultiTableInsertValues, MultiTableInsertWhenClause, OutputClause,
100    Update,
101};
102pub use self::operator::{BinaryOperator, UnaryOperator};
103pub use self::query::{
104    AfterMatchSkip, ConnectByKind, Cte, CteAsMaterialized, Distinct, EmptyMatchesMode,
105    ExceptSelectItem, ExcludeSelectItem, ExprWithAlias, ExprWithAliasAndOrderBy, Fetch, ForClause,
106    ForJson, ForXml, FormatClause, GroupByExpr, GroupByWithModifier, IdentWithAlias,
107    IlikeSelectItem, InputFormatClause, Interpolate, InterpolateExpr, Join, JoinConstraint,
108    JoinOperator, JsonTableColumn, JsonTableColumnErrorHandling, JsonTableNamedColumn,
109    JsonTableNestedColumn, LateralView, LimitClause, LockClause, LockType, MatchRecognizePattern,
110    MatchRecognizeSymbol, Measure, NamedWindowDefinition, NamedWindowExpr, NonBlock, Offset,
111    OffsetRows, OpenJsonTableColumn, OrderBy, OrderByExpr, OrderByKind, OrderByOptions,
112    PipeOperator, PivotValueSource, ProjectionSelect, Query, RenameSelectItem,
113    RepetitionQuantifier, ReplaceSelectElement, ReplaceSelectItem, RowsPerMatch, Select,
114    SelectFlavor, SelectInto, SelectItem, SelectItemQualifiedWildcardKind, SelectModifiers,
115    SetExpr, SetOperator, SetQuantifier, Setting, SymbolDefinition, Table, TableAlias,
116    TableAliasColumnDef, TableFactor, TableFunctionArgs, TableIndexHintForClause,
117    TableIndexHintType, TableIndexHints, TableIndexType, TableSample, TableSampleBucket,
118    TableSampleKind, TableSampleMethod, TableSampleModifier, TableSampleQuantity, TableSampleSeed,
119    TableSampleSeedModifier, TableSampleUnit, TableVersion, TableWithJoins, Top, TopQuantity,
120    UpdateTableFromKind, ValueTableMode, Values, WildcardAdditionalOptions, With, WithFill,
121    XmlNamespaceDefinition, XmlPassingArgument, XmlPassingClause, XmlTableColumn,
122    XmlTableColumnOption,
123};
124
125pub use self::trigger::{
126    TriggerEvent, TriggerExecBody, TriggerExecBodyType, TriggerObject, TriggerPeriod,
127    TriggerReferencing, TriggerReferencingType,
128};
129
130pub use self::value::{
131    escape_double_quote_string, escape_quoted_string, DateTimeField, DollarQuotedString,
132    NormalizationForm, QuoteDelimitedString, TrimWhereField, Value, ValueWithSpan,
133};
134
135use crate::ast::helpers::key_value_options::KeyValueOptions;
136use crate::ast::helpers::stmt_data_loading::StageParamsObject;
137
138#[cfg(feature = "visitor")]
139pub use visitor::*;
140
141pub use self::data_type::GeometricTypeKind;
142
143mod data_type;
144mod dcl;
145mod ddl;
146mod dml;
147/// Helper modules for building and manipulating AST nodes.
148pub mod helpers;
149pub mod table_constraints;
150pub use table_constraints::{
151    CheckConstraint, ConstraintUsingIndex, ExclusionConstraint, ExclusionElement,
152    ForeignKeyConstraint, FullTextOrSpatialConstraint, IndexConstraint, PrimaryKeyConstraint,
153    TableConstraint, UniqueConstraint,
154};
155mod operator;
156mod query;
157mod spans;
158pub use spans::Spanned;
159
160pub mod comments;
161mod trigger;
162mod value;
163
164#[cfg(feature = "visitor")]
165mod visitor;
166
167/// Helper used to format a slice using a separator string (e.g., `", "`).
168pub struct DisplaySeparated<'a, T>
169where
170    T: fmt::Display,
171{
172    slice: &'a [T],
173    sep: &'static str,
174}
175
176impl<T> fmt::Display for DisplaySeparated<'_, T>
177where
178    T: fmt::Display,
179{
180    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
181        let mut delim = "";
182        for t in self.slice {
183            f.write_str(delim)?;
184            delim = self.sep;
185            t.fmt(f)?;
186        }
187        Ok(())
188    }
189}
190
191pub(crate) fn display_separated<'a, T>(slice: &'a [T], sep: &'static str) -> DisplaySeparated<'a, T>
192where
193    T: fmt::Display,
194{
195    DisplaySeparated { slice, sep }
196}
197
198pub(crate) fn display_comma_separated<T>(slice: &[T]) -> DisplaySeparated<'_, T>
199where
200    T: fmt::Display,
201{
202    DisplaySeparated { slice, sep: ", " }
203}
204
205/// Writes the given statements to the formatter, each ending with
206/// a semicolon and space separated.
207fn format_statement_list(f: &mut fmt::Formatter, statements: &[Statement]) -> fmt::Result {
208    write!(f, "{}", display_separated(statements, "; "))?;
209    // We manually insert semicolon for the last statement,
210    // since display_separated doesn't handle that case.
211    write!(f, ";")
212}
213
214/// An identifier, decomposed into its value or character data and the quote style.
215#[derive(Debug, Clone)]
216#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
217#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
218pub struct Ident {
219    /// The value of the identifier without quotes.
220    pub value: String,
221    /// The starting quote if any. Valid quote characters are the single quote,
222    /// double quote, backtick, and opening square bracket.
223    pub quote_style: Option<char>,
224    /// The span of the identifier in the original SQL string.
225    pub span: Span,
226}
227
228impl PartialEq for Ident {
229    fn eq(&self, other: &Self) -> bool {
230        let Ident {
231            value,
232            quote_style,
233            // exhaustiveness check; we ignore spans in comparisons
234            span: _,
235        } = self;
236
237        value == &other.value && quote_style == &other.quote_style
238    }
239}
240
241impl core::hash::Hash for Ident {
242    fn hash<H: hash::Hasher>(&self, state: &mut H) {
243        let Ident {
244            value,
245            quote_style,
246            // exhaustiveness check; we ignore spans in hashes
247            span: _,
248        } = self;
249
250        value.hash(state);
251        quote_style.hash(state);
252    }
253}
254
255impl Eq for Ident {}
256
257impl PartialOrd for Ident {
258    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
259        Some(self.cmp(other))
260    }
261}
262
263impl Ord for Ident {
264    fn cmp(&self, other: &Self) -> Ordering {
265        let Ident {
266            value,
267            quote_style,
268            // exhaustiveness check; we ignore spans in ordering
269            span: _,
270        } = self;
271
272        let Ident {
273            value: other_value,
274            quote_style: other_quote_style,
275            // exhaustiveness check; we ignore spans in ordering
276            span: _,
277        } = other;
278
279        // First compare by value, then by quote_style
280        value
281            .cmp(other_value)
282            .then_with(|| quote_style.cmp(other_quote_style))
283    }
284}
285
286impl Ident {
287    /// Create a new identifier with the given value and no quotes and an empty span.
288    pub fn new<S>(value: S) -> Self
289    where
290        S: Into<String>,
291    {
292        Ident {
293            value: value.into(),
294            quote_style: None,
295            span: Span::empty(),
296        }
297    }
298
299    /// Create a new quoted identifier with the given quote and value. This function
300    /// panics if the given quote is not a valid quote character.
301    pub fn with_quote<S>(quote: char, value: S) -> Self
302    where
303        S: Into<String>,
304    {
305        assert!(quote == '\'' || quote == '"' || quote == '`' || quote == '[');
306        Ident {
307            value: value.into(),
308            quote_style: Some(quote),
309            span: Span::empty(),
310        }
311    }
312
313    /// Create an `Ident` with the given `span` and `value` (unquoted).
314    pub fn with_span<S>(span: Span, value: S) -> Self
315    where
316        S: Into<String>,
317    {
318        Ident {
319            value: value.into(),
320            quote_style: None,
321            span,
322        }
323    }
324
325    /// Create a quoted `Ident` with the given `quote` and `span`.
326    pub fn with_quote_and_span<S>(quote: char, span: Span, value: S) -> Self
327    where
328        S: Into<String>,
329    {
330        assert!(quote == '\'' || quote == '"' || quote == '`' || quote == '[');
331        Ident {
332            value: value.into(),
333            quote_style: Some(quote),
334            span,
335        }
336    }
337}
338
339impl From<&str> for Ident {
340    fn from(value: &str) -> Self {
341        Ident {
342            value: value.to_string(),
343            quote_style: None,
344            span: Span::empty(),
345        }
346    }
347}
348
349impl fmt::Display for Ident {
350    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
351        match self.quote_style {
352            Some(q) if q == '"' || q == '\'' || q == '`' => {
353                let escaped = value::escape_quoted_string(&self.value, q);
354                write!(f, "{q}{escaped}{q}")
355            }
356            Some('[') => write!(f, "[{}]", self.value),
357            None => f.write_str(&self.value),
358            _ => panic!("unexpected quote style"),
359        }
360    }
361}
362
363/// A name of a table, view, custom type, etc., possibly multi-part, i.e. db.schema.obj
364#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
365#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
366#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
367pub struct ObjectName(pub Vec<ObjectNamePart>);
368
369impl From<Vec<Ident>> for ObjectName {
370    fn from(idents: Vec<Ident>) -> Self {
371        ObjectName(idents.into_iter().map(ObjectNamePart::Identifier).collect())
372    }
373}
374
375impl From<Ident> for ObjectName {
376    fn from(ident: Ident) -> Self {
377        ObjectName(vec![ObjectNamePart::Identifier(ident)])
378    }
379}
380
381impl fmt::Display for ObjectName {
382    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
383        write!(f, "{}", display_separated(&self.0, "."))
384    }
385}
386
387/// A single part of an ObjectName
388#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
389#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
390#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
391pub enum ObjectNamePart {
392    /// A single identifier part, e.g. `schema` or `table`.
393    Identifier(Ident),
394    /// A function that returns an identifier (dialect-specific).
395    Function(ObjectNamePartFunction),
396}
397
398impl ObjectNamePart {
399    /// Return the identifier if this is an `Identifier` variant.
400    pub fn as_ident(&self) -> Option<&Ident> {
401        match self {
402            ObjectNamePart::Identifier(ident) => Some(ident),
403            ObjectNamePart::Function(_) => None,
404        }
405    }
406}
407
408impl fmt::Display for ObjectNamePart {
409    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
410        match self {
411            ObjectNamePart::Identifier(ident) => write!(f, "{ident}"),
412            ObjectNamePart::Function(func) => write!(f, "{func}"),
413        }
414    }
415}
416
417/// An object name part that consists of a function that dynamically
418/// constructs identifiers.
419///
420/// - [Snowflake](https://docs.snowflake.com/en/sql-reference/identifier-literal)
421#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
422#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
423#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
424pub struct ObjectNamePartFunction {
425    /// The function name that produces the object name part.
426    pub name: Ident,
427    /// Function arguments used to compute the identifier.
428    pub args: Vec<FunctionArg>,
429}
430
431impl fmt::Display for ObjectNamePartFunction {
432    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
433        write!(f, "{}(", self.name)?;
434        write!(f, "{})", display_comma_separated(&self.args))
435    }
436}
437
438/// Represents an Array Expression, either
439/// `ARRAY[..]`, or `[..]`
440#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
441#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
442#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
443pub struct Array {
444    /// The list of expressions between brackets
445    pub elem: Vec<Expr>,
446
447    /// `true` for  `ARRAY[..]`, `false` for `[..]`
448    pub named: bool,
449}
450
451impl fmt::Display for Array {
452    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
453        write!(
454            f,
455            "{}[{}]",
456            if self.named { "ARRAY" } else { "" },
457            display_comma_separated(&self.elem)
458        )
459    }
460}
461
462/// Represents an INTERVAL expression, roughly in the following format:
463/// `INTERVAL '<value>' [ <leading_field> [ (<leading_precision>) ] ]
464/// [ TO <last_field> [ (<fractional_seconds_precision>) ] ]`,
465/// e.g. `INTERVAL '123:45.67' MINUTE(3) TO SECOND(2)`.
466///
467/// The parser does not validate the `<value>`, nor does it ensure
468/// that the `<leading_field>` units >= the units in `<last_field>`,
469/// so the user will have to reject intervals like `HOUR TO YEAR`.
470#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
471#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
472#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
473pub struct Interval {
474    /// The interval value expression (commonly a string literal).
475    pub value: Box<Expr>,
476    /// Optional leading time unit (e.g., `HOUR`, `MINUTE`).
477    pub leading_field: Option<DateTimeField>,
478    /// Optional leading precision for the leading field.
479    pub leading_precision: Option<u64>,
480    /// Optional trailing time unit for a range (e.g., `SECOND`).
481    pub last_field: Option<DateTimeField>,
482    /// The fractional seconds precision, when specified.
483    ///
484    /// See SQL `SECOND(n)` or `SECOND(m, n)` forms.
485    pub fractional_seconds_precision: Option<u64>,
486}
487
488impl fmt::Display for Interval {
489    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
490        let value = self.value.as_ref();
491        match (
492            &self.leading_field,
493            self.leading_precision,
494            self.fractional_seconds_precision,
495        ) {
496            (
497                Some(DateTimeField::Second),
498                Some(leading_precision),
499                Some(fractional_seconds_precision),
500            ) => {
501                // When the leading field is SECOND, the parser guarantees that
502                // the last field is None.
503                assert!(self.last_field.is_none());
504                write!(
505                    f,
506                    "INTERVAL {value} SECOND ({leading_precision}, {fractional_seconds_precision})"
507                )
508            }
509            _ => {
510                write!(f, "INTERVAL {value}")?;
511                if let Some(leading_field) = &self.leading_field {
512                    write!(f, " {leading_field}")?;
513                }
514                if let Some(leading_precision) = self.leading_precision {
515                    write!(f, " ({leading_precision})")?;
516                }
517                if let Some(last_field) = &self.last_field {
518                    write!(f, " TO {last_field}")?;
519                }
520                if let Some(fractional_seconds_precision) = self.fractional_seconds_precision {
521                    write!(f, " ({fractional_seconds_precision})")?;
522                }
523                Ok(())
524            }
525        }
526    }
527}
528
529/// A field definition within a struct
530///
531/// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-types#struct_type
532#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
533#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
534#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
535pub struct StructField {
536    /// Optional name of the struct field.
537    pub field_name: Option<Ident>,
538    /// The field data type.
539    pub field_type: DataType,
540    /// Struct field options (e.g., `OPTIONS(...)` on BigQuery).
541    /// See [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#column_name_and_column_schema)
542    pub options: Option<Vec<SqlOption>>,
543}
544
545impl fmt::Display for StructField {
546    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
547        if let Some(name) = &self.field_name {
548            write!(f, "{name} {}", self.field_type)?;
549        } else {
550            write!(f, "{}", self.field_type)?;
551        }
552        if let Some(options) = &self.options {
553            write!(f, " OPTIONS({})", display_separated(options, ", "))
554        } else {
555            Ok(())
556        }
557    }
558}
559
560/// A field definition within a union
561///
562/// [DuckDB]: https://duckdb.org/docs/sql/data_types/union.html
563#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
564#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
565#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
566pub struct UnionField {
567    /// Name of the union field.
568    pub field_name: Ident,
569    /// Type of the union field.
570    pub field_type: DataType,
571}
572
573impl fmt::Display for UnionField {
574    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
575        write!(f, "{} {}", self.field_name, self.field_type)
576    }
577}
578
579/// A dictionary field within a dictionary.
580///
581/// [DuckDB]: https://duckdb.org/docs/sql/data_types/struct#creating-structs
582#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
583#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
584#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
585pub struct DictionaryField {
586    /// Dictionary key identifier.
587    pub key: Ident,
588    /// Value expression for the dictionary entry.
589    pub value: Box<Expr>,
590}
591
592impl fmt::Display for DictionaryField {
593    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
594        write!(f, "{}: {}", self.key, self.value)
595    }
596}
597
598/// Represents a Map expression.
599#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
600#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
601#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
602pub struct Map {
603    /// Entries of the map as key/value pairs.
604    pub entries: Vec<MapEntry>,
605}
606
607impl Display for Map {
608    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
609        write!(f, "MAP {{{}}}", display_comma_separated(&self.entries))
610    }
611}
612
613/// A map field within a map.
614///
615/// [DuckDB]: https://duckdb.org/docs/sql/data_types/map.html#creating-maps
616#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
617#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
618#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
619pub struct MapEntry {
620    /// Key expression of the map entry.
621    pub key: Box<Expr>,
622    /// Value expression of the map entry.
623    pub value: Box<Expr>,
624}
625
626impl fmt::Display for MapEntry {
627    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
628        write!(f, "{}: {}", self.key, self.value)
629    }
630}
631
632/// Options for `CAST` / `TRY_CAST`
633/// BigQuery: <https://cloud.google.com/bigquery/docs/reference/standard-sql/format-elements#formatting_syntax>
634#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
635#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
636#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
637pub enum CastFormat {
638    /// A simple cast format specified by a `Value`.
639    Value(ValueWithSpan),
640    /// A cast format with an explicit time zone: `(format, timezone)`.
641    ValueAtTimeZone(ValueWithSpan, ValueWithSpan),
642}
643
644/// An element of a JSON path.
645#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
646#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
647#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
648pub enum JsonPathElem {
649    /// Accesses an object field using dot notation, e.g. `obj:foo.bar.baz`.
650    ///
651    /// See <https://docs.snowflake.com/en/user-guide/querying-semistructured#dot-notation>.
652    Dot {
653        /// The object key text (without quotes).
654        key: String,
655        /// `true` when the key was quoted in the source.
656        quoted: bool,
657    },
658    /// Accesses an object field or array element using bracket notation,
659    /// e.g. `obj['foo']`.
660    ///
661    /// See <https://docs.snowflake.com/en/user-guide/querying-semistructured#bracket-notation>.
662    Bracket {
663        /// The expression used as the bracket key (string or numeric expression).
664        key: Expr,
665    },
666    /// Access an object field using colon bracket notation
667    /// e.g. `obj:['foo']`
668    ///
669    /// See <https://docs.databricks.com/en/sql/language-manual/functions/colonsign.html>
670    ColonBracket {
671        /// The expression used as the bracket key (string or numeric expression).
672        key: Expr,
673    },
674}
675
676/// A JSON path.
677///
678/// See <https://docs.snowflake.com/en/user-guide/querying-semistructured>.
679/// See <https://docs.databricks.com/en/sql/language-manual/sql-ref-json-path-expression.html>.
680#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
681#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
682#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
683pub struct JsonPath {
684    /// Sequence of path elements that form the JSON path.
685    pub path: Vec<JsonPathElem>,
686}
687
688impl fmt::Display for JsonPath {
689    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
690        for (i, elem) in self.path.iter().enumerate() {
691            match elem {
692                JsonPathElem::Dot { key, quoted } => {
693                    if i == 0 {
694                        write!(f, ":")?;
695                    } else {
696                        write!(f, ".")?;
697                    }
698
699                    if *quoted {
700                        write!(f, "\"{}\"", escape_double_quote_string(key))?;
701                    } else {
702                        write!(f, "{key}")?;
703                    }
704                }
705                JsonPathElem::Bracket { key } => {
706                    write!(f, "[{key}]")?;
707                }
708                JsonPathElem::ColonBracket { key } => {
709                    write!(f, ":[{key}]")?;
710                }
711            }
712        }
713        Ok(())
714    }
715}
716
717/// The syntax used for in a cast expression.
718#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
719#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
720#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
721pub enum CastKind {
722    /// The standard SQL cast syntax, e.g. `CAST(<expr> as <datatype>)`
723    Cast,
724    /// A cast that returns `NULL` on failure, e.g. `TRY_CAST(<expr> as <datatype>)`.
725    ///
726    /// See <https://docs.snowflake.com/en/sql-reference/functions/try_cast>.
727    /// See <https://learn.microsoft.com/en-us/sql/t-sql/functions/try-cast-transact-sql>.
728    TryCast,
729    /// A cast that returns `NULL` on failure, bigQuery-specific ,  e.g. `SAFE_CAST(<expr> as <datatype>)`.
730    ///
731    /// See <https://cloud.google.com/bigquery/docs/reference/standard-sql/functions-and-operators#safe_casting>.
732    SafeCast,
733    /// `<expr> :: <datatype>`
734    DoubleColon,
735}
736
737/// `MATCH` type for constraint references
738///
739/// See: <https://www.postgresql.org/docs/current/sql-createtable.html#SQL-CREATETABLE-PARMS-REFERENCES>
740#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
741#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
742#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
743pub enum ConstraintReferenceMatchKind {
744    /// `MATCH FULL`
745    Full,
746    /// `MATCH PARTIAL`
747    Partial,
748    /// `MATCH SIMPLE`
749    Simple,
750}
751
752impl fmt::Display for ConstraintReferenceMatchKind {
753    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
754        match self {
755            Self::Full => write!(f, "MATCH FULL"),
756            Self::Partial => write!(f, "MATCH PARTIAL"),
757            Self::Simple => write!(f, "MATCH SIMPLE"),
758        }
759    }
760}
761
762/// `EXTRACT` syntax variants.
763///
764/// In Snowflake dialect, the `EXTRACT` expression can support either the `from` syntax
765/// or the comma syntax.
766///
767/// See <https://docs.snowflake.com/en/sql-reference/functions/extract>
768#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
769#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
770#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
771pub enum ExtractSyntax {
772    /// `EXTRACT( <date_or_time_part> FROM <date_or_time_expr> )`
773    From,
774    /// `EXTRACT( <date_or_time_part> , <date_or_timestamp_expr> )`
775    Comma,
776}
777
778/// The syntax used in a CEIL or FLOOR expression.
779///
780/// The `CEIL/FLOOR(<datetime value expression> TO <time unit>)` is an Amazon Kinesis Data Analytics extension.
781/// See <https://docs.aws.amazon.com/kinesisanalytics/latest/sqlref/sql-reference-ceil.html> for
782/// details.
783///
784/// Other dialects either support `CEIL/FLOOR( <expr> [, <scale>])` format or just
785/// `CEIL/FLOOR(<expr>)`.
786#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
787#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
788#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
789pub enum CeilFloorKind {
790    /// `CEIL( <expr> TO <DateTimeField>)`
791    DateTimeField(DateTimeField),
792    /// `CEIL( <expr> [, <scale>])`
793    Scale(ValueWithSpan),
794}
795
796/// A WHEN clause in a CASE expression containing both
797/// the condition and its corresponding result
798#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
799#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
800#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
801pub struct CaseWhen {
802    /// The `WHEN` condition expression.
803    pub condition: Expr,
804    /// The expression returned when `condition` matches.
805    pub result: Expr,
806}
807
808impl fmt::Display for CaseWhen {
809    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
810        f.write_str("WHEN ")?;
811        self.condition.fmt(f)?;
812        f.write_str(" THEN")?;
813        SpaceOrNewline.fmt(f)?;
814        Indent(&self.result).fmt(f)?;
815        Ok(())
816    }
817}
818
819/// An SQL expression of any type.
820///
821/// # Semantics / Type Checking
822///
823/// The parser does not distinguish between expressions of different types
824/// (e.g. boolean vs string). The caller is responsible for detecting and
825/// validating types as necessary (for example  `WHERE 1` vs `SELECT 1=1`)
826/// See the [README.md] for more details.
827///
828/// [README.md]: https://github.com/apache/datafusion-sqlparser-rs/blob/main/README.md#syntax-vs-semantics
829///
830/// # Equality and Hashing Does not Include Source Locations
831///
832/// The `Expr` type implements `PartialEq` and `Eq` based on the semantic value
833/// of the expression (not bitwise comparison). This means that `Expr` instances
834/// that are semantically equivalent but have different spans (locations in the
835/// source tree) will compare as equal.
836#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
837#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
838#[cfg_attr(
839    feature = "visitor",
840    derive(Visit, VisitMut),
841    visit(with = "visit_expr")
842)]
843pub enum Expr {
844    /// Identifier e.g. table name or column name
845    Identifier(Ident),
846    /// Multi-part identifier, e.g. `table_alias.column` or `schema.table.col`
847    CompoundIdentifier(Vec<Ident>),
848    /// Multi-part expression access.
849    ///
850    /// This structure represents an access chain in structured / nested types
851    /// such as maps, arrays, and lists:
852    /// - Array
853    ///     - A 1-dim array `a[1]` will be represented like:
854    ///       `CompoundFieldAccess(Ident('a'), vec![Subscript(1)]`
855    ///     - A 2-dim array `a[1][2]` will be represented like:
856    ///       `CompoundFieldAccess(Ident('a'), vec![Subscript(1), Subscript(2)]`
857    /// - Map or Struct (Bracket-style)
858    ///     - A map `a['field1']` will be represented like:
859    ///       `CompoundFieldAccess(Ident('a'), vec![Subscript('field')]`
860    ///     - A 2-dim map `a['field1']['field2']` will be represented like:
861    ///       `CompoundFieldAccess(Ident('a'), vec![Subscript('field1'), Subscript('field2')]`
862    /// - Struct (Dot-style) (only effect when the chain contains both subscript and expr)
863    ///     - A struct access `a[field1].field2` will be represented like:
864    ///       `CompoundFieldAccess(Ident('a'), vec![Subscript('field1'), Ident('field2')]`
865    /// - If a struct access likes `a.field1.field2`, it will be represented by CompoundIdentifier([a, field1, field2])
866    CompoundFieldAccess {
867        /// The base expression being accessed.
868        root: Box<Expr>,
869        /// Sequence of access operations (subscript or identifier accesses).
870        access_chain: Vec<AccessExpr>,
871    },
872    /// Access data nested in a value containing semi-structured data, such as
873    /// the `VARIANT` type on Snowflake. for example `src:customer[0].name`.
874    ///
875    /// See <https://docs.snowflake.com/en/user-guide/querying-semistructured>.
876    /// See <https://docs.databricks.com/en/sql/language-manual/functions/colonsign.html>.
877    JsonAccess {
878        /// The value being queried.
879        value: Box<Expr>,
880        /// The path to the data to extract.
881        path: JsonPath,
882    },
883    /// `IS FALSE` operator
884    IsFalse(Box<Expr>),
885    /// `IS NOT FALSE` operator
886    IsNotFalse(Box<Expr>),
887    /// `IS TRUE` operator
888    IsTrue(Box<Expr>),
889    /// `IS NOT TRUE` operator
890    IsNotTrue(Box<Expr>),
891    /// `IS NULL` operator
892    IsNull(Box<Expr>),
893    /// `IS NOT NULL` operator
894    IsNotNull(Box<Expr>),
895    /// `IS UNKNOWN` operator
896    IsUnknown(Box<Expr>),
897    /// `IS NOT UNKNOWN` operator
898    IsNotUnknown(Box<Expr>),
899    /// `IS DISTINCT FROM` operator
900    IsDistinctFrom(Box<Expr>, Box<Expr>),
901    /// `IS NOT DISTINCT FROM` operator
902    IsNotDistinctFrom(Box<Expr>, Box<Expr>),
903    /// `<expr> IS [ NOT ] [ form ] NORMALIZED`
904    IsNormalized {
905        /// Expression being tested.
906        expr: Box<Expr>,
907        /// Optional normalization `form` (e.g., NFC, NFD).
908        form: Option<NormalizationForm>,
909        /// `true` when `NOT` is present.
910        negated: bool,
911    },
912    /// `[ NOT ] IN (val1, val2, ...)`
913    InList {
914        /// Left-hand expression to test for membership.
915        expr: Box<Expr>,
916        /// Literal list of expressions to check against.
917        list: Vec<Expr>,
918        /// `true` when the `NOT` modifier is present.
919        negated: bool,
920    },
921    /// `[ NOT ] IN (SELECT ...)`
922    InSubquery {
923        /// Left-hand expression to test for membership.
924        expr: Box<Expr>,
925        /// The subquery providing the candidate values.
926        subquery: Box<Query>,
927        /// `true` when the `NOT` modifier is present.
928        negated: bool,
929    },
930    /// `[ NOT ] IN UNNEST(array_expression)`
931    InUnnest {
932        /// Left-hand expression to test for membership.
933        expr: Box<Expr>,
934        /// Array expression being unnested.
935        array_expr: Box<Expr>,
936        /// `true` when the `NOT` modifier is present.
937        negated: bool,
938    },
939    /// `<expr> [ NOT ] BETWEEN <low> AND <high>`
940    Between {
941        /// Expression being compared.
942        expr: Box<Expr>,
943        /// `true` when the `NOT` modifier is present.
944        negated: bool,
945        /// Lower bound.
946        low: Box<Expr>,
947        /// Upper bound.
948        high: Box<Expr>,
949    },
950    /// Binary operation e.g. `1 + 1` or `foo > bar`
951    BinaryOp {
952        /// Left operand.
953        left: Box<Expr>,
954        /// Operator between operands.
955        op: BinaryOperator,
956        /// Right operand.
957        right: Box<Expr>,
958    },
959    /// `[NOT] LIKE <pattern> [ESCAPE <escape_character>]`
960    Like {
961        /// `true` when `NOT` is present.
962        negated: bool,
963        /// Snowflake supports the ANY keyword to match against a list of patterns
964        /// <https://docs.snowflake.com/en/sql-reference/functions/like_any>
965        any: bool,
966        /// Expression to match.
967        expr: Box<Expr>,
968        /// Pattern expression.
969        pattern: Box<Expr>,
970        /// Optional escape character.
971        escape_char: Option<ValueWithSpan>,
972    },
973    /// `ILIKE` (case-insensitive `LIKE`)
974    ILike {
975        /// `true` when `NOT` is present.
976        negated: bool,
977        /// Snowflake supports the ANY keyword to match against a list of patterns
978        /// <https://docs.snowflake.com/en/sql-reference/functions/like_any>
979        any: bool,
980        /// Expression to match.
981        expr: Box<Expr>,
982        /// Pattern expression.
983        pattern: Box<Expr>,
984        /// Optional escape character.
985        escape_char: Option<ValueWithSpan>,
986    },
987    /// `SIMILAR TO` regex
988    SimilarTo {
989        /// `true` when `NOT` is present.
990        negated: bool,
991        /// Expression to test.
992        expr: Box<Expr>,
993        /// Pattern expression.
994        pattern: Box<Expr>,
995        /// Optional escape character.
996        escape_char: Option<ValueWithSpan>,
997    },
998    /// MySQL: `RLIKE` regex or `REGEXP` regex
999    RLike {
1000        /// `true` when `NOT` is present.
1001        negated: bool,
1002        /// Expression to test.
1003        expr: Box<Expr>,
1004        /// Pattern expression.
1005        pattern: Box<Expr>,
1006        /// true for REGEXP, false for RLIKE (no difference in semantics)
1007        regexp: bool,
1008    },
1009    /// `ANY` operation e.g. `foo > ANY(bar)`, comparison operator is one of `[=, >, <, =>, =<, !=]`
1010    /// <https://docs.snowflake.com/en/sql-reference/operators-subquery#all-any>
1011    AnyOp {
1012        /// Left operand.
1013        left: Box<Expr>,
1014        /// Comparison operator.
1015        compare_op: BinaryOperator,
1016        /// Right-hand subquery expression.
1017        right: Box<Expr>,
1018        /// ANY and SOME are synonymous: <https://docs.cloudera.com/cdw-runtime/cloud/using-hiveql/topics/hive_comparison_predicates.html>
1019        is_some: bool,
1020    },
1021    /// `ALL` operation e.g. `foo > ALL(bar)`, comparison operator is one of `[=, >, <, =>, =<, !=]`
1022    /// <https://docs.snowflake.com/en/sql-reference/operators-subquery#all-any>
1023    AllOp {
1024        /// Left operand.
1025        left: Box<Expr>,
1026        /// Comparison operator.
1027        compare_op: BinaryOperator,
1028        /// Right-hand subquery expression.
1029        right: Box<Expr>,
1030    },
1031
1032    /// Unary operation e.g. `NOT foo`
1033    UnaryOp {
1034        /// The unary operator (e.g., `NOT`, `-`).
1035        op: UnaryOperator,
1036        /// Operand expression.
1037        expr: Box<Expr>,
1038    },
1039    /// CONVERT a value to a different data type or character encoding. e.g. `CONVERT(foo USING utf8mb4)`
1040    Convert {
1041        /// CONVERT (false) or TRY_CONVERT (true)
1042        /// <https://learn.microsoft.com/en-us/sql/t-sql/functions/try-convert-transact-sql?view=sql-server-ver16>
1043        is_try: bool,
1044        /// The expression to convert.
1045        expr: Box<Expr>,
1046        /// The target data type, if provided.
1047        data_type: Option<DataType>,
1048        /// Optional target character encoding (e.g., `utf8mb4`).
1049        charset: Option<ObjectName>,
1050        /// `true` when target precedes the value (MSSQL syntax).
1051        target_before_value: bool,
1052        /// How to translate the expression.
1053        ///
1054        /// [MSSQL]: https://learn.microsoft.com/en-us/sql/t-sql/functions/cast-and-convert-transact-sql?view=sql-server-ver16#style
1055        styles: Vec<Expr>,
1056    },
1057    /// `CAST` an expression to a different data type e.g. `CAST(foo AS VARCHAR(123))`
1058    Cast {
1059        /// The cast kind (e.g., `CAST`, `TRY_CAST`).
1060        kind: CastKind,
1061        /// Expression being cast.
1062        expr: Box<Expr>,
1063        /// Target data type.
1064        data_type: DataType,
1065        /// [MySQL] allows CAST(... AS type ARRAY) in functional index definitions for InnoDB
1066        /// multi-valued indices. It's not really a datatype, and is only allowed in `CAST` in key
1067        /// specifications, so it's a flag here.
1068        ///
1069        /// [MySQL]: https://dev.mysql.com/doc/refman/8.4/en/cast-functions.html#function_cast
1070        array: bool,
1071        /// Optional CAST(string_expression AS type FORMAT format_string_expression) as used by [BigQuery]
1072        ///
1073        /// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/format-elements#formatting_syntax
1074        format: Option<CastFormat>,
1075    },
1076    /// AT a timestamp to a different timezone e.g. `FROM_UNIXTIME(0) AT TIME ZONE 'UTC-06:00'`
1077    AtTimeZone {
1078        /// Timestamp expression to shift.
1079        timestamp: Box<Expr>,
1080        /// Time zone expression to apply.
1081        time_zone: Box<Expr>,
1082    },
1083    /// Extract a field from a timestamp e.g. `EXTRACT(MONTH FROM foo)`
1084    /// Or `EXTRACT(MONTH, foo)`
1085    ///
1086    /// Syntax:
1087    /// ```sql
1088    /// EXTRACT(DateTimeField FROM <expr>) | EXTRACT(DateTimeField, <expr>)
1089    /// ```
1090    Extract {
1091        /// Which datetime field is being extracted.
1092        field: DateTimeField,
1093        /// Syntax variant used (`From` or `Comma`).
1094        syntax: ExtractSyntax,
1095        /// Expression to extract from.
1096        expr: Box<Expr>,
1097    },
1098    /// ```sql
1099    /// CEIL(<expr> [TO DateTimeField])
1100    /// ```
1101    /// ```sql
1102    /// CEIL( <input_expr> [, <scale_expr> ] )
1103    /// ```
1104    Ceil {
1105        /// Expression to ceil.
1106        expr: Box<Expr>,
1107        /// The CEIL/FLOOR kind (datetime field or scale).
1108        field: CeilFloorKind,
1109    },
1110    /// ```sql
1111    /// FLOOR(<expr> [TO DateTimeField])
1112    /// ```
1113    /// ```sql
1114    /// FLOOR( <input_expr> [, <scale_expr> ] )
1115    ///
1116    Floor {
1117        /// Expression to floor.
1118        expr: Box<Expr>,
1119        /// The CEIL/FLOOR kind (datetime field or scale).
1120        field: CeilFloorKind,
1121    },
1122    /// ```sql
1123    /// POSITION(<expr> in <expr>)
1124    /// ```
1125    Position {
1126        /// Expression to search for.
1127        expr: Box<Expr>,
1128        /// Expression to search in.
1129        r#in: Box<Expr>,
1130    },
1131    /// ```sql
1132    /// SUBSTRING(<expr> [FROM <expr>] [FOR <expr>])
1133    /// ```
1134    /// or
1135    /// ```sql
1136    /// SUBSTRING(<expr>, <expr>, <expr>)
1137    /// ```
1138    Substring {
1139        /// Source expression.
1140        expr: Box<Expr>,
1141        /// Optional `FROM` expression.
1142        substring_from: Option<Box<Expr>>,
1143        /// Optional `FOR` expression.
1144        substring_for: Option<Box<Expr>>,
1145
1146        /// false if the expression is represented using the `SUBSTRING(expr [FROM start] [FOR len])` syntax
1147        /// true if the expression is represented using the `SUBSTRING(expr, start, len)` syntax
1148        /// This flag is used for formatting.
1149        special: bool,
1150
1151        /// true if the expression is represented using the `SUBSTR` shorthand
1152        /// This flag is used for formatting.
1153        shorthand: bool,
1154    },
1155    /// ```sql
1156    /// TRIM([BOTH | LEADING | TRAILING] [<expr> FROM] <expr>)
1157    /// TRIM(<expr>)
1158    /// TRIM(<expr>, [, characters]) -- PostgreSQL, DuckDB, Snowflake, BigQuery, Generic
1159    /// ```
1160    Trim {
1161        /// Which side to trim: `BOTH`, `LEADING`, or `TRAILING`.
1162        trim_where: Option<TrimWhereField>,
1163        /// Optional expression specifying what to trim from the value `expr`.
1164        trim_what: Option<Box<Expr>>,
1165        /// The expression to trim from.
1166        expr: Box<Expr>,
1167        /// Optional list of characters to trim (dialect-specific).
1168        trim_characters: Option<Vec<Expr>>,
1169    },
1170    /// ```sql
1171    /// OVERLAY(<expr> PLACING <expr> FROM <expr>[ FOR <expr> ]
1172    /// ```
1173    Overlay {
1174        /// The target expression being overlayed.
1175        expr: Box<Expr>,
1176        /// The expression to place into the target.
1177        overlay_what: Box<Expr>,
1178        /// The `FROM` position expression indicating where to start overlay.
1179        overlay_from: Box<Expr>,
1180        /// Optional `FOR` length expression limiting the overlay span.
1181        overlay_for: Option<Box<Expr>>,
1182    },
1183    /// `expr COLLATE collation`
1184    Collate {
1185        /// The expression being collated.
1186        expr: Box<Expr>,
1187        /// The collation name to apply to the expression.
1188        collation: ObjectName,
1189    },
1190    /// Nested expression e.g. `(foo > bar)` or `(1)`
1191    Nested(Box<Expr>),
1192    /// A literal value, such as string, number, date or NULL
1193    Value(ValueWithSpan),
1194    /// Prefixed expression, e.g. introducer strings, projection prefix
1195    /// <https://dev.mysql.com/doc/refman/8.0/en/charset-introducer.html>
1196    /// <https://docs.snowflake.com/en/sql-reference/constructs/connect-by>
1197    Prefixed {
1198        /// The prefix identifier (introducer or projection prefix).
1199        prefix: Ident,
1200        /// The value expression being prefixed.
1201        /// Hint: you can unwrap the string value using `value.into_string()`.
1202        value: Box<Expr>,
1203    },
1204    /// A constant of form `<data_type> 'value'`.
1205    /// This can represent ANSI SQL `DATE`, `TIME`, and `TIMESTAMP` literals (such as `DATE '2020-01-01'`),
1206    /// as well as constants of other types (a non-standard PostgreSQL extension).
1207    TypedString(TypedString),
1208    /// Scalar function call e.g. `LEFT(foo, 5)`
1209    Function(Function),
1210    /// `CASE [<operand>] WHEN <condition> THEN <result> ... [ELSE <result>] END`
1211    ///
1212    /// Note we only recognize a complete single expression as `<condition>`,
1213    /// not `< 0` nor `1, 2, 3` as allowed in a `<simple when clause>` per
1214    /// <https://jakewheat.github.io/sql-overview/sql-2011-foundation-grammar.html#simple-when-clause>
1215    Case {
1216        /// The attached `CASE` token (keeps original spacing/comments).
1217        case_token: AttachedToken,
1218        /// The attached `END` token (keeps original spacing/comments).
1219        end_token: AttachedToken,
1220        /// Optional operand expression after `CASE` (for simple CASE).
1221        operand: Option<Box<Expr>>,
1222        /// The `WHEN ... THEN` conditions and results.
1223        conditions: Vec<CaseWhen>,
1224        /// Optional `ELSE` result expression.
1225        else_result: Option<Box<Expr>>,
1226    },
1227    /// An exists expression `[ NOT ] EXISTS(SELECT ...)`, used in expressions like
1228    /// `WHERE [ NOT ] EXISTS (SELECT ...)`.
1229    Exists {
1230        /// The subquery checked by `EXISTS`.
1231        subquery: Box<Query>,
1232        /// Whether the `EXISTS` is negated (`NOT EXISTS`).
1233        negated: bool,
1234    },
1235    /// A parenthesized subquery `(SELECT ...)`, used in expression like
1236    /// `SELECT (subquery) AS x` or `WHERE (subquery) = x`
1237    Subquery(Box<Query>),
1238    /// The `GROUPING SETS` expr.
1239    GroupingSets(Vec<Vec<Expr>>),
1240    /// The `CUBE` expr.
1241    Cube(Vec<Vec<Expr>>),
1242    /// The `ROLLUP` expr.
1243    Rollup(Vec<Vec<Expr>>),
1244    /// ROW / TUPLE a single value, such as `SELECT (1, 2)`
1245    Tuple(Vec<Expr>),
1246    /// `Struct` literal expression
1247    /// Syntax:
1248    /// ```sql
1249    /// STRUCT<[field_name] field_type, ...>( expr1 [, ... ])
1250    ///
1251    /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-types#struct_type)
1252    /// [Databricks](https://docs.databricks.com/en/sql/language-manual/functions/struct.html)
1253    /// ```
1254    Struct {
1255        /// Struct values.
1256        values: Vec<Expr>,
1257        /// Struct field definitions.
1258        fields: Vec<StructField>,
1259    },
1260    /// `BigQuery` specific: An named expression in a typeless struct [1]
1261    ///
1262    /// Syntax
1263    /// ```sql
1264    /// 1 AS A
1265    /// ```
1266    /// [1]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-types#struct_type
1267    Named {
1268        /// The expression being named.
1269        expr: Box<Expr>,
1270        /// The assigned identifier name for the expression.
1271        name: Ident,
1272    },
1273    /// `DuckDB` specific `Struct` literal expression [1]
1274    ///
1275    /// Syntax:
1276    /// ```sql
1277    /// syntax: {'field_name': expr1[, ... ]}
1278    /// ```
1279    /// [1]: https://duckdb.org/docs/sql/data_types/struct#creating-structs
1280    Dictionary(Vec<DictionaryField>),
1281    /// `DuckDB` specific `Map` literal expression [1]
1282    ///
1283    /// Syntax:
1284    /// ```sql
1285    /// syntax: Map {key1: value1[, ... ]}
1286    /// ```
1287    /// [1]: https://duckdb.org/docs/sql/data_types/map#creating-maps
1288    Map(Map),
1289    /// An array expression e.g. `ARRAY[1, 2]`
1290    Array(Array),
1291    /// An interval expression e.g. `INTERVAL '1' YEAR`
1292    Interval(Interval),
1293    /// `MySQL` specific text search function [(1)].
1294    ///
1295    /// Syntax:
1296    /// ```sql
1297    /// MATCH (<col>, <col>, ...) AGAINST (<expr> [<search modifier>])
1298    ///
1299    /// <col> = CompoundIdentifier
1300    /// <expr> = String literal
1301    /// ```
1302    /// [(1)]: https://dev.mysql.com/doc/refman/8.0/en/fulltext-search.html#function_match
1303    MatchAgainst {
1304        /// `(<col>, <col>, ...)`.
1305        columns: Vec<ObjectName>,
1306        /// `<expr>`.
1307        match_value: ValueWithSpan,
1308        /// `<search modifier>`
1309        opt_search_modifier: Option<SearchModifier>,
1310    },
1311    /// An unqualified `*` wildcard token (e.g. `*`).
1312    Wildcard(AttachedToken),
1313    /// Qualified wildcard, e.g. `alias.*` or `schema.table.*`.
1314    /// (Same caveats apply to `QualifiedWildcard` as to `Wildcard`.)
1315    QualifiedWildcard(ObjectName, AttachedToken),
1316    /// Some dialects support an older syntax for outer joins where columns are
1317    /// marked with the `(+)` operator in the WHERE clause, for example:
1318    ///
1319    /// ```sql
1320    /// SELECT t1.c1, t2.c2 FROM t1, t2 WHERE t1.c1 = t2.c2 (+)
1321    /// ```
1322    ///
1323    /// which is equivalent to
1324    ///
1325    /// ```sql
1326    /// SELECT t1.c1, t2.c2 FROM t1 LEFT OUTER JOIN t2 ON t1.c1 = t2.c2
1327    /// ```
1328    ///
1329    /// See <https://docs.snowflake.com/en/sql-reference/constructs/where#joins-in-the-where-clause>.
1330    OuterJoin(Box<Expr>),
1331    /// A reference to the prior level in a CONNECT BY clause.
1332    Prior(Box<Expr>),
1333    /// A lambda function.
1334    ///
1335    /// Syntax:
1336    /// ```plaintext
1337    /// param -> expr | (param1, ...) -> expr
1338    /// ```
1339    ///
1340    /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/functions#higher-order-functions---operator-and-lambdaparams-expr-function)
1341    /// [Databricks](https://docs.databricks.com/en/sql/language-manual/sql-ref-lambda-functions.html)
1342    /// [DuckDB](https://duckdb.org/docs/stable/sql/functions/lambda)
1343    Lambda(LambdaFunction),
1344    /// Checks membership of a value in a JSON array
1345    MemberOf(MemberOf),
1346}
1347
1348impl Expr {
1349    /// Creates a new [`Expr::Value`]
1350    pub fn value(value: impl Into<ValueWithSpan>) -> Self {
1351        Expr::Value(value.into())
1352    }
1353}
1354
1355/// The contents inside the `[` and `]` in a subscript expression.
1356#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1357#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1358#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1359pub enum Subscript {
1360    /// Accesses the element of the array at the given index.
1361    Index {
1362        /// The index expression used to access the array element.
1363        index: Expr,
1364    },
1365
1366    /// Accesses a slice of an array on PostgreSQL, e.g.
1367    ///
1368    /// ```plaintext
1369    /// => select (array[1,2,3,4,5,6])[2:5];
1370    /// -----------
1371    /// {2,3,4,5}
1372    /// ```
1373    ///
1374    /// The lower and/or upper bound can be omitted to slice from the start or
1375    /// end of the array respectively.
1376    ///
1377    /// See <https://www.postgresql.org/docs/current/arrays.html#ARRAYS-ACCESSING>.
1378    ///
1379    /// Also supports an optional "stride" as the last element (this is not
1380    /// supported by postgres), e.g.
1381    ///
1382    /// ```plaintext
1383    /// => select (array[1,2,3,4,5,6])[1:6:2];
1384    /// -----------
1385    /// {1,3,5}
1386    /// ```
1387    Slice {
1388        /// Optional lower bound for the slice (inclusive).
1389        lower_bound: Option<Expr>,
1390        /// Optional upper bound for the slice (inclusive).
1391        upper_bound: Option<Expr>,
1392        /// Optional stride for the slice (step size).
1393        stride: Option<Expr>,
1394    },
1395}
1396
1397impl fmt::Display for Subscript {
1398    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1399        match self {
1400            Subscript::Index { index } => write!(f, "{index}"),
1401            Subscript::Slice {
1402                lower_bound,
1403                upper_bound,
1404                stride,
1405            } => {
1406                if let Some(lower) = lower_bound {
1407                    write!(f, "{lower}")?;
1408                }
1409                write!(f, ":")?;
1410                if let Some(upper) = upper_bound {
1411                    write!(f, "{upper}")?;
1412                }
1413                if let Some(stride) = stride {
1414                    write!(f, ":")?;
1415                    write!(f, "{stride}")?;
1416                }
1417                Ok(())
1418            }
1419        }
1420    }
1421}
1422
1423/// An element of a [`Expr::CompoundFieldAccess`].
1424/// It can be an expression or a subscript.
1425#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1426#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1427#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1428pub enum AccessExpr {
1429    /// Accesses a field using dot notation, e.g. `foo.bar.baz`.
1430    Dot(Expr),
1431    /// Accesses a field or array element using bracket notation, e.g. `foo['bar']`.
1432    Subscript(Subscript),
1433}
1434
1435impl fmt::Display for AccessExpr {
1436    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1437        match self {
1438            AccessExpr::Dot(expr) => write!(f, ".{expr}"),
1439            AccessExpr::Subscript(subscript) => write!(f, "[{subscript}]"),
1440        }
1441    }
1442}
1443
1444/// A lambda function.
1445#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1446#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1447#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1448pub struct LambdaFunction {
1449    /// The parameters to the lambda function.
1450    pub params: OneOrManyWithParens<LambdaFunctionParameter>,
1451    /// The body of the lambda function.
1452    pub body: Box<Expr>,
1453    /// The syntax style used to write the lambda function.
1454    pub syntax: LambdaSyntax,
1455}
1456
1457impl fmt::Display for LambdaFunction {
1458    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1459        match self.syntax {
1460            LambdaSyntax::Arrow => write!(f, "{} -> {}", self.params, self.body),
1461            LambdaSyntax::LambdaKeyword => {
1462                // For lambda keyword syntax, display params without parentheses
1463                // e.g., `lambda x, y : expr` not `lambda (x, y) : expr`
1464                write!(f, "lambda ")?;
1465                match &self.params {
1466                    OneOrManyWithParens::One(p) => write!(f, "{p}")?,
1467                    OneOrManyWithParens::Many(ps) => write!(f, "{}", display_comma_separated(ps))?,
1468                };
1469                write!(f, " : {}", self.body)
1470            }
1471        }
1472    }
1473}
1474
1475/// A parameter to a lambda function, optionally with a data type.
1476#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1477#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1478#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1479pub struct LambdaFunctionParameter {
1480    /// The name of the parameter
1481    pub name: Ident,
1482    /// The optional data type of the parameter
1483    /// [Snowflake Syntax](https://docs.snowflake.com/en/sql-reference/functions/filter#arguments)
1484    pub data_type: Option<DataType>,
1485}
1486
1487impl fmt::Display for LambdaFunctionParameter {
1488    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1489        match &self.data_type {
1490            Some(dt) => write!(f, "{} {}", self.name, dt),
1491            None => write!(f, "{}", self.name),
1492        }
1493    }
1494}
1495
1496/// The syntax style for a lambda function.
1497#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Copy)]
1498#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1499#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1500pub enum LambdaSyntax {
1501    /// Arrow syntax: `param -> expr` or `(param1, param2) -> expr`
1502    ///
1503    /// <https://docs.databricks.com/aws/en/sql/language-manual/sql-ref-lambda-functions>
1504    ///
1505    /// Supported, but deprecated in DuckDB:
1506    /// <https://duckdb.org/docs/stable/sql/functions/lambda>
1507    Arrow,
1508    /// Lambda keyword syntax: `lambda param : expr` or `lambda param1, param2 : expr`
1509    ///
1510    /// Recommended in DuckDB:
1511    /// <https://duckdb.org/docs/stable/sql/functions/lambda>
1512    LambdaKeyword,
1513}
1514
1515/// Encapsulates the common pattern in SQL where either one unparenthesized item
1516/// such as an identifier or expression is permitted, or multiple of the same
1517/// item in a parenthesized list. For accessing items regardless of the form,
1518/// `OneOrManyWithParens` implements `Deref<Target = [T]>` and `IntoIterator`,
1519/// so you can call slice methods on it and iterate over items
1520/// # Examples
1521/// Accessing as a slice:
1522/// ```
1523/// # use sqlparser::ast::OneOrManyWithParens;
1524/// let one = OneOrManyWithParens::One("a");
1525///
1526/// assert_eq!(one[0], "a");
1527/// assert_eq!(one.len(), 1);
1528/// ```
1529/// Iterating:
1530/// ```
1531/// # use sqlparser::ast::OneOrManyWithParens;
1532/// let one = OneOrManyWithParens::One("a");
1533/// let many = OneOrManyWithParens::Many(vec!["a", "b"]);
1534///
1535/// assert_eq!(one.into_iter().chain(many).collect::<Vec<_>>(), vec!["a", "a", "b"] );
1536/// ```
1537#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1538#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1539#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1540pub enum OneOrManyWithParens<T> {
1541    /// A single `T`, unparenthesized.
1542    One(T),
1543    /// One or more `T`s, parenthesized.
1544    Many(Vec<T>),
1545}
1546
1547impl<T> Deref for OneOrManyWithParens<T> {
1548    type Target = [T];
1549
1550    fn deref(&self) -> &[T] {
1551        match self {
1552            OneOrManyWithParens::One(one) => core::slice::from_ref(one),
1553            OneOrManyWithParens::Many(many) => many,
1554        }
1555    }
1556}
1557
1558impl<T> AsRef<[T]> for OneOrManyWithParens<T> {
1559    fn as_ref(&self) -> &[T] {
1560        self
1561    }
1562}
1563
1564impl<'a, T> IntoIterator for &'a OneOrManyWithParens<T> {
1565    type Item = &'a T;
1566    type IntoIter = core::slice::Iter<'a, T>;
1567
1568    fn into_iter(self) -> Self::IntoIter {
1569        self.iter()
1570    }
1571}
1572
1573/// Owned iterator implementation of `OneOrManyWithParens`
1574#[derive(Debug, Clone)]
1575pub struct OneOrManyWithParensIntoIter<T> {
1576    inner: OneOrManyWithParensIntoIterInner<T>,
1577}
1578
1579#[derive(Debug, Clone)]
1580enum OneOrManyWithParensIntoIterInner<T> {
1581    One(core::iter::Once<T>),
1582    Many(<Vec<T> as IntoIterator>::IntoIter),
1583}
1584
1585impl<T> core::iter::FusedIterator for OneOrManyWithParensIntoIter<T>
1586where
1587    core::iter::Once<T>: core::iter::FusedIterator,
1588    <Vec<T> as IntoIterator>::IntoIter: core::iter::FusedIterator,
1589{
1590}
1591
1592impl<T> core::iter::ExactSizeIterator for OneOrManyWithParensIntoIter<T>
1593where
1594    core::iter::Once<T>: core::iter::ExactSizeIterator,
1595    <Vec<T> as IntoIterator>::IntoIter: core::iter::ExactSizeIterator,
1596{
1597}
1598
1599impl<T> core::iter::Iterator for OneOrManyWithParensIntoIter<T> {
1600    type Item = T;
1601
1602    fn next(&mut self) -> Option<Self::Item> {
1603        match &mut self.inner {
1604            OneOrManyWithParensIntoIterInner::One(one) => one.next(),
1605            OneOrManyWithParensIntoIterInner::Many(many) => many.next(),
1606        }
1607    }
1608
1609    fn size_hint(&self) -> (usize, Option<usize>) {
1610        match &self.inner {
1611            OneOrManyWithParensIntoIterInner::One(one) => one.size_hint(),
1612            OneOrManyWithParensIntoIterInner::Many(many) => many.size_hint(),
1613        }
1614    }
1615
1616    fn count(self) -> usize
1617    where
1618        Self: Sized,
1619    {
1620        match self.inner {
1621            OneOrManyWithParensIntoIterInner::One(one) => one.count(),
1622            OneOrManyWithParensIntoIterInner::Many(many) => many.count(),
1623        }
1624    }
1625
1626    fn fold<B, F>(mut self, init: B, f: F) -> B
1627    where
1628        Self: Sized,
1629        F: FnMut(B, Self::Item) -> B,
1630    {
1631        match &mut self.inner {
1632            OneOrManyWithParensIntoIterInner::One(one) => one.fold(init, f),
1633            OneOrManyWithParensIntoIterInner::Many(many) => many.fold(init, f),
1634        }
1635    }
1636}
1637
1638impl<T> core::iter::DoubleEndedIterator for OneOrManyWithParensIntoIter<T> {
1639    fn next_back(&mut self) -> Option<Self::Item> {
1640        match &mut self.inner {
1641            OneOrManyWithParensIntoIterInner::One(one) => one.next_back(),
1642            OneOrManyWithParensIntoIterInner::Many(many) => many.next_back(),
1643        }
1644    }
1645}
1646
1647impl<T> IntoIterator for OneOrManyWithParens<T> {
1648    type Item = T;
1649
1650    type IntoIter = OneOrManyWithParensIntoIter<T>;
1651
1652    fn into_iter(self) -> Self::IntoIter {
1653        let inner = match self {
1654            OneOrManyWithParens::One(one) => {
1655                OneOrManyWithParensIntoIterInner::One(core::iter::once(one))
1656            }
1657            OneOrManyWithParens::Many(many) => {
1658                OneOrManyWithParensIntoIterInner::Many(many.into_iter())
1659            }
1660        };
1661
1662        OneOrManyWithParensIntoIter { inner }
1663    }
1664}
1665
1666impl<T> fmt::Display for OneOrManyWithParens<T>
1667where
1668    T: fmt::Display,
1669{
1670    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1671        match self {
1672            OneOrManyWithParens::One(value) => write!(f, "{value}"),
1673            OneOrManyWithParens::Many(values) => {
1674                write!(f, "({})", display_comma_separated(values))
1675            }
1676        }
1677    }
1678}
1679
1680impl fmt::Display for CastFormat {
1681    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1682        match self {
1683            CastFormat::Value(v) => write!(f, "{v}"),
1684            CastFormat::ValueAtTimeZone(v, tz) => write!(f, "{v} AT TIME ZONE {tz}"),
1685        }
1686    }
1687}
1688
1689impl fmt::Display for Expr {
1690    #[cfg_attr(feature = "recursive-protection", recursive::recursive)]
1691    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1692        match self {
1693            Expr::Identifier(s) => write!(f, "{s}"),
1694            Expr::Wildcard(_) => f.write_str("*"),
1695            Expr::QualifiedWildcard(prefix, _) => write!(f, "{prefix}.*"),
1696            Expr::CompoundIdentifier(s) => write!(f, "{}", display_separated(s, ".")),
1697            Expr::CompoundFieldAccess { root, access_chain } => {
1698                write!(f, "{root}")?;
1699                for field in access_chain {
1700                    write!(f, "{field}")?;
1701                }
1702                Ok(())
1703            }
1704            Expr::IsTrue(ast) => write!(f, "{ast} IS TRUE"),
1705            Expr::IsNotTrue(ast) => write!(f, "{ast} IS NOT TRUE"),
1706            Expr::IsFalse(ast) => write!(f, "{ast} IS FALSE"),
1707            Expr::IsNotFalse(ast) => write!(f, "{ast} IS NOT FALSE"),
1708            Expr::IsNull(ast) => write!(f, "{ast} IS NULL"),
1709            Expr::IsNotNull(ast) => write!(f, "{ast} IS NOT NULL"),
1710            Expr::IsUnknown(ast) => write!(f, "{ast} IS UNKNOWN"),
1711            Expr::IsNotUnknown(ast) => write!(f, "{ast} IS NOT UNKNOWN"),
1712            Expr::InList {
1713                expr,
1714                list,
1715                negated,
1716            } => write!(
1717                f,
1718                "{} {}IN ({})",
1719                expr,
1720                if *negated { "NOT " } else { "" },
1721                display_comma_separated(list)
1722            ),
1723            Expr::InSubquery {
1724                expr,
1725                subquery,
1726                negated,
1727            } => write!(
1728                f,
1729                "{} {}IN ({})",
1730                expr,
1731                if *negated { "NOT " } else { "" },
1732                subquery
1733            ),
1734            Expr::InUnnest {
1735                expr,
1736                array_expr,
1737                negated,
1738            } => write!(
1739                f,
1740                "{} {}IN UNNEST({})",
1741                expr,
1742                if *negated { "NOT " } else { "" },
1743                array_expr
1744            ),
1745            Expr::Between {
1746                expr,
1747                negated,
1748                low,
1749                high,
1750            } => write!(
1751                f,
1752                "{} {}BETWEEN {} AND {}",
1753                expr,
1754                if *negated { "NOT " } else { "" },
1755                low,
1756                high
1757            ),
1758            Expr::BinaryOp { left, op, right } => write!(f, "{left} {op} {right}"),
1759            Expr::Like {
1760                negated,
1761                expr,
1762                pattern,
1763                escape_char,
1764                any,
1765            } => match escape_char {
1766                Some(ch) => write!(
1767                    f,
1768                    "{} {}LIKE {}{} ESCAPE {}",
1769                    expr,
1770                    if *negated { "NOT " } else { "" },
1771                    if *any { "ANY " } else { "" },
1772                    pattern,
1773                    ch
1774                ),
1775                _ => write!(
1776                    f,
1777                    "{} {}LIKE {}{}",
1778                    expr,
1779                    if *negated { "NOT " } else { "" },
1780                    if *any { "ANY " } else { "" },
1781                    pattern
1782                ),
1783            },
1784            Expr::ILike {
1785                negated,
1786                expr,
1787                pattern,
1788                escape_char,
1789                any,
1790            } => match escape_char {
1791                Some(ch) => write!(
1792                    f,
1793                    "{} {}ILIKE {}{} ESCAPE {}",
1794                    expr,
1795                    if *negated { "NOT " } else { "" },
1796                    if *any { "ANY" } else { "" },
1797                    pattern,
1798                    ch
1799                ),
1800                _ => write!(
1801                    f,
1802                    "{} {}ILIKE {}{}",
1803                    expr,
1804                    if *negated { "NOT " } else { "" },
1805                    if *any { "ANY " } else { "" },
1806                    pattern
1807                ),
1808            },
1809            Expr::RLike {
1810                negated,
1811                expr,
1812                pattern,
1813                regexp,
1814            } => write!(
1815                f,
1816                "{} {}{} {}",
1817                expr,
1818                if *negated { "NOT " } else { "" },
1819                if *regexp { "REGEXP" } else { "RLIKE" },
1820                pattern
1821            ),
1822            Expr::IsNormalized {
1823                expr,
1824                form,
1825                negated,
1826            } => {
1827                let not_ = if *negated { "NOT " } else { "" };
1828                if form.is_none() {
1829                    write!(f, "{expr} IS {not_}NORMALIZED")
1830                } else {
1831                    write!(
1832                        f,
1833                        "{} IS {}{} NORMALIZED",
1834                        expr,
1835                        not_,
1836                        form.as_ref().unwrap()
1837                    )
1838                }
1839            }
1840            Expr::SimilarTo {
1841                negated,
1842                expr,
1843                pattern,
1844                escape_char,
1845            } => match escape_char {
1846                Some(ch) => write!(
1847                    f,
1848                    "{} {}SIMILAR TO {} ESCAPE {}",
1849                    expr,
1850                    if *negated { "NOT " } else { "" },
1851                    pattern,
1852                    ch
1853                ),
1854                _ => write!(
1855                    f,
1856                    "{} {}SIMILAR TO {}",
1857                    expr,
1858                    if *negated { "NOT " } else { "" },
1859                    pattern
1860                ),
1861            },
1862            Expr::AnyOp {
1863                left,
1864                compare_op,
1865                right,
1866                is_some,
1867            } => {
1868                let add_parens = !matches!(right.as_ref(), Expr::Subquery(_));
1869                write!(
1870                    f,
1871                    "{left} {compare_op} {}{}{right}{}",
1872                    if *is_some { "SOME" } else { "ANY" },
1873                    if add_parens { "(" } else { "" },
1874                    if add_parens { ")" } else { "" },
1875                )
1876            }
1877            Expr::AllOp {
1878                left,
1879                compare_op,
1880                right,
1881            } => {
1882                let add_parens = !matches!(right.as_ref(), Expr::Subquery(_));
1883                write!(
1884                    f,
1885                    "{left} {compare_op} ALL{}{right}{}",
1886                    if add_parens { "(" } else { "" },
1887                    if add_parens { ")" } else { "" },
1888                )
1889            }
1890            Expr::UnaryOp { op, expr } => {
1891                if op == &UnaryOperator::PGPostfixFactorial {
1892                    write!(f, "{expr}{op}")
1893                } else if matches!(
1894                    op,
1895                    UnaryOperator::Not
1896                        | UnaryOperator::Hash
1897                        | UnaryOperator::AtDashAt
1898                        | UnaryOperator::DoubleAt
1899                        | UnaryOperator::QuestionDash
1900                        | UnaryOperator::QuestionPipe
1901                ) {
1902                    write!(f, "{op} {expr}")
1903                } else {
1904                    write!(f, "{op}{expr}")
1905                }
1906            }
1907            Expr::Convert {
1908                is_try,
1909                expr,
1910                target_before_value,
1911                data_type,
1912                charset,
1913                styles,
1914            } => {
1915                write!(f, "{}CONVERT(", if *is_try { "TRY_" } else { "" })?;
1916                if let Some(data_type) = data_type {
1917                    if let Some(charset) = charset {
1918                        write!(f, "{expr}, {data_type} CHARACTER SET {charset}")
1919                    } else if *target_before_value {
1920                        write!(f, "{data_type}, {expr}")
1921                    } else {
1922                        write!(f, "{expr}, {data_type}")
1923                    }
1924                } else if let Some(charset) = charset {
1925                    write!(f, "{expr} USING {charset}")
1926                } else {
1927                    write!(f, "{expr}") // This should never happen
1928                }?;
1929                if !styles.is_empty() {
1930                    write!(f, ", {}", display_comma_separated(styles))?;
1931                }
1932                write!(f, ")")
1933            }
1934            Expr::Cast {
1935                kind,
1936                expr,
1937                data_type,
1938                array,
1939                format,
1940            } => match kind {
1941                CastKind::Cast => {
1942                    write!(f, "CAST({expr} AS {data_type}")?;
1943                    if *array {
1944                        write!(f, " ARRAY")?;
1945                    }
1946                    if let Some(format) = format {
1947                        write!(f, " FORMAT {format}")?;
1948                    }
1949                    write!(f, ")")
1950                }
1951                CastKind::TryCast => {
1952                    if let Some(format) = format {
1953                        write!(f, "TRY_CAST({expr} AS {data_type} FORMAT {format})")
1954                    } else {
1955                        write!(f, "TRY_CAST({expr} AS {data_type})")
1956                    }
1957                }
1958                CastKind::SafeCast => {
1959                    if let Some(format) = format {
1960                        write!(f, "SAFE_CAST({expr} AS {data_type} FORMAT {format})")
1961                    } else {
1962                        write!(f, "SAFE_CAST({expr} AS {data_type})")
1963                    }
1964                }
1965                CastKind::DoubleColon => {
1966                    write!(f, "{expr}::{data_type}")
1967                }
1968            },
1969            Expr::Extract {
1970                field,
1971                syntax,
1972                expr,
1973            } => match syntax {
1974                ExtractSyntax::From => write!(f, "EXTRACT({field} FROM {expr})"),
1975                ExtractSyntax::Comma => write!(f, "EXTRACT({field}, {expr})"),
1976            },
1977            Expr::Ceil { expr, field } => match field {
1978                CeilFloorKind::DateTimeField(DateTimeField::NoDateTime) => {
1979                    write!(f, "CEIL({expr})")
1980                }
1981                CeilFloorKind::DateTimeField(dt_field) => write!(f, "CEIL({expr} TO {dt_field})"),
1982                CeilFloorKind::Scale(s) => write!(f, "CEIL({expr}, {s})"),
1983            },
1984            Expr::Floor { expr, field } => match field {
1985                CeilFloorKind::DateTimeField(DateTimeField::NoDateTime) => {
1986                    write!(f, "FLOOR({expr})")
1987                }
1988                CeilFloorKind::DateTimeField(dt_field) => write!(f, "FLOOR({expr} TO {dt_field})"),
1989                CeilFloorKind::Scale(s) => write!(f, "FLOOR({expr}, {s})"),
1990            },
1991            Expr::Position { expr, r#in } => write!(f, "POSITION({expr} IN {in})"),
1992            Expr::Collate { expr, collation } => write!(f, "{expr} COLLATE {collation}"),
1993            Expr::Nested(ast) => write!(f, "({ast})"),
1994            Expr::Value(v) => write!(f, "{v}"),
1995            Expr::Prefixed { prefix, value } => write!(f, "{prefix} {value}"),
1996            Expr::TypedString(ts) => ts.fmt(f),
1997            Expr::Function(fun) => fun.fmt(f),
1998            Expr::Case {
1999                case_token: _,
2000                end_token: _,
2001                operand,
2002                conditions,
2003                else_result,
2004            } => {
2005                f.write_str("CASE")?;
2006                if let Some(operand) = operand {
2007                    f.write_str(" ")?;
2008                    operand.fmt(f)?;
2009                }
2010                for when in conditions {
2011                    SpaceOrNewline.fmt(f)?;
2012                    Indent(when).fmt(f)?;
2013                }
2014                if let Some(else_result) = else_result {
2015                    SpaceOrNewline.fmt(f)?;
2016                    Indent("ELSE").fmt(f)?;
2017                    SpaceOrNewline.fmt(f)?;
2018                    Indent(Indent(else_result)).fmt(f)?;
2019                }
2020                SpaceOrNewline.fmt(f)?;
2021                f.write_str("END")
2022            }
2023            Expr::Exists { subquery, negated } => write!(
2024                f,
2025                "{}EXISTS ({})",
2026                if *negated { "NOT " } else { "" },
2027                subquery
2028            ),
2029            Expr::Subquery(s) => write!(f, "({s})"),
2030            Expr::GroupingSets(sets) => {
2031                write!(f, "GROUPING SETS (")?;
2032                let mut sep = "";
2033                for set in sets {
2034                    write!(f, "{sep}")?;
2035                    sep = ", ";
2036                    write!(f, "({})", display_comma_separated(set))?;
2037                }
2038                write!(f, ")")
2039            }
2040            Expr::Cube(sets) => {
2041                write!(f, "CUBE (")?;
2042                let mut sep = "";
2043                for set in sets {
2044                    write!(f, "{sep}")?;
2045                    sep = ", ";
2046                    if set.len() == 1 {
2047                        write!(f, "{}", set[0])?;
2048                    } else {
2049                        write!(f, "({})", display_comma_separated(set))?;
2050                    }
2051                }
2052                write!(f, ")")
2053            }
2054            Expr::Rollup(sets) => {
2055                write!(f, "ROLLUP (")?;
2056                let mut sep = "";
2057                for set in sets {
2058                    write!(f, "{sep}")?;
2059                    sep = ", ";
2060                    if set.len() == 1 {
2061                        write!(f, "{}", set[0])?;
2062                    } else {
2063                        write!(f, "({})", display_comma_separated(set))?;
2064                    }
2065                }
2066                write!(f, ")")
2067            }
2068            Expr::Substring {
2069                expr,
2070                substring_from,
2071                substring_for,
2072                special,
2073                shorthand,
2074            } => {
2075                f.write_str("SUBSTR")?;
2076                if !*shorthand {
2077                    f.write_str("ING")?;
2078                }
2079                write!(f, "({expr}")?;
2080                if let Some(from_part) = substring_from {
2081                    if *special {
2082                        write!(f, ", {from_part}")?;
2083                    } else {
2084                        write!(f, " FROM {from_part}")?;
2085                    }
2086                }
2087                if let Some(for_part) = substring_for {
2088                    if *special {
2089                        write!(f, ", {for_part}")?;
2090                    } else {
2091                        write!(f, " FOR {for_part}")?;
2092                    }
2093                }
2094
2095                write!(f, ")")
2096            }
2097            Expr::Overlay {
2098                expr,
2099                overlay_what,
2100                overlay_from,
2101                overlay_for,
2102            } => {
2103                write!(
2104                    f,
2105                    "OVERLAY({expr} PLACING {overlay_what} FROM {overlay_from}"
2106                )?;
2107                if let Some(for_part) = overlay_for {
2108                    write!(f, " FOR {for_part}")?;
2109                }
2110
2111                write!(f, ")")
2112            }
2113            Expr::IsDistinctFrom(a, b) => write!(f, "{a} IS DISTINCT FROM {b}"),
2114            Expr::IsNotDistinctFrom(a, b) => write!(f, "{a} IS NOT DISTINCT FROM {b}"),
2115            Expr::Trim {
2116                expr,
2117                trim_where,
2118                trim_what,
2119                trim_characters,
2120            } => {
2121                write!(f, "TRIM(")?;
2122                if let Some(ident) = trim_where {
2123                    write!(f, "{ident} ")?;
2124                }
2125                if let Some(trim_char) = trim_what {
2126                    write!(f, "{trim_char} FROM {expr}")?;
2127                } else {
2128                    write!(f, "{expr}")?;
2129                }
2130                if let Some(characters) = trim_characters {
2131                    write!(f, ", {}", display_comma_separated(characters))?;
2132                }
2133
2134                write!(f, ")")
2135            }
2136            Expr::Tuple(exprs) => {
2137                write!(f, "({})", display_comma_separated(exprs))
2138            }
2139            Expr::Struct { values, fields } => {
2140                if !fields.is_empty() {
2141                    write!(
2142                        f,
2143                        "STRUCT<{}>({})",
2144                        display_comma_separated(fields),
2145                        display_comma_separated(values)
2146                    )
2147                } else {
2148                    write!(f, "STRUCT({})", display_comma_separated(values))
2149                }
2150            }
2151            Expr::Named { expr, name } => {
2152                write!(f, "{expr} AS {name}")
2153            }
2154            Expr::Dictionary(fields) => {
2155                write!(f, "{{{}}}", display_comma_separated(fields))
2156            }
2157            Expr::Map(map) => {
2158                write!(f, "{map}")
2159            }
2160            Expr::Array(set) => {
2161                write!(f, "{set}")
2162            }
2163            Expr::JsonAccess { value, path } => {
2164                write!(f, "{value}{path}")
2165            }
2166            Expr::AtTimeZone {
2167                timestamp,
2168                time_zone,
2169            } => {
2170                write!(f, "{timestamp} AT TIME ZONE {time_zone}")
2171            }
2172            Expr::Interval(interval) => {
2173                write!(f, "{interval}")
2174            }
2175            Expr::MatchAgainst {
2176                columns,
2177                match_value: match_expr,
2178                opt_search_modifier,
2179            } => {
2180                write!(f, "MATCH ({}) AGAINST ", display_comma_separated(columns),)?;
2181
2182                if let Some(search_modifier) = opt_search_modifier {
2183                    write!(f, "({match_expr} {search_modifier})")?;
2184                } else {
2185                    write!(f, "({match_expr})")?;
2186                }
2187
2188                Ok(())
2189            }
2190            Expr::OuterJoin(expr) => {
2191                write!(f, "{expr} (+)")
2192            }
2193            Expr::Prior(expr) => write!(f, "PRIOR {expr}"),
2194            Expr::Lambda(lambda) => write!(f, "{lambda}"),
2195            Expr::MemberOf(member_of) => write!(f, "{member_of}"),
2196        }
2197    }
2198}
2199
2200/// The type of a window used in `OVER` clauses.
2201///
2202/// A window can be either an inline specification (`WindowSpec`) or a
2203/// reference to a previously defined named window.
2204///
2205/// - `WindowSpec(WindowSpec)`: An inline window specification, e.g.
2206///   `OVER (PARTITION BY ... ORDER BY ...)`.
2207/// - `NamedWindow(Ident)`: A reference to a named window declared elsewhere.
2208#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2209#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2210#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2211pub enum WindowType {
2212    /// An inline window specification.
2213    WindowSpec(WindowSpec),
2214    /// A reference to a previously defined named window.
2215    NamedWindow(Ident),
2216}
2217
2218impl Display for WindowType {
2219    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2220        match self {
2221            WindowType::WindowSpec(spec) => {
2222                f.write_str("(")?;
2223                NewLine.fmt(f)?;
2224                Indent(spec).fmt(f)?;
2225                NewLine.fmt(f)?;
2226                f.write_str(")")
2227            }
2228            WindowType::NamedWindow(name) => name.fmt(f),
2229        }
2230    }
2231}
2232
2233/// A window specification (i.e. `OVER ([window_name] PARTITION BY .. ORDER BY .. etc.)`)
2234#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2235#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2236#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2237pub struct WindowSpec {
2238    /// Optional window name.
2239    ///
2240    /// You can find it at least in [MySQL][1], [BigQuery][2], [PostgreSQL][3]
2241    ///
2242    /// [1]: https://dev.mysql.com/doc/refman/8.0/en/window-functions-named-windows.html
2243    /// [2]: https://cloud.google.com/bigquery/docs/reference/standard-sql/window-function-calls
2244    /// [3]: https://www.postgresql.org/docs/current/sql-expressions.html#SYNTAX-WINDOW-FUNCTIONS
2245    pub window_name: Option<Ident>,
2246    /// `OVER (PARTITION BY ...)`
2247    pub partition_by: Vec<Expr>,
2248    /// `OVER (ORDER BY ...)`
2249    pub order_by: Vec<OrderByExpr>,
2250    /// `OVER (window frame)`
2251    pub window_frame: Option<WindowFrame>,
2252}
2253
2254impl fmt::Display for WindowSpec {
2255    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2256        let mut is_first = true;
2257        if let Some(window_name) = &self.window_name {
2258            if !is_first {
2259                SpaceOrNewline.fmt(f)?;
2260            }
2261            is_first = false;
2262            write!(f, "{window_name}")?;
2263        }
2264        if !self.partition_by.is_empty() {
2265            if !is_first {
2266                SpaceOrNewline.fmt(f)?;
2267            }
2268            is_first = false;
2269            write!(
2270                f,
2271                "PARTITION BY {}",
2272                display_comma_separated(&self.partition_by)
2273            )?;
2274        }
2275        if !self.order_by.is_empty() {
2276            if !is_first {
2277                SpaceOrNewline.fmt(f)?;
2278            }
2279            is_first = false;
2280            write!(f, "ORDER BY {}", display_comma_separated(&self.order_by))?;
2281        }
2282        if let Some(window_frame) = &self.window_frame {
2283            if !is_first {
2284                SpaceOrNewline.fmt(f)?;
2285            }
2286            if let Some(end_bound) = &window_frame.end_bound {
2287                write!(
2288                    f,
2289                    "{} BETWEEN {} AND {}",
2290                    window_frame.units, window_frame.start_bound, end_bound
2291                )?;
2292            } else {
2293                write!(f, "{} {}", window_frame.units, window_frame.start_bound)?;
2294            }
2295        }
2296        Ok(())
2297    }
2298}
2299
2300/// Specifies the data processed by a window function, e.g.
2301/// `RANGE UNBOUNDED PRECEDING` or `ROWS BETWEEN 5 PRECEDING AND CURRENT ROW`.
2302///
2303/// Note: The parser does not validate the specified bounds; the caller should
2304/// reject invalid bounds like `ROWS UNBOUNDED FOLLOWING` before execution.
2305#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2306#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2307#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2308pub struct WindowFrame {
2309    /// Units for the frame (e.g. `ROWS`, `RANGE`, `GROUPS`).
2310    pub units: WindowFrameUnits,
2311    /// The start bound of the window frame.
2312    pub start_bound: WindowFrameBound,
2313    /// The right bound of the `BETWEEN .. AND` clause. The end bound of `None`
2314    /// indicates the shorthand form (e.g. `ROWS 1 PRECEDING`), which must
2315    /// behave the same as `end_bound = WindowFrameBound::CurrentRow`.
2316    pub end_bound: Option<WindowFrameBound>,
2317    // TBD: EXCLUDE
2318}
2319
2320impl Default for WindowFrame {
2321    /// Returns default value for window frame
2322    ///
2323    /// See [this page](https://www.sqlite.org/windowfunctions.html#frame_specifications) for more details.
2324    fn default() -> Self {
2325        Self {
2326            units: WindowFrameUnits::Range,
2327            start_bound: WindowFrameBound::Preceding(None),
2328            end_bound: None,
2329        }
2330    }
2331}
2332
2333#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2334#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2335#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2336/// Units used to describe the window frame scope.
2337pub enum WindowFrameUnits {
2338    /// `ROWS` unit.
2339    Rows,
2340    /// `RANGE` unit.
2341    Range,
2342    /// `GROUPS` unit.
2343    Groups,
2344}
2345
2346impl fmt::Display for WindowFrameUnits {
2347    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2348        f.write_str(match self {
2349            WindowFrameUnits::Rows => "ROWS",
2350            WindowFrameUnits::Range => "RANGE",
2351            WindowFrameUnits::Groups => "GROUPS",
2352        })
2353    }
2354}
2355
2356/// Specifies Ignore / Respect NULL within window functions.
2357/// For example
2358/// `FIRST_VALUE(column2) IGNORE NULLS OVER (PARTITION BY column1)`
2359#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2360#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2361#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2362/// How NULL values are treated in certain window functions.
2363pub enum NullTreatment {
2364    /// Ignore NULL values (e.g. `IGNORE NULLS`).
2365    IgnoreNulls,
2366    /// Respect NULL values (e.g. `RESPECT NULLS`).
2367    RespectNulls,
2368}
2369
2370impl fmt::Display for NullTreatment {
2371    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2372        f.write_str(match self {
2373            NullTreatment::IgnoreNulls => "IGNORE NULLS",
2374            NullTreatment::RespectNulls => "RESPECT NULLS",
2375        })
2376    }
2377}
2378
2379/// Specifies [WindowFrame]'s `start_bound` and `end_bound`
2380#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2381#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2382#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2383pub enum WindowFrameBound {
2384    /// `CURRENT ROW`
2385    CurrentRow,
2386    /// `<N> PRECEDING` or `UNBOUNDED PRECEDING`
2387    Preceding(Option<Box<Expr>>),
2388    /// `<N> FOLLOWING` or `UNBOUNDED FOLLOWING`.
2389    Following(Option<Box<Expr>>),
2390}
2391
2392impl fmt::Display for WindowFrameBound {
2393    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2394        match self {
2395            WindowFrameBound::CurrentRow => f.write_str("CURRENT ROW"),
2396            WindowFrameBound::Preceding(None) => f.write_str("UNBOUNDED PRECEDING"),
2397            WindowFrameBound::Following(None) => f.write_str("UNBOUNDED FOLLOWING"),
2398            WindowFrameBound::Preceding(Some(n)) => write!(f, "{n} PRECEDING"),
2399            WindowFrameBound::Following(Some(n)) => write!(f, "{n} FOLLOWING"),
2400        }
2401    }
2402}
2403
2404#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2405#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2406#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2407/// Indicates partition operation type for partition management statements.
2408pub enum AddDropSync {
2409    /// Add partitions.
2410    ADD,
2411    /// Drop partitions.
2412    DROP,
2413    /// Sync partitions.
2414    SYNC,
2415}
2416
2417impl fmt::Display for AddDropSync {
2418    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2419        match self {
2420            AddDropSync::SYNC => f.write_str("SYNC PARTITIONS"),
2421            AddDropSync::DROP => f.write_str("DROP PARTITIONS"),
2422            AddDropSync::ADD => f.write_str("ADD PARTITIONS"),
2423        }
2424    }
2425}
2426
2427#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2428#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2429#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2430/// Object kinds supported by `SHOW CREATE` statements.
2431pub enum ShowCreateObject {
2432    /// An event object for `SHOW CREATE EVENT`.
2433    Event,
2434    /// A function object for `SHOW CREATE FUNCTION`.
2435    Function,
2436    /// A procedure object for `SHOW CREATE PROCEDURE`.
2437    Procedure,
2438    /// A table object for `SHOW CREATE TABLE`.
2439    Table,
2440    /// A trigger object for `SHOW CREATE TRIGGER`.
2441    Trigger,
2442    /// A view object for `SHOW CREATE VIEW`.
2443    View,
2444}
2445
2446impl fmt::Display for ShowCreateObject {
2447    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2448        match self {
2449            ShowCreateObject::Event => f.write_str("EVENT"),
2450            ShowCreateObject::Function => f.write_str("FUNCTION"),
2451            ShowCreateObject::Procedure => f.write_str("PROCEDURE"),
2452            ShowCreateObject::Table => f.write_str("TABLE"),
2453            ShowCreateObject::Trigger => f.write_str("TRIGGER"),
2454            ShowCreateObject::View => f.write_str("VIEW"),
2455        }
2456    }
2457}
2458
2459#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2460#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2461#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2462/// Objects that can be targeted by a `COMMENT` statement.
2463pub enum CommentObject {
2464    /// An aggregate function.
2465    Aggregate,
2466    /// A collation.
2467    Collation,
2468    /// A table column.
2469    Column,
2470    /// A database.
2471    Database,
2472    /// A domain.
2473    Domain,
2474    /// An extension.
2475    Extension,
2476    /// A function.
2477    Function,
2478    /// An index.
2479    Index,
2480    /// A materialized view.
2481    MaterializedView,
2482    /// A row-level security policy.
2483    Policy,
2484    /// A procedure.
2485    Procedure,
2486    /// A role.
2487    Role,
2488    /// A schema.
2489    Schema,
2490    /// A sequence.
2491    Sequence,
2492    /// A table.
2493    Table,
2494    /// A trigger.
2495    Trigger,
2496    /// A type.
2497    Type,
2498    /// A user.
2499    User,
2500    /// A view.
2501    View,
2502}
2503
2504impl CommentObject {
2505    pub(crate) fn keyword_str(&self) -> &'static str {
2506        match self {
2507            CommentObject::Aggregate => "AGGREGATE",
2508            CommentObject::Collation => "COLLATION",
2509            CommentObject::Column => "COLUMN",
2510            CommentObject::Database => "DATABASE",
2511            CommentObject::Domain => "DOMAIN",
2512            CommentObject::Extension => "EXTENSION",
2513            CommentObject::Function => "FUNCTION",
2514            CommentObject::Index => "INDEX",
2515            CommentObject::MaterializedView => "MATERIALIZED VIEW",
2516            CommentObject::Policy => "POLICY",
2517            CommentObject::Procedure => "PROCEDURE",
2518            CommentObject::Role => "ROLE",
2519            CommentObject::Schema => "SCHEMA",
2520            CommentObject::Sequence => "SEQUENCE",
2521            CommentObject::Table => "TABLE",
2522            CommentObject::Trigger => "TRIGGER",
2523            CommentObject::Type => "TYPE",
2524            CommentObject::User => "USER",
2525            CommentObject::View => "VIEW",
2526        }
2527    }
2528
2529    /// Map a single keyword to its [`CommentObject`].
2530    ///
2531    /// `MATERIALIZED VIEW` is the only multi-keyword case and must be handled
2532    /// by the caller.
2533    pub(crate) fn from_keyword(keyword: Keyword) -> Option<Self> {
2534        Some(match keyword {
2535            Keyword::AGGREGATE => CommentObject::Aggregate,
2536            Keyword::COLLATION => CommentObject::Collation,
2537            Keyword::COLUMN => CommentObject::Column,
2538            Keyword::DATABASE => CommentObject::Database,
2539            Keyword::DOMAIN => CommentObject::Domain,
2540            Keyword::EXTENSION => CommentObject::Extension,
2541            Keyword::FUNCTION => CommentObject::Function,
2542            Keyword::INDEX => CommentObject::Index,
2543            Keyword::POLICY => CommentObject::Policy,
2544            Keyword::PROCEDURE => CommentObject::Procedure,
2545            Keyword::ROLE => CommentObject::Role,
2546            Keyword::SCHEMA => CommentObject::Schema,
2547            Keyword::SEQUENCE => CommentObject::Sequence,
2548            Keyword::TABLE => CommentObject::Table,
2549            Keyword::TRIGGER => CommentObject::Trigger,
2550            Keyword::TYPE => CommentObject::Type,
2551            Keyword::USER => CommentObject::User,
2552            Keyword::VIEW => CommentObject::View,
2553            _ => return None,
2554        })
2555    }
2556}
2557
2558impl fmt::Display for CommentObject {
2559    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2560        f.write_str(self.keyword_str())
2561    }
2562}
2563
2564#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2565#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2566#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2567/// Password specification variants used in user-related statements.
2568pub enum Password {
2569    /// A concrete password expression.
2570    Password(Expr),
2571    /// Represents a `NULL` password.
2572    NullPassword,
2573}
2574
2575/// A `CASE` statement.
2576///
2577/// Examples:
2578/// ```sql
2579/// CASE
2580///     WHEN EXISTS(SELECT 1)
2581///         THEN SELECT 1 FROM T;
2582///     WHEN EXISTS(SELECT 2)
2583///         THEN SELECT 1 FROM U;
2584///     ELSE
2585///         SELECT 1 FROM V;
2586/// END CASE;
2587/// ```
2588///
2589/// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#case_search_expression)
2590/// [Snowflake](https://docs.snowflake.com/en/sql-reference/snowflake-scripting/case)
2591#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2592#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2593#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2594pub struct CaseStatement {
2595    /// The `CASE` token that starts the statement.
2596    pub case_token: AttachedToken,
2597    /// Optional expression to match against in `CASE ... WHEN`.
2598    pub match_expr: Option<Expr>,
2599    /// The `WHEN ... THEN` blocks of the `CASE` statement.
2600    pub when_blocks: Vec<ConditionalStatementBlock>,
2601    /// Optional `ELSE` block for the `CASE` statement.
2602    pub else_block: Option<ConditionalStatementBlock>,
2603    /// The last token of the statement (`END` or `CASE`).
2604    pub end_case_token: AttachedToken,
2605}
2606
2607impl fmt::Display for CaseStatement {
2608    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2609        let CaseStatement {
2610            case_token: _,
2611            match_expr,
2612            when_blocks,
2613            else_block,
2614            end_case_token: AttachedToken(end),
2615        } = self;
2616
2617        write!(f, "CASE")?;
2618
2619        if let Some(expr) = match_expr {
2620            write!(f, " {expr}")?;
2621        }
2622
2623        if !when_blocks.is_empty() {
2624            write!(f, " {}", display_separated(when_blocks, " "))?;
2625        }
2626
2627        if let Some(else_block) = else_block {
2628            write!(f, " {else_block}")?;
2629        }
2630
2631        write!(f, " END")?;
2632
2633        if let Token::Word(w) = &end.token {
2634            if w.keyword == Keyword::CASE {
2635                write!(f, " CASE")?;
2636            }
2637        }
2638
2639        Ok(())
2640    }
2641}
2642
2643/// An `IF` statement.
2644///
2645/// Example (BigQuery or Snowflake):
2646/// ```sql
2647/// IF TRUE THEN
2648///     SELECT 1;
2649///     SELECT 2;
2650/// ELSEIF TRUE THEN
2651///     SELECT 3;
2652/// ELSE
2653///     SELECT 4;
2654/// END IF
2655/// ```
2656/// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#if)
2657/// [Snowflake](https://docs.snowflake.com/en/sql-reference/snowflake-scripting/if)
2658///
2659/// Example (MSSQL):
2660/// ```sql
2661/// IF 1=1 SELECT 1 ELSE SELECT 2
2662/// ```
2663/// [MSSQL](https://learn.microsoft.com/en-us/sql/t-sql/language-elements/if-else-transact-sql?view=sql-server-ver16)
2664#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2665#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2666#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2667pub struct IfStatement {
2668    /// The initial `IF` block containing the condition and statements.
2669    pub if_block: ConditionalStatementBlock,
2670    /// Additional `ELSEIF` blocks.
2671    pub elseif_blocks: Vec<ConditionalStatementBlock>,
2672    /// Optional `ELSE` block.
2673    pub else_block: Option<ConditionalStatementBlock>,
2674    /// Optional trailing `END` token for the `IF` statement.
2675    pub end_token: Option<AttachedToken>,
2676}
2677
2678impl fmt::Display for IfStatement {
2679    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2680        let IfStatement {
2681            if_block,
2682            elseif_blocks,
2683            else_block,
2684            end_token,
2685        } = self;
2686
2687        write!(f, "{if_block}")?;
2688
2689        for elseif_block in elseif_blocks {
2690            write!(f, " {elseif_block}")?;
2691        }
2692
2693        if let Some(else_block) = else_block {
2694            write!(f, " {else_block}")?;
2695        }
2696
2697        if let Some(AttachedToken(end_token)) = end_token {
2698            write!(f, " END {end_token}")?;
2699        }
2700
2701        Ok(())
2702    }
2703}
2704
2705/// A `WHILE` statement.
2706///
2707/// Example:
2708/// ```sql
2709/// WHILE @@FETCH_STATUS = 0
2710/// BEGIN
2711///    FETCH NEXT FROM c1 INTO @var1, @var2;
2712/// END
2713/// ```
2714///
2715/// [MsSql](https://learn.microsoft.com/en-us/sql/t-sql/language-elements/while-transact-sql)
2716#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2717#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2718#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2719pub struct WhileStatement {
2720    /// Block executed while the condition holds.
2721    pub while_block: ConditionalStatementBlock,
2722}
2723
2724impl fmt::Display for WhileStatement {
2725    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2726        let WhileStatement { while_block } = self;
2727        write!(f, "{while_block}")?;
2728        Ok(())
2729    }
2730}
2731
2732/// A block within a [Statement::Case] or [Statement::If] or [Statement::While]-like statement
2733///
2734/// Example 1:
2735/// ```sql
2736/// WHEN EXISTS(SELECT 1) THEN SELECT 1;
2737/// ```
2738///
2739/// Example 2:
2740/// ```sql
2741/// IF TRUE THEN SELECT 1; SELECT 2;
2742/// ```
2743///
2744/// Example 3:
2745/// ```sql
2746/// ELSE SELECT 1; SELECT 2;
2747/// ```
2748///
2749/// Example 4:
2750/// ```sql
2751/// WHILE @@FETCH_STATUS = 0
2752/// BEGIN
2753///    FETCH NEXT FROM c1 INTO @var1, @var2;
2754/// END
2755/// ```
2756#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2757#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2758#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2759pub struct ConditionalStatementBlock {
2760    /// Token representing the start of the block (e.g., WHEN/IF/WHILE).
2761    pub start_token: AttachedToken,
2762    /// Optional condition expression for the block.
2763    pub condition: Option<Expr>,
2764    /// Optional token for the `THEN` keyword.
2765    pub then_token: Option<AttachedToken>,
2766    /// The statements contained in this conditional block.
2767    pub conditional_statements: ConditionalStatements,
2768}
2769
2770impl ConditionalStatementBlock {
2771    /// Get the statements in this conditional block.
2772    pub fn statements(&self) -> &Vec<Statement> {
2773        self.conditional_statements.statements()
2774    }
2775}
2776
2777impl fmt::Display for ConditionalStatementBlock {
2778    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2779        let ConditionalStatementBlock {
2780            start_token: AttachedToken(start_token),
2781            condition,
2782            then_token,
2783            conditional_statements,
2784        } = self;
2785
2786        write!(f, "{start_token}")?;
2787
2788        if let Some(condition) = condition {
2789            write!(f, " {condition}")?;
2790        }
2791
2792        if then_token.is_some() {
2793            write!(f, " THEN")?;
2794        }
2795
2796        if !conditional_statements.statements().is_empty() {
2797            write!(f, " {conditional_statements}")?;
2798        }
2799
2800        Ok(())
2801    }
2802}
2803
2804/// A list of statements in a [ConditionalStatementBlock].
2805#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2806#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2807#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2808/// Statements used inside conditional blocks (`IF`, `WHEN`, `WHILE`).
2809pub enum ConditionalStatements {
2810    /// Simple sequence of statements (no `BEGIN`/`END`).
2811    Sequence {
2812        /// The statements in the sequence.
2813        statements: Vec<Statement>,
2814    },
2815    /// Block enclosed by `BEGIN` and `END`.
2816    BeginEnd(BeginEndStatements),
2817}
2818
2819impl ConditionalStatements {
2820    /// Get the statements in this conditional statements block.
2821    pub fn statements(&self) -> &Vec<Statement> {
2822        match self {
2823            ConditionalStatements::Sequence { statements } => statements,
2824            ConditionalStatements::BeginEnd(bes) => &bes.statements,
2825        }
2826    }
2827}
2828
2829impl fmt::Display for ConditionalStatements {
2830    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2831        match self {
2832            ConditionalStatements::Sequence { statements } => {
2833                if !statements.is_empty() {
2834                    format_statement_list(f, statements)?;
2835                }
2836                Ok(())
2837            }
2838            ConditionalStatements::BeginEnd(bes) => write!(f, "{bes}"),
2839        }
2840    }
2841}
2842
2843/// Represents a list of statements enclosed within `BEGIN` and `END` keywords.
2844/// Example:
2845/// ```sql
2846/// BEGIN
2847///     SELECT 1;
2848///     SELECT 2;
2849/// END
2850/// ```
2851#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2852#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2853#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2854pub struct BeginEndStatements {
2855    /// Token representing the `BEGIN` keyword (may include span info).
2856    pub begin_token: AttachedToken,
2857    /// Statements contained within the block.
2858    pub statements: Vec<Statement>,
2859    /// Token representing the `END` keyword (may include span info).
2860    pub end_token: AttachedToken,
2861}
2862
2863impl fmt::Display for BeginEndStatements {
2864    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2865        let BeginEndStatements {
2866            begin_token: AttachedToken(begin_token),
2867            statements,
2868            end_token: AttachedToken(end_token),
2869        } = self;
2870
2871        if begin_token.token != Token::EOF {
2872            write!(f, "{begin_token} ")?;
2873        }
2874        if !statements.is_empty() {
2875            format_statement_list(f, statements)?;
2876        }
2877        if end_token.token != Token::EOF {
2878            write!(f, " {end_token}")?;
2879        }
2880        Ok(())
2881    }
2882}
2883
2884/// A `RAISE` statement.
2885///
2886/// Examples:
2887/// ```sql
2888/// RAISE USING MESSAGE = 'error';
2889///
2890/// RAISE myerror;
2891/// ```
2892///
2893/// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#raise)
2894/// [Snowflake](https://docs.snowflake.com/en/sql-reference/snowflake-scripting/raise)
2895#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2896#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2897#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2898pub struct RaiseStatement {
2899    /// Optional value provided to the RAISE statement.
2900    pub value: Option<RaiseStatementValue>,
2901}
2902
2903impl fmt::Display for RaiseStatement {
2904    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2905        let RaiseStatement { value } = self;
2906
2907        write!(f, "RAISE")?;
2908        if let Some(value) = value {
2909            write!(f, " {value}")?;
2910        }
2911
2912        Ok(())
2913    }
2914}
2915
2916/// Represents the error value of a [RaiseStatement].
2917#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2918#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2919#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2920pub enum RaiseStatementValue {
2921    /// `RAISE USING MESSAGE = 'error'`
2922    UsingMessage(Expr),
2923    /// `RAISE myerror`
2924    Expr(Expr),
2925}
2926
2927impl fmt::Display for RaiseStatementValue {
2928    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2929        match self {
2930            RaiseStatementValue::Expr(expr) => write!(f, "{expr}"),
2931            RaiseStatementValue::UsingMessage(expr) => write!(f, "USING MESSAGE = {expr}"),
2932        }
2933    }
2934}
2935
2936/// A MSSQL `THROW` statement.
2937///
2938/// ```sql
2939/// THROW [ error_number, message, state ]
2940/// ```
2941///
2942/// [MSSQL](https://learn.microsoft.com/en-us/sql/t-sql/language-elements/throw-transact-sql)
2943#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2944#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2945#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2946pub struct ThrowStatement {
2947    /// Error number expression.
2948    pub error_number: Option<Box<Expr>>,
2949    /// Error message expression.
2950    pub message: Option<Box<Expr>>,
2951    /// State expression.
2952    pub state: Option<Box<Expr>>,
2953}
2954
2955impl fmt::Display for ThrowStatement {
2956    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2957        let ThrowStatement {
2958            error_number,
2959            message,
2960            state,
2961        } = self;
2962
2963        write!(f, "THROW")?;
2964        if let (Some(error_number), Some(message), Some(state)) = (error_number, message, state) {
2965            write!(f, " {error_number}, {message}, {state}")?;
2966        }
2967        Ok(())
2968    }
2969}
2970
2971/// Represents an expression assignment within a variable `DECLARE` statement.
2972///
2973/// Examples:
2974/// ```sql
2975/// DECLARE variable_name := 42
2976/// DECLARE variable_name DEFAULT 42
2977/// ```
2978#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2979#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2980#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2981pub enum DeclareAssignment {
2982    /// Plain expression specified.
2983    Expr(Box<Expr>),
2984
2985    /// Expression assigned via the `DEFAULT` keyword
2986    Default(Box<Expr>),
2987
2988    /// Expression assigned via the `:=` syntax
2989    ///
2990    /// Example:
2991    /// ```sql
2992    /// DECLARE variable_name := 42;
2993    /// ```
2994    DuckAssignment(Box<Expr>),
2995
2996    /// Expression via the `FOR` keyword
2997    ///
2998    /// Example:
2999    /// ```sql
3000    /// DECLARE c1 CURSOR FOR res
3001    /// ```
3002    For(Box<Expr>),
3003
3004    /// Expression via the `=` syntax.
3005    ///
3006    /// Example:
3007    /// ```sql
3008    /// DECLARE @variable AS INT = 100
3009    /// ```
3010    MsSqlAssignment(Box<Expr>),
3011}
3012
3013impl fmt::Display for DeclareAssignment {
3014    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3015        match self {
3016            DeclareAssignment::Expr(expr) => {
3017                write!(f, "{expr}")
3018            }
3019            DeclareAssignment::Default(expr) => {
3020                write!(f, "DEFAULT {expr}")
3021            }
3022            DeclareAssignment::DuckAssignment(expr) => {
3023                write!(f, ":= {expr}")
3024            }
3025            DeclareAssignment::MsSqlAssignment(expr) => {
3026                write!(f, "= {expr}")
3027            }
3028            DeclareAssignment::For(expr) => {
3029                write!(f, "FOR {expr}")
3030            }
3031        }
3032    }
3033}
3034
3035/// Represents the type of a `DECLARE` statement.
3036#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3037#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3038#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3039pub enum DeclareType {
3040    /// Cursor variable type. e.g. [Snowflake] [PostgreSQL] [MsSql]
3041    ///
3042    /// [Snowflake]: https://docs.snowflake.com/en/developer-guide/snowflake-scripting/cursors#declaring-a-cursor
3043    /// [PostgreSQL]: https://www.postgresql.org/docs/current/plpgsql-cursors.html
3044    /// [MsSql]: https://learn.microsoft.com/en-us/sql/t-sql/language-elements/declare-cursor-transact-sql
3045    Cursor,
3046
3047    /// Result set variable type. [Snowflake]
3048    ///
3049    /// Syntax:
3050    /// ```text
3051    /// <resultset_name> RESULTSET [ { DEFAULT | := } ( <query> ) ] ;
3052    /// ```
3053    /// [Snowflake]: https://docs.snowflake.com/en/sql-reference/snowflake-scripting/declare#resultset-declaration-syntax
3054    ResultSet,
3055
3056    /// Exception declaration syntax. [Snowflake]
3057    ///
3058    /// Syntax:
3059    /// ```text
3060    /// <exception_name> EXCEPTION [ ( <exception_number> , '<exception_message>' ) ] ;
3061    /// ```
3062    /// [Snowflake]: https://docs.snowflake.com/en/sql-reference/snowflake-scripting/declare#exception-declaration-syntax
3063    Exception,
3064}
3065
3066impl fmt::Display for DeclareType {
3067    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3068        match self {
3069            DeclareType::Cursor => {
3070                write!(f, "CURSOR")
3071            }
3072            DeclareType::ResultSet => {
3073                write!(f, "RESULTSET")
3074            }
3075            DeclareType::Exception => {
3076                write!(f, "EXCEPTION")
3077            }
3078        }
3079    }
3080}
3081
3082/// A `DECLARE` statement.
3083/// [PostgreSQL] [Snowflake] [BigQuery]
3084///
3085/// Examples:
3086/// ```sql
3087/// DECLARE variable_name := 42
3088/// DECLARE liahona CURSOR FOR SELECT * FROM films;
3089/// ```
3090///
3091/// [PostgreSQL]: https://www.postgresql.org/docs/current/sql-declare.html
3092/// [Snowflake]: https://docs.snowflake.com/en/sql-reference/snowflake-scripting/declare
3093/// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#declare
3094#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3095#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3096#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3097pub struct Declare {
3098    /// The name(s) being declared.
3099    /// Example: `DECLARE a, b, c DEFAULT 42;
3100    pub names: Vec<Ident>,
3101    /// Data-type assigned to the declared variable.
3102    /// Example: `DECLARE x INT64 DEFAULT 42;
3103    pub data_type: Option<DataType>,
3104    /// Expression being assigned to the declared variable.
3105    pub assignment: Option<DeclareAssignment>,
3106    /// Represents the type of the declared variable.
3107    pub declare_type: Option<DeclareType>,
3108    /// Causes the cursor to return data in binary rather than in text format.
3109    pub binary: Option<bool>,
3110    /// None = Not specified
3111    /// Some(true) = INSENSITIVE
3112    /// Some(false) = ASENSITIVE
3113    pub sensitive: Option<bool>,
3114    /// None = Not specified
3115    /// Some(true) = SCROLL
3116    /// Some(false) = NO SCROLL
3117    pub scroll: Option<bool>,
3118    /// None = Not specified
3119    /// Some(true) = WITH HOLD, specifies that the cursor can continue to be used after the transaction that created it successfully commits
3120    /// Some(false) = WITHOUT HOLD, specifies that the cursor cannot be used outside of the transaction that created it
3121    pub hold: Option<bool>,
3122    /// `FOR <query>` clause in a CURSOR declaration.
3123    pub for_query: Option<Box<Query>>,
3124}
3125
3126impl fmt::Display for Declare {
3127    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3128        let Declare {
3129            names,
3130            data_type,
3131            assignment,
3132            declare_type,
3133            binary,
3134            sensitive,
3135            scroll,
3136            hold,
3137            for_query,
3138        } = self;
3139        write!(f, "{}", display_comma_separated(names))?;
3140
3141        if let Some(true) = binary {
3142            write!(f, " BINARY")?;
3143        }
3144
3145        if let Some(sensitive) = sensitive {
3146            if *sensitive {
3147                write!(f, " INSENSITIVE")?;
3148            } else {
3149                write!(f, " ASENSITIVE")?;
3150            }
3151        }
3152
3153        if let Some(scroll) = scroll {
3154            if *scroll {
3155                write!(f, " SCROLL")?;
3156            } else {
3157                write!(f, " NO SCROLL")?;
3158            }
3159        }
3160
3161        if let Some(declare_type) = declare_type {
3162            write!(f, " {declare_type}")?;
3163        }
3164
3165        if let Some(hold) = hold {
3166            if *hold {
3167                write!(f, " WITH HOLD")?;
3168            } else {
3169                write!(f, " WITHOUT HOLD")?;
3170            }
3171        }
3172
3173        if let Some(query) = for_query {
3174            write!(f, " FOR {query}")?;
3175        }
3176
3177        if let Some(data_type) = data_type {
3178            write!(f, " {data_type}")?;
3179        }
3180
3181        if let Some(expr) = assignment {
3182            write!(f, " {expr}")?;
3183        }
3184        Ok(())
3185    }
3186}
3187
3188/// Sql options of a `CREATE TABLE` statement.
3189#[derive(Debug, Default, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3190#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3191#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3192/// Options allowed within a `CREATE TABLE` statement.
3193pub enum CreateTableOptions {
3194    /// No options specified.
3195    #[default]
3196    None,
3197    /// Options specified using the `WITH` keyword, e.g. `WITH (k = v)`.
3198    With(Vec<SqlOption>),
3199    /// Options specified using the `OPTIONS(...)` clause.
3200    Options(Vec<SqlOption>),
3201    /// Plain space-separated options.
3202    Plain(Vec<SqlOption>),
3203    /// Table properties (e.g., TBLPROPERTIES / storage properties).
3204    TableProperties(Vec<SqlOption>),
3205}
3206
3207impl fmt::Display for CreateTableOptions {
3208    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3209        match self {
3210            CreateTableOptions::With(with_options) => {
3211                write!(f, "WITH ({})", display_comma_separated(with_options))
3212            }
3213            CreateTableOptions::Options(options) => {
3214                write!(f, "OPTIONS({})", display_comma_separated(options))
3215            }
3216            CreateTableOptions::TableProperties(options) => {
3217                write!(f, "TBLPROPERTIES ({})", display_comma_separated(options))
3218            }
3219            CreateTableOptions::Plain(options) => {
3220                write!(f, "{}", display_separated(options, " "))
3221            }
3222            CreateTableOptions::None => Ok(()),
3223        }
3224    }
3225}
3226
3227/// A `FROM` clause within a `DELETE` statement.
3228///
3229/// Syntax
3230/// ```sql
3231/// [FROM] table
3232/// ```
3233#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3234#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3235#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3236pub enum FromTable {
3237    /// An explicit `FROM` keyword was specified.
3238    WithFromKeyword(Vec<TableWithJoins>),
3239    /// BigQuery: `FROM` keyword was omitted.
3240    /// <https://cloud.google.com/bigquery/docs/reference/standard-sql/dml-syntax#delete_statement>
3241    WithoutKeyword(Vec<TableWithJoins>),
3242}
3243impl Display for FromTable {
3244    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3245        match self {
3246            FromTable::WithFromKeyword(tables) => {
3247                write!(f, "FROM {}", display_comma_separated(tables))
3248            }
3249            FromTable::WithoutKeyword(tables) => {
3250                write!(f, "{}", display_comma_separated(tables))
3251            }
3252        }
3253    }
3254}
3255
3256#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3257#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3258#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3259/// Variants for the `SET` family of statements.
3260pub enum Set {
3261    /// SQL Standard-style
3262    /// SET a = 1;
3263    /// `SET var = value` (standard SQL-style assignment).
3264    SingleAssignment {
3265        /// Optional scope modifier (`SESSION` / `LOCAL`).
3266        scope: Option<ContextModifier>,
3267        /// Whether this is a Hive-style `HIVEVAR:` assignment.
3268        hivevar: bool,
3269        /// Variable name to assign.
3270        variable: ObjectName,
3271        /// Values assigned to the variable.
3272        values: Vec<Expr>,
3273    },
3274    /// Snowflake-style
3275    /// SET (a, b, ..) = (1, 2, ..);
3276    /// `SET (a, b) = (1, 2)` (tuple assignment syntax).
3277    ParenthesizedAssignments {
3278        /// Variables being assigned in tuple form.
3279        variables: Vec<ObjectName>,
3280        /// Corresponding values for the variables.
3281        values: Vec<Expr>,
3282    },
3283    /// MySQL-style
3284    /// SET a = 1, b = 2, ..;
3285    /// `SET a = 1, b = 2` (MySQL-style comma-separated assignments).
3286    MultipleAssignments {
3287        /// List of `SET` assignments (MySQL-style comma-separated).
3288        assignments: Vec<SetAssignment>,
3289    },
3290    /// Session authorization for Postgres/Redshift
3291    ///
3292    /// ```sql
3293    /// SET SESSION AUTHORIZATION { user_name | DEFAULT }
3294    /// ```
3295    ///
3296    /// See <https://www.postgresql.org/docs/current/sql-set-session-authorization.html>
3297    /// See <https://docs.aws.amazon.com/redshift/latest/dg/r_SET_SESSION_AUTHORIZATION.html>
3298    SetSessionAuthorization(SetSessionAuthorizationParam),
3299    /// MS-SQL session
3300    ///
3301    /// See <https://learn.microsoft.com/en-us/sql/t-sql/statements/set-statements-transact-sql>
3302    SetSessionParam(SetSessionParamKind),
3303    /// ```sql
3304    /// SET [ SESSION | LOCAL ] ROLE role_name
3305    /// ```
3306    ///
3307    /// Sets session state. Examples: [ANSI][1], [Postgresql][2], [MySQL][3], and [Oracle][4]
3308    ///
3309    /// [1]: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#set-role-statement
3310    /// [2]: https://www.postgresql.org/docs/14/sql-set-role.html
3311    /// [3]: https://dev.mysql.com/doc/refman/8.0/en/set-role.html
3312    /// [4]: https://docs.oracle.com/cd/B19306_01/server.102/b14200/statements_10004.htm
3313    SetRole {
3314        /// Non-ANSI optional identifier to inform if the role is defined inside the current session (`SESSION`) or transaction (`LOCAL`).
3315        context_modifier: Option<ContextModifier>,
3316        /// Role name. If NONE is specified, then the current role name is removed.
3317        role_name: Option<Ident>,
3318    },
3319    /// ```sql
3320    /// SET TIME ZONE <value>
3321    /// ```
3322    ///
3323    /// Note: this is a PostgreSQL-specific statements
3324    /// `SET TIME ZONE <value>` is an alias for `SET timezone TO <value>` in PostgreSQL
3325    /// However, we allow it for all dialects.
3326    /// `SET TIME ZONE` statement. `local` indicates the `LOCAL` keyword.
3327    /// `SET TIME ZONE <value>` statement.
3328    SetTimeZone {
3329        /// Whether the `LOCAL` keyword was specified.
3330        local: bool,
3331        /// Time zone expression value.
3332        value: Expr,
3333    },
3334    /// ```sql
3335    /// SET NAMES 'charset_name' [COLLATE 'collation_name']
3336    /// ```
3337    SetNames {
3338        /// Character set name to set.
3339        charset_name: Ident,
3340        /// Optional collation name.
3341        collation_name: Option<String>,
3342    },
3343    /// ```sql
3344    /// SET NAMES DEFAULT
3345    /// ```
3346    ///
3347    /// Note: this is a MySQL-specific statement.
3348    SetNamesDefault {},
3349    /// ```sql
3350    /// SET TRANSACTION ...
3351    /// ```
3352    SetTransaction {
3353        /// Transaction modes (e.g., ISOLATION LEVEL, READ ONLY).
3354        modes: Vec<TransactionMode>,
3355        /// Optional snapshot value for transaction snapshot control.
3356        snapshot: Option<ValueWithSpan>,
3357        /// `true` when the `SESSION` keyword was used.
3358        session: bool,
3359    },
3360}
3361
3362impl Display for Set {
3363    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3364        match self {
3365            Self::ParenthesizedAssignments { variables, values } => write!(
3366                f,
3367                "SET ({}) = ({})",
3368                display_comma_separated(variables),
3369                display_comma_separated(values)
3370            ),
3371            Self::MultipleAssignments { assignments } => {
3372                write!(f, "SET {}", display_comma_separated(assignments))
3373            }
3374            Self::SetRole {
3375                context_modifier,
3376                role_name,
3377            } => {
3378                let role_name = role_name.clone().unwrap_or_else(|| Ident::new("NONE"));
3379                write!(
3380                    f,
3381                    "SET {modifier}ROLE {role_name}",
3382                    modifier = context_modifier.map(|m| format!("{m}")).unwrap_or_default()
3383                )
3384            }
3385            Self::SetSessionAuthorization(kind) => write!(f, "SET SESSION AUTHORIZATION {kind}"),
3386            Self::SetSessionParam(kind) => write!(f, "SET {kind}"),
3387            Self::SetTransaction {
3388                modes,
3389                snapshot,
3390                session,
3391            } => {
3392                if *session {
3393                    write!(f, "SET SESSION CHARACTERISTICS AS TRANSACTION")?;
3394                } else {
3395                    write!(f, "SET TRANSACTION")?;
3396                }
3397                if !modes.is_empty() {
3398                    write!(f, " {}", display_comma_separated(modes))?;
3399                }
3400                if let Some(snapshot_id) = snapshot {
3401                    write!(f, " SNAPSHOT {snapshot_id}")?;
3402                }
3403                Ok(())
3404            }
3405            Self::SetTimeZone { local, value } => {
3406                f.write_str("SET ")?;
3407                if *local {
3408                    f.write_str("LOCAL ")?;
3409                }
3410                write!(f, "TIME ZONE {value}")
3411            }
3412            Self::SetNames {
3413                charset_name,
3414                collation_name,
3415            } => {
3416                write!(f, "SET NAMES {charset_name}")?;
3417
3418                if let Some(collation) = collation_name {
3419                    f.write_str(" COLLATE ")?;
3420                    f.write_str(collation)?;
3421                };
3422
3423                Ok(())
3424            }
3425            Self::SetNamesDefault {} => {
3426                f.write_str("SET NAMES DEFAULT")?;
3427
3428                Ok(())
3429            }
3430            Set::SingleAssignment {
3431                scope,
3432                hivevar,
3433                variable,
3434                values,
3435            } => {
3436                write!(
3437                    f,
3438                    "SET {}{}{} = {}",
3439                    scope.map(|s| format!("{s}")).unwrap_or_default(),
3440                    if *hivevar { "HIVEVAR:" } else { "" },
3441                    variable,
3442                    display_comma_separated(values)
3443                )
3444            }
3445        }
3446    }
3447}
3448
3449/// A representation of a `WHEN` arm with all the identifiers catched and the statements to execute
3450/// for the arm.
3451///
3452/// Snowflake: <https://docs.snowflake.com/en/sql-reference/snowflake-scripting/exception>
3453/// BigQuery: <https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#beginexceptionend>
3454#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3455#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3456#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3457pub struct ExceptionWhen {
3458    /// Identifiers that trigger this branch (error conditions).
3459    pub idents: Vec<Ident>,
3460    /// Statements to execute when the condition matches.
3461    pub statements: Vec<Statement>,
3462}
3463
3464impl Display for ExceptionWhen {
3465    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3466        write!(
3467            f,
3468            "WHEN {idents} THEN",
3469            idents = display_separated(&self.idents, " OR ")
3470        )?;
3471
3472        if !self.statements.is_empty() {
3473            write!(f, " ")?;
3474            format_statement_list(f, &self.statements)?;
3475        }
3476
3477        Ok(())
3478    }
3479}
3480
3481/// ANALYZE statement
3482///
3483/// Supported syntax varies by dialect:
3484/// - Hive: `ANALYZE TABLE t [PARTITION (...)] COMPUTE STATISTICS [NOSCAN] [FOR COLUMNS [col1, ...]] [CACHE METADATA]`
3485/// - PostgreSQL: `ANALYZE [VERBOSE] [t [(col1, ...)]]` See <https://www.postgresql.org/docs/current/sql-analyze.html>
3486/// - General: `ANALYZE [TABLE] t`
3487#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3488#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3489#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3490pub struct Analyze {
3491    #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
3492    /// Name of the table to analyze. `None` for bare `ANALYZE`.
3493    pub table_name: Option<ObjectName>,
3494    /// Optional partition expressions to restrict the analysis.
3495    pub partitions: Option<Vec<Expr>>,
3496    /// `true` when analyzing specific columns (Hive `FOR COLUMNS` syntax).
3497    pub for_columns: bool,
3498    /// Columns to analyze.
3499    pub columns: Vec<Ident>,
3500    /// Whether to cache metadata before analyzing.
3501    pub cache_metadata: bool,
3502    /// Whether to skip scanning the table.
3503    pub noscan: bool,
3504    /// Whether to compute statistics during analysis.
3505    pub compute_statistics: bool,
3506    /// Whether the `TABLE` keyword was present.
3507    pub has_table_keyword: bool,
3508}
3509
3510impl fmt::Display for Analyze {
3511    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3512        write!(f, "ANALYZE")?;
3513        if let Some(ref table_name) = self.table_name {
3514            if self.has_table_keyword {
3515                write!(f, " TABLE")?;
3516            }
3517            write!(f, " {table_name}")?;
3518        }
3519        if !self.for_columns && !self.columns.is_empty() {
3520            write!(f, " ({})", display_comma_separated(&self.columns))?;
3521        }
3522        if let Some(ref parts) = self.partitions {
3523            if !parts.is_empty() {
3524                write!(f, " PARTITION ({})", display_comma_separated(parts))?;
3525            }
3526        }
3527        if self.compute_statistics {
3528            write!(f, " COMPUTE STATISTICS")?;
3529        }
3530        if self.noscan {
3531            write!(f, " NOSCAN")?;
3532        }
3533        if self.cache_metadata {
3534            write!(f, " CACHE METADATA")?;
3535        }
3536        if self.for_columns {
3537            write!(f, " FOR COLUMNS")?;
3538            if !self.columns.is_empty() {
3539                write!(f, " {}", display_comma_separated(&self.columns))?;
3540            }
3541        }
3542        Ok(())
3543    }
3544}
3545
3546/// A top-level statement (SELECT, INSERT, CREATE, etc.)
3547#[allow(clippy::large_enum_variant)]
3548#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3549#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3550#[cfg_attr(
3551    feature = "visitor",
3552    derive(Visit, VisitMut),
3553    visit(with = "visit_statement")
3554)]
3555pub enum Statement {
3556    /// ```sql
3557    /// ANALYZE
3558    /// ```
3559    /// Analyze (Hive)
3560    Analyze(Analyze),
3561    /// `SET` statements (session, transaction, timezone, etc.).
3562    Set(Set),
3563    /// ```sql
3564    /// TRUNCATE
3565    /// ```
3566    /// Truncate (Hive)
3567    Truncate(Truncate),
3568    /// ```sql
3569    /// MSCK
3570    /// ```
3571    /// Msck (Hive)
3572    Msck(Msck),
3573    /// ```sql
3574    /// SELECT
3575    /// ```
3576    Query(Box<Query>),
3577    /// ```sql
3578    /// INSERT
3579    /// ```
3580    Insert(Insert),
3581    /// ```sql
3582    /// INSTALL
3583    /// ```
3584    Install {
3585        /// Only for DuckDB
3586        extension_name: Ident,
3587    },
3588    /// ```sql
3589    /// LOAD
3590    /// ```
3591    Load {
3592        /// Only for DuckDB
3593        extension_name: Ident,
3594    },
3595    // TODO: Support ROW FORMAT
3596    /// LOAD DATA from a directory or query source.
3597    Directory {
3598        /// Whether to overwrite existing files.
3599        overwrite: bool,
3600        /// Whether the directory is local to the server.
3601        local: bool,
3602        /// Path to the directory or files.
3603        path: String,
3604        /// Optional file format for the data.
3605        file_format: Option<FileFormat>,
3606        /// Source query providing data to load.
3607        source: Box<Query>,
3608    },
3609    /// A `CASE` statement.
3610    Case(CaseStatement),
3611    /// An `IF` statement.
3612    If(IfStatement),
3613    /// A `WHILE` statement.
3614    While(WhileStatement),
3615    /// A `RAISE` statement.
3616    Raise(RaiseStatement),
3617    /// ```sql
3618    /// CALL <function>
3619    /// ```
3620    Call(Function),
3621    /// ```sql
3622    /// COPY [TO | FROM] ...
3623    /// ```
3624    Copy {
3625        /// The source of 'COPY TO', or the target of 'COPY FROM'
3626        source: CopySource,
3627        /// If true, is a 'COPY TO' statement. If false is a 'COPY FROM'
3628        to: bool,
3629        /// The target of 'COPY TO', or the source of 'COPY FROM'
3630        target: CopyTarget,
3631        /// WITH options (from PostgreSQL version 9.0)
3632        options: Vec<CopyOption>,
3633        /// WITH options (before PostgreSQL version 9.0)
3634        legacy_options: Vec<CopyLegacyOption>,
3635        /// VALUES a vector of values to be copied
3636        values: Vec<Option<String>>,
3637    },
3638    /// ```sql
3639    /// COPY INTO <table> | <location>
3640    /// ```
3641    /// See:
3642    /// <https://docs.snowflake.com/en/sql-reference/sql/copy-into-table>
3643    /// <https://docs.snowflake.com/en/sql-reference/sql/copy-into-location>
3644    ///
3645    /// Copy Into syntax available for Snowflake is different than the one implemented in
3646    /// Postgres. Although they share common prefix, it is reasonable to implement them
3647    /// in different enums. This can be refactored later once custom dialects
3648    /// are allowed to have custom Statements.
3649    CopyIntoSnowflake {
3650        /// Kind of COPY INTO operation (table or location).
3651        kind: CopyIntoSnowflakeKind,
3652        /// Target object for the COPY INTO operation.
3653        into: ObjectName,
3654        /// Optional list of target columns.
3655        into_columns: Option<Vec<Ident>>,
3656        /// Optional source object name (staged data).
3657        from_obj: Option<ObjectName>,
3658        /// Optional alias for the source object.
3659        from_obj_alias: Option<Ident>,
3660        /// Stage-specific parameters (e.g., credentials, path).
3661        stage_params: StageParamsObject,
3662        /// Optional list of transformations applied when loading.
3663        from_transformations: Option<Vec<StageLoadSelectItemKind>>,
3664        /// Optional source query instead of a staged object.
3665        from_query: Option<Box<Query>>,
3666        /// Optional list of specific file names to load.
3667        files: Option<Vec<String>>,
3668        /// Optional filename matching pattern.
3669        pattern: Option<String>,
3670        /// File format options.
3671        file_format: KeyValueOptions,
3672        /// Additional copy options.
3673        copy_options: KeyValueOptions,
3674        /// Optional validation mode string.
3675        validation_mode: Option<String>,
3676        /// Optional partition expression for loading.
3677        partition: Option<Box<Expr>>,
3678    },
3679    /// ```sql
3680    /// OPEN cursor_name
3681    /// ```
3682    /// Opens a cursor.
3683    Open(OpenStatement),
3684    /// ```sql
3685    /// CLOSE
3686    /// ```
3687    /// Closes the portal underlying an open cursor.
3688    Close {
3689        /// Cursor name
3690        cursor: CloseCursor,
3691    },
3692    /// ```sql
3693    /// UPDATE
3694    /// ```
3695    Update(Update),
3696    /// ```sql
3697    /// DELETE
3698    /// ```
3699    Delete(Delete),
3700    /// ```sql
3701    /// CREATE VIEW
3702    /// ```
3703    CreateView(CreateView),
3704    /// ```sql
3705    /// CREATE TABLE
3706    /// ```
3707    CreateTable(CreateTable),
3708    /// ```sql
3709    /// CREATE VIRTUAL TABLE .. USING <module_name> (<module_args>)`
3710    /// ```
3711    /// Sqlite specific statement
3712    CreateVirtualTable {
3713        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
3714        /// Name of the virtual table module instance.
3715        name: ObjectName,
3716        /// `true` when `IF NOT EXISTS` was specified.
3717        if_not_exists: bool,
3718        /// Module name used by the virtual table.
3719        module_name: Ident,
3720        /// Arguments passed to the module.
3721        module_args: Vec<Ident>,
3722    },
3723    /// ```sql
3724    /// `CREATE INDEX`
3725    /// ```
3726    CreateIndex(CreateIndex),
3727    /// ```sql
3728    /// CREATE ROLE
3729    /// ```
3730    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createrole.html)
3731    CreateRole(CreateRole),
3732    /// ```sql
3733    /// CREATE SECRET
3734    /// ```
3735    /// See [DuckDB](https://duckdb.org/docs/sql/statements/create_secret.html)
3736    CreateSecret {
3737        /// `true` when `OR REPLACE` was specified.
3738        or_replace: bool,
3739        /// Optional `TEMPORARY` flag.
3740        temporary: Option<bool>,
3741        /// `true` when `IF NOT EXISTS` was present.
3742        if_not_exists: bool,
3743        /// Optional secret name.
3744        name: Option<Ident>,
3745        /// Optional storage specifier identifier.
3746        storage_specifier: Option<Ident>,
3747        /// The secret type identifier.
3748        secret_type: Ident,
3749        /// Additional secret options.
3750        options: Vec<SecretOption>,
3751    },
3752    /// A `CREATE SERVER` statement.
3753    CreateServer(CreateServerStatement),
3754    /// ```sql
3755    /// CREATE FOREIGN DATA WRAPPER
3756    /// ```
3757    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createforeigndatawrapper.html)
3758    CreateForeignDataWrapper(CreateForeignDataWrapper),
3759    /// ```sql
3760    /// CREATE FOREIGN TABLE
3761    /// ```
3762    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createforeigntable.html)
3763    CreateForeignTable(CreateForeignTable),
3764    /// ```sql
3765    /// CREATE POLICY
3766    /// ```
3767    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createpolicy.html)
3768    CreatePolicy(CreatePolicy),
3769    /// ```sql
3770    /// CREATE CONNECTOR
3771    /// ```
3772    /// See [Hive](https://cwiki.apache.org/confluence/pages/viewpage.action?pageId=27362034#LanguageManualDDL-CreateDataConnectorCreateConnector)
3773    CreateConnector(CreateConnector),
3774    /// ```sql
3775    /// CREATE OPERATOR
3776    /// ```
3777    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createoperator.html)
3778    CreateOperator(CreateOperator),
3779    /// ```sql
3780    /// CREATE OPERATOR FAMILY
3781    /// ```
3782    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createopfamily.html)
3783    CreateOperatorFamily(CreateOperatorFamily),
3784    /// ```sql
3785    /// CREATE OPERATOR CLASS
3786    /// ```
3787    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createopclass.html)
3788    CreateOperatorClass(CreateOperatorClass),
3789    /// ```sql
3790    /// CREATE AGGREGATE
3791    /// ```
3792    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createaggregate.html)
3793    CreateAggregate(CreateAggregate),
3794    /// ```sql
3795    /// ALTER TABLE
3796    /// ```
3797    AlterTable(AlterTable),
3798    /// ```sql
3799    /// ALTER SCHEMA
3800    /// ```
3801    /// See [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#alter_schema_collate_statement)
3802    AlterSchema(AlterSchema),
3803    /// ```sql
3804    /// ALTER INDEX
3805    /// ```
3806    AlterIndex {
3807        /// Name of the index to alter.
3808        name: ObjectName,
3809        /// The operation to perform on the index.
3810        operation: AlterIndexOperation,
3811    },
3812    /// ```sql
3813    /// ALTER VIEW
3814    /// ```
3815    AlterView {
3816        /// View name being altered.
3817        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
3818        name: ObjectName,
3819        /// Optional new column list for the view.
3820        columns: Vec<Ident>,
3821        /// Replacement query for the view definition.
3822        query: Box<Query>,
3823        /// Additional WITH options for the view.
3824        with_options: Vec<SqlOption>,
3825    },
3826    /// ```sql
3827    /// ALTER DOMAIN
3828    /// ```
3829    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-alterdomain.html)
3830    AlterDomain(AlterDomain),
3831    /// ```sql
3832    /// ALTER EXTENSION
3833    /// ```
3834    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-alterextension.html)
3835    AlterExtension(AlterExtension),
3836    /// ```sql
3837    /// ALTER FUNCTION
3838    /// ALTER AGGREGATE
3839    /// ALTER PROCEDURE
3840    /// ```
3841    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-alterfunction.html)
3842    /// and [PostgreSQL](https://www.postgresql.org/docs/current/sql-alteraggregate.html)
3843    /// and [PostgreSQL](https://www.postgresql.org/docs/current/sql-alterprocedure.html)
3844    AlterFunction(AlterFunction),
3845    /// ```sql
3846    /// ALTER TYPE
3847    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-altertype.html)
3848    /// ```
3849    AlterType(AlterType),
3850    /// ```sql
3851    /// ALTER TRIGGER
3852    /// ```
3853    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-altertrigger.html)
3854    AlterTrigger(AlterTrigger),
3855    /// ```sql
3856    /// ALTER COLLATION
3857    /// ```
3858    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-altercollation.html)
3859    AlterCollation(AlterCollation),
3860    /// ```sql
3861    /// ALTER DEFAULT PRIVILEGES
3862    ///     [ FOR { ROLE | USER } target_role [, ...] ]
3863    ///     [ IN SCHEMA schema_name [, ...] ]
3864    ///     abbreviated_grant_or_revoke
3865    /// ```
3866    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-alterdefaultprivileges.html)
3867    AlterDefaultPrivileges(AlterDefaultPrivileges),
3868    /// ```sql
3869    /// ALTER OPERATOR
3870    /// ```
3871    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-alteroperator.html)
3872    AlterOperator(AlterOperator),
3873    /// ```sql
3874    /// ALTER OPERATOR FAMILY
3875    /// ```
3876    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-alteropfamily.html)
3877    AlterOperatorFamily(AlterOperatorFamily),
3878    /// ```sql
3879    /// ALTER OPERATOR CLASS
3880    /// ```
3881    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-alteropclass.html)
3882    AlterOperatorClass(AlterOperatorClass),
3883    /// ```sql
3884    /// ALTER ROLE
3885    /// ```
3886    AlterRole {
3887        /// Role name being altered.
3888        name: Ident,
3889        /// Operation to perform on the role.
3890        operation: AlterRoleOperation,
3891    },
3892    /// ```sql
3893    /// ALTER POLICY <NAME> ON <TABLE NAME> [<OPERATION>]
3894    /// ```
3895    /// (Postgresql-specific)
3896    AlterPolicy(AlterPolicy),
3897    /// ```sql
3898    /// ALTER CONNECTOR connector_name SET DCPROPERTIES(property_name=property_value, ...);
3899    /// or
3900    /// ALTER CONNECTOR connector_name SET URL new_url;
3901    /// or
3902    /// ALTER CONNECTOR connector_name SET OWNER [USER|ROLE] user_or_role;
3903    /// ```
3904    /// (Hive-specific)
3905    AlterConnector {
3906        /// Name of the connector to alter.
3907        name: Ident,
3908        /// Optional connector properties to set.
3909        properties: Option<Vec<SqlOption>>,
3910        /// Optional new URL for the connector.
3911        url: Option<String>,
3912        /// Optional new owner specification.
3913        owner: Option<ddl::AlterConnectorOwner>,
3914    },
3915    /// ```sql
3916    /// ALTER SESSION SET sessionParam
3917    /// ALTER SESSION UNSET <param_name> [ , <param_name> , ... ]
3918    /// ```
3919    /// See <https://docs.snowflake.com/en/sql-reference/sql/alter-session>
3920    AlterSession {
3921        /// true is to set for the session parameters, false is to unset
3922        set: bool,
3923        /// The session parameters to set or unset
3924        session_params: KeyValueOptions,
3925    },
3926    /// ```sql
3927    /// ATTACH DATABASE 'path/to/file' AS alias
3928    /// ```
3929    /// (SQLite-specific)
3930    AttachDatabase {
3931        /// The name to bind to the newly attached database
3932        schema_name: Ident,
3933        /// An expression that indicates the path to the database file
3934        database_file_name: Expr,
3935        /// true if the syntax is 'ATTACH DATABASE', false if it's just 'ATTACH'
3936        database: bool,
3937    },
3938    /// (DuckDB-specific)
3939    /// ```sql
3940    /// ATTACH 'sqlite_file.db' AS sqlite_db (READ_ONLY, TYPE SQLITE);
3941    /// ```
3942    /// See <https://duckdb.org/docs/sql/statements/attach.html>
3943    AttachDuckDBDatabase {
3944        /// `true` when `IF NOT EXISTS` was present.
3945        if_not_exists: bool,
3946        /// `true` if the syntax used `ATTACH DATABASE` rather than `ATTACH`.
3947        database: bool,
3948        /// The path identifier to the database file being attached.
3949        database_path: Ident,
3950        /// Optional alias assigned to the attached database.
3951        database_alias: Option<Ident>,
3952        /// Dialect-specific attach options (e.g., `READ_ONLY`).
3953        attach_options: Vec<AttachDuckDBDatabaseOption>,
3954    },
3955    /// (DuckDB-specific)
3956    /// ```sql
3957    /// DETACH db_alias;
3958    /// ```
3959    /// See <https://duckdb.org/docs/sql/statements/attach.html>
3960    DetachDuckDBDatabase {
3961        /// `true` when `IF EXISTS` was present.
3962        if_exists: bool,
3963        /// `true` if the syntax used `DETACH DATABASE` rather than `DETACH`.
3964        database: bool,
3965        /// Alias of the database to detach.
3966        database_alias: Ident,
3967    },
3968    /// ```sql
3969    /// DROP [TABLE, VIEW, ...]
3970    /// ```
3971    Drop {
3972        /// The type of the object to drop: TABLE, VIEW, etc.
3973        object_type: ObjectType,
3974        /// An optional `IF EXISTS` clause. (Non-standard.)
3975        if_exists: bool,
3976        /// One or more objects to drop. (ANSI SQL requires exactly one.)
3977        names: Vec<ObjectName>,
3978        /// Whether `CASCADE` was specified. This will be `false` when
3979        /// `RESTRICT` or no drop behavior at all was specified.
3980        cascade: bool,
3981        /// Whether `RESTRICT` was specified. This will be `false` when
3982        /// `CASCADE` or no drop behavior at all was specified.
3983        restrict: bool,
3984        /// Hive allows you specify whether the table's stored data will be
3985        /// deleted along with the dropped table
3986        purge: bool,
3987        /// MySQL-specific "TEMPORARY" keyword
3988        temporary: bool,
3989        /// MySQL-specific drop index syntax, which requires table specification
3990        /// See <https://dev.mysql.com/doc/refman/8.4/en/drop-index.html>
3991        table: Option<ObjectName>,
3992    },
3993    /// ```sql
3994    /// DROP FUNCTION
3995    /// ```
3996    DropFunction(DropFunction),
3997    /// ```sql
3998    /// DROP DOMAIN
3999    /// ```
4000    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-dropdomain.html)
4001    ///
4002    /// DROP DOMAIN [ IF EXISTS ] name [, ...] [ CASCADE | RESTRICT ]
4003    ///
4004    DropDomain(DropDomain),
4005    /// ```sql
4006    /// DROP PROCEDURE
4007    /// ```
4008    DropProcedure {
4009        /// `true` when `IF EXISTS` was present.
4010        if_exists: bool,
4011        /// One or more functions/procedures to drop.
4012        proc_desc: Vec<FunctionDesc>,
4013        /// Optional drop behavior (`CASCADE` or `RESTRICT`).
4014        drop_behavior: Option<DropBehavior>,
4015    },
4016    /// ```sql
4017    /// DROP SECRET
4018    /// ```
4019    DropSecret {
4020        /// `true` when `IF EXISTS` was present.
4021        if_exists: bool,
4022        /// Optional `TEMPORARY` marker.
4023        temporary: Option<bool>,
4024        /// Name of the secret to drop.
4025        name: Ident,
4026        /// Optional storage specifier identifier.
4027        storage_specifier: Option<Ident>,
4028    },
4029    ///```sql
4030    /// DROP POLICY
4031    /// ```
4032    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-droppolicy.html)
4033    DropPolicy(DropPolicy),
4034    /// ```sql
4035    /// DROP CONNECTOR
4036    /// ```
4037    /// See [Hive](https://cwiki.apache.org/confluence/pages/viewpage.action?pageId=27362034#LanguageManualDDL-DropConnector)
4038    DropConnector {
4039        /// `true` when `IF EXISTS` was present.
4040        if_exists: bool,
4041        /// Name of the connector to drop.
4042        name: Ident,
4043    },
4044    /// ```sql
4045    /// DECLARE
4046    /// ```
4047    /// Declare Cursor Variables
4048    ///
4049    /// Note: this is a PostgreSQL-specific statement,
4050    /// but may also compatible with other SQL.
4051    Declare {
4052        /// Cursor declaration statements collected by `DECLARE`.
4053        stmts: Vec<Declare>,
4054    },
4055    /// ```sql
4056    /// CREATE EXTENSION [ IF NOT EXISTS ] extension_name
4057    ///     [ WITH ] [ SCHEMA schema_name ]
4058    ///              [ VERSION version ]
4059    ///              [ CASCADE ]
4060    /// ```
4061    ///
4062    /// Note: this is a PostgreSQL-specific statement,
4063    CreateExtension(CreateExtension),
4064    /// ```sql
4065    /// CREATE COLLATION
4066    /// ```
4067    /// Note: this is a PostgreSQL-specific statement.
4068    /// <https://www.postgresql.org/docs/current/sql-createcollation.html>
4069    CreateCollation(CreateCollation),
4070    /// ```sql
4071    /// CREATE TEXT SEARCH CONFIGURATION name ( PARSER = parser_name )
4072    /// ```
4073    /// Note: this is a PostgreSQL-specific statement.
4074    /// <https://www.postgresql.org/docs/current/sql-createtsconfig.html>
4075    CreateTextSearchConfiguration(CreateTextSearchConfiguration),
4076    /// ```sql
4077    /// CREATE TEXT SEARCH DICTIONARY name ( TEMPLATE = template_name [, option = value, ...] )
4078    /// ```
4079    /// Note: this is a PostgreSQL-specific statement.
4080    /// <https://www.postgresql.org/docs/current/sql-createtsdictionary.html>
4081    CreateTextSearchDictionary(CreateTextSearchDictionary),
4082    /// ```sql
4083    /// CREATE TEXT SEARCH PARSER name ( START = start_fn, GETTOKEN = gettoken_fn, END = end_fn, LEXTYPES = lextypes_fn [, HEADLINE = headline_fn] )
4084    /// ```
4085    /// Note: this is a PostgreSQL-specific statement.
4086    /// <https://www.postgresql.org/docs/current/sql-createtsparser.html>
4087    CreateTextSearchParser(CreateTextSearchParser),
4088    /// ```sql
4089    /// CREATE TEXT SEARCH TEMPLATE name ( [INIT = init_fn,] LEXIZE = lexize_fn )
4090    /// ```
4091    /// Note: this is a PostgreSQL-specific statement.
4092    /// <https://www.postgresql.org/docs/current/sql-createtstemplate.html>
4093    CreateTextSearchTemplate(CreateTextSearchTemplate),
4094    /// ```sql
4095    /// CREATE PUBLICATION name [ FOR ALL TABLES | FOR TABLE table [, ...] | FOR TABLES IN SCHEMA schema [, ...] ] [ WITH ( option = value [, ...] ) ]
4096    /// ```
4097    /// Note: this is a PostgreSQL-specific statement.
4098    /// <https://www.postgresql.org/docs/current/sql-createpublication.html>
4099    CreatePublication(CreatePublication),
4100    /// ```sql
4101    /// CREATE SUBSCRIPTION name CONNECTION 'conninfo' PUBLICATION publication_name [, ...] [ WITH ( option = value [, ...] ) ]
4102    /// ```
4103    /// Note: this is a PostgreSQL-specific statement.
4104    /// <https://www.postgresql.org/docs/current/sql-createsubscription.html>
4105    CreateSubscription(CreateSubscription),
4106    /// ```sql
4107    /// CREATE CAST (source_type AS target_type) WITH FUNCTION func_name [(arg_types)] [AS ASSIGNMENT | AS IMPLICIT]
4108    /// CREATE CAST (source_type AS target_type) WITHOUT FUNCTION [AS ASSIGNMENT | AS IMPLICIT]
4109    /// CREATE CAST (source_type AS target_type) WITH INOUT [AS ASSIGNMENT | AS IMPLICIT]
4110    /// ```
4111    /// Note: this is a PostgreSQL-specific statement.
4112    /// <https://www.postgresql.org/docs/current/sql-createcast.html>
4113    CreateCast(CreateCast),
4114    /// ```sql
4115    /// CREATE [DEFAULT] CONVERSION name FOR 'source_encoding' TO 'dest_encoding' FROM function_name
4116    /// ```
4117    /// Note: this is a PostgreSQL-specific statement.
4118    /// <https://www.postgresql.org/docs/current/sql-createconversion.html>
4119    CreateConversion(CreateConversion),
4120    /// ```sql
4121    /// CREATE [OR REPLACE] [TRUSTED] [PROCEDURAL] LANGUAGE name [HANDLER handler_func] [INLINE inline_func] [VALIDATOR validator_func | NO VALIDATOR]
4122    /// ```
4123    /// Note: this is a PostgreSQL-specific statement.
4124    /// <https://www.postgresql.org/docs/current/sql-createlanguage.html>
4125    CreateLanguage(CreateLanguage),
4126    /// ```sql
4127    /// CREATE RULE name AS ON event TO table [WHERE condition] DO [ALSO | INSTEAD] { NOTHING | command | (command ; ...) }
4128    /// ```
4129    /// Note: this is a PostgreSQL-specific statement.
4130    /// <https://www.postgresql.org/docs/current/sql-createrule.html>
4131    CreateRule(CreateRule),
4132    /// ```sql
4133    /// CREATE STATISTICS [ IF NOT EXISTS ] name [ ( kind [, ...] ) ] ON expr [, ...] FROM table_name
4134    /// ```
4135    /// Note: this is a PostgreSQL-specific statement.
4136    /// <https://www.postgresql.org/docs/current/sql-createstatistics.html>
4137    CreateStatistics(CreateStatistics),
4138    /// ```sql
4139    /// CREATE ACCESS METHOD name TYPE INDEX | TABLE HANDLER handler_function
4140    /// ```
4141    /// Note: this is a PostgreSQL-specific statement.
4142    /// <https://www.postgresql.org/docs/current/sql-create-access-method.html>
4143    CreateAccessMethod(CreateAccessMethod),
4144    /// ```sql
4145    /// CREATE EVENT TRIGGER name ON event [ WHEN TAG IN ( 'tag' [, ...] ) ] EXECUTE FUNCTION | PROCEDURE function_name()
4146    /// ```
4147    /// Note: this is a PostgreSQL-specific statement.
4148    /// <https://www.postgresql.org/docs/current/sql-createeventtrigger.html>
4149    CreateEventTrigger(CreateEventTrigger),
4150    /// ```sql
4151    /// CREATE [ OR REPLACE ] TRANSFORM FOR type_name LANGUAGE lang_name ( transform_element_list )
4152    /// ```
4153    /// Note: this is a PostgreSQL-specific statement.
4154    /// <https://www.postgresql.org/docs/current/sql-createtransform.html>
4155    CreateTransform(CreateTransform),
4156    /// ```sql
4157    /// SECURITY LABEL [ FOR provider_name ] ON object_type object_name IS { 'label' | NULL }
4158    /// ```
4159    /// Note: this is a PostgreSQL-specific statement.
4160    /// <https://www.postgresql.org/docs/current/sql-securitylabel.html>
4161    SecurityLabel(SecurityLabel),
4162    /// ```sql
4163    /// CREATE USER MAPPING [ IF NOT EXISTS ] FOR { role | USER | CURRENT_ROLE | CURRENT_USER | PUBLIC } SERVER server_name [ OPTIONS (...) ]
4164    /// ```
4165    /// Note: this is a PostgreSQL-specific statement.
4166    /// <https://www.postgresql.org/docs/current/sql-createusermapping.html>
4167    CreateUserMapping(CreateUserMapping),
4168    /// ```sql
4169    /// CREATE TABLESPACE name [ OWNER role ] LOCATION 'directory' [ WITH (options) ]
4170    /// ```
4171    /// Note: this is a PostgreSQL-specific statement.
4172    /// <https://www.postgresql.org/docs/current/sql-createtablespace.html>
4173    CreateTablespace(CreateTablespace),
4174    /// ```sql
4175    /// DROP EXTENSION [ IF EXISTS ] name [, ...] [ CASCADE | RESTRICT ]
4176    /// ```
4177    /// Note: this is a PostgreSQL-specific statement.
4178    /// <https://www.postgresql.org/docs/current/sql-dropextension.html>
4179    DropExtension(DropExtension),
4180    /// ```sql
4181    /// DROP OPERATOR [ IF EXISTS ] name ( { left_type | NONE } , right_type ) [, ...] [ CASCADE | RESTRICT ]
4182    /// ```
4183    /// Note: this is a PostgreSQL-specific statement.
4184    /// <https://www.postgresql.org/docs/current/sql-dropoperator.html>
4185    DropOperator(DropOperator),
4186    /// ```sql
4187    /// DROP OPERATOR FAMILY [ IF EXISTS ] name USING index_method [ CASCADE | RESTRICT ]
4188    /// ```
4189    /// Note: this is a PostgreSQL-specific statement.
4190    /// <https://www.postgresql.org/docs/current/sql-dropopfamily.html>
4191    DropOperatorFamily(DropOperatorFamily),
4192    /// ```sql
4193    /// DROP OPERATOR CLASS [ IF EXISTS ] name USING index_method [ CASCADE | RESTRICT ]
4194    /// ```
4195    /// Note: this is a PostgreSQL-specific statement.
4196    /// <https://www.postgresql.org/docs/current/sql-dropopclass.html>
4197    DropOperatorClass(DropOperatorClass),
4198    /// ```sql
4199    /// FETCH
4200    /// ```
4201    /// Retrieve rows from a query using a cursor
4202    ///
4203    /// Note: this is a PostgreSQL-specific statement,
4204    /// but may also compatible with other SQL.
4205    Fetch {
4206        /// Cursor name
4207        name: Ident,
4208        /// The fetch direction (e.g., `FORWARD`, `BACKWARD`).
4209        direction: FetchDirection,
4210        /// The fetch position (e.g., `ALL`, `NEXT`, `ABSOLUTE`).
4211        position: FetchPosition,
4212        /// Optional target table to fetch rows into.
4213        into: Option<ObjectName>,
4214    },
4215    /// ```sql
4216    /// FLUSH [NO_WRITE_TO_BINLOG | LOCAL] flush_option [, flush_option] ... | tables_option
4217    /// ```
4218    ///
4219    /// Note: this is a Mysql-specific statement,
4220    /// but may also compatible with other SQL.
4221    Flush {
4222        /// The specific flush option or object to flush.
4223        object_type: FlushType,
4224        /// Optional flush location (dialect-specific).
4225        location: Option<FlushLocation>,
4226        /// Optional channel name used for flush operations.
4227        channel: Option<String>,
4228        /// Whether a read lock was requested.
4229        read_lock: bool,
4230        /// Whether this is an export flush operation.
4231        export: bool,
4232        /// Optional list of tables involved in the flush.
4233        tables: Vec<ObjectName>,
4234    },
4235    /// ```sql
4236    /// DISCARD [ ALL | PLANS | SEQUENCES | TEMPORARY | TEMP ]
4237    /// ```
4238    ///
4239    /// Note: this is a PostgreSQL-specific statement,
4240    /// but may also compatible with other SQL.
4241    Discard {
4242        /// The kind of object(s) to discard (ALL, PLANS, etc.).
4243        object_type: DiscardObject,
4244    },
4245    /// `SHOW FUNCTIONS`
4246    ///
4247    /// Note: this is a Presto-specific statement.
4248    ShowFunctions {
4249        /// Optional filter for which functions to display.
4250        filter: Option<ShowStatementFilter>,
4251    },
4252    /// ```sql
4253    /// SHOW <variable>
4254    /// ```
4255    ///
4256    /// Note: this is a PostgreSQL-specific statement.
4257    ShowVariable {
4258        /// Variable name as one or more identifiers.
4259        variable: Vec<Ident>,
4260    },
4261    /// ```sql
4262    /// SHOW [GLOBAL | SESSION] STATUS [LIKE 'pattern' | WHERE expr]
4263    /// ```
4264    ///
4265    /// Note: this is a MySQL-specific statement.
4266    ShowStatus {
4267        /// Optional filter for which status entries to display.
4268        filter: Option<ShowStatementFilter>,
4269        /// `true` when `GLOBAL` scope was requested.
4270        global: bool,
4271        /// `true` when `SESSION` scope was requested.
4272        session: bool,
4273    },
4274    /// ```sql
4275    /// SHOW VARIABLES
4276    /// ```
4277    ///
4278    /// Note: this is a MySQL-specific statement.
4279    ShowVariables {
4280        /// Optional filter for which variables to display.
4281        filter: Option<ShowStatementFilter>,
4282        /// `true` when `GLOBAL` scope was requested.
4283        global: bool,
4284        /// `true` when `SESSION` scope was requested.
4285        session: bool,
4286    },
4287    /// ```sql
4288    /// SHOW CREATE TABLE
4289    /// ```
4290    ///
4291    /// Note: this is a MySQL-specific statement.
4292    ShowCreate {
4293        /// The kind of object being shown (TABLE, VIEW, etc.).
4294        obj_type: ShowCreateObject,
4295        /// The name of the object to show create statement for.
4296        obj_name: ObjectName,
4297    },
4298    /// ```sql
4299    /// SHOW COLUMNS
4300    /// ```
4301    ShowColumns {
4302        /// `true` when extended column information was requested.
4303        extended: bool,
4304        /// `true` when full column details were requested.
4305        full: bool,
4306        /// Additional options for `SHOW COLUMNS`.
4307        show_options: ShowStatementOptions,
4308    },
4309    /// ```sql
4310    /// SHOW CATALOGS
4311    /// ```
4312    ShowCatalogs {
4313        /// `true` when terse output format was requested.
4314        terse: bool,
4315        /// `true` when history information was requested.
4316        history: bool,
4317        /// Additional options for `SHOW CATALOGS`.
4318        show_options: ShowStatementOptions,
4319    },
4320    /// ```sql
4321    /// SHOW DATABASES
4322    /// ```
4323    ShowDatabases {
4324        /// `true` when terse output format was requested.
4325        terse: bool,
4326        /// `true` when history information was requested.
4327        history: bool,
4328        /// Additional options for `SHOW DATABASES`.
4329        show_options: ShowStatementOptions,
4330    },
4331    /// ```sql
4332    /// SHOW [FULL] PROCESSLIST
4333    /// ```
4334    ///
4335    /// Note: this is a MySQL-specific statement.
4336    ShowProcessList {
4337        /// `true` when full process information was requested.
4338        full: bool,
4339    },
4340    /// ```sql
4341    /// SHOW SCHEMAS
4342    /// ```
4343    ShowSchemas {
4344        /// `true` when terse (compact) output was requested.
4345        terse: bool,
4346        /// `true` when history information was requested.
4347        history: bool,
4348        /// Additional options for `SHOW SCHEMAS`.
4349        show_options: ShowStatementOptions,
4350    },
4351    // ```sql
4352    // SHOW {CHARACTER SET | CHARSET}
4353    // ```
4354    // [MySQL]:
4355    // <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>
4356    /// Show the available character sets (alias `CHARSET`).
4357    ShowCharset(ShowCharset),
4358    /// ```sql
4359    /// SHOW OBJECTS LIKE 'line%' IN mydb.public
4360    /// ```
4361    /// Snowflake-specific statement
4362    /// <https://docs.snowflake.com/en/sql-reference/sql/show-objects>
4363    ShowObjects(ShowObjects),
4364    /// ```sql
4365    /// SHOW TABLES
4366    /// ```
4367    ShowTables {
4368        /// `true` when terse output format was requested (compact listing).
4369        terse: bool,
4370        /// `true` when history rows are requested.
4371        history: bool,
4372        /// `true` when extended information should be shown.
4373        extended: bool,
4374        /// `true` when a full listing was requested.
4375        full: bool,
4376        /// `true` when external tables should be included.
4377        external: bool,
4378        /// Additional options for `SHOW` statements.
4379        show_options: ShowStatementOptions,
4380    },
4381    /// ```sql
4382    /// SHOW VIEWS
4383    /// ```
4384    ShowViews {
4385        /// `true` when terse output format was requested.
4386        terse: bool,
4387        /// `true` when materialized views should be included.
4388        materialized: bool,
4389        /// Additional options for `SHOW` statements.
4390        show_options: ShowStatementOptions,
4391    },
4392    /// ```sql
4393    /// SHOW COLLATION
4394    /// ```
4395    ///
4396    /// Note: this is a MySQL-specific statement.
4397    ShowCollation {
4398        /// Optional filter for which collations to display.
4399        filter: Option<ShowStatementFilter>,
4400    },
4401    /// ```sql
4402    /// `USE ...`
4403    /// ```
4404    Use(Use),
4405    /// ```sql
4406    /// START  [ TRANSACTION | WORK ] | START TRANSACTION } ...
4407    /// ```
4408    /// If `begin` is false.
4409    ///
4410    /// ```sql
4411    /// `BEGIN  [ TRANSACTION | WORK ] | START TRANSACTION } ...`
4412    /// ```
4413    /// If `begin` is true
4414    StartTransaction {
4415        /// Transaction modes such as `ISOLATION LEVEL` or `READ WRITE`.
4416        modes: Vec<TransactionMode>,
4417        /// `true` when this was parsed as `BEGIN` instead of `START`.
4418        begin: bool,
4419        /// Optional specific keyword used: `TRANSACTION` or `WORK`.
4420        transaction: Option<BeginTransactionKind>,
4421        /// Optional transaction modifier (e.g., `AND NO CHAIN`).
4422        modifier: Option<TransactionModifier>,
4423        /// List of statements belonging to the `BEGIN` block.
4424        /// Example:
4425        /// ```sql
4426        /// BEGIN
4427        ///     SELECT 1;
4428        ///     SELECT 2;
4429        /// END;
4430        /// ```
4431        statements: Vec<Statement>,
4432        /// Exception handling with exception clauses.
4433        /// Example:
4434        /// ```sql
4435        /// EXCEPTION
4436        ///     WHEN EXCEPTION_1 THEN
4437        ///         SELECT 2;
4438        ///     WHEN EXCEPTION_2 OR EXCEPTION_3 THEN
4439        ///         SELECT 3;
4440        ///     WHEN OTHER THEN
4441        ///         SELECT 4;
4442        /// ```
4443        /// <https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#beginexceptionend>
4444        /// <https://docs.snowflake.com/en/sql-reference/snowflake-scripting/exception>
4445        exception: Option<Vec<ExceptionWhen>>,
4446        /// TRUE if the statement has an `END` keyword.
4447        has_end_keyword: bool,
4448    },
4449    /// ```sql
4450    /// COMMENT ON ...
4451    /// ```
4452    ///
4453    /// Note: this is a PostgreSQL-specific statement.
4454    Comment {
4455        /// Type of object being commented (table, column, etc.).
4456        object_type: CommentObject,
4457        /// Name of the object the comment applies to.
4458        object_name: ObjectName,
4459        /// Argument types for overloaded objects. `Some(vec![])` represents an
4460        /// empty `()` parameter list (e.g. `COMMENT ON FUNCTION f() IS '…'`),
4461        /// while `None` means no parameter list was provided. Used for
4462        /// `FUNCTION`, `PROCEDURE`, and `AGGREGATE` targets.
4463        arguments: Option<Vec<DataType>>,
4464        /// Partner table for objects scoped to a table, i.e. the
4465        /// `ON <table>` tail in `COMMENT ON TRIGGER t ON tbl IS '…'` or
4466        /// `COMMENT ON POLICY p ON tbl IS '…'`.
4467        table_name: Option<ObjectName>,
4468        /// Optional comment text (None to remove comment).
4469        comment: Option<String>,
4470        /// An optional `IF EXISTS` clause. (Non-standard.)
4471        /// See <https://docs.snowflake.com/en/sql-reference/sql/comment>
4472        if_exists: bool,
4473    },
4474    /// ```sql
4475    /// COMMIT [ TRANSACTION | WORK ] [ AND [ NO ] CHAIN ]
4476    /// ```
4477    /// If `end` is false
4478    ///
4479    /// ```sql
4480    /// END [ TRY | CATCH ]
4481    /// ```
4482    /// If `end` is true
4483    Commit {
4484        /// `true` when `AND [ NO ] CHAIN` was present.
4485        chain: bool,
4486        /// `true` when this `COMMIT` was parsed as an `END` block terminator.
4487        end: bool,
4488        /// Optional transaction modifier for commit semantics.
4489        modifier: Option<TransactionModifier>,
4490    },
4491    /// ```sql
4492    /// ROLLBACK [ TRANSACTION | WORK ] [ AND [ NO ] CHAIN ] [ TO [ SAVEPOINT ] savepoint_name ]
4493    /// ```
4494    Rollback {
4495        /// `true` when `AND [ NO ] CHAIN` was present.
4496        chain: bool,
4497        /// Optional savepoint name to roll back to.
4498        savepoint: Option<Ident>,
4499    },
4500    /// ```sql
4501    /// CREATE SCHEMA
4502    /// ```
4503    CreateSchema {
4504        /// `<schema name> | AUTHORIZATION <schema authorization identifier>  | <schema name>  AUTHORIZATION <schema authorization identifier>`
4505        schema_name: SchemaName,
4506        /// `true` when `IF NOT EXISTS` was present.
4507        if_not_exists: bool,
4508        /// Schema properties.
4509        ///
4510        /// ```sql
4511        /// CREATE SCHEMA myschema WITH (key1='value1');
4512        /// ```
4513        ///
4514        /// [Trino](https://trino.io/docs/current/sql/create-schema.html)
4515        with: Option<Vec<SqlOption>>,
4516        /// Schema options.
4517        ///
4518        /// ```sql
4519        /// CREATE SCHEMA myschema OPTIONS(key1='value1');
4520        /// ```
4521        ///
4522        /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_schema_statement)
4523        options: Option<Vec<SqlOption>>,
4524        /// Default collation specification for the schema.
4525        ///
4526        /// ```sql
4527        /// CREATE SCHEMA myschema DEFAULT COLLATE 'und:ci';
4528        /// ```
4529        ///
4530        /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_schema_statement)
4531        default_collate_spec: Option<Expr>,
4532        /// Clones a schema
4533        ///
4534        /// ```sql
4535        /// CREATE SCHEMA myschema CLONE otherschema
4536        /// ```
4537        ///
4538        /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-clone#databases-schemas)
4539        clone: Option<ObjectName>,
4540    },
4541    /// ```sql
4542    /// CREATE DATABASE
4543    /// ```
4544    /// See:
4545    /// <https://docs.snowflake.com/en/sql-reference/sql/create-database>
4546    CreateDatabase {
4547        /// Database name.
4548        db_name: ObjectName,
4549        /// `IF NOT EXISTS` flag.
4550        if_not_exists: bool,
4551        /// Optional location URI.
4552        location: Option<String>,
4553        /// Optional managed location.
4554        managed_location: Option<String>,
4555        /// `OR REPLACE` flag.
4556        or_replace: bool,
4557        /// `TRANSIENT` flag.
4558        transient: bool,
4559        /// Optional clone source.
4560        clone: Option<ObjectName>,
4561        /// Optional data retention time in days.
4562        data_retention_time_in_days: Option<u64>,
4563        /// Optional maximum data extension time in days.
4564        max_data_extension_time_in_days: Option<u64>,
4565        /// Optional external volume identifier.
4566        external_volume: Option<String>,
4567        /// Optional catalog name.
4568        catalog: Option<String>,
4569        /// Whether to replace invalid characters.
4570        replace_invalid_characters: Option<bool>,
4571        /// Default DDL collation string.
4572        default_ddl_collation: Option<String>,
4573        /// Storage serialization policy.
4574        storage_serialization_policy: Option<StorageSerializationPolicy>,
4575        /// Optional comment.
4576        comment: Option<String>,
4577        /// Optional default character set (MySQL).
4578        default_charset: Option<String>,
4579        /// Optional default collation (MySQL).
4580        default_collation: Option<String>,
4581        /// Optional catalog sync identifier.
4582        catalog_sync: Option<String>,
4583        /// Catalog sync namespace mode.
4584        catalog_sync_namespace_mode: Option<CatalogSyncNamespaceMode>,
4585        /// Optional flatten delimiter for namespace sync.
4586        catalog_sync_namespace_flatten_delimiter: Option<String>,
4587        /// Optional tags for the database.
4588        with_tags: Option<Vec<Tag>>,
4589        /// Optional contact entries for the database.
4590        with_contacts: Option<Vec<ContactEntry>>,
4591    },
4592    /// ```sql
4593    /// CREATE FUNCTION
4594    /// ```
4595    ///
4596    /// Supported variants:
4597    /// 1. [Hive](https://cwiki.apache.org/confluence/display/hive/languagemanual+ddl#LanguageManualDDL-Create/Drop/ReloadFunction)
4598    /// 2. [PostgreSQL](https://www.postgresql.org/docs/15/sql-createfunction.html)
4599    /// 3. [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_function_statement)
4600    /// 4. [MsSql](https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql)
4601    CreateFunction(CreateFunction),
4602    /// CREATE TRIGGER statement. See struct [CreateTrigger] for details.
4603    CreateTrigger(CreateTrigger),
4604    /// DROP TRIGGER statement. See struct [DropTrigger] for details.
4605    DropTrigger(DropTrigger),
4606    /// ```sql
4607    /// CREATE PROCEDURE
4608    /// ```
4609    CreateProcedure {
4610        /// `OR ALTER` flag.
4611        or_alter: bool,
4612        /// Procedure name.
4613        name: ObjectName,
4614        /// Optional procedure parameters.
4615        params: Option<Vec<ProcedureParam>>,
4616        /// Optional language identifier.
4617        language: Option<Ident>,
4618        /// Procedure body statements.
4619        body: ConditionalStatements,
4620    },
4621    /// ```sql
4622    /// CREATE MACRO
4623    /// ```
4624    ///
4625    /// Supported variants:
4626    /// 1. [DuckDB](https://duckdb.org/docs/sql/statements/create_macro)
4627    CreateMacro {
4628        /// `OR REPLACE` flag.
4629        or_replace: bool,
4630        /// Whether macro is temporary.
4631        temporary: bool,
4632        /// Macro name.
4633        name: ObjectName,
4634        /// Optional macro arguments.
4635        args: Option<Vec<MacroArg>>,
4636        /// Macro definition body.
4637        definition: MacroDefinition,
4638    },
4639    /// ```sql
4640    /// CREATE STAGE
4641    /// ```
4642    /// See <https://docs.snowflake.com/en/sql-reference/sql/create-stage>
4643    CreateStage {
4644        /// `OR REPLACE` flag for stage.
4645        or_replace: bool,
4646        /// Whether stage is temporary.
4647        temporary: bool,
4648        /// `IF NOT EXISTS` flag.
4649        if_not_exists: bool,
4650        /// Stage name.
4651        name: ObjectName,
4652        /// Stage parameters.
4653        stage_params: StageParamsObject,
4654        /// Directory table parameters.
4655        directory_table_params: KeyValueOptions,
4656        /// File format options.
4657        file_format: KeyValueOptions,
4658        /// Copy options for stage.
4659        copy_options: KeyValueOptions,
4660        /// Optional comment.
4661        comment: Option<String>,
4662    },
4663    /// ```sql
4664    /// ASSERT <condition> [AS <message>]
4665    /// ```
4666    Assert {
4667        /// Assertion condition expression.
4668        condition: Expr,
4669        /// Optional message expression.
4670        message: Option<Expr>,
4671    },
4672    /// ```sql
4673    /// GRANT privileges ON objects TO grantees
4674    /// ```
4675    Grant(Grant),
4676    /// ```sql
4677    /// DENY privileges ON object TO grantees
4678    /// ```
4679    Deny(DenyStatement),
4680    /// ```sql
4681    /// REVOKE privileges ON objects FROM grantees
4682    /// ```
4683    Revoke(Revoke),
4684    /// ```sql
4685    /// DEALLOCATE [ PREPARE ] { name | ALL }
4686    /// ```
4687    ///
4688    /// Note: this is a PostgreSQL-specific statement.
4689    Deallocate {
4690        /// Name to deallocate (or `ALL`).
4691        name: Ident,
4692        /// Whether `PREPARE` keyword was present.
4693        prepare: bool,
4694    },
4695    /// ```sql
4696    /// An `EXECUTE` statement
4697    /// ```
4698    ///
4699    /// Postgres: <https://www.postgresql.org/docs/current/sql-execute.html>
4700    /// MSSQL: <https://learn.microsoft.com/en-us/sql/relational-databases/stored-procedures/execute-a-stored-procedure>
4701    /// BigQuery: <https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#execute_immediate>
4702    /// Snowflake: <https://docs.snowflake.com/en/sql-reference/sql/execute-immediate>
4703    Execute {
4704        /// Optional function/procedure name.
4705        name: Option<ObjectName>,
4706        /// Parameter expressions passed to execute.
4707        parameters: Vec<Expr>,
4708        /// Whether parentheses were present around `parameters`.
4709        has_parentheses: bool,
4710        /// Is this an `EXECUTE IMMEDIATE`.
4711        immediate: bool,
4712        /// Identifiers to capture results into.
4713        into: Vec<Ident>,
4714        /// `USING` expressions with optional aliases.
4715        using: Vec<ExprWithAlias>,
4716        /// Whether the last parameter is the return value of the procedure
4717        /// MSSQL: <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/execute-transact-sql?view=sql-server-ver17#output>
4718        output: bool,
4719        /// Whether to invoke the procedure with the default parameter values
4720        /// MSSQL: <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/execute-transact-sql?view=sql-server-ver17#default>
4721        default: bool,
4722    },
4723    /// ```sql
4724    /// PREPARE name [ ( data_type [, ...] ) ] AS statement
4725    /// ```
4726    ///
4727    /// Note: this is a PostgreSQL-specific statement.
4728    Prepare {
4729        /// Name of the prepared statement.
4730        name: Ident,
4731        /// Optional data types for parameters.
4732        data_types: Vec<DataType>,
4733        /// Statement being prepared.
4734        statement: Box<Statement>,
4735    },
4736    /// ```sql
4737    /// KILL [CONNECTION | QUERY | MUTATION]
4738    /// ```
4739    ///
4740    /// See <https://clickhouse.com/docs/en/sql-reference/statements/kill/>
4741    /// See <https://dev.mysql.com/doc/refman/8.0/en/kill.html>
4742    Kill {
4743        /// Optional kill modifier (CONNECTION, QUERY, MUTATION).
4744        modifier: Option<KillType>,
4745        // processlist_id
4746        /// The id of the process to kill.
4747        id: u64,
4748    },
4749    /// ```sql
4750    /// [EXPLAIN | DESC | DESCRIBE] TABLE
4751    /// ```
4752    /// Note: this is a MySQL-specific statement. See <https://dev.mysql.com/doc/refman/8.0/en/explain.html>
4753    ExplainTable {
4754        /// `EXPLAIN | DESC | DESCRIBE`
4755        describe_alias: DescribeAlias,
4756        /// Hive style `FORMATTED | EXTENDED`
4757        hive_format: Option<HiveDescribeFormat>,
4758        /// Snowflake and ClickHouse support `DESC|DESCRIBE TABLE <table_name>` syntax
4759        ///
4760        /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/desc-table.html)
4761        /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/describe-table)
4762        has_table_keyword: bool,
4763        /// Table name
4764        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
4765        table_name: ObjectName,
4766    },
4767    /// ```sql
4768    /// [EXPLAIN | DESC | DESCRIBE]  <statement>
4769    /// ```
4770    Explain {
4771        /// `EXPLAIN | DESC | DESCRIBE`
4772        describe_alias: DescribeAlias,
4773        /// Carry out the command and show actual run times and other statistics.
4774        analyze: bool,
4775        /// Display additional information regarding the plan.
4776        verbose: bool,
4777        /// `EXPLAIN QUERY PLAN`
4778        /// Display the query plan without running the query.
4779        ///
4780        /// [SQLite](https://sqlite.org/lang_explain.html)
4781        query_plan: bool,
4782        /// `EXPLAIN ESTIMATE`
4783        /// [Clickhouse](https://clickhouse.com/docs/en/sql-reference/statements/explain#explain-estimate)
4784        estimate: bool,
4785        /// A SQL query that specifies what to explain
4786        statement: Box<Statement>,
4787        /// Optional output format of explain
4788        format: Option<AnalyzeFormatKind>,
4789        /// Postgres style utility options, `(analyze, verbose true)`
4790        options: Option<Vec<UtilityOption>>,
4791    },
4792    /// ```sql
4793    /// SAVEPOINT
4794    /// ```
4795    /// Define a new savepoint within the current transaction
4796    Savepoint {
4797        /// Name of the savepoint being defined.
4798        name: Ident,
4799    },
4800    /// ```sql
4801    /// RELEASE [ SAVEPOINT ] savepoint_name
4802    /// ```
4803    ReleaseSavepoint {
4804        /// Name of the savepoint to release.
4805        name: Ident,
4806    },
4807    /// A `MERGE` statement.
4808    ///
4809    /// ```sql
4810    /// MERGE INTO <target_table> USING <source> ON <join_expr> { matchedClause | notMatchedClause } [ ... ]
4811    /// ```
4812    /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/merge)
4813    /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/dml-syntax#merge_statement)
4814    /// [MSSQL](https://learn.microsoft.com/en-us/sql/t-sql/statements/merge-transact-sql?view=sql-server-ver16)
4815    Merge(Merge),
4816    /// ```sql
4817    /// CACHE [ FLAG ] TABLE <table_name> [ OPTIONS('K1' = 'V1', 'K2' = V2) ] [ AS ] [ <query> ]
4818    /// ```
4819    ///
4820    /// See [Spark SQL docs] for more details.
4821    ///
4822    /// [Spark SQL docs]: https://docs.databricks.com/spark/latest/spark-sql/language-manual/sql-ref-syntax-aux-cache-cache-table.html
4823    Cache {
4824        /// Table flag
4825        table_flag: Option<ObjectName>,
4826        /// Table name
4827        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
4828        table_name: ObjectName,
4829        /// `true` if `AS` keyword was present before the query.
4830        has_as: bool,
4831        /// Table confs
4832        options: Vec<SqlOption>,
4833        /// Cache table as a Query
4834        query: Option<Box<Query>>,
4835    },
4836    /// ```sql
4837    /// UNCACHE TABLE [ IF EXISTS ]  <table_name>
4838    /// ```
4839    UNCache {
4840        /// Table name
4841        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
4842        table_name: ObjectName,
4843        /// `true` when `IF EXISTS` was present.
4844        if_exists: bool,
4845    },
4846    /// ```sql
4847    /// CREATE [ { TEMPORARY | TEMP } ] SEQUENCE [ IF NOT EXISTS ] <sequence_name>
4848    /// ```
4849    /// Define a new sequence:
4850    CreateSequence {
4851        /// Whether the sequence is temporary.
4852        temporary: bool,
4853        /// `IF NOT EXISTS` flag.
4854        if_not_exists: bool,
4855        /// Sequence name.
4856        name: ObjectName,
4857        /// Optional data type for the sequence.
4858        data_type: Option<DataType>,
4859        /// Sequence options (INCREMENT, MINVALUE, etc.).
4860        sequence_options: Vec<SequenceOptions>,
4861        /// Optional `OWNED BY` target.
4862        owned_by: Option<ObjectName>,
4863    },
4864    /// A `CREATE DOMAIN` statement.
4865    CreateDomain(CreateDomain),
4866    /// ```sql
4867    /// CREATE TYPE <name>
4868    /// ```
4869    CreateType {
4870        /// Type name to create.
4871        name: ObjectName,
4872        /// Optional type representation details.
4873        representation: Option<UserDefinedTypeRepresentation>,
4874    },
4875    /// ```sql
4876    /// PRAGMA <schema-name>.<pragma-name> = <pragma-value>
4877    /// ```
4878    Pragma {
4879        /// Pragma name (possibly qualified).
4880        name: ObjectName,
4881        /// Optional pragma value.
4882        value: Option<ValueWithSpan>,
4883        /// Whether the pragma used `=`.
4884        is_eq: bool,
4885    },
4886    /// ```sql
4887    /// LOCK [ TABLE ] [ ONLY ] name [ * ] [, ...] [ IN lockmode MODE ] [ NOWAIT ]
4888    /// ```
4889    ///
4890    /// See <https://www.postgresql.org/docs/current/sql-lock.html>
4891    Lock(Lock),
4892    /// ```sql
4893    /// LOCK TABLES <table_name> [READ [LOCAL] | [LOW_PRIORITY] WRITE]
4894    /// ```
4895    /// Note: this is a MySQL-specific statement. See <https://dev.mysql.com/doc/refman/8.0/en/lock-tables.html>
4896    LockTables {
4897        /// List of tables to lock with modes.
4898        tables: Vec<LockTable>,
4899    },
4900    /// ```sql
4901    /// UNLOCK TABLES
4902    /// ```
4903    /// Note: this is a MySQL-specific statement. See <https://dev.mysql.com/doc/refman/8.0/en/lock-tables.html>
4904    UnlockTables,
4905    /// Unloads the result of a query to file
4906    ///
4907    /// [Athena](https://docs.aws.amazon.com/athena/latest/ug/unload.html):
4908    /// ```sql
4909    /// UNLOAD(statement) TO <destination> [ WITH options ]
4910    /// ```
4911    ///
4912    /// [Redshift](https://docs.aws.amazon.com/redshift/latest/dg/r_UNLOAD.html):
4913    /// ```sql
4914    /// UNLOAD('statement') TO <destination> [ OPTIONS ]
4915    /// ```
4916    Unload {
4917        /// Optional query AST to unload.
4918        query: Option<Box<Query>>,
4919        /// Optional original query text.
4920        query_text: Option<String>,
4921        /// Destination identifier.
4922        to: Ident,
4923        /// Optional IAM role/auth information.
4924        auth: Option<IamRoleKind>,
4925        /// Additional `WITH` options.
4926        with: Vec<SqlOption>,
4927        /// Legacy copy-style options.
4928        options: Vec<CopyLegacyOption>,
4929    },
4930    /// ClickHouse:
4931    /// ```sql
4932    /// OPTIMIZE TABLE [db.]name [ON CLUSTER cluster] [PARTITION partition | PARTITION ID 'partition_id'] [FINAL] [DEDUPLICATE [BY expression]]
4933    /// ```
4934    /// See ClickHouse <https://clickhouse.com/docs/en/sql-reference/statements/optimize>
4935    ///
4936    /// Databricks:
4937    /// ```sql
4938    /// OPTIMIZE table_name [WHERE predicate] [ZORDER BY (col_name1 [, ...])]
4939    /// ```
4940    /// See Databricks <https://docs.databricks.com/en/sql/language-manual/delta-optimize.html>
4941    OptimizeTable {
4942        /// Table name to optimize.
4943        name: ObjectName,
4944        /// Whether the `TABLE` keyword was present (ClickHouse uses `OPTIMIZE TABLE`, Databricks uses `OPTIMIZE`).
4945        has_table_keyword: bool,
4946        /// Optional cluster identifier.
4947        /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/optimize)
4948        on_cluster: Option<Ident>,
4949        /// Optional partition spec.
4950        /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/optimize)
4951        partition: Option<Partition>,
4952        /// Whether `FINAL` was specified.
4953        /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/optimize)
4954        include_final: bool,
4955        /// Optional deduplication settings.
4956        /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/optimize)
4957        deduplicate: Option<Deduplicate>,
4958        /// Optional WHERE predicate.
4959        /// [Databricks](https://docs.databricks.com/en/sql/language-manual/delta-optimize.html)
4960        predicate: Option<Expr>,
4961        /// Optional ZORDER BY columns.
4962        /// [Databricks](https://docs.databricks.com/en/sql/language-manual/delta-optimize.html)
4963        zorder: Option<Vec<Expr>>,
4964    },
4965    /// ```sql
4966    /// LISTEN
4967    /// ```
4968    /// listen for a notification channel
4969    ///
4970    /// See Postgres <https://www.postgresql.org/docs/current/sql-listen.html>
4971    LISTEN {
4972        /// Notification channel identifier.
4973        channel: Ident,
4974    },
4975    /// ```sql
4976    /// UNLISTEN
4977    /// ```
4978    /// stop listening for a notification
4979    ///
4980    /// See Postgres <https://www.postgresql.org/docs/current/sql-unlisten.html>
4981    UNLISTEN {
4982        /// Notification channel identifier.
4983        channel: Ident,
4984    },
4985    /// ```sql
4986    /// NOTIFY channel [ , payload ]
4987    /// ```
4988    /// send a notification event together with an optional "payload" string to channel
4989    ///
4990    /// See Postgres <https://www.postgresql.org/docs/current/sql-notify.html>
4991    NOTIFY {
4992        /// Notification channel identifier.
4993        channel: Ident,
4994        /// Optional payload string.
4995        payload: Option<String>,
4996    },
4997    /// ```sql
4998    /// LOAD DATA [LOCAL] INPATH 'filepath' [OVERWRITE] INTO TABLE tablename
4999    /// [PARTITION (partcol1=val1, partcol2=val2 ...)]
5000    /// [INPUTFORMAT 'inputformat' SERDE 'serde']
5001    /// ```
5002    /// Loading files into tables
5003    ///
5004    /// See Hive <https://cwiki.apache.org/confluence/pages/viewpage.action?pageId=27362036#LanguageManualDML-Loadingfilesintotables>
5005    LoadData {
5006        /// Whether `LOCAL` is present.
5007        local: bool,
5008        /// Input path for files to load.
5009        inpath: String,
5010        /// Whether `OVERWRITE` was specified.
5011        overwrite: bool,
5012        /// Target table name to load into.
5013        table_name: ObjectName,
5014        /// Optional partition specification.
5015        partitioned: Option<Vec<Expr>>,
5016        /// Optional table format information.
5017        table_format: Option<HiveLoadDataFormat>,
5018    },
5019    /// ```sql
5020    /// Rename TABLE tbl_name TO new_tbl_name[, tbl_name2 TO new_tbl_name2] ...
5021    /// ```
5022    /// Renames one or more tables
5023    ///
5024    /// See Mysql <https://dev.mysql.com/doc/refman/9.1/en/rename-table.html>
5025    RenameTable(Vec<RenameTable>),
5026    /// Snowflake `LIST`
5027    /// See: <https://docs.snowflake.com/en/sql-reference/sql/list>
5028    List(FileStagingCommand),
5029    /// Snowflake `REMOVE`
5030    /// See: <https://docs.snowflake.com/en/sql-reference/sql/remove>
5031    Remove(FileStagingCommand),
5032    /// RaiseError (MSSQL)
5033    /// RAISERROR ( { msg_id | msg_str | @local_variable }
5034    /// { , severity , state }
5035    /// [ , argument [ , ...n ] ] )
5036    /// [ WITH option [ , ...n ] ]
5037    /// See <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/raiserror-transact-sql?view=sql-server-ver16>
5038    RaisError {
5039        /// Error message expression or identifier.
5040        message: Box<Expr>,
5041        /// Severity expression.
5042        severity: Box<Expr>,
5043        /// State expression.
5044        state: Box<Expr>,
5045        /// Substitution arguments for the message.
5046        arguments: Vec<Expr>,
5047        /// Additional `WITH` options for RAISERROR.
5048        options: Vec<RaisErrorOption>,
5049    },
5050    /// A MSSQL `THROW` statement.
5051    Throw(ThrowStatement),
5052    /// ```sql
5053    /// PRINT msg_str | @local_variable | string_expr
5054    /// ```
5055    ///
5056    /// See: <https://learn.microsoft.com/en-us/sql/t-sql/statements/print-transact-sql>
5057    Print(PrintStatement),
5058    /// MSSQL `WAITFOR` statement.
5059    ///
5060    /// See: <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/waitfor-transact-sql>
5061    WaitFor(WaitForStatement),
5062    /// ```sql
5063    /// RETURN [ expression ]
5064    /// ```
5065    ///
5066    /// See [ReturnStatement]
5067    Return(ReturnStatement),
5068    /// Export data statement
5069    ///
5070    /// Example:
5071    /// ```sql
5072    /// EXPORT DATA OPTIONS(uri='gs://bucket/folder/*', format='PARQUET', overwrite=true) AS
5073    /// SELECT field1, field2 FROM mydataset.table1 ORDER BY field1 LIMIT 10
5074    /// ```
5075    /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/export-statements)
5076    ExportData(ExportData),
5077    /// ```sql
5078    /// CREATE [OR REPLACE] USER <user> [IF NOT EXISTS]
5079    /// ```
5080    /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-user)
5081    CreateUser(CreateUser),
5082    /// ```sql
5083    /// ALTER USER \[ IF EXISTS \] \[ <name> \]
5084    /// ```
5085    /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/alter-user)
5086    AlterUser(AlterUser),
5087    /// Re-sorts rows and reclaims space in either a specified table or all tables in the current database
5088    ///
5089    /// ```sql
5090    /// VACUUM tbl
5091    /// ```
5092    /// [Redshift](https://docs.aws.amazon.com/redshift/latest/dg/r_VACUUM_command.html)
5093    Vacuum(VacuumStatement),
5094    /// Restore the value of a run-time parameter to the default value.
5095    ///
5096    /// ```sql
5097    /// RESET configuration_parameter;
5098    /// RESET ALL;
5099    /// ```
5100    /// [PostgreSQL](https://www.postgresql.org/docs/current/sql-reset.html)
5101    Reset(ResetStatement),
5102}
5103
5104impl From<Analyze> for Statement {
5105    fn from(analyze: Analyze) -> Self {
5106        Statement::Analyze(analyze)
5107    }
5108}
5109
5110impl From<ddl::Truncate> for Statement {
5111    fn from(truncate: ddl::Truncate) -> Self {
5112        Statement::Truncate(truncate)
5113    }
5114}
5115
5116impl From<Lock> for Statement {
5117    fn from(lock: Lock) -> Self {
5118        Statement::Lock(lock)
5119    }
5120}
5121
5122impl From<ddl::Msck> for Statement {
5123    fn from(msck: ddl::Msck) -> Self {
5124        Statement::Msck(msck)
5125    }
5126}
5127
5128/// ```sql
5129/// {COPY | REVOKE} CURRENT GRANTS
5130/// ```
5131///
5132/// - [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/grant-ownership#optional-parameters)
5133#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
5134#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
5135#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
5136pub enum CurrentGrantsKind {
5137    /// `COPY CURRENT GRANTS` (copy current grants to target).
5138    CopyCurrentGrants,
5139    /// `REVOKE CURRENT GRANTS` (revoke current grants from target).
5140    RevokeCurrentGrants,
5141}
5142
5143impl fmt::Display for CurrentGrantsKind {
5144    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
5145        match self {
5146            CurrentGrantsKind::CopyCurrentGrants => write!(f, "COPY CURRENT GRANTS"),
5147            CurrentGrantsKind::RevokeCurrentGrants => write!(f, "REVOKE CURRENT GRANTS"),
5148        }
5149    }
5150}
5151
5152#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
5153#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
5154#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
5155/// `RAISERROR` options
5156/// See <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/raiserror-transact-sql?view=sql-server-ver16#options>
5157pub enum RaisErrorOption {
5158    /// Log the error.
5159    Log,
5160    /// Do not wait for completion.
5161    NoWait,
5162    /// Set the error state.
5163    SetError,
5164}
5165
5166impl fmt::Display for RaisErrorOption {
5167    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
5168        match self {
5169            RaisErrorOption::Log => write!(f, "LOG"),
5170            RaisErrorOption::NoWait => write!(f, "NOWAIT"),
5171            RaisErrorOption::SetError => write!(f, "SETERROR"),
5172        }
5173    }
5174}
5175
5176impl fmt::Display for Statement {
5177    /// Formats a SQL statement with support for pretty printing.
5178    ///
5179    /// When using the alternate flag (`{:#}`), the statement will be formatted with proper
5180    /// indentation and line breaks. For example:
5181    ///
5182    /// ```
5183    /// # use sqlparser::dialect::GenericDialect;
5184    /// # use sqlparser::parser::Parser;
5185    /// let sql = "SELECT a, b FROM table_1";
5186    /// let ast = Parser::parse_sql(&GenericDialect, sql).unwrap();
5187    ///
5188    /// // Regular formatting
5189    /// assert_eq!(format!("{}", ast[0]), "SELECT a, b FROM table_1");
5190    ///
5191    /// // Pretty printing
5192    /// assert_eq!(format!("{:#}", ast[0]),
5193    /// r#"SELECT
5194    ///   a,
5195    ///   b
5196    /// FROM
5197    ///   table_1"#);
5198    /// ```
5199    // Clippy thinks this function is too complicated, but it is painful to
5200    // split up without extracting structs for each `Statement` variant.
5201    #[allow(clippy::cognitive_complexity)]
5202    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
5203        match self {
5204            Statement::Flush {
5205                object_type,
5206                location,
5207                channel,
5208                read_lock,
5209                export,
5210                tables,
5211            } => {
5212                write!(f, "FLUSH")?;
5213                if let Some(location) = location {
5214                    f.write_str(" ")?;
5215                    location.fmt(f)?;
5216                }
5217                write!(f, " {object_type}")?;
5218
5219                if let Some(channel) = channel {
5220                    write!(f, " FOR CHANNEL {channel}")?;
5221                }
5222
5223                write!(
5224                    f,
5225                    "{tables}{read}{export}",
5226                    tables = if !tables.is_empty() {
5227                        format!(" {}", display_comma_separated(tables))
5228                    } else {
5229                        String::new()
5230                    },
5231                    export = if *export { " FOR EXPORT" } else { "" },
5232                    read = if *read_lock { " WITH READ LOCK" } else { "" }
5233                )
5234            }
5235            Statement::Kill { modifier, id } => {
5236                write!(f, "KILL ")?;
5237
5238                if let Some(m) = modifier {
5239                    write!(f, "{m} ")?;
5240                }
5241
5242                write!(f, "{id}")
5243            }
5244            Statement::ExplainTable {
5245                describe_alias,
5246                hive_format,
5247                has_table_keyword,
5248                table_name,
5249            } => {
5250                write!(f, "{describe_alias} ")?;
5251
5252                if let Some(format) = hive_format {
5253                    write!(f, "{format} ")?;
5254                }
5255                if *has_table_keyword {
5256                    write!(f, "TABLE ")?;
5257                }
5258
5259                write!(f, "{table_name}")
5260            }
5261            Statement::Explain {
5262                describe_alias,
5263                verbose,
5264                analyze,
5265                query_plan,
5266                estimate,
5267                statement,
5268                format,
5269                options,
5270            } => {
5271                write!(f, "{describe_alias} ")?;
5272
5273                if *query_plan {
5274                    write!(f, "QUERY PLAN ")?;
5275                }
5276                if *analyze {
5277                    write!(f, "ANALYZE ")?;
5278                }
5279                if *estimate {
5280                    write!(f, "ESTIMATE ")?;
5281                }
5282
5283                if *verbose {
5284                    write!(f, "VERBOSE ")?;
5285                }
5286
5287                if let Some(format) = format {
5288                    write!(f, "{format} ")?;
5289                }
5290
5291                if let Some(options) = options {
5292                    write!(f, "({}) ", display_comma_separated(options))?;
5293                }
5294
5295                write!(f, "{statement}")
5296            }
5297            Statement::Query(s) => s.fmt(f),
5298            Statement::Declare { stmts } => {
5299                write!(f, "DECLARE ")?;
5300                write!(f, "{}", display_separated(stmts, "; "))
5301            }
5302            Statement::Fetch {
5303                name,
5304                direction,
5305                position,
5306                into,
5307            } => {
5308                write!(f, "FETCH {direction} {position} {name}")?;
5309
5310                if let Some(into) = into {
5311                    write!(f, " INTO {into}")?;
5312                }
5313
5314                Ok(())
5315            }
5316            Statement::Directory {
5317                overwrite,
5318                local,
5319                path,
5320                file_format,
5321                source,
5322            } => {
5323                write!(
5324                    f,
5325                    "INSERT{overwrite}{local} DIRECTORY '{path}'",
5326                    overwrite = if *overwrite { " OVERWRITE" } else { "" },
5327                    local = if *local { " LOCAL" } else { "" },
5328                    path = path
5329                )?;
5330                if let Some(ref ff) = file_format {
5331                    write!(f, " STORED AS {ff}")?
5332                }
5333                write!(f, " {source}")
5334            }
5335            Statement::Msck(msck) => msck.fmt(f),
5336            Statement::Truncate(truncate) => truncate.fmt(f),
5337            Statement::Case(stmt) => {
5338                write!(f, "{stmt}")
5339            }
5340            Statement::If(stmt) => {
5341                write!(f, "{stmt}")
5342            }
5343            Statement::While(stmt) => {
5344                write!(f, "{stmt}")
5345            }
5346            Statement::Raise(stmt) => {
5347                write!(f, "{stmt}")
5348            }
5349            Statement::AttachDatabase {
5350                schema_name,
5351                database_file_name,
5352                database,
5353            } => {
5354                let keyword = if *database { "DATABASE " } else { "" };
5355                write!(f, "ATTACH {keyword}{database_file_name} AS {schema_name}")
5356            }
5357            Statement::AttachDuckDBDatabase {
5358                if_not_exists,
5359                database,
5360                database_path,
5361                database_alias,
5362                attach_options,
5363            } => {
5364                write!(
5365                    f,
5366                    "ATTACH{database}{if_not_exists} {database_path}",
5367                    database = if *database { " DATABASE" } else { "" },
5368                    if_not_exists = if *if_not_exists { " IF NOT EXISTS" } else { "" },
5369                )?;
5370                if let Some(alias) = database_alias {
5371                    write!(f, " AS {alias}")?;
5372                }
5373                if !attach_options.is_empty() {
5374                    write!(f, " ({})", display_comma_separated(attach_options))?;
5375                }
5376                Ok(())
5377            }
5378            Statement::DetachDuckDBDatabase {
5379                if_exists,
5380                database,
5381                database_alias,
5382            } => {
5383                write!(
5384                    f,
5385                    "DETACH{database}{if_exists} {database_alias}",
5386                    database = if *database { " DATABASE" } else { "" },
5387                    if_exists = if *if_exists { " IF EXISTS" } else { "" },
5388                )?;
5389                Ok(())
5390            }
5391            Statement::Analyze(analyze) => analyze.fmt(f),
5392            Statement::Insert(insert) => insert.fmt(f),
5393            Statement::Install {
5394                extension_name: name,
5395            } => write!(f, "INSTALL {name}"),
5396
5397            Statement::Load {
5398                extension_name: name,
5399            } => write!(f, "LOAD {name}"),
5400
5401            Statement::Call(function) => write!(f, "CALL {function}"),
5402
5403            Statement::Copy {
5404                source,
5405                to,
5406                target,
5407                options,
5408                legacy_options,
5409                values,
5410            } => {
5411                write!(f, "COPY")?;
5412                match source {
5413                    CopySource::Query(query) => write!(f, " ({query})")?,
5414                    CopySource::Table {
5415                        table_name,
5416                        columns,
5417                    } => {
5418                        write!(f, " {table_name}")?;
5419                        if !columns.is_empty() {
5420                            write!(f, " ({})", display_comma_separated(columns))?;
5421                        }
5422                    }
5423                }
5424                write!(f, " {} {}", if *to { "TO" } else { "FROM" }, target)?;
5425                if !options.is_empty() {
5426                    write!(f, " ({})", display_comma_separated(options))?;
5427                }
5428                if !legacy_options.is_empty() {
5429                    write!(f, " {}", display_separated(legacy_options, " "))?;
5430                }
5431                if !values.is_empty() {
5432                    writeln!(f, ";")?;
5433                    let mut delim = "";
5434                    for v in values {
5435                        write!(f, "{delim}")?;
5436                        delim = "\t";
5437                        if let Some(v) = v {
5438                            write!(f, "{v}")?;
5439                        } else {
5440                            write!(f, "\\N")?;
5441                        }
5442                    }
5443                    write!(f, "\n\\.")?;
5444                }
5445                Ok(())
5446            }
5447            Statement::Update(update) => update.fmt(f),
5448            Statement::Delete(delete) => delete.fmt(f),
5449            Statement::Open(open) => open.fmt(f),
5450            Statement::Close { cursor } => {
5451                write!(f, "CLOSE {cursor}")?;
5452
5453                Ok(())
5454            }
5455            Statement::CreateDatabase {
5456                db_name,
5457                if_not_exists,
5458                location,
5459                managed_location,
5460                or_replace,
5461                transient,
5462                clone,
5463                data_retention_time_in_days,
5464                max_data_extension_time_in_days,
5465                external_volume,
5466                catalog,
5467                replace_invalid_characters,
5468                default_ddl_collation,
5469                storage_serialization_policy,
5470                comment,
5471                default_charset,
5472                default_collation,
5473                catalog_sync,
5474                catalog_sync_namespace_mode,
5475                catalog_sync_namespace_flatten_delimiter,
5476                with_tags,
5477                with_contacts,
5478            } => {
5479                write!(
5480                    f,
5481                    "CREATE {or_replace}{transient}DATABASE {if_not_exists}{name}",
5482                    or_replace = if *or_replace { "OR REPLACE " } else { "" },
5483                    transient = if *transient { "TRANSIENT " } else { "" },
5484                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
5485                    name = db_name,
5486                )?;
5487
5488                if let Some(l) = location {
5489                    write!(f, " LOCATION '{l}'")?;
5490                }
5491                if let Some(ml) = managed_location {
5492                    write!(f, " MANAGEDLOCATION '{ml}'")?;
5493                }
5494                if let Some(clone) = clone {
5495                    write!(f, " CLONE {clone}")?;
5496                }
5497
5498                if let Some(value) = data_retention_time_in_days {
5499                    write!(f, " DATA_RETENTION_TIME_IN_DAYS = {value}")?;
5500                }
5501
5502                if let Some(value) = max_data_extension_time_in_days {
5503                    write!(f, " MAX_DATA_EXTENSION_TIME_IN_DAYS = {value}")?;
5504                }
5505
5506                if let Some(vol) = external_volume {
5507                    write!(f, " EXTERNAL_VOLUME = '{vol}'")?;
5508                }
5509
5510                if let Some(cat) = catalog {
5511                    write!(f, " CATALOG = '{cat}'")?;
5512                }
5513
5514                if let Some(true) = replace_invalid_characters {
5515                    write!(f, " REPLACE_INVALID_CHARACTERS = TRUE")?;
5516                } else if let Some(false) = replace_invalid_characters {
5517                    write!(f, " REPLACE_INVALID_CHARACTERS = FALSE")?;
5518                }
5519
5520                if let Some(collation) = default_ddl_collation {
5521                    write!(f, " DEFAULT_DDL_COLLATION = '{collation}'")?;
5522                }
5523
5524                if let Some(policy) = storage_serialization_policy {
5525                    write!(f, " STORAGE_SERIALIZATION_POLICY = {policy}")?;
5526                }
5527
5528                if let Some(comment) = comment {
5529                    write!(f, " COMMENT = '{comment}'")?;
5530                }
5531
5532                if let Some(charset) = default_charset {
5533                    write!(f, " DEFAULT CHARACTER SET {charset}")?;
5534                }
5535
5536                if let Some(collation) = default_collation {
5537                    write!(f, " DEFAULT COLLATE {collation}")?;
5538                }
5539
5540                if let Some(sync) = catalog_sync {
5541                    write!(f, " CATALOG_SYNC = '{sync}'")?;
5542                }
5543
5544                if let Some(mode) = catalog_sync_namespace_mode {
5545                    write!(f, " CATALOG_SYNC_NAMESPACE_MODE = {mode}")?;
5546                }
5547
5548                if let Some(delim) = catalog_sync_namespace_flatten_delimiter {
5549                    write!(f, " CATALOG_SYNC_NAMESPACE_FLATTEN_DELIMITER = '{delim}'")?;
5550                }
5551
5552                if let Some(tags) = with_tags {
5553                    write!(f, " WITH TAG ({})", display_comma_separated(tags))?;
5554                }
5555
5556                if let Some(contacts) = with_contacts {
5557                    write!(f, " WITH CONTACT ({})", display_comma_separated(contacts))?;
5558                }
5559                Ok(())
5560            }
5561            Statement::CreateFunction(create_function) => create_function.fmt(f),
5562            Statement::CreateDomain(create_domain) => create_domain.fmt(f),
5563            Statement::CreateTrigger(create_trigger) => create_trigger.fmt(f),
5564            Statement::DropTrigger(drop_trigger) => drop_trigger.fmt(f),
5565            Statement::CreateProcedure {
5566                name,
5567                or_alter,
5568                params,
5569                language,
5570                body,
5571            } => {
5572                write!(
5573                    f,
5574                    "CREATE {or_alter}PROCEDURE {name}",
5575                    or_alter = if *or_alter { "OR ALTER " } else { "" },
5576                    name = name
5577                )?;
5578
5579                if let Some(p) = params {
5580                    if !p.is_empty() {
5581                        write!(f, " ({})", display_comma_separated(p))?;
5582                    }
5583                }
5584
5585                if let Some(language) = language {
5586                    write!(f, " LANGUAGE {language}")?;
5587                }
5588
5589                write!(f, " AS {body}")
5590            }
5591            Statement::CreateMacro {
5592                or_replace,
5593                temporary,
5594                name,
5595                args,
5596                definition,
5597            } => {
5598                write!(
5599                    f,
5600                    "CREATE {or_replace}{temp}MACRO {name}",
5601                    temp = if *temporary { "TEMPORARY " } else { "" },
5602                    or_replace = if *or_replace { "OR REPLACE " } else { "" },
5603                )?;
5604                if let Some(args) = args {
5605                    write!(f, "({})", display_comma_separated(args))?;
5606                }
5607                match definition {
5608                    MacroDefinition::Expr(expr) => write!(f, " AS {expr}")?,
5609                    MacroDefinition::Table(query) => write!(f, " AS TABLE {query}")?,
5610                }
5611                Ok(())
5612            }
5613            Statement::CreateView(create_view) => create_view.fmt(f),
5614            Statement::CreateTable(create_table) => create_table.fmt(f),
5615            Statement::LoadData {
5616                local,
5617                inpath,
5618                overwrite,
5619                table_name,
5620                partitioned,
5621                table_format,
5622            } => {
5623                write!(
5624                    f,
5625                    "LOAD DATA {local}INPATH '{inpath}' {overwrite}INTO TABLE {table_name}",
5626                    local = if *local { "LOCAL " } else { "" },
5627                    inpath = inpath,
5628                    overwrite = if *overwrite { "OVERWRITE " } else { "" },
5629                    table_name = table_name,
5630                )?;
5631                if let Some(ref parts) = &partitioned {
5632                    if !parts.is_empty() {
5633                        write!(f, " PARTITION ({})", display_comma_separated(parts))?;
5634                    }
5635                }
5636                if let Some(HiveLoadDataFormat {
5637                    serde,
5638                    input_format,
5639                }) = &table_format
5640                {
5641                    write!(f, " INPUTFORMAT {input_format} SERDE {serde}")?;
5642                }
5643                Ok(())
5644            }
5645            Statement::CreateVirtualTable {
5646                name,
5647                if_not_exists,
5648                module_name,
5649                module_args,
5650            } => {
5651                write!(
5652                    f,
5653                    "CREATE VIRTUAL TABLE {if_not_exists}{name} USING {module_name}",
5654                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
5655                    name = name,
5656                    module_name = module_name
5657                )?;
5658                if !module_args.is_empty() {
5659                    write!(f, " ({})", display_comma_separated(module_args))?;
5660                }
5661                Ok(())
5662            }
5663            Statement::CreateIndex(create_index) => create_index.fmt(f),
5664            Statement::CreateExtension(create_extension) => write!(f, "{create_extension}"),
5665            Statement::CreateCollation(create_collation) => write!(f, "{create_collation}"),
5666            Statement::CreateTextSearchConfiguration(v) => write!(f, "{v}"),
5667            Statement::CreateTextSearchDictionary(v) => write!(f, "{v}"),
5668            Statement::CreateTextSearchParser(v) => write!(f, "{v}"),
5669            Statement::CreateTextSearchTemplate(v) => write!(f, "{v}"),
5670            Statement::CreatePublication(v) => write!(f, "{v}"),
5671            Statement::CreateSubscription(v) => write!(f, "{v}"),
5672            Statement::CreateCast(v) => write!(f, "{v}"),
5673            Statement::CreateConversion(v) => write!(f, "{v}"),
5674            Statement::CreateLanguage(v) => write!(f, "{v}"),
5675            Statement::CreateRule(v) => write!(f, "{v}"),
5676            Statement::CreateStatistics(v) => write!(f, "{v}"),
5677            Statement::CreateAccessMethod(v) => write!(f, "{v}"),
5678            Statement::CreateEventTrigger(v) => write!(f, "{v}"),
5679            Statement::CreateTransform(v) => write!(f, "{v}"),
5680            Statement::SecurityLabel(v) => write!(f, "{v}"),
5681            Statement::CreateUserMapping(v) => write!(f, "{v}"),
5682            Statement::CreateTablespace(v) => write!(f, "{v}"),
5683            Statement::DropExtension(drop_extension) => write!(f, "{drop_extension}"),
5684            Statement::DropOperator(drop_operator) => write!(f, "{drop_operator}"),
5685            Statement::DropOperatorFamily(drop_operator_family) => {
5686                write!(f, "{drop_operator_family}")
5687            }
5688            Statement::DropOperatorClass(drop_operator_class) => {
5689                write!(f, "{drop_operator_class}")
5690            }
5691            Statement::CreateRole(create_role) => write!(f, "{create_role}"),
5692            Statement::CreateSecret {
5693                or_replace,
5694                temporary,
5695                if_not_exists,
5696                name,
5697                storage_specifier,
5698                secret_type,
5699                options,
5700            } => {
5701                write!(
5702                    f,
5703                    "CREATE {or_replace}",
5704                    or_replace = if *or_replace { "OR REPLACE " } else { "" },
5705                )?;
5706                if let Some(t) = temporary {
5707                    write!(f, "{}", if *t { "TEMPORARY " } else { "PERSISTENT " })?;
5708                }
5709                write!(
5710                    f,
5711                    "SECRET {if_not_exists}",
5712                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
5713                )?;
5714                if let Some(n) = name {
5715                    write!(f, "{n} ")?;
5716                };
5717                if let Some(s) = storage_specifier {
5718                    write!(f, "IN {s} ")?;
5719                }
5720                write!(f, "( TYPE {secret_type}",)?;
5721                if !options.is_empty() {
5722                    write!(f, ", {o}", o = display_comma_separated(options))?;
5723                }
5724                write!(f, " )")?;
5725                Ok(())
5726            }
5727            Statement::CreateServer(stmt) => {
5728                write!(f, "{stmt}")
5729            }
5730            Statement::CreateForeignDataWrapper(stmt) => write!(f, "{stmt}"),
5731            Statement::CreateForeignTable(stmt) => write!(f, "{stmt}"),
5732            Statement::CreatePolicy(policy) => write!(f, "{policy}"),
5733            Statement::CreateConnector(create_connector) => create_connector.fmt(f),
5734            Statement::CreateOperator(create_operator) => create_operator.fmt(f),
5735            Statement::CreateOperatorFamily(create_operator_family) => {
5736                create_operator_family.fmt(f)
5737            }
5738            Statement::CreateOperatorClass(create_operator_class) => create_operator_class.fmt(f),
5739            Statement::CreateAggregate(create_aggregate) => create_aggregate.fmt(f),
5740            Statement::AlterTable(alter_table) => write!(f, "{alter_table}"),
5741            Statement::AlterIndex { name, operation } => {
5742                write!(f, "ALTER INDEX {name} {operation}")
5743            }
5744            Statement::AlterView {
5745                name,
5746                columns,
5747                query,
5748                with_options,
5749            } => {
5750                write!(f, "ALTER VIEW {name}")?;
5751                if !with_options.is_empty() {
5752                    write!(f, " WITH ({})", display_comma_separated(with_options))?;
5753                }
5754                if !columns.is_empty() {
5755                    write!(f, " ({})", display_comma_separated(columns))?;
5756                }
5757                write!(f, " AS {query}")
5758            }
5759            Statement::AlterDomain(alter_domain) => write!(f, "{alter_domain}"),
5760            Statement::AlterExtension(alter_extension) => write!(f, "{alter_extension}"),
5761            Statement::AlterFunction(alter_function) => write!(f, "{alter_function}"),
5762            Statement::AlterTrigger(alter_trigger) => write!(f, "{alter_trigger}"),
5763            Statement::AlterType(AlterType { name, operation }) => {
5764                write!(f, "ALTER TYPE {name} {operation}")
5765            }
5766            Statement::AlterCollation(alter_collation) => write!(f, "{alter_collation}"),
5767            Statement::AlterDefaultPrivileges(alter_default_privileges) => {
5768                write!(f, "{alter_default_privileges}")
5769            }
5770            Statement::AlterOperator(alter_operator) => write!(f, "{alter_operator}"),
5771            Statement::AlterOperatorFamily(alter_operator_family) => {
5772                write!(f, "{alter_operator_family}")
5773            }
5774            Statement::AlterOperatorClass(alter_operator_class) => {
5775                write!(f, "{alter_operator_class}")
5776            }
5777            Statement::AlterRole { name, operation } => {
5778                write!(f, "ALTER ROLE {name} {operation}")
5779            }
5780            Statement::AlterPolicy(alter_policy) => write!(f, "{alter_policy}"),
5781            Statement::AlterConnector {
5782                name,
5783                properties,
5784                url,
5785                owner,
5786            } => {
5787                write!(f, "ALTER CONNECTOR {name}")?;
5788                if let Some(properties) = properties {
5789                    write!(
5790                        f,
5791                        " SET DCPROPERTIES({})",
5792                        display_comma_separated(properties)
5793                    )?;
5794                }
5795                if let Some(url) = url {
5796                    write!(f, " SET URL '{url}'")?;
5797                }
5798                if let Some(owner) = owner {
5799                    write!(f, " SET OWNER {owner}")?;
5800                }
5801                Ok(())
5802            }
5803            Statement::AlterSession {
5804                set,
5805                session_params,
5806            } => {
5807                write!(
5808                    f,
5809                    "ALTER SESSION {set}",
5810                    set = if *set { "SET" } else { "UNSET" }
5811                )?;
5812                if !session_params.options.is_empty() {
5813                    if *set {
5814                        write!(f, " {session_params}")?;
5815                    } else {
5816                        let options = session_params
5817                            .options
5818                            .iter()
5819                            .map(|p| p.option_name.clone())
5820                            .collect::<Vec<_>>();
5821                        write!(f, " {}", display_separated(&options, ", "))?;
5822                    }
5823                }
5824                Ok(())
5825            }
5826            Statement::Drop {
5827                object_type,
5828                if_exists,
5829                names,
5830                cascade,
5831                restrict,
5832                purge,
5833                temporary,
5834                table,
5835            } => {
5836                write!(
5837                    f,
5838                    "DROP {}{}{} {}{}{}{}",
5839                    if *temporary { "TEMPORARY " } else { "" },
5840                    object_type,
5841                    if *if_exists { " IF EXISTS" } else { "" },
5842                    display_comma_separated(names),
5843                    if *cascade { " CASCADE" } else { "" },
5844                    if *restrict { " RESTRICT" } else { "" },
5845                    if *purge { " PURGE" } else { "" },
5846                )?;
5847                if let Some(table_name) = table.as_ref() {
5848                    write!(f, " ON {table_name}")?;
5849                };
5850                Ok(())
5851            }
5852            Statement::DropFunction(drop_function) => write!(f, "{drop_function}"),
5853            Statement::DropDomain(DropDomain {
5854                if_exists,
5855                name,
5856                drop_behavior,
5857            }) => {
5858                write!(
5859                    f,
5860                    "DROP DOMAIN{} {name}",
5861                    if *if_exists { " IF EXISTS" } else { "" },
5862                )?;
5863                if let Some(op) = drop_behavior {
5864                    write!(f, " {op}")?;
5865                }
5866                Ok(())
5867            }
5868            Statement::DropProcedure {
5869                if_exists,
5870                proc_desc,
5871                drop_behavior,
5872            } => {
5873                write!(
5874                    f,
5875                    "DROP PROCEDURE{} {}",
5876                    if *if_exists { " IF EXISTS" } else { "" },
5877                    display_comma_separated(proc_desc),
5878                )?;
5879                if let Some(op) = drop_behavior {
5880                    write!(f, " {op}")?;
5881                }
5882                Ok(())
5883            }
5884            Statement::DropSecret {
5885                if_exists,
5886                temporary,
5887                name,
5888                storage_specifier,
5889            } => {
5890                write!(f, "DROP ")?;
5891                if let Some(t) = temporary {
5892                    write!(f, "{}", if *t { "TEMPORARY " } else { "PERSISTENT " })?;
5893                }
5894                write!(
5895                    f,
5896                    "SECRET {if_exists}{name}",
5897                    if_exists = if *if_exists { "IF EXISTS " } else { "" },
5898                )?;
5899                if let Some(s) = storage_specifier {
5900                    write!(f, " FROM {s}")?;
5901                }
5902                Ok(())
5903            }
5904            Statement::DropPolicy(policy) => write!(f, "{policy}"),
5905            Statement::DropConnector { if_exists, name } => {
5906                write!(
5907                    f,
5908                    "DROP CONNECTOR {if_exists}{name}",
5909                    if_exists = if *if_exists { "IF EXISTS " } else { "" }
5910                )?;
5911                Ok(())
5912            }
5913            Statement::Discard { object_type } => {
5914                write!(f, "DISCARD {object_type}")?;
5915                Ok(())
5916            }
5917            Self::Set(set) => write!(f, "{set}"),
5918            Statement::ShowVariable { variable } => {
5919                write!(f, "SHOW")?;
5920                if !variable.is_empty() {
5921                    write!(f, " {}", display_separated(variable, " "))?;
5922                }
5923                Ok(())
5924            }
5925            Statement::ShowStatus {
5926                filter,
5927                global,
5928                session,
5929            } => {
5930                write!(f, "SHOW")?;
5931                if *global {
5932                    write!(f, " GLOBAL")?;
5933                }
5934                if *session {
5935                    write!(f, " SESSION")?;
5936                }
5937                write!(f, " STATUS")?;
5938                if filter.is_some() {
5939                    write!(f, " {}", filter.as_ref().unwrap())?;
5940                }
5941                Ok(())
5942            }
5943            Statement::ShowVariables {
5944                filter,
5945                global,
5946                session,
5947            } => {
5948                write!(f, "SHOW")?;
5949                if *global {
5950                    write!(f, " GLOBAL")?;
5951                }
5952                if *session {
5953                    write!(f, " SESSION")?;
5954                }
5955                write!(f, " VARIABLES")?;
5956                if filter.is_some() {
5957                    write!(f, " {}", filter.as_ref().unwrap())?;
5958                }
5959                Ok(())
5960            }
5961            Statement::ShowCreate { obj_type, obj_name } => {
5962                write!(f, "SHOW CREATE {obj_type} {obj_name}",)?;
5963                Ok(())
5964            }
5965            Statement::ShowColumns {
5966                extended,
5967                full,
5968                show_options,
5969            } => {
5970                write!(
5971                    f,
5972                    "SHOW {extended}{full}COLUMNS{show_options}",
5973                    extended = if *extended { "EXTENDED " } else { "" },
5974                    full = if *full { "FULL " } else { "" },
5975                )?;
5976                Ok(())
5977            }
5978            Statement::ShowDatabases {
5979                terse,
5980                history,
5981                show_options,
5982            } => {
5983                write!(
5984                    f,
5985                    "SHOW {terse}DATABASES{history}{show_options}",
5986                    terse = if *terse { "TERSE " } else { "" },
5987                    history = if *history { " HISTORY" } else { "" },
5988                )?;
5989                Ok(())
5990            }
5991            Statement::ShowCatalogs {
5992                terse,
5993                history,
5994                show_options,
5995            } => {
5996                write!(
5997                    f,
5998                    "SHOW {terse}CATALOGS{history}{show_options}",
5999                    terse = if *terse { "TERSE " } else { "" },
6000                    history = if *history { " HISTORY" } else { "" },
6001                )?;
6002                Ok(())
6003            }
6004            Statement::ShowProcessList { full } => {
6005                write!(
6006                    f,
6007                    "SHOW {full}PROCESSLIST",
6008                    full = if *full { "FULL " } else { "" },
6009                )?;
6010                Ok(())
6011            }
6012            Statement::ShowSchemas {
6013                terse,
6014                history,
6015                show_options,
6016            } => {
6017                write!(
6018                    f,
6019                    "SHOW {terse}SCHEMAS{history}{show_options}",
6020                    terse = if *terse { "TERSE " } else { "" },
6021                    history = if *history { " HISTORY" } else { "" },
6022                )?;
6023                Ok(())
6024            }
6025            Statement::ShowObjects(ShowObjects {
6026                terse,
6027                show_options,
6028            }) => {
6029                write!(
6030                    f,
6031                    "SHOW {terse}OBJECTS{show_options}",
6032                    terse = if *terse { "TERSE " } else { "" },
6033                )?;
6034                Ok(())
6035            }
6036            Statement::ShowTables {
6037                terse,
6038                history,
6039                extended,
6040                full,
6041                external,
6042                show_options,
6043            } => {
6044                write!(
6045                    f,
6046                    "SHOW {terse}{extended}{full}{external}TABLES{history}{show_options}",
6047                    terse = if *terse { "TERSE " } else { "" },
6048                    extended = if *extended { "EXTENDED " } else { "" },
6049                    full = if *full { "FULL " } else { "" },
6050                    external = if *external { "EXTERNAL " } else { "" },
6051                    history = if *history { " HISTORY" } else { "" },
6052                )?;
6053                Ok(())
6054            }
6055            Statement::ShowViews {
6056                terse,
6057                materialized,
6058                show_options,
6059            } => {
6060                write!(
6061                    f,
6062                    "SHOW {terse}{materialized}VIEWS{show_options}",
6063                    terse = if *terse { "TERSE " } else { "" },
6064                    materialized = if *materialized { "MATERIALIZED " } else { "" }
6065                )?;
6066                Ok(())
6067            }
6068            Statement::ShowFunctions { filter } => {
6069                write!(f, "SHOW FUNCTIONS")?;
6070                if let Some(filter) = filter {
6071                    write!(f, " {filter}")?;
6072                }
6073                Ok(())
6074            }
6075            Statement::Use(use_expr) => use_expr.fmt(f),
6076            Statement::ShowCollation { filter } => {
6077                write!(f, "SHOW COLLATION")?;
6078                if let Some(filter) = filter {
6079                    write!(f, " {filter}")?;
6080                }
6081                Ok(())
6082            }
6083            Statement::ShowCharset(show_stm) => show_stm.fmt(f),
6084            Statement::StartTransaction {
6085                modes,
6086                begin: syntax_begin,
6087                transaction,
6088                modifier,
6089                statements,
6090                exception,
6091                has_end_keyword,
6092            } => {
6093                if *syntax_begin {
6094                    if let Some(modifier) = *modifier {
6095                        write!(f, "BEGIN {modifier}")?;
6096                    } else {
6097                        write!(f, "BEGIN")?;
6098                    }
6099                } else {
6100                    write!(f, "START")?;
6101                }
6102                if let Some(transaction) = transaction {
6103                    write!(f, " {transaction}")?;
6104                }
6105                if !modes.is_empty() {
6106                    write!(f, " {}", display_comma_separated(modes))?;
6107                }
6108                if !statements.is_empty() {
6109                    write!(f, " ")?;
6110                    format_statement_list(f, statements)?;
6111                }
6112                if let Some(exception_when) = exception {
6113                    write!(f, " EXCEPTION")?;
6114                    for when in exception_when {
6115                        write!(f, " {when}")?;
6116                    }
6117                }
6118                if *has_end_keyword {
6119                    write!(f, " END")?;
6120                }
6121                Ok(())
6122            }
6123            Statement::Commit {
6124                chain,
6125                end: end_syntax,
6126                modifier,
6127            } => {
6128                if *end_syntax {
6129                    write!(f, "END")?;
6130                    if let Some(modifier) = *modifier {
6131                        write!(f, " {modifier}")?;
6132                    }
6133                    if *chain {
6134                        write!(f, " AND CHAIN")?;
6135                    }
6136                } else {
6137                    write!(f, "COMMIT{}", if *chain { " AND CHAIN" } else { "" })?;
6138                }
6139                Ok(())
6140            }
6141            Statement::Rollback { chain, savepoint } => {
6142                write!(f, "ROLLBACK")?;
6143
6144                if *chain {
6145                    write!(f, " AND CHAIN")?;
6146                }
6147
6148                if let Some(savepoint) = savepoint {
6149                    write!(f, " TO SAVEPOINT {savepoint}")?;
6150                }
6151
6152                Ok(())
6153            }
6154            Statement::CreateSchema {
6155                schema_name,
6156                if_not_exists,
6157                with,
6158                options,
6159                default_collate_spec,
6160                clone,
6161            } => {
6162                write!(
6163                    f,
6164                    "CREATE SCHEMA {if_not_exists}{name}",
6165                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
6166                    name = schema_name
6167                )?;
6168
6169                if let Some(collate) = default_collate_spec {
6170                    write!(f, " DEFAULT COLLATE {collate}")?;
6171                }
6172
6173                if let Some(with) = with {
6174                    write!(f, " WITH ({})", display_comma_separated(with))?;
6175                }
6176
6177                if let Some(options) = options {
6178                    write!(f, " OPTIONS({})", display_comma_separated(options))?;
6179                }
6180
6181                if let Some(clone) = clone {
6182                    write!(f, " CLONE {clone}")?;
6183                }
6184                Ok(())
6185            }
6186            Statement::Assert { condition, message } => {
6187                write!(f, "ASSERT {condition}")?;
6188                if let Some(m) = message {
6189                    write!(f, " AS {m}")?;
6190                }
6191                Ok(())
6192            }
6193            Statement::Grant(grant) => write!(f, "{grant}"),
6194            Statement::Deny(s) => write!(f, "{s}"),
6195            Statement::Revoke(revoke) => write!(f, "{revoke}"),
6196            Statement::Deallocate { name, prepare } => write!(
6197                f,
6198                "DEALLOCATE {prepare}{name}",
6199                prepare = if *prepare { "PREPARE " } else { "" },
6200                name = name,
6201            ),
6202            Statement::Execute {
6203                name,
6204                parameters,
6205                has_parentheses,
6206                immediate,
6207                into,
6208                using,
6209                output,
6210                default,
6211            } => {
6212                let (open, close) = if *has_parentheses {
6213                    // Space before `(` only when there is no name directly preceding it.
6214                    (if name.is_some() { "(" } else { " (" }, ")")
6215                } else {
6216                    (if parameters.is_empty() { "" } else { " " }, "")
6217                };
6218                write!(f, "EXECUTE")?;
6219                if *immediate {
6220                    write!(f, " IMMEDIATE")?;
6221                }
6222                if let Some(name) = name {
6223                    write!(f, " {name}")?;
6224                }
6225                write!(f, "{open}{}{close}", display_comma_separated(parameters),)?;
6226                if !into.is_empty() {
6227                    write!(f, " INTO {}", display_comma_separated(into))?;
6228                }
6229                if !using.is_empty() {
6230                    write!(f, " USING {}", display_comma_separated(using))?;
6231                };
6232                if *output {
6233                    write!(f, " OUTPUT")?;
6234                }
6235                if *default {
6236                    write!(f, " DEFAULT")?;
6237                }
6238                Ok(())
6239            }
6240            Statement::Prepare {
6241                name,
6242                data_types,
6243                statement,
6244            } => {
6245                write!(f, "PREPARE {name} ")?;
6246                if !data_types.is_empty() {
6247                    write!(f, "({}) ", display_comma_separated(data_types))?;
6248                }
6249                write!(f, "AS {statement}")
6250            }
6251            Statement::Comment {
6252                object_type,
6253                object_name,
6254                arguments,
6255                table_name,
6256                comment,
6257                if_exists,
6258            } => {
6259                write!(f, "COMMENT ")?;
6260                if *if_exists {
6261                    write!(f, "IF EXISTS ")?;
6262                }
6263                write!(f, "ON {object_type} {object_name}")?;
6264                if let Some(args) = arguments {
6265                    write!(f, "({})", display_comma_separated(args))?;
6266                }
6267                if let Some(table_name) = table_name {
6268                    write!(f, " ON {table_name}")?;
6269                }
6270                write!(f, " IS ")?;
6271                if let Some(c) = comment {
6272                    write!(f, "'{}'", value::escape_single_quote_string(c))
6273                } else {
6274                    write!(f, "NULL")
6275                }
6276            }
6277            Statement::Savepoint { name } => {
6278                write!(f, "SAVEPOINT ")?;
6279                write!(f, "{name}")
6280            }
6281            Statement::ReleaseSavepoint { name } => {
6282                write!(f, "RELEASE SAVEPOINT {name}")
6283            }
6284            Statement::Merge(merge) => merge.fmt(f),
6285            Statement::Cache {
6286                table_name,
6287                table_flag,
6288                has_as,
6289                options,
6290                query,
6291            } => {
6292                if let Some(table_flag) = table_flag {
6293                    write!(f, "CACHE {table_flag} TABLE {table_name}")?;
6294                } else {
6295                    write!(f, "CACHE TABLE {table_name}")?;
6296                }
6297
6298                if !options.is_empty() {
6299                    write!(f, " OPTIONS({})", display_comma_separated(options))?;
6300                }
6301
6302                match (*has_as, query) {
6303                    (true, Some(query)) => write!(f, " AS {query}"),
6304                    (true, None) => f.write_str(" AS"),
6305                    (false, Some(query)) => write!(f, " {query}"),
6306                    (false, None) => Ok(()),
6307                }
6308            }
6309            Statement::UNCache {
6310                table_name,
6311                if_exists,
6312            } => {
6313                if *if_exists {
6314                    write!(f, "UNCACHE TABLE IF EXISTS {table_name}")
6315                } else {
6316                    write!(f, "UNCACHE TABLE {table_name}")
6317                }
6318            }
6319            Statement::CreateSequence {
6320                temporary,
6321                if_not_exists,
6322                name,
6323                data_type,
6324                sequence_options,
6325                owned_by,
6326            } => {
6327                let as_type: String = if let Some(dt) = data_type.as_ref() {
6328                    //Cannot use format!(" AS {}", dt), due to format! is not available in --target thumbv6m-none-eabi
6329                    // " AS ".to_owned() + &dt.to_string()
6330                    [" AS ", &dt.to_string()].concat()
6331                } else {
6332                    "".to_string()
6333                };
6334                write!(
6335                    f,
6336                    "CREATE {temporary}SEQUENCE {if_not_exists}{name}{as_type}",
6337                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
6338                    temporary = if *temporary { "TEMPORARY " } else { "" },
6339                    name = name,
6340                    as_type = as_type
6341                )?;
6342                for sequence_option in sequence_options {
6343                    write!(f, "{sequence_option}")?;
6344                }
6345                if let Some(ob) = owned_by.as_ref() {
6346                    write!(f, " OWNED BY {ob}")?;
6347                }
6348                write!(f, "")
6349            }
6350            Statement::CreateStage {
6351                or_replace,
6352                temporary,
6353                if_not_exists,
6354                name,
6355                stage_params,
6356                directory_table_params,
6357                file_format,
6358                copy_options,
6359                comment,
6360                ..
6361            } => {
6362                write!(
6363                    f,
6364                    "CREATE {or_replace}{temp}STAGE {if_not_exists}{name}{stage_params}",
6365                    temp = if *temporary { "TEMPORARY " } else { "" },
6366                    or_replace = if *or_replace { "OR REPLACE " } else { "" },
6367                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
6368                )?;
6369                if !directory_table_params.options.is_empty() {
6370                    write!(f, " DIRECTORY=({directory_table_params})")?;
6371                }
6372                if !file_format.options.is_empty() {
6373                    write!(f, " FILE_FORMAT=({file_format})")?;
6374                }
6375                if !copy_options.options.is_empty() {
6376                    write!(f, " COPY_OPTIONS=({copy_options})")?;
6377                }
6378                if comment.is_some() {
6379                    write!(f, " COMMENT='{}'", comment.as_ref().unwrap())?;
6380                }
6381                Ok(())
6382            }
6383            Statement::CopyIntoSnowflake {
6384                kind,
6385                into,
6386                into_columns,
6387                from_obj,
6388                from_obj_alias,
6389                stage_params,
6390                from_transformations,
6391                from_query,
6392                files,
6393                pattern,
6394                file_format,
6395                copy_options,
6396                validation_mode,
6397                partition,
6398            } => {
6399                write!(f, "COPY INTO {into}")?;
6400                if let Some(into_columns) = into_columns {
6401                    write!(f, " ({})", display_comma_separated(into_columns))?;
6402                }
6403                if let Some(from_transformations) = from_transformations {
6404                    // Data load with transformation
6405                    if let Some(from_stage) = from_obj {
6406                        write!(
6407                            f,
6408                            " FROM (SELECT {} FROM {}{}",
6409                            display_separated(from_transformations, ", "),
6410                            from_stage,
6411                            stage_params
6412                        )?;
6413                    }
6414                    if let Some(from_obj_alias) = from_obj_alias {
6415                        write!(f, " AS {from_obj_alias}")?;
6416                    }
6417                    write!(f, ")")?;
6418                } else if let Some(from_obj) = from_obj {
6419                    // Standard data load
6420                    write!(f, " FROM {from_obj}{stage_params}")?;
6421                    if let Some(from_obj_alias) = from_obj_alias {
6422                        write!(f, " AS {from_obj_alias}")?;
6423                    }
6424                } else if let Some(from_query) = from_query {
6425                    // Data unload from query
6426                    write!(f, " FROM ({from_query})")?;
6427                }
6428
6429                if let Some(files) = files {
6430                    write!(f, " FILES = ('{}')", display_separated(files, "', '"))?;
6431                }
6432                if let Some(pattern) = pattern {
6433                    write!(f, " PATTERN = '{pattern}'")?;
6434                }
6435                if let Some(partition) = partition {
6436                    write!(f, " PARTITION BY {partition}")?;
6437                }
6438                if !file_format.options.is_empty() {
6439                    write!(f, " FILE_FORMAT=({file_format})")?;
6440                }
6441                if !copy_options.options.is_empty() {
6442                    match kind {
6443                        CopyIntoSnowflakeKind::Table => {
6444                            write!(f, " COPY_OPTIONS=({copy_options})")?
6445                        }
6446                        CopyIntoSnowflakeKind::Location => write!(f, " {copy_options}")?,
6447                    }
6448                }
6449                if let Some(validation_mode) = validation_mode {
6450                    write!(f, " VALIDATION_MODE = {validation_mode}")?;
6451                }
6452                Ok(())
6453            }
6454            Statement::CreateType {
6455                name,
6456                representation,
6457            } => {
6458                write!(f, "CREATE TYPE {name}")?;
6459                if let Some(repr) = representation {
6460                    write!(f, " {repr}")?;
6461                }
6462                Ok(())
6463            }
6464            Statement::Pragma { name, value, is_eq } => {
6465                write!(f, "PRAGMA {name}")?;
6466                if value.is_some() {
6467                    let val = value.as_ref().unwrap();
6468                    if *is_eq {
6469                        write!(f, " = {val}")?;
6470                    } else {
6471                        write!(f, "({val})")?;
6472                    }
6473                }
6474                Ok(())
6475            }
6476            Statement::Lock(lock) => lock.fmt(f),
6477            Statement::LockTables { tables } => {
6478                write!(f, "LOCK TABLES {}", display_comma_separated(tables))
6479            }
6480            Statement::UnlockTables => {
6481                write!(f, "UNLOCK TABLES")
6482            }
6483            Statement::Unload {
6484                query,
6485                query_text,
6486                to,
6487                auth,
6488                with,
6489                options,
6490            } => {
6491                write!(f, "UNLOAD(")?;
6492                if let Some(query) = query {
6493                    write!(f, "{query}")?;
6494                }
6495                if let Some(query_text) = query_text {
6496                    write!(f, "'{query_text}'")?;
6497                }
6498                write!(f, ") TO {to}")?;
6499                if let Some(auth) = auth {
6500                    write!(f, " IAM_ROLE {auth}")?;
6501                }
6502                if !with.is_empty() {
6503                    write!(f, " WITH ({})", display_comma_separated(with))?;
6504                }
6505                if !options.is_empty() {
6506                    write!(f, " {}", display_separated(options, " "))?;
6507                }
6508                Ok(())
6509            }
6510            Statement::OptimizeTable {
6511                name,
6512                has_table_keyword,
6513                on_cluster,
6514                partition,
6515                include_final,
6516                deduplicate,
6517                predicate,
6518                zorder,
6519            } => {
6520                write!(f, "OPTIMIZE")?;
6521                if *has_table_keyword {
6522                    write!(f, " TABLE")?;
6523                }
6524                write!(f, " {name}")?;
6525                if let Some(on_cluster) = on_cluster {
6526                    write!(f, " ON CLUSTER {on_cluster}")?;
6527                }
6528                if let Some(partition) = partition {
6529                    write!(f, " {partition}")?;
6530                }
6531                if *include_final {
6532                    write!(f, " FINAL")?;
6533                }
6534                if let Some(deduplicate) = deduplicate {
6535                    write!(f, " {deduplicate}")?;
6536                }
6537                if let Some(predicate) = predicate {
6538                    write!(f, " WHERE {predicate}")?;
6539                }
6540                if let Some(zorder) = zorder {
6541                    write!(f, " ZORDER BY ({})", display_comma_separated(zorder))?;
6542                }
6543                Ok(())
6544            }
6545            Statement::LISTEN { channel } => {
6546                write!(f, "LISTEN {channel}")?;
6547                Ok(())
6548            }
6549            Statement::UNLISTEN { channel } => {
6550                write!(f, "UNLISTEN {channel}")?;
6551                Ok(())
6552            }
6553            Statement::NOTIFY { channel, payload } => {
6554                write!(f, "NOTIFY {channel}")?;
6555                if let Some(payload) = payload {
6556                    write!(f, ", '{payload}'")?;
6557                }
6558                Ok(())
6559            }
6560            Statement::RenameTable(rename_tables) => {
6561                write!(f, "RENAME TABLE {}", display_comma_separated(rename_tables))
6562            }
6563            Statement::RaisError {
6564                message,
6565                severity,
6566                state,
6567                arguments,
6568                options,
6569            } => {
6570                write!(f, "RAISERROR({message}, {severity}, {state}")?;
6571                if !arguments.is_empty() {
6572                    write!(f, ", {}", display_comma_separated(arguments))?;
6573                }
6574                write!(f, ")")?;
6575                if !options.is_empty() {
6576                    write!(f, " WITH {}", display_comma_separated(options))?;
6577                }
6578                Ok(())
6579            }
6580            Statement::Throw(s) => write!(f, "{s}"),
6581            Statement::Print(s) => write!(f, "{s}"),
6582            Statement::WaitFor(s) => write!(f, "{s}"),
6583            Statement::Return(r) => write!(f, "{r}"),
6584            Statement::List(command) => write!(f, "LIST {command}"),
6585            Statement::Remove(command) => write!(f, "REMOVE {command}"),
6586            Statement::ExportData(e) => write!(f, "{e}"),
6587            Statement::CreateUser(s) => write!(f, "{s}"),
6588            Statement::AlterSchema(s) => write!(f, "{s}"),
6589            Statement::Vacuum(s) => write!(f, "{s}"),
6590            Statement::AlterUser(s) => write!(f, "{s}"),
6591            Statement::Reset(s) => write!(f, "{s}"),
6592        }
6593    }
6594}
6595
6596/// Can use to describe options in create sequence or table column type identity
6597/// ```sql
6598/// [ INCREMENT [ BY ] increment ]
6599///     [ MINVALUE minvalue | NO MINVALUE ] [ MAXVALUE maxvalue | NO MAXVALUE ]
6600///     [ START [ WITH ] start ] [ CACHE cache ] [ [ NO ] CYCLE ]
6601/// ```
6602#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6603#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6604#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6605pub enum SequenceOptions {
6606    /// `INCREMENT [BY] <expr>` option; second value indicates presence of `BY` keyword.
6607    IncrementBy(Expr, bool),
6608    /// `MINVALUE <expr>` or `NO MINVALUE`.
6609    MinValue(Option<Expr>),
6610    /// `MAXVALUE <expr>` or `NO MAXVALUE`.
6611    MaxValue(Option<Expr>),
6612    /// `START [WITH] <expr>`; second value indicates presence of `WITH`.
6613    StartWith(Expr, bool),
6614    /// `CACHE <expr>` option.
6615    Cache(Expr),
6616    /// `CYCLE` or `NO CYCLE` option.
6617    Cycle(bool),
6618}
6619
6620impl fmt::Display for SequenceOptions {
6621    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6622        match self {
6623            SequenceOptions::IncrementBy(increment, by) => {
6624                write!(
6625                    f,
6626                    " INCREMENT{by} {increment}",
6627                    by = if *by { " BY" } else { "" },
6628                    increment = increment
6629                )
6630            }
6631            SequenceOptions::MinValue(Some(expr)) => {
6632                write!(f, " MINVALUE {expr}")
6633            }
6634            SequenceOptions::MinValue(None) => {
6635                write!(f, " NO MINVALUE")
6636            }
6637            SequenceOptions::MaxValue(Some(expr)) => {
6638                write!(f, " MAXVALUE {expr}")
6639            }
6640            SequenceOptions::MaxValue(None) => {
6641                write!(f, " NO MAXVALUE")
6642            }
6643            SequenceOptions::StartWith(start, with) => {
6644                write!(
6645                    f,
6646                    " START{with} {start}",
6647                    with = if *with { " WITH" } else { "" },
6648                    start = start
6649                )
6650            }
6651            SequenceOptions::Cache(cache) => {
6652                write!(f, " CACHE {}", *cache)
6653            }
6654            SequenceOptions::Cycle(no) => {
6655                write!(f, " {}CYCLE", if *no { "NO " } else { "" })
6656            }
6657        }
6658    }
6659}
6660
6661/// Assignment for a `SET` statement (name [=|TO] value)
6662#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6663#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6664#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6665pub struct SetAssignment {
6666    /// Optional context scope (e.g., SESSION or LOCAL).
6667    pub scope: Option<ContextModifier>,
6668    /// Assignment target name.
6669    pub name: ObjectName,
6670    /// Assigned expression value.
6671    pub value: Expr,
6672}
6673
6674impl fmt::Display for SetAssignment {
6675    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6676        write!(
6677            f,
6678            "{}{} = {}",
6679            self.scope.map(|s| format!("{s}")).unwrap_or_default(),
6680            self.name,
6681            self.value
6682        )
6683    }
6684}
6685
6686/// Target of a `TRUNCATE TABLE` command
6687///
6688/// Note this is its own struct because `visit_relation` requires an `ObjectName` (not a `Vec<ObjectName>`)
6689#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6690#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6691#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6692pub struct TruncateTableTarget {
6693    /// name of the table being truncated
6694    #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
6695    pub name: ObjectName,
6696    /// Postgres-specific option: explicitly exclude descendants (also default without ONLY)
6697    /// ```sql
6698    /// TRUNCATE TABLE ONLY name
6699    /// ```
6700    /// <https://www.postgresql.org/docs/current/sql-truncate.html>
6701    pub only: bool,
6702    /// Postgres-specific option: asterisk after table name to explicitly indicate descendants
6703    /// ```sql
6704    /// TRUNCATE TABLE name [ * ]
6705    /// ```
6706    /// <https://www.postgresql.org/docs/current/sql-truncate.html>
6707    pub has_asterisk: bool,
6708}
6709
6710impl fmt::Display for TruncateTableTarget {
6711    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6712        if self.only {
6713            write!(f, "ONLY ")?;
6714        };
6715        write!(f, "{}", self.name)?;
6716        if self.has_asterisk {
6717            write!(f, " *")?;
6718        };
6719        Ok(())
6720    }
6721}
6722
6723/// A `LOCK` statement.
6724///
6725/// See <https://www.postgresql.org/docs/current/sql-lock.html>
6726#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6727#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6728#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6729pub struct Lock {
6730    /// List of tables to lock.
6731    pub tables: Vec<LockTableTarget>,
6732    /// Lock mode.
6733    pub lock_mode: Option<LockTableMode>,
6734    /// Whether `NOWAIT` was specified.
6735    pub nowait: bool,
6736}
6737
6738impl fmt::Display for Lock {
6739    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6740        write!(f, "LOCK TABLE {}", display_comma_separated(&self.tables))?;
6741        if let Some(lock_mode) = &self.lock_mode {
6742            write!(f, " IN {lock_mode} MODE")?;
6743        }
6744        if self.nowait {
6745            write!(f, " NOWAIT")?;
6746        }
6747        Ok(())
6748    }
6749}
6750
6751/// Target of a `LOCK TABLE` command
6752///
6753/// See <https://www.postgresql.org/docs/current/sql-lock.html>
6754#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6755#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6756#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6757pub struct LockTableTarget {
6758    /// Name of the table being locked.
6759    #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
6760    pub name: ObjectName,
6761    /// Whether `ONLY` was specified to exclude descendant tables.
6762    pub only: bool,
6763    /// Whether `*` was specified to explicitly include descendant tables.
6764    pub has_asterisk: bool,
6765}
6766
6767impl fmt::Display for LockTableTarget {
6768    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6769        if self.only {
6770            write!(f, "ONLY ")?;
6771        }
6772        write!(f, "{}", self.name)?;
6773        if self.has_asterisk {
6774            write!(f, " *")?;
6775        }
6776        Ok(())
6777    }
6778}
6779
6780/// PostgreSQL lock modes for `LOCK TABLE`.
6781///
6782/// See <https://www.postgresql.org/docs/current/sql-lock.html>
6783#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6784#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6785#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6786pub enum LockTableMode {
6787    /// `ACCESS SHARE`
6788    AccessShare,
6789    /// `ROW SHARE`
6790    RowShare,
6791    /// `ROW EXCLUSIVE`
6792    RowExclusive,
6793    /// `SHARE UPDATE EXCLUSIVE`
6794    ShareUpdateExclusive,
6795    /// `SHARE`
6796    Share,
6797    /// `SHARE ROW EXCLUSIVE`
6798    ShareRowExclusive,
6799    /// `EXCLUSIVE`
6800    Exclusive,
6801    /// `ACCESS EXCLUSIVE`
6802    AccessExclusive,
6803}
6804
6805impl fmt::Display for LockTableMode {
6806    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
6807        let text = match self {
6808            Self::AccessShare => "ACCESS SHARE",
6809            Self::RowShare => "ROW SHARE",
6810            Self::RowExclusive => "ROW EXCLUSIVE",
6811            Self::ShareUpdateExclusive => "SHARE UPDATE EXCLUSIVE",
6812            Self::Share => "SHARE",
6813            Self::ShareRowExclusive => "SHARE ROW EXCLUSIVE",
6814            Self::Exclusive => "EXCLUSIVE",
6815            Self::AccessExclusive => "ACCESS EXCLUSIVE",
6816        };
6817        write!(f, "{text}")
6818    }
6819}
6820
6821/// PostgreSQL identity option for TRUNCATE table
6822/// [ RESTART IDENTITY | CONTINUE IDENTITY ]
6823#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6824#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6825#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6826pub enum TruncateIdentityOption {
6827    /// Restart identity values (RESTART IDENTITY).
6828    Restart,
6829    /// Continue identity values (CONTINUE IDENTITY).
6830    Continue,
6831}
6832
6833/// Cascade/restrict option for Postgres TRUNCATE table, MySQL GRANT/REVOKE, etc.
6834/// [ CASCADE | RESTRICT ]
6835#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6836#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6837#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6838pub enum CascadeOption {
6839    /// Apply cascading action (e.g., CASCADE).
6840    Cascade,
6841    /// Restrict the action (e.g., RESTRICT).
6842    Restrict,
6843}
6844
6845impl Display for CascadeOption {
6846    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6847        match self {
6848            CascadeOption::Cascade => write!(f, "CASCADE"),
6849            CascadeOption::Restrict => write!(f, "RESTRICT"),
6850        }
6851    }
6852}
6853
6854/// Transaction started with [ TRANSACTION | WORK | TRAN ]
6855#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6856#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6857#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6858pub enum BeginTransactionKind {
6859    /// Standard `TRANSACTION` keyword.
6860    Transaction,
6861    /// Alternate `WORK` keyword.
6862    Work,
6863    /// MSSQL shorthand `TRAN` keyword.
6864    /// See <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/begin-transaction-transact-sql>
6865    Tran,
6866}
6867
6868impl Display for BeginTransactionKind {
6869    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6870        match self {
6871            BeginTransactionKind::Transaction => write!(f, "TRANSACTION"),
6872            BeginTransactionKind::Work => write!(f, "WORK"),
6873            BeginTransactionKind::Tran => write!(f, "TRAN"),
6874        }
6875    }
6876}
6877
6878/// Can use to describe options in  create sequence or table column type identity
6879/// [ MINVALUE minvalue | NO MINVALUE ] [ MAXVALUE maxvalue | NO MAXVALUE ]
6880#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6881#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6882#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6883pub enum MinMaxValue {
6884    /// Clause is not specified.
6885    Empty,
6886    /// NO MINVALUE / NO MAXVALUE.
6887    None,
6888    /// `MINVALUE <expr>` / `MAXVALUE <expr>`.
6889    Some(Expr),
6890}
6891
6892#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6893#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6894#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6895#[non_exhaustive]
6896/// Behavior to apply for `INSERT` when a conflict occurs.
6897pub enum OnInsert {
6898    /// ON DUPLICATE KEY UPDATE (MySQL when the key already exists, then execute an update instead)
6899    DuplicateKeyUpdate(Vec<Assignment>),
6900    /// ON CONFLICT is a PostgreSQL and Sqlite extension
6901    OnConflict(OnConflict),
6902}
6903
6904#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6905#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6906#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6907/// Optional aliases for `INSERT` targets: row alias and optional column aliases.
6908pub struct InsertAliases {
6909    /// Row alias (table-style alias) for the inserted values.
6910    pub row_alias: ObjectName,
6911    /// Optional list of column aliases for the inserted values.
6912    pub col_aliases: Option<Vec<Ident>>,
6913}
6914
6915#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6916#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6917#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6918/// Optional alias for an `INSERT` table; i.e. the table to be inserted into
6919pub struct TableAliasWithoutColumns {
6920    /// `true` if the aliases was explicitly introduced with the "AS" keyword
6921    pub explicit: bool,
6922    /// the alias name itself
6923    pub alias: Ident,
6924}
6925
6926#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6927#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6928#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6929/// `ON CONFLICT` clause representation.
6930pub struct OnConflict {
6931    /// Optional conflict target specifying columns or constraint.
6932    pub conflict_target: Option<ConflictTarget>,
6933    /// Action to take when a conflict occurs.
6934    pub action: OnConflictAction,
6935}
6936#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6937#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6938#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6939/// Target specification for an `ON CONFLICT` clause.
6940pub enum ConflictTarget {
6941    /// Target specified as a list of columns.
6942    Columns(Vec<Ident>),
6943    /// Target specified as a named constraint.
6944    OnConstraint(ObjectName),
6945}
6946#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6947#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6948#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6949/// Action to perform when an `ON CONFLICT` target is matched.
6950pub enum OnConflictAction {
6951    /// Do nothing on conflict.
6952    DoNothing,
6953    /// Perform an update on conflict.
6954    DoUpdate(DoUpdate),
6955}
6956
6957#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6958#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6959#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6960/// Details for `DO UPDATE` action of an `ON CONFLICT` clause.
6961pub struct DoUpdate {
6962    /// Column assignments to perform on update.
6963    pub assignments: Vec<Assignment>,
6964    /// Optional WHERE clause limiting the update.
6965    pub selection: Option<Expr>,
6966}
6967
6968impl fmt::Display for OnInsert {
6969    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6970        match self {
6971            Self::DuplicateKeyUpdate(expr) => write!(
6972                f,
6973                " ON DUPLICATE KEY UPDATE {}",
6974                display_comma_separated(expr)
6975            ),
6976            Self::OnConflict(o) => write!(f, "{o}"),
6977        }
6978    }
6979}
6980impl fmt::Display for OnConflict {
6981    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6982        write!(f, " ON CONFLICT")?;
6983        if let Some(target) = &self.conflict_target {
6984            write!(f, "{target}")?;
6985        }
6986        write!(f, " {}", self.action)
6987    }
6988}
6989impl fmt::Display for ConflictTarget {
6990    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6991        match self {
6992            ConflictTarget::Columns(cols) => write!(f, "({})", display_comma_separated(cols)),
6993            ConflictTarget::OnConstraint(name) => write!(f, " ON CONSTRAINT {name}"),
6994        }
6995    }
6996}
6997impl fmt::Display for OnConflictAction {
6998    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6999        match self {
7000            Self::DoNothing => write!(f, "DO NOTHING"),
7001            Self::DoUpdate(do_update) => {
7002                write!(f, "DO UPDATE")?;
7003                if !do_update.assignments.is_empty() {
7004                    write!(
7005                        f,
7006                        " SET {}",
7007                        display_comma_separated(&do_update.assignments)
7008                    )?;
7009                }
7010                if let Some(selection) = &do_update.selection {
7011                    write!(f, " WHERE {selection}")?;
7012                }
7013                Ok(())
7014            }
7015        }
7016    }
7017}
7018
7019/// Privileges granted in a GRANT statement or revoked in a REVOKE statement.
7020#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7021#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7022#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7023pub enum Privileges {
7024    /// All privileges applicable to the object type
7025    All {
7026        /// Optional keyword from the spec, ignored in practice
7027        with_privileges_keyword: bool,
7028    },
7029    /// Specific privileges (e.g. `SELECT`, `INSERT`)
7030    Actions(Vec<Action>),
7031}
7032
7033impl fmt::Display for Privileges {
7034    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7035        match self {
7036            Privileges::All {
7037                with_privileges_keyword,
7038            } => {
7039                write!(
7040                    f,
7041                    "ALL{}",
7042                    if *with_privileges_keyword {
7043                        " PRIVILEGES"
7044                    } else {
7045                        ""
7046                    }
7047                )
7048            }
7049            Privileges::Actions(actions) => {
7050                write!(f, "{}", display_comma_separated(actions))
7051            }
7052        }
7053    }
7054}
7055
7056/// Specific direction for FETCH statement
7057#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7058#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7059#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7060pub enum FetchDirection {
7061    /// Fetch a specific count of rows.
7062    Count {
7063        /// The limit value for the count.
7064        limit: ValueWithSpan,
7065    },
7066    /// Fetch the next row.
7067    Next,
7068    /// Fetch the prior row.
7069    Prior,
7070    /// Fetch the first row.
7071    First,
7072    /// Fetch the last row.
7073    Last,
7074    /// Fetch an absolute row by index.
7075    Absolute {
7076        /// The absolute index value.
7077        limit: ValueWithSpan,
7078    },
7079    /// Fetch a row relative to the current position.
7080    Relative {
7081        /// The relative offset value.
7082        limit: ValueWithSpan,
7083    },
7084    /// Fetch all rows.
7085    All,
7086    // FORWARD
7087    // FORWARD count
7088    /// Fetch forward by an optional limit.
7089    Forward {
7090        /// Optional forward limit.
7091        limit: Option<ValueWithSpan>,
7092    },
7093    /// Fetch all forward rows.
7094    ForwardAll,
7095    // BACKWARD
7096    // BACKWARD count
7097    /// Fetch backward by an optional limit.
7098    Backward {
7099        /// Optional backward limit.
7100        limit: Option<ValueWithSpan>,
7101    },
7102    /// Fetch all backward rows.
7103    BackwardAll,
7104}
7105
7106impl fmt::Display for FetchDirection {
7107    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7108        match self {
7109            FetchDirection::Count { limit } => f.write_str(&limit.to_string())?,
7110            FetchDirection::Next => f.write_str("NEXT")?,
7111            FetchDirection::Prior => f.write_str("PRIOR")?,
7112            FetchDirection::First => f.write_str("FIRST")?,
7113            FetchDirection::Last => f.write_str("LAST")?,
7114            FetchDirection::Absolute { limit } => {
7115                f.write_str("ABSOLUTE ")?;
7116                f.write_str(&limit.to_string())?;
7117            }
7118            FetchDirection::Relative { limit } => {
7119                f.write_str("RELATIVE ")?;
7120                f.write_str(&limit.to_string())?;
7121            }
7122            FetchDirection::All => f.write_str("ALL")?,
7123            FetchDirection::Forward { limit } => {
7124                f.write_str("FORWARD")?;
7125
7126                if let Some(l) = limit {
7127                    f.write_str(" ")?;
7128                    f.write_str(&l.to_string())?;
7129                }
7130            }
7131            FetchDirection::ForwardAll => f.write_str("FORWARD ALL")?,
7132            FetchDirection::Backward { limit } => {
7133                f.write_str("BACKWARD")?;
7134
7135                if let Some(l) = limit {
7136                    f.write_str(" ")?;
7137                    f.write_str(&l.to_string())?;
7138                }
7139            }
7140            FetchDirection::BackwardAll => f.write_str("BACKWARD ALL")?,
7141        };
7142
7143        Ok(())
7144    }
7145}
7146
7147/// The "position" for a FETCH statement.
7148///
7149/// [MsSql](https://learn.microsoft.com/en-us/sql/t-sql/language-elements/fetch-transact-sql)
7150#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7151#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7152#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7153pub enum FetchPosition {
7154    /// Use `FROM <pos>` position specifier.
7155    From,
7156    /// Use `IN <pos>` position specifier.
7157    In,
7158}
7159
7160impl fmt::Display for FetchPosition {
7161    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7162        match self {
7163            FetchPosition::From => f.write_str("FROM")?,
7164            FetchPosition::In => f.write_str("IN")?,
7165        };
7166
7167        Ok(())
7168    }
7169}
7170
7171/// A privilege on a database object (table, sequence, etc.).
7172#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7173#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7174#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7175pub enum Action {
7176    /// Add a search optimization.
7177    AddSearchOptimization,
7178    /// Apply an `APPLY` operation with a specific type.
7179    Apply {
7180        /// The type of apply operation.
7181        apply_type: ActionApplyType,
7182    },
7183    /// Apply a budget operation.
7184    ApplyBudget,
7185    /// Attach a listing.
7186    AttachListing,
7187    /// Attach a policy.
7188    AttachPolicy,
7189    /// Audit operation.
7190    Audit,
7191    /// Bind a service endpoint.
7192    BindServiceEndpoint,
7193    /// Connect permission.
7194    Connect,
7195    /// Create action, optionally specifying an object type.
7196    Create {
7197        /// Optional object type to create.
7198        obj_type: Option<ActionCreateObjectType>,
7199    },
7200    /// Actions related to database roles.
7201    DatabaseRole {
7202        /// The role name.
7203        role: ObjectName,
7204    },
7205    /// Delete permission.
7206    Delete,
7207    /// Drop permission.
7208    Drop,
7209    /// Evolve schema permission.
7210    EvolveSchema,
7211    /// Exec action (execute) with optional object type.
7212    Exec {
7213        /// Optional execute object type.
7214        obj_type: Option<ActionExecuteObjectType>,
7215    },
7216    /// Execute action with optional object type.
7217    Execute {
7218        /// Optional execute object type.
7219        obj_type: Option<ActionExecuteObjectType>,
7220    },
7221    /// Failover operation.
7222    Failover,
7223    /// Use imported privileges.
7224    ImportedPrivileges,
7225    /// Import a share.
7226    ImportShare,
7227    /// Insert rows with optional column list.
7228    Insert {
7229        /// Optional list of target columns for insert.
7230        columns: Option<Vec<Ident>>,
7231    },
7232    /// Manage operation with a specific manage type.
7233    Manage {
7234        /// The specific manage sub-type.
7235        manage_type: ActionManageType,
7236    },
7237    /// Manage releases.
7238    ManageReleases,
7239    /// Manage versions.
7240    ManageVersions,
7241    /// Modify operation with an optional modify type.
7242    Modify {
7243        /// The optional modify sub-type.
7244        modify_type: Option<ActionModifyType>,
7245    },
7246    /// Monitor operation with an optional monitor type.
7247    Monitor {
7248        /// The optional monitor sub-type.
7249        monitor_type: Option<ActionMonitorType>,
7250    },
7251    /// Operate permission.
7252    Operate,
7253    /// Override share restrictions.
7254    OverrideShareRestrictions,
7255    /// Ownership permission.
7256    Ownership,
7257    /// Purchase a data exchange listing.
7258    PurchaseDataExchangeListing,
7259
7260    /// Read access.
7261    Read,
7262    /// Read session-level access.
7263    ReadSession,
7264    /// References with optional column list.
7265    References {
7266        /// Optional list of referenced column identifiers.
7267        columns: Option<Vec<Ident>>,
7268    },
7269    /// Replication permission.
7270    Replicate,
7271    /// Resolve all references.
7272    ResolveAll,
7273    /// Role-related permission with target role name.
7274    Role {
7275        /// The target role name.
7276        role: ObjectName,
7277    },
7278    /// Select permission with optional column list.
7279    Select {
7280        /// Optional list of selected columns.
7281        columns: Option<Vec<Ident>>,
7282    },
7283    /// Temporary object permission.
7284    Temporary,
7285    /// Trigger-related permission.
7286    Trigger,
7287    /// Truncate permission.
7288    Truncate,
7289    /// Update permission with optional affected columns.
7290    Update {
7291        /// Optional list of columns affected by update.
7292        columns: Option<Vec<Ident>>,
7293    },
7294    /// Usage permission.
7295    Usage,
7296}
7297
7298impl fmt::Display for Action {
7299    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7300        match self {
7301            Action::AddSearchOptimization => f.write_str("ADD SEARCH OPTIMIZATION")?,
7302            Action::Apply { apply_type } => write!(f, "APPLY {apply_type}")?,
7303            Action::ApplyBudget => f.write_str("APPLYBUDGET")?,
7304            Action::AttachListing => f.write_str("ATTACH LISTING")?,
7305            Action::AttachPolicy => f.write_str("ATTACH POLICY")?,
7306            Action::Audit => f.write_str("AUDIT")?,
7307            Action::BindServiceEndpoint => f.write_str("BIND SERVICE ENDPOINT")?,
7308            Action::Connect => f.write_str("CONNECT")?,
7309            Action::Create { obj_type } => {
7310                f.write_str("CREATE")?;
7311                if let Some(obj_type) = obj_type {
7312                    write!(f, " {obj_type}")?
7313                }
7314            }
7315            Action::DatabaseRole { role } => write!(f, "DATABASE ROLE {role}")?,
7316            Action::Delete => f.write_str("DELETE")?,
7317            Action::Drop => f.write_str("DROP")?,
7318            Action::EvolveSchema => f.write_str("EVOLVE SCHEMA")?,
7319            Action::Exec { obj_type } => {
7320                f.write_str("EXEC")?;
7321                if let Some(obj_type) = obj_type {
7322                    write!(f, " {obj_type}")?
7323                }
7324            }
7325            Action::Execute { obj_type } => {
7326                f.write_str("EXECUTE")?;
7327                if let Some(obj_type) = obj_type {
7328                    write!(f, " {obj_type}")?
7329                }
7330            }
7331            Action::Failover => f.write_str("FAILOVER")?,
7332            Action::ImportedPrivileges => f.write_str("IMPORTED PRIVILEGES")?,
7333            Action::ImportShare => f.write_str("IMPORT SHARE")?,
7334            Action::Insert { .. } => f.write_str("INSERT")?,
7335            Action::Manage { manage_type } => write!(f, "MANAGE {manage_type}")?,
7336            Action::ManageReleases => f.write_str("MANAGE RELEASES")?,
7337            Action::ManageVersions => f.write_str("MANAGE VERSIONS")?,
7338            Action::Modify { modify_type } => {
7339                write!(f, "MODIFY")?;
7340                if let Some(modify_type) = modify_type {
7341                    write!(f, " {modify_type}")?;
7342                }
7343            }
7344            Action::Monitor { monitor_type } => {
7345                write!(f, "MONITOR")?;
7346                if let Some(monitor_type) = monitor_type {
7347                    write!(f, " {monitor_type}")?
7348                }
7349            }
7350            Action::Operate => f.write_str("OPERATE")?,
7351            Action::OverrideShareRestrictions => f.write_str("OVERRIDE SHARE RESTRICTIONS")?,
7352            Action::Ownership => f.write_str("OWNERSHIP")?,
7353            Action::PurchaseDataExchangeListing => f.write_str("PURCHASE DATA EXCHANGE LISTING")?,
7354            Action::Read => f.write_str("READ")?,
7355            Action::ReadSession => f.write_str("READ SESSION")?,
7356            Action::References { .. } => f.write_str("REFERENCES")?,
7357            Action::Replicate => f.write_str("REPLICATE")?,
7358            Action::ResolveAll => f.write_str("RESOLVE ALL")?,
7359            Action::Role { role } => write!(f, "ROLE {role}")?,
7360            Action::Select { .. } => f.write_str("SELECT")?,
7361            Action::Temporary => f.write_str("TEMPORARY")?,
7362            Action::Trigger => f.write_str("TRIGGER")?,
7363            Action::Truncate => f.write_str("TRUNCATE")?,
7364            Action::Update { .. } => f.write_str("UPDATE")?,
7365            Action::Usage => f.write_str("USAGE")?,
7366        };
7367        match self {
7368            Action::Insert { columns }
7369            | Action::References { columns }
7370            | Action::Select { columns }
7371            | Action::Update { columns } => {
7372                if let Some(columns) = columns {
7373                    write!(f, " ({})", display_comma_separated(columns))?;
7374                }
7375            }
7376            _ => (),
7377        };
7378        Ok(())
7379    }
7380}
7381
7382#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7383#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7384#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7385/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
7386/// under `globalPrivileges` in the `CREATE` privilege.
7387pub enum ActionCreateObjectType {
7388    /// An account-level object.
7389    Account,
7390    /// An application object.
7391    Application,
7392    /// An application package object.
7393    ApplicationPackage,
7394    /// A compute pool object.
7395    ComputePool,
7396    /// A data exchange listing.
7397    DataExchangeListing,
7398    /// A database object.
7399    Database,
7400    /// An external volume object.
7401    ExternalVolume,
7402    /// A failover group object.
7403    FailoverGroup,
7404    /// An integration object.
7405    Integration,
7406    /// A network policy object.
7407    NetworkPolicy,
7408    /// An organization listing.
7409    OrganiationListing,
7410    /// A replication group object.
7411    ReplicationGroup,
7412    /// A role object.
7413    Role,
7414    /// A schema object.
7415    Schema,
7416    /// A share object.
7417    Share,
7418    /// A user object.
7419    User,
7420    /// A warehouse object.
7421    Warehouse,
7422}
7423
7424impl fmt::Display for ActionCreateObjectType {
7425    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7426        match self {
7427            ActionCreateObjectType::Account => write!(f, "ACCOUNT"),
7428            ActionCreateObjectType::Application => write!(f, "APPLICATION"),
7429            ActionCreateObjectType::ApplicationPackage => write!(f, "APPLICATION PACKAGE"),
7430            ActionCreateObjectType::ComputePool => write!(f, "COMPUTE POOL"),
7431            ActionCreateObjectType::DataExchangeListing => write!(f, "DATA EXCHANGE LISTING"),
7432            ActionCreateObjectType::Database => write!(f, "DATABASE"),
7433            ActionCreateObjectType::ExternalVolume => write!(f, "EXTERNAL VOLUME"),
7434            ActionCreateObjectType::FailoverGroup => write!(f, "FAILOVER GROUP"),
7435            ActionCreateObjectType::Integration => write!(f, "INTEGRATION"),
7436            ActionCreateObjectType::NetworkPolicy => write!(f, "NETWORK POLICY"),
7437            ActionCreateObjectType::OrganiationListing => write!(f, "ORGANIZATION LISTING"),
7438            ActionCreateObjectType::ReplicationGroup => write!(f, "REPLICATION GROUP"),
7439            ActionCreateObjectType::Role => write!(f, "ROLE"),
7440            ActionCreateObjectType::Schema => write!(f, "SCHEMA"),
7441            ActionCreateObjectType::Share => write!(f, "SHARE"),
7442            ActionCreateObjectType::User => write!(f, "USER"),
7443            ActionCreateObjectType::Warehouse => write!(f, "WAREHOUSE"),
7444        }
7445    }
7446}
7447
7448#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7449#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7450#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7451/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
7452/// under `globalPrivileges` in the `APPLY` privilege.
7453pub enum ActionApplyType {
7454    /// Apply an aggregation policy.
7455    AggregationPolicy,
7456    /// Apply an authentication policy.
7457    AuthenticationPolicy,
7458    /// Apply a join policy.
7459    JoinPolicy,
7460    /// Apply a masking policy.
7461    MaskingPolicy,
7462    /// Apply a packages policy.
7463    PackagesPolicy,
7464    /// Apply a password policy.
7465    PasswordPolicy,
7466    /// Apply a projection policy.
7467    ProjectionPolicy,
7468    /// Apply a row access policy.
7469    RowAccessPolicy,
7470    /// Apply a session policy.
7471    SessionPolicy,
7472    /// Apply a tag.
7473    Tag,
7474}
7475
7476impl fmt::Display for ActionApplyType {
7477    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7478        match self {
7479            ActionApplyType::AggregationPolicy => write!(f, "AGGREGATION POLICY"),
7480            ActionApplyType::AuthenticationPolicy => write!(f, "AUTHENTICATION POLICY"),
7481            ActionApplyType::JoinPolicy => write!(f, "JOIN POLICY"),
7482            ActionApplyType::MaskingPolicy => write!(f, "MASKING POLICY"),
7483            ActionApplyType::PackagesPolicy => write!(f, "PACKAGES POLICY"),
7484            ActionApplyType::PasswordPolicy => write!(f, "PASSWORD POLICY"),
7485            ActionApplyType::ProjectionPolicy => write!(f, "PROJECTION POLICY"),
7486            ActionApplyType::RowAccessPolicy => write!(f, "ROW ACCESS POLICY"),
7487            ActionApplyType::SessionPolicy => write!(f, "SESSION POLICY"),
7488            ActionApplyType::Tag => write!(f, "TAG"),
7489        }
7490    }
7491}
7492
7493#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7494#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7495#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7496/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
7497/// under `globalPrivileges` in the `EXECUTE` privilege.
7498pub enum ActionExecuteObjectType {
7499    /// Alert object.
7500    Alert,
7501    /// Data metric function object.
7502    DataMetricFunction,
7503    /// Managed alert object.
7504    ManagedAlert,
7505    /// Managed task object.
7506    ManagedTask,
7507    /// Task object.
7508    Task,
7509}
7510
7511impl fmt::Display for ActionExecuteObjectType {
7512    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7513        match self {
7514            ActionExecuteObjectType::Alert => write!(f, "ALERT"),
7515            ActionExecuteObjectType::DataMetricFunction => write!(f, "DATA METRIC FUNCTION"),
7516            ActionExecuteObjectType::ManagedAlert => write!(f, "MANAGED ALERT"),
7517            ActionExecuteObjectType::ManagedTask => write!(f, "MANAGED TASK"),
7518            ActionExecuteObjectType::Task => write!(f, "TASK"),
7519        }
7520    }
7521}
7522
7523#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7524#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7525#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7526/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
7527/// under `globalPrivileges` in the `MANAGE` privilege.
7528pub enum ActionManageType {
7529    /// Account support cases management.
7530    AccountSupportCases,
7531    /// Event sharing management.
7532    EventSharing,
7533    /// Grants management.
7534    Grants,
7535    /// Listing auto-fulfillment management.
7536    ListingAutoFulfillment,
7537    /// Organization support cases management.
7538    OrganizationSupportCases,
7539    /// User support cases management.
7540    UserSupportCases,
7541    /// Warehouses management.
7542    Warehouses,
7543}
7544
7545impl fmt::Display for ActionManageType {
7546    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7547        match self {
7548            ActionManageType::AccountSupportCases => write!(f, "ACCOUNT SUPPORT CASES"),
7549            ActionManageType::EventSharing => write!(f, "EVENT SHARING"),
7550            ActionManageType::Grants => write!(f, "GRANTS"),
7551            ActionManageType::ListingAutoFulfillment => write!(f, "LISTING AUTO FULFILLMENT"),
7552            ActionManageType::OrganizationSupportCases => write!(f, "ORGANIZATION SUPPORT CASES"),
7553            ActionManageType::UserSupportCases => write!(f, "USER SUPPORT CASES"),
7554            ActionManageType::Warehouses => write!(f, "WAREHOUSES"),
7555        }
7556    }
7557}
7558
7559#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7560#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7561#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7562/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
7563/// under `globalPrivileges` in the `MODIFY` privilege.
7564pub enum ActionModifyType {
7565    /// Modify log level.
7566    LogLevel,
7567    /// Modify trace level.
7568    TraceLevel,
7569    /// Modify session log level.
7570    SessionLogLevel,
7571    /// Modify session trace level.
7572    SessionTraceLevel,
7573}
7574
7575impl fmt::Display for ActionModifyType {
7576    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7577        match self {
7578            ActionModifyType::LogLevel => write!(f, "LOG LEVEL"),
7579            ActionModifyType::TraceLevel => write!(f, "TRACE LEVEL"),
7580            ActionModifyType::SessionLogLevel => write!(f, "SESSION LOG LEVEL"),
7581            ActionModifyType::SessionTraceLevel => write!(f, "SESSION TRACE LEVEL"),
7582        }
7583    }
7584}
7585
7586#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7587#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7588#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7589/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
7590/// under `globalPrivileges` in the `MONITOR` privilege.
7591pub enum ActionMonitorType {
7592    /// Monitor execution.
7593    Execution,
7594    /// Monitor security.
7595    Security,
7596    /// Monitor usage.
7597    Usage,
7598}
7599
7600impl fmt::Display for ActionMonitorType {
7601    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7602        match self {
7603            ActionMonitorType::Execution => write!(f, "EXECUTION"),
7604            ActionMonitorType::Security => write!(f, "SECURITY"),
7605            ActionMonitorType::Usage => write!(f, "USAGE"),
7606        }
7607    }
7608}
7609
7610/// The principal that receives the privileges
7611#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7612#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7613#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7614pub struct Grantee {
7615    /// The category/type of grantee (role, user, share, etc.).
7616    pub grantee_type: GranteesType,
7617    /// Optional name of the grantee (identifier or user@host).
7618    pub name: Option<GranteeName>,
7619}
7620
7621impl fmt::Display for Grantee {
7622    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7623        if matches!(self.grantee_type, GranteesType::Public) {
7624            return write!(f, "PUBLIC");
7625        }
7626        match self.grantee_type {
7627            GranteesType::Role => {
7628                write!(f, "ROLE ")?;
7629            }
7630            GranteesType::Share => {
7631                write!(f, "SHARE ")?;
7632            }
7633            GranteesType::User => {
7634                write!(f, "USER ")?;
7635            }
7636            GranteesType::Group => {
7637                write!(f, "GROUP ")?;
7638            }
7639            GranteesType::Public => {}
7640            GranteesType::DatabaseRole => {
7641                write!(f, "DATABASE ROLE ")?;
7642            }
7643            GranteesType::Application => {
7644                write!(f, "APPLICATION ")?;
7645            }
7646            GranteesType::ApplicationRole => {
7647                write!(f, "APPLICATION ROLE ")?;
7648            }
7649            GranteesType::None => (),
7650        }
7651        if let Some(ref name) = self.name {
7652            name.fmt(f)?;
7653        }
7654        Ok(())
7655    }
7656}
7657
7658#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7659#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7660#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7661/// The kind of principal receiving privileges.
7662pub enum GranteesType {
7663    /// A role principal.
7664    Role,
7665    /// A share principal.
7666    Share,
7667    /// A user principal.
7668    User,
7669    /// A group principal.
7670    Group,
7671    /// The public principal.
7672    Public,
7673    /// A database role principal.
7674    DatabaseRole,
7675    /// An application principal.
7676    Application,
7677    /// An application role principal.
7678    ApplicationRole,
7679    /// No specific principal (e.g. `NONE`).
7680    None,
7681}
7682
7683/// Users/roles designated in a GRANT/REVOKE
7684#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7685#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7686#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7687pub enum GranteeName {
7688    /// A bare identifier
7689    ObjectName(ObjectName),
7690    /// A MySQL user/host pair such as 'root'@'%'
7691    UserHost {
7692        /// The user identifier portion.
7693        user: Ident,
7694        /// The host identifier portion.
7695        host: Ident,
7696    },
7697}
7698
7699impl fmt::Display for GranteeName {
7700    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7701        match self {
7702            GranteeName::ObjectName(name) => name.fmt(f),
7703            GranteeName::UserHost { user, host } => {
7704                write!(f, "{user}@{host}")
7705            }
7706        }
7707    }
7708}
7709
7710/// Objects on which privileges are granted in a GRANT statement.
7711#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7712#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7713#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7714pub enum GrantObjects {
7715    /// Grant privileges on `ALL SEQUENCES IN SCHEMA <schema_name> [, ...]`
7716    AllSequencesInSchema {
7717        /// The target schema names.
7718        schemas: Vec<ObjectName>,
7719    },
7720    /// Grant privileges on `ALL TABLES IN SCHEMA <schema_name> [, ...]`
7721    AllTablesInSchema {
7722        /// The target schema names.
7723        schemas: Vec<ObjectName>,
7724    },
7725    /// Grant privileges on `ALL VIEWS IN SCHEMA <schema_name> [, ...]`
7726    AllViewsInSchema {
7727        /// The target schema names.
7728        schemas: Vec<ObjectName>,
7729    },
7730    /// Grant privileges on `ALL MATERIALIZED VIEWS IN SCHEMA <schema_name> [, ...]`
7731    AllMaterializedViewsInSchema {
7732        /// The target schema names.
7733        schemas: Vec<ObjectName>,
7734    },
7735    /// Grant privileges on `ALL EXTERNAL TABLES IN SCHEMA <schema_name> [, ...]`
7736    AllExternalTablesInSchema {
7737        /// The target schema names.
7738        schemas: Vec<ObjectName>,
7739    },
7740    /// Grant privileges on `ALL FUNCTIONS IN SCHEMA <schema_name> [, ...]`
7741    AllFunctionsInSchema {
7742        /// The target schema names.
7743        schemas: Vec<ObjectName>,
7744    },
7745    /// Grant privileges on `FUTURE SCHEMAS IN DATABASE <database_name> [, ...]`
7746    FutureSchemasInDatabase {
7747        /// The target database names.
7748        databases: Vec<ObjectName>,
7749    },
7750    /// Grant privileges on `FUTURE TABLES IN SCHEMA <schema_name> [, ...]`
7751    FutureTablesInSchema {
7752        /// The target schema names.
7753        schemas: Vec<ObjectName>,
7754    },
7755    /// Grant privileges on `FUTURE VIEWS IN SCHEMA <schema_name> [, ...]`
7756    FutureViewsInSchema {
7757        /// The target schema names.
7758        schemas: Vec<ObjectName>,
7759    },
7760    /// Grant privileges on `FUTURE EXTERNAL TABLES IN SCHEMA <schema_name> [, ...]`
7761    FutureExternalTablesInSchema {
7762        /// The target schema names.
7763        schemas: Vec<ObjectName>,
7764    },
7765    /// Grant privileges on `FUTURE MATERIALIZED VIEWS IN SCHEMA <schema_name> [, ...]`
7766    FutureMaterializedViewsInSchema {
7767        /// The target schema names.
7768        schemas: Vec<ObjectName>,
7769    },
7770    /// Grant privileges on `FUTURE SEQUENCES IN SCHEMA <schema_name> [, ...]`
7771    FutureSequencesInSchema {
7772        /// The target schema names.
7773        schemas: Vec<ObjectName>,
7774    },
7775    /// Grant privileges on specific databases
7776    Databases(Vec<ObjectName>),
7777    /// Grant privileges on specific schemas
7778    Schemas(Vec<ObjectName>),
7779    /// Grant privileges on specific sequences
7780    Sequences(Vec<ObjectName>),
7781    /// Grant privileges on specific tables
7782    Tables(Vec<ObjectName>),
7783    /// Grant privileges on specific views
7784    Views(Vec<ObjectName>),
7785    /// Grant privileges on specific warehouses
7786    Warehouses(Vec<ObjectName>),
7787    /// Grant privileges on specific integrations
7788    Integrations(Vec<ObjectName>),
7789    /// Grant privileges on resource monitors
7790    ResourceMonitors(Vec<ObjectName>),
7791    /// Grant privileges on users
7792    Users(Vec<ObjectName>),
7793    /// Grant privileges on compute pools
7794    ComputePools(Vec<ObjectName>),
7795    /// Grant privileges on connections
7796    Connections(Vec<ObjectName>),
7797    /// Grant privileges on failover groups
7798    FailoverGroup(Vec<ObjectName>),
7799    /// Grant privileges on replication group
7800    ReplicationGroup(Vec<ObjectName>),
7801    /// Grant privileges on external volumes
7802    ExternalVolumes(Vec<ObjectName>),
7803    /// Grant privileges on a procedure. In dialects that
7804    /// support overloading, the argument types must be specified.
7805    ///
7806    /// For example:
7807    /// `GRANT USAGE ON PROCEDURE foo(varchar) TO ROLE role1`
7808    Procedure {
7809        /// The procedure name.
7810        name: ObjectName,
7811        /// Optional argument types for overloaded procedures.
7812        arg_types: Vec<DataType>,
7813    },
7814
7815    /// Grant privileges on a function. In dialects that
7816    /// support overloading, the argument types must be specified.
7817    ///
7818    /// For example:
7819    /// `GRANT USAGE ON FUNCTION foo(varchar) TO ROLE role1`
7820    Function {
7821        /// The function name.
7822        name: ObjectName,
7823        /// Optional argument types for overloaded functions.
7824        arg_types: Vec<DataType>,
7825    },
7826
7827    /// Grant privileges on specific user-defined types (PostgreSQL).
7828    ///
7829    /// For example:
7830    /// `GRANT USAGE ON TYPE user_role TO app_user`
7831    Types(Vec<ObjectName>),
7832
7833    /// Grant privileges on specific domains (PostgreSQL).
7834    ///
7835    /// For example:
7836    /// `GRANT USAGE ON DOMAIN email_addr TO app_user`
7837    Domains(Vec<ObjectName>),
7838}
7839
7840impl fmt::Display for GrantObjects {
7841    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7842        match self {
7843            GrantObjects::Sequences(sequences) => {
7844                write!(f, "SEQUENCE {}", display_comma_separated(sequences))
7845            }
7846            GrantObjects::Databases(databases) => {
7847                write!(f, "DATABASE {}", display_comma_separated(databases))
7848            }
7849            GrantObjects::Schemas(schemas) => {
7850                write!(f, "SCHEMA {}", display_comma_separated(schemas))
7851            }
7852            GrantObjects::Tables(tables) => {
7853                write!(f, "{}", display_comma_separated(tables))
7854            }
7855            GrantObjects::Views(views) => {
7856                write!(f, "VIEW {}", display_comma_separated(views))
7857            }
7858            GrantObjects::Warehouses(warehouses) => {
7859                write!(f, "WAREHOUSE {}", display_comma_separated(warehouses))
7860            }
7861            GrantObjects::Integrations(integrations) => {
7862                write!(f, "INTEGRATION {}", display_comma_separated(integrations))
7863            }
7864            GrantObjects::AllSequencesInSchema { schemas } => {
7865                write!(
7866                    f,
7867                    "ALL SEQUENCES IN SCHEMA {}",
7868                    display_comma_separated(schemas)
7869                )
7870            }
7871            GrantObjects::AllTablesInSchema { schemas } => {
7872                write!(
7873                    f,
7874                    "ALL TABLES IN SCHEMA {}",
7875                    display_comma_separated(schemas)
7876                )
7877            }
7878            GrantObjects::AllExternalTablesInSchema { schemas } => {
7879                write!(
7880                    f,
7881                    "ALL EXTERNAL TABLES IN SCHEMA {}",
7882                    display_comma_separated(schemas)
7883                )
7884            }
7885            GrantObjects::AllViewsInSchema { schemas } => {
7886                write!(
7887                    f,
7888                    "ALL VIEWS IN SCHEMA {}",
7889                    display_comma_separated(schemas)
7890                )
7891            }
7892            GrantObjects::AllMaterializedViewsInSchema { schemas } => {
7893                write!(
7894                    f,
7895                    "ALL MATERIALIZED VIEWS IN SCHEMA {}",
7896                    display_comma_separated(schemas)
7897                )
7898            }
7899            GrantObjects::AllFunctionsInSchema { schemas } => {
7900                write!(
7901                    f,
7902                    "ALL FUNCTIONS IN SCHEMA {}",
7903                    display_comma_separated(schemas)
7904                )
7905            }
7906            GrantObjects::FutureSchemasInDatabase { databases } => {
7907                write!(
7908                    f,
7909                    "FUTURE SCHEMAS IN DATABASE {}",
7910                    display_comma_separated(databases)
7911                )
7912            }
7913            GrantObjects::FutureTablesInSchema { schemas } => {
7914                write!(
7915                    f,
7916                    "FUTURE TABLES IN SCHEMA {}",
7917                    display_comma_separated(schemas)
7918                )
7919            }
7920            GrantObjects::FutureExternalTablesInSchema { schemas } => {
7921                write!(
7922                    f,
7923                    "FUTURE EXTERNAL TABLES IN SCHEMA {}",
7924                    display_comma_separated(schemas)
7925                )
7926            }
7927            GrantObjects::FutureViewsInSchema { schemas } => {
7928                write!(
7929                    f,
7930                    "FUTURE VIEWS IN SCHEMA {}",
7931                    display_comma_separated(schemas)
7932                )
7933            }
7934            GrantObjects::FutureMaterializedViewsInSchema { schemas } => {
7935                write!(
7936                    f,
7937                    "FUTURE MATERIALIZED VIEWS IN SCHEMA {}",
7938                    display_comma_separated(schemas)
7939                )
7940            }
7941            GrantObjects::FutureSequencesInSchema { schemas } => {
7942                write!(
7943                    f,
7944                    "FUTURE SEQUENCES IN SCHEMA {}",
7945                    display_comma_separated(schemas)
7946                )
7947            }
7948            GrantObjects::ResourceMonitors(objects) => {
7949                write!(f, "RESOURCE MONITOR {}", display_comma_separated(objects))
7950            }
7951            GrantObjects::Users(objects) => {
7952                write!(f, "USER {}", display_comma_separated(objects))
7953            }
7954            GrantObjects::ComputePools(objects) => {
7955                write!(f, "COMPUTE POOL {}", display_comma_separated(objects))
7956            }
7957            GrantObjects::Connections(objects) => {
7958                write!(f, "CONNECTION {}", display_comma_separated(objects))
7959            }
7960            GrantObjects::FailoverGroup(objects) => {
7961                write!(f, "FAILOVER GROUP {}", display_comma_separated(objects))
7962            }
7963            GrantObjects::ReplicationGroup(objects) => {
7964                write!(f, "REPLICATION GROUP {}", display_comma_separated(objects))
7965            }
7966            GrantObjects::ExternalVolumes(objects) => {
7967                write!(f, "EXTERNAL VOLUME {}", display_comma_separated(objects))
7968            }
7969            GrantObjects::Procedure { name, arg_types } => {
7970                write!(f, "PROCEDURE {name}")?;
7971                if !arg_types.is_empty() {
7972                    write!(f, "({})", display_comma_separated(arg_types))?;
7973                }
7974                Ok(())
7975            }
7976            GrantObjects::Function { name, arg_types } => {
7977                write!(f, "FUNCTION {name}")?;
7978                if !arg_types.is_empty() {
7979                    write!(f, "({})", display_comma_separated(arg_types))?;
7980                }
7981                Ok(())
7982            }
7983            GrantObjects::Types(types) => {
7984                write!(f, "TYPE {}", display_comma_separated(types))
7985            }
7986            GrantObjects::Domains(domains) => {
7987                write!(f, "DOMAIN {}", display_comma_separated(domains))
7988            }
7989        }
7990    }
7991}
7992
7993/// A `DENY` statement
7994///
7995/// [MsSql](https://learn.microsoft.com/en-us/sql/t-sql/statements/deny-transact-sql)
7996#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7997#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7998#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7999pub struct DenyStatement {
8000    /// The privileges to deny.
8001    pub privileges: Privileges,
8002    /// The objects the privileges apply to.
8003    pub objects: GrantObjects,
8004    /// The grantees (users/roles) to whom the denial applies.
8005    pub grantees: Vec<Grantee>,
8006    /// Optional identifier of the principal that performed the grant.
8007    pub granted_by: Option<Ident>,
8008    /// Optional cascade option controlling dependent objects.
8009    pub cascade: Option<CascadeOption>,
8010}
8011
8012impl fmt::Display for DenyStatement {
8013    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8014        write!(f, "DENY {}", self.privileges)?;
8015        write!(f, " ON {}", self.objects)?;
8016        if !self.grantees.is_empty() {
8017            write!(f, " TO {}", display_comma_separated(&self.grantees))?;
8018        }
8019        if let Some(cascade) = &self.cascade {
8020            write!(f, " {cascade}")?;
8021        }
8022        if let Some(granted_by) = &self.granted_by {
8023            write!(f, " AS {granted_by}")?;
8024        }
8025        Ok(())
8026    }
8027}
8028
8029/// SQL assignment `foo = expr` as used in SQLUpdate
8030#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8031#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8032#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8033pub struct Assignment {
8034    /// The left-hand side of the assignment.
8035    pub target: AssignmentTarget,
8036    /// The expression assigned to the target.
8037    pub value: Expr,
8038}
8039
8040impl fmt::Display for Assignment {
8041    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8042        write!(f, "{} = {}", self.target, self.value)
8043    }
8044}
8045
8046/// Left-hand side of an assignment in an UPDATE statement,
8047/// e.g. `foo` in `foo = 5` (ColumnName assignment) or
8048/// `(a, b)` in `(a, b) = (1, 2)` (Tuple assignment).
8049#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8050#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8051#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8052pub enum AssignmentTarget {
8053    /// A single column
8054    ColumnName(ObjectName),
8055    /// A tuple of columns
8056    Tuple(Vec<ObjectName>),
8057}
8058
8059impl fmt::Display for AssignmentTarget {
8060    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8061        match self {
8062            AssignmentTarget::ColumnName(column) => write!(f, "{column}"),
8063            AssignmentTarget::Tuple(columns) => write!(f, "({})", display_comma_separated(columns)),
8064        }
8065    }
8066}
8067
8068#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8069#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8070#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8071/// Expression forms allowed as a function argument.
8072pub enum FunctionArgExpr {
8073    /// A normal expression argument.
8074    Expr(Expr),
8075    /// Qualified wildcard, e.g. `alias.*` or `schema.table.*`.
8076    QualifiedWildcard(ObjectName),
8077    /// An unqualified `*` wildcard.
8078    Wildcard,
8079    /// An unqualified `*` wildcard with additional options, e.g. `* EXCLUDE(col)`.
8080    ///
8081    /// Used in Snowflake to support expressions like `HASH(* EXCLUDE(col))`.
8082    WildcardWithOptions(WildcardAdditionalOptions),
8083}
8084
8085impl From<Expr> for FunctionArgExpr {
8086    fn from(wildcard_expr: Expr) -> Self {
8087        match wildcard_expr {
8088            Expr::QualifiedWildcard(prefix, _) => Self::QualifiedWildcard(prefix),
8089            Expr::Wildcard(_) => Self::Wildcard,
8090            expr => Self::Expr(expr),
8091        }
8092    }
8093}
8094
8095impl fmt::Display for FunctionArgExpr {
8096    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8097        match self {
8098            FunctionArgExpr::Expr(expr) => write!(f, "{expr}"),
8099            FunctionArgExpr::QualifiedWildcard(prefix) => write!(f, "{prefix}.*"),
8100            FunctionArgExpr::Wildcard => f.write_str("*"),
8101            FunctionArgExpr::WildcardWithOptions(opts) => write!(f, "*{opts}"),
8102        }
8103    }
8104}
8105
8106#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8107#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8108#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8109/// Operator used to separate function arguments
8110pub enum FunctionArgOperator {
8111    /// function(arg1 = value1)
8112    Equals,
8113    /// function(arg1 => value1)
8114    RightArrow,
8115    /// function(arg1 := value1)
8116    Assignment,
8117    /// function(arg1 : value1)
8118    Colon,
8119    /// function(arg1 VALUE value1)
8120    Value,
8121}
8122
8123impl fmt::Display for FunctionArgOperator {
8124    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8125        match self {
8126            FunctionArgOperator::Equals => f.write_str("="),
8127            FunctionArgOperator::RightArrow => f.write_str("=>"),
8128            FunctionArgOperator::Assignment => f.write_str(":="),
8129            FunctionArgOperator::Colon => f.write_str(":"),
8130            FunctionArgOperator::Value => f.write_str("VALUE"),
8131        }
8132    }
8133}
8134
8135#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8136#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8137#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8138/// Forms of function arguments (named, expression-named, or positional).
8139pub enum FunctionArg {
8140    /// `name` is identifier
8141    ///
8142    /// Enabled when `Dialect::supports_named_fn_args_with_expr_name` returns 'false'
8143    Named {
8144        /// The identifier name of the argument.
8145        name: Ident,
8146        /// The argument expression or wildcard form.
8147        arg: FunctionArgExpr,
8148        /// The operator separating name and value.
8149        operator: FunctionArgOperator,
8150    },
8151    /// `name` is arbitrary expression
8152    ///
8153    /// Enabled when `Dialect::supports_named_fn_args_with_expr_name` returns 'true'
8154    ExprNamed {
8155        /// The expression used as the argument name.
8156        name: Expr,
8157        /// The argument expression or wildcard form.
8158        arg: FunctionArgExpr,
8159        /// The operator separating name and value.
8160        operator: FunctionArgOperator,
8161    },
8162    /// An unnamed argument (positional), given by expression or wildcard.
8163    Unnamed(FunctionArgExpr),
8164}
8165
8166impl fmt::Display for FunctionArg {
8167    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8168        match self {
8169            FunctionArg::Named {
8170                name,
8171                arg,
8172                operator,
8173            } => write!(f, "{name} {operator} {arg}"),
8174            FunctionArg::ExprNamed {
8175                name,
8176                arg,
8177                operator,
8178            } => write!(f, "{name} {operator} {arg}"),
8179            FunctionArg::Unnamed(unnamed_arg) => write!(f, "{unnamed_arg}"),
8180        }
8181    }
8182}
8183
8184#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8185#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8186#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8187/// Which cursor(s) to close.
8188pub enum CloseCursor {
8189    /// Close all cursors.
8190    All,
8191    /// Close a specific cursor by name.
8192    Specific {
8193        /// The name of the cursor to close.
8194        name: Ident,
8195    },
8196}
8197
8198impl fmt::Display for CloseCursor {
8199    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8200        match self {
8201            CloseCursor::All => write!(f, "ALL"),
8202            CloseCursor::Specific { name } => write!(f, "{name}"),
8203        }
8204    }
8205}
8206
8207/// A Drop Domain statement
8208#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8209#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8210#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8211pub struct DropDomain {
8212    /// Whether to drop the domain if it exists
8213    pub if_exists: bool,
8214    /// The name of the domain to drop
8215    pub name: ObjectName,
8216    /// The behavior to apply when dropping the domain
8217    pub drop_behavior: Option<DropBehavior>,
8218}
8219
8220/// A constant of form `<data_type> 'value'`.
8221/// This can represent ANSI SQL `DATE`, `TIME`, and `TIMESTAMP` literals (such as `DATE '2020-01-01'`),
8222/// as well as constants of other types (a non-standard PostgreSQL extension).
8223#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8224#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8225#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8226pub struct TypedString {
8227    /// The data type of the typed string (e.g. DATE, TIME, TIMESTAMP).
8228    pub data_type: DataType,
8229    /// The value of the constant.
8230    /// Hint: you can unwrap the string value using `value.into_string()`.
8231    pub value: ValueWithSpan,
8232    /// Flags whether this TypedString uses the [ODBC syntax].
8233    ///
8234    /// Example:
8235    /// ```sql
8236    /// -- An ODBC date literal:
8237    /// SELECT {d '2025-07-16'}
8238    /// -- This is equivalent to the standard ANSI SQL literal:
8239    /// SELECT DATE '2025-07-16'
8240    ///
8241    /// [ODBC syntax]: https://learn.microsoft.com/en-us/sql/odbc/reference/develop-app/date-time-and-timestamp-literals?view=sql-server-2017
8242    pub uses_odbc_syntax: bool,
8243}
8244
8245impl fmt::Display for TypedString {
8246    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8247        let data_type = &self.data_type;
8248        let value = &self.value;
8249        match self.uses_odbc_syntax {
8250            false => {
8251                write!(f, "{data_type}")?;
8252                write!(f, " {value}")
8253            }
8254            true => {
8255                let prefix = match data_type {
8256                    DataType::Date => "d",
8257                    DataType::Time(..) => "t",
8258                    DataType::Timestamp(..) => "ts",
8259                    _ => "?",
8260                };
8261                write!(f, "{{{prefix} {value}}}")
8262            }
8263        }
8264    }
8265}
8266
8267/// A function call
8268#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8269#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8270#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8271pub struct Function {
8272    /// The function name (may be qualified).
8273    pub name: ObjectName,
8274    /// Flags whether this function call uses the [ODBC syntax].
8275    ///
8276    /// Example:
8277    /// ```sql
8278    /// SELECT {fn CONCAT('foo', 'bar')}
8279    /// ```
8280    ///
8281    /// [ODBC syntax]: https://learn.microsoft.com/en-us/sql/odbc/reference/develop-app/scalar-function-calls?view=sql-server-2017
8282    pub uses_odbc_syntax: bool,
8283    /// The parameters to the function, including any options specified within the
8284    /// delimiting parentheses.
8285    ///
8286    /// Example:
8287    /// ```plaintext
8288    /// HISTOGRAM(0.5, 0.6)(x, y)
8289    /// ```
8290    ///
8291    /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/aggregate-functions/parametric-functions)
8292    pub parameters: FunctionArguments,
8293    /// The arguments to the function, including any options specified within the
8294    /// delimiting parentheses.
8295    pub args: FunctionArguments,
8296    /// e.g. `x > 5` in `COUNT(x) FILTER (WHERE x > 5)`
8297    pub filter: Option<Box<Expr>>,
8298    /// Indicates how `NULL`s should be handled in the calculation.
8299    ///
8300    /// Example:
8301    /// ```plaintext
8302    /// FIRST_VALUE( <expr> ) [ { IGNORE | RESPECT } NULLS ] OVER ...
8303    /// ```
8304    ///
8305    /// [Snowflake](https://docs.snowflake.com/en/sql-reference/functions/first_value)
8306    pub null_treatment: Option<NullTreatment>,
8307    /// The `OVER` clause, indicating a window function call.
8308    pub over: Option<WindowType>,
8309    /// A clause used with certain aggregate functions to control the ordering
8310    /// within grouped sets before the function is applied.
8311    ///
8312    /// Syntax:
8313    /// ```plaintext
8314    /// <aggregate_function>(expression) WITHIN GROUP (ORDER BY key [ASC | DESC], ...)
8315    /// ```
8316    pub within_group: Vec<OrderByExpr>,
8317}
8318
8319impl fmt::Display for Function {
8320    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8321        if self.uses_odbc_syntax {
8322            write!(f, "{{fn ")?;
8323        }
8324
8325        write!(f, "{}{}{}", self.name, self.parameters, self.args)?;
8326
8327        if !self.within_group.is_empty() {
8328            write!(
8329                f,
8330                " WITHIN GROUP (ORDER BY {})",
8331                display_comma_separated(&self.within_group)
8332            )?;
8333        }
8334
8335        if let Some(filter_cond) = &self.filter {
8336            write!(f, " FILTER (WHERE {filter_cond})")?;
8337        }
8338
8339        if let Some(null_treatment) = &self.null_treatment {
8340            write!(f, " {null_treatment}")?;
8341        }
8342
8343        if let Some(o) = &self.over {
8344            f.write_str(" OVER ")?;
8345            o.fmt(f)?;
8346        }
8347
8348        if self.uses_odbc_syntax {
8349            write!(f, "}}")?;
8350        }
8351
8352        Ok(())
8353    }
8354}
8355
8356/// The arguments passed to a function call.
8357#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8358#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8359#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8360pub enum FunctionArguments {
8361    /// Used for special functions like `CURRENT_TIMESTAMP` that are invoked
8362    /// without parentheses.
8363    None,
8364    /// On some dialects, a subquery can be passed without surrounding
8365    /// parentheses if it's the sole argument to the function.
8366    Subquery(Box<Query>),
8367    /// A normal function argument list, including any clauses within it such as
8368    /// `DISTINCT` or `ORDER BY`.
8369    List(FunctionArgumentList),
8370}
8371
8372impl fmt::Display for FunctionArguments {
8373    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8374        match self {
8375            FunctionArguments::None => Ok(()),
8376            FunctionArguments::Subquery(query) => write!(f, "({query})"),
8377            FunctionArguments::List(args) => write!(f, "({args})"),
8378        }
8379    }
8380}
8381
8382/// This represents everything inside the parentheses when calling a function.
8383#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8384#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8385#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8386pub struct FunctionArgumentList {
8387    /// `[ ALL | DISTINCT ]`
8388    pub duplicate_treatment: Option<DuplicateTreatment>,
8389    /// The function arguments.
8390    pub args: Vec<FunctionArg>,
8391    /// Additional clauses specified within the argument list.
8392    pub clauses: Vec<FunctionArgumentClause>,
8393}
8394
8395impl fmt::Display for FunctionArgumentList {
8396    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8397        if let Some(duplicate_treatment) = self.duplicate_treatment {
8398            write!(f, "{duplicate_treatment} ")?;
8399        }
8400        write!(f, "{}", display_comma_separated(&self.args))?;
8401        if !self.clauses.is_empty() {
8402            if !self.args.is_empty() {
8403                write!(f, " ")?;
8404            }
8405            write!(f, "{}", display_separated(&self.clauses, " "))?;
8406        }
8407        Ok(())
8408    }
8409}
8410
8411#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8412#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8413#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8414/// Clauses that can appear inside a function argument list.
8415pub enum FunctionArgumentClause {
8416    /// Indicates how `NULL`s should be handled in the calculation, e.g. in `FIRST_VALUE` on [BigQuery].
8417    ///
8418    /// Syntax:
8419    /// ```plaintext
8420    /// { IGNORE | RESPECT } NULLS ]
8421    /// ```
8422    ///
8423    /// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/navigation_functions#first_value
8424    IgnoreOrRespectNulls(NullTreatment),
8425    /// Specifies the the ordering for some ordered set aggregates, e.g. `ARRAY_AGG` on [BigQuery].
8426    ///
8427    /// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/aggregate_functions#array_agg
8428    OrderBy(Vec<OrderByExpr>),
8429    /// Specifies a limit for the `ARRAY_AGG` and `ARRAY_CONCAT_AGG` functions on BigQuery.
8430    Limit(Expr),
8431    /// Specifies the behavior on overflow of the `LISTAGG` function.
8432    ///
8433    /// See <https://trino.io/docs/current/functions/aggregate.html>.
8434    OnOverflow(ListAggOnOverflow),
8435    /// Specifies a minimum or maximum bound on the input to [`ANY_VALUE`] on BigQuery.
8436    ///
8437    /// Syntax:
8438    /// ```plaintext
8439    /// HAVING { MAX | MIN } expression
8440    /// ```
8441    ///
8442    /// [`ANY_VALUE`]: https://cloud.google.com/bigquery/docs/reference/standard-sql/aggregate_functions#any_value
8443    Having(HavingBound),
8444    /// The `SEPARATOR` clause to the [`GROUP_CONCAT`] function in MySQL.
8445    ///
8446    /// [`GROUP_CONCAT`]: https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html#function_group-concat
8447    Separator(ValueWithSpan),
8448    /// The `ON NULL` clause for some JSON functions.
8449    ///
8450    /// [MSSQL `JSON_ARRAY`](https://learn.microsoft.com/en-us/sql/t-sql/functions/json-array-transact-sql?view=sql-server-ver16)
8451    /// [MSSQL `JSON_OBJECT`](https://learn.microsoft.com/en-us/sql/t-sql/functions/json-object-transact-sql?view=sql-server-ver16>)
8452    /// [PostgreSQL JSON functions](https://www.postgresql.org/docs/current/functions-json.html#FUNCTIONS-JSON-PROCESSING)
8453    JsonNullClause(JsonNullClause),
8454    /// The `RETURNING` clause for some JSON functions in PostgreSQL
8455    ///
8456    /// [`JSON_OBJECT`](https://www.postgresql.org/docs/current/functions-json.html#:~:text=json_object)
8457    JsonReturningClause(JsonReturningClause),
8458}
8459
8460impl fmt::Display for FunctionArgumentClause {
8461    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8462        match self {
8463            FunctionArgumentClause::IgnoreOrRespectNulls(null_treatment) => {
8464                write!(f, "{null_treatment}")
8465            }
8466            FunctionArgumentClause::OrderBy(order_by) => {
8467                write!(f, "ORDER BY {}", display_comma_separated(order_by))
8468            }
8469            FunctionArgumentClause::Limit(limit) => write!(f, "LIMIT {limit}"),
8470            FunctionArgumentClause::OnOverflow(on_overflow) => write!(f, "{on_overflow}"),
8471            FunctionArgumentClause::Having(bound) => write!(f, "{bound}"),
8472            FunctionArgumentClause::Separator(sep) => write!(f, "SEPARATOR {sep}"),
8473            FunctionArgumentClause::JsonNullClause(null_clause) => write!(f, "{null_clause}"),
8474            FunctionArgumentClause::JsonReturningClause(returning_clause) => {
8475                write!(f, "{returning_clause}")
8476            }
8477        }
8478    }
8479}
8480
8481/// A method call
8482#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8483#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8484#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8485pub struct Method {
8486    /// The expression on which the method is invoked.
8487    pub expr: Box<Expr>,
8488    // always non-empty
8489    /// The sequence of chained method calls.
8490    pub method_chain: Vec<Function>,
8491}
8492
8493impl fmt::Display for Method {
8494    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8495        write!(
8496            f,
8497            "{}.{}",
8498            self.expr,
8499            display_separated(&self.method_chain, ".")
8500        )
8501    }
8502}
8503
8504#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8505#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8506#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8507/// How duplicate values are treated inside function argument lists.
8508pub enum DuplicateTreatment {
8509    /// Consider only unique values.
8510    Distinct,
8511    /// Retain all duplicate values (the default).
8512    All,
8513}
8514
8515impl fmt::Display for DuplicateTreatment {
8516    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8517        match self {
8518            DuplicateTreatment::Distinct => write!(f, "DISTINCT"),
8519            DuplicateTreatment::All => write!(f, "ALL"),
8520        }
8521    }
8522}
8523
8524#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8525#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8526#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8527/// How the `ANALYZE`/`EXPLAIN ANALYZE` format is specified.
8528pub enum AnalyzeFormatKind {
8529    /// Format provided as a keyword, e.g. `FORMAT JSON`.
8530    Keyword(AnalyzeFormat),
8531    /// Format provided as an assignment, e.g. `FORMAT=JSON`.
8532    Assignment(AnalyzeFormat),
8533}
8534
8535impl fmt::Display for AnalyzeFormatKind {
8536    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
8537        match self {
8538            AnalyzeFormatKind::Keyword(format) => write!(f, "FORMAT {format}"),
8539            AnalyzeFormatKind::Assignment(format) => write!(f, "FORMAT={format}"),
8540        }
8541    }
8542}
8543
8544#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8545#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8546#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8547/// Output formats supported for `ANALYZE`/`EXPLAIN ANALYZE`.
8548pub enum AnalyzeFormat {
8549    /// Plain text format.
8550    TEXT,
8551    /// Graphviz DOT format.
8552    GRAPHVIZ,
8553    /// JSON format.
8554    JSON,
8555    /// Traditional explain output.
8556    TRADITIONAL,
8557    /// Tree-style explain output.
8558    TREE,
8559}
8560
8561impl fmt::Display for AnalyzeFormat {
8562    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
8563        f.write_str(match self {
8564            AnalyzeFormat::TEXT => "TEXT",
8565            AnalyzeFormat::GRAPHVIZ => "GRAPHVIZ",
8566            AnalyzeFormat::JSON => "JSON",
8567            AnalyzeFormat::TRADITIONAL => "TRADITIONAL",
8568            AnalyzeFormat::TREE => "TREE",
8569        })
8570    }
8571}
8572
8573/// External table's available file format
8574#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8575#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8576#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8577pub enum FileFormat {
8578    /// Text file format.
8579    TEXTFILE,
8580    /// Sequence file format.
8581    SEQUENCEFILE,
8582    /// ORC file format.
8583    ORC,
8584    /// Parquet file format.
8585    PARQUET,
8586    /// Avro file format.
8587    AVRO,
8588    /// RCFile format.
8589    RCFILE,
8590    /// JSON file format.
8591    JSONFILE,
8592}
8593
8594impl fmt::Display for FileFormat {
8595    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8596        use self::FileFormat::*;
8597        f.write_str(match self {
8598            TEXTFILE => "TEXTFILE",
8599            SEQUENCEFILE => "SEQUENCEFILE",
8600            ORC => "ORC",
8601            PARQUET => "PARQUET",
8602            AVRO => "AVRO",
8603            RCFILE => "RCFILE",
8604            JSONFILE => "JSONFILE",
8605        })
8606    }
8607}
8608
8609/// The `ON OVERFLOW` clause of a LISTAGG invocation
8610#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8611#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8612#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8613pub enum ListAggOnOverflow {
8614    /// `ON OVERFLOW ERROR`
8615    Error,
8616
8617    /// `ON OVERFLOW TRUNCATE [ <filler> ] WITH[OUT] COUNT`
8618    Truncate {
8619        /// Optional filler expression used when truncating.
8620        filler: Option<Box<Expr>>,
8621        /// Whether to include a count when truncating.
8622        with_count: bool,
8623    },
8624}
8625
8626impl fmt::Display for ListAggOnOverflow {
8627    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8628        write!(f, "ON OVERFLOW")?;
8629        match self {
8630            ListAggOnOverflow::Error => write!(f, " ERROR"),
8631            ListAggOnOverflow::Truncate { filler, with_count } => {
8632                write!(f, " TRUNCATE")?;
8633                if let Some(filler) = filler {
8634                    write!(f, " {filler}")?;
8635                }
8636                if *with_count {
8637                    write!(f, " WITH")?;
8638                } else {
8639                    write!(f, " WITHOUT")?;
8640                }
8641                write!(f, " COUNT")
8642            }
8643        }
8644    }
8645}
8646
8647/// The `HAVING` clause in a call to `ANY_VALUE` on BigQuery.
8648#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8649#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8650#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8651pub struct HavingBound(pub HavingBoundKind, pub Expr);
8652
8653impl fmt::Display for HavingBound {
8654    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8655        write!(f, "HAVING {} {}", self.0, self.1)
8656    }
8657}
8658
8659#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8660#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8661#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8662/// Which bound is used in a HAVING clause for ANY_VALUE on BigQuery.
8663pub enum HavingBoundKind {
8664    /// The minimum bound.
8665    Min,
8666    /// The maximum bound.
8667    Max,
8668}
8669
8670impl fmt::Display for HavingBoundKind {
8671    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8672        match self {
8673            HavingBoundKind::Min => write!(f, "MIN"),
8674            HavingBoundKind::Max => write!(f, "MAX"),
8675        }
8676    }
8677}
8678
8679#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8680#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8681#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8682/// Types of database objects referenced by DDL statements.
8683pub enum ObjectType {
8684    /// A collation.
8685    Collation,
8686    /// A table.
8687    Table,
8688    /// A view.
8689    View,
8690    /// A materialized view.
8691    MaterializedView,
8692    /// An index.
8693    Index,
8694    /// A schema.
8695    Schema,
8696    /// A database.
8697    Database,
8698    /// A role.
8699    Role,
8700    /// A sequence.
8701    Sequence,
8702    /// A stage.
8703    Stage,
8704    /// A type definition.
8705    Type,
8706    /// A user.
8707    User,
8708    /// A stream.
8709    Stream,
8710}
8711
8712impl fmt::Display for ObjectType {
8713    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8714        f.write_str(match self {
8715            ObjectType::Collation => "COLLATION",
8716            ObjectType::Table => "TABLE",
8717            ObjectType::View => "VIEW",
8718            ObjectType::MaterializedView => "MATERIALIZED VIEW",
8719            ObjectType::Index => "INDEX",
8720            ObjectType::Schema => "SCHEMA",
8721            ObjectType::Database => "DATABASE",
8722            ObjectType::Role => "ROLE",
8723            ObjectType::Sequence => "SEQUENCE",
8724            ObjectType::Stage => "STAGE",
8725            ObjectType::Type => "TYPE",
8726            ObjectType::User => "USER",
8727            ObjectType::Stream => "STREAM",
8728        })
8729    }
8730}
8731
8732#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8733#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8734#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8735/// Types supported by `KILL` statements.
8736pub enum KillType {
8737    /// Kill a connection.
8738    Connection,
8739    /// Kill a running query.
8740    Query,
8741    /// Kill a mutation (ClickHouse).
8742    Mutation,
8743}
8744
8745impl fmt::Display for KillType {
8746    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8747        f.write_str(match self {
8748            // MySQL
8749            KillType::Connection => "CONNECTION",
8750            KillType::Query => "QUERY",
8751            // Clickhouse supports Mutation
8752            KillType::Mutation => "MUTATION",
8753        })
8754    }
8755}
8756
8757#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8758#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8759#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8760/// Distribution style options for Hive tables.
8761pub enum HiveDistributionStyle {
8762    /// Partitioned distribution with the given columns.
8763    PARTITIONED {
8764        /// Columns used for partitioning.
8765        columns: Vec<ColumnDef>,
8766    },
8767    /// Skewed distribution definition.
8768    SKEWED {
8769        /// Columns participating in the skew definition.
8770        columns: Vec<ColumnDef>,
8771        /// Columns listed in the `ON` clause for skewing.
8772        on: Vec<ColumnDef>,
8773        /// Whether skewed data is stored as directories.
8774        stored_as_directories: bool,
8775    },
8776    /// No distribution style specified.
8777    NONE,
8778}
8779
8780#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8781#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8782#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8783/// Row format specification for Hive tables (SERDE or DELIMITED).
8784pub enum HiveRowFormat {
8785    /// SerDe class specification with the implementing class name.
8786    SERDE {
8787        /// The SerDe implementation class name.
8788        class: String,
8789    },
8790    /// Delimited row format with one or more delimiter specifications.
8791    DELIMITED {
8792        /// The list of delimiters used for delimiting fields/lines.
8793        delimiters: Vec<HiveRowDelimiter>,
8794    },
8795}
8796
8797#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8798#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8799#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8800/// Format specification for `LOAD DATA` Hive operations.
8801pub struct HiveLoadDataFormat {
8802    /// SerDe expression used for the table.
8803    pub serde: Expr,
8804    /// Input format expression.
8805    pub input_format: Expr,
8806}
8807
8808#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8809#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8810#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8811/// A single row delimiter specification for Hive `ROW FORMAT`.
8812pub struct HiveRowDelimiter {
8813    /// The delimiter kind (fields/lines/etc.).
8814    pub delimiter: HiveDelimiter,
8815    /// The delimiter character identifier.
8816    pub char: Ident,
8817}
8818
8819impl fmt::Display for HiveRowDelimiter {
8820    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8821        write!(f, "{} ", self.delimiter)?;
8822        write!(f, "{}", self.char)
8823    }
8824}
8825
8826#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8827#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8828#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8829/// Kind of delimiter used in Hive `ROW FORMAT` definitions.
8830pub enum HiveDelimiter {
8831    /// Fields terminated by a delimiter.
8832    FieldsTerminatedBy,
8833    /// Fields escaped by a character.
8834    FieldsEscapedBy,
8835    /// Collection items terminated by a delimiter.
8836    CollectionItemsTerminatedBy,
8837    /// Map keys terminated by a delimiter.
8838    MapKeysTerminatedBy,
8839    /// Lines terminated by a delimiter.
8840    LinesTerminatedBy,
8841    /// Null represented by a specific token.
8842    NullDefinedAs,
8843}
8844
8845impl fmt::Display for HiveDelimiter {
8846    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8847        use HiveDelimiter::*;
8848        f.write_str(match self {
8849            FieldsTerminatedBy => "FIELDS TERMINATED BY",
8850            FieldsEscapedBy => "ESCAPED BY",
8851            CollectionItemsTerminatedBy => "COLLECTION ITEMS TERMINATED BY",
8852            MapKeysTerminatedBy => "MAP KEYS TERMINATED BY",
8853            LinesTerminatedBy => "LINES TERMINATED BY",
8854            NullDefinedAs => "NULL DEFINED AS",
8855        })
8856    }
8857}
8858
8859#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8860#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8861#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8862/// Describe output format options for Hive `DESCRIBE`/`EXPLAIN`.
8863pub enum HiveDescribeFormat {
8864    /// Extended describe output.
8865    Extended,
8866    /// Formatted describe output.
8867    Formatted,
8868}
8869
8870impl fmt::Display for HiveDescribeFormat {
8871    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8872        use HiveDescribeFormat::*;
8873        f.write_str(match self {
8874            Extended => "EXTENDED",
8875            Formatted => "FORMATTED",
8876        })
8877    }
8878}
8879
8880#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8881#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8882#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8883/// Aliases accepted for describe-style commands.
8884pub enum DescribeAlias {
8885    /// `DESCRIBE` alias.
8886    Describe,
8887    /// `EXPLAIN` alias.
8888    Explain,
8889    /// `DESC` alias.
8890    Desc,
8891}
8892
8893impl fmt::Display for DescribeAlias {
8894    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8895        use DescribeAlias::*;
8896        f.write_str(match self {
8897            Describe => "DESCRIBE",
8898            Explain => "EXPLAIN",
8899            Desc => "DESC",
8900        })
8901    }
8902}
8903
8904#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8905#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8906#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8907#[allow(clippy::large_enum_variant)]
8908/// Hive input/output format specification used in `CREATE TABLE`.
8909pub enum HiveIOFormat {
8910    /// Generic IO format with separate input and output expressions.
8911    IOF {
8912        /// Expression for the input format.
8913        input_format: Expr,
8914        /// Expression for the output format.
8915        output_format: Expr,
8916    },
8917    /// File format wrapper referencing a `FileFormat` variant.
8918    FileFormat {
8919        /// The file format used for storage.
8920        format: FileFormat,
8921    },
8922}
8923
8924#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Default)]
8925#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8926#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8927/// Hive table format and storage-related options.
8928pub struct HiveFormat {
8929    /// Optional row format specification.
8930    pub row_format: Option<HiveRowFormat>,
8931    /// Optional SerDe properties expressed as SQL options.
8932    pub serde_properties: Option<Vec<SqlOption>>,
8933    /// Optional input/output storage format details.
8934    pub storage: Option<HiveIOFormat>,
8935    /// Optional location (URI or path) for table data.
8936    pub location: Option<String>,
8937}
8938
8939#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8940#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8941#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8942/// A clustered index column specification.
8943pub struct ClusteredIndex {
8944    /// Column identifier for the clustered index entry.
8945    pub name: Ident,
8946    /// Optional sort direction: `Some(true)` for ASC, `Some(false)` for DESC, `None` for unspecified.
8947    pub asc: Option<bool>,
8948}
8949
8950impl fmt::Display for ClusteredIndex {
8951    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8952        write!(f, "{}", self.name)?;
8953        match self.asc {
8954            Some(true) => write!(f, " ASC"),
8955            Some(false) => write!(f, " DESC"),
8956            _ => Ok(()),
8957        }
8958    }
8959}
8960
8961#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8962#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8963#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8964/// Clustered options used for `CREATE TABLE` clustered/indexed storage.
8965pub enum TableOptionsClustered {
8966    /// Use a columnstore index.
8967    ColumnstoreIndex,
8968    /// Columnstore index with an explicit ordering of columns.
8969    ColumnstoreIndexOrder(Vec<Ident>),
8970    /// A named clustered index with one or more columns.
8971    Index(Vec<ClusteredIndex>),
8972}
8973
8974impl fmt::Display for TableOptionsClustered {
8975    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8976        match self {
8977            TableOptionsClustered::ColumnstoreIndex => {
8978                write!(f, "CLUSTERED COLUMNSTORE INDEX")
8979            }
8980            TableOptionsClustered::ColumnstoreIndexOrder(values) => {
8981                write!(
8982                    f,
8983                    "CLUSTERED COLUMNSTORE INDEX ORDER ({})",
8984                    display_comma_separated(values)
8985                )
8986            }
8987            TableOptionsClustered::Index(values) => {
8988                write!(f, "CLUSTERED INDEX ({})", display_comma_separated(values))
8989            }
8990        }
8991    }
8992}
8993
8994/// Specifies which partition the boundary values on table partitioning belongs to.
8995#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash)]
8996#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8997#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8998pub enum PartitionRangeDirection {
8999    /// LEFT range direction.
9000    Left,
9001    /// RIGHT range direction.
9002    Right,
9003}
9004
9005#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9006#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9007#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9008/// SQL option syntax used in table and server definitions.
9009pub enum SqlOption {
9010    /// Clustered represents the clustered version of table storage for MSSQL.
9011    ///
9012    /// <https://learn.microsoft.com/en-us/sql/t-sql/statements/create-table-azure-sql-data-warehouse?view=aps-pdw-2016-au7#TableOptions>
9013    Clustered(TableOptionsClustered),
9014    /// Single identifier options, e.g. `HEAP` for MSSQL.
9015    ///
9016    /// <https://learn.microsoft.com/en-us/sql/t-sql/statements/create-table-azure-sql-data-warehouse?view=aps-pdw-2016-au7#TableOptions>
9017    Ident(Ident),
9018    /// Any option that consists of a key value pair where the value is an expression. e.g.
9019    ///
9020    ///   WITH(DISTRIBUTION = ROUND_ROBIN)
9021    KeyValue {
9022        /// The option key identifier.
9023        key: Ident,
9024        /// The expression value for the option.
9025        value: Expr,
9026    },
9027    /// One or more table partitions and represents which partition the boundary values belong to,
9028    /// e.g.
9029    ///
9030    ///   PARTITION (id RANGE LEFT FOR VALUES (10, 20, 30, 40))
9031    ///
9032    /// <https://learn.microsoft.com/en-us/sql/t-sql/statements/create-table-azure-sql-data-warehouse?view=aps-pdw-2016-au7#TablePartitionOptions>
9033    Partition {
9034        /// The partition column name.
9035        column_name: Ident,
9036        /// Optional direction for the partition range (LEFT/RIGHT).
9037        range_direction: Option<PartitionRangeDirection>,
9038        /// Values that define the partition boundaries.
9039        for_values: Vec<Expr>,
9040    },
9041    /// Comment parameter (supports `=` and no `=` syntax)
9042    Comment(CommentDef),
9043    /// MySQL TableSpace option
9044    /// <https://dev.mysql.com/doc/refman/8.4/en/create-table.html>
9045    TableSpace(TablespaceOption),
9046    /// An option representing a key value pair, where the value is a parenthesized list and with an optional name
9047    /// e.g.
9048    ///
9049    ///   UNION  = (tbl_name\[,tbl_name\]...) <https://dev.mysql.com/doc/refman/8.4/en/create-table.html>
9050    ///   ENGINE = ReplicatedMergeTree('/table_name','{replica}', ver) <https://clickhouse.com/docs/engines/table-engines/mergetree-family/replication>
9051    ///   ENGINE = SummingMergeTree(\[columns\]) <https://clickhouse.com/docs/engines/table-engines/mergetree-family/summingmergetree>
9052    NamedParenthesizedList(NamedParenthesizedList),
9053}
9054
9055impl fmt::Display for SqlOption {
9056    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9057        match self {
9058            SqlOption::Clustered(c) => write!(f, "{c}"),
9059            SqlOption::Ident(ident) => {
9060                write!(f, "{ident}")
9061            }
9062            SqlOption::KeyValue { key: name, value } => {
9063                write!(f, "{name} = {value}")
9064            }
9065            SqlOption::Partition {
9066                column_name,
9067                range_direction,
9068                for_values,
9069            } => {
9070                let direction = match range_direction {
9071                    Some(PartitionRangeDirection::Left) => " LEFT",
9072                    Some(PartitionRangeDirection::Right) => " RIGHT",
9073                    None => "",
9074                };
9075
9076                write!(
9077                    f,
9078                    "PARTITION ({} RANGE{} FOR VALUES ({}))",
9079                    column_name,
9080                    direction,
9081                    display_comma_separated(for_values)
9082                )
9083            }
9084            SqlOption::TableSpace(tablespace_option) => {
9085                write!(f, "TABLESPACE {}", tablespace_option.name)?;
9086                match tablespace_option.storage {
9087                    Some(StorageType::Disk) => write!(f, " STORAGE DISK"),
9088                    Some(StorageType::Memory) => write!(f, " STORAGE MEMORY"),
9089                    None => Ok(()),
9090                }
9091            }
9092            SqlOption::Comment(comment) => match comment {
9093                CommentDef::WithEq(comment) => {
9094                    write!(f, "COMMENT = '{comment}'")
9095                }
9096                CommentDef::WithoutEq(comment) => {
9097                    write!(f, "COMMENT '{comment}'")
9098                }
9099            },
9100            SqlOption::NamedParenthesizedList(value) => {
9101                write!(f, "{} = ", value.key)?;
9102                if let Some(key) = &value.name {
9103                    write!(f, "{key}")?;
9104                }
9105                if !value.values.is_empty() {
9106                    write!(f, "({})", display_comma_separated(&value.values))?
9107                }
9108                Ok(())
9109            }
9110        }
9111    }
9112}
9113
9114#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
9115#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9116#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9117/// Storage type options for a tablespace.
9118pub enum StorageType {
9119    /// Store on disk.
9120    Disk,
9121    /// Store in memory.
9122    Memory,
9123}
9124
9125#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
9126#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9127#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9128/// MySql TableSpace option
9129/// <https://dev.mysql.com/doc/refman/8.4/en/create-table.html>
9130pub struct TablespaceOption {
9131    /// Name of the tablespace.
9132    pub name: String,
9133    /// Optional storage type for the tablespace.
9134    pub storage: Option<StorageType>,
9135}
9136
9137#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9138#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9139#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9140/// A key/value identifier pair used for secret or key-based options.
9141pub struct SecretOption {
9142    /// The option key identifier.
9143    pub key: Ident,
9144    /// The option value identifier.
9145    pub value: Ident,
9146}
9147
9148impl fmt::Display for SecretOption {
9149    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9150        write!(f, "{} {}", self.key, self.value)
9151    }
9152}
9153
9154/// A `CREATE SERVER` statement.
9155///
9156/// [PostgreSQL Documentation](https://www.postgresql.org/docs/current/sql-createserver.html)
9157#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9158#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9159#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9160pub struct CreateServerStatement {
9161    /// The server name.
9162    pub name: ObjectName,
9163    /// Whether `IF NOT EXISTS` was specified.
9164    pub if_not_exists: bool,
9165    /// Optional server type identifier.
9166    pub server_type: Option<Ident>,
9167    /// Optional server version identifier.
9168    pub version: Option<Ident>,
9169    /// Foreign-data wrapper object name.
9170    pub foreign_data_wrapper: ObjectName,
9171    /// Optional list of server options.
9172    pub options: Option<Vec<CreateServerOption>>,
9173}
9174
9175impl fmt::Display for CreateServerStatement {
9176    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
9177        let CreateServerStatement {
9178            name,
9179            if_not_exists,
9180            server_type,
9181            version,
9182            foreign_data_wrapper,
9183            options,
9184        } = self;
9185
9186        write!(
9187            f,
9188            "CREATE SERVER {if_not_exists}{name} ",
9189            if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
9190        )?;
9191
9192        if let Some(st) = server_type {
9193            write!(f, "TYPE {st} ")?;
9194        }
9195
9196        if let Some(v) = version {
9197            write!(f, "VERSION {v} ")?;
9198        }
9199
9200        write!(f, "FOREIGN DATA WRAPPER {foreign_data_wrapper}")?;
9201
9202        if let Some(o) = options {
9203            write!(f, " OPTIONS ({o})", o = display_comma_separated(o))?;
9204        }
9205
9206        Ok(())
9207    }
9208}
9209
9210/// A key/value option for `CREATE SERVER`.
9211#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9212#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9213#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9214pub struct CreateServerOption {
9215    /// Option key identifier.
9216    pub key: Ident,
9217    /// Option value identifier.
9218    pub value: Ident,
9219}
9220
9221impl fmt::Display for CreateServerOption {
9222    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9223        write!(f, "{} {}", self.key, self.value)
9224    }
9225}
9226
9227#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9228#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9229#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9230/// Options supported by DuckDB for `ATTACH DATABASE`.
9231pub enum AttachDuckDBDatabaseOption {
9232    /// READ_ONLY option, optional boolean value.
9233    ReadOnly(Option<bool>),
9234    /// TYPE option specifying a database type identifier.
9235    Type(Ident),
9236}
9237
9238impl fmt::Display for AttachDuckDBDatabaseOption {
9239    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9240        match self {
9241            AttachDuckDBDatabaseOption::ReadOnly(Some(true)) => write!(f, "READ_ONLY true"),
9242            AttachDuckDBDatabaseOption::ReadOnly(Some(false)) => write!(f, "READ_ONLY false"),
9243            AttachDuckDBDatabaseOption::ReadOnly(None) => write!(f, "READ_ONLY"),
9244            AttachDuckDBDatabaseOption::Type(t) => write!(f, "TYPE {t}"),
9245        }
9246    }
9247}
9248
9249#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9250#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9251#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9252/// Mode for transactions: access mode or isolation level.
9253pub enum TransactionMode {
9254    /// Access mode for a transaction (e.g. `READ ONLY` / `READ WRITE`).
9255    AccessMode(TransactionAccessMode),
9256    /// Isolation level for a transaction (e.g. `SERIALIZABLE`).
9257    IsolationLevel(TransactionIsolationLevel),
9258}
9259
9260impl fmt::Display for TransactionMode {
9261    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9262        use TransactionMode::*;
9263        match self {
9264            AccessMode(access_mode) => write!(f, "{access_mode}"),
9265            IsolationLevel(iso_level) => write!(f, "ISOLATION LEVEL {iso_level}"),
9266        }
9267    }
9268}
9269
9270#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9271#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9272#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9273/// Transaction access mode (READ ONLY / READ WRITE).
9274pub enum TransactionAccessMode {
9275    /// READ ONLY access mode.
9276    ReadOnly,
9277    /// READ WRITE access mode.
9278    ReadWrite,
9279}
9280
9281impl fmt::Display for TransactionAccessMode {
9282    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9283        use TransactionAccessMode::*;
9284        f.write_str(match self {
9285            ReadOnly => "READ ONLY",
9286            ReadWrite => "READ WRITE",
9287        })
9288    }
9289}
9290
9291#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9292#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9293#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9294/// Transaction isolation levels.
9295pub enum TransactionIsolationLevel {
9296    /// READ UNCOMMITTED isolation level.
9297    ReadUncommitted,
9298    /// READ COMMITTED isolation level.
9299    ReadCommitted,
9300    /// REPEATABLE READ isolation level.
9301    RepeatableRead,
9302    /// SERIALIZABLE isolation level.
9303    Serializable,
9304    /// SNAPSHOT isolation level.
9305    Snapshot,
9306}
9307
9308impl fmt::Display for TransactionIsolationLevel {
9309    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9310        use TransactionIsolationLevel::*;
9311        f.write_str(match self {
9312            ReadUncommitted => "READ UNCOMMITTED",
9313            ReadCommitted => "READ COMMITTED",
9314            RepeatableRead => "REPEATABLE READ",
9315            Serializable => "SERIALIZABLE",
9316            Snapshot => "SNAPSHOT",
9317        })
9318    }
9319}
9320
9321/// Modifier for the transaction in the `BEGIN` syntax
9322///
9323/// SQLite: <https://sqlite.org/lang_transaction.html>
9324/// MS-SQL: <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/try-catch-transact-sql>
9325#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9326#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9327#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9328pub enum TransactionModifier {
9329    /// DEFERRED transaction modifier.
9330    Deferred,
9331    /// IMMEDIATE transaction modifier.
9332    Immediate,
9333    /// EXCLUSIVE transaction modifier.
9334    Exclusive,
9335    /// TRY block modifier (MS-SQL style TRY/CATCH).
9336    Try,
9337    /// CATCH block modifier (MS-SQL style TRY/CATCH).
9338    Catch,
9339}
9340
9341impl fmt::Display for TransactionModifier {
9342    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9343        use TransactionModifier::*;
9344        f.write_str(match self {
9345            Deferred => "DEFERRED",
9346            Immediate => "IMMEDIATE",
9347            Exclusive => "EXCLUSIVE",
9348            Try => "TRY",
9349            Catch => "CATCH",
9350        })
9351    }
9352}
9353
9354#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9355#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9356#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9357/// Filter forms usable in SHOW statements.
9358pub enum ShowStatementFilter {
9359    /// Filter using LIKE pattern.
9360    Like(String),
9361    /// Filter using ILIKE pattern.
9362    ILike(String),
9363    /// Filter using a WHERE expression.
9364    Where(Expr),
9365    /// Filter provided without a keyword (raw string).
9366    NoKeyword(String),
9367}
9368
9369impl fmt::Display for ShowStatementFilter {
9370    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9371        use ShowStatementFilter::*;
9372        match self {
9373            Like(pattern) => write!(f, "LIKE '{}'", value::escape_single_quote_string(pattern)),
9374            ILike(pattern) => write!(f, "ILIKE {}", value::escape_single_quote_string(pattern)),
9375            Where(expr) => write!(f, "WHERE {expr}"),
9376            NoKeyword(pattern) => write!(f, "'{}'", value::escape_single_quote_string(pattern)),
9377        }
9378    }
9379}
9380
9381#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9382#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9383#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9384/// Clause types used with SHOW ... IN/FROM.
9385pub enum ShowStatementInClause {
9386    /// Use the `IN` clause.
9387    IN,
9388    /// Use the `FROM` clause.
9389    FROM,
9390}
9391
9392impl fmt::Display for ShowStatementInClause {
9393    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9394        use ShowStatementInClause::*;
9395        match self {
9396            FROM => write!(f, "FROM"),
9397            IN => write!(f, "IN"),
9398        }
9399    }
9400}
9401
9402/// Sqlite specific syntax
9403///
9404/// See [Sqlite documentation](https://sqlite.org/lang_conflict.html)
9405/// for more details.
9406#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9407#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9408#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9409pub enum SqliteOnConflict {
9410    /// Use ROLLBACK on conflict.
9411    Rollback,
9412    /// Use ABORT on conflict.
9413    Abort,
9414    /// Use FAIL on conflict.
9415    Fail,
9416    /// Use IGNORE on conflict.
9417    Ignore,
9418    /// Use REPLACE on conflict.
9419    Replace,
9420}
9421
9422impl fmt::Display for SqliteOnConflict {
9423    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9424        use SqliteOnConflict::*;
9425        match self {
9426            Rollback => write!(f, "OR ROLLBACK"),
9427            Abort => write!(f, "OR ABORT"),
9428            Fail => write!(f, "OR FAIL"),
9429            Ignore => write!(f, "OR IGNORE"),
9430            Replace => write!(f, "OR REPLACE"),
9431        }
9432    }
9433}
9434
9435/// Mysql specific syntax
9436///
9437/// See [Mysql documentation](https://dev.mysql.com/doc/refman/8.0/en/replace.html)
9438/// See [Mysql documentation](https://dev.mysql.com/doc/refman/8.0/en/insert.html)
9439/// for more details.
9440#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9441#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9442#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9443pub enum MysqlInsertPriority {
9444    /// LOW_PRIORITY modifier for INSERT/REPLACE.
9445    LowPriority,
9446    /// DELAYED modifier for INSERT/REPLACE.
9447    Delayed,
9448    /// HIGH_PRIORITY modifier for INSERT/REPLACE.
9449    HighPriority,
9450}
9451
9452impl fmt::Display for crate::ast::MysqlInsertPriority {
9453    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9454        use MysqlInsertPriority::*;
9455        match self {
9456            LowPriority => write!(f, "LOW_PRIORITY"),
9457            Delayed => write!(f, "DELAYED"),
9458            HighPriority => write!(f, "HIGH_PRIORITY"),
9459        }
9460    }
9461}
9462
9463#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9464#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9465#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9466/// Source for the `COPY` command: a table or a query.
9467pub enum CopySource {
9468    /// Copy from a table with optional column list.
9469    Table {
9470        /// The name of the table to copy from.
9471        table_name: ObjectName,
9472        /// A list of column names to copy. Empty list means that all columns
9473        /// are copied.
9474        columns: Vec<Ident>,
9475    },
9476    /// Copy from the results of a query.
9477    Query(Box<Query>),
9478}
9479
9480#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9481#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9482#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9483/// Target for the `COPY` command: STDIN, STDOUT, a file, or a program.
9484pub enum CopyTarget {
9485    /// Use standard input as the source.
9486    Stdin,
9487    /// Use standard output as the target.
9488    Stdout,
9489    /// Read from or write to a file.
9490    File {
9491        /// The path name of the input or output file.
9492        filename: String,
9493    },
9494    /// Use a program as the source or target (shell command).
9495    Program {
9496        /// A command to execute
9497        command: String,
9498    },
9499}
9500
9501impl fmt::Display for CopyTarget {
9502    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9503        use CopyTarget::*;
9504        match self {
9505            Stdin => write!(f, "STDIN"),
9506            Stdout => write!(f, "STDOUT"),
9507            File { filename } => write!(f, "'{}'", value::escape_single_quote_string(filename)),
9508            Program { command } => write!(
9509                f,
9510                "PROGRAM '{}'",
9511                value::escape_single_quote_string(command)
9512            ),
9513        }
9514    }
9515}
9516
9517#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9518#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9519#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9520/// Action to take `ON COMMIT` for temporary tables.
9521pub enum OnCommit {
9522    /// Delete rows on commit.
9523    DeleteRows,
9524    /// Preserve rows on commit.
9525    PreserveRows,
9526    /// Drop the table on commit.
9527    Drop,
9528}
9529
9530/// An option in `COPY` statement.
9531///
9532/// <https://www.postgresql.org/docs/14/sql-copy.html>
9533#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9534#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9535#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9536pub enum CopyOption {
9537    /// FORMAT format_name
9538    Format(Ident),
9539    /// FREEZE \[ boolean \]
9540    Freeze(bool),
9541    /// DELIMITER 'delimiter_character'
9542    Delimiter(char),
9543    /// NULL 'null_string'
9544    Null(String),
9545    /// HEADER \[ boolean \]
9546    Header(bool),
9547    /// QUOTE 'quote_character'
9548    Quote(char),
9549    /// ESCAPE 'escape_character'
9550    Escape(char),
9551    /// FORCE_QUOTE { ( column_name [, ...] ) | * }
9552    ForceQuote(Vec<Ident>),
9553    /// FORCE_NOT_NULL ( column_name [, ...] )
9554    ForceNotNull(Vec<Ident>),
9555    /// FORCE_NULL ( column_name [, ...] )
9556    ForceNull(Vec<Ident>),
9557    /// ENCODING 'encoding_name'
9558    Encoding(String),
9559}
9560
9561impl fmt::Display for CopyOption {
9562    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9563        use CopyOption::*;
9564        match self {
9565            Format(name) => write!(f, "FORMAT {name}"),
9566            Freeze(true) => write!(f, "FREEZE"),
9567            Freeze(false) => write!(f, "FREEZE FALSE"),
9568            Delimiter(char) => write!(f, "DELIMITER '{char}'"),
9569            Null(string) => write!(f, "NULL '{}'", value::escape_single_quote_string(string)),
9570            Header(true) => write!(f, "HEADER"),
9571            Header(false) => write!(f, "HEADER FALSE"),
9572            Quote(char) => write!(f, "QUOTE '{char}'"),
9573            Escape(char) => write!(f, "ESCAPE '{char}'"),
9574            ForceQuote(columns) => write!(f, "FORCE_QUOTE ({})", display_comma_separated(columns)),
9575            ForceNotNull(columns) => {
9576                write!(f, "FORCE_NOT_NULL ({})", display_comma_separated(columns))
9577            }
9578            ForceNull(columns) => write!(f, "FORCE_NULL ({})", display_comma_separated(columns)),
9579            Encoding(name) => write!(f, "ENCODING '{}'", value::escape_single_quote_string(name)),
9580        }
9581    }
9582}
9583
9584/// An option in `COPY` statement before PostgreSQL version 9.0.
9585///
9586/// [PostgreSQL](https://www.postgresql.org/docs/8.4/sql-copy.html)
9587/// [Redshift](https://docs.aws.amazon.com/redshift/latest/dg/r_COPY-alphabetical-parm-list.html)
9588#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9589#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9590#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9591pub enum CopyLegacyOption {
9592    /// ACCEPTANYDATE
9593    AcceptAnyDate,
9594    /// ACCEPTINVCHARS
9595    AcceptInvChars(Option<String>),
9596    /// ADDQUOTES
9597    AddQuotes,
9598    /// ALLOWOVERWRITE
9599    AllowOverwrite,
9600    /// BINARY
9601    Binary,
9602    /// BLANKSASNULL
9603    BlankAsNull,
9604    /// BZIP2
9605    Bzip2,
9606    /// CLEANPATH
9607    CleanPath,
9608    /// COMPUPDATE [ PRESET | { ON | TRUE } | { OFF | FALSE } ]
9609    CompUpdate {
9610        /// Whether the COMPUPDATE PRESET option was used.
9611        preset: bool,
9612        /// Optional enabled flag for COMPUPDATE.
9613        enabled: Option<bool>,
9614    },
9615    /// CSV ...
9616    Csv(Vec<CopyLegacyCsvOption>),
9617    /// DATEFORMAT \[ AS \] {'dateformat_string' | 'auto' }
9618    DateFormat(Option<String>),
9619    /// DELIMITER \[ AS \] 'delimiter_character'
9620    Delimiter(char),
9621    /// EMPTYASNULL
9622    EmptyAsNull,
9623    /// `ENCRYPTED \[ AUTO \]`
9624    Encrypted {
9625        /// Whether `AUTO` was specified for encryption.
9626        auto: bool,
9627    },
9628    /// ESCAPE
9629    Escape,
9630    /// EXTENSION 'extension-name'
9631    Extension(String),
9632    /// FIXEDWIDTH \[ AS \] 'fixedwidth-spec'
9633    FixedWidth(String),
9634    /// GZIP
9635    Gzip,
9636    /// HEADER
9637    Header,
9638    /// IAM_ROLE { DEFAULT | 'arn:aws:iam::123456789:role/role1' }
9639    IamRole(IamRoleKind),
9640    /// IGNOREHEADER \[ AS \] number_rows
9641    IgnoreHeader(u64),
9642    /// JSON \[ AS \] 'json_option'
9643    Json(Option<String>),
9644    /// MANIFEST \[ VERBOSE \]
9645    Manifest {
9646        /// Whether the MANIFEST is verbose.
9647        verbose: bool,
9648    },
9649    /// MAXFILESIZE \[ AS \] max-size \[ MB | GB \]
9650    MaxFileSize(FileSize),
9651    /// `NULL \[ AS \] 'null_string'`
9652    Null(String),
9653    /// `PARALLEL [ { ON | TRUE } | { OFF | FALSE } ]`
9654    Parallel(Option<bool>),
9655    /// PARQUET
9656    Parquet,
9657    /// PARTITION BY ( column_name [, ... ] ) \[ INCLUDE \]
9658    PartitionBy(UnloadPartitionBy),
9659    /// REGION \[ AS \] 'aws-region' }
9660    Region(String),
9661    /// REMOVEQUOTES
9662    RemoveQuotes,
9663    /// ROWGROUPSIZE \[ AS \] size \[ MB | GB \]
9664    RowGroupSize(FileSize),
9665    /// STATUPDATE [ { ON | TRUE } | { OFF | FALSE } ]
9666    StatUpdate(Option<bool>),
9667    /// TIMEFORMAT \[ AS \] {'timeformat_string' | 'auto' | 'epochsecs' | 'epochmillisecs' }
9668    TimeFormat(Option<String>),
9669    /// TRUNCATECOLUMNS
9670    TruncateColumns,
9671    /// ZSTD
9672    Zstd,
9673    /// Redshift `CREDENTIALS 'auth-args'`
9674    /// <https://docs.aws.amazon.com/redshift/latest/dg/copy-parameters-authorization.html>
9675    Credentials(String),
9676}
9677
9678impl fmt::Display for CopyLegacyOption {
9679    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9680        use CopyLegacyOption::*;
9681        match self {
9682            AcceptAnyDate => write!(f, "ACCEPTANYDATE"),
9683            AcceptInvChars(ch) => {
9684                write!(f, "ACCEPTINVCHARS")?;
9685                if let Some(ch) = ch {
9686                    write!(f, " '{}'", value::escape_single_quote_string(ch))?;
9687                }
9688                Ok(())
9689            }
9690            AddQuotes => write!(f, "ADDQUOTES"),
9691            AllowOverwrite => write!(f, "ALLOWOVERWRITE"),
9692            Binary => write!(f, "BINARY"),
9693            BlankAsNull => write!(f, "BLANKSASNULL"),
9694            Bzip2 => write!(f, "BZIP2"),
9695            CleanPath => write!(f, "CLEANPATH"),
9696            CompUpdate { preset, enabled } => {
9697                write!(f, "COMPUPDATE")?;
9698                if *preset {
9699                    write!(f, " PRESET")?;
9700                } else if let Some(enabled) = enabled {
9701                    write!(
9702                        f,
9703                        "{}",
9704                        match enabled {
9705                            true => " TRUE",
9706                            false => " FALSE",
9707                        }
9708                    )?;
9709                }
9710                Ok(())
9711            }
9712            Csv(opts) => {
9713                write!(f, "CSV")?;
9714                if !opts.is_empty() {
9715                    write!(f, " {}", display_separated(opts, " "))?;
9716                }
9717                Ok(())
9718            }
9719            DateFormat(fmt) => {
9720                write!(f, "DATEFORMAT")?;
9721                if let Some(fmt) = fmt {
9722                    write!(f, " '{}'", value::escape_single_quote_string(fmt))?;
9723                }
9724                Ok(())
9725            }
9726            Delimiter(char) => write!(f, "DELIMITER '{char}'"),
9727            EmptyAsNull => write!(f, "EMPTYASNULL"),
9728            Encrypted { auto } => write!(f, "ENCRYPTED{}", if *auto { " AUTO" } else { "" }),
9729            Escape => write!(f, "ESCAPE"),
9730            Extension(ext) => write!(f, "EXTENSION '{}'", value::escape_single_quote_string(ext)),
9731            FixedWidth(spec) => write!(
9732                f,
9733                "FIXEDWIDTH '{}'",
9734                value::escape_single_quote_string(spec)
9735            ),
9736            Gzip => write!(f, "GZIP"),
9737            Header => write!(f, "HEADER"),
9738            IamRole(role) => write!(f, "IAM_ROLE {role}"),
9739            IgnoreHeader(num_rows) => write!(f, "IGNOREHEADER {num_rows}"),
9740            Json(opt) => {
9741                write!(f, "JSON")?;
9742                if let Some(opt) = opt {
9743                    write!(f, " AS '{}'", value::escape_single_quote_string(opt))?;
9744                }
9745                Ok(())
9746            }
9747            Manifest { verbose } => write!(f, "MANIFEST{}", if *verbose { " VERBOSE" } else { "" }),
9748            MaxFileSize(file_size) => write!(f, "MAXFILESIZE {file_size}"),
9749            Null(string) => write!(f, "NULL '{}'", value::escape_single_quote_string(string)),
9750            Parallel(enabled) => {
9751                write!(
9752                    f,
9753                    "PARALLEL{}",
9754                    match enabled {
9755                        Some(true) => " TRUE",
9756                        Some(false) => " FALSE",
9757                        _ => "",
9758                    }
9759                )
9760            }
9761            Parquet => write!(f, "PARQUET"),
9762            PartitionBy(p) => write!(f, "{p}"),
9763            Region(region) => write!(f, "REGION '{}'", value::escape_single_quote_string(region)),
9764            RemoveQuotes => write!(f, "REMOVEQUOTES"),
9765            RowGroupSize(file_size) => write!(f, "ROWGROUPSIZE {file_size}"),
9766            StatUpdate(enabled) => {
9767                write!(
9768                    f,
9769                    "STATUPDATE{}",
9770                    match enabled {
9771                        Some(true) => " TRUE",
9772                        Some(false) => " FALSE",
9773                        _ => "",
9774                    }
9775                )
9776            }
9777            TimeFormat(fmt) => {
9778                write!(f, "TIMEFORMAT")?;
9779                if let Some(fmt) = fmt {
9780                    write!(f, " '{}'", value::escape_single_quote_string(fmt))?;
9781                }
9782                Ok(())
9783            }
9784            TruncateColumns => write!(f, "TRUNCATECOLUMNS"),
9785            Zstd => write!(f, "ZSTD"),
9786            Credentials(s) => write!(f, "CREDENTIALS '{}'", value::escape_single_quote_string(s)),
9787        }
9788    }
9789}
9790
9791/// ```sql
9792/// SIZE \[ MB | GB \]
9793/// ```
9794#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9795#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9796#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9797pub struct FileSize {
9798    /// Numeric size value.
9799    pub size: ValueWithSpan,
9800    /// Optional unit for the size (MB or GB).
9801    pub unit: Option<FileSizeUnit>,
9802}
9803
9804impl fmt::Display for FileSize {
9805    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9806        write!(f, "{}", self.size)?;
9807        if let Some(unit) = &self.unit {
9808            write!(f, " {unit}")?;
9809        }
9810        Ok(())
9811    }
9812}
9813
9814/// Units for `FileSize` (MB or GB).
9815#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9816#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9817#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9818pub enum FileSizeUnit {
9819    /// Megabytes.
9820    MB,
9821    /// Gigabytes.
9822    GB,
9823}
9824
9825impl fmt::Display for FileSizeUnit {
9826    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9827        match self {
9828            FileSizeUnit::MB => write!(f, "MB"),
9829            FileSizeUnit::GB => write!(f, "GB"),
9830        }
9831    }
9832}
9833
9834/// Specifies the partition keys for the unload operation
9835///
9836/// ```sql
9837/// PARTITION BY ( column_name [, ... ] ) [ INCLUDE ]
9838/// ```
9839#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9840#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9841#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9842pub struct UnloadPartitionBy {
9843    /// Columns used to partition the unload output.
9844    pub columns: Vec<Ident>,
9845    /// Whether to include the partition in the output.
9846    pub include: bool,
9847}
9848
9849impl fmt::Display for UnloadPartitionBy {
9850    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9851        write!(
9852            f,
9853            "PARTITION BY ({}){}",
9854            display_comma_separated(&self.columns),
9855            if self.include { " INCLUDE" } else { "" }
9856        )
9857    }
9858}
9859
9860/// An `IAM_ROLE` option in the AWS ecosystem
9861///
9862/// [Redshift COPY](https://docs.aws.amazon.com/redshift/latest/dg/copy-parameters-authorization.html#copy-iam-role)
9863#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9864#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9865#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9866pub enum IamRoleKind {
9867    /// Default role
9868    Default,
9869    /// Specific role ARN, for example: `arn:aws:iam::123456789:role/role1`
9870    Arn(String),
9871}
9872
9873impl fmt::Display for IamRoleKind {
9874    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9875        match self {
9876            IamRoleKind::Default => write!(f, "DEFAULT"),
9877            IamRoleKind::Arn(arn) => write!(f, "'{arn}'"),
9878        }
9879    }
9880}
9881
9882/// A `CSV` option in `COPY` statement before PostgreSQL version 9.0.
9883///
9884/// <https://www.postgresql.org/docs/8.4/sql-copy.html>
9885#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9886#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9887#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9888pub enum CopyLegacyCsvOption {
9889    /// HEADER
9890    Header,
9891    /// QUOTE \[ AS \] 'quote_character'
9892    Quote(char),
9893    /// ESCAPE \[ AS \] 'escape_character'
9894    Escape(char),
9895    /// FORCE QUOTE { column_name [, ...] | * }
9896    ForceQuote(Vec<Ident>),
9897    /// FORCE NOT NULL column_name [, ...]
9898    ForceNotNull(Vec<Ident>),
9899}
9900
9901impl fmt::Display for CopyLegacyCsvOption {
9902    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9903        use CopyLegacyCsvOption::*;
9904        match self {
9905            Header => write!(f, "HEADER"),
9906            Quote(char) => write!(f, "QUOTE '{char}'"),
9907            Escape(char) => write!(f, "ESCAPE '{char}'"),
9908            ForceQuote(columns) => write!(f, "FORCE QUOTE {}", display_comma_separated(columns)),
9909            ForceNotNull(columns) => {
9910                write!(f, "FORCE NOT NULL {}", display_comma_separated(columns))
9911            }
9912        }
9913    }
9914}
9915
9916/// Objects that can be discarded with `DISCARD`.
9917#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9918#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9919#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9920pub enum DiscardObject {
9921    /// Discard all session state.
9922    ALL,
9923    /// Discard cached plans.
9924    PLANS,
9925    /// Discard sequence values.
9926    SEQUENCES,
9927    /// Discard temporary objects.
9928    TEMP,
9929}
9930
9931impl fmt::Display for DiscardObject {
9932    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9933        match self {
9934            DiscardObject::ALL => f.write_str("ALL"),
9935            DiscardObject::PLANS => f.write_str("PLANS"),
9936            DiscardObject::SEQUENCES => f.write_str("SEQUENCES"),
9937            DiscardObject::TEMP => f.write_str("TEMP"),
9938        }
9939    }
9940}
9941
9942/// Types of flush operations supported by `FLUSH`.
9943#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9944#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9945#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9946pub enum FlushType {
9947    /// Flush binary logs.
9948    BinaryLogs,
9949    /// Flush engine logs.
9950    EngineLogs,
9951    /// Flush error logs.
9952    ErrorLogs,
9953    /// Flush general logs.
9954    GeneralLogs,
9955    /// Flush hosts information.
9956    Hosts,
9957    /// Flush logs.
9958    Logs,
9959    /// Flush privileges.
9960    Privileges,
9961    /// Flush optimizer costs.
9962    OptimizerCosts,
9963    /// Flush relay logs.
9964    RelayLogs,
9965    /// Flush slow logs.
9966    SlowLogs,
9967    /// Flush status.
9968    Status,
9969    /// Flush user resources.
9970    UserResources,
9971    /// Flush table data.
9972    Tables,
9973}
9974
9975impl fmt::Display for FlushType {
9976    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9977        match self {
9978            FlushType::BinaryLogs => f.write_str("BINARY LOGS"),
9979            FlushType::EngineLogs => f.write_str("ENGINE LOGS"),
9980            FlushType::ErrorLogs => f.write_str("ERROR LOGS"),
9981            FlushType::GeneralLogs => f.write_str("GENERAL LOGS"),
9982            FlushType::Hosts => f.write_str("HOSTS"),
9983            FlushType::Logs => f.write_str("LOGS"),
9984            FlushType::Privileges => f.write_str("PRIVILEGES"),
9985            FlushType::OptimizerCosts => f.write_str("OPTIMIZER_COSTS"),
9986            FlushType::RelayLogs => f.write_str("RELAY LOGS"),
9987            FlushType::SlowLogs => f.write_str("SLOW LOGS"),
9988            FlushType::Status => f.write_str("STATUS"),
9989            FlushType::UserResources => f.write_str("USER_RESOURCES"),
9990            FlushType::Tables => f.write_str("TABLES"),
9991        }
9992    }
9993}
9994
9995/// Location modifier for flush commands.
9996#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9997#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9998#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9999pub enum FlushLocation {
10000    /// Do not write changes to the binary log.
10001    NoWriteToBinlog,
10002    /// Apply flush locally.
10003    Local,
10004}
10005
10006impl fmt::Display for FlushLocation {
10007    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10008        match self {
10009            FlushLocation::NoWriteToBinlog => f.write_str("NO_WRITE_TO_BINLOG"),
10010            FlushLocation::Local => f.write_str("LOCAL"),
10011        }
10012    }
10013}
10014
10015/// Optional context modifier for statements that can be or `LOCAL`, `GLOBAL`, or `SESSION`.
10016#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10017#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10018#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10019pub enum ContextModifier {
10020    /// `LOCAL` identifier, usually related to transactional states.
10021    Local,
10022    /// `SESSION` identifier
10023    Session,
10024    /// `GLOBAL` identifier
10025    Global,
10026}
10027
10028impl fmt::Display for ContextModifier {
10029    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10030        match self {
10031            Self::Local => {
10032                write!(f, "LOCAL ")
10033            }
10034            Self::Session => {
10035                write!(f, "SESSION ")
10036            }
10037            Self::Global => {
10038                write!(f, "GLOBAL ")
10039            }
10040        }
10041    }
10042}
10043
10044/// Function describe in DROP FUNCTION.
10045#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10046#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10047pub enum DropFunctionOption {
10048    /// `RESTRICT` option for DROP FUNCTION.
10049    Restrict,
10050    /// `CASCADE` option for DROP FUNCTION.
10051    Cascade,
10052}
10053
10054impl fmt::Display for DropFunctionOption {
10055    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10056        match self {
10057            DropFunctionOption::Restrict => write!(f, "RESTRICT "),
10058            DropFunctionOption::Cascade => write!(f, "CASCADE  "),
10059        }
10060    }
10061}
10062
10063/// Generic function description for DROP FUNCTION and CREATE TRIGGER.
10064#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10065#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10066#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10067pub struct FunctionDesc {
10068    /// The function name.
10069    pub name: ObjectName,
10070    /// Optional list of function arguments.
10071    pub args: Option<Vec<OperateFunctionArg>>,
10072}
10073
10074impl fmt::Display for FunctionDesc {
10075    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10076        write!(f, "{}", self.name)?;
10077        if let Some(args) = &self.args {
10078            write!(f, "({})", display_comma_separated(args))?;
10079        }
10080        Ok(())
10081    }
10082}
10083
10084/// Function argument in CREATE OR DROP FUNCTION.
10085#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10086#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10087#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10088pub struct OperateFunctionArg {
10089    /// Optional argument mode (`IN`, `OUT`, `INOUT`).
10090    pub mode: Option<ArgMode>,
10091    /// Optional argument identifier/name.
10092    pub name: Option<Ident>,
10093    /// The data type of the argument.
10094    pub data_type: DataType,
10095    /// Optional default expression for the argument.
10096    pub default_expr: Option<Expr>,
10097}
10098
10099impl OperateFunctionArg {
10100    /// Returns an unnamed argument.
10101    pub fn unnamed(data_type: DataType) -> Self {
10102        Self {
10103            mode: None,
10104            name: None,
10105            data_type,
10106            default_expr: None,
10107        }
10108    }
10109
10110    /// Returns an argument with name.
10111    pub fn with_name(name: &str, data_type: DataType) -> Self {
10112        Self {
10113            mode: None,
10114            name: Some(name.into()),
10115            data_type,
10116            default_expr: None,
10117        }
10118    }
10119}
10120
10121impl fmt::Display for OperateFunctionArg {
10122    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10123        if let Some(mode) = &self.mode {
10124            write!(f, "{mode} ")?;
10125        }
10126        if let Some(name) = &self.name {
10127            write!(f, "{name} ")?;
10128        }
10129        write!(f, "{}", self.data_type)?;
10130        if let Some(default_expr) = &self.default_expr {
10131            write!(f, " = {default_expr}")?;
10132        }
10133        Ok(())
10134    }
10135}
10136
10137/// The mode of an argument in CREATE FUNCTION.
10138#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10139#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10140#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10141pub enum ArgMode {
10142    /// `IN` mode.
10143    In,
10144    /// `OUT` mode.
10145    Out,
10146    /// `INOUT` mode.
10147    InOut,
10148    /// `VARIADIC` mode.
10149    Variadic,
10150}
10151
10152impl fmt::Display for ArgMode {
10153    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10154        match self {
10155            ArgMode::In => write!(f, "IN"),
10156            ArgMode::Out => write!(f, "OUT"),
10157            ArgMode::InOut => write!(f, "INOUT"),
10158            ArgMode::Variadic => write!(f, "VARIADIC"),
10159        }
10160    }
10161}
10162
10163/// These attributes inform the query optimizer about the behavior of the function.
10164#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10165#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10166#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10167pub enum FunctionBehavior {
10168    /// Function is immutable.
10169    Immutable,
10170    /// Function is stable.
10171    Stable,
10172    /// Function is volatile.
10173    Volatile,
10174}
10175
10176impl fmt::Display for FunctionBehavior {
10177    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10178        match self {
10179            FunctionBehavior::Immutable => write!(f, "IMMUTABLE"),
10180            FunctionBehavior::Stable => write!(f, "STABLE"),
10181            FunctionBehavior::Volatile => write!(f, "VOLATILE"),
10182        }
10183    }
10184}
10185
10186/// Security attribute for functions: SECURITY DEFINER or SECURITY INVOKER.
10187///
10188/// [PostgreSQL](https://www.postgresql.org/docs/current/sql-createfunction.html)
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 enum FunctionSecurity {
10193    /// Execute the function with the privileges of the user who defined it.
10194    Definer,
10195    /// Execute the function with the privileges of the user who invokes it.
10196    Invoker,
10197}
10198
10199impl fmt::Display for FunctionSecurity {
10200    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10201        match self {
10202            FunctionSecurity::Definer => write!(f, "SECURITY DEFINER"),
10203            FunctionSecurity::Invoker => write!(f, "SECURITY INVOKER"),
10204        }
10205    }
10206}
10207
10208/// Value for a SET configuration parameter in a CREATE FUNCTION statement.
10209///
10210/// [PostgreSQL](https://www.postgresql.org/docs/current/sql-createfunction.html)
10211#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10212#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10213#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10214pub enum FunctionSetValue {
10215    /// SET param = DEFAULT / SET param TO DEFAULT
10216    Default,
10217    /// SET param = value1, value2, ...
10218    Values(Vec<Expr>),
10219    /// SET param FROM CURRENT
10220    FromCurrent,
10221}
10222
10223/// A SET configuration_parameter clause in a CREATE FUNCTION statement.
10224///
10225/// [PostgreSQL](https://www.postgresql.org/docs/current/sql-createfunction.html)
10226#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10227#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10228#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10229pub struct FunctionDefinitionSetParam {
10230    /// The name of the configuration parameter.
10231    pub name: ObjectName,
10232    /// The value to set for the parameter.
10233    pub value: FunctionSetValue,
10234}
10235
10236impl fmt::Display for FunctionDefinitionSetParam {
10237    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10238        write!(f, "SET {} ", self.name)?;
10239        match &self.value {
10240            FunctionSetValue::Default => write!(f, "= DEFAULT"),
10241            FunctionSetValue::Values(values) => {
10242                write!(f, "= {}", display_comma_separated(values))
10243            }
10244            FunctionSetValue::FromCurrent => write!(f, "FROM CURRENT"),
10245        }
10246    }
10247}
10248
10249/// These attributes describe the behavior of the function when called with a null argument.
10250#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10251#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10252#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10253pub enum FunctionCalledOnNull {
10254    /// Function is called even when inputs are null.
10255    CalledOnNullInput,
10256    /// Function returns null when any input is null.
10257    ReturnsNullOnNullInput,
10258    /// Function is strict about null inputs.
10259    Strict,
10260}
10261
10262impl fmt::Display for FunctionCalledOnNull {
10263    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10264        match self {
10265            FunctionCalledOnNull::CalledOnNullInput => write!(f, "CALLED ON NULL INPUT"),
10266            FunctionCalledOnNull::ReturnsNullOnNullInput => write!(f, "RETURNS NULL ON NULL INPUT"),
10267            FunctionCalledOnNull::Strict => write!(f, "STRICT"),
10268        }
10269    }
10270}
10271
10272/// If it is safe for PostgreSQL to call the function from multiple threads at once
10273#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10274#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10275#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10276pub enum FunctionParallel {
10277    /// The function is not safe to run in parallel.
10278    Unsafe,
10279    /// The function is restricted for parallel execution.
10280    Restricted,
10281    /// The function is safe to run in parallel.
10282    Safe,
10283}
10284
10285impl fmt::Display for FunctionParallel {
10286    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10287        match self {
10288            FunctionParallel::Unsafe => write!(f, "PARALLEL UNSAFE"),
10289            FunctionParallel::Restricted => write!(f, "PARALLEL RESTRICTED"),
10290            FunctionParallel::Safe => write!(f, "PARALLEL SAFE"),
10291        }
10292    }
10293}
10294
10295/// [BigQuery] Determinism specifier used in a UDF definition.
10296///
10297/// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#syntax_11
10298#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10299#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10300#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10301pub enum FunctionDeterminismSpecifier {
10302    /// Function is deterministic.
10303    Deterministic,
10304    /// Function is not deterministic.
10305    NotDeterministic,
10306}
10307
10308impl fmt::Display for FunctionDeterminismSpecifier {
10309    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10310        match self {
10311            FunctionDeterminismSpecifier::Deterministic => {
10312                write!(f, "DETERMINISTIC")
10313            }
10314            FunctionDeterminismSpecifier::NotDeterministic => {
10315                write!(f, "NOT DETERMINISTIC")
10316            }
10317        }
10318    }
10319}
10320
10321/// Represent the expression body of a `CREATE FUNCTION` statement as well as
10322/// where within the statement, the body shows up.
10323///
10324/// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#syntax_11
10325/// [PostgreSQL]: https://www.postgresql.org/docs/15/sql-createfunction.html
10326/// [MsSql]: https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql
10327#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10328#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10329#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10330pub enum CreateFunctionBody {
10331    /// A function body expression using the 'AS' keyword and shows up
10332    /// before any `OPTIONS` clause.
10333    ///
10334    /// Example:
10335    /// ```sql
10336    /// CREATE FUNCTION myfunc(x FLOAT64, y FLOAT64) RETURNS FLOAT64
10337    /// AS (x * y)
10338    /// OPTIONS(description="desc");
10339    /// ```
10340    ///
10341    /// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#syntax_11
10342    /// [PostgreSQL]: https://www.postgresql.org/docs/current/sql-createfunction.html
10343    AsBeforeOptions {
10344        /// The primary expression.
10345        body: Expr,
10346        /// Link symbol if the primary expression contains the name of shared library file.
10347        ///
10348        /// Example:
10349        /// ```sql
10350        /// CREATE FUNCTION cas_in(input cstring) RETURNS cas
10351        /// AS 'MODULE_PATHNAME', 'cas_in_wrapper'
10352        /// ```
10353        /// [PostgreSQL]: https://www.postgresql.org/docs/current/sql-createfunction.html
10354        link_symbol: Option<Expr>,
10355    },
10356    /// A function body expression using the 'AS' keyword and shows up
10357    /// after any `OPTIONS` clause.
10358    ///
10359    /// Example:
10360    /// ```sql
10361    /// CREATE FUNCTION myfunc(x FLOAT64, y FLOAT64) RETURNS FLOAT64
10362    /// OPTIONS(description="desc")
10363    /// AS (x * y);
10364    /// ```
10365    ///
10366    /// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#syntax_11
10367    AsAfterOptions(Expr),
10368    /// Function body with statements before the `RETURN` keyword.
10369    ///
10370    /// Example:
10371    /// ```sql
10372    /// CREATE FUNCTION my_scalar_udf(a INT, b INT)
10373    /// RETURNS INT
10374    /// AS
10375    /// BEGIN
10376    ///     DECLARE c INT;
10377    ///     SET c = a + b;
10378    ///     RETURN c;
10379    /// END
10380    /// ```
10381    ///
10382    /// [MsSql]: https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql
10383    AsBeginEnd(BeginEndStatements),
10384    /// Function body expression using the 'RETURN' keyword.
10385    ///
10386    /// Example:
10387    /// ```sql
10388    /// CREATE FUNCTION myfunc(a INTEGER, IN b INTEGER = 1) RETURNS INTEGER
10389    /// LANGUAGE SQL
10390    /// RETURN a + b;
10391    /// ```
10392    ///
10393    /// [PostgreSQL]: https://www.postgresql.org/docs/current/sql-createfunction.html
10394    Return(Expr),
10395
10396    /// Function body expression using the 'AS RETURN' keywords
10397    ///
10398    /// Example:
10399    /// ```sql
10400    /// CREATE FUNCTION myfunc(a INT, b INT)
10401    /// RETURNS TABLE
10402    /// AS RETURN (SELECT a + b AS sum);
10403    /// ```
10404    ///
10405    /// [MsSql]: https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql
10406    AsReturnExpr(Expr),
10407
10408    /// Function body expression using the 'AS RETURN' keywords, with an un-parenthesized SELECT query
10409    ///
10410    /// Example:
10411    /// ```sql
10412    /// CREATE FUNCTION myfunc(a INT, b INT)
10413    /// RETURNS TABLE
10414    /// AS RETURN SELECT a + b AS sum;
10415    /// ```
10416    ///
10417    /// [MsSql]: https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql?view=sql-server-ver16#select_stmt
10418    AsReturnSelect(Select),
10419}
10420
10421#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10422#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10423#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10424/// `USING` clause options for `CREATE FUNCTION` (e.g., JAR, FILE, ARCHIVE).
10425pub enum CreateFunctionUsing {
10426    /// Use a JAR file located at the given URI.
10427    Jar(String),
10428    /// Use a file located at the given URI.
10429    File(String),
10430    /// Use an archive located at the given URI.
10431    Archive(String),
10432}
10433
10434impl fmt::Display for CreateFunctionUsing {
10435    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10436        write!(f, "USING ")?;
10437        match self {
10438            CreateFunctionUsing::Jar(uri) => write!(f, "JAR '{uri}'"),
10439            CreateFunctionUsing::File(uri) => write!(f, "FILE '{uri}'"),
10440            CreateFunctionUsing::Archive(uri) => write!(f, "ARCHIVE '{uri}'"),
10441        }
10442    }
10443}
10444
10445/// `NAME = <EXPR>` arguments for DuckDB macros
10446///
10447/// See [Create Macro - DuckDB](https://duckdb.org/docs/sql/statements/create_macro)
10448/// for more details
10449#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10450#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10451#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10452pub struct MacroArg {
10453    /// The argument name.
10454    pub name: Ident,
10455    /// Optional default expression for the argument.
10456    pub default_expr: Option<Expr>,
10457}
10458
10459impl MacroArg {
10460    /// Returns an argument with name.
10461    pub fn new(name: &str) -> Self {
10462        Self {
10463            name: name.into(),
10464            default_expr: None,
10465        }
10466    }
10467}
10468
10469impl fmt::Display for MacroArg {
10470    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10471        write!(f, "{}", self.name)?;
10472        if let Some(default_expr) = &self.default_expr {
10473            write!(f, " := {default_expr}")?;
10474        }
10475        Ok(())
10476    }
10477}
10478
10479#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10480#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10481#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10482/// Definition for a DuckDB macro: either an expression or a table-producing query.
10483pub enum MacroDefinition {
10484    /// The macro is defined as an expression.
10485    Expr(Expr),
10486    /// The macro is defined as a table (query).
10487    Table(Box<Query>),
10488}
10489
10490impl fmt::Display for MacroDefinition {
10491    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10492        match self {
10493            MacroDefinition::Expr(expr) => write!(f, "{expr}")?,
10494            MacroDefinition::Table(query) => write!(f, "{query}")?,
10495        }
10496        Ok(())
10497    }
10498}
10499
10500/// Schema possible naming variants ([1]).
10501///
10502/// [1]: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#schema-definition
10503#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10504#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10505#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10506pub enum SchemaName {
10507    /// Only schema name specified: `<schema name>`.
10508    Simple(ObjectName),
10509    /// Only authorization identifier specified: `AUTHORIZATION <schema authorization identifier>`.
10510    UnnamedAuthorization(Ident),
10511    /// Both schema name and authorization identifier specified: `<schema name>  AUTHORIZATION <schema authorization identifier>`.
10512    NamedAuthorization(ObjectName, Ident),
10513}
10514
10515impl fmt::Display for SchemaName {
10516    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10517        match self {
10518            SchemaName::Simple(name) => {
10519                write!(f, "{name}")
10520            }
10521            SchemaName::UnnamedAuthorization(authorization) => {
10522                write!(f, "AUTHORIZATION {authorization}")
10523            }
10524            SchemaName::NamedAuthorization(name, authorization) => {
10525                write!(f, "{name} AUTHORIZATION {authorization}")
10526            }
10527        }
10528    }
10529}
10530
10531/// Fulltext search modifiers ([1]).
10532///
10533/// [1]: https://dev.mysql.com/doc/refman/8.0/en/fulltext-search.html#function_match
10534#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10535#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10536#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10537pub enum SearchModifier {
10538    /// `IN NATURAL LANGUAGE MODE`.
10539    InNaturalLanguageMode,
10540    /// `IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION`.
10541    InNaturalLanguageModeWithQueryExpansion,
10542    ///`IN BOOLEAN MODE`.
10543    InBooleanMode,
10544    ///`WITH QUERY EXPANSION`.
10545    WithQueryExpansion,
10546}
10547
10548impl fmt::Display for SearchModifier {
10549    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10550        match self {
10551            Self::InNaturalLanguageMode => {
10552                write!(f, "IN NATURAL LANGUAGE MODE")?;
10553            }
10554            Self::InNaturalLanguageModeWithQueryExpansion => {
10555                write!(f, "IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION")?;
10556            }
10557            Self::InBooleanMode => {
10558                write!(f, "IN BOOLEAN MODE")?;
10559            }
10560            Self::WithQueryExpansion => {
10561                write!(f, "WITH QUERY EXPANSION")?;
10562            }
10563        }
10564
10565        Ok(())
10566    }
10567}
10568
10569/// Represents a `LOCK TABLE` clause with optional alias and lock type.
10570#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10571#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10572#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10573pub struct LockTable {
10574    /// The table identifier to lock.
10575    pub table: Ident,
10576    /// Optional alias for the table.
10577    pub alias: Option<Ident>,
10578    /// The type of lock to apply to the table.
10579    pub lock_type: LockTableType,
10580}
10581
10582impl fmt::Display for LockTable {
10583    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10584        let Self {
10585            table: tbl_name,
10586            alias,
10587            lock_type,
10588        } = self;
10589
10590        write!(f, "{tbl_name} ")?;
10591        if let Some(alias) = alias {
10592            write!(f, "AS {alias} ")?;
10593        }
10594        write!(f, "{lock_type}")?;
10595        Ok(())
10596    }
10597}
10598
10599#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10600#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10601#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10602/// The type of lock used in `LOCK TABLE` statements.
10603pub enum LockTableType {
10604    /// Shared/read lock. If `local` is true, it's a local read lock.
10605    Read {
10606        /// Whether the read lock is local.
10607        local: bool,
10608    },
10609    /// Exclusive/write lock. If `low_priority` is true, the write is low priority.
10610    Write {
10611        /// Whether the write lock is low priority.
10612        low_priority: bool,
10613    },
10614}
10615
10616impl fmt::Display for LockTableType {
10617    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10618        match self {
10619            Self::Read { local } => {
10620                write!(f, "READ")?;
10621                if *local {
10622                    write!(f, " LOCAL")?;
10623                }
10624            }
10625            Self::Write { low_priority } => {
10626                if *low_priority {
10627                    write!(f, "LOW_PRIORITY ")?;
10628                }
10629                write!(f, "WRITE")?;
10630            }
10631        }
10632
10633        Ok(())
10634    }
10635}
10636
10637#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10638#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10639#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10640/// Hive-specific `SET LOCATION` helper used in some `LOAD DATA` statements.
10641pub struct HiveSetLocation {
10642    /// Whether the `SET` keyword was present.
10643    pub has_set: bool,
10644    /// The location identifier.
10645    pub location: Ident,
10646}
10647
10648impl fmt::Display for HiveSetLocation {
10649    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10650        if self.has_set {
10651            write!(f, "SET ")?;
10652        }
10653        write!(f, "LOCATION {}", self.location)
10654    }
10655}
10656
10657/// MySQL `ALTER TABLE` only  [FIRST | AFTER column_name]
10658#[allow(clippy::large_enum_variant)]
10659#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10660#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10661#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10662/// MySQL `ALTER TABLE` column position specifier: `FIRST` or `AFTER <column>`.
10663pub enum MySQLColumnPosition {
10664    /// Place the column first in the table.
10665    First,
10666    /// Place the column after the specified identifier.
10667    After(Ident),
10668}
10669
10670impl Display for MySQLColumnPosition {
10671    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10672        match self {
10673            MySQLColumnPosition::First => write!(f, "FIRST"),
10674            MySQLColumnPosition::After(ident) => {
10675                let column_name = &ident.value;
10676                write!(f, "AFTER {column_name}")
10677            }
10678        }
10679    }
10680}
10681
10682/// MySQL `CREATE VIEW` algorithm parameter: [ALGORITHM = {UNDEFINED | MERGE | TEMPTABLE}]
10683#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10684#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10685#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10686/// MySQL `CREATE VIEW` algorithm options.
10687pub enum CreateViewAlgorithm {
10688    /// `UNDEFINED` algorithm.
10689    Undefined,
10690    /// `MERGE` algorithm.
10691    Merge,
10692    /// `TEMPTABLE` algorithm.
10693    TempTable,
10694}
10695
10696impl Display for CreateViewAlgorithm {
10697    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10698        match self {
10699            CreateViewAlgorithm::Undefined => write!(f, "UNDEFINED"),
10700            CreateViewAlgorithm::Merge => write!(f, "MERGE"),
10701            CreateViewAlgorithm::TempTable => write!(f, "TEMPTABLE"),
10702        }
10703    }
10704}
10705/// MySQL `CREATE VIEW` security parameter: [SQL SECURITY { DEFINER | INVOKER }]
10706#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10707#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10708#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10709/// MySQL `CREATE VIEW` SQL SECURITY options.
10710pub enum CreateViewSecurity {
10711    /// The view runs with the privileges of the definer.
10712    Definer,
10713    /// The view runs with the privileges of the invoker.
10714    Invoker,
10715}
10716
10717impl Display for CreateViewSecurity {
10718    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10719        match self {
10720            CreateViewSecurity::Definer => write!(f, "DEFINER"),
10721            CreateViewSecurity::Invoker => write!(f, "INVOKER"),
10722        }
10723    }
10724}
10725
10726/// [MySQL] `CREATE VIEW` additional parameters
10727///
10728/// [MySQL]: https://dev.mysql.com/doc/refman/9.1/en/create-view.html
10729#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10730#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10731#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10732pub struct CreateViewParams {
10733    /// Optional view algorithm (e.g., MERGE, TEMPTABLE).
10734    pub algorithm: Option<CreateViewAlgorithm>,
10735    /// Optional definer (the security principal that will own the view).
10736    pub definer: Option<GranteeName>,
10737    /// Optional SQL SECURITY setting for the view.
10738    pub security: Option<CreateViewSecurity>,
10739}
10740
10741impl Display for CreateViewParams {
10742    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10743        let CreateViewParams {
10744            algorithm,
10745            definer,
10746            security,
10747        } = self;
10748        if let Some(algorithm) = algorithm {
10749            write!(f, "ALGORITHM = {algorithm} ")?;
10750        }
10751        if let Some(definers) = definer {
10752            write!(f, "DEFINER = {definers} ")?;
10753        }
10754        if let Some(security) = security {
10755            write!(f, "SQL SECURITY {security} ")?;
10756        }
10757        Ok(())
10758    }
10759}
10760
10761#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10762#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10763#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10764/// Key/Value, where the value is a (optionally named) list of identifiers
10765///
10766/// ```sql
10767/// UNION = (tbl_name[,tbl_name]...)
10768/// ENGINE = ReplicatedMergeTree('/table_name','{replica}', ver)
10769/// ENGINE = SummingMergeTree([columns])
10770/// ```
10771pub struct NamedParenthesizedList {
10772    /// The option key (identifier) for this named list.
10773    pub key: Ident,
10774    /// Optional secondary name associated with the key.
10775    pub name: Option<Ident>,
10776    /// The list of identifier values for the key.
10777    pub values: Vec<Ident>,
10778}
10779
10780/// Snowflake `WITH ROW ACCESS POLICY policy_name ON (identifier, ...)`
10781///
10782/// <https://docs.snowflake.com/en/sql-reference/sql/create-table>
10783/// <https://docs.snowflake.com/en/user-guide/security-row-intro>
10784#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10785#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10786#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10787pub struct RowAccessPolicy {
10788    /// The fully-qualified policy object name.
10789    pub policy: ObjectName,
10790    /// Identifiers for the columns or objects the policy applies to.
10791    pub on: Vec<Ident>,
10792}
10793
10794impl RowAccessPolicy {
10795    /// Create a new `RowAccessPolicy` for the given `policy` and `on` identifiers.
10796    pub fn new(policy: ObjectName, on: Vec<Ident>) -> Self {
10797        Self { policy, on }
10798    }
10799}
10800
10801impl Display for RowAccessPolicy {
10802    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10803        write!(
10804            f,
10805            "WITH ROW ACCESS POLICY {} ON ({})",
10806            self.policy,
10807            display_comma_separated(self.on.as_slice())
10808        )
10809    }
10810}
10811
10812/// Snowflake `[ WITH ] STORAGE LIFECYCLE POLICY <policy_name> ON ( <col_name> [ , ... ] )`
10813///
10814/// <https://docs.snowflake.com/en/sql-reference/sql/create-table>
10815#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10816#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10817#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10818pub struct StorageLifecyclePolicy {
10819    /// The fully-qualified policy object name.
10820    pub policy: ObjectName,
10821    /// Column names the policy applies to.
10822    pub on: Vec<Ident>,
10823}
10824
10825impl Display for StorageLifecyclePolicy {
10826    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10827        write!(
10828            f,
10829            "WITH STORAGE LIFECYCLE POLICY {} ON ({})",
10830            self.policy,
10831            display_comma_separated(self.on.as_slice())
10832        )
10833    }
10834}
10835
10836/// Snowflake `WITH TAG ( tag_name = '<tag_value>', ...)`
10837///
10838/// <https://docs.snowflake.com/en/sql-reference/sql/create-table>
10839#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10840#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10841#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10842pub struct Tag {
10843    /// The tag key (can be qualified).
10844    pub key: ObjectName,
10845    /// The tag value as a string.
10846    pub value: String,
10847}
10848
10849impl Tag {
10850    /// Create a new `Tag` with the given key and value.
10851    pub fn new(key: ObjectName, value: String) -> Self {
10852        Self { key, value }
10853    }
10854}
10855
10856impl Display for Tag {
10857    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10858        write!(f, "{}='{}'", self.key, self.value)
10859    }
10860}
10861
10862/// Snowflake `WITH CONTACT ( purpose = contact [ , purpose = contact ...] )`
10863///
10864/// <https://docs.snowflake.com/en/sql-reference/sql/create-database>
10865#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10866#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10867#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10868pub struct ContactEntry {
10869    /// The purpose label for the contact entry.
10870    pub purpose: String,
10871    /// The contact information associated with the purpose.
10872    pub contact: String,
10873}
10874
10875impl Display for ContactEntry {
10876    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10877        write!(f, "{} = {}", self.purpose, self.contact)
10878    }
10879}
10880
10881/// Helper to indicate if a comment includes the `=` in the display form
10882#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10883#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10884#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10885pub enum CommentDef {
10886    /// Includes `=` when printing the comment, as `COMMENT = 'comment'`
10887    /// Does not include `=` when printing the comment, as `COMMENT 'comment'`
10888    WithEq(String),
10889    /// Comment variant that omits the `=` when displayed.
10890    WithoutEq(String),
10891}
10892
10893impl Display for CommentDef {
10894    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10895        match self {
10896            CommentDef::WithEq(comment) | CommentDef::WithoutEq(comment) => write!(f, "{comment}"),
10897        }
10898    }
10899}
10900
10901/// Helper to indicate if a collection should be wrapped by a symbol in the display form
10902///
10903/// [`Display`] is implemented for every [`Vec<T>`] where `T: Display`.
10904/// The string output is a comma separated list for the vec items
10905///
10906/// # Examples
10907/// ```
10908/// # use sqlparser::ast::WrappedCollection;
10909/// let items = WrappedCollection::Parentheses(vec!["one", "two", "three"]);
10910/// assert_eq!("(one, two, three)", items.to_string());
10911///
10912/// let items = WrappedCollection::NoWrapping(vec!["one", "two", "three"]);
10913/// assert_eq!("one, two, three", items.to_string());
10914/// ```
10915#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10916#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10917#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10918pub enum WrappedCollection<T> {
10919    /// Print the collection without wrapping symbols, as `item, item, item`
10920    NoWrapping(T),
10921    /// Wraps the collection in Parentheses, as `(item, item, item)`
10922    Parentheses(T),
10923}
10924
10925impl<T> Display for WrappedCollection<Vec<T>>
10926where
10927    T: Display,
10928{
10929    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10930        match self {
10931            WrappedCollection::NoWrapping(inner) => {
10932                write!(f, "{}", display_comma_separated(inner.as_slice()))
10933            }
10934            WrappedCollection::Parentheses(inner) => {
10935                write!(f, "({})", display_comma_separated(inner.as_slice()))
10936            }
10937        }
10938    }
10939}
10940
10941/// Represents a single PostgreSQL utility option.
10942///
10943/// A utility option is a key-value pair where the key is an identifier (IDENT) and the value
10944/// can be one of the following:
10945/// - A number with an optional sign (`+` or `-`). Example: `+10`, `-10.2`, `3`
10946/// - A non-keyword string. Example: `option1`, `'option2'`, `"option3"`
10947/// - keyword: `TRUE`, `FALSE`, `ON` (`off` is also accept).
10948/// - Empty. Example: `ANALYZE` (identifier only)
10949///
10950/// Utility options are used in various PostgreSQL DDL statements, including statements such as
10951/// `CLUSTER`, `EXPLAIN`, `VACUUM`, and `REINDEX`. These statements format options as `( option [, ...] )`.
10952///
10953/// [CLUSTER](https://www.postgresql.org/docs/current/sql-cluster.html)
10954/// [EXPLAIN](https://www.postgresql.org/docs/current/sql-explain.html)
10955/// [VACUUM](https://www.postgresql.org/docs/current/sql-vacuum.html)
10956/// [REINDEX](https://www.postgresql.org/docs/current/sql-reindex.html)
10957///
10958/// For example, the `EXPLAIN` AND `VACUUM` statements with options might look like this:
10959/// ```sql
10960/// EXPLAIN (ANALYZE, VERBOSE TRUE, FORMAT TEXT) SELECT * FROM my_table;
10961///
10962/// VACUUM (VERBOSE, ANALYZE ON, PARALLEL 10) my_table;
10963/// ```
10964#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10965#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10966#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10967pub struct UtilityOption {
10968    /// The option name (identifier).
10969    pub name: Ident,
10970    /// Optional argument for the option (number, string, keyword, etc.).
10971    pub arg: Option<Expr>,
10972}
10973
10974impl Display for UtilityOption {
10975    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10976        if let Some(ref arg) = self.arg {
10977            write!(f, "{} {}", self.name, arg)
10978        } else {
10979            write!(f, "{}", self.name)
10980        }
10981    }
10982}
10983
10984/// Represents the different options available for `SHOW`
10985/// statements to filter the results. Example from Snowflake:
10986/// <https://docs.snowflake.com/en/sql-reference/sql/show-tables>
10987#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10988#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10989#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10990pub struct ShowStatementOptions {
10991    /// Optional scope to show in (for example: TABLE, SCHEMA).
10992    pub show_in: Option<ShowStatementIn>,
10993    /// Optional `STARTS WITH` filter value.
10994    pub starts_with: Option<ValueWithSpan>,
10995    /// Optional `LIMIT` expression.
10996    pub limit: Option<Expr>,
10997    /// Optional `FROM` value used with `LIMIT`.
10998    pub limit_from: Option<ValueWithSpan>,
10999    /// Optional filter position (infix or suffix) for `LIKE`/`FILTER`.
11000    pub filter_position: Option<ShowStatementFilterPosition>,
11001}
11002
11003impl Display for ShowStatementOptions {
11004    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
11005        let (like_in_infix, like_in_suffix) = match &self.filter_position {
11006            Some(ShowStatementFilterPosition::Infix(filter)) => {
11007                (format!(" {filter}"), "".to_string())
11008            }
11009            Some(ShowStatementFilterPosition::Suffix(filter)) => {
11010                ("".to_string(), format!(" {filter}"))
11011            }
11012            None => ("".to_string(), "".to_string()),
11013        };
11014        write!(
11015            f,
11016            "{like_in_infix}{show_in}{starts_with}{limit}{from}{like_in_suffix}",
11017            show_in = match &self.show_in {
11018                Some(i) => format!(" {i}"),
11019                None => String::new(),
11020            },
11021            starts_with = match &self.starts_with {
11022                Some(s) => format!(" STARTS WITH {s}"),
11023                None => String::new(),
11024            },
11025            limit = match &self.limit {
11026                Some(l) => format!(" LIMIT {l}"),
11027                None => String::new(),
11028            },
11029            from = match &self.limit_from {
11030                Some(f) => format!(" FROM {f}"),
11031                None => String::new(),
11032            }
11033        )?;
11034        Ok(())
11035    }
11036}
11037
11038#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11039#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11040#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11041/// Where a `SHOW` filter appears relative to the main clause.
11042pub enum ShowStatementFilterPosition {
11043    /// Put the filter in an infix position (e.g. `SHOW COLUMNS LIKE '%name%' IN TABLE tbl`).
11044    Infix(ShowStatementFilter), // For example: SHOW COLUMNS LIKE '%name%' IN TABLE tbl
11045    /// Put the filter in a suffix position (e.g. `SHOW COLUMNS IN tbl LIKE '%name%'`).
11046    Suffix(ShowStatementFilter), // For example: SHOW COLUMNS IN tbl LIKE '%name%'
11047}
11048
11049#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11050#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11051#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11052/// Parent object types usable with `SHOW ... IN <parent>` clauses.
11053pub enum ShowStatementInParentType {
11054    /// ACCOUNT parent type for SHOW statements.
11055    Account,
11056    /// DATABASE parent type for SHOW statements.
11057    Database,
11058    /// SCHEMA parent type for SHOW statements.
11059    Schema,
11060    /// TABLE parent type for SHOW statements.
11061    Table,
11062    /// VIEW parent type for SHOW statements.
11063    View,
11064}
11065
11066impl fmt::Display for ShowStatementInParentType {
11067    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11068        match self {
11069            ShowStatementInParentType::Account => write!(f, "ACCOUNT"),
11070            ShowStatementInParentType::Database => write!(f, "DATABASE"),
11071            ShowStatementInParentType::Schema => write!(f, "SCHEMA"),
11072            ShowStatementInParentType::Table => write!(f, "TABLE"),
11073            ShowStatementInParentType::View => write!(f, "VIEW"),
11074        }
11075    }
11076}
11077
11078#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11079#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11080#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11081/// Represents a `SHOW ... IN` clause with optional parent qualifier and name.
11082pub struct ShowStatementIn {
11083    /// The clause that specifies what to show (e.g. COLUMNS, TABLES).
11084    pub clause: ShowStatementInClause,
11085    /// Optional parent type qualifier (ACCOUNT/DATABASE/...).
11086    pub parent_type: Option<ShowStatementInParentType>,
11087    /// Optional parent object name for the SHOW clause.
11088    #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
11089    pub parent_name: Option<ObjectName>,
11090}
11091
11092impl fmt::Display for ShowStatementIn {
11093    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11094        write!(f, "{}", self.clause)?;
11095        if let Some(parent_type) = &self.parent_type {
11096            write!(f, " {parent_type}")?;
11097        }
11098        if let Some(parent_name) = &self.parent_name {
11099            write!(f, " {parent_name}")?;
11100        }
11101        Ok(())
11102    }
11103}
11104
11105/// A Show Charset statement
11106#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11107#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11108#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11109pub struct ShowCharset {
11110    /// The statement can be written as `SHOW CHARSET` or `SHOW CHARACTER SET`
11111    /// true means CHARSET was used and false means CHARACTER SET was used
11112    pub is_shorthand: bool,
11113    /// Optional `LIKE`/`WHERE`-style filter for the statement.
11114    pub filter: Option<ShowStatementFilter>,
11115}
11116
11117impl fmt::Display for ShowCharset {
11118    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11119        write!(f, "SHOW")?;
11120        if self.is_shorthand {
11121            write!(f, " CHARSET")?;
11122        } else {
11123            write!(f, " CHARACTER SET")?;
11124        }
11125        if let Some(filter) = &self.filter {
11126            write!(f, " {filter}")?;
11127        }
11128        Ok(())
11129    }
11130}
11131
11132#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11133#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11134#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11135/// Options for a `SHOW OBJECTS` statement.
11136pub struct ShowObjects {
11137    /// Whether to show terse output.
11138    pub terse: bool,
11139    /// Additional options controlling the SHOW output.
11140    pub show_options: ShowStatementOptions,
11141}
11142
11143/// MSSQL's json null clause
11144///
11145/// ```plaintext
11146/// <json_null_clause> ::=
11147///       NULL ON NULL
11148///     | ABSENT ON NULL
11149/// ```
11150///
11151/// <https://learn.microsoft.com/en-us/sql/t-sql/functions/json-object-transact-sql?view=sql-server-ver16#json_null_clause>
11152#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11153#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11154#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11155pub enum JsonNullClause {
11156    /// `NULL ON NULL` behavior for JSON functions.
11157    NullOnNull,
11158    /// `ABSENT ON NULL` behavior for JSON functions.
11159    AbsentOnNull,
11160}
11161
11162impl Display for JsonNullClause {
11163    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
11164        match self {
11165            JsonNullClause::NullOnNull => write!(f, "NULL ON NULL"),
11166            JsonNullClause::AbsentOnNull => write!(f, "ABSENT ON NULL"),
11167        }
11168    }
11169}
11170
11171/// PostgreSQL JSON function RETURNING clause
11172///
11173/// Example:
11174/// ```sql
11175/// JSON_OBJECT('a': 1 RETURNING jsonb)
11176/// ```
11177#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11178#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11179#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11180pub struct JsonReturningClause {
11181    /// The data type to return from the JSON function (e.g. JSON/JSONB).
11182    pub data_type: DataType,
11183}
11184
11185impl Display for JsonReturningClause {
11186    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
11187        write!(f, "RETURNING {}", self.data_type)
11188    }
11189}
11190
11191/// rename object definition
11192#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11193#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11194#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11195pub struct RenameTable {
11196    /// The current name of the object to rename.
11197    pub old_name: ObjectName,
11198    /// The new name for the object.
11199    pub new_name: ObjectName,
11200}
11201
11202impl fmt::Display for RenameTable {
11203    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11204        write!(f, "{} TO {}", self.old_name, self.new_name)?;
11205        Ok(())
11206    }
11207}
11208
11209/// Represents the referenced table in an `INSERT INTO` statement
11210#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11211#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11212#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11213pub enum TableObject {
11214    /// Table specified by name.
11215    /// Example:
11216    /// ```sql
11217    /// INSERT INTO my_table
11218    /// ```
11219    TableName(#[cfg_attr(feature = "visitor", visit(with = "visit_relation"))] ObjectName),
11220
11221    /// Table specified as a function.
11222    /// Example:
11223    /// ```sql
11224    /// INSERT INTO TABLE FUNCTION remote('localhost', default.simple_table)
11225    /// ```
11226    /// [Clickhouse](https://clickhouse.com/docs/en/sql-reference/table-functions)
11227    TableFunction(Function),
11228
11229    /// Table specified through a sub-query
11230    /// Example:
11231    /// ```sql
11232    /// INSERT INTO
11233    /// (SELECT employee_id, last_name, email, hire_date, job_id,  salary, commission_pct FROM employees)
11234    /// VALUES (207, 'Gregory', 'pgregory@example.com', sysdate, 'PU_CLERK', 1.2E3, NULL);
11235    /// ```
11236    /// [Oracle](https://docs.oracle.com/en/database/oracle/oracle-database/21/sqlrf/INSERT.html#GUID-903F8043-0254-4EE9-ACC1-CB8AC0AF3423__I2126242)
11237    TableQuery(Box<Query>),
11238}
11239
11240impl fmt::Display for TableObject {
11241    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11242        match self {
11243            Self::TableName(table_name) => write!(f, "{table_name}"),
11244            Self::TableFunction(func) => write!(f, "FUNCTION {func}"),
11245            Self::TableQuery(table_query) => write!(f, "({table_query})"),
11246        }
11247    }
11248}
11249
11250/// Represents a SET SESSION AUTHORIZATION statement
11251#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11252#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11253#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11254pub struct SetSessionAuthorizationParam {
11255    /// The scope for the `SET SESSION AUTHORIZATION` (e.g., GLOBAL/SESSION).
11256    pub scope: ContextModifier,
11257    /// The specific authorization parameter kind.
11258    pub kind: SetSessionAuthorizationParamKind,
11259}
11260
11261impl fmt::Display for SetSessionAuthorizationParam {
11262    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11263        write!(f, "{}", self.kind)
11264    }
11265}
11266
11267/// Represents the parameter kind for SET SESSION AUTHORIZATION
11268#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11269#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11270#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11271pub enum SetSessionAuthorizationParamKind {
11272    /// Default authorization
11273    Default,
11274
11275    /// User name
11276    User(Ident),
11277}
11278
11279impl fmt::Display for SetSessionAuthorizationParamKind {
11280    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11281        match self {
11282            SetSessionAuthorizationParamKind::Default => write!(f, "DEFAULT"),
11283            SetSessionAuthorizationParamKind::User(name) => write!(f, "{}", name),
11284        }
11285    }
11286}
11287
11288#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11289#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11290#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11291/// Kind of session parameter being set by `SET SESSION`.
11292pub enum SetSessionParamKind {
11293    /// Generic session parameter (name/value pair).
11294    Generic(SetSessionParamGeneric),
11295    /// Identity insert related parameter.
11296    IdentityInsert(SetSessionParamIdentityInsert),
11297    /// Offsets-related parameter.
11298    Offsets(SetSessionParamOffsets),
11299    /// Statistics-related parameter.
11300    Statistics(SetSessionParamStatistics),
11301}
11302
11303impl fmt::Display for SetSessionParamKind {
11304    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11305        match self {
11306            SetSessionParamKind::Generic(x) => write!(f, "{x}"),
11307            SetSessionParamKind::IdentityInsert(x) => write!(f, "{x}"),
11308            SetSessionParamKind::Offsets(x) => write!(f, "{x}"),
11309            SetSessionParamKind::Statistics(x) => write!(f, "{x}"),
11310        }
11311    }
11312}
11313
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))]
11317/// Generic `SET SESSION` parameter represented as name(s) and value.
11318pub struct SetSessionParamGeneric {
11319    /// Names of the session parameters being set.
11320    pub names: Vec<String>,
11321    /// The value to assign to the parameter(s).
11322    pub value: String,
11323}
11324
11325impl fmt::Display for SetSessionParamGeneric {
11326    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11327        write!(f, "{} {}", display_comma_separated(&self.names), self.value)
11328    }
11329}
11330
11331#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11332#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11333#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11334/// `IDENTITY_INSERT` session parameter for a specific object.
11335pub struct SetSessionParamIdentityInsert {
11336    /// Object name targeted by `IDENTITY_INSERT`.
11337    pub obj: ObjectName,
11338    /// Value (ON/OFF) for the identity insert setting.
11339    pub value: SessionParamValue,
11340}
11341
11342impl fmt::Display for SetSessionParamIdentityInsert {
11343    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11344        write!(f, "IDENTITY_INSERT {} {}", self.obj, self.value)
11345    }
11346}
11347
11348#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11349#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11350#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11351/// Offsets-related session parameter with keywords and a value.
11352pub struct SetSessionParamOffsets {
11353    /// Keywords specifying which offsets to modify.
11354    pub keywords: Vec<String>,
11355    /// Value (ON/OFF) for the offsets setting.
11356    pub value: SessionParamValue,
11357}
11358
11359impl fmt::Display for SetSessionParamOffsets {
11360    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11361        write!(
11362            f,
11363            "OFFSETS {} {}",
11364            display_comma_separated(&self.keywords),
11365            self.value
11366        )
11367    }
11368}
11369
11370#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11371#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11372#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11373/// Statistics-related session parameter specifying topic and value.
11374pub struct SetSessionParamStatistics {
11375    /// Statistics topic to set (IO/PROFILE/TIME/XML).
11376    pub topic: SessionParamStatsTopic,
11377    /// Value (ON/OFF) for the statistics topic.
11378    pub value: SessionParamValue,
11379}
11380
11381impl fmt::Display for SetSessionParamStatistics {
11382    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11383        write!(f, "STATISTICS {} {}", self.topic, self.value)
11384    }
11385}
11386
11387#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11388#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11389#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11390/// Topics available for session statistics configuration.
11391pub enum SessionParamStatsTopic {
11392    /// Input/output statistics.
11393    IO,
11394    /// Profile statistics.
11395    Profile,
11396    /// Time statistics.
11397    Time,
11398    /// XML-related statistics.
11399    Xml,
11400}
11401
11402impl fmt::Display for SessionParamStatsTopic {
11403    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11404        match self {
11405            SessionParamStatsTopic::IO => write!(f, "IO"),
11406            SessionParamStatsTopic::Profile => write!(f, "PROFILE"),
11407            SessionParamStatsTopic::Time => write!(f, "TIME"),
11408            SessionParamStatsTopic::Xml => write!(f, "XML"),
11409        }
11410    }
11411}
11412
11413#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11414#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11415#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11416/// Value for a session boolean-like parameter (ON/OFF).
11417pub enum SessionParamValue {
11418    /// Session parameter enabled.
11419    On,
11420    /// Session parameter disabled.
11421    Off,
11422}
11423
11424impl fmt::Display for SessionParamValue {
11425    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11426        match self {
11427            SessionParamValue::On => write!(f, "ON"),
11428            SessionParamValue::Off => write!(f, "OFF"),
11429        }
11430    }
11431}
11432
11433/// Snowflake StorageSerializationPolicy for Iceberg Tables
11434/// ```sql
11435/// [ STORAGE_SERIALIZATION_POLICY = { COMPATIBLE | OPTIMIZED } ]
11436/// ```
11437///
11438/// <https://docs.snowflake.com/en/sql-reference/sql/create-iceberg-table>
11439#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11440#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11441#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11442pub enum StorageSerializationPolicy {
11443    /// Use compatible serialization mode.
11444    Compatible,
11445    /// Use optimized serialization mode.
11446    Optimized,
11447}
11448
11449impl Display for StorageSerializationPolicy {
11450    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
11451        match self {
11452            StorageSerializationPolicy::Compatible => write!(f, "COMPATIBLE"),
11453            StorageSerializationPolicy::Optimized => write!(f, "OPTIMIZED"),
11454        }
11455    }
11456}
11457
11458/// Snowflake CatalogSyncNamespaceMode
11459/// ```sql
11460/// [ CATALOG_SYNC_NAMESPACE_MODE = { NEST | FLATTEN } ]
11461/// ```
11462///
11463/// <https://docs.snowflake.com/en/sql-reference/sql/create-database>
11464#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11465#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11466#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11467pub enum CatalogSyncNamespaceMode {
11468    /// Nest namespaces when syncing catalog.
11469    Nest,
11470    /// Flatten namespaces when syncing catalog.
11471    Flatten,
11472}
11473
11474impl Display for CatalogSyncNamespaceMode {
11475    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
11476        match self {
11477            CatalogSyncNamespaceMode::Nest => write!(f, "NEST"),
11478            CatalogSyncNamespaceMode::Flatten => write!(f, "FLATTEN"),
11479        }
11480    }
11481}
11482
11483/// Variants of the Snowflake `COPY INTO` statement
11484#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11485#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11486#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11487pub enum CopyIntoSnowflakeKind {
11488    /// Loads data from files to a table
11489    /// See: <https://docs.snowflake.com/en/sql-reference/sql/copy-into-table>
11490    Table,
11491    /// Unloads data from a table or query to external files
11492    /// See: <https://docs.snowflake.com/en/sql-reference/sql/copy-into-location>
11493    Location,
11494}
11495
11496#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11497#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11498#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11499/// `PRINT` statement for producing debug/output messages.
11500pub struct PrintStatement {
11501    /// The expression producing the message to print.
11502    pub message: Box<Expr>,
11503}
11504
11505impl fmt::Display for PrintStatement {
11506    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11507        write!(f, "PRINT {}", self.message)
11508    }
11509}
11510
11511/// The type of `WAITFOR` statement (MSSQL).
11512///
11513/// See: <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/waitfor-transact-sql>
11514#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11515#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11516#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11517pub enum WaitForType {
11518    /// `WAITFOR DELAY 'time_to_pass'`
11519    Delay,
11520    /// `WAITFOR TIME 'time_to_execute'`
11521    Time,
11522}
11523
11524impl fmt::Display for WaitForType {
11525    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11526        match self {
11527            WaitForType::Delay => write!(f, "DELAY"),
11528            WaitForType::Time => write!(f, "TIME"),
11529        }
11530    }
11531}
11532
11533/// MSSQL `WAITFOR` statement.
11534///
11535/// See: <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/waitfor-transact-sql>
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 WaitForStatement {
11540    /// `DELAY` or `TIME`.
11541    pub wait_type: WaitForType,
11542    /// The time expression.
11543    pub expr: Expr,
11544}
11545
11546impl fmt::Display for WaitForStatement {
11547    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11548        write!(f, "WAITFOR {} {}", self.wait_type, self.expr)
11549    }
11550}
11551
11552/// Represents a `Return` statement.
11553///
11554/// [MsSql triggers](https://learn.microsoft.com/en-us/sql/t-sql/statements/create-trigger-transact-sql)
11555/// [MsSql functions](https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql)
11556#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11557#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11558#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11559pub struct ReturnStatement {
11560    /// Optional return value expression.
11561    pub value: Option<ReturnStatementValue>,
11562}
11563
11564impl fmt::Display for ReturnStatement {
11565    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11566        match &self.value {
11567            Some(ReturnStatementValue::Expr(expr)) => write!(f, "RETURN {expr}"),
11568            None => write!(f, "RETURN"),
11569        }
11570    }
11571}
11572
11573/// Variants of a `RETURN` statement
11574#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11575#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11576#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11577pub enum ReturnStatementValue {
11578    /// Return an expression from a function or trigger.
11579    Expr(Expr),
11580}
11581
11582/// Represents an `OPEN` statement.
11583#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11584#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11585#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11586pub struct OpenStatement {
11587    /// Cursor name
11588    pub cursor_name: Ident,
11589}
11590
11591impl fmt::Display for OpenStatement {
11592    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11593        write!(f, "OPEN {}", self.cursor_name)
11594    }
11595}
11596
11597/// Specifies Include / Exclude NULL within UNPIVOT command.
11598/// For example
11599/// `UNPIVOT (column1 FOR new_column IN (col3, col4, col5, col6))`
11600#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11601#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11602#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11603pub enum NullInclusion {
11604    /// Include NULL values in the UNPIVOT output.
11605    IncludeNulls,
11606    /// Exclude NULL values from the UNPIVOT output.
11607    ExcludeNulls,
11608}
11609
11610impl fmt::Display for NullInclusion {
11611    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11612        match self {
11613            NullInclusion::IncludeNulls => write!(f, "INCLUDE NULLS"),
11614            NullInclusion::ExcludeNulls => write!(f, "EXCLUDE NULLS"),
11615        }
11616    }
11617}
11618
11619/// Checks membership of a value in a JSON array
11620///
11621/// Syntax:
11622/// ```sql
11623/// <value> MEMBER OF(<array>)
11624/// ```
11625/// [MySQL](https://dev.mysql.com/doc/refman/8.4/en/json-search-functions.html#operator_member-of)
11626#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11627#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11628#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11629pub struct MemberOf {
11630    /// The value to check for membership.
11631    pub value: Box<Expr>,
11632    /// The JSON array expression to check against.
11633    pub array: Box<Expr>,
11634}
11635
11636impl fmt::Display for MemberOf {
11637    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11638        write!(f, "{} MEMBER OF({})", self.value, self.array)
11639    }
11640}
11641
11642#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11643#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11644#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11645/// Represents an `EXPORT DATA` statement.
11646pub struct ExportData {
11647    /// Options for the export operation.
11648    pub options: Vec<SqlOption>,
11649    /// The query producing the data to export.
11650    pub query: Box<Query>,
11651    /// Optional named connection to use for export.
11652    pub connection: Option<ObjectName>,
11653}
11654
11655impl fmt::Display for ExportData {
11656    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11657        if let Some(connection) = &self.connection {
11658            write!(
11659                f,
11660                "EXPORT DATA WITH CONNECTION {connection} OPTIONS({}) AS {}",
11661                display_comma_separated(&self.options),
11662                self.query
11663            )
11664        } else {
11665            write!(
11666                f,
11667                "EXPORT DATA OPTIONS({}) AS {}",
11668                display_comma_separated(&self.options),
11669                self.query
11670            )
11671        }
11672    }
11673}
11674/// Creates a user
11675///
11676/// Syntax:
11677/// ```sql
11678/// CREATE [OR REPLACE] USER [IF NOT EXISTS] <name> [OPTIONS]
11679/// ```
11680///
11681/// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-user)
11682#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11683#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11684#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11685pub struct CreateUser {
11686    /// Replace existing user if present.
11687    pub or_replace: bool,
11688    /// Only create the user if it does not already exist.
11689    pub if_not_exists: bool,
11690    /// The name of the user to create.
11691    pub name: Ident,
11692    /// Key/value options for user creation.
11693    pub options: KeyValueOptions,
11694    /// Whether tags are specified using `WITH TAG`.
11695    pub with_tags: bool,
11696    /// Tags for the user.
11697    pub tags: KeyValueOptions,
11698}
11699
11700impl fmt::Display for CreateUser {
11701    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11702        write!(f, "CREATE")?;
11703        if self.or_replace {
11704            write!(f, " OR REPLACE")?;
11705        }
11706        write!(f, " USER")?;
11707        if self.if_not_exists {
11708            write!(f, " IF NOT EXISTS")?;
11709        }
11710        write!(f, " {}", self.name)?;
11711        if !self.options.options.is_empty() {
11712            write!(f, " {}", self.options)?;
11713        }
11714        if !self.tags.options.is_empty() {
11715            if self.with_tags {
11716                write!(f, " WITH")?;
11717            }
11718            write!(f, " TAG ({})", self.tags)?;
11719        }
11720        Ok(())
11721    }
11722}
11723
11724/// Modifies the properties of a user
11725///
11726/// [Snowflake Syntax:](https://docs.snowflake.com/en/sql-reference/sql/alter-user)
11727/// ```sql
11728/// ALTER USER [ IF EXISTS ] [ <name> ] [ OPTIONS ]
11729/// ```
11730///
11731/// [PostgreSQL Syntax:](https://www.postgresql.org/docs/current/sql-alteruser.html)
11732/// ```sql
11733/// ALTER USER <role_specification> [ WITH ] option [ ... ]
11734/// ```
11735#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11736#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11737#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11738pub struct AlterUser {
11739    /// Whether to only alter the user if it exists.
11740    pub if_exists: bool,
11741    /// The name of the user to alter.
11742    pub name: Ident,
11743    /// Optional new name for the user (Snowflake-specific).
11744    /// See: <https://docs.snowflake.com/en/sql-reference/sql/alter-user#syntax>
11745    pub rename_to: Option<Ident>,
11746    /// Reset the user's password.
11747    pub reset_password: bool,
11748    /// Abort all running queries for the user.
11749    pub abort_all_queries: bool,
11750    /// Optionally add a delegated role authorization.
11751    pub add_role_delegation: Option<AlterUserAddRoleDelegation>,
11752    /// Optionally remove a delegated role authorization.
11753    pub remove_role_delegation: Option<AlterUserRemoveRoleDelegation>,
11754    /// Enroll the user in MFA.
11755    pub enroll_mfa: bool,
11756    /// Set the default MFA method for the user.
11757    pub set_default_mfa_method: Option<MfaMethodKind>,
11758    /// Remove the user's default MFA method.
11759    pub remove_mfa_method: Option<MfaMethodKind>,
11760    /// Modify an MFA method for the user.
11761    pub modify_mfa_method: Option<AlterUserModifyMfaMethod>,
11762    /// Add an MFA OTP method with optional count.
11763    pub add_mfa_method_otp: Option<AlterUserAddMfaMethodOtp>,
11764    /// Set a user policy.
11765    pub set_policy: Option<AlterUserSetPolicy>,
11766    /// Unset a user policy.
11767    pub unset_policy: Option<UserPolicyKind>,
11768    /// Key/value tag options to set on the user.
11769    pub set_tag: KeyValueOptions,
11770    /// Tags to unset on the user.
11771    pub unset_tag: Vec<String>,
11772    /// Key/value properties to set on the user.
11773    pub set_props: KeyValueOptions,
11774    /// Properties to unset on the user.
11775    pub unset_props: Vec<String>,
11776    /// The following options are PostgreSQL-specific: <https://www.postgresql.org/docs/current/sql-alteruser.html>
11777    pub password: Option<AlterUserPassword>,
11778}
11779
11780/// ```sql
11781/// ALTER USER [ IF EXISTS ] [ <name> ] ADD DELEGATED AUTHORIZATION OF ROLE <role_name> TO SECURITY INTEGRATION <integration_name>
11782/// ```
11783#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11784#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11785#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11786pub struct AlterUserAddRoleDelegation {
11787    /// Role name to delegate.
11788    pub role: Ident,
11789    /// Security integration receiving the delegation.
11790    pub integration: Ident,
11791}
11792
11793/// ```sql
11794/// ALTER USER [ IF EXISTS ] [ <name> ] REMOVE DELEGATED { AUTHORIZATION OF ROLE <role_name> | AUTHORIZATIONS } FROM SECURITY INTEGRATION <integration_name>
11795/// ```
11796#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11797#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11798#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11799pub struct AlterUserRemoveRoleDelegation {
11800    /// Optional role name to remove delegation for.
11801    pub role: Option<Ident>,
11802    /// Security integration from which to remove delegation.
11803    pub integration: Ident,
11804}
11805
11806/// ```sql
11807/// ADD MFA METHOD OTP [ COUNT = number ]
11808/// ```
11809#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11810#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11811#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11812pub struct AlterUserAddMfaMethodOtp {
11813    /// Optional OTP count parameter.
11814    pub count: Option<ValueWithSpan>,
11815}
11816
11817/// ```sql
11818/// ALTER USER [ IF EXISTS ] [ <name> ] MODIFY MFA METHOD <mfa_method> SET COMMENT = '<string>'
11819/// ```
11820#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11821#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11822#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11823pub struct AlterUserModifyMfaMethod {
11824    /// The MFA method being modified.
11825    pub method: MfaMethodKind,
11826    /// The new comment for the MFA method.
11827    pub comment: String,
11828}
11829
11830/// Types of MFA methods
11831#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11832#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11833#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11834pub enum MfaMethodKind {
11835    /// PassKey (hardware or platform passkey) MFA method.
11836    PassKey,
11837    /// Time-based One-Time Password (TOTP) MFA method.
11838    Totp,
11839    /// Duo Security MFA method.
11840    Duo,
11841}
11842
11843impl fmt::Display for MfaMethodKind {
11844    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11845        match self {
11846            MfaMethodKind::PassKey => write!(f, "PASSKEY"),
11847            MfaMethodKind::Totp => write!(f, "TOTP"),
11848            MfaMethodKind::Duo => write!(f, "DUO"),
11849        }
11850    }
11851}
11852
11853/// ```sql
11854/// ALTER USER [ IF EXISTS ] [ <name> ] SET { AUTHENTICATION | PASSWORD | SESSION } POLICY <policy_name>
11855/// ```
11856#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11857#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11858#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11859pub struct AlterUserSetPolicy {
11860    /// The kind of user policy being set (authentication/password/session).
11861    pub policy_kind: UserPolicyKind,
11862    /// The identifier of the policy to apply.
11863    pub policy: Ident,
11864}
11865
11866/// Types of user-based policies
11867#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11868#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11869#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11870pub enum UserPolicyKind {
11871    /// Authentication policy.
11872    Authentication,
11873    /// Password policy.
11874    Password,
11875    /// Session policy.
11876    Session,
11877}
11878
11879impl fmt::Display for UserPolicyKind {
11880    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11881        match self {
11882            UserPolicyKind::Authentication => write!(f, "AUTHENTICATION"),
11883            UserPolicyKind::Password => write!(f, "PASSWORD"),
11884            UserPolicyKind::Session => write!(f, "SESSION"),
11885        }
11886    }
11887}
11888
11889impl fmt::Display for AlterUser {
11890    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11891        write!(f, "ALTER")?;
11892        write!(f, " USER")?;
11893        if self.if_exists {
11894            write!(f, " IF EXISTS")?;
11895        }
11896        write!(f, " {}", self.name)?;
11897        if let Some(new_name) = &self.rename_to {
11898            write!(f, " RENAME TO {new_name}")?;
11899        }
11900        if self.reset_password {
11901            write!(f, " RESET PASSWORD")?;
11902        }
11903        if self.abort_all_queries {
11904            write!(f, " ABORT ALL QUERIES")?;
11905        }
11906        if let Some(role_delegation) = &self.add_role_delegation {
11907            let role = &role_delegation.role;
11908            let integration = &role_delegation.integration;
11909            write!(
11910                f,
11911                " ADD DELEGATED AUTHORIZATION OF ROLE {role} TO SECURITY INTEGRATION {integration}"
11912            )?;
11913        }
11914        if let Some(role_delegation) = &self.remove_role_delegation {
11915            write!(f, " REMOVE DELEGATED")?;
11916            match &role_delegation.role {
11917                Some(role) => write!(f, " AUTHORIZATION OF ROLE {role}")?,
11918                None => write!(f, " AUTHORIZATIONS")?,
11919            }
11920            let integration = &role_delegation.integration;
11921            write!(f, " FROM SECURITY INTEGRATION {integration}")?;
11922        }
11923        if self.enroll_mfa {
11924            write!(f, " ENROLL MFA")?;
11925        }
11926        if let Some(method) = &self.set_default_mfa_method {
11927            write!(f, " SET DEFAULT_MFA_METHOD {method}")?
11928        }
11929        if let Some(method) = &self.remove_mfa_method {
11930            write!(f, " REMOVE MFA METHOD {method}")?;
11931        }
11932        if let Some(modify) = &self.modify_mfa_method {
11933            let method = &modify.method;
11934            let comment = &modify.comment;
11935            write!(
11936                f,
11937                " MODIFY MFA METHOD {method} SET COMMENT '{}'",
11938                value::escape_single_quote_string(comment)
11939            )?;
11940        }
11941        if let Some(add_mfa_method_otp) = &self.add_mfa_method_otp {
11942            write!(f, " ADD MFA METHOD OTP")?;
11943            if let Some(count) = &add_mfa_method_otp.count {
11944                write!(f, " COUNT = {count}")?;
11945            }
11946        }
11947        if let Some(policy) = &self.set_policy {
11948            let policy_kind = &policy.policy_kind;
11949            let name = &policy.policy;
11950            write!(f, " SET {policy_kind} POLICY {name}")?;
11951        }
11952        if let Some(policy_kind) = &self.unset_policy {
11953            write!(f, " UNSET {policy_kind} POLICY")?;
11954        }
11955        if !self.set_tag.options.is_empty() {
11956            write!(f, " SET TAG {}", self.set_tag)?;
11957        }
11958        if !self.unset_tag.is_empty() {
11959            write!(f, " UNSET TAG {}", display_comma_separated(&self.unset_tag))?;
11960        }
11961        let has_props = !self.set_props.options.is_empty();
11962        if has_props {
11963            write!(f, " SET")?;
11964            write!(f, " {}", &self.set_props)?;
11965        }
11966        if !self.unset_props.is_empty() {
11967            write!(f, " UNSET {}", display_comma_separated(&self.unset_props))?;
11968        }
11969        if let Some(password) = &self.password {
11970            write!(f, " {}", password)?;
11971        }
11972        Ok(())
11973    }
11974}
11975
11976/// ```sql
11977/// ALTER USER <role_specification> [ WITH ] PASSWORD { 'password' | NULL }``
11978/// ```
11979#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11980#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11981#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11982pub struct AlterUserPassword {
11983    /// Whether the password is encrypted.
11984    pub encrypted: bool,
11985    /// The password string, or `None` for `NULL`.
11986    pub password: Option<String>,
11987}
11988
11989impl Display for AlterUserPassword {
11990    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11991        if self.encrypted {
11992            write!(f, "ENCRYPTED ")?;
11993        }
11994        write!(f, "PASSWORD")?;
11995        match &self.password {
11996            None => write!(f, " NULL")?,
11997            Some(password) => write!(f, " '{}'", value::escape_single_quote_string(password))?,
11998        }
11999        Ok(())
12000    }
12001}
12002
12003/// Specifies how to create a new table based on an existing table's schema.
12004/// '''sql
12005/// CREATE TABLE new LIKE old ...
12006/// '''
12007#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
12008#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
12009#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
12010pub enum CreateTableLikeKind {
12011    /// '''sql
12012    /// CREATE TABLE new (LIKE old ...)
12013    /// '''
12014    /// [Redshift](https://docs.aws.amazon.com/redshift/latest/dg/r_CREATE_TABLE_NEW.html)
12015    Parenthesized(CreateTableLike),
12016    /// '''sql
12017    /// CREATE TABLE new LIKE old ...
12018    /// '''
12019    /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-table#label-create-table-like)
12020    /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_table_like)
12021    Plain(CreateTableLike),
12022}
12023
12024#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
12025#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
12026#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
12027/// Controls whether defaults are included when creating a table FROM/LILE another.
12028pub enum CreateTableLikeDefaults {
12029    /// Include default values from the source table.
12030    Including,
12031    /// Exclude default values from the source table.
12032    Excluding,
12033}
12034
12035impl fmt::Display for CreateTableLikeDefaults {
12036    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
12037        match self {
12038            CreateTableLikeDefaults::Including => write!(f, "INCLUDING DEFAULTS"),
12039            CreateTableLikeDefaults::Excluding => write!(f, "EXCLUDING DEFAULTS"),
12040        }
12041    }
12042}
12043
12044#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
12045#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
12046#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
12047/// Represents the `LIKE` clause of a `CREATE TABLE` statement.
12048pub struct CreateTableLike {
12049    /// The source table name to copy the schema from.
12050    pub name: ObjectName,
12051    /// Optional behavior controlling whether defaults are copied.
12052    pub defaults: Option<CreateTableLikeDefaults>,
12053}
12054
12055impl fmt::Display for CreateTableLike {
12056    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
12057        write!(f, "LIKE {}", self.name)?;
12058        if let Some(defaults) = &self.defaults {
12059            write!(f, " {defaults}")?;
12060        }
12061        Ok(())
12062    }
12063}
12064
12065/// Specifies the refresh mode for the dynamic table.
12066///
12067/// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-dynamic-table)
12068#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
12069#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
12070#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
12071pub enum RefreshModeKind {
12072    /// Automatic refresh mode (`AUTO`).
12073    Auto,
12074    /// Full refresh mode (`FULL`).
12075    Full,
12076    /// Incremental refresh mode (`INCREMENTAL`).
12077    Incremental,
12078}
12079
12080impl fmt::Display for RefreshModeKind {
12081    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
12082        match self {
12083            RefreshModeKind::Auto => write!(f, "AUTO"),
12084            RefreshModeKind::Full => write!(f, "FULL"),
12085            RefreshModeKind::Incremental => write!(f, "INCREMENTAL"),
12086        }
12087    }
12088}
12089
12090/// Specifies the behavior of the initial refresh of the dynamic table.
12091///
12092/// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-dynamic-table)
12093#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
12094#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
12095#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
12096pub enum InitializeKind {
12097    /// Initialize on creation (`ON CREATE`).
12098    OnCreate,
12099    /// Initialize on schedule (`ON SCHEDULE`).
12100    OnSchedule,
12101}
12102
12103impl fmt::Display for InitializeKind {
12104    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
12105        match self {
12106            InitializeKind::OnCreate => write!(f, "ON_CREATE"),
12107            InitializeKind::OnSchedule => write!(f, "ON_SCHEDULE"),
12108        }
12109    }
12110}
12111
12112/// Re-sorts rows and reclaims space in either a specified table or all tables in the current database
12113///
12114/// '''sql
12115/// VACUUM [ FULL | SORT ONLY | DELETE ONLY | REINDEX | RECLUSTER ] [ \[ table_name \] [ TO threshold PERCENT ] \[ BOOST \] ]
12116/// '''
12117/// [Redshift](https://docs.aws.amazon.com/redshift/latest/dg/r_VACUUM_command.html)
12118#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
12119#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
12120#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
12121pub struct VacuumStatement {
12122    /// Whether `FULL` was specified.
12123    pub full: bool,
12124    /// Whether `SORT ONLY` was specified.
12125    pub sort_only: bool,
12126    /// Whether `DELETE ONLY` was specified.
12127    pub delete_only: bool,
12128    /// Whether `REINDEX` was specified.
12129    pub reindex: bool,
12130    /// Whether `RECLUSTER` was specified.
12131    pub recluster: bool,
12132    /// Optional table to run `VACUUM` on.
12133    pub table_name: Option<ObjectName>,
12134    /// Optional threshold value (percent) for `TO threshold PERCENT`.
12135    pub threshold: Option<ValueWithSpan>,
12136    /// Whether `BOOST` was specified.
12137    pub boost: bool,
12138}
12139
12140impl fmt::Display for VacuumStatement {
12141    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
12142        write!(
12143            f,
12144            "VACUUM{}{}{}{}{}",
12145            if self.full { " FULL" } else { "" },
12146            if self.sort_only { " SORT ONLY" } else { "" },
12147            if self.delete_only { " DELETE ONLY" } else { "" },
12148            if self.reindex { " REINDEX" } else { "" },
12149            if self.recluster { " RECLUSTER" } else { "" },
12150        )?;
12151        if let Some(table_name) = &self.table_name {
12152            write!(f, " {table_name}")?;
12153        }
12154        if let Some(threshold) = &self.threshold {
12155            write!(f, " TO {threshold} PERCENT")?;
12156        }
12157        if self.boost {
12158            write!(f, " BOOST")?;
12159        }
12160        Ok(())
12161    }
12162}
12163
12164/// Variants of the RESET statement
12165#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
12166#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
12167#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
12168pub enum Reset {
12169    /// Resets all session parameters to their default values.
12170    ALL,
12171
12172    /// Resets a specific session parameter to its default value.
12173    ConfigurationParameter(ObjectName),
12174}
12175
12176/// Resets a session parameter to its default value.
12177/// ```sql
12178/// RESET { ALL | <configuration_parameter> }
12179/// ```
12180#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
12181#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
12182#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
12183pub struct ResetStatement {
12184    /// The reset action to perform (either `ALL` or a specific configuration parameter).
12185    pub reset: Reset,
12186}
12187
12188/// Query optimizer hints are optionally supported comments after the
12189/// `SELECT`, `INSERT`, `UPDATE`, `REPLACE`, `MERGE`, and `DELETE` keywords in
12190/// the corresponding statements.
12191///
12192/// See [Select::optimizer_hints]
12193#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
12194#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
12195#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
12196pub struct OptimizerHint {
12197    /// An optional prefix between the comment marker and `+`.
12198    ///
12199    /// Standard optimizer hints like `/*+ ... */` have an empty prefix,
12200    /// while system-specific hints like `/*abc+ ... */` have `prefix = "abc"`.
12201    /// The prefix is any sequence of ASCII alphanumeric characters
12202    /// immediately before the `+` marker.
12203    pub prefix: String,
12204    /// the raw text of the optimizer hint without its markers
12205    pub text: String,
12206    /// the style of the comment which `text` was extracted from,
12207    /// e.g. `/*+...*/` or `--+...`
12208    ///
12209    /// Not all dialects support all styles, though.
12210    pub style: OptimizerHintStyle,
12211}
12212
12213/// The commentary style of an [optimizer hint](OptimizerHint)
12214#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
12215#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
12216#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
12217pub enum OptimizerHintStyle {
12218    /// A hint corresponding to a single line comment,
12219    /// e.g. `--+ LEADING(v.e v.d t)`
12220    SingleLine {
12221        /// the comment prefix, e.g. `--`
12222        prefix: String,
12223    },
12224    /// A hint corresponding to a multi line comment,
12225    /// e.g. `/*+ LEADING(v.e v.d t) */`
12226    MultiLine,
12227}
12228
12229impl fmt::Display for OptimizerHint {
12230    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
12231        match &self.style {
12232            OptimizerHintStyle::SingleLine { prefix } => {
12233                f.write_str(prefix)?;
12234                f.write_str(&self.prefix)?;
12235                f.write_str("+")?;
12236                f.write_str(&self.text)
12237            }
12238            OptimizerHintStyle::MultiLine => {
12239                f.write_str("/*")?;
12240                f.write_str(&self.prefix)?;
12241                f.write_str("+")?;
12242                f.write_str(&self.text)?;
12243                f.write_str("*/")
12244            }
12245        }
12246    }
12247}
12248
12249impl fmt::Display for ResetStatement {
12250    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
12251        match &self.reset {
12252            Reset::ALL => write!(f, "RESET ALL"),
12253            Reset::ConfigurationParameter(param) => write!(f, "RESET {}", param),
12254        }
12255    }
12256}
12257
12258impl From<Set> for Statement {
12259    fn from(s: Set) -> Self {
12260        Self::Set(s)
12261    }
12262}
12263
12264impl From<Query> for Statement {
12265    fn from(q: Query) -> Self {
12266        Box::new(q).into()
12267    }
12268}
12269
12270impl From<Box<Query>> for Statement {
12271    fn from(q: Box<Query>) -> Self {
12272        Self::Query(q)
12273    }
12274}
12275
12276impl From<Insert> for Statement {
12277    fn from(i: Insert) -> Self {
12278        Self::Insert(i)
12279    }
12280}
12281
12282impl From<Update> for Statement {
12283    fn from(u: Update) -> Self {
12284        Self::Update(u)
12285    }
12286}
12287
12288impl From<CreateView> for Statement {
12289    fn from(cv: CreateView) -> Self {
12290        Self::CreateView(cv)
12291    }
12292}
12293
12294impl From<CreateRole> for Statement {
12295    fn from(cr: CreateRole) -> Self {
12296        Self::CreateRole(cr)
12297    }
12298}
12299
12300impl From<AlterTable> for Statement {
12301    fn from(at: AlterTable) -> Self {
12302        Self::AlterTable(at)
12303    }
12304}
12305
12306impl From<DropFunction> for Statement {
12307    fn from(df: DropFunction) -> Self {
12308        Self::DropFunction(df)
12309    }
12310}
12311
12312impl From<CreateExtension> for Statement {
12313    fn from(ce: CreateExtension) -> Self {
12314        Self::CreateExtension(ce)
12315    }
12316}
12317
12318impl From<CreateCollation> for Statement {
12319    fn from(c: CreateCollation) -> Self {
12320        Self::CreateCollation(c)
12321    }
12322}
12323
12324impl From<DropExtension> for Statement {
12325    fn from(de: DropExtension) -> Self {
12326        Self::DropExtension(de)
12327    }
12328}
12329
12330impl From<CaseStatement> for Statement {
12331    fn from(c: CaseStatement) -> Self {
12332        Self::Case(c)
12333    }
12334}
12335
12336impl From<IfStatement> for Statement {
12337    fn from(i: IfStatement) -> Self {
12338        Self::If(i)
12339    }
12340}
12341
12342impl From<WhileStatement> for Statement {
12343    fn from(w: WhileStatement) -> Self {
12344        Self::While(w)
12345    }
12346}
12347
12348impl From<RaiseStatement> for Statement {
12349    fn from(r: RaiseStatement) -> Self {
12350        Self::Raise(r)
12351    }
12352}
12353
12354impl From<ThrowStatement> for Statement {
12355    fn from(t: ThrowStatement) -> Self {
12356        Self::Throw(t)
12357    }
12358}
12359
12360impl From<Function> for Statement {
12361    fn from(f: Function) -> Self {
12362        Self::Call(f)
12363    }
12364}
12365
12366impl From<OpenStatement> for Statement {
12367    fn from(o: OpenStatement) -> Self {
12368        Self::Open(o)
12369    }
12370}
12371
12372impl From<Delete> for Statement {
12373    fn from(d: Delete) -> Self {
12374        Self::Delete(d)
12375    }
12376}
12377
12378impl From<CreateTable> for Statement {
12379    fn from(c: CreateTable) -> Self {
12380        Self::CreateTable(c)
12381    }
12382}
12383
12384impl From<CreateIndex> for Statement {
12385    fn from(c: CreateIndex) -> Self {
12386        Self::CreateIndex(c)
12387    }
12388}
12389
12390impl From<CreateServerStatement> for Statement {
12391    fn from(c: CreateServerStatement) -> Self {
12392        Self::CreateServer(c)
12393    }
12394}
12395
12396impl From<CreateConnector> for Statement {
12397    fn from(c: CreateConnector) -> Self {
12398        Self::CreateConnector(c)
12399    }
12400}
12401
12402impl From<CreateOperator> for Statement {
12403    fn from(c: CreateOperator) -> Self {
12404        Self::CreateOperator(c)
12405    }
12406}
12407
12408impl From<CreateOperatorFamily> for Statement {
12409    fn from(c: CreateOperatorFamily) -> Self {
12410        Self::CreateOperatorFamily(c)
12411    }
12412}
12413
12414impl From<CreateOperatorClass> for Statement {
12415    fn from(c: CreateOperatorClass) -> Self {
12416        Self::CreateOperatorClass(c)
12417    }
12418}
12419
12420impl From<AlterSchema> for Statement {
12421    fn from(a: AlterSchema) -> Self {
12422        Self::AlterSchema(a)
12423    }
12424}
12425
12426impl From<AlterFunction> for Statement {
12427    fn from(a: AlterFunction) -> Self {
12428        Self::AlterFunction(a)
12429    }
12430}
12431
12432impl From<AlterType> for Statement {
12433    fn from(a: AlterType) -> Self {
12434        Self::AlterType(a)
12435    }
12436}
12437
12438impl From<AlterCollation> for Statement {
12439    fn from(a: AlterCollation) -> Self {
12440        Self::AlterCollation(a)
12441    }
12442}
12443
12444impl From<AlterOperator> for Statement {
12445    fn from(a: AlterOperator) -> Self {
12446        Self::AlterOperator(a)
12447    }
12448}
12449
12450impl From<AlterOperatorFamily> for Statement {
12451    fn from(a: AlterOperatorFamily) -> Self {
12452        Self::AlterOperatorFamily(a)
12453    }
12454}
12455
12456impl From<AlterOperatorClass> for Statement {
12457    fn from(a: AlterOperatorClass) -> Self {
12458        Self::AlterOperatorClass(a)
12459    }
12460}
12461
12462impl From<Merge> for Statement {
12463    fn from(m: Merge) -> Self {
12464        Self::Merge(m)
12465    }
12466}
12467
12468impl From<AlterUser> for Statement {
12469    fn from(a: AlterUser) -> Self {
12470        Self::AlterUser(a)
12471    }
12472}
12473
12474impl From<DropDomain> for Statement {
12475    fn from(d: DropDomain) -> Self {
12476        Self::DropDomain(d)
12477    }
12478}
12479
12480impl From<ShowCharset> for Statement {
12481    fn from(s: ShowCharset) -> Self {
12482        Self::ShowCharset(s)
12483    }
12484}
12485
12486impl From<ShowObjects> for Statement {
12487    fn from(s: ShowObjects) -> Self {
12488        Self::ShowObjects(s)
12489    }
12490}
12491
12492impl From<Use> for Statement {
12493    fn from(u: Use) -> Self {
12494        Self::Use(u)
12495    }
12496}
12497
12498impl From<CreateFunction> for Statement {
12499    fn from(c: CreateFunction) -> Self {
12500        Self::CreateFunction(c)
12501    }
12502}
12503
12504impl From<CreateTrigger> for Statement {
12505    fn from(c: CreateTrigger) -> Self {
12506        Self::CreateTrigger(c)
12507    }
12508}
12509
12510impl From<DropTrigger> for Statement {
12511    fn from(d: DropTrigger) -> Self {
12512        Self::DropTrigger(d)
12513    }
12514}
12515
12516impl From<DropOperator> for Statement {
12517    fn from(d: DropOperator) -> Self {
12518        Self::DropOperator(d)
12519    }
12520}
12521
12522impl From<DropOperatorFamily> for Statement {
12523    fn from(d: DropOperatorFamily) -> Self {
12524        Self::DropOperatorFamily(d)
12525    }
12526}
12527
12528impl From<DropOperatorClass> for Statement {
12529    fn from(d: DropOperatorClass) -> Self {
12530        Self::DropOperatorClass(d)
12531    }
12532}
12533
12534impl From<DenyStatement> for Statement {
12535    fn from(d: DenyStatement) -> Self {
12536        Self::Deny(d)
12537    }
12538}
12539
12540impl From<CreateDomain> for Statement {
12541    fn from(c: CreateDomain) -> Self {
12542        Self::CreateDomain(c)
12543    }
12544}
12545
12546impl From<RenameTable> for Statement {
12547    fn from(r: RenameTable) -> Self {
12548        vec![r].into()
12549    }
12550}
12551
12552impl From<Vec<RenameTable>> for Statement {
12553    fn from(r: Vec<RenameTable>) -> Self {
12554        Self::RenameTable(r)
12555    }
12556}
12557
12558impl From<PrintStatement> for Statement {
12559    fn from(p: PrintStatement) -> Self {
12560        Self::Print(p)
12561    }
12562}
12563
12564impl From<ReturnStatement> for Statement {
12565    fn from(r: ReturnStatement) -> Self {
12566        Self::Return(r)
12567    }
12568}
12569
12570impl From<ExportData> for Statement {
12571    fn from(e: ExportData) -> Self {
12572        Self::ExportData(e)
12573    }
12574}
12575
12576impl From<CreateUser> for Statement {
12577    fn from(c: CreateUser) -> Self {
12578        Self::CreateUser(c)
12579    }
12580}
12581
12582impl From<VacuumStatement> for Statement {
12583    fn from(v: VacuumStatement) -> Self {
12584        Self::Vacuum(v)
12585    }
12586}
12587
12588impl From<ResetStatement> for Statement {
12589    fn from(r: ResetStatement) -> Self {
12590        Self::Reset(r)
12591    }
12592}
12593
12594#[cfg(test)]
12595mod tests {
12596    use crate::tokenizer::Location;
12597
12598    use super::*;
12599
12600    #[test]
12601    fn test_window_frame_default() {
12602        let window_frame = WindowFrame::default();
12603        assert_eq!(WindowFrameBound::Preceding(None), window_frame.start_bound);
12604    }
12605
12606    #[test]
12607    fn test_grouping_sets_display() {
12608        // a and b in different group
12609        let grouping_sets = Expr::GroupingSets(vec![
12610            vec![Expr::Identifier(Ident::new("a"))],
12611            vec![Expr::Identifier(Ident::new("b"))],
12612        ]);
12613        assert_eq!("GROUPING SETS ((a), (b))", format!("{grouping_sets}"));
12614
12615        // a and b in the same group
12616        let grouping_sets = Expr::GroupingSets(vec![vec![
12617            Expr::Identifier(Ident::new("a")),
12618            Expr::Identifier(Ident::new("b")),
12619        ]]);
12620        assert_eq!("GROUPING SETS ((a, b))", format!("{grouping_sets}"));
12621
12622        // (a, b) and (c, d) in different group
12623        let grouping_sets = Expr::GroupingSets(vec![
12624            vec![
12625                Expr::Identifier(Ident::new("a")),
12626                Expr::Identifier(Ident::new("b")),
12627            ],
12628            vec![
12629                Expr::Identifier(Ident::new("c")),
12630                Expr::Identifier(Ident::new("d")),
12631            ],
12632        ]);
12633        assert_eq!("GROUPING SETS ((a, b), (c, d))", format!("{grouping_sets}"));
12634    }
12635
12636    #[test]
12637    fn test_rollup_display() {
12638        let rollup = Expr::Rollup(vec![vec![Expr::Identifier(Ident::new("a"))]]);
12639        assert_eq!("ROLLUP (a)", format!("{rollup}"));
12640
12641        let rollup = Expr::Rollup(vec![vec![
12642            Expr::Identifier(Ident::new("a")),
12643            Expr::Identifier(Ident::new("b")),
12644        ]]);
12645        assert_eq!("ROLLUP ((a, b))", format!("{rollup}"));
12646
12647        let rollup = Expr::Rollup(vec![
12648            vec![Expr::Identifier(Ident::new("a"))],
12649            vec![Expr::Identifier(Ident::new("b"))],
12650        ]);
12651        assert_eq!("ROLLUP (a, b)", format!("{rollup}"));
12652
12653        let rollup = Expr::Rollup(vec![
12654            vec![Expr::Identifier(Ident::new("a"))],
12655            vec![
12656                Expr::Identifier(Ident::new("b")),
12657                Expr::Identifier(Ident::new("c")),
12658            ],
12659            vec![Expr::Identifier(Ident::new("d"))],
12660        ]);
12661        assert_eq!("ROLLUP (a, (b, c), d)", format!("{rollup}"));
12662    }
12663
12664    #[test]
12665    fn test_cube_display() {
12666        let cube = Expr::Cube(vec![vec![Expr::Identifier(Ident::new("a"))]]);
12667        assert_eq!("CUBE (a)", format!("{cube}"));
12668
12669        let cube = Expr::Cube(vec![vec![
12670            Expr::Identifier(Ident::new("a")),
12671            Expr::Identifier(Ident::new("b")),
12672        ]]);
12673        assert_eq!("CUBE ((a, b))", format!("{cube}"));
12674
12675        let cube = Expr::Cube(vec![
12676            vec![Expr::Identifier(Ident::new("a"))],
12677            vec![Expr::Identifier(Ident::new("b"))],
12678        ]);
12679        assert_eq!("CUBE (a, b)", format!("{cube}"));
12680
12681        let cube = Expr::Cube(vec![
12682            vec![Expr::Identifier(Ident::new("a"))],
12683            vec![
12684                Expr::Identifier(Ident::new("b")),
12685                Expr::Identifier(Ident::new("c")),
12686            ],
12687            vec![Expr::Identifier(Ident::new("d"))],
12688        ]);
12689        assert_eq!("CUBE (a, (b, c), d)", format!("{cube}"));
12690    }
12691
12692    #[test]
12693    fn test_interval_display() {
12694        let interval = Expr::Interval(Interval {
12695            value: Box::new(Expr::Value(
12696                Value::SingleQuotedString(String::from("123:45.67")).with_empty_span(),
12697            )),
12698            leading_field: Some(DateTimeField::Minute),
12699            leading_precision: Some(10),
12700            last_field: Some(DateTimeField::Second),
12701            fractional_seconds_precision: Some(9),
12702        });
12703        assert_eq!(
12704            "INTERVAL '123:45.67' MINUTE (10) TO SECOND (9)",
12705            format!("{interval}"),
12706        );
12707
12708        let interval = Expr::Interval(Interval {
12709            value: Box::new(Expr::Value(
12710                Value::SingleQuotedString(String::from("5")).with_empty_span(),
12711            )),
12712            leading_field: Some(DateTimeField::Second),
12713            leading_precision: Some(1),
12714            last_field: None,
12715            fractional_seconds_precision: Some(3),
12716        });
12717        assert_eq!("INTERVAL '5' SECOND (1, 3)", format!("{interval}"));
12718    }
12719
12720    #[test]
12721    fn test_one_or_many_with_parens_deref() {
12722        use core::ops::Index;
12723
12724        let one = OneOrManyWithParens::One("a");
12725
12726        assert_eq!(one.deref(), &["a"]);
12727        assert_eq!(<OneOrManyWithParens<_> as Deref>::deref(&one), &["a"]);
12728
12729        assert_eq!(one[0], "a");
12730        assert_eq!(one.index(0), &"a");
12731        assert_eq!(
12732            <<OneOrManyWithParens<_> as Deref>::Target as Index<usize>>::index(&one, 0),
12733            &"a"
12734        );
12735
12736        assert_eq!(one.len(), 1);
12737        assert_eq!(<OneOrManyWithParens<_> as Deref>::Target::len(&one), 1);
12738
12739        let many1 = OneOrManyWithParens::Many(vec!["b"]);
12740
12741        assert_eq!(many1.deref(), &["b"]);
12742        assert_eq!(<OneOrManyWithParens<_> as Deref>::deref(&many1), &["b"]);
12743
12744        assert_eq!(many1[0], "b");
12745        assert_eq!(many1.index(0), &"b");
12746        assert_eq!(
12747            <<OneOrManyWithParens<_> as Deref>::Target as Index<usize>>::index(&many1, 0),
12748            &"b"
12749        );
12750
12751        assert_eq!(many1.len(), 1);
12752        assert_eq!(<OneOrManyWithParens<_> as Deref>::Target::len(&many1), 1);
12753
12754        let many2 = OneOrManyWithParens::Many(vec!["c", "d"]);
12755
12756        assert_eq!(many2.deref(), &["c", "d"]);
12757        assert_eq!(
12758            <OneOrManyWithParens<_> as Deref>::deref(&many2),
12759            &["c", "d"]
12760        );
12761
12762        assert_eq!(many2[0], "c");
12763        assert_eq!(many2.index(0), &"c");
12764        assert_eq!(
12765            <<OneOrManyWithParens<_> as Deref>::Target as Index<usize>>::index(&many2, 0),
12766            &"c"
12767        );
12768
12769        assert_eq!(many2[1], "d");
12770        assert_eq!(many2.index(1), &"d");
12771        assert_eq!(
12772            <<OneOrManyWithParens<_> as Deref>::Target as Index<usize>>::index(&many2, 1),
12773            &"d"
12774        );
12775
12776        assert_eq!(many2.len(), 2);
12777        assert_eq!(<OneOrManyWithParens<_> as Deref>::Target::len(&many2), 2);
12778    }
12779
12780    #[test]
12781    fn test_one_or_many_with_parens_as_ref() {
12782        let one = OneOrManyWithParens::One("a");
12783
12784        assert_eq!(one.as_ref(), &["a"]);
12785        assert_eq!(<OneOrManyWithParens<_> as AsRef<_>>::as_ref(&one), &["a"]);
12786
12787        let many1 = OneOrManyWithParens::Many(vec!["b"]);
12788
12789        assert_eq!(many1.as_ref(), &["b"]);
12790        assert_eq!(<OneOrManyWithParens<_> as AsRef<_>>::as_ref(&many1), &["b"]);
12791
12792        let many2 = OneOrManyWithParens::Many(vec!["c", "d"]);
12793
12794        assert_eq!(many2.as_ref(), &["c", "d"]);
12795        assert_eq!(
12796            <OneOrManyWithParens<_> as AsRef<_>>::as_ref(&many2),
12797            &["c", "d"]
12798        );
12799    }
12800
12801    #[test]
12802    fn test_one_or_many_with_parens_ref_into_iter() {
12803        let one = OneOrManyWithParens::One("a");
12804
12805        assert_eq!(Vec::from_iter(&one), vec![&"a"]);
12806
12807        let many1 = OneOrManyWithParens::Many(vec!["b"]);
12808
12809        assert_eq!(Vec::from_iter(&many1), vec![&"b"]);
12810
12811        let many2 = OneOrManyWithParens::Many(vec!["c", "d"]);
12812
12813        assert_eq!(Vec::from_iter(&many2), vec![&"c", &"d"]);
12814    }
12815
12816    #[test]
12817    fn test_one_or_many_with_parens_value_into_iter() {
12818        use core::iter::once;
12819
12820        //tests that our iterator implemented methods behaves exactly as it's inner iterator, at every step up to n calls to next/next_back
12821        fn test_steps<I>(ours: OneOrManyWithParens<usize>, inner: I, n: usize)
12822        where
12823            I: IntoIterator<Item = usize, IntoIter: DoubleEndedIterator + Clone> + Clone,
12824        {
12825            fn checks<I>(ours: OneOrManyWithParensIntoIter<usize>, inner: I)
12826            where
12827                I: Iterator<Item = usize> + Clone + DoubleEndedIterator,
12828            {
12829                assert_eq!(ours.size_hint(), inner.size_hint());
12830                assert_eq!(ours.clone().count(), inner.clone().count());
12831
12832                assert_eq!(
12833                    ours.clone().fold(1, |a, v| a + v),
12834                    inner.clone().fold(1, |a, v| a + v)
12835                );
12836
12837                assert_eq!(Vec::from_iter(ours.clone()), Vec::from_iter(inner.clone()));
12838                assert_eq!(
12839                    Vec::from_iter(ours.clone().rev()),
12840                    Vec::from_iter(inner.clone().rev())
12841                );
12842            }
12843
12844            let mut ours_next = ours.clone().into_iter();
12845            let mut inner_next = inner.clone().into_iter();
12846
12847            for _ in 0..n {
12848                checks(ours_next.clone(), inner_next.clone());
12849
12850                assert_eq!(ours_next.next(), inner_next.next());
12851            }
12852
12853            let mut ours_next_back = ours.clone().into_iter();
12854            let mut inner_next_back = inner.clone().into_iter();
12855
12856            for _ in 0..n {
12857                checks(ours_next_back.clone(), inner_next_back.clone());
12858
12859                assert_eq!(ours_next_back.next_back(), inner_next_back.next_back());
12860            }
12861
12862            let mut ours_mixed = ours.clone().into_iter();
12863            let mut inner_mixed = inner.clone().into_iter();
12864
12865            for i in 0..n {
12866                checks(ours_mixed.clone(), inner_mixed.clone());
12867
12868                if i % 2 == 0 {
12869                    assert_eq!(ours_mixed.next_back(), inner_mixed.next_back());
12870                } else {
12871                    assert_eq!(ours_mixed.next(), inner_mixed.next());
12872                }
12873            }
12874
12875            let mut ours_mixed2 = ours.into_iter();
12876            let mut inner_mixed2 = inner.into_iter();
12877
12878            for i in 0..n {
12879                checks(ours_mixed2.clone(), inner_mixed2.clone());
12880
12881                if i % 2 == 0 {
12882                    assert_eq!(ours_mixed2.next(), inner_mixed2.next());
12883                } else {
12884                    assert_eq!(ours_mixed2.next_back(), inner_mixed2.next_back());
12885                }
12886            }
12887        }
12888
12889        test_steps(OneOrManyWithParens::One(1), once(1), 3);
12890        test_steps(OneOrManyWithParens::Many(vec![2]), vec![2], 3);
12891        test_steps(OneOrManyWithParens::Many(vec![3, 4]), vec![3, 4], 4);
12892    }
12893
12894    // Tests that the position in the code of an `Ident` does not affect its
12895    // ordering.
12896    #[test]
12897    fn test_ident_ord() {
12898        let mut a = Ident::with_span(Span::new(Location::new(1, 1), Location::new(1, 1)), "a");
12899        let mut b = Ident::with_span(Span::new(Location::new(2, 2), Location::new(2, 2)), "b");
12900
12901        assert!(a < b);
12902        std::mem::swap(&mut a.span, &mut b.span);
12903        assert!(a < b);
12904    }
12905}