Skip to main content

sqlparser/ast/
mod.rs

1// Licensed to the Apache Software Foundation (ASF) under one
2// or more contributor license agreements.  See the NOTICE file
3// distributed with this work for additional information
4// regarding copyright ownership.  The ASF licenses this file
5// to you under the Apache License, Version 2.0 (the
6// "License"); you may not use this file except in compliance
7// with the License.  You may obtain a copy of the License at
8//
9//   http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing,
12// software distributed under the License is distributed on an
13// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14// KIND, either express or implied.  See the License for the
15// specific language governing permissions and limitations
16// under the License.
17
18//! SQL Abstract Syntax Tree (AST) types
19#[cfg(not(feature = "std"))]
20use alloc::{
21    boxed::Box,
22    format,
23    string::{String, ToString},
24    vec,
25    vec::Vec,
26};
27use helpers::{
28    attached_token::AttachedToken,
29    stmt_data_loading::{FileStagingCommand, StageLoadSelectItemKind},
30};
31
32use core::cmp::Ordering;
33use core::ops::Deref;
34use core::{
35    fmt::{self, Display},
36    hash,
37};
38
39#[cfg(feature = "serde")]
40use serde::{Deserialize, Serialize};
41
42#[cfg(feature = "visitor")]
43use sqlparser_derive::{Visit, VisitMut};
44
45use crate::{
46    display_utils::SpaceOrNewline,
47    tokenizer::{Span, Token},
48};
49use crate::{
50    display_utils::{Indent, NewLine},
51    keywords::Keyword,
52};
53
54pub use self::data_type::{
55    ArrayElemTypeDef, BinaryLength, CharLengthUnits, CharacterLength, DataType, EnumMember,
56    ExactNumberInfo, IntervalFields, StructBracketKind, TimezoneInfo,
57};
58pub use self::dcl::{
59    AlterRoleOperation, CreateRole, Grant, ResetConfig, Revoke, RoleOption, SecondaryRoles,
60    SetConfigValue, Use,
61};
62pub use self::ddl::{
63    AccessMethodType, AggregateModifyKind, Alignment, AlterCollation, AlterCollationOperation,
64    AlterColumnOperation, AlterConnectorOwner, AlterDomain, AlterDomainOperation, AlterExtension,
65    AlterExtensionOperation, AlterFunction, AlterFunctionAction, AlterFunctionKind,
66    AlterFunctionOperation, AlterIndexOperation, AlterOperator, AlterOperatorClass,
67    AlterOperatorClassOperation, AlterOperatorFamily, AlterOperatorFamilyOperation,
68    AlterOperatorOperation, AlterPolicy, AlterPolicyOperation, AlterSchema, AlterSchemaOperation,
69    AlterTable, AlterTableAlgorithm, AlterTableLock, AlterTableOperation, AlterTableType,
70    AlterTrigger, AlterTriggerOperation, AlterType, AlterTypeAddValue, AlterTypeAddValuePosition,
71    AlterTypeOperation, AlterTypeRename, AlterTypeRenameValue, CastContext, CastFunctionKind,
72    ClusteredBy, ColumnDef, ColumnOption, ColumnOptionDef, ColumnOptions, ColumnPolicy,
73    ColumnPolicyProperty, ConstraintCharacteristics, CreateAccessMethod, CreateAggregate,
74    CreateAggregateOption, CreateCast, CreateCollation, CreateCollationDefinition, CreateConnector,
75    CreateConversion, CreateDomain, CreateEventTrigger, CreateExtension, CreateForeignDataWrapper,
76    CreateForeignTable, CreateFunction, CreateIndex, CreateLanguage, CreateOperator,
77    CreateOperatorClass, CreateOperatorFamily, CreatePolicy, CreatePolicyCommand, CreatePolicyType,
78    CreatePublication, CreateRule, CreateStatistics, CreateSubscription, CreateTable,
79    CreateTablespace, CreateTextSearchConfiguration, CreateTextSearchDictionary,
80    CreateTextSearchParser, CreateTextSearchTemplate, CreateTransform, CreateTrigger,
81    CreateUserMapping, CreateView, Deduplicate, DeferrableInitial, DistStyle, DropBehavior,
82    DropExtension, DropFunction, DropOperator, DropOperatorClass, DropOperatorFamily,
83    DropOperatorSignature, DropPolicy, DropTrigger, EventTriggerEvent, FdwRoutineClause, ForValues,
84    FunctionReturnType, GeneratedAs, GeneratedExpressionMode, IdentityParameters, IdentityProperty,
85    IdentityPropertyFormatKind, IdentityPropertyKind, IdentityPropertyOrder, IndexColumn,
86    IndexOption, IndexType, KeyOrIndexDisplay, Msck, NullsDistinctOption, OperatorArgTypes,
87    OperatorClassItem, OperatorFamilyDropItem, OperatorFamilyItem, OperatorOption, OperatorPurpose,
88    Owner, Partition, PartitionBoundValue, ProcedureParam, PublicationTarget, ReferentialAction,
89    RenameTableNameKind, ReplicaIdentity, RuleAction, RuleEvent, SecurityLabel,
90    SecurityLabelObjectKind, StatisticsKind, TagsColumnOption, TransformElement, TriggerObjectKind,
91    Truncate, UserDefinedTypeCompositeAttributeDef, UserDefinedTypeInternalLength,
92    UserDefinedTypeRangeOption, UserDefinedTypeRepresentation, UserDefinedTypeSqlDefinitionOption,
93    UserDefinedTypeStorage, UserMappingUser, ViewColumnDef
94};
95pub use self::dml::{
96    Delete, Insert, Merge, MergeAction, MergeClause, MergeClauseKind, MergeInsertExpr,
97    MergeInsertKind, MergeUpdateExpr, MultiTableInsertIntoClause, MultiTableInsertType,
98    MultiTableInsertValue, MultiTableInsertValues, MultiTableInsertWhenClause, OutputClause,
99    Update,
100};
101pub use self::operator::{BinaryOperator, UnaryOperator};
102pub use self::query::{
103    AfterMatchSkip, ConnectByKind, Cte, CteAsMaterialized, Distinct, EmptyMatchesMode,
104    ExceptSelectItem, ExcludeSelectItem, ExprWithAlias, ExprWithAliasAndOrderBy, Fetch, ForClause,
105    ForJson, ForXml, FormatClause, GroupByExpr, GroupByWithModifier, IdentWithAlias,
106    IlikeSelectItem, InputFormatClause, Interpolate, InterpolateExpr, Join, JoinConstraint,
107    JoinOperator, JsonTableColumn, JsonTableColumnErrorHandling, JsonTableNamedColumn,
108    JsonTableNestedColumn, LateralView, LimitClause, LockClause, LockType, MatchRecognizePattern,
109    MatchRecognizeSymbol, Measure, NamedWindowDefinition, NamedWindowExpr, NonBlock, Offset,
110    OffsetRows, OpenJsonTableColumn, OrderBy, OrderByExpr, OrderByKind, OrderByOptions,
111    PipeOperator, PivotValueSource, ProjectionSelect, Query, RenameSelectItem,
112    RepetitionQuantifier, ReplaceSelectElement, ReplaceSelectItem, RowsPerMatch, Select,
113    SelectFlavor, SelectInto, SelectItem, SelectItemQualifiedWildcardKind, SelectModifiers,
114    SetExpr, SetOperator, SetQuantifier, Setting, SymbolDefinition, Table, TableAlias,
115    TableAliasColumnDef, TableFactor, TableFunctionArgs, TableIndexHintForClause,
116    TableIndexHintType, TableIndexHints, TableIndexType, TableSample, TableSampleBucket,
117    TableSampleKind, TableSampleMethod, TableSampleModifier, TableSampleQuantity, TableSampleSeed,
118    TableSampleSeedModifier, TableSampleUnit, TableVersion, TableWithJoins, Top, TopQuantity,
119    UpdateTableFromKind, ValueTableMode, Values, WildcardAdditionalOptions, With, WithFill,
120    XmlNamespaceDefinition, XmlPassingArgument, XmlPassingClause, XmlTableColumn,
121    XmlTableColumnOption,
122};
123
124pub use self::trigger::{
125    TriggerEvent, TriggerExecBody, TriggerExecBodyType, TriggerObject, TriggerPeriod,
126    TriggerReferencing, TriggerReferencingType,
127};
128
129pub use self::value::{
130    escape_double_quote_string, escape_quoted_string, DateTimeField, DollarQuotedString,
131    NormalizationForm, QuoteDelimitedString, TrimWhereField, Value, ValueWithSpan,
132};
133
134use crate::ast::helpers::key_value_options::KeyValueOptions;
135use crate::ast::helpers::stmt_data_loading::StageParamsObject;
136
137#[cfg(feature = "visitor")]
138pub use visitor::*;
139
140pub use self::data_type::GeometricTypeKind;
141
142mod data_type;
143mod dcl;
144mod ddl;
145mod dml;
146/// Helper modules for building and manipulating AST nodes.
147pub mod helpers;
148pub mod table_constraints;
149pub use table_constraints::{
150    CheckConstraint, ConstraintUsingIndex, ExclusionConstraint, ExclusionElement,
151    ForeignKeyConstraint, FullTextOrSpatialConstraint, IndexConstraint, PrimaryKeyConstraint,
152    TableConstraint, UniqueConstraint,
153};
154mod operator;
155mod query;
156mod spans;
157pub use spans::Spanned;
158
159pub mod comments;
160mod trigger;
161mod value;
162
163#[cfg(feature = "visitor")]
164mod visitor;
165
166/// Helper used to format a slice using a separator string (e.g., `", "`).
167pub struct DisplaySeparated<'a, T>
168where
169    T: fmt::Display,
170{
171    slice: &'a [T],
172    sep: &'static str,
173}
174
175impl<T> fmt::Display for DisplaySeparated<'_, T>
176where
177    T: fmt::Display,
178{
179    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
180        let mut delim = "";
181        for t in self.slice {
182            f.write_str(delim)?;
183            delim = self.sep;
184            t.fmt(f)?;
185        }
186        Ok(())
187    }
188}
189
190pub(crate) fn display_separated<'a, T>(slice: &'a [T], sep: &'static str) -> DisplaySeparated<'a, T>
191where
192    T: fmt::Display,
193{
194    DisplaySeparated { slice, sep }
195}
196
197pub(crate) fn display_comma_separated<T>(slice: &[T]) -> DisplaySeparated<'_, T>
198where
199    T: fmt::Display,
200{
201    DisplaySeparated { slice, sep: ", " }
202}
203
204/// Writes the given statements to the formatter, each ending with
205/// a semicolon and space separated.
206fn format_statement_list(f: &mut fmt::Formatter, statements: &[Statement]) -> fmt::Result {
207    write!(f, "{}", display_separated(statements, "; "))?;
208    // We manually insert semicolon for the last statement,
209    // since display_separated doesn't handle that case.
210    write!(f, ";")
211}
212
213/// An identifier, decomposed into its value or character data and the quote style.
214#[derive(Debug, Clone)]
215#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
216#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
217pub struct Ident {
218    /// The value of the identifier without quotes.
219    pub value: String,
220    /// The starting quote if any. Valid quote characters are the single quote,
221    /// double quote, backtick, and opening square bracket.
222    pub quote_style: Option<char>,
223    /// The span of the identifier in the original SQL string.
224    pub span: Span,
225}
226
227impl PartialEq for Ident {
228    fn eq(&self, other: &Self) -> bool {
229        let Ident {
230            value,
231            quote_style,
232            // exhaustiveness check; we ignore spans in comparisons
233            span: _,
234        } = self;
235
236        value == &other.value && quote_style == &other.quote_style
237    }
238}
239
240impl core::hash::Hash for Ident {
241    fn hash<H: hash::Hasher>(&self, state: &mut H) {
242        let Ident {
243            value,
244            quote_style,
245            // exhaustiveness check; we ignore spans in hashes
246            span: _,
247        } = self;
248
249        value.hash(state);
250        quote_style.hash(state);
251    }
252}
253
254impl Eq for Ident {}
255
256impl PartialOrd for Ident {
257    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
258        Some(self.cmp(other))
259    }
260}
261
262impl Ord for Ident {
263    fn cmp(&self, other: &Self) -> Ordering {
264        let Ident {
265            value,
266            quote_style,
267            // exhaustiveness check; we ignore spans in ordering
268            span: _,
269        } = self;
270
271        let Ident {
272            value: other_value,
273            quote_style: other_quote_style,
274            // exhaustiveness check; we ignore spans in ordering
275            span: _,
276        } = other;
277
278        // First compare by value, then by quote_style
279        value
280            .cmp(other_value)
281            .then_with(|| quote_style.cmp(other_quote_style))
282    }
283}
284
285impl Ident {
286    /// Create a new identifier with the given value and no quotes and an empty span.
287    pub fn new<S>(value: S) -> Self
288    where
289        S: Into<String>,
290    {
291        Ident {
292            value: value.into(),
293            quote_style: None,
294            span: Span::empty(),
295        }
296    }
297
298    /// Create a new quoted identifier with the given quote and value. This function
299    /// panics if the given quote is not a valid quote character.
300    pub fn with_quote<S>(quote: char, value: S) -> Self
301    where
302        S: Into<String>,
303    {
304        assert!(quote == '\'' || quote == '"' || quote == '`' || quote == '[');
305        Ident {
306            value: value.into(),
307            quote_style: Some(quote),
308            span: Span::empty(),
309        }
310    }
311
312    /// Create an `Ident` with the given `span` and `value` (unquoted).
313    pub fn with_span<S>(span: Span, value: S) -> Self
314    where
315        S: Into<String>,
316    {
317        Ident {
318            value: value.into(),
319            quote_style: None,
320            span,
321        }
322    }
323
324    /// Create a quoted `Ident` with the given `quote` and `span`.
325    pub fn with_quote_and_span<S>(quote: char, span: Span, value: S) -> Self
326    where
327        S: Into<String>,
328    {
329        assert!(quote == '\'' || quote == '"' || quote == '`' || quote == '[');
330        Ident {
331            value: value.into(),
332            quote_style: Some(quote),
333            span,
334        }
335    }
336}
337
338impl From<&str> for Ident {
339    fn from(value: &str) -> Self {
340        Ident {
341            value: value.to_string(),
342            quote_style: None,
343            span: Span::empty(),
344        }
345    }
346}
347
348impl fmt::Display for Ident {
349    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
350        match self.quote_style {
351            Some(q) if q == '"' || q == '\'' || q == '`' => {
352                let escaped = value::escape_quoted_string(&self.value, q);
353                write!(f, "{q}{escaped}{q}")
354            }
355            Some('[') => write!(f, "[{}]", self.value),
356            None => f.write_str(&self.value),
357            _ => panic!("unexpected quote style"),
358        }
359    }
360}
361
362/// A name of a table, view, custom type, etc., possibly multi-part, i.e. db.schema.obj
363#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
364#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
365#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
366pub struct ObjectName(pub Vec<ObjectNamePart>);
367
368impl From<Vec<Ident>> for ObjectName {
369    fn from(idents: Vec<Ident>) -> Self {
370        ObjectName(idents.into_iter().map(ObjectNamePart::Identifier).collect())
371    }
372}
373
374impl From<Ident> for ObjectName {
375    fn from(ident: Ident) -> Self {
376        ObjectName(vec![ObjectNamePart::Identifier(ident)])
377    }
378}
379
380impl fmt::Display for ObjectName {
381    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
382        write!(f, "{}", display_separated(&self.0, "."))
383    }
384}
385
386/// A single part of an ObjectName
387#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
388#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
389#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
390pub enum ObjectNamePart {
391    /// A single identifier part, e.g. `schema` or `table`.
392    Identifier(Ident),
393    /// A function that returns an identifier (dialect-specific).
394    Function(ObjectNamePartFunction),
395}
396
397impl ObjectNamePart {
398    /// Return the identifier if this is an `Identifier` variant.
399    pub fn as_ident(&self) -> Option<&Ident> {
400        match self {
401            ObjectNamePart::Identifier(ident) => Some(ident),
402            ObjectNamePart::Function(_) => None,
403        }
404    }
405}
406
407impl fmt::Display for ObjectNamePart {
408    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
409        match self {
410            ObjectNamePart::Identifier(ident) => write!(f, "{ident}"),
411            ObjectNamePart::Function(func) => write!(f, "{func}"),
412        }
413    }
414}
415
416/// An object name part that consists of a function that dynamically
417/// constructs identifiers.
418///
419/// - [Snowflake](https://docs.snowflake.com/en/sql-reference/identifier-literal)
420#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
421#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
422#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
423pub struct ObjectNamePartFunction {
424    /// The function name that produces the object name part.
425    pub name: Ident,
426    /// Function arguments used to compute the identifier.
427    pub args: Vec<FunctionArg>,
428}
429
430impl fmt::Display for ObjectNamePartFunction {
431    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
432        write!(f, "{}(", self.name)?;
433        write!(f, "{})", display_comma_separated(&self.args))
434    }
435}
436
437/// Represents an Array Expression, either
438/// `ARRAY[..]`, or `[..]`
439#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
440#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
441#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
442pub struct Array {
443    /// The list of expressions between brackets
444    pub elem: Vec<Expr>,
445
446    /// `true` for  `ARRAY[..]`, `false` for `[..]`
447    pub named: bool,
448}
449
450impl fmt::Display for Array {
451    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
452        write!(
453            f,
454            "{}[{}]",
455            if self.named { "ARRAY" } else { "" },
456            display_comma_separated(&self.elem)
457        )
458    }
459}
460
461/// Represents an INTERVAL expression, roughly in the following format:
462/// `INTERVAL '<value>' [ <leading_field> [ (<leading_precision>) ] ]
463/// [ TO <last_field> [ (<fractional_seconds_precision>) ] ]`,
464/// e.g. `INTERVAL '123:45.67' MINUTE(3) TO SECOND(2)`.
465///
466/// The parser does not validate the `<value>`, nor does it ensure
467/// that the `<leading_field>` units >= the units in `<last_field>`,
468/// so the user will have to reject intervals like `HOUR TO YEAR`.
469#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
470#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
471#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
472pub struct Interval {
473    /// The interval value expression (commonly a string literal).
474    pub value: Box<Expr>,
475    /// Optional leading time unit (e.g., `HOUR`, `MINUTE`).
476    pub leading_field: Option<DateTimeField>,
477    /// Optional leading precision for the leading field.
478    pub leading_precision: Option<u64>,
479    /// Optional trailing time unit for a range (e.g., `SECOND`).
480    pub last_field: Option<DateTimeField>,
481    /// The fractional seconds precision, when specified.
482    ///
483    /// See SQL `SECOND(n)` or `SECOND(m, n)` forms.
484    pub fractional_seconds_precision: Option<u64>,
485}
486
487impl fmt::Display for Interval {
488    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
489        let value = self.value.as_ref();
490        match (
491            &self.leading_field,
492            self.leading_precision,
493            self.fractional_seconds_precision,
494        ) {
495            (
496                Some(DateTimeField::Second),
497                Some(leading_precision),
498                Some(fractional_seconds_precision),
499            ) => {
500                // When the leading field is SECOND, the parser guarantees that
501                // the last field is None.
502                assert!(self.last_field.is_none());
503                write!(
504                    f,
505                    "INTERVAL {value} SECOND ({leading_precision}, {fractional_seconds_precision})"
506                )
507            }
508            _ => {
509                write!(f, "INTERVAL {value}")?;
510                if let Some(leading_field) = &self.leading_field {
511                    write!(f, " {leading_field}")?;
512                }
513                if let Some(leading_precision) = self.leading_precision {
514                    write!(f, " ({leading_precision})")?;
515                }
516                if let Some(last_field) = &self.last_field {
517                    write!(f, " TO {last_field}")?;
518                }
519                if let Some(fractional_seconds_precision) = self.fractional_seconds_precision {
520                    write!(f, " ({fractional_seconds_precision})")?;
521                }
522                Ok(())
523            }
524        }
525    }
526}
527
528/// A field definition within a struct
529///
530/// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-types#struct_type
531#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
532#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
533#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
534pub struct StructField {
535    /// Optional name of the struct field.
536    pub field_name: Option<Ident>,
537    /// The field data type.
538    pub field_type: DataType,
539    /// Struct field options (e.g., `OPTIONS(...)` on BigQuery).
540    /// See [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#column_name_and_column_schema)
541    pub options: Option<Vec<SqlOption>>,
542}
543
544impl fmt::Display for StructField {
545    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
546        if let Some(name) = &self.field_name {
547            write!(f, "{name} {}", self.field_type)?;
548        } else {
549            write!(f, "{}", self.field_type)?;
550        }
551        if let Some(options) = &self.options {
552            write!(f, " OPTIONS({})", display_separated(options, ", "))
553        } else {
554            Ok(())
555        }
556    }
557}
558
559/// A field definition within a union
560///
561/// [DuckDB]: https://duckdb.org/docs/sql/data_types/union.html
562#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
563#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
564#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
565pub struct UnionField {
566    /// Name of the union field.
567    pub field_name: Ident,
568    /// Type of the union field.
569    pub field_type: DataType,
570}
571
572impl fmt::Display for UnionField {
573    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
574        write!(f, "{} {}", self.field_name, self.field_type)
575    }
576}
577
578/// A dictionary field within a dictionary.
579///
580/// [DuckDB]: https://duckdb.org/docs/sql/data_types/struct#creating-structs
581#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
582#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
583#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
584pub struct DictionaryField {
585    /// Dictionary key identifier.
586    pub key: Ident,
587    /// Value expression for the dictionary entry.
588    pub value: Box<Expr>,
589}
590
591impl fmt::Display for DictionaryField {
592    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
593        write!(f, "{}: {}", self.key, self.value)
594    }
595}
596
597/// Represents a Map expression.
598#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
599#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
600#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
601pub struct Map {
602    /// Entries of the map as key/value pairs.
603    pub entries: Vec<MapEntry>,
604}
605
606impl Display for Map {
607    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
608        write!(f, "MAP {{{}}}", display_comma_separated(&self.entries))
609    }
610}
611
612/// A map field within a map.
613///
614/// [DuckDB]: https://duckdb.org/docs/sql/data_types/map.html#creating-maps
615#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
616#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
617#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
618pub struct MapEntry {
619    /// Key expression of the map entry.
620    pub key: Box<Expr>,
621    /// Value expression of the map entry.
622    pub value: Box<Expr>,
623}
624
625impl fmt::Display for MapEntry {
626    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
627        write!(f, "{}: {}", self.key, self.value)
628    }
629}
630
631/// Options for `CAST` / `TRY_CAST`
632/// BigQuery: <https://cloud.google.com/bigquery/docs/reference/standard-sql/format-elements#formatting_syntax>
633#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
634#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
635#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
636pub enum CastFormat {
637    /// A simple cast format specified by a `Value`.
638    Value(ValueWithSpan),
639    /// A cast format with an explicit time zone: `(format, timezone)`.
640    ValueAtTimeZone(ValueWithSpan, ValueWithSpan),
641}
642
643/// An element of a JSON path.
644#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
645#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
646#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
647pub enum JsonPathElem {
648    /// Accesses an object field using dot notation, e.g. `obj:foo.bar.baz`.
649    ///
650    /// See <https://docs.snowflake.com/en/user-guide/querying-semistructured#dot-notation>.
651    Dot {
652        /// The object key text (without quotes).
653        key: String,
654        /// `true` when the key was quoted in the source.
655        quoted: bool,
656    },
657    /// Accesses an object field or array element using bracket notation,
658    /// e.g. `obj['foo']`.
659    ///
660    /// See <https://docs.snowflake.com/en/user-guide/querying-semistructured#bracket-notation>.
661    Bracket {
662        /// The expression used as the bracket key (string or numeric expression).
663        key: Expr,
664    },
665    /// Access an object field using colon bracket notation
666    /// e.g. `obj:['foo']`
667    ///
668    /// See <https://docs.databricks.com/en/sql/language-manual/functions/colonsign.html>
669    ColonBracket {
670        /// The expression used as the bracket key (string or numeric expression).
671        key: Expr,
672    },
673}
674
675/// A JSON path.
676///
677/// See <https://docs.snowflake.com/en/user-guide/querying-semistructured>.
678/// See <https://docs.databricks.com/en/sql/language-manual/sql-ref-json-path-expression.html>.
679#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
680#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
681#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
682pub struct JsonPath {
683    /// Sequence of path elements that form the JSON path.
684    pub path: Vec<JsonPathElem>,
685}
686
687impl fmt::Display for JsonPath {
688    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
689        for (i, elem) in self.path.iter().enumerate() {
690            match elem {
691                JsonPathElem::Dot { key, quoted } => {
692                    if i == 0 {
693                        write!(f, ":")?;
694                    } else {
695                        write!(f, ".")?;
696                    }
697
698                    if *quoted {
699                        write!(f, "\"{}\"", escape_double_quote_string(key))?;
700                    } else {
701                        write!(f, "{key}")?;
702                    }
703                }
704                JsonPathElem::Bracket { key } => {
705                    write!(f, "[{key}]")?;
706                }
707                JsonPathElem::ColonBracket { key } => {
708                    write!(f, ":[{key}]")?;
709                }
710            }
711        }
712        Ok(())
713    }
714}
715
716/// The syntax used for in a cast expression.
717#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
718#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
719#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
720pub enum CastKind {
721    /// The standard SQL cast syntax, e.g. `CAST(<expr> as <datatype>)`
722    Cast,
723    /// A cast that returns `NULL` on failure, e.g. `TRY_CAST(<expr> as <datatype>)`.
724    ///
725    /// See <https://docs.snowflake.com/en/sql-reference/functions/try_cast>.
726    /// See <https://learn.microsoft.com/en-us/sql/t-sql/functions/try-cast-transact-sql>.
727    TryCast,
728    /// A cast that returns `NULL` on failure, bigQuery-specific ,  e.g. `SAFE_CAST(<expr> as <datatype>)`.
729    ///
730    /// See <https://cloud.google.com/bigquery/docs/reference/standard-sql/functions-and-operators#safe_casting>.
731    SafeCast,
732    /// `<expr> :: <datatype>`
733    DoubleColon,
734}
735
736/// `MATCH` type for constraint references
737///
738/// See: <https://www.postgresql.org/docs/current/sql-createtable.html#SQL-CREATETABLE-PARMS-REFERENCES>
739#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
740#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
741#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
742pub enum ConstraintReferenceMatchKind {
743    /// `MATCH FULL`
744    Full,
745    /// `MATCH PARTIAL`
746    Partial,
747    /// `MATCH SIMPLE`
748    Simple,
749}
750
751impl fmt::Display for ConstraintReferenceMatchKind {
752    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
753        match self {
754            Self::Full => write!(f, "MATCH FULL"),
755            Self::Partial => write!(f, "MATCH PARTIAL"),
756            Self::Simple => write!(f, "MATCH SIMPLE"),
757        }
758    }
759}
760
761/// `EXTRACT` syntax variants.
762///
763/// In Snowflake dialect, the `EXTRACT` expression can support either the `from` syntax
764/// or the comma syntax.
765///
766/// See <https://docs.snowflake.com/en/sql-reference/functions/extract>
767#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
768#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
769#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
770pub enum ExtractSyntax {
771    /// `EXTRACT( <date_or_time_part> FROM <date_or_time_expr> )`
772    From,
773    /// `EXTRACT( <date_or_time_part> , <date_or_timestamp_expr> )`
774    Comma,
775}
776
777/// The syntax used in a CEIL or FLOOR expression.
778///
779/// The `CEIL/FLOOR(<datetime value expression> TO <time unit>)` is an Amazon Kinesis Data Analytics extension.
780/// See <https://docs.aws.amazon.com/kinesisanalytics/latest/sqlref/sql-reference-ceil.html> for
781/// details.
782///
783/// Other dialects either support `CEIL/FLOOR( <expr> [, <scale>])` format or just
784/// `CEIL/FLOOR(<expr>)`.
785#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
786#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
787#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
788pub enum CeilFloorKind {
789    /// `CEIL( <expr> TO <DateTimeField>)`
790    DateTimeField(DateTimeField),
791    /// `CEIL( <expr> [, <scale>])`
792    Scale(ValueWithSpan),
793}
794
795/// A WHEN clause in a CASE expression containing both
796/// the condition and its corresponding result
797#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
798#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
799#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
800pub struct CaseWhen {
801    /// The `WHEN` condition expression.
802    pub condition: Expr,
803    /// The expression returned when `condition` matches.
804    pub result: Expr,
805}
806
807impl fmt::Display for CaseWhen {
808    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
809        f.write_str("WHEN ")?;
810        self.condition.fmt(f)?;
811        f.write_str(" THEN")?;
812        SpaceOrNewline.fmt(f)?;
813        Indent(&self.result).fmt(f)?;
814        Ok(())
815    }
816}
817
818/// An SQL expression of any type.
819///
820/// # Semantics / Type Checking
821///
822/// The parser does not distinguish between expressions of different types
823/// (e.g. boolean vs string). The caller is responsible for detecting and
824/// validating types as necessary (for example  `WHERE 1` vs `SELECT 1=1`)
825/// See the [README.md] for more details.
826///
827/// [README.md]: https://github.com/apache/datafusion-sqlparser-rs/blob/main/README.md#syntax-vs-semantics
828///
829/// # Equality and Hashing Does not Include Source Locations
830///
831/// The `Expr` type implements `PartialEq` and `Eq` based on the semantic value
832/// of the expression (not bitwise comparison). This means that `Expr` instances
833/// that are semantically equivalent but have different spans (locations in the
834/// source tree) will compare as equal.
835#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
836#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
837#[cfg_attr(
838    feature = "visitor",
839    derive(Visit, VisitMut),
840    visit(with = "visit_expr")
841)]
842pub enum Expr {
843    /// Identifier e.g. table name or column name
844    Identifier(Ident),
845    /// Multi-part identifier, e.g. `table_alias.column` or `schema.table.col`
846    CompoundIdentifier(Vec<Ident>),
847    /// Multi-part expression access.
848    ///
849    /// This structure represents an access chain in structured / nested types
850    /// such as maps, arrays, and lists:
851    /// - Array
852    ///     - A 1-dim array `a[1]` will be represented like:
853    ///       `CompoundFieldAccess(Ident('a'), vec![Subscript(1)]`
854    ///     - A 2-dim array `a[1][2]` will be represented like:
855    ///       `CompoundFieldAccess(Ident('a'), vec![Subscript(1), Subscript(2)]`
856    /// - Map or Struct (Bracket-style)
857    ///     - A map `a['field1']` will be represented like:
858    ///       `CompoundFieldAccess(Ident('a'), vec![Subscript('field')]`
859    ///     - A 2-dim map `a['field1']['field2']` will be represented like:
860    ///       `CompoundFieldAccess(Ident('a'), vec![Subscript('field1'), Subscript('field2')]`
861    /// - Struct (Dot-style) (only effect when the chain contains both subscript and expr)
862    ///     - A struct access `a[field1].field2` will be represented like:
863    ///       `CompoundFieldAccess(Ident('a'), vec![Subscript('field1'), Ident('field2')]`
864    /// - If a struct access likes `a.field1.field2`, it will be represented by CompoundIdentifier([a, field1, field2])
865    CompoundFieldAccess {
866        /// The base expression being accessed.
867        root: Box<Expr>,
868        /// Sequence of access operations (subscript or identifier accesses).
869        access_chain: Vec<AccessExpr>,
870    },
871    /// Access data nested in a value containing semi-structured data, such as
872    /// the `VARIANT` type on Snowflake. for example `src:customer[0].name`.
873    ///
874    /// See <https://docs.snowflake.com/en/user-guide/querying-semistructured>.
875    /// See <https://docs.databricks.com/en/sql/language-manual/functions/colonsign.html>.
876    JsonAccess {
877        /// The value being queried.
878        value: Box<Expr>,
879        /// The path to the data to extract.
880        path: JsonPath,
881    },
882    /// `IS FALSE` operator
883    IsFalse(Box<Expr>),
884    /// `IS NOT FALSE` operator
885    IsNotFalse(Box<Expr>),
886    /// `IS TRUE` operator
887    IsTrue(Box<Expr>),
888    /// `IS NOT TRUE` operator
889    IsNotTrue(Box<Expr>),
890    /// `IS NULL` operator
891    IsNull(Box<Expr>),
892    /// `IS NOT NULL` operator
893    IsNotNull(Box<Expr>),
894    /// `IS UNKNOWN` operator
895    IsUnknown(Box<Expr>),
896    /// `IS NOT UNKNOWN` operator
897    IsNotUnknown(Box<Expr>),
898    /// `IS DISTINCT FROM` operator
899    IsDistinctFrom(Box<Expr>, Box<Expr>),
900    /// `IS NOT DISTINCT FROM` operator
901    IsNotDistinctFrom(Box<Expr>, Box<Expr>),
902    /// `<expr> IS [ NOT ] [ form ] NORMALIZED`
903    IsNormalized {
904        /// Expression being tested.
905        expr: Box<Expr>,
906        /// Optional normalization `form` (e.g., NFC, NFD).
907        form: Option<NormalizationForm>,
908        /// `true` when `NOT` is present.
909        negated: bool,
910    },
911    /// `[ NOT ] IN (val1, val2, ...)`
912    InList {
913        /// Left-hand expression to test for membership.
914        expr: Box<Expr>,
915        /// Literal list of expressions to check against.
916        list: Vec<Expr>,
917        /// `true` when the `NOT` modifier is present.
918        negated: bool,
919    },
920    /// `[ NOT ] IN (SELECT ...)`
921    InSubquery {
922        /// Left-hand expression to test for membership.
923        expr: Box<Expr>,
924        /// The subquery providing the candidate values.
925        subquery: Box<Query>,
926        /// `true` when the `NOT` modifier is present.
927        negated: bool,
928    },
929    /// `[ NOT ] IN UNNEST(array_expression)`
930    InUnnest {
931        /// Left-hand expression to test for membership.
932        expr: Box<Expr>,
933        /// Array expression being unnested.
934        array_expr: Box<Expr>,
935        /// `true` when the `NOT` modifier is present.
936        negated: bool,
937    },
938    /// `<expr> [ NOT ] BETWEEN <low> AND <high>`
939    Between {
940        /// Expression being compared.
941        expr: Box<Expr>,
942        /// `true` when the `NOT` modifier is present.
943        negated: bool,
944        /// Lower bound.
945        low: Box<Expr>,
946        /// Upper bound.
947        high: Box<Expr>,
948    },
949    /// Binary operation e.g. `1 + 1` or `foo > bar`
950    BinaryOp {
951        /// Left operand.
952        left: Box<Expr>,
953        /// Operator between operands.
954        op: BinaryOperator,
955        /// Right operand.
956        right: Box<Expr>,
957    },
958    /// `[NOT] LIKE <pattern> [ESCAPE <escape_character>]`
959    Like {
960        /// `true` when `NOT` is present.
961        negated: bool,
962        /// Snowflake supports the ANY keyword to match against a list of patterns
963        /// <https://docs.snowflake.com/en/sql-reference/functions/like_any>
964        any: bool,
965        /// Expression to match.
966        expr: Box<Expr>,
967        /// Pattern expression.
968        pattern: Box<Expr>,
969        /// Optional escape character.
970        escape_char: Option<ValueWithSpan>,
971    },
972    /// `ILIKE` (case-insensitive `LIKE`)
973    ILike {
974        /// `true` when `NOT` is present.
975        negated: bool,
976        /// Snowflake supports the ANY keyword to match against a list of patterns
977        /// <https://docs.snowflake.com/en/sql-reference/functions/like_any>
978        any: bool,
979        /// Expression to match.
980        expr: Box<Expr>,
981        /// Pattern expression.
982        pattern: Box<Expr>,
983        /// Optional escape character.
984        escape_char: Option<ValueWithSpan>,
985    },
986    /// `SIMILAR TO` regex
987    SimilarTo {
988        /// `true` when `NOT` is present.
989        negated: bool,
990        /// Expression to test.
991        expr: Box<Expr>,
992        /// Pattern expression.
993        pattern: Box<Expr>,
994        /// Optional escape character.
995        escape_char: Option<ValueWithSpan>,
996    },
997    /// MySQL: `RLIKE` regex or `REGEXP` regex
998    RLike {
999        /// `true` when `NOT` is present.
1000        negated: bool,
1001        /// Expression to test.
1002        expr: Box<Expr>,
1003        /// Pattern expression.
1004        pattern: Box<Expr>,
1005        /// true for REGEXP, false for RLIKE (no difference in semantics)
1006        regexp: bool,
1007    },
1008    /// `ANY` operation e.g. `foo > ANY(bar)`, comparison operator is one of `[=, >, <, =>, =<, !=]`
1009    /// <https://docs.snowflake.com/en/sql-reference/operators-subquery#all-any>
1010    AnyOp {
1011        /// Left operand.
1012        left: Box<Expr>,
1013        /// Comparison operator.
1014        compare_op: BinaryOperator,
1015        /// Right-hand subquery expression.
1016        right: Box<Expr>,
1017        /// ANY and SOME are synonymous: <https://docs.cloudera.com/cdw-runtime/cloud/using-hiveql/topics/hive_comparison_predicates.html>
1018        is_some: bool,
1019    },
1020    /// `ALL` operation e.g. `foo > ALL(bar)`, comparison operator is one of `[=, >, <, =>, =<, !=]`
1021    /// <https://docs.snowflake.com/en/sql-reference/operators-subquery#all-any>
1022    AllOp {
1023        /// Left operand.
1024        left: Box<Expr>,
1025        /// Comparison operator.
1026        compare_op: BinaryOperator,
1027        /// Right-hand subquery expression.
1028        right: Box<Expr>,
1029    },
1030
1031    /// Unary operation e.g. `NOT foo`
1032    UnaryOp {
1033        /// The unary operator (e.g., `NOT`, `-`).
1034        op: UnaryOperator,
1035        /// Operand expression.
1036        expr: Box<Expr>,
1037    },
1038    /// CONVERT a value to a different data type or character encoding. e.g. `CONVERT(foo USING utf8mb4)`
1039    Convert {
1040        /// CONVERT (false) or TRY_CONVERT (true)
1041        /// <https://learn.microsoft.com/en-us/sql/t-sql/functions/try-convert-transact-sql?view=sql-server-ver16>
1042        is_try: bool,
1043        /// The expression to convert.
1044        expr: Box<Expr>,
1045        /// The target data type, if provided.
1046        data_type: Option<DataType>,
1047        /// Optional target character encoding (e.g., `utf8mb4`).
1048        charset: Option<ObjectName>,
1049        /// `true` when target precedes the value (MSSQL syntax).
1050        target_before_value: bool,
1051        /// How to translate the expression.
1052        ///
1053        /// [MSSQL]: https://learn.microsoft.com/en-us/sql/t-sql/functions/cast-and-convert-transact-sql?view=sql-server-ver16#style
1054        styles: Vec<Expr>,
1055    },
1056    /// `CAST` an expression to a different data type e.g. `CAST(foo AS VARCHAR(123))`
1057    Cast {
1058        /// The cast kind (e.g., `CAST`, `TRY_CAST`).
1059        kind: CastKind,
1060        /// Expression being cast.
1061        expr: Box<Expr>,
1062        /// Target data type.
1063        data_type: DataType,
1064        /// [MySQL] allows CAST(... AS type ARRAY) in functional index definitions for InnoDB
1065        /// multi-valued indices. It's not really a datatype, and is only allowed in `CAST` in key
1066        /// specifications, so it's a flag here.
1067        ///
1068        /// [MySQL]: https://dev.mysql.com/doc/refman/8.4/en/cast-functions.html#function_cast
1069        array: bool,
1070        /// Optional CAST(string_expression AS type FORMAT format_string_expression) as used by [BigQuery]
1071        ///
1072        /// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/format-elements#formatting_syntax
1073        format: Option<CastFormat>,
1074    },
1075    /// AT a timestamp to a different timezone e.g. `FROM_UNIXTIME(0) AT TIME ZONE 'UTC-06:00'`
1076    AtTimeZone {
1077        /// Timestamp expression to shift.
1078        timestamp: Box<Expr>,
1079        /// Time zone expression to apply.
1080        time_zone: Box<Expr>,
1081    },
1082    /// Extract a field from a timestamp e.g. `EXTRACT(MONTH FROM foo)`
1083    /// Or `EXTRACT(MONTH, foo)`
1084    ///
1085    /// Syntax:
1086    /// ```sql
1087    /// EXTRACT(DateTimeField FROM <expr>) | EXTRACT(DateTimeField, <expr>)
1088    /// ```
1089    Extract {
1090        /// Which datetime field is being extracted.
1091        field: DateTimeField,
1092        /// Syntax variant used (`From` or `Comma`).
1093        syntax: ExtractSyntax,
1094        /// Expression to extract from.
1095        expr: Box<Expr>,
1096    },
1097    /// ```sql
1098    /// CEIL(<expr> [TO DateTimeField])
1099    /// ```
1100    /// ```sql
1101    /// CEIL( <input_expr> [, <scale_expr> ] )
1102    /// ```
1103    Ceil {
1104        /// Expression to ceil.
1105        expr: Box<Expr>,
1106        /// The CEIL/FLOOR kind (datetime field or scale).
1107        field: CeilFloorKind,
1108    },
1109    /// ```sql
1110    /// FLOOR(<expr> [TO DateTimeField])
1111    /// ```
1112    /// ```sql
1113    /// FLOOR( <input_expr> [, <scale_expr> ] )
1114    ///
1115    Floor {
1116        /// Expression to floor.
1117        expr: Box<Expr>,
1118        /// The CEIL/FLOOR kind (datetime field or scale).
1119        field: CeilFloorKind,
1120    },
1121    /// ```sql
1122    /// POSITION(<expr> in <expr>)
1123    /// ```
1124    Position {
1125        /// Expression to search for.
1126        expr: Box<Expr>,
1127        /// Expression to search in.
1128        r#in: Box<Expr>,
1129    },
1130    /// ```sql
1131    /// SUBSTRING(<expr> [FROM <expr>] [FOR <expr>])
1132    /// ```
1133    /// or
1134    /// ```sql
1135    /// SUBSTRING(<expr>, <expr>, <expr>)
1136    /// ```
1137    Substring {
1138        /// Source expression.
1139        expr: Box<Expr>,
1140        /// Optional `FROM` expression.
1141        substring_from: Option<Box<Expr>>,
1142        /// Optional `FOR` expression.
1143        substring_for: Option<Box<Expr>>,
1144
1145        /// false if the expression is represented using the `SUBSTRING(expr [FROM start] [FOR len])` syntax
1146        /// true if the expression is represented using the `SUBSTRING(expr, start, len)` syntax
1147        /// This flag is used for formatting.
1148        special: bool,
1149
1150        /// true if the expression is represented using the `SUBSTR` shorthand
1151        /// This flag is used for formatting.
1152        shorthand: bool,
1153    },
1154    /// ```sql
1155    /// TRIM([BOTH | LEADING | TRAILING] [<expr> FROM] <expr>)
1156    /// TRIM(<expr>)
1157    /// TRIM(<expr>, [, characters]) -- PostgreSQL, DuckDB, Snowflake, BigQuery, Generic
1158    /// ```
1159    Trim {
1160        /// Which side to trim: `BOTH`, `LEADING`, or `TRAILING`.
1161        trim_where: Option<TrimWhereField>,
1162        /// Optional expression specifying what to trim from the value `expr`.
1163        trim_what: Option<Box<Expr>>,
1164        /// The expression to trim from.
1165        expr: Box<Expr>,
1166        /// Optional list of characters to trim (dialect-specific).
1167        trim_characters: Option<Vec<Expr>>,
1168    },
1169    /// ```sql
1170    /// OVERLAY(<expr> PLACING <expr> FROM <expr>[ FOR <expr> ]
1171    /// ```
1172    Overlay {
1173        /// The target expression being overlayed.
1174        expr: Box<Expr>,
1175        /// The expression to place into the target.
1176        overlay_what: Box<Expr>,
1177        /// The `FROM` position expression indicating where to start overlay.
1178        overlay_from: Box<Expr>,
1179        /// Optional `FOR` length expression limiting the overlay span.
1180        overlay_for: Option<Box<Expr>>,
1181    },
1182    /// `expr COLLATE collation`
1183    Collate {
1184        /// The expression being collated.
1185        expr: Box<Expr>,
1186        /// The collation name to apply to the expression.
1187        collation: ObjectName,
1188    },
1189    /// Nested expression e.g. `(foo > bar)` or `(1)`
1190    Nested(Box<Expr>),
1191    /// A literal value, such as string, number, date or NULL
1192    Value(ValueWithSpan),
1193    /// Prefixed expression, e.g. introducer strings, projection prefix
1194    /// <https://dev.mysql.com/doc/refman/8.0/en/charset-introducer.html>
1195    /// <https://docs.snowflake.com/en/sql-reference/constructs/connect-by>
1196    Prefixed {
1197        /// The prefix identifier (introducer or projection prefix).
1198        prefix: Ident,
1199        /// The value expression being prefixed.
1200        /// Hint: you can unwrap the string value using `value.into_string()`.
1201        value: Box<Expr>,
1202    },
1203    /// A constant of form `<data_type> 'value'`.
1204    /// This can represent ANSI SQL `DATE`, `TIME`, and `TIMESTAMP` literals (such as `DATE '2020-01-01'`),
1205    /// as well as constants of other types (a non-standard PostgreSQL extension).
1206    TypedString(TypedString),
1207    /// Scalar function call e.g. `LEFT(foo, 5)`
1208    Function(Function),
1209    /// `CASE [<operand>] WHEN <condition> THEN <result> ... [ELSE <result>] END`
1210    ///
1211    /// Note we only recognize a complete single expression as `<condition>`,
1212    /// not `< 0` nor `1, 2, 3` as allowed in a `<simple when clause>` per
1213    /// <https://jakewheat.github.io/sql-overview/sql-2011-foundation-grammar.html#simple-when-clause>
1214    Case {
1215        /// The attached `CASE` token (keeps original spacing/comments).
1216        case_token: AttachedToken,
1217        /// The attached `END` token (keeps original spacing/comments).
1218        end_token: AttachedToken,
1219        /// Optional operand expression after `CASE` (for simple CASE).
1220        operand: Option<Box<Expr>>,
1221        /// The `WHEN ... THEN` conditions and results.
1222        conditions: Vec<CaseWhen>,
1223        /// Optional `ELSE` result expression.
1224        else_result: Option<Box<Expr>>,
1225    },
1226    /// An exists expression `[ NOT ] EXISTS(SELECT ...)`, used in expressions like
1227    /// `WHERE [ NOT ] EXISTS (SELECT ...)`.
1228    Exists {
1229        /// The subquery checked by `EXISTS`.
1230        subquery: Box<Query>,
1231        /// Whether the `EXISTS` is negated (`NOT EXISTS`).
1232        negated: bool,
1233    },
1234    /// A parenthesized subquery `(SELECT ...)`, used in expression like
1235    /// `SELECT (subquery) AS x` or `WHERE (subquery) = x`
1236    Subquery(Box<Query>),
1237    /// The `GROUPING SETS` expr.
1238    GroupingSets(Vec<Vec<Expr>>),
1239    /// The `CUBE` expr.
1240    Cube(Vec<Vec<Expr>>),
1241    /// The `ROLLUP` expr.
1242    Rollup(Vec<Vec<Expr>>),
1243    /// ROW / TUPLE a single value, such as `SELECT (1, 2)`
1244    Tuple(Vec<Expr>),
1245    /// `Struct` literal expression
1246    /// Syntax:
1247    /// ```sql
1248    /// STRUCT<[field_name] field_type, ...>( expr1 [, ... ])
1249    ///
1250    /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-types#struct_type)
1251    /// [Databricks](https://docs.databricks.com/en/sql/language-manual/functions/struct.html)
1252    /// ```
1253    Struct {
1254        /// Struct values.
1255        values: Vec<Expr>,
1256        /// Struct field definitions.
1257        fields: Vec<StructField>,
1258    },
1259    /// `BigQuery` specific: An named expression in a typeless struct [1]
1260    ///
1261    /// Syntax
1262    /// ```sql
1263    /// 1 AS A
1264    /// ```
1265    /// [1]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-types#struct_type
1266    Named {
1267        /// The expression being named.
1268        expr: Box<Expr>,
1269        /// The assigned identifier name for the expression.
1270        name: Ident,
1271    },
1272    /// `DuckDB` specific `Struct` literal expression [1]
1273    ///
1274    /// Syntax:
1275    /// ```sql
1276    /// syntax: {'field_name': expr1[, ... ]}
1277    /// ```
1278    /// [1]: https://duckdb.org/docs/sql/data_types/struct#creating-structs
1279    Dictionary(Vec<DictionaryField>),
1280    /// `DuckDB` specific `Map` literal expression [1]
1281    ///
1282    /// Syntax:
1283    /// ```sql
1284    /// syntax: Map {key1: value1[, ... ]}
1285    /// ```
1286    /// [1]: https://duckdb.org/docs/sql/data_types/map#creating-maps
1287    Map(Map),
1288    /// An array expression e.g. `ARRAY[1, 2]`
1289    Array(Array),
1290    /// An interval expression e.g. `INTERVAL '1' YEAR`
1291    Interval(Interval),
1292    /// `MySQL` specific text search function [(1)].
1293    ///
1294    /// Syntax:
1295    /// ```sql
1296    /// MATCH (<col>, <col>, ...) AGAINST (<expr> [<search modifier>])
1297    ///
1298    /// <col> = CompoundIdentifier
1299    /// <expr> = String literal
1300    /// ```
1301    /// [(1)]: https://dev.mysql.com/doc/refman/8.0/en/fulltext-search.html#function_match
1302    MatchAgainst {
1303        /// `(<col>, <col>, ...)`.
1304        columns: Vec<ObjectName>,
1305        /// `<expr>`.
1306        match_value: ValueWithSpan,
1307        /// `<search modifier>`
1308        opt_search_modifier: Option<SearchModifier>,
1309    },
1310    /// An unqualified `*` wildcard token (e.g. `*`).
1311    Wildcard(AttachedToken),
1312    /// Qualified wildcard, e.g. `alias.*` or `schema.table.*`.
1313    /// (Same caveats apply to `QualifiedWildcard` as to `Wildcard`.)
1314    QualifiedWildcard(ObjectName, AttachedToken),
1315    /// Some dialects support an older syntax for outer joins where columns are
1316    /// marked with the `(+)` operator in the WHERE clause, for example:
1317    ///
1318    /// ```sql
1319    /// SELECT t1.c1, t2.c2 FROM t1, t2 WHERE t1.c1 = t2.c2 (+)
1320    /// ```
1321    ///
1322    /// which is equivalent to
1323    ///
1324    /// ```sql
1325    /// SELECT t1.c1, t2.c2 FROM t1 LEFT OUTER JOIN t2 ON t1.c1 = t2.c2
1326    /// ```
1327    ///
1328    /// See <https://docs.snowflake.com/en/sql-reference/constructs/where#joins-in-the-where-clause>.
1329    OuterJoin(Box<Expr>),
1330    /// A reference to the prior level in a CONNECT BY clause.
1331    Prior(Box<Expr>),
1332    /// A lambda function.
1333    ///
1334    /// Syntax:
1335    /// ```plaintext
1336    /// param -> expr | (param1, ...) -> expr
1337    /// ```
1338    ///
1339    /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/functions#higher-order-functions---operator-and-lambdaparams-expr-function)
1340    /// [Databricks](https://docs.databricks.com/en/sql/language-manual/sql-ref-lambda-functions.html)
1341    /// [DuckDB](https://duckdb.org/docs/stable/sql/functions/lambda)
1342    Lambda(LambdaFunction),
1343    /// Checks membership of a value in a JSON array
1344    MemberOf(MemberOf),
1345}
1346
1347impl Expr {
1348    /// Creates a new [`Expr::Value`]
1349    pub fn value(value: impl Into<ValueWithSpan>) -> Self {
1350        Expr::Value(value.into())
1351    }
1352}
1353
1354/// The contents inside the `[` and `]` in a subscript expression.
1355#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1356#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1357#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1358pub enum Subscript {
1359    /// Accesses the element of the array at the given index.
1360    Index {
1361        /// The index expression used to access the array element.
1362        index: Expr,
1363    },
1364
1365    /// Accesses a slice of an array on PostgreSQL, e.g.
1366    ///
1367    /// ```plaintext
1368    /// => select (array[1,2,3,4,5,6])[2:5];
1369    /// -----------
1370    /// {2,3,4,5}
1371    /// ```
1372    ///
1373    /// The lower and/or upper bound can be omitted to slice from the start or
1374    /// end of the array respectively.
1375    ///
1376    /// See <https://www.postgresql.org/docs/current/arrays.html#ARRAYS-ACCESSING>.
1377    ///
1378    /// Also supports an optional "stride" as the last element (this is not
1379    /// supported by postgres), e.g.
1380    ///
1381    /// ```plaintext
1382    /// => select (array[1,2,3,4,5,6])[1:6:2];
1383    /// -----------
1384    /// {1,3,5}
1385    /// ```
1386    Slice {
1387        /// Optional lower bound for the slice (inclusive).
1388        lower_bound: Option<Expr>,
1389        /// Optional upper bound for the slice (inclusive).
1390        upper_bound: Option<Expr>,
1391        /// Optional stride for the slice (step size).
1392        stride: Option<Expr>,
1393    },
1394}
1395
1396impl fmt::Display for Subscript {
1397    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1398        match self {
1399            Subscript::Index { index } => write!(f, "{index}"),
1400            Subscript::Slice {
1401                lower_bound,
1402                upper_bound,
1403                stride,
1404            } => {
1405                if let Some(lower) = lower_bound {
1406                    write!(f, "{lower}")?;
1407                }
1408                write!(f, ":")?;
1409                if let Some(upper) = upper_bound {
1410                    write!(f, "{upper}")?;
1411                }
1412                if let Some(stride) = stride {
1413                    write!(f, ":")?;
1414                    write!(f, "{stride}")?;
1415                }
1416                Ok(())
1417            }
1418        }
1419    }
1420}
1421
1422/// An element of a [`Expr::CompoundFieldAccess`].
1423/// It can be an expression or a subscript.
1424#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1425#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1426#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1427pub enum AccessExpr {
1428    /// Accesses a field using dot notation, e.g. `foo.bar.baz`.
1429    Dot(Expr),
1430    /// Accesses a field or array element using bracket notation, e.g. `foo['bar']`.
1431    Subscript(Subscript),
1432}
1433
1434impl fmt::Display for AccessExpr {
1435    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1436        match self {
1437            AccessExpr::Dot(expr) => write!(f, ".{expr}"),
1438            AccessExpr::Subscript(subscript) => write!(f, "[{subscript}]"),
1439        }
1440    }
1441}
1442
1443/// A lambda function.
1444#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1445#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1446#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1447pub struct LambdaFunction {
1448    /// The parameters to the lambda function.
1449    pub params: OneOrManyWithParens<LambdaFunctionParameter>,
1450    /// The body of the lambda function.
1451    pub body: Box<Expr>,
1452    /// The syntax style used to write the lambda function.
1453    pub syntax: LambdaSyntax,
1454}
1455
1456impl fmt::Display for LambdaFunction {
1457    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1458        match self.syntax {
1459            LambdaSyntax::Arrow => write!(f, "{} -> {}", self.params, self.body),
1460            LambdaSyntax::LambdaKeyword => {
1461                // For lambda keyword syntax, display params without parentheses
1462                // e.g., `lambda x, y : expr` not `lambda (x, y) : expr`
1463                write!(f, "lambda ")?;
1464                match &self.params {
1465                    OneOrManyWithParens::One(p) => write!(f, "{p}")?,
1466                    OneOrManyWithParens::Many(ps) => write!(f, "{}", display_comma_separated(ps))?,
1467                };
1468                write!(f, " : {}", self.body)
1469            }
1470        }
1471    }
1472}
1473
1474/// A parameter to a lambda function, optionally with a data type.
1475#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1476#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1477#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1478pub struct LambdaFunctionParameter {
1479    /// The name of the parameter
1480    pub name: Ident,
1481    /// The optional data type of the parameter
1482    /// [Snowflake Syntax](https://docs.snowflake.com/en/sql-reference/functions/filter#arguments)
1483    pub data_type: Option<DataType>,
1484}
1485
1486impl fmt::Display for LambdaFunctionParameter {
1487    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1488        match &self.data_type {
1489            Some(dt) => write!(f, "{} {}", self.name, dt),
1490            None => write!(f, "{}", self.name),
1491        }
1492    }
1493}
1494
1495/// The syntax style for a lambda function.
1496#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Copy)]
1497#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1498#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1499pub enum LambdaSyntax {
1500    /// Arrow syntax: `param -> expr` or `(param1, param2) -> expr`
1501    ///
1502    /// <https://docs.databricks.com/aws/en/sql/language-manual/sql-ref-lambda-functions>
1503    ///
1504    /// Supported, but deprecated in DuckDB:
1505    /// <https://duckdb.org/docs/stable/sql/functions/lambda>
1506    Arrow,
1507    /// Lambda keyword syntax: `lambda param : expr` or `lambda param1, param2 : expr`
1508    ///
1509    /// Recommended in DuckDB:
1510    /// <https://duckdb.org/docs/stable/sql/functions/lambda>
1511    LambdaKeyword,
1512}
1513
1514/// Encapsulates the common pattern in SQL where either one unparenthesized item
1515/// such as an identifier or expression is permitted, or multiple of the same
1516/// item in a parenthesized list. For accessing items regardless of the form,
1517/// `OneOrManyWithParens` implements `Deref<Target = [T]>` and `IntoIterator`,
1518/// so you can call slice methods on it and iterate over items
1519/// # Examples
1520/// Accessing as a slice:
1521/// ```
1522/// # use sqlparser::ast::OneOrManyWithParens;
1523/// let one = OneOrManyWithParens::One("a");
1524///
1525/// assert_eq!(one[0], "a");
1526/// assert_eq!(one.len(), 1);
1527/// ```
1528/// Iterating:
1529/// ```
1530/// # use sqlparser::ast::OneOrManyWithParens;
1531/// let one = OneOrManyWithParens::One("a");
1532/// let many = OneOrManyWithParens::Many(vec!["a", "b"]);
1533///
1534/// assert_eq!(one.into_iter().chain(many).collect::<Vec<_>>(), vec!["a", "a", "b"] );
1535/// ```
1536#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1537#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1538#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1539pub enum OneOrManyWithParens<T> {
1540    /// A single `T`, unparenthesized.
1541    One(T),
1542    /// One or more `T`s, parenthesized.
1543    Many(Vec<T>),
1544}
1545
1546impl<T> Deref for OneOrManyWithParens<T> {
1547    type Target = [T];
1548
1549    fn deref(&self) -> &[T] {
1550        match self {
1551            OneOrManyWithParens::One(one) => core::slice::from_ref(one),
1552            OneOrManyWithParens::Many(many) => many,
1553        }
1554    }
1555}
1556
1557impl<T> AsRef<[T]> for OneOrManyWithParens<T> {
1558    fn as_ref(&self) -> &[T] {
1559        self
1560    }
1561}
1562
1563impl<'a, T> IntoIterator for &'a OneOrManyWithParens<T> {
1564    type Item = &'a T;
1565    type IntoIter = core::slice::Iter<'a, T>;
1566
1567    fn into_iter(self) -> Self::IntoIter {
1568        self.iter()
1569    }
1570}
1571
1572/// Owned iterator implementation of `OneOrManyWithParens`
1573#[derive(Debug, Clone)]
1574pub struct OneOrManyWithParensIntoIter<T> {
1575    inner: OneOrManyWithParensIntoIterInner<T>,
1576}
1577
1578#[derive(Debug, Clone)]
1579enum OneOrManyWithParensIntoIterInner<T> {
1580    One(core::iter::Once<T>),
1581    Many(<Vec<T> as IntoIterator>::IntoIter),
1582}
1583
1584impl<T> core::iter::FusedIterator for OneOrManyWithParensIntoIter<T>
1585where
1586    core::iter::Once<T>: core::iter::FusedIterator,
1587    <Vec<T> as IntoIterator>::IntoIter: core::iter::FusedIterator,
1588{
1589}
1590
1591impl<T> core::iter::ExactSizeIterator for OneOrManyWithParensIntoIter<T>
1592where
1593    core::iter::Once<T>: core::iter::ExactSizeIterator,
1594    <Vec<T> as IntoIterator>::IntoIter: core::iter::ExactSizeIterator,
1595{
1596}
1597
1598impl<T> core::iter::Iterator for OneOrManyWithParensIntoIter<T> {
1599    type Item = T;
1600
1601    fn next(&mut self) -> Option<Self::Item> {
1602        match &mut self.inner {
1603            OneOrManyWithParensIntoIterInner::One(one) => one.next(),
1604            OneOrManyWithParensIntoIterInner::Many(many) => many.next(),
1605        }
1606    }
1607
1608    fn size_hint(&self) -> (usize, Option<usize>) {
1609        match &self.inner {
1610            OneOrManyWithParensIntoIterInner::One(one) => one.size_hint(),
1611            OneOrManyWithParensIntoIterInner::Many(many) => many.size_hint(),
1612        }
1613    }
1614
1615    fn count(self) -> usize
1616    where
1617        Self: Sized,
1618    {
1619        match self.inner {
1620            OneOrManyWithParensIntoIterInner::One(one) => one.count(),
1621            OneOrManyWithParensIntoIterInner::Many(many) => many.count(),
1622        }
1623    }
1624
1625    fn fold<B, F>(mut self, init: B, f: F) -> B
1626    where
1627        Self: Sized,
1628        F: FnMut(B, Self::Item) -> B,
1629    {
1630        match &mut self.inner {
1631            OneOrManyWithParensIntoIterInner::One(one) => one.fold(init, f),
1632            OneOrManyWithParensIntoIterInner::Many(many) => many.fold(init, f),
1633        }
1634    }
1635}
1636
1637impl<T> core::iter::DoubleEndedIterator for OneOrManyWithParensIntoIter<T> {
1638    fn next_back(&mut self) -> Option<Self::Item> {
1639        match &mut self.inner {
1640            OneOrManyWithParensIntoIterInner::One(one) => one.next_back(),
1641            OneOrManyWithParensIntoIterInner::Many(many) => many.next_back(),
1642        }
1643    }
1644}
1645
1646impl<T> IntoIterator for OneOrManyWithParens<T> {
1647    type Item = T;
1648
1649    type IntoIter = OneOrManyWithParensIntoIter<T>;
1650
1651    fn into_iter(self) -> Self::IntoIter {
1652        let inner = match self {
1653            OneOrManyWithParens::One(one) => {
1654                OneOrManyWithParensIntoIterInner::One(core::iter::once(one))
1655            }
1656            OneOrManyWithParens::Many(many) => {
1657                OneOrManyWithParensIntoIterInner::Many(many.into_iter())
1658            }
1659        };
1660
1661        OneOrManyWithParensIntoIter { inner }
1662    }
1663}
1664
1665impl<T> fmt::Display for OneOrManyWithParens<T>
1666where
1667    T: fmt::Display,
1668{
1669    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1670        match self {
1671            OneOrManyWithParens::One(value) => write!(f, "{value}"),
1672            OneOrManyWithParens::Many(values) => {
1673                write!(f, "({})", display_comma_separated(values))
1674            }
1675        }
1676    }
1677}
1678
1679impl fmt::Display for CastFormat {
1680    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1681        match self {
1682            CastFormat::Value(v) => write!(f, "{v}"),
1683            CastFormat::ValueAtTimeZone(v, tz) => write!(f, "{v} AT TIME ZONE {tz}"),
1684        }
1685    }
1686}
1687
1688impl fmt::Display for Expr {
1689    #[cfg_attr(feature = "recursive-protection", recursive::recursive)]
1690    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1691        match self {
1692            Expr::Identifier(s) => write!(f, "{s}"),
1693            Expr::Wildcard(_) => f.write_str("*"),
1694            Expr::QualifiedWildcard(prefix, _) => write!(f, "{prefix}.*"),
1695            Expr::CompoundIdentifier(s) => write!(f, "{}", display_separated(s, ".")),
1696            Expr::CompoundFieldAccess { root, access_chain } => {
1697                write!(f, "{root}")?;
1698                for field in access_chain {
1699                    write!(f, "{field}")?;
1700                }
1701                Ok(())
1702            }
1703            Expr::IsTrue(ast) => write!(f, "{ast} IS TRUE"),
1704            Expr::IsNotTrue(ast) => write!(f, "{ast} IS NOT TRUE"),
1705            Expr::IsFalse(ast) => write!(f, "{ast} IS FALSE"),
1706            Expr::IsNotFalse(ast) => write!(f, "{ast} IS NOT FALSE"),
1707            Expr::IsNull(ast) => write!(f, "{ast} IS NULL"),
1708            Expr::IsNotNull(ast) => write!(f, "{ast} IS NOT NULL"),
1709            Expr::IsUnknown(ast) => write!(f, "{ast} IS UNKNOWN"),
1710            Expr::IsNotUnknown(ast) => write!(f, "{ast} IS NOT UNKNOWN"),
1711            Expr::InList {
1712                expr,
1713                list,
1714                negated,
1715            } => write!(
1716                f,
1717                "{} {}IN ({})",
1718                expr,
1719                if *negated { "NOT " } else { "" },
1720                display_comma_separated(list)
1721            ),
1722            Expr::InSubquery {
1723                expr,
1724                subquery,
1725                negated,
1726            } => write!(
1727                f,
1728                "{} {}IN ({})",
1729                expr,
1730                if *negated { "NOT " } else { "" },
1731                subquery
1732            ),
1733            Expr::InUnnest {
1734                expr,
1735                array_expr,
1736                negated,
1737            } => write!(
1738                f,
1739                "{} {}IN UNNEST({})",
1740                expr,
1741                if *negated { "NOT " } else { "" },
1742                array_expr
1743            ),
1744            Expr::Between {
1745                expr,
1746                negated,
1747                low,
1748                high,
1749            } => write!(
1750                f,
1751                "{} {}BETWEEN {} AND {}",
1752                expr,
1753                if *negated { "NOT " } else { "" },
1754                low,
1755                high
1756            ),
1757            Expr::BinaryOp { left, op, right } => write!(f, "{left} {op} {right}"),
1758            Expr::Like {
1759                negated,
1760                expr,
1761                pattern,
1762                escape_char,
1763                any,
1764            } => match escape_char {
1765                Some(ch) => write!(
1766                    f,
1767                    "{} {}LIKE {}{} ESCAPE {}",
1768                    expr,
1769                    if *negated { "NOT " } else { "" },
1770                    if *any { "ANY " } else { "" },
1771                    pattern,
1772                    ch
1773                ),
1774                _ => write!(
1775                    f,
1776                    "{} {}LIKE {}{}",
1777                    expr,
1778                    if *negated { "NOT " } else { "" },
1779                    if *any { "ANY " } else { "" },
1780                    pattern
1781                ),
1782            },
1783            Expr::ILike {
1784                negated,
1785                expr,
1786                pattern,
1787                escape_char,
1788                any,
1789            } => match escape_char {
1790                Some(ch) => write!(
1791                    f,
1792                    "{} {}ILIKE {}{} ESCAPE {}",
1793                    expr,
1794                    if *negated { "NOT " } else { "" },
1795                    if *any { "ANY" } else { "" },
1796                    pattern,
1797                    ch
1798                ),
1799                _ => write!(
1800                    f,
1801                    "{} {}ILIKE {}{}",
1802                    expr,
1803                    if *negated { "NOT " } else { "" },
1804                    if *any { "ANY " } else { "" },
1805                    pattern
1806                ),
1807            },
1808            Expr::RLike {
1809                negated,
1810                expr,
1811                pattern,
1812                regexp,
1813            } => write!(
1814                f,
1815                "{} {}{} {}",
1816                expr,
1817                if *negated { "NOT " } else { "" },
1818                if *regexp { "REGEXP" } else { "RLIKE" },
1819                pattern
1820            ),
1821            Expr::IsNormalized {
1822                expr,
1823                form,
1824                negated,
1825            } => {
1826                let not_ = if *negated { "NOT " } else { "" };
1827                if form.is_none() {
1828                    write!(f, "{expr} IS {not_}NORMALIZED")
1829                } else {
1830                    write!(
1831                        f,
1832                        "{} IS {}{} NORMALIZED",
1833                        expr,
1834                        not_,
1835                        form.as_ref().unwrap()
1836                    )
1837                }
1838            }
1839            Expr::SimilarTo {
1840                negated,
1841                expr,
1842                pattern,
1843                escape_char,
1844            } => match escape_char {
1845                Some(ch) => write!(
1846                    f,
1847                    "{} {}SIMILAR TO {} ESCAPE {}",
1848                    expr,
1849                    if *negated { "NOT " } else { "" },
1850                    pattern,
1851                    ch
1852                ),
1853                _ => write!(
1854                    f,
1855                    "{} {}SIMILAR TO {}",
1856                    expr,
1857                    if *negated { "NOT " } else { "" },
1858                    pattern
1859                ),
1860            },
1861            Expr::AnyOp {
1862                left,
1863                compare_op,
1864                right,
1865                is_some,
1866            } => {
1867                let add_parens = !matches!(right.as_ref(), Expr::Subquery(_));
1868                write!(
1869                    f,
1870                    "{left} {compare_op} {}{}{right}{}",
1871                    if *is_some { "SOME" } else { "ANY" },
1872                    if add_parens { "(" } else { "" },
1873                    if add_parens { ")" } else { "" },
1874                )
1875            }
1876            Expr::AllOp {
1877                left,
1878                compare_op,
1879                right,
1880            } => {
1881                let add_parens = !matches!(right.as_ref(), Expr::Subquery(_));
1882                write!(
1883                    f,
1884                    "{left} {compare_op} ALL{}{right}{}",
1885                    if add_parens { "(" } else { "" },
1886                    if add_parens { ")" } else { "" },
1887                )
1888            }
1889            Expr::UnaryOp { op, expr } => {
1890                if op == &UnaryOperator::PGPostfixFactorial {
1891                    write!(f, "{expr}{op}")
1892                } else if matches!(
1893                    op,
1894                    UnaryOperator::Not
1895                        | UnaryOperator::Hash
1896                        | UnaryOperator::AtDashAt
1897                        | UnaryOperator::DoubleAt
1898                        | UnaryOperator::QuestionDash
1899                        | UnaryOperator::QuestionPipe
1900                ) {
1901                    write!(f, "{op} {expr}")
1902                } else {
1903                    write!(f, "{op}{expr}")
1904                }
1905            }
1906            Expr::Convert {
1907                is_try,
1908                expr,
1909                target_before_value,
1910                data_type,
1911                charset,
1912                styles,
1913            } => {
1914                write!(f, "{}CONVERT(", if *is_try { "TRY_" } else { "" })?;
1915                if let Some(data_type) = data_type {
1916                    if let Some(charset) = charset {
1917                        write!(f, "{expr}, {data_type} CHARACTER SET {charset}")
1918                    } else if *target_before_value {
1919                        write!(f, "{data_type}, {expr}")
1920                    } else {
1921                        write!(f, "{expr}, {data_type}")
1922                    }
1923                } else if let Some(charset) = charset {
1924                    write!(f, "{expr} USING {charset}")
1925                } else {
1926                    write!(f, "{expr}") // This should never happen
1927                }?;
1928                if !styles.is_empty() {
1929                    write!(f, ", {}", display_comma_separated(styles))?;
1930                }
1931                write!(f, ")")
1932            }
1933            Expr::Cast {
1934                kind,
1935                expr,
1936                data_type,
1937                array,
1938                format,
1939            } => match kind {
1940                CastKind::Cast => {
1941                    write!(f, "CAST({expr} AS {data_type}")?;
1942                    if *array {
1943                        write!(f, " ARRAY")?;
1944                    }
1945                    if let Some(format) = format {
1946                        write!(f, " FORMAT {format}")?;
1947                    }
1948                    write!(f, ")")
1949                }
1950                CastKind::TryCast => {
1951                    if let Some(format) = format {
1952                        write!(f, "TRY_CAST({expr} AS {data_type} FORMAT {format})")
1953                    } else {
1954                        write!(f, "TRY_CAST({expr} AS {data_type})")
1955                    }
1956                }
1957                CastKind::SafeCast => {
1958                    if let Some(format) = format {
1959                        write!(f, "SAFE_CAST({expr} AS {data_type} FORMAT {format})")
1960                    } else {
1961                        write!(f, "SAFE_CAST({expr} AS {data_type})")
1962                    }
1963                }
1964                CastKind::DoubleColon => {
1965                    write!(f, "{expr}::{data_type}")
1966                }
1967            },
1968            Expr::Extract {
1969                field,
1970                syntax,
1971                expr,
1972            } => match syntax {
1973                ExtractSyntax::From => write!(f, "EXTRACT({field} FROM {expr})"),
1974                ExtractSyntax::Comma => write!(f, "EXTRACT({field}, {expr})"),
1975            },
1976            Expr::Ceil { expr, field } => match field {
1977                CeilFloorKind::DateTimeField(DateTimeField::NoDateTime) => {
1978                    write!(f, "CEIL({expr})")
1979                }
1980                CeilFloorKind::DateTimeField(dt_field) => write!(f, "CEIL({expr} TO {dt_field})"),
1981                CeilFloorKind::Scale(s) => write!(f, "CEIL({expr}, {s})"),
1982            },
1983            Expr::Floor { expr, field } => match field {
1984                CeilFloorKind::DateTimeField(DateTimeField::NoDateTime) => {
1985                    write!(f, "FLOOR({expr})")
1986                }
1987                CeilFloorKind::DateTimeField(dt_field) => write!(f, "FLOOR({expr} TO {dt_field})"),
1988                CeilFloorKind::Scale(s) => write!(f, "FLOOR({expr}, {s})"),
1989            },
1990            Expr::Position { expr, r#in } => write!(f, "POSITION({expr} IN {in})"),
1991            Expr::Collate { expr, collation } => write!(f, "{expr} COLLATE {collation}"),
1992            Expr::Nested(ast) => write!(f, "({ast})"),
1993            Expr::Value(v) => write!(f, "{v}"),
1994            Expr::Prefixed { prefix, value } => write!(f, "{prefix} {value}"),
1995            Expr::TypedString(ts) => ts.fmt(f),
1996            Expr::Function(fun) => fun.fmt(f),
1997            Expr::Case {
1998                case_token: _,
1999                end_token: _,
2000                operand,
2001                conditions,
2002                else_result,
2003            } => {
2004                f.write_str("CASE")?;
2005                if let Some(operand) = operand {
2006                    f.write_str(" ")?;
2007                    operand.fmt(f)?;
2008                }
2009                for when in conditions {
2010                    SpaceOrNewline.fmt(f)?;
2011                    Indent(when).fmt(f)?;
2012                }
2013                if let Some(else_result) = else_result {
2014                    SpaceOrNewline.fmt(f)?;
2015                    Indent("ELSE").fmt(f)?;
2016                    SpaceOrNewline.fmt(f)?;
2017                    Indent(Indent(else_result)).fmt(f)?;
2018                }
2019                SpaceOrNewline.fmt(f)?;
2020                f.write_str("END")
2021            }
2022            Expr::Exists { subquery, negated } => write!(
2023                f,
2024                "{}EXISTS ({})",
2025                if *negated { "NOT " } else { "" },
2026                subquery
2027            ),
2028            Expr::Subquery(s) => write!(f, "({s})"),
2029            Expr::GroupingSets(sets) => {
2030                write!(f, "GROUPING SETS (")?;
2031                let mut sep = "";
2032                for set in sets {
2033                    write!(f, "{sep}")?;
2034                    sep = ", ";
2035                    write!(f, "({})", display_comma_separated(set))?;
2036                }
2037                write!(f, ")")
2038            }
2039            Expr::Cube(sets) => {
2040                write!(f, "CUBE (")?;
2041                let mut sep = "";
2042                for set in sets {
2043                    write!(f, "{sep}")?;
2044                    sep = ", ";
2045                    if set.len() == 1 {
2046                        write!(f, "{}", set[0])?;
2047                    } else {
2048                        write!(f, "({})", display_comma_separated(set))?;
2049                    }
2050                }
2051                write!(f, ")")
2052            }
2053            Expr::Rollup(sets) => {
2054                write!(f, "ROLLUP (")?;
2055                let mut sep = "";
2056                for set in sets {
2057                    write!(f, "{sep}")?;
2058                    sep = ", ";
2059                    if set.len() == 1 {
2060                        write!(f, "{}", set[0])?;
2061                    } else {
2062                        write!(f, "({})", display_comma_separated(set))?;
2063                    }
2064                }
2065                write!(f, ")")
2066            }
2067            Expr::Substring {
2068                expr,
2069                substring_from,
2070                substring_for,
2071                special,
2072                shorthand,
2073            } => {
2074                f.write_str("SUBSTR")?;
2075                if !*shorthand {
2076                    f.write_str("ING")?;
2077                }
2078                write!(f, "({expr}")?;
2079                if let Some(from_part) = substring_from {
2080                    if *special {
2081                        write!(f, ", {from_part}")?;
2082                    } else {
2083                        write!(f, " FROM {from_part}")?;
2084                    }
2085                }
2086                if let Some(for_part) = substring_for {
2087                    if *special {
2088                        write!(f, ", {for_part}")?;
2089                    } else {
2090                        write!(f, " FOR {for_part}")?;
2091                    }
2092                }
2093
2094                write!(f, ")")
2095            }
2096            Expr::Overlay {
2097                expr,
2098                overlay_what,
2099                overlay_from,
2100                overlay_for,
2101            } => {
2102                write!(
2103                    f,
2104                    "OVERLAY({expr} PLACING {overlay_what} FROM {overlay_from}"
2105                )?;
2106                if let Some(for_part) = overlay_for {
2107                    write!(f, " FOR {for_part}")?;
2108                }
2109
2110                write!(f, ")")
2111            }
2112            Expr::IsDistinctFrom(a, b) => write!(f, "{a} IS DISTINCT FROM {b}"),
2113            Expr::IsNotDistinctFrom(a, b) => write!(f, "{a} IS NOT DISTINCT FROM {b}"),
2114            Expr::Trim {
2115                expr,
2116                trim_where,
2117                trim_what,
2118                trim_characters,
2119            } => {
2120                write!(f, "TRIM(")?;
2121                if let Some(ident) = trim_where {
2122                    write!(f, "{ident} ")?;
2123                }
2124                if let Some(trim_char) = trim_what {
2125                    write!(f, "{trim_char} FROM {expr}")?;
2126                } else {
2127                    write!(f, "{expr}")?;
2128                }
2129                if let Some(characters) = trim_characters {
2130                    write!(f, ", {}", display_comma_separated(characters))?;
2131                }
2132
2133                write!(f, ")")
2134            }
2135            Expr::Tuple(exprs) => {
2136                write!(f, "({})", display_comma_separated(exprs))
2137            }
2138            Expr::Struct { values, fields } => {
2139                if !fields.is_empty() {
2140                    write!(
2141                        f,
2142                        "STRUCT<{}>({})",
2143                        display_comma_separated(fields),
2144                        display_comma_separated(values)
2145                    )
2146                } else {
2147                    write!(f, "STRUCT({})", display_comma_separated(values))
2148                }
2149            }
2150            Expr::Named { expr, name } => {
2151                write!(f, "{expr} AS {name}")
2152            }
2153            Expr::Dictionary(fields) => {
2154                write!(f, "{{{}}}", display_comma_separated(fields))
2155            }
2156            Expr::Map(map) => {
2157                write!(f, "{map}")
2158            }
2159            Expr::Array(set) => {
2160                write!(f, "{set}")
2161            }
2162            Expr::JsonAccess { value, path } => {
2163                write!(f, "{value}{path}")
2164            }
2165            Expr::AtTimeZone {
2166                timestamp,
2167                time_zone,
2168            } => {
2169                write!(f, "{timestamp} AT TIME ZONE {time_zone}")
2170            }
2171            Expr::Interval(interval) => {
2172                write!(f, "{interval}")
2173            }
2174            Expr::MatchAgainst {
2175                columns,
2176                match_value: match_expr,
2177                opt_search_modifier,
2178            } => {
2179                write!(f, "MATCH ({}) AGAINST ", display_comma_separated(columns),)?;
2180
2181                if let Some(search_modifier) = opt_search_modifier {
2182                    write!(f, "({match_expr} {search_modifier})")?;
2183                } else {
2184                    write!(f, "({match_expr})")?;
2185                }
2186
2187                Ok(())
2188            }
2189            Expr::OuterJoin(expr) => {
2190                write!(f, "{expr} (+)")
2191            }
2192            Expr::Prior(expr) => write!(f, "PRIOR {expr}"),
2193            Expr::Lambda(lambda) => write!(f, "{lambda}"),
2194            Expr::MemberOf(member_of) => write!(f, "{member_of}"),
2195        }
2196    }
2197}
2198
2199/// The type of a window used in `OVER` clauses.
2200///
2201/// A window can be either an inline specification (`WindowSpec`) or a
2202/// reference to a previously defined named window.
2203///
2204/// - `WindowSpec(WindowSpec)`: An inline window specification, e.g.
2205///   `OVER (PARTITION BY ... ORDER BY ...)`.
2206/// - `NamedWindow(Ident)`: A reference to a named window declared elsewhere.
2207#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2208#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2209#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2210pub enum WindowType {
2211    /// An inline window specification.
2212    WindowSpec(WindowSpec),
2213    /// A reference to a previously defined named window.
2214    NamedWindow(Ident),
2215}
2216
2217impl Display for WindowType {
2218    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2219        match self {
2220            WindowType::WindowSpec(spec) => {
2221                f.write_str("(")?;
2222                NewLine.fmt(f)?;
2223                Indent(spec).fmt(f)?;
2224                NewLine.fmt(f)?;
2225                f.write_str(")")
2226            }
2227            WindowType::NamedWindow(name) => name.fmt(f),
2228        }
2229    }
2230}
2231
2232/// A window specification (i.e. `OVER ([window_name] PARTITION BY .. ORDER BY .. etc.)`)
2233#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2234#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2235#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2236pub struct WindowSpec {
2237    /// Optional window name.
2238    ///
2239    /// You can find it at least in [MySQL][1], [BigQuery][2], [PostgreSQL][3]
2240    ///
2241    /// [1]: https://dev.mysql.com/doc/refman/8.0/en/window-functions-named-windows.html
2242    /// [2]: https://cloud.google.com/bigquery/docs/reference/standard-sql/window-function-calls
2243    /// [3]: https://www.postgresql.org/docs/current/sql-expressions.html#SYNTAX-WINDOW-FUNCTIONS
2244    pub window_name: Option<Ident>,
2245    /// `OVER (PARTITION BY ...)`
2246    pub partition_by: Vec<Expr>,
2247    /// `OVER (ORDER BY ...)`
2248    pub order_by: Vec<OrderByExpr>,
2249    /// `OVER (window frame)`
2250    pub window_frame: Option<WindowFrame>,
2251}
2252
2253impl fmt::Display for WindowSpec {
2254    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2255        let mut is_first = true;
2256        if let Some(window_name) = &self.window_name {
2257            if !is_first {
2258                SpaceOrNewline.fmt(f)?;
2259            }
2260            is_first = false;
2261            write!(f, "{window_name}")?;
2262        }
2263        if !self.partition_by.is_empty() {
2264            if !is_first {
2265                SpaceOrNewline.fmt(f)?;
2266            }
2267            is_first = false;
2268            write!(
2269                f,
2270                "PARTITION BY {}",
2271                display_comma_separated(&self.partition_by)
2272            )?;
2273        }
2274        if !self.order_by.is_empty() {
2275            if !is_first {
2276                SpaceOrNewline.fmt(f)?;
2277            }
2278            is_first = false;
2279            write!(f, "ORDER BY {}", display_comma_separated(&self.order_by))?;
2280        }
2281        if let Some(window_frame) = &self.window_frame {
2282            if !is_first {
2283                SpaceOrNewline.fmt(f)?;
2284            }
2285            if let Some(end_bound) = &window_frame.end_bound {
2286                write!(
2287                    f,
2288                    "{} BETWEEN {} AND {}",
2289                    window_frame.units, window_frame.start_bound, end_bound
2290                )?;
2291            } else {
2292                write!(f, "{} {}", window_frame.units, window_frame.start_bound)?;
2293            }
2294        }
2295        Ok(())
2296    }
2297}
2298
2299/// Specifies the data processed by a window function, e.g.
2300/// `RANGE UNBOUNDED PRECEDING` or `ROWS BETWEEN 5 PRECEDING AND CURRENT ROW`.
2301///
2302/// Note: The parser does not validate the specified bounds; the caller should
2303/// reject invalid bounds like `ROWS UNBOUNDED FOLLOWING` before execution.
2304#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2305#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2306#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2307pub struct WindowFrame {
2308    /// Units for the frame (e.g. `ROWS`, `RANGE`, `GROUPS`).
2309    pub units: WindowFrameUnits,
2310    /// The start bound of the window frame.
2311    pub start_bound: WindowFrameBound,
2312    /// The right bound of the `BETWEEN .. AND` clause. The end bound of `None`
2313    /// indicates the shorthand form (e.g. `ROWS 1 PRECEDING`), which must
2314    /// behave the same as `end_bound = WindowFrameBound::CurrentRow`.
2315    pub end_bound: Option<WindowFrameBound>,
2316    // TBD: EXCLUDE
2317}
2318
2319impl Default for WindowFrame {
2320    /// Returns default value for window frame
2321    ///
2322    /// See [this page](https://www.sqlite.org/windowfunctions.html#frame_specifications) for more details.
2323    fn default() -> Self {
2324        Self {
2325            units: WindowFrameUnits::Range,
2326            start_bound: WindowFrameBound::Preceding(None),
2327            end_bound: None,
2328        }
2329    }
2330}
2331
2332#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2333#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2334#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2335/// Units used to describe the window frame scope.
2336pub enum WindowFrameUnits {
2337    /// `ROWS` unit.
2338    Rows,
2339    /// `RANGE` unit.
2340    Range,
2341    /// `GROUPS` unit.
2342    Groups,
2343}
2344
2345impl fmt::Display for WindowFrameUnits {
2346    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2347        f.write_str(match self {
2348            WindowFrameUnits::Rows => "ROWS",
2349            WindowFrameUnits::Range => "RANGE",
2350            WindowFrameUnits::Groups => "GROUPS",
2351        })
2352    }
2353}
2354
2355/// Specifies Ignore / Respect NULL within window functions.
2356/// For example
2357/// `FIRST_VALUE(column2) IGNORE NULLS OVER (PARTITION BY column1)`
2358#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2359#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2360#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2361/// How NULL values are treated in certain window functions.
2362pub enum NullTreatment {
2363    /// Ignore NULL values (e.g. `IGNORE NULLS`).
2364    IgnoreNulls,
2365    /// Respect NULL values (e.g. `RESPECT NULLS`).
2366    RespectNulls,
2367}
2368
2369impl fmt::Display for NullTreatment {
2370    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2371        f.write_str(match self {
2372            NullTreatment::IgnoreNulls => "IGNORE NULLS",
2373            NullTreatment::RespectNulls => "RESPECT NULLS",
2374        })
2375    }
2376}
2377
2378/// Specifies [WindowFrame]'s `start_bound` and `end_bound`
2379#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2380#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2381#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2382pub enum WindowFrameBound {
2383    /// `CURRENT ROW`
2384    CurrentRow,
2385    /// `<N> PRECEDING` or `UNBOUNDED PRECEDING`
2386    Preceding(Option<Box<Expr>>),
2387    /// `<N> FOLLOWING` or `UNBOUNDED FOLLOWING`.
2388    Following(Option<Box<Expr>>),
2389}
2390
2391impl fmt::Display for WindowFrameBound {
2392    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2393        match self {
2394            WindowFrameBound::CurrentRow => f.write_str("CURRENT ROW"),
2395            WindowFrameBound::Preceding(None) => f.write_str("UNBOUNDED PRECEDING"),
2396            WindowFrameBound::Following(None) => f.write_str("UNBOUNDED FOLLOWING"),
2397            WindowFrameBound::Preceding(Some(n)) => write!(f, "{n} PRECEDING"),
2398            WindowFrameBound::Following(Some(n)) => write!(f, "{n} FOLLOWING"),
2399        }
2400    }
2401}
2402
2403#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2404#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2405#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2406/// Indicates partition operation type for partition management statements.
2407pub enum AddDropSync {
2408    /// Add partitions.
2409    ADD,
2410    /// Drop partitions.
2411    DROP,
2412    /// Sync partitions.
2413    SYNC,
2414}
2415
2416impl fmt::Display for AddDropSync {
2417    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2418        match self {
2419            AddDropSync::SYNC => f.write_str("SYNC PARTITIONS"),
2420            AddDropSync::DROP => f.write_str("DROP PARTITIONS"),
2421            AddDropSync::ADD => f.write_str("ADD PARTITIONS"),
2422        }
2423    }
2424}
2425
2426#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2427#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2428#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2429/// Object kinds supported by `SHOW CREATE` statements.
2430pub enum ShowCreateObject {
2431    /// An event object for `SHOW CREATE EVENT`.
2432    Event,
2433    /// A function object for `SHOW CREATE FUNCTION`.
2434    Function,
2435    /// A procedure object for `SHOW CREATE PROCEDURE`.
2436    Procedure,
2437    /// A table object for `SHOW CREATE TABLE`.
2438    Table,
2439    /// A trigger object for `SHOW CREATE TRIGGER`.
2440    Trigger,
2441    /// A view object for `SHOW CREATE VIEW`.
2442    View,
2443}
2444
2445impl fmt::Display for ShowCreateObject {
2446    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2447        match self {
2448            ShowCreateObject::Event => f.write_str("EVENT"),
2449            ShowCreateObject::Function => f.write_str("FUNCTION"),
2450            ShowCreateObject::Procedure => f.write_str("PROCEDURE"),
2451            ShowCreateObject::Table => f.write_str("TABLE"),
2452            ShowCreateObject::Trigger => f.write_str("TRIGGER"),
2453            ShowCreateObject::View => f.write_str("VIEW"),
2454        }
2455    }
2456}
2457
2458#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2459#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2460#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2461/// Objects that can be targeted by a `COMMENT` statement.
2462pub enum CommentObject {
2463    /// A collation.
2464    Collation,
2465    /// A table column.
2466    Column,
2467    /// A database.
2468    Database,
2469    /// A domain.
2470    Domain,
2471    /// An extension.
2472    Extension,
2473    /// A function.
2474    Function,
2475    /// An index.
2476    Index,
2477    /// A materialized view.
2478    MaterializedView,
2479    /// A procedure.
2480    Procedure,
2481    /// A role.
2482    Role,
2483    /// A schema.
2484    Schema,
2485    /// A sequence.
2486    Sequence,
2487    /// A table.
2488    Table,
2489    /// A type.
2490    Type,
2491    /// A user.
2492    User,
2493    /// A view.
2494    View,
2495}
2496
2497impl fmt::Display for CommentObject {
2498    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2499        match self {
2500            CommentObject::Collation => f.write_str("COLLATION"),
2501            CommentObject::Column => f.write_str("COLUMN"),
2502            CommentObject::Database => f.write_str("DATABASE"),
2503            CommentObject::Domain => f.write_str("DOMAIN"),
2504            CommentObject::Extension => f.write_str("EXTENSION"),
2505            CommentObject::Function => f.write_str("FUNCTION"),
2506            CommentObject::Index => f.write_str("INDEX"),
2507            CommentObject::MaterializedView => f.write_str("MATERIALIZED VIEW"),
2508            CommentObject::Procedure => f.write_str("PROCEDURE"),
2509            CommentObject::Role => f.write_str("ROLE"),
2510            CommentObject::Schema => f.write_str("SCHEMA"),
2511            CommentObject::Sequence => f.write_str("SEQUENCE"),
2512            CommentObject::Table => f.write_str("TABLE"),
2513            CommentObject::Type => f.write_str("TYPE"),
2514            CommentObject::User => f.write_str("USER"),
2515            CommentObject::View => f.write_str("VIEW"),
2516        }
2517    }
2518}
2519
2520#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2521#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2522#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2523/// Password specification variants used in user-related statements.
2524pub enum Password {
2525    /// A concrete password expression.
2526    Password(Expr),
2527    /// Represents a `NULL` password.
2528    NullPassword,
2529}
2530
2531/// A `CASE` statement.
2532///
2533/// Examples:
2534/// ```sql
2535/// CASE
2536///     WHEN EXISTS(SELECT 1)
2537///         THEN SELECT 1 FROM T;
2538///     WHEN EXISTS(SELECT 2)
2539///         THEN SELECT 1 FROM U;
2540///     ELSE
2541///         SELECT 1 FROM V;
2542/// END CASE;
2543/// ```
2544///
2545/// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#case_search_expression)
2546/// [Snowflake](https://docs.snowflake.com/en/sql-reference/snowflake-scripting/case)
2547#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2548#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2549#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2550pub struct CaseStatement {
2551    /// The `CASE` token that starts the statement.
2552    pub case_token: AttachedToken,
2553    /// Optional expression to match against in `CASE ... WHEN`.
2554    pub match_expr: Option<Expr>,
2555    /// The `WHEN ... THEN` blocks of the `CASE` statement.
2556    pub when_blocks: Vec<ConditionalStatementBlock>,
2557    /// Optional `ELSE` block for the `CASE` statement.
2558    pub else_block: Option<ConditionalStatementBlock>,
2559    /// The last token of the statement (`END` or `CASE`).
2560    pub end_case_token: AttachedToken,
2561}
2562
2563impl fmt::Display for CaseStatement {
2564    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2565        let CaseStatement {
2566            case_token: _,
2567            match_expr,
2568            when_blocks,
2569            else_block,
2570            end_case_token: AttachedToken(end),
2571        } = self;
2572
2573        write!(f, "CASE")?;
2574
2575        if let Some(expr) = match_expr {
2576            write!(f, " {expr}")?;
2577        }
2578
2579        if !when_blocks.is_empty() {
2580            write!(f, " {}", display_separated(when_blocks, " "))?;
2581        }
2582
2583        if let Some(else_block) = else_block {
2584            write!(f, " {else_block}")?;
2585        }
2586
2587        write!(f, " END")?;
2588
2589        if let Token::Word(w) = &end.token {
2590            if w.keyword == Keyword::CASE {
2591                write!(f, " CASE")?;
2592            }
2593        }
2594
2595        Ok(())
2596    }
2597}
2598
2599/// An `IF` statement.
2600///
2601/// Example (BigQuery or Snowflake):
2602/// ```sql
2603/// IF TRUE THEN
2604///     SELECT 1;
2605///     SELECT 2;
2606/// ELSEIF TRUE THEN
2607///     SELECT 3;
2608/// ELSE
2609///     SELECT 4;
2610/// END IF
2611/// ```
2612/// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#if)
2613/// [Snowflake](https://docs.snowflake.com/en/sql-reference/snowflake-scripting/if)
2614///
2615/// Example (MSSQL):
2616/// ```sql
2617/// IF 1=1 SELECT 1 ELSE SELECT 2
2618/// ```
2619/// [MSSQL](https://learn.microsoft.com/en-us/sql/t-sql/language-elements/if-else-transact-sql?view=sql-server-ver16)
2620#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2621#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2622#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2623pub struct IfStatement {
2624    /// The initial `IF` block containing the condition and statements.
2625    pub if_block: ConditionalStatementBlock,
2626    /// Additional `ELSEIF` blocks.
2627    pub elseif_blocks: Vec<ConditionalStatementBlock>,
2628    /// Optional `ELSE` block.
2629    pub else_block: Option<ConditionalStatementBlock>,
2630    /// Optional trailing `END` token for the `IF` statement.
2631    pub end_token: Option<AttachedToken>,
2632}
2633
2634impl fmt::Display for IfStatement {
2635    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2636        let IfStatement {
2637            if_block,
2638            elseif_blocks,
2639            else_block,
2640            end_token,
2641        } = self;
2642
2643        write!(f, "{if_block}")?;
2644
2645        for elseif_block in elseif_blocks {
2646            write!(f, " {elseif_block}")?;
2647        }
2648
2649        if let Some(else_block) = else_block {
2650            write!(f, " {else_block}")?;
2651        }
2652
2653        if let Some(AttachedToken(end_token)) = end_token {
2654            write!(f, " END {end_token}")?;
2655        }
2656
2657        Ok(())
2658    }
2659}
2660
2661/// A `WHILE` statement.
2662///
2663/// Example:
2664/// ```sql
2665/// WHILE @@FETCH_STATUS = 0
2666/// BEGIN
2667///    FETCH NEXT FROM c1 INTO @var1, @var2;
2668/// END
2669/// ```
2670///
2671/// [MsSql](https://learn.microsoft.com/en-us/sql/t-sql/language-elements/while-transact-sql)
2672#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2673#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2674#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2675pub struct WhileStatement {
2676    /// Block executed while the condition holds.
2677    pub while_block: ConditionalStatementBlock,
2678}
2679
2680impl fmt::Display for WhileStatement {
2681    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2682        let WhileStatement { while_block } = self;
2683        write!(f, "{while_block}")?;
2684        Ok(())
2685    }
2686}
2687
2688/// A block within a [Statement::Case] or [Statement::If] or [Statement::While]-like statement
2689///
2690/// Example 1:
2691/// ```sql
2692/// WHEN EXISTS(SELECT 1) THEN SELECT 1;
2693/// ```
2694///
2695/// Example 2:
2696/// ```sql
2697/// IF TRUE THEN SELECT 1; SELECT 2;
2698/// ```
2699///
2700/// Example 3:
2701/// ```sql
2702/// ELSE SELECT 1; SELECT 2;
2703/// ```
2704///
2705/// Example 4:
2706/// ```sql
2707/// WHILE @@FETCH_STATUS = 0
2708/// BEGIN
2709///    FETCH NEXT FROM c1 INTO @var1, @var2;
2710/// END
2711/// ```
2712#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2713#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2714#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2715pub struct ConditionalStatementBlock {
2716    /// Token representing the start of the block (e.g., WHEN/IF/WHILE).
2717    pub start_token: AttachedToken,
2718    /// Optional condition expression for the block.
2719    pub condition: Option<Expr>,
2720    /// Optional token for the `THEN` keyword.
2721    pub then_token: Option<AttachedToken>,
2722    /// The statements contained in this conditional block.
2723    pub conditional_statements: ConditionalStatements,
2724}
2725
2726impl ConditionalStatementBlock {
2727    /// Get the statements in this conditional block.
2728    pub fn statements(&self) -> &Vec<Statement> {
2729        self.conditional_statements.statements()
2730    }
2731}
2732
2733impl fmt::Display for ConditionalStatementBlock {
2734    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2735        let ConditionalStatementBlock {
2736            start_token: AttachedToken(start_token),
2737            condition,
2738            then_token,
2739            conditional_statements,
2740        } = self;
2741
2742        write!(f, "{start_token}")?;
2743
2744        if let Some(condition) = condition {
2745            write!(f, " {condition}")?;
2746        }
2747
2748        if then_token.is_some() {
2749            write!(f, " THEN")?;
2750        }
2751
2752        if !conditional_statements.statements().is_empty() {
2753            write!(f, " {conditional_statements}")?;
2754        }
2755
2756        Ok(())
2757    }
2758}
2759
2760/// A list of statements in a [ConditionalStatementBlock].
2761#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2762#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2763#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2764/// Statements used inside conditional blocks (`IF`, `WHEN`, `WHILE`).
2765pub enum ConditionalStatements {
2766    /// Simple sequence of statements (no `BEGIN`/`END`).
2767    Sequence {
2768        /// The statements in the sequence.
2769        statements: Vec<Statement>,
2770    },
2771    /// Block enclosed by `BEGIN` and `END`.
2772    BeginEnd(BeginEndStatements),
2773}
2774
2775impl ConditionalStatements {
2776    /// Get the statements in this conditional statements block.
2777    pub fn statements(&self) -> &Vec<Statement> {
2778        match self {
2779            ConditionalStatements::Sequence { statements } => statements,
2780            ConditionalStatements::BeginEnd(bes) => &bes.statements,
2781        }
2782    }
2783}
2784
2785impl fmt::Display for ConditionalStatements {
2786    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2787        match self {
2788            ConditionalStatements::Sequence { statements } => {
2789                if !statements.is_empty() {
2790                    format_statement_list(f, statements)?;
2791                }
2792                Ok(())
2793            }
2794            ConditionalStatements::BeginEnd(bes) => write!(f, "{bes}"),
2795        }
2796    }
2797}
2798
2799/// Represents a list of statements enclosed within `BEGIN` and `END` keywords.
2800/// Example:
2801/// ```sql
2802/// BEGIN
2803///     SELECT 1;
2804///     SELECT 2;
2805/// END
2806/// ```
2807#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2808#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2809#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2810pub struct BeginEndStatements {
2811    /// Token representing the `BEGIN` keyword (may include span info).
2812    pub begin_token: AttachedToken,
2813    /// Statements contained within the block.
2814    pub statements: Vec<Statement>,
2815    /// Token representing the `END` keyword (may include span info).
2816    pub end_token: AttachedToken,
2817}
2818
2819impl fmt::Display for BeginEndStatements {
2820    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2821        let BeginEndStatements {
2822            begin_token: AttachedToken(begin_token),
2823            statements,
2824            end_token: AttachedToken(end_token),
2825        } = self;
2826
2827        if begin_token.token != Token::EOF {
2828            write!(f, "{begin_token} ")?;
2829        }
2830        if !statements.is_empty() {
2831            format_statement_list(f, statements)?;
2832        }
2833        if end_token.token != Token::EOF {
2834            write!(f, " {end_token}")?;
2835        }
2836        Ok(())
2837    }
2838}
2839
2840/// A `RAISE` statement.
2841///
2842/// Examples:
2843/// ```sql
2844/// RAISE USING MESSAGE = 'error';
2845///
2846/// RAISE myerror;
2847/// ```
2848///
2849/// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#raise)
2850/// [Snowflake](https://docs.snowflake.com/en/sql-reference/snowflake-scripting/raise)
2851#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2852#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2853#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2854pub struct RaiseStatement {
2855    /// Optional value provided to the RAISE statement.
2856    pub value: Option<RaiseStatementValue>,
2857}
2858
2859impl fmt::Display for RaiseStatement {
2860    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2861        let RaiseStatement { value } = self;
2862
2863        write!(f, "RAISE")?;
2864        if let Some(value) = value {
2865            write!(f, " {value}")?;
2866        }
2867
2868        Ok(())
2869    }
2870}
2871
2872/// Represents the error value of a [RaiseStatement].
2873#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2874#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2875#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2876pub enum RaiseStatementValue {
2877    /// `RAISE USING MESSAGE = 'error'`
2878    UsingMessage(Expr),
2879    /// `RAISE myerror`
2880    Expr(Expr),
2881}
2882
2883impl fmt::Display for RaiseStatementValue {
2884    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2885        match self {
2886            RaiseStatementValue::Expr(expr) => write!(f, "{expr}"),
2887            RaiseStatementValue::UsingMessage(expr) => write!(f, "USING MESSAGE = {expr}"),
2888        }
2889    }
2890}
2891
2892/// A MSSQL `THROW` statement.
2893///
2894/// ```sql
2895/// THROW [ error_number, message, state ]
2896/// ```
2897///
2898/// [MSSQL](https://learn.microsoft.com/en-us/sql/t-sql/language-elements/throw-transact-sql)
2899#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2900#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2901#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2902pub struct ThrowStatement {
2903    /// Error number expression.
2904    pub error_number: Option<Box<Expr>>,
2905    /// Error message expression.
2906    pub message: Option<Box<Expr>>,
2907    /// State expression.
2908    pub state: Option<Box<Expr>>,
2909}
2910
2911impl fmt::Display for ThrowStatement {
2912    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2913        let ThrowStatement {
2914            error_number,
2915            message,
2916            state,
2917        } = self;
2918
2919        write!(f, "THROW")?;
2920        if let (Some(error_number), Some(message), Some(state)) = (error_number, message, state) {
2921            write!(f, " {error_number}, {message}, {state}")?;
2922        }
2923        Ok(())
2924    }
2925}
2926
2927/// Represents an expression assignment within a variable `DECLARE` statement.
2928///
2929/// Examples:
2930/// ```sql
2931/// DECLARE variable_name := 42
2932/// DECLARE variable_name DEFAULT 42
2933/// ```
2934#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2935#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2936#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2937pub enum DeclareAssignment {
2938    /// Plain expression specified.
2939    Expr(Box<Expr>),
2940
2941    /// Expression assigned via the `DEFAULT` keyword
2942    Default(Box<Expr>),
2943
2944    /// Expression assigned via the `:=` syntax
2945    ///
2946    /// Example:
2947    /// ```sql
2948    /// DECLARE variable_name := 42;
2949    /// ```
2950    DuckAssignment(Box<Expr>),
2951
2952    /// Expression via the `FOR` keyword
2953    ///
2954    /// Example:
2955    /// ```sql
2956    /// DECLARE c1 CURSOR FOR res
2957    /// ```
2958    For(Box<Expr>),
2959
2960    /// Expression via the `=` syntax.
2961    ///
2962    /// Example:
2963    /// ```sql
2964    /// DECLARE @variable AS INT = 100
2965    /// ```
2966    MsSqlAssignment(Box<Expr>),
2967}
2968
2969impl fmt::Display for DeclareAssignment {
2970    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2971        match self {
2972            DeclareAssignment::Expr(expr) => {
2973                write!(f, "{expr}")
2974            }
2975            DeclareAssignment::Default(expr) => {
2976                write!(f, "DEFAULT {expr}")
2977            }
2978            DeclareAssignment::DuckAssignment(expr) => {
2979                write!(f, ":= {expr}")
2980            }
2981            DeclareAssignment::MsSqlAssignment(expr) => {
2982                write!(f, "= {expr}")
2983            }
2984            DeclareAssignment::For(expr) => {
2985                write!(f, "FOR {expr}")
2986            }
2987        }
2988    }
2989}
2990
2991/// Represents the type of a `DECLARE` statement.
2992#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2993#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2994#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2995pub enum DeclareType {
2996    /// Cursor variable type. e.g. [Snowflake] [PostgreSQL] [MsSql]
2997    ///
2998    /// [Snowflake]: https://docs.snowflake.com/en/developer-guide/snowflake-scripting/cursors#declaring-a-cursor
2999    /// [PostgreSQL]: https://www.postgresql.org/docs/current/plpgsql-cursors.html
3000    /// [MsSql]: https://learn.microsoft.com/en-us/sql/t-sql/language-elements/declare-cursor-transact-sql
3001    Cursor,
3002
3003    /// Result set variable type. [Snowflake]
3004    ///
3005    /// Syntax:
3006    /// ```text
3007    /// <resultset_name> RESULTSET [ { DEFAULT | := } ( <query> ) ] ;
3008    /// ```
3009    /// [Snowflake]: https://docs.snowflake.com/en/sql-reference/snowflake-scripting/declare#resultset-declaration-syntax
3010    ResultSet,
3011
3012    /// Exception declaration syntax. [Snowflake]
3013    ///
3014    /// Syntax:
3015    /// ```text
3016    /// <exception_name> EXCEPTION [ ( <exception_number> , '<exception_message>' ) ] ;
3017    /// ```
3018    /// [Snowflake]: https://docs.snowflake.com/en/sql-reference/snowflake-scripting/declare#exception-declaration-syntax
3019    Exception,
3020}
3021
3022impl fmt::Display for DeclareType {
3023    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3024        match self {
3025            DeclareType::Cursor => {
3026                write!(f, "CURSOR")
3027            }
3028            DeclareType::ResultSet => {
3029                write!(f, "RESULTSET")
3030            }
3031            DeclareType::Exception => {
3032                write!(f, "EXCEPTION")
3033            }
3034        }
3035    }
3036}
3037
3038/// A `DECLARE` statement.
3039/// [PostgreSQL] [Snowflake] [BigQuery]
3040///
3041/// Examples:
3042/// ```sql
3043/// DECLARE variable_name := 42
3044/// DECLARE liahona CURSOR FOR SELECT * FROM films;
3045/// ```
3046///
3047/// [PostgreSQL]: https://www.postgresql.org/docs/current/sql-declare.html
3048/// [Snowflake]: https://docs.snowflake.com/en/sql-reference/snowflake-scripting/declare
3049/// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#declare
3050#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3051#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3052#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3053pub struct Declare {
3054    /// The name(s) being declared.
3055    /// Example: `DECLARE a, b, c DEFAULT 42;
3056    pub names: Vec<Ident>,
3057    /// Data-type assigned to the declared variable.
3058    /// Example: `DECLARE x INT64 DEFAULT 42;
3059    pub data_type: Option<DataType>,
3060    /// Expression being assigned to the declared variable.
3061    pub assignment: Option<DeclareAssignment>,
3062    /// Represents the type of the declared variable.
3063    pub declare_type: Option<DeclareType>,
3064    /// Causes the cursor to return data in binary rather than in text format.
3065    pub binary: Option<bool>,
3066    /// None = Not specified
3067    /// Some(true) = INSENSITIVE
3068    /// Some(false) = ASENSITIVE
3069    pub sensitive: Option<bool>,
3070    /// None = Not specified
3071    /// Some(true) = SCROLL
3072    /// Some(false) = NO SCROLL
3073    pub scroll: Option<bool>,
3074    /// None = Not specified
3075    /// Some(true) = WITH HOLD, specifies that the cursor can continue to be used after the transaction that created it successfully commits
3076    /// Some(false) = WITHOUT HOLD, specifies that the cursor cannot be used outside of the transaction that created it
3077    pub hold: Option<bool>,
3078    /// `FOR <query>` clause in a CURSOR declaration.
3079    pub for_query: Option<Box<Query>>,
3080}
3081
3082impl fmt::Display for Declare {
3083    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3084        let Declare {
3085            names,
3086            data_type,
3087            assignment,
3088            declare_type,
3089            binary,
3090            sensitive,
3091            scroll,
3092            hold,
3093            for_query,
3094        } = self;
3095        write!(f, "{}", display_comma_separated(names))?;
3096
3097        if let Some(true) = binary {
3098            write!(f, " BINARY")?;
3099        }
3100
3101        if let Some(sensitive) = sensitive {
3102            if *sensitive {
3103                write!(f, " INSENSITIVE")?;
3104            } else {
3105                write!(f, " ASENSITIVE")?;
3106            }
3107        }
3108
3109        if let Some(scroll) = scroll {
3110            if *scroll {
3111                write!(f, " SCROLL")?;
3112            } else {
3113                write!(f, " NO SCROLL")?;
3114            }
3115        }
3116
3117        if let Some(declare_type) = declare_type {
3118            write!(f, " {declare_type}")?;
3119        }
3120
3121        if let Some(hold) = hold {
3122            if *hold {
3123                write!(f, " WITH HOLD")?;
3124            } else {
3125                write!(f, " WITHOUT HOLD")?;
3126            }
3127        }
3128
3129        if let Some(query) = for_query {
3130            write!(f, " FOR {query}")?;
3131        }
3132
3133        if let Some(data_type) = data_type {
3134            write!(f, " {data_type}")?;
3135        }
3136
3137        if let Some(expr) = assignment {
3138            write!(f, " {expr}")?;
3139        }
3140        Ok(())
3141    }
3142}
3143
3144/// Sql options of a `CREATE TABLE` statement.
3145#[derive(Debug, Default, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3146#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3147#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3148/// Options allowed within a `CREATE TABLE` statement.
3149pub enum CreateTableOptions {
3150    /// No options specified.
3151    #[default]
3152    None,
3153    /// Options specified using the `WITH` keyword, e.g. `WITH (k = v)`.
3154    With(Vec<SqlOption>),
3155    /// Options specified using the `OPTIONS(...)` clause.
3156    Options(Vec<SqlOption>),
3157    /// Plain space-separated options.
3158    Plain(Vec<SqlOption>),
3159    /// Table properties (e.g., TBLPROPERTIES / storage properties).
3160    TableProperties(Vec<SqlOption>),
3161}
3162
3163impl fmt::Display for CreateTableOptions {
3164    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3165        match self {
3166            CreateTableOptions::With(with_options) => {
3167                write!(f, "WITH ({})", display_comma_separated(with_options))
3168            }
3169            CreateTableOptions::Options(options) => {
3170                write!(f, "OPTIONS({})", display_comma_separated(options))
3171            }
3172            CreateTableOptions::TableProperties(options) => {
3173                write!(f, "TBLPROPERTIES ({})", display_comma_separated(options))
3174            }
3175            CreateTableOptions::Plain(options) => {
3176                write!(f, "{}", display_separated(options, " "))
3177            }
3178            CreateTableOptions::None => Ok(()),
3179        }
3180    }
3181}
3182
3183/// A `FROM` clause within a `DELETE` statement.
3184///
3185/// Syntax
3186/// ```sql
3187/// [FROM] table
3188/// ```
3189#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3190#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3191#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3192pub enum FromTable {
3193    /// An explicit `FROM` keyword was specified.
3194    WithFromKeyword(Vec<TableWithJoins>),
3195    /// BigQuery: `FROM` keyword was omitted.
3196    /// <https://cloud.google.com/bigquery/docs/reference/standard-sql/dml-syntax#delete_statement>
3197    WithoutKeyword(Vec<TableWithJoins>),
3198}
3199impl Display for FromTable {
3200    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3201        match self {
3202            FromTable::WithFromKeyword(tables) => {
3203                write!(f, "FROM {}", display_comma_separated(tables))
3204            }
3205            FromTable::WithoutKeyword(tables) => {
3206                write!(f, "{}", display_comma_separated(tables))
3207            }
3208        }
3209    }
3210}
3211
3212#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3213#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3214#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3215/// Variants for the `SET` family of statements.
3216pub enum Set {
3217    /// SQL Standard-style
3218    /// SET a = 1;
3219    /// `SET var = value` (standard SQL-style assignment).
3220    SingleAssignment {
3221        /// Optional scope modifier (`SESSION` / `LOCAL`).
3222        scope: Option<ContextModifier>,
3223        /// Whether this is a Hive-style `HIVEVAR:` assignment.
3224        hivevar: bool,
3225        /// Variable name to assign.
3226        variable: ObjectName,
3227        /// Values assigned to the variable.
3228        values: Vec<Expr>,
3229    },
3230    /// Snowflake-style
3231    /// SET (a, b, ..) = (1, 2, ..);
3232    /// `SET (a, b) = (1, 2)` (tuple assignment syntax).
3233    ParenthesizedAssignments {
3234        /// Variables being assigned in tuple form.
3235        variables: Vec<ObjectName>,
3236        /// Corresponding values for the variables.
3237        values: Vec<Expr>,
3238    },
3239    /// MySQL-style
3240    /// SET a = 1, b = 2, ..;
3241    /// `SET a = 1, b = 2` (MySQL-style comma-separated assignments).
3242    MultipleAssignments {
3243        /// List of `SET` assignments (MySQL-style comma-separated).
3244        assignments: Vec<SetAssignment>,
3245    },
3246    /// Session authorization for Postgres/Redshift
3247    ///
3248    /// ```sql
3249    /// SET SESSION AUTHORIZATION { user_name | DEFAULT }
3250    /// ```
3251    ///
3252    /// See <https://www.postgresql.org/docs/current/sql-set-session-authorization.html>
3253    /// See <https://docs.aws.amazon.com/redshift/latest/dg/r_SET_SESSION_AUTHORIZATION.html>
3254    SetSessionAuthorization(SetSessionAuthorizationParam),
3255    /// MS-SQL session
3256    ///
3257    /// See <https://learn.microsoft.com/en-us/sql/t-sql/statements/set-statements-transact-sql>
3258    SetSessionParam(SetSessionParamKind),
3259    /// ```sql
3260    /// SET [ SESSION | LOCAL ] ROLE role_name
3261    /// ```
3262    ///
3263    /// Sets session state. Examples: [ANSI][1], [Postgresql][2], [MySQL][3], and [Oracle][4]
3264    ///
3265    /// [1]: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#set-role-statement
3266    /// [2]: https://www.postgresql.org/docs/14/sql-set-role.html
3267    /// [3]: https://dev.mysql.com/doc/refman/8.0/en/set-role.html
3268    /// [4]: https://docs.oracle.com/cd/B19306_01/server.102/b14200/statements_10004.htm
3269    SetRole {
3270        /// Non-ANSI optional identifier to inform if the role is defined inside the current session (`SESSION`) or transaction (`LOCAL`).
3271        context_modifier: Option<ContextModifier>,
3272        /// Role name. If NONE is specified, then the current role name is removed.
3273        role_name: Option<Ident>,
3274    },
3275    /// ```sql
3276    /// SET TIME ZONE <value>
3277    /// ```
3278    ///
3279    /// Note: this is a PostgreSQL-specific statements
3280    /// `SET TIME ZONE <value>` is an alias for `SET timezone TO <value>` in PostgreSQL
3281    /// However, we allow it for all dialects.
3282    /// `SET TIME ZONE` statement. `local` indicates the `LOCAL` keyword.
3283    /// `SET TIME ZONE <value>` statement.
3284    SetTimeZone {
3285        /// Whether the `LOCAL` keyword was specified.
3286        local: bool,
3287        /// Time zone expression value.
3288        value: Expr,
3289    },
3290    /// ```sql
3291    /// SET NAMES 'charset_name' [COLLATE 'collation_name']
3292    /// ```
3293    SetNames {
3294        /// Character set name to set.
3295        charset_name: Ident,
3296        /// Optional collation name.
3297        collation_name: Option<String>,
3298    },
3299    /// ```sql
3300    /// SET NAMES DEFAULT
3301    /// ```
3302    ///
3303    /// Note: this is a MySQL-specific statement.
3304    SetNamesDefault {},
3305    /// ```sql
3306    /// SET TRANSACTION ...
3307    /// ```
3308    SetTransaction {
3309        /// Transaction modes (e.g., ISOLATION LEVEL, READ ONLY).
3310        modes: Vec<TransactionMode>,
3311        /// Optional snapshot value for transaction snapshot control.
3312        snapshot: Option<ValueWithSpan>,
3313        /// `true` when the `SESSION` keyword was used.
3314        session: bool,
3315    },
3316}
3317
3318impl Display for Set {
3319    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3320        match self {
3321            Self::ParenthesizedAssignments { variables, values } => write!(
3322                f,
3323                "SET ({}) = ({})",
3324                display_comma_separated(variables),
3325                display_comma_separated(values)
3326            ),
3327            Self::MultipleAssignments { assignments } => {
3328                write!(f, "SET {}", display_comma_separated(assignments))
3329            }
3330            Self::SetRole {
3331                context_modifier,
3332                role_name,
3333            } => {
3334                let role_name = role_name.clone().unwrap_or_else(|| Ident::new("NONE"));
3335                write!(
3336                    f,
3337                    "SET {modifier}ROLE {role_name}",
3338                    modifier = context_modifier.map(|m| format!("{m}")).unwrap_or_default()
3339                )
3340            }
3341            Self::SetSessionAuthorization(kind) => write!(f, "SET SESSION AUTHORIZATION {kind}"),
3342            Self::SetSessionParam(kind) => write!(f, "SET {kind}"),
3343            Self::SetTransaction {
3344                modes,
3345                snapshot,
3346                session,
3347            } => {
3348                if *session {
3349                    write!(f, "SET SESSION CHARACTERISTICS AS TRANSACTION")?;
3350                } else {
3351                    write!(f, "SET TRANSACTION")?;
3352                }
3353                if !modes.is_empty() {
3354                    write!(f, " {}", display_comma_separated(modes))?;
3355                }
3356                if let Some(snapshot_id) = snapshot {
3357                    write!(f, " SNAPSHOT {snapshot_id}")?;
3358                }
3359                Ok(())
3360            }
3361            Self::SetTimeZone { local, value } => {
3362                f.write_str("SET ")?;
3363                if *local {
3364                    f.write_str("LOCAL ")?;
3365                }
3366                write!(f, "TIME ZONE {value}")
3367            }
3368            Self::SetNames {
3369                charset_name,
3370                collation_name,
3371            } => {
3372                write!(f, "SET NAMES {charset_name}")?;
3373
3374                if let Some(collation) = collation_name {
3375                    f.write_str(" COLLATE ")?;
3376                    f.write_str(collation)?;
3377                };
3378
3379                Ok(())
3380            }
3381            Self::SetNamesDefault {} => {
3382                f.write_str("SET NAMES DEFAULT")?;
3383
3384                Ok(())
3385            }
3386            Set::SingleAssignment {
3387                scope,
3388                hivevar,
3389                variable,
3390                values,
3391            } => {
3392                write!(
3393                    f,
3394                    "SET {}{}{} = {}",
3395                    scope.map(|s| format!("{s}")).unwrap_or_default(),
3396                    if *hivevar { "HIVEVAR:" } else { "" },
3397                    variable,
3398                    display_comma_separated(values)
3399                )
3400            }
3401        }
3402    }
3403}
3404
3405/// A representation of a `WHEN` arm with all the identifiers catched and the statements to execute
3406/// for the arm.
3407///
3408/// Snowflake: <https://docs.snowflake.com/en/sql-reference/snowflake-scripting/exception>
3409/// BigQuery: <https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#beginexceptionend>
3410#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3411#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3412#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3413pub struct ExceptionWhen {
3414    /// Identifiers that trigger this branch (error conditions).
3415    pub idents: Vec<Ident>,
3416    /// Statements to execute when the condition matches.
3417    pub statements: Vec<Statement>,
3418}
3419
3420impl Display for ExceptionWhen {
3421    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3422        write!(
3423            f,
3424            "WHEN {idents} THEN",
3425            idents = display_separated(&self.idents, " OR ")
3426        )?;
3427
3428        if !self.statements.is_empty() {
3429            write!(f, " ")?;
3430            format_statement_list(f, &self.statements)?;
3431        }
3432
3433        Ok(())
3434    }
3435}
3436
3437/// ANALYZE statement
3438///
3439/// Supported syntax varies by dialect:
3440/// - Hive: `ANALYZE TABLE t [PARTITION (...)] COMPUTE STATISTICS [NOSCAN] [FOR COLUMNS [col1, ...]] [CACHE METADATA]`
3441/// - PostgreSQL: `ANALYZE [VERBOSE] [t [(col1, ...)]]` See <https://www.postgresql.org/docs/current/sql-analyze.html>
3442/// - General: `ANALYZE [TABLE] t`
3443#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3444#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3445#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3446pub struct Analyze {
3447    #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
3448    /// Name of the table to analyze. `None` for bare `ANALYZE`.
3449    pub table_name: Option<ObjectName>,
3450    /// Optional partition expressions to restrict the analysis.
3451    pub partitions: Option<Vec<Expr>>,
3452    /// `true` when analyzing specific columns (Hive `FOR COLUMNS` syntax).
3453    pub for_columns: bool,
3454    /// Columns to analyze.
3455    pub columns: Vec<Ident>,
3456    /// Whether to cache metadata before analyzing.
3457    pub cache_metadata: bool,
3458    /// Whether to skip scanning the table.
3459    pub noscan: bool,
3460    /// Whether to compute statistics during analysis.
3461    pub compute_statistics: bool,
3462    /// Whether the `TABLE` keyword was present.
3463    pub has_table_keyword: bool,
3464}
3465
3466impl fmt::Display for Analyze {
3467    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3468        write!(f, "ANALYZE")?;
3469        if let Some(ref table_name) = self.table_name {
3470            if self.has_table_keyword {
3471                write!(f, " TABLE")?;
3472            }
3473            write!(f, " {table_name}")?;
3474        }
3475        if !self.for_columns && !self.columns.is_empty() {
3476            write!(f, " ({})", display_comma_separated(&self.columns))?;
3477        }
3478        if let Some(ref parts) = self.partitions {
3479            if !parts.is_empty() {
3480                write!(f, " PARTITION ({})", display_comma_separated(parts))?;
3481            }
3482        }
3483        if self.compute_statistics {
3484            write!(f, " COMPUTE STATISTICS")?;
3485        }
3486        if self.noscan {
3487            write!(f, " NOSCAN")?;
3488        }
3489        if self.cache_metadata {
3490            write!(f, " CACHE METADATA")?;
3491        }
3492        if self.for_columns {
3493            write!(f, " FOR COLUMNS")?;
3494            if !self.columns.is_empty() {
3495                write!(f, " {}", display_comma_separated(&self.columns))?;
3496            }
3497        }
3498        Ok(())
3499    }
3500}
3501
3502/// A top-level statement (SELECT, INSERT, CREATE, etc.)
3503#[allow(clippy::large_enum_variant)]
3504#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3505#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3506#[cfg_attr(
3507    feature = "visitor",
3508    derive(Visit, VisitMut),
3509    visit(with = "visit_statement")
3510)]
3511pub enum Statement {
3512    /// ```sql
3513    /// ANALYZE
3514    /// ```
3515    /// Analyze (Hive)
3516    Analyze(Analyze),
3517    /// `SET` statements (session, transaction, timezone, etc.).
3518    Set(Set),
3519    /// ```sql
3520    /// TRUNCATE
3521    /// ```
3522    /// Truncate (Hive)
3523    Truncate(Truncate),
3524    /// ```sql
3525    /// MSCK
3526    /// ```
3527    /// Msck (Hive)
3528    Msck(Msck),
3529    /// ```sql
3530    /// SELECT
3531    /// ```
3532    Query(Box<Query>),
3533    /// ```sql
3534    /// INSERT
3535    /// ```
3536    Insert(Insert),
3537    /// ```sql
3538    /// INSTALL
3539    /// ```
3540    Install {
3541        /// Only for DuckDB
3542        extension_name: Ident,
3543    },
3544    /// ```sql
3545    /// LOAD
3546    /// ```
3547    Load {
3548        /// Only for DuckDB
3549        extension_name: Ident,
3550    },
3551    // TODO: Support ROW FORMAT
3552    /// LOAD DATA from a directory or query source.
3553    Directory {
3554        /// Whether to overwrite existing files.
3555        overwrite: bool,
3556        /// Whether the directory is local to the server.
3557        local: bool,
3558        /// Path to the directory or files.
3559        path: String,
3560        /// Optional file format for the data.
3561        file_format: Option<FileFormat>,
3562        /// Source query providing data to load.
3563        source: Box<Query>,
3564    },
3565    /// A `CASE` statement.
3566    Case(CaseStatement),
3567    /// An `IF` statement.
3568    If(IfStatement),
3569    /// A `WHILE` statement.
3570    While(WhileStatement),
3571    /// A `RAISE` statement.
3572    Raise(RaiseStatement),
3573    /// ```sql
3574    /// CALL <function>
3575    /// ```
3576    Call(Function),
3577    /// ```sql
3578    /// COPY [TO | FROM] ...
3579    /// ```
3580    Copy {
3581        /// The source of 'COPY TO', or the target of 'COPY FROM'
3582        source: CopySource,
3583        /// If true, is a 'COPY TO' statement. If false is a 'COPY FROM'
3584        to: bool,
3585        /// The target of 'COPY TO', or the source of 'COPY FROM'
3586        target: CopyTarget,
3587        /// WITH options (from PostgreSQL version 9.0)
3588        options: Vec<CopyOption>,
3589        /// WITH options (before PostgreSQL version 9.0)
3590        legacy_options: Vec<CopyLegacyOption>,
3591        /// VALUES a vector of values to be copied
3592        values: Vec<Option<String>>,
3593    },
3594    /// ```sql
3595    /// COPY INTO <table> | <location>
3596    /// ```
3597    /// See:
3598    /// <https://docs.snowflake.com/en/sql-reference/sql/copy-into-table>
3599    /// <https://docs.snowflake.com/en/sql-reference/sql/copy-into-location>
3600    ///
3601    /// Copy Into syntax available for Snowflake is different than the one implemented in
3602    /// Postgres. Although they share common prefix, it is reasonable to implement them
3603    /// in different enums. This can be refactored later once custom dialects
3604    /// are allowed to have custom Statements.
3605    CopyIntoSnowflake {
3606        /// Kind of COPY INTO operation (table or location).
3607        kind: CopyIntoSnowflakeKind,
3608        /// Target object for the COPY INTO operation.
3609        into: ObjectName,
3610        /// Optional list of target columns.
3611        into_columns: Option<Vec<Ident>>,
3612        /// Optional source object name (staged data).
3613        from_obj: Option<ObjectName>,
3614        /// Optional alias for the source object.
3615        from_obj_alias: Option<Ident>,
3616        /// Stage-specific parameters (e.g., credentials, path).
3617        stage_params: StageParamsObject,
3618        /// Optional list of transformations applied when loading.
3619        from_transformations: Option<Vec<StageLoadSelectItemKind>>,
3620        /// Optional source query instead of a staged object.
3621        from_query: Option<Box<Query>>,
3622        /// Optional list of specific file names to load.
3623        files: Option<Vec<String>>,
3624        /// Optional filename matching pattern.
3625        pattern: Option<String>,
3626        /// File format options.
3627        file_format: KeyValueOptions,
3628        /// Additional copy options.
3629        copy_options: KeyValueOptions,
3630        /// Optional validation mode string.
3631        validation_mode: Option<String>,
3632        /// Optional partition expression for loading.
3633        partition: Option<Box<Expr>>,
3634    },
3635    /// ```sql
3636    /// OPEN cursor_name
3637    /// ```
3638    /// Opens a cursor.
3639    Open(OpenStatement),
3640    /// ```sql
3641    /// CLOSE
3642    /// ```
3643    /// Closes the portal underlying an open cursor.
3644    Close {
3645        /// Cursor name
3646        cursor: CloseCursor,
3647    },
3648    /// ```sql
3649    /// UPDATE
3650    /// ```
3651    Update(Update),
3652    /// ```sql
3653    /// DELETE
3654    /// ```
3655    Delete(Delete),
3656    /// ```sql
3657    /// CREATE VIEW
3658    /// ```
3659    CreateView(CreateView),
3660    /// ```sql
3661    /// CREATE TABLE
3662    /// ```
3663    CreateTable(CreateTable),
3664    /// ```sql
3665    /// CREATE VIRTUAL TABLE .. USING <module_name> (<module_args>)`
3666    /// ```
3667    /// Sqlite specific statement
3668    CreateVirtualTable {
3669        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
3670        /// Name of the virtual table module instance.
3671        name: ObjectName,
3672        /// `true` when `IF NOT EXISTS` was specified.
3673        if_not_exists: bool,
3674        /// Module name used by the virtual table.
3675        module_name: Ident,
3676        /// Arguments passed to the module.
3677        module_args: Vec<Ident>,
3678    },
3679    /// ```sql
3680    /// `CREATE INDEX`
3681    /// ```
3682    CreateIndex(CreateIndex),
3683    /// ```sql
3684    /// CREATE ROLE
3685    /// ```
3686    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createrole.html)
3687    CreateRole(CreateRole),
3688    /// ```sql
3689    /// CREATE SECRET
3690    /// ```
3691    /// See [DuckDB](https://duckdb.org/docs/sql/statements/create_secret.html)
3692    CreateSecret {
3693        /// `true` when `OR REPLACE` was specified.
3694        or_replace: bool,
3695        /// Optional `TEMPORARY` flag.
3696        temporary: Option<bool>,
3697        /// `true` when `IF NOT EXISTS` was present.
3698        if_not_exists: bool,
3699        /// Optional secret name.
3700        name: Option<Ident>,
3701        /// Optional storage specifier identifier.
3702        storage_specifier: Option<Ident>,
3703        /// The secret type identifier.
3704        secret_type: Ident,
3705        /// Additional secret options.
3706        options: Vec<SecretOption>,
3707    },
3708    /// A `CREATE SERVER` statement.
3709    CreateServer(CreateServerStatement),
3710    /// ```sql
3711    /// CREATE FOREIGN DATA WRAPPER
3712    /// ```
3713    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createforeigndatawrapper.html)
3714    CreateForeignDataWrapper(CreateForeignDataWrapper),
3715    /// ```sql
3716    /// CREATE FOREIGN TABLE
3717    /// ```
3718    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createforeigntable.html)
3719    CreateForeignTable(CreateForeignTable),
3720    /// ```sql
3721    /// CREATE POLICY
3722    /// ```
3723    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createpolicy.html)
3724    CreatePolicy(CreatePolicy),
3725    /// ```sql
3726    /// CREATE CONNECTOR
3727    /// ```
3728    /// See [Hive](https://cwiki.apache.org/confluence/pages/viewpage.action?pageId=27362034#LanguageManualDDL-CreateDataConnectorCreateConnector)
3729    CreateConnector(CreateConnector),
3730    /// ```sql
3731    /// CREATE OPERATOR
3732    /// ```
3733    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createoperator.html)
3734    CreateOperator(CreateOperator),
3735    /// ```sql
3736    /// CREATE OPERATOR FAMILY
3737    /// ```
3738    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createopfamily.html)
3739    CreateOperatorFamily(CreateOperatorFamily),
3740    /// ```sql
3741    /// CREATE OPERATOR CLASS
3742    /// ```
3743    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createopclass.html)
3744    CreateOperatorClass(CreateOperatorClass),
3745    /// ```sql
3746    /// CREATE AGGREGATE
3747    /// ```
3748    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createaggregate.html)
3749    CreateAggregate(CreateAggregate),
3750    /// ```sql
3751    /// ALTER TABLE
3752    /// ```
3753    AlterTable(AlterTable),
3754    /// ```sql
3755    /// ALTER SCHEMA
3756    /// ```
3757    /// See [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#alter_schema_collate_statement)
3758    AlterSchema(AlterSchema),
3759    /// ```sql
3760    /// ALTER INDEX
3761    /// ```
3762    AlterIndex {
3763        /// Name of the index to alter.
3764        name: ObjectName,
3765        /// The operation to perform on the index.
3766        operation: AlterIndexOperation,
3767    },
3768    /// ```sql
3769    /// ALTER VIEW
3770    /// ```
3771    AlterView {
3772        /// View name being altered.
3773        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
3774        name: ObjectName,
3775        /// Optional new column list for the view.
3776        columns: Vec<Ident>,
3777        /// Replacement query for the view definition.
3778        query: Box<Query>,
3779        /// Additional WITH options for the view.
3780        with_options: Vec<SqlOption>,
3781    },
3782    /// ```sql
3783    /// ALTER DOMAIN
3784    /// ```
3785    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-alterdomain.html)
3786    AlterDomain(AlterDomain),
3787    /// ```sql
3788    /// ALTER EXTENSION
3789    /// ```
3790    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-alterextension.html)
3791    AlterExtension(AlterExtension),
3792    /// ```sql
3793    /// ALTER FUNCTION
3794    /// ALTER AGGREGATE
3795    /// ALTER PROCEDURE
3796    /// ```
3797    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-alterfunction.html)
3798    /// and [PostgreSQL](https://www.postgresql.org/docs/current/sql-alteraggregate.html)
3799    /// and [PostgreSQL](https://www.postgresql.org/docs/current/sql-alterprocedure.html)
3800    AlterFunction(AlterFunction),
3801    /// ```sql
3802    /// ALTER TYPE
3803    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-altertype.html)
3804    /// ```
3805    AlterType(AlterType),
3806    /// ```sql
3807    /// ALTER TRIGGER
3808    /// ```
3809    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-altertrigger.html)
3810    AlterTrigger(AlterTrigger),
3811    /// ```sql
3812    /// ALTER COLLATION
3813    /// ```
3814    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-altercollation.html)
3815    AlterCollation(AlterCollation),
3816    /// ```sql
3817    /// ALTER OPERATOR
3818    /// ```
3819    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-alteroperator.html)
3820    AlterOperator(AlterOperator),
3821    /// ```sql
3822    /// ALTER OPERATOR FAMILY
3823    /// ```
3824    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-alteropfamily.html)
3825    AlterOperatorFamily(AlterOperatorFamily),
3826    /// ```sql
3827    /// ALTER OPERATOR CLASS
3828    /// ```
3829    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-alteropclass.html)
3830    AlterOperatorClass(AlterOperatorClass),
3831    /// ```sql
3832    /// ALTER ROLE
3833    /// ```
3834    AlterRole {
3835        /// Role name being altered.
3836        name: Ident,
3837        /// Operation to perform on the role.
3838        operation: AlterRoleOperation,
3839    },
3840    /// ```sql
3841    /// ALTER POLICY <NAME> ON <TABLE NAME> [<OPERATION>]
3842    /// ```
3843    /// (Postgresql-specific)
3844    AlterPolicy(AlterPolicy),
3845    /// ```sql
3846    /// ALTER CONNECTOR connector_name SET DCPROPERTIES(property_name=property_value, ...);
3847    /// or
3848    /// ALTER CONNECTOR connector_name SET URL new_url;
3849    /// or
3850    /// ALTER CONNECTOR connector_name SET OWNER [USER|ROLE] user_or_role;
3851    /// ```
3852    /// (Hive-specific)
3853    AlterConnector {
3854        /// Name of the connector to alter.
3855        name: Ident,
3856        /// Optional connector properties to set.
3857        properties: Option<Vec<SqlOption>>,
3858        /// Optional new URL for the connector.
3859        url: Option<String>,
3860        /// Optional new owner specification.
3861        owner: Option<ddl::AlterConnectorOwner>,
3862    },
3863    /// ```sql
3864    /// ALTER SESSION SET sessionParam
3865    /// ALTER SESSION UNSET <param_name> [ , <param_name> , ... ]
3866    /// ```
3867    /// See <https://docs.snowflake.com/en/sql-reference/sql/alter-session>
3868    AlterSession {
3869        /// true is to set for the session parameters, false is to unset
3870        set: bool,
3871        /// The session parameters to set or unset
3872        session_params: KeyValueOptions,
3873    },
3874    /// ```sql
3875    /// ATTACH DATABASE 'path/to/file' AS alias
3876    /// ```
3877    /// (SQLite-specific)
3878    AttachDatabase {
3879        /// The name to bind to the newly attached database
3880        schema_name: Ident,
3881        /// An expression that indicates the path to the database file
3882        database_file_name: Expr,
3883        /// true if the syntax is 'ATTACH DATABASE', false if it's just 'ATTACH'
3884        database: bool,
3885    },
3886    /// (DuckDB-specific)
3887    /// ```sql
3888    /// ATTACH 'sqlite_file.db' AS sqlite_db (READ_ONLY, TYPE SQLITE);
3889    /// ```
3890    /// See <https://duckdb.org/docs/sql/statements/attach.html>
3891    AttachDuckDBDatabase {
3892        /// `true` when `IF NOT EXISTS` was present.
3893        if_not_exists: bool,
3894        /// `true` if the syntax used `ATTACH DATABASE` rather than `ATTACH`.
3895        database: bool,
3896        /// The path identifier to the database file being attached.
3897        database_path: Ident,
3898        /// Optional alias assigned to the attached database.
3899        database_alias: Option<Ident>,
3900        /// Dialect-specific attach options (e.g., `READ_ONLY`).
3901        attach_options: Vec<AttachDuckDBDatabaseOption>,
3902    },
3903    /// (DuckDB-specific)
3904    /// ```sql
3905    /// DETACH db_alias;
3906    /// ```
3907    /// See <https://duckdb.org/docs/sql/statements/attach.html>
3908    DetachDuckDBDatabase {
3909        /// `true` when `IF EXISTS` was present.
3910        if_exists: bool,
3911        /// `true` if the syntax used `DETACH DATABASE` rather than `DETACH`.
3912        database: bool,
3913        /// Alias of the database to detach.
3914        database_alias: Ident,
3915    },
3916    /// ```sql
3917    /// DROP [TABLE, VIEW, ...]
3918    /// ```
3919    Drop {
3920        /// The type of the object to drop: TABLE, VIEW, etc.
3921        object_type: ObjectType,
3922        /// An optional `IF EXISTS` clause. (Non-standard.)
3923        if_exists: bool,
3924        /// One or more objects to drop. (ANSI SQL requires exactly one.)
3925        names: Vec<ObjectName>,
3926        /// Whether `CASCADE` was specified. This will be `false` when
3927        /// `RESTRICT` or no drop behavior at all was specified.
3928        cascade: bool,
3929        /// Whether `RESTRICT` was specified. This will be `false` when
3930        /// `CASCADE` or no drop behavior at all was specified.
3931        restrict: bool,
3932        /// Hive allows you specify whether the table's stored data will be
3933        /// deleted along with the dropped table
3934        purge: bool,
3935        /// MySQL-specific "TEMPORARY" keyword
3936        temporary: bool,
3937        /// MySQL-specific drop index syntax, which requires table specification
3938        /// See <https://dev.mysql.com/doc/refman/8.4/en/drop-index.html>
3939        table: Option<ObjectName>,
3940    },
3941    /// ```sql
3942    /// DROP FUNCTION
3943    /// ```
3944    DropFunction(DropFunction),
3945    /// ```sql
3946    /// DROP DOMAIN
3947    /// ```
3948    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-dropdomain.html)
3949    ///
3950    /// DROP DOMAIN [ IF EXISTS ] name [, ...] [ CASCADE | RESTRICT ]
3951    ///
3952    DropDomain(DropDomain),
3953    /// ```sql
3954    /// DROP PROCEDURE
3955    /// ```
3956    DropProcedure {
3957        /// `true` when `IF EXISTS` was present.
3958        if_exists: bool,
3959        /// One or more functions/procedures to drop.
3960        proc_desc: Vec<FunctionDesc>,
3961        /// Optional drop behavior (`CASCADE` or `RESTRICT`).
3962        drop_behavior: Option<DropBehavior>,
3963    },
3964    /// ```sql
3965    /// DROP SECRET
3966    /// ```
3967    DropSecret {
3968        /// `true` when `IF EXISTS` was present.
3969        if_exists: bool,
3970        /// Optional `TEMPORARY` marker.
3971        temporary: Option<bool>,
3972        /// Name of the secret to drop.
3973        name: Ident,
3974        /// Optional storage specifier identifier.
3975        storage_specifier: Option<Ident>,
3976    },
3977    ///```sql
3978    /// DROP POLICY
3979    /// ```
3980    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-droppolicy.html)
3981    DropPolicy(DropPolicy),
3982    /// ```sql
3983    /// DROP CONNECTOR
3984    /// ```
3985    /// See [Hive](https://cwiki.apache.org/confluence/pages/viewpage.action?pageId=27362034#LanguageManualDDL-DropConnector)
3986    DropConnector {
3987        /// `true` when `IF EXISTS` was present.
3988        if_exists: bool,
3989        /// Name of the connector to drop.
3990        name: Ident,
3991    },
3992    /// ```sql
3993    /// DECLARE
3994    /// ```
3995    /// Declare Cursor Variables
3996    ///
3997    /// Note: this is a PostgreSQL-specific statement,
3998    /// but may also compatible with other SQL.
3999    Declare {
4000        /// Cursor declaration statements collected by `DECLARE`.
4001        stmts: Vec<Declare>,
4002    },
4003    /// ```sql
4004    /// CREATE EXTENSION [ IF NOT EXISTS ] extension_name
4005    ///     [ WITH ] [ SCHEMA schema_name ]
4006    ///              [ VERSION version ]
4007    ///              [ CASCADE ]
4008    /// ```
4009    ///
4010    /// Note: this is a PostgreSQL-specific statement,
4011    CreateExtension(CreateExtension),
4012    /// ```sql
4013    /// CREATE COLLATION
4014    /// ```
4015    /// Note: this is a PostgreSQL-specific statement.
4016    /// <https://www.postgresql.org/docs/current/sql-createcollation.html>
4017    CreateCollation(CreateCollation),
4018    /// ```sql
4019    /// CREATE TEXT SEARCH CONFIGURATION name ( PARSER = parser_name )
4020    /// ```
4021    /// Note: this is a PostgreSQL-specific statement.
4022    /// <https://www.postgresql.org/docs/current/sql-createtsconfig.html>
4023    CreateTextSearchConfiguration(CreateTextSearchConfiguration),
4024    /// ```sql
4025    /// CREATE TEXT SEARCH DICTIONARY name ( TEMPLATE = template_name [, option = value, ...] )
4026    /// ```
4027    /// Note: this is a PostgreSQL-specific statement.
4028    /// <https://www.postgresql.org/docs/current/sql-createtsdictionary.html>
4029    CreateTextSearchDictionary(CreateTextSearchDictionary),
4030    /// ```sql
4031    /// CREATE TEXT SEARCH PARSER name ( START = start_fn, GETTOKEN = gettoken_fn, END = end_fn, LEXTYPES = lextypes_fn [, HEADLINE = headline_fn] )
4032    /// ```
4033    /// Note: this is a PostgreSQL-specific statement.
4034    /// <https://www.postgresql.org/docs/current/sql-createtsparser.html>
4035    CreateTextSearchParser(CreateTextSearchParser),
4036    /// ```sql
4037    /// CREATE TEXT SEARCH TEMPLATE name ( [INIT = init_fn,] LEXIZE = lexize_fn )
4038    /// ```
4039    /// Note: this is a PostgreSQL-specific statement.
4040    /// <https://www.postgresql.org/docs/current/sql-createtstemplate.html>
4041    CreateTextSearchTemplate(CreateTextSearchTemplate),
4042    /// ```sql
4043    /// CREATE PUBLICATION name [ FOR ALL TABLES | FOR TABLE table [, ...] | FOR TABLES IN SCHEMA schema [, ...] ] [ WITH ( option = value [, ...] ) ]
4044    /// ```
4045    /// Note: this is a PostgreSQL-specific statement.
4046    /// <https://www.postgresql.org/docs/current/sql-createpublication.html>
4047    CreatePublication(CreatePublication),
4048    /// ```sql
4049    /// CREATE SUBSCRIPTION name CONNECTION 'conninfo' PUBLICATION publication_name [, ...] [ WITH ( option = value [, ...] ) ]
4050    /// ```
4051    /// Note: this is a PostgreSQL-specific statement.
4052    /// <https://www.postgresql.org/docs/current/sql-createsubscription.html>
4053    CreateSubscription(CreateSubscription),
4054    /// ```sql
4055    /// CREATE CAST (source_type AS target_type) WITH FUNCTION func_name [(arg_types)] [AS ASSIGNMENT | AS IMPLICIT]
4056    /// CREATE CAST (source_type AS target_type) WITHOUT FUNCTION [AS ASSIGNMENT | AS IMPLICIT]
4057    /// CREATE CAST (source_type AS target_type) WITH INOUT [AS ASSIGNMENT | AS IMPLICIT]
4058    /// ```
4059    /// Note: this is a PostgreSQL-specific statement.
4060    /// <https://www.postgresql.org/docs/current/sql-createcast.html>
4061    CreateCast(CreateCast),
4062    /// ```sql
4063    /// CREATE [DEFAULT] CONVERSION name FOR 'source_encoding' TO 'dest_encoding' FROM function_name
4064    /// ```
4065    /// Note: this is a PostgreSQL-specific statement.
4066    /// <https://www.postgresql.org/docs/current/sql-createconversion.html>
4067    CreateConversion(CreateConversion),
4068    /// ```sql
4069    /// CREATE [OR REPLACE] [TRUSTED] [PROCEDURAL] LANGUAGE name [HANDLER handler_func] [INLINE inline_func] [VALIDATOR validator_func | NO VALIDATOR]
4070    /// ```
4071    /// Note: this is a PostgreSQL-specific statement.
4072    /// <https://www.postgresql.org/docs/current/sql-createlanguage.html>
4073    CreateLanguage(CreateLanguage),
4074    /// ```sql
4075    /// CREATE RULE name AS ON event TO table [WHERE condition] DO [ALSO | INSTEAD] { NOTHING | command | (command ; ...) }
4076    /// ```
4077    /// Note: this is a PostgreSQL-specific statement.
4078    /// <https://www.postgresql.org/docs/current/sql-createrule.html>
4079    CreateRule(CreateRule),
4080    /// CREATE STATISTICS [ IF NOT EXISTS ] name [ ( kind [, ...] ) ] ON expr [, ...] FROM table_name
4081    /// ```
4082    /// Note: this is a PostgreSQL-specific statement.
4083    /// <https://www.postgresql.org/docs/current/sql-createstatistics.html>
4084    CreateStatistics(CreateStatistics),
4085    /// ```sql
4086    /// CREATE ACCESS METHOD name TYPE INDEX | TABLE HANDLER handler_function
4087    /// ```
4088    /// Note: this is a PostgreSQL-specific statement.
4089    /// <https://www.postgresql.org/docs/current/sql-create-access-method.html>
4090    CreateAccessMethod(CreateAccessMethod),
4091    /// ```sql
4092    /// CREATE EVENT TRIGGER name ON event [ WHEN TAG IN ( 'tag' [, ...] ) ] EXECUTE FUNCTION | PROCEDURE function_name()
4093    /// ```
4094    /// Note: this is a PostgreSQL-specific statement.
4095    /// <https://www.postgresql.org/docs/current/sql-createeventtrigger.html>
4096    CreateEventTrigger(CreateEventTrigger),
4097    /// ```sql
4098    /// CREATE [ OR REPLACE ] TRANSFORM FOR type_name LANGUAGE lang_name ( transform_element_list )
4099    /// ```
4100    /// Note: this is a PostgreSQL-specific statement.
4101    /// <https://www.postgresql.org/docs/current/sql-createtransform.html>
4102    CreateTransform(CreateTransform),
4103    /// ```sql
4104    /// SECURITY LABEL [ FOR provider_name ] ON object_type object_name IS { 'label' | NULL }
4105    /// ```
4106    /// Note: this is a PostgreSQL-specific statement.
4107    /// <https://www.postgresql.org/docs/current/sql-securitylabel.html>
4108    SecurityLabel(SecurityLabel),
4109    /// ```sql
4110    /// CREATE USER MAPPING [ IF NOT EXISTS ] FOR { role | USER | CURRENT_ROLE | CURRENT_USER | PUBLIC } SERVER server_name [ OPTIONS (...) ]
4111    /// ```
4112    /// Note: this is a PostgreSQL-specific statement.
4113    /// <https://www.postgresql.org/docs/current/sql-createusermapping.html>
4114    CreateUserMapping(CreateUserMapping),
4115    /// ```sql
4116    /// CREATE TABLESPACE name [ OWNER role ] LOCATION 'directory' [ WITH (options) ]
4117    /// ```
4118    /// Note: this is a PostgreSQL-specific statement.
4119    /// <https://www.postgresql.org/docs/current/sql-createtablespace.html>
4120    CreateTablespace(CreateTablespace),
4121    /// ```sql
4122    /// DROP EXTENSION [ IF EXISTS ] name [, ...] [ CASCADE | RESTRICT ]
4123    /// ```
4124    /// Note: this is a PostgreSQL-specific statement.
4125    /// <https://www.postgresql.org/docs/current/sql-dropextension.html>
4126    DropExtension(DropExtension),
4127    /// ```sql
4128    /// DROP OPERATOR [ IF EXISTS ] name ( { left_type | NONE } , right_type ) [, ...] [ CASCADE | RESTRICT ]
4129    /// ```
4130    /// Note: this is a PostgreSQL-specific statement.
4131    /// <https://www.postgresql.org/docs/current/sql-dropoperator.html>
4132    DropOperator(DropOperator),
4133    /// ```sql
4134    /// DROP OPERATOR FAMILY [ IF EXISTS ] name USING index_method [ CASCADE | RESTRICT ]
4135    /// ```
4136    /// Note: this is a PostgreSQL-specific statement.
4137    /// <https://www.postgresql.org/docs/current/sql-dropopfamily.html>
4138    DropOperatorFamily(DropOperatorFamily),
4139    /// ```sql
4140    /// DROP OPERATOR CLASS [ IF EXISTS ] name USING index_method [ CASCADE | RESTRICT ]
4141    /// ```
4142    /// Note: this is a PostgreSQL-specific statement.
4143    /// <https://www.postgresql.org/docs/current/sql-dropopclass.html>
4144    DropOperatorClass(DropOperatorClass),
4145    /// ```sql
4146    /// FETCH
4147    /// ```
4148    /// Retrieve rows from a query using a cursor
4149    ///
4150    /// Note: this is a PostgreSQL-specific statement,
4151    /// but may also compatible with other SQL.
4152    Fetch {
4153        /// Cursor name
4154        name: Ident,
4155        /// The fetch direction (e.g., `FORWARD`, `BACKWARD`).
4156        direction: FetchDirection,
4157        /// The fetch position (e.g., `ALL`, `NEXT`, `ABSOLUTE`).
4158        position: FetchPosition,
4159        /// Optional target table to fetch rows into.
4160        into: Option<ObjectName>,
4161    },
4162    /// ```sql
4163    /// FLUSH [NO_WRITE_TO_BINLOG | LOCAL] flush_option [, flush_option] ... | tables_option
4164    /// ```
4165    ///
4166    /// Note: this is a Mysql-specific statement,
4167    /// but may also compatible with other SQL.
4168    Flush {
4169        /// The specific flush option or object to flush.
4170        object_type: FlushType,
4171        /// Optional flush location (dialect-specific).
4172        location: Option<FlushLocation>,
4173        /// Optional channel name used for flush operations.
4174        channel: Option<String>,
4175        /// Whether a read lock was requested.
4176        read_lock: bool,
4177        /// Whether this is an export flush operation.
4178        export: bool,
4179        /// Optional list of tables involved in the flush.
4180        tables: Vec<ObjectName>,
4181    },
4182    /// ```sql
4183    /// DISCARD [ ALL | PLANS | SEQUENCES | TEMPORARY | TEMP ]
4184    /// ```
4185    ///
4186    /// Note: this is a PostgreSQL-specific statement,
4187    /// but may also compatible with other SQL.
4188    Discard {
4189        /// The kind of object(s) to discard (ALL, PLANS, etc.).
4190        object_type: DiscardObject,
4191    },
4192    /// `SHOW FUNCTIONS`
4193    ///
4194    /// Note: this is a Presto-specific statement.
4195    ShowFunctions {
4196        /// Optional filter for which functions to display.
4197        filter: Option<ShowStatementFilter>,
4198    },
4199    /// ```sql
4200    /// SHOW <variable>
4201    /// ```
4202    ///
4203    /// Note: this is a PostgreSQL-specific statement.
4204    ShowVariable {
4205        /// Variable name as one or more identifiers.
4206        variable: Vec<Ident>,
4207    },
4208    /// ```sql
4209    /// SHOW [GLOBAL | SESSION] STATUS [LIKE 'pattern' | WHERE expr]
4210    /// ```
4211    ///
4212    /// Note: this is a MySQL-specific statement.
4213    ShowStatus {
4214        /// Optional filter for which status entries to display.
4215        filter: Option<ShowStatementFilter>,
4216        /// `true` when `GLOBAL` scope was requested.
4217        global: bool,
4218        /// `true` when `SESSION` scope was requested.
4219        session: bool,
4220    },
4221    /// ```sql
4222    /// SHOW VARIABLES
4223    /// ```
4224    ///
4225    /// Note: this is a MySQL-specific statement.
4226    ShowVariables {
4227        /// Optional filter for which variables to display.
4228        filter: Option<ShowStatementFilter>,
4229        /// `true` when `GLOBAL` scope was requested.
4230        global: bool,
4231        /// `true` when `SESSION` scope was requested.
4232        session: bool,
4233    },
4234    /// ```sql
4235    /// SHOW CREATE TABLE
4236    /// ```
4237    ///
4238    /// Note: this is a MySQL-specific statement.
4239    ShowCreate {
4240        /// The kind of object being shown (TABLE, VIEW, etc.).
4241        obj_type: ShowCreateObject,
4242        /// The name of the object to show create statement for.
4243        obj_name: ObjectName,
4244    },
4245    /// ```sql
4246    /// SHOW COLUMNS
4247    /// ```
4248    ShowColumns {
4249        /// `true` when extended column information was requested.
4250        extended: bool,
4251        /// `true` when full column details were requested.
4252        full: bool,
4253        /// Additional options for `SHOW COLUMNS`.
4254        show_options: ShowStatementOptions,
4255    },
4256    /// ```sql
4257    /// SHOW CATALOGS
4258    /// ```
4259    ShowCatalogs {
4260        /// `true` when terse output format was requested.
4261        terse: bool,
4262        /// `true` when history information was requested.
4263        history: bool,
4264        /// Additional options for `SHOW CATALOGS`.
4265        show_options: ShowStatementOptions,
4266    },
4267    /// ```sql
4268    /// SHOW DATABASES
4269    /// ```
4270    ShowDatabases {
4271        /// `true` when terse output format was requested.
4272        terse: bool,
4273        /// `true` when history information was requested.
4274        history: bool,
4275        /// Additional options for `SHOW DATABASES`.
4276        show_options: ShowStatementOptions,
4277    },
4278    /// ```sql
4279    /// SHOW [FULL] PROCESSLIST
4280    /// ```
4281    ///
4282    /// Note: this is a MySQL-specific statement.
4283    ShowProcessList {
4284        /// `true` when full process information was requested.
4285        full: bool,
4286    },
4287    /// ```sql
4288    /// SHOW SCHEMAS
4289    /// ```
4290    ShowSchemas {
4291        /// `true` when terse (compact) output was requested.
4292        terse: bool,
4293        /// `true` when history information was requested.
4294        history: bool,
4295        /// Additional options for `SHOW SCHEMAS`.
4296        show_options: ShowStatementOptions,
4297    },
4298    // ```sql
4299    // SHOW {CHARACTER SET | CHARSET}
4300    // ```
4301    // [MySQL]:
4302    // <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>
4303    /// Show the available character sets (alias `CHARSET`).
4304    ShowCharset(ShowCharset),
4305    /// ```sql
4306    /// SHOW OBJECTS LIKE 'line%' IN mydb.public
4307    /// ```
4308    /// Snowflake-specific statement
4309    /// <https://docs.snowflake.com/en/sql-reference/sql/show-objects>
4310    ShowObjects(ShowObjects),
4311    /// ```sql
4312    /// SHOW TABLES
4313    /// ```
4314    ShowTables {
4315        /// `true` when terse output format was requested (compact listing).
4316        terse: bool,
4317        /// `true` when history rows are requested.
4318        history: bool,
4319        /// `true` when extended information should be shown.
4320        extended: bool,
4321        /// `true` when a full listing was requested.
4322        full: bool,
4323        /// `true` when external tables should be included.
4324        external: bool,
4325        /// Additional options for `SHOW` statements.
4326        show_options: ShowStatementOptions,
4327    },
4328    /// ```sql
4329    /// SHOW VIEWS
4330    /// ```
4331    ShowViews {
4332        /// `true` when terse output format was requested.
4333        terse: bool,
4334        /// `true` when materialized views should be included.
4335        materialized: bool,
4336        /// Additional options for `SHOW` statements.
4337        show_options: ShowStatementOptions,
4338    },
4339    /// ```sql
4340    /// SHOW COLLATION
4341    /// ```
4342    ///
4343    /// Note: this is a MySQL-specific statement.
4344    ShowCollation {
4345        /// Optional filter for which collations to display.
4346        filter: Option<ShowStatementFilter>,
4347    },
4348    /// ```sql
4349    /// `USE ...`
4350    /// ```
4351    Use(Use),
4352    /// ```sql
4353    /// START  [ TRANSACTION | WORK ] | START TRANSACTION } ...
4354    /// ```
4355    /// If `begin` is false.
4356    ///
4357    /// ```sql
4358    /// `BEGIN  [ TRANSACTION | WORK ] | START TRANSACTION } ...`
4359    /// ```
4360    /// If `begin` is true
4361    StartTransaction {
4362        /// Transaction modes such as `ISOLATION LEVEL` or `READ WRITE`.
4363        modes: Vec<TransactionMode>,
4364        /// `true` when this was parsed as `BEGIN` instead of `START`.
4365        begin: bool,
4366        /// Optional specific keyword used: `TRANSACTION` or `WORK`.
4367        transaction: Option<BeginTransactionKind>,
4368        /// Optional transaction modifier (e.g., `AND NO CHAIN`).
4369        modifier: Option<TransactionModifier>,
4370        /// List of statements belonging to the `BEGIN` block.
4371        /// Example:
4372        /// ```sql
4373        /// BEGIN
4374        ///     SELECT 1;
4375        ///     SELECT 2;
4376        /// END;
4377        /// ```
4378        statements: Vec<Statement>,
4379        /// Exception handling with exception clauses.
4380        /// Example:
4381        /// ```sql
4382        /// EXCEPTION
4383        ///     WHEN EXCEPTION_1 THEN
4384        ///         SELECT 2;
4385        ///     WHEN EXCEPTION_2 OR EXCEPTION_3 THEN
4386        ///         SELECT 3;
4387        ///     WHEN OTHER THEN
4388        ///         SELECT 4;
4389        /// ```
4390        /// <https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#beginexceptionend>
4391        /// <https://docs.snowflake.com/en/sql-reference/snowflake-scripting/exception>
4392        exception: Option<Vec<ExceptionWhen>>,
4393        /// TRUE if the statement has an `END` keyword.
4394        has_end_keyword: bool,
4395    },
4396    /// ```sql
4397    /// COMMENT ON ...
4398    /// ```
4399    ///
4400    /// Note: this is a PostgreSQL-specific statement.
4401    Comment {
4402        /// Type of object being commented (table, column, etc.).
4403        object_type: CommentObject,
4404        /// Name of the object the comment applies to.
4405        object_name: ObjectName,
4406        /// Optional comment text (None to remove comment).
4407        comment: Option<String>,
4408        /// An optional `IF EXISTS` clause. (Non-standard.)
4409        /// See <https://docs.snowflake.com/en/sql-reference/sql/comment>
4410        if_exists: bool,
4411    },
4412    /// ```sql
4413    /// COMMIT [ TRANSACTION | WORK ] [ AND [ NO ] CHAIN ]
4414    /// ```
4415    /// If `end` is false
4416    ///
4417    /// ```sql
4418    /// END [ TRY | CATCH ]
4419    /// ```
4420    /// If `end` is true
4421    Commit {
4422        /// `true` when `AND [ NO ] CHAIN` was present.
4423        chain: bool,
4424        /// `true` when this `COMMIT` was parsed as an `END` block terminator.
4425        end: bool,
4426        /// Optional transaction modifier for commit semantics.
4427        modifier: Option<TransactionModifier>,
4428    },
4429    /// ```sql
4430    /// ROLLBACK [ TRANSACTION | WORK ] [ AND [ NO ] CHAIN ] [ TO [ SAVEPOINT ] savepoint_name ]
4431    /// ```
4432    Rollback {
4433        /// `true` when `AND [ NO ] CHAIN` was present.
4434        chain: bool,
4435        /// Optional savepoint name to roll back to.
4436        savepoint: Option<Ident>,
4437    },
4438    /// ```sql
4439    /// CREATE SCHEMA
4440    /// ```
4441    CreateSchema {
4442        /// `<schema name> | AUTHORIZATION <schema authorization identifier>  | <schema name>  AUTHORIZATION <schema authorization identifier>`
4443        schema_name: SchemaName,
4444        /// `true` when `IF NOT EXISTS` was present.
4445        if_not_exists: bool,
4446        /// Schema properties.
4447        ///
4448        /// ```sql
4449        /// CREATE SCHEMA myschema WITH (key1='value1');
4450        /// ```
4451        ///
4452        /// [Trino](https://trino.io/docs/current/sql/create-schema.html)
4453        with: Option<Vec<SqlOption>>,
4454        /// Schema options.
4455        ///
4456        /// ```sql
4457        /// CREATE SCHEMA myschema OPTIONS(key1='value1');
4458        /// ```
4459        ///
4460        /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_schema_statement)
4461        options: Option<Vec<SqlOption>>,
4462        /// Default collation specification for the schema.
4463        ///
4464        /// ```sql
4465        /// CREATE SCHEMA myschema DEFAULT COLLATE 'und:ci';
4466        /// ```
4467        ///
4468        /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_schema_statement)
4469        default_collate_spec: Option<Expr>,
4470        /// Clones a schema
4471        ///
4472        /// ```sql
4473        /// CREATE SCHEMA myschema CLONE otherschema
4474        /// ```
4475        ///
4476        /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-clone#databases-schemas)
4477        clone: Option<ObjectName>,
4478    },
4479    /// ```sql
4480    /// CREATE DATABASE
4481    /// ```
4482    /// See:
4483    /// <https://docs.snowflake.com/en/sql-reference/sql/create-database>
4484    CreateDatabase {
4485        /// Database name.
4486        db_name: ObjectName,
4487        /// `IF NOT EXISTS` flag.
4488        if_not_exists: bool,
4489        /// Optional location URI.
4490        location: Option<String>,
4491        /// Optional managed location.
4492        managed_location: Option<String>,
4493        /// `OR REPLACE` flag.
4494        or_replace: bool,
4495        /// `TRANSIENT` flag.
4496        transient: bool,
4497        /// Optional clone source.
4498        clone: Option<ObjectName>,
4499        /// Optional data retention time in days.
4500        data_retention_time_in_days: Option<u64>,
4501        /// Optional maximum data extension time in days.
4502        max_data_extension_time_in_days: Option<u64>,
4503        /// Optional external volume identifier.
4504        external_volume: Option<String>,
4505        /// Optional catalog name.
4506        catalog: Option<String>,
4507        /// Whether to replace invalid characters.
4508        replace_invalid_characters: Option<bool>,
4509        /// Default DDL collation string.
4510        default_ddl_collation: Option<String>,
4511        /// Storage serialization policy.
4512        storage_serialization_policy: Option<StorageSerializationPolicy>,
4513        /// Optional comment.
4514        comment: Option<String>,
4515        /// Optional default character set (MySQL).
4516        default_charset: Option<String>,
4517        /// Optional default collation (MySQL).
4518        default_collation: Option<String>,
4519        /// Optional catalog sync identifier.
4520        catalog_sync: Option<String>,
4521        /// Catalog sync namespace mode.
4522        catalog_sync_namespace_mode: Option<CatalogSyncNamespaceMode>,
4523        /// Optional flatten delimiter for namespace sync.
4524        catalog_sync_namespace_flatten_delimiter: Option<String>,
4525        /// Optional tags for the database.
4526        with_tags: Option<Vec<Tag>>,
4527        /// Optional contact entries for the database.
4528        with_contacts: Option<Vec<ContactEntry>>,
4529    },
4530    /// ```sql
4531    /// CREATE FUNCTION
4532    /// ```
4533    ///
4534    /// Supported variants:
4535    /// 1. [Hive](https://cwiki.apache.org/confluence/display/hive/languagemanual+ddl#LanguageManualDDL-Create/Drop/ReloadFunction)
4536    /// 2. [PostgreSQL](https://www.postgresql.org/docs/15/sql-createfunction.html)
4537    /// 3. [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_function_statement)
4538    /// 4. [MsSql](https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql)
4539    CreateFunction(CreateFunction),
4540    /// CREATE TRIGGER statement. See struct [CreateTrigger] for details.
4541    CreateTrigger(CreateTrigger),
4542    /// DROP TRIGGER statement. See struct [DropTrigger] for details.
4543    DropTrigger(DropTrigger),
4544    /// ```sql
4545    /// CREATE PROCEDURE
4546    /// ```
4547    CreateProcedure {
4548        /// `OR ALTER` flag.
4549        or_alter: bool,
4550        /// Procedure name.
4551        name: ObjectName,
4552        /// Optional procedure parameters.
4553        params: Option<Vec<ProcedureParam>>,
4554        /// Optional language identifier.
4555        language: Option<Ident>,
4556        /// Procedure body statements.
4557        body: ConditionalStatements,
4558    },
4559    /// ```sql
4560    /// CREATE MACRO
4561    /// ```
4562    ///
4563    /// Supported variants:
4564    /// 1. [DuckDB](https://duckdb.org/docs/sql/statements/create_macro)
4565    CreateMacro {
4566        /// `OR REPLACE` flag.
4567        or_replace: bool,
4568        /// Whether macro is temporary.
4569        temporary: bool,
4570        /// Macro name.
4571        name: ObjectName,
4572        /// Optional macro arguments.
4573        args: Option<Vec<MacroArg>>,
4574        /// Macro definition body.
4575        definition: MacroDefinition,
4576    },
4577    /// ```sql
4578    /// CREATE STAGE
4579    /// ```
4580    /// See <https://docs.snowflake.com/en/sql-reference/sql/create-stage>
4581    CreateStage {
4582        /// `OR REPLACE` flag for stage.
4583        or_replace: bool,
4584        /// Whether stage is temporary.
4585        temporary: bool,
4586        /// `IF NOT EXISTS` flag.
4587        if_not_exists: bool,
4588        /// Stage name.
4589        name: ObjectName,
4590        /// Stage parameters.
4591        stage_params: StageParamsObject,
4592        /// Directory table parameters.
4593        directory_table_params: KeyValueOptions,
4594        /// File format options.
4595        file_format: KeyValueOptions,
4596        /// Copy options for stage.
4597        copy_options: KeyValueOptions,
4598        /// Optional comment.
4599        comment: Option<String>,
4600    },
4601    /// ```sql
4602    /// ASSERT <condition> [AS <message>]
4603    /// ```
4604    Assert {
4605        /// Assertion condition expression.
4606        condition: Expr,
4607        /// Optional message expression.
4608        message: Option<Expr>,
4609    },
4610    /// ```sql
4611    /// GRANT privileges ON objects TO grantees
4612    /// ```
4613    Grant(Grant),
4614    /// ```sql
4615    /// DENY privileges ON object TO grantees
4616    /// ```
4617    Deny(DenyStatement),
4618    /// ```sql
4619    /// REVOKE privileges ON objects FROM grantees
4620    /// ```
4621    Revoke(Revoke),
4622    /// ```sql
4623    /// DEALLOCATE [ PREPARE ] { name | ALL }
4624    /// ```
4625    ///
4626    /// Note: this is a PostgreSQL-specific statement.
4627    Deallocate {
4628        /// Name to deallocate (or `ALL`).
4629        name: Ident,
4630        /// Whether `PREPARE` keyword was present.
4631        prepare: bool,
4632    },
4633    /// ```sql
4634    /// An `EXECUTE` statement
4635    /// ```
4636    ///
4637    /// Postgres: <https://www.postgresql.org/docs/current/sql-execute.html>
4638    /// MSSQL: <https://learn.microsoft.com/en-us/sql/relational-databases/stored-procedures/execute-a-stored-procedure>
4639    /// BigQuery: <https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#execute_immediate>
4640    /// Snowflake: <https://docs.snowflake.com/en/sql-reference/sql/execute-immediate>
4641    Execute {
4642        /// Optional function/procedure name.
4643        name: Option<ObjectName>,
4644        /// Parameter expressions passed to execute.
4645        parameters: Vec<Expr>,
4646        /// Whether parentheses were present around `parameters`.
4647        has_parentheses: bool,
4648        /// Is this an `EXECUTE IMMEDIATE`.
4649        immediate: bool,
4650        /// Identifiers to capture results into.
4651        into: Vec<Ident>,
4652        /// `USING` expressions with optional aliases.
4653        using: Vec<ExprWithAlias>,
4654        /// Whether the last parameter is the return value of the procedure
4655        /// MSSQL: <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/execute-transact-sql?view=sql-server-ver17#output>
4656        output: bool,
4657        /// Whether to invoke the procedure with the default parameter values
4658        /// MSSQL: <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/execute-transact-sql?view=sql-server-ver17#default>
4659        default: bool,
4660    },
4661    /// ```sql
4662    /// PREPARE name [ ( data_type [, ...] ) ] AS statement
4663    /// ```
4664    ///
4665    /// Note: this is a PostgreSQL-specific statement.
4666    Prepare {
4667        /// Name of the prepared statement.
4668        name: Ident,
4669        /// Optional data types for parameters.
4670        data_types: Vec<DataType>,
4671        /// Statement being prepared.
4672        statement: Box<Statement>,
4673    },
4674    /// ```sql
4675    /// KILL [CONNECTION | QUERY | MUTATION]
4676    /// ```
4677    ///
4678    /// See <https://clickhouse.com/docs/en/sql-reference/statements/kill/>
4679    /// See <https://dev.mysql.com/doc/refman/8.0/en/kill.html>
4680    Kill {
4681        /// Optional kill modifier (CONNECTION, QUERY, MUTATION).
4682        modifier: Option<KillType>,
4683        // processlist_id
4684        /// The id of the process to kill.
4685        id: u64,
4686    },
4687    /// ```sql
4688    /// [EXPLAIN | DESC | DESCRIBE] TABLE
4689    /// ```
4690    /// Note: this is a MySQL-specific statement. See <https://dev.mysql.com/doc/refman/8.0/en/explain.html>
4691    ExplainTable {
4692        /// `EXPLAIN | DESC | DESCRIBE`
4693        describe_alias: DescribeAlias,
4694        /// Hive style `FORMATTED | EXTENDED`
4695        hive_format: Option<HiveDescribeFormat>,
4696        /// Snowflake and ClickHouse support `DESC|DESCRIBE TABLE <table_name>` syntax
4697        ///
4698        /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/desc-table.html)
4699        /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/describe-table)
4700        has_table_keyword: bool,
4701        /// Table name
4702        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
4703        table_name: ObjectName,
4704    },
4705    /// ```sql
4706    /// [EXPLAIN | DESC | DESCRIBE]  <statement>
4707    /// ```
4708    Explain {
4709        /// `EXPLAIN | DESC | DESCRIBE`
4710        describe_alias: DescribeAlias,
4711        /// Carry out the command and show actual run times and other statistics.
4712        analyze: bool,
4713        /// Display additional information regarding the plan.
4714        verbose: bool,
4715        /// `EXPLAIN QUERY PLAN`
4716        /// Display the query plan without running the query.
4717        ///
4718        /// [SQLite](https://sqlite.org/lang_explain.html)
4719        query_plan: bool,
4720        /// `EXPLAIN ESTIMATE`
4721        /// [Clickhouse](https://clickhouse.com/docs/en/sql-reference/statements/explain#explain-estimate)
4722        estimate: bool,
4723        /// A SQL query that specifies what to explain
4724        statement: Box<Statement>,
4725        /// Optional output format of explain
4726        format: Option<AnalyzeFormatKind>,
4727        /// Postgres style utility options, `(analyze, verbose true)`
4728        options: Option<Vec<UtilityOption>>,
4729    },
4730    /// ```sql
4731    /// SAVEPOINT
4732    /// ```
4733    /// Define a new savepoint within the current transaction
4734    Savepoint {
4735        /// Name of the savepoint being defined.
4736        name: Ident,
4737    },
4738    /// ```sql
4739    /// RELEASE [ SAVEPOINT ] savepoint_name
4740    /// ```
4741    ReleaseSavepoint {
4742        /// Name of the savepoint to release.
4743        name: Ident,
4744    },
4745    /// A `MERGE` statement.
4746    ///
4747    /// ```sql
4748    /// MERGE INTO <target_table> USING <source> ON <join_expr> { matchedClause | notMatchedClause } [ ... ]
4749    /// ```
4750    /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/merge)
4751    /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/dml-syntax#merge_statement)
4752    /// [MSSQL](https://learn.microsoft.com/en-us/sql/t-sql/statements/merge-transact-sql?view=sql-server-ver16)
4753    Merge(Merge),
4754    /// ```sql
4755    /// CACHE [ FLAG ] TABLE <table_name> [ OPTIONS('K1' = 'V1', 'K2' = V2) ] [ AS ] [ <query> ]
4756    /// ```
4757    ///
4758    /// See [Spark SQL docs] for more details.
4759    ///
4760    /// [Spark SQL docs]: https://docs.databricks.com/spark/latest/spark-sql/language-manual/sql-ref-syntax-aux-cache-cache-table.html
4761    Cache {
4762        /// Table flag
4763        table_flag: Option<ObjectName>,
4764        /// Table name
4765        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
4766        table_name: ObjectName,
4767        /// `true` if `AS` keyword was present before the query.
4768        has_as: bool,
4769        /// Table confs
4770        options: Vec<SqlOption>,
4771        /// Cache table as a Query
4772        query: Option<Box<Query>>,
4773    },
4774    /// ```sql
4775    /// UNCACHE TABLE [ IF EXISTS ]  <table_name>
4776    /// ```
4777    UNCache {
4778        /// Table name
4779        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
4780        table_name: ObjectName,
4781        /// `true` when `IF EXISTS` was present.
4782        if_exists: bool,
4783    },
4784    /// ```sql
4785    /// CREATE [ { TEMPORARY | TEMP } ] SEQUENCE [ IF NOT EXISTS ] <sequence_name>
4786    /// ```
4787    /// Define a new sequence:
4788    CreateSequence {
4789        /// Whether the sequence is temporary.
4790        temporary: bool,
4791        /// `IF NOT EXISTS` flag.
4792        if_not_exists: bool,
4793        /// Sequence name.
4794        name: ObjectName,
4795        /// Optional data type for the sequence.
4796        data_type: Option<DataType>,
4797        /// Sequence options (INCREMENT, MINVALUE, etc.).
4798        sequence_options: Vec<SequenceOptions>,
4799        /// Optional `OWNED BY` target.
4800        owned_by: Option<ObjectName>,
4801    },
4802    /// A `CREATE DOMAIN` statement.
4803    CreateDomain(CreateDomain),
4804    /// ```sql
4805    /// CREATE TYPE <name>
4806    /// ```
4807    CreateType {
4808        /// Type name to create.
4809        name: ObjectName,
4810        /// Optional type representation details.
4811        representation: Option<UserDefinedTypeRepresentation>,
4812    },
4813    /// ```sql
4814    /// PRAGMA <schema-name>.<pragma-name> = <pragma-value>
4815    /// ```
4816    Pragma {
4817        /// Pragma name (possibly qualified).
4818        name: ObjectName,
4819        /// Optional pragma value.
4820        value: Option<ValueWithSpan>,
4821        /// Whether the pragma used `=`.
4822        is_eq: bool,
4823    },
4824    /// ```sql
4825    /// LOCK [ TABLE ] [ ONLY ] name [ * ] [, ...] [ IN lockmode MODE ] [ NOWAIT ]
4826    /// ```
4827    ///
4828    /// See <https://www.postgresql.org/docs/current/sql-lock.html>
4829    Lock(Lock),
4830    /// ```sql
4831    /// LOCK TABLES <table_name> [READ [LOCAL] | [LOW_PRIORITY] WRITE]
4832    /// ```
4833    /// Note: this is a MySQL-specific statement. See <https://dev.mysql.com/doc/refman/8.0/en/lock-tables.html>
4834    LockTables {
4835        /// List of tables to lock with modes.
4836        tables: Vec<LockTable>,
4837    },
4838    /// ```sql
4839    /// UNLOCK TABLES
4840    /// ```
4841    /// Note: this is a MySQL-specific statement. See <https://dev.mysql.com/doc/refman/8.0/en/lock-tables.html>
4842    UnlockTables,
4843    /// Unloads the result of a query to file
4844    ///
4845    /// [Athena](https://docs.aws.amazon.com/athena/latest/ug/unload.html):
4846    /// ```sql
4847    /// UNLOAD(statement) TO <destination> [ WITH options ]
4848    /// ```
4849    ///
4850    /// [Redshift](https://docs.aws.amazon.com/redshift/latest/dg/r_UNLOAD.html):
4851    /// ```sql
4852    /// UNLOAD('statement') TO <destination> [ OPTIONS ]
4853    /// ```
4854    Unload {
4855        /// Optional query AST to unload.
4856        query: Option<Box<Query>>,
4857        /// Optional original query text.
4858        query_text: Option<String>,
4859        /// Destination identifier.
4860        to: Ident,
4861        /// Optional IAM role/auth information.
4862        auth: Option<IamRoleKind>,
4863        /// Additional `WITH` options.
4864        with: Vec<SqlOption>,
4865        /// Legacy copy-style options.
4866        options: Vec<CopyLegacyOption>,
4867    },
4868    /// ClickHouse:
4869    /// ```sql
4870    /// OPTIMIZE TABLE [db.]name [ON CLUSTER cluster] [PARTITION partition | PARTITION ID 'partition_id'] [FINAL] [DEDUPLICATE [BY expression]]
4871    /// ```
4872    /// See ClickHouse <https://clickhouse.com/docs/en/sql-reference/statements/optimize>
4873    ///
4874    /// Databricks:
4875    /// ```sql
4876    /// OPTIMIZE table_name [WHERE predicate] [ZORDER BY (col_name1 [, ...])]
4877    /// ```
4878    /// See Databricks <https://docs.databricks.com/en/sql/language-manual/delta-optimize.html>
4879    OptimizeTable {
4880        /// Table name to optimize.
4881        name: ObjectName,
4882        /// Whether the `TABLE` keyword was present (ClickHouse uses `OPTIMIZE TABLE`, Databricks uses `OPTIMIZE`).
4883        has_table_keyword: bool,
4884        /// Optional cluster identifier.
4885        /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/optimize)
4886        on_cluster: Option<Ident>,
4887        /// Optional partition spec.
4888        /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/optimize)
4889        partition: Option<Partition>,
4890        /// Whether `FINAL` was specified.
4891        /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/optimize)
4892        include_final: bool,
4893        /// Optional deduplication settings.
4894        /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/optimize)
4895        deduplicate: Option<Deduplicate>,
4896        /// Optional WHERE predicate.
4897        /// [Databricks](https://docs.databricks.com/en/sql/language-manual/delta-optimize.html)
4898        predicate: Option<Expr>,
4899        /// Optional ZORDER BY columns.
4900        /// [Databricks](https://docs.databricks.com/en/sql/language-manual/delta-optimize.html)
4901        zorder: Option<Vec<Expr>>,
4902    },
4903    /// ```sql
4904    /// LISTEN
4905    /// ```
4906    /// listen for a notification channel
4907    ///
4908    /// See Postgres <https://www.postgresql.org/docs/current/sql-listen.html>
4909    LISTEN {
4910        /// Notification channel identifier.
4911        channel: Ident,
4912    },
4913    /// ```sql
4914    /// UNLISTEN
4915    /// ```
4916    /// stop listening for a notification
4917    ///
4918    /// See Postgres <https://www.postgresql.org/docs/current/sql-unlisten.html>
4919    UNLISTEN {
4920        /// Notification channel identifier.
4921        channel: Ident,
4922    },
4923    /// ```sql
4924    /// NOTIFY channel [ , payload ]
4925    /// ```
4926    /// send a notification event together with an optional "payload" string to channel
4927    ///
4928    /// See Postgres <https://www.postgresql.org/docs/current/sql-notify.html>
4929    NOTIFY {
4930        /// Notification channel identifier.
4931        channel: Ident,
4932        /// Optional payload string.
4933        payload: Option<String>,
4934    },
4935    /// ```sql
4936    /// LOAD DATA [LOCAL] INPATH 'filepath' [OVERWRITE] INTO TABLE tablename
4937    /// [PARTITION (partcol1=val1, partcol2=val2 ...)]
4938    /// [INPUTFORMAT 'inputformat' SERDE 'serde']
4939    /// ```
4940    /// Loading files into tables
4941    ///
4942    /// See Hive <https://cwiki.apache.org/confluence/pages/viewpage.action?pageId=27362036#LanguageManualDML-Loadingfilesintotables>
4943    LoadData {
4944        /// Whether `LOCAL` is present.
4945        local: bool,
4946        /// Input path for files to load.
4947        inpath: String,
4948        /// Whether `OVERWRITE` was specified.
4949        overwrite: bool,
4950        /// Target table name to load into.
4951        table_name: ObjectName,
4952        /// Optional partition specification.
4953        partitioned: Option<Vec<Expr>>,
4954        /// Optional table format information.
4955        table_format: Option<HiveLoadDataFormat>,
4956    },
4957    /// ```sql
4958    /// Rename TABLE tbl_name TO new_tbl_name[, tbl_name2 TO new_tbl_name2] ...
4959    /// ```
4960    /// Renames one or more tables
4961    ///
4962    /// See Mysql <https://dev.mysql.com/doc/refman/9.1/en/rename-table.html>
4963    RenameTable(Vec<RenameTable>),
4964    /// Snowflake `LIST`
4965    /// See: <https://docs.snowflake.com/en/sql-reference/sql/list>
4966    List(FileStagingCommand),
4967    /// Snowflake `REMOVE`
4968    /// See: <https://docs.snowflake.com/en/sql-reference/sql/remove>
4969    Remove(FileStagingCommand),
4970    /// RaiseError (MSSQL)
4971    /// RAISERROR ( { msg_id | msg_str | @local_variable }
4972    /// { , severity , state }
4973    /// [ , argument [ , ...n ] ] )
4974    /// [ WITH option [ , ...n ] ]
4975    /// See <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/raiserror-transact-sql?view=sql-server-ver16>
4976    RaisError {
4977        /// Error message expression or identifier.
4978        message: Box<Expr>,
4979        /// Severity expression.
4980        severity: Box<Expr>,
4981        /// State expression.
4982        state: Box<Expr>,
4983        /// Substitution arguments for the message.
4984        arguments: Vec<Expr>,
4985        /// Additional `WITH` options for RAISERROR.
4986        options: Vec<RaisErrorOption>,
4987    },
4988    /// A MSSQL `THROW` statement.
4989    Throw(ThrowStatement),
4990    /// ```sql
4991    /// PRINT msg_str | @local_variable | string_expr
4992    /// ```
4993    ///
4994    /// See: <https://learn.microsoft.com/en-us/sql/t-sql/statements/print-transact-sql>
4995    Print(PrintStatement),
4996    /// MSSQL `WAITFOR` statement.
4997    ///
4998    /// See: <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/waitfor-transact-sql>
4999    WaitFor(WaitForStatement),
5000    /// ```sql
5001    /// RETURN [ expression ]
5002    /// ```
5003    ///
5004    /// See [ReturnStatement]
5005    Return(ReturnStatement),
5006    /// Export data statement
5007    ///
5008    /// Example:
5009    /// ```sql
5010    /// EXPORT DATA OPTIONS(uri='gs://bucket/folder/*', format='PARQUET', overwrite=true) AS
5011    /// SELECT field1, field2 FROM mydataset.table1 ORDER BY field1 LIMIT 10
5012    /// ```
5013    /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/export-statements)
5014    ExportData(ExportData),
5015    /// ```sql
5016    /// CREATE [OR REPLACE] USER <user> [IF NOT EXISTS]
5017    /// ```
5018    /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-user)
5019    CreateUser(CreateUser),
5020    /// ```sql
5021    /// ALTER USER \[ IF EXISTS \] \[ <name> \]
5022    /// ```
5023    /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/alter-user)
5024    AlterUser(AlterUser),
5025    /// Re-sorts rows and reclaims space in either a specified table or all tables in the current database
5026    ///
5027    /// ```sql
5028    /// VACUUM tbl
5029    /// ```
5030    /// [Redshift](https://docs.aws.amazon.com/redshift/latest/dg/r_VACUUM_command.html)
5031    Vacuum(VacuumStatement),
5032    /// Restore the value of a run-time parameter to the default value.
5033    ///
5034    /// ```sql
5035    /// RESET configuration_parameter;
5036    /// RESET ALL;
5037    /// ```
5038    /// [PostgreSQL](https://www.postgresql.org/docs/current/sql-reset.html)
5039    Reset(ResetStatement),
5040}
5041
5042impl From<Analyze> for Statement {
5043    fn from(analyze: Analyze) -> Self {
5044        Statement::Analyze(analyze)
5045    }
5046}
5047
5048impl From<ddl::Truncate> for Statement {
5049    fn from(truncate: ddl::Truncate) -> Self {
5050        Statement::Truncate(truncate)
5051    }
5052}
5053
5054impl From<Lock> for Statement {
5055    fn from(lock: Lock) -> Self {
5056        Statement::Lock(lock)
5057    }
5058}
5059
5060impl From<ddl::Msck> for Statement {
5061    fn from(msck: ddl::Msck) -> Self {
5062        Statement::Msck(msck)
5063    }
5064}
5065
5066/// ```sql
5067/// {COPY | REVOKE} CURRENT GRANTS
5068/// ```
5069///
5070/// - [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/grant-ownership#optional-parameters)
5071#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
5072#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
5073#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
5074pub enum CurrentGrantsKind {
5075    /// `COPY CURRENT GRANTS` (copy current grants to target).
5076    CopyCurrentGrants,
5077    /// `REVOKE CURRENT GRANTS` (revoke current grants from target).
5078    RevokeCurrentGrants,
5079}
5080
5081impl fmt::Display for CurrentGrantsKind {
5082    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
5083        match self {
5084            CurrentGrantsKind::CopyCurrentGrants => write!(f, "COPY CURRENT GRANTS"),
5085            CurrentGrantsKind::RevokeCurrentGrants => write!(f, "REVOKE CURRENT GRANTS"),
5086        }
5087    }
5088}
5089
5090#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
5091#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
5092#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
5093/// `RAISERROR` options
5094/// See <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/raiserror-transact-sql?view=sql-server-ver16#options>
5095pub enum RaisErrorOption {
5096    /// Log the error.
5097    Log,
5098    /// Do not wait for completion.
5099    NoWait,
5100    /// Set the error state.
5101    SetError,
5102}
5103
5104impl fmt::Display for RaisErrorOption {
5105    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
5106        match self {
5107            RaisErrorOption::Log => write!(f, "LOG"),
5108            RaisErrorOption::NoWait => write!(f, "NOWAIT"),
5109            RaisErrorOption::SetError => write!(f, "SETERROR"),
5110        }
5111    }
5112}
5113
5114impl fmt::Display for Statement {
5115    /// Formats a SQL statement with support for pretty printing.
5116    ///
5117    /// When using the alternate flag (`{:#}`), the statement will be formatted with proper
5118    /// indentation and line breaks. For example:
5119    ///
5120    /// ```
5121    /// # use sqlparser::dialect::GenericDialect;
5122    /// # use sqlparser::parser::Parser;
5123    /// let sql = "SELECT a, b FROM table_1";
5124    /// let ast = Parser::parse_sql(&GenericDialect, sql).unwrap();
5125    ///
5126    /// // Regular formatting
5127    /// assert_eq!(format!("{}", ast[0]), "SELECT a, b FROM table_1");
5128    ///
5129    /// // Pretty printing
5130    /// assert_eq!(format!("{:#}", ast[0]),
5131    /// r#"SELECT
5132    ///   a,
5133    ///   b
5134    /// FROM
5135    ///   table_1"#);
5136    /// ```
5137    // Clippy thinks this function is too complicated, but it is painful to
5138    // split up without extracting structs for each `Statement` variant.
5139    #[allow(clippy::cognitive_complexity)]
5140    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
5141        match self {
5142            Statement::Flush {
5143                object_type,
5144                location,
5145                channel,
5146                read_lock,
5147                export,
5148                tables,
5149            } => {
5150                write!(f, "FLUSH")?;
5151                if let Some(location) = location {
5152                    f.write_str(" ")?;
5153                    location.fmt(f)?;
5154                }
5155                write!(f, " {object_type}")?;
5156
5157                if let Some(channel) = channel {
5158                    write!(f, " FOR CHANNEL {channel}")?;
5159                }
5160
5161                write!(
5162                    f,
5163                    "{tables}{read}{export}",
5164                    tables = if !tables.is_empty() {
5165                        format!(" {}", display_comma_separated(tables))
5166                    } else {
5167                        String::new()
5168                    },
5169                    export = if *export { " FOR EXPORT" } else { "" },
5170                    read = if *read_lock { " WITH READ LOCK" } else { "" }
5171                )
5172            }
5173            Statement::Kill { modifier, id } => {
5174                write!(f, "KILL ")?;
5175
5176                if let Some(m) = modifier {
5177                    write!(f, "{m} ")?;
5178                }
5179
5180                write!(f, "{id}")
5181            }
5182            Statement::ExplainTable {
5183                describe_alias,
5184                hive_format,
5185                has_table_keyword,
5186                table_name,
5187            } => {
5188                write!(f, "{describe_alias} ")?;
5189
5190                if let Some(format) = hive_format {
5191                    write!(f, "{format} ")?;
5192                }
5193                if *has_table_keyword {
5194                    write!(f, "TABLE ")?;
5195                }
5196
5197                write!(f, "{table_name}")
5198            }
5199            Statement::Explain {
5200                describe_alias,
5201                verbose,
5202                analyze,
5203                query_plan,
5204                estimate,
5205                statement,
5206                format,
5207                options,
5208            } => {
5209                write!(f, "{describe_alias} ")?;
5210
5211                if *query_plan {
5212                    write!(f, "QUERY PLAN ")?;
5213                }
5214                if *analyze {
5215                    write!(f, "ANALYZE ")?;
5216                }
5217                if *estimate {
5218                    write!(f, "ESTIMATE ")?;
5219                }
5220
5221                if *verbose {
5222                    write!(f, "VERBOSE ")?;
5223                }
5224
5225                if let Some(format) = format {
5226                    write!(f, "{format} ")?;
5227                }
5228
5229                if let Some(options) = options {
5230                    write!(f, "({}) ", display_comma_separated(options))?;
5231                }
5232
5233                write!(f, "{statement}")
5234            }
5235            Statement::Query(s) => s.fmt(f),
5236            Statement::Declare { stmts } => {
5237                write!(f, "DECLARE ")?;
5238                write!(f, "{}", display_separated(stmts, "; "))
5239            }
5240            Statement::Fetch {
5241                name,
5242                direction,
5243                position,
5244                into,
5245            } => {
5246                write!(f, "FETCH {direction} {position} {name}")?;
5247
5248                if let Some(into) = into {
5249                    write!(f, " INTO {into}")?;
5250                }
5251
5252                Ok(())
5253            }
5254            Statement::Directory {
5255                overwrite,
5256                local,
5257                path,
5258                file_format,
5259                source,
5260            } => {
5261                write!(
5262                    f,
5263                    "INSERT{overwrite}{local} DIRECTORY '{path}'",
5264                    overwrite = if *overwrite { " OVERWRITE" } else { "" },
5265                    local = if *local { " LOCAL" } else { "" },
5266                    path = path
5267                )?;
5268                if let Some(ref ff) = file_format {
5269                    write!(f, " STORED AS {ff}")?
5270                }
5271                write!(f, " {source}")
5272            }
5273            Statement::Msck(msck) => msck.fmt(f),
5274            Statement::Truncate(truncate) => truncate.fmt(f),
5275            Statement::Case(stmt) => {
5276                write!(f, "{stmt}")
5277            }
5278            Statement::If(stmt) => {
5279                write!(f, "{stmt}")
5280            }
5281            Statement::While(stmt) => {
5282                write!(f, "{stmt}")
5283            }
5284            Statement::Raise(stmt) => {
5285                write!(f, "{stmt}")
5286            }
5287            Statement::AttachDatabase {
5288                schema_name,
5289                database_file_name,
5290                database,
5291            } => {
5292                let keyword = if *database { "DATABASE " } else { "" };
5293                write!(f, "ATTACH {keyword}{database_file_name} AS {schema_name}")
5294            }
5295            Statement::AttachDuckDBDatabase {
5296                if_not_exists,
5297                database,
5298                database_path,
5299                database_alias,
5300                attach_options,
5301            } => {
5302                write!(
5303                    f,
5304                    "ATTACH{database}{if_not_exists} {database_path}",
5305                    database = if *database { " DATABASE" } else { "" },
5306                    if_not_exists = if *if_not_exists { " IF NOT EXISTS" } else { "" },
5307                )?;
5308                if let Some(alias) = database_alias {
5309                    write!(f, " AS {alias}")?;
5310                }
5311                if !attach_options.is_empty() {
5312                    write!(f, " ({})", display_comma_separated(attach_options))?;
5313                }
5314                Ok(())
5315            }
5316            Statement::DetachDuckDBDatabase {
5317                if_exists,
5318                database,
5319                database_alias,
5320            } => {
5321                write!(
5322                    f,
5323                    "DETACH{database}{if_exists} {database_alias}",
5324                    database = if *database { " DATABASE" } else { "" },
5325                    if_exists = if *if_exists { " IF EXISTS" } else { "" },
5326                )?;
5327                Ok(())
5328            }
5329            Statement::Analyze(analyze) => analyze.fmt(f),
5330            Statement::Insert(insert) => insert.fmt(f),
5331            Statement::Install {
5332                extension_name: name,
5333            } => write!(f, "INSTALL {name}"),
5334
5335            Statement::Load {
5336                extension_name: name,
5337            } => write!(f, "LOAD {name}"),
5338
5339            Statement::Call(function) => write!(f, "CALL {function}"),
5340
5341            Statement::Copy {
5342                source,
5343                to,
5344                target,
5345                options,
5346                legacy_options,
5347                values,
5348            } => {
5349                write!(f, "COPY")?;
5350                match source {
5351                    CopySource::Query(query) => write!(f, " ({query})")?,
5352                    CopySource::Table {
5353                        table_name,
5354                        columns,
5355                    } => {
5356                        write!(f, " {table_name}")?;
5357                        if !columns.is_empty() {
5358                            write!(f, " ({})", display_comma_separated(columns))?;
5359                        }
5360                    }
5361                }
5362                write!(f, " {} {}", if *to { "TO" } else { "FROM" }, target)?;
5363                if !options.is_empty() {
5364                    write!(f, " ({})", display_comma_separated(options))?;
5365                }
5366                if !legacy_options.is_empty() {
5367                    write!(f, " {}", display_separated(legacy_options, " "))?;
5368                }
5369                if !values.is_empty() {
5370                    writeln!(f, ";")?;
5371                    let mut delim = "";
5372                    for v in values {
5373                        write!(f, "{delim}")?;
5374                        delim = "\t";
5375                        if let Some(v) = v {
5376                            write!(f, "{v}")?;
5377                        } else {
5378                            write!(f, "\\N")?;
5379                        }
5380                    }
5381                    write!(f, "\n\\.")?;
5382                }
5383                Ok(())
5384            }
5385            Statement::Update(update) => update.fmt(f),
5386            Statement::Delete(delete) => delete.fmt(f),
5387            Statement::Open(open) => open.fmt(f),
5388            Statement::Close { cursor } => {
5389                write!(f, "CLOSE {cursor}")?;
5390
5391                Ok(())
5392            }
5393            Statement::CreateDatabase {
5394                db_name,
5395                if_not_exists,
5396                location,
5397                managed_location,
5398                or_replace,
5399                transient,
5400                clone,
5401                data_retention_time_in_days,
5402                max_data_extension_time_in_days,
5403                external_volume,
5404                catalog,
5405                replace_invalid_characters,
5406                default_ddl_collation,
5407                storage_serialization_policy,
5408                comment,
5409                default_charset,
5410                default_collation,
5411                catalog_sync,
5412                catalog_sync_namespace_mode,
5413                catalog_sync_namespace_flatten_delimiter,
5414                with_tags,
5415                with_contacts,
5416            } => {
5417                write!(
5418                    f,
5419                    "CREATE {or_replace}{transient}DATABASE {if_not_exists}{name}",
5420                    or_replace = if *or_replace { "OR REPLACE " } else { "" },
5421                    transient = if *transient { "TRANSIENT " } else { "" },
5422                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
5423                    name = db_name,
5424                )?;
5425
5426                if let Some(l) = location {
5427                    write!(f, " LOCATION '{l}'")?;
5428                }
5429                if let Some(ml) = managed_location {
5430                    write!(f, " MANAGEDLOCATION '{ml}'")?;
5431                }
5432                if let Some(clone) = clone {
5433                    write!(f, " CLONE {clone}")?;
5434                }
5435
5436                if let Some(value) = data_retention_time_in_days {
5437                    write!(f, " DATA_RETENTION_TIME_IN_DAYS = {value}")?;
5438                }
5439
5440                if let Some(value) = max_data_extension_time_in_days {
5441                    write!(f, " MAX_DATA_EXTENSION_TIME_IN_DAYS = {value}")?;
5442                }
5443
5444                if let Some(vol) = external_volume {
5445                    write!(f, " EXTERNAL_VOLUME = '{vol}'")?;
5446                }
5447
5448                if let Some(cat) = catalog {
5449                    write!(f, " CATALOG = '{cat}'")?;
5450                }
5451
5452                if let Some(true) = replace_invalid_characters {
5453                    write!(f, " REPLACE_INVALID_CHARACTERS = TRUE")?;
5454                } else if let Some(false) = replace_invalid_characters {
5455                    write!(f, " REPLACE_INVALID_CHARACTERS = FALSE")?;
5456                }
5457
5458                if let Some(collation) = default_ddl_collation {
5459                    write!(f, " DEFAULT_DDL_COLLATION = '{collation}'")?;
5460                }
5461
5462                if let Some(policy) = storage_serialization_policy {
5463                    write!(f, " STORAGE_SERIALIZATION_POLICY = {policy}")?;
5464                }
5465
5466                if let Some(comment) = comment {
5467                    write!(f, " COMMENT = '{comment}'")?;
5468                }
5469
5470                if let Some(charset) = default_charset {
5471                    write!(f, " DEFAULT CHARACTER SET {charset}")?;
5472                }
5473
5474                if let Some(collation) = default_collation {
5475                    write!(f, " DEFAULT COLLATE {collation}")?;
5476                }
5477
5478                if let Some(sync) = catalog_sync {
5479                    write!(f, " CATALOG_SYNC = '{sync}'")?;
5480                }
5481
5482                if let Some(mode) = catalog_sync_namespace_mode {
5483                    write!(f, " CATALOG_SYNC_NAMESPACE_MODE = {mode}")?;
5484                }
5485
5486                if let Some(delim) = catalog_sync_namespace_flatten_delimiter {
5487                    write!(f, " CATALOG_SYNC_NAMESPACE_FLATTEN_DELIMITER = '{delim}'")?;
5488                }
5489
5490                if let Some(tags) = with_tags {
5491                    write!(f, " WITH TAG ({})", display_comma_separated(tags))?;
5492                }
5493
5494                if let Some(contacts) = with_contacts {
5495                    write!(f, " WITH CONTACT ({})", display_comma_separated(contacts))?;
5496                }
5497                Ok(())
5498            }
5499            Statement::CreateFunction(create_function) => create_function.fmt(f),
5500            Statement::CreateDomain(create_domain) => create_domain.fmt(f),
5501            Statement::CreateTrigger(create_trigger) => create_trigger.fmt(f),
5502            Statement::DropTrigger(drop_trigger) => drop_trigger.fmt(f),
5503            Statement::CreateProcedure {
5504                name,
5505                or_alter,
5506                params,
5507                language,
5508                body,
5509            } => {
5510                write!(
5511                    f,
5512                    "CREATE {or_alter}PROCEDURE {name}",
5513                    or_alter = if *or_alter { "OR ALTER " } else { "" },
5514                    name = name
5515                )?;
5516
5517                if let Some(p) = params {
5518                    if !p.is_empty() {
5519                        write!(f, " ({})", display_comma_separated(p))?;
5520                    }
5521                }
5522
5523                if let Some(language) = language {
5524                    write!(f, " LANGUAGE {language}")?;
5525                }
5526
5527                write!(f, " AS {body}")
5528            }
5529            Statement::CreateMacro {
5530                or_replace,
5531                temporary,
5532                name,
5533                args,
5534                definition,
5535            } => {
5536                write!(
5537                    f,
5538                    "CREATE {or_replace}{temp}MACRO {name}",
5539                    temp = if *temporary { "TEMPORARY " } else { "" },
5540                    or_replace = if *or_replace { "OR REPLACE " } else { "" },
5541                )?;
5542                if let Some(args) = args {
5543                    write!(f, "({})", display_comma_separated(args))?;
5544                }
5545                match definition {
5546                    MacroDefinition::Expr(expr) => write!(f, " AS {expr}")?,
5547                    MacroDefinition::Table(query) => write!(f, " AS TABLE {query}")?,
5548                }
5549                Ok(())
5550            }
5551            Statement::CreateView(create_view) => create_view.fmt(f),
5552            Statement::CreateTable(create_table) => create_table.fmt(f),
5553            Statement::LoadData {
5554                local,
5555                inpath,
5556                overwrite,
5557                table_name,
5558                partitioned,
5559                table_format,
5560            } => {
5561                write!(
5562                    f,
5563                    "LOAD DATA {local}INPATH '{inpath}' {overwrite}INTO TABLE {table_name}",
5564                    local = if *local { "LOCAL " } else { "" },
5565                    inpath = inpath,
5566                    overwrite = if *overwrite { "OVERWRITE " } else { "" },
5567                    table_name = table_name,
5568                )?;
5569                if let Some(ref parts) = &partitioned {
5570                    if !parts.is_empty() {
5571                        write!(f, " PARTITION ({})", display_comma_separated(parts))?;
5572                    }
5573                }
5574                if let Some(HiveLoadDataFormat {
5575                    serde,
5576                    input_format,
5577                }) = &table_format
5578                {
5579                    write!(f, " INPUTFORMAT {input_format} SERDE {serde}")?;
5580                }
5581                Ok(())
5582            }
5583            Statement::CreateVirtualTable {
5584                name,
5585                if_not_exists,
5586                module_name,
5587                module_args,
5588            } => {
5589                write!(
5590                    f,
5591                    "CREATE VIRTUAL TABLE {if_not_exists}{name} USING {module_name}",
5592                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
5593                    name = name,
5594                    module_name = module_name
5595                )?;
5596                if !module_args.is_empty() {
5597                    write!(f, " ({})", display_comma_separated(module_args))?;
5598                }
5599                Ok(())
5600            }
5601            Statement::CreateIndex(create_index) => create_index.fmt(f),
5602            Statement::CreateExtension(create_extension) => write!(f, "{create_extension}"),
5603            Statement::CreateCollation(create_collation) => write!(f, "{create_collation}"),
5604            Statement::CreateTextSearchConfiguration(v) => write!(f, "{v}"),
5605            Statement::CreateTextSearchDictionary(v) => write!(f, "{v}"),
5606            Statement::CreateTextSearchParser(v) => write!(f, "{v}"),
5607            Statement::CreateTextSearchTemplate(v) => write!(f, "{v}"),
5608            Statement::CreatePublication(v) => write!(f, "{v}"),
5609            Statement::CreateSubscription(v) => write!(f, "{v}"),
5610            Statement::CreateCast(v) => write!(f, "{v}"),
5611            Statement::CreateConversion(v) => write!(f, "{v}"),
5612            Statement::CreateLanguage(v) => write!(f, "{v}"),
5613            Statement::CreateRule(v) => write!(f, "{v}"),
5614            Statement::CreateStatistics(v) => write!(f, "{v}"),
5615            Statement::CreateAccessMethod(v) => write!(f, "{v}"),
5616            Statement::CreateEventTrigger(v) => write!(f, "{v}"),
5617            Statement::CreateTransform(v) => write!(f, "{v}"),
5618            Statement::SecurityLabel(v) => write!(f, "{v}"),
5619            Statement::CreateUserMapping(v) => write!(f, "{v}"),
5620            Statement::CreateTablespace(v) => write!(f, "{v}"),
5621            Statement::DropExtension(drop_extension) => write!(f, "{drop_extension}"),
5622            Statement::DropOperator(drop_operator) => write!(f, "{drop_operator}"),
5623            Statement::DropOperatorFamily(drop_operator_family) => {
5624                write!(f, "{drop_operator_family}")
5625            }
5626            Statement::DropOperatorClass(drop_operator_class) => {
5627                write!(f, "{drop_operator_class}")
5628            }
5629            Statement::CreateRole(create_role) => write!(f, "{create_role}"),
5630            Statement::CreateSecret {
5631                or_replace,
5632                temporary,
5633                if_not_exists,
5634                name,
5635                storage_specifier,
5636                secret_type,
5637                options,
5638            } => {
5639                write!(
5640                    f,
5641                    "CREATE {or_replace}",
5642                    or_replace = if *or_replace { "OR REPLACE " } else { "" },
5643                )?;
5644                if let Some(t) = temporary {
5645                    write!(f, "{}", if *t { "TEMPORARY " } else { "PERSISTENT " })?;
5646                }
5647                write!(
5648                    f,
5649                    "SECRET {if_not_exists}",
5650                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
5651                )?;
5652                if let Some(n) = name {
5653                    write!(f, "{n} ")?;
5654                };
5655                if let Some(s) = storage_specifier {
5656                    write!(f, "IN {s} ")?;
5657                }
5658                write!(f, "( TYPE {secret_type}",)?;
5659                if !options.is_empty() {
5660                    write!(f, ", {o}", o = display_comma_separated(options))?;
5661                }
5662                write!(f, " )")?;
5663                Ok(())
5664            }
5665            Statement::CreateServer(stmt) => {
5666                write!(f, "{stmt}")
5667            }
5668            Statement::CreateForeignDataWrapper(stmt) => write!(f, "{stmt}"),
5669            Statement::CreateForeignTable(stmt) => write!(f, "{stmt}"),
5670            Statement::CreatePolicy(policy) => write!(f, "{policy}"),
5671            Statement::CreateConnector(create_connector) => create_connector.fmt(f),
5672            Statement::CreateOperator(create_operator) => create_operator.fmt(f),
5673            Statement::CreateOperatorFamily(create_operator_family) => {
5674                create_operator_family.fmt(f)
5675            }
5676            Statement::CreateOperatorClass(create_operator_class) => create_operator_class.fmt(f),
5677            Statement::CreateAggregate(create_aggregate) => create_aggregate.fmt(f),
5678            Statement::AlterTable(alter_table) => write!(f, "{alter_table}"),
5679            Statement::AlterIndex { name, operation } => {
5680                write!(f, "ALTER INDEX {name} {operation}")
5681            }
5682            Statement::AlterView {
5683                name,
5684                columns,
5685                query,
5686                with_options,
5687            } => {
5688                write!(f, "ALTER VIEW {name}")?;
5689                if !with_options.is_empty() {
5690                    write!(f, " WITH ({})", display_comma_separated(with_options))?;
5691                }
5692                if !columns.is_empty() {
5693                    write!(f, " ({})", display_comma_separated(columns))?;
5694                }
5695                write!(f, " AS {query}")
5696            }
5697            Statement::AlterDomain(alter_domain) => write!(f, "{alter_domain}"),
5698            Statement::AlterExtension(alter_extension) => write!(f, "{alter_extension}"),
5699            Statement::AlterFunction(alter_function) => write!(f, "{alter_function}"),
5700            Statement::AlterTrigger(alter_trigger) => write!(f, "{alter_trigger}"),
5701            Statement::AlterType(AlterType { name, operation }) => {
5702                write!(f, "ALTER TYPE {name} {operation}")
5703            }
5704            Statement::AlterCollation(alter_collation) => write!(f, "{alter_collation}"),
5705            Statement::AlterOperator(alter_operator) => write!(f, "{alter_operator}"),
5706            Statement::AlterOperatorFamily(alter_operator_family) => {
5707                write!(f, "{alter_operator_family}")
5708            }
5709            Statement::AlterOperatorClass(alter_operator_class) => {
5710                write!(f, "{alter_operator_class}")
5711            }
5712            Statement::AlterRole { name, operation } => {
5713                write!(f, "ALTER ROLE {name} {operation}")
5714            }
5715            Statement::AlterPolicy(alter_policy) => write!(f, "{alter_policy}"),
5716            Statement::AlterConnector {
5717                name,
5718                properties,
5719                url,
5720                owner,
5721            } => {
5722                write!(f, "ALTER CONNECTOR {name}")?;
5723                if let Some(properties) = properties {
5724                    write!(
5725                        f,
5726                        " SET DCPROPERTIES({})",
5727                        display_comma_separated(properties)
5728                    )?;
5729                }
5730                if let Some(url) = url {
5731                    write!(f, " SET URL '{url}'")?;
5732                }
5733                if let Some(owner) = owner {
5734                    write!(f, " SET OWNER {owner}")?;
5735                }
5736                Ok(())
5737            }
5738            Statement::AlterSession {
5739                set,
5740                session_params,
5741            } => {
5742                write!(
5743                    f,
5744                    "ALTER SESSION {set}",
5745                    set = if *set { "SET" } else { "UNSET" }
5746                )?;
5747                if !session_params.options.is_empty() {
5748                    if *set {
5749                        write!(f, " {session_params}")?;
5750                    } else {
5751                        let options = session_params
5752                            .options
5753                            .iter()
5754                            .map(|p| p.option_name.clone())
5755                            .collect::<Vec<_>>();
5756                        write!(f, " {}", display_separated(&options, ", "))?;
5757                    }
5758                }
5759                Ok(())
5760            }
5761            Statement::Drop {
5762                object_type,
5763                if_exists,
5764                names,
5765                cascade,
5766                restrict,
5767                purge,
5768                temporary,
5769                table,
5770            } => {
5771                write!(
5772                    f,
5773                    "DROP {}{}{} {}{}{}{}",
5774                    if *temporary { "TEMPORARY " } else { "" },
5775                    object_type,
5776                    if *if_exists { " IF EXISTS" } else { "" },
5777                    display_comma_separated(names),
5778                    if *cascade { " CASCADE" } else { "" },
5779                    if *restrict { " RESTRICT" } else { "" },
5780                    if *purge { " PURGE" } else { "" },
5781                )?;
5782                if let Some(table_name) = table.as_ref() {
5783                    write!(f, " ON {table_name}")?;
5784                };
5785                Ok(())
5786            }
5787            Statement::DropFunction(drop_function) => write!(f, "{drop_function}"),
5788            Statement::DropDomain(DropDomain {
5789                if_exists,
5790                name,
5791                drop_behavior,
5792            }) => {
5793                write!(
5794                    f,
5795                    "DROP DOMAIN{} {name}",
5796                    if *if_exists { " IF EXISTS" } else { "" },
5797                )?;
5798                if let Some(op) = drop_behavior {
5799                    write!(f, " {op}")?;
5800                }
5801                Ok(())
5802            }
5803            Statement::DropProcedure {
5804                if_exists,
5805                proc_desc,
5806                drop_behavior,
5807            } => {
5808                write!(
5809                    f,
5810                    "DROP PROCEDURE{} {}",
5811                    if *if_exists { " IF EXISTS" } else { "" },
5812                    display_comma_separated(proc_desc),
5813                )?;
5814                if let Some(op) = drop_behavior {
5815                    write!(f, " {op}")?;
5816                }
5817                Ok(())
5818            }
5819            Statement::DropSecret {
5820                if_exists,
5821                temporary,
5822                name,
5823                storage_specifier,
5824            } => {
5825                write!(f, "DROP ")?;
5826                if let Some(t) = temporary {
5827                    write!(f, "{}", if *t { "TEMPORARY " } else { "PERSISTENT " })?;
5828                }
5829                write!(
5830                    f,
5831                    "SECRET {if_exists}{name}",
5832                    if_exists = if *if_exists { "IF EXISTS " } else { "" },
5833                )?;
5834                if let Some(s) = storage_specifier {
5835                    write!(f, " FROM {s}")?;
5836                }
5837                Ok(())
5838            }
5839            Statement::DropPolicy(policy) => write!(f, "{policy}"),
5840            Statement::DropConnector { if_exists, name } => {
5841                write!(
5842                    f,
5843                    "DROP CONNECTOR {if_exists}{name}",
5844                    if_exists = if *if_exists { "IF EXISTS " } else { "" }
5845                )?;
5846                Ok(())
5847            }
5848            Statement::Discard { object_type } => {
5849                write!(f, "DISCARD {object_type}")?;
5850                Ok(())
5851            }
5852            Self::Set(set) => write!(f, "{set}"),
5853            Statement::ShowVariable { variable } => {
5854                write!(f, "SHOW")?;
5855                if !variable.is_empty() {
5856                    write!(f, " {}", display_separated(variable, " "))?;
5857                }
5858                Ok(())
5859            }
5860            Statement::ShowStatus {
5861                filter,
5862                global,
5863                session,
5864            } => {
5865                write!(f, "SHOW")?;
5866                if *global {
5867                    write!(f, " GLOBAL")?;
5868                }
5869                if *session {
5870                    write!(f, " SESSION")?;
5871                }
5872                write!(f, " STATUS")?;
5873                if filter.is_some() {
5874                    write!(f, " {}", filter.as_ref().unwrap())?;
5875                }
5876                Ok(())
5877            }
5878            Statement::ShowVariables {
5879                filter,
5880                global,
5881                session,
5882            } => {
5883                write!(f, "SHOW")?;
5884                if *global {
5885                    write!(f, " GLOBAL")?;
5886                }
5887                if *session {
5888                    write!(f, " SESSION")?;
5889                }
5890                write!(f, " VARIABLES")?;
5891                if filter.is_some() {
5892                    write!(f, " {}", filter.as_ref().unwrap())?;
5893                }
5894                Ok(())
5895            }
5896            Statement::ShowCreate { obj_type, obj_name } => {
5897                write!(f, "SHOW CREATE {obj_type} {obj_name}",)?;
5898                Ok(())
5899            }
5900            Statement::ShowColumns {
5901                extended,
5902                full,
5903                show_options,
5904            } => {
5905                write!(
5906                    f,
5907                    "SHOW {extended}{full}COLUMNS{show_options}",
5908                    extended = if *extended { "EXTENDED " } else { "" },
5909                    full = if *full { "FULL " } else { "" },
5910                )?;
5911                Ok(())
5912            }
5913            Statement::ShowDatabases {
5914                terse,
5915                history,
5916                show_options,
5917            } => {
5918                write!(
5919                    f,
5920                    "SHOW {terse}DATABASES{history}{show_options}",
5921                    terse = if *terse { "TERSE " } else { "" },
5922                    history = if *history { " HISTORY" } else { "" },
5923                )?;
5924                Ok(())
5925            }
5926            Statement::ShowCatalogs {
5927                terse,
5928                history,
5929                show_options,
5930            } => {
5931                write!(
5932                    f,
5933                    "SHOW {terse}CATALOGS{history}{show_options}",
5934                    terse = if *terse { "TERSE " } else { "" },
5935                    history = if *history { " HISTORY" } else { "" },
5936                )?;
5937                Ok(())
5938            }
5939            Statement::ShowProcessList { full } => {
5940                write!(
5941                    f,
5942                    "SHOW {full}PROCESSLIST",
5943                    full = if *full { "FULL " } else { "" },
5944                )?;
5945                Ok(())
5946            }
5947            Statement::ShowSchemas {
5948                terse,
5949                history,
5950                show_options,
5951            } => {
5952                write!(
5953                    f,
5954                    "SHOW {terse}SCHEMAS{history}{show_options}",
5955                    terse = if *terse { "TERSE " } else { "" },
5956                    history = if *history { " HISTORY" } else { "" },
5957                )?;
5958                Ok(())
5959            }
5960            Statement::ShowObjects(ShowObjects {
5961                terse,
5962                show_options,
5963            }) => {
5964                write!(
5965                    f,
5966                    "SHOW {terse}OBJECTS{show_options}",
5967                    terse = if *terse { "TERSE " } else { "" },
5968                )?;
5969                Ok(())
5970            }
5971            Statement::ShowTables {
5972                terse,
5973                history,
5974                extended,
5975                full,
5976                external,
5977                show_options,
5978            } => {
5979                write!(
5980                    f,
5981                    "SHOW {terse}{extended}{full}{external}TABLES{history}{show_options}",
5982                    terse = if *terse { "TERSE " } else { "" },
5983                    extended = if *extended { "EXTENDED " } else { "" },
5984                    full = if *full { "FULL " } else { "" },
5985                    external = if *external { "EXTERNAL " } else { "" },
5986                    history = if *history { " HISTORY" } else { "" },
5987                )?;
5988                Ok(())
5989            }
5990            Statement::ShowViews {
5991                terse,
5992                materialized,
5993                show_options,
5994            } => {
5995                write!(
5996                    f,
5997                    "SHOW {terse}{materialized}VIEWS{show_options}",
5998                    terse = if *terse { "TERSE " } else { "" },
5999                    materialized = if *materialized { "MATERIALIZED " } else { "" }
6000                )?;
6001                Ok(())
6002            }
6003            Statement::ShowFunctions { filter } => {
6004                write!(f, "SHOW FUNCTIONS")?;
6005                if let Some(filter) = filter {
6006                    write!(f, " {filter}")?;
6007                }
6008                Ok(())
6009            }
6010            Statement::Use(use_expr) => use_expr.fmt(f),
6011            Statement::ShowCollation { filter } => {
6012                write!(f, "SHOW COLLATION")?;
6013                if let Some(filter) = filter {
6014                    write!(f, " {filter}")?;
6015                }
6016                Ok(())
6017            }
6018            Statement::ShowCharset(show_stm) => show_stm.fmt(f),
6019            Statement::StartTransaction {
6020                modes,
6021                begin: syntax_begin,
6022                transaction,
6023                modifier,
6024                statements,
6025                exception,
6026                has_end_keyword,
6027            } => {
6028                if *syntax_begin {
6029                    if let Some(modifier) = *modifier {
6030                        write!(f, "BEGIN {modifier}")?;
6031                    } else {
6032                        write!(f, "BEGIN")?;
6033                    }
6034                } else {
6035                    write!(f, "START")?;
6036                }
6037                if let Some(transaction) = transaction {
6038                    write!(f, " {transaction}")?;
6039                }
6040                if !modes.is_empty() {
6041                    write!(f, " {}", display_comma_separated(modes))?;
6042                }
6043                if !statements.is_empty() {
6044                    write!(f, " ")?;
6045                    format_statement_list(f, statements)?;
6046                }
6047                if let Some(exception_when) = exception {
6048                    write!(f, " EXCEPTION")?;
6049                    for when in exception_when {
6050                        write!(f, " {when}")?;
6051                    }
6052                }
6053                if *has_end_keyword {
6054                    write!(f, " END")?;
6055                }
6056                Ok(())
6057            }
6058            Statement::Commit {
6059                chain,
6060                end: end_syntax,
6061                modifier,
6062            } => {
6063                if *end_syntax {
6064                    write!(f, "END")?;
6065                    if let Some(modifier) = *modifier {
6066                        write!(f, " {modifier}")?;
6067                    }
6068                    if *chain {
6069                        write!(f, " AND CHAIN")?;
6070                    }
6071                } else {
6072                    write!(f, "COMMIT{}", if *chain { " AND CHAIN" } else { "" })?;
6073                }
6074                Ok(())
6075            }
6076            Statement::Rollback { chain, savepoint } => {
6077                write!(f, "ROLLBACK")?;
6078
6079                if *chain {
6080                    write!(f, " AND CHAIN")?;
6081                }
6082
6083                if let Some(savepoint) = savepoint {
6084                    write!(f, " TO SAVEPOINT {savepoint}")?;
6085                }
6086
6087                Ok(())
6088            }
6089            Statement::CreateSchema {
6090                schema_name,
6091                if_not_exists,
6092                with,
6093                options,
6094                default_collate_spec,
6095                clone,
6096            } => {
6097                write!(
6098                    f,
6099                    "CREATE SCHEMA {if_not_exists}{name}",
6100                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
6101                    name = schema_name
6102                )?;
6103
6104                if let Some(collate) = default_collate_spec {
6105                    write!(f, " DEFAULT COLLATE {collate}")?;
6106                }
6107
6108                if let Some(with) = with {
6109                    write!(f, " WITH ({})", display_comma_separated(with))?;
6110                }
6111
6112                if let Some(options) = options {
6113                    write!(f, " OPTIONS({})", display_comma_separated(options))?;
6114                }
6115
6116                if let Some(clone) = clone {
6117                    write!(f, " CLONE {clone}")?;
6118                }
6119                Ok(())
6120            }
6121            Statement::Assert { condition, message } => {
6122                write!(f, "ASSERT {condition}")?;
6123                if let Some(m) = message {
6124                    write!(f, " AS {m}")?;
6125                }
6126                Ok(())
6127            }
6128            Statement::Grant(grant) => write!(f, "{grant}"),
6129            Statement::Deny(s) => write!(f, "{s}"),
6130            Statement::Revoke(revoke) => write!(f, "{revoke}"),
6131            Statement::Deallocate { name, prepare } => write!(
6132                f,
6133                "DEALLOCATE {prepare}{name}",
6134                prepare = if *prepare { "PREPARE " } else { "" },
6135                name = name,
6136            ),
6137            Statement::Execute {
6138                name,
6139                parameters,
6140                has_parentheses,
6141                immediate,
6142                into,
6143                using,
6144                output,
6145                default,
6146            } => {
6147                let (open, close) = if *has_parentheses {
6148                    // Space before `(` only when there is no name directly preceding it.
6149                    (if name.is_some() { "(" } else { " (" }, ")")
6150                } else {
6151                    (if parameters.is_empty() { "" } else { " " }, "")
6152                };
6153                write!(f, "EXECUTE")?;
6154                if *immediate {
6155                    write!(f, " IMMEDIATE")?;
6156                }
6157                if let Some(name) = name {
6158                    write!(f, " {name}")?;
6159                }
6160                write!(f, "{open}{}{close}", display_comma_separated(parameters),)?;
6161                if !into.is_empty() {
6162                    write!(f, " INTO {}", display_comma_separated(into))?;
6163                }
6164                if !using.is_empty() {
6165                    write!(f, " USING {}", display_comma_separated(using))?;
6166                };
6167                if *output {
6168                    write!(f, " OUTPUT")?;
6169                }
6170                if *default {
6171                    write!(f, " DEFAULT")?;
6172                }
6173                Ok(())
6174            }
6175            Statement::Prepare {
6176                name,
6177                data_types,
6178                statement,
6179            } => {
6180                write!(f, "PREPARE {name} ")?;
6181                if !data_types.is_empty() {
6182                    write!(f, "({}) ", display_comma_separated(data_types))?;
6183                }
6184                write!(f, "AS {statement}")
6185            }
6186            Statement::Comment {
6187                object_type,
6188                object_name,
6189                comment,
6190                if_exists,
6191            } => {
6192                write!(f, "COMMENT ")?;
6193                if *if_exists {
6194                    write!(f, "IF EXISTS ")?
6195                };
6196                write!(f, "ON {object_type} {object_name} IS ")?;
6197                if let Some(c) = comment {
6198                    write!(f, "'{c}'")
6199                } else {
6200                    write!(f, "NULL")
6201                }
6202            }
6203            Statement::Savepoint { name } => {
6204                write!(f, "SAVEPOINT ")?;
6205                write!(f, "{name}")
6206            }
6207            Statement::ReleaseSavepoint { name } => {
6208                write!(f, "RELEASE SAVEPOINT {name}")
6209            }
6210            Statement::Merge(merge) => merge.fmt(f),
6211            Statement::Cache {
6212                table_name,
6213                table_flag,
6214                has_as,
6215                options,
6216                query,
6217            } => {
6218                if let Some(table_flag) = table_flag {
6219                    write!(f, "CACHE {table_flag} TABLE {table_name}")?;
6220                } else {
6221                    write!(f, "CACHE TABLE {table_name}")?;
6222                }
6223
6224                if !options.is_empty() {
6225                    write!(f, " OPTIONS({})", display_comma_separated(options))?;
6226                }
6227
6228                match (*has_as, query) {
6229                    (true, Some(query)) => write!(f, " AS {query}"),
6230                    (true, None) => f.write_str(" AS"),
6231                    (false, Some(query)) => write!(f, " {query}"),
6232                    (false, None) => Ok(()),
6233                }
6234            }
6235            Statement::UNCache {
6236                table_name,
6237                if_exists,
6238            } => {
6239                if *if_exists {
6240                    write!(f, "UNCACHE TABLE IF EXISTS {table_name}")
6241                } else {
6242                    write!(f, "UNCACHE TABLE {table_name}")
6243                }
6244            }
6245            Statement::CreateSequence {
6246                temporary,
6247                if_not_exists,
6248                name,
6249                data_type,
6250                sequence_options,
6251                owned_by,
6252            } => {
6253                let as_type: String = if let Some(dt) = data_type.as_ref() {
6254                    //Cannot use format!(" AS {}", dt), due to format! is not available in --target thumbv6m-none-eabi
6255                    // " AS ".to_owned() + &dt.to_string()
6256                    [" AS ", &dt.to_string()].concat()
6257                } else {
6258                    "".to_string()
6259                };
6260                write!(
6261                    f,
6262                    "CREATE {temporary}SEQUENCE {if_not_exists}{name}{as_type}",
6263                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
6264                    temporary = if *temporary { "TEMPORARY " } else { "" },
6265                    name = name,
6266                    as_type = as_type
6267                )?;
6268                for sequence_option in sequence_options {
6269                    write!(f, "{sequence_option}")?;
6270                }
6271                if let Some(ob) = owned_by.as_ref() {
6272                    write!(f, " OWNED BY {ob}")?;
6273                }
6274                write!(f, "")
6275            }
6276            Statement::CreateStage {
6277                or_replace,
6278                temporary,
6279                if_not_exists,
6280                name,
6281                stage_params,
6282                directory_table_params,
6283                file_format,
6284                copy_options,
6285                comment,
6286                ..
6287            } => {
6288                write!(
6289                    f,
6290                    "CREATE {or_replace}{temp}STAGE {if_not_exists}{name}{stage_params}",
6291                    temp = if *temporary { "TEMPORARY " } else { "" },
6292                    or_replace = if *or_replace { "OR REPLACE " } else { "" },
6293                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
6294                )?;
6295                if !directory_table_params.options.is_empty() {
6296                    write!(f, " DIRECTORY=({directory_table_params})")?;
6297                }
6298                if !file_format.options.is_empty() {
6299                    write!(f, " FILE_FORMAT=({file_format})")?;
6300                }
6301                if !copy_options.options.is_empty() {
6302                    write!(f, " COPY_OPTIONS=({copy_options})")?;
6303                }
6304                if comment.is_some() {
6305                    write!(f, " COMMENT='{}'", comment.as_ref().unwrap())?;
6306                }
6307                Ok(())
6308            }
6309            Statement::CopyIntoSnowflake {
6310                kind,
6311                into,
6312                into_columns,
6313                from_obj,
6314                from_obj_alias,
6315                stage_params,
6316                from_transformations,
6317                from_query,
6318                files,
6319                pattern,
6320                file_format,
6321                copy_options,
6322                validation_mode,
6323                partition,
6324            } => {
6325                write!(f, "COPY INTO {into}")?;
6326                if let Some(into_columns) = into_columns {
6327                    write!(f, " ({})", display_comma_separated(into_columns))?;
6328                }
6329                if let Some(from_transformations) = from_transformations {
6330                    // Data load with transformation
6331                    if let Some(from_stage) = from_obj {
6332                        write!(
6333                            f,
6334                            " FROM (SELECT {} FROM {}{}",
6335                            display_separated(from_transformations, ", "),
6336                            from_stage,
6337                            stage_params
6338                        )?;
6339                    }
6340                    if let Some(from_obj_alias) = from_obj_alias {
6341                        write!(f, " AS {from_obj_alias}")?;
6342                    }
6343                    write!(f, ")")?;
6344                } else if let Some(from_obj) = from_obj {
6345                    // Standard data load
6346                    write!(f, " FROM {from_obj}{stage_params}")?;
6347                    if let Some(from_obj_alias) = from_obj_alias {
6348                        write!(f, " AS {from_obj_alias}")?;
6349                    }
6350                } else if let Some(from_query) = from_query {
6351                    // Data unload from query
6352                    write!(f, " FROM ({from_query})")?;
6353                }
6354
6355                if let Some(files) = files {
6356                    write!(f, " FILES = ('{}')", display_separated(files, "', '"))?;
6357                }
6358                if let Some(pattern) = pattern {
6359                    write!(f, " PATTERN = '{pattern}'")?;
6360                }
6361                if let Some(partition) = partition {
6362                    write!(f, " PARTITION BY {partition}")?;
6363                }
6364                if !file_format.options.is_empty() {
6365                    write!(f, " FILE_FORMAT=({file_format})")?;
6366                }
6367                if !copy_options.options.is_empty() {
6368                    match kind {
6369                        CopyIntoSnowflakeKind::Table => {
6370                            write!(f, " COPY_OPTIONS=({copy_options})")?
6371                        }
6372                        CopyIntoSnowflakeKind::Location => write!(f, " {copy_options}")?,
6373                    }
6374                }
6375                if let Some(validation_mode) = validation_mode {
6376                    write!(f, " VALIDATION_MODE = {validation_mode}")?;
6377                }
6378                Ok(())
6379            }
6380            Statement::CreateType {
6381                name,
6382                representation,
6383            } => {
6384                write!(f, "CREATE TYPE {name}")?;
6385                if let Some(repr) = representation {
6386                    write!(f, " {repr}")?;
6387                }
6388                Ok(())
6389            }
6390            Statement::Pragma { name, value, is_eq } => {
6391                write!(f, "PRAGMA {name}")?;
6392                if value.is_some() {
6393                    let val = value.as_ref().unwrap();
6394                    if *is_eq {
6395                        write!(f, " = {val}")?;
6396                    } else {
6397                        write!(f, "({val})")?;
6398                    }
6399                }
6400                Ok(())
6401            }
6402            Statement::Lock(lock) => lock.fmt(f),
6403            Statement::LockTables { tables } => {
6404                write!(f, "LOCK TABLES {}", display_comma_separated(tables))
6405            }
6406            Statement::UnlockTables => {
6407                write!(f, "UNLOCK TABLES")
6408            }
6409            Statement::Unload {
6410                query,
6411                query_text,
6412                to,
6413                auth,
6414                with,
6415                options,
6416            } => {
6417                write!(f, "UNLOAD(")?;
6418                if let Some(query) = query {
6419                    write!(f, "{query}")?;
6420                }
6421                if let Some(query_text) = query_text {
6422                    write!(f, "'{query_text}'")?;
6423                }
6424                write!(f, ") TO {to}")?;
6425                if let Some(auth) = auth {
6426                    write!(f, " IAM_ROLE {auth}")?;
6427                }
6428                if !with.is_empty() {
6429                    write!(f, " WITH ({})", display_comma_separated(with))?;
6430                }
6431                if !options.is_empty() {
6432                    write!(f, " {}", display_separated(options, " "))?;
6433                }
6434                Ok(())
6435            }
6436            Statement::OptimizeTable {
6437                name,
6438                has_table_keyword,
6439                on_cluster,
6440                partition,
6441                include_final,
6442                deduplicate,
6443                predicate,
6444                zorder,
6445            } => {
6446                write!(f, "OPTIMIZE")?;
6447                if *has_table_keyword {
6448                    write!(f, " TABLE")?;
6449                }
6450                write!(f, " {name}")?;
6451                if let Some(on_cluster) = on_cluster {
6452                    write!(f, " ON CLUSTER {on_cluster}")?;
6453                }
6454                if let Some(partition) = partition {
6455                    write!(f, " {partition}")?;
6456                }
6457                if *include_final {
6458                    write!(f, " FINAL")?;
6459                }
6460                if let Some(deduplicate) = deduplicate {
6461                    write!(f, " {deduplicate}")?;
6462                }
6463                if let Some(predicate) = predicate {
6464                    write!(f, " WHERE {predicate}")?;
6465                }
6466                if let Some(zorder) = zorder {
6467                    write!(f, " ZORDER BY ({})", display_comma_separated(zorder))?;
6468                }
6469                Ok(())
6470            }
6471            Statement::LISTEN { channel } => {
6472                write!(f, "LISTEN {channel}")?;
6473                Ok(())
6474            }
6475            Statement::UNLISTEN { channel } => {
6476                write!(f, "UNLISTEN {channel}")?;
6477                Ok(())
6478            }
6479            Statement::NOTIFY { channel, payload } => {
6480                write!(f, "NOTIFY {channel}")?;
6481                if let Some(payload) = payload {
6482                    write!(f, ", '{payload}'")?;
6483                }
6484                Ok(())
6485            }
6486            Statement::RenameTable(rename_tables) => {
6487                write!(f, "RENAME TABLE {}", display_comma_separated(rename_tables))
6488            }
6489            Statement::RaisError {
6490                message,
6491                severity,
6492                state,
6493                arguments,
6494                options,
6495            } => {
6496                write!(f, "RAISERROR({message}, {severity}, {state}")?;
6497                if !arguments.is_empty() {
6498                    write!(f, ", {}", display_comma_separated(arguments))?;
6499                }
6500                write!(f, ")")?;
6501                if !options.is_empty() {
6502                    write!(f, " WITH {}", display_comma_separated(options))?;
6503                }
6504                Ok(())
6505            }
6506            Statement::Throw(s) => write!(f, "{s}"),
6507            Statement::Print(s) => write!(f, "{s}"),
6508            Statement::WaitFor(s) => write!(f, "{s}"),
6509            Statement::Return(r) => write!(f, "{r}"),
6510            Statement::List(command) => write!(f, "LIST {command}"),
6511            Statement::Remove(command) => write!(f, "REMOVE {command}"),
6512            Statement::ExportData(e) => write!(f, "{e}"),
6513            Statement::CreateUser(s) => write!(f, "{s}"),
6514            Statement::AlterSchema(s) => write!(f, "{s}"),
6515            Statement::Vacuum(s) => write!(f, "{s}"),
6516            Statement::AlterUser(s) => write!(f, "{s}"),
6517            Statement::Reset(s) => write!(f, "{s}"),
6518        }
6519    }
6520}
6521
6522/// Can use to describe options in create sequence or table column type identity
6523/// ```sql
6524/// [ INCREMENT [ BY ] increment ]
6525///     [ MINVALUE minvalue | NO MINVALUE ] [ MAXVALUE maxvalue | NO MAXVALUE ]
6526///     [ START [ WITH ] start ] [ CACHE cache ] [ [ NO ] CYCLE ]
6527/// ```
6528#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6529#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6530#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6531pub enum SequenceOptions {
6532    /// `INCREMENT [BY] <expr>` option; second value indicates presence of `BY` keyword.
6533    IncrementBy(Expr, bool),
6534    /// `MINVALUE <expr>` or `NO MINVALUE`.
6535    MinValue(Option<Expr>),
6536    /// `MAXVALUE <expr>` or `NO MAXVALUE`.
6537    MaxValue(Option<Expr>),
6538    /// `START [WITH] <expr>`; second value indicates presence of `WITH`.
6539    StartWith(Expr, bool),
6540    /// `CACHE <expr>` option.
6541    Cache(Expr),
6542    /// `CYCLE` or `NO CYCLE` option.
6543    Cycle(bool),
6544}
6545
6546impl fmt::Display for SequenceOptions {
6547    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6548        match self {
6549            SequenceOptions::IncrementBy(increment, by) => {
6550                write!(
6551                    f,
6552                    " INCREMENT{by} {increment}",
6553                    by = if *by { " BY" } else { "" },
6554                    increment = increment
6555                )
6556            }
6557            SequenceOptions::MinValue(Some(expr)) => {
6558                write!(f, " MINVALUE {expr}")
6559            }
6560            SequenceOptions::MinValue(None) => {
6561                write!(f, " NO MINVALUE")
6562            }
6563            SequenceOptions::MaxValue(Some(expr)) => {
6564                write!(f, " MAXVALUE {expr}")
6565            }
6566            SequenceOptions::MaxValue(None) => {
6567                write!(f, " NO MAXVALUE")
6568            }
6569            SequenceOptions::StartWith(start, with) => {
6570                write!(
6571                    f,
6572                    " START{with} {start}",
6573                    with = if *with { " WITH" } else { "" },
6574                    start = start
6575                )
6576            }
6577            SequenceOptions::Cache(cache) => {
6578                write!(f, " CACHE {}", *cache)
6579            }
6580            SequenceOptions::Cycle(no) => {
6581                write!(f, " {}CYCLE", if *no { "NO " } else { "" })
6582            }
6583        }
6584    }
6585}
6586
6587/// Assignment for a `SET` statement (name [=|TO] value)
6588#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6589#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6590#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6591pub struct SetAssignment {
6592    /// Optional context scope (e.g., SESSION or LOCAL).
6593    pub scope: Option<ContextModifier>,
6594    /// Assignment target name.
6595    pub name: ObjectName,
6596    /// Assigned expression value.
6597    pub value: Expr,
6598}
6599
6600impl fmt::Display for SetAssignment {
6601    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6602        write!(
6603            f,
6604            "{}{} = {}",
6605            self.scope.map(|s| format!("{s}")).unwrap_or_default(),
6606            self.name,
6607            self.value
6608        )
6609    }
6610}
6611
6612/// Target of a `TRUNCATE TABLE` command
6613///
6614/// Note this is its own struct because `visit_relation` requires an `ObjectName` (not a `Vec<ObjectName>`)
6615#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6616#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6617#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6618pub struct TruncateTableTarget {
6619    /// name of the table being truncated
6620    #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
6621    pub name: ObjectName,
6622    /// Postgres-specific option: explicitly exclude descendants (also default without ONLY)
6623    /// ```sql
6624    /// TRUNCATE TABLE ONLY name
6625    /// ```
6626    /// <https://www.postgresql.org/docs/current/sql-truncate.html>
6627    pub only: bool,
6628    /// Postgres-specific option: asterisk after table name to explicitly indicate descendants
6629    /// ```sql
6630    /// TRUNCATE TABLE name [ * ]
6631    /// ```
6632    /// <https://www.postgresql.org/docs/current/sql-truncate.html>
6633    pub has_asterisk: bool,
6634}
6635
6636impl fmt::Display for TruncateTableTarget {
6637    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6638        if self.only {
6639            write!(f, "ONLY ")?;
6640        };
6641        write!(f, "{}", self.name)?;
6642        if self.has_asterisk {
6643            write!(f, " *")?;
6644        };
6645        Ok(())
6646    }
6647}
6648
6649/// A `LOCK` statement.
6650///
6651/// See <https://www.postgresql.org/docs/current/sql-lock.html>
6652#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6653#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6654#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6655pub struct Lock {
6656    /// List of tables to lock.
6657    pub tables: Vec<LockTableTarget>,
6658    /// Lock mode.
6659    pub lock_mode: Option<LockTableMode>,
6660    /// Whether `NOWAIT` was specified.
6661    pub nowait: bool,
6662}
6663
6664impl fmt::Display for Lock {
6665    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6666        write!(f, "LOCK TABLE {}", display_comma_separated(&self.tables))?;
6667        if let Some(lock_mode) = &self.lock_mode {
6668            write!(f, " IN {lock_mode} MODE")?;
6669        }
6670        if self.nowait {
6671            write!(f, " NOWAIT")?;
6672        }
6673        Ok(())
6674    }
6675}
6676
6677/// Target of a `LOCK TABLE` command
6678///
6679/// See <https://www.postgresql.org/docs/current/sql-lock.html>
6680#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6681#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6682#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6683pub struct LockTableTarget {
6684    /// Name of the table being locked.
6685    #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
6686    pub name: ObjectName,
6687    /// Whether `ONLY` was specified to exclude descendant tables.
6688    pub only: bool,
6689    /// Whether `*` was specified to explicitly include descendant tables.
6690    pub has_asterisk: bool,
6691}
6692
6693impl fmt::Display for LockTableTarget {
6694    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6695        if self.only {
6696            write!(f, "ONLY ")?;
6697        }
6698        write!(f, "{}", self.name)?;
6699        if self.has_asterisk {
6700            write!(f, " *")?;
6701        }
6702        Ok(())
6703    }
6704}
6705
6706/// PostgreSQL lock modes for `LOCK TABLE`.
6707///
6708/// See <https://www.postgresql.org/docs/current/sql-lock.html>
6709#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6710#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6711#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6712pub enum LockTableMode {
6713    /// `ACCESS SHARE`
6714    AccessShare,
6715    /// `ROW SHARE`
6716    RowShare,
6717    /// `ROW EXCLUSIVE`
6718    RowExclusive,
6719    /// `SHARE UPDATE EXCLUSIVE`
6720    ShareUpdateExclusive,
6721    /// `SHARE`
6722    Share,
6723    /// `SHARE ROW EXCLUSIVE`
6724    ShareRowExclusive,
6725    /// `EXCLUSIVE`
6726    Exclusive,
6727    /// `ACCESS EXCLUSIVE`
6728    AccessExclusive,
6729}
6730
6731impl fmt::Display for LockTableMode {
6732    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
6733        let text = match self {
6734            Self::AccessShare => "ACCESS SHARE",
6735            Self::RowShare => "ROW SHARE",
6736            Self::RowExclusive => "ROW EXCLUSIVE",
6737            Self::ShareUpdateExclusive => "SHARE UPDATE EXCLUSIVE",
6738            Self::Share => "SHARE",
6739            Self::ShareRowExclusive => "SHARE ROW EXCLUSIVE",
6740            Self::Exclusive => "EXCLUSIVE",
6741            Self::AccessExclusive => "ACCESS EXCLUSIVE",
6742        };
6743        write!(f, "{text}")
6744    }
6745}
6746
6747/// PostgreSQL identity option for TRUNCATE table
6748/// [ RESTART IDENTITY | CONTINUE IDENTITY ]
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 TruncateIdentityOption {
6753    /// Restart identity values (RESTART IDENTITY).
6754    Restart,
6755    /// Continue identity values (CONTINUE IDENTITY).
6756    Continue,
6757}
6758
6759/// Cascade/restrict option for Postgres TRUNCATE table, MySQL GRANT/REVOKE, etc.
6760/// [ CASCADE | RESTRICT ]
6761#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6762#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6763#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6764pub enum CascadeOption {
6765    /// Apply cascading action (e.g., CASCADE).
6766    Cascade,
6767    /// Restrict the action (e.g., RESTRICT).
6768    Restrict,
6769}
6770
6771impl Display for CascadeOption {
6772    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6773        match self {
6774            CascadeOption::Cascade => write!(f, "CASCADE"),
6775            CascadeOption::Restrict => write!(f, "RESTRICT"),
6776        }
6777    }
6778}
6779
6780/// Transaction started with [ TRANSACTION | WORK | TRAN ]
6781#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6782#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6783#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6784pub enum BeginTransactionKind {
6785    /// Standard `TRANSACTION` keyword.
6786    Transaction,
6787    /// Alternate `WORK` keyword.
6788    Work,
6789    /// MSSQL shorthand `TRAN` keyword.
6790    /// See <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/begin-transaction-transact-sql>
6791    Tran,
6792}
6793
6794impl Display for BeginTransactionKind {
6795    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6796        match self {
6797            BeginTransactionKind::Transaction => write!(f, "TRANSACTION"),
6798            BeginTransactionKind::Work => write!(f, "WORK"),
6799            BeginTransactionKind::Tran => write!(f, "TRAN"),
6800        }
6801    }
6802}
6803
6804/// Can use to describe options in  create sequence or table column type identity
6805/// [ MINVALUE minvalue | NO MINVALUE ] [ MAXVALUE maxvalue | NO MAXVALUE ]
6806#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6807#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6808#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6809pub enum MinMaxValue {
6810    /// Clause is not specified.
6811    Empty,
6812    /// NO MINVALUE / NO MAXVALUE.
6813    None,
6814    /// `MINVALUE <expr>` / `MAXVALUE <expr>`.
6815    Some(Expr),
6816}
6817
6818#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6819#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6820#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6821#[non_exhaustive]
6822/// Behavior to apply for `INSERT` when a conflict occurs.
6823pub enum OnInsert {
6824    /// ON DUPLICATE KEY UPDATE (MySQL when the key already exists, then execute an update instead)
6825    DuplicateKeyUpdate(Vec<Assignment>),
6826    /// ON CONFLICT is a PostgreSQL and Sqlite extension
6827    OnConflict(OnConflict),
6828}
6829
6830#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6831#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6832#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6833/// Optional aliases for `INSERT` targets: row alias and optional column aliases.
6834pub struct InsertAliases {
6835    /// Row alias (table-style alias) for the inserted values.
6836    pub row_alias: ObjectName,
6837    /// Optional list of column aliases for the inserted values.
6838    pub col_aliases: Option<Vec<Ident>>,
6839}
6840
6841#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6842#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6843#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6844/// Optional alias for an `INSERT` table; i.e. the table to be inserted into
6845pub struct TableAliasWithoutColumns {
6846    /// `true` if the aliases was explicitly introduced with the "AS" keyword
6847    pub explicit: bool,
6848    /// the alias name itself
6849    pub alias: Ident,
6850}
6851
6852#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6853#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6854#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6855/// `ON CONFLICT` clause representation.
6856pub struct OnConflict {
6857    /// Optional conflict target specifying columns or constraint.
6858    pub conflict_target: Option<ConflictTarget>,
6859    /// Action to take when a conflict occurs.
6860    pub action: OnConflictAction,
6861}
6862#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6863#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6864#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6865/// Target specification for an `ON CONFLICT` clause.
6866pub enum ConflictTarget {
6867    /// Target specified as a list of columns.
6868    Columns(Vec<Ident>),
6869    /// Target specified as a named constraint.
6870    OnConstraint(ObjectName),
6871}
6872#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6873#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6874#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6875/// Action to perform when an `ON CONFLICT` target is matched.
6876pub enum OnConflictAction {
6877    /// Do nothing on conflict.
6878    DoNothing,
6879    /// Perform an update on conflict.
6880    DoUpdate(DoUpdate),
6881}
6882
6883#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6884#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6885#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6886/// Details for `DO UPDATE` action of an `ON CONFLICT` clause.
6887pub struct DoUpdate {
6888    /// Column assignments to perform on update.
6889    pub assignments: Vec<Assignment>,
6890    /// Optional WHERE clause limiting the update.
6891    pub selection: Option<Expr>,
6892}
6893
6894impl fmt::Display for OnInsert {
6895    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6896        match self {
6897            Self::DuplicateKeyUpdate(expr) => write!(
6898                f,
6899                " ON DUPLICATE KEY UPDATE {}",
6900                display_comma_separated(expr)
6901            ),
6902            Self::OnConflict(o) => write!(f, "{o}"),
6903        }
6904    }
6905}
6906impl fmt::Display for OnConflict {
6907    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6908        write!(f, " ON CONFLICT")?;
6909        if let Some(target) = &self.conflict_target {
6910            write!(f, "{target}")?;
6911        }
6912        write!(f, " {}", self.action)
6913    }
6914}
6915impl fmt::Display for ConflictTarget {
6916    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6917        match self {
6918            ConflictTarget::Columns(cols) => write!(f, "({})", display_comma_separated(cols)),
6919            ConflictTarget::OnConstraint(name) => write!(f, " ON CONSTRAINT {name}"),
6920        }
6921    }
6922}
6923impl fmt::Display for OnConflictAction {
6924    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6925        match self {
6926            Self::DoNothing => write!(f, "DO NOTHING"),
6927            Self::DoUpdate(do_update) => {
6928                write!(f, "DO UPDATE")?;
6929                if !do_update.assignments.is_empty() {
6930                    write!(
6931                        f,
6932                        " SET {}",
6933                        display_comma_separated(&do_update.assignments)
6934                    )?;
6935                }
6936                if let Some(selection) = &do_update.selection {
6937                    write!(f, " WHERE {selection}")?;
6938                }
6939                Ok(())
6940            }
6941        }
6942    }
6943}
6944
6945/// Privileges granted in a GRANT statement or revoked in a REVOKE statement.
6946#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6947#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6948#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6949pub enum Privileges {
6950    /// All privileges applicable to the object type
6951    All {
6952        /// Optional keyword from the spec, ignored in practice
6953        with_privileges_keyword: bool,
6954    },
6955    /// Specific privileges (e.g. `SELECT`, `INSERT`)
6956    Actions(Vec<Action>),
6957}
6958
6959impl fmt::Display for Privileges {
6960    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6961        match self {
6962            Privileges::All {
6963                with_privileges_keyword,
6964            } => {
6965                write!(
6966                    f,
6967                    "ALL{}",
6968                    if *with_privileges_keyword {
6969                        " PRIVILEGES"
6970                    } else {
6971                        ""
6972                    }
6973                )
6974            }
6975            Privileges::Actions(actions) => {
6976                write!(f, "{}", display_comma_separated(actions))
6977            }
6978        }
6979    }
6980}
6981
6982/// Specific direction for FETCH statement
6983#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6984#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6985#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6986pub enum FetchDirection {
6987    /// Fetch a specific count of rows.
6988    Count {
6989        /// The limit value for the count.
6990        limit: ValueWithSpan,
6991    },
6992    /// Fetch the next row.
6993    Next,
6994    /// Fetch the prior row.
6995    Prior,
6996    /// Fetch the first row.
6997    First,
6998    /// Fetch the last row.
6999    Last,
7000    /// Fetch an absolute row by index.
7001    Absolute {
7002        /// The absolute index value.
7003        limit: ValueWithSpan,
7004    },
7005    /// Fetch a row relative to the current position.
7006    Relative {
7007        /// The relative offset value.
7008        limit: ValueWithSpan,
7009    },
7010    /// Fetch all rows.
7011    All,
7012    // FORWARD
7013    // FORWARD count
7014    /// Fetch forward by an optional limit.
7015    Forward {
7016        /// Optional forward limit.
7017        limit: Option<ValueWithSpan>,
7018    },
7019    /// Fetch all forward rows.
7020    ForwardAll,
7021    // BACKWARD
7022    // BACKWARD count
7023    /// Fetch backward by an optional limit.
7024    Backward {
7025        /// Optional backward limit.
7026        limit: Option<ValueWithSpan>,
7027    },
7028    /// Fetch all backward rows.
7029    BackwardAll,
7030}
7031
7032impl fmt::Display for FetchDirection {
7033    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7034        match self {
7035            FetchDirection::Count { limit } => f.write_str(&limit.to_string())?,
7036            FetchDirection::Next => f.write_str("NEXT")?,
7037            FetchDirection::Prior => f.write_str("PRIOR")?,
7038            FetchDirection::First => f.write_str("FIRST")?,
7039            FetchDirection::Last => f.write_str("LAST")?,
7040            FetchDirection::Absolute { limit } => {
7041                f.write_str("ABSOLUTE ")?;
7042                f.write_str(&limit.to_string())?;
7043            }
7044            FetchDirection::Relative { limit } => {
7045                f.write_str("RELATIVE ")?;
7046                f.write_str(&limit.to_string())?;
7047            }
7048            FetchDirection::All => f.write_str("ALL")?,
7049            FetchDirection::Forward { limit } => {
7050                f.write_str("FORWARD")?;
7051
7052                if let Some(l) = limit {
7053                    f.write_str(" ")?;
7054                    f.write_str(&l.to_string())?;
7055                }
7056            }
7057            FetchDirection::ForwardAll => f.write_str("FORWARD ALL")?,
7058            FetchDirection::Backward { limit } => {
7059                f.write_str("BACKWARD")?;
7060
7061                if let Some(l) = limit {
7062                    f.write_str(" ")?;
7063                    f.write_str(&l.to_string())?;
7064                }
7065            }
7066            FetchDirection::BackwardAll => f.write_str("BACKWARD ALL")?,
7067        };
7068
7069        Ok(())
7070    }
7071}
7072
7073/// The "position" for a FETCH statement.
7074///
7075/// [MsSql](https://learn.microsoft.com/en-us/sql/t-sql/language-elements/fetch-transact-sql)
7076#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7077#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7078#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7079pub enum FetchPosition {
7080    /// Use `FROM <pos>` position specifier.
7081    From,
7082    /// Use `IN <pos>` position specifier.
7083    In,
7084}
7085
7086impl fmt::Display for FetchPosition {
7087    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7088        match self {
7089            FetchPosition::From => f.write_str("FROM")?,
7090            FetchPosition::In => f.write_str("IN")?,
7091        };
7092
7093        Ok(())
7094    }
7095}
7096
7097/// A privilege on a database object (table, sequence, etc.).
7098#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7099#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7100#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7101pub enum Action {
7102    /// Add a search optimization.
7103    AddSearchOptimization,
7104    /// Apply an `APPLY` operation with a specific type.
7105    Apply {
7106        /// The type of apply operation.
7107        apply_type: ActionApplyType,
7108    },
7109    /// Apply a budget operation.
7110    ApplyBudget,
7111    /// Attach a listing.
7112    AttachListing,
7113    /// Attach a policy.
7114    AttachPolicy,
7115    /// Audit operation.
7116    Audit,
7117    /// Bind a service endpoint.
7118    BindServiceEndpoint,
7119    /// Connect permission.
7120    Connect,
7121    /// Create action, optionally specifying an object type.
7122    Create {
7123        /// Optional object type to create.
7124        obj_type: Option<ActionCreateObjectType>,
7125    },
7126    /// Actions related to database roles.
7127    DatabaseRole {
7128        /// The role name.
7129        role: ObjectName,
7130    },
7131    /// Delete permission.
7132    Delete,
7133    /// Drop permission.
7134    Drop,
7135    /// Evolve schema permission.
7136    EvolveSchema,
7137    /// Exec action (execute) with optional object type.
7138    Exec {
7139        /// Optional execute object type.
7140        obj_type: Option<ActionExecuteObjectType>,
7141    },
7142    /// Execute action with optional object type.
7143    Execute {
7144        /// Optional execute object type.
7145        obj_type: Option<ActionExecuteObjectType>,
7146    },
7147    /// Failover operation.
7148    Failover,
7149    /// Use imported privileges.
7150    ImportedPrivileges,
7151    /// Import a share.
7152    ImportShare,
7153    /// Insert rows with optional column list.
7154    Insert {
7155        /// Optional list of target columns for insert.
7156        columns: Option<Vec<Ident>>,
7157    },
7158    /// Manage operation with a specific manage type.
7159    Manage {
7160        /// The specific manage sub-type.
7161        manage_type: ActionManageType,
7162    },
7163    /// Manage releases.
7164    ManageReleases,
7165    /// Manage versions.
7166    ManageVersions,
7167    /// Modify operation with an optional modify type.
7168    Modify {
7169        /// The optional modify sub-type.
7170        modify_type: Option<ActionModifyType>,
7171    },
7172    /// Monitor operation with an optional monitor type.
7173    Monitor {
7174        /// The optional monitor sub-type.
7175        monitor_type: Option<ActionMonitorType>,
7176    },
7177    /// Operate permission.
7178    Operate,
7179    /// Override share restrictions.
7180    OverrideShareRestrictions,
7181    /// Ownership permission.
7182    Ownership,
7183    /// Purchase a data exchange listing.
7184    PurchaseDataExchangeListing,
7185
7186    /// Read access.
7187    Read,
7188    /// Read session-level access.
7189    ReadSession,
7190    /// References with optional column list.
7191    References {
7192        /// Optional list of referenced column identifiers.
7193        columns: Option<Vec<Ident>>,
7194    },
7195    /// Replication permission.
7196    Replicate,
7197    /// Resolve all references.
7198    ResolveAll,
7199    /// Role-related permission with target role name.
7200    Role {
7201        /// The target role name.
7202        role: ObjectName,
7203    },
7204    /// Select permission with optional column list.
7205    Select {
7206        /// Optional list of selected columns.
7207        columns: Option<Vec<Ident>>,
7208    },
7209    /// Temporary object permission.
7210    Temporary,
7211    /// Trigger-related permission.
7212    Trigger,
7213    /// Truncate permission.
7214    Truncate,
7215    /// Update permission with optional affected columns.
7216    Update {
7217        /// Optional list of columns affected by update.
7218        columns: Option<Vec<Ident>>,
7219    },
7220    /// Usage permission.
7221    Usage,
7222}
7223
7224impl fmt::Display for Action {
7225    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7226        match self {
7227            Action::AddSearchOptimization => f.write_str("ADD SEARCH OPTIMIZATION")?,
7228            Action::Apply { apply_type } => write!(f, "APPLY {apply_type}")?,
7229            Action::ApplyBudget => f.write_str("APPLYBUDGET")?,
7230            Action::AttachListing => f.write_str("ATTACH LISTING")?,
7231            Action::AttachPolicy => f.write_str("ATTACH POLICY")?,
7232            Action::Audit => f.write_str("AUDIT")?,
7233            Action::BindServiceEndpoint => f.write_str("BIND SERVICE ENDPOINT")?,
7234            Action::Connect => f.write_str("CONNECT")?,
7235            Action::Create { obj_type } => {
7236                f.write_str("CREATE")?;
7237                if let Some(obj_type) = obj_type {
7238                    write!(f, " {obj_type}")?
7239                }
7240            }
7241            Action::DatabaseRole { role } => write!(f, "DATABASE ROLE {role}")?,
7242            Action::Delete => f.write_str("DELETE")?,
7243            Action::Drop => f.write_str("DROP")?,
7244            Action::EvolveSchema => f.write_str("EVOLVE SCHEMA")?,
7245            Action::Exec { obj_type } => {
7246                f.write_str("EXEC")?;
7247                if let Some(obj_type) = obj_type {
7248                    write!(f, " {obj_type}")?
7249                }
7250            }
7251            Action::Execute { obj_type } => {
7252                f.write_str("EXECUTE")?;
7253                if let Some(obj_type) = obj_type {
7254                    write!(f, " {obj_type}")?
7255                }
7256            }
7257            Action::Failover => f.write_str("FAILOVER")?,
7258            Action::ImportedPrivileges => f.write_str("IMPORTED PRIVILEGES")?,
7259            Action::ImportShare => f.write_str("IMPORT SHARE")?,
7260            Action::Insert { .. } => f.write_str("INSERT")?,
7261            Action::Manage { manage_type } => write!(f, "MANAGE {manage_type}")?,
7262            Action::ManageReleases => f.write_str("MANAGE RELEASES")?,
7263            Action::ManageVersions => f.write_str("MANAGE VERSIONS")?,
7264            Action::Modify { modify_type } => {
7265                write!(f, "MODIFY")?;
7266                if let Some(modify_type) = modify_type {
7267                    write!(f, " {modify_type}")?;
7268                }
7269            }
7270            Action::Monitor { monitor_type } => {
7271                write!(f, "MONITOR")?;
7272                if let Some(monitor_type) = monitor_type {
7273                    write!(f, " {monitor_type}")?
7274                }
7275            }
7276            Action::Operate => f.write_str("OPERATE")?,
7277            Action::OverrideShareRestrictions => f.write_str("OVERRIDE SHARE RESTRICTIONS")?,
7278            Action::Ownership => f.write_str("OWNERSHIP")?,
7279            Action::PurchaseDataExchangeListing => f.write_str("PURCHASE DATA EXCHANGE LISTING")?,
7280            Action::Read => f.write_str("READ")?,
7281            Action::ReadSession => f.write_str("READ SESSION")?,
7282            Action::References { .. } => f.write_str("REFERENCES")?,
7283            Action::Replicate => f.write_str("REPLICATE")?,
7284            Action::ResolveAll => f.write_str("RESOLVE ALL")?,
7285            Action::Role { role } => write!(f, "ROLE {role}")?,
7286            Action::Select { .. } => f.write_str("SELECT")?,
7287            Action::Temporary => f.write_str("TEMPORARY")?,
7288            Action::Trigger => f.write_str("TRIGGER")?,
7289            Action::Truncate => f.write_str("TRUNCATE")?,
7290            Action::Update { .. } => f.write_str("UPDATE")?,
7291            Action::Usage => f.write_str("USAGE")?,
7292        };
7293        match self {
7294            Action::Insert { columns }
7295            | Action::References { columns }
7296            | Action::Select { columns }
7297            | Action::Update { columns } => {
7298                if let Some(columns) = columns {
7299                    write!(f, " ({})", display_comma_separated(columns))?;
7300                }
7301            }
7302            _ => (),
7303        };
7304        Ok(())
7305    }
7306}
7307
7308#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7309#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7310#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7311/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
7312/// under `globalPrivileges` in the `CREATE` privilege.
7313pub enum ActionCreateObjectType {
7314    /// An account-level object.
7315    Account,
7316    /// An application object.
7317    Application,
7318    /// An application package object.
7319    ApplicationPackage,
7320    /// A compute pool object.
7321    ComputePool,
7322    /// A data exchange listing.
7323    DataExchangeListing,
7324    /// A database object.
7325    Database,
7326    /// An external volume object.
7327    ExternalVolume,
7328    /// A failover group object.
7329    FailoverGroup,
7330    /// An integration object.
7331    Integration,
7332    /// A network policy object.
7333    NetworkPolicy,
7334    /// An organization listing.
7335    OrganiationListing,
7336    /// A replication group object.
7337    ReplicationGroup,
7338    /// A role object.
7339    Role,
7340    /// A schema object.
7341    Schema,
7342    /// A share object.
7343    Share,
7344    /// A user object.
7345    User,
7346    /// A warehouse object.
7347    Warehouse,
7348}
7349
7350impl fmt::Display for ActionCreateObjectType {
7351    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7352        match self {
7353            ActionCreateObjectType::Account => write!(f, "ACCOUNT"),
7354            ActionCreateObjectType::Application => write!(f, "APPLICATION"),
7355            ActionCreateObjectType::ApplicationPackage => write!(f, "APPLICATION PACKAGE"),
7356            ActionCreateObjectType::ComputePool => write!(f, "COMPUTE POOL"),
7357            ActionCreateObjectType::DataExchangeListing => write!(f, "DATA EXCHANGE LISTING"),
7358            ActionCreateObjectType::Database => write!(f, "DATABASE"),
7359            ActionCreateObjectType::ExternalVolume => write!(f, "EXTERNAL VOLUME"),
7360            ActionCreateObjectType::FailoverGroup => write!(f, "FAILOVER GROUP"),
7361            ActionCreateObjectType::Integration => write!(f, "INTEGRATION"),
7362            ActionCreateObjectType::NetworkPolicy => write!(f, "NETWORK POLICY"),
7363            ActionCreateObjectType::OrganiationListing => write!(f, "ORGANIZATION LISTING"),
7364            ActionCreateObjectType::ReplicationGroup => write!(f, "REPLICATION GROUP"),
7365            ActionCreateObjectType::Role => write!(f, "ROLE"),
7366            ActionCreateObjectType::Schema => write!(f, "SCHEMA"),
7367            ActionCreateObjectType::Share => write!(f, "SHARE"),
7368            ActionCreateObjectType::User => write!(f, "USER"),
7369            ActionCreateObjectType::Warehouse => write!(f, "WAREHOUSE"),
7370        }
7371    }
7372}
7373
7374#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7375#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7376#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7377/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
7378/// under `globalPrivileges` in the `APPLY` privilege.
7379pub enum ActionApplyType {
7380    /// Apply an aggregation policy.
7381    AggregationPolicy,
7382    /// Apply an authentication policy.
7383    AuthenticationPolicy,
7384    /// Apply a join policy.
7385    JoinPolicy,
7386    /// Apply a masking policy.
7387    MaskingPolicy,
7388    /// Apply a packages policy.
7389    PackagesPolicy,
7390    /// Apply a password policy.
7391    PasswordPolicy,
7392    /// Apply a projection policy.
7393    ProjectionPolicy,
7394    /// Apply a row access policy.
7395    RowAccessPolicy,
7396    /// Apply a session policy.
7397    SessionPolicy,
7398    /// Apply a tag.
7399    Tag,
7400}
7401
7402impl fmt::Display for ActionApplyType {
7403    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7404        match self {
7405            ActionApplyType::AggregationPolicy => write!(f, "AGGREGATION POLICY"),
7406            ActionApplyType::AuthenticationPolicy => write!(f, "AUTHENTICATION POLICY"),
7407            ActionApplyType::JoinPolicy => write!(f, "JOIN POLICY"),
7408            ActionApplyType::MaskingPolicy => write!(f, "MASKING POLICY"),
7409            ActionApplyType::PackagesPolicy => write!(f, "PACKAGES POLICY"),
7410            ActionApplyType::PasswordPolicy => write!(f, "PASSWORD POLICY"),
7411            ActionApplyType::ProjectionPolicy => write!(f, "PROJECTION POLICY"),
7412            ActionApplyType::RowAccessPolicy => write!(f, "ROW ACCESS POLICY"),
7413            ActionApplyType::SessionPolicy => write!(f, "SESSION POLICY"),
7414            ActionApplyType::Tag => write!(f, "TAG"),
7415        }
7416    }
7417}
7418
7419#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7420#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7421#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7422/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
7423/// under `globalPrivileges` in the `EXECUTE` privilege.
7424pub enum ActionExecuteObjectType {
7425    /// Alert object.
7426    Alert,
7427    /// Data metric function object.
7428    DataMetricFunction,
7429    /// Managed alert object.
7430    ManagedAlert,
7431    /// Managed task object.
7432    ManagedTask,
7433    /// Task object.
7434    Task,
7435}
7436
7437impl fmt::Display for ActionExecuteObjectType {
7438    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7439        match self {
7440            ActionExecuteObjectType::Alert => write!(f, "ALERT"),
7441            ActionExecuteObjectType::DataMetricFunction => write!(f, "DATA METRIC FUNCTION"),
7442            ActionExecuteObjectType::ManagedAlert => write!(f, "MANAGED ALERT"),
7443            ActionExecuteObjectType::ManagedTask => write!(f, "MANAGED TASK"),
7444            ActionExecuteObjectType::Task => write!(f, "TASK"),
7445        }
7446    }
7447}
7448
7449#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7450#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7451#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7452/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
7453/// under `globalPrivileges` in the `MANAGE` privilege.
7454pub enum ActionManageType {
7455    /// Account support cases management.
7456    AccountSupportCases,
7457    /// Event sharing management.
7458    EventSharing,
7459    /// Grants management.
7460    Grants,
7461    /// Listing auto-fulfillment management.
7462    ListingAutoFulfillment,
7463    /// Organization support cases management.
7464    OrganizationSupportCases,
7465    /// User support cases management.
7466    UserSupportCases,
7467    /// Warehouses management.
7468    Warehouses,
7469}
7470
7471impl fmt::Display for ActionManageType {
7472    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7473        match self {
7474            ActionManageType::AccountSupportCases => write!(f, "ACCOUNT SUPPORT CASES"),
7475            ActionManageType::EventSharing => write!(f, "EVENT SHARING"),
7476            ActionManageType::Grants => write!(f, "GRANTS"),
7477            ActionManageType::ListingAutoFulfillment => write!(f, "LISTING AUTO FULFILLMENT"),
7478            ActionManageType::OrganizationSupportCases => write!(f, "ORGANIZATION SUPPORT CASES"),
7479            ActionManageType::UserSupportCases => write!(f, "USER SUPPORT CASES"),
7480            ActionManageType::Warehouses => write!(f, "WAREHOUSES"),
7481        }
7482    }
7483}
7484
7485#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7486#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7487#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7488/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
7489/// under `globalPrivileges` in the `MODIFY` privilege.
7490pub enum ActionModifyType {
7491    /// Modify log level.
7492    LogLevel,
7493    /// Modify trace level.
7494    TraceLevel,
7495    /// Modify session log level.
7496    SessionLogLevel,
7497    /// Modify session trace level.
7498    SessionTraceLevel,
7499}
7500
7501impl fmt::Display for ActionModifyType {
7502    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7503        match self {
7504            ActionModifyType::LogLevel => write!(f, "LOG LEVEL"),
7505            ActionModifyType::TraceLevel => write!(f, "TRACE LEVEL"),
7506            ActionModifyType::SessionLogLevel => write!(f, "SESSION LOG LEVEL"),
7507            ActionModifyType::SessionTraceLevel => write!(f, "SESSION TRACE LEVEL"),
7508        }
7509    }
7510}
7511
7512#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7513#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7514#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7515/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
7516/// under `globalPrivileges` in the `MONITOR` privilege.
7517pub enum ActionMonitorType {
7518    /// Monitor execution.
7519    Execution,
7520    /// Monitor security.
7521    Security,
7522    /// Monitor usage.
7523    Usage,
7524}
7525
7526impl fmt::Display for ActionMonitorType {
7527    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7528        match self {
7529            ActionMonitorType::Execution => write!(f, "EXECUTION"),
7530            ActionMonitorType::Security => write!(f, "SECURITY"),
7531            ActionMonitorType::Usage => write!(f, "USAGE"),
7532        }
7533    }
7534}
7535
7536/// The principal that receives the privileges
7537#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7538#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7539#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7540pub struct Grantee {
7541    /// The category/type of grantee (role, user, share, etc.).
7542    pub grantee_type: GranteesType,
7543    /// Optional name of the grantee (identifier or user@host).
7544    pub name: Option<GranteeName>,
7545}
7546
7547impl fmt::Display for Grantee {
7548    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7549        match self.grantee_type {
7550            GranteesType::Role => {
7551                write!(f, "ROLE ")?;
7552            }
7553            GranteesType::Share => {
7554                write!(f, "SHARE ")?;
7555            }
7556            GranteesType::User => {
7557                write!(f, "USER ")?;
7558            }
7559            GranteesType::Group => {
7560                write!(f, "GROUP ")?;
7561            }
7562            GranteesType::Public => {
7563                write!(f, "PUBLIC ")?;
7564            }
7565            GranteesType::DatabaseRole => {
7566                write!(f, "DATABASE ROLE ")?;
7567            }
7568            GranteesType::Application => {
7569                write!(f, "APPLICATION ")?;
7570            }
7571            GranteesType::ApplicationRole => {
7572                write!(f, "APPLICATION ROLE ")?;
7573            }
7574            GranteesType::None => (),
7575        }
7576        if let Some(ref name) = self.name {
7577            name.fmt(f)?;
7578        }
7579        Ok(())
7580    }
7581}
7582
7583#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7584#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7585#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7586/// The kind of principal receiving privileges.
7587pub enum GranteesType {
7588    /// A role principal.
7589    Role,
7590    /// A share principal.
7591    Share,
7592    /// A user principal.
7593    User,
7594    /// A group principal.
7595    Group,
7596    /// The public principal.
7597    Public,
7598    /// A database role principal.
7599    DatabaseRole,
7600    /// An application principal.
7601    Application,
7602    /// An application role principal.
7603    ApplicationRole,
7604    /// No specific principal (e.g. `NONE`).
7605    None,
7606}
7607
7608/// Users/roles designated in a GRANT/REVOKE
7609#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7610#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7611#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7612pub enum GranteeName {
7613    /// A bare identifier
7614    ObjectName(ObjectName),
7615    /// A MySQL user/host pair such as 'root'@'%'
7616    UserHost {
7617        /// The user identifier portion.
7618        user: Ident,
7619        /// The host identifier portion.
7620        host: Ident,
7621    },
7622}
7623
7624impl fmt::Display for GranteeName {
7625    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7626        match self {
7627            GranteeName::ObjectName(name) => name.fmt(f),
7628            GranteeName::UserHost { user, host } => {
7629                write!(f, "{user}@{host}")
7630            }
7631        }
7632    }
7633}
7634
7635/// Objects on which privileges are granted in a GRANT statement.
7636#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7637#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7638#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7639pub enum GrantObjects {
7640    /// Grant privileges on `ALL SEQUENCES IN SCHEMA <schema_name> [, ...]`
7641    AllSequencesInSchema {
7642        /// The target schema names.
7643        schemas: Vec<ObjectName>,
7644    },
7645    /// Grant privileges on `ALL TABLES IN SCHEMA <schema_name> [, ...]`
7646    AllTablesInSchema {
7647        /// The target schema names.
7648        schemas: Vec<ObjectName>,
7649    },
7650    /// Grant privileges on `ALL VIEWS IN SCHEMA <schema_name> [, ...]`
7651    AllViewsInSchema {
7652        /// The target schema names.
7653        schemas: Vec<ObjectName>,
7654    },
7655    /// Grant privileges on `ALL MATERIALIZED VIEWS IN SCHEMA <schema_name> [, ...]`
7656    AllMaterializedViewsInSchema {
7657        /// The target schema names.
7658        schemas: Vec<ObjectName>,
7659    },
7660    /// Grant privileges on `ALL EXTERNAL TABLES IN SCHEMA <schema_name> [, ...]`
7661    AllExternalTablesInSchema {
7662        /// The target schema names.
7663        schemas: Vec<ObjectName>,
7664    },
7665    /// Grant privileges on `ALL FUNCTIONS IN SCHEMA <schema_name> [, ...]`
7666    AllFunctionsInSchema {
7667        /// The target schema names.
7668        schemas: Vec<ObjectName>,
7669    },
7670    /// Grant privileges on `FUTURE SCHEMAS IN DATABASE <database_name> [, ...]`
7671    FutureSchemasInDatabase {
7672        /// The target database names.
7673        databases: Vec<ObjectName>,
7674    },
7675    /// Grant privileges on `FUTURE TABLES IN SCHEMA <schema_name> [, ...]`
7676    FutureTablesInSchema {
7677        /// The target schema names.
7678        schemas: Vec<ObjectName>,
7679    },
7680    /// Grant privileges on `FUTURE VIEWS IN SCHEMA <schema_name> [, ...]`
7681    FutureViewsInSchema {
7682        /// The target schema names.
7683        schemas: Vec<ObjectName>,
7684    },
7685    /// Grant privileges on `FUTURE EXTERNAL TABLES IN SCHEMA <schema_name> [, ...]`
7686    FutureExternalTablesInSchema {
7687        /// The target schema names.
7688        schemas: Vec<ObjectName>,
7689    },
7690    /// Grant privileges on `FUTURE MATERIALIZED VIEWS IN SCHEMA <schema_name> [, ...]`
7691    FutureMaterializedViewsInSchema {
7692        /// The target schema names.
7693        schemas: Vec<ObjectName>,
7694    },
7695    /// Grant privileges on `FUTURE SEQUENCES IN SCHEMA <schema_name> [, ...]`
7696    FutureSequencesInSchema {
7697        /// The target schema names.
7698        schemas: Vec<ObjectName>,
7699    },
7700    /// Grant privileges on specific databases
7701    Databases(Vec<ObjectName>),
7702    /// Grant privileges on specific schemas
7703    Schemas(Vec<ObjectName>),
7704    /// Grant privileges on specific sequences
7705    Sequences(Vec<ObjectName>),
7706    /// Grant privileges on specific tables
7707    Tables(Vec<ObjectName>),
7708    /// Grant privileges on specific views
7709    Views(Vec<ObjectName>),
7710    /// Grant privileges on specific warehouses
7711    Warehouses(Vec<ObjectName>),
7712    /// Grant privileges on specific integrations
7713    Integrations(Vec<ObjectName>),
7714    /// Grant privileges on resource monitors
7715    ResourceMonitors(Vec<ObjectName>),
7716    /// Grant privileges on users
7717    Users(Vec<ObjectName>),
7718    /// Grant privileges on compute pools
7719    ComputePools(Vec<ObjectName>),
7720    /// Grant privileges on connections
7721    Connections(Vec<ObjectName>),
7722    /// Grant privileges on failover groups
7723    FailoverGroup(Vec<ObjectName>),
7724    /// Grant privileges on replication group
7725    ReplicationGroup(Vec<ObjectName>),
7726    /// Grant privileges on external volumes
7727    ExternalVolumes(Vec<ObjectName>),
7728    /// Grant privileges on a procedure. In dialects that
7729    /// support overloading, the argument types must be specified.
7730    ///
7731    /// For example:
7732    /// `GRANT USAGE ON PROCEDURE foo(varchar) TO ROLE role1`
7733    Procedure {
7734        /// The procedure name.
7735        name: ObjectName,
7736        /// Optional argument types for overloaded procedures.
7737        arg_types: Vec<DataType>,
7738    },
7739
7740    /// Grant privileges on a function. In dialects that
7741    /// support overloading, the argument types must be specified.
7742    ///
7743    /// For example:
7744    /// `GRANT USAGE ON FUNCTION foo(varchar) TO ROLE role1`
7745    Function {
7746        /// The function name.
7747        name: ObjectName,
7748        /// Optional argument types for overloaded functions.
7749        arg_types: Vec<DataType>,
7750    },
7751}
7752
7753impl fmt::Display for GrantObjects {
7754    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7755        match self {
7756            GrantObjects::Sequences(sequences) => {
7757                write!(f, "SEQUENCE {}", display_comma_separated(sequences))
7758            }
7759            GrantObjects::Databases(databases) => {
7760                write!(f, "DATABASE {}", display_comma_separated(databases))
7761            }
7762            GrantObjects::Schemas(schemas) => {
7763                write!(f, "SCHEMA {}", display_comma_separated(schemas))
7764            }
7765            GrantObjects::Tables(tables) => {
7766                write!(f, "{}", display_comma_separated(tables))
7767            }
7768            GrantObjects::Views(views) => {
7769                write!(f, "VIEW {}", display_comma_separated(views))
7770            }
7771            GrantObjects::Warehouses(warehouses) => {
7772                write!(f, "WAREHOUSE {}", display_comma_separated(warehouses))
7773            }
7774            GrantObjects::Integrations(integrations) => {
7775                write!(f, "INTEGRATION {}", display_comma_separated(integrations))
7776            }
7777            GrantObjects::AllSequencesInSchema { schemas } => {
7778                write!(
7779                    f,
7780                    "ALL SEQUENCES IN SCHEMA {}",
7781                    display_comma_separated(schemas)
7782                )
7783            }
7784            GrantObjects::AllTablesInSchema { schemas } => {
7785                write!(
7786                    f,
7787                    "ALL TABLES IN SCHEMA {}",
7788                    display_comma_separated(schemas)
7789                )
7790            }
7791            GrantObjects::AllExternalTablesInSchema { schemas } => {
7792                write!(
7793                    f,
7794                    "ALL EXTERNAL TABLES IN SCHEMA {}",
7795                    display_comma_separated(schemas)
7796                )
7797            }
7798            GrantObjects::AllViewsInSchema { schemas } => {
7799                write!(
7800                    f,
7801                    "ALL VIEWS IN SCHEMA {}",
7802                    display_comma_separated(schemas)
7803                )
7804            }
7805            GrantObjects::AllMaterializedViewsInSchema { schemas } => {
7806                write!(
7807                    f,
7808                    "ALL MATERIALIZED VIEWS IN SCHEMA {}",
7809                    display_comma_separated(schemas)
7810                )
7811            }
7812            GrantObjects::AllFunctionsInSchema { schemas } => {
7813                write!(
7814                    f,
7815                    "ALL FUNCTIONS IN SCHEMA {}",
7816                    display_comma_separated(schemas)
7817                )
7818            }
7819            GrantObjects::FutureSchemasInDatabase { databases } => {
7820                write!(
7821                    f,
7822                    "FUTURE SCHEMAS IN DATABASE {}",
7823                    display_comma_separated(databases)
7824                )
7825            }
7826            GrantObjects::FutureTablesInSchema { schemas } => {
7827                write!(
7828                    f,
7829                    "FUTURE TABLES IN SCHEMA {}",
7830                    display_comma_separated(schemas)
7831                )
7832            }
7833            GrantObjects::FutureExternalTablesInSchema { schemas } => {
7834                write!(
7835                    f,
7836                    "FUTURE EXTERNAL TABLES IN SCHEMA {}",
7837                    display_comma_separated(schemas)
7838                )
7839            }
7840            GrantObjects::FutureViewsInSchema { schemas } => {
7841                write!(
7842                    f,
7843                    "FUTURE VIEWS IN SCHEMA {}",
7844                    display_comma_separated(schemas)
7845                )
7846            }
7847            GrantObjects::FutureMaterializedViewsInSchema { schemas } => {
7848                write!(
7849                    f,
7850                    "FUTURE MATERIALIZED VIEWS IN SCHEMA {}",
7851                    display_comma_separated(schemas)
7852                )
7853            }
7854            GrantObjects::FutureSequencesInSchema { schemas } => {
7855                write!(
7856                    f,
7857                    "FUTURE SEQUENCES IN SCHEMA {}",
7858                    display_comma_separated(schemas)
7859                )
7860            }
7861            GrantObjects::ResourceMonitors(objects) => {
7862                write!(f, "RESOURCE MONITOR {}", display_comma_separated(objects))
7863            }
7864            GrantObjects::Users(objects) => {
7865                write!(f, "USER {}", display_comma_separated(objects))
7866            }
7867            GrantObjects::ComputePools(objects) => {
7868                write!(f, "COMPUTE POOL {}", display_comma_separated(objects))
7869            }
7870            GrantObjects::Connections(objects) => {
7871                write!(f, "CONNECTION {}", display_comma_separated(objects))
7872            }
7873            GrantObjects::FailoverGroup(objects) => {
7874                write!(f, "FAILOVER GROUP {}", display_comma_separated(objects))
7875            }
7876            GrantObjects::ReplicationGroup(objects) => {
7877                write!(f, "REPLICATION GROUP {}", display_comma_separated(objects))
7878            }
7879            GrantObjects::ExternalVolumes(objects) => {
7880                write!(f, "EXTERNAL VOLUME {}", display_comma_separated(objects))
7881            }
7882            GrantObjects::Procedure { name, arg_types } => {
7883                write!(f, "PROCEDURE {name}")?;
7884                if !arg_types.is_empty() {
7885                    write!(f, "({})", display_comma_separated(arg_types))?;
7886                }
7887                Ok(())
7888            }
7889            GrantObjects::Function { name, arg_types } => {
7890                write!(f, "FUNCTION {name}")?;
7891                if !arg_types.is_empty() {
7892                    write!(f, "({})", display_comma_separated(arg_types))?;
7893                }
7894                Ok(())
7895            }
7896        }
7897    }
7898}
7899
7900/// A `DENY` statement
7901///
7902/// [MsSql](https://learn.microsoft.com/en-us/sql/t-sql/statements/deny-transact-sql)
7903#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7904#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7905#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7906pub struct DenyStatement {
7907    /// The privileges to deny.
7908    pub privileges: Privileges,
7909    /// The objects the privileges apply to.
7910    pub objects: GrantObjects,
7911    /// The grantees (users/roles) to whom the denial applies.
7912    pub grantees: Vec<Grantee>,
7913    /// Optional identifier of the principal that performed the grant.
7914    pub granted_by: Option<Ident>,
7915    /// Optional cascade option controlling dependent objects.
7916    pub cascade: Option<CascadeOption>,
7917}
7918
7919impl fmt::Display for DenyStatement {
7920    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7921        write!(f, "DENY {}", self.privileges)?;
7922        write!(f, " ON {}", self.objects)?;
7923        if !self.grantees.is_empty() {
7924            write!(f, " TO {}", display_comma_separated(&self.grantees))?;
7925        }
7926        if let Some(cascade) = &self.cascade {
7927            write!(f, " {cascade}")?;
7928        }
7929        if let Some(granted_by) = &self.granted_by {
7930            write!(f, " AS {granted_by}")?;
7931        }
7932        Ok(())
7933    }
7934}
7935
7936/// SQL assignment `foo = expr` as used in SQLUpdate
7937#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7938#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7939#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7940pub struct Assignment {
7941    /// The left-hand side of the assignment.
7942    pub target: AssignmentTarget,
7943    /// The expression assigned to the target.
7944    pub value: Expr,
7945}
7946
7947impl fmt::Display for Assignment {
7948    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7949        write!(f, "{} = {}", self.target, self.value)
7950    }
7951}
7952
7953/// Left-hand side of an assignment in an UPDATE statement,
7954/// e.g. `foo` in `foo = 5` (ColumnName assignment) or
7955/// `(a, b)` in `(a, b) = (1, 2)` (Tuple assignment).
7956#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7957#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7958#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7959pub enum AssignmentTarget {
7960    /// A single column
7961    ColumnName(ObjectName),
7962    /// A tuple of columns
7963    Tuple(Vec<ObjectName>),
7964}
7965
7966impl fmt::Display for AssignmentTarget {
7967    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7968        match self {
7969            AssignmentTarget::ColumnName(column) => write!(f, "{column}"),
7970            AssignmentTarget::Tuple(columns) => write!(f, "({})", display_comma_separated(columns)),
7971        }
7972    }
7973}
7974
7975#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7976#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7977#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7978/// Expression forms allowed as a function argument.
7979pub enum FunctionArgExpr {
7980    /// A normal expression argument.
7981    Expr(Expr),
7982    /// Qualified wildcard, e.g. `alias.*` or `schema.table.*`.
7983    QualifiedWildcard(ObjectName),
7984    /// An unqualified `*` wildcard.
7985    Wildcard,
7986    /// An unqualified `*` wildcard with additional options, e.g. `* EXCLUDE(col)`.
7987    ///
7988    /// Used in Snowflake to support expressions like `HASH(* EXCLUDE(col))`.
7989    WildcardWithOptions(WildcardAdditionalOptions),
7990}
7991
7992impl From<Expr> for FunctionArgExpr {
7993    fn from(wildcard_expr: Expr) -> Self {
7994        match wildcard_expr {
7995            Expr::QualifiedWildcard(prefix, _) => Self::QualifiedWildcard(prefix),
7996            Expr::Wildcard(_) => Self::Wildcard,
7997            expr => Self::Expr(expr),
7998        }
7999    }
8000}
8001
8002impl fmt::Display for FunctionArgExpr {
8003    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8004        match self {
8005            FunctionArgExpr::Expr(expr) => write!(f, "{expr}"),
8006            FunctionArgExpr::QualifiedWildcard(prefix) => write!(f, "{prefix}.*"),
8007            FunctionArgExpr::Wildcard => f.write_str("*"),
8008            FunctionArgExpr::WildcardWithOptions(opts) => write!(f, "*{opts}"),
8009        }
8010    }
8011}
8012
8013#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8014#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8015#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8016/// Operator used to separate function arguments
8017pub enum FunctionArgOperator {
8018    /// function(arg1 = value1)
8019    Equals,
8020    /// function(arg1 => value1)
8021    RightArrow,
8022    /// function(arg1 := value1)
8023    Assignment,
8024    /// function(arg1 : value1)
8025    Colon,
8026    /// function(arg1 VALUE value1)
8027    Value,
8028}
8029
8030impl fmt::Display for FunctionArgOperator {
8031    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8032        match self {
8033            FunctionArgOperator::Equals => f.write_str("="),
8034            FunctionArgOperator::RightArrow => f.write_str("=>"),
8035            FunctionArgOperator::Assignment => f.write_str(":="),
8036            FunctionArgOperator::Colon => f.write_str(":"),
8037            FunctionArgOperator::Value => f.write_str("VALUE"),
8038        }
8039    }
8040}
8041
8042#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8043#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8044#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8045/// Forms of function arguments (named, expression-named, or positional).
8046pub enum FunctionArg {
8047    /// `name` is identifier
8048    ///
8049    /// Enabled when `Dialect::supports_named_fn_args_with_expr_name` returns 'false'
8050    Named {
8051        /// The identifier name of the argument.
8052        name: Ident,
8053        /// The argument expression or wildcard form.
8054        arg: FunctionArgExpr,
8055        /// The operator separating name and value.
8056        operator: FunctionArgOperator,
8057    },
8058    /// `name` is arbitrary expression
8059    ///
8060    /// Enabled when `Dialect::supports_named_fn_args_with_expr_name` returns 'true'
8061    ExprNamed {
8062        /// The expression used as the argument name.
8063        name: Expr,
8064        /// The argument expression or wildcard form.
8065        arg: FunctionArgExpr,
8066        /// The operator separating name and value.
8067        operator: FunctionArgOperator,
8068    },
8069    /// An unnamed argument (positional), given by expression or wildcard.
8070    Unnamed(FunctionArgExpr),
8071}
8072
8073impl fmt::Display for FunctionArg {
8074    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8075        match self {
8076            FunctionArg::Named {
8077                name,
8078                arg,
8079                operator,
8080            } => write!(f, "{name} {operator} {arg}"),
8081            FunctionArg::ExprNamed {
8082                name,
8083                arg,
8084                operator,
8085            } => write!(f, "{name} {operator} {arg}"),
8086            FunctionArg::Unnamed(unnamed_arg) => write!(f, "{unnamed_arg}"),
8087        }
8088    }
8089}
8090
8091#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8092#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8093#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8094/// Which cursor(s) to close.
8095pub enum CloseCursor {
8096    /// Close all cursors.
8097    All,
8098    /// Close a specific cursor by name.
8099    Specific {
8100        /// The name of the cursor to close.
8101        name: Ident,
8102    },
8103}
8104
8105impl fmt::Display for CloseCursor {
8106    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8107        match self {
8108            CloseCursor::All => write!(f, "ALL"),
8109            CloseCursor::Specific { name } => write!(f, "{name}"),
8110        }
8111    }
8112}
8113
8114/// A Drop Domain statement
8115#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8116#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8117#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8118pub struct DropDomain {
8119    /// Whether to drop the domain if it exists
8120    pub if_exists: bool,
8121    /// The name of the domain to drop
8122    pub name: ObjectName,
8123    /// The behavior to apply when dropping the domain
8124    pub drop_behavior: Option<DropBehavior>,
8125}
8126
8127/// A constant of form `<data_type> 'value'`.
8128/// This can represent ANSI SQL `DATE`, `TIME`, and `TIMESTAMP` literals (such as `DATE '2020-01-01'`),
8129/// as well as constants of other types (a non-standard PostgreSQL extension).
8130#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8131#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8132#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8133pub struct TypedString {
8134    /// The data type of the typed string (e.g. DATE, TIME, TIMESTAMP).
8135    pub data_type: DataType,
8136    /// The value of the constant.
8137    /// Hint: you can unwrap the string value using `value.into_string()`.
8138    pub value: ValueWithSpan,
8139    /// Flags whether this TypedString uses the [ODBC syntax].
8140    ///
8141    /// Example:
8142    /// ```sql
8143    /// -- An ODBC date literal:
8144    /// SELECT {d '2025-07-16'}
8145    /// -- This is equivalent to the standard ANSI SQL literal:
8146    /// SELECT DATE '2025-07-16'
8147    ///
8148    /// [ODBC syntax]: https://learn.microsoft.com/en-us/sql/odbc/reference/develop-app/date-time-and-timestamp-literals?view=sql-server-2017
8149    pub uses_odbc_syntax: bool,
8150}
8151
8152impl fmt::Display for TypedString {
8153    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8154        let data_type = &self.data_type;
8155        let value = &self.value;
8156        match self.uses_odbc_syntax {
8157            false => {
8158                write!(f, "{data_type}")?;
8159                write!(f, " {value}")
8160            }
8161            true => {
8162                let prefix = match data_type {
8163                    DataType::Date => "d",
8164                    DataType::Time(..) => "t",
8165                    DataType::Timestamp(..) => "ts",
8166                    _ => "?",
8167                };
8168                write!(f, "{{{prefix} {value}}}")
8169            }
8170        }
8171    }
8172}
8173
8174/// A function call
8175#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8176#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8177#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8178pub struct Function {
8179    /// The function name (may be qualified).
8180    pub name: ObjectName,
8181    /// Flags whether this function call uses the [ODBC syntax].
8182    ///
8183    /// Example:
8184    /// ```sql
8185    /// SELECT {fn CONCAT('foo', 'bar')}
8186    /// ```
8187    ///
8188    /// [ODBC syntax]: https://learn.microsoft.com/en-us/sql/odbc/reference/develop-app/scalar-function-calls?view=sql-server-2017
8189    pub uses_odbc_syntax: bool,
8190    /// The parameters to the function, including any options specified within the
8191    /// delimiting parentheses.
8192    ///
8193    /// Example:
8194    /// ```plaintext
8195    /// HISTOGRAM(0.5, 0.6)(x, y)
8196    /// ```
8197    ///
8198    /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/aggregate-functions/parametric-functions)
8199    pub parameters: FunctionArguments,
8200    /// The arguments to the function, including any options specified within the
8201    /// delimiting parentheses.
8202    pub args: FunctionArguments,
8203    /// e.g. `x > 5` in `COUNT(x) FILTER (WHERE x > 5)`
8204    pub filter: Option<Box<Expr>>,
8205    /// Indicates how `NULL`s should be handled in the calculation.
8206    ///
8207    /// Example:
8208    /// ```plaintext
8209    /// FIRST_VALUE( <expr> ) [ { IGNORE | RESPECT } NULLS ] OVER ...
8210    /// ```
8211    ///
8212    /// [Snowflake](https://docs.snowflake.com/en/sql-reference/functions/first_value)
8213    pub null_treatment: Option<NullTreatment>,
8214    /// The `OVER` clause, indicating a window function call.
8215    pub over: Option<WindowType>,
8216    /// A clause used with certain aggregate functions to control the ordering
8217    /// within grouped sets before the function is applied.
8218    ///
8219    /// Syntax:
8220    /// ```plaintext
8221    /// <aggregate_function>(expression) WITHIN GROUP (ORDER BY key [ASC | DESC], ...)
8222    /// ```
8223    pub within_group: Vec<OrderByExpr>,
8224}
8225
8226impl fmt::Display for Function {
8227    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8228        if self.uses_odbc_syntax {
8229            write!(f, "{{fn ")?;
8230        }
8231
8232        write!(f, "{}{}{}", self.name, self.parameters, self.args)?;
8233
8234        if !self.within_group.is_empty() {
8235            write!(
8236                f,
8237                " WITHIN GROUP (ORDER BY {})",
8238                display_comma_separated(&self.within_group)
8239            )?;
8240        }
8241
8242        if let Some(filter_cond) = &self.filter {
8243            write!(f, " FILTER (WHERE {filter_cond})")?;
8244        }
8245
8246        if let Some(null_treatment) = &self.null_treatment {
8247            write!(f, " {null_treatment}")?;
8248        }
8249
8250        if let Some(o) = &self.over {
8251            f.write_str(" OVER ")?;
8252            o.fmt(f)?;
8253        }
8254
8255        if self.uses_odbc_syntax {
8256            write!(f, "}}")?;
8257        }
8258
8259        Ok(())
8260    }
8261}
8262
8263/// The arguments passed to a function call.
8264#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8265#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8266#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8267pub enum FunctionArguments {
8268    /// Used for special functions like `CURRENT_TIMESTAMP` that are invoked
8269    /// without parentheses.
8270    None,
8271    /// On some dialects, a subquery can be passed without surrounding
8272    /// parentheses if it's the sole argument to the function.
8273    Subquery(Box<Query>),
8274    /// A normal function argument list, including any clauses within it such as
8275    /// `DISTINCT` or `ORDER BY`.
8276    List(FunctionArgumentList),
8277}
8278
8279impl fmt::Display for FunctionArguments {
8280    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8281        match self {
8282            FunctionArguments::None => Ok(()),
8283            FunctionArguments::Subquery(query) => write!(f, "({query})"),
8284            FunctionArguments::List(args) => write!(f, "({args})"),
8285        }
8286    }
8287}
8288
8289/// This represents everything inside the parentheses when calling a function.
8290#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8291#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8292#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8293pub struct FunctionArgumentList {
8294    /// `[ ALL | DISTINCT ]`
8295    pub duplicate_treatment: Option<DuplicateTreatment>,
8296    /// The function arguments.
8297    pub args: Vec<FunctionArg>,
8298    /// Additional clauses specified within the argument list.
8299    pub clauses: Vec<FunctionArgumentClause>,
8300}
8301
8302impl fmt::Display for FunctionArgumentList {
8303    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8304        if let Some(duplicate_treatment) = self.duplicate_treatment {
8305            write!(f, "{duplicate_treatment} ")?;
8306        }
8307        write!(f, "{}", display_comma_separated(&self.args))?;
8308        if !self.clauses.is_empty() {
8309            if !self.args.is_empty() {
8310                write!(f, " ")?;
8311            }
8312            write!(f, "{}", display_separated(&self.clauses, " "))?;
8313        }
8314        Ok(())
8315    }
8316}
8317
8318#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8319#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8320#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8321/// Clauses that can appear inside a function argument list.
8322pub enum FunctionArgumentClause {
8323    /// Indicates how `NULL`s should be handled in the calculation, e.g. in `FIRST_VALUE` on [BigQuery].
8324    ///
8325    /// Syntax:
8326    /// ```plaintext
8327    /// { IGNORE | RESPECT } NULLS ]
8328    /// ```
8329    ///
8330    /// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/navigation_functions#first_value
8331    IgnoreOrRespectNulls(NullTreatment),
8332    /// Specifies the the ordering for some ordered set aggregates, e.g. `ARRAY_AGG` on [BigQuery].
8333    ///
8334    /// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/aggregate_functions#array_agg
8335    OrderBy(Vec<OrderByExpr>),
8336    /// Specifies a limit for the `ARRAY_AGG` and `ARRAY_CONCAT_AGG` functions on BigQuery.
8337    Limit(Expr),
8338    /// Specifies the behavior on overflow of the `LISTAGG` function.
8339    ///
8340    /// See <https://trino.io/docs/current/functions/aggregate.html>.
8341    OnOverflow(ListAggOnOverflow),
8342    /// Specifies a minimum or maximum bound on the input to [`ANY_VALUE`] on BigQuery.
8343    ///
8344    /// Syntax:
8345    /// ```plaintext
8346    /// HAVING { MAX | MIN } expression
8347    /// ```
8348    ///
8349    /// [`ANY_VALUE`]: https://cloud.google.com/bigquery/docs/reference/standard-sql/aggregate_functions#any_value
8350    Having(HavingBound),
8351    /// The `SEPARATOR` clause to the [`GROUP_CONCAT`] function in MySQL.
8352    ///
8353    /// [`GROUP_CONCAT`]: https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html#function_group-concat
8354    Separator(ValueWithSpan),
8355    /// The `ON NULL` clause for some JSON functions.
8356    ///
8357    /// [MSSQL `JSON_ARRAY`](https://learn.microsoft.com/en-us/sql/t-sql/functions/json-array-transact-sql?view=sql-server-ver16)
8358    /// [MSSQL `JSON_OBJECT`](https://learn.microsoft.com/en-us/sql/t-sql/functions/json-object-transact-sql?view=sql-server-ver16>)
8359    /// [PostgreSQL JSON functions](https://www.postgresql.org/docs/current/functions-json.html#FUNCTIONS-JSON-PROCESSING)
8360    JsonNullClause(JsonNullClause),
8361    /// The `RETURNING` clause for some JSON functions in PostgreSQL
8362    ///
8363    /// [`JSON_OBJECT`](https://www.postgresql.org/docs/current/functions-json.html#:~:text=json_object)
8364    JsonReturningClause(JsonReturningClause),
8365}
8366
8367impl fmt::Display for FunctionArgumentClause {
8368    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8369        match self {
8370            FunctionArgumentClause::IgnoreOrRespectNulls(null_treatment) => {
8371                write!(f, "{null_treatment}")
8372            }
8373            FunctionArgumentClause::OrderBy(order_by) => {
8374                write!(f, "ORDER BY {}", display_comma_separated(order_by))
8375            }
8376            FunctionArgumentClause::Limit(limit) => write!(f, "LIMIT {limit}"),
8377            FunctionArgumentClause::OnOverflow(on_overflow) => write!(f, "{on_overflow}"),
8378            FunctionArgumentClause::Having(bound) => write!(f, "{bound}"),
8379            FunctionArgumentClause::Separator(sep) => write!(f, "SEPARATOR {sep}"),
8380            FunctionArgumentClause::JsonNullClause(null_clause) => write!(f, "{null_clause}"),
8381            FunctionArgumentClause::JsonReturningClause(returning_clause) => {
8382                write!(f, "{returning_clause}")
8383            }
8384        }
8385    }
8386}
8387
8388/// A method call
8389#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8390#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8391#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8392pub struct Method {
8393    /// The expression on which the method is invoked.
8394    pub expr: Box<Expr>,
8395    // always non-empty
8396    /// The sequence of chained method calls.
8397    pub method_chain: Vec<Function>,
8398}
8399
8400impl fmt::Display for Method {
8401    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8402        write!(
8403            f,
8404            "{}.{}",
8405            self.expr,
8406            display_separated(&self.method_chain, ".")
8407        )
8408    }
8409}
8410
8411#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8412#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8413#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8414/// How duplicate values are treated inside function argument lists.
8415pub enum DuplicateTreatment {
8416    /// Consider only unique values.
8417    Distinct,
8418    /// Retain all duplicate values (the default).
8419    All,
8420}
8421
8422impl fmt::Display for DuplicateTreatment {
8423    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8424        match self {
8425            DuplicateTreatment::Distinct => write!(f, "DISTINCT"),
8426            DuplicateTreatment::All => write!(f, "ALL"),
8427        }
8428    }
8429}
8430
8431#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8432#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8433#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8434/// How the `ANALYZE`/`EXPLAIN ANALYZE` format is specified.
8435pub enum AnalyzeFormatKind {
8436    /// Format provided as a keyword, e.g. `FORMAT JSON`.
8437    Keyword(AnalyzeFormat),
8438    /// Format provided as an assignment, e.g. `FORMAT=JSON`.
8439    Assignment(AnalyzeFormat),
8440}
8441
8442impl fmt::Display for AnalyzeFormatKind {
8443    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
8444        match self {
8445            AnalyzeFormatKind::Keyword(format) => write!(f, "FORMAT {format}"),
8446            AnalyzeFormatKind::Assignment(format) => write!(f, "FORMAT={format}"),
8447        }
8448    }
8449}
8450
8451#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8452#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8453#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8454/// Output formats supported for `ANALYZE`/`EXPLAIN ANALYZE`.
8455pub enum AnalyzeFormat {
8456    /// Plain text format.
8457    TEXT,
8458    /// Graphviz DOT format.
8459    GRAPHVIZ,
8460    /// JSON format.
8461    JSON,
8462    /// Traditional explain output.
8463    TRADITIONAL,
8464    /// Tree-style explain output.
8465    TREE,
8466}
8467
8468impl fmt::Display for AnalyzeFormat {
8469    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
8470        f.write_str(match self {
8471            AnalyzeFormat::TEXT => "TEXT",
8472            AnalyzeFormat::GRAPHVIZ => "GRAPHVIZ",
8473            AnalyzeFormat::JSON => "JSON",
8474            AnalyzeFormat::TRADITIONAL => "TRADITIONAL",
8475            AnalyzeFormat::TREE => "TREE",
8476        })
8477    }
8478}
8479
8480/// External table's available file format
8481#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8482#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8483#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8484pub enum FileFormat {
8485    /// Text file format.
8486    TEXTFILE,
8487    /// Sequence file format.
8488    SEQUENCEFILE,
8489    /// ORC file format.
8490    ORC,
8491    /// Parquet file format.
8492    PARQUET,
8493    /// Avro file format.
8494    AVRO,
8495    /// RCFile format.
8496    RCFILE,
8497    /// JSON file format.
8498    JSONFILE,
8499}
8500
8501impl fmt::Display for FileFormat {
8502    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8503        use self::FileFormat::*;
8504        f.write_str(match self {
8505            TEXTFILE => "TEXTFILE",
8506            SEQUENCEFILE => "SEQUENCEFILE",
8507            ORC => "ORC",
8508            PARQUET => "PARQUET",
8509            AVRO => "AVRO",
8510            RCFILE => "RCFILE",
8511            JSONFILE => "JSONFILE",
8512        })
8513    }
8514}
8515
8516/// The `ON OVERFLOW` clause of a LISTAGG invocation
8517#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8518#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8519#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8520pub enum ListAggOnOverflow {
8521    /// `ON OVERFLOW ERROR`
8522    Error,
8523
8524    /// `ON OVERFLOW TRUNCATE [ <filler> ] WITH[OUT] COUNT`
8525    Truncate {
8526        /// Optional filler expression used when truncating.
8527        filler: Option<Box<Expr>>,
8528        /// Whether to include a count when truncating.
8529        with_count: bool,
8530    },
8531}
8532
8533impl fmt::Display for ListAggOnOverflow {
8534    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8535        write!(f, "ON OVERFLOW")?;
8536        match self {
8537            ListAggOnOverflow::Error => write!(f, " ERROR"),
8538            ListAggOnOverflow::Truncate { filler, with_count } => {
8539                write!(f, " TRUNCATE")?;
8540                if let Some(filler) = filler {
8541                    write!(f, " {filler}")?;
8542                }
8543                if *with_count {
8544                    write!(f, " WITH")?;
8545                } else {
8546                    write!(f, " WITHOUT")?;
8547                }
8548                write!(f, " COUNT")
8549            }
8550        }
8551    }
8552}
8553
8554/// The `HAVING` clause in a call to `ANY_VALUE` on BigQuery.
8555#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8556#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8557#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8558pub struct HavingBound(pub HavingBoundKind, pub Expr);
8559
8560impl fmt::Display for HavingBound {
8561    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8562        write!(f, "HAVING {} {}", self.0, self.1)
8563    }
8564}
8565
8566#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8567#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8568#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8569/// Which bound is used in a HAVING clause for ANY_VALUE on BigQuery.
8570pub enum HavingBoundKind {
8571    /// The minimum bound.
8572    Min,
8573    /// The maximum bound.
8574    Max,
8575}
8576
8577impl fmt::Display for HavingBoundKind {
8578    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8579        match self {
8580            HavingBoundKind::Min => write!(f, "MIN"),
8581            HavingBoundKind::Max => write!(f, "MAX"),
8582        }
8583    }
8584}
8585
8586#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8587#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8588#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8589/// Types of database objects referenced by DDL statements.
8590pub enum ObjectType {
8591    /// A collation.
8592    Collation,
8593    /// A table.
8594    Table,
8595    /// A view.
8596    View,
8597    /// A materialized view.
8598    MaterializedView,
8599    /// An index.
8600    Index,
8601    /// A schema.
8602    Schema,
8603    /// A database.
8604    Database,
8605    /// A role.
8606    Role,
8607    /// A sequence.
8608    Sequence,
8609    /// A stage.
8610    Stage,
8611    /// A type definition.
8612    Type,
8613    /// A user.
8614    User,
8615    /// A stream.
8616    Stream,
8617}
8618
8619impl fmt::Display for ObjectType {
8620    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8621        f.write_str(match self {
8622            ObjectType::Collation => "COLLATION",
8623            ObjectType::Table => "TABLE",
8624            ObjectType::View => "VIEW",
8625            ObjectType::MaterializedView => "MATERIALIZED VIEW",
8626            ObjectType::Index => "INDEX",
8627            ObjectType::Schema => "SCHEMA",
8628            ObjectType::Database => "DATABASE",
8629            ObjectType::Role => "ROLE",
8630            ObjectType::Sequence => "SEQUENCE",
8631            ObjectType::Stage => "STAGE",
8632            ObjectType::Type => "TYPE",
8633            ObjectType::User => "USER",
8634            ObjectType::Stream => "STREAM",
8635        })
8636    }
8637}
8638
8639#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8640#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8641#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8642/// Types supported by `KILL` statements.
8643pub enum KillType {
8644    /// Kill a connection.
8645    Connection,
8646    /// Kill a running query.
8647    Query,
8648    /// Kill a mutation (ClickHouse).
8649    Mutation,
8650}
8651
8652impl fmt::Display for KillType {
8653    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8654        f.write_str(match self {
8655            // MySQL
8656            KillType::Connection => "CONNECTION",
8657            KillType::Query => "QUERY",
8658            // Clickhouse supports Mutation
8659            KillType::Mutation => "MUTATION",
8660        })
8661    }
8662}
8663
8664#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8665#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8666#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8667/// Distribution style options for Hive tables.
8668pub enum HiveDistributionStyle {
8669    /// Partitioned distribution with the given columns.
8670    PARTITIONED {
8671        /// Columns used for partitioning.
8672        columns: Vec<ColumnDef>,
8673    },
8674    /// Skewed distribution definition.
8675    SKEWED {
8676        /// Columns participating in the skew definition.
8677        columns: Vec<ColumnDef>,
8678        /// Columns listed in the `ON` clause for skewing.
8679        on: Vec<ColumnDef>,
8680        /// Whether skewed data is stored as directories.
8681        stored_as_directories: bool,
8682    },
8683    /// No distribution style specified.
8684    NONE,
8685}
8686
8687#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8688#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8689#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8690/// Row format specification for Hive tables (SERDE or DELIMITED).
8691pub enum HiveRowFormat {
8692    /// SerDe class specification with the implementing class name.
8693    SERDE {
8694        /// The SerDe implementation class name.
8695        class: String,
8696    },
8697    /// Delimited row format with one or more delimiter specifications.
8698    DELIMITED {
8699        /// The list of delimiters used for delimiting fields/lines.
8700        delimiters: Vec<HiveRowDelimiter>,
8701    },
8702}
8703
8704#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8705#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8706#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8707/// Format specification for `LOAD DATA` Hive operations.
8708pub struct HiveLoadDataFormat {
8709    /// SerDe expression used for the table.
8710    pub serde: Expr,
8711    /// Input format expression.
8712    pub input_format: Expr,
8713}
8714
8715#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8716#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8717#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8718/// A single row delimiter specification for Hive `ROW FORMAT`.
8719pub struct HiveRowDelimiter {
8720    /// The delimiter kind (fields/lines/etc.).
8721    pub delimiter: HiveDelimiter,
8722    /// The delimiter character identifier.
8723    pub char: Ident,
8724}
8725
8726impl fmt::Display for HiveRowDelimiter {
8727    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8728        write!(f, "{} ", self.delimiter)?;
8729        write!(f, "{}", self.char)
8730    }
8731}
8732
8733#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8734#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8735#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8736/// Kind of delimiter used in Hive `ROW FORMAT` definitions.
8737pub enum HiveDelimiter {
8738    /// Fields terminated by a delimiter.
8739    FieldsTerminatedBy,
8740    /// Fields escaped by a character.
8741    FieldsEscapedBy,
8742    /// Collection items terminated by a delimiter.
8743    CollectionItemsTerminatedBy,
8744    /// Map keys terminated by a delimiter.
8745    MapKeysTerminatedBy,
8746    /// Lines terminated by a delimiter.
8747    LinesTerminatedBy,
8748    /// Null represented by a specific token.
8749    NullDefinedAs,
8750}
8751
8752impl fmt::Display for HiveDelimiter {
8753    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8754        use HiveDelimiter::*;
8755        f.write_str(match self {
8756            FieldsTerminatedBy => "FIELDS TERMINATED BY",
8757            FieldsEscapedBy => "ESCAPED BY",
8758            CollectionItemsTerminatedBy => "COLLECTION ITEMS TERMINATED BY",
8759            MapKeysTerminatedBy => "MAP KEYS TERMINATED BY",
8760            LinesTerminatedBy => "LINES TERMINATED BY",
8761            NullDefinedAs => "NULL DEFINED AS",
8762        })
8763    }
8764}
8765
8766#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8767#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8768#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8769/// Describe output format options for Hive `DESCRIBE`/`EXPLAIN`.
8770pub enum HiveDescribeFormat {
8771    /// Extended describe output.
8772    Extended,
8773    /// Formatted describe output.
8774    Formatted,
8775}
8776
8777impl fmt::Display for HiveDescribeFormat {
8778    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8779        use HiveDescribeFormat::*;
8780        f.write_str(match self {
8781            Extended => "EXTENDED",
8782            Formatted => "FORMATTED",
8783        })
8784    }
8785}
8786
8787#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8788#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8789#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8790/// Aliases accepted for describe-style commands.
8791pub enum DescribeAlias {
8792    /// `DESCRIBE` alias.
8793    Describe,
8794    /// `EXPLAIN` alias.
8795    Explain,
8796    /// `DESC` alias.
8797    Desc,
8798}
8799
8800impl fmt::Display for DescribeAlias {
8801    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8802        use DescribeAlias::*;
8803        f.write_str(match self {
8804            Describe => "DESCRIBE",
8805            Explain => "EXPLAIN",
8806            Desc => "DESC",
8807        })
8808    }
8809}
8810
8811#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8812#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8813#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8814#[allow(clippy::large_enum_variant)]
8815/// Hive input/output format specification used in `CREATE TABLE`.
8816pub enum HiveIOFormat {
8817    /// Generic IO format with separate input and output expressions.
8818    IOF {
8819        /// Expression for the input format.
8820        input_format: Expr,
8821        /// Expression for the output format.
8822        output_format: Expr,
8823    },
8824    /// File format wrapper referencing a `FileFormat` variant.
8825    FileFormat {
8826        /// The file format used for storage.
8827        format: FileFormat,
8828    },
8829}
8830
8831#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Default)]
8832#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8833#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8834/// Hive table format and storage-related options.
8835pub struct HiveFormat {
8836    /// Optional row format specification.
8837    pub row_format: Option<HiveRowFormat>,
8838    /// Optional SerDe properties expressed as SQL options.
8839    pub serde_properties: Option<Vec<SqlOption>>,
8840    /// Optional input/output storage format details.
8841    pub storage: Option<HiveIOFormat>,
8842    /// Optional location (URI or path) for table data.
8843    pub location: Option<String>,
8844}
8845
8846#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8847#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8848#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8849/// A clustered index column specification.
8850pub struct ClusteredIndex {
8851    /// Column identifier for the clustered index entry.
8852    pub name: Ident,
8853    /// Optional sort direction: `Some(true)` for ASC, `Some(false)` for DESC, `None` for unspecified.
8854    pub asc: Option<bool>,
8855}
8856
8857impl fmt::Display for ClusteredIndex {
8858    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8859        write!(f, "{}", self.name)?;
8860        match self.asc {
8861            Some(true) => write!(f, " ASC"),
8862            Some(false) => write!(f, " DESC"),
8863            _ => Ok(()),
8864        }
8865    }
8866}
8867
8868#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8869#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8870#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8871/// Clustered options used for `CREATE TABLE` clustered/indexed storage.
8872pub enum TableOptionsClustered {
8873    /// Use a columnstore index.
8874    ColumnstoreIndex,
8875    /// Columnstore index with an explicit ordering of columns.
8876    ColumnstoreIndexOrder(Vec<Ident>),
8877    /// A named clustered index with one or more columns.
8878    Index(Vec<ClusteredIndex>),
8879}
8880
8881impl fmt::Display for TableOptionsClustered {
8882    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8883        match self {
8884            TableOptionsClustered::ColumnstoreIndex => {
8885                write!(f, "CLUSTERED COLUMNSTORE INDEX")
8886            }
8887            TableOptionsClustered::ColumnstoreIndexOrder(values) => {
8888                write!(
8889                    f,
8890                    "CLUSTERED COLUMNSTORE INDEX ORDER ({})",
8891                    display_comma_separated(values)
8892                )
8893            }
8894            TableOptionsClustered::Index(values) => {
8895                write!(f, "CLUSTERED INDEX ({})", display_comma_separated(values))
8896            }
8897        }
8898    }
8899}
8900
8901/// Specifies which partition the boundary values on table partitioning belongs to.
8902#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash)]
8903#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8904#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8905pub enum PartitionRangeDirection {
8906    /// LEFT range direction.
8907    Left,
8908    /// RIGHT range direction.
8909    Right,
8910}
8911
8912#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8913#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8914#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8915/// SQL option syntax used in table and server definitions.
8916pub enum SqlOption {
8917    /// Clustered represents the clustered version of table storage for MSSQL.
8918    ///
8919    /// <https://learn.microsoft.com/en-us/sql/t-sql/statements/create-table-azure-sql-data-warehouse?view=aps-pdw-2016-au7#TableOptions>
8920    Clustered(TableOptionsClustered),
8921    /// Single identifier options, e.g. `HEAP` for MSSQL.
8922    ///
8923    /// <https://learn.microsoft.com/en-us/sql/t-sql/statements/create-table-azure-sql-data-warehouse?view=aps-pdw-2016-au7#TableOptions>
8924    Ident(Ident),
8925    /// Any option that consists of a key value pair where the value is an expression. e.g.
8926    ///
8927    ///   WITH(DISTRIBUTION = ROUND_ROBIN)
8928    KeyValue {
8929        /// The option key identifier.
8930        key: Ident,
8931        /// The expression value for the option.
8932        value: Expr,
8933    },
8934    /// One or more table partitions and represents which partition the boundary values belong to,
8935    /// e.g.
8936    ///
8937    ///   PARTITION (id RANGE LEFT FOR VALUES (10, 20, 30, 40))
8938    ///
8939    /// <https://learn.microsoft.com/en-us/sql/t-sql/statements/create-table-azure-sql-data-warehouse?view=aps-pdw-2016-au7#TablePartitionOptions>
8940    Partition {
8941        /// The partition column name.
8942        column_name: Ident,
8943        /// Optional direction for the partition range (LEFT/RIGHT).
8944        range_direction: Option<PartitionRangeDirection>,
8945        /// Values that define the partition boundaries.
8946        for_values: Vec<Expr>,
8947    },
8948    /// Comment parameter (supports `=` and no `=` syntax)
8949    Comment(CommentDef),
8950    /// MySQL TableSpace option
8951    /// <https://dev.mysql.com/doc/refman/8.4/en/create-table.html>
8952    TableSpace(TablespaceOption),
8953    /// An option representing a key value pair, where the value is a parenthesized list and with an optional name
8954    /// e.g.
8955    ///
8956    ///   UNION  = (tbl_name\[,tbl_name\]...) <https://dev.mysql.com/doc/refman/8.4/en/create-table.html>
8957    ///   ENGINE = ReplicatedMergeTree('/table_name','{replica}', ver) <https://clickhouse.com/docs/engines/table-engines/mergetree-family/replication>
8958    ///   ENGINE = SummingMergeTree(\[columns\]) <https://clickhouse.com/docs/engines/table-engines/mergetree-family/summingmergetree>
8959    NamedParenthesizedList(NamedParenthesizedList),
8960}
8961
8962impl fmt::Display for SqlOption {
8963    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8964        match self {
8965            SqlOption::Clustered(c) => write!(f, "{c}"),
8966            SqlOption::Ident(ident) => {
8967                write!(f, "{ident}")
8968            }
8969            SqlOption::KeyValue { key: name, value } => {
8970                write!(f, "{name} = {value}")
8971            }
8972            SqlOption::Partition {
8973                column_name,
8974                range_direction,
8975                for_values,
8976            } => {
8977                let direction = match range_direction {
8978                    Some(PartitionRangeDirection::Left) => " LEFT",
8979                    Some(PartitionRangeDirection::Right) => " RIGHT",
8980                    None => "",
8981                };
8982
8983                write!(
8984                    f,
8985                    "PARTITION ({} RANGE{} FOR VALUES ({}))",
8986                    column_name,
8987                    direction,
8988                    display_comma_separated(for_values)
8989                )
8990            }
8991            SqlOption::TableSpace(tablespace_option) => {
8992                write!(f, "TABLESPACE {}", tablespace_option.name)?;
8993                match tablespace_option.storage {
8994                    Some(StorageType::Disk) => write!(f, " STORAGE DISK"),
8995                    Some(StorageType::Memory) => write!(f, " STORAGE MEMORY"),
8996                    None => Ok(()),
8997                }
8998            }
8999            SqlOption::Comment(comment) => match comment {
9000                CommentDef::WithEq(comment) => {
9001                    write!(f, "COMMENT = '{comment}'")
9002                }
9003                CommentDef::WithoutEq(comment) => {
9004                    write!(f, "COMMENT '{comment}'")
9005                }
9006            },
9007            SqlOption::NamedParenthesizedList(value) => {
9008                write!(f, "{} = ", value.key)?;
9009                if let Some(key) = &value.name {
9010                    write!(f, "{key}")?;
9011                }
9012                if !value.values.is_empty() {
9013                    write!(f, "({})", display_comma_separated(&value.values))?
9014                }
9015                Ok(())
9016            }
9017        }
9018    }
9019}
9020
9021#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
9022#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9023#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9024/// Storage type options for a tablespace.
9025pub enum StorageType {
9026    /// Store on disk.
9027    Disk,
9028    /// Store in memory.
9029    Memory,
9030}
9031
9032#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
9033#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9034#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9035/// MySql TableSpace option
9036/// <https://dev.mysql.com/doc/refman/8.4/en/create-table.html>
9037pub struct TablespaceOption {
9038    /// Name of the tablespace.
9039    pub name: String,
9040    /// Optional storage type for the tablespace.
9041    pub storage: Option<StorageType>,
9042}
9043
9044#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9045#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9046#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9047/// A key/value identifier pair used for secret or key-based options.
9048pub struct SecretOption {
9049    /// The option key identifier.
9050    pub key: Ident,
9051    /// The option value identifier.
9052    pub value: Ident,
9053}
9054
9055impl fmt::Display for SecretOption {
9056    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9057        write!(f, "{} {}", self.key, self.value)
9058    }
9059}
9060
9061/// A `CREATE SERVER` statement.
9062///
9063/// [PostgreSQL Documentation](https://www.postgresql.org/docs/current/sql-createserver.html)
9064#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9065#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9066#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9067pub struct CreateServerStatement {
9068    /// The server name.
9069    pub name: ObjectName,
9070    /// Whether `IF NOT EXISTS` was specified.
9071    pub if_not_exists: bool,
9072    /// Optional server type identifier.
9073    pub server_type: Option<Ident>,
9074    /// Optional server version identifier.
9075    pub version: Option<Ident>,
9076    /// Foreign-data wrapper object name.
9077    pub foreign_data_wrapper: ObjectName,
9078    /// Optional list of server options.
9079    pub options: Option<Vec<CreateServerOption>>,
9080}
9081
9082impl fmt::Display for CreateServerStatement {
9083    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
9084        let CreateServerStatement {
9085            name,
9086            if_not_exists,
9087            server_type,
9088            version,
9089            foreign_data_wrapper,
9090            options,
9091        } = self;
9092
9093        write!(
9094            f,
9095            "CREATE SERVER {if_not_exists}{name} ",
9096            if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
9097        )?;
9098
9099        if let Some(st) = server_type {
9100            write!(f, "TYPE {st} ")?;
9101        }
9102
9103        if let Some(v) = version {
9104            write!(f, "VERSION {v} ")?;
9105        }
9106
9107        write!(f, "FOREIGN DATA WRAPPER {foreign_data_wrapper}")?;
9108
9109        if let Some(o) = options {
9110            write!(f, " OPTIONS ({o})", o = display_comma_separated(o))?;
9111        }
9112
9113        Ok(())
9114    }
9115}
9116
9117/// A key/value option for `CREATE SERVER`.
9118#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9119#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9120#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9121pub struct CreateServerOption {
9122    /// Option key identifier.
9123    pub key: Ident,
9124    /// Option value identifier.
9125    pub value: Ident,
9126}
9127
9128impl fmt::Display for CreateServerOption {
9129    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9130        write!(f, "{} {}", self.key, self.value)
9131    }
9132}
9133
9134#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9135#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9136#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9137/// Options supported by DuckDB for `ATTACH DATABASE`.
9138pub enum AttachDuckDBDatabaseOption {
9139    /// READ_ONLY option, optional boolean value.
9140    ReadOnly(Option<bool>),
9141    /// TYPE option specifying a database type identifier.
9142    Type(Ident),
9143}
9144
9145impl fmt::Display for AttachDuckDBDatabaseOption {
9146    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9147        match self {
9148            AttachDuckDBDatabaseOption::ReadOnly(Some(true)) => write!(f, "READ_ONLY true"),
9149            AttachDuckDBDatabaseOption::ReadOnly(Some(false)) => write!(f, "READ_ONLY false"),
9150            AttachDuckDBDatabaseOption::ReadOnly(None) => write!(f, "READ_ONLY"),
9151            AttachDuckDBDatabaseOption::Type(t) => write!(f, "TYPE {t}"),
9152        }
9153    }
9154}
9155
9156#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9157#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9158#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9159/// Mode for transactions: access mode or isolation level.
9160pub enum TransactionMode {
9161    /// Access mode for a transaction (e.g. `READ ONLY` / `READ WRITE`).
9162    AccessMode(TransactionAccessMode),
9163    /// Isolation level for a transaction (e.g. `SERIALIZABLE`).
9164    IsolationLevel(TransactionIsolationLevel),
9165}
9166
9167impl fmt::Display for TransactionMode {
9168    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9169        use TransactionMode::*;
9170        match self {
9171            AccessMode(access_mode) => write!(f, "{access_mode}"),
9172            IsolationLevel(iso_level) => write!(f, "ISOLATION LEVEL {iso_level}"),
9173        }
9174    }
9175}
9176
9177#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9178#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9179#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9180/// Transaction access mode (READ ONLY / READ WRITE).
9181pub enum TransactionAccessMode {
9182    /// READ ONLY access mode.
9183    ReadOnly,
9184    /// READ WRITE access mode.
9185    ReadWrite,
9186}
9187
9188impl fmt::Display for TransactionAccessMode {
9189    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9190        use TransactionAccessMode::*;
9191        f.write_str(match self {
9192            ReadOnly => "READ ONLY",
9193            ReadWrite => "READ WRITE",
9194        })
9195    }
9196}
9197
9198#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9199#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9200#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9201/// Transaction isolation levels.
9202pub enum TransactionIsolationLevel {
9203    /// READ UNCOMMITTED isolation level.
9204    ReadUncommitted,
9205    /// READ COMMITTED isolation level.
9206    ReadCommitted,
9207    /// REPEATABLE READ isolation level.
9208    RepeatableRead,
9209    /// SERIALIZABLE isolation level.
9210    Serializable,
9211    /// SNAPSHOT isolation level.
9212    Snapshot,
9213}
9214
9215impl fmt::Display for TransactionIsolationLevel {
9216    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9217        use TransactionIsolationLevel::*;
9218        f.write_str(match self {
9219            ReadUncommitted => "READ UNCOMMITTED",
9220            ReadCommitted => "READ COMMITTED",
9221            RepeatableRead => "REPEATABLE READ",
9222            Serializable => "SERIALIZABLE",
9223            Snapshot => "SNAPSHOT",
9224        })
9225    }
9226}
9227
9228/// Modifier for the transaction in the `BEGIN` syntax
9229///
9230/// SQLite: <https://sqlite.org/lang_transaction.html>
9231/// MS-SQL: <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/try-catch-transact-sql>
9232#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9233#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9234#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9235pub enum TransactionModifier {
9236    /// DEFERRED transaction modifier.
9237    Deferred,
9238    /// IMMEDIATE transaction modifier.
9239    Immediate,
9240    /// EXCLUSIVE transaction modifier.
9241    Exclusive,
9242    /// TRY block modifier (MS-SQL style TRY/CATCH).
9243    Try,
9244    /// CATCH block modifier (MS-SQL style TRY/CATCH).
9245    Catch,
9246}
9247
9248impl fmt::Display for TransactionModifier {
9249    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9250        use TransactionModifier::*;
9251        f.write_str(match self {
9252            Deferred => "DEFERRED",
9253            Immediate => "IMMEDIATE",
9254            Exclusive => "EXCLUSIVE",
9255            Try => "TRY",
9256            Catch => "CATCH",
9257        })
9258    }
9259}
9260
9261#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9262#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9263#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9264/// Filter forms usable in SHOW statements.
9265pub enum ShowStatementFilter {
9266    /// Filter using LIKE pattern.
9267    Like(String),
9268    /// Filter using ILIKE pattern.
9269    ILike(String),
9270    /// Filter using a WHERE expression.
9271    Where(Expr),
9272    /// Filter provided without a keyword (raw string).
9273    NoKeyword(String),
9274}
9275
9276impl fmt::Display for ShowStatementFilter {
9277    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9278        use ShowStatementFilter::*;
9279        match self {
9280            Like(pattern) => write!(f, "LIKE '{}'", value::escape_single_quote_string(pattern)),
9281            ILike(pattern) => write!(f, "ILIKE {}", value::escape_single_quote_string(pattern)),
9282            Where(expr) => write!(f, "WHERE {expr}"),
9283            NoKeyword(pattern) => write!(f, "'{}'", value::escape_single_quote_string(pattern)),
9284        }
9285    }
9286}
9287
9288#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9289#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9290#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9291/// Clause types used with SHOW ... IN/FROM.
9292pub enum ShowStatementInClause {
9293    /// Use the `IN` clause.
9294    IN,
9295    /// Use the `FROM` clause.
9296    FROM,
9297}
9298
9299impl fmt::Display for ShowStatementInClause {
9300    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9301        use ShowStatementInClause::*;
9302        match self {
9303            FROM => write!(f, "FROM"),
9304            IN => write!(f, "IN"),
9305        }
9306    }
9307}
9308
9309/// Sqlite specific syntax
9310///
9311/// See [Sqlite documentation](https://sqlite.org/lang_conflict.html)
9312/// for more details.
9313#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9314#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9315#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9316pub enum SqliteOnConflict {
9317    /// Use ROLLBACK on conflict.
9318    Rollback,
9319    /// Use ABORT on conflict.
9320    Abort,
9321    /// Use FAIL on conflict.
9322    Fail,
9323    /// Use IGNORE on conflict.
9324    Ignore,
9325    /// Use REPLACE on conflict.
9326    Replace,
9327}
9328
9329impl fmt::Display for SqliteOnConflict {
9330    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9331        use SqliteOnConflict::*;
9332        match self {
9333            Rollback => write!(f, "OR ROLLBACK"),
9334            Abort => write!(f, "OR ABORT"),
9335            Fail => write!(f, "OR FAIL"),
9336            Ignore => write!(f, "OR IGNORE"),
9337            Replace => write!(f, "OR REPLACE"),
9338        }
9339    }
9340}
9341
9342/// Mysql specific syntax
9343///
9344/// See [Mysql documentation](https://dev.mysql.com/doc/refman/8.0/en/replace.html)
9345/// See [Mysql documentation](https://dev.mysql.com/doc/refman/8.0/en/insert.html)
9346/// for more details.
9347#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9348#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9349#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9350pub enum MysqlInsertPriority {
9351    /// LOW_PRIORITY modifier for INSERT/REPLACE.
9352    LowPriority,
9353    /// DELAYED modifier for INSERT/REPLACE.
9354    Delayed,
9355    /// HIGH_PRIORITY modifier for INSERT/REPLACE.
9356    HighPriority,
9357}
9358
9359impl fmt::Display for crate::ast::MysqlInsertPriority {
9360    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9361        use MysqlInsertPriority::*;
9362        match self {
9363            LowPriority => write!(f, "LOW_PRIORITY"),
9364            Delayed => write!(f, "DELAYED"),
9365            HighPriority => write!(f, "HIGH_PRIORITY"),
9366        }
9367    }
9368}
9369
9370#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9371#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9372#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9373/// Source for the `COPY` command: a table or a query.
9374pub enum CopySource {
9375    /// Copy from a table with optional column list.
9376    Table {
9377        /// The name of the table to copy from.
9378        table_name: ObjectName,
9379        /// A list of column names to copy. Empty list means that all columns
9380        /// are copied.
9381        columns: Vec<Ident>,
9382    },
9383    /// Copy from the results of a query.
9384    Query(Box<Query>),
9385}
9386
9387#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9388#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9389#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9390/// Target for the `COPY` command: STDIN, STDOUT, a file, or a program.
9391pub enum CopyTarget {
9392    /// Use standard input as the source.
9393    Stdin,
9394    /// Use standard output as the target.
9395    Stdout,
9396    /// Read from or write to a file.
9397    File {
9398        /// The path name of the input or output file.
9399        filename: String,
9400    },
9401    /// Use a program as the source or target (shell command).
9402    Program {
9403        /// A command to execute
9404        command: String,
9405    },
9406}
9407
9408impl fmt::Display for CopyTarget {
9409    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9410        use CopyTarget::*;
9411        match self {
9412            Stdin => write!(f, "STDIN"),
9413            Stdout => write!(f, "STDOUT"),
9414            File { filename } => write!(f, "'{}'", value::escape_single_quote_string(filename)),
9415            Program { command } => write!(
9416                f,
9417                "PROGRAM '{}'",
9418                value::escape_single_quote_string(command)
9419            ),
9420        }
9421    }
9422}
9423
9424#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9425#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9426#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9427/// Action to take `ON COMMIT` for temporary tables.
9428pub enum OnCommit {
9429    /// Delete rows on commit.
9430    DeleteRows,
9431    /// Preserve rows on commit.
9432    PreserveRows,
9433    /// Drop the table on commit.
9434    Drop,
9435}
9436
9437/// An option in `COPY` statement.
9438///
9439/// <https://www.postgresql.org/docs/14/sql-copy.html>
9440#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9441#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9442#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9443pub enum CopyOption {
9444    /// FORMAT format_name
9445    Format(Ident),
9446    /// FREEZE \[ boolean \]
9447    Freeze(bool),
9448    /// DELIMITER 'delimiter_character'
9449    Delimiter(char),
9450    /// NULL 'null_string'
9451    Null(String),
9452    /// HEADER \[ boolean \]
9453    Header(bool),
9454    /// QUOTE 'quote_character'
9455    Quote(char),
9456    /// ESCAPE 'escape_character'
9457    Escape(char),
9458    /// FORCE_QUOTE { ( column_name [, ...] ) | * }
9459    ForceQuote(Vec<Ident>),
9460    /// FORCE_NOT_NULL ( column_name [, ...] )
9461    ForceNotNull(Vec<Ident>),
9462    /// FORCE_NULL ( column_name [, ...] )
9463    ForceNull(Vec<Ident>),
9464    /// ENCODING 'encoding_name'
9465    Encoding(String),
9466}
9467
9468impl fmt::Display for CopyOption {
9469    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9470        use CopyOption::*;
9471        match self {
9472            Format(name) => write!(f, "FORMAT {name}"),
9473            Freeze(true) => write!(f, "FREEZE"),
9474            Freeze(false) => write!(f, "FREEZE FALSE"),
9475            Delimiter(char) => write!(f, "DELIMITER '{char}'"),
9476            Null(string) => write!(f, "NULL '{}'", value::escape_single_quote_string(string)),
9477            Header(true) => write!(f, "HEADER"),
9478            Header(false) => write!(f, "HEADER FALSE"),
9479            Quote(char) => write!(f, "QUOTE '{char}'"),
9480            Escape(char) => write!(f, "ESCAPE '{char}'"),
9481            ForceQuote(columns) => write!(f, "FORCE_QUOTE ({})", display_comma_separated(columns)),
9482            ForceNotNull(columns) => {
9483                write!(f, "FORCE_NOT_NULL ({})", display_comma_separated(columns))
9484            }
9485            ForceNull(columns) => write!(f, "FORCE_NULL ({})", display_comma_separated(columns)),
9486            Encoding(name) => write!(f, "ENCODING '{}'", value::escape_single_quote_string(name)),
9487        }
9488    }
9489}
9490
9491/// An option in `COPY` statement before PostgreSQL version 9.0.
9492///
9493/// [PostgreSQL](https://www.postgresql.org/docs/8.4/sql-copy.html)
9494/// [Redshift](https://docs.aws.amazon.com/redshift/latest/dg/r_COPY-alphabetical-parm-list.html)
9495#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9496#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9497#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9498pub enum CopyLegacyOption {
9499    /// ACCEPTANYDATE
9500    AcceptAnyDate,
9501    /// ACCEPTINVCHARS
9502    AcceptInvChars(Option<String>),
9503    /// ADDQUOTES
9504    AddQuotes,
9505    /// ALLOWOVERWRITE
9506    AllowOverwrite,
9507    /// BINARY
9508    Binary,
9509    /// BLANKSASNULL
9510    BlankAsNull,
9511    /// BZIP2
9512    Bzip2,
9513    /// CLEANPATH
9514    CleanPath,
9515    /// COMPUPDATE [ PRESET | { ON | TRUE } | { OFF | FALSE } ]
9516    CompUpdate {
9517        /// Whether the COMPUPDATE PRESET option was used.
9518        preset: bool,
9519        /// Optional enabled flag for COMPUPDATE.
9520        enabled: Option<bool>,
9521    },
9522    /// CSV ...
9523    Csv(Vec<CopyLegacyCsvOption>),
9524    /// DATEFORMAT \[ AS \] {'dateformat_string' | 'auto' }
9525    DateFormat(Option<String>),
9526    /// DELIMITER \[ AS \] 'delimiter_character'
9527    Delimiter(char),
9528    /// EMPTYASNULL
9529    EmptyAsNull,
9530    /// `ENCRYPTED \[ AUTO \]`
9531    Encrypted {
9532        /// Whether `AUTO` was specified for encryption.
9533        auto: bool,
9534    },
9535    /// ESCAPE
9536    Escape,
9537    /// EXTENSION 'extension-name'
9538    Extension(String),
9539    /// FIXEDWIDTH \[ AS \] 'fixedwidth-spec'
9540    FixedWidth(String),
9541    /// GZIP
9542    Gzip,
9543    /// HEADER
9544    Header,
9545    /// IAM_ROLE { DEFAULT | 'arn:aws:iam::123456789:role/role1' }
9546    IamRole(IamRoleKind),
9547    /// IGNOREHEADER \[ AS \] number_rows
9548    IgnoreHeader(u64),
9549    /// JSON \[ AS \] 'json_option'
9550    Json(Option<String>),
9551    /// MANIFEST \[ VERBOSE \]
9552    Manifest {
9553        /// Whether the MANIFEST is verbose.
9554        verbose: bool,
9555    },
9556    /// MAXFILESIZE \[ AS \] max-size \[ MB | GB \]
9557    MaxFileSize(FileSize),
9558    /// `NULL \[ AS \] 'null_string'`
9559    Null(String),
9560    /// `PARALLEL [ { ON | TRUE } | { OFF | FALSE } ]`
9561    Parallel(Option<bool>),
9562    /// PARQUET
9563    Parquet,
9564    /// PARTITION BY ( column_name [, ... ] ) \[ INCLUDE \]
9565    PartitionBy(UnloadPartitionBy),
9566    /// REGION \[ AS \] 'aws-region' }
9567    Region(String),
9568    /// REMOVEQUOTES
9569    RemoveQuotes,
9570    /// ROWGROUPSIZE \[ AS \] size \[ MB | GB \]
9571    RowGroupSize(FileSize),
9572    /// STATUPDATE [ { ON | TRUE } | { OFF | FALSE } ]
9573    StatUpdate(Option<bool>),
9574    /// TIMEFORMAT \[ AS \] {'timeformat_string' | 'auto' | 'epochsecs' | 'epochmillisecs' }
9575    TimeFormat(Option<String>),
9576    /// TRUNCATECOLUMNS
9577    TruncateColumns,
9578    /// ZSTD
9579    Zstd,
9580    /// Redshift `CREDENTIALS 'auth-args'`
9581    /// <https://docs.aws.amazon.com/redshift/latest/dg/copy-parameters-authorization.html>
9582    Credentials(String),
9583}
9584
9585impl fmt::Display for CopyLegacyOption {
9586    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9587        use CopyLegacyOption::*;
9588        match self {
9589            AcceptAnyDate => write!(f, "ACCEPTANYDATE"),
9590            AcceptInvChars(ch) => {
9591                write!(f, "ACCEPTINVCHARS")?;
9592                if let Some(ch) = ch {
9593                    write!(f, " '{}'", value::escape_single_quote_string(ch))?;
9594                }
9595                Ok(())
9596            }
9597            AddQuotes => write!(f, "ADDQUOTES"),
9598            AllowOverwrite => write!(f, "ALLOWOVERWRITE"),
9599            Binary => write!(f, "BINARY"),
9600            BlankAsNull => write!(f, "BLANKSASNULL"),
9601            Bzip2 => write!(f, "BZIP2"),
9602            CleanPath => write!(f, "CLEANPATH"),
9603            CompUpdate { preset, enabled } => {
9604                write!(f, "COMPUPDATE")?;
9605                if *preset {
9606                    write!(f, " PRESET")?;
9607                } else if let Some(enabled) = enabled {
9608                    write!(
9609                        f,
9610                        "{}",
9611                        match enabled {
9612                            true => " TRUE",
9613                            false => " FALSE",
9614                        }
9615                    )?;
9616                }
9617                Ok(())
9618            }
9619            Csv(opts) => {
9620                write!(f, "CSV")?;
9621                if !opts.is_empty() {
9622                    write!(f, " {}", display_separated(opts, " "))?;
9623                }
9624                Ok(())
9625            }
9626            DateFormat(fmt) => {
9627                write!(f, "DATEFORMAT")?;
9628                if let Some(fmt) = fmt {
9629                    write!(f, " '{}'", value::escape_single_quote_string(fmt))?;
9630                }
9631                Ok(())
9632            }
9633            Delimiter(char) => write!(f, "DELIMITER '{char}'"),
9634            EmptyAsNull => write!(f, "EMPTYASNULL"),
9635            Encrypted { auto } => write!(f, "ENCRYPTED{}", if *auto { " AUTO" } else { "" }),
9636            Escape => write!(f, "ESCAPE"),
9637            Extension(ext) => write!(f, "EXTENSION '{}'", value::escape_single_quote_string(ext)),
9638            FixedWidth(spec) => write!(
9639                f,
9640                "FIXEDWIDTH '{}'",
9641                value::escape_single_quote_string(spec)
9642            ),
9643            Gzip => write!(f, "GZIP"),
9644            Header => write!(f, "HEADER"),
9645            IamRole(role) => write!(f, "IAM_ROLE {role}"),
9646            IgnoreHeader(num_rows) => write!(f, "IGNOREHEADER {num_rows}"),
9647            Json(opt) => {
9648                write!(f, "JSON")?;
9649                if let Some(opt) = opt {
9650                    write!(f, " AS '{}'", value::escape_single_quote_string(opt))?;
9651                }
9652                Ok(())
9653            }
9654            Manifest { verbose } => write!(f, "MANIFEST{}", if *verbose { " VERBOSE" } else { "" }),
9655            MaxFileSize(file_size) => write!(f, "MAXFILESIZE {file_size}"),
9656            Null(string) => write!(f, "NULL '{}'", value::escape_single_quote_string(string)),
9657            Parallel(enabled) => {
9658                write!(
9659                    f,
9660                    "PARALLEL{}",
9661                    match enabled {
9662                        Some(true) => " TRUE",
9663                        Some(false) => " FALSE",
9664                        _ => "",
9665                    }
9666                )
9667            }
9668            Parquet => write!(f, "PARQUET"),
9669            PartitionBy(p) => write!(f, "{p}"),
9670            Region(region) => write!(f, "REGION '{}'", value::escape_single_quote_string(region)),
9671            RemoveQuotes => write!(f, "REMOVEQUOTES"),
9672            RowGroupSize(file_size) => write!(f, "ROWGROUPSIZE {file_size}"),
9673            StatUpdate(enabled) => {
9674                write!(
9675                    f,
9676                    "STATUPDATE{}",
9677                    match enabled {
9678                        Some(true) => " TRUE",
9679                        Some(false) => " FALSE",
9680                        _ => "",
9681                    }
9682                )
9683            }
9684            TimeFormat(fmt) => {
9685                write!(f, "TIMEFORMAT")?;
9686                if let Some(fmt) = fmt {
9687                    write!(f, " '{}'", value::escape_single_quote_string(fmt))?;
9688                }
9689                Ok(())
9690            }
9691            TruncateColumns => write!(f, "TRUNCATECOLUMNS"),
9692            Zstd => write!(f, "ZSTD"),
9693            Credentials(s) => write!(f, "CREDENTIALS '{}'", value::escape_single_quote_string(s)),
9694        }
9695    }
9696}
9697
9698/// ```sql
9699/// SIZE \[ MB | GB \]
9700/// ```
9701#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9702#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9703#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9704pub struct FileSize {
9705    /// Numeric size value.
9706    pub size: ValueWithSpan,
9707    /// Optional unit for the size (MB or GB).
9708    pub unit: Option<FileSizeUnit>,
9709}
9710
9711impl fmt::Display for FileSize {
9712    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9713        write!(f, "{}", self.size)?;
9714        if let Some(unit) = &self.unit {
9715            write!(f, " {unit}")?;
9716        }
9717        Ok(())
9718    }
9719}
9720
9721/// Units for `FileSize` (MB or GB).
9722#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9723#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9724#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9725pub enum FileSizeUnit {
9726    /// Megabytes.
9727    MB,
9728    /// Gigabytes.
9729    GB,
9730}
9731
9732impl fmt::Display for FileSizeUnit {
9733    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9734        match self {
9735            FileSizeUnit::MB => write!(f, "MB"),
9736            FileSizeUnit::GB => write!(f, "GB"),
9737        }
9738    }
9739}
9740
9741/// Specifies the partition keys for the unload operation
9742///
9743/// ```sql
9744/// PARTITION BY ( column_name [, ... ] ) [ INCLUDE ]
9745/// ```
9746#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9747#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9748#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9749pub struct UnloadPartitionBy {
9750    /// Columns used to partition the unload output.
9751    pub columns: Vec<Ident>,
9752    /// Whether to include the partition in the output.
9753    pub include: bool,
9754}
9755
9756impl fmt::Display for UnloadPartitionBy {
9757    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9758        write!(
9759            f,
9760            "PARTITION BY ({}){}",
9761            display_comma_separated(&self.columns),
9762            if self.include { " INCLUDE" } else { "" }
9763        )
9764    }
9765}
9766
9767/// An `IAM_ROLE` option in the AWS ecosystem
9768///
9769/// [Redshift COPY](https://docs.aws.amazon.com/redshift/latest/dg/copy-parameters-authorization.html#copy-iam-role)
9770#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9771#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9772#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9773pub enum IamRoleKind {
9774    /// Default role
9775    Default,
9776    /// Specific role ARN, for example: `arn:aws:iam::123456789:role/role1`
9777    Arn(String),
9778}
9779
9780impl fmt::Display for IamRoleKind {
9781    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9782        match self {
9783            IamRoleKind::Default => write!(f, "DEFAULT"),
9784            IamRoleKind::Arn(arn) => write!(f, "'{arn}'"),
9785        }
9786    }
9787}
9788
9789/// A `CSV` option in `COPY` statement before PostgreSQL version 9.0.
9790///
9791/// <https://www.postgresql.org/docs/8.4/sql-copy.html>
9792#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9793#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9794#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9795pub enum CopyLegacyCsvOption {
9796    /// HEADER
9797    Header,
9798    /// QUOTE \[ AS \] 'quote_character'
9799    Quote(char),
9800    /// ESCAPE \[ AS \] 'escape_character'
9801    Escape(char),
9802    /// FORCE QUOTE { column_name [, ...] | * }
9803    ForceQuote(Vec<Ident>),
9804    /// FORCE NOT NULL column_name [, ...]
9805    ForceNotNull(Vec<Ident>),
9806}
9807
9808impl fmt::Display for CopyLegacyCsvOption {
9809    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9810        use CopyLegacyCsvOption::*;
9811        match self {
9812            Header => write!(f, "HEADER"),
9813            Quote(char) => write!(f, "QUOTE '{char}'"),
9814            Escape(char) => write!(f, "ESCAPE '{char}'"),
9815            ForceQuote(columns) => write!(f, "FORCE QUOTE {}", display_comma_separated(columns)),
9816            ForceNotNull(columns) => {
9817                write!(f, "FORCE NOT NULL {}", display_comma_separated(columns))
9818            }
9819        }
9820    }
9821}
9822
9823/// Objects that can be discarded with `DISCARD`.
9824#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9825#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9826#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9827pub enum DiscardObject {
9828    /// Discard all session state.
9829    ALL,
9830    /// Discard cached plans.
9831    PLANS,
9832    /// Discard sequence values.
9833    SEQUENCES,
9834    /// Discard temporary objects.
9835    TEMP,
9836}
9837
9838impl fmt::Display for DiscardObject {
9839    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9840        match self {
9841            DiscardObject::ALL => f.write_str("ALL"),
9842            DiscardObject::PLANS => f.write_str("PLANS"),
9843            DiscardObject::SEQUENCES => f.write_str("SEQUENCES"),
9844            DiscardObject::TEMP => f.write_str("TEMP"),
9845        }
9846    }
9847}
9848
9849/// Types of flush operations supported by `FLUSH`.
9850#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9851#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9852#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9853pub enum FlushType {
9854    /// Flush binary logs.
9855    BinaryLogs,
9856    /// Flush engine logs.
9857    EngineLogs,
9858    /// Flush error logs.
9859    ErrorLogs,
9860    /// Flush general logs.
9861    GeneralLogs,
9862    /// Flush hosts information.
9863    Hosts,
9864    /// Flush logs.
9865    Logs,
9866    /// Flush privileges.
9867    Privileges,
9868    /// Flush optimizer costs.
9869    OptimizerCosts,
9870    /// Flush relay logs.
9871    RelayLogs,
9872    /// Flush slow logs.
9873    SlowLogs,
9874    /// Flush status.
9875    Status,
9876    /// Flush user resources.
9877    UserResources,
9878    /// Flush table data.
9879    Tables,
9880}
9881
9882impl fmt::Display for FlushType {
9883    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9884        match self {
9885            FlushType::BinaryLogs => f.write_str("BINARY LOGS"),
9886            FlushType::EngineLogs => f.write_str("ENGINE LOGS"),
9887            FlushType::ErrorLogs => f.write_str("ERROR LOGS"),
9888            FlushType::GeneralLogs => f.write_str("GENERAL LOGS"),
9889            FlushType::Hosts => f.write_str("HOSTS"),
9890            FlushType::Logs => f.write_str("LOGS"),
9891            FlushType::Privileges => f.write_str("PRIVILEGES"),
9892            FlushType::OptimizerCosts => f.write_str("OPTIMIZER_COSTS"),
9893            FlushType::RelayLogs => f.write_str("RELAY LOGS"),
9894            FlushType::SlowLogs => f.write_str("SLOW LOGS"),
9895            FlushType::Status => f.write_str("STATUS"),
9896            FlushType::UserResources => f.write_str("USER_RESOURCES"),
9897            FlushType::Tables => f.write_str("TABLES"),
9898        }
9899    }
9900}
9901
9902/// Location modifier for flush commands.
9903#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9904#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9905#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9906pub enum FlushLocation {
9907    /// Do not write changes to the binary log.
9908    NoWriteToBinlog,
9909    /// Apply flush locally.
9910    Local,
9911}
9912
9913impl fmt::Display for FlushLocation {
9914    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9915        match self {
9916            FlushLocation::NoWriteToBinlog => f.write_str("NO_WRITE_TO_BINLOG"),
9917            FlushLocation::Local => f.write_str("LOCAL"),
9918        }
9919    }
9920}
9921
9922/// Optional context modifier for statements that can be or `LOCAL`, `GLOBAL`, or `SESSION`.
9923#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9924#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9925#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9926pub enum ContextModifier {
9927    /// `LOCAL` identifier, usually related to transactional states.
9928    Local,
9929    /// `SESSION` identifier
9930    Session,
9931    /// `GLOBAL` identifier
9932    Global,
9933}
9934
9935impl fmt::Display for ContextModifier {
9936    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9937        match self {
9938            Self::Local => {
9939                write!(f, "LOCAL ")
9940            }
9941            Self::Session => {
9942                write!(f, "SESSION ")
9943            }
9944            Self::Global => {
9945                write!(f, "GLOBAL ")
9946            }
9947        }
9948    }
9949}
9950
9951/// Function describe in DROP FUNCTION.
9952#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9953#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9954pub enum DropFunctionOption {
9955    /// `RESTRICT` option for DROP FUNCTION.
9956    Restrict,
9957    /// `CASCADE` option for DROP FUNCTION.
9958    Cascade,
9959}
9960
9961impl fmt::Display for DropFunctionOption {
9962    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9963        match self {
9964            DropFunctionOption::Restrict => write!(f, "RESTRICT "),
9965            DropFunctionOption::Cascade => write!(f, "CASCADE  "),
9966        }
9967    }
9968}
9969
9970/// Generic function description for DROP FUNCTION and CREATE TRIGGER.
9971#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9972#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9973#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9974pub struct FunctionDesc {
9975    /// The function name.
9976    pub name: ObjectName,
9977    /// Optional list of function arguments.
9978    pub args: Option<Vec<OperateFunctionArg>>,
9979}
9980
9981impl fmt::Display for FunctionDesc {
9982    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9983        write!(f, "{}", self.name)?;
9984        if let Some(args) = &self.args {
9985            write!(f, "({})", display_comma_separated(args))?;
9986        }
9987        Ok(())
9988    }
9989}
9990
9991/// Function argument in CREATE OR DROP FUNCTION.
9992#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9993#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9994#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9995pub struct OperateFunctionArg {
9996    /// Optional argument mode (`IN`, `OUT`, `INOUT`).
9997    pub mode: Option<ArgMode>,
9998    /// Optional argument identifier/name.
9999    pub name: Option<Ident>,
10000    /// The data type of the argument.
10001    pub data_type: DataType,
10002    /// Optional default expression for the argument.
10003    pub default_expr: Option<Expr>,
10004}
10005
10006impl OperateFunctionArg {
10007    /// Returns an unnamed argument.
10008    pub fn unnamed(data_type: DataType) -> Self {
10009        Self {
10010            mode: None,
10011            name: None,
10012            data_type,
10013            default_expr: None,
10014        }
10015    }
10016
10017    /// Returns an argument with name.
10018    pub fn with_name(name: &str, data_type: DataType) -> Self {
10019        Self {
10020            mode: None,
10021            name: Some(name.into()),
10022            data_type,
10023            default_expr: None,
10024        }
10025    }
10026}
10027
10028impl fmt::Display for OperateFunctionArg {
10029    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10030        if let Some(mode) = &self.mode {
10031            write!(f, "{mode} ")?;
10032        }
10033        if let Some(name) = &self.name {
10034            write!(f, "{name} ")?;
10035        }
10036        write!(f, "{}", self.data_type)?;
10037        if let Some(default_expr) = &self.default_expr {
10038            write!(f, " = {default_expr}")?;
10039        }
10040        Ok(())
10041    }
10042}
10043
10044/// The mode of an argument in CREATE FUNCTION.
10045#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10046#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10047#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10048pub enum ArgMode {
10049    /// `IN` mode.
10050    In,
10051    /// `OUT` mode.
10052    Out,
10053    /// `INOUT` mode.
10054    InOut,
10055    /// `VARIADIC` mode.
10056    Variadic,
10057}
10058
10059impl fmt::Display for ArgMode {
10060    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10061        match self {
10062            ArgMode::In => write!(f, "IN"),
10063            ArgMode::Out => write!(f, "OUT"),
10064            ArgMode::InOut => write!(f, "INOUT"),
10065            ArgMode::Variadic => write!(f, "VARIADIC"),
10066        }
10067    }
10068}
10069
10070/// These attributes inform the query optimizer about the behavior of the function.
10071#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10072#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10073#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10074pub enum FunctionBehavior {
10075    /// Function is immutable.
10076    Immutable,
10077    /// Function is stable.
10078    Stable,
10079    /// Function is volatile.
10080    Volatile,
10081}
10082
10083impl fmt::Display for FunctionBehavior {
10084    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10085        match self {
10086            FunctionBehavior::Immutable => write!(f, "IMMUTABLE"),
10087            FunctionBehavior::Stable => write!(f, "STABLE"),
10088            FunctionBehavior::Volatile => write!(f, "VOLATILE"),
10089        }
10090    }
10091}
10092
10093/// Security attribute for functions: SECURITY DEFINER or SECURITY INVOKER.
10094///
10095/// [PostgreSQL](https://www.postgresql.org/docs/current/sql-createfunction.html)
10096#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10097#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10098#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10099pub enum FunctionSecurity {
10100    /// Execute the function with the privileges of the user who defined it.
10101    Definer,
10102    /// Execute the function with the privileges of the user who invokes it.
10103    Invoker,
10104}
10105
10106impl fmt::Display for FunctionSecurity {
10107    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10108        match self {
10109            FunctionSecurity::Definer => write!(f, "SECURITY DEFINER"),
10110            FunctionSecurity::Invoker => write!(f, "SECURITY INVOKER"),
10111        }
10112    }
10113}
10114
10115/// Value for a SET configuration parameter in a CREATE FUNCTION statement.
10116///
10117/// [PostgreSQL](https://www.postgresql.org/docs/current/sql-createfunction.html)
10118#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10119#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10120#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10121pub enum FunctionSetValue {
10122    /// SET param = DEFAULT / SET param TO DEFAULT
10123    Default,
10124    /// SET param = value1, value2, ...
10125    Values(Vec<Expr>),
10126    /// SET param FROM CURRENT
10127    FromCurrent,
10128}
10129
10130/// A SET configuration_parameter clause in a CREATE FUNCTION statement.
10131///
10132/// [PostgreSQL](https://www.postgresql.org/docs/current/sql-createfunction.html)
10133#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10134#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10135#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10136pub struct FunctionDefinitionSetParam {
10137    /// The name of the configuration parameter.
10138    pub name: ObjectName,
10139    /// The value to set for the parameter.
10140    pub value: FunctionSetValue,
10141}
10142
10143impl fmt::Display for FunctionDefinitionSetParam {
10144    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10145        write!(f, "SET {} ", self.name)?;
10146        match &self.value {
10147            FunctionSetValue::Default => write!(f, "= DEFAULT"),
10148            FunctionSetValue::Values(values) => {
10149                write!(f, "= {}", display_comma_separated(values))
10150            }
10151            FunctionSetValue::FromCurrent => write!(f, "FROM CURRENT"),
10152        }
10153    }
10154}
10155
10156/// These attributes describe the behavior of the function when called with a null argument.
10157#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10158#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10159#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10160pub enum FunctionCalledOnNull {
10161    /// Function is called even when inputs are null.
10162    CalledOnNullInput,
10163    /// Function returns null when any input is null.
10164    ReturnsNullOnNullInput,
10165    /// Function is strict about null inputs.
10166    Strict,
10167}
10168
10169impl fmt::Display for FunctionCalledOnNull {
10170    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10171        match self {
10172            FunctionCalledOnNull::CalledOnNullInput => write!(f, "CALLED ON NULL INPUT"),
10173            FunctionCalledOnNull::ReturnsNullOnNullInput => write!(f, "RETURNS NULL ON NULL INPUT"),
10174            FunctionCalledOnNull::Strict => write!(f, "STRICT"),
10175        }
10176    }
10177}
10178
10179/// If it is safe for PostgreSQL to call the function from multiple threads at once
10180#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10181#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10182#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10183pub enum FunctionParallel {
10184    /// The function is not safe to run in parallel.
10185    Unsafe,
10186    /// The function is restricted for parallel execution.
10187    Restricted,
10188    /// The function is safe to run in parallel.
10189    Safe,
10190}
10191
10192impl fmt::Display for FunctionParallel {
10193    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10194        match self {
10195            FunctionParallel::Unsafe => write!(f, "PARALLEL UNSAFE"),
10196            FunctionParallel::Restricted => write!(f, "PARALLEL RESTRICTED"),
10197            FunctionParallel::Safe => write!(f, "PARALLEL SAFE"),
10198        }
10199    }
10200}
10201
10202/// [BigQuery] Determinism specifier used in a UDF definition.
10203///
10204/// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#syntax_11
10205#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10206#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10207#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10208pub enum FunctionDeterminismSpecifier {
10209    /// Function is deterministic.
10210    Deterministic,
10211    /// Function is not deterministic.
10212    NotDeterministic,
10213}
10214
10215impl fmt::Display for FunctionDeterminismSpecifier {
10216    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10217        match self {
10218            FunctionDeterminismSpecifier::Deterministic => {
10219                write!(f, "DETERMINISTIC")
10220            }
10221            FunctionDeterminismSpecifier::NotDeterministic => {
10222                write!(f, "NOT DETERMINISTIC")
10223            }
10224        }
10225    }
10226}
10227
10228/// Represent the expression body of a `CREATE FUNCTION` statement as well as
10229/// where within the statement, the body shows up.
10230///
10231/// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#syntax_11
10232/// [PostgreSQL]: https://www.postgresql.org/docs/15/sql-createfunction.html
10233/// [MsSql]: https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql
10234#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10235#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10236#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10237pub enum CreateFunctionBody {
10238    /// A function body expression using the 'AS' keyword and shows up
10239    /// before any `OPTIONS` clause.
10240    ///
10241    /// Example:
10242    /// ```sql
10243    /// CREATE FUNCTION myfunc(x FLOAT64, y FLOAT64) RETURNS FLOAT64
10244    /// AS (x * y)
10245    /// OPTIONS(description="desc");
10246    /// ```
10247    ///
10248    /// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#syntax_11
10249    /// [PostgreSQL]: https://www.postgresql.org/docs/current/sql-createfunction.html
10250    AsBeforeOptions {
10251        /// The primary expression.
10252        body: Expr,
10253        /// Link symbol if the primary expression contains the name of shared library file.
10254        ///
10255        /// Example:
10256        /// ```sql
10257        /// CREATE FUNCTION cas_in(input cstring) RETURNS cas
10258        /// AS 'MODULE_PATHNAME', 'cas_in_wrapper'
10259        /// ```
10260        /// [PostgreSQL]: https://www.postgresql.org/docs/current/sql-createfunction.html
10261        link_symbol: Option<Expr>,
10262    },
10263    /// A function body expression using the 'AS' keyword and shows up
10264    /// after any `OPTIONS` clause.
10265    ///
10266    /// Example:
10267    /// ```sql
10268    /// CREATE FUNCTION myfunc(x FLOAT64, y FLOAT64) RETURNS FLOAT64
10269    /// OPTIONS(description="desc")
10270    /// AS (x * y);
10271    /// ```
10272    ///
10273    /// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#syntax_11
10274    AsAfterOptions(Expr),
10275    /// Function body with statements before the `RETURN` keyword.
10276    ///
10277    /// Example:
10278    /// ```sql
10279    /// CREATE FUNCTION my_scalar_udf(a INT, b INT)
10280    /// RETURNS INT
10281    /// AS
10282    /// BEGIN
10283    ///     DECLARE c INT;
10284    ///     SET c = a + b;
10285    ///     RETURN c;
10286    /// END
10287    /// ```
10288    ///
10289    /// [MsSql]: https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql
10290    AsBeginEnd(BeginEndStatements),
10291    /// Function body expression using the 'RETURN' keyword.
10292    ///
10293    /// Example:
10294    /// ```sql
10295    /// CREATE FUNCTION myfunc(a INTEGER, IN b INTEGER = 1) RETURNS INTEGER
10296    /// LANGUAGE SQL
10297    /// RETURN a + b;
10298    /// ```
10299    ///
10300    /// [PostgreSQL]: https://www.postgresql.org/docs/current/sql-createfunction.html
10301    Return(Expr),
10302
10303    /// Function body expression using the 'AS RETURN' keywords
10304    ///
10305    /// Example:
10306    /// ```sql
10307    /// CREATE FUNCTION myfunc(a INT, b INT)
10308    /// RETURNS TABLE
10309    /// AS RETURN (SELECT a + b AS sum);
10310    /// ```
10311    ///
10312    /// [MsSql]: https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql
10313    AsReturnExpr(Expr),
10314
10315    /// Function body expression using the 'AS RETURN' keywords, with an un-parenthesized SELECT query
10316    ///
10317    /// Example:
10318    /// ```sql
10319    /// CREATE FUNCTION myfunc(a INT, b INT)
10320    /// RETURNS TABLE
10321    /// AS RETURN SELECT a + b AS sum;
10322    /// ```
10323    ///
10324    /// [MsSql]: https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql?view=sql-server-ver16#select_stmt
10325    AsReturnSelect(Select),
10326}
10327
10328#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10329#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10330#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10331/// `USING` clause options for `CREATE FUNCTION` (e.g., JAR, FILE, ARCHIVE).
10332pub enum CreateFunctionUsing {
10333    /// Use a JAR file located at the given URI.
10334    Jar(String),
10335    /// Use a file located at the given URI.
10336    File(String),
10337    /// Use an archive located at the given URI.
10338    Archive(String),
10339}
10340
10341impl fmt::Display for CreateFunctionUsing {
10342    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10343        write!(f, "USING ")?;
10344        match self {
10345            CreateFunctionUsing::Jar(uri) => write!(f, "JAR '{uri}'"),
10346            CreateFunctionUsing::File(uri) => write!(f, "FILE '{uri}'"),
10347            CreateFunctionUsing::Archive(uri) => write!(f, "ARCHIVE '{uri}'"),
10348        }
10349    }
10350}
10351
10352/// `NAME = <EXPR>` arguments for DuckDB macros
10353///
10354/// See [Create Macro - DuckDB](https://duckdb.org/docs/sql/statements/create_macro)
10355/// for more details
10356#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10357#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10358#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10359pub struct MacroArg {
10360    /// The argument name.
10361    pub name: Ident,
10362    /// Optional default expression for the argument.
10363    pub default_expr: Option<Expr>,
10364}
10365
10366impl MacroArg {
10367    /// Returns an argument with name.
10368    pub fn new(name: &str) -> Self {
10369        Self {
10370            name: name.into(),
10371            default_expr: None,
10372        }
10373    }
10374}
10375
10376impl fmt::Display for MacroArg {
10377    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10378        write!(f, "{}", self.name)?;
10379        if let Some(default_expr) = &self.default_expr {
10380            write!(f, " := {default_expr}")?;
10381        }
10382        Ok(())
10383    }
10384}
10385
10386#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10387#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10388#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10389/// Definition for a DuckDB macro: either an expression or a table-producing query.
10390pub enum MacroDefinition {
10391    /// The macro is defined as an expression.
10392    Expr(Expr),
10393    /// The macro is defined as a table (query).
10394    Table(Box<Query>),
10395}
10396
10397impl fmt::Display for MacroDefinition {
10398    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10399        match self {
10400            MacroDefinition::Expr(expr) => write!(f, "{expr}")?,
10401            MacroDefinition::Table(query) => write!(f, "{query}")?,
10402        }
10403        Ok(())
10404    }
10405}
10406
10407/// Schema possible naming variants ([1]).
10408///
10409/// [1]: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#schema-definition
10410#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10411#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10412#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10413pub enum SchemaName {
10414    /// Only schema name specified: `<schema name>`.
10415    Simple(ObjectName),
10416    /// Only authorization identifier specified: `AUTHORIZATION <schema authorization identifier>`.
10417    UnnamedAuthorization(Ident),
10418    /// Both schema name and authorization identifier specified: `<schema name>  AUTHORIZATION <schema authorization identifier>`.
10419    NamedAuthorization(ObjectName, Ident),
10420}
10421
10422impl fmt::Display for SchemaName {
10423    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10424        match self {
10425            SchemaName::Simple(name) => {
10426                write!(f, "{name}")
10427            }
10428            SchemaName::UnnamedAuthorization(authorization) => {
10429                write!(f, "AUTHORIZATION {authorization}")
10430            }
10431            SchemaName::NamedAuthorization(name, authorization) => {
10432                write!(f, "{name} AUTHORIZATION {authorization}")
10433            }
10434        }
10435    }
10436}
10437
10438/// Fulltext search modifiers ([1]).
10439///
10440/// [1]: https://dev.mysql.com/doc/refman/8.0/en/fulltext-search.html#function_match
10441#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10442#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10443#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10444pub enum SearchModifier {
10445    /// `IN NATURAL LANGUAGE MODE`.
10446    InNaturalLanguageMode,
10447    /// `IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION`.
10448    InNaturalLanguageModeWithQueryExpansion,
10449    ///`IN BOOLEAN MODE`.
10450    InBooleanMode,
10451    ///`WITH QUERY EXPANSION`.
10452    WithQueryExpansion,
10453}
10454
10455impl fmt::Display for SearchModifier {
10456    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10457        match self {
10458            Self::InNaturalLanguageMode => {
10459                write!(f, "IN NATURAL LANGUAGE MODE")?;
10460            }
10461            Self::InNaturalLanguageModeWithQueryExpansion => {
10462                write!(f, "IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION")?;
10463            }
10464            Self::InBooleanMode => {
10465                write!(f, "IN BOOLEAN MODE")?;
10466            }
10467            Self::WithQueryExpansion => {
10468                write!(f, "WITH QUERY EXPANSION")?;
10469            }
10470        }
10471
10472        Ok(())
10473    }
10474}
10475
10476/// Represents a `LOCK TABLE` clause with optional alias and lock type.
10477#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10478#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10479#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10480pub struct LockTable {
10481    /// The table identifier to lock.
10482    pub table: Ident,
10483    /// Optional alias for the table.
10484    pub alias: Option<Ident>,
10485    /// The type of lock to apply to the table.
10486    pub lock_type: LockTableType,
10487}
10488
10489impl fmt::Display for LockTable {
10490    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10491        let Self {
10492            table: tbl_name,
10493            alias,
10494            lock_type,
10495        } = self;
10496
10497        write!(f, "{tbl_name} ")?;
10498        if let Some(alias) = alias {
10499            write!(f, "AS {alias} ")?;
10500        }
10501        write!(f, "{lock_type}")?;
10502        Ok(())
10503    }
10504}
10505
10506#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10507#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10508#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10509/// The type of lock used in `LOCK TABLE` statements.
10510pub enum LockTableType {
10511    /// Shared/read lock. If `local` is true, it's a local read lock.
10512    Read {
10513        /// Whether the read lock is local.
10514        local: bool,
10515    },
10516    /// Exclusive/write lock. If `low_priority` is true, the write is low priority.
10517    Write {
10518        /// Whether the write lock is low priority.
10519        low_priority: bool,
10520    },
10521}
10522
10523impl fmt::Display for LockTableType {
10524    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10525        match self {
10526            Self::Read { local } => {
10527                write!(f, "READ")?;
10528                if *local {
10529                    write!(f, " LOCAL")?;
10530                }
10531            }
10532            Self::Write { low_priority } => {
10533                if *low_priority {
10534                    write!(f, "LOW_PRIORITY ")?;
10535                }
10536                write!(f, "WRITE")?;
10537            }
10538        }
10539
10540        Ok(())
10541    }
10542}
10543
10544#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10545#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10546#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10547/// Hive-specific `SET LOCATION` helper used in some `LOAD DATA` statements.
10548pub struct HiveSetLocation {
10549    /// Whether the `SET` keyword was present.
10550    pub has_set: bool,
10551    /// The location identifier.
10552    pub location: Ident,
10553}
10554
10555impl fmt::Display for HiveSetLocation {
10556    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10557        if self.has_set {
10558            write!(f, "SET ")?;
10559        }
10560        write!(f, "LOCATION {}", self.location)
10561    }
10562}
10563
10564/// MySQL `ALTER TABLE` only  [FIRST | AFTER column_name]
10565#[allow(clippy::large_enum_variant)]
10566#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10567#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10568#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10569/// MySQL `ALTER TABLE` column position specifier: `FIRST` or `AFTER <column>`.
10570pub enum MySQLColumnPosition {
10571    /// Place the column first in the table.
10572    First,
10573    /// Place the column after the specified identifier.
10574    After(Ident),
10575}
10576
10577impl Display for MySQLColumnPosition {
10578    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10579        match self {
10580            MySQLColumnPosition::First => write!(f, "FIRST"),
10581            MySQLColumnPosition::After(ident) => {
10582                let column_name = &ident.value;
10583                write!(f, "AFTER {column_name}")
10584            }
10585        }
10586    }
10587}
10588
10589/// MySQL `CREATE VIEW` algorithm parameter: [ALGORITHM = {UNDEFINED | MERGE | TEMPTABLE}]
10590#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10591#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10592#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10593/// MySQL `CREATE VIEW` algorithm options.
10594pub enum CreateViewAlgorithm {
10595    /// `UNDEFINED` algorithm.
10596    Undefined,
10597    /// `MERGE` algorithm.
10598    Merge,
10599    /// `TEMPTABLE` algorithm.
10600    TempTable,
10601}
10602
10603impl Display for CreateViewAlgorithm {
10604    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10605        match self {
10606            CreateViewAlgorithm::Undefined => write!(f, "UNDEFINED"),
10607            CreateViewAlgorithm::Merge => write!(f, "MERGE"),
10608            CreateViewAlgorithm::TempTable => write!(f, "TEMPTABLE"),
10609        }
10610    }
10611}
10612/// MySQL `CREATE VIEW` security parameter: [SQL SECURITY { DEFINER | INVOKER }]
10613#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10614#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10615#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10616/// MySQL `CREATE VIEW` SQL SECURITY options.
10617pub enum CreateViewSecurity {
10618    /// The view runs with the privileges of the definer.
10619    Definer,
10620    /// The view runs with the privileges of the invoker.
10621    Invoker,
10622}
10623
10624impl Display for CreateViewSecurity {
10625    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10626        match self {
10627            CreateViewSecurity::Definer => write!(f, "DEFINER"),
10628            CreateViewSecurity::Invoker => write!(f, "INVOKER"),
10629        }
10630    }
10631}
10632
10633/// [MySQL] `CREATE VIEW` additional parameters
10634///
10635/// [MySQL]: https://dev.mysql.com/doc/refman/9.1/en/create-view.html
10636#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10637#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10638#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10639pub struct CreateViewParams {
10640    /// Optional view algorithm (e.g., MERGE, TEMPTABLE).
10641    pub algorithm: Option<CreateViewAlgorithm>,
10642    /// Optional definer (the security principal that will own the view).
10643    pub definer: Option<GranteeName>,
10644    /// Optional SQL SECURITY setting for the view.
10645    pub security: Option<CreateViewSecurity>,
10646}
10647
10648impl Display for CreateViewParams {
10649    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10650        let CreateViewParams {
10651            algorithm,
10652            definer,
10653            security,
10654        } = self;
10655        if let Some(algorithm) = algorithm {
10656            write!(f, "ALGORITHM = {algorithm} ")?;
10657        }
10658        if let Some(definers) = definer {
10659            write!(f, "DEFINER = {definers} ")?;
10660        }
10661        if let Some(security) = security {
10662            write!(f, "SQL SECURITY {security} ")?;
10663        }
10664        Ok(())
10665    }
10666}
10667
10668#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10669#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10670#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10671/// Key/Value, where the value is a (optionally named) list of identifiers
10672///
10673/// ```sql
10674/// UNION = (tbl_name[,tbl_name]...)
10675/// ENGINE = ReplicatedMergeTree('/table_name','{replica}', ver)
10676/// ENGINE = SummingMergeTree([columns])
10677/// ```
10678pub struct NamedParenthesizedList {
10679    /// The option key (identifier) for this named list.
10680    pub key: Ident,
10681    /// Optional secondary name associated with the key.
10682    pub name: Option<Ident>,
10683    /// The list of identifier values for the key.
10684    pub values: Vec<Ident>,
10685}
10686
10687/// Snowflake `WITH ROW ACCESS POLICY policy_name ON (identifier, ...)`
10688///
10689/// <https://docs.snowflake.com/en/sql-reference/sql/create-table>
10690/// <https://docs.snowflake.com/en/user-guide/security-row-intro>
10691#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10692#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10693#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10694pub struct RowAccessPolicy {
10695    /// The fully-qualified policy object name.
10696    pub policy: ObjectName,
10697    /// Identifiers for the columns or objects the policy applies to.
10698    pub on: Vec<Ident>,
10699}
10700
10701impl RowAccessPolicy {
10702    /// Create a new `RowAccessPolicy` for the given `policy` and `on` identifiers.
10703    pub fn new(policy: ObjectName, on: Vec<Ident>) -> Self {
10704        Self { policy, on }
10705    }
10706}
10707
10708impl Display for RowAccessPolicy {
10709    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10710        write!(
10711            f,
10712            "WITH ROW ACCESS POLICY {} ON ({})",
10713            self.policy,
10714            display_comma_separated(self.on.as_slice())
10715        )
10716    }
10717}
10718
10719/// Snowflake `[ WITH ] STORAGE LIFECYCLE POLICY <policy_name> ON ( <col_name> [ , ... ] )`
10720///
10721/// <https://docs.snowflake.com/en/sql-reference/sql/create-table>
10722#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10723#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10724#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10725pub struct StorageLifecyclePolicy {
10726    /// The fully-qualified policy object name.
10727    pub policy: ObjectName,
10728    /// Column names the policy applies to.
10729    pub on: Vec<Ident>,
10730}
10731
10732impl Display for StorageLifecyclePolicy {
10733    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10734        write!(
10735            f,
10736            "WITH STORAGE LIFECYCLE POLICY {} ON ({})",
10737            self.policy,
10738            display_comma_separated(self.on.as_slice())
10739        )
10740    }
10741}
10742
10743/// Snowflake `WITH TAG ( tag_name = '<tag_value>', ...)`
10744///
10745/// <https://docs.snowflake.com/en/sql-reference/sql/create-table>
10746#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10747#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10748#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10749pub struct Tag {
10750    /// The tag key (can be qualified).
10751    pub key: ObjectName,
10752    /// The tag value as a string.
10753    pub value: String,
10754}
10755
10756impl Tag {
10757    /// Create a new `Tag` with the given key and value.
10758    pub fn new(key: ObjectName, value: String) -> Self {
10759        Self { key, value }
10760    }
10761}
10762
10763impl Display for Tag {
10764    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10765        write!(f, "{}='{}'", self.key, self.value)
10766    }
10767}
10768
10769/// Snowflake `WITH CONTACT ( purpose = contact [ , purpose = contact ...] )`
10770///
10771/// <https://docs.snowflake.com/en/sql-reference/sql/create-database>
10772#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10773#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10774#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10775pub struct ContactEntry {
10776    /// The purpose label for the contact entry.
10777    pub purpose: String,
10778    /// The contact information associated with the purpose.
10779    pub contact: String,
10780}
10781
10782impl Display for ContactEntry {
10783    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10784        write!(f, "{} = {}", self.purpose, self.contact)
10785    }
10786}
10787
10788/// Helper to indicate if a comment includes the `=` in the display form
10789#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10790#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10791#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10792pub enum CommentDef {
10793    /// Includes `=` when printing the comment, as `COMMENT = 'comment'`
10794    /// Does not include `=` when printing the comment, as `COMMENT 'comment'`
10795    WithEq(String),
10796    /// Comment variant that omits the `=` when displayed.
10797    WithoutEq(String),
10798}
10799
10800impl Display for CommentDef {
10801    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10802        match self {
10803            CommentDef::WithEq(comment) | CommentDef::WithoutEq(comment) => write!(f, "{comment}"),
10804        }
10805    }
10806}
10807
10808/// Helper to indicate if a collection should be wrapped by a symbol in the display form
10809///
10810/// [`Display`] is implemented for every [`Vec<T>`] where `T: Display`.
10811/// The string output is a comma separated list for the vec items
10812///
10813/// # Examples
10814/// ```
10815/// # use sqlparser::ast::WrappedCollection;
10816/// let items = WrappedCollection::Parentheses(vec!["one", "two", "three"]);
10817/// assert_eq!("(one, two, three)", items.to_string());
10818///
10819/// let items = WrappedCollection::NoWrapping(vec!["one", "two", "three"]);
10820/// assert_eq!("one, two, three", items.to_string());
10821/// ```
10822#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10823#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10824#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10825pub enum WrappedCollection<T> {
10826    /// Print the collection without wrapping symbols, as `item, item, item`
10827    NoWrapping(T),
10828    /// Wraps the collection in Parentheses, as `(item, item, item)`
10829    Parentheses(T),
10830}
10831
10832impl<T> Display for WrappedCollection<Vec<T>>
10833where
10834    T: Display,
10835{
10836    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10837        match self {
10838            WrappedCollection::NoWrapping(inner) => {
10839                write!(f, "{}", display_comma_separated(inner.as_slice()))
10840            }
10841            WrappedCollection::Parentheses(inner) => {
10842                write!(f, "({})", display_comma_separated(inner.as_slice()))
10843            }
10844        }
10845    }
10846}
10847
10848/// Represents a single PostgreSQL utility option.
10849///
10850/// A utility option is a key-value pair where the key is an identifier (IDENT) and the value
10851/// can be one of the following:
10852/// - A number with an optional sign (`+` or `-`). Example: `+10`, `-10.2`, `3`
10853/// - A non-keyword string. Example: `option1`, `'option2'`, `"option3"`
10854/// - keyword: `TRUE`, `FALSE`, `ON` (`off` is also accept).
10855/// - Empty. Example: `ANALYZE` (identifier only)
10856///
10857/// Utility options are used in various PostgreSQL DDL statements, including statements such as
10858/// `CLUSTER`, `EXPLAIN`, `VACUUM`, and `REINDEX`. These statements format options as `( option [, ...] )`.
10859///
10860/// [CLUSTER](https://www.postgresql.org/docs/current/sql-cluster.html)
10861/// [EXPLAIN](https://www.postgresql.org/docs/current/sql-explain.html)
10862/// [VACUUM](https://www.postgresql.org/docs/current/sql-vacuum.html)
10863/// [REINDEX](https://www.postgresql.org/docs/current/sql-reindex.html)
10864///
10865/// For example, the `EXPLAIN` AND `VACUUM` statements with options might look like this:
10866/// ```sql
10867/// EXPLAIN (ANALYZE, VERBOSE TRUE, FORMAT TEXT) SELECT * FROM my_table;
10868///
10869/// VACUUM (VERBOSE, ANALYZE ON, PARALLEL 10) my_table;
10870/// ```
10871#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10872#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10873#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10874pub struct UtilityOption {
10875    /// The option name (identifier).
10876    pub name: Ident,
10877    /// Optional argument for the option (number, string, keyword, etc.).
10878    pub arg: Option<Expr>,
10879}
10880
10881impl Display for UtilityOption {
10882    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10883        if let Some(ref arg) = self.arg {
10884            write!(f, "{} {}", self.name, arg)
10885        } else {
10886            write!(f, "{}", self.name)
10887        }
10888    }
10889}
10890
10891/// Represents the different options available for `SHOW`
10892/// statements to filter the results. Example from Snowflake:
10893/// <https://docs.snowflake.com/en/sql-reference/sql/show-tables>
10894#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10895#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10896#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10897pub struct ShowStatementOptions {
10898    /// Optional scope to show in (for example: TABLE, SCHEMA).
10899    pub show_in: Option<ShowStatementIn>,
10900    /// Optional `STARTS WITH` filter value.
10901    pub starts_with: Option<ValueWithSpan>,
10902    /// Optional `LIMIT` expression.
10903    pub limit: Option<Expr>,
10904    /// Optional `FROM` value used with `LIMIT`.
10905    pub limit_from: Option<ValueWithSpan>,
10906    /// Optional filter position (infix or suffix) for `LIKE`/`FILTER`.
10907    pub filter_position: Option<ShowStatementFilterPosition>,
10908}
10909
10910impl Display for ShowStatementOptions {
10911    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10912        let (like_in_infix, like_in_suffix) = match &self.filter_position {
10913            Some(ShowStatementFilterPosition::Infix(filter)) => {
10914                (format!(" {filter}"), "".to_string())
10915            }
10916            Some(ShowStatementFilterPosition::Suffix(filter)) => {
10917                ("".to_string(), format!(" {filter}"))
10918            }
10919            None => ("".to_string(), "".to_string()),
10920        };
10921        write!(
10922            f,
10923            "{like_in_infix}{show_in}{starts_with}{limit}{from}{like_in_suffix}",
10924            show_in = match &self.show_in {
10925                Some(i) => format!(" {i}"),
10926                None => String::new(),
10927            },
10928            starts_with = match &self.starts_with {
10929                Some(s) => format!(" STARTS WITH {s}"),
10930                None => String::new(),
10931            },
10932            limit = match &self.limit {
10933                Some(l) => format!(" LIMIT {l}"),
10934                None => String::new(),
10935            },
10936            from = match &self.limit_from {
10937                Some(f) => format!(" FROM {f}"),
10938                None => String::new(),
10939            }
10940        )?;
10941        Ok(())
10942    }
10943}
10944
10945#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10946#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10947#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10948/// Where a `SHOW` filter appears relative to the main clause.
10949pub enum ShowStatementFilterPosition {
10950    /// Put the filter in an infix position (e.g. `SHOW COLUMNS LIKE '%name%' IN TABLE tbl`).
10951    Infix(ShowStatementFilter), // For example: SHOW COLUMNS LIKE '%name%' IN TABLE tbl
10952    /// Put the filter in a suffix position (e.g. `SHOW COLUMNS IN tbl LIKE '%name%'`).
10953    Suffix(ShowStatementFilter), // For example: SHOW COLUMNS IN tbl LIKE '%name%'
10954}
10955
10956#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10957#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10958#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10959/// Parent object types usable with `SHOW ... IN <parent>` clauses.
10960pub enum ShowStatementInParentType {
10961    /// ACCOUNT parent type for SHOW statements.
10962    Account,
10963    /// DATABASE parent type for SHOW statements.
10964    Database,
10965    /// SCHEMA parent type for SHOW statements.
10966    Schema,
10967    /// TABLE parent type for SHOW statements.
10968    Table,
10969    /// VIEW parent type for SHOW statements.
10970    View,
10971}
10972
10973impl fmt::Display for ShowStatementInParentType {
10974    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10975        match self {
10976            ShowStatementInParentType::Account => write!(f, "ACCOUNT"),
10977            ShowStatementInParentType::Database => write!(f, "DATABASE"),
10978            ShowStatementInParentType::Schema => write!(f, "SCHEMA"),
10979            ShowStatementInParentType::Table => write!(f, "TABLE"),
10980            ShowStatementInParentType::View => write!(f, "VIEW"),
10981        }
10982    }
10983}
10984
10985#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10986#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10987#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10988/// Represents a `SHOW ... IN` clause with optional parent qualifier and name.
10989pub struct ShowStatementIn {
10990    /// The clause that specifies what to show (e.g. COLUMNS, TABLES).
10991    pub clause: ShowStatementInClause,
10992    /// Optional parent type qualifier (ACCOUNT/DATABASE/...).
10993    pub parent_type: Option<ShowStatementInParentType>,
10994    /// Optional parent object name for the SHOW clause.
10995    #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
10996    pub parent_name: Option<ObjectName>,
10997}
10998
10999impl fmt::Display for ShowStatementIn {
11000    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11001        write!(f, "{}", self.clause)?;
11002        if let Some(parent_type) = &self.parent_type {
11003            write!(f, " {parent_type}")?;
11004        }
11005        if let Some(parent_name) = &self.parent_name {
11006            write!(f, " {parent_name}")?;
11007        }
11008        Ok(())
11009    }
11010}
11011
11012/// A Show Charset statement
11013#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11014#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11015#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11016pub struct ShowCharset {
11017    /// The statement can be written as `SHOW CHARSET` or `SHOW CHARACTER SET`
11018    /// true means CHARSET was used and false means CHARACTER SET was used
11019    pub is_shorthand: bool,
11020    /// Optional `LIKE`/`WHERE`-style filter for the statement.
11021    pub filter: Option<ShowStatementFilter>,
11022}
11023
11024impl fmt::Display for ShowCharset {
11025    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11026        write!(f, "SHOW")?;
11027        if self.is_shorthand {
11028            write!(f, " CHARSET")?;
11029        } else {
11030            write!(f, " CHARACTER SET")?;
11031        }
11032        if let Some(filter) = &self.filter {
11033            write!(f, " {filter}")?;
11034        }
11035        Ok(())
11036    }
11037}
11038
11039#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11040#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11041#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11042/// Options for a `SHOW OBJECTS` statement.
11043pub struct ShowObjects {
11044    /// Whether to show terse output.
11045    pub terse: bool,
11046    /// Additional options controlling the SHOW output.
11047    pub show_options: ShowStatementOptions,
11048}
11049
11050/// MSSQL's json null clause
11051///
11052/// ```plaintext
11053/// <json_null_clause> ::=
11054///       NULL ON NULL
11055///     | ABSENT ON NULL
11056/// ```
11057///
11058/// <https://learn.microsoft.com/en-us/sql/t-sql/functions/json-object-transact-sql?view=sql-server-ver16#json_null_clause>
11059#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11060#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11061#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11062pub enum JsonNullClause {
11063    /// `NULL ON NULL` behavior for JSON functions.
11064    NullOnNull,
11065    /// `ABSENT ON NULL` behavior for JSON functions.
11066    AbsentOnNull,
11067}
11068
11069impl Display for JsonNullClause {
11070    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
11071        match self {
11072            JsonNullClause::NullOnNull => write!(f, "NULL ON NULL"),
11073            JsonNullClause::AbsentOnNull => write!(f, "ABSENT ON NULL"),
11074        }
11075    }
11076}
11077
11078/// PostgreSQL JSON function RETURNING clause
11079///
11080/// Example:
11081/// ```sql
11082/// JSON_OBJECT('a': 1 RETURNING jsonb)
11083/// ```
11084#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11085#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11086#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11087pub struct JsonReturningClause {
11088    /// The data type to return from the JSON function (e.g. JSON/JSONB).
11089    pub data_type: DataType,
11090}
11091
11092impl Display for JsonReturningClause {
11093    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
11094        write!(f, "RETURNING {}", self.data_type)
11095    }
11096}
11097
11098/// rename object definition
11099#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11100#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11101#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11102pub struct RenameTable {
11103    /// The current name of the object to rename.
11104    pub old_name: ObjectName,
11105    /// The new name for the object.
11106    pub new_name: ObjectName,
11107}
11108
11109impl fmt::Display for RenameTable {
11110    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11111        write!(f, "{} TO {}", self.old_name, self.new_name)?;
11112        Ok(())
11113    }
11114}
11115
11116/// Represents the referenced table in an `INSERT INTO` statement
11117#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11118#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11119#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11120pub enum TableObject {
11121    /// Table specified by name.
11122    /// Example:
11123    /// ```sql
11124    /// INSERT INTO my_table
11125    /// ```
11126    TableName(#[cfg_attr(feature = "visitor", visit(with = "visit_relation"))] ObjectName),
11127
11128    /// Table specified as a function.
11129    /// Example:
11130    /// ```sql
11131    /// INSERT INTO TABLE FUNCTION remote('localhost', default.simple_table)
11132    /// ```
11133    /// [Clickhouse](https://clickhouse.com/docs/en/sql-reference/table-functions)
11134    TableFunction(Function),
11135
11136    /// Table specified through a sub-query
11137    /// Example:
11138    /// ```sql
11139    /// INSERT INTO
11140    /// (SELECT employee_id, last_name, email, hire_date, job_id,  salary, commission_pct FROM employees)
11141    /// VALUES (207, 'Gregory', 'pgregory@example.com', sysdate, 'PU_CLERK', 1.2E3, NULL);
11142    /// ```
11143    /// [Oracle](https://docs.oracle.com/en/database/oracle/oracle-database/21/sqlrf/INSERT.html#GUID-903F8043-0254-4EE9-ACC1-CB8AC0AF3423__I2126242)
11144    TableQuery(Box<Query>),
11145}
11146
11147impl fmt::Display for TableObject {
11148    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11149        match self {
11150            Self::TableName(table_name) => write!(f, "{table_name}"),
11151            Self::TableFunction(func) => write!(f, "FUNCTION {func}"),
11152            Self::TableQuery(table_query) => write!(f, "({table_query})"),
11153        }
11154    }
11155}
11156
11157/// Represents a SET SESSION AUTHORIZATION statement
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 SetSessionAuthorizationParam {
11162    /// The scope for the `SET SESSION AUTHORIZATION` (e.g., GLOBAL/SESSION).
11163    pub scope: ContextModifier,
11164    /// The specific authorization parameter kind.
11165    pub kind: SetSessionAuthorizationParamKind,
11166}
11167
11168impl fmt::Display for SetSessionAuthorizationParam {
11169    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11170        write!(f, "{}", self.kind)
11171    }
11172}
11173
11174/// Represents the parameter kind for SET SESSION AUTHORIZATION
11175#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11176#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11177#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11178pub enum SetSessionAuthorizationParamKind {
11179    /// Default authorization
11180    Default,
11181
11182    /// User name
11183    User(Ident),
11184}
11185
11186impl fmt::Display for SetSessionAuthorizationParamKind {
11187    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11188        match self {
11189            SetSessionAuthorizationParamKind::Default => write!(f, "DEFAULT"),
11190            SetSessionAuthorizationParamKind::User(name) => write!(f, "{}", name),
11191        }
11192    }
11193}
11194
11195#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11196#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11197#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11198/// Kind of session parameter being set by `SET SESSION`.
11199pub enum SetSessionParamKind {
11200    /// Generic session parameter (name/value pair).
11201    Generic(SetSessionParamGeneric),
11202    /// Identity insert related parameter.
11203    IdentityInsert(SetSessionParamIdentityInsert),
11204    /// Offsets-related parameter.
11205    Offsets(SetSessionParamOffsets),
11206    /// Statistics-related parameter.
11207    Statistics(SetSessionParamStatistics),
11208}
11209
11210impl fmt::Display for SetSessionParamKind {
11211    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11212        match self {
11213            SetSessionParamKind::Generic(x) => write!(f, "{x}"),
11214            SetSessionParamKind::IdentityInsert(x) => write!(f, "{x}"),
11215            SetSessionParamKind::Offsets(x) => write!(f, "{x}"),
11216            SetSessionParamKind::Statistics(x) => write!(f, "{x}"),
11217        }
11218    }
11219}
11220
11221#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11222#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11223#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11224/// Generic `SET SESSION` parameter represented as name(s) and value.
11225pub struct SetSessionParamGeneric {
11226    /// Names of the session parameters being set.
11227    pub names: Vec<String>,
11228    /// The value to assign to the parameter(s).
11229    pub value: String,
11230}
11231
11232impl fmt::Display for SetSessionParamGeneric {
11233    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11234        write!(f, "{} {}", display_comma_separated(&self.names), self.value)
11235    }
11236}
11237
11238#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11239#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11240#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11241/// `IDENTITY_INSERT` session parameter for a specific object.
11242pub struct SetSessionParamIdentityInsert {
11243    /// Object name targeted by `IDENTITY_INSERT`.
11244    pub obj: ObjectName,
11245    /// Value (ON/OFF) for the identity insert setting.
11246    pub value: SessionParamValue,
11247}
11248
11249impl fmt::Display for SetSessionParamIdentityInsert {
11250    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11251        write!(f, "IDENTITY_INSERT {} {}", self.obj, self.value)
11252    }
11253}
11254
11255#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11256#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11257#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11258/// Offsets-related session parameter with keywords and a value.
11259pub struct SetSessionParamOffsets {
11260    /// Keywords specifying which offsets to modify.
11261    pub keywords: Vec<String>,
11262    /// Value (ON/OFF) for the offsets setting.
11263    pub value: SessionParamValue,
11264}
11265
11266impl fmt::Display for SetSessionParamOffsets {
11267    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11268        write!(
11269            f,
11270            "OFFSETS {} {}",
11271            display_comma_separated(&self.keywords),
11272            self.value
11273        )
11274    }
11275}
11276
11277#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11278#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11279#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11280/// Statistics-related session parameter specifying topic and value.
11281pub struct SetSessionParamStatistics {
11282    /// Statistics topic to set (IO/PROFILE/TIME/XML).
11283    pub topic: SessionParamStatsTopic,
11284    /// Value (ON/OFF) for the statistics topic.
11285    pub value: SessionParamValue,
11286}
11287
11288impl fmt::Display for SetSessionParamStatistics {
11289    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11290        write!(f, "STATISTICS {} {}", self.topic, self.value)
11291    }
11292}
11293
11294#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11295#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11296#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11297/// Topics available for session statistics configuration.
11298pub enum SessionParamStatsTopic {
11299    /// Input/output statistics.
11300    IO,
11301    /// Profile statistics.
11302    Profile,
11303    /// Time statistics.
11304    Time,
11305    /// XML-related statistics.
11306    Xml,
11307}
11308
11309impl fmt::Display for SessionParamStatsTopic {
11310    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11311        match self {
11312            SessionParamStatsTopic::IO => write!(f, "IO"),
11313            SessionParamStatsTopic::Profile => write!(f, "PROFILE"),
11314            SessionParamStatsTopic::Time => write!(f, "TIME"),
11315            SessionParamStatsTopic::Xml => write!(f, "XML"),
11316        }
11317    }
11318}
11319
11320#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11321#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11322#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11323/// Value for a session boolean-like parameter (ON/OFF).
11324pub enum SessionParamValue {
11325    /// Session parameter enabled.
11326    On,
11327    /// Session parameter disabled.
11328    Off,
11329}
11330
11331impl fmt::Display for SessionParamValue {
11332    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11333        match self {
11334            SessionParamValue::On => write!(f, "ON"),
11335            SessionParamValue::Off => write!(f, "OFF"),
11336        }
11337    }
11338}
11339
11340/// Snowflake StorageSerializationPolicy for Iceberg Tables
11341/// ```sql
11342/// [ STORAGE_SERIALIZATION_POLICY = { COMPATIBLE | OPTIMIZED } ]
11343/// ```
11344///
11345/// <https://docs.snowflake.com/en/sql-reference/sql/create-iceberg-table>
11346#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11347#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11348#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11349pub enum StorageSerializationPolicy {
11350    /// Use compatible serialization mode.
11351    Compatible,
11352    /// Use optimized serialization mode.
11353    Optimized,
11354}
11355
11356impl Display for StorageSerializationPolicy {
11357    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
11358        match self {
11359            StorageSerializationPolicy::Compatible => write!(f, "COMPATIBLE"),
11360            StorageSerializationPolicy::Optimized => write!(f, "OPTIMIZED"),
11361        }
11362    }
11363}
11364
11365/// Snowflake CatalogSyncNamespaceMode
11366/// ```sql
11367/// [ CATALOG_SYNC_NAMESPACE_MODE = { NEST | FLATTEN } ]
11368/// ```
11369///
11370/// <https://docs.snowflake.com/en/sql-reference/sql/create-database>
11371#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11372#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11373#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11374pub enum CatalogSyncNamespaceMode {
11375    /// Nest namespaces when syncing catalog.
11376    Nest,
11377    /// Flatten namespaces when syncing catalog.
11378    Flatten,
11379}
11380
11381impl Display for CatalogSyncNamespaceMode {
11382    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
11383        match self {
11384            CatalogSyncNamespaceMode::Nest => write!(f, "NEST"),
11385            CatalogSyncNamespaceMode::Flatten => write!(f, "FLATTEN"),
11386        }
11387    }
11388}
11389
11390/// Variants of the Snowflake `COPY INTO` statement
11391#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11392#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11393#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11394pub enum CopyIntoSnowflakeKind {
11395    /// Loads data from files to a table
11396    /// See: <https://docs.snowflake.com/en/sql-reference/sql/copy-into-table>
11397    Table,
11398    /// Unloads data from a table or query to external files
11399    /// See: <https://docs.snowflake.com/en/sql-reference/sql/copy-into-location>
11400    Location,
11401}
11402
11403#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11404#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11405#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11406/// `PRINT` statement for producing debug/output messages.
11407pub struct PrintStatement {
11408    /// The expression producing the message to print.
11409    pub message: Box<Expr>,
11410}
11411
11412impl fmt::Display for PrintStatement {
11413    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11414        write!(f, "PRINT {}", self.message)
11415    }
11416}
11417
11418/// The type of `WAITFOR` statement (MSSQL).
11419///
11420/// See: <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/waitfor-transact-sql>
11421#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11422#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11423#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11424pub enum WaitForType {
11425    /// `WAITFOR DELAY 'time_to_pass'`
11426    Delay,
11427    /// `WAITFOR TIME 'time_to_execute'`
11428    Time,
11429}
11430
11431impl fmt::Display for WaitForType {
11432    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11433        match self {
11434            WaitForType::Delay => write!(f, "DELAY"),
11435            WaitForType::Time => write!(f, "TIME"),
11436        }
11437    }
11438}
11439
11440/// MSSQL `WAITFOR` statement.
11441///
11442/// See: <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/waitfor-transact-sql>
11443#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11444#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11445#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11446pub struct WaitForStatement {
11447    /// `DELAY` or `TIME`.
11448    pub wait_type: WaitForType,
11449    /// The time expression.
11450    pub expr: Expr,
11451}
11452
11453impl fmt::Display for WaitForStatement {
11454    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11455        write!(f, "WAITFOR {} {}", self.wait_type, self.expr)
11456    }
11457}
11458
11459/// Represents a `Return` statement.
11460///
11461/// [MsSql triggers](https://learn.microsoft.com/en-us/sql/t-sql/statements/create-trigger-transact-sql)
11462/// [MsSql functions](https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql)
11463#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11464#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11465#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11466pub struct ReturnStatement {
11467    /// Optional return value expression.
11468    pub value: Option<ReturnStatementValue>,
11469}
11470
11471impl fmt::Display for ReturnStatement {
11472    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11473        match &self.value {
11474            Some(ReturnStatementValue::Expr(expr)) => write!(f, "RETURN {expr}"),
11475            None => write!(f, "RETURN"),
11476        }
11477    }
11478}
11479
11480/// Variants of a `RETURN` statement
11481#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11482#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11483#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11484pub enum ReturnStatementValue {
11485    /// Return an expression from a function or trigger.
11486    Expr(Expr),
11487}
11488
11489/// Represents an `OPEN` statement.
11490#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11491#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11492#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11493pub struct OpenStatement {
11494    /// Cursor name
11495    pub cursor_name: Ident,
11496}
11497
11498impl fmt::Display for OpenStatement {
11499    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11500        write!(f, "OPEN {}", self.cursor_name)
11501    }
11502}
11503
11504/// Specifies Include / Exclude NULL within UNPIVOT command.
11505/// For example
11506/// `UNPIVOT (column1 FOR new_column IN (col3, col4, col5, col6))`
11507#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11508#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11509#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11510pub enum NullInclusion {
11511    /// Include NULL values in the UNPIVOT output.
11512    IncludeNulls,
11513    /// Exclude NULL values from the UNPIVOT output.
11514    ExcludeNulls,
11515}
11516
11517impl fmt::Display for NullInclusion {
11518    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11519        match self {
11520            NullInclusion::IncludeNulls => write!(f, "INCLUDE NULLS"),
11521            NullInclusion::ExcludeNulls => write!(f, "EXCLUDE NULLS"),
11522        }
11523    }
11524}
11525
11526/// Checks membership of a value in a JSON array
11527///
11528/// Syntax:
11529/// ```sql
11530/// <value> MEMBER OF(<array>)
11531/// ```
11532/// [MySQL](https://dev.mysql.com/doc/refman/8.4/en/json-search-functions.html#operator_member-of)
11533#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11534#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11535#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11536pub struct MemberOf {
11537    /// The value to check for membership.
11538    pub value: Box<Expr>,
11539    /// The JSON array expression to check against.
11540    pub array: Box<Expr>,
11541}
11542
11543impl fmt::Display for MemberOf {
11544    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11545        write!(f, "{} MEMBER OF({})", self.value, self.array)
11546    }
11547}
11548
11549#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11550#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11551#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11552/// Represents an `EXPORT DATA` statement.
11553pub struct ExportData {
11554    /// Options for the export operation.
11555    pub options: Vec<SqlOption>,
11556    /// The query producing the data to export.
11557    pub query: Box<Query>,
11558    /// Optional named connection to use for export.
11559    pub connection: Option<ObjectName>,
11560}
11561
11562impl fmt::Display for ExportData {
11563    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11564        if let Some(connection) = &self.connection {
11565            write!(
11566                f,
11567                "EXPORT DATA WITH CONNECTION {connection} OPTIONS({}) AS {}",
11568                display_comma_separated(&self.options),
11569                self.query
11570            )
11571        } else {
11572            write!(
11573                f,
11574                "EXPORT DATA OPTIONS({}) AS {}",
11575                display_comma_separated(&self.options),
11576                self.query
11577            )
11578        }
11579    }
11580}
11581/// Creates a user
11582///
11583/// Syntax:
11584/// ```sql
11585/// CREATE [OR REPLACE] USER [IF NOT EXISTS] <name> [OPTIONS]
11586/// ```
11587///
11588/// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-user)
11589#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11590#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11591#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11592pub struct CreateUser {
11593    /// Replace existing user if present.
11594    pub or_replace: bool,
11595    /// Only create the user if it does not already exist.
11596    pub if_not_exists: bool,
11597    /// The name of the user to create.
11598    pub name: Ident,
11599    /// Key/value options for user creation.
11600    pub options: KeyValueOptions,
11601    /// Whether tags are specified using `WITH TAG`.
11602    pub with_tags: bool,
11603    /// Tags for the user.
11604    pub tags: KeyValueOptions,
11605}
11606
11607impl fmt::Display for CreateUser {
11608    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11609        write!(f, "CREATE")?;
11610        if self.or_replace {
11611            write!(f, " OR REPLACE")?;
11612        }
11613        write!(f, " USER")?;
11614        if self.if_not_exists {
11615            write!(f, " IF NOT EXISTS")?;
11616        }
11617        write!(f, " {}", self.name)?;
11618        if !self.options.options.is_empty() {
11619            write!(f, " {}", self.options)?;
11620        }
11621        if !self.tags.options.is_empty() {
11622            if self.with_tags {
11623                write!(f, " WITH")?;
11624            }
11625            write!(f, " TAG ({})", self.tags)?;
11626        }
11627        Ok(())
11628    }
11629}
11630
11631/// Modifies the properties of a user
11632///
11633/// [Snowflake Syntax:](https://docs.snowflake.com/en/sql-reference/sql/alter-user)
11634/// ```sql
11635/// ALTER USER [ IF EXISTS ] [ <name> ] [ OPTIONS ]
11636/// ```
11637///
11638/// [PostgreSQL Syntax:](https://www.postgresql.org/docs/current/sql-alteruser.html)
11639/// ```sql
11640/// ALTER USER <role_specification> [ WITH ] option [ ... ]
11641/// ```
11642#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11643#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11644#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11645pub struct AlterUser {
11646    /// Whether to only alter the user if it exists.
11647    pub if_exists: bool,
11648    /// The name of the user to alter.
11649    pub name: Ident,
11650    /// Optional new name for the user (Snowflake-specific).
11651    /// See: <https://docs.snowflake.com/en/sql-reference/sql/alter-user#syntax>
11652    pub rename_to: Option<Ident>,
11653    /// Reset the user's password.
11654    pub reset_password: bool,
11655    /// Abort all running queries for the user.
11656    pub abort_all_queries: bool,
11657    /// Optionally add a delegated role authorization.
11658    pub add_role_delegation: Option<AlterUserAddRoleDelegation>,
11659    /// Optionally remove a delegated role authorization.
11660    pub remove_role_delegation: Option<AlterUserRemoveRoleDelegation>,
11661    /// Enroll the user in MFA.
11662    pub enroll_mfa: bool,
11663    /// Set the default MFA method for the user.
11664    pub set_default_mfa_method: Option<MfaMethodKind>,
11665    /// Remove the user's default MFA method.
11666    pub remove_mfa_method: Option<MfaMethodKind>,
11667    /// Modify an MFA method for the user.
11668    pub modify_mfa_method: Option<AlterUserModifyMfaMethod>,
11669    /// Add an MFA OTP method with optional count.
11670    pub add_mfa_method_otp: Option<AlterUserAddMfaMethodOtp>,
11671    /// Set a user policy.
11672    pub set_policy: Option<AlterUserSetPolicy>,
11673    /// Unset a user policy.
11674    pub unset_policy: Option<UserPolicyKind>,
11675    /// Key/value tag options to set on the user.
11676    pub set_tag: KeyValueOptions,
11677    /// Tags to unset on the user.
11678    pub unset_tag: Vec<String>,
11679    /// Key/value properties to set on the user.
11680    pub set_props: KeyValueOptions,
11681    /// Properties to unset on the user.
11682    pub unset_props: Vec<String>,
11683    /// The following options are PostgreSQL-specific: <https://www.postgresql.org/docs/current/sql-alteruser.html>
11684    pub password: Option<AlterUserPassword>,
11685}
11686
11687/// ```sql
11688/// ALTER USER [ IF EXISTS ] [ <name> ] ADD DELEGATED AUTHORIZATION OF ROLE <role_name> TO SECURITY INTEGRATION <integration_name>
11689/// ```
11690#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11691#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11692#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11693pub struct AlterUserAddRoleDelegation {
11694    /// Role name to delegate.
11695    pub role: Ident,
11696    /// Security integration receiving the delegation.
11697    pub integration: Ident,
11698}
11699
11700/// ```sql
11701/// ALTER USER [ IF EXISTS ] [ <name> ] REMOVE DELEGATED { AUTHORIZATION OF ROLE <role_name> | AUTHORIZATIONS } FROM SECURITY INTEGRATION <integration_name>
11702/// ```
11703#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11704#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11705#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11706pub struct AlterUserRemoveRoleDelegation {
11707    /// Optional role name to remove delegation for.
11708    pub role: Option<Ident>,
11709    /// Security integration from which to remove delegation.
11710    pub integration: Ident,
11711}
11712
11713/// ```sql
11714/// ADD MFA METHOD OTP [ COUNT = number ]
11715/// ```
11716#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11717#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11718#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11719pub struct AlterUserAddMfaMethodOtp {
11720    /// Optional OTP count parameter.
11721    pub count: Option<ValueWithSpan>,
11722}
11723
11724/// ```sql
11725/// ALTER USER [ IF EXISTS ] [ <name> ] MODIFY MFA METHOD <mfa_method> SET COMMENT = '<string>'
11726/// ```
11727#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11728#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11729#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11730pub struct AlterUserModifyMfaMethod {
11731    /// The MFA method being modified.
11732    pub method: MfaMethodKind,
11733    /// The new comment for the MFA method.
11734    pub comment: String,
11735}
11736
11737/// Types of MFA methods
11738#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11739#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11740#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11741pub enum MfaMethodKind {
11742    /// PassKey (hardware or platform passkey) MFA method.
11743    PassKey,
11744    /// Time-based One-Time Password (TOTP) MFA method.
11745    Totp,
11746    /// Duo Security MFA method.
11747    Duo,
11748}
11749
11750impl fmt::Display for MfaMethodKind {
11751    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11752        match self {
11753            MfaMethodKind::PassKey => write!(f, "PASSKEY"),
11754            MfaMethodKind::Totp => write!(f, "TOTP"),
11755            MfaMethodKind::Duo => write!(f, "DUO"),
11756        }
11757    }
11758}
11759
11760/// ```sql
11761/// ALTER USER [ IF EXISTS ] [ <name> ] SET { AUTHENTICATION | PASSWORD | SESSION } POLICY <policy_name>
11762/// ```
11763#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11764#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11765#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11766pub struct AlterUserSetPolicy {
11767    /// The kind of user policy being set (authentication/password/session).
11768    pub policy_kind: UserPolicyKind,
11769    /// The identifier of the policy to apply.
11770    pub policy: Ident,
11771}
11772
11773/// Types of user-based policies
11774#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11775#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11776#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11777pub enum UserPolicyKind {
11778    /// Authentication policy.
11779    Authentication,
11780    /// Password policy.
11781    Password,
11782    /// Session policy.
11783    Session,
11784}
11785
11786impl fmt::Display for UserPolicyKind {
11787    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11788        match self {
11789            UserPolicyKind::Authentication => write!(f, "AUTHENTICATION"),
11790            UserPolicyKind::Password => write!(f, "PASSWORD"),
11791            UserPolicyKind::Session => write!(f, "SESSION"),
11792        }
11793    }
11794}
11795
11796impl fmt::Display for AlterUser {
11797    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11798        write!(f, "ALTER")?;
11799        write!(f, " USER")?;
11800        if self.if_exists {
11801            write!(f, " IF EXISTS")?;
11802        }
11803        write!(f, " {}", self.name)?;
11804        if let Some(new_name) = &self.rename_to {
11805            write!(f, " RENAME TO {new_name}")?;
11806        }
11807        if self.reset_password {
11808            write!(f, " RESET PASSWORD")?;
11809        }
11810        if self.abort_all_queries {
11811            write!(f, " ABORT ALL QUERIES")?;
11812        }
11813        if let Some(role_delegation) = &self.add_role_delegation {
11814            let role = &role_delegation.role;
11815            let integration = &role_delegation.integration;
11816            write!(
11817                f,
11818                " ADD DELEGATED AUTHORIZATION OF ROLE {role} TO SECURITY INTEGRATION {integration}"
11819            )?;
11820        }
11821        if let Some(role_delegation) = &self.remove_role_delegation {
11822            write!(f, " REMOVE DELEGATED")?;
11823            match &role_delegation.role {
11824                Some(role) => write!(f, " AUTHORIZATION OF ROLE {role}")?,
11825                None => write!(f, " AUTHORIZATIONS")?,
11826            }
11827            let integration = &role_delegation.integration;
11828            write!(f, " FROM SECURITY INTEGRATION {integration}")?;
11829        }
11830        if self.enroll_mfa {
11831            write!(f, " ENROLL MFA")?;
11832        }
11833        if let Some(method) = &self.set_default_mfa_method {
11834            write!(f, " SET DEFAULT_MFA_METHOD {method}")?
11835        }
11836        if let Some(method) = &self.remove_mfa_method {
11837            write!(f, " REMOVE MFA METHOD {method}")?;
11838        }
11839        if let Some(modify) = &self.modify_mfa_method {
11840            let method = &modify.method;
11841            let comment = &modify.comment;
11842            write!(
11843                f,
11844                " MODIFY MFA METHOD {method} SET COMMENT '{}'",
11845                value::escape_single_quote_string(comment)
11846            )?;
11847        }
11848        if let Some(add_mfa_method_otp) = &self.add_mfa_method_otp {
11849            write!(f, " ADD MFA METHOD OTP")?;
11850            if let Some(count) = &add_mfa_method_otp.count {
11851                write!(f, " COUNT = {count}")?;
11852            }
11853        }
11854        if let Some(policy) = &self.set_policy {
11855            let policy_kind = &policy.policy_kind;
11856            let name = &policy.policy;
11857            write!(f, " SET {policy_kind} POLICY {name}")?;
11858        }
11859        if let Some(policy_kind) = &self.unset_policy {
11860            write!(f, " UNSET {policy_kind} POLICY")?;
11861        }
11862        if !self.set_tag.options.is_empty() {
11863            write!(f, " SET TAG {}", self.set_tag)?;
11864        }
11865        if !self.unset_tag.is_empty() {
11866            write!(f, " UNSET TAG {}", display_comma_separated(&self.unset_tag))?;
11867        }
11868        let has_props = !self.set_props.options.is_empty();
11869        if has_props {
11870            write!(f, " SET")?;
11871            write!(f, " {}", &self.set_props)?;
11872        }
11873        if !self.unset_props.is_empty() {
11874            write!(f, " UNSET {}", display_comma_separated(&self.unset_props))?;
11875        }
11876        if let Some(password) = &self.password {
11877            write!(f, " {}", password)?;
11878        }
11879        Ok(())
11880    }
11881}
11882
11883/// ```sql
11884/// ALTER USER <role_specification> [ WITH ] PASSWORD { 'password' | NULL }``
11885/// ```
11886#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11887#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11888#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11889pub struct AlterUserPassword {
11890    /// Whether the password is encrypted.
11891    pub encrypted: bool,
11892    /// The password string, or `None` for `NULL`.
11893    pub password: Option<String>,
11894}
11895
11896impl Display for AlterUserPassword {
11897    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11898        if self.encrypted {
11899            write!(f, "ENCRYPTED ")?;
11900        }
11901        write!(f, "PASSWORD")?;
11902        match &self.password {
11903            None => write!(f, " NULL")?,
11904            Some(password) => write!(f, " '{}'", value::escape_single_quote_string(password))?,
11905        }
11906        Ok(())
11907    }
11908}
11909
11910/// Specifies how to create a new table based on an existing table's schema.
11911/// '''sql
11912/// CREATE TABLE new LIKE old ...
11913/// '''
11914#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11915#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11916#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11917pub enum CreateTableLikeKind {
11918    /// '''sql
11919    /// CREATE TABLE new (LIKE old ...)
11920    /// '''
11921    /// [Redshift](https://docs.aws.amazon.com/redshift/latest/dg/r_CREATE_TABLE_NEW.html)
11922    Parenthesized(CreateTableLike),
11923    /// '''sql
11924    /// CREATE TABLE new LIKE old ...
11925    /// '''
11926    /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-table#label-create-table-like)
11927    /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_table_like)
11928    Plain(CreateTableLike),
11929}
11930
11931#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11932#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11933#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11934/// Controls whether defaults are included when creating a table FROM/LILE another.
11935pub enum CreateTableLikeDefaults {
11936    /// Include default values from the source table.
11937    Including,
11938    /// Exclude default values from the source table.
11939    Excluding,
11940}
11941
11942impl fmt::Display for CreateTableLikeDefaults {
11943    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11944        match self {
11945            CreateTableLikeDefaults::Including => write!(f, "INCLUDING DEFAULTS"),
11946            CreateTableLikeDefaults::Excluding => write!(f, "EXCLUDING DEFAULTS"),
11947        }
11948    }
11949}
11950
11951#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11952#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11953#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11954/// Represents the `LIKE` clause of a `CREATE TABLE` statement.
11955pub struct CreateTableLike {
11956    /// The source table name to copy the schema from.
11957    pub name: ObjectName,
11958    /// Optional behavior controlling whether defaults are copied.
11959    pub defaults: Option<CreateTableLikeDefaults>,
11960}
11961
11962impl fmt::Display for CreateTableLike {
11963    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11964        write!(f, "LIKE {}", self.name)?;
11965        if let Some(defaults) = &self.defaults {
11966            write!(f, " {defaults}")?;
11967        }
11968        Ok(())
11969    }
11970}
11971
11972/// Specifies the refresh mode for the dynamic table.
11973///
11974/// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-dynamic-table)
11975#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11976#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11977#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11978pub enum RefreshModeKind {
11979    /// Automatic refresh mode (`AUTO`).
11980    Auto,
11981    /// Full refresh mode (`FULL`).
11982    Full,
11983    /// Incremental refresh mode (`INCREMENTAL`).
11984    Incremental,
11985}
11986
11987impl fmt::Display for RefreshModeKind {
11988    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11989        match self {
11990            RefreshModeKind::Auto => write!(f, "AUTO"),
11991            RefreshModeKind::Full => write!(f, "FULL"),
11992            RefreshModeKind::Incremental => write!(f, "INCREMENTAL"),
11993        }
11994    }
11995}
11996
11997/// Specifies the behavior of the initial refresh of the dynamic table.
11998///
11999/// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-dynamic-table)
12000#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
12001#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
12002#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
12003pub enum InitializeKind {
12004    /// Initialize on creation (`ON CREATE`).
12005    OnCreate,
12006    /// Initialize on schedule (`ON SCHEDULE`).
12007    OnSchedule,
12008}
12009
12010impl fmt::Display for InitializeKind {
12011    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
12012        match self {
12013            InitializeKind::OnCreate => write!(f, "ON_CREATE"),
12014            InitializeKind::OnSchedule => write!(f, "ON_SCHEDULE"),
12015        }
12016    }
12017}
12018
12019/// Re-sorts rows and reclaims space in either a specified table or all tables in the current database
12020///
12021/// '''sql
12022/// VACUUM [ FULL | SORT ONLY | DELETE ONLY | REINDEX | RECLUSTER ] [ \[ table_name \] [ TO threshold PERCENT ] \[ BOOST \] ]
12023/// '''
12024/// [Redshift](https://docs.aws.amazon.com/redshift/latest/dg/r_VACUUM_command.html)
12025#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
12026#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
12027#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
12028pub struct VacuumStatement {
12029    /// Whether `FULL` was specified.
12030    pub full: bool,
12031    /// Whether `SORT ONLY` was specified.
12032    pub sort_only: bool,
12033    /// Whether `DELETE ONLY` was specified.
12034    pub delete_only: bool,
12035    /// Whether `REINDEX` was specified.
12036    pub reindex: bool,
12037    /// Whether `RECLUSTER` was specified.
12038    pub recluster: bool,
12039    /// Optional table to run `VACUUM` on.
12040    pub table_name: Option<ObjectName>,
12041    /// Optional threshold value (percent) for `TO threshold PERCENT`.
12042    pub threshold: Option<ValueWithSpan>,
12043    /// Whether `BOOST` was specified.
12044    pub boost: bool,
12045}
12046
12047impl fmt::Display for VacuumStatement {
12048    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
12049        write!(
12050            f,
12051            "VACUUM{}{}{}{}{}",
12052            if self.full { " FULL" } else { "" },
12053            if self.sort_only { " SORT ONLY" } else { "" },
12054            if self.delete_only { " DELETE ONLY" } else { "" },
12055            if self.reindex { " REINDEX" } else { "" },
12056            if self.recluster { " RECLUSTER" } else { "" },
12057        )?;
12058        if let Some(table_name) = &self.table_name {
12059            write!(f, " {table_name}")?;
12060        }
12061        if let Some(threshold) = &self.threshold {
12062            write!(f, " TO {threshold} PERCENT")?;
12063        }
12064        if self.boost {
12065            write!(f, " BOOST")?;
12066        }
12067        Ok(())
12068    }
12069}
12070
12071/// Variants of the RESET statement
12072#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
12073#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
12074#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
12075pub enum Reset {
12076    /// Resets all session parameters to their default values.
12077    ALL,
12078
12079    /// Resets a specific session parameter to its default value.
12080    ConfigurationParameter(ObjectName),
12081}
12082
12083/// Resets a session parameter to its default value.
12084/// ```sql
12085/// RESET { ALL | <configuration_parameter> }
12086/// ```
12087#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
12088#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
12089#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
12090pub struct ResetStatement {
12091    /// The reset action to perform (either `ALL` or a specific configuration parameter).
12092    pub reset: Reset,
12093}
12094
12095/// Query optimizer hints are optionally supported comments after the
12096/// `SELECT`, `INSERT`, `UPDATE`, `REPLACE`, `MERGE`, and `DELETE` keywords in
12097/// the corresponding statements.
12098///
12099/// See [Select::optimizer_hints]
12100#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
12101#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
12102#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
12103pub struct OptimizerHint {
12104    /// An optional prefix between the comment marker and `+`.
12105    ///
12106    /// Standard optimizer hints like `/*+ ... */` have an empty prefix,
12107    /// while system-specific hints like `/*abc+ ... */` have `prefix = "abc"`.
12108    /// The prefix is any sequence of ASCII alphanumeric characters
12109    /// immediately before the `+` marker.
12110    pub prefix: String,
12111    /// the raw text of the optimizer hint without its markers
12112    pub text: String,
12113    /// the style of the comment which `text` was extracted from,
12114    /// e.g. `/*+...*/` or `--+...`
12115    ///
12116    /// Not all dialects support all styles, though.
12117    pub style: OptimizerHintStyle,
12118}
12119
12120/// The commentary style of an [optimizer hint](OptimizerHint)
12121#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
12122#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
12123#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
12124pub enum OptimizerHintStyle {
12125    /// A hint corresponding to a single line comment,
12126    /// e.g. `--+ LEADING(v.e v.d t)`
12127    SingleLine {
12128        /// the comment prefix, e.g. `--`
12129        prefix: String,
12130    },
12131    /// A hint corresponding to a multi line comment,
12132    /// e.g. `/*+ LEADING(v.e v.d t) */`
12133    MultiLine,
12134}
12135
12136impl fmt::Display for OptimizerHint {
12137    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
12138        match &self.style {
12139            OptimizerHintStyle::SingleLine { prefix } => {
12140                f.write_str(prefix)?;
12141                f.write_str(&self.prefix)?;
12142                f.write_str("+")?;
12143                f.write_str(&self.text)
12144            }
12145            OptimizerHintStyle::MultiLine => {
12146                f.write_str("/*")?;
12147                f.write_str(&self.prefix)?;
12148                f.write_str("+")?;
12149                f.write_str(&self.text)?;
12150                f.write_str("*/")
12151            }
12152        }
12153    }
12154}
12155
12156impl fmt::Display for ResetStatement {
12157    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
12158        match &self.reset {
12159            Reset::ALL => write!(f, "RESET ALL"),
12160            Reset::ConfigurationParameter(param) => write!(f, "RESET {}", param),
12161        }
12162    }
12163}
12164
12165impl From<Set> for Statement {
12166    fn from(s: Set) -> Self {
12167        Self::Set(s)
12168    }
12169}
12170
12171impl From<Query> for Statement {
12172    fn from(q: Query) -> Self {
12173        Box::new(q).into()
12174    }
12175}
12176
12177impl From<Box<Query>> for Statement {
12178    fn from(q: Box<Query>) -> Self {
12179        Self::Query(q)
12180    }
12181}
12182
12183impl From<Insert> for Statement {
12184    fn from(i: Insert) -> Self {
12185        Self::Insert(i)
12186    }
12187}
12188
12189impl From<Update> for Statement {
12190    fn from(u: Update) -> Self {
12191        Self::Update(u)
12192    }
12193}
12194
12195impl From<CreateView> for Statement {
12196    fn from(cv: CreateView) -> Self {
12197        Self::CreateView(cv)
12198    }
12199}
12200
12201impl From<CreateRole> for Statement {
12202    fn from(cr: CreateRole) -> Self {
12203        Self::CreateRole(cr)
12204    }
12205}
12206
12207impl From<AlterTable> for Statement {
12208    fn from(at: AlterTable) -> Self {
12209        Self::AlterTable(at)
12210    }
12211}
12212
12213impl From<DropFunction> for Statement {
12214    fn from(df: DropFunction) -> Self {
12215        Self::DropFunction(df)
12216    }
12217}
12218
12219impl From<CreateExtension> for Statement {
12220    fn from(ce: CreateExtension) -> Self {
12221        Self::CreateExtension(ce)
12222    }
12223}
12224
12225impl From<CreateCollation> for Statement {
12226    fn from(c: CreateCollation) -> Self {
12227        Self::CreateCollation(c)
12228    }
12229}
12230
12231impl From<DropExtension> for Statement {
12232    fn from(de: DropExtension) -> Self {
12233        Self::DropExtension(de)
12234    }
12235}
12236
12237impl From<CaseStatement> for Statement {
12238    fn from(c: CaseStatement) -> Self {
12239        Self::Case(c)
12240    }
12241}
12242
12243impl From<IfStatement> for Statement {
12244    fn from(i: IfStatement) -> Self {
12245        Self::If(i)
12246    }
12247}
12248
12249impl From<WhileStatement> for Statement {
12250    fn from(w: WhileStatement) -> Self {
12251        Self::While(w)
12252    }
12253}
12254
12255impl From<RaiseStatement> for Statement {
12256    fn from(r: RaiseStatement) -> Self {
12257        Self::Raise(r)
12258    }
12259}
12260
12261impl From<ThrowStatement> for Statement {
12262    fn from(t: ThrowStatement) -> Self {
12263        Self::Throw(t)
12264    }
12265}
12266
12267impl From<Function> for Statement {
12268    fn from(f: Function) -> Self {
12269        Self::Call(f)
12270    }
12271}
12272
12273impl From<OpenStatement> for Statement {
12274    fn from(o: OpenStatement) -> Self {
12275        Self::Open(o)
12276    }
12277}
12278
12279impl From<Delete> for Statement {
12280    fn from(d: Delete) -> Self {
12281        Self::Delete(d)
12282    }
12283}
12284
12285impl From<CreateTable> for Statement {
12286    fn from(c: CreateTable) -> Self {
12287        Self::CreateTable(c)
12288    }
12289}
12290
12291impl From<CreateIndex> for Statement {
12292    fn from(c: CreateIndex) -> Self {
12293        Self::CreateIndex(c)
12294    }
12295}
12296
12297impl From<CreateServerStatement> for Statement {
12298    fn from(c: CreateServerStatement) -> Self {
12299        Self::CreateServer(c)
12300    }
12301}
12302
12303impl From<CreateConnector> for Statement {
12304    fn from(c: CreateConnector) -> Self {
12305        Self::CreateConnector(c)
12306    }
12307}
12308
12309impl From<CreateOperator> for Statement {
12310    fn from(c: CreateOperator) -> Self {
12311        Self::CreateOperator(c)
12312    }
12313}
12314
12315impl From<CreateOperatorFamily> for Statement {
12316    fn from(c: CreateOperatorFamily) -> Self {
12317        Self::CreateOperatorFamily(c)
12318    }
12319}
12320
12321impl From<CreateOperatorClass> for Statement {
12322    fn from(c: CreateOperatorClass) -> Self {
12323        Self::CreateOperatorClass(c)
12324    }
12325}
12326
12327impl From<AlterSchema> for Statement {
12328    fn from(a: AlterSchema) -> Self {
12329        Self::AlterSchema(a)
12330    }
12331}
12332
12333impl From<AlterFunction> for Statement {
12334    fn from(a: AlterFunction) -> Self {
12335        Self::AlterFunction(a)
12336    }
12337}
12338
12339impl From<AlterType> for Statement {
12340    fn from(a: AlterType) -> Self {
12341        Self::AlterType(a)
12342    }
12343}
12344
12345impl From<AlterCollation> for Statement {
12346    fn from(a: AlterCollation) -> Self {
12347        Self::AlterCollation(a)
12348    }
12349}
12350
12351impl From<AlterOperator> for Statement {
12352    fn from(a: AlterOperator) -> Self {
12353        Self::AlterOperator(a)
12354    }
12355}
12356
12357impl From<AlterOperatorFamily> for Statement {
12358    fn from(a: AlterOperatorFamily) -> Self {
12359        Self::AlterOperatorFamily(a)
12360    }
12361}
12362
12363impl From<AlterOperatorClass> for Statement {
12364    fn from(a: AlterOperatorClass) -> Self {
12365        Self::AlterOperatorClass(a)
12366    }
12367}
12368
12369impl From<Merge> for Statement {
12370    fn from(m: Merge) -> Self {
12371        Self::Merge(m)
12372    }
12373}
12374
12375impl From<AlterUser> for Statement {
12376    fn from(a: AlterUser) -> Self {
12377        Self::AlterUser(a)
12378    }
12379}
12380
12381impl From<DropDomain> for Statement {
12382    fn from(d: DropDomain) -> Self {
12383        Self::DropDomain(d)
12384    }
12385}
12386
12387impl From<ShowCharset> for Statement {
12388    fn from(s: ShowCharset) -> Self {
12389        Self::ShowCharset(s)
12390    }
12391}
12392
12393impl From<ShowObjects> for Statement {
12394    fn from(s: ShowObjects) -> Self {
12395        Self::ShowObjects(s)
12396    }
12397}
12398
12399impl From<Use> for Statement {
12400    fn from(u: Use) -> Self {
12401        Self::Use(u)
12402    }
12403}
12404
12405impl From<CreateFunction> for Statement {
12406    fn from(c: CreateFunction) -> Self {
12407        Self::CreateFunction(c)
12408    }
12409}
12410
12411impl From<CreateTrigger> for Statement {
12412    fn from(c: CreateTrigger) -> Self {
12413        Self::CreateTrigger(c)
12414    }
12415}
12416
12417impl From<DropTrigger> for Statement {
12418    fn from(d: DropTrigger) -> Self {
12419        Self::DropTrigger(d)
12420    }
12421}
12422
12423impl From<DropOperator> for Statement {
12424    fn from(d: DropOperator) -> Self {
12425        Self::DropOperator(d)
12426    }
12427}
12428
12429impl From<DropOperatorFamily> for Statement {
12430    fn from(d: DropOperatorFamily) -> Self {
12431        Self::DropOperatorFamily(d)
12432    }
12433}
12434
12435impl From<DropOperatorClass> for Statement {
12436    fn from(d: DropOperatorClass) -> Self {
12437        Self::DropOperatorClass(d)
12438    }
12439}
12440
12441impl From<DenyStatement> for Statement {
12442    fn from(d: DenyStatement) -> Self {
12443        Self::Deny(d)
12444    }
12445}
12446
12447impl From<CreateDomain> for Statement {
12448    fn from(c: CreateDomain) -> Self {
12449        Self::CreateDomain(c)
12450    }
12451}
12452
12453impl From<RenameTable> for Statement {
12454    fn from(r: RenameTable) -> Self {
12455        vec![r].into()
12456    }
12457}
12458
12459impl From<Vec<RenameTable>> for Statement {
12460    fn from(r: Vec<RenameTable>) -> Self {
12461        Self::RenameTable(r)
12462    }
12463}
12464
12465impl From<PrintStatement> for Statement {
12466    fn from(p: PrintStatement) -> Self {
12467        Self::Print(p)
12468    }
12469}
12470
12471impl From<ReturnStatement> for Statement {
12472    fn from(r: ReturnStatement) -> Self {
12473        Self::Return(r)
12474    }
12475}
12476
12477impl From<ExportData> for Statement {
12478    fn from(e: ExportData) -> Self {
12479        Self::ExportData(e)
12480    }
12481}
12482
12483impl From<CreateUser> for Statement {
12484    fn from(c: CreateUser) -> Self {
12485        Self::CreateUser(c)
12486    }
12487}
12488
12489impl From<VacuumStatement> for Statement {
12490    fn from(v: VacuumStatement) -> Self {
12491        Self::Vacuum(v)
12492    }
12493}
12494
12495impl From<ResetStatement> for Statement {
12496    fn from(r: ResetStatement) -> Self {
12497        Self::Reset(r)
12498    }
12499}
12500
12501#[cfg(test)]
12502mod tests {
12503    use crate::tokenizer::Location;
12504
12505    use super::*;
12506
12507    #[test]
12508    fn test_window_frame_default() {
12509        let window_frame = WindowFrame::default();
12510        assert_eq!(WindowFrameBound::Preceding(None), window_frame.start_bound);
12511    }
12512
12513    #[test]
12514    fn test_grouping_sets_display() {
12515        // a and b in different group
12516        let grouping_sets = Expr::GroupingSets(vec![
12517            vec![Expr::Identifier(Ident::new("a"))],
12518            vec![Expr::Identifier(Ident::new("b"))],
12519        ]);
12520        assert_eq!("GROUPING SETS ((a), (b))", format!("{grouping_sets}"));
12521
12522        // a and b in the same group
12523        let grouping_sets = Expr::GroupingSets(vec![vec![
12524            Expr::Identifier(Ident::new("a")),
12525            Expr::Identifier(Ident::new("b")),
12526        ]]);
12527        assert_eq!("GROUPING SETS ((a, b))", format!("{grouping_sets}"));
12528
12529        // (a, b) and (c, d) in different group
12530        let grouping_sets = Expr::GroupingSets(vec![
12531            vec![
12532                Expr::Identifier(Ident::new("a")),
12533                Expr::Identifier(Ident::new("b")),
12534            ],
12535            vec![
12536                Expr::Identifier(Ident::new("c")),
12537                Expr::Identifier(Ident::new("d")),
12538            ],
12539        ]);
12540        assert_eq!("GROUPING SETS ((a, b), (c, d))", format!("{grouping_sets}"));
12541    }
12542
12543    #[test]
12544    fn test_rollup_display() {
12545        let rollup = Expr::Rollup(vec![vec![Expr::Identifier(Ident::new("a"))]]);
12546        assert_eq!("ROLLUP (a)", format!("{rollup}"));
12547
12548        let rollup = Expr::Rollup(vec![vec![
12549            Expr::Identifier(Ident::new("a")),
12550            Expr::Identifier(Ident::new("b")),
12551        ]]);
12552        assert_eq!("ROLLUP ((a, b))", format!("{rollup}"));
12553
12554        let rollup = Expr::Rollup(vec![
12555            vec![Expr::Identifier(Ident::new("a"))],
12556            vec![Expr::Identifier(Ident::new("b"))],
12557        ]);
12558        assert_eq!("ROLLUP (a, b)", format!("{rollup}"));
12559
12560        let rollup = Expr::Rollup(vec![
12561            vec![Expr::Identifier(Ident::new("a"))],
12562            vec![
12563                Expr::Identifier(Ident::new("b")),
12564                Expr::Identifier(Ident::new("c")),
12565            ],
12566            vec![Expr::Identifier(Ident::new("d"))],
12567        ]);
12568        assert_eq!("ROLLUP (a, (b, c), d)", format!("{rollup}"));
12569    }
12570
12571    #[test]
12572    fn test_cube_display() {
12573        let cube = Expr::Cube(vec![vec![Expr::Identifier(Ident::new("a"))]]);
12574        assert_eq!("CUBE (a)", format!("{cube}"));
12575
12576        let cube = Expr::Cube(vec![vec![
12577            Expr::Identifier(Ident::new("a")),
12578            Expr::Identifier(Ident::new("b")),
12579        ]]);
12580        assert_eq!("CUBE ((a, b))", format!("{cube}"));
12581
12582        let cube = Expr::Cube(vec![
12583            vec![Expr::Identifier(Ident::new("a"))],
12584            vec![Expr::Identifier(Ident::new("b"))],
12585        ]);
12586        assert_eq!("CUBE (a, b)", format!("{cube}"));
12587
12588        let cube = Expr::Cube(vec![
12589            vec![Expr::Identifier(Ident::new("a"))],
12590            vec![
12591                Expr::Identifier(Ident::new("b")),
12592                Expr::Identifier(Ident::new("c")),
12593            ],
12594            vec![Expr::Identifier(Ident::new("d"))],
12595        ]);
12596        assert_eq!("CUBE (a, (b, c), d)", format!("{cube}"));
12597    }
12598
12599    #[test]
12600    fn test_interval_display() {
12601        let interval = Expr::Interval(Interval {
12602            value: Box::new(Expr::Value(
12603                Value::SingleQuotedString(String::from("123:45.67")).with_empty_span(),
12604            )),
12605            leading_field: Some(DateTimeField::Minute),
12606            leading_precision: Some(10),
12607            last_field: Some(DateTimeField::Second),
12608            fractional_seconds_precision: Some(9),
12609        });
12610        assert_eq!(
12611            "INTERVAL '123:45.67' MINUTE (10) TO SECOND (9)",
12612            format!("{interval}"),
12613        );
12614
12615        let interval = Expr::Interval(Interval {
12616            value: Box::new(Expr::Value(
12617                Value::SingleQuotedString(String::from("5")).with_empty_span(),
12618            )),
12619            leading_field: Some(DateTimeField::Second),
12620            leading_precision: Some(1),
12621            last_field: None,
12622            fractional_seconds_precision: Some(3),
12623        });
12624        assert_eq!("INTERVAL '5' SECOND (1, 3)", format!("{interval}"));
12625    }
12626
12627    #[test]
12628    fn test_one_or_many_with_parens_deref() {
12629        use core::ops::Index;
12630
12631        let one = OneOrManyWithParens::One("a");
12632
12633        assert_eq!(one.deref(), &["a"]);
12634        assert_eq!(<OneOrManyWithParens<_> as Deref>::deref(&one), &["a"]);
12635
12636        assert_eq!(one[0], "a");
12637        assert_eq!(one.index(0), &"a");
12638        assert_eq!(
12639            <<OneOrManyWithParens<_> as Deref>::Target as Index<usize>>::index(&one, 0),
12640            &"a"
12641        );
12642
12643        assert_eq!(one.len(), 1);
12644        assert_eq!(<OneOrManyWithParens<_> as Deref>::Target::len(&one), 1);
12645
12646        let many1 = OneOrManyWithParens::Many(vec!["b"]);
12647
12648        assert_eq!(many1.deref(), &["b"]);
12649        assert_eq!(<OneOrManyWithParens<_> as Deref>::deref(&many1), &["b"]);
12650
12651        assert_eq!(many1[0], "b");
12652        assert_eq!(many1.index(0), &"b");
12653        assert_eq!(
12654            <<OneOrManyWithParens<_> as Deref>::Target as Index<usize>>::index(&many1, 0),
12655            &"b"
12656        );
12657
12658        assert_eq!(many1.len(), 1);
12659        assert_eq!(<OneOrManyWithParens<_> as Deref>::Target::len(&many1), 1);
12660
12661        let many2 = OneOrManyWithParens::Many(vec!["c", "d"]);
12662
12663        assert_eq!(many2.deref(), &["c", "d"]);
12664        assert_eq!(
12665            <OneOrManyWithParens<_> as Deref>::deref(&many2),
12666            &["c", "d"]
12667        );
12668
12669        assert_eq!(many2[0], "c");
12670        assert_eq!(many2.index(0), &"c");
12671        assert_eq!(
12672            <<OneOrManyWithParens<_> as Deref>::Target as Index<usize>>::index(&many2, 0),
12673            &"c"
12674        );
12675
12676        assert_eq!(many2[1], "d");
12677        assert_eq!(many2.index(1), &"d");
12678        assert_eq!(
12679            <<OneOrManyWithParens<_> as Deref>::Target as Index<usize>>::index(&many2, 1),
12680            &"d"
12681        );
12682
12683        assert_eq!(many2.len(), 2);
12684        assert_eq!(<OneOrManyWithParens<_> as Deref>::Target::len(&many2), 2);
12685    }
12686
12687    #[test]
12688    fn test_one_or_many_with_parens_as_ref() {
12689        let one = OneOrManyWithParens::One("a");
12690
12691        assert_eq!(one.as_ref(), &["a"]);
12692        assert_eq!(<OneOrManyWithParens<_> as AsRef<_>>::as_ref(&one), &["a"]);
12693
12694        let many1 = OneOrManyWithParens::Many(vec!["b"]);
12695
12696        assert_eq!(many1.as_ref(), &["b"]);
12697        assert_eq!(<OneOrManyWithParens<_> as AsRef<_>>::as_ref(&many1), &["b"]);
12698
12699        let many2 = OneOrManyWithParens::Many(vec!["c", "d"]);
12700
12701        assert_eq!(many2.as_ref(), &["c", "d"]);
12702        assert_eq!(
12703            <OneOrManyWithParens<_> as AsRef<_>>::as_ref(&many2),
12704            &["c", "d"]
12705        );
12706    }
12707
12708    #[test]
12709    fn test_one_or_many_with_parens_ref_into_iter() {
12710        let one = OneOrManyWithParens::One("a");
12711
12712        assert_eq!(Vec::from_iter(&one), vec![&"a"]);
12713
12714        let many1 = OneOrManyWithParens::Many(vec!["b"]);
12715
12716        assert_eq!(Vec::from_iter(&many1), vec![&"b"]);
12717
12718        let many2 = OneOrManyWithParens::Many(vec!["c", "d"]);
12719
12720        assert_eq!(Vec::from_iter(&many2), vec![&"c", &"d"]);
12721    }
12722
12723    #[test]
12724    fn test_one_or_many_with_parens_value_into_iter() {
12725        use core::iter::once;
12726
12727        //tests that our iterator implemented methods behaves exactly as it's inner iterator, at every step up to n calls to next/next_back
12728        fn test_steps<I>(ours: OneOrManyWithParens<usize>, inner: I, n: usize)
12729        where
12730            I: IntoIterator<Item = usize, IntoIter: DoubleEndedIterator + Clone> + Clone,
12731        {
12732            fn checks<I>(ours: OneOrManyWithParensIntoIter<usize>, inner: I)
12733            where
12734                I: Iterator<Item = usize> + Clone + DoubleEndedIterator,
12735            {
12736                assert_eq!(ours.size_hint(), inner.size_hint());
12737                assert_eq!(ours.clone().count(), inner.clone().count());
12738
12739                assert_eq!(
12740                    ours.clone().fold(1, |a, v| a + v),
12741                    inner.clone().fold(1, |a, v| a + v)
12742                );
12743
12744                assert_eq!(Vec::from_iter(ours.clone()), Vec::from_iter(inner.clone()));
12745                assert_eq!(
12746                    Vec::from_iter(ours.clone().rev()),
12747                    Vec::from_iter(inner.clone().rev())
12748                );
12749            }
12750
12751            let mut ours_next = ours.clone().into_iter();
12752            let mut inner_next = inner.clone().into_iter();
12753
12754            for _ in 0..n {
12755                checks(ours_next.clone(), inner_next.clone());
12756
12757                assert_eq!(ours_next.next(), inner_next.next());
12758            }
12759
12760            let mut ours_next_back = ours.clone().into_iter();
12761            let mut inner_next_back = inner.clone().into_iter();
12762
12763            for _ in 0..n {
12764                checks(ours_next_back.clone(), inner_next_back.clone());
12765
12766                assert_eq!(ours_next_back.next_back(), inner_next_back.next_back());
12767            }
12768
12769            let mut ours_mixed = ours.clone().into_iter();
12770            let mut inner_mixed = inner.clone().into_iter();
12771
12772            for i in 0..n {
12773                checks(ours_mixed.clone(), inner_mixed.clone());
12774
12775                if i % 2 == 0 {
12776                    assert_eq!(ours_mixed.next_back(), inner_mixed.next_back());
12777                } else {
12778                    assert_eq!(ours_mixed.next(), inner_mixed.next());
12779                }
12780            }
12781
12782            let mut ours_mixed2 = ours.into_iter();
12783            let mut inner_mixed2 = inner.into_iter();
12784
12785            for i in 0..n {
12786                checks(ours_mixed2.clone(), inner_mixed2.clone());
12787
12788                if i % 2 == 0 {
12789                    assert_eq!(ours_mixed2.next(), inner_mixed2.next());
12790                } else {
12791                    assert_eq!(ours_mixed2.next_back(), inner_mixed2.next_back());
12792                }
12793            }
12794        }
12795
12796        test_steps(OneOrManyWithParens::One(1), once(1), 3);
12797        test_steps(OneOrManyWithParens::Many(vec![2]), vec![2], 3);
12798        test_steps(OneOrManyWithParens::Many(vec![3, 4]), vec![3, 4], 4);
12799    }
12800
12801    // Tests that the position in the code of an `Ident` does not affect its
12802    // ordering.
12803    #[test]
12804    fn test_ident_ord() {
12805        let mut a = Ident::with_span(Span::new(Location::new(1, 1), Location::new(1, 1)), "a");
12806        let mut b = Ident::with_span(Span::new(Location::new(2, 2), Location::new(2, 2)), "b");
12807
12808        assert!(a < b);
12809        std::mem::swap(&mut a.span, &mut b.span);
12810        assert!(a < b);
12811    }
12812}