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 fmt::Display for CommentObject {
2505    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2506        match self {
2507            CommentObject::Aggregate => f.write_str("AGGREGATE"),
2508            CommentObject::Collation => f.write_str("COLLATION"),
2509            CommentObject::Column => f.write_str("COLUMN"),
2510            CommentObject::Database => f.write_str("DATABASE"),
2511            CommentObject::Domain => f.write_str("DOMAIN"),
2512            CommentObject::Extension => f.write_str("EXTENSION"),
2513            CommentObject::Function => f.write_str("FUNCTION"),
2514            CommentObject::Index => f.write_str("INDEX"),
2515            CommentObject::MaterializedView => f.write_str("MATERIALIZED VIEW"),
2516            CommentObject::Policy => f.write_str("POLICY"),
2517            CommentObject::Procedure => f.write_str("PROCEDURE"),
2518            CommentObject::Role => f.write_str("ROLE"),
2519            CommentObject::Schema => f.write_str("SCHEMA"),
2520            CommentObject::Sequence => f.write_str("SEQUENCE"),
2521            CommentObject::Table => f.write_str("TABLE"),
2522            CommentObject::Trigger => f.write_str("TRIGGER"),
2523            CommentObject::Type => f.write_str("TYPE"),
2524            CommentObject::User => f.write_str("USER"),
2525            CommentObject::View => f.write_str("VIEW"),
2526        }
2527    }
2528}
2529
2530#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2531#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2532#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2533/// Password specification variants used in user-related statements.
2534pub enum Password {
2535    /// A concrete password expression.
2536    Password(Expr),
2537    /// Represents a `NULL` password.
2538    NullPassword,
2539}
2540
2541/// A `CASE` statement.
2542///
2543/// Examples:
2544/// ```sql
2545/// CASE
2546///     WHEN EXISTS(SELECT 1)
2547///         THEN SELECT 1 FROM T;
2548///     WHEN EXISTS(SELECT 2)
2549///         THEN SELECT 1 FROM U;
2550///     ELSE
2551///         SELECT 1 FROM V;
2552/// END CASE;
2553/// ```
2554///
2555/// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#case_search_expression)
2556/// [Snowflake](https://docs.snowflake.com/en/sql-reference/snowflake-scripting/case)
2557#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2558#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2559#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2560pub struct CaseStatement {
2561    /// The `CASE` token that starts the statement.
2562    pub case_token: AttachedToken,
2563    /// Optional expression to match against in `CASE ... WHEN`.
2564    pub match_expr: Option<Expr>,
2565    /// The `WHEN ... THEN` blocks of the `CASE` statement.
2566    pub when_blocks: Vec<ConditionalStatementBlock>,
2567    /// Optional `ELSE` block for the `CASE` statement.
2568    pub else_block: Option<ConditionalStatementBlock>,
2569    /// The last token of the statement (`END` or `CASE`).
2570    pub end_case_token: AttachedToken,
2571}
2572
2573impl fmt::Display for CaseStatement {
2574    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2575        let CaseStatement {
2576            case_token: _,
2577            match_expr,
2578            when_blocks,
2579            else_block,
2580            end_case_token: AttachedToken(end),
2581        } = self;
2582
2583        write!(f, "CASE")?;
2584
2585        if let Some(expr) = match_expr {
2586            write!(f, " {expr}")?;
2587        }
2588
2589        if !when_blocks.is_empty() {
2590            write!(f, " {}", display_separated(when_blocks, " "))?;
2591        }
2592
2593        if let Some(else_block) = else_block {
2594            write!(f, " {else_block}")?;
2595        }
2596
2597        write!(f, " END")?;
2598
2599        if let Token::Word(w) = &end.token {
2600            if w.keyword == Keyword::CASE {
2601                write!(f, " CASE")?;
2602            }
2603        }
2604
2605        Ok(())
2606    }
2607}
2608
2609/// An `IF` statement.
2610///
2611/// Example (BigQuery or Snowflake):
2612/// ```sql
2613/// IF TRUE THEN
2614///     SELECT 1;
2615///     SELECT 2;
2616/// ELSEIF TRUE THEN
2617///     SELECT 3;
2618/// ELSE
2619///     SELECT 4;
2620/// END IF
2621/// ```
2622/// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#if)
2623/// [Snowflake](https://docs.snowflake.com/en/sql-reference/snowflake-scripting/if)
2624///
2625/// Example (MSSQL):
2626/// ```sql
2627/// IF 1=1 SELECT 1 ELSE SELECT 2
2628/// ```
2629/// [MSSQL](https://learn.microsoft.com/en-us/sql/t-sql/language-elements/if-else-transact-sql?view=sql-server-ver16)
2630#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2631#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2632#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2633pub struct IfStatement {
2634    /// The initial `IF` block containing the condition and statements.
2635    pub if_block: ConditionalStatementBlock,
2636    /// Additional `ELSEIF` blocks.
2637    pub elseif_blocks: Vec<ConditionalStatementBlock>,
2638    /// Optional `ELSE` block.
2639    pub else_block: Option<ConditionalStatementBlock>,
2640    /// Optional trailing `END` token for the `IF` statement.
2641    pub end_token: Option<AttachedToken>,
2642}
2643
2644impl fmt::Display for IfStatement {
2645    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2646        let IfStatement {
2647            if_block,
2648            elseif_blocks,
2649            else_block,
2650            end_token,
2651        } = self;
2652
2653        write!(f, "{if_block}")?;
2654
2655        for elseif_block in elseif_blocks {
2656            write!(f, " {elseif_block}")?;
2657        }
2658
2659        if let Some(else_block) = else_block {
2660            write!(f, " {else_block}")?;
2661        }
2662
2663        if let Some(AttachedToken(end_token)) = end_token {
2664            write!(f, " END {end_token}")?;
2665        }
2666
2667        Ok(())
2668    }
2669}
2670
2671/// A `WHILE` statement.
2672///
2673/// Example:
2674/// ```sql
2675/// WHILE @@FETCH_STATUS = 0
2676/// BEGIN
2677///    FETCH NEXT FROM c1 INTO @var1, @var2;
2678/// END
2679/// ```
2680///
2681/// [MsSql](https://learn.microsoft.com/en-us/sql/t-sql/language-elements/while-transact-sql)
2682#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2683#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2684#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2685pub struct WhileStatement {
2686    /// Block executed while the condition holds.
2687    pub while_block: ConditionalStatementBlock,
2688}
2689
2690impl fmt::Display for WhileStatement {
2691    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2692        let WhileStatement { while_block } = self;
2693        write!(f, "{while_block}")?;
2694        Ok(())
2695    }
2696}
2697
2698/// A block within a [Statement::Case] or [Statement::If] or [Statement::While]-like statement
2699///
2700/// Example 1:
2701/// ```sql
2702/// WHEN EXISTS(SELECT 1) THEN SELECT 1;
2703/// ```
2704///
2705/// Example 2:
2706/// ```sql
2707/// IF TRUE THEN SELECT 1; SELECT 2;
2708/// ```
2709///
2710/// Example 3:
2711/// ```sql
2712/// ELSE SELECT 1; SELECT 2;
2713/// ```
2714///
2715/// Example 4:
2716/// ```sql
2717/// WHILE @@FETCH_STATUS = 0
2718/// BEGIN
2719///    FETCH NEXT FROM c1 INTO @var1, @var2;
2720/// END
2721/// ```
2722#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2723#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2724#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2725pub struct ConditionalStatementBlock {
2726    /// Token representing the start of the block (e.g., WHEN/IF/WHILE).
2727    pub start_token: AttachedToken,
2728    /// Optional condition expression for the block.
2729    pub condition: Option<Expr>,
2730    /// Optional token for the `THEN` keyword.
2731    pub then_token: Option<AttachedToken>,
2732    /// The statements contained in this conditional block.
2733    pub conditional_statements: ConditionalStatements,
2734}
2735
2736impl ConditionalStatementBlock {
2737    /// Get the statements in this conditional block.
2738    pub fn statements(&self) -> &Vec<Statement> {
2739        self.conditional_statements.statements()
2740    }
2741}
2742
2743impl fmt::Display for ConditionalStatementBlock {
2744    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2745        let ConditionalStatementBlock {
2746            start_token: AttachedToken(start_token),
2747            condition,
2748            then_token,
2749            conditional_statements,
2750        } = self;
2751
2752        write!(f, "{start_token}")?;
2753
2754        if let Some(condition) = condition {
2755            write!(f, " {condition}")?;
2756        }
2757
2758        if then_token.is_some() {
2759            write!(f, " THEN")?;
2760        }
2761
2762        if !conditional_statements.statements().is_empty() {
2763            write!(f, " {conditional_statements}")?;
2764        }
2765
2766        Ok(())
2767    }
2768}
2769
2770/// A list of statements in a [ConditionalStatementBlock].
2771#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2772#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2773#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2774/// Statements used inside conditional blocks (`IF`, `WHEN`, `WHILE`).
2775pub enum ConditionalStatements {
2776    /// Simple sequence of statements (no `BEGIN`/`END`).
2777    Sequence {
2778        /// The statements in the sequence.
2779        statements: Vec<Statement>,
2780    },
2781    /// Block enclosed by `BEGIN` and `END`.
2782    BeginEnd(BeginEndStatements),
2783}
2784
2785impl ConditionalStatements {
2786    /// Get the statements in this conditional statements block.
2787    pub fn statements(&self) -> &Vec<Statement> {
2788        match self {
2789            ConditionalStatements::Sequence { statements } => statements,
2790            ConditionalStatements::BeginEnd(bes) => &bes.statements,
2791        }
2792    }
2793}
2794
2795impl fmt::Display for ConditionalStatements {
2796    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2797        match self {
2798            ConditionalStatements::Sequence { statements } => {
2799                if !statements.is_empty() {
2800                    format_statement_list(f, statements)?;
2801                }
2802                Ok(())
2803            }
2804            ConditionalStatements::BeginEnd(bes) => write!(f, "{bes}"),
2805        }
2806    }
2807}
2808
2809/// Represents a list of statements enclosed within `BEGIN` and `END` keywords.
2810/// Example:
2811/// ```sql
2812/// BEGIN
2813///     SELECT 1;
2814///     SELECT 2;
2815/// END
2816/// ```
2817#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2818#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2819#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2820pub struct BeginEndStatements {
2821    /// Token representing the `BEGIN` keyword (may include span info).
2822    pub begin_token: AttachedToken,
2823    /// Statements contained within the block.
2824    pub statements: Vec<Statement>,
2825    /// Token representing the `END` keyword (may include span info).
2826    pub end_token: AttachedToken,
2827}
2828
2829impl fmt::Display for BeginEndStatements {
2830    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2831        let BeginEndStatements {
2832            begin_token: AttachedToken(begin_token),
2833            statements,
2834            end_token: AttachedToken(end_token),
2835        } = self;
2836
2837        if begin_token.token != Token::EOF {
2838            write!(f, "{begin_token} ")?;
2839        }
2840        if !statements.is_empty() {
2841            format_statement_list(f, statements)?;
2842        }
2843        if end_token.token != Token::EOF {
2844            write!(f, " {end_token}")?;
2845        }
2846        Ok(())
2847    }
2848}
2849
2850/// A `RAISE` statement.
2851///
2852/// Examples:
2853/// ```sql
2854/// RAISE USING MESSAGE = 'error';
2855///
2856/// RAISE myerror;
2857/// ```
2858///
2859/// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#raise)
2860/// [Snowflake](https://docs.snowflake.com/en/sql-reference/snowflake-scripting/raise)
2861#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2862#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2863#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2864pub struct RaiseStatement {
2865    /// Optional value provided to the RAISE statement.
2866    pub value: Option<RaiseStatementValue>,
2867}
2868
2869impl fmt::Display for RaiseStatement {
2870    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2871        let RaiseStatement { value } = self;
2872
2873        write!(f, "RAISE")?;
2874        if let Some(value) = value {
2875            write!(f, " {value}")?;
2876        }
2877
2878        Ok(())
2879    }
2880}
2881
2882/// Represents the error value of a [RaiseStatement].
2883#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2884#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2885#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2886pub enum RaiseStatementValue {
2887    /// `RAISE USING MESSAGE = 'error'`
2888    UsingMessage(Expr),
2889    /// `RAISE myerror`
2890    Expr(Expr),
2891}
2892
2893impl fmt::Display for RaiseStatementValue {
2894    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2895        match self {
2896            RaiseStatementValue::Expr(expr) => write!(f, "{expr}"),
2897            RaiseStatementValue::UsingMessage(expr) => write!(f, "USING MESSAGE = {expr}"),
2898        }
2899    }
2900}
2901
2902/// A MSSQL `THROW` statement.
2903///
2904/// ```sql
2905/// THROW [ error_number, message, state ]
2906/// ```
2907///
2908/// [MSSQL](https://learn.microsoft.com/en-us/sql/t-sql/language-elements/throw-transact-sql)
2909#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2910#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2911#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2912pub struct ThrowStatement {
2913    /// Error number expression.
2914    pub error_number: Option<Box<Expr>>,
2915    /// Error message expression.
2916    pub message: Option<Box<Expr>>,
2917    /// State expression.
2918    pub state: Option<Box<Expr>>,
2919}
2920
2921impl fmt::Display for ThrowStatement {
2922    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2923        let ThrowStatement {
2924            error_number,
2925            message,
2926            state,
2927        } = self;
2928
2929        write!(f, "THROW")?;
2930        if let (Some(error_number), Some(message), Some(state)) = (error_number, message, state) {
2931            write!(f, " {error_number}, {message}, {state}")?;
2932        }
2933        Ok(())
2934    }
2935}
2936
2937/// Represents an expression assignment within a variable `DECLARE` statement.
2938///
2939/// Examples:
2940/// ```sql
2941/// DECLARE variable_name := 42
2942/// DECLARE variable_name DEFAULT 42
2943/// ```
2944#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2945#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2946#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2947pub enum DeclareAssignment {
2948    /// Plain expression specified.
2949    Expr(Box<Expr>),
2950
2951    /// Expression assigned via the `DEFAULT` keyword
2952    Default(Box<Expr>),
2953
2954    /// Expression assigned via the `:=` syntax
2955    ///
2956    /// Example:
2957    /// ```sql
2958    /// DECLARE variable_name := 42;
2959    /// ```
2960    DuckAssignment(Box<Expr>),
2961
2962    /// Expression via the `FOR` keyword
2963    ///
2964    /// Example:
2965    /// ```sql
2966    /// DECLARE c1 CURSOR FOR res
2967    /// ```
2968    For(Box<Expr>),
2969
2970    /// Expression via the `=` syntax.
2971    ///
2972    /// Example:
2973    /// ```sql
2974    /// DECLARE @variable AS INT = 100
2975    /// ```
2976    MsSqlAssignment(Box<Expr>),
2977}
2978
2979impl fmt::Display for DeclareAssignment {
2980    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2981        match self {
2982            DeclareAssignment::Expr(expr) => {
2983                write!(f, "{expr}")
2984            }
2985            DeclareAssignment::Default(expr) => {
2986                write!(f, "DEFAULT {expr}")
2987            }
2988            DeclareAssignment::DuckAssignment(expr) => {
2989                write!(f, ":= {expr}")
2990            }
2991            DeclareAssignment::MsSqlAssignment(expr) => {
2992                write!(f, "= {expr}")
2993            }
2994            DeclareAssignment::For(expr) => {
2995                write!(f, "FOR {expr}")
2996            }
2997        }
2998    }
2999}
3000
3001/// Represents the type of a `DECLARE` statement.
3002#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3003#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3004#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3005pub enum DeclareType {
3006    /// Cursor variable type. e.g. [Snowflake] [PostgreSQL] [MsSql]
3007    ///
3008    /// [Snowflake]: https://docs.snowflake.com/en/developer-guide/snowflake-scripting/cursors#declaring-a-cursor
3009    /// [PostgreSQL]: https://www.postgresql.org/docs/current/plpgsql-cursors.html
3010    /// [MsSql]: https://learn.microsoft.com/en-us/sql/t-sql/language-elements/declare-cursor-transact-sql
3011    Cursor,
3012
3013    /// Result set variable type. [Snowflake]
3014    ///
3015    /// Syntax:
3016    /// ```text
3017    /// <resultset_name> RESULTSET [ { DEFAULT | := } ( <query> ) ] ;
3018    /// ```
3019    /// [Snowflake]: https://docs.snowflake.com/en/sql-reference/snowflake-scripting/declare#resultset-declaration-syntax
3020    ResultSet,
3021
3022    /// Exception declaration syntax. [Snowflake]
3023    ///
3024    /// Syntax:
3025    /// ```text
3026    /// <exception_name> EXCEPTION [ ( <exception_number> , '<exception_message>' ) ] ;
3027    /// ```
3028    /// [Snowflake]: https://docs.snowflake.com/en/sql-reference/snowflake-scripting/declare#exception-declaration-syntax
3029    Exception,
3030}
3031
3032impl fmt::Display for DeclareType {
3033    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3034        match self {
3035            DeclareType::Cursor => {
3036                write!(f, "CURSOR")
3037            }
3038            DeclareType::ResultSet => {
3039                write!(f, "RESULTSET")
3040            }
3041            DeclareType::Exception => {
3042                write!(f, "EXCEPTION")
3043            }
3044        }
3045    }
3046}
3047
3048/// A `DECLARE` statement.
3049/// [PostgreSQL] [Snowflake] [BigQuery]
3050///
3051/// Examples:
3052/// ```sql
3053/// DECLARE variable_name := 42
3054/// DECLARE liahona CURSOR FOR SELECT * FROM films;
3055/// ```
3056///
3057/// [PostgreSQL]: https://www.postgresql.org/docs/current/sql-declare.html
3058/// [Snowflake]: https://docs.snowflake.com/en/sql-reference/snowflake-scripting/declare
3059/// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#declare
3060#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3061#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3062#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3063pub struct Declare {
3064    /// The name(s) being declared.
3065    /// Example: `DECLARE a, b, c DEFAULT 42;
3066    pub names: Vec<Ident>,
3067    /// Data-type assigned to the declared variable.
3068    /// Example: `DECLARE x INT64 DEFAULT 42;
3069    pub data_type: Option<DataType>,
3070    /// Expression being assigned to the declared variable.
3071    pub assignment: Option<DeclareAssignment>,
3072    /// Represents the type of the declared variable.
3073    pub declare_type: Option<DeclareType>,
3074    /// Causes the cursor to return data in binary rather than in text format.
3075    pub binary: Option<bool>,
3076    /// None = Not specified
3077    /// Some(true) = INSENSITIVE
3078    /// Some(false) = ASENSITIVE
3079    pub sensitive: Option<bool>,
3080    /// None = Not specified
3081    /// Some(true) = SCROLL
3082    /// Some(false) = NO SCROLL
3083    pub scroll: Option<bool>,
3084    /// None = Not specified
3085    /// Some(true) = WITH HOLD, specifies that the cursor can continue to be used after the transaction that created it successfully commits
3086    /// Some(false) = WITHOUT HOLD, specifies that the cursor cannot be used outside of the transaction that created it
3087    pub hold: Option<bool>,
3088    /// `FOR <query>` clause in a CURSOR declaration.
3089    pub for_query: Option<Box<Query>>,
3090}
3091
3092impl fmt::Display for Declare {
3093    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3094        let Declare {
3095            names,
3096            data_type,
3097            assignment,
3098            declare_type,
3099            binary,
3100            sensitive,
3101            scroll,
3102            hold,
3103            for_query,
3104        } = self;
3105        write!(f, "{}", display_comma_separated(names))?;
3106
3107        if let Some(true) = binary {
3108            write!(f, " BINARY")?;
3109        }
3110
3111        if let Some(sensitive) = sensitive {
3112            if *sensitive {
3113                write!(f, " INSENSITIVE")?;
3114            } else {
3115                write!(f, " ASENSITIVE")?;
3116            }
3117        }
3118
3119        if let Some(scroll) = scroll {
3120            if *scroll {
3121                write!(f, " SCROLL")?;
3122            } else {
3123                write!(f, " NO SCROLL")?;
3124            }
3125        }
3126
3127        if let Some(declare_type) = declare_type {
3128            write!(f, " {declare_type}")?;
3129        }
3130
3131        if let Some(hold) = hold {
3132            if *hold {
3133                write!(f, " WITH HOLD")?;
3134            } else {
3135                write!(f, " WITHOUT HOLD")?;
3136            }
3137        }
3138
3139        if let Some(query) = for_query {
3140            write!(f, " FOR {query}")?;
3141        }
3142
3143        if let Some(data_type) = data_type {
3144            write!(f, " {data_type}")?;
3145        }
3146
3147        if let Some(expr) = assignment {
3148            write!(f, " {expr}")?;
3149        }
3150        Ok(())
3151    }
3152}
3153
3154/// Sql options of a `CREATE TABLE` statement.
3155#[derive(Debug, Default, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3156#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3157#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3158/// Options allowed within a `CREATE TABLE` statement.
3159pub enum CreateTableOptions {
3160    /// No options specified.
3161    #[default]
3162    None,
3163    /// Options specified using the `WITH` keyword, e.g. `WITH (k = v)`.
3164    With(Vec<SqlOption>),
3165    /// Options specified using the `OPTIONS(...)` clause.
3166    Options(Vec<SqlOption>),
3167    /// Plain space-separated options.
3168    Plain(Vec<SqlOption>),
3169    /// Table properties (e.g., TBLPROPERTIES / storage properties).
3170    TableProperties(Vec<SqlOption>),
3171}
3172
3173impl fmt::Display for CreateTableOptions {
3174    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3175        match self {
3176            CreateTableOptions::With(with_options) => {
3177                write!(f, "WITH ({})", display_comma_separated(with_options))
3178            }
3179            CreateTableOptions::Options(options) => {
3180                write!(f, "OPTIONS({})", display_comma_separated(options))
3181            }
3182            CreateTableOptions::TableProperties(options) => {
3183                write!(f, "TBLPROPERTIES ({})", display_comma_separated(options))
3184            }
3185            CreateTableOptions::Plain(options) => {
3186                write!(f, "{}", display_separated(options, " "))
3187            }
3188            CreateTableOptions::None => Ok(()),
3189        }
3190    }
3191}
3192
3193/// A `FROM` clause within a `DELETE` statement.
3194///
3195/// Syntax
3196/// ```sql
3197/// [FROM] table
3198/// ```
3199#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3200#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3201#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3202pub enum FromTable {
3203    /// An explicit `FROM` keyword was specified.
3204    WithFromKeyword(Vec<TableWithJoins>),
3205    /// BigQuery: `FROM` keyword was omitted.
3206    /// <https://cloud.google.com/bigquery/docs/reference/standard-sql/dml-syntax#delete_statement>
3207    WithoutKeyword(Vec<TableWithJoins>),
3208}
3209impl Display for FromTable {
3210    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3211        match self {
3212            FromTable::WithFromKeyword(tables) => {
3213                write!(f, "FROM {}", display_comma_separated(tables))
3214            }
3215            FromTable::WithoutKeyword(tables) => {
3216                write!(f, "{}", display_comma_separated(tables))
3217            }
3218        }
3219    }
3220}
3221
3222#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3223#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3224#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3225/// Variants for the `SET` family of statements.
3226pub enum Set {
3227    /// SQL Standard-style
3228    /// SET a = 1;
3229    /// `SET var = value` (standard SQL-style assignment).
3230    SingleAssignment {
3231        /// Optional scope modifier (`SESSION` / `LOCAL`).
3232        scope: Option<ContextModifier>,
3233        /// Whether this is a Hive-style `HIVEVAR:` assignment.
3234        hivevar: bool,
3235        /// Variable name to assign.
3236        variable: ObjectName,
3237        /// Values assigned to the variable.
3238        values: Vec<Expr>,
3239    },
3240    /// Snowflake-style
3241    /// SET (a, b, ..) = (1, 2, ..);
3242    /// `SET (a, b) = (1, 2)` (tuple assignment syntax).
3243    ParenthesizedAssignments {
3244        /// Variables being assigned in tuple form.
3245        variables: Vec<ObjectName>,
3246        /// Corresponding values for the variables.
3247        values: Vec<Expr>,
3248    },
3249    /// MySQL-style
3250    /// SET a = 1, b = 2, ..;
3251    /// `SET a = 1, b = 2` (MySQL-style comma-separated assignments).
3252    MultipleAssignments {
3253        /// List of `SET` assignments (MySQL-style comma-separated).
3254        assignments: Vec<SetAssignment>,
3255    },
3256    /// Session authorization for Postgres/Redshift
3257    ///
3258    /// ```sql
3259    /// SET SESSION AUTHORIZATION { user_name | DEFAULT }
3260    /// ```
3261    ///
3262    /// See <https://www.postgresql.org/docs/current/sql-set-session-authorization.html>
3263    /// See <https://docs.aws.amazon.com/redshift/latest/dg/r_SET_SESSION_AUTHORIZATION.html>
3264    SetSessionAuthorization(SetSessionAuthorizationParam),
3265    /// MS-SQL session
3266    ///
3267    /// See <https://learn.microsoft.com/en-us/sql/t-sql/statements/set-statements-transact-sql>
3268    SetSessionParam(SetSessionParamKind),
3269    /// ```sql
3270    /// SET [ SESSION | LOCAL ] ROLE role_name
3271    /// ```
3272    ///
3273    /// Sets session state. Examples: [ANSI][1], [Postgresql][2], [MySQL][3], and [Oracle][4]
3274    ///
3275    /// [1]: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#set-role-statement
3276    /// [2]: https://www.postgresql.org/docs/14/sql-set-role.html
3277    /// [3]: https://dev.mysql.com/doc/refman/8.0/en/set-role.html
3278    /// [4]: https://docs.oracle.com/cd/B19306_01/server.102/b14200/statements_10004.htm
3279    SetRole {
3280        /// Non-ANSI optional identifier to inform if the role is defined inside the current session (`SESSION`) or transaction (`LOCAL`).
3281        context_modifier: Option<ContextModifier>,
3282        /// Role name. If NONE is specified, then the current role name is removed.
3283        role_name: Option<Ident>,
3284    },
3285    /// ```sql
3286    /// SET TIME ZONE <value>
3287    /// ```
3288    ///
3289    /// Note: this is a PostgreSQL-specific statements
3290    /// `SET TIME ZONE <value>` is an alias for `SET timezone TO <value>` in PostgreSQL
3291    /// However, we allow it for all dialects.
3292    /// `SET TIME ZONE` statement. `local` indicates the `LOCAL` keyword.
3293    /// `SET TIME ZONE <value>` statement.
3294    SetTimeZone {
3295        /// Whether the `LOCAL` keyword was specified.
3296        local: bool,
3297        /// Time zone expression value.
3298        value: Expr,
3299    },
3300    /// ```sql
3301    /// SET NAMES 'charset_name' [COLLATE 'collation_name']
3302    /// ```
3303    SetNames {
3304        /// Character set name to set.
3305        charset_name: Ident,
3306        /// Optional collation name.
3307        collation_name: Option<String>,
3308    },
3309    /// ```sql
3310    /// SET NAMES DEFAULT
3311    /// ```
3312    ///
3313    /// Note: this is a MySQL-specific statement.
3314    SetNamesDefault {},
3315    /// ```sql
3316    /// SET TRANSACTION ...
3317    /// ```
3318    SetTransaction {
3319        /// Transaction modes (e.g., ISOLATION LEVEL, READ ONLY).
3320        modes: Vec<TransactionMode>,
3321        /// Optional snapshot value for transaction snapshot control.
3322        snapshot: Option<ValueWithSpan>,
3323        /// `true` when the `SESSION` keyword was used.
3324        session: bool,
3325    },
3326}
3327
3328impl Display for Set {
3329    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3330        match self {
3331            Self::ParenthesizedAssignments { variables, values } => write!(
3332                f,
3333                "SET ({}) = ({})",
3334                display_comma_separated(variables),
3335                display_comma_separated(values)
3336            ),
3337            Self::MultipleAssignments { assignments } => {
3338                write!(f, "SET {}", display_comma_separated(assignments))
3339            }
3340            Self::SetRole {
3341                context_modifier,
3342                role_name,
3343            } => {
3344                let role_name = role_name.clone().unwrap_or_else(|| Ident::new("NONE"));
3345                write!(
3346                    f,
3347                    "SET {modifier}ROLE {role_name}",
3348                    modifier = context_modifier.map(|m| format!("{m}")).unwrap_or_default()
3349                )
3350            }
3351            Self::SetSessionAuthorization(kind) => write!(f, "SET SESSION AUTHORIZATION {kind}"),
3352            Self::SetSessionParam(kind) => write!(f, "SET {kind}"),
3353            Self::SetTransaction {
3354                modes,
3355                snapshot,
3356                session,
3357            } => {
3358                if *session {
3359                    write!(f, "SET SESSION CHARACTERISTICS AS TRANSACTION")?;
3360                } else {
3361                    write!(f, "SET TRANSACTION")?;
3362                }
3363                if !modes.is_empty() {
3364                    write!(f, " {}", display_comma_separated(modes))?;
3365                }
3366                if let Some(snapshot_id) = snapshot {
3367                    write!(f, " SNAPSHOT {snapshot_id}")?;
3368                }
3369                Ok(())
3370            }
3371            Self::SetTimeZone { local, value } => {
3372                f.write_str("SET ")?;
3373                if *local {
3374                    f.write_str("LOCAL ")?;
3375                }
3376                write!(f, "TIME ZONE {value}")
3377            }
3378            Self::SetNames {
3379                charset_name,
3380                collation_name,
3381            } => {
3382                write!(f, "SET NAMES {charset_name}")?;
3383
3384                if let Some(collation) = collation_name {
3385                    f.write_str(" COLLATE ")?;
3386                    f.write_str(collation)?;
3387                };
3388
3389                Ok(())
3390            }
3391            Self::SetNamesDefault {} => {
3392                f.write_str("SET NAMES DEFAULT")?;
3393
3394                Ok(())
3395            }
3396            Set::SingleAssignment {
3397                scope,
3398                hivevar,
3399                variable,
3400                values,
3401            } => {
3402                write!(
3403                    f,
3404                    "SET {}{}{} = {}",
3405                    scope.map(|s| format!("{s}")).unwrap_or_default(),
3406                    if *hivevar { "HIVEVAR:" } else { "" },
3407                    variable,
3408                    display_comma_separated(values)
3409                )
3410            }
3411        }
3412    }
3413}
3414
3415/// A representation of a `WHEN` arm with all the identifiers catched and the statements to execute
3416/// for the arm.
3417///
3418/// Snowflake: <https://docs.snowflake.com/en/sql-reference/snowflake-scripting/exception>
3419/// BigQuery: <https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#beginexceptionend>
3420#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3421#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3422#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3423pub struct ExceptionWhen {
3424    /// Identifiers that trigger this branch (error conditions).
3425    pub idents: Vec<Ident>,
3426    /// Statements to execute when the condition matches.
3427    pub statements: Vec<Statement>,
3428}
3429
3430impl Display for ExceptionWhen {
3431    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3432        write!(
3433            f,
3434            "WHEN {idents} THEN",
3435            idents = display_separated(&self.idents, " OR ")
3436        )?;
3437
3438        if !self.statements.is_empty() {
3439            write!(f, " ")?;
3440            format_statement_list(f, &self.statements)?;
3441        }
3442
3443        Ok(())
3444    }
3445}
3446
3447/// ANALYZE statement
3448///
3449/// Supported syntax varies by dialect:
3450/// - Hive: `ANALYZE TABLE t [PARTITION (...)] COMPUTE STATISTICS [NOSCAN] [FOR COLUMNS [col1, ...]] [CACHE METADATA]`
3451/// - PostgreSQL: `ANALYZE [VERBOSE] [t [(col1, ...)]]` See <https://www.postgresql.org/docs/current/sql-analyze.html>
3452/// - General: `ANALYZE [TABLE] t`
3453#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3454#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3455#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3456pub struct Analyze {
3457    #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
3458    /// Name of the table to analyze. `None` for bare `ANALYZE`.
3459    pub table_name: Option<ObjectName>,
3460    /// Optional partition expressions to restrict the analysis.
3461    pub partitions: Option<Vec<Expr>>,
3462    /// `true` when analyzing specific columns (Hive `FOR COLUMNS` syntax).
3463    pub for_columns: bool,
3464    /// Columns to analyze.
3465    pub columns: Vec<Ident>,
3466    /// Whether to cache metadata before analyzing.
3467    pub cache_metadata: bool,
3468    /// Whether to skip scanning the table.
3469    pub noscan: bool,
3470    /// Whether to compute statistics during analysis.
3471    pub compute_statistics: bool,
3472    /// Whether the `TABLE` keyword was present.
3473    pub has_table_keyword: bool,
3474}
3475
3476impl fmt::Display for Analyze {
3477    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3478        write!(f, "ANALYZE")?;
3479        if let Some(ref table_name) = self.table_name {
3480            if self.has_table_keyword {
3481                write!(f, " TABLE")?;
3482            }
3483            write!(f, " {table_name}")?;
3484        }
3485        if !self.for_columns && !self.columns.is_empty() {
3486            write!(f, " ({})", display_comma_separated(&self.columns))?;
3487        }
3488        if let Some(ref parts) = self.partitions {
3489            if !parts.is_empty() {
3490                write!(f, " PARTITION ({})", display_comma_separated(parts))?;
3491            }
3492        }
3493        if self.compute_statistics {
3494            write!(f, " COMPUTE STATISTICS")?;
3495        }
3496        if self.noscan {
3497            write!(f, " NOSCAN")?;
3498        }
3499        if self.cache_metadata {
3500            write!(f, " CACHE METADATA")?;
3501        }
3502        if self.for_columns {
3503            write!(f, " FOR COLUMNS")?;
3504            if !self.columns.is_empty() {
3505                write!(f, " {}", display_comma_separated(&self.columns))?;
3506            }
3507        }
3508        Ok(())
3509    }
3510}
3511
3512/// A top-level statement (SELECT, INSERT, CREATE, etc.)
3513#[allow(clippy::large_enum_variant)]
3514#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3515#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3516#[cfg_attr(
3517    feature = "visitor",
3518    derive(Visit, VisitMut),
3519    visit(with = "visit_statement")
3520)]
3521pub enum Statement {
3522    /// ```sql
3523    /// ANALYZE
3524    /// ```
3525    /// Analyze (Hive)
3526    Analyze(Analyze),
3527    /// `SET` statements (session, transaction, timezone, etc.).
3528    Set(Set),
3529    /// ```sql
3530    /// TRUNCATE
3531    /// ```
3532    /// Truncate (Hive)
3533    Truncate(Truncate),
3534    /// ```sql
3535    /// MSCK
3536    /// ```
3537    /// Msck (Hive)
3538    Msck(Msck),
3539    /// ```sql
3540    /// SELECT
3541    /// ```
3542    Query(Box<Query>),
3543    /// ```sql
3544    /// INSERT
3545    /// ```
3546    Insert(Insert),
3547    /// ```sql
3548    /// INSTALL
3549    /// ```
3550    Install {
3551        /// Only for DuckDB
3552        extension_name: Ident,
3553    },
3554    /// ```sql
3555    /// LOAD
3556    /// ```
3557    Load {
3558        /// Only for DuckDB
3559        extension_name: Ident,
3560    },
3561    // TODO: Support ROW FORMAT
3562    /// LOAD DATA from a directory or query source.
3563    Directory {
3564        /// Whether to overwrite existing files.
3565        overwrite: bool,
3566        /// Whether the directory is local to the server.
3567        local: bool,
3568        /// Path to the directory or files.
3569        path: String,
3570        /// Optional file format for the data.
3571        file_format: Option<FileFormat>,
3572        /// Source query providing data to load.
3573        source: Box<Query>,
3574    },
3575    /// A `CASE` statement.
3576    Case(CaseStatement),
3577    /// An `IF` statement.
3578    If(IfStatement),
3579    /// A `WHILE` statement.
3580    While(WhileStatement),
3581    /// A `RAISE` statement.
3582    Raise(RaiseStatement),
3583    /// ```sql
3584    /// CALL <function>
3585    /// ```
3586    Call(Function),
3587    /// ```sql
3588    /// COPY [TO | FROM] ...
3589    /// ```
3590    Copy {
3591        /// The source of 'COPY TO', or the target of 'COPY FROM'
3592        source: CopySource,
3593        /// If true, is a 'COPY TO' statement. If false is a 'COPY FROM'
3594        to: bool,
3595        /// The target of 'COPY TO', or the source of 'COPY FROM'
3596        target: CopyTarget,
3597        /// WITH options (from PostgreSQL version 9.0)
3598        options: Vec<CopyOption>,
3599        /// WITH options (before PostgreSQL version 9.0)
3600        legacy_options: Vec<CopyLegacyOption>,
3601        /// VALUES a vector of values to be copied
3602        values: Vec<Option<String>>,
3603    },
3604    /// ```sql
3605    /// COPY INTO <table> | <location>
3606    /// ```
3607    /// See:
3608    /// <https://docs.snowflake.com/en/sql-reference/sql/copy-into-table>
3609    /// <https://docs.snowflake.com/en/sql-reference/sql/copy-into-location>
3610    ///
3611    /// Copy Into syntax available for Snowflake is different than the one implemented in
3612    /// Postgres. Although they share common prefix, it is reasonable to implement them
3613    /// in different enums. This can be refactored later once custom dialects
3614    /// are allowed to have custom Statements.
3615    CopyIntoSnowflake {
3616        /// Kind of COPY INTO operation (table or location).
3617        kind: CopyIntoSnowflakeKind,
3618        /// Target object for the COPY INTO operation.
3619        into: ObjectName,
3620        /// Optional list of target columns.
3621        into_columns: Option<Vec<Ident>>,
3622        /// Optional source object name (staged data).
3623        from_obj: Option<ObjectName>,
3624        /// Optional alias for the source object.
3625        from_obj_alias: Option<Ident>,
3626        /// Stage-specific parameters (e.g., credentials, path).
3627        stage_params: StageParamsObject,
3628        /// Optional list of transformations applied when loading.
3629        from_transformations: Option<Vec<StageLoadSelectItemKind>>,
3630        /// Optional source query instead of a staged object.
3631        from_query: Option<Box<Query>>,
3632        /// Optional list of specific file names to load.
3633        files: Option<Vec<String>>,
3634        /// Optional filename matching pattern.
3635        pattern: Option<String>,
3636        /// File format options.
3637        file_format: KeyValueOptions,
3638        /// Additional copy options.
3639        copy_options: KeyValueOptions,
3640        /// Optional validation mode string.
3641        validation_mode: Option<String>,
3642        /// Optional partition expression for loading.
3643        partition: Option<Box<Expr>>,
3644    },
3645    /// ```sql
3646    /// OPEN cursor_name
3647    /// ```
3648    /// Opens a cursor.
3649    Open(OpenStatement),
3650    /// ```sql
3651    /// CLOSE
3652    /// ```
3653    /// Closes the portal underlying an open cursor.
3654    Close {
3655        /// Cursor name
3656        cursor: CloseCursor,
3657    },
3658    /// ```sql
3659    /// UPDATE
3660    /// ```
3661    Update(Update),
3662    /// ```sql
3663    /// DELETE
3664    /// ```
3665    Delete(Delete),
3666    /// ```sql
3667    /// CREATE VIEW
3668    /// ```
3669    CreateView(CreateView),
3670    /// ```sql
3671    /// CREATE TABLE
3672    /// ```
3673    CreateTable(CreateTable),
3674    /// ```sql
3675    /// CREATE VIRTUAL TABLE .. USING <module_name> (<module_args>)`
3676    /// ```
3677    /// Sqlite specific statement
3678    CreateVirtualTable {
3679        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
3680        /// Name of the virtual table module instance.
3681        name: ObjectName,
3682        /// `true` when `IF NOT EXISTS` was specified.
3683        if_not_exists: bool,
3684        /// Module name used by the virtual table.
3685        module_name: Ident,
3686        /// Arguments passed to the module.
3687        module_args: Vec<Ident>,
3688    },
3689    /// ```sql
3690    /// `CREATE INDEX`
3691    /// ```
3692    CreateIndex(CreateIndex),
3693    /// ```sql
3694    /// CREATE ROLE
3695    /// ```
3696    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createrole.html)
3697    CreateRole(CreateRole),
3698    /// ```sql
3699    /// CREATE SECRET
3700    /// ```
3701    /// See [DuckDB](https://duckdb.org/docs/sql/statements/create_secret.html)
3702    CreateSecret {
3703        /// `true` when `OR REPLACE` was specified.
3704        or_replace: bool,
3705        /// Optional `TEMPORARY` flag.
3706        temporary: Option<bool>,
3707        /// `true` when `IF NOT EXISTS` was present.
3708        if_not_exists: bool,
3709        /// Optional secret name.
3710        name: Option<Ident>,
3711        /// Optional storage specifier identifier.
3712        storage_specifier: Option<Ident>,
3713        /// The secret type identifier.
3714        secret_type: Ident,
3715        /// Additional secret options.
3716        options: Vec<SecretOption>,
3717    },
3718    /// A `CREATE SERVER` statement.
3719    CreateServer(CreateServerStatement),
3720    /// ```sql
3721    /// CREATE FOREIGN DATA WRAPPER
3722    /// ```
3723    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createforeigndatawrapper.html)
3724    CreateForeignDataWrapper(CreateForeignDataWrapper),
3725    /// ```sql
3726    /// CREATE FOREIGN TABLE
3727    /// ```
3728    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createforeigntable.html)
3729    CreateForeignTable(CreateForeignTable),
3730    /// ```sql
3731    /// CREATE POLICY
3732    /// ```
3733    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createpolicy.html)
3734    CreatePolicy(CreatePolicy),
3735    /// ```sql
3736    /// CREATE CONNECTOR
3737    /// ```
3738    /// See [Hive](https://cwiki.apache.org/confluence/pages/viewpage.action?pageId=27362034#LanguageManualDDL-CreateDataConnectorCreateConnector)
3739    CreateConnector(CreateConnector),
3740    /// ```sql
3741    /// CREATE OPERATOR
3742    /// ```
3743    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createoperator.html)
3744    CreateOperator(CreateOperator),
3745    /// ```sql
3746    /// CREATE OPERATOR FAMILY
3747    /// ```
3748    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createopfamily.html)
3749    CreateOperatorFamily(CreateOperatorFamily),
3750    /// ```sql
3751    /// CREATE OPERATOR CLASS
3752    /// ```
3753    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createopclass.html)
3754    CreateOperatorClass(CreateOperatorClass),
3755    /// ```sql
3756    /// CREATE AGGREGATE
3757    /// ```
3758    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createaggregate.html)
3759    CreateAggregate(CreateAggregate),
3760    /// ```sql
3761    /// ALTER TABLE
3762    /// ```
3763    AlterTable(AlterTable),
3764    /// ```sql
3765    /// ALTER SCHEMA
3766    /// ```
3767    /// See [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#alter_schema_collate_statement)
3768    AlterSchema(AlterSchema),
3769    /// ```sql
3770    /// ALTER INDEX
3771    /// ```
3772    AlterIndex {
3773        /// Name of the index to alter.
3774        name: ObjectName,
3775        /// The operation to perform on the index.
3776        operation: AlterIndexOperation,
3777    },
3778    /// ```sql
3779    /// ALTER VIEW
3780    /// ```
3781    AlterView {
3782        /// View name being altered.
3783        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
3784        name: ObjectName,
3785        /// Optional new column list for the view.
3786        columns: Vec<Ident>,
3787        /// Replacement query for the view definition.
3788        query: Box<Query>,
3789        /// Additional WITH options for the view.
3790        with_options: Vec<SqlOption>,
3791    },
3792    /// ```sql
3793    /// ALTER DOMAIN
3794    /// ```
3795    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-alterdomain.html)
3796    AlterDomain(AlterDomain),
3797    /// ```sql
3798    /// ALTER EXTENSION
3799    /// ```
3800    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-alterextension.html)
3801    AlterExtension(AlterExtension),
3802    /// ```sql
3803    /// ALTER FUNCTION
3804    /// ALTER AGGREGATE
3805    /// ALTER PROCEDURE
3806    /// ```
3807    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-alterfunction.html)
3808    /// and [PostgreSQL](https://www.postgresql.org/docs/current/sql-alteraggregate.html)
3809    /// and [PostgreSQL](https://www.postgresql.org/docs/current/sql-alterprocedure.html)
3810    AlterFunction(AlterFunction),
3811    /// ```sql
3812    /// ALTER TYPE
3813    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-altertype.html)
3814    /// ```
3815    AlterType(AlterType),
3816    /// ```sql
3817    /// ALTER TRIGGER
3818    /// ```
3819    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-altertrigger.html)
3820    AlterTrigger(AlterTrigger),
3821    /// ```sql
3822    /// ALTER COLLATION
3823    /// ```
3824    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-altercollation.html)
3825    AlterCollation(AlterCollation),
3826    /// ```sql
3827    /// ALTER DEFAULT PRIVILEGES
3828    ///     [ FOR { ROLE | USER } target_role [, ...] ]
3829    ///     [ IN SCHEMA schema_name [, ...] ]
3830    ///     abbreviated_grant_or_revoke
3831    /// ```
3832    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-alterdefaultprivileges.html)
3833    AlterDefaultPrivileges(AlterDefaultPrivileges),
3834    /// ```sql
3835    /// ALTER OPERATOR
3836    /// ```
3837    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-alteroperator.html)
3838    AlterOperator(AlterOperator),
3839    /// ```sql
3840    /// ALTER OPERATOR FAMILY
3841    /// ```
3842    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-alteropfamily.html)
3843    AlterOperatorFamily(AlterOperatorFamily),
3844    /// ```sql
3845    /// ALTER OPERATOR CLASS
3846    /// ```
3847    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-alteropclass.html)
3848    AlterOperatorClass(AlterOperatorClass),
3849    /// ```sql
3850    /// ALTER ROLE
3851    /// ```
3852    AlterRole {
3853        /// Role name being altered.
3854        name: Ident,
3855        /// Operation to perform on the role.
3856        operation: AlterRoleOperation,
3857    },
3858    /// ```sql
3859    /// ALTER POLICY <NAME> ON <TABLE NAME> [<OPERATION>]
3860    /// ```
3861    /// (Postgresql-specific)
3862    AlterPolicy(AlterPolicy),
3863    /// ```sql
3864    /// ALTER CONNECTOR connector_name SET DCPROPERTIES(property_name=property_value, ...);
3865    /// or
3866    /// ALTER CONNECTOR connector_name SET URL new_url;
3867    /// or
3868    /// ALTER CONNECTOR connector_name SET OWNER [USER|ROLE] user_or_role;
3869    /// ```
3870    /// (Hive-specific)
3871    AlterConnector {
3872        /// Name of the connector to alter.
3873        name: Ident,
3874        /// Optional connector properties to set.
3875        properties: Option<Vec<SqlOption>>,
3876        /// Optional new URL for the connector.
3877        url: Option<String>,
3878        /// Optional new owner specification.
3879        owner: Option<ddl::AlterConnectorOwner>,
3880    },
3881    /// ```sql
3882    /// ALTER SESSION SET sessionParam
3883    /// ALTER SESSION UNSET <param_name> [ , <param_name> , ... ]
3884    /// ```
3885    /// See <https://docs.snowflake.com/en/sql-reference/sql/alter-session>
3886    AlterSession {
3887        /// true is to set for the session parameters, false is to unset
3888        set: bool,
3889        /// The session parameters to set or unset
3890        session_params: KeyValueOptions,
3891    },
3892    /// ```sql
3893    /// ATTACH DATABASE 'path/to/file' AS alias
3894    /// ```
3895    /// (SQLite-specific)
3896    AttachDatabase {
3897        /// The name to bind to the newly attached database
3898        schema_name: Ident,
3899        /// An expression that indicates the path to the database file
3900        database_file_name: Expr,
3901        /// true if the syntax is 'ATTACH DATABASE', false if it's just 'ATTACH'
3902        database: bool,
3903    },
3904    /// (DuckDB-specific)
3905    /// ```sql
3906    /// ATTACH 'sqlite_file.db' AS sqlite_db (READ_ONLY, TYPE SQLITE);
3907    /// ```
3908    /// See <https://duckdb.org/docs/sql/statements/attach.html>
3909    AttachDuckDBDatabase {
3910        /// `true` when `IF NOT EXISTS` was present.
3911        if_not_exists: bool,
3912        /// `true` if the syntax used `ATTACH DATABASE` rather than `ATTACH`.
3913        database: bool,
3914        /// The path identifier to the database file being attached.
3915        database_path: Ident,
3916        /// Optional alias assigned to the attached database.
3917        database_alias: Option<Ident>,
3918        /// Dialect-specific attach options (e.g., `READ_ONLY`).
3919        attach_options: Vec<AttachDuckDBDatabaseOption>,
3920    },
3921    /// (DuckDB-specific)
3922    /// ```sql
3923    /// DETACH db_alias;
3924    /// ```
3925    /// See <https://duckdb.org/docs/sql/statements/attach.html>
3926    DetachDuckDBDatabase {
3927        /// `true` when `IF EXISTS` was present.
3928        if_exists: bool,
3929        /// `true` if the syntax used `DETACH DATABASE` rather than `DETACH`.
3930        database: bool,
3931        /// Alias of the database to detach.
3932        database_alias: Ident,
3933    },
3934    /// ```sql
3935    /// DROP [TABLE, VIEW, ...]
3936    /// ```
3937    Drop {
3938        /// The type of the object to drop: TABLE, VIEW, etc.
3939        object_type: ObjectType,
3940        /// An optional `IF EXISTS` clause. (Non-standard.)
3941        if_exists: bool,
3942        /// One or more objects to drop. (ANSI SQL requires exactly one.)
3943        names: Vec<ObjectName>,
3944        /// Whether `CASCADE` was specified. This will be `false` when
3945        /// `RESTRICT` or no drop behavior at all was specified.
3946        cascade: bool,
3947        /// Whether `RESTRICT` was specified. This will be `false` when
3948        /// `CASCADE` or no drop behavior at all was specified.
3949        restrict: bool,
3950        /// Hive allows you specify whether the table's stored data will be
3951        /// deleted along with the dropped table
3952        purge: bool,
3953        /// MySQL-specific "TEMPORARY" keyword
3954        temporary: bool,
3955        /// MySQL-specific drop index syntax, which requires table specification
3956        /// See <https://dev.mysql.com/doc/refman/8.4/en/drop-index.html>
3957        table: Option<ObjectName>,
3958    },
3959    /// ```sql
3960    /// DROP FUNCTION
3961    /// ```
3962    DropFunction(DropFunction),
3963    /// ```sql
3964    /// DROP DOMAIN
3965    /// ```
3966    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-dropdomain.html)
3967    ///
3968    /// DROP DOMAIN [ IF EXISTS ] name [, ...] [ CASCADE | RESTRICT ]
3969    ///
3970    DropDomain(DropDomain),
3971    /// ```sql
3972    /// DROP PROCEDURE
3973    /// ```
3974    DropProcedure {
3975        /// `true` when `IF EXISTS` was present.
3976        if_exists: bool,
3977        /// One or more functions/procedures to drop.
3978        proc_desc: Vec<FunctionDesc>,
3979        /// Optional drop behavior (`CASCADE` or `RESTRICT`).
3980        drop_behavior: Option<DropBehavior>,
3981    },
3982    /// ```sql
3983    /// DROP SECRET
3984    /// ```
3985    DropSecret {
3986        /// `true` when `IF EXISTS` was present.
3987        if_exists: bool,
3988        /// Optional `TEMPORARY` marker.
3989        temporary: Option<bool>,
3990        /// Name of the secret to drop.
3991        name: Ident,
3992        /// Optional storage specifier identifier.
3993        storage_specifier: Option<Ident>,
3994    },
3995    ///```sql
3996    /// DROP POLICY
3997    /// ```
3998    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-droppolicy.html)
3999    DropPolicy(DropPolicy),
4000    /// ```sql
4001    /// DROP CONNECTOR
4002    /// ```
4003    /// See [Hive](https://cwiki.apache.org/confluence/pages/viewpage.action?pageId=27362034#LanguageManualDDL-DropConnector)
4004    DropConnector {
4005        /// `true` when `IF EXISTS` was present.
4006        if_exists: bool,
4007        /// Name of the connector to drop.
4008        name: Ident,
4009    },
4010    /// ```sql
4011    /// DECLARE
4012    /// ```
4013    /// Declare Cursor Variables
4014    ///
4015    /// Note: this is a PostgreSQL-specific statement,
4016    /// but may also compatible with other SQL.
4017    Declare {
4018        /// Cursor declaration statements collected by `DECLARE`.
4019        stmts: Vec<Declare>,
4020    },
4021    /// ```sql
4022    /// CREATE EXTENSION [ IF NOT EXISTS ] extension_name
4023    ///     [ WITH ] [ SCHEMA schema_name ]
4024    ///              [ VERSION version ]
4025    ///              [ CASCADE ]
4026    /// ```
4027    ///
4028    /// Note: this is a PostgreSQL-specific statement,
4029    CreateExtension(CreateExtension),
4030    /// ```sql
4031    /// CREATE COLLATION
4032    /// ```
4033    /// Note: this is a PostgreSQL-specific statement.
4034    /// <https://www.postgresql.org/docs/current/sql-createcollation.html>
4035    CreateCollation(CreateCollation),
4036    /// ```sql
4037    /// CREATE TEXT SEARCH CONFIGURATION name ( PARSER = parser_name )
4038    /// ```
4039    /// Note: this is a PostgreSQL-specific statement.
4040    /// <https://www.postgresql.org/docs/current/sql-createtsconfig.html>
4041    CreateTextSearchConfiguration(CreateTextSearchConfiguration),
4042    /// ```sql
4043    /// CREATE TEXT SEARCH DICTIONARY name ( TEMPLATE = template_name [, option = value, ...] )
4044    /// ```
4045    /// Note: this is a PostgreSQL-specific statement.
4046    /// <https://www.postgresql.org/docs/current/sql-createtsdictionary.html>
4047    CreateTextSearchDictionary(CreateTextSearchDictionary),
4048    /// ```sql
4049    /// CREATE TEXT SEARCH PARSER name ( START = start_fn, GETTOKEN = gettoken_fn, END = end_fn, LEXTYPES = lextypes_fn [, HEADLINE = headline_fn] )
4050    /// ```
4051    /// Note: this is a PostgreSQL-specific statement.
4052    /// <https://www.postgresql.org/docs/current/sql-createtsparser.html>
4053    CreateTextSearchParser(CreateTextSearchParser),
4054    /// ```sql
4055    /// CREATE TEXT SEARCH TEMPLATE name ( [INIT = init_fn,] LEXIZE = lexize_fn )
4056    /// ```
4057    /// Note: this is a PostgreSQL-specific statement.
4058    /// <https://www.postgresql.org/docs/current/sql-createtstemplate.html>
4059    CreateTextSearchTemplate(CreateTextSearchTemplate),
4060    /// ```sql
4061    /// CREATE PUBLICATION name [ FOR ALL TABLES | FOR TABLE table [, ...] | FOR TABLES IN SCHEMA schema [, ...] ] [ WITH ( option = value [, ...] ) ]
4062    /// ```
4063    /// Note: this is a PostgreSQL-specific statement.
4064    /// <https://www.postgresql.org/docs/current/sql-createpublication.html>
4065    CreatePublication(CreatePublication),
4066    /// ```sql
4067    /// CREATE SUBSCRIPTION name CONNECTION 'conninfo' PUBLICATION publication_name [, ...] [ WITH ( option = value [, ...] ) ]
4068    /// ```
4069    /// Note: this is a PostgreSQL-specific statement.
4070    /// <https://www.postgresql.org/docs/current/sql-createsubscription.html>
4071    CreateSubscription(CreateSubscription),
4072    /// ```sql
4073    /// CREATE CAST (source_type AS target_type) WITH FUNCTION func_name [(arg_types)] [AS ASSIGNMENT | AS IMPLICIT]
4074    /// CREATE CAST (source_type AS target_type) WITHOUT FUNCTION [AS ASSIGNMENT | AS IMPLICIT]
4075    /// CREATE CAST (source_type AS target_type) WITH INOUT [AS ASSIGNMENT | AS IMPLICIT]
4076    /// ```
4077    /// Note: this is a PostgreSQL-specific statement.
4078    /// <https://www.postgresql.org/docs/current/sql-createcast.html>
4079    CreateCast(CreateCast),
4080    /// ```sql
4081    /// CREATE [DEFAULT] CONVERSION name FOR 'source_encoding' TO 'dest_encoding' FROM function_name
4082    /// ```
4083    /// Note: this is a PostgreSQL-specific statement.
4084    /// <https://www.postgresql.org/docs/current/sql-createconversion.html>
4085    CreateConversion(CreateConversion),
4086    /// ```sql
4087    /// CREATE [OR REPLACE] [TRUSTED] [PROCEDURAL] LANGUAGE name [HANDLER handler_func] [INLINE inline_func] [VALIDATOR validator_func | NO VALIDATOR]
4088    /// ```
4089    /// Note: this is a PostgreSQL-specific statement.
4090    /// <https://www.postgresql.org/docs/current/sql-createlanguage.html>
4091    CreateLanguage(CreateLanguage),
4092    /// ```sql
4093    /// CREATE RULE name AS ON event TO table [WHERE condition] DO [ALSO | INSTEAD] { NOTHING | command | (command ; ...) }
4094    /// ```
4095    /// Note: this is a PostgreSQL-specific statement.
4096    /// <https://www.postgresql.org/docs/current/sql-createrule.html>
4097    CreateRule(CreateRule),
4098    /// ```sql
4099    /// CREATE STATISTICS [ IF NOT EXISTS ] name [ ( kind [, ...] ) ] ON expr [, ...] FROM table_name
4100    /// ```
4101    /// Note: this is a PostgreSQL-specific statement.
4102    /// <https://www.postgresql.org/docs/current/sql-createstatistics.html>
4103    CreateStatistics(CreateStatistics),
4104    /// ```sql
4105    /// CREATE ACCESS METHOD name TYPE INDEX | TABLE HANDLER handler_function
4106    /// ```
4107    /// Note: this is a PostgreSQL-specific statement.
4108    /// <https://www.postgresql.org/docs/current/sql-create-access-method.html>
4109    CreateAccessMethod(CreateAccessMethod),
4110    /// ```sql
4111    /// CREATE EVENT TRIGGER name ON event [ WHEN TAG IN ( 'tag' [, ...] ) ] EXECUTE FUNCTION | PROCEDURE function_name()
4112    /// ```
4113    /// Note: this is a PostgreSQL-specific statement.
4114    /// <https://www.postgresql.org/docs/current/sql-createeventtrigger.html>
4115    CreateEventTrigger(CreateEventTrigger),
4116    /// ```sql
4117    /// CREATE [ OR REPLACE ] TRANSFORM FOR type_name LANGUAGE lang_name ( transform_element_list )
4118    /// ```
4119    /// Note: this is a PostgreSQL-specific statement.
4120    /// <https://www.postgresql.org/docs/current/sql-createtransform.html>
4121    CreateTransform(CreateTransform),
4122    /// ```sql
4123    /// SECURITY LABEL [ FOR provider_name ] ON object_type object_name IS { 'label' | NULL }
4124    /// ```
4125    /// Note: this is a PostgreSQL-specific statement.
4126    /// <https://www.postgresql.org/docs/current/sql-securitylabel.html>
4127    SecurityLabel(SecurityLabel),
4128    /// ```sql
4129    /// CREATE USER MAPPING [ IF NOT EXISTS ] FOR { role | USER | CURRENT_ROLE | CURRENT_USER | PUBLIC } SERVER server_name [ OPTIONS (...) ]
4130    /// ```
4131    /// Note: this is a PostgreSQL-specific statement.
4132    /// <https://www.postgresql.org/docs/current/sql-createusermapping.html>
4133    CreateUserMapping(CreateUserMapping),
4134    /// ```sql
4135    /// CREATE TABLESPACE name [ OWNER role ] LOCATION 'directory' [ WITH (options) ]
4136    /// ```
4137    /// Note: this is a PostgreSQL-specific statement.
4138    /// <https://www.postgresql.org/docs/current/sql-createtablespace.html>
4139    CreateTablespace(CreateTablespace),
4140    /// ```sql
4141    /// DROP EXTENSION [ IF EXISTS ] name [, ...] [ CASCADE | RESTRICT ]
4142    /// ```
4143    /// Note: this is a PostgreSQL-specific statement.
4144    /// <https://www.postgresql.org/docs/current/sql-dropextension.html>
4145    DropExtension(DropExtension),
4146    /// ```sql
4147    /// DROP OPERATOR [ IF EXISTS ] name ( { left_type | NONE } , right_type ) [, ...] [ CASCADE | RESTRICT ]
4148    /// ```
4149    /// Note: this is a PostgreSQL-specific statement.
4150    /// <https://www.postgresql.org/docs/current/sql-dropoperator.html>
4151    DropOperator(DropOperator),
4152    /// ```sql
4153    /// DROP OPERATOR FAMILY [ IF EXISTS ] name USING index_method [ CASCADE | RESTRICT ]
4154    /// ```
4155    /// Note: this is a PostgreSQL-specific statement.
4156    /// <https://www.postgresql.org/docs/current/sql-dropopfamily.html>
4157    DropOperatorFamily(DropOperatorFamily),
4158    /// ```sql
4159    /// DROP OPERATOR CLASS [ IF EXISTS ] name USING index_method [ CASCADE | RESTRICT ]
4160    /// ```
4161    /// Note: this is a PostgreSQL-specific statement.
4162    /// <https://www.postgresql.org/docs/current/sql-dropopclass.html>
4163    DropOperatorClass(DropOperatorClass),
4164    /// ```sql
4165    /// FETCH
4166    /// ```
4167    /// Retrieve rows from a query using a cursor
4168    ///
4169    /// Note: this is a PostgreSQL-specific statement,
4170    /// but may also compatible with other SQL.
4171    Fetch {
4172        /// Cursor name
4173        name: Ident,
4174        /// The fetch direction (e.g., `FORWARD`, `BACKWARD`).
4175        direction: FetchDirection,
4176        /// The fetch position (e.g., `ALL`, `NEXT`, `ABSOLUTE`).
4177        position: FetchPosition,
4178        /// Optional target table to fetch rows into.
4179        into: Option<ObjectName>,
4180    },
4181    /// ```sql
4182    /// FLUSH [NO_WRITE_TO_BINLOG | LOCAL] flush_option [, flush_option] ... | tables_option
4183    /// ```
4184    ///
4185    /// Note: this is a Mysql-specific statement,
4186    /// but may also compatible with other SQL.
4187    Flush {
4188        /// The specific flush option or object to flush.
4189        object_type: FlushType,
4190        /// Optional flush location (dialect-specific).
4191        location: Option<FlushLocation>,
4192        /// Optional channel name used for flush operations.
4193        channel: Option<String>,
4194        /// Whether a read lock was requested.
4195        read_lock: bool,
4196        /// Whether this is an export flush operation.
4197        export: bool,
4198        /// Optional list of tables involved in the flush.
4199        tables: Vec<ObjectName>,
4200    },
4201    /// ```sql
4202    /// DISCARD [ ALL | PLANS | SEQUENCES | TEMPORARY | TEMP ]
4203    /// ```
4204    ///
4205    /// Note: this is a PostgreSQL-specific statement,
4206    /// but may also compatible with other SQL.
4207    Discard {
4208        /// The kind of object(s) to discard (ALL, PLANS, etc.).
4209        object_type: DiscardObject,
4210    },
4211    /// `SHOW FUNCTIONS`
4212    ///
4213    /// Note: this is a Presto-specific statement.
4214    ShowFunctions {
4215        /// Optional filter for which functions to display.
4216        filter: Option<ShowStatementFilter>,
4217    },
4218    /// ```sql
4219    /// SHOW <variable>
4220    /// ```
4221    ///
4222    /// Note: this is a PostgreSQL-specific statement.
4223    ShowVariable {
4224        /// Variable name as one or more identifiers.
4225        variable: Vec<Ident>,
4226    },
4227    /// ```sql
4228    /// SHOW [GLOBAL | SESSION] STATUS [LIKE 'pattern' | WHERE expr]
4229    /// ```
4230    ///
4231    /// Note: this is a MySQL-specific statement.
4232    ShowStatus {
4233        /// Optional filter for which status entries to display.
4234        filter: Option<ShowStatementFilter>,
4235        /// `true` when `GLOBAL` scope was requested.
4236        global: bool,
4237        /// `true` when `SESSION` scope was requested.
4238        session: bool,
4239    },
4240    /// ```sql
4241    /// SHOW VARIABLES
4242    /// ```
4243    ///
4244    /// Note: this is a MySQL-specific statement.
4245    ShowVariables {
4246        /// Optional filter for which variables to display.
4247        filter: Option<ShowStatementFilter>,
4248        /// `true` when `GLOBAL` scope was requested.
4249        global: bool,
4250        /// `true` when `SESSION` scope was requested.
4251        session: bool,
4252    },
4253    /// ```sql
4254    /// SHOW CREATE TABLE
4255    /// ```
4256    ///
4257    /// Note: this is a MySQL-specific statement.
4258    ShowCreate {
4259        /// The kind of object being shown (TABLE, VIEW, etc.).
4260        obj_type: ShowCreateObject,
4261        /// The name of the object to show create statement for.
4262        obj_name: ObjectName,
4263    },
4264    /// ```sql
4265    /// SHOW COLUMNS
4266    /// ```
4267    ShowColumns {
4268        /// `true` when extended column information was requested.
4269        extended: bool,
4270        /// `true` when full column details were requested.
4271        full: bool,
4272        /// Additional options for `SHOW COLUMNS`.
4273        show_options: ShowStatementOptions,
4274    },
4275    /// ```sql
4276    /// SHOW CATALOGS
4277    /// ```
4278    ShowCatalogs {
4279        /// `true` when terse output format was requested.
4280        terse: bool,
4281        /// `true` when history information was requested.
4282        history: bool,
4283        /// Additional options for `SHOW CATALOGS`.
4284        show_options: ShowStatementOptions,
4285    },
4286    /// ```sql
4287    /// SHOW DATABASES
4288    /// ```
4289    ShowDatabases {
4290        /// `true` when terse output format was requested.
4291        terse: bool,
4292        /// `true` when history information was requested.
4293        history: bool,
4294        /// Additional options for `SHOW DATABASES`.
4295        show_options: ShowStatementOptions,
4296    },
4297    /// ```sql
4298    /// SHOW [FULL] PROCESSLIST
4299    /// ```
4300    ///
4301    /// Note: this is a MySQL-specific statement.
4302    ShowProcessList {
4303        /// `true` when full process information was requested.
4304        full: bool,
4305    },
4306    /// ```sql
4307    /// SHOW SCHEMAS
4308    /// ```
4309    ShowSchemas {
4310        /// `true` when terse (compact) output was requested.
4311        terse: bool,
4312        /// `true` when history information was requested.
4313        history: bool,
4314        /// Additional options for `SHOW SCHEMAS`.
4315        show_options: ShowStatementOptions,
4316    },
4317    // ```sql
4318    // SHOW {CHARACTER SET | CHARSET}
4319    // ```
4320    // [MySQL]:
4321    // <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>
4322    /// Show the available character sets (alias `CHARSET`).
4323    ShowCharset(ShowCharset),
4324    /// ```sql
4325    /// SHOW OBJECTS LIKE 'line%' IN mydb.public
4326    /// ```
4327    /// Snowflake-specific statement
4328    /// <https://docs.snowflake.com/en/sql-reference/sql/show-objects>
4329    ShowObjects(ShowObjects),
4330    /// ```sql
4331    /// SHOW TABLES
4332    /// ```
4333    ShowTables {
4334        /// `true` when terse output format was requested (compact listing).
4335        terse: bool,
4336        /// `true` when history rows are requested.
4337        history: bool,
4338        /// `true` when extended information should be shown.
4339        extended: bool,
4340        /// `true` when a full listing was requested.
4341        full: bool,
4342        /// `true` when external tables should be included.
4343        external: bool,
4344        /// Additional options for `SHOW` statements.
4345        show_options: ShowStatementOptions,
4346    },
4347    /// ```sql
4348    /// SHOW VIEWS
4349    /// ```
4350    ShowViews {
4351        /// `true` when terse output format was requested.
4352        terse: bool,
4353        /// `true` when materialized views should be included.
4354        materialized: bool,
4355        /// Additional options for `SHOW` statements.
4356        show_options: ShowStatementOptions,
4357    },
4358    /// ```sql
4359    /// SHOW COLLATION
4360    /// ```
4361    ///
4362    /// Note: this is a MySQL-specific statement.
4363    ShowCollation {
4364        /// Optional filter for which collations to display.
4365        filter: Option<ShowStatementFilter>,
4366    },
4367    /// ```sql
4368    /// `USE ...`
4369    /// ```
4370    Use(Use),
4371    /// ```sql
4372    /// START  [ TRANSACTION | WORK ] | START TRANSACTION } ...
4373    /// ```
4374    /// If `begin` is false.
4375    ///
4376    /// ```sql
4377    /// `BEGIN  [ TRANSACTION | WORK ] | START TRANSACTION } ...`
4378    /// ```
4379    /// If `begin` is true
4380    StartTransaction {
4381        /// Transaction modes such as `ISOLATION LEVEL` or `READ WRITE`.
4382        modes: Vec<TransactionMode>,
4383        /// `true` when this was parsed as `BEGIN` instead of `START`.
4384        begin: bool,
4385        /// Optional specific keyword used: `TRANSACTION` or `WORK`.
4386        transaction: Option<BeginTransactionKind>,
4387        /// Optional transaction modifier (e.g., `AND NO CHAIN`).
4388        modifier: Option<TransactionModifier>,
4389        /// List of statements belonging to the `BEGIN` block.
4390        /// Example:
4391        /// ```sql
4392        /// BEGIN
4393        ///     SELECT 1;
4394        ///     SELECT 2;
4395        /// END;
4396        /// ```
4397        statements: Vec<Statement>,
4398        /// Exception handling with exception clauses.
4399        /// Example:
4400        /// ```sql
4401        /// EXCEPTION
4402        ///     WHEN EXCEPTION_1 THEN
4403        ///         SELECT 2;
4404        ///     WHEN EXCEPTION_2 OR EXCEPTION_3 THEN
4405        ///         SELECT 3;
4406        ///     WHEN OTHER THEN
4407        ///         SELECT 4;
4408        /// ```
4409        /// <https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#beginexceptionend>
4410        /// <https://docs.snowflake.com/en/sql-reference/snowflake-scripting/exception>
4411        exception: Option<Vec<ExceptionWhen>>,
4412        /// TRUE if the statement has an `END` keyword.
4413        has_end_keyword: bool,
4414    },
4415    /// ```sql
4416    /// COMMENT ON ...
4417    /// ```
4418    ///
4419    /// Note: this is a PostgreSQL-specific statement.
4420    Comment {
4421        /// Type of object being commented (table, column, etc.).
4422        object_type: CommentObject,
4423        /// Name of the object the comment applies to.
4424        object_name: ObjectName,
4425        /// Argument types for overloaded objects. `Some(vec![])` represents an
4426        /// empty `()` parameter list (e.g. `COMMENT ON FUNCTION f() IS '…'`),
4427        /// while `None` means no parameter list was provided. Used for
4428        /// `FUNCTION`, `PROCEDURE`, and `AGGREGATE` targets.
4429        arguments: Option<Vec<DataType>>,
4430        /// Partner relation for objects scoped to a table, i.e. the
4431        /// `ON <relation>` tail in `COMMENT ON TRIGGER t ON tbl IS '…'` or
4432        /// `COMMENT ON POLICY p ON tbl IS '…'`.
4433        relation: Option<ObjectName>,
4434        /// Optional comment text (None to remove comment).
4435        comment: Option<String>,
4436        /// An optional `IF EXISTS` clause. (Non-standard.)
4437        /// See <https://docs.snowflake.com/en/sql-reference/sql/comment>
4438        if_exists: bool,
4439    },
4440    /// ```sql
4441    /// COMMIT [ TRANSACTION | WORK ] [ AND [ NO ] CHAIN ]
4442    /// ```
4443    /// If `end` is false
4444    ///
4445    /// ```sql
4446    /// END [ TRY | CATCH ]
4447    /// ```
4448    /// If `end` is true
4449    Commit {
4450        /// `true` when `AND [ NO ] CHAIN` was present.
4451        chain: bool,
4452        /// `true` when this `COMMIT` was parsed as an `END` block terminator.
4453        end: bool,
4454        /// Optional transaction modifier for commit semantics.
4455        modifier: Option<TransactionModifier>,
4456    },
4457    /// ```sql
4458    /// ROLLBACK [ TRANSACTION | WORK ] [ AND [ NO ] CHAIN ] [ TO [ SAVEPOINT ] savepoint_name ]
4459    /// ```
4460    Rollback {
4461        /// `true` when `AND [ NO ] CHAIN` was present.
4462        chain: bool,
4463        /// Optional savepoint name to roll back to.
4464        savepoint: Option<Ident>,
4465    },
4466    /// ```sql
4467    /// CREATE SCHEMA
4468    /// ```
4469    CreateSchema {
4470        /// `<schema name> | AUTHORIZATION <schema authorization identifier>  | <schema name>  AUTHORIZATION <schema authorization identifier>`
4471        schema_name: SchemaName,
4472        /// `true` when `IF NOT EXISTS` was present.
4473        if_not_exists: bool,
4474        /// Schema properties.
4475        ///
4476        /// ```sql
4477        /// CREATE SCHEMA myschema WITH (key1='value1');
4478        /// ```
4479        ///
4480        /// [Trino](https://trino.io/docs/current/sql/create-schema.html)
4481        with: Option<Vec<SqlOption>>,
4482        /// Schema options.
4483        ///
4484        /// ```sql
4485        /// CREATE SCHEMA myschema OPTIONS(key1='value1');
4486        /// ```
4487        ///
4488        /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_schema_statement)
4489        options: Option<Vec<SqlOption>>,
4490        /// Default collation specification for the schema.
4491        ///
4492        /// ```sql
4493        /// CREATE SCHEMA myschema DEFAULT COLLATE 'und:ci';
4494        /// ```
4495        ///
4496        /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_schema_statement)
4497        default_collate_spec: Option<Expr>,
4498        /// Clones a schema
4499        ///
4500        /// ```sql
4501        /// CREATE SCHEMA myschema CLONE otherschema
4502        /// ```
4503        ///
4504        /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-clone#databases-schemas)
4505        clone: Option<ObjectName>,
4506    },
4507    /// ```sql
4508    /// CREATE DATABASE
4509    /// ```
4510    /// See:
4511    /// <https://docs.snowflake.com/en/sql-reference/sql/create-database>
4512    CreateDatabase {
4513        /// Database name.
4514        db_name: ObjectName,
4515        /// `IF NOT EXISTS` flag.
4516        if_not_exists: bool,
4517        /// Optional location URI.
4518        location: Option<String>,
4519        /// Optional managed location.
4520        managed_location: Option<String>,
4521        /// `OR REPLACE` flag.
4522        or_replace: bool,
4523        /// `TRANSIENT` flag.
4524        transient: bool,
4525        /// Optional clone source.
4526        clone: Option<ObjectName>,
4527        /// Optional data retention time in days.
4528        data_retention_time_in_days: Option<u64>,
4529        /// Optional maximum data extension time in days.
4530        max_data_extension_time_in_days: Option<u64>,
4531        /// Optional external volume identifier.
4532        external_volume: Option<String>,
4533        /// Optional catalog name.
4534        catalog: Option<String>,
4535        /// Whether to replace invalid characters.
4536        replace_invalid_characters: Option<bool>,
4537        /// Default DDL collation string.
4538        default_ddl_collation: Option<String>,
4539        /// Storage serialization policy.
4540        storage_serialization_policy: Option<StorageSerializationPolicy>,
4541        /// Optional comment.
4542        comment: Option<String>,
4543        /// Optional default character set (MySQL).
4544        default_charset: Option<String>,
4545        /// Optional default collation (MySQL).
4546        default_collation: Option<String>,
4547        /// Optional catalog sync identifier.
4548        catalog_sync: Option<String>,
4549        /// Catalog sync namespace mode.
4550        catalog_sync_namespace_mode: Option<CatalogSyncNamespaceMode>,
4551        /// Optional flatten delimiter for namespace sync.
4552        catalog_sync_namespace_flatten_delimiter: Option<String>,
4553        /// Optional tags for the database.
4554        with_tags: Option<Vec<Tag>>,
4555        /// Optional contact entries for the database.
4556        with_contacts: Option<Vec<ContactEntry>>,
4557    },
4558    /// ```sql
4559    /// CREATE FUNCTION
4560    /// ```
4561    ///
4562    /// Supported variants:
4563    /// 1. [Hive](https://cwiki.apache.org/confluence/display/hive/languagemanual+ddl#LanguageManualDDL-Create/Drop/ReloadFunction)
4564    /// 2. [PostgreSQL](https://www.postgresql.org/docs/15/sql-createfunction.html)
4565    /// 3. [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_function_statement)
4566    /// 4. [MsSql](https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql)
4567    CreateFunction(CreateFunction),
4568    /// CREATE TRIGGER statement. See struct [CreateTrigger] for details.
4569    CreateTrigger(CreateTrigger),
4570    /// DROP TRIGGER statement. See struct [DropTrigger] for details.
4571    DropTrigger(DropTrigger),
4572    /// ```sql
4573    /// CREATE PROCEDURE
4574    /// ```
4575    CreateProcedure {
4576        /// `OR ALTER` flag.
4577        or_alter: bool,
4578        /// Procedure name.
4579        name: ObjectName,
4580        /// Optional procedure parameters.
4581        params: Option<Vec<ProcedureParam>>,
4582        /// Optional language identifier.
4583        language: Option<Ident>,
4584        /// Procedure body statements.
4585        body: ConditionalStatements,
4586    },
4587    /// ```sql
4588    /// CREATE MACRO
4589    /// ```
4590    ///
4591    /// Supported variants:
4592    /// 1. [DuckDB](https://duckdb.org/docs/sql/statements/create_macro)
4593    CreateMacro {
4594        /// `OR REPLACE` flag.
4595        or_replace: bool,
4596        /// Whether macro is temporary.
4597        temporary: bool,
4598        /// Macro name.
4599        name: ObjectName,
4600        /// Optional macro arguments.
4601        args: Option<Vec<MacroArg>>,
4602        /// Macro definition body.
4603        definition: MacroDefinition,
4604    },
4605    /// ```sql
4606    /// CREATE STAGE
4607    /// ```
4608    /// See <https://docs.snowflake.com/en/sql-reference/sql/create-stage>
4609    CreateStage {
4610        /// `OR REPLACE` flag for stage.
4611        or_replace: bool,
4612        /// Whether stage is temporary.
4613        temporary: bool,
4614        /// `IF NOT EXISTS` flag.
4615        if_not_exists: bool,
4616        /// Stage name.
4617        name: ObjectName,
4618        /// Stage parameters.
4619        stage_params: StageParamsObject,
4620        /// Directory table parameters.
4621        directory_table_params: KeyValueOptions,
4622        /// File format options.
4623        file_format: KeyValueOptions,
4624        /// Copy options for stage.
4625        copy_options: KeyValueOptions,
4626        /// Optional comment.
4627        comment: Option<String>,
4628    },
4629    /// ```sql
4630    /// ASSERT <condition> [AS <message>]
4631    /// ```
4632    Assert {
4633        /// Assertion condition expression.
4634        condition: Expr,
4635        /// Optional message expression.
4636        message: Option<Expr>,
4637    },
4638    /// ```sql
4639    /// GRANT privileges ON objects TO grantees
4640    /// ```
4641    Grant(Grant),
4642    /// ```sql
4643    /// DENY privileges ON object TO grantees
4644    /// ```
4645    Deny(DenyStatement),
4646    /// ```sql
4647    /// REVOKE privileges ON objects FROM grantees
4648    /// ```
4649    Revoke(Revoke),
4650    /// ```sql
4651    /// DEALLOCATE [ PREPARE ] { name | ALL }
4652    /// ```
4653    ///
4654    /// Note: this is a PostgreSQL-specific statement.
4655    Deallocate {
4656        /// Name to deallocate (or `ALL`).
4657        name: Ident,
4658        /// Whether `PREPARE` keyword was present.
4659        prepare: bool,
4660    },
4661    /// ```sql
4662    /// An `EXECUTE` statement
4663    /// ```
4664    ///
4665    /// Postgres: <https://www.postgresql.org/docs/current/sql-execute.html>
4666    /// MSSQL: <https://learn.microsoft.com/en-us/sql/relational-databases/stored-procedures/execute-a-stored-procedure>
4667    /// BigQuery: <https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#execute_immediate>
4668    /// Snowflake: <https://docs.snowflake.com/en/sql-reference/sql/execute-immediate>
4669    Execute {
4670        /// Optional function/procedure name.
4671        name: Option<ObjectName>,
4672        /// Parameter expressions passed to execute.
4673        parameters: Vec<Expr>,
4674        /// Whether parentheses were present around `parameters`.
4675        has_parentheses: bool,
4676        /// Is this an `EXECUTE IMMEDIATE`.
4677        immediate: bool,
4678        /// Identifiers to capture results into.
4679        into: Vec<Ident>,
4680        /// `USING` expressions with optional aliases.
4681        using: Vec<ExprWithAlias>,
4682        /// Whether the last parameter is the return value of the procedure
4683        /// MSSQL: <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/execute-transact-sql?view=sql-server-ver17#output>
4684        output: bool,
4685        /// Whether to invoke the procedure with the default parameter values
4686        /// MSSQL: <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/execute-transact-sql?view=sql-server-ver17#default>
4687        default: bool,
4688    },
4689    /// ```sql
4690    /// PREPARE name [ ( data_type [, ...] ) ] AS statement
4691    /// ```
4692    ///
4693    /// Note: this is a PostgreSQL-specific statement.
4694    Prepare {
4695        /// Name of the prepared statement.
4696        name: Ident,
4697        /// Optional data types for parameters.
4698        data_types: Vec<DataType>,
4699        /// Statement being prepared.
4700        statement: Box<Statement>,
4701    },
4702    /// ```sql
4703    /// KILL [CONNECTION | QUERY | MUTATION]
4704    /// ```
4705    ///
4706    /// See <https://clickhouse.com/docs/en/sql-reference/statements/kill/>
4707    /// See <https://dev.mysql.com/doc/refman/8.0/en/kill.html>
4708    Kill {
4709        /// Optional kill modifier (CONNECTION, QUERY, MUTATION).
4710        modifier: Option<KillType>,
4711        // processlist_id
4712        /// The id of the process to kill.
4713        id: u64,
4714    },
4715    /// ```sql
4716    /// [EXPLAIN | DESC | DESCRIBE] TABLE
4717    /// ```
4718    /// Note: this is a MySQL-specific statement. See <https://dev.mysql.com/doc/refman/8.0/en/explain.html>
4719    ExplainTable {
4720        /// `EXPLAIN | DESC | DESCRIBE`
4721        describe_alias: DescribeAlias,
4722        /// Hive style `FORMATTED | EXTENDED`
4723        hive_format: Option<HiveDescribeFormat>,
4724        /// Snowflake and ClickHouse support `DESC|DESCRIBE TABLE <table_name>` syntax
4725        ///
4726        /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/desc-table.html)
4727        /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/describe-table)
4728        has_table_keyword: bool,
4729        /// Table name
4730        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
4731        table_name: ObjectName,
4732    },
4733    /// ```sql
4734    /// [EXPLAIN | DESC | DESCRIBE]  <statement>
4735    /// ```
4736    Explain {
4737        /// `EXPLAIN | DESC | DESCRIBE`
4738        describe_alias: DescribeAlias,
4739        /// Carry out the command and show actual run times and other statistics.
4740        analyze: bool,
4741        /// Display additional information regarding the plan.
4742        verbose: bool,
4743        /// `EXPLAIN QUERY PLAN`
4744        /// Display the query plan without running the query.
4745        ///
4746        /// [SQLite](https://sqlite.org/lang_explain.html)
4747        query_plan: bool,
4748        /// `EXPLAIN ESTIMATE`
4749        /// [Clickhouse](https://clickhouse.com/docs/en/sql-reference/statements/explain#explain-estimate)
4750        estimate: bool,
4751        /// A SQL query that specifies what to explain
4752        statement: Box<Statement>,
4753        /// Optional output format of explain
4754        format: Option<AnalyzeFormatKind>,
4755        /// Postgres style utility options, `(analyze, verbose true)`
4756        options: Option<Vec<UtilityOption>>,
4757    },
4758    /// ```sql
4759    /// SAVEPOINT
4760    /// ```
4761    /// Define a new savepoint within the current transaction
4762    Savepoint {
4763        /// Name of the savepoint being defined.
4764        name: Ident,
4765    },
4766    /// ```sql
4767    /// RELEASE [ SAVEPOINT ] savepoint_name
4768    /// ```
4769    ReleaseSavepoint {
4770        /// Name of the savepoint to release.
4771        name: Ident,
4772    },
4773    /// A `MERGE` statement.
4774    ///
4775    /// ```sql
4776    /// MERGE INTO <target_table> USING <source> ON <join_expr> { matchedClause | notMatchedClause } [ ... ]
4777    /// ```
4778    /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/merge)
4779    /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/dml-syntax#merge_statement)
4780    /// [MSSQL](https://learn.microsoft.com/en-us/sql/t-sql/statements/merge-transact-sql?view=sql-server-ver16)
4781    Merge(Merge),
4782    /// ```sql
4783    /// CACHE [ FLAG ] TABLE <table_name> [ OPTIONS('K1' = 'V1', 'K2' = V2) ] [ AS ] [ <query> ]
4784    /// ```
4785    ///
4786    /// See [Spark SQL docs] for more details.
4787    ///
4788    /// [Spark SQL docs]: https://docs.databricks.com/spark/latest/spark-sql/language-manual/sql-ref-syntax-aux-cache-cache-table.html
4789    Cache {
4790        /// Table flag
4791        table_flag: Option<ObjectName>,
4792        /// Table name
4793        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
4794        table_name: ObjectName,
4795        /// `true` if `AS` keyword was present before the query.
4796        has_as: bool,
4797        /// Table confs
4798        options: Vec<SqlOption>,
4799        /// Cache table as a Query
4800        query: Option<Box<Query>>,
4801    },
4802    /// ```sql
4803    /// UNCACHE TABLE [ IF EXISTS ]  <table_name>
4804    /// ```
4805    UNCache {
4806        /// Table name
4807        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
4808        table_name: ObjectName,
4809        /// `true` when `IF EXISTS` was present.
4810        if_exists: bool,
4811    },
4812    /// ```sql
4813    /// CREATE [ { TEMPORARY | TEMP } ] SEQUENCE [ IF NOT EXISTS ] <sequence_name>
4814    /// ```
4815    /// Define a new sequence:
4816    CreateSequence {
4817        /// Whether the sequence is temporary.
4818        temporary: bool,
4819        /// `IF NOT EXISTS` flag.
4820        if_not_exists: bool,
4821        /// Sequence name.
4822        name: ObjectName,
4823        /// Optional data type for the sequence.
4824        data_type: Option<DataType>,
4825        /// Sequence options (INCREMENT, MINVALUE, etc.).
4826        sequence_options: Vec<SequenceOptions>,
4827        /// Optional `OWNED BY` target.
4828        owned_by: Option<ObjectName>,
4829    },
4830    /// A `CREATE DOMAIN` statement.
4831    CreateDomain(CreateDomain),
4832    /// ```sql
4833    /// CREATE TYPE <name>
4834    /// ```
4835    CreateType {
4836        /// Type name to create.
4837        name: ObjectName,
4838        /// Optional type representation details.
4839        representation: Option<UserDefinedTypeRepresentation>,
4840    },
4841    /// ```sql
4842    /// PRAGMA <schema-name>.<pragma-name> = <pragma-value>
4843    /// ```
4844    Pragma {
4845        /// Pragma name (possibly qualified).
4846        name: ObjectName,
4847        /// Optional pragma value.
4848        value: Option<ValueWithSpan>,
4849        /// Whether the pragma used `=`.
4850        is_eq: bool,
4851    },
4852    /// ```sql
4853    /// LOCK [ TABLE ] [ ONLY ] name [ * ] [, ...] [ IN lockmode MODE ] [ NOWAIT ]
4854    /// ```
4855    ///
4856    /// See <https://www.postgresql.org/docs/current/sql-lock.html>
4857    Lock(Lock),
4858    /// ```sql
4859    /// LOCK TABLES <table_name> [READ [LOCAL] | [LOW_PRIORITY] WRITE]
4860    /// ```
4861    /// Note: this is a MySQL-specific statement. See <https://dev.mysql.com/doc/refman/8.0/en/lock-tables.html>
4862    LockTables {
4863        /// List of tables to lock with modes.
4864        tables: Vec<LockTable>,
4865    },
4866    /// ```sql
4867    /// UNLOCK TABLES
4868    /// ```
4869    /// Note: this is a MySQL-specific statement. See <https://dev.mysql.com/doc/refman/8.0/en/lock-tables.html>
4870    UnlockTables,
4871    /// Unloads the result of a query to file
4872    ///
4873    /// [Athena](https://docs.aws.amazon.com/athena/latest/ug/unload.html):
4874    /// ```sql
4875    /// UNLOAD(statement) TO <destination> [ WITH options ]
4876    /// ```
4877    ///
4878    /// [Redshift](https://docs.aws.amazon.com/redshift/latest/dg/r_UNLOAD.html):
4879    /// ```sql
4880    /// UNLOAD('statement') TO <destination> [ OPTIONS ]
4881    /// ```
4882    Unload {
4883        /// Optional query AST to unload.
4884        query: Option<Box<Query>>,
4885        /// Optional original query text.
4886        query_text: Option<String>,
4887        /// Destination identifier.
4888        to: Ident,
4889        /// Optional IAM role/auth information.
4890        auth: Option<IamRoleKind>,
4891        /// Additional `WITH` options.
4892        with: Vec<SqlOption>,
4893        /// Legacy copy-style options.
4894        options: Vec<CopyLegacyOption>,
4895    },
4896    /// ClickHouse:
4897    /// ```sql
4898    /// OPTIMIZE TABLE [db.]name [ON CLUSTER cluster] [PARTITION partition | PARTITION ID 'partition_id'] [FINAL] [DEDUPLICATE [BY expression]]
4899    /// ```
4900    /// See ClickHouse <https://clickhouse.com/docs/en/sql-reference/statements/optimize>
4901    ///
4902    /// Databricks:
4903    /// ```sql
4904    /// OPTIMIZE table_name [WHERE predicate] [ZORDER BY (col_name1 [, ...])]
4905    /// ```
4906    /// See Databricks <https://docs.databricks.com/en/sql/language-manual/delta-optimize.html>
4907    OptimizeTable {
4908        /// Table name to optimize.
4909        name: ObjectName,
4910        /// Whether the `TABLE` keyword was present (ClickHouse uses `OPTIMIZE TABLE`, Databricks uses `OPTIMIZE`).
4911        has_table_keyword: bool,
4912        /// Optional cluster identifier.
4913        /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/optimize)
4914        on_cluster: Option<Ident>,
4915        /// Optional partition spec.
4916        /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/optimize)
4917        partition: Option<Partition>,
4918        /// Whether `FINAL` was specified.
4919        /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/optimize)
4920        include_final: bool,
4921        /// Optional deduplication settings.
4922        /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/optimize)
4923        deduplicate: Option<Deduplicate>,
4924        /// Optional WHERE predicate.
4925        /// [Databricks](https://docs.databricks.com/en/sql/language-manual/delta-optimize.html)
4926        predicate: Option<Expr>,
4927        /// Optional ZORDER BY columns.
4928        /// [Databricks](https://docs.databricks.com/en/sql/language-manual/delta-optimize.html)
4929        zorder: Option<Vec<Expr>>,
4930    },
4931    /// ```sql
4932    /// LISTEN
4933    /// ```
4934    /// listen for a notification channel
4935    ///
4936    /// See Postgres <https://www.postgresql.org/docs/current/sql-listen.html>
4937    LISTEN {
4938        /// Notification channel identifier.
4939        channel: Ident,
4940    },
4941    /// ```sql
4942    /// UNLISTEN
4943    /// ```
4944    /// stop listening for a notification
4945    ///
4946    /// See Postgres <https://www.postgresql.org/docs/current/sql-unlisten.html>
4947    UNLISTEN {
4948        /// Notification channel identifier.
4949        channel: Ident,
4950    },
4951    /// ```sql
4952    /// NOTIFY channel [ , payload ]
4953    /// ```
4954    /// send a notification event together with an optional "payload" string to channel
4955    ///
4956    /// See Postgres <https://www.postgresql.org/docs/current/sql-notify.html>
4957    NOTIFY {
4958        /// Notification channel identifier.
4959        channel: Ident,
4960        /// Optional payload string.
4961        payload: Option<String>,
4962    },
4963    /// ```sql
4964    /// LOAD DATA [LOCAL] INPATH 'filepath' [OVERWRITE] INTO TABLE tablename
4965    /// [PARTITION (partcol1=val1, partcol2=val2 ...)]
4966    /// [INPUTFORMAT 'inputformat' SERDE 'serde']
4967    /// ```
4968    /// Loading files into tables
4969    ///
4970    /// See Hive <https://cwiki.apache.org/confluence/pages/viewpage.action?pageId=27362036#LanguageManualDML-Loadingfilesintotables>
4971    LoadData {
4972        /// Whether `LOCAL` is present.
4973        local: bool,
4974        /// Input path for files to load.
4975        inpath: String,
4976        /// Whether `OVERWRITE` was specified.
4977        overwrite: bool,
4978        /// Target table name to load into.
4979        table_name: ObjectName,
4980        /// Optional partition specification.
4981        partitioned: Option<Vec<Expr>>,
4982        /// Optional table format information.
4983        table_format: Option<HiveLoadDataFormat>,
4984    },
4985    /// ```sql
4986    /// Rename TABLE tbl_name TO new_tbl_name[, tbl_name2 TO new_tbl_name2] ...
4987    /// ```
4988    /// Renames one or more tables
4989    ///
4990    /// See Mysql <https://dev.mysql.com/doc/refman/9.1/en/rename-table.html>
4991    RenameTable(Vec<RenameTable>),
4992    /// Snowflake `LIST`
4993    /// See: <https://docs.snowflake.com/en/sql-reference/sql/list>
4994    List(FileStagingCommand),
4995    /// Snowflake `REMOVE`
4996    /// See: <https://docs.snowflake.com/en/sql-reference/sql/remove>
4997    Remove(FileStagingCommand),
4998    /// RaiseError (MSSQL)
4999    /// RAISERROR ( { msg_id | msg_str | @local_variable }
5000    /// { , severity , state }
5001    /// [ , argument [ , ...n ] ] )
5002    /// [ WITH option [ , ...n ] ]
5003    /// See <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/raiserror-transact-sql?view=sql-server-ver16>
5004    RaisError {
5005        /// Error message expression or identifier.
5006        message: Box<Expr>,
5007        /// Severity expression.
5008        severity: Box<Expr>,
5009        /// State expression.
5010        state: Box<Expr>,
5011        /// Substitution arguments for the message.
5012        arguments: Vec<Expr>,
5013        /// Additional `WITH` options for RAISERROR.
5014        options: Vec<RaisErrorOption>,
5015    },
5016    /// A MSSQL `THROW` statement.
5017    Throw(ThrowStatement),
5018    /// ```sql
5019    /// PRINT msg_str | @local_variable | string_expr
5020    /// ```
5021    ///
5022    /// See: <https://learn.microsoft.com/en-us/sql/t-sql/statements/print-transact-sql>
5023    Print(PrintStatement),
5024    /// MSSQL `WAITFOR` statement.
5025    ///
5026    /// See: <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/waitfor-transact-sql>
5027    WaitFor(WaitForStatement),
5028    /// ```sql
5029    /// RETURN [ expression ]
5030    /// ```
5031    ///
5032    /// See [ReturnStatement]
5033    Return(ReturnStatement),
5034    /// Export data statement
5035    ///
5036    /// Example:
5037    /// ```sql
5038    /// EXPORT DATA OPTIONS(uri='gs://bucket/folder/*', format='PARQUET', overwrite=true) AS
5039    /// SELECT field1, field2 FROM mydataset.table1 ORDER BY field1 LIMIT 10
5040    /// ```
5041    /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/export-statements)
5042    ExportData(ExportData),
5043    /// ```sql
5044    /// CREATE [OR REPLACE] USER <user> [IF NOT EXISTS]
5045    /// ```
5046    /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-user)
5047    CreateUser(CreateUser),
5048    /// ```sql
5049    /// ALTER USER \[ IF EXISTS \] \[ <name> \]
5050    /// ```
5051    /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/alter-user)
5052    AlterUser(AlterUser),
5053    /// Re-sorts rows and reclaims space in either a specified table or all tables in the current database
5054    ///
5055    /// ```sql
5056    /// VACUUM tbl
5057    /// ```
5058    /// [Redshift](https://docs.aws.amazon.com/redshift/latest/dg/r_VACUUM_command.html)
5059    Vacuum(VacuumStatement),
5060    /// Restore the value of a run-time parameter to the default value.
5061    ///
5062    /// ```sql
5063    /// RESET configuration_parameter;
5064    /// RESET ALL;
5065    /// ```
5066    /// [PostgreSQL](https://www.postgresql.org/docs/current/sql-reset.html)
5067    Reset(ResetStatement),
5068}
5069
5070impl From<Analyze> for Statement {
5071    fn from(analyze: Analyze) -> Self {
5072        Statement::Analyze(analyze)
5073    }
5074}
5075
5076impl From<ddl::Truncate> for Statement {
5077    fn from(truncate: ddl::Truncate) -> Self {
5078        Statement::Truncate(truncate)
5079    }
5080}
5081
5082impl From<Lock> for Statement {
5083    fn from(lock: Lock) -> Self {
5084        Statement::Lock(lock)
5085    }
5086}
5087
5088impl From<ddl::Msck> for Statement {
5089    fn from(msck: ddl::Msck) -> Self {
5090        Statement::Msck(msck)
5091    }
5092}
5093
5094/// ```sql
5095/// {COPY | REVOKE} CURRENT GRANTS
5096/// ```
5097///
5098/// - [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/grant-ownership#optional-parameters)
5099#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
5100#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
5101#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
5102pub enum CurrentGrantsKind {
5103    /// `COPY CURRENT GRANTS` (copy current grants to target).
5104    CopyCurrentGrants,
5105    /// `REVOKE CURRENT GRANTS` (revoke current grants from target).
5106    RevokeCurrentGrants,
5107}
5108
5109impl fmt::Display for CurrentGrantsKind {
5110    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
5111        match self {
5112            CurrentGrantsKind::CopyCurrentGrants => write!(f, "COPY CURRENT GRANTS"),
5113            CurrentGrantsKind::RevokeCurrentGrants => write!(f, "REVOKE CURRENT GRANTS"),
5114        }
5115    }
5116}
5117
5118#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
5119#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
5120#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
5121/// `RAISERROR` options
5122/// See <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/raiserror-transact-sql?view=sql-server-ver16#options>
5123pub enum RaisErrorOption {
5124    /// Log the error.
5125    Log,
5126    /// Do not wait for completion.
5127    NoWait,
5128    /// Set the error state.
5129    SetError,
5130}
5131
5132impl fmt::Display for RaisErrorOption {
5133    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
5134        match self {
5135            RaisErrorOption::Log => write!(f, "LOG"),
5136            RaisErrorOption::NoWait => write!(f, "NOWAIT"),
5137            RaisErrorOption::SetError => write!(f, "SETERROR"),
5138        }
5139    }
5140}
5141
5142impl fmt::Display for Statement {
5143    /// Formats a SQL statement with support for pretty printing.
5144    ///
5145    /// When using the alternate flag (`{:#}`), the statement will be formatted with proper
5146    /// indentation and line breaks. For example:
5147    ///
5148    /// ```
5149    /// # use sqlparser::dialect::GenericDialect;
5150    /// # use sqlparser::parser::Parser;
5151    /// let sql = "SELECT a, b FROM table_1";
5152    /// let ast = Parser::parse_sql(&GenericDialect, sql).unwrap();
5153    ///
5154    /// // Regular formatting
5155    /// assert_eq!(format!("{}", ast[0]), "SELECT a, b FROM table_1");
5156    ///
5157    /// // Pretty printing
5158    /// assert_eq!(format!("{:#}", ast[0]),
5159    /// r#"SELECT
5160    ///   a,
5161    ///   b
5162    /// FROM
5163    ///   table_1"#);
5164    /// ```
5165    // Clippy thinks this function is too complicated, but it is painful to
5166    // split up without extracting structs for each `Statement` variant.
5167    #[allow(clippy::cognitive_complexity)]
5168    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
5169        match self {
5170            Statement::Flush {
5171                object_type,
5172                location,
5173                channel,
5174                read_lock,
5175                export,
5176                tables,
5177            } => {
5178                write!(f, "FLUSH")?;
5179                if let Some(location) = location {
5180                    f.write_str(" ")?;
5181                    location.fmt(f)?;
5182                }
5183                write!(f, " {object_type}")?;
5184
5185                if let Some(channel) = channel {
5186                    write!(f, " FOR CHANNEL {channel}")?;
5187                }
5188
5189                write!(
5190                    f,
5191                    "{tables}{read}{export}",
5192                    tables = if !tables.is_empty() {
5193                        format!(" {}", display_comma_separated(tables))
5194                    } else {
5195                        String::new()
5196                    },
5197                    export = if *export { " FOR EXPORT" } else { "" },
5198                    read = if *read_lock { " WITH READ LOCK" } else { "" }
5199                )
5200            }
5201            Statement::Kill { modifier, id } => {
5202                write!(f, "KILL ")?;
5203
5204                if let Some(m) = modifier {
5205                    write!(f, "{m} ")?;
5206                }
5207
5208                write!(f, "{id}")
5209            }
5210            Statement::ExplainTable {
5211                describe_alias,
5212                hive_format,
5213                has_table_keyword,
5214                table_name,
5215            } => {
5216                write!(f, "{describe_alias} ")?;
5217
5218                if let Some(format) = hive_format {
5219                    write!(f, "{format} ")?;
5220                }
5221                if *has_table_keyword {
5222                    write!(f, "TABLE ")?;
5223                }
5224
5225                write!(f, "{table_name}")
5226            }
5227            Statement::Explain {
5228                describe_alias,
5229                verbose,
5230                analyze,
5231                query_plan,
5232                estimate,
5233                statement,
5234                format,
5235                options,
5236            } => {
5237                write!(f, "{describe_alias} ")?;
5238
5239                if *query_plan {
5240                    write!(f, "QUERY PLAN ")?;
5241                }
5242                if *analyze {
5243                    write!(f, "ANALYZE ")?;
5244                }
5245                if *estimate {
5246                    write!(f, "ESTIMATE ")?;
5247                }
5248
5249                if *verbose {
5250                    write!(f, "VERBOSE ")?;
5251                }
5252
5253                if let Some(format) = format {
5254                    write!(f, "{format} ")?;
5255                }
5256
5257                if let Some(options) = options {
5258                    write!(f, "({}) ", display_comma_separated(options))?;
5259                }
5260
5261                write!(f, "{statement}")
5262            }
5263            Statement::Query(s) => s.fmt(f),
5264            Statement::Declare { stmts } => {
5265                write!(f, "DECLARE ")?;
5266                write!(f, "{}", display_separated(stmts, "; "))
5267            }
5268            Statement::Fetch {
5269                name,
5270                direction,
5271                position,
5272                into,
5273            } => {
5274                write!(f, "FETCH {direction} {position} {name}")?;
5275
5276                if let Some(into) = into {
5277                    write!(f, " INTO {into}")?;
5278                }
5279
5280                Ok(())
5281            }
5282            Statement::Directory {
5283                overwrite,
5284                local,
5285                path,
5286                file_format,
5287                source,
5288            } => {
5289                write!(
5290                    f,
5291                    "INSERT{overwrite}{local} DIRECTORY '{path}'",
5292                    overwrite = if *overwrite { " OVERWRITE" } else { "" },
5293                    local = if *local { " LOCAL" } else { "" },
5294                    path = path
5295                )?;
5296                if let Some(ref ff) = file_format {
5297                    write!(f, " STORED AS {ff}")?
5298                }
5299                write!(f, " {source}")
5300            }
5301            Statement::Msck(msck) => msck.fmt(f),
5302            Statement::Truncate(truncate) => truncate.fmt(f),
5303            Statement::Case(stmt) => {
5304                write!(f, "{stmt}")
5305            }
5306            Statement::If(stmt) => {
5307                write!(f, "{stmt}")
5308            }
5309            Statement::While(stmt) => {
5310                write!(f, "{stmt}")
5311            }
5312            Statement::Raise(stmt) => {
5313                write!(f, "{stmt}")
5314            }
5315            Statement::AttachDatabase {
5316                schema_name,
5317                database_file_name,
5318                database,
5319            } => {
5320                let keyword = if *database { "DATABASE " } else { "" };
5321                write!(f, "ATTACH {keyword}{database_file_name} AS {schema_name}")
5322            }
5323            Statement::AttachDuckDBDatabase {
5324                if_not_exists,
5325                database,
5326                database_path,
5327                database_alias,
5328                attach_options,
5329            } => {
5330                write!(
5331                    f,
5332                    "ATTACH{database}{if_not_exists} {database_path}",
5333                    database = if *database { " DATABASE" } else { "" },
5334                    if_not_exists = if *if_not_exists { " IF NOT EXISTS" } else { "" },
5335                )?;
5336                if let Some(alias) = database_alias {
5337                    write!(f, " AS {alias}")?;
5338                }
5339                if !attach_options.is_empty() {
5340                    write!(f, " ({})", display_comma_separated(attach_options))?;
5341                }
5342                Ok(())
5343            }
5344            Statement::DetachDuckDBDatabase {
5345                if_exists,
5346                database,
5347                database_alias,
5348            } => {
5349                write!(
5350                    f,
5351                    "DETACH{database}{if_exists} {database_alias}",
5352                    database = if *database { " DATABASE" } else { "" },
5353                    if_exists = if *if_exists { " IF EXISTS" } else { "" },
5354                )?;
5355                Ok(())
5356            }
5357            Statement::Analyze(analyze) => analyze.fmt(f),
5358            Statement::Insert(insert) => insert.fmt(f),
5359            Statement::Install {
5360                extension_name: name,
5361            } => write!(f, "INSTALL {name}"),
5362
5363            Statement::Load {
5364                extension_name: name,
5365            } => write!(f, "LOAD {name}"),
5366
5367            Statement::Call(function) => write!(f, "CALL {function}"),
5368
5369            Statement::Copy {
5370                source,
5371                to,
5372                target,
5373                options,
5374                legacy_options,
5375                values,
5376            } => {
5377                write!(f, "COPY")?;
5378                match source {
5379                    CopySource::Query(query) => write!(f, " ({query})")?,
5380                    CopySource::Table {
5381                        table_name,
5382                        columns,
5383                    } => {
5384                        write!(f, " {table_name}")?;
5385                        if !columns.is_empty() {
5386                            write!(f, " ({})", display_comma_separated(columns))?;
5387                        }
5388                    }
5389                }
5390                write!(f, " {} {}", if *to { "TO" } else { "FROM" }, target)?;
5391                if !options.is_empty() {
5392                    write!(f, " ({})", display_comma_separated(options))?;
5393                }
5394                if !legacy_options.is_empty() {
5395                    write!(f, " {}", display_separated(legacy_options, " "))?;
5396                }
5397                if !values.is_empty() {
5398                    writeln!(f, ";")?;
5399                    let mut delim = "";
5400                    for v in values {
5401                        write!(f, "{delim}")?;
5402                        delim = "\t";
5403                        if let Some(v) = v {
5404                            write!(f, "{v}")?;
5405                        } else {
5406                            write!(f, "\\N")?;
5407                        }
5408                    }
5409                    write!(f, "\n\\.")?;
5410                }
5411                Ok(())
5412            }
5413            Statement::Update(update) => update.fmt(f),
5414            Statement::Delete(delete) => delete.fmt(f),
5415            Statement::Open(open) => open.fmt(f),
5416            Statement::Close { cursor } => {
5417                write!(f, "CLOSE {cursor}")?;
5418
5419                Ok(())
5420            }
5421            Statement::CreateDatabase {
5422                db_name,
5423                if_not_exists,
5424                location,
5425                managed_location,
5426                or_replace,
5427                transient,
5428                clone,
5429                data_retention_time_in_days,
5430                max_data_extension_time_in_days,
5431                external_volume,
5432                catalog,
5433                replace_invalid_characters,
5434                default_ddl_collation,
5435                storage_serialization_policy,
5436                comment,
5437                default_charset,
5438                default_collation,
5439                catalog_sync,
5440                catalog_sync_namespace_mode,
5441                catalog_sync_namespace_flatten_delimiter,
5442                with_tags,
5443                with_contacts,
5444            } => {
5445                write!(
5446                    f,
5447                    "CREATE {or_replace}{transient}DATABASE {if_not_exists}{name}",
5448                    or_replace = if *or_replace { "OR REPLACE " } else { "" },
5449                    transient = if *transient { "TRANSIENT " } else { "" },
5450                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
5451                    name = db_name,
5452                )?;
5453
5454                if let Some(l) = location {
5455                    write!(f, " LOCATION '{l}'")?;
5456                }
5457                if let Some(ml) = managed_location {
5458                    write!(f, " MANAGEDLOCATION '{ml}'")?;
5459                }
5460                if let Some(clone) = clone {
5461                    write!(f, " CLONE {clone}")?;
5462                }
5463
5464                if let Some(value) = data_retention_time_in_days {
5465                    write!(f, " DATA_RETENTION_TIME_IN_DAYS = {value}")?;
5466                }
5467
5468                if let Some(value) = max_data_extension_time_in_days {
5469                    write!(f, " MAX_DATA_EXTENSION_TIME_IN_DAYS = {value}")?;
5470                }
5471
5472                if let Some(vol) = external_volume {
5473                    write!(f, " EXTERNAL_VOLUME = '{vol}'")?;
5474                }
5475
5476                if let Some(cat) = catalog {
5477                    write!(f, " CATALOG = '{cat}'")?;
5478                }
5479
5480                if let Some(true) = replace_invalid_characters {
5481                    write!(f, " REPLACE_INVALID_CHARACTERS = TRUE")?;
5482                } else if let Some(false) = replace_invalid_characters {
5483                    write!(f, " REPLACE_INVALID_CHARACTERS = FALSE")?;
5484                }
5485
5486                if let Some(collation) = default_ddl_collation {
5487                    write!(f, " DEFAULT_DDL_COLLATION = '{collation}'")?;
5488                }
5489
5490                if let Some(policy) = storage_serialization_policy {
5491                    write!(f, " STORAGE_SERIALIZATION_POLICY = {policy}")?;
5492                }
5493
5494                if let Some(comment) = comment {
5495                    write!(f, " COMMENT = '{comment}'")?;
5496                }
5497
5498                if let Some(charset) = default_charset {
5499                    write!(f, " DEFAULT CHARACTER SET {charset}")?;
5500                }
5501
5502                if let Some(collation) = default_collation {
5503                    write!(f, " DEFAULT COLLATE {collation}")?;
5504                }
5505
5506                if let Some(sync) = catalog_sync {
5507                    write!(f, " CATALOG_SYNC = '{sync}'")?;
5508                }
5509
5510                if let Some(mode) = catalog_sync_namespace_mode {
5511                    write!(f, " CATALOG_SYNC_NAMESPACE_MODE = {mode}")?;
5512                }
5513
5514                if let Some(delim) = catalog_sync_namespace_flatten_delimiter {
5515                    write!(f, " CATALOG_SYNC_NAMESPACE_FLATTEN_DELIMITER = '{delim}'")?;
5516                }
5517
5518                if let Some(tags) = with_tags {
5519                    write!(f, " WITH TAG ({})", display_comma_separated(tags))?;
5520                }
5521
5522                if let Some(contacts) = with_contacts {
5523                    write!(f, " WITH CONTACT ({})", display_comma_separated(contacts))?;
5524                }
5525                Ok(())
5526            }
5527            Statement::CreateFunction(create_function) => create_function.fmt(f),
5528            Statement::CreateDomain(create_domain) => create_domain.fmt(f),
5529            Statement::CreateTrigger(create_trigger) => create_trigger.fmt(f),
5530            Statement::DropTrigger(drop_trigger) => drop_trigger.fmt(f),
5531            Statement::CreateProcedure {
5532                name,
5533                or_alter,
5534                params,
5535                language,
5536                body,
5537            } => {
5538                write!(
5539                    f,
5540                    "CREATE {or_alter}PROCEDURE {name}",
5541                    or_alter = if *or_alter { "OR ALTER " } else { "" },
5542                    name = name
5543                )?;
5544
5545                if let Some(p) = params {
5546                    if !p.is_empty() {
5547                        write!(f, " ({})", display_comma_separated(p))?;
5548                    }
5549                }
5550
5551                if let Some(language) = language {
5552                    write!(f, " LANGUAGE {language}")?;
5553                }
5554
5555                write!(f, " AS {body}")
5556            }
5557            Statement::CreateMacro {
5558                or_replace,
5559                temporary,
5560                name,
5561                args,
5562                definition,
5563            } => {
5564                write!(
5565                    f,
5566                    "CREATE {or_replace}{temp}MACRO {name}",
5567                    temp = if *temporary { "TEMPORARY " } else { "" },
5568                    or_replace = if *or_replace { "OR REPLACE " } else { "" },
5569                )?;
5570                if let Some(args) = args {
5571                    write!(f, "({})", display_comma_separated(args))?;
5572                }
5573                match definition {
5574                    MacroDefinition::Expr(expr) => write!(f, " AS {expr}")?,
5575                    MacroDefinition::Table(query) => write!(f, " AS TABLE {query}")?,
5576                }
5577                Ok(())
5578            }
5579            Statement::CreateView(create_view) => create_view.fmt(f),
5580            Statement::CreateTable(create_table) => create_table.fmt(f),
5581            Statement::LoadData {
5582                local,
5583                inpath,
5584                overwrite,
5585                table_name,
5586                partitioned,
5587                table_format,
5588            } => {
5589                write!(
5590                    f,
5591                    "LOAD DATA {local}INPATH '{inpath}' {overwrite}INTO TABLE {table_name}",
5592                    local = if *local { "LOCAL " } else { "" },
5593                    inpath = inpath,
5594                    overwrite = if *overwrite { "OVERWRITE " } else { "" },
5595                    table_name = table_name,
5596                )?;
5597                if let Some(ref parts) = &partitioned {
5598                    if !parts.is_empty() {
5599                        write!(f, " PARTITION ({})", display_comma_separated(parts))?;
5600                    }
5601                }
5602                if let Some(HiveLoadDataFormat {
5603                    serde,
5604                    input_format,
5605                }) = &table_format
5606                {
5607                    write!(f, " INPUTFORMAT {input_format} SERDE {serde}")?;
5608                }
5609                Ok(())
5610            }
5611            Statement::CreateVirtualTable {
5612                name,
5613                if_not_exists,
5614                module_name,
5615                module_args,
5616            } => {
5617                write!(
5618                    f,
5619                    "CREATE VIRTUAL TABLE {if_not_exists}{name} USING {module_name}",
5620                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
5621                    name = name,
5622                    module_name = module_name
5623                )?;
5624                if !module_args.is_empty() {
5625                    write!(f, " ({})", display_comma_separated(module_args))?;
5626                }
5627                Ok(())
5628            }
5629            Statement::CreateIndex(create_index) => create_index.fmt(f),
5630            Statement::CreateExtension(create_extension) => write!(f, "{create_extension}"),
5631            Statement::CreateCollation(create_collation) => write!(f, "{create_collation}"),
5632            Statement::CreateTextSearchConfiguration(v) => write!(f, "{v}"),
5633            Statement::CreateTextSearchDictionary(v) => write!(f, "{v}"),
5634            Statement::CreateTextSearchParser(v) => write!(f, "{v}"),
5635            Statement::CreateTextSearchTemplate(v) => write!(f, "{v}"),
5636            Statement::CreatePublication(v) => write!(f, "{v}"),
5637            Statement::CreateSubscription(v) => write!(f, "{v}"),
5638            Statement::CreateCast(v) => write!(f, "{v}"),
5639            Statement::CreateConversion(v) => write!(f, "{v}"),
5640            Statement::CreateLanguage(v) => write!(f, "{v}"),
5641            Statement::CreateRule(v) => write!(f, "{v}"),
5642            Statement::CreateStatistics(v) => write!(f, "{v}"),
5643            Statement::CreateAccessMethod(v) => write!(f, "{v}"),
5644            Statement::CreateEventTrigger(v) => write!(f, "{v}"),
5645            Statement::CreateTransform(v) => write!(f, "{v}"),
5646            Statement::SecurityLabel(v) => write!(f, "{v}"),
5647            Statement::CreateUserMapping(v) => write!(f, "{v}"),
5648            Statement::CreateTablespace(v) => write!(f, "{v}"),
5649            Statement::DropExtension(drop_extension) => write!(f, "{drop_extension}"),
5650            Statement::DropOperator(drop_operator) => write!(f, "{drop_operator}"),
5651            Statement::DropOperatorFamily(drop_operator_family) => {
5652                write!(f, "{drop_operator_family}")
5653            }
5654            Statement::DropOperatorClass(drop_operator_class) => {
5655                write!(f, "{drop_operator_class}")
5656            }
5657            Statement::CreateRole(create_role) => write!(f, "{create_role}"),
5658            Statement::CreateSecret {
5659                or_replace,
5660                temporary,
5661                if_not_exists,
5662                name,
5663                storage_specifier,
5664                secret_type,
5665                options,
5666            } => {
5667                write!(
5668                    f,
5669                    "CREATE {or_replace}",
5670                    or_replace = if *or_replace { "OR REPLACE " } else { "" },
5671                )?;
5672                if let Some(t) = temporary {
5673                    write!(f, "{}", if *t { "TEMPORARY " } else { "PERSISTENT " })?;
5674                }
5675                write!(
5676                    f,
5677                    "SECRET {if_not_exists}",
5678                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
5679                )?;
5680                if let Some(n) = name {
5681                    write!(f, "{n} ")?;
5682                };
5683                if let Some(s) = storage_specifier {
5684                    write!(f, "IN {s} ")?;
5685                }
5686                write!(f, "( TYPE {secret_type}",)?;
5687                if !options.is_empty() {
5688                    write!(f, ", {o}", o = display_comma_separated(options))?;
5689                }
5690                write!(f, " )")?;
5691                Ok(())
5692            }
5693            Statement::CreateServer(stmt) => {
5694                write!(f, "{stmt}")
5695            }
5696            Statement::CreateForeignDataWrapper(stmt) => write!(f, "{stmt}"),
5697            Statement::CreateForeignTable(stmt) => write!(f, "{stmt}"),
5698            Statement::CreatePolicy(policy) => write!(f, "{policy}"),
5699            Statement::CreateConnector(create_connector) => create_connector.fmt(f),
5700            Statement::CreateOperator(create_operator) => create_operator.fmt(f),
5701            Statement::CreateOperatorFamily(create_operator_family) => {
5702                create_operator_family.fmt(f)
5703            }
5704            Statement::CreateOperatorClass(create_operator_class) => create_operator_class.fmt(f),
5705            Statement::CreateAggregate(create_aggregate) => create_aggregate.fmt(f),
5706            Statement::AlterTable(alter_table) => write!(f, "{alter_table}"),
5707            Statement::AlterIndex { name, operation } => {
5708                write!(f, "ALTER INDEX {name} {operation}")
5709            }
5710            Statement::AlterView {
5711                name,
5712                columns,
5713                query,
5714                with_options,
5715            } => {
5716                write!(f, "ALTER VIEW {name}")?;
5717                if !with_options.is_empty() {
5718                    write!(f, " WITH ({})", display_comma_separated(with_options))?;
5719                }
5720                if !columns.is_empty() {
5721                    write!(f, " ({})", display_comma_separated(columns))?;
5722                }
5723                write!(f, " AS {query}")
5724            }
5725            Statement::AlterDomain(alter_domain) => write!(f, "{alter_domain}"),
5726            Statement::AlterExtension(alter_extension) => write!(f, "{alter_extension}"),
5727            Statement::AlterFunction(alter_function) => write!(f, "{alter_function}"),
5728            Statement::AlterTrigger(alter_trigger) => write!(f, "{alter_trigger}"),
5729            Statement::AlterType(AlterType { name, operation }) => {
5730                write!(f, "ALTER TYPE {name} {operation}")
5731            }
5732            Statement::AlterCollation(alter_collation) => write!(f, "{alter_collation}"),
5733            Statement::AlterDefaultPrivileges(alter_default_privileges) => {
5734                write!(f, "{alter_default_privileges}")
5735            }
5736            Statement::AlterOperator(alter_operator) => write!(f, "{alter_operator}"),
5737            Statement::AlterOperatorFamily(alter_operator_family) => {
5738                write!(f, "{alter_operator_family}")
5739            }
5740            Statement::AlterOperatorClass(alter_operator_class) => {
5741                write!(f, "{alter_operator_class}")
5742            }
5743            Statement::AlterRole { name, operation } => {
5744                write!(f, "ALTER ROLE {name} {operation}")
5745            }
5746            Statement::AlterPolicy(alter_policy) => write!(f, "{alter_policy}"),
5747            Statement::AlterConnector {
5748                name,
5749                properties,
5750                url,
5751                owner,
5752            } => {
5753                write!(f, "ALTER CONNECTOR {name}")?;
5754                if let Some(properties) = properties {
5755                    write!(
5756                        f,
5757                        " SET DCPROPERTIES({})",
5758                        display_comma_separated(properties)
5759                    )?;
5760                }
5761                if let Some(url) = url {
5762                    write!(f, " SET URL '{url}'")?;
5763                }
5764                if let Some(owner) = owner {
5765                    write!(f, " SET OWNER {owner}")?;
5766                }
5767                Ok(())
5768            }
5769            Statement::AlterSession {
5770                set,
5771                session_params,
5772            } => {
5773                write!(
5774                    f,
5775                    "ALTER SESSION {set}",
5776                    set = if *set { "SET" } else { "UNSET" }
5777                )?;
5778                if !session_params.options.is_empty() {
5779                    if *set {
5780                        write!(f, " {session_params}")?;
5781                    } else {
5782                        let options = session_params
5783                            .options
5784                            .iter()
5785                            .map(|p| p.option_name.clone())
5786                            .collect::<Vec<_>>();
5787                        write!(f, " {}", display_separated(&options, ", "))?;
5788                    }
5789                }
5790                Ok(())
5791            }
5792            Statement::Drop {
5793                object_type,
5794                if_exists,
5795                names,
5796                cascade,
5797                restrict,
5798                purge,
5799                temporary,
5800                table,
5801            } => {
5802                write!(
5803                    f,
5804                    "DROP {}{}{} {}{}{}{}",
5805                    if *temporary { "TEMPORARY " } else { "" },
5806                    object_type,
5807                    if *if_exists { " IF EXISTS" } else { "" },
5808                    display_comma_separated(names),
5809                    if *cascade { " CASCADE" } else { "" },
5810                    if *restrict { " RESTRICT" } else { "" },
5811                    if *purge { " PURGE" } else { "" },
5812                )?;
5813                if let Some(table_name) = table.as_ref() {
5814                    write!(f, " ON {table_name}")?;
5815                };
5816                Ok(())
5817            }
5818            Statement::DropFunction(drop_function) => write!(f, "{drop_function}"),
5819            Statement::DropDomain(DropDomain {
5820                if_exists,
5821                name,
5822                drop_behavior,
5823            }) => {
5824                write!(
5825                    f,
5826                    "DROP DOMAIN{} {name}",
5827                    if *if_exists { " IF EXISTS" } else { "" },
5828                )?;
5829                if let Some(op) = drop_behavior {
5830                    write!(f, " {op}")?;
5831                }
5832                Ok(())
5833            }
5834            Statement::DropProcedure {
5835                if_exists,
5836                proc_desc,
5837                drop_behavior,
5838            } => {
5839                write!(
5840                    f,
5841                    "DROP PROCEDURE{} {}",
5842                    if *if_exists { " IF EXISTS" } else { "" },
5843                    display_comma_separated(proc_desc),
5844                )?;
5845                if let Some(op) = drop_behavior {
5846                    write!(f, " {op}")?;
5847                }
5848                Ok(())
5849            }
5850            Statement::DropSecret {
5851                if_exists,
5852                temporary,
5853                name,
5854                storage_specifier,
5855            } => {
5856                write!(f, "DROP ")?;
5857                if let Some(t) = temporary {
5858                    write!(f, "{}", if *t { "TEMPORARY " } else { "PERSISTENT " })?;
5859                }
5860                write!(
5861                    f,
5862                    "SECRET {if_exists}{name}",
5863                    if_exists = if *if_exists { "IF EXISTS " } else { "" },
5864                )?;
5865                if let Some(s) = storage_specifier {
5866                    write!(f, " FROM {s}")?;
5867                }
5868                Ok(())
5869            }
5870            Statement::DropPolicy(policy) => write!(f, "{policy}"),
5871            Statement::DropConnector { if_exists, name } => {
5872                write!(
5873                    f,
5874                    "DROP CONNECTOR {if_exists}{name}",
5875                    if_exists = if *if_exists { "IF EXISTS " } else { "" }
5876                )?;
5877                Ok(())
5878            }
5879            Statement::Discard { object_type } => {
5880                write!(f, "DISCARD {object_type}")?;
5881                Ok(())
5882            }
5883            Self::Set(set) => write!(f, "{set}"),
5884            Statement::ShowVariable { variable } => {
5885                write!(f, "SHOW")?;
5886                if !variable.is_empty() {
5887                    write!(f, " {}", display_separated(variable, " "))?;
5888                }
5889                Ok(())
5890            }
5891            Statement::ShowStatus {
5892                filter,
5893                global,
5894                session,
5895            } => {
5896                write!(f, "SHOW")?;
5897                if *global {
5898                    write!(f, " GLOBAL")?;
5899                }
5900                if *session {
5901                    write!(f, " SESSION")?;
5902                }
5903                write!(f, " STATUS")?;
5904                if filter.is_some() {
5905                    write!(f, " {}", filter.as_ref().unwrap())?;
5906                }
5907                Ok(())
5908            }
5909            Statement::ShowVariables {
5910                filter,
5911                global,
5912                session,
5913            } => {
5914                write!(f, "SHOW")?;
5915                if *global {
5916                    write!(f, " GLOBAL")?;
5917                }
5918                if *session {
5919                    write!(f, " SESSION")?;
5920                }
5921                write!(f, " VARIABLES")?;
5922                if filter.is_some() {
5923                    write!(f, " {}", filter.as_ref().unwrap())?;
5924                }
5925                Ok(())
5926            }
5927            Statement::ShowCreate { obj_type, obj_name } => {
5928                write!(f, "SHOW CREATE {obj_type} {obj_name}",)?;
5929                Ok(())
5930            }
5931            Statement::ShowColumns {
5932                extended,
5933                full,
5934                show_options,
5935            } => {
5936                write!(
5937                    f,
5938                    "SHOW {extended}{full}COLUMNS{show_options}",
5939                    extended = if *extended { "EXTENDED " } else { "" },
5940                    full = if *full { "FULL " } else { "" },
5941                )?;
5942                Ok(())
5943            }
5944            Statement::ShowDatabases {
5945                terse,
5946                history,
5947                show_options,
5948            } => {
5949                write!(
5950                    f,
5951                    "SHOW {terse}DATABASES{history}{show_options}",
5952                    terse = if *terse { "TERSE " } else { "" },
5953                    history = if *history { " HISTORY" } else { "" },
5954                )?;
5955                Ok(())
5956            }
5957            Statement::ShowCatalogs {
5958                terse,
5959                history,
5960                show_options,
5961            } => {
5962                write!(
5963                    f,
5964                    "SHOW {terse}CATALOGS{history}{show_options}",
5965                    terse = if *terse { "TERSE " } else { "" },
5966                    history = if *history { " HISTORY" } else { "" },
5967                )?;
5968                Ok(())
5969            }
5970            Statement::ShowProcessList { full } => {
5971                write!(
5972                    f,
5973                    "SHOW {full}PROCESSLIST",
5974                    full = if *full { "FULL " } else { "" },
5975                )?;
5976                Ok(())
5977            }
5978            Statement::ShowSchemas {
5979                terse,
5980                history,
5981                show_options,
5982            } => {
5983                write!(
5984                    f,
5985                    "SHOW {terse}SCHEMAS{history}{show_options}",
5986                    terse = if *terse { "TERSE " } else { "" },
5987                    history = if *history { " HISTORY" } else { "" },
5988                )?;
5989                Ok(())
5990            }
5991            Statement::ShowObjects(ShowObjects {
5992                terse,
5993                show_options,
5994            }) => {
5995                write!(
5996                    f,
5997                    "SHOW {terse}OBJECTS{show_options}",
5998                    terse = if *terse { "TERSE " } else { "" },
5999                )?;
6000                Ok(())
6001            }
6002            Statement::ShowTables {
6003                terse,
6004                history,
6005                extended,
6006                full,
6007                external,
6008                show_options,
6009            } => {
6010                write!(
6011                    f,
6012                    "SHOW {terse}{extended}{full}{external}TABLES{history}{show_options}",
6013                    terse = if *terse { "TERSE " } else { "" },
6014                    extended = if *extended { "EXTENDED " } else { "" },
6015                    full = if *full { "FULL " } else { "" },
6016                    external = if *external { "EXTERNAL " } else { "" },
6017                    history = if *history { " HISTORY" } else { "" },
6018                )?;
6019                Ok(())
6020            }
6021            Statement::ShowViews {
6022                terse,
6023                materialized,
6024                show_options,
6025            } => {
6026                write!(
6027                    f,
6028                    "SHOW {terse}{materialized}VIEWS{show_options}",
6029                    terse = if *terse { "TERSE " } else { "" },
6030                    materialized = if *materialized { "MATERIALIZED " } else { "" }
6031                )?;
6032                Ok(())
6033            }
6034            Statement::ShowFunctions { filter } => {
6035                write!(f, "SHOW FUNCTIONS")?;
6036                if let Some(filter) = filter {
6037                    write!(f, " {filter}")?;
6038                }
6039                Ok(())
6040            }
6041            Statement::Use(use_expr) => use_expr.fmt(f),
6042            Statement::ShowCollation { filter } => {
6043                write!(f, "SHOW COLLATION")?;
6044                if let Some(filter) = filter {
6045                    write!(f, " {filter}")?;
6046                }
6047                Ok(())
6048            }
6049            Statement::ShowCharset(show_stm) => show_stm.fmt(f),
6050            Statement::StartTransaction {
6051                modes,
6052                begin: syntax_begin,
6053                transaction,
6054                modifier,
6055                statements,
6056                exception,
6057                has_end_keyword,
6058            } => {
6059                if *syntax_begin {
6060                    if let Some(modifier) = *modifier {
6061                        write!(f, "BEGIN {modifier}")?;
6062                    } else {
6063                        write!(f, "BEGIN")?;
6064                    }
6065                } else {
6066                    write!(f, "START")?;
6067                }
6068                if let Some(transaction) = transaction {
6069                    write!(f, " {transaction}")?;
6070                }
6071                if !modes.is_empty() {
6072                    write!(f, " {}", display_comma_separated(modes))?;
6073                }
6074                if !statements.is_empty() {
6075                    write!(f, " ")?;
6076                    format_statement_list(f, statements)?;
6077                }
6078                if let Some(exception_when) = exception {
6079                    write!(f, " EXCEPTION")?;
6080                    for when in exception_when {
6081                        write!(f, " {when}")?;
6082                    }
6083                }
6084                if *has_end_keyword {
6085                    write!(f, " END")?;
6086                }
6087                Ok(())
6088            }
6089            Statement::Commit {
6090                chain,
6091                end: end_syntax,
6092                modifier,
6093            } => {
6094                if *end_syntax {
6095                    write!(f, "END")?;
6096                    if let Some(modifier) = *modifier {
6097                        write!(f, " {modifier}")?;
6098                    }
6099                    if *chain {
6100                        write!(f, " AND CHAIN")?;
6101                    }
6102                } else {
6103                    write!(f, "COMMIT{}", if *chain { " AND CHAIN" } else { "" })?;
6104                }
6105                Ok(())
6106            }
6107            Statement::Rollback { chain, savepoint } => {
6108                write!(f, "ROLLBACK")?;
6109
6110                if *chain {
6111                    write!(f, " AND CHAIN")?;
6112                }
6113
6114                if let Some(savepoint) = savepoint {
6115                    write!(f, " TO SAVEPOINT {savepoint}")?;
6116                }
6117
6118                Ok(())
6119            }
6120            Statement::CreateSchema {
6121                schema_name,
6122                if_not_exists,
6123                with,
6124                options,
6125                default_collate_spec,
6126                clone,
6127            } => {
6128                write!(
6129                    f,
6130                    "CREATE SCHEMA {if_not_exists}{name}",
6131                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
6132                    name = schema_name
6133                )?;
6134
6135                if let Some(collate) = default_collate_spec {
6136                    write!(f, " DEFAULT COLLATE {collate}")?;
6137                }
6138
6139                if let Some(with) = with {
6140                    write!(f, " WITH ({})", display_comma_separated(with))?;
6141                }
6142
6143                if let Some(options) = options {
6144                    write!(f, " OPTIONS({})", display_comma_separated(options))?;
6145                }
6146
6147                if let Some(clone) = clone {
6148                    write!(f, " CLONE {clone}")?;
6149                }
6150                Ok(())
6151            }
6152            Statement::Assert { condition, message } => {
6153                write!(f, "ASSERT {condition}")?;
6154                if let Some(m) = message {
6155                    write!(f, " AS {m}")?;
6156                }
6157                Ok(())
6158            }
6159            Statement::Grant(grant) => write!(f, "{grant}"),
6160            Statement::Deny(s) => write!(f, "{s}"),
6161            Statement::Revoke(revoke) => write!(f, "{revoke}"),
6162            Statement::Deallocate { name, prepare } => write!(
6163                f,
6164                "DEALLOCATE {prepare}{name}",
6165                prepare = if *prepare { "PREPARE " } else { "" },
6166                name = name,
6167            ),
6168            Statement::Execute {
6169                name,
6170                parameters,
6171                has_parentheses,
6172                immediate,
6173                into,
6174                using,
6175                output,
6176                default,
6177            } => {
6178                let (open, close) = if *has_parentheses {
6179                    // Space before `(` only when there is no name directly preceding it.
6180                    (if name.is_some() { "(" } else { " (" }, ")")
6181                } else {
6182                    (if parameters.is_empty() { "" } else { " " }, "")
6183                };
6184                write!(f, "EXECUTE")?;
6185                if *immediate {
6186                    write!(f, " IMMEDIATE")?;
6187                }
6188                if let Some(name) = name {
6189                    write!(f, " {name}")?;
6190                }
6191                write!(f, "{open}{}{close}", display_comma_separated(parameters),)?;
6192                if !into.is_empty() {
6193                    write!(f, " INTO {}", display_comma_separated(into))?;
6194                }
6195                if !using.is_empty() {
6196                    write!(f, " USING {}", display_comma_separated(using))?;
6197                };
6198                if *output {
6199                    write!(f, " OUTPUT")?;
6200                }
6201                if *default {
6202                    write!(f, " DEFAULT")?;
6203                }
6204                Ok(())
6205            }
6206            Statement::Prepare {
6207                name,
6208                data_types,
6209                statement,
6210            } => {
6211                write!(f, "PREPARE {name} ")?;
6212                if !data_types.is_empty() {
6213                    write!(f, "({}) ", display_comma_separated(data_types))?;
6214                }
6215                write!(f, "AS {statement}")
6216            }
6217            Statement::Comment {
6218                object_type,
6219                object_name,
6220                arguments,
6221                relation,
6222                comment,
6223                if_exists,
6224            } => {
6225                write!(f, "COMMENT ")?;
6226                if *if_exists {
6227                    write!(f, "IF EXISTS ")?
6228                };
6229                write!(f, "ON {object_type} {object_name}")?;
6230                if let Some(args) = arguments {
6231                    write!(f, "({})", display_comma_separated(args))?;
6232                }
6233                if let Some(relation) = relation {
6234                    write!(f, " ON {relation}")?;
6235                }
6236                write!(f, " IS ")?;
6237                if let Some(c) = comment {
6238                    write!(f, "'{}'", value::escape_single_quote_string(c))
6239                } else {
6240                    write!(f, "NULL")
6241                }
6242            }
6243            Statement::Savepoint { name } => {
6244                write!(f, "SAVEPOINT ")?;
6245                write!(f, "{name}")
6246            }
6247            Statement::ReleaseSavepoint { name } => {
6248                write!(f, "RELEASE SAVEPOINT {name}")
6249            }
6250            Statement::Merge(merge) => merge.fmt(f),
6251            Statement::Cache {
6252                table_name,
6253                table_flag,
6254                has_as,
6255                options,
6256                query,
6257            } => {
6258                if let Some(table_flag) = table_flag {
6259                    write!(f, "CACHE {table_flag} TABLE {table_name}")?;
6260                } else {
6261                    write!(f, "CACHE TABLE {table_name}")?;
6262                }
6263
6264                if !options.is_empty() {
6265                    write!(f, " OPTIONS({})", display_comma_separated(options))?;
6266                }
6267
6268                match (*has_as, query) {
6269                    (true, Some(query)) => write!(f, " AS {query}"),
6270                    (true, None) => f.write_str(" AS"),
6271                    (false, Some(query)) => write!(f, " {query}"),
6272                    (false, None) => Ok(()),
6273                }
6274            }
6275            Statement::UNCache {
6276                table_name,
6277                if_exists,
6278            } => {
6279                if *if_exists {
6280                    write!(f, "UNCACHE TABLE IF EXISTS {table_name}")
6281                } else {
6282                    write!(f, "UNCACHE TABLE {table_name}")
6283                }
6284            }
6285            Statement::CreateSequence {
6286                temporary,
6287                if_not_exists,
6288                name,
6289                data_type,
6290                sequence_options,
6291                owned_by,
6292            } => {
6293                let as_type: String = if let Some(dt) = data_type.as_ref() {
6294                    //Cannot use format!(" AS {}", dt), due to format! is not available in --target thumbv6m-none-eabi
6295                    // " AS ".to_owned() + &dt.to_string()
6296                    [" AS ", &dt.to_string()].concat()
6297                } else {
6298                    "".to_string()
6299                };
6300                write!(
6301                    f,
6302                    "CREATE {temporary}SEQUENCE {if_not_exists}{name}{as_type}",
6303                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
6304                    temporary = if *temporary { "TEMPORARY " } else { "" },
6305                    name = name,
6306                    as_type = as_type
6307                )?;
6308                for sequence_option in sequence_options {
6309                    write!(f, "{sequence_option}")?;
6310                }
6311                if let Some(ob) = owned_by.as_ref() {
6312                    write!(f, " OWNED BY {ob}")?;
6313                }
6314                write!(f, "")
6315            }
6316            Statement::CreateStage {
6317                or_replace,
6318                temporary,
6319                if_not_exists,
6320                name,
6321                stage_params,
6322                directory_table_params,
6323                file_format,
6324                copy_options,
6325                comment,
6326                ..
6327            } => {
6328                write!(
6329                    f,
6330                    "CREATE {or_replace}{temp}STAGE {if_not_exists}{name}{stage_params}",
6331                    temp = if *temporary { "TEMPORARY " } else { "" },
6332                    or_replace = if *or_replace { "OR REPLACE " } else { "" },
6333                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
6334                )?;
6335                if !directory_table_params.options.is_empty() {
6336                    write!(f, " DIRECTORY=({directory_table_params})")?;
6337                }
6338                if !file_format.options.is_empty() {
6339                    write!(f, " FILE_FORMAT=({file_format})")?;
6340                }
6341                if !copy_options.options.is_empty() {
6342                    write!(f, " COPY_OPTIONS=({copy_options})")?;
6343                }
6344                if comment.is_some() {
6345                    write!(f, " COMMENT='{}'", comment.as_ref().unwrap())?;
6346                }
6347                Ok(())
6348            }
6349            Statement::CopyIntoSnowflake {
6350                kind,
6351                into,
6352                into_columns,
6353                from_obj,
6354                from_obj_alias,
6355                stage_params,
6356                from_transformations,
6357                from_query,
6358                files,
6359                pattern,
6360                file_format,
6361                copy_options,
6362                validation_mode,
6363                partition,
6364            } => {
6365                write!(f, "COPY INTO {into}")?;
6366                if let Some(into_columns) = into_columns {
6367                    write!(f, " ({})", display_comma_separated(into_columns))?;
6368                }
6369                if let Some(from_transformations) = from_transformations {
6370                    // Data load with transformation
6371                    if let Some(from_stage) = from_obj {
6372                        write!(
6373                            f,
6374                            " FROM (SELECT {} FROM {}{}",
6375                            display_separated(from_transformations, ", "),
6376                            from_stage,
6377                            stage_params
6378                        )?;
6379                    }
6380                    if let Some(from_obj_alias) = from_obj_alias {
6381                        write!(f, " AS {from_obj_alias}")?;
6382                    }
6383                    write!(f, ")")?;
6384                } else if let Some(from_obj) = from_obj {
6385                    // Standard data load
6386                    write!(f, " FROM {from_obj}{stage_params}")?;
6387                    if let Some(from_obj_alias) = from_obj_alias {
6388                        write!(f, " AS {from_obj_alias}")?;
6389                    }
6390                } else if let Some(from_query) = from_query {
6391                    // Data unload from query
6392                    write!(f, " FROM ({from_query})")?;
6393                }
6394
6395                if let Some(files) = files {
6396                    write!(f, " FILES = ('{}')", display_separated(files, "', '"))?;
6397                }
6398                if let Some(pattern) = pattern {
6399                    write!(f, " PATTERN = '{pattern}'")?;
6400                }
6401                if let Some(partition) = partition {
6402                    write!(f, " PARTITION BY {partition}")?;
6403                }
6404                if !file_format.options.is_empty() {
6405                    write!(f, " FILE_FORMAT=({file_format})")?;
6406                }
6407                if !copy_options.options.is_empty() {
6408                    match kind {
6409                        CopyIntoSnowflakeKind::Table => {
6410                            write!(f, " COPY_OPTIONS=({copy_options})")?
6411                        }
6412                        CopyIntoSnowflakeKind::Location => write!(f, " {copy_options}")?,
6413                    }
6414                }
6415                if let Some(validation_mode) = validation_mode {
6416                    write!(f, " VALIDATION_MODE = {validation_mode}")?;
6417                }
6418                Ok(())
6419            }
6420            Statement::CreateType {
6421                name,
6422                representation,
6423            } => {
6424                write!(f, "CREATE TYPE {name}")?;
6425                if let Some(repr) = representation {
6426                    write!(f, " {repr}")?;
6427                }
6428                Ok(())
6429            }
6430            Statement::Pragma { name, value, is_eq } => {
6431                write!(f, "PRAGMA {name}")?;
6432                if value.is_some() {
6433                    let val = value.as_ref().unwrap();
6434                    if *is_eq {
6435                        write!(f, " = {val}")?;
6436                    } else {
6437                        write!(f, "({val})")?;
6438                    }
6439                }
6440                Ok(())
6441            }
6442            Statement::Lock(lock) => lock.fmt(f),
6443            Statement::LockTables { tables } => {
6444                write!(f, "LOCK TABLES {}", display_comma_separated(tables))
6445            }
6446            Statement::UnlockTables => {
6447                write!(f, "UNLOCK TABLES")
6448            }
6449            Statement::Unload {
6450                query,
6451                query_text,
6452                to,
6453                auth,
6454                with,
6455                options,
6456            } => {
6457                write!(f, "UNLOAD(")?;
6458                if let Some(query) = query {
6459                    write!(f, "{query}")?;
6460                }
6461                if let Some(query_text) = query_text {
6462                    write!(f, "'{query_text}'")?;
6463                }
6464                write!(f, ") TO {to}")?;
6465                if let Some(auth) = auth {
6466                    write!(f, " IAM_ROLE {auth}")?;
6467                }
6468                if !with.is_empty() {
6469                    write!(f, " WITH ({})", display_comma_separated(with))?;
6470                }
6471                if !options.is_empty() {
6472                    write!(f, " {}", display_separated(options, " "))?;
6473                }
6474                Ok(())
6475            }
6476            Statement::OptimizeTable {
6477                name,
6478                has_table_keyword,
6479                on_cluster,
6480                partition,
6481                include_final,
6482                deduplicate,
6483                predicate,
6484                zorder,
6485            } => {
6486                write!(f, "OPTIMIZE")?;
6487                if *has_table_keyword {
6488                    write!(f, " TABLE")?;
6489                }
6490                write!(f, " {name}")?;
6491                if let Some(on_cluster) = on_cluster {
6492                    write!(f, " ON CLUSTER {on_cluster}")?;
6493                }
6494                if let Some(partition) = partition {
6495                    write!(f, " {partition}")?;
6496                }
6497                if *include_final {
6498                    write!(f, " FINAL")?;
6499                }
6500                if let Some(deduplicate) = deduplicate {
6501                    write!(f, " {deduplicate}")?;
6502                }
6503                if let Some(predicate) = predicate {
6504                    write!(f, " WHERE {predicate}")?;
6505                }
6506                if let Some(zorder) = zorder {
6507                    write!(f, " ZORDER BY ({})", display_comma_separated(zorder))?;
6508                }
6509                Ok(())
6510            }
6511            Statement::LISTEN { channel } => {
6512                write!(f, "LISTEN {channel}")?;
6513                Ok(())
6514            }
6515            Statement::UNLISTEN { channel } => {
6516                write!(f, "UNLISTEN {channel}")?;
6517                Ok(())
6518            }
6519            Statement::NOTIFY { channel, payload } => {
6520                write!(f, "NOTIFY {channel}")?;
6521                if let Some(payload) = payload {
6522                    write!(f, ", '{payload}'")?;
6523                }
6524                Ok(())
6525            }
6526            Statement::RenameTable(rename_tables) => {
6527                write!(f, "RENAME TABLE {}", display_comma_separated(rename_tables))
6528            }
6529            Statement::RaisError {
6530                message,
6531                severity,
6532                state,
6533                arguments,
6534                options,
6535            } => {
6536                write!(f, "RAISERROR({message}, {severity}, {state}")?;
6537                if !arguments.is_empty() {
6538                    write!(f, ", {}", display_comma_separated(arguments))?;
6539                }
6540                write!(f, ")")?;
6541                if !options.is_empty() {
6542                    write!(f, " WITH {}", display_comma_separated(options))?;
6543                }
6544                Ok(())
6545            }
6546            Statement::Throw(s) => write!(f, "{s}"),
6547            Statement::Print(s) => write!(f, "{s}"),
6548            Statement::WaitFor(s) => write!(f, "{s}"),
6549            Statement::Return(r) => write!(f, "{r}"),
6550            Statement::List(command) => write!(f, "LIST {command}"),
6551            Statement::Remove(command) => write!(f, "REMOVE {command}"),
6552            Statement::ExportData(e) => write!(f, "{e}"),
6553            Statement::CreateUser(s) => write!(f, "{s}"),
6554            Statement::AlterSchema(s) => write!(f, "{s}"),
6555            Statement::Vacuum(s) => write!(f, "{s}"),
6556            Statement::AlterUser(s) => write!(f, "{s}"),
6557            Statement::Reset(s) => write!(f, "{s}"),
6558        }
6559    }
6560}
6561
6562/// Can use to describe options in create sequence or table column type identity
6563/// ```sql
6564/// [ INCREMENT [ BY ] increment ]
6565///     [ MINVALUE minvalue | NO MINVALUE ] [ MAXVALUE maxvalue | NO MAXVALUE ]
6566///     [ START [ WITH ] start ] [ CACHE cache ] [ [ NO ] CYCLE ]
6567/// ```
6568#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6569#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6570#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6571pub enum SequenceOptions {
6572    /// `INCREMENT [BY] <expr>` option; second value indicates presence of `BY` keyword.
6573    IncrementBy(Expr, bool),
6574    /// `MINVALUE <expr>` or `NO MINVALUE`.
6575    MinValue(Option<Expr>),
6576    /// `MAXVALUE <expr>` or `NO MAXVALUE`.
6577    MaxValue(Option<Expr>),
6578    /// `START [WITH] <expr>`; second value indicates presence of `WITH`.
6579    StartWith(Expr, bool),
6580    /// `CACHE <expr>` option.
6581    Cache(Expr),
6582    /// `CYCLE` or `NO CYCLE` option.
6583    Cycle(bool),
6584}
6585
6586impl fmt::Display for SequenceOptions {
6587    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6588        match self {
6589            SequenceOptions::IncrementBy(increment, by) => {
6590                write!(
6591                    f,
6592                    " INCREMENT{by} {increment}",
6593                    by = if *by { " BY" } else { "" },
6594                    increment = increment
6595                )
6596            }
6597            SequenceOptions::MinValue(Some(expr)) => {
6598                write!(f, " MINVALUE {expr}")
6599            }
6600            SequenceOptions::MinValue(None) => {
6601                write!(f, " NO MINVALUE")
6602            }
6603            SequenceOptions::MaxValue(Some(expr)) => {
6604                write!(f, " MAXVALUE {expr}")
6605            }
6606            SequenceOptions::MaxValue(None) => {
6607                write!(f, " NO MAXVALUE")
6608            }
6609            SequenceOptions::StartWith(start, with) => {
6610                write!(
6611                    f,
6612                    " START{with} {start}",
6613                    with = if *with { " WITH" } else { "" },
6614                    start = start
6615                )
6616            }
6617            SequenceOptions::Cache(cache) => {
6618                write!(f, " CACHE {}", *cache)
6619            }
6620            SequenceOptions::Cycle(no) => {
6621                write!(f, " {}CYCLE", if *no { "NO " } else { "" })
6622            }
6623        }
6624    }
6625}
6626
6627/// Assignment for a `SET` statement (name [=|TO] value)
6628#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6629#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6630#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6631pub struct SetAssignment {
6632    /// Optional context scope (e.g., SESSION or LOCAL).
6633    pub scope: Option<ContextModifier>,
6634    /// Assignment target name.
6635    pub name: ObjectName,
6636    /// Assigned expression value.
6637    pub value: Expr,
6638}
6639
6640impl fmt::Display for SetAssignment {
6641    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6642        write!(
6643            f,
6644            "{}{} = {}",
6645            self.scope.map(|s| format!("{s}")).unwrap_or_default(),
6646            self.name,
6647            self.value
6648        )
6649    }
6650}
6651
6652/// Target of a `TRUNCATE TABLE` command
6653///
6654/// Note this is its own struct because `visit_relation` requires an `ObjectName` (not a `Vec<ObjectName>`)
6655#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6656#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6657#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6658pub struct TruncateTableTarget {
6659    /// name of the table being truncated
6660    #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
6661    pub name: ObjectName,
6662    /// Postgres-specific option: explicitly exclude descendants (also default without ONLY)
6663    /// ```sql
6664    /// TRUNCATE TABLE ONLY name
6665    /// ```
6666    /// <https://www.postgresql.org/docs/current/sql-truncate.html>
6667    pub only: bool,
6668    /// Postgres-specific option: asterisk after table name to explicitly indicate descendants
6669    /// ```sql
6670    /// TRUNCATE TABLE name [ * ]
6671    /// ```
6672    /// <https://www.postgresql.org/docs/current/sql-truncate.html>
6673    pub has_asterisk: bool,
6674}
6675
6676impl fmt::Display for TruncateTableTarget {
6677    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6678        if self.only {
6679            write!(f, "ONLY ")?;
6680        };
6681        write!(f, "{}", self.name)?;
6682        if self.has_asterisk {
6683            write!(f, " *")?;
6684        };
6685        Ok(())
6686    }
6687}
6688
6689/// A `LOCK` statement.
6690///
6691/// See <https://www.postgresql.org/docs/current/sql-lock.html>
6692#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6693#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6694#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6695pub struct Lock {
6696    /// List of tables to lock.
6697    pub tables: Vec<LockTableTarget>,
6698    /// Lock mode.
6699    pub lock_mode: Option<LockTableMode>,
6700    /// Whether `NOWAIT` was specified.
6701    pub nowait: bool,
6702}
6703
6704impl fmt::Display for Lock {
6705    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6706        write!(f, "LOCK TABLE {}", display_comma_separated(&self.tables))?;
6707        if let Some(lock_mode) = &self.lock_mode {
6708            write!(f, " IN {lock_mode} MODE")?;
6709        }
6710        if self.nowait {
6711            write!(f, " NOWAIT")?;
6712        }
6713        Ok(())
6714    }
6715}
6716
6717/// Target of a `LOCK TABLE` command
6718///
6719/// See <https://www.postgresql.org/docs/current/sql-lock.html>
6720#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6721#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6722#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6723pub struct LockTableTarget {
6724    /// Name of the table being locked.
6725    #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
6726    pub name: ObjectName,
6727    /// Whether `ONLY` was specified to exclude descendant tables.
6728    pub only: bool,
6729    /// Whether `*` was specified to explicitly include descendant tables.
6730    pub has_asterisk: bool,
6731}
6732
6733impl fmt::Display for LockTableTarget {
6734    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6735        if self.only {
6736            write!(f, "ONLY ")?;
6737        }
6738        write!(f, "{}", self.name)?;
6739        if self.has_asterisk {
6740            write!(f, " *")?;
6741        }
6742        Ok(())
6743    }
6744}
6745
6746/// PostgreSQL lock modes for `LOCK TABLE`.
6747///
6748/// See <https://www.postgresql.org/docs/current/sql-lock.html>
6749#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6750#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6751#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6752pub enum LockTableMode {
6753    /// `ACCESS SHARE`
6754    AccessShare,
6755    /// `ROW SHARE`
6756    RowShare,
6757    /// `ROW EXCLUSIVE`
6758    RowExclusive,
6759    /// `SHARE UPDATE EXCLUSIVE`
6760    ShareUpdateExclusive,
6761    /// `SHARE`
6762    Share,
6763    /// `SHARE ROW EXCLUSIVE`
6764    ShareRowExclusive,
6765    /// `EXCLUSIVE`
6766    Exclusive,
6767    /// `ACCESS EXCLUSIVE`
6768    AccessExclusive,
6769}
6770
6771impl fmt::Display for LockTableMode {
6772    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
6773        let text = match self {
6774            Self::AccessShare => "ACCESS SHARE",
6775            Self::RowShare => "ROW SHARE",
6776            Self::RowExclusive => "ROW EXCLUSIVE",
6777            Self::ShareUpdateExclusive => "SHARE UPDATE EXCLUSIVE",
6778            Self::Share => "SHARE",
6779            Self::ShareRowExclusive => "SHARE ROW EXCLUSIVE",
6780            Self::Exclusive => "EXCLUSIVE",
6781            Self::AccessExclusive => "ACCESS EXCLUSIVE",
6782        };
6783        write!(f, "{text}")
6784    }
6785}
6786
6787/// PostgreSQL identity option for TRUNCATE table
6788/// [ RESTART IDENTITY | CONTINUE IDENTITY ]
6789#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6790#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6791#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6792pub enum TruncateIdentityOption {
6793    /// Restart identity values (RESTART IDENTITY).
6794    Restart,
6795    /// Continue identity values (CONTINUE IDENTITY).
6796    Continue,
6797}
6798
6799/// Cascade/restrict option for Postgres TRUNCATE table, MySQL GRANT/REVOKE, etc.
6800/// [ CASCADE | RESTRICT ]
6801#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6802#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6803#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6804pub enum CascadeOption {
6805    /// Apply cascading action (e.g., CASCADE).
6806    Cascade,
6807    /// Restrict the action (e.g., RESTRICT).
6808    Restrict,
6809}
6810
6811impl Display for CascadeOption {
6812    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6813        match self {
6814            CascadeOption::Cascade => write!(f, "CASCADE"),
6815            CascadeOption::Restrict => write!(f, "RESTRICT"),
6816        }
6817    }
6818}
6819
6820/// Transaction started with [ TRANSACTION | WORK | TRAN ]
6821#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6822#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6823#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6824pub enum BeginTransactionKind {
6825    /// Standard `TRANSACTION` keyword.
6826    Transaction,
6827    /// Alternate `WORK` keyword.
6828    Work,
6829    /// MSSQL shorthand `TRAN` keyword.
6830    /// See <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/begin-transaction-transact-sql>
6831    Tran,
6832}
6833
6834impl Display for BeginTransactionKind {
6835    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6836        match self {
6837            BeginTransactionKind::Transaction => write!(f, "TRANSACTION"),
6838            BeginTransactionKind::Work => write!(f, "WORK"),
6839            BeginTransactionKind::Tran => write!(f, "TRAN"),
6840        }
6841    }
6842}
6843
6844/// Can use to describe options in  create sequence or table column type identity
6845/// [ MINVALUE minvalue | NO MINVALUE ] [ MAXVALUE maxvalue | NO MAXVALUE ]
6846#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6847#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6848#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6849pub enum MinMaxValue {
6850    /// Clause is not specified.
6851    Empty,
6852    /// NO MINVALUE / NO MAXVALUE.
6853    None,
6854    /// `MINVALUE <expr>` / `MAXVALUE <expr>`.
6855    Some(Expr),
6856}
6857
6858#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6859#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6860#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6861#[non_exhaustive]
6862/// Behavior to apply for `INSERT` when a conflict occurs.
6863pub enum OnInsert {
6864    /// ON DUPLICATE KEY UPDATE (MySQL when the key already exists, then execute an update instead)
6865    DuplicateKeyUpdate(Vec<Assignment>),
6866    /// ON CONFLICT is a PostgreSQL and Sqlite extension
6867    OnConflict(OnConflict),
6868}
6869
6870#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6871#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6872#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6873/// Optional aliases for `INSERT` targets: row alias and optional column aliases.
6874pub struct InsertAliases {
6875    /// Row alias (table-style alias) for the inserted values.
6876    pub row_alias: ObjectName,
6877    /// Optional list of column aliases for the inserted values.
6878    pub col_aliases: Option<Vec<Ident>>,
6879}
6880
6881#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6882#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6883#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6884/// Optional alias for an `INSERT` table; i.e. the table to be inserted into
6885pub struct TableAliasWithoutColumns {
6886    /// `true` if the aliases was explicitly introduced with the "AS" keyword
6887    pub explicit: bool,
6888    /// the alias name itself
6889    pub alias: Ident,
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/// `ON CONFLICT` clause representation.
6896pub struct OnConflict {
6897    /// Optional conflict target specifying columns or constraint.
6898    pub conflict_target: Option<ConflictTarget>,
6899    /// Action to take when a conflict occurs.
6900    pub action: OnConflictAction,
6901}
6902#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6903#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6904#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6905/// Target specification for an `ON CONFLICT` clause.
6906pub enum ConflictTarget {
6907    /// Target specified as a list of columns.
6908    Columns(Vec<Ident>),
6909    /// Target specified as a named constraint.
6910    OnConstraint(ObjectName),
6911}
6912#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6913#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6914#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6915/// Action to perform when an `ON CONFLICT` target is matched.
6916pub enum OnConflictAction {
6917    /// Do nothing on conflict.
6918    DoNothing,
6919    /// Perform an update on conflict.
6920    DoUpdate(DoUpdate),
6921}
6922
6923#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6924#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6925#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6926/// Details for `DO UPDATE` action of an `ON CONFLICT` clause.
6927pub struct DoUpdate {
6928    /// Column assignments to perform on update.
6929    pub assignments: Vec<Assignment>,
6930    /// Optional WHERE clause limiting the update.
6931    pub selection: Option<Expr>,
6932}
6933
6934impl fmt::Display for OnInsert {
6935    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6936        match self {
6937            Self::DuplicateKeyUpdate(expr) => write!(
6938                f,
6939                " ON DUPLICATE KEY UPDATE {}",
6940                display_comma_separated(expr)
6941            ),
6942            Self::OnConflict(o) => write!(f, "{o}"),
6943        }
6944    }
6945}
6946impl fmt::Display for OnConflict {
6947    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6948        write!(f, " ON CONFLICT")?;
6949        if let Some(target) = &self.conflict_target {
6950            write!(f, "{target}")?;
6951        }
6952        write!(f, " {}", self.action)
6953    }
6954}
6955impl fmt::Display for ConflictTarget {
6956    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6957        match self {
6958            ConflictTarget::Columns(cols) => write!(f, "({})", display_comma_separated(cols)),
6959            ConflictTarget::OnConstraint(name) => write!(f, " ON CONSTRAINT {name}"),
6960        }
6961    }
6962}
6963impl fmt::Display for OnConflictAction {
6964    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6965        match self {
6966            Self::DoNothing => write!(f, "DO NOTHING"),
6967            Self::DoUpdate(do_update) => {
6968                write!(f, "DO UPDATE")?;
6969                if !do_update.assignments.is_empty() {
6970                    write!(
6971                        f,
6972                        " SET {}",
6973                        display_comma_separated(&do_update.assignments)
6974                    )?;
6975                }
6976                if let Some(selection) = &do_update.selection {
6977                    write!(f, " WHERE {selection}")?;
6978                }
6979                Ok(())
6980            }
6981        }
6982    }
6983}
6984
6985/// Privileges granted in a GRANT statement or revoked in a REVOKE statement.
6986#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6987#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6988#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6989pub enum Privileges {
6990    /// All privileges applicable to the object type
6991    All {
6992        /// Optional keyword from the spec, ignored in practice
6993        with_privileges_keyword: bool,
6994    },
6995    /// Specific privileges (e.g. `SELECT`, `INSERT`)
6996    Actions(Vec<Action>),
6997}
6998
6999impl fmt::Display for Privileges {
7000    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7001        match self {
7002            Privileges::All {
7003                with_privileges_keyword,
7004            } => {
7005                write!(
7006                    f,
7007                    "ALL{}",
7008                    if *with_privileges_keyword {
7009                        " PRIVILEGES"
7010                    } else {
7011                        ""
7012                    }
7013                )
7014            }
7015            Privileges::Actions(actions) => {
7016                write!(f, "{}", display_comma_separated(actions))
7017            }
7018        }
7019    }
7020}
7021
7022/// Specific direction for FETCH statement
7023#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7024#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7025#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7026pub enum FetchDirection {
7027    /// Fetch a specific count of rows.
7028    Count {
7029        /// The limit value for the count.
7030        limit: ValueWithSpan,
7031    },
7032    /// Fetch the next row.
7033    Next,
7034    /// Fetch the prior row.
7035    Prior,
7036    /// Fetch the first row.
7037    First,
7038    /// Fetch the last row.
7039    Last,
7040    /// Fetch an absolute row by index.
7041    Absolute {
7042        /// The absolute index value.
7043        limit: ValueWithSpan,
7044    },
7045    /// Fetch a row relative to the current position.
7046    Relative {
7047        /// The relative offset value.
7048        limit: ValueWithSpan,
7049    },
7050    /// Fetch all rows.
7051    All,
7052    // FORWARD
7053    // FORWARD count
7054    /// Fetch forward by an optional limit.
7055    Forward {
7056        /// Optional forward limit.
7057        limit: Option<ValueWithSpan>,
7058    },
7059    /// Fetch all forward rows.
7060    ForwardAll,
7061    // BACKWARD
7062    // BACKWARD count
7063    /// Fetch backward by an optional limit.
7064    Backward {
7065        /// Optional backward limit.
7066        limit: Option<ValueWithSpan>,
7067    },
7068    /// Fetch all backward rows.
7069    BackwardAll,
7070}
7071
7072impl fmt::Display for FetchDirection {
7073    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7074        match self {
7075            FetchDirection::Count { limit } => f.write_str(&limit.to_string())?,
7076            FetchDirection::Next => f.write_str("NEXT")?,
7077            FetchDirection::Prior => f.write_str("PRIOR")?,
7078            FetchDirection::First => f.write_str("FIRST")?,
7079            FetchDirection::Last => f.write_str("LAST")?,
7080            FetchDirection::Absolute { limit } => {
7081                f.write_str("ABSOLUTE ")?;
7082                f.write_str(&limit.to_string())?;
7083            }
7084            FetchDirection::Relative { limit } => {
7085                f.write_str("RELATIVE ")?;
7086                f.write_str(&limit.to_string())?;
7087            }
7088            FetchDirection::All => f.write_str("ALL")?,
7089            FetchDirection::Forward { limit } => {
7090                f.write_str("FORWARD")?;
7091
7092                if let Some(l) = limit {
7093                    f.write_str(" ")?;
7094                    f.write_str(&l.to_string())?;
7095                }
7096            }
7097            FetchDirection::ForwardAll => f.write_str("FORWARD ALL")?,
7098            FetchDirection::Backward { limit } => {
7099                f.write_str("BACKWARD")?;
7100
7101                if let Some(l) = limit {
7102                    f.write_str(" ")?;
7103                    f.write_str(&l.to_string())?;
7104                }
7105            }
7106            FetchDirection::BackwardAll => f.write_str("BACKWARD ALL")?,
7107        };
7108
7109        Ok(())
7110    }
7111}
7112
7113/// The "position" for a FETCH statement.
7114///
7115/// [MsSql](https://learn.microsoft.com/en-us/sql/t-sql/language-elements/fetch-transact-sql)
7116#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7117#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7118#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7119pub enum FetchPosition {
7120    /// Use `FROM <pos>` position specifier.
7121    From,
7122    /// Use `IN <pos>` position specifier.
7123    In,
7124}
7125
7126impl fmt::Display for FetchPosition {
7127    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7128        match self {
7129            FetchPosition::From => f.write_str("FROM")?,
7130            FetchPosition::In => f.write_str("IN")?,
7131        };
7132
7133        Ok(())
7134    }
7135}
7136
7137/// A privilege on a database object (table, sequence, etc.).
7138#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7139#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7140#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7141pub enum Action {
7142    /// Add a search optimization.
7143    AddSearchOptimization,
7144    /// Apply an `APPLY` operation with a specific type.
7145    Apply {
7146        /// The type of apply operation.
7147        apply_type: ActionApplyType,
7148    },
7149    /// Apply a budget operation.
7150    ApplyBudget,
7151    /// Attach a listing.
7152    AttachListing,
7153    /// Attach a policy.
7154    AttachPolicy,
7155    /// Audit operation.
7156    Audit,
7157    /// Bind a service endpoint.
7158    BindServiceEndpoint,
7159    /// Connect permission.
7160    Connect,
7161    /// Create action, optionally specifying an object type.
7162    Create {
7163        /// Optional object type to create.
7164        obj_type: Option<ActionCreateObjectType>,
7165    },
7166    /// Actions related to database roles.
7167    DatabaseRole {
7168        /// The role name.
7169        role: ObjectName,
7170    },
7171    /// Delete permission.
7172    Delete,
7173    /// Drop permission.
7174    Drop,
7175    /// Evolve schema permission.
7176    EvolveSchema,
7177    /// Exec action (execute) with optional object type.
7178    Exec {
7179        /// Optional execute object type.
7180        obj_type: Option<ActionExecuteObjectType>,
7181    },
7182    /// Execute action with optional object type.
7183    Execute {
7184        /// Optional execute object type.
7185        obj_type: Option<ActionExecuteObjectType>,
7186    },
7187    /// Failover operation.
7188    Failover,
7189    /// Use imported privileges.
7190    ImportedPrivileges,
7191    /// Import a share.
7192    ImportShare,
7193    /// Insert rows with optional column list.
7194    Insert {
7195        /// Optional list of target columns for insert.
7196        columns: Option<Vec<Ident>>,
7197    },
7198    /// Manage operation with a specific manage type.
7199    Manage {
7200        /// The specific manage sub-type.
7201        manage_type: ActionManageType,
7202    },
7203    /// Manage releases.
7204    ManageReleases,
7205    /// Manage versions.
7206    ManageVersions,
7207    /// Modify operation with an optional modify type.
7208    Modify {
7209        /// The optional modify sub-type.
7210        modify_type: Option<ActionModifyType>,
7211    },
7212    /// Monitor operation with an optional monitor type.
7213    Monitor {
7214        /// The optional monitor sub-type.
7215        monitor_type: Option<ActionMonitorType>,
7216    },
7217    /// Operate permission.
7218    Operate,
7219    /// Override share restrictions.
7220    OverrideShareRestrictions,
7221    /// Ownership permission.
7222    Ownership,
7223    /// Purchase a data exchange listing.
7224    PurchaseDataExchangeListing,
7225
7226    /// Read access.
7227    Read,
7228    /// Read session-level access.
7229    ReadSession,
7230    /// References with optional column list.
7231    References {
7232        /// Optional list of referenced column identifiers.
7233        columns: Option<Vec<Ident>>,
7234    },
7235    /// Replication permission.
7236    Replicate,
7237    /// Resolve all references.
7238    ResolveAll,
7239    /// Role-related permission with target role name.
7240    Role {
7241        /// The target role name.
7242        role: ObjectName,
7243    },
7244    /// Select permission with optional column list.
7245    Select {
7246        /// Optional list of selected columns.
7247        columns: Option<Vec<Ident>>,
7248    },
7249    /// Temporary object permission.
7250    Temporary,
7251    /// Trigger-related permission.
7252    Trigger,
7253    /// Truncate permission.
7254    Truncate,
7255    /// Update permission with optional affected columns.
7256    Update {
7257        /// Optional list of columns affected by update.
7258        columns: Option<Vec<Ident>>,
7259    },
7260    /// Usage permission.
7261    Usage,
7262}
7263
7264impl fmt::Display for Action {
7265    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7266        match self {
7267            Action::AddSearchOptimization => f.write_str("ADD SEARCH OPTIMIZATION")?,
7268            Action::Apply { apply_type } => write!(f, "APPLY {apply_type}")?,
7269            Action::ApplyBudget => f.write_str("APPLYBUDGET")?,
7270            Action::AttachListing => f.write_str("ATTACH LISTING")?,
7271            Action::AttachPolicy => f.write_str("ATTACH POLICY")?,
7272            Action::Audit => f.write_str("AUDIT")?,
7273            Action::BindServiceEndpoint => f.write_str("BIND SERVICE ENDPOINT")?,
7274            Action::Connect => f.write_str("CONNECT")?,
7275            Action::Create { obj_type } => {
7276                f.write_str("CREATE")?;
7277                if let Some(obj_type) = obj_type {
7278                    write!(f, " {obj_type}")?
7279                }
7280            }
7281            Action::DatabaseRole { role } => write!(f, "DATABASE ROLE {role}")?,
7282            Action::Delete => f.write_str("DELETE")?,
7283            Action::Drop => f.write_str("DROP")?,
7284            Action::EvolveSchema => f.write_str("EVOLVE SCHEMA")?,
7285            Action::Exec { obj_type } => {
7286                f.write_str("EXEC")?;
7287                if let Some(obj_type) = obj_type {
7288                    write!(f, " {obj_type}")?
7289                }
7290            }
7291            Action::Execute { obj_type } => {
7292                f.write_str("EXECUTE")?;
7293                if let Some(obj_type) = obj_type {
7294                    write!(f, " {obj_type}")?
7295                }
7296            }
7297            Action::Failover => f.write_str("FAILOVER")?,
7298            Action::ImportedPrivileges => f.write_str("IMPORTED PRIVILEGES")?,
7299            Action::ImportShare => f.write_str("IMPORT SHARE")?,
7300            Action::Insert { .. } => f.write_str("INSERT")?,
7301            Action::Manage { manage_type } => write!(f, "MANAGE {manage_type}")?,
7302            Action::ManageReleases => f.write_str("MANAGE RELEASES")?,
7303            Action::ManageVersions => f.write_str("MANAGE VERSIONS")?,
7304            Action::Modify { modify_type } => {
7305                write!(f, "MODIFY")?;
7306                if let Some(modify_type) = modify_type {
7307                    write!(f, " {modify_type}")?;
7308                }
7309            }
7310            Action::Monitor { monitor_type } => {
7311                write!(f, "MONITOR")?;
7312                if let Some(monitor_type) = monitor_type {
7313                    write!(f, " {monitor_type}")?
7314                }
7315            }
7316            Action::Operate => f.write_str("OPERATE")?,
7317            Action::OverrideShareRestrictions => f.write_str("OVERRIDE SHARE RESTRICTIONS")?,
7318            Action::Ownership => f.write_str("OWNERSHIP")?,
7319            Action::PurchaseDataExchangeListing => f.write_str("PURCHASE DATA EXCHANGE LISTING")?,
7320            Action::Read => f.write_str("READ")?,
7321            Action::ReadSession => f.write_str("READ SESSION")?,
7322            Action::References { .. } => f.write_str("REFERENCES")?,
7323            Action::Replicate => f.write_str("REPLICATE")?,
7324            Action::ResolveAll => f.write_str("RESOLVE ALL")?,
7325            Action::Role { role } => write!(f, "ROLE {role}")?,
7326            Action::Select { .. } => f.write_str("SELECT")?,
7327            Action::Temporary => f.write_str("TEMPORARY")?,
7328            Action::Trigger => f.write_str("TRIGGER")?,
7329            Action::Truncate => f.write_str("TRUNCATE")?,
7330            Action::Update { .. } => f.write_str("UPDATE")?,
7331            Action::Usage => f.write_str("USAGE")?,
7332        };
7333        match self {
7334            Action::Insert { columns }
7335            | Action::References { columns }
7336            | Action::Select { columns }
7337            | Action::Update { columns } => {
7338                if let Some(columns) = columns {
7339                    write!(f, " ({})", display_comma_separated(columns))?;
7340                }
7341            }
7342            _ => (),
7343        };
7344        Ok(())
7345    }
7346}
7347
7348#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7349#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7350#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7351/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
7352/// under `globalPrivileges` in the `CREATE` privilege.
7353pub enum ActionCreateObjectType {
7354    /// An account-level object.
7355    Account,
7356    /// An application object.
7357    Application,
7358    /// An application package object.
7359    ApplicationPackage,
7360    /// A compute pool object.
7361    ComputePool,
7362    /// A data exchange listing.
7363    DataExchangeListing,
7364    /// A database object.
7365    Database,
7366    /// An external volume object.
7367    ExternalVolume,
7368    /// A failover group object.
7369    FailoverGroup,
7370    /// An integration object.
7371    Integration,
7372    /// A network policy object.
7373    NetworkPolicy,
7374    /// An organization listing.
7375    OrganiationListing,
7376    /// A replication group object.
7377    ReplicationGroup,
7378    /// A role object.
7379    Role,
7380    /// A schema object.
7381    Schema,
7382    /// A share object.
7383    Share,
7384    /// A user object.
7385    User,
7386    /// A warehouse object.
7387    Warehouse,
7388}
7389
7390impl fmt::Display for ActionCreateObjectType {
7391    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7392        match self {
7393            ActionCreateObjectType::Account => write!(f, "ACCOUNT"),
7394            ActionCreateObjectType::Application => write!(f, "APPLICATION"),
7395            ActionCreateObjectType::ApplicationPackage => write!(f, "APPLICATION PACKAGE"),
7396            ActionCreateObjectType::ComputePool => write!(f, "COMPUTE POOL"),
7397            ActionCreateObjectType::DataExchangeListing => write!(f, "DATA EXCHANGE LISTING"),
7398            ActionCreateObjectType::Database => write!(f, "DATABASE"),
7399            ActionCreateObjectType::ExternalVolume => write!(f, "EXTERNAL VOLUME"),
7400            ActionCreateObjectType::FailoverGroup => write!(f, "FAILOVER GROUP"),
7401            ActionCreateObjectType::Integration => write!(f, "INTEGRATION"),
7402            ActionCreateObjectType::NetworkPolicy => write!(f, "NETWORK POLICY"),
7403            ActionCreateObjectType::OrganiationListing => write!(f, "ORGANIZATION LISTING"),
7404            ActionCreateObjectType::ReplicationGroup => write!(f, "REPLICATION GROUP"),
7405            ActionCreateObjectType::Role => write!(f, "ROLE"),
7406            ActionCreateObjectType::Schema => write!(f, "SCHEMA"),
7407            ActionCreateObjectType::Share => write!(f, "SHARE"),
7408            ActionCreateObjectType::User => write!(f, "USER"),
7409            ActionCreateObjectType::Warehouse => write!(f, "WAREHOUSE"),
7410        }
7411    }
7412}
7413
7414#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7415#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7416#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7417/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
7418/// under `globalPrivileges` in the `APPLY` privilege.
7419pub enum ActionApplyType {
7420    /// Apply an aggregation policy.
7421    AggregationPolicy,
7422    /// Apply an authentication policy.
7423    AuthenticationPolicy,
7424    /// Apply a join policy.
7425    JoinPolicy,
7426    /// Apply a masking policy.
7427    MaskingPolicy,
7428    /// Apply a packages policy.
7429    PackagesPolicy,
7430    /// Apply a password policy.
7431    PasswordPolicy,
7432    /// Apply a projection policy.
7433    ProjectionPolicy,
7434    /// Apply a row access policy.
7435    RowAccessPolicy,
7436    /// Apply a session policy.
7437    SessionPolicy,
7438    /// Apply a tag.
7439    Tag,
7440}
7441
7442impl fmt::Display for ActionApplyType {
7443    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7444        match self {
7445            ActionApplyType::AggregationPolicy => write!(f, "AGGREGATION POLICY"),
7446            ActionApplyType::AuthenticationPolicy => write!(f, "AUTHENTICATION POLICY"),
7447            ActionApplyType::JoinPolicy => write!(f, "JOIN POLICY"),
7448            ActionApplyType::MaskingPolicy => write!(f, "MASKING POLICY"),
7449            ActionApplyType::PackagesPolicy => write!(f, "PACKAGES POLICY"),
7450            ActionApplyType::PasswordPolicy => write!(f, "PASSWORD POLICY"),
7451            ActionApplyType::ProjectionPolicy => write!(f, "PROJECTION POLICY"),
7452            ActionApplyType::RowAccessPolicy => write!(f, "ROW ACCESS POLICY"),
7453            ActionApplyType::SessionPolicy => write!(f, "SESSION POLICY"),
7454            ActionApplyType::Tag => write!(f, "TAG"),
7455        }
7456    }
7457}
7458
7459#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7460#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7461#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7462/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
7463/// under `globalPrivileges` in the `EXECUTE` privilege.
7464pub enum ActionExecuteObjectType {
7465    /// Alert object.
7466    Alert,
7467    /// Data metric function object.
7468    DataMetricFunction,
7469    /// Managed alert object.
7470    ManagedAlert,
7471    /// Managed task object.
7472    ManagedTask,
7473    /// Task object.
7474    Task,
7475}
7476
7477impl fmt::Display for ActionExecuteObjectType {
7478    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7479        match self {
7480            ActionExecuteObjectType::Alert => write!(f, "ALERT"),
7481            ActionExecuteObjectType::DataMetricFunction => write!(f, "DATA METRIC FUNCTION"),
7482            ActionExecuteObjectType::ManagedAlert => write!(f, "MANAGED ALERT"),
7483            ActionExecuteObjectType::ManagedTask => write!(f, "MANAGED TASK"),
7484            ActionExecuteObjectType::Task => write!(f, "TASK"),
7485        }
7486    }
7487}
7488
7489#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7490#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7491#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7492/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
7493/// under `globalPrivileges` in the `MANAGE` privilege.
7494pub enum ActionManageType {
7495    /// Account support cases management.
7496    AccountSupportCases,
7497    /// Event sharing management.
7498    EventSharing,
7499    /// Grants management.
7500    Grants,
7501    /// Listing auto-fulfillment management.
7502    ListingAutoFulfillment,
7503    /// Organization support cases management.
7504    OrganizationSupportCases,
7505    /// User support cases management.
7506    UserSupportCases,
7507    /// Warehouses management.
7508    Warehouses,
7509}
7510
7511impl fmt::Display for ActionManageType {
7512    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7513        match self {
7514            ActionManageType::AccountSupportCases => write!(f, "ACCOUNT SUPPORT CASES"),
7515            ActionManageType::EventSharing => write!(f, "EVENT SHARING"),
7516            ActionManageType::Grants => write!(f, "GRANTS"),
7517            ActionManageType::ListingAutoFulfillment => write!(f, "LISTING AUTO FULFILLMENT"),
7518            ActionManageType::OrganizationSupportCases => write!(f, "ORGANIZATION SUPPORT CASES"),
7519            ActionManageType::UserSupportCases => write!(f, "USER SUPPORT CASES"),
7520            ActionManageType::Warehouses => write!(f, "WAREHOUSES"),
7521        }
7522    }
7523}
7524
7525#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7526#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7527#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7528/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
7529/// under `globalPrivileges` in the `MODIFY` privilege.
7530pub enum ActionModifyType {
7531    /// Modify log level.
7532    LogLevel,
7533    /// Modify trace level.
7534    TraceLevel,
7535    /// Modify session log level.
7536    SessionLogLevel,
7537    /// Modify session trace level.
7538    SessionTraceLevel,
7539}
7540
7541impl fmt::Display for ActionModifyType {
7542    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7543        match self {
7544            ActionModifyType::LogLevel => write!(f, "LOG LEVEL"),
7545            ActionModifyType::TraceLevel => write!(f, "TRACE LEVEL"),
7546            ActionModifyType::SessionLogLevel => write!(f, "SESSION LOG LEVEL"),
7547            ActionModifyType::SessionTraceLevel => write!(f, "SESSION TRACE LEVEL"),
7548        }
7549    }
7550}
7551
7552#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7553#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7554#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7555/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
7556/// under `globalPrivileges` in the `MONITOR` privilege.
7557pub enum ActionMonitorType {
7558    /// Monitor execution.
7559    Execution,
7560    /// Monitor security.
7561    Security,
7562    /// Monitor usage.
7563    Usage,
7564}
7565
7566impl fmt::Display for ActionMonitorType {
7567    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7568        match self {
7569            ActionMonitorType::Execution => write!(f, "EXECUTION"),
7570            ActionMonitorType::Security => write!(f, "SECURITY"),
7571            ActionMonitorType::Usage => write!(f, "USAGE"),
7572        }
7573    }
7574}
7575
7576/// The principal that receives the privileges
7577#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7578#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7579#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7580pub struct Grantee {
7581    /// The category/type of grantee (role, user, share, etc.).
7582    pub grantee_type: GranteesType,
7583    /// Optional name of the grantee (identifier or user@host).
7584    pub name: Option<GranteeName>,
7585}
7586
7587impl fmt::Display for Grantee {
7588    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7589        if matches!(self.grantee_type, GranteesType::Public) {
7590            return write!(f, "PUBLIC");
7591        }
7592        match self.grantee_type {
7593            GranteesType::Role => {
7594                write!(f, "ROLE ")?;
7595            }
7596            GranteesType::Share => {
7597                write!(f, "SHARE ")?;
7598            }
7599            GranteesType::User => {
7600                write!(f, "USER ")?;
7601            }
7602            GranteesType::Group => {
7603                write!(f, "GROUP ")?;
7604            }
7605            GranteesType::Public => {}
7606            GranteesType::DatabaseRole => {
7607                write!(f, "DATABASE ROLE ")?;
7608            }
7609            GranteesType::Application => {
7610                write!(f, "APPLICATION ")?;
7611            }
7612            GranteesType::ApplicationRole => {
7613                write!(f, "APPLICATION ROLE ")?;
7614            }
7615            GranteesType::None => (),
7616        }
7617        if let Some(ref name) = self.name {
7618            name.fmt(f)?;
7619        }
7620        Ok(())
7621    }
7622}
7623
7624#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7625#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7626#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7627/// The kind of principal receiving privileges.
7628pub enum GranteesType {
7629    /// A role principal.
7630    Role,
7631    /// A share principal.
7632    Share,
7633    /// A user principal.
7634    User,
7635    /// A group principal.
7636    Group,
7637    /// The public principal.
7638    Public,
7639    /// A database role principal.
7640    DatabaseRole,
7641    /// An application principal.
7642    Application,
7643    /// An application role principal.
7644    ApplicationRole,
7645    /// No specific principal (e.g. `NONE`).
7646    None,
7647}
7648
7649/// Users/roles designated in a GRANT/REVOKE
7650#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7651#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7652#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7653pub enum GranteeName {
7654    /// A bare identifier
7655    ObjectName(ObjectName),
7656    /// A MySQL user/host pair such as 'root'@'%'
7657    UserHost {
7658        /// The user identifier portion.
7659        user: Ident,
7660        /// The host identifier portion.
7661        host: Ident,
7662    },
7663}
7664
7665impl fmt::Display for GranteeName {
7666    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7667        match self {
7668            GranteeName::ObjectName(name) => name.fmt(f),
7669            GranteeName::UserHost { user, host } => {
7670                write!(f, "{user}@{host}")
7671            }
7672        }
7673    }
7674}
7675
7676/// Objects on which privileges are granted in a GRANT statement.
7677#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7678#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7679#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7680pub enum GrantObjects {
7681    /// Grant privileges on `ALL SEQUENCES IN SCHEMA <schema_name> [, ...]`
7682    AllSequencesInSchema {
7683        /// The target schema names.
7684        schemas: Vec<ObjectName>,
7685    },
7686    /// Grant privileges on `ALL TABLES IN SCHEMA <schema_name> [, ...]`
7687    AllTablesInSchema {
7688        /// The target schema names.
7689        schemas: Vec<ObjectName>,
7690    },
7691    /// Grant privileges on `ALL VIEWS IN SCHEMA <schema_name> [, ...]`
7692    AllViewsInSchema {
7693        /// The target schema names.
7694        schemas: Vec<ObjectName>,
7695    },
7696    /// Grant privileges on `ALL MATERIALIZED VIEWS IN SCHEMA <schema_name> [, ...]`
7697    AllMaterializedViewsInSchema {
7698        /// The target schema names.
7699        schemas: Vec<ObjectName>,
7700    },
7701    /// Grant privileges on `ALL EXTERNAL TABLES IN SCHEMA <schema_name> [, ...]`
7702    AllExternalTablesInSchema {
7703        /// The target schema names.
7704        schemas: Vec<ObjectName>,
7705    },
7706    /// Grant privileges on `ALL FUNCTIONS IN SCHEMA <schema_name> [, ...]`
7707    AllFunctionsInSchema {
7708        /// The target schema names.
7709        schemas: Vec<ObjectName>,
7710    },
7711    /// Grant privileges on `FUTURE SCHEMAS IN DATABASE <database_name> [, ...]`
7712    FutureSchemasInDatabase {
7713        /// The target database names.
7714        databases: Vec<ObjectName>,
7715    },
7716    /// Grant privileges on `FUTURE TABLES IN SCHEMA <schema_name> [, ...]`
7717    FutureTablesInSchema {
7718        /// The target schema names.
7719        schemas: Vec<ObjectName>,
7720    },
7721    /// Grant privileges on `FUTURE VIEWS IN SCHEMA <schema_name> [, ...]`
7722    FutureViewsInSchema {
7723        /// The target schema names.
7724        schemas: Vec<ObjectName>,
7725    },
7726    /// Grant privileges on `FUTURE EXTERNAL TABLES IN SCHEMA <schema_name> [, ...]`
7727    FutureExternalTablesInSchema {
7728        /// The target schema names.
7729        schemas: Vec<ObjectName>,
7730    },
7731    /// Grant privileges on `FUTURE MATERIALIZED VIEWS IN SCHEMA <schema_name> [, ...]`
7732    FutureMaterializedViewsInSchema {
7733        /// The target schema names.
7734        schemas: Vec<ObjectName>,
7735    },
7736    /// Grant privileges on `FUTURE SEQUENCES IN SCHEMA <schema_name> [, ...]`
7737    FutureSequencesInSchema {
7738        /// The target schema names.
7739        schemas: Vec<ObjectName>,
7740    },
7741    /// Grant privileges on specific databases
7742    Databases(Vec<ObjectName>),
7743    /// Grant privileges on specific schemas
7744    Schemas(Vec<ObjectName>),
7745    /// Grant privileges on specific sequences
7746    Sequences(Vec<ObjectName>),
7747    /// Grant privileges on specific tables
7748    Tables(Vec<ObjectName>),
7749    /// Grant privileges on specific views
7750    Views(Vec<ObjectName>),
7751    /// Grant privileges on specific warehouses
7752    Warehouses(Vec<ObjectName>),
7753    /// Grant privileges on specific integrations
7754    Integrations(Vec<ObjectName>),
7755    /// Grant privileges on resource monitors
7756    ResourceMonitors(Vec<ObjectName>),
7757    /// Grant privileges on users
7758    Users(Vec<ObjectName>),
7759    /// Grant privileges on compute pools
7760    ComputePools(Vec<ObjectName>),
7761    /// Grant privileges on connections
7762    Connections(Vec<ObjectName>),
7763    /// Grant privileges on failover groups
7764    FailoverGroup(Vec<ObjectName>),
7765    /// Grant privileges on replication group
7766    ReplicationGroup(Vec<ObjectName>),
7767    /// Grant privileges on external volumes
7768    ExternalVolumes(Vec<ObjectName>),
7769    /// Grant privileges on a procedure. In dialects that
7770    /// support overloading, the argument types must be specified.
7771    ///
7772    /// For example:
7773    /// `GRANT USAGE ON PROCEDURE foo(varchar) TO ROLE role1`
7774    Procedure {
7775        /// The procedure name.
7776        name: ObjectName,
7777        /// Optional argument types for overloaded procedures.
7778        arg_types: Vec<DataType>,
7779    },
7780
7781    /// Grant privileges on a function. In dialects that
7782    /// support overloading, the argument types must be specified.
7783    ///
7784    /// For example:
7785    /// `GRANT USAGE ON FUNCTION foo(varchar) TO ROLE role1`
7786    Function {
7787        /// The function name.
7788        name: ObjectName,
7789        /// Optional argument types for overloaded functions.
7790        arg_types: Vec<DataType>,
7791    },
7792
7793    /// Grant privileges on specific user-defined types (PostgreSQL).
7794    ///
7795    /// For example:
7796    /// `GRANT USAGE ON TYPE user_role TO app_user`
7797    Types(Vec<ObjectName>),
7798
7799    /// Grant privileges on specific domains (PostgreSQL).
7800    ///
7801    /// For example:
7802    /// `GRANT USAGE ON DOMAIN email_addr TO app_user`
7803    Domains(Vec<ObjectName>),
7804}
7805
7806impl fmt::Display for GrantObjects {
7807    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7808        match self {
7809            GrantObjects::Sequences(sequences) => {
7810                write!(f, "SEQUENCE {}", display_comma_separated(sequences))
7811            }
7812            GrantObjects::Databases(databases) => {
7813                write!(f, "DATABASE {}", display_comma_separated(databases))
7814            }
7815            GrantObjects::Schemas(schemas) => {
7816                write!(f, "SCHEMA {}", display_comma_separated(schemas))
7817            }
7818            GrantObjects::Tables(tables) => {
7819                write!(f, "{}", display_comma_separated(tables))
7820            }
7821            GrantObjects::Views(views) => {
7822                write!(f, "VIEW {}", display_comma_separated(views))
7823            }
7824            GrantObjects::Warehouses(warehouses) => {
7825                write!(f, "WAREHOUSE {}", display_comma_separated(warehouses))
7826            }
7827            GrantObjects::Integrations(integrations) => {
7828                write!(f, "INTEGRATION {}", display_comma_separated(integrations))
7829            }
7830            GrantObjects::AllSequencesInSchema { schemas } => {
7831                write!(
7832                    f,
7833                    "ALL SEQUENCES IN SCHEMA {}",
7834                    display_comma_separated(schemas)
7835                )
7836            }
7837            GrantObjects::AllTablesInSchema { schemas } => {
7838                write!(
7839                    f,
7840                    "ALL TABLES IN SCHEMA {}",
7841                    display_comma_separated(schemas)
7842                )
7843            }
7844            GrantObjects::AllExternalTablesInSchema { schemas } => {
7845                write!(
7846                    f,
7847                    "ALL EXTERNAL TABLES IN SCHEMA {}",
7848                    display_comma_separated(schemas)
7849                )
7850            }
7851            GrantObjects::AllViewsInSchema { schemas } => {
7852                write!(
7853                    f,
7854                    "ALL VIEWS IN SCHEMA {}",
7855                    display_comma_separated(schemas)
7856                )
7857            }
7858            GrantObjects::AllMaterializedViewsInSchema { schemas } => {
7859                write!(
7860                    f,
7861                    "ALL MATERIALIZED VIEWS IN SCHEMA {}",
7862                    display_comma_separated(schemas)
7863                )
7864            }
7865            GrantObjects::AllFunctionsInSchema { schemas } => {
7866                write!(
7867                    f,
7868                    "ALL FUNCTIONS IN SCHEMA {}",
7869                    display_comma_separated(schemas)
7870                )
7871            }
7872            GrantObjects::FutureSchemasInDatabase { databases } => {
7873                write!(
7874                    f,
7875                    "FUTURE SCHEMAS IN DATABASE {}",
7876                    display_comma_separated(databases)
7877                )
7878            }
7879            GrantObjects::FutureTablesInSchema { schemas } => {
7880                write!(
7881                    f,
7882                    "FUTURE TABLES IN SCHEMA {}",
7883                    display_comma_separated(schemas)
7884                )
7885            }
7886            GrantObjects::FutureExternalTablesInSchema { schemas } => {
7887                write!(
7888                    f,
7889                    "FUTURE EXTERNAL TABLES IN SCHEMA {}",
7890                    display_comma_separated(schemas)
7891                )
7892            }
7893            GrantObjects::FutureViewsInSchema { schemas } => {
7894                write!(
7895                    f,
7896                    "FUTURE VIEWS IN SCHEMA {}",
7897                    display_comma_separated(schemas)
7898                )
7899            }
7900            GrantObjects::FutureMaterializedViewsInSchema { schemas } => {
7901                write!(
7902                    f,
7903                    "FUTURE MATERIALIZED VIEWS IN SCHEMA {}",
7904                    display_comma_separated(schemas)
7905                )
7906            }
7907            GrantObjects::FutureSequencesInSchema { schemas } => {
7908                write!(
7909                    f,
7910                    "FUTURE SEQUENCES IN SCHEMA {}",
7911                    display_comma_separated(schemas)
7912                )
7913            }
7914            GrantObjects::ResourceMonitors(objects) => {
7915                write!(f, "RESOURCE MONITOR {}", display_comma_separated(objects))
7916            }
7917            GrantObjects::Users(objects) => {
7918                write!(f, "USER {}", display_comma_separated(objects))
7919            }
7920            GrantObjects::ComputePools(objects) => {
7921                write!(f, "COMPUTE POOL {}", display_comma_separated(objects))
7922            }
7923            GrantObjects::Connections(objects) => {
7924                write!(f, "CONNECTION {}", display_comma_separated(objects))
7925            }
7926            GrantObjects::FailoverGroup(objects) => {
7927                write!(f, "FAILOVER GROUP {}", display_comma_separated(objects))
7928            }
7929            GrantObjects::ReplicationGroup(objects) => {
7930                write!(f, "REPLICATION GROUP {}", display_comma_separated(objects))
7931            }
7932            GrantObjects::ExternalVolumes(objects) => {
7933                write!(f, "EXTERNAL VOLUME {}", display_comma_separated(objects))
7934            }
7935            GrantObjects::Procedure { name, arg_types } => {
7936                write!(f, "PROCEDURE {name}")?;
7937                if !arg_types.is_empty() {
7938                    write!(f, "({})", display_comma_separated(arg_types))?;
7939                }
7940                Ok(())
7941            }
7942            GrantObjects::Function { name, arg_types } => {
7943                write!(f, "FUNCTION {name}")?;
7944                if !arg_types.is_empty() {
7945                    write!(f, "({})", display_comma_separated(arg_types))?;
7946                }
7947                Ok(())
7948            }
7949            GrantObjects::Types(types) => {
7950                write!(f, "TYPE {}", display_comma_separated(types))
7951            }
7952            GrantObjects::Domains(domains) => {
7953                write!(f, "DOMAIN {}", display_comma_separated(domains))
7954            }
7955        }
7956    }
7957}
7958
7959/// A `DENY` statement
7960///
7961/// [MsSql](https://learn.microsoft.com/en-us/sql/t-sql/statements/deny-transact-sql)
7962#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7963#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7964#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7965pub struct DenyStatement {
7966    /// The privileges to deny.
7967    pub privileges: Privileges,
7968    /// The objects the privileges apply to.
7969    pub objects: GrantObjects,
7970    /// The grantees (users/roles) to whom the denial applies.
7971    pub grantees: Vec<Grantee>,
7972    /// Optional identifier of the principal that performed the grant.
7973    pub granted_by: Option<Ident>,
7974    /// Optional cascade option controlling dependent objects.
7975    pub cascade: Option<CascadeOption>,
7976}
7977
7978impl fmt::Display for DenyStatement {
7979    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7980        write!(f, "DENY {}", self.privileges)?;
7981        write!(f, " ON {}", self.objects)?;
7982        if !self.grantees.is_empty() {
7983            write!(f, " TO {}", display_comma_separated(&self.grantees))?;
7984        }
7985        if let Some(cascade) = &self.cascade {
7986            write!(f, " {cascade}")?;
7987        }
7988        if let Some(granted_by) = &self.granted_by {
7989            write!(f, " AS {granted_by}")?;
7990        }
7991        Ok(())
7992    }
7993}
7994
7995/// SQL assignment `foo = expr` as used in SQLUpdate
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 Assignment {
8000    /// The left-hand side of the assignment.
8001    pub target: AssignmentTarget,
8002    /// The expression assigned to the target.
8003    pub value: Expr,
8004}
8005
8006impl fmt::Display for Assignment {
8007    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8008        write!(f, "{} = {}", self.target, self.value)
8009    }
8010}
8011
8012/// Left-hand side of an assignment in an UPDATE statement,
8013/// e.g. `foo` in `foo = 5` (ColumnName assignment) or
8014/// `(a, b)` in `(a, b) = (1, 2)` (Tuple assignment).
8015#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8016#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8017#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8018pub enum AssignmentTarget {
8019    /// A single column
8020    ColumnName(ObjectName),
8021    /// A tuple of columns
8022    Tuple(Vec<ObjectName>),
8023}
8024
8025impl fmt::Display for AssignmentTarget {
8026    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8027        match self {
8028            AssignmentTarget::ColumnName(column) => write!(f, "{column}"),
8029            AssignmentTarget::Tuple(columns) => write!(f, "({})", display_comma_separated(columns)),
8030        }
8031    }
8032}
8033
8034#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8035#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8036#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8037/// Expression forms allowed as a function argument.
8038pub enum FunctionArgExpr {
8039    /// A normal expression argument.
8040    Expr(Expr),
8041    /// Qualified wildcard, e.g. `alias.*` or `schema.table.*`.
8042    QualifiedWildcard(ObjectName),
8043    /// An unqualified `*` wildcard.
8044    Wildcard,
8045    /// An unqualified `*` wildcard with additional options, e.g. `* EXCLUDE(col)`.
8046    ///
8047    /// Used in Snowflake to support expressions like `HASH(* EXCLUDE(col))`.
8048    WildcardWithOptions(WildcardAdditionalOptions),
8049}
8050
8051impl From<Expr> for FunctionArgExpr {
8052    fn from(wildcard_expr: Expr) -> Self {
8053        match wildcard_expr {
8054            Expr::QualifiedWildcard(prefix, _) => Self::QualifiedWildcard(prefix),
8055            Expr::Wildcard(_) => Self::Wildcard,
8056            expr => Self::Expr(expr),
8057        }
8058    }
8059}
8060
8061impl fmt::Display for FunctionArgExpr {
8062    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8063        match self {
8064            FunctionArgExpr::Expr(expr) => write!(f, "{expr}"),
8065            FunctionArgExpr::QualifiedWildcard(prefix) => write!(f, "{prefix}.*"),
8066            FunctionArgExpr::Wildcard => f.write_str("*"),
8067            FunctionArgExpr::WildcardWithOptions(opts) => write!(f, "*{opts}"),
8068        }
8069    }
8070}
8071
8072#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8073#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8074#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8075/// Operator used to separate function arguments
8076pub enum FunctionArgOperator {
8077    /// function(arg1 = value1)
8078    Equals,
8079    /// function(arg1 => value1)
8080    RightArrow,
8081    /// function(arg1 := value1)
8082    Assignment,
8083    /// function(arg1 : value1)
8084    Colon,
8085    /// function(arg1 VALUE value1)
8086    Value,
8087}
8088
8089impl fmt::Display for FunctionArgOperator {
8090    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8091        match self {
8092            FunctionArgOperator::Equals => f.write_str("="),
8093            FunctionArgOperator::RightArrow => f.write_str("=>"),
8094            FunctionArgOperator::Assignment => f.write_str(":="),
8095            FunctionArgOperator::Colon => f.write_str(":"),
8096            FunctionArgOperator::Value => f.write_str("VALUE"),
8097        }
8098    }
8099}
8100
8101#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8102#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8103#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8104/// Forms of function arguments (named, expression-named, or positional).
8105pub enum FunctionArg {
8106    /// `name` is identifier
8107    ///
8108    /// Enabled when `Dialect::supports_named_fn_args_with_expr_name` returns 'false'
8109    Named {
8110        /// The identifier name of the argument.
8111        name: Ident,
8112        /// The argument expression or wildcard form.
8113        arg: FunctionArgExpr,
8114        /// The operator separating name and value.
8115        operator: FunctionArgOperator,
8116    },
8117    /// `name` is arbitrary expression
8118    ///
8119    /// Enabled when `Dialect::supports_named_fn_args_with_expr_name` returns 'true'
8120    ExprNamed {
8121        /// The expression used as the argument name.
8122        name: Expr,
8123        /// The argument expression or wildcard form.
8124        arg: FunctionArgExpr,
8125        /// The operator separating name and value.
8126        operator: FunctionArgOperator,
8127    },
8128    /// An unnamed argument (positional), given by expression or wildcard.
8129    Unnamed(FunctionArgExpr),
8130}
8131
8132impl fmt::Display for FunctionArg {
8133    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8134        match self {
8135            FunctionArg::Named {
8136                name,
8137                arg,
8138                operator,
8139            } => write!(f, "{name} {operator} {arg}"),
8140            FunctionArg::ExprNamed {
8141                name,
8142                arg,
8143                operator,
8144            } => write!(f, "{name} {operator} {arg}"),
8145            FunctionArg::Unnamed(unnamed_arg) => write!(f, "{unnamed_arg}"),
8146        }
8147    }
8148}
8149
8150#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8151#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8152#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8153/// Which cursor(s) to close.
8154pub enum CloseCursor {
8155    /// Close all cursors.
8156    All,
8157    /// Close a specific cursor by name.
8158    Specific {
8159        /// The name of the cursor to close.
8160        name: Ident,
8161    },
8162}
8163
8164impl fmt::Display for CloseCursor {
8165    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8166        match self {
8167            CloseCursor::All => write!(f, "ALL"),
8168            CloseCursor::Specific { name } => write!(f, "{name}"),
8169        }
8170    }
8171}
8172
8173/// A Drop Domain statement
8174#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8175#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8176#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8177pub struct DropDomain {
8178    /// Whether to drop the domain if it exists
8179    pub if_exists: bool,
8180    /// The name of the domain to drop
8181    pub name: ObjectName,
8182    /// The behavior to apply when dropping the domain
8183    pub drop_behavior: Option<DropBehavior>,
8184}
8185
8186/// A constant of form `<data_type> 'value'`.
8187/// This can represent ANSI SQL `DATE`, `TIME`, and `TIMESTAMP` literals (such as `DATE '2020-01-01'`),
8188/// as well as constants of other types (a non-standard PostgreSQL extension).
8189#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8190#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8191#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8192pub struct TypedString {
8193    /// The data type of the typed string (e.g. DATE, TIME, TIMESTAMP).
8194    pub data_type: DataType,
8195    /// The value of the constant.
8196    /// Hint: you can unwrap the string value using `value.into_string()`.
8197    pub value: ValueWithSpan,
8198    /// Flags whether this TypedString uses the [ODBC syntax].
8199    ///
8200    /// Example:
8201    /// ```sql
8202    /// -- An ODBC date literal:
8203    /// SELECT {d '2025-07-16'}
8204    /// -- This is equivalent to the standard ANSI SQL literal:
8205    /// SELECT DATE '2025-07-16'
8206    ///
8207    /// [ODBC syntax]: https://learn.microsoft.com/en-us/sql/odbc/reference/develop-app/date-time-and-timestamp-literals?view=sql-server-2017
8208    pub uses_odbc_syntax: bool,
8209}
8210
8211impl fmt::Display for TypedString {
8212    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8213        let data_type = &self.data_type;
8214        let value = &self.value;
8215        match self.uses_odbc_syntax {
8216            false => {
8217                write!(f, "{data_type}")?;
8218                write!(f, " {value}")
8219            }
8220            true => {
8221                let prefix = match data_type {
8222                    DataType::Date => "d",
8223                    DataType::Time(..) => "t",
8224                    DataType::Timestamp(..) => "ts",
8225                    _ => "?",
8226                };
8227                write!(f, "{{{prefix} {value}}}")
8228            }
8229        }
8230    }
8231}
8232
8233/// A function call
8234#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8235#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8236#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8237pub struct Function {
8238    /// The function name (may be qualified).
8239    pub name: ObjectName,
8240    /// Flags whether this function call uses the [ODBC syntax].
8241    ///
8242    /// Example:
8243    /// ```sql
8244    /// SELECT {fn CONCAT('foo', 'bar')}
8245    /// ```
8246    ///
8247    /// [ODBC syntax]: https://learn.microsoft.com/en-us/sql/odbc/reference/develop-app/scalar-function-calls?view=sql-server-2017
8248    pub uses_odbc_syntax: bool,
8249    /// The parameters to the function, including any options specified within the
8250    /// delimiting parentheses.
8251    ///
8252    /// Example:
8253    /// ```plaintext
8254    /// HISTOGRAM(0.5, 0.6)(x, y)
8255    /// ```
8256    ///
8257    /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/aggregate-functions/parametric-functions)
8258    pub parameters: FunctionArguments,
8259    /// The arguments to the function, including any options specified within the
8260    /// delimiting parentheses.
8261    pub args: FunctionArguments,
8262    /// e.g. `x > 5` in `COUNT(x) FILTER (WHERE x > 5)`
8263    pub filter: Option<Box<Expr>>,
8264    /// Indicates how `NULL`s should be handled in the calculation.
8265    ///
8266    /// Example:
8267    /// ```plaintext
8268    /// FIRST_VALUE( <expr> ) [ { IGNORE | RESPECT } NULLS ] OVER ...
8269    /// ```
8270    ///
8271    /// [Snowflake](https://docs.snowflake.com/en/sql-reference/functions/first_value)
8272    pub null_treatment: Option<NullTreatment>,
8273    /// The `OVER` clause, indicating a window function call.
8274    pub over: Option<WindowType>,
8275    /// A clause used with certain aggregate functions to control the ordering
8276    /// within grouped sets before the function is applied.
8277    ///
8278    /// Syntax:
8279    /// ```plaintext
8280    /// <aggregate_function>(expression) WITHIN GROUP (ORDER BY key [ASC | DESC], ...)
8281    /// ```
8282    pub within_group: Vec<OrderByExpr>,
8283}
8284
8285impl fmt::Display for Function {
8286    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8287        if self.uses_odbc_syntax {
8288            write!(f, "{{fn ")?;
8289        }
8290
8291        write!(f, "{}{}{}", self.name, self.parameters, self.args)?;
8292
8293        if !self.within_group.is_empty() {
8294            write!(
8295                f,
8296                " WITHIN GROUP (ORDER BY {})",
8297                display_comma_separated(&self.within_group)
8298            )?;
8299        }
8300
8301        if let Some(filter_cond) = &self.filter {
8302            write!(f, " FILTER (WHERE {filter_cond})")?;
8303        }
8304
8305        if let Some(null_treatment) = &self.null_treatment {
8306            write!(f, " {null_treatment}")?;
8307        }
8308
8309        if let Some(o) = &self.over {
8310            f.write_str(" OVER ")?;
8311            o.fmt(f)?;
8312        }
8313
8314        if self.uses_odbc_syntax {
8315            write!(f, "}}")?;
8316        }
8317
8318        Ok(())
8319    }
8320}
8321
8322/// The arguments passed to a function call.
8323#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8324#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8325#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8326pub enum FunctionArguments {
8327    /// Used for special functions like `CURRENT_TIMESTAMP` that are invoked
8328    /// without parentheses.
8329    None,
8330    /// On some dialects, a subquery can be passed without surrounding
8331    /// parentheses if it's the sole argument to the function.
8332    Subquery(Box<Query>),
8333    /// A normal function argument list, including any clauses within it such as
8334    /// `DISTINCT` or `ORDER BY`.
8335    List(FunctionArgumentList),
8336}
8337
8338impl fmt::Display for FunctionArguments {
8339    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8340        match self {
8341            FunctionArguments::None => Ok(()),
8342            FunctionArguments::Subquery(query) => write!(f, "({query})"),
8343            FunctionArguments::List(args) => write!(f, "({args})"),
8344        }
8345    }
8346}
8347
8348/// This represents everything inside the parentheses when calling a function.
8349#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8350#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8351#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8352pub struct FunctionArgumentList {
8353    /// `[ ALL | DISTINCT ]`
8354    pub duplicate_treatment: Option<DuplicateTreatment>,
8355    /// The function arguments.
8356    pub args: Vec<FunctionArg>,
8357    /// Additional clauses specified within the argument list.
8358    pub clauses: Vec<FunctionArgumentClause>,
8359}
8360
8361impl fmt::Display for FunctionArgumentList {
8362    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8363        if let Some(duplicate_treatment) = self.duplicate_treatment {
8364            write!(f, "{duplicate_treatment} ")?;
8365        }
8366        write!(f, "{}", display_comma_separated(&self.args))?;
8367        if !self.clauses.is_empty() {
8368            if !self.args.is_empty() {
8369                write!(f, " ")?;
8370            }
8371            write!(f, "{}", display_separated(&self.clauses, " "))?;
8372        }
8373        Ok(())
8374    }
8375}
8376
8377#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8378#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8379#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8380/// Clauses that can appear inside a function argument list.
8381pub enum FunctionArgumentClause {
8382    /// Indicates how `NULL`s should be handled in the calculation, e.g. in `FIRST_VALUE` on [BigQuery].
8383    ///
8384    /// Syntax:
8385    /// ```plaintext
8386    /// { IGNORE | RESPECT } NULLS ]
8387    /// ```
8388    ///
8389    /// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/navigation_functions#first_value
8390    IgnoreOrRespectNulls(NullTreatment),
8391    /// Specifies the the ordering for some ordered set aggregates, e.g. `ARRAY_AGG` on [BigQuery].
8392    ///
8393    /// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/aggregate_functions#array_agg
8394    OrderBy(Vec<OrderByExpr>),
8395    /// Specifies a limit for the `ARRAY_AGG` and `ARRAY_CONCAT_AGG` functions on BigQuery.
8396    Limit(Expr),
8397    /// Specifies the behavior on overflow of the `LISTAGG` function.
8398    ///
8399    /// See <https://trino.io/docs/current/functions/aggregate.html>.
8400    OnOverflow(ListAggOnOverflow),
8401    /// Specifies a minimum or maximum bound on the input to [`ANY_VALUE`] on BigQuery.
8402    ///
8403    /// Syntax:
8404    /// ```plaintext
8405    /// HAVING { MAX | MIN } expression
8406    /// ```
8407    ///
8408    /// [`ANY_VALUE`]: https://cloud.google.com/bigquery/docs/reference/standard-sql/aggregate_functions#any_value
8409    Having(HavingBound),
8410    /// The `SEPARATOR` clause to the [`GROUP_CONCAT`] function in MySQL.
8411    ///
8412    /// [`GROUP_CONCAT`]: https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html#function_group-concat
8413    Separator(ValueWithSpan),
8414    /// The `ON NULL` clause for some JSON functions.
8415    ///
8416    /// [MSSQL `JSON_ARRAY`](https://learn.microsoft.com/en-us/sql/t-sql/functions/json-array-transact-sql?view=sql-server-ver16)
8417    /// [MSSQL `JSON_OBJECT`](https://learn.microsoft.com/en-us/sql/t-sql/functions/json-object-transact-sql?view=sql-server-ver16>)
8418    /// [PostgreSQL JSON functions](https://www.postgresql.org/docs/current/functions-json.html#FUNCTIONS-JSON-PROCESSING)
8419    JsonNullClause(JsonNullClause),
8420    /// The `RETURNING` clause for some JSON functions in PostgreSQL
8421    ///
8422    /// [`JSON_OBJECT`](https://www.postgresql.org/docs/current/functions-json.html#:~:text=json_object)
8423    JsonReturningClause(JsonReturningClause),
8424}
8425
8426impl fmt::Display for FunctionArgumentClause {
8427    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8428        match self {
8429            FunctionArgumentClause::IgnoreOrRespectNulls(null_treatment) => {
8430                write!(f, "{null_treatment}")
8431            }
8432            FunctionArgumentClause::OrderBy(order_by) => {
8433                write!(f, "ORDER BY {}", display_comma_separated(order_by))
8434            }
8435            FunctionArgumentClause::Limit(limit) => write!(f, "LIMIT {limit}"),
8436            FunctionArgumentClause::OnOverflow(on_overflow) => write!(f, "{on_overflow}"),
8437            FunctionArgumentClause::Having(bound) => write!(f, "{bound}"),
8438            FunctionArgumentClause::Separator(sep) => write!(f, "SEPARATOR {sep}"),
8439            FunctionArgumentClause::JsonNullClause(null_clause) => write!(f, "{null_clause}"),
8440            FunctionArgumentClause::JsonReturningClause(returning_clause) => {
8441                write!(f, "{returning_clause}")
8442            }
8443        }
8444    }
8445}
8446
8447/// A method call
8448#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8449#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8450#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8451pub struct Method {
8452    /// The expression on which the method is invoked.
8453    pub expr: Box<Expr>,
8454    // always non-empty
8455    /// The sequence of chained method calls.
8456    pub method_chain: Vec<Function>,
8457}
8458
8459impl fmt::Display for Method {
8460    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8461        write!(
8462            f,
8463            "{}.{}",
8464            self.expr,
8465            display_separated(&self.method_chain, ".")
8466        )
8467    }
8468}
8469
8470#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8471#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8472#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8473/// How duplicate values are treated inside function argument lists.
8474pub enum DuplicateTreatment {
8475    /// Consider only unique values.
8476    Distinct,
8477    /// Retain all duplicate values (the default).
8478    All,
8479}
8480
8481impl fmt::Display for DuplicateTreatment {
8482    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8483        match self {
8484            DuplicateTreatment::Distinct => write!(f, "DISTINCT"),
8485            DuplicateTreatment::All => write!(f, "ALL"),
8486        }
8487    }
8488}
8489
8490#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8491#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8492#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8493/// How the `ANALYZE`/`EXPLAIN ANALYZE` format is specified.
8494pub enum AnalyzeFormatKind {
8495    /// Format provided as a keyword, e.g. `FORMAT JSON`.
8496    Keyword(AnalyzeFormat),
8497    /// Format provided as an assignment, e.g. `FORMAT=JSON`.
8498    Assignment(AnalyzeFormat),
8499}
8500
8501impl fmt::Display for AnalyzeFormatKind {
8502    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
8503        match self {
8504            AnalyzeFormatKind::Keyword(format) => write!(f, "FORMAT {format}"),
8505            AnalyzeFormatKind::Assignment(format) => write!(f, "FORMAT={format}"),
8506        }
8507    }
8508}
8509
8510#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8511#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8512#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8513/// Output formats supported for `ANALYZE`/`EXPLAIN ANALYZE`.
8514pub enum AnalyzeFormat {
8515    /// Plain text format.
8516    TEXT,
8517    /// Graphviz DOT format.
8518    GRAPHVIZ,
8519    /// JSON format.
8520    JSON,
8521    /// Traditional explain output.
8522    TRADITIONAL,
8523    /// Tree-style explain output.
8524    TREE,
8525}
8526
8527impl fmt::Display for AnalyzeFormat {
8528    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
8529        f.write_str(match self {
8530            AnalyzeFormat::TEXT => "TEXT",
8531            AnalyzeFormat::GRAPHVIZ => "GRAPHVIZ",
8532            AnalyzeFormat::JSON => "JSON",
8533            AnalyzeFormat::TRADITIONAL => "TRADITIONAL",
8534            AnalyzeFormat::TREE => "TREE",
8535        })
8536    }
8537}
8538
8539/// External table's available file format
8540#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8541#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8542#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8543pub enum FileFormat {
8544    /// Text file format.
8545    TEXTFILE,
8546    /// Sequence file format.
8547    SEQUENCEFILE,
8548    /// ORC file format.
8549    ORC,
8550    /// Parquet file format.
8551    PARQUET,
8552    /// Avro file format.
8553    AVRO,
8554    /// RCFile format.
8555    RCFILE,
8556    /// JSON file format.
8557    JSONFILE,
8558}
8559
8560impl fmt::Display for FileFormat {
8561    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8562        use self::FileFormat::*;
8563        f.write_str(match self {
8564            TEXTFILE => "TEXTFILE",
8565            SEQUENCEFILE => "SEQUENCEFILE",
8566            ORC => "ORC",
8567            PARQUET => "PARQUET",
8568            AVRO => "AVRO",
8569            RCFILE => "RCFILE",
8570            JSONFILE => "JSONFILE",
8571        })
8572    }
8573}
8574
8575/// The `ON OVERFLOW` clause of a LISTAGG invocation
8576#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8577#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8578#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8579pub enum ListAggOnOverflow {
8580    /// `ON OVERFLOW ERROR`
8581    Error,
8582
8583    /// `ON OVERFLOW TRUNCATE [ <filler> ] WITH[OUT] COUNT`
8584    Truncate {
8585        /// Optional filler expression used when truncating.
8586        filler: Option<Box<Expr>>,
8587        /// Whether to include a count when truncating.
8588        with_count: bool,
8589    },
8590}
8591
8592impl fmt::Display for ListAggOnOverflow {
8593    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8594        write!(f, "ON OVERFLOW")?;
8595        match self {
8596            ListAggOnOverflow::Error => write!(f, " ERROR"),
8597            ListAggOnOverflow::Truncate { filler, with_count } => {
8598                write!(f, " TRUNCATE")?;
8599                if let Some(filler) = filler {
8600                    write!(f, " {filler}")?;
8601                }
8602                if *with_count {
8603                    write!(f, " WITH")?;
8604                } else {
8605                    write!(f, " WITHOUT")?;
8606                }
8607                write!(f, " COUNT")
8608            }
8609        }
8610    }
8611}
8612
8613/// The `HAVING` clause in a call to `ANY_VALUE` on BigQuery.
8614#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8615#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8616#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8617pub struct HavingBound(pub HavingBoundKind, pub Expr);
8618
8619impl fmt::Display for HavingBound {
8620    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8621        write!(f, "HAVING {} {}", self.0, self.1)
8622    }
8623}
8624
8625#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8626#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8627#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8628/// Which bound is used in a HAVING clause for ANY_VALUE on BigQuery.
8629pub enum HavingBoundKind {
8630    /// The minimum bound.
8631    Min,
8632    /// The maximum bound.
8633    Max,
8634}
8635
8636impl fmt::Display for HavingBoundKind {
8637    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8638        match self {
8639            HavingBoundKind::Min => write!(f, "MIN"),
8640            HavingBoundKind::Max => write!(f, "MAX"),
8641        }
8642    }
8643}
8644
8645#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8646#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8647#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8648/// Types of database objects referenced by DDL statements.
8649pub enum ObjectType {
8650    /// A collation.
8651    Collation,
8652    /// A table.
8653    Table,
8654    /// A view.
8655    View,
8656    /// A materialized view.
8657    MaterializedView,
8658    /// An index.
8659    Index,
8660    /// A schema.
8661    Schema,
8662    /// A database.
8663    Database,
8664    /// A role.
8665    Role,
8666    /// A sequence.
8667    Sequence,
8668    /// A stage.
8669    Stage,
8670    /// A type definition.
8671    Type,
8672    /// A user.
8673    User,
8674    /// A stream.
8675    Stream,
8676}
8677
8678impl fmt::Display for ObjectType {
8679    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8680        f.write_str(match self {
8681            ObjectType::Collation => "COLLATION",
8682            ObjectType::Table => "TABLE",
8683            ObjectType::View => "VIEW",
8684            ObjectType::MaterializedView => "MATERIALIZED VIEW",
8685            ObjectType::Index => "INDEX",
8686            ObjectType::Schema => "SCHEMA",
8687            ObjectType::Database => "DATABASE",
8688            ObjectType::Role => "ROLE",
8689            ObjectType::Sequence => "SEQUENCE",
8690            ObjectType::Stage => "STAGE",
8691            ObjectType::Type => "TYPE",
8692            ObjectType::User => "USER",
8693            ObjectType::Stream => "STREAM",
8694        })
8695    }
8696}
8697
8698#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8699#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8700#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8701/// Types supported by `KILL` statements.
8702pub enum KillType {
8703    /// Kill a connection.
8704    Connection,
8705    /// Kill a running query.
8706    Query,
8707    /// Kill a mutation (ClickHouse).
8708    Mutation,
8709}
8710
8711impl fmt::Display for KillType {
8712    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8713        f.write_str(match self {
8714            // MySQL
8715            KillType::Connection => "CONNECTION",
8716            KillType::Query => "QUERY",
8717            // Clickhouse supports Mutation
8718            KillType::Mutation => "MUTATION",
8719        })
8720    }
8721}
8722
8723#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8724#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8725#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8726/// Distribution style options for Hive tables.
8727pub enum HiveDistributionStyle {
8728    /// Partitioned distribution with the given columns.
8729    PARTITIONED {
8730        /// Columns used for partitioning.
8731        columns: Vec<ColumnDef>,
8732    },
8733    /// Skewed distribution definition.
8734    SKEWED {
8735        /// Columns participating in the skew definition.
8736        columns: Vec<ColumnDef>,
8737        /// Columns listed in the `ON` clause for skewing.
8738        on: Vec<ColumnDef>,
8739        /// Whether skewed data is stored as directories.
8740        stored_as_directories: bool,
8741    },
8742    /// No distribution style specified.
8743    NONE,
8744}
8745
8746#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8747#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8748#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8749/// Row format specification for Hive tables (SERDE or DELIMITED).
8750pub enum HiveRowFormat {
8751    /// SerDe class specification with the implementing class name.
8752    SERDE {
8753        /// The SerDe implementation class name.
8754        class: String,
8755    },
8756    /// Delimited row format with one or more delimiter specifications.
8757    DELIMITED {
8758        /// The list of delimiters used for delimiting fields/lines.
8759        delimiters: Vec<HiveRowDelimiter>,
8760    },
8761}
8762
8763#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8764#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8765#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8766/// Format specification for `LOAD DATA` Hive operations.
8767pub struct HiveLoadDataFormat {
8768    /// SerDe expression used for the table.
8769    pub serde: Expr,
8770    /// Input format expression.
8771    pub input_format: Expr,
8772}
8773
8774#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8775#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8776#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8777/// A single row delimiter specification for Hive `ROW FORMAT`.
8778pub struct HiveRowDelimiter {
8779    /// The delimiter kind (fields/lines/etc.).
8780    pub delimiter: HiveDelimiter,
8781    /// The delimiter character identifier.
8782    pub char: Ident,
8783}
8784
8785impl fmt::Display for HiveRowDelimiter {
8786    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8787        write!(f, "{} ", self.delimiter)?;
8788        write!(f, "{}", self.char)
8789    }
8790}
8791
8792#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8793#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8794#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8795/// Kind of delimiter used in Hive `ROW FORMAT` definitions.
8796pub enum HiveDelimiter {
8797    /// Fields terminated by a delimiter.
8798    FieldsTerminatedBy,
8799    /// Fields escaped by a character.
8800    FieldsEscapedBy,
8801    /// Collection items terminated by a delimiter.
8802    CollectionItemsTerminatedBy,
8803    /// Map keys terminated by a delimiter.
8804    MapKeysTerminatedBy,
8805    /// Lines terminated by a delimiter.
8806    LinesTerminatedBy,
8807    /// Null represented by a specific token.
8808    NullDefinedAs,
8809}
8810
8811impl fmt::Display for HiveDelimiter {
8812    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8813        use HiveDelimiter::*;
8814        f.write_str(match self {
8815            FieldsTerminatedBy => "FIELDS TERMINATED BY",
8816            FieldsEscapedBy => "ESCAPED BY",
8817            CollectionItemsTerminatedBy => "COLLECTION ITEMS TERMINATED BY",
8818            MapKeysTerminatedBy => "MAP KEYS TERMINATED BY",
8819            LinesTerminatedBy => "LINES TERMINATED BY",
8820            NullDefinedAs => "NULL DEFINED AS",
8821        })
8822    }
8823}
8824
8825#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8826#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8827#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8828/// Describe output format options for Hive `DESCRIBE`/`EXPLAIN`.
8829pub enum HiveDescribeFormat {
8830    /// Extended describe output.
8831    Extended,
8832    /// Formatted describe output.
8833    Formatted,
8834}
8835
8836impl fmt::Display for HiveDescribeFormat {
8837    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8838        use HiveDescribeFormat::*;
8839        f.write_str(match self {
8840            Extended => "EXTENDED",
8841            Formatted => "FORMATTED",
8842        })
8843    }
8844}
8845
8846#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8847#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8848#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8849/// Aliases accepted for describe-style commands.
8850pub enum DescribeAlias {
8851    /// `DESCRIBE` alias.
8852    Describe,
8853    /// `EXPLAIN` alias.
8854    Explain,
8855    /// `DESC` alias.
8856    Desc,
8857}
8858
8859impl fmt::Display for DescribeAlias {
8860    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8861        use DescribeAlias::*;
8862        f.write_str(match self {
8863            Describe => "DESCRIBE",
8864            Explain => "EXPLAIN",
8865            Desc => "DESC",
8866        })
8867    }
8868}
8869
8870#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8871#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8872#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8873#[allow(clippy::large_enum_variant)]
8874/// Hive input/output format specification used in `CREATE TABLE`.
8875pub enum HiveIOFormat {
8876    /// Generic IO format with separate input and output expressions.
8877    IOF {
8878        /// Expression for the input format.
8879        input_format: Expr,
8880        /// Expression for the output format.
8881        output_format: Expr,
8882    },
8883    /// File format wrapper referencing a `FileFormat` variant.
8884    FileFormat {
8885        /// The file format used for storage.
8886        format: FileFormat,
8887    },
8888}
8889
8890#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Default)]
8891#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8892#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8893/// Hive table format and storage-related options.
8894pub struct HiveFormat {
8895    /// Optional row format specification.
8896    pub row_format: Option<HiveRowFormat>,
8897    /// Optional SerDe properties expressed as SQL options.
8898    pub serde_properties: Option<Vec<SqlOption>>,
8899    /// Optional input/output storage format details.
8900    pub storage: Option<HiveIOFormat>,
8901    /// Optional location (URI or path) for table data.
8902    pub location: Option<String>,
8903}
8904
8905#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8906#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8907#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8908/// A clustered index column specification.
8909pub struct ClusteredIndex {
8910    /// Column identifier for the clustered index entry.
8911    pub name: Ident,
8912    /// Optional sort direction: `Some(true)` for ASC, `Some(false)` for DESC, `None` for unspecified.
8913    pub asc: Option<bool>,
8914}
8915
8916impl fmt::Display for ClusteredIndex {
8917    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8918        write!(f, "{}", self.name)?;
8919        match self.asc {
8920            Some(true) => write!(f, " ASC"),
8921            Some(false) => write!(f, " DESC"),
8922            _ => Ok(()),
8923        }
8924    }
8925}
8926
8927#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8928#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8929#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8930/// Clustered options used for `CREATE TABLE` clustered/indexed storage.
8931pub enum TableOptionsClustered {
8932    /// Use a columnstore index.
8933    ColumnstoreIndex,
8934    /// Columnstore index with an explicit ordering of columns.
8935    ColumnstoreIndexOrder(Vec<Ident>),
8936    /// A named clustered index with one or more columns.
8937    Index(Vec<ClusteredIndex>),
8938}
8939
8940impl fmt::Display for TableOptionsClustered {
8941    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8942        match self {
8943            TableOptionsClustered::ColumnstoreIndex => {
8944                write!(f, "CLUSTERED COLUMNSTORE INDEX")
8945            }
8946            TableOptionsClustered::ColumnstoreIndexOrder(values) => {
8947                write!(
8948                    f,
8949                    "CLUSTERED COLUMNSTORE INDEX ORDER ({})",
8950                    display_comma_separated(values)
8951                )
8952            }
8953            TableOptionsClustered::Index(values) => {
8954                write!(f, "CLUSTERED INDEX ({})", display_comma_separated(values))
8955            }
8956        }
8957    }
8958}
8959
8960/// Specifies which partition the boundary values on table partitioning belongs to.
8961#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash)]
8962#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8963#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8964pub enum PartitionRangeDirection {
8965    /// LEFT range direction.
8966    Left,
8967    /// RIGHT range direction.
8968    Right,
8969}
8970
8971#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8972#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8973#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8974/// SQL option syntax used in table and server definitions.
8975pub enum SqlOption {
8976    /// Clustered represents the clustered version of table storage for MSSQL.
8977    ///
8978    /// <https://learn.microsoft.com/en-us/sql/t-sql/statements/create-table-azure-sql-data-warehouse?view=aps-pdw-2016-au7#TableOptions>
8979    Clustered(TableOptionsClustered),
8980    /// Single identifier options, e.g. `HEAP` for MSSQL.
8981    ///
8982    /// <https://learn.microsoft.com/en-us/sql/t-sql/statements/create-table-azure-sql-data-warehouse?view=aps-pdw-2016-au7#TableOptions>
8983    Ident(Ident),
8984    /// Any option that consists of a key value pair where the value is an expression. e.g.
8985    ///
8986    ///   WITH(DISTRIBUTION = ROUND_ROBIN)
8987    KeyValue {
8988        /// The option key identifier.
8989        key: Ident,
8990        /// The expression value for the option.
8991        value: Expr,
8992    },
8993    /// One or more table partitions and represents which partition the boundary values belong to,
8994    /// e.g.
8995    ///
8996    ///   PARTITION (id RANGE LEFT FOR VALUES (10, 20, 30, 40))
8997    ///
8998    /// <https://learn.microsoft.com/en-us/sql/t-sql/statements/create-table-azure-sql-data-warehouse?view=aps-pdw-2016-au7#TablePartitionOptions>
8999    Partition {
9000        /// The partition column name.
9001        column_name: Ident,
9002        /// Optional direction for the partition range (LEFT/RIGHT).
9003        range_direction: Option<PartitionRangeDirection>,
9004        /// Values that define the partition boundaries.
9005        for_values: Vec<Expr>,
9006    },
9007    /// Comment parameter (supports `=` and no `=` syntax)
9008    Comment(CommentDef),
9009    /// MySQL TableSpace option
9010    /// <https://dev.mysql.com/doc/refman/8.4/en/create-table.html>
9011    TableSpace(TablespaceOption),
9012    /// An option representing a key value pair, where the value is a parenthesized list and with an optional name
9013    /// e.g.
9014    ///
9015    ///   UNION  = (tbl_name\[,tbl_name\]...) <https://dev.mysql.com/doc/refman/8.4/en/create-table.html>
9016    ///   ENGINE = ReplicatedMergeTree('/table_name','{replica}', ver) <https://clickhouse.com/docs/engines/table-engines/mergetree-family/replication>
9017    ///   ENGINE = SummingMergeTree(\[columns\]) <https://clickhouse.com/docs/engines/table-engines/mergetree-family/summingmergetree>
9018    NamedParenthesizedList(NamedParenthesizedList),
9019}
9020
9021impl fmt::Display for SqlOption {
9022    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9023        match self {
9024            SqlOption::Clustered(c) => write!(f, "{c}"),
9025            SqlOption::Ident(ident) => {
9026                write!(f, "{ident}")
9027            }
9028            SqlOption::KeyValue { key: name, value } => {
9029                write!(f, "{name} = {value}")
9030            }
9031            SqlOption::Partition {
9032                column_name,
9033                range_direction,
9034                for_values,
9035            } => {
9036                let direction = match range_direction {
9037                    Some(PartitionRangeDirection::Left) => " LEFT",
9038                    Some(PartitionRangeDirection::Right) => " RIGHT",
9039                    None => "",
9040                };
9041
9042                write!(
9043                    f,
9044                    "PARTITION ({} RANGE{} FOR VALUES ({}))",
9045                    column_name,
9046                    direction,
9047                    display_comma_separated(for_values)
9048                )
9049            }
9050            SqlOption::TableSpace(tablespace_option) => {
9051                write!(f, "TABLESPACE {}", tablespace_option.name)?;
9052                match tablespace_option.storage {
9053                    Some(StorageType::Disk) => write!(f, " STORAGE DISK"),
9054                    Some(StorageType::Memory) => write!(f, " STORAGE MEMORY"),
9055                    None => Ok(()),
9056                }
9057            }
9058            SqlOption::Comment(comment) => match comment {
9059                CommentDef::WithEq(comment) => {
9060                    write!(f, "COMMENT = '{comment}'")
9061                }
9062                CommentDef::WithoutEq(comment) => {
9063                    write!(f, "COMMENT '{comment}'")
9064                }
9065            },
9066            SqlOption::NamedParenthesizedList(value) => {
9067                write!(f, "{} = ", value.key)?;
9068                if let Some(key) = &value.name {
9069                    write!(f, "{key}")?;
9070                }
9071                if !value.values.is_empty() {
9072                    write!(f, "({})", display_comma_separated(&value.values))?
9073                }
9074                Ok(())
9075            }
9076        }
9077    }
9078}
9079
9080#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
9081#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9082#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9083/// Storage type options for a tablespace.
9084pub enum StorageType {
9085    /// Store on disk.
9086    Disk,
9087    /// Store in memory.
9088    Memory,
9089}
9090
9091#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
9092#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9093#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9094/// MySql TableSpace option
9095/// <https://dev.mysql.com/doc/refman/8.4/en/create-table.html>
9096pub struct TablespaceOption {
9097    /// Name of the tablespace.
9098    pub name: String,
9099    /// Optional storage type for the tablespace.
9100    pub storage: Option<StorageType>,
9101}
9102
9103#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9104#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9105#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9106/// A key/value identifier pair used for secret or key-based options.
9107pub struct SecretOption {
9108    /// The option key identifier.
9109    pub key: Ident,
9110    /// The option value identifier.
9111    pub value: Ident,
9112}
9113
9114impl fmt::Display for SecretOption {
9115    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9116        write!(f, "{} {}", self.key, self.value)
9117    }
9118}
9119
9120/// A `CREATE SERVER` statement.
9121///
9122/// [PostgreSQL Documentation](https://www.postgresql.org/docs/current/sql-createserver.html)
9123#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9124#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9125#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9126pub struct CreateServerStatement {
9127    /// The server name.
9128    pub name: ObjectName,
9129    /// Whether `IF NOT EXISTS` was specified.
9130    pub if_not_exists: bool,
9131    /// Optional server type identifier.
9132    pub server_type: Option<Ident>,
9133    /// Optional server version identifier.
9134    pub version: Option<Ident>,
9135    /// Foreign-data wrapper object name.
9136    pub foreign_data_wrapper: ObjectName,
9137    /// Optional list of server options.
9138    pub options: Option<Vec<CreateServerOption>>,
9139}
9140
9141impl fmt::Display for CreateServerStatement {
9142    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
9143        let CreateServerStatement {
9144            name,
9145            if_not_exists,
9146            server_type,
9147            version,
9148            foreign_data_wrapper,
9149            options,
9150        } = self;
9151
9152        write!(
9153            f,
9154            "CREATE SERVER {if_not_exists}{name} ",
9155            if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
9156        )?;
9157
9158        if let Some(st) = server_type {
9159            write!(f, "TYPE {st} ")?;
9160        }
9161
9162        if let Some(v) = version {
9163            write!(f, "VERSION {v} ")?;
9164        }
9165
9166        write!(f, "FOREIGN DATA WRAPPER {foreign_data_wrapper}")?;
9167
9168        if let Some(o) = options {
9169            write!(f, " OPTIONS ({o})", o = display_comma_separated(o))?;
9170        }
9171
9172        Ok(())
9173    }
9174}
9175
9176/// A key/value option for `CREATE SERVER`.
9177#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9178#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9179#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9180pub struct CreateServerOption {
9181    /// Option key identifier.
9182    pub key: Ident,
9183    /// Option value identifier.
9184    pub value: Ident,
9185}
9186
9187impl fmt::Display for CreateServerOption {
9188    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9189        write!(f, "{} {}", self.key, self.value)
9190    }
9191}
9192
9193#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9194#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9195#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9196/// Options supported by DuckDB for `ATTACH DATABASE`.
9197pub enum AttachDuckDBDatabaseOption {
9198    /// READ_ONLY option, optional boolean value.
9199    ReadOnly(Option<bool>),
9200    /// TYPE option specifying a database type identifier.
9201    Type(Ident),
9202}
9203
9204impl fmt::Display for AttachDuckDBDatabaseOption {
9205    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9206        match self {
9207            AttachDuckDBDatabaseOption::ReadOnly(Some(true)) => write!(f, "READ_ONLY true"),
9208            AttachDuckDBDatabaseOption::ReadOnly(Some(false)) => write!(f, "READ_ONLY false"),
9209            AttachDuckDBDatabaseOption::ReadOnly(None) => write!(f, "READ_ONLY"),
9210            AttachDuckDBDatabaseOption::Type(t) => write!(f, "TYPE {t}"),
9211        }
9212    }
9213}
9214
9215#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9216#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9217#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9218/// Mode for transactions: access mode or isolation level.
9219pub enum TransactionMode {
9220    /// Access mode for a transaction (e.g. `READ ONLY` / `READ WRITE`).
9221    AccessMode(TransactionAccessMode),
9222    /// Isolation level for a transaction (e.g. `SERIALIZABLE`).
9223    IsolationLevel(TransactionIsolationLevel),
9224}
9225
9226impl fmt::Display for TransactionMode {
9227    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9228        use TransactionMode::*;
9229        match self {
9230            AccessMode(access_mode) => write!(f, "{access_mode}"),
9231            IsolationLevel(iso_level) => write!(f, "ISOLATION LEVEL {iso_level}"),
9232        }
9233    }
9234}
9235
9236#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9237#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9238#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9239/// Transaction access mode (READ ONLY / READ WRITE).
9240pub enum TransactionAccessMode {
9241    /// READ ONLY access mode.
9242    ReadOnly,
9243    /// READ WRITE access mode.
9244    ReadWrite,
9245}
9246
9247impl fmt::Display for TransactionAccessMode {
9248    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9249        use TransactionAccessMode::*;
9250        f.write_str(match self {
9251            ReadOnly => "READ ONLY",
9252            ReadWrite => "READ WRITE",
9253        })
9254    }
9255}
9256
9257#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9258#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9259#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9260/// Transaction isolation levels.
9261pub enum TransactionIsolationLevel {
9262    /// READ UNCOMMITTED isolation level.
9263    ReadUncommitted,
9264    /// READ COMMITTED isolation level.
9265    ReadCommitted,
9266    /// REPEATABLE READ isolation level.
9267    RepeatableRead,
9268    /// SERIALIZABLE isolation level.
9269    Serializable,
9270    /// SNAPSHOT isolation level.
9271    Snapshot,
9272}
9273
9274impl fmt::Display for TransactionIsolationLevel {
9275    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9276        use TransactionIsolationLevel::*;
9277        f.write_str(match self {
9278            ReadUncommitted => "READ UNCOMMITTED",
9279            ReadCommitted => "READ COMMITTED",
9280            RepeatableRead => "REPEATABLE READ",
9281            Serializable => "SERIALIZABLE",
9282            Snapshot => "SNAPSHOT",
9283        })
9284    }
9285}
9286
9287/// Modifier for the transaction in the `BEGIN` syntax
9288///
9289/// SQLite: <https://sqlite.org/lang_transaction.html>
9290/// MS-SQL: <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/try-catch-transact-sql>
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))]
9294pub enum TransactionModifier {
9295    /// DEFERRED transaction modifier.
9296    Deferred,
9297    /// IMMEDIATE transaction modifier.
9298    Immediate,
9299    /// EXCLUSIVE transaction modifier.
9300    Exclusive,
9301    /// TRY block modifier (MS-SQL style TRY/CATCH).
9302    Try,
9303    /// CATCH block modifier (MS-SQL style TRY/CATCH).
9304    Catch,
9305}
9306
9307impl fmt::Display for TransactionModifier {
9308    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9309        use TransactionModifier::*;
9310        f.write_str(match self {
9311            Deferred => "DEFERRED",
9312            Immediate => "IMMEDIATE",
9313            Exclusive => "EXCLUSIVE",
9314            Try => "TRY",
9315            Catch => "CATCH",
9316        })
9317    }
9318}
9319
9320#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9321#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9322#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9323/// Filter forms usable in SHOW statements.
9324pub enum ShowStatementFilter {
9325    /// Filter using LIKE pattern.
9326    Like(String),
9327    /// Filter using ILIKE pattern.
9328    ILike(String),
9329    /// Filter using a WHERE expression.
9330    Where(Expr),
9331    /// Filter provided without a keyword (raw string).
9332    NoKeyword(String),
9333}
9334
9335impl fmt::Display for ShowStatementFilter {
9336    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9337        use ShowStatementFilter::*;
9338        match self {
9339            Like(pattern) => write!(f, "LIKE '{}'", value::escape_single_quote_string(pattern)),
9340            ILike(pattern) => write!(f, "ILIKE {}", value::escape_single_quote_string(pattern)),
9341            Where(expr) => write!(f, "WHERE {expr}"),
9342            NoKeyword(pattern) => write!(f, "'{}'", value::escape_single_quote_string(pattern)),
9343        }
9344    }
9345}
9346
9347#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9348#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9349#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9350/// Clause types used with SHOW ... IN/FROM.
9351pub enum ShowStatementInClause {
9352    /// Use the `IN` clause.
9353    IN,
9354    /// Use the `FROM` clause.
9355    FROM,
9356}
9357
9358impl fmt::Display for ShowStatementInClause {
9359    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9360        use ShowStatementInClause::*;
9361        match self {
9362            FROM => write!(f, "FROM"),
9363            IN => write!(f, "IN"),
9364        }
9365    }
9366}
9367
9368/// Sqlite specific syntax
9369///
9370/// See [Sqlite documentation](https://sqlite.org/lang_conflict.html)
9371/// for more details.
9372#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9373#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9374#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9375pub enum SqliteOnConflict {
9376    /// Use ROLLBACK on conflict.
9377    Rollback,
9378    /// Use ABORT on conflict.
9379    Abort,
9380    /// Use FAIL on conflict.
9381    Fail,
9382    /// Use IGNORE on conflict.
9383    Ignore,
9384    /// Use REPLACE on conflict.
9385    Replace,
9386}
9387
9388impl fmt::Display for SqliteOnConflict {
9389    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9390        use SqliteOnConflict::*;
9391        match self {
9392            Rollback => write!(f, "OR ROLLBACK"),
9393            Abort => write!(f, "OR ABORT"),
9394            Fail => write!(f, "OR FAIL"),
9395            Ignore => write!(f, "OR IGNORE"),
9396            Replace => write!(f, "OR REPLACE"),
9397        }
9398    }
9399}
9400
9401/// Mysql specific syntax
9402///
9403/// See [Mysql documentation](https://dev.mysql.com/doc/refman/8.0/en/replace.html)
9404/// See [Mysql documentation](https://dev.mysql.com/doc/refman/8.0/en/insert.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 MysqlInsertPriority {
9410    /// LOW_PRIORITY modifier for INSERT/REPLACE.
9411    LowPriority,
9412    /// DELAYED modifier for INSERT/REPLACE.
9413    Delayed,
9414    /// HIGH_PRIORITY modifier for INSERT/REPLACE.
9415    HighPriority,
9416}
9417
9418impl fmt::Display for crate::ast::MysqlInsertPriority {
9419    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9420        use MysqlInsertPriority::*;
9421        match self {
9422            LowPriority => write!(f, "LOW_PRIORITY"),
9423            Delayed => write!(f, "DELAYED"),
9424            HighPriority => write!(f, "HIGH_PRIORITY"),
9425        }
9426    }
9427}
9428
9429#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9430#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9431#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9432/// Source for the `COPY` command: a table or a query.
9433pub enum CopySource {
9434    /// Copy from a table with optional column list.
9435    Table {
9436        /// The name of the table to copy from.
9437        table_name: ObjectName,
9438        /// A list of column names to copy. Empty list means that all columns
9439        /// are copied.
9440        columns: Vec<Ident>,
9441    },
9442    /// Copy from the results of a query.
9443    Query(Box<Query>),
9444}
9445
9446#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9447#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9448#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9449/// Target for the `COPY` command: STDIN, STDOUT, a file, or a program.
9450pub enum CopyTarget {
9451    /// Use standard input as the source.
9452    Stdin,
9453    /// Use standard output as the target.
9454    Stdout,
9455    /// Read from or write to a file.
9456    File {
9457        /// The path name of the input or output file.
9458        filename: String,
9459    },
9460    /// Use a program as the source or target (shell command).
9461    Program {
9462        /// A command to execute
9463        command: String,
9464    },
9465}
9466
9467impl fmt::Display for CopyTarget {
9468    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9469        use CopyTarget::*;
9470        match self {
9471            Stdin => write!(f, "STDIN"),
9472            Stdout => write!(f, "STDOUT"),
9473            File { filename } => write!(f, "'{}'", value::escape_single_quote_string(filename)),
9474            Program { command } => write!(
9475                f,
9476                "PROGRAM '{}'",
9477                value::escape_single_quote_string(command)
9478            ),
9479        }
9480    }
9481}
9482
9483#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9484#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9485#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9486/// Action to take `ON COMMIT` for temporary tables.
9487pub enum OnCommit {
9488    /// Delete rows on commit.
9489    DeleteRows,
9490    /// Preserve rows on commit.
9491    PreserveRows,
9492    /// Drop the table on commit.
9493    Drop,
9494}
9495
9496/// An option in `COPY` statement.
9497///
9498/// <https://www.postgresql.org/docs/14/sql-copy.html>
9499#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9500#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9501#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9502pub enum CopyOption {
9503    /// FORMAT format_name
9504    Format(Ident),
9505    /// FREEZE \[ boolean \]
9506    Freeze(bool),
9507    /// DELIMITER 'delimiter_character'
9508    Delimiter(char),
9509    /// NULL 'null_string'
9510    Null(String),
9511    /// HEADER \[ boolean \]
9512    Header(bool),
9513    /// QUOTE 'quote_character'
9514    Quote(char),
9515    /// ESCAPE 'escape_character'
9516    Escape(char),
9517    /// FORCE_QUOTE { ( column_name [, ...] ) | * }
9518    ForceQuote(Vec<Ident>),
9519    /// FORCE_NOT_NULL ( column_name [, ...] )
9520    ForceNotNull(Vec<Ident>),
9521    /// FORCE_NULL ( column_name [, ...] )
9522    ForceNull(Vec<Ident>),
9523    /// ENCODING 'encoding_name'
9524    Encoding(String),
9525}
9526
9527impl fmt::Display for CopyOption {
9528    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9529        use CopyOption::*;
9530        match self {
9531            Format(name) => write!(f, "FORMAT {name}"),
9532            Freeze(true) => write!(f, "FREEZE"),
9533            Freeze(false) => write!(f, "FREEZE FALSE"),
9534            Delimiter(char) => write!(f, "DELIMITER '{char}'"),
9535            Null(string) => write!(f, "NULL '{}'", value::escape_single_quote_string(string)),
9536            Header(true) => write!(f, "HEADER"),
9537            Header(false) => write!(f, "HEADER FALSE"),
9538            Quote(char) => write!(f, "QUOTE '{char}'"),
9539            Escape(char) => write!(f, "ESCAPE '{char}'"),
9540            ForceQuote(columns) => write!(f, "FORCE_QUOTE ({})", display_comma_separated(columns)),
9541            ForceNotNull(columns) => {
9542                write!(f, "FORCE_NOT_NULL ({})", display_comma_separated(columns))
9543            }
9544            ForceNull(columns) => write!(f, "FORCE_NULL ({})", display_comma_separated(columns)),
9545            Encoding(name) => write!(f, "ENCODING '{}'", value::escape_single_quote_string(name)),
9546        }
9547    }
9548}
9549
9550/// An option in `COPY` statement before PostgreSQL version 9.0.
9551///
9552/// [PostgreSQL](https://www.postgresql.org/docs/8.4/sql-copy.html)
9553/// [Redshift](https://docs.aws.amazon.com/redshift/latest/dg/r_COPY-alphabetical-parm-list.html)
9554#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9555#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9556#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9557pub enum CopyLegacyOption {
9558    /// ACCEPTANYDATE
9559    AcceptAnyDate,
9560    /// ACCEPTINVCHARS
9561    AcceptInvChars(Option<String>),
9562    /// ADDQUOTES
9563    AddQuotes,
9564    /// ALLOWOVERWRITE
9565    AllowOverwrite,
9566    /// BINARY
9567    Binary,
9568    /// BLANKSASNULL
9569    BlankAsNull,
9570    /// BZIP2
9571    Bzip2,
9572    /// CLEANPATH
9573    CleanPath,
9574    /// COMPUPDATE [ PRESET | { ON | TRUE } | { OFF | FALSE } ]
9575    CompUpdate {
9576        /// Whether the COMPUPDATE PRESET option was used.
9577        preset: bool,
9578        /// Optional enabled flag for COMPUPDATE.
9579        enabled: Option<bool>,
9580    },
9581    /// CSV ...
9582    Csv(Vec<CopyLegacyCsvOption>),
9583    /// DATEFORMAT \[ AS \] {'dateformat_string' | 'auto' }
9584    DateFormat(Option<String>),
9585    /// DELIMITER \[ AS \] 'delimiter_character'
9586    Delimiter(char),
9587    /// EMPTYASNULL
9588    EmptyAsNull,
9589    /// `ENCRYPTED \[ AUTO \]`
9590    Encrypted {
9591        /// Whether `AUTO` was specified for encryption.
9592        auto: bool,
9593    },
9594    /// ESCAPE
9595    Escape,
9596    /// EXTENSION 'extension-name'
9597    Extension(String),
9598    /// FIXEDWIDTH \[ AS \] 'fixedwidth-spec'
9599    FixedWidth(String),
9600    /// GZIP
9601    Gzip,
9602    /// HEADER
9603    Header,
9604    /// IAM_ROLE { DEFAULT | 'arn:aws:iam::123456789:role/role1' }
9605    IamRole(IamRoleKind),
9606    /// IGNOREHEADER \[ AS \] number_rows
9607    IgnoreHeader(u64),
9608    /// JSON \[ AS \] 'json_option'
9609    Json(Option<String>),
9610    /// MANIFEST \[ VERBOSE \]
9611    Manifest {
9612        /// Whether the MANIFEST is verbose.
9613        verbose: bool,
9614    },
9615    /// MAXFILESIZE \[ AS \] max-size \[ MB | GB \]
9616    MaxFileSize(FileSize),
9617    /// `NULL \[ AS \] 'null_string'`
9618    Null(String),
9619    /// `PARALLEL [ { ON | TRUE } | { OFF | FALSE } ]`
9620    Parallel(Option<bool>),
9621    /// PARQUET
9622    Parquet,
9623    /// PARTITION BY ( column_name [, ... ] ) \[ INCLUDE \]
9624    PartitionBy(UnloadPartitionBy),
9625    /// REGION \[ AS \] 'aws-region' }
9626    Region(String),
9627    /// REMOVEQUOTES
9628    RemoveQuotes,
9629    /// ROWGROUPSIZE \[ AS \] size \[ MB | GB \]
9630    RowGroupSize(FileSize),
9631    /// STATUPDATE [ { ON | TRUE } | { OFF | FALSE } ]
9632    StatUpdate(Option<bool>),
9633    /// TIMEFORMAT \[ AS \] {'timeformat_string' | 'auto' | 'epochsecs' | 'epochmillisecs' }
9634    TimeFormat(Option<String>),
9635    /// TRUNCATECOLUMNS
9636    TruncateColumns,
9637    /// ZSTD
9638    Zstd,
9639    /// Redshift `CREDENTIALS 'auth-args'`
9640    /// <https://docs.aws.amazon.com/redshift/latest/dg/copy-parameters-authorization.html>
9641    Credentials(String),
9642}
9643
9644impl fmt::Display for CopyLegacyOption {
9645    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9646        use CopyLegacyOption::*;
9647        match self {
9648            AcceptAnyDate => write!(f, "ACCEPTANYDATE"),
9649            AcceptInvChars(ch) => {
9650                write!(f, "ACCEPTINVCHARS")?;
9651                if let Some(ch) = ch {
9652                    write!(f, " '{}'", value::escape_single_quote_string(ch))?;
9653                }
9654                Ok(())
9655            }
9656            AddQuotes => write!(f, "ADDQUOTES"),
9657            AllowOverwrite => write!(f, "ALLOWOVERWRITE"),
9658            Binary => write!(f, "BINARY"),
9659            BlankAsNull => write!(f, "BLANKSASNULL"),
9660            Bzip2 => write!(f, "BZIP2"),
9661            CleanPath => write!(f, "CLEANPATH"),
9662            CompUpdate { preset, enabled } => {
9663                write!(f, "COMPUPDATE")?;
9664                if *preset {
9665                    write!(f, " PRESET")?;
9666                } else if let Some(enabled) = enabled {
9667                    write!(
9668                        f,
9669                        "{}",
9670                        match enabled {
9671                            true => " TRUE",
9672                            false => " FALSE",
9673                        }
9674                    )?;
9675                }
9676                Ok(())
9677            }
9678            Csv(opts) => {
9679                write!(f, "CSV")?;
9680                if !opts.is_empty() {
9681                    write!(f, " {}", display_separated(opts, " "))?;
9682                }
9683                Ok(())
9684            }
9685            DateFormat(fmt) => {
9686                write!(f, "DATEFORMAT")?;
9687                if let Some(fmt) = fmt {
9688                    write!(f, " '{}'", value::escape_single_quote_string(fmt))?;
9689                }
9690                Ok(())
9691            }
9692            Delimiter(char) => write!(f, "DELIMITER '{char}'"),
9693            EmptyAsNull => write!(f, "EMPTYASNULL"),
9694            Encrypted { auto } => write!(f, "ENCRYPTED{}", if *auto { " AUTO" } else { "" }),
9695            Escape => write!(f, "ESCAPE"),
9696            Extension(ext) => write!(f, "EXTENSION '{}'", value::escape_single_quote_string(ext)),
9697            FixedWidth(spec) => write!(
9698                f,
9699                "FIXEDWIDTH '{}'",
9700                value::escape_single_quote_string(spec)
9701            ),
9702            Gzip => write!(f, "GZIP"),
9703            Header => write!(f, "HEADER"),
9704            IamRole(role) => write!(f, "IAM_ROLE {role}"),
9705            IgnoreHeader(num_rows) => write!(f, "IGNOREHEADER {num_rows}"),
9706            Json(opt) => {
9707                write!(f, "JSON")?;
9708                if let Some(opt) = opt {
9709                    write!(f, " AS '{}'", value::escape_single_quote_string(opt))?;
9710                }
9711                Ok(())
9712            }
9713            Manifest { verbose } => write!(f, "MANIFEST{}", if *verbose { " VERBOSE" } else { "" }),
9714            MaxFileSize(file_size) => write!(f, "MAXFILESIZE {file_size}"),
9715            Null(string) => write!(f, "NULL '{}'", value::escape_single_quote_string(string)),
9716            Parallel(enabled) => {
9717                write!(
9718                    f,
9719                    "PARALLEL{}",
9720                    match enabled {
9721                        Some(true) => " TRUE",
9722                        Some(false) => " FALSE",
9723                        _ => "",
9724                    }
9725                )
9726            }
9727            Parquet => write!(f, "PARQUET"),
9728            PartitionBy(p) => write!(f, "{p}"),
9729            Region(region) => write!(f, "REGION '{}'", value::escape_single_quote_string(region)),
9730            RemoveQuotes => write!(f, "REMOVEQUOTES"),
9731            RowGroupSize(file_size) => write!(f, "ROWGROUPSIZE {file_size}"),
9732            StatUpdate(enabled) => {
9733                write!(
9734                    f,
9735                    "STATUPDATE{}",
9736                    match enabled {
9737                        Some(true) => " TRUE",
9738                        Some(false) => " FALSE",
9739                        _ => "",
9740                    }
9741                )
9742            }
9743            TimeFormat(fmt) => {
9744                write!(f, "TIMEFORMAT")?;
9745                if let Some(fmt) = fmt {
9746                    write!(f, " '{}'", value::escape_single_quote_string(fmt))?;
9747                }
9748                Ok(())
9749            }
9750            TruncateColumns => write!(f, "TRUNCATECOLUMNS"),
9751            Zstd => write!(f, "ZSTD"),
9752            Credentials(s) => write!(f, "CREDENTIALS '{}'", value::escape_single_quote_string(s)),
9753        }
9754    }
9755}
9756
9757/// ```sql
9758/// SIZE \[ MB | GB \]
9759/// ```
9760#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9761#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9762#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9763pub struct FileSize {
9764    /// Numeric size value.
9765    pub size: ValueWithSpan,
9766    /// Optional unit for the size (MB or GB).
9767    pub unit: Option<FileSizeUnit>,
9768}
9769
9770impl fmt::Display for FileSize {
9771    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9772        write!(f, "{}", self.size)?;
9773        if let Some(unit) = &self.unit {
9774            write!(f, " {unit}")?;
9775        }
9776        Ok(())
9777    }
9778}
9779
9780/// Units for `FileSize` (MB or GB).
9781#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9782#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9783#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9784pub enum FileSizeUnit {
9785    /// Megabytes.
9786    MB,
9787    /// Gigabytes.
9788    GB,
9789}
9790
9791impl fmt::Display for FileSizeUnit {
9792    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9793        match self {
9794            FileSizeUnit::MB => write!(f, "MB"),
9795            FileSizeUnit::GB => write!(f, "GB"),
9796        }
9797    }
9798}
9799
9800/// Specifies the partition keys for the unload operation
9801///
9802/// ```sql
9803/// PARTITION BY ( column_name [, ... ] ) [ INCLUDE ]
9804/// ```
9805#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9806#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9807#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9808pub struct UnloadPartitionBy {
9809    /// Columns used to partition the unload output.
9810    pub columns: Vec<Ident>,
9811    /// Whether to include the partition in the output.
9812    pub include: bool,
9813}
9814
9815impl fmt::Display for UnloadPartitionBy {
9816    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9817        write!(
9818            f,
9819            "PARTITION BY ({}){}",
9820            display_comma_separated(&self.columns),
9821            if self.include { " INCLUDE" } else { "" }
9822        )
9823    }
9824}
9825
9826/// An `IAM_ROLE` option in the AWS ecosystem
9827///
9828/// [Redshift COPY](https://docs.aws.amazon.com/redshift/latest/dg/copy-parameters-authorization.html#copy-iam-role)
9829#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9830#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9831#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9832pub enum IamRoleKind {
9833    /// Default role
9834    Default,
9835    /// Specific role ARN, for example: `arn:aws:iam::123456789:role/role1`
9836    Arn(String),
9837}
9838
9839impl fmt::Display for IamRoleKind {
9840    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9841        match self {
9842            IamRoleKind::Default => write!(f, "DEFAULT"),
9843            IamRoleKind::Arn(arn) => write!(f, "'{arn}'"),
9844        }
9845    }
9846}
9847
9848/// A `CSV` option in `COPY` statement before PostgreSQL version 9.0.
9849///
9850/// <https://www.postgresql.org/docs/8.4/sql-copy.html>
9851#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9852#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9853#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9854pub enum CopyLegacyCsvOption {
9855    /// HEADER
9856    Header,
9857    /// QUOTE \[ AS \] 'quote_character'
9858    Quote(char),
9859    /// ESCAPE \[ AS \] 'escape_character'
9860    Escape(char),
9861    /// FORCE QUOTE { column_name [, ...] | * }
9862    ForceQuote(Vec<Ident>),
9863    /// FORCE NOT NULL column_name [, ...]
9864    ForceNotNull(Vec<Ident>),
9865}
9866
9867impl fmt::Display for CopyLegacyCsvOption {
9868    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9869        use CopyLegacyCsvOption::*;
9870        match self {
9871            Header => write!(f, "HEADER"),
9872            Quote(char) => write!(f, "QUOTE '{char}'"),
9873            Escape(char) => write!(f, "ESCAPE '{char}'"),
9874            ForceQuote(columns) => write!(f, "FORCE QUOTE {}", display_comma_separated(columns)),
9875            ForceNotNull(columns) => {
9876                write!(f, "FORCE NOT NULL {}", display_comma_separated(columns))
9877            }
9878        }
9879    }
9880}
9881
9882/// Objects that can be discarded with `DISCARD`.
9883#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9884#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9885#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9886pub enum DiscardObject {
9887    /// Discard all session state.
9888    ALL,
9889    /// Discard cached plans.
9890    PLANS,
9891    /// Discard sequence values.
9892    SEQUENCES,
9893    /// Discard temporary objects.
9894    TEMP,
9895}
9896
9897impl fmt::Display for DiscardObject {
9898    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9899        match self {
9900            DiscardObject::ALL => f.write_str("ALL"),
9901            DiscardObject::PLANS => f.write_str("PLANS"),
9902            DiscardObject::SEQUENCES => f.write_str("SEQUENCES"),
9903            DiscardObject::TEMP => f.write_str("TEMP"),
9904        }
9905    }
9906}
9907
9908/// Types of flush operations supported by `FLUSH`.
9909#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9910#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9911#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9912pub enum FlushType {
9913    /// Flush binary logs.
9914    BinaryLogs,
9915    /// Flush engine logs.
9916    EngineLogs,
9917    /// Flush error logs.
9918    ErrorLogs,
9919    /// Flush general logs.
9920    GeneralLogs,
9921    /// Flush hosts information.
9922    Hosts,
9923    /// Flush logs.
9924    Logs,
9925    /// Flush privileges.
9926    Privileges,
9927    /// Flush optimizer costs.
9928    OptimizerCosts,
9929    /// Flush relay logs.
9930    RelayLogs,
9931    /// Flush slow logs.
9932    SlowLogs,
9933    /// Flush status.
9934    Status,
9935    /// Flush user resources.
9936    UserResources,
9937    /// Flush table data.
9938    Tables,
9939}
9940
9941impl fmt::Display for FlushType {
9942    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9943        match self {
9944            FlushType::BinaryLogs => f.write_str("BINARY LOGS"),
9945            FlushType::EngineLogs => f.write_str("ENGINE LOGS"),
9946            FlushType::ErrorLogs => f.write_str("ERROR LOGS"),
9947            FlushType::GeneralLogs => f.write_str("GENERAL LOGS"),
9948            FlushType::Hosts => f.write_str("HOSTS"),
9949            FlushType::Logs => f.write_str("LOGS"),
9950            FlushType::Privileges => f.write_str("PRIVILEGES"),
9951            FlushType::OptimizerCosts => f.write_str("OPTIMIZER_COSTS"),
9952            FlushType::RelayLogs => f.write_str("RELAY LOGS"),
9953            FlushType::SlowLogs => f.write_str("SLOW LOGS"),
9954            FlushType::Status => f.write_str("STATUS"),
9955            FlushType::UserResources => f.write_str("USER_RESOURCES"),
9956            FlushType::Tables => f.write_str("TABLES"),
9957        }
9958    }
9959}
9960
9961/// Location modifier for flush commands.
9962#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9963#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9964#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9965pub enum FlushLocation {
9966    /// Do not write changes to the binary log.
9967    NoWriteToBinlog,
9968    /// Apply flush locally.
9969    Local,
9970}
9971
9972impl fmt::Display for FlushLocation {
9973    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9974        match self {
9975            FlushLocation::NoWriteToBinlog => f.write_str("NO_WRITE_TO_BINLOG"),
9976            FlushLocation::Local => f.write_str("LOCAL"),
9977        }
9978    }
9979}
9980
9981/// Optional context modifier for statements that can be or `LOCAL`, `GLOBAL`, or `SESSION`.
9982#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9983#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9984#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9985pub enum ContextModifier {
9986    /// `LOCAL` identifier, usually related to transactional states.
9987    Local,
9988    /// `SESSION` identifier
9989    Session,
9990    /// `GLOBAL` identifier
9991    Global,
9992}
9993
9994impl fmt::Display for ContextModifier {
9995    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9996        match self {
9997            Self::Local => {
9998                write!(f, "LOCAL ")
9999            }
10000            Self::Session => {
10001                write!(f, "SESSION ")
10002            }
10003            Self::Global => {
10004                write!(f, "GLOBAL ")
10005            }
10006        }
10007    }
10008}
10009
10010/// Function describe in DROP FUNCTION.
10011#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10012#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10013pub enum DropFunctionOption {
10014    /// `RESTRICT` option for DROP FUNCTION.
10015    Restrict,
10016    /// `CASCADE` option for DROP FUNCTION.
10017    Cascade,
10018}
10019
10020impl fmt::Display for DropFunctionOption {
10021    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10022        match self {
10023            DropFunctionOption::Restrict => write!(f, "RESTRICT "),
10024            DropFunctionOption::Cascade => write!(f, "CASCADE  "),
10025        }
10026    }
10027}
10028
10029/// Generic function description for DROP FUNCTION and CREATE TRIGGER.
10030#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10031#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10032#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10033pub struct FunctionDesc {
10034    /// The function name.
10035    pub name: ObjectName,
10036    /// Optional list of function arguments.
10037    pub args: Option<Vec<OperateFunctionArg>>,
10038}
10039
10040impl fmt::Display for FunctionDesc {
10041    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10042        write!(f, "{}", self.name)?;
10043        if let Some(args) = &self.args {
10044            write!(f, "({})", display_comma_separated(args))?;
10045        }
10046        Ok(())
10047    }
10048}
10049
10050/// Function argument in CREATE OR DROP FUNCTION.
10051#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10052#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10053#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10054pub struct OperateFunctionArg {
10055    /// Optional argument mode (`IN`, `OUT`, `INOUT`).
10056    pub mode: Option<ArgMode>,
10057    /// Optional argument identifier/name.
10058    pub name: Option<Ident>,
10059    /// The data type of the argument.
10060    pub data_type: DataType,
10061    /// Optional default expression for the argument.
10062    pub default_expr: Option<Expr>,
10063}
10064
10065impl OperateFunctionArg {
10066    /// Returns an unnamed argument.
10067    pub fn unnamed(data_type: DataType) -> Self {
10068        Self {
10069            mode: None,
10070            name: None,
10071            data_type,
10072            default_expr: None,
10073        }
10074    }
10075
10076    /// Returns an argument with name.
10077    pub fn with_name(name: &str, data_type: DataType) -> Self {
10078        Self {
10079            mode: None,
10080            name: Some(name.into()),
10081            data_type,
10082            default_expr: None,
10083        }
10084    }
10085}
10086
10087impl fmt::Display for OperateFunctionArg {
10088    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10089        if let Some(mode) = &self.mode {
10090            write!(f, "{mode} ")?;
10091        }
10092        if let Some(name) = &self.name {
10093            write!(f, "{name} ")?;
10094        }
10095        write!(f, "{}", self.data_type)?;
10096        if let Some(default_expr) = &self.default_expr {
10097            write!(f, " = {default_expr}")?;
10098        }
10099        Ok(())
10100    }
10101}
10102
10103/// The mode of an argument in CREATE FUNCTION.
10104#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10105#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10106#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10107pub enum ArgMode {
10108    /// `IN` mode.
10109    In,
10110    /// `OUT` mode.
10111    Out,
10112    /// `INOUT` mode.
10113    InOut,
10114    /// `VARIADIC` mode.
10115    Variadic,
10116}
10117
10118impl fmt::Display for ArgMode {
10119    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10120        match self {
10121            ArgMode::In => write!(f, "IN"),
10122            ArgMode::Out => write!(f, "OUT"),
10123            ArgMode::InOut => write!(f, "INOUT"),
10124            ArgMode::Variadic => write!(f, "VARIADIC"),
10125        }
10126    }
10127}
10128
10129/// These attributes inform the query optimizer about the behavior of the function.
10130#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10131#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10132#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10133pub enum FunctionBehavior {
10134    /// Function is immutable.
10135    Immutable,
10136    /// Function is stable.
10137    Stable,
10138    /// Function is volatile.
10139    Volatile,
10140}
10141
10142impl fmt::Display for FunctionBehavior {
10143    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10144        match self {
10145            FunctionBehavior::Immutable => write!(f, "IMMUTABLE"),
10146            FunctionBehavior::Stable => write!(f, "STABLE"),
10147            FunctionBehavior::Volatile => write!(f, "VOLATILE"),
10148        }
10149    }
10150}
10151
10152/// Security attribute for functions: SECURITY DEFINER or SECURITY INVOKER.
10153///
10154/// [PostgreSQL](https://www.postgresql.org/docs/current/sql-createfunction.html)
10155#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10156#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10157#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10158pub enum FunctionSecurity {
10159    /// Execute the function with the privileges of the user who defined it.
10160    Definer,
10161    /// Execute the function with the privileges of the user who invokes it.
10162    Invoker,
10163}
10164
10165impl fmt::Display for FunctionSecurity {
10166    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10167        match self {
10168            FunctionSecurity::Definer => write!(f, "SECURITY DEFINER"),
10169            FunctionSecurity::Invoker => write!(f, "SECURITY INVOKER"),
10170        }
10171    }
10172}
10173
10174/// Value for a SET configuration parameter in a CREATE FUNCTION statement.
10175///
10176/// [PostgreSQL](https://www.postgresql.org/docs/current/sql-createfunction.html)
10177#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10178#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10179#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10180pub enum FunctionSetValue {
10181    /// SET param = DEFAULT / SET param TO DEFAULT
10182    Default,
10183    /// SET param = value1, value2, ...
10184    Values(Vec<Expr>),
10185    /// SET param FROM CURRENT
10186    FromCurrent,
10187}
10188
10189/// A SET configuration_parameter clause in a CREATE FUNCTION statement.
10190///
10191/// [PostgreSQL](https://www.postgresql.org/docs/current/sql-createfunction.html)
10192#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10193#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10194#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10195pub struct FunctionDefinitionSetParam {
10196    /// The name of the configuration parameter.
10197    pub name: ObjectName,
10198    /// The value to set for the parameter.
10199    pub value: FunctionSetValue,
10200}
10201
10202impl fmt::Display for FunctionDefinitionSetParam {
10203    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10204        write!(f, "SET {} ", self.name)?;
10205        match &self.value {
10206            FunctionSetValue::Default => write!(f, "= DEFAULT"),
10207            FunctionSetValue::Values(values) => {
10208                write!(f, "= {}", display_comma_separated(values))
10209            }
10210            FunctionSetValue::FromCurrent => write!(f, "FROM CURRENT"),
10211        }
10212    }
10213}
10214
10215/// These attributes describe the behavior of the function when called with a null argument.
10216#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10217#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10218#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10219pub enum FunctionCalledOnNull {
10220    /// Function is called even when inputs are null.
10221    CalledOnNullInput,
10222    /// Function returns null when any input is null.
10223    ReturnsNullOnNullInput,
10224    /// Function is strict about null inputs.
10225    Strict,
10226}
10227
10228impl fmt::Display for FunctionCalledOnNull {
10229    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10230        match self {
10231            FunctionCalledOnNull::CalledOnNullInput => write!(f, "CALLED ON NULL INPUT"),
10232            FunctionCalledOnNull::ReturnsNullOnNullInput => write!(f, "RETURNS NULL ON NULL INPUT"),
10233            FunctionCalledOnNull::Strict => write!(f, "STRICT"),
10234        }
10235    }
10236}
10237
10238/// If it is safe for PostgreSQL to call the function from multiple threads at once
10239#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10240#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10241#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10242pub enum FunctionParallel {
10243    /// The function is not safe to run in parallel.
10244    Unsafe,
10245    /// The function is restricted for parallel execution.
10246    Restricted,
10247    /// The function is safe to run in parallel.
10248    Safe,
10249}
10250
10251impl fmt::Display for FunctionParallel {
10252    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10253        match self {
10254            FunctionParallel::Unsafe => write!(f, "PARALLEL UNSAFE"),
10255            FunctionParallel::Restricted => write!(f, "PARALLEL RESTRICTED"),
10256            FunctionParallel::Safe => write!(f, "PARALLEL SAFE"),
10257        }
10258    }
10259}
10260
10261/// [BigQuery] Determinism specifier used in a UDF definition.
10262///
10263/// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#syntax_11
10264#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10265#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10266#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10267pub enum FunctionDeterminismSpecifier {
10268    /// Function is deterministic.
10269    Deterministic,
10270    /// Function is not deterministic.
10271    NotDeterministic,
10272}
10273
10274impl fmt::Display for FunctionDeterminismSpecifier {
10275    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10276        match self {
10277            FunctionDeterminismSpecifier::Deterministic => {
10278                write!(f, "DETERMINISTIC")
10279            }
10280            FunctionDeterminismSpecifier::NotDeterministic => {
10281                write!(f, "NOT DETERMINISTIC")
10282            }
10283        }
10284    }
10285}
10286
10287/// Represent the expression body of a `CREATE FUNCTION` statement as well as
10288/// where within the statement, the body shows up.
10289///
10290/// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#syntax_11
10291/// [PostgreSQL]: https://www.postgresql.org/docs/15/sql-createfunction.html
10292/// [MsSql]: https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql
10293#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10294#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10295#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10296pub enum CreateFunctionBody {
10297    /// A function body expression using the 'AS' keyword and shows up
10298    /// before any `OPTIONS` clause.
10299    ///
10300    /// Example:
10301    /// ```sql
10302    /// CREATE FUNCTION myfunc(x FLOAT64, y FLOAT64) RETURNS FLOAT64
10303    /// AS (x * y)
10304    /// OPTIONS(description="desc");
10305    /// ```
10306    ///
10307    /// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#syntax_11
10308    /// [PostgreSQL]: https://www.postgresql.org/docs/current/sql-createfunction.html
10309    AsBeforeOptions {
10310        /// The primary expression.
10311        body: Expr,
10312        /// Link symbol if the primary expression contains the name of shared library file.
10313        ///
10314        /// Example:
10315        /// ```sql
10316        /// CREATE FUNCTION cas_in(input cstring) RETURNS cas
10317        /// AS 'MODULE_PATHNAME', 'cas_in_wrapper'
10318        /// ```
10319        /// [PostgreSQL]: https://www.postgresql.org/docs/current/sql-createfunction.html
10320        link_symbol: Option<Expr>,
10321    },
10322    /// A function body expression using the 'AS' keyword and shows up
10323    /// after any `OPTIONS` clause.
10324    ///
10325    /// Example:
10326    /// ```sql
10327    /// CREATE FUNCTION myfunc(x FLOAT64, y FLOAT64) RETURNS FLOAT64
10328    /// OPTIONS(description="desc")
10329    /// AS (x * y);
10330    /// ```
10331    ///
10332    /// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#syntax_11
10333    AsAfterOptions(Expr),
10334    /// Function body with statements before the `RETURN` keyword.
10335    ///
10336    /// Example:
10337    /// ```sql
10338    /// CREATE FUNCTION my_scalar_udf(a INT, b INT)
10339    /// RETURNS INT
10340    /// AS
10341    /// BEGIN
10342    ///     DECLARE c INT;
10343    ///     SET c = a + b;
10344    ///     RETURN c;
10345    /// END
10346    /// ```
10347    ///
10348    /// [MsSql]: https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql
10349    AsBeginEnd(BeginEndStatements),
10350    /// Function body expression using the 'RETURN' keyword.
10351    ///
10352    /// Example:
10353    /// ```sql
10354    /// CREATE FUNCTION myfunc(a INTEGER, IN b INTEGER = 1) RETURNS INTEGER
10355    /// LANGUAGE SQL
10356    /// RETURN a + b;
10357    /// ```
10358    ///
10359    /// [PostgreSQL]: https://www.postgresql.org/docs/current/sql-createfunction.html
10360    Return(Expr),
10361
10362    /// Function body expression using the 'AS RETURN' keywords
10363    ///
10364    /// Example:
10365    /// ```sql
10366    /// CREATE FUNCTION myfunc(a INT, b INT)
10367    /// RETURNS TABLE
10368    /// AS RETURN (SELECT a + b AS sum);
10369    /// ```
10370    ///
10371    /// [MsSql]: https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql
10372    AsReturnExpr(Expr),
10373
10374    /// Function body expression using the 'AS RETURN' keywords, with an un-parenthesized SELECT query
10375    ///
10376    /// Example:
10377    /// ```sql
10378    /// CREATE FUNCTION myfunc(a INT, b INT)
10379    /// RETURNS TABLE
10380    /// AS RETURN SELECT a + b AS sum;
10381    /// ```
10382    ///
10383    /// [MsSql]: https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql?view=sql-server-ver16#select_stmt
10384    AsReturnSelect(Select),
10385}
10386
10387#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10388#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10389#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10390/// `USING` clause options for `CREATE FUNCTION` (e.g., JAR, FILE, ARCHIVE).
10391pub enum CreateFunctionUsing {
10392    /// Use a JAR file located at the given URI.
10393    Jar(String),
10394    /// Use a file located at the given URI.
10395    File(String),
10396    /// Use an archive located at the given URI.
10397    Archive(String),
10398}
10399
10400impl fmt::Display for CreateFunctionUsing {
10401    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10402        write!(f, "USING ")?;
10403        match self {
10404            CreateFunctionUsing::Jar(uri) => write!(f, "JAR '{uri}'"),
10405            CreateFunctionUsing::File(uri) => write!(f, "FILE '{uri}'"),
10406            CreateFunctionUsing::Archive(uri) => write!(f, "ARCHIVE '{uri}'"),
10407        }
10408    }
10409}
10410
10411/// `NAME = <EXPR>` arguments for DuckDB macros
10412///
10413/// See [Create Macro - DuckDB](https://duckdb.org/docs/sql/statements/create_macro)
10414/// for more details
10415#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10416#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10417#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10418pub struct MacroArg {
10419    /// The argument name.
10420    pub name: Ident,
10421    /// Optional default expression for the argument.
10422    pub default_expr: Option<Expr>,
10423}
10424
10425impl MacroArg {
10426    /// Returns an argument with name.
10427    pub fn new(name: &str) -> Self {
10428        Self {
10429            name: name.into(),
10430            default_expr: None,
10431        }
10432    }
10433}
10434
10435impl fmt::Display for MacroArg {
10436    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10437        write!(f, "{}", self.name)?;
10438        if let Some(default_expr) = &self.default_expr {
10439            write!(f, " := {default_expr}")?;
10440        }
10441        Ok(())
10442    }
10443}
10444
10445#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10446#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10447#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10448/// Definition for a DuckDB macro: either an expression or a table-producing query.
10449pub enum MacroDefinition {
10450    /// The macro is defined as an expression.
10451    Expr(Expr),
10452    /// The macro is defined as a table (query).
10453    Table(Box<Query>),
10454}
10455
10456impl fmt::Display for MacroDefinition {
10457    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10458        match self {
10459            MacroDefinition::Expr(expr) => write!(f, "{expr}")?,
10460            MacroDefinition::Table(query) => write!(f, "{query}")?,
10461        }
10462        Ok(())
10463    }
10464}
10465
10466/// Schema possible naming variants ([1]).
10467///
10468/// [1]: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#schema-definition
10469#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10470#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10471#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10472pub enum SchemaName {
10473    /// Only schema name specified: `<schema name>`.
10474    Simple(ObjectName),
10475    /// Only authorization identifier specified: `AUTHORIZATION <schema authorization identifier>`.
10476    UnnamedAuthorization(Ident),
10477    /// Both schema name and authorization identifier specified: `<schema name>  AUTHORIZATION <schema authorization identifier>`.
10478    NamedAuthorization(ObjectName, Ident),
10479}
10480
10481impl fmt::Display for SchemaName {
10482    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10483        match self {
10484            SchemaName::Simple(name) => {
10485                write!(f, "{name}")
10486            }
10487            SchemaName::UnnamedAuthorization(authorization) => {
10488                write!(f, "AUTHORIZATION {authorization}")
10489            }
10490            SchemaName::NamedAuthorization(name, authorization) => {
10491                write!(f, "{name} AUTHORIZATION {authorization}")
10492            }
10493        }
10494    }
10495}
10496
10497/// Fulltext search modifiers ([1]).
10498///
10499/// [1]: https://dev.mysql.com/doc/refman/8.0/en/fulltext-search.html#function_match
10500#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10501#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10502#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10503pub enum SearchModifier {
10504    /// `IN NATURAL LANGUAGE MODE`.
10505    InNaturalLanguageMode,
10506    /// `IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION`.
10507    InNaturalLanguageModeWithQueryExpansion,
10508    ///`IN BOOLEAN MODE`.
10509    InBooleanMode,
10510    ///`WITH QUERY EXPANSION`.
10511    WithQueryExpansion,
10512}
10513
10514impl fmt::Display for SearchModifier {
10515    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10516        match self {
10517            Self::InNaturalLanguageMode => {
10518                write!(f, "IN NATURAL LANGUAGE MODE")?;
10519            }
10520            Self::InNaturalLanguageModeWithQueryExpansion => {
10521                write!(f, "IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION")?;
10522            }
10523            Self::InBooleanMode => {
10524                write!(f, "IN BOOLEAN MODE")?;
10525            }
10526            Self::WithQueryExpansion => {
10527                write!(f, "WITH QUERY EXPANSION")?;
10528            }
10529        }
10530
10531        Ok(())
10532    }
10533}
10534
10535/// Represents a `LOCK TABLE` clause with optional alias and lock type.
10536#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10537#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10538#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10539pub struct LockTable {
10540    /// The table identifier to lock.
10541    pub table: Ident,
10542    /// Optional alias for the table.
10543    pub alias: Option<Ident>,
10544    /// The type of lock to apply to the table.
10545    pub lock_type: LockTableType,
10546}
10547
10548impl fmt::Display for LockTable {
10549    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10550        let Self {
10551            table: tbl_name,
10552            alias,
10553            lock_type,
10554        } = self;
10555
10556        write!(f, "{tbl_name} ")?;
10557        if let Some(alias) = alias {
10558            write!(f, "AS {alias} ")?;
10559        }
10560        write!(f, "{lock_type}")?;
10561        Ok(())
10562    }
10563}
10564
10565#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10566#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10567#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10568/// The type of lock used in `LOCK TABLE` statements.
10569pub enum LockTableType {
10570    /// Shared/read lock. If `local` is true, it's a local read lock.
10571    Read {
10572        /// Whether the read lock is local.
10573        local: bool,
10574    },
10575    /// Exclusive/write lock. If `low_priority` is true, the write is low priority.
10576    Write {
10577        /// Whether the write lock is low priority.
10578        low_priority: bool,
10579    },
10580}
10581
10582impl fmt::Display for LockTableType {
10583    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10584        match self {
10585            Self::Read { local } => {
10586                write!(f, "READ")?;
10587                if *local {
10588                    write!(f, " LOCAL")?;
10589                }
10590            }
10591            Self::Write { low_priority } => {
10592                if *low_priority {
10593                    write!(f, "LOW_PRIORITY ")?;
10594                }
10595                write!(f, "WRITE")?;
10596            }
10597        }
10598
10599        Ok(())
10600    }
10601}
10602
10603#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10604#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10605#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10606/// Hive-specific `SET LOCATION` helper used in some `LOAD DATA` statements.
10607pub struct HiveSetLocation {
10608    /// Whether the `SET` keyword was present.
10609    pub has_set: bool,
10610    /// The location identifier.
10611    pub location: Ident,
10612}
10613
10614impl fmt::Display for HiveSetLocation {
10615    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10616        if self.has_set {
10617            write!(f, "SET ")?;
10618        }
10619        write!(f, "LOCATION {}", self.location)
10620    }
10621}
10622
10623/// MySQL `ALTER TABLE` only  [FIRST | AFTER column_name]
10624#[allow(clippy::large_enum_variant)]
10625#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10626#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10627#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10628/// MySQL `ALTER TABLE` column position specifier: `FIRST` or `AFTER <column>`.
10629pub enum MySQLColumnPosition {
10630    /// Place the column first in the table.
10631    First,
10632    /// Place the column after the specified identifier.
10633    After(Ident),
10634}
10635
10636impl Display for MySQLColumnPosition {
10637    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10638        match self {
10639            MySQLColumnPosition::First => write!(f, "FIRST"),
10640            MySQLColumnPosition::After(ident) => {
10641                let column_name = &ident.value;
10642                write!(f, "AFTER {column_name}")
10643            }
10644        }
10645    }
10646}
10647
10648/// MySQL `CREATE VIEW` algorithm parameter: [ALGORITHM = {UNDEFINED | MERGE | TEMPTABLE}]
10649#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10650#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10651#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10652/// MySQL `CREATE VIEW` algorithm options.
10653pub enum CreateViewAlgorithm {
10654    /// `UNDEFINED` algorithm.
10655    Undefined,
10656    /// `MERGE` algorithm.
10657    Merge,
10658    /// `TEMPTABLE` algorithm.
10659    TempTable,
10660}
10661
10662impl Display for CreateViewAlgorithm {
10663    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10664        match self {
10665            CreateViewAlgorithm::Undefined => write!(f, "UNDEFINED"),
10666            CreateViewAlgorithm::Merge => write!(f, "MERGE"),
10667            CreateViewAlgorithm::TempTable => write!(f, "TEMPTABLE"),
10668        }
10669    }
10670}
10671/// MySQL `CREATE VIEW` security parameter: [SQL SECURITY { DEFINER | INVOKER }]
10672#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10673#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10674#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10675/// MySQL `CREATE VIEW` SQL SECURITY options.
10676pub enum CreateViewSecurity {
10677    /// The view runs with the privileges of the definer.
10678    Definer,
10679    /// The view runs with the privileges of the invoker.
10680    Invoker,
10681}
10682
10683impl Display for CreateViewSecurity {
10684    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10685        match self {
10686            CreateViewSecurity::Definer => write!(f, "DEFINER"),
10687            CreateViewSecurity::Invoker => write!(f, "INVOKER"),
10688        }
10689    }
10690}
10691
10692/// [MySQL] `CREATE VIEW` additional parameters
10693///
10694/// [MySQL]: https://dev.mysql.com/doc/refman/9.1/en/create-view.html
10695#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10696#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10697#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10698pub struct CreateViewParams {
10699    /// Optional view algorithm (e.g., MERGE, TEMPTABLE).
10700    pub algorithm: Option<CreateViewAlgorithm>,
10701    /// Optional definer (the security principal that will own the view).
10702    pub definer: Option<GranteeName>,
10703    /// Optional SQL SECURITY setting for the view.
10704    pub security: Option<CreateViewSecurity>,
10705}
10706
10707impl Display for CreateViewParams {
10708    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10709        let CreateViewParams {
10710            algorithm,
10711            definer,
10712            security,
10713        } = self;
10714        if let Some(algorithm) = algorithm {
10715            write!(f, "ALGORITHM = {algorithm} ")?;
10716        }
10717        if let Some(definers) = definer {
10718            write!(f, "DEFINER = {definers} ")?;
10719        }
10720        if let Some(security) = security {
10721            write!(f, "SQL SECURITY {security} ")?;
10722        }
10723        Ok(())
10724    }
10725}
10726
10727#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10728#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10729#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10730/// Key/Value, where the value is a (optionally named) list of identifiers
10731///
10732/// ```sql
10733/// UNION = (tbl_name[,tbl_name]...)
10734/// ENGINE = ReplicatedMergeTree('/table_name','{replica}', ver)
10735/// ENGINE = SummingMergeTree([columns])
10736/// ```
10737pub struct NamedParenthesizedList {
10738    /// The option key (identifier) for this named list.
10739    pub key: Ident,
10740    /// Optional secondary name associated with the key.
10741    pub name: Option<Ident>,
10742    /// The list of identifier values for the key.
10743    pub values: Vec<Ident>,
10744}
10745
10746/// Snowflake `WITH ROW ACCESS POLICY policy_name ON (identifier, ...)`
10747///
10748/// <https://docs.snowflake.com/en/sql-reference/sql/create-table>
10749/// <https://docs.snowflake.com/en/user-guide/security-row-intro>
10750#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10751#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10752#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10753pub struct RowAccessPolicy {
10754    /// The fully-qualified policy object name.
10755    pub policy: ObjectName,
10756    /// Identifiers for the columns or objects the policy applies to.
10757    pub on: Vec<Ident>,
10758}
10759
10760impl RowAccessPolicy {
10761    /// Create a new `RowAccessPolicy` for the given `policy` and `on` identifiers.
10762    pub fn new(policy: ObjectName, on: Vec<Ident>) -> Self {
10763        Self { policy, on }
10764    }
10765}
10766
10767impl Display for RowAccessPolicy {
10768    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10769        write!(
10770            f,
10771            "WITH ROW ACCESS POLICY {} ON ({})",
10772            self.policy,
10773            display_comma_separated(self.on.as_slice())
10774        )
10775    }
10776}
10777
10778/// Snowflake `[ WITH ] STORAGE LIFECYCLE POLICY <policy_name> ON ( <col_name> [ , ... ] )`
10779///
10780/// <https://docs.snowflake.com/en/sql-reference/sql/create-table>
10781#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10782#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10783#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10784pub struct StorageLifecyclePolicy {
10785    /// The fully-qualified policy object name.
10786    pub policy: ObjectName,
10787    /// Column names the policy applies to.
10788    pub on: Vec<Ident>,
10789}
10790
10791impl Display for StorageLifecyclePolicy {
10792    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10793        write!(
10794            f,
10795            "WITH STORAGE LIFECYCLE POLICY {} ON ({})",
10796            self.policy,
10797            display_comma_separated(self.on.as_slice())
10798        )
10799    }
10800}
10801
10802/// Snowflake `WITH TAG ( tag_name = '<tag_value>', ...)`
10803///
10804/// <https://docs.snowflake.com/en/sql-reference/sql/create-table>
10805#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10806#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10807#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10808pub struct Tag {
10809    /// The tag key (can be qualified).
10810    pub key: ObjectName,
10811    /// The tag value as a string.
10812    pub value: String,
10813}
10814
10815impl Tag {
10816    /// Create a new `Tag` with the given key and value.
10817    pub fn new(key: ObjectName, value: String) -> Self {
10818        Self { key, value }
10819    }
10820}
10821
10822impl Display for Tag {
10823    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10824        write!(f, "{}='{}'", self.key, self.value)
10825    }
10826}
10827
10828/// Snowflake `WITH CONTACT ( purpose = contact [ , purpose = contact ...] )`
10829///
10830/// <https://docs.snowflake.com/en/sql-reference/sql/create-database>
10831#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10832#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10833#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10834pub struct ContactEntry {
10835    /// The purpose label for the contact entry.
10836    pub purpose: String,
10837    /// The contact information associated with the purpose.
10838    pub contact: String,
10839}
10840
10841impl Display for ContactEntry {
10842    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10843        write!(f, "{} = {}", self.purpose, self.contact)
10844    }
10845}
10846
10847/// Helper to indicate if a comment includes the `=` in the display form
10848#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10849#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10850#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10851pub enum CommentDef {
10852    /// Includes `=` when printing the comment, as `COMMENT = 'comment'`
10853    /// Does not include `=` when printing the comment, as `COMMENT 'comment'`
10854    WithEq(String),
10855    /// Comment variant that omits the `=` when displayed.
10856    WithoutEq(String),
10857}
10858
10859impl Display for CommentDef {
10860    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10861        match self {
10862            CommentDef::WithEq(comment) | CommentDef::WithoutEq(comment) => write!(f, "{comment}"),
10863        }
10864    }
10865}
10866
10867/// Helper to indicate if a collection should be wrapped by a symbol in the display form
10868///
10869/// [`Display`] is implemented for every [`Vec<T>`] where `T: Display`.
10870/// The string output is a comma separated list for the vec items
10871///
10872/// # Examples
10873/// ```
10874/// # use sqlparser::ast::WrappedCollection;
10875/// let items = WrappedCollection::Parentheses(vec!["one", "two", "three"]);
10876/// assert_eq!("(one, two, three)", items.to_string());
10877///
10878/// let items = WrappedCollection::NoWrapping(vec!["one", "two", "three"]);
10879/// assert_eq!("one, two, three", items.to_string());
10880/// ```
10881#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10882#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10883#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10884pub enum WrappedCollection<T> {
10885    /// Print the collection without wrapping symbols, as `item, item, item`
10886    NoWrapping(T),
10887    /// Wraps the collection in Parentheses, as `(item, item, item)`
10888    Parentheses(T),
10889}
10890
10891impl<T> Display for WrappedCollection<Vec<T>>
10892where
10893    T: Display,
10894{
10895    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10896        match self {
10897            WrappedCollection::NoWrapping(inner) => {
10898                write!(f, "{}", display_comma_separated(inner.as_slice()))
10899            }
10900            WrappedCollection::Parentheses(inner) => {
10901                write!(f, "({})", display_comma_separated(inner.as_slice()))
10902            }
10903        }
10904    }
10905}
10906
10907/// Represents a single PostgreSQL utility option.
10908///
10909/// A utility option is a key-value pair where the key is an identifier (IDENT) and the value
10910/// can be one of the following:
10911/// - A number with an optional sign (`+` or `-`). Example: `+10`, `-10.2`, `3`
10912/// - A non-keyword string. Example: `option1`, `'option2'`, `"option3"`
10913/// - keyword: `TRUE`, `FALSE`, `ON` (`off` is also accept).
10914/// - Empty. Example: `ANALYZE` (identifier only)
10915///
10916/// Utility options are used in various PostgreSQL DDL statements, including statements such as
10917/// `CLUSTER`, `EXPLAIN`, `VACUUM`, and `REINDEX`. These statements format options as `( option [, ...] )`.
10918///
10919/// [CLUSTER](https://www.postgresql.org/docs/current/sql-cluster.html)
10920/// [EXPLAIN](https://www.postgresql.org/docs/current/sql-explain.html)
10921/// [VACUUM](https://www.postgresql.org/docs/current/sql-vacuum.html)
10922/// [REINDEX](https://www.postgresql.org/docs/current/sql-reindex.html)
10923///
10924/// For example, the `EXPLAIN` AND `VACUUM` statements with options might look like this:
10925/// ```sql
10926/// EXPLAIN (ANALYZE, VERBOSE TRUE, FORMAT TEXT) SELECT * FROM my_table;
10927///
10928/// VACUUM (VERBOSE, ANALYZE ON, PARALLEL 10) my_table;
10929/// ```
10930#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10931#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10932#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10933pub struct UtilityOption {
10934    /// The option name (identifier).
10935    pub name: Ident,
10936    /// Optional argument for the option (number, string, keyword, etc.).
10937    pub arg: Option<Expr>,
10938}
10939
10940impl Display for UtilityOption {
10941    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10942        if let Some(ref arg) = self.arg {
10943            write!(f, "{} {}", self.name, arg)
10944        } else {
10945            write!(f, "{}", self.name)
10946        }
10947    }
10948}
10949
10950/// Represents the different options available for `SHOW`
10951/// statements to filter the results. Example from Snowflake:
10952/// <https://docs.snowflake.com/en/sql-reference/sql/show-tables>
10953#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10954#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10955#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10956pub struct ShowStatementOptions {
10957    /// Optional scope to show in (for example: TABLE, SCHEMA).
10958    pub show_in: Option<ShowStatementIn>,
10959    /// Optional `STARTS WITH` filter value.
10960    pub starts_with: Option<ValueWithSpan>,
10961    /// Optional `LIMIT` expression.
10962    pub limit: Option<Expr>,
10963    /// Optional `FROM` value used with `LIMIT`.
10964    pub limit_from: Option<ValueWithSpan>,
10965    /// Optional filter position (infix or suffix) for `LIKE`/`FILTER`.
10966    pub filter_position: Option<ShowStatementFilterPosition>,
10967}
10968
10969impl Display for ShowStatementOptions {
10970    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10971        let (like_in_infix, like_in_suffix) = match &self.filter_position {
10972            Some(ShowStatementFilterPosition::Infix(filter)) => {
10973                (format!(" {filter}"), "".to_string())
10974            }
10975            Some(ShowStatementFilterPosition::Suffix(filter)) => {
10976                ("".to_string(), format!(" {filter}"))
10977            }
10978            None => ("".to_string(), "".to_string()),
10979        };
10980        write!(
10981            f,
10982            "{like_in_infix}{show_in}{starts_with}{limit}{from}{like_in_suffix}",
10983            show_in = match &self.show_in {
10984                Some(i) => format!(" {i}"),
10985                None => String::new(),
10986            },
10987            starts_with = match &self.starts_with {
10988                Some(s) => format!(" STARTS WITH {s}"),
10989                None => String::new(),
10990            },
10991            limit = match &self.limit {
10992                Some(l) => format!(" LIMIT {l}"),
10993                None => String::new(),
10994            },
10995            from = match &self.limit_from {
10996                Some(f) => format!(" FROM {f}"),
10997                None => String::new(),
10998            }
10999        )?;
11000        Ok(())
11001    }
11002}
11003
11004#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11005#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11006#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11007/// Where a `SHOW` filter appears relative to the main clause.
11008pub enum ShowStatementFilterPosition {
11009    /// Put the filter in an infix position (e.g. `SHOW COLUMNS LIKE '%name%' IN TABLE tbl`).
11010    Infix(ShowStatementFilter), // For example: SHOW COLUMNS LIKE '%name%' IN TABLE tbl
11011    /// Put the filter in a suffix position (e.g. `SHOW COLUMNS IN tbl LIKE '%name%'`).
11012    Suffix(ShowStatementFilter), // For example: SHOW COLUMNS IN tbl LIKE '%name%'
11013}
11014
11015#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11016#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11017#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11018/// Parent object types usable with `SHOW ... IN <parent>` clauses.
11019pub enum ShowStatementInParentType {
11020    /// ACCOUNT parent type for SHOW statements.
11021    Account,
11022    /// DATABASE parent type for SHOW statements.
11023    Database,
11024    /// SCHEMA parent type for SHOW statements.
11025    Schema,
11026    /// TABLE parent type for SHOW statements.
11027    Table,
11028    /// VIEW parent type for SHOW statements.
11029    View,
11030}
11031
11032impl fmt::Display for ShowStatementInParentType {
11033    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11034        match self {
11035            ShowStatementInParentType::Account => write!(f, "ACCOUNT"),
11036            ShowStatementInParentType::Database => write!(f, "DATABASE"),
11037            ShowStatementInParentType::Schema => write!(f, "SCHEMA"),
11038            ShowStatementInParentType::Table => write!(f, "TABLE"),
11039            ShowStatementInParentType::View => write!(f, "VIEW"),
11040        }
11041    }
11042}
11043
11044#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11045#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11046#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11047/// Represents a `SHOW ... IN` clause with optional parent qualifier and name.
11048pub struct ShowStatementIn {
11049    /// The clause that specifies what to show (e.g. COLUMNS, TABLES).
11050    pub clause: ShowStatementInClause,
11051    /// Optional parent type qualifier (ACCOUNT/DATABASE/...).
11052    pub parent_type: Option<ShowStatementInParentType>,
11053    /// Optional parent object name for the SHOW clause.
11054    #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
11055    pub parent_name: Option<ObjectName>,
11056}
11057
11058impl fmt::Display for ShowStatementIn {
11059    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11060        write!(f, "{}", self.clause)?;
11061        if let Some(parent_type) = &self.parent_type {
11062            write!(f, " {parent_type}")?;
11063        }
11064        if let Some(parent_name) = &self.parent_name {
11065            write!(f, " {parent_name}")?;
11066        }
11067        Ok(())
11068    }
11069}
11070
11071/// A Show Charset statement
11072#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11073#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11074#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11075pub struct ShowCharset {
11076    /// The statement can be written as `SHOW CHARSET` or `SHOW CHARACTER SET`
11077    /// true means CHARSET was used and false means CHARACTER SET was used
11078    pub is_shorthand: bool,
11079    /// Optional `LIKE`/`WHERE`-style filter for the statement.
11080    pub filter: Option<ShowStatementFilter>,
11081}
11082
11083impl fmt::Display for ShowCharset {
11084    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11085        write!(f, "SHOW")?;
11086        if self.is_shorthand {
11087            write!(f, " CHARSET")?;
11088        } else {
11089            write!(f, " CHARACTER SET")?;
11090        }
11091        if let Some(filter) = &self.filter {
11092            write!(f, " {filter}")?;
11093        }
11094        Ok(())
11095    }
11096}
11097
11098#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11099#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11100#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11101/// Options for a `SHOW OBJECTS` statement.
11102pub struct ShowObjects {
11103    /// Whether to show terse output.
11104    pub terse: bool,
11105    /// Additional options controlling the SHOW output.
11106    pub show_options: ShowStatementOptions,
11107}
11108
11109/// MSSQL's json null clause
11110///
11111/// ```plaintext
11112/// <json_null_clause> ::=
11113///       NULL ON NULL
11114///     | ABSENT ON NULL
11115/// ```
11116///
11117/// <https://learn.microsoft.com/en-us/sql/t-sql/functions/json-object-transact-sql?view=sql-server-ver16#json_null_clause>
11118#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11119#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11120#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11121pub enum JsonNullClause {
11122    /// `NULL ON NULL` behavior for JSON functions.
11123    NullOnNull,
11124    /// `ABSENT ON NULL` behavior for JSON functions.
11125    AbsentOnNull,
11126}
11127
11128impl Display for JsonNullClause {
11129    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
11130        match self {
11131            JsonNullClause::NullOnNull => write!(f, "NULL ON NULL"),
11132            JsonNullClause::AbsentOnNull => write!(f, "ABSENT ON NULL"),
11133        }
11134    }
11135}
11136
11137/// PostgreSQL JSON function RETURNING clause
11138///
11139/// Example:
11140/// ```sql
11141/// JSON_OBJECT('a': 1 RETURNING jsonb)
11142/// ```
11143#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11144#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11145#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11146pub struct JsonReturningClause {
11147    /// The data type to return from the JSON function (e.g. JSON/JSONB).
11148    pub data_type: DataType,
11149}
11150
11151impl Display for JsonReturningClause {
11152    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
11153        write!(f, "RETURNING {}", self.data_type)
11154    }
11155}
11156
11157/// rename object definition
11158#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11159#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11160#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11161pub struct RenameTable {
11162    /// The current name of the object to rename.
11163    pub old_name: ObjectName,
11164    /// The new name for the object.
11165    pub new_name: ObjectName,
11166}
11167
11168impl fmt::Display for RenameTable {
11169    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11170        write!(f, "{} TO {}", self.old_name, self.new_name)?;
11171        Ok(())
11172    }
11173}
11174
11175/// Represents the referenced table in an `INSERT INTO` statement
11176#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11177#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11178#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11179pub enum TableObject {
11180    /// Table specified by name.
11181    /// Example:
11182    /// ```sql
11183    /// INSERT INTO my_table
11184    /// ```
11185    TableName(#[cfg_attr(feature = "visitor", visit(with = "visit_relation"))] ObjectName),
11186
11187    /// Table specified as a function.
11188    /// Example:
11189    /// ```sql
11190    /// INSERT INTO TABLE FUNCTION remote('localhost', default.simple_table)
11191    /// ```
11192    /// [Clickhouse](https://clickhouse.com/docs/en/sql-reference/table-functions)
11193    TableFunction(Function),
11194
11195    /// Table specified through a sub-query
11196    /// Example:
11197    /// ```sql
11198    /// INSERT INTO
11199    /// (SELECT employee_id, last_name, email, hire_date, job_id,  salary, commission_pct FROM employees)
11200    /// VALUES (207, 'Gregory', 'pgregory@example.com', sysdate, 'PU_CLERK', 1.2E3, NULL);
11201    /// ```
11202    /// [Oracle](https://docs.oracle.com/en/database/oracle/oracle-database/21/sqlrf/INSERT.html#GUID-903F8043-0254-4EE9-ACC1-CB8AC0AF3423__I2126242)
11203    TableQuery(Box<Query>),
11204}
11205
11206impl fmt::Display for TableObject {
11207    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11208        match self {
11209            Self::TableName(table_name) => write!(f, "{table_name}"),
11210            Self::TableFunction(func) => write!(f, "FUNCTION {func}"),
11211            Self::TableQuery(table_query) => write!(f, "({table_query})"),
11212        }
11213    }
11214}
11215
11216/// Represents a SET SESSION AUTHORIZATION statement
11217#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11218#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11219#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11220pub struct SetSessionAuthorizationParam {
11221    /// The scope for the `SET SESSION AUTHORIZATION` (e.g., GLOBAL/SESSION).
11222    pub scope: ContextModifier,
11223    /// The specific authorization parameter kind.
11224    pub kind: SetSessionAuthorizationParamKind,
11225}
11226
11227impl fmt::Display for SetSessionAuthorizationParam {
11228    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11229        write!(f, "{}", self.kind)
11230    }
11231}
11232
11233/// Represents the parameter kind for SET SESSION AUTHORIZATION
11234#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11235#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11236#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11237pub enum SetSessionAuthorizationParamKind {
11238    /// Default authorization
11239    Default,
11240
11241    /// User name
11242    User(Ident),
11243}
11244
11245impl fmt::Display for SetSessionAuthorizationParamKind {
11246    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11247        match self {
11248            SetSessionAuthorizationParamKind::Default => write!(f, "DEFAULT"),
11249            SetSessionAuthorizationParamKind::User(name) => write!(f, "{}", name),
11250        }
11251    }
11252}
11253
11254#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11255#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11256#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11257/// Kind of session parameter being set by `SET SESSION`.
11258pub enum SetSessionParamKind {
11259    /// Generic session parameter (name/value pair).
11260    Generic(SetSessionParamGeneric),
11261    /// Identity insert related parameter.
11262    IdentityInsert(SetSessionParamIdentityInsert),
11263    /// Offsets-related parameter.
11264    Offsets(SetSessionParamOffsets),
11265    /// Statistics-related parameter.
11266    Statistics(SetSessionParamStatistics),
11267}
11268
11269impl fmt::Display for SetSessionParamKind {
11270    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11271        match self {
11272            SetSessionParamKind::Generic(x) => write!(f, "{x}"),
11273            SetSessionParamKind::IdentityInsert(x) => write!(f, "{x}"),
11274            SetSessionParamKind::Offsets(x) => write!(f, "{x}"),
11275            SetSessionParamKind::Statistics(x) => write!(f, "{x}"),
11276        }
11277    }
11278}
11279
11280#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11281#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11282#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11283/// Generic `SET SESSION` parameter represented as name(s) and value.
11284pub struct SetSessionParamGeneric {
11285    /// Names of the session parameters being set.
11286    pub names: Vec<String>,
11287    /// The value to assign to the parameter(s).
11288    pub value: String,
11289}
11290
11291impl fmt::Display for SetSessionParamGeneric {
11292    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11293        write!(f, "{} {}", display_comma_separated(&self.names), self.value)
11294    }
11295}
11296
11297#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11298#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11299#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11300/// `IDENTITY_INSERT` session parameter for a specific object.
11301pub struct SetSessionParamIdentityInsert {
11302    /// Object name targeted by `IDENTITY_INSERT`.
11303    pub obj: ObjectName,
11304    /// Value (ON/OFF) for the identity insert setting.
11305    pub value: SessionParamValue,
11306}
11307
11308impl fmt::Display for SetSessionParamIdentityInsert {
11309    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11310        write!(f, "IDENTITY_INSERT {} {}", self.obj, self.value)
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/// Offsets-related session parameter with keywords and a value.
11318pub struct SetSessionParamOffsets {
11319    /// Keywords specifying which offsets to modify.
11320    pub keywords: Vec<String>,
11321    /// Value (ON/OFF) for the offsets setting.
11322    pub value: SessionParamValue,
11323}
11324
11325impl fmt::Display for SetSessionParamOffsets {
11326    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11327        write!(
11328            f,
11329            "OFFSETS {} {}",
11330            display_comma_separated(&self.keywords),
11331            self.value
11332        )
11333    }
11334}
11335
11336#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11337#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11338#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11339/// Statistics-related session parameter specifying topic and value.
11340pub struct SetSessionParamStatistics {
11341    /// Statistics topic to set (IO/PROFILE/TIME/XML).
11342    pub topic: SessionParamStatsTopic,
11343    /// Value (ON/OFF) for the statistics topic.
11344    pub value: SessionParamValue,
11345}
11346
11347impl fmt::Display for SetSessionParamStatistics {
11348    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11349        write!(f, "STATISTICS {} {}", self.topic, self.value)
11350    }
11351}
11352
11353#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11354#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11355#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11356/// Topics available for session statistics configuration.
11357pub enum SessionParamStatsTopic {
11358    /// Input/output statistics.
11359    IO,
11360    /// Profile statistics.
11361    Profile,
11362    /// Time statistics.
11363    Time,
11364    /// XML-related statistics.
11365    Xml,
11366}
11367
11368impl fmt::Display for SessionParamStatsTopic {
11369    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11370        match self {
11371            SessionParamStatsTopic::IO => write!(f, "IO"),
11372            SessionParamStatsTopic::Profile => write!(f, "PROFILE"),
11373            SessionParamStatsTopic::Time => write!(f, "TIME"),
11374            SessionParamStatsTopic::Xml => write!(f, "XML"),
11375        }
11376    }
11377}
11378
11379#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11380#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11381#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11382/// Value for a session boolean-like parameter (ON/OFF).
11383pub enum SessionParamValue {
11384    /// Session parameter enabled.
11385    On,
11386    /// Session parameter disabled.
11387    Off,
11388}
11389
11390impl fmt::Display for SessionParamValue {
11391    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11392        match self {
11393            SessionParamValue::On => write!(f, "ON"),
11394            SessionParamValue::Off => write!(f, "OFF"),
11395        }
11396    }
11397}
11398
11399/// Snowflake StorageSerializationPolicy for Iceberg Tables
11400/// ```sql
11401/// [ STORAGE_SERIALIZATION_POLICY = { COMPATIBLE | OPTIMIZED } ]
11402/// ```
11403///
11404/// <https://docs.snowflake.com/en/sql-reference/sql/create-iceberg-table>
11405#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11406#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11407#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11408pub enum StorageSerializationPolicy {
11409    /// Use compatible serialization mode.
11410    Compatible,
11411    /// Use optimized serialization mode.
11412    Optimized,
11413}
11414
11415impl Display for StorageSerializationPolicy {
11416    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
11417        match self {
11418            StorageSerializationPolicy::Compatible => write!(f, "COMPATIBLE"),
11419            StorageSerializationPolicy::Optimized => write!(f, "OPTIMIZED"),
11420        }
11421    }
11422}
11423
11424/// Snowflake CatalogSyncNamespaceMode
11425/// ```sql
11426/// [ CATALOG_SYNC_NAMESPACE_MODE = { NEST | FLATTEN } ]
11427/// ```
11428///
11429/// <https://docs.snowflake.com/en/sql-reference/sql/create-database>
11430#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11431#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11432#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11433pub enum CatalogSyncNamespaceMode {
11434    /// Nest namespaces when syncing catalog.
11435    Nest,
11436    /// Flatten namespaces when syncing catalog.
11437    Flatten,
11438}
11439
11440impl Display for CatalogSyncNamespaceMode {
11441    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
11442        match self {
11443            CatalogSyncNamespaceMode::Nest => write!(f, "NEST"),
11444            CatalogSyncNamespaceMode::Flatten => write!(f, "FLATTEN"),
11445        }
11446    }
11447}
11448
11449/// Variants of the Snowflake `COPY INTO` statement
11450#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11451#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11452#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11453pub enum CopyIntoSnowflakeKind {
11454    /// Loads data from files to a table
11455    /// See: <https://docs.snowflake.com/en/sql-reference/sql/copy-into-table>
11456    Table,
11457    /// Unloads data from a table or query to external files
11458    /// See: <https://docs.snowflake.com/en/sql-reference/sql/copy-into-location>
11459    Location,
11460}
11461
11462#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11463#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11464#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11465/// `PRINT` statement for producing debug/output messages.
11466pub struct PrintStatement {
11467    /// The expression producing the message to print.
11468    pub message: Box<Expr>,
11469}
11470
11471impl fmt::Display for PrintStatement {
11472    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11473        write!(f, "PRINT {}", self.message)
11474    }
11475}
11476
11477/// The type of `WAITFOR` statement (MSSQL).
11478///
11479/// See: <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/waitfor-transact-sql>
11480#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11481#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11482#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11483pub enum WaitForType {
11484    /// `WAITFOR DELAY 'time_to_pass'`
11485    Delay,
11486    /// `WAITFOR TIME 'time_to_execute'`
11487    Time,
11488}
11489
11490impl fmt::Display for WaitForType {
11491    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11492        match self {
11493            WaitForType::Delay => write!(f, "DELAY"),
11494            WaitForType::Time => write!(f, "TIME"),
11495        }
11496    }
11497}
11498
11499/// MSSQL `WAITFOR` statement.
11500///
11501/// See: <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/waitfor-transact-sql>
11502#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11503#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11504#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11505pub struct WaitForStatement {
11506    /// `DELAY` or `TIME`.
11507    pub wait_type: WaitForType,
11508    /// The time expression.
11509    pub expr: Expr,
11510}
11511
11512impl fmt::Display for WaitForStatement {
11513    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11514        write!(f, "WAITFOR {} {}", self.wait_type, self.expr)
11515    }
11516}
11517
11518/// Represents a `Return` statement.
11519///
11520/// [MsSql triggers](https://learn.microsoft.com/en-us/sql/t-sql/statements/create-trigger-transact-sql)
11521/// [MsSql functions](https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql)
11522#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11523#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11524#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11525pub struct ReturnStatement {
11526    /// Optional return value expression.
11527    pub value: Option<ReturnStatementValue>,
11528}
11529
11530impl fmt::Display for ReturnStatement {
11531    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11532        match &self.value {
11533            Some(ReturnStatementValue::Expr(expr)) => write!(f, "RETURN {expr}"),
11534            None => write!(f, "RETURN"),
11535        }
11536    }
11537}
11538
11539/// Variants of a `RETURN` statement
11540#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11541#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11542#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11543pub enum ReturnStatementValue {
11544    /// Return an expression from a function or trigger.
11545    Expr(Expr),
11546}
11547
11548/// Represents an `OPEN` statement.
11549#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11550#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11551#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11552pub struct OpenStatement {
11553    /// Cursor name
11554    pub cursor_name: Ident,
11555}
11556
11557impl fmt::Display for OpenStatement {
11558    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11559        write!(f, "OPEN {}", self.cursor_name)
11560    }
11561}
11562
11563/// Specifies Include / Exclude NULL within UNPIVOT command.
11564/// For example
11565/// `UNPIVOT (column1 FOR new_column IN (col3, col4, col5, col6))`
11566#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11567#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11568#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11569pub enum NullInclusion {
11570    /// Include NULL values in the UNPIVOT output.
11571    IncludeNulls,
11572    /// Exclude NULL values from the UNPIVOT output.
11573    ExcludeNulls,
11574}
11575
11576impl fmt::Display for NullInclusion {
11577    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11578        match self {
11579            NullInclusion::IncludeNulls => write!(f, "INCLUDE NULLS"),
11580            NullInclusion::ExcludeNulls => write!(f, "EXCLUDE NULLS"),
11581        }
11582    }
11583}
11584
11585/// Checks membership of a value in a JSON array
11586///
11587/// Syntax:
11588/// ```sql
11589/// <value> MEMBER OF(<array>)
11590/// ```
11591/// [MySQL](https://dev.mysql.com/doc/refman/8.4/en/json-search-functions.html#operator_member-of)
11592#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11593#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11594#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11595pub struct MemberOf {
11596    /// The value to check for membership.
11597    pub value: Box<Expr>,
11598    /// The JSON array expression to check against.
11599    pub array: Box<Expr>,
11600}
11601
11602impl fmt::Display for MemberOf {
11603    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11604        write!(f, "{} MEMBER OF({})", self.value, self.array)
11605    }
11606}
11607
11608#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11609#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11610#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11611/// Represents an `EXPORT DATA` statement.
11612pub struct ExportData {
11613    /// Options for the export operation.
11614    pub options: Vec<SqlOption>,
11615    /// The query producing the data to export.
11616    pub query: Box<Query>,
11617    /// Optional named connection to use for export.
11618    pub connection: Option<ObjectName>,
11619}
11620
11621impl fmt::Display for ExportData {
11622    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11623        if let Some(connection) = &self.connection {
11624            write!(
11625                f,
11626                "EXPORT DATA WITH CONNECTION {connection} OPTIONS({}) AS {}",
11627                display_comma_separated(&self.options),
11628                self.query
11629            )
11630        } else {
11631            write!(
11632                f,
11633                "EXPORT DATA OPTIONS({}) AS {}",
11634                display_comma_separated(&self.options),
11635                self.query
11636            )
11637        }
11638    }
11639}
11640/// Creates a user
11641///
11642/// Syntax:
11643/// ```sql
11644/// CREATE [OR REPLACE] USER [IF NOT EXISTS] <name> [OPTIONS]
11645/// ```
11646///
11647/// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-user)
11648#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11649#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11650#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11651pub struct CreateUser {
11652    /// Replace existing user if present.
11653    pub or_replace: bool,
11654    /// Only create the user if it does not already exist.
11655    pub if_not_exists: bool,
11656    /// The name of the user to create.
11657    pub name: Ident,
11658    /// Key/value options for user creation.
11659    pub options: KeyValueOptions,
11660    /// Whether tags are specified using `WITH TAG`.
11661    pub with_tags: bool,
11662    /// Tags for the user.
11663    pub tags: KeyValueOptions,
11664}
11665
11666impl fmt::Display for CreateUser {
11667    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11668        write!(f, "CREATE")?;
11669        if self.or_replace {
11670            write!(f, " OR REPLACE")?;
11671        }
11672        write!(f, " USER")?;
11673        if self.if_not_exists {
11674            write!(f, " IF NOT EXISTS")?;
11675        }
11676        write!(f, " {}", self.name)?;
11677        if !self.options.options.is_empty() {
11678            write!(f, " {}", self.options)?;
11679        }
11680        if !self.tags.options.is_empty() {
11681            if self.with_tags {
11682                write!(f, " WITH")?;
11683            }
11684            write!(f, " TAG ({})", self.tags)?;
11685        }
11686        Ok(())
11687    }
11688}
11689
11690/// Modifies the properties of a user
11691///
11692/// [Snowflake Syntax:](https://docs.snowflake.com/en/sql-reference/sql/alter-user)
11693/// ```sql
11694/// ALTER USER [ IF EXISTS ] [ <name> ] [ OPTIONS ]
11695/// ```
11696///
11697/// [PostgreSQL Syntax:](https://www.postgresql.org/docs/current/sql-alteruser.html)
11698/// ```sql
11699/// ALTER USER <role_specification> [ WITH ] option [ ... ]
11700/// ```
11701#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11702#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11703#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11704pub struct AlterUser {
11705    /// Whether to only alter the user if it exists.
11706    pub if_exists: bool,
11707    /// The name of the user to alter.
11708    pub name: Ident,
11709    /// Optional new name for the user (Snowflake-specific).
11710    /// See: <https://docs.snowflake.com/en/sql-reference/sql/alter-user#syntax>
11711    pub rename_to: Option<Ident>,
11712    /// Reset the user's password.
11713    pub reset_password: bool,
11714    /// Abort all running queries for the user.
11715    pub abort_all_queries: bool,
11716    /// Optionally add a delegated role authorization.
11717    pub add_role_delegation: Option<AlterUserAddRoleDelegation>,
11718    /// Optionally remove a delegated role authorization.
11719    pub remove_role_delegation: Option<AlterUserRemoveRoleDelegation>,
11720    /// Enroll the user in MFA.
11721    pub enroll_mfa: bool,
11722    /// Set the default MFA method for the user.
11723    pub set_default_mfa_method: Option<MfaMethodKind>,
11724    /// Remove the user's default MFA method.
11725    pub remove_mfa_method: Option<MfaMethodKind>,
11726    /// Modify an MFA method for the user.
11727    pub modify_mfa_method: Option<AlterUserModifyMfaMethod>,
11728    /// Add an MFA OTP method with optional count.
11729    pub add_mfa_method_otp: Option<AlterUserAddMfaMethodOtp>,
11730    /// Set a user policy.
11731    pub set_policy: Option<AlterUserSetPolicy>,
11732    /// Unset a user policy.
11733    pub unset_policy: Option<UserPolicyKind>,
11734    /// Key/value tag options to set on the user.
11735    pub set_tag: KeyValueOptions,
11736    /// Tags to unset on the user.
11737    pub unset_tag: Vec<String>,
11738    /// Key/value properties to set on the user.
11739    pub set_props: KeyValueOptions,
11740    /// Properties to unset on the user.
11741    pub unset_props: Vec<String>,
11742    /// The following options are PostgreSQL-specific: <https://www.postgresql.org/docs/current/sql-alteruser.html>
11743    pub password: Option<AlterUserPassword>,
11744}
11745
11746/// ```sql
11747/// ALTER USER [ IF EXISTS ] [ <name> ] ADD DELEGATED AUTHORIZATION OF ROLE <role_name> TO SECURITY INTEGRATION <integration_name>
11748/// ```
11749#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11750#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11751#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11752pub struct AlterUserAddRoleDelegation {
11753    /// Role name to delegate.
11754    pub role: Ident,
11755    /// Security integration receiving the delegation.
11756    pub integration: Ident,
11757}
11758
11759/// ```sql
11760/// ALTER USER [ IF EXISTS ] [ <name> ] REMOVE DELEGATED { AUTHORIZATION OF ROLE <role_name> | AUTHORIZATIONS } FROM SECURITY INTEGRATION <integration_name>
11761/// ```
11762#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11763#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11764#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11765pub struct AlterUserRemoveRoleDelegation {
11766    /// Optional role name to remove delegation for.
11767    pub role: Option<Ident>,
11768    /// Security integration from which to remove delegation.
11769    pub integration: Ident,
11770}
11771
11772/// ```sql
11773/// ADD MFA METHOD OTP [ COUNT = number ]
11774/// ```
11775#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11776#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11777#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11778pub struct AlterUserAddMfaMethodOtp {
11779    /// Optional OTP count parameter.
11780    pub count: Option<ValueWithSpan>,
11781}
11782
11783/// ```sql
11784/// ALTER USER [ IF EXISTS ] [ <name> ] MODIFY MFA METHOD <mfa_method> SET COMMENT = '<string>'
11785/// ```
11786#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11787#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11788#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11789pub struct AlterUserModifyMfaMethod {
11790    /// The MFA method being modified.
11791    pub method: MfaMethodKind,
11792    /// The new comment for the MFA method.
11793    pub comment: String,
11794}
11795
11796/// Types of MFA methods
11797#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11798#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11799#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11800pub enum MfaMethodKind {
11801    /// PassKey (hardware or platform passkey) MFA method.
11802    PassKey,
11803    /// Time-based One-Time Password (TOTP) MFA method.
11804    Totp,
11805    /// Duo Security MFA method.
11806    Duo,
11807}
11808
11809impl fmt::Display for MfaMethodKind {
11810    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11811        match self {
11812            MfaMethodKind::PassKey => write!(f, "PASSKEY"),
11813            MfaMethodKind::Totp => write!(f, "TOTP"),
11814            MfaMethodKind::Duo => write!(f, "DUO"),
11815        }
11816    }
11817}
11818
11819/// ```sql
11820/// ALTER USER [ IF EXISTS ] [ <name> ] SET { AUTHENTICATION | PASSWORD | SESSION } POLICY <policy_name>
11821/// ```
11822#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11823#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11824#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11825pub struct AlterUserSetPolicy {
11826    /// The kind of user policy being set (authentication/password/session).
11827    pub policy_kind: UserPolicyKind,
11828    /// The identifier of the policy to apply.
11829    pub policy: Ident,
11830}
11831
11832/// Types of user-based policies
11833#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11834#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11835#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11836pub enum UserPolicyKind {
11837    /// Authentication policy.
11838    Authentication,
11839    /// Password policy.
11840    Password,
11841    /// Session policy.
11842    Session,
11843}
11844
11845impl fmt::Display for UserPolicyKind {
11846    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11847        match self {
11848            UserPolicyKind::Authentication => write!(f, "AUTHENTICATION"),
11849            UserPolicyKind::Password => write!(f, "PASSWORD"),
11850            UserPolicyKind::Session => write!(f, "SESSION"),
11851        }
11852    }
11853}
11854
11855impl fmt::Display for AlterUser {
11856    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11857        write!(f, "ALTER")?;
11858        write!(f, " USER")?;
11859        if self.if_exists {
11860            write!(f, " IF EXISTS")?;
11861        }
11862        write!(f, " {}", self.name)?;
11863        if let Some(new_name) = &self.rename_to {
11864            write!(f, " RENAME TO {new_name}")?;
11865        }
11866        if self.reset_password {
11867            write!(f, " RESET PASSWORD")?;
11868        }
11869        if self.abort_all_queries {
11870            write!(f, " ABORT ALL QUERIES")?;
11871        }
11872        if let Some(role_delegation) = &self.add_role_delegation {
11873            let role = &role_delegation.role;
11874            let integration = &role_delegation.integration;
11875            write!(
11876                f,
11877                " ADD DELEGATED AUTHORIZATION OF ROLE {role} TO SECURITY INTEGRATION {integration}"
11878            )?;
11879        }
11880        if let Some(role_delegation) = &self.remove_role_delegation {
11881            write!(f, " REMOVE DELEGATED")?;
11882            match &role_delegation.role {
11883                Some(role) => write!(f, " AUTHORIZATION OF ROLE {role}")?,
11884                None => write!(f, " AUTHORIZATIONS")?,
11885            }
11886            let integration = &role_delegation.integration;
11887            write!(f, " FROM SECURITY INTEGRATION {integration}")?;
11888        }
11889        if self.enroll_mfa {
11890            write!(f, " ENROLL MFA")?;
11891        }
11892        if let Some(method) = &self.set_default_mfa_method {
11893            write!(f, " SET DEFAULT_MFA_METHOD {method}")?
11894        }
11895        if let Some(method) = &self.remove_mfa_method {
11896            write!(f, " REMOVE MFA METHOD {method}")?;
11897        }
11898        if let Some(modify) = &self.modify_mfa_method {
11899            let method = &modify.method;
11900            let comment = &modify.comment;
11901            write!(
11902                f,
11903                " MODIFY MFA METHOD {method} SET COMMENT '{}'",
11904                value::escape_single_quote_string(comment)
11905            )?;
11906        }
11907        if let Some(add_mfa_method_otp) = &self.add_mfa_method_otp {
11908            write!(f, " ADD MFA METHOD OTP")?;
11909            if let Some(count) = &add_mfa_method_otp.count {
11910                write!(f, " COUNT = {count}")?;
11911            }
11912        }
11913        if let Some(policy) = &self.set_policy {
11914            let policy_kind = &policy.policy_kind;
11915            let name = &policy.policy;
11916            write!(f, " SET {policy_kind} POLICY {name}")?;
11917        }
11918        if let Some(policy_kind) = &self.unset_policy {
11919            write!(f, " UNSET {policy_kind} POLICY")?;
11920        }
11921        if !self.set_tag.options.is_empty() {
11922            write!(f, " SET TAG {}", self.set_tag)?;
11923        }
11924        if !self.unset_tag.is_empty() {
11925            write!(f, " UNSET TAG {}", display_comma_separated(&self.unset_tag))?;
11926        }
11927        let has_props = !self.set_props.options.is_empty();
11928        if has_props {
11929            write!(f, " SET")?;
11930            write!(f, " {}", &self.set_props)?;
11931        }
11932        if !self.unset_props.is_empty() {
11933            write!(f, " UNSET {}", display_comma_separated(&self.unset_props))?;
11934        }
11935        if let Some(password) = &self.password {
11936            write!(f, " {}", password)?;
11937        }
11938        Ok(())
11939    }
11940}
11941
11942/// ```sql
11943/// ALTER USER <role_specification> [ WITH ] PASSWORD { 'password' | NULL }``
11944/// ```
11945#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11946#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11947#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11948pub struct AlterUserPassword {
11949    /// Whether the password is encrypted.
11950    pub encrypted: bool,
11951    /// The password string, or `None` for `NULL`.
11952    pub password: Option<String>,
11953}
11954
11955impl Display for AlterUserPassword {
11956    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11957        if self.encrypted {
11958            write!(f, "ENCRYPTED ")?;
11959        }
11960        write!(f, "PASSWORD")?;
11961        match &self.password {
11962            None => write!(f, " NULL")?,
11963            Some(password) => write!(f, " '{}'", value::escape_single_quote_string(password))?,
11964        }
11965        Ok(())
11966    }
11967}
11968
11969/// Specifies how to create a new table based on an existing table's schema.
11970/// '''sql
11971/// CREATE TABLE new LIKE old ...
11972/// '''
11973#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11974#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11975#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11976pub enum CreateTableLikeKind {
11977    /// '''sql
11978    /// CREATE TABLE new (LIKE old ...)
11979    /// '''
11980    /// [Redshift](https://docs.aws.amazon.com/redshift/latest/dg/r_CREATE_TABLE_NEW.html)
11981    Parenthesized(CreateTableLike),
11982    /// '''sql
11983    /// CREATE TABLE new LIKE old ...
11984    /// '''
11985    /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-table#label-create-table-like)
11986    /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_table_like)
11987    Plain(CreateTableLike),
11988}
11989
11990#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11991#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11992#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11993/// Controls whether defaults are included when creating a table FROM/LILE another.
11994pub enum CreateTableLikeDefaults {
11995    /// Include default values from the source table.
11996    Including,
11997    /// Exclude default values from the source table.
11998    Excluding,
11999}
12000
12001impl fmt::Display for CreateTableLikeDefaults {
12002    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
12003        match self {
12004            CreateTableLikeDefaults::Including => write!(f, "INCLUDING DEFAULTS"),
12005            CreateTableLikeDefaults::Excluding => write!(f, "EXCLUDING DEFAULTS"),
12006        }
12007    }
12008}
12009
12010#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
12011#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
12012#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
12013/// Represents the `LIKE` clause of a `CREATE TABLE` statement.
12014pub struct CreateTableLike {
12015    /// The source table name to copy the schema from.
12016    pub name: ObjectName,
12017    /// Optional behavior controlling whether defaults are copied.
12018    pub defaults: Option<CreateTableLikeDefaults>,
12019}
12020
12021impl fmt::Display for CreateTableLike {
12022    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
12023        write!(f, "LIKE {}", self.name)?;
12024        if let Some(defaults) = &self.defaults {
12025            write!(f, " {defaults}")?;
12026        }
12027        Ok(())
12028    }
12029}
12030
12031/// Specifies the refresh mode for the dynamic table.
12032///
12033/// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-dynamic-table)
12034#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
12035#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
12036#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
12037pub enum RefreshModeKind {
12038    /// Automatic refresh mode (`AUTO`).
12039    Auto,
12040    /// Full refresh mode (`FULL`).
12041    Full,
12042    /// Incremental refresh mode (`INCREMENTAL`).
12043    Incremental,
12044}
12045
12046impl fmt::Display for RefreshModeKind {
12047    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
12048        match self {
12049            RefreshModeKind::Auto => write!(f, "AUTO"),
12050            RefreshModeKind::Full => write!(f, "FULL"),
12051            RefreshModeKind::Incremental => write!(f, "INCREMENTAL"),
12052        }
12053    }
12054}
12055
12056/// Specifies the behavior of the initial refresh of the dynamic table.
12057///
12058/// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-dynamic-table)
12059#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
12060#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
12061#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
12062pub enum InitializeKind {
12063    /// Initialize on creation (`ON CREATE`).
12064    OnCreate,
12065    /// Initialize on schedule (`ON SCHEDULE`).
12066    OnSchedule,
12067}
12068
12069impl fmt::Display for InitializeKind {
12070    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
12071        match self {
12072            InitializeKind::OnCreate => write!(f, "ON_CREATE"),
12073            InitializeKind::OnSchedule => write!(f, "ON_SCHEDULE"),
12074        }
12075    }
12076}
12077
12078/// Re-sorts rows and reclaims space in either a specified table or all tables in the current database
12079///
12080/// '''sql
12081/// VACUUM [ FULL | SORT ONLY | DELETE ONLY | REINDEX | RECLUSTER ] [ \[ table_name \] [ TO threshold PERCENT ] \[ BOOST \] ]
12082/// '''
12083/// [Redshift](https://docs.aws.amazon.com/redshift/latest/dg/r_VACUUM_command.html)
12084#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
12085#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
12086#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
12087pub struct VacuumStatement {
12088    /// Whether `FULL` was specified.
12089    pub full: bool,
12090    /// Whether `SORT ONLY` was specified.
12091    pub sort_only: bool,
12092    /// Whether `DELETE ONLY` was specified.
12093    pub delete_only: bool,
12094    /// Whether `REINDEX` was specified.
12095    pub reindex: bool,
12096    /// Whether `RECLUSTER` was specified.
12097    pub recluster: bool,
12098    /// Optional table to run `VACUUM` on.
12099    pub table_name: Option<ObjectName>,
12100    /// Optional threshold value (percent) for `TO threshold PERCENT`.
12101    pub threshold: Option<ValueWithSpan>,
12102    /// Whether `BOOST` was specified.
12103    pub boost: bool,
12104}
12105
12106impl fmt::Display for VacuumStatement {
12107    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
12108        write!(
12109            f,
12110            "VACUUM{}{}{}{}{}",
12111            if self.full { " FULL" } else { "" },
12112            if self.sort_only { " SORT ONLY" } else { "" },
12113            if self.delete_only { " DELETE ONLY" } else { "" },
12114            if self.reindex { " REINDEX" } else { "" },
12115            if self.recluster { " RECLUSTER" } else { "" },
12116        )?;
12117        if let Some(table_name) = &self.table_name {
12118            write!(f, " {table_name}")?;
12119        }
12120        if let Some(threshold) = &self.threshold {
12121            write!(f, " TO {threshold} PERCENT")?;
12122        }
12123        if self.boost {
12124            write!(f, " BOOST")?;
12125        }
12126        Ok(())
12127    }
12128}
12129
12130/// Variants of the RESET statement
12131#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
12132#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
12133#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
12134pub enum Reset {
12135    /// Resets all session parameters to their default values.
12136    ALL,
12137
12138    /// Resets a specific session parameter to its default value.
12139    ConfigurationParameter(ObjectName),
12140}
12141
12142/// Resets a session parameter to its default value.
12143/// ```sql
12144/// RESET { ALL | <configuration_parameter> }
12145/// ```
12146#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
12147#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
12148#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
12149pub struct ResetStatement {
12150    /// The reset action to perform (either `ALL` or a specific configuration parameter).
12151    pub reset: Reset,
12152}
12153
12154/// Query optimizer hints are optionally supported comments after the
12155/// `SELECT`, `INSERT`, `UPDATE`, `REPLACE`, `MERGE`, and `DELETE` keywords in
12156/// the corresponding statements.
12157///
12158/// See [Select::optimizer_hints]
12159#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
12160#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
12161#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
12162pub struct OptimizerHint {
12163    /// An optional prefix between the comment marker and `+`.
12164    ///
12165    /// Standard optimizer hints like `/*+ ... */` have an empty prefix,
12166    /// while system-specific hints like `/*abc+ ... */` have `prefix = "abc"`.
12167    /// The prefix is any sequence of ASCII alphanumeric characters
12168    /// immediately before the `+` marker.
12169    pub prefix: String,
12170    /// the raw text of the optimizer hint without its markers
12171    pub text: String,
12172    /// the style of the comment which `text` was extracted from,
12173    /// e.g. `/*+...*/` or `--+...`
12174    ///
12175    /// Not all dialects support all styles, though.
12176    pub style: OptimizerHintStyle,
12177}
12178
12179/// The commentary style of an [optimizer hint](OptimizerHint)
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 enum OptimizerHintStyle {
12184    /// A hint corresponding to a single line comment,
12185    /// e.g. `--+ LEADING(v.e v.d t)`
12186    SingleLine {
12187        /// the comment prefix, e.g. `--`
12188        prefix: String,
12189    },
12190    /// A hint corresponding to a multi line comment,
12191    /// e.g. `/*+ LEADING(v.e v.d t) */`
12192    MultiLine,
12193}
12194
12195impl fmt::Display for OptimizerHint {
12196    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
12197        match &self.style {
12198            OptimizerHintStyle::SingleLine { prefix } => {
12199                f.write_str(prefix)?;
12200                f.write_str(&self.prefix)?;
12201                f.write_str("+")?;
12202                f.write_str(&self.text)
12203            }
12204            OptimizerHintStyle::MultiLine => {
12205                f.write_str("/*")?;
12206                f.write_str(&self.prefix)?;
12207                f.write_str("+")?;
12208                f.write_str(&self.text)?;
12209                f.write_str("*/")
12210            }
12211        }
12212    }
12213}
12214
12215impl fmt::Display for ResetStatement {
12216    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
12217        match &self.reset {
12218            Reset::ALL => write!(f, "RESET ALL"),
12219            Reset::ConfigurationParameter(param) => write!(f, "RESET {}", param),
12220        }
12221    }
12222}
12223
12224impl From<Set> for Statement {
12225    fn from(s: Set) -> Self {
12226        Self::Set(s)
12227    }
12228}
12229
12230impl From<Query> for Statement {
12231    fn from(q: Query) -> Self {
12232        Box::new(q).into()
12233    }
12234}
12235
12236impl From<Box<Query>> for Statement {
12237    fn from(q: Box<Query>) -> Self {
12238        Self::Query(q)
12239    }
12240}
12241
12242impl From<Insert> for Statement {
12243    fn from(i: Insert) -> Self {
12244        Self::Insert(i)
12245    }
12246}
12247
12248impl From<Update> for Statement {
12249    fn from(u: Update) -> Self {
12250        Self::Update(u)
12251    }
12252}
12253
12254impl From<CreateView> for Statement {
12255    fn from(cv: CreateView) -> Self {
12256        Self::CreateView(cv)
12257    }
12258}
12259
12260impl From<CreateRole> for Statement {
12261    fn from(cr: CreateRole) -> Self {
12262        Self::CreateRole(cr)
12263    }
12264}
12265
12266impl From<AlterTable> for Statement {
12267    fn from(at: AlterTable) -> Self {
12268        Self::AlterTable(at)
12269    }
12270}
12271
12272impl From<DropFunction> for Statement {
12273    fn from(df: DropFunction) -> Self {
12274        Self::DropFunction(df)
12275    }
12276}
12277
12278impl From<CreateExtension> for Statement {
12279    fn from(ce: CreateExtension) -> Self {
12280        Self::CreateExtension(ce)
12281    }
12282}
12283
12284impl From<CreateCollation> for Statement {
12285    fn from(c: CreateCollation) -> Self {
12286        Self::CreateCollation(c)
12287    }
12288}
12289
12290impl From<DropExtension> for Statement {
12291    fn from(de: DropExtension) -> Self {
12292        Self::DropExtension(de)
12293    }
12294}
12295
12296impl From<CaseStatement> for Statement {
12297    fn from(c: CaseStatement) -> Self {
12298        Self::Case(c)
12299    }
12300}
12301
12302impl From<IfStatement> for Statement {
12303    fn from(i: IfStatement) -> Self {
12304        Self::If(i)
12305    }
12306}
12307
12308impl From<WhileStatement> for Statement {
12309    fn from(w: WhileStatement) -> Self {
12310        Self::While(w)
12311    }
12312}
12313
12314impl From<RaiseStatement> for Statement {
12315    fn from(r: RaiseStatement) -> Self {
12316        Self::Raise(r)
12317    }
12318}
12319
12320impl From<ThrowStatement> for Statement {
12321    fn from(t: ThrowStatement) -> Self {
12322        Self::Throw(t)
12323    }
12324}
12325
12326impl From<Function> for Statement {
12327    fn from(f: Function) -> Self {
12328        Self::Call(f)
12329    }
12330}
12331
12332impl From<OpenStatement> for Statement {
12333    fn from(o: OpenStatement) -> Self {
12334        Self::Open(o)
12335    }
12336}
12337
12338impl From<Delete> for Statement {
12339    fn from(d: Delete) -> Self {
12340        Self::Delete(d)
12341    }
12342}
12343
12344impl From<CreateTable> for Statement {
12345    fn from(c: CreateTable) -> Self {
12346        Self::CreateTable(c)
12347    }
12348}
12349
12350impl From<CreateIndex> for Statement {
12351    fn from(c: CreateIndex) -> Self {
12352        Self::CreateIndex(c)
12353    }
12354}
12355
12356impl From<CreateServerStatement> for Statement {
12357    fn from(c: CreateServerStatement) -> Self {
12358        Self::CreateServer(c)
12359    }
12360}
12361
12362impl From<CreateConnector> for Statement {
12363    fn from(c: CreateConnector) -> Self {
12364        Self::CreateConnector(c)
12365    }
12366}
12367
12368impl From<CreateOperator> for Statement {
12369    fn from(c: CreateOperator) -> Self {
12370        Self::CreateOperator(c)
12371    }
12372}
12373
12374impl From<CreateOperatorFamily> for Statement {
12375    fn from(c: CreateOperatorFamily) -> Self {
12376        Self::CreateOperatorFamily(c)
12377    }
12378}
12379
12380impl From<CreateOperatorClass> for Statement {
12381    fn from(c: CreateOperatorClass) -> Self {
12382        Self::CreateOperatorClass(c)
12383    }
12384}
12385
12386impl From<AlterSchema> for Statement {
12387    fn from(a: AlterSchema) -> Self {
12388        Self::AlterSchema(a)
12389    }
12390}
12391
12392impl From<AlterFunction> for Statement {
12393    fn from(a: AlterFunction) -> Self {
12394        Self::AlterFunction(a)
12395    }
12396}
12397
12398impl From<AlterType> for Statement {
12399    fn from(a: AlterType) -> Self {
12400        Self::AlterType(a)
12401    }
12402}
12403
12404impl From<AlterCollation> for Statement {
12405    fn from(a: AlterCollation) -> Self {
12406        Self::AlterCollation(a)
12407    }
12408}
12409
12410impl From<AlterOperator> for Statement {
12411    fn from(a: AlterOperator) -> Self {
12412        Self::AlterOperator(a)
12413    }
12414}
12415
12416impl From<AlterOperatorFamily> for Statement {
12417    fn from(a: AlterOperatorFamily) -> Self {
12418        Self::AlterOperatorFamily(a)
12419    }
12420}
12421
12422impl From<AlterOperatorClass> for Statement {
12423    fn from(a: AlterOperatorClass) -> Self {
12424        Self::AlterOperatorClass(a)
12425    }
12426}
12427
12428impl From<Merge> for Statement {
12429    fn from(m: Merge) -> Self {
12430        Self::Merge(m)
12431    }
12432}
12433
12434impl From<AlterUser> for Statement {
12435    fn from(a: AlterUser) -> Self {
12436        Self::AlterUser(a)
12437    }
12438}
12439
12440impl From<DropDomain> for Statement {
12441    fn from(d: DropDomain) -> Self {
12442        Self::DropDomain(d)
12443    }
12444}
12445
12446impl From<ShowCharset> for Statement {
12447    fn from(s: ShowCharset) -> Self {
12448        Self::ShowCharset(s)
12449    }
12450}
12451
12452impl From<ShowObjects> for Statement {
12453    fn from(s: ShowObjects) -> Self {
12454        Self::ShowObjects(s)
12455    }
12456}
12457
12458impl From<Use> for Statement {
12459    fn from(u: Use) -> Self {
12460        Self::Use(u)
12461    }
12462}
12463
12464impl From<CreateFunction> for Statement {
12465    fn from(c: CreateFunction) -> Self {
12466        Self::CreateFunction(c)
12467    }
12468}
12469
12470impl From<CreateTrigger> for Statement {
12471    fn from(c: CreateTrigger) -> Self {
12472        Self::CreateTrigger(c)
12473    }
12474}
12475
12476impl From<DropTrigger> for Statement {
12477    fn from(d: DropTrigger) -> Self {
12478        Self::DropTrigger(d)
12479    }
12480}
12481
12482impl From<DropOperator> for Statement {
12483    fn from(d: DropOperator) -> Self {
12484        Self::DropOperator(d)
12485    }
12486}
12487
12488impl From<DropOperatorFamily> for Statement {
12489    fn from(d: DropOperatorFamily) -> Self {
12490        Self::DropOperatorFamily(d)
12491    }
12492}
12493
12494impl From<DropOperatorClass> for Statement {
12495    fn from(d: DropOperatorClass) -> Self {
12496        Self::DropOperatorClass(d)
12497    }
12498}
12499
12500impl From<DenyStatement> for Statement {
12501    fn from(d: DenyStatement) -> Self {
12502        Self::Deny(d)
12503    }
12504}
12505
12506impl From<CreateDomain> for Statement {
12507    fn from(c: CreateDomain) -> Self {
12508        Self::CreateDomain(c)
12509    }
12510}
12511
12512impl From<RenameTable> for Statement {
12513    fn from(r: RenameTable) -> Self {
12514        vec![r].into()
12515    }
12516}
12517
12518impl From<Vec<RenameTable>> for Statement {
12519    fn from(r: Vec<RenameTable>) -> Self {
12520        Self::RenameTable(r)
12521    }
12522}
12523
12524impl From<PrintStatement> for Statement {
12525    fn from(p: PrintStatement) -> Self {
12526        Self::Print(p)
12527    }
12528}
12529
12530impl From<ReturnStatement> for Statement {
12531    fn from(r: ReturnStatement) -> Self {
12532        Self::Return(r)
12533    }
12534}
12535
12536impl From<ExportData> for Statement {
12537    fn from(e: ExportData) -> Self {
12538        Self::ExportData(e)
12539    }
12540}
12541
12542impl From<CreateUser> for Statement {
12543    fn from(c: CreateUser) -> Self {
12544        Self::CreateUser(c)
12545    }
12546}
12547
12548impl From<VacuumStatement> for Statement {
12549    fn from(v: VacuumStatement) -> Self {
12550        Self::Vacuum(v)
12551    }
12552}
12553
12554impl From<ResetStatement> for Statement {
12555    fn from(r: ResetStatement) -> Self {
12556        Self::Reset(r)
12557    }
12558}
12559
12560#[cfg(test)]
12561mod tests {
12562    use crate::tokenizer::Location;
12563
12564    use super::*;
12565
12566    #[test]
12567    fn test_window_frame_default() {
12568        let window_frame = WindowFrame::default();
12569        assert_eq!(WindowFrameBound::Preceding(None), window_frame.start_bound);
12570    }
12571
12572    #[test]
12573    fn test_grouping_sets_display() {
12574        // a and b in different group
12575        let grouping_sets = Expr::GroupingSets(vec![
12576            vec![Expr::Identifier(Ident::new("a"))],
12577            vec![Expr::Identifier(Ident::new("b"))],
12578        ]);
12579        assert_eq!("GROUPING SETS ((a), (b))", format!("{grouping_sets}"));
12580
12581        // a and b in the same group
12582        let grouping_sets = Expr::GroupingSets(vec![vec![
12583            Expr::Identifier(Ident::new("a")),
12584            Expr::Identifier(Ident::new("b")),
12585        ]]);
12586        assert_eq!("GROUPING SETS ((a, b))", format!("{grouping_sets}"));
12587
12588        // (a, b) and (c, d) in different group
12589        let grouping_sets = Expr::GroupingSets(vec![
12590            vec![
12591                Expr::Identifier(Ident::new("a")),
12592                Expr::Identifier(Ident::new("b")),
12593            ],
12594            vec![
12595                Expr::Identifier(Ident::new("c")),
12596                Expr::Identifier(Ident::new("d")),
12597            ],
12598        ]);
12599        assert_eq!("GROUPING SETS ((a, b), (c, d))", format!("{grouping_sets}"));
12600    }
12601
12602    #[test]
12603    fn test_rollup_display() {
12604        let rollup = Expr::Rollup(vec![vec![Expr::Identifier(Ident::new("a"))]]);
12605        assert_eq!("ROLLUP (a)", format!("{rollup}"));
12606
12607        let rollup = Expr::Rollup(vec![vec![
12608            Expr::Identifier(Ident::new("a")),
12609            Expr::Identifier(Ident::new("b")),
12610        ]]);
12611        assert_eq!("ROLLUP ((a, b))", format!("{rollup}"));
12612
12613        let rollup = Expr::Rollup(vec![
12614            vec![Expr::Identifier(Ident::new("a"))],
12615            vec![Expr::Identifier(Ident::new("b"))],
12616        ]);
12617        assert_eq!("ROLLUP (a, b)", format!("{rollup}"));
12618
12619        let rollup = Expr::Rollup(vec![
12620            vec![Expr::Identifier(Ident::new("a"))],
12621            vec![
12622                Expr::Identifier(Ident::new("b")),
12623                Expr::Identifier(Ident::new("c")),
12624            ],
12625            vec![Expr::Identifier(Ident::new("d"))],
12626        ]);
12627        assert_eq!("ROLLUP (a, (b, c), d)", format!("{rollup}"));
12628    }
12629
12630    #[test]
12631    fn test_cube_display() {
12632        let cube = Expr::Cube(vec![vec![Expr::Identifier(Ident::new("a"))]]);
12633        assert_eq!("CUBE (a)", format!("{cube}"));
12634
12635        let cube = Expr::Cube(vec![vec![
12636            Expr::Identifier(Ident::new("a")),
12637            Expr::Identifier(Ident::new("b")),
12638        ]]);
12639        assert_eq!("CUBE ((a, b))", format!("{cube}"));
12640
12641        let cube = Expr::Cube(vec![
12642            vec![Expr::Identifier(Ident::new("a"))],
12643            vec![Expr::Identifier(Ident::new("b"))],
12644        ]);
12645        assert_eq!("CUBE (a, b)", format!("{cube}"));
12646
12647        let cube = Expr::Cube(vec![
12648            vec![Expr::Identifier(Ident::new("a"))],
12649            vec![
12650                Expr::Identifier(Ident::new("b")),
12651                Expr::Identifier(Ident::new("c")),
12652            ],
12653            vec![Expr::Identifier(Ident::new("d"))],
12654        ]);
12655        assert_eq!("CUBE (a, (b, c), d)", format!("{cube}"));
12656    }
12657
12658    #[test]
12659    fn test_interval_display() {
12660        let interval = Expr::Interval(Interval {
12661            value: Box::new(Expr::Value(
12662                Value::SingleQuotedString(String::from("123:45.67")).with_empty_span(),
12663            )),
12664            leading_field: Some(DateTimeField::Minute),
12665            leading_precision: Some(10),
12666            last_field: Some(DateTimeField::Second),
12667            fractional_seconds_precision: Some(9),
12668        });
12669        assert_eq!(
12670            "INTERVAL '123:45.67' MINUTE (10) TO SECOND (9)",
12671            format!("{interval}"),
12672        );
12673
12674        let interval = Expr::Interval(Interval {
12675            value: Box::new(Expr::Value(
12676                Value::SingleQuotedString(String::from("5")).with_empty_span(),
12677            )),
12678            leading_field: Some(DateTimeField::Second),
12679            leading_precision: Some(1),
12680            last_field: None,
12681            fractional_seconds_precision: Some(3),
12682        });
12683        assert_eq!("INTERVAL '5' SECOND (1, 3)", format!("{interval}"));
12684    }
12685
12686    #[test]
12687    fn test_one_or_many_with_parens_deref() {
12688        use core::ops::Index;
12689
12690        let one = OneOrManyWithParens::One("a");
12691
12692        assert_eq!(one.deref(), &["a"]);
12693        assert_eq!(<OneOrManyWithParens<_> as Deref>::deref(&one), &["a"]);
12694
12695        assert_eq!(one[0], "a");
12696        assert_eq!(one.index(0), &"a");
12697        assert_eq!(
12698            <<OneOrManyWithParens<_> as Deref>::Target as Index<usize>>::index(&one, 0),
12699            &"a"
12700        );
12701
12702        assert_eq!(one.len(), 1);
12703        assert_eq!(<OneOrManyWithParens<_> as Deref>::Target::len(&one), 1);
12704
12705        let many1 = OneOrManyWithParens::Many(vec!["b"]);
12706
12707        assert_eq!(many1.deref(), &["b"]);
12708        assert_eq!(<OneOrManyWithParens<_> as Deref>::deref(&many1), &["b"]);
12709
12710        assert_eq!(many1[0], "b");
12711        assert_eq!(many1.index(0), &"b");
12712        assert_eq!(
12713            <<OneOrManyWithParens<_> as Deref>::Target as Index<usize>>::index(&many1, 0),
12714            &"b"
12715        );
12716
12717        assert_eq!(many1.len(), 1);
12718        assert_eq!(<OneOrManyWithParens<_> as Deref>::Target::len(&many1), 1);
12719
12720        let many2 = OneOrManyWithParens::Many(vec!["c", "d"]);
12721
12722        assert_eq!(many2.deref(), &["c", "d"]);
12723        assert_eq!(
12724            <OneOrManyWithParens<_> as Deref>::deref(&many2),
12725            &["c", "d"]
12726        );
12727
12728        assert_eq!(many2[0], "c");
12729        assert_eq!(many2.index(0), &"c");
12730        assert_eq!(
12731            <<OneOrManyWithParens<_> as Deref>::Target as Index<usize>>::index(&many2, 0),
12732            &"c"
12733        );
12734
12735        assert_eq!(many2[1], "d");
12736        assert_eq!(many2.index(1), &"d");
12737        assert_eq!(
12738            <<OneOrManyWithParens<_> as Deref>::Target as Index<usize>>::index(&many2, 1),
12739            &"d"
12740        );
12741
12742        assert_eq!(many2.len(), 2);
12743        assert_eq!(<OneOrManyWithParens<_> as Deref>::Target::len(&many2), 2);
12744    }
12745
12746    #[test]
12747    fn test_one_or_many_with_parens_as_ref() {
12748        let one = OneOrManyWithParens::One("a");
12749
12750        assert_eq!(one.as_ref(), &["a"]);
12751        assert_eq!(<OneOrManyWithParens<_> as AsRef<_>>::as_ref(&one), &["a"]);
12752
12753        let many1 = OneOrManyWithParens::Many(vec!["b"]);
12754
12755        assert_eq!(many1.as_ref(), &["b"]);
12756        assert_eq!(<OneOrManyWithParens<_> as AsRef<_>>::as_ref(&many1), &["b"]);
12757
12758        let many2 = OneOrManyWithParens::Many(vec!["c", "d"]);
12759
12760        assert_eq!(many2.as_ref(), &["c", "d"]);
12761        assert_eq!(
12762            <OneOrManyWithParens<_> as AsRef<_>>::as_ref(&many2),
12763            &["c", "d"]
12764        );
12765    }
12766
12767    #[test]
12768    fn test_one_or_many_with_parens_ref_into_iter() {
12769        let one = OneOrManyWithParens::One("a");
12770
12771        assert_eq!(Vec::from_iter(&one), vec![&"a"]);
12772
12773        let many1 = OneOrManyWithParens::Many(vec!["b"]);
12774
12775        assert_eq!(Vec::from_iter(&many1), vec![&"b"]);
12776
12777        let many2 = OneOrManyWithParens::Many(vec!["c", "d"]);
12778
12779        assert_eq!(Vec::from_iter(&many2), vec![&"c", &"d"]);
12780    }
12781
12782    #[test]
12783    fn test_one_or_many_with_parens_value_into_iter() {
12784        use core::iter::once;
12785
12786        //tests that our iterator implemented methods behaves exactly as it's inner iterator, at every step up to n calls to next/next_back
12787        fn test_steps<I>(ours: OneOrManyWithParens<usize>, inner: I, n: usize)
12788        where
12789            I: IntoIterator<Item = usize, IntoIter: DoubleEndedIterator + Clone> + Clone,
12790        {
12791            fn checks<I>(ours: OneOrManyWithParensIntoIter<usize>, inner: I)
12792            where
12793                I: Iterator<Item = usize> + Clone + DoubleEndedIterator,
12794            {
12795                assert_eq!(ours.size_hint(), inner.size_hint());
12796                assert_eq!(ours.clone().count(), inner.clone().count());
12797
12798                assert_eq!(
12799                    ours.clone().fold(1, |a, v| a + v),
12800                    inner.clone().fold(1, |a, v| a + v)
12801                );
12802
12803                assert_eq!(Vec::from_iter(ours.clone()), Vec::from_iter(inner.clone()));
12804                assert_eq!(
12805                    Vec::from_iter(ours.clone().rev()),
12806                    Vec::from_iter(inner.clone().rev())
12807                );
12808            }
12809
12810            let mut ours_next = ours.clone().into_iter();
12811            let mut inner_next = inner.clone().into_iter();
12812
12813            for _ in 0..n {
12814                checks(ours_next.clone(), inner_next.clone());
12815
12816                assert_eq!(ours_next.next(), inner_next.next());
12817            }
12818
12819            let mut ours_next_back = ours.clone().into_iter();
12820            let mut inner_next_back = inner.clone().into_iter();
12821
12822            for _ in 0..n {
12823                checks(ours_next_back.clone(), inner_next_back.clone());
12824
12825                assert_eq!(ours_next_back.next_back(), inner_next_back.next_back());
12826            }
12827
12828            let mut ours_mixed = ours.clone().into_iter();
12829            let mut inner_mixed = inner.clone().into_iter();
12830
12831            for i in 0..n {
12832                checks(ours_mixed.clone(), inner_mixed.clone());
12833
12834                if i % 2 == 0 {
12835                    assert_eq!(ours_mixed.next_back(), inner_mixed.next_back());
12836                } else {
12837                    assert_eq!(ours_mixed.next(), inner_mixed.next());
12838                }
12839            }
12840
12841            let mut ours_mixed2 = ours.into_iter();
12842            let mut inner_mixed2 = inner.into_iter();
12843
12844            for i in 0..n {
12845                checks(ours_mixed2.clone(), inner_mixed2.clone());
12846
12847                if i % 2 == 0 {
12848                    assert_eq!(ours_mixed2.next(), inner_mixed2.next());
12849                } else {
12850                    assert_eq!(ours_mixed2.next_back(), inner_mixed2.next_back());
12851                }
12852            }
12853        }
12854
12855        test_steps(OneOrManyWithParens::One(1), once(1), 3);
12856        test_steps(OneOrManyWithParens::Many(vec![2]), vec![2], 3);
12857        test_steps(OneOrManyWithParens::Many(vec![3, 4]), vec![3, 4], 4);
12858    }
12859
12860    // Tests that the position in the code of an `Ident` does not affect its
12861    // ordering.
12862    #[test]
12863    fn test_ident_ord() {
12864        let mut a = Ident::with_span(Span::new(Location::new(1, 1), Location::new(1, 1)), "a");
12865        let mut b = Ident::with_span(Span::new(Location::new(2, 2), Location::new(2, 2)), "b");
12866
12867        assert!(a < b);
12868        std::mem::swap(&mut a.span, &mut b.span);
12869        assert!(a < b);
12870    }
12871}