Skip to main content

sqlparser/ast/
mod.rs

1// Licensed to the Apache Software Foundation (ASF) under one
2// or more contributor license agreements.  See the NOTICE file
3// distributed with this work for additional information
4// regarding copyright ownership.  The ASF licenses this file
5// to you under the Apache License, Version 2.0 (the
6// "License"); you may not use this file except in compliance
7// with the License.  You may obtain a copy of the License at
8//
9//   http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing,
12// software distributed under the License is distributed on an
13// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14// KIND, either express or implied.  See the License for the
15// specific language governing permissions and limitations
16// under the License.
17
18//! SQL Abstract Syntax Tree (AST) types
19#[cfg(not(feature = "std"))]
20use alloc::{
21    boxed::Box,
22    format,
23    string::{String, ToString},
24    vec,
25    vec::Vec,
26};
27use helpers::{
28    attached_token::AttachedToken,
29    stmt_data_loading::{FileStagingCommand, StageLoadSelectItemKind},
30};
31
32use core::cmp::Ordering;
33use core::ops::Deref;
34use core::{
35    fmt::{self, Display},
36    hash,
37};
38
39#[cfg(feature = "serde")]
40use serde::{Deserialize, Serialize};
41
42#[cfg(feature = "visitor")]
43use sqlparser_derive::{Visit, VisitMut};
44
45use crate::{
46    display_utils::SpaceOrNewline,
47    tokenizer::{Span, Token},
48};
49use crate::{
50    display_utils::{Indent, NewLine},
51    keywords::Keyword,
52};
53
54pub use self::data_type::{
55    ArrayElemTypeDef, BinaryLength, CharLengthUnits, CharacterLength, DataType, EnumMember,
56    ExactNumberInfo, IntervalFields, StructBracketKind, TimezoneInfo,
57};
58pub use self::dcl::{
59    AlterDefaultPrivileges, AlterDefaultPrivilegesAction, AlterDefaultPrivilegesObjectType,
60    AlterRoleOperation, CreateRole, Grant, ResetConfig, Revoke, RoleOption, SecondaryRoles,
61    SetConfigValue, Use,
62};
63pub use self::ddl::{
64    AccessMethodType, AggregateModifyKind, Alignment, AlterCollation, AlterCollationOperation,
65    AlterColumnOperation, AlterConnectorOwner, AlterDomain, AlterDomainOperation, AlterExtension,
66    AlterExtensionOperation, AlterFunction, AlterFunctionAction, AlterFunctionKind,
67    AlterFunctionOperation, AlterIndexOperation, AlterOperator, AlterOperatorClass,
68    AlterOperatorClassOperation, AlterOperatorFamily, AlterOperatorFamilyOperation,
69    AlterOperatorOperation, AlterPolicy, AlterPolicyOperation, AlterSchema, AlterSchemaOperation,
70    AlterTable, AlterTableAlgorithm, AlterTableLock, AlterTableOperation, AlterTableType,
71    AlterTrigger, AlterTriggerOperation, AlterType, AlterTypeAddValue, AlterTypeAddValuePosition,
72    AlterTypeOperation, AlterTypeRename, AlterTypeRenameValue, CastContext, CastFunctionKind,
73    ClusteredBy, ColumnDef, ColumnOption, ColumnOptionDef, ColumnOptions, ColumnPolicy,
74    ColumnPolicyProperty, ConstraintCharacteristics, CreateAccessMethod, CreateAggregate,
75    CreateAggregateOption, CreateCast, CreateCollation, CreateCollationDefinition, CreateConnector,
76    CreateConversion, CreateDomain, CreateEventTrigger, CreateExtension, CreateForeignDataWrapper,
77    CreateForeignTable, CreateFunction, CreateIndex, CreateLanguage, CreateOperator,
78    CreateOperatorClass, CreateOperatorFamily, CreatePolicy, CreatePolicyCommand, CreatePolicyType,
79    CreatePublication, CreateRule, CreateStatistics, CreateSubscription, CreateTable,
80    CreateTablespace, CreateTextSearchConfiguration, CreateTextSearchDictionary,
81    CreateTextSearchParser, CreateTextSearchTemplate, CreateTransform, CreateTrigger,
82    CreateUserMapping, CreateView, Deduplicate, DeferrableInitial, DistStyle, DropBehavior,
83    DropExtension, DropFunction, DropOperator, DropOperatorClass, DropOperatorFamily,
84    DropOperatorSignature, DropPolicy, DropTrigger, EventTriggerEvent, FdwRoutineClause, ForValues,
85    FunctionReturnType, GeneratedAs, GeneratedExpressionMode, IdentityParameters, IdentityProperty,
86    IdentityPropertyFormatKind, IdentityPropertyKind, IdentityPropertyOrder, IndexColumn,
87    IndexOption, IndexType, KeyOrIndexDisplay, Msck, NullsDistinctOption, OperatorArgTypes,
88    OperatorClassItem, OperatorFamilyDropItem, OperatorFamilyItem, OperatorOption, OperatorPurpose,
89    Owner, Partition, PartitionBoundValue, ProcedureParam, PublicationTarget, ReferentialAction,
90    RenameTableNameKind, ReplicaIdentity, RuleAction, RuleEvent, SecurityLabel,
91    SecurityLabelObjectKind, StatisticsKind, TagsColumnOption, TransformElement, TriggerObjectKind,
92    Truncate, UserDefinedTypeCompositeAttributeDef, UserDefinedTypeInternalLength,
93    UserDefinedTypeRangeOption, UserDefinedTypeRepresentation, UserDefinedTypeSqlDefinitionOption,
94    UserDefinedTypeStorage, UserMappingUser, ViewColumnDef,
95};
96pub use self::dml::{
97    Delete, Insert, Merge, MergeAction, MergeClause, MergeClauseKind, MergeInsertExpr,
98    MergeInsertKind, MergeUpdateExpr, MultiTableInsertIntoClause, MultiTableInsertType,
99    MultiTableInsertValue, MultiTableInsertValues, MultiTableInsertWhenClause, OutputClause,
100    Update,
101};
102pub use self::operator::{BinaryOperator, UnaryOperator};
103pub use self::query::{
104    AfterMatchSkip, ConnectByKind, Cte, CteAsMaterialized, Distinct, EmptyMatchesMode,
105    ExceptSelectItem, ExcludeSelectItem, ExprWithAlias, ExprWithAliasAndOrderBy, Fetch, ForClause,
106    ForJson, ForXml, FormatClause, GroupByExpr, GroupByWithModifier, IdentWithAlias,
107    IlikeSelectItem, InputFormatClause, Interpolate, InterpolateExpr, Join, JoinConstraint,
108    JoinOperator, JsonTableColumn, JsonTableColumnErrorHandling, JsonTableNamedColumn,
109    JsonTableNestedColumn, LateralView, LimitClause, LockClause, LockType, MatchRecognizePattern,
110    MatchRecognizeSymbol, Measure, NamedWindowDefinition, NamedWindowExpr, NonBlock, Offset,
111    OffsetRows, OpenJsonTableColumn, OrderBy, OrderByExpr, OrderByKind, OrderByOptions,
112    PipeOperator, PivotValueSource, ProjectionSelect, Query, RenameSelectItem,
113    RepetitionQuantifier, ReplaceSelectElement, ReplaceSelectItem, RowsPerMatch, Select,
114    SelectFlavor, SelectInto, SelectItem, SelectItemQualifiedWildcardKind, SelectModifiers,
115    SetExpr, SetOperator, SetQuantifier, Setting, SymbolDefinition, Table, TableAlias,
116    TableAliasColumnDef, TableFactor, TableFunctionArgs, TableIndexHintForClause,
117    TableIndexHintType, TableIndexHints, TableIndexType, TableSample, TableSampleBucket,
118    TableSampleKind, TableSampleMethod, TableSampleModifier, TableSampleQuantity, TableSampleSeed,
119    TableSampleSeedModifier, TableSampleUnit, TableVersion, TableWithJoins, Top, TopQuantity,
120    UpdateTableFromKind, ValueTableMode, Values, WildcardAdditionalOptions, With, WithFill,
121    XmlNamespaceDefinition, XmlPassingArgument, XmlPassingClause, XmlTableColumn,
122    XmlTableColumnOption,
123};
124
125pub use self::trigger::{
126    TriggerEvent, TriggerExecBody, TriggerExecBodyType, TriggerObject, TriggerPeriod,
127    TriggerReferencing, TriggerReferencingType,
128};
129
130pub use self::value::{
131    escape_double_quote_string, escape_quoted_string, DateTimeField, DollarQuotedString,
132    NormalizationForm, QuoteDelimitedString, TrimWhereField, Value, ValueWithSpan,
133};
134
135use crate::ast::helpers::key_value_options::KeyValueOptions;
136use crate::ast::helpers::stmt_data_loading::StageParamsObject;
137
138#[cfg(feature = "visitor")]
139pub use visitor::*;
140
141pub use self::data_type::GeometricTypeKind;
142
143mod data_type;
144mod dcl;
145mod ddl;
146mod dml;
147/// Helper modules for building and manipulating AST nodes.
148pub mod helpers;
149pub mod table_constraints;
150pub use table_constraints::{
151    CheckConstraint, ConstraintUsingIndex, ExclusionConstraint, ExclusionElement,
152    ForeignKeyConstraint, FullTextOrSpatialConstraint, IndexConstraint, PrimaryKeyConstraint,
153    TableConstraint, UniqueConstraint,
154};
155mod operator;
156mod query;
157mod spans;
158pub use spans::Spanned;
159
160pub mod comments;
161mod trigger;
162mod value;
163
164#[cfg(feature = "visitor")]
165mod visitor;
166
167/// Helper used to format a slice using a separator string (e.g., `", "`).
168pub struct DisplaySeparated<'a, T>
169where
170    T: fmt::Display,
171{
172    slice: &'a [T],
173    sep: &'static str,
174}
175
176impl<T> fmt::Display for DisplaySeparated<'_, T>
177where
178    T: fmt::Display,
179{
180    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
181        let mut delim = "";
182        for t in self.slice {
183            f.write_str(delim)?;
184            delim = self.sep;
185            t.fmt(f)?;
186        }
187        Ok(())
188    }
189}
190
191pub(crate) fn display_separated<'a, T>(slice: &'a [T], sep: &'static str) -> DisplaySeparated<'a, T>
192where
193    T: fmt::Display,
194{
195    DisplaySeparated { slice, sep }
196}
197
198pub(crate) fn display_comma_separated<T>(slice: &[T]) -> DisplaySeparated<'_, T>
199where
200    T: fmt::Display,
201{
202    DisplaySeparated { slice, sep: ", " }
203}
204
205/// Writes the given statements to the formatter, each ending with
206/// a semicolon and space separated.
207fn format_statement_list(f: &mut fmt::Formatter, statements: &[Statement]) -> fmt::Result {
208    write!(f, "{}", display_separated(statements, "; "))?;
209    // We manually insert semicolon for the last statement,
210    // since display_separated doesn't handle that case.
211    write!(f, ";")
212}
213
214/// An identifier, decomposed into its value or character data and the quote style.
215#[derive(Debug, Clone)]
216#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
217#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
218pub struct Ident {
219    /// The value of the identifier without quotes.
220    pub value: String,
221    /// The starting quote if any. Valid quote characters are the single quote,
222    /// double quote, backtick, and opening square bracket.
223    pub quote_style: Option<char>,
224    /// The span of the identifier in the original SQL string.
225    pub span: Span,
226}
227
228impl PartialEq for Ident {
229    fn eq(&self, other: &Self) -> bool {
230        let Ident {
231            value,
232            quote_style,
233            // exhaustiveness check; we ignore spans in comparisons
234            span: _,
235        } = self;
236
237        value == &other.value && quote_style == &other.quote_style
238    }
239}
240
241impl core::hash::Hash for Ident {
242    fn hash<H: hash::Hasher>(&self, state: &mut H) {
243        let Ident {
244            value,
245            quote_style,
246            // exhaustiveness check; we ignore spans in hashes
247            span: _,
248        } = self;
249
250        value.hash(state);
251        quote_style.hash(state);
252    }
253}
254
255impl Eq for Ident {}
256
257impl PartialOrd for Ident {
258    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
259        Some(self.cmp(other))
260    }
261}
262
263impl Ord for Ident {
264    fn cmp(&self, other: &Self) -> Ordering {
265        let Ident {
266            value,
267            quote_style,
268            // exhaustiveness check; we ignore spans in ordering
269            span: _,
270        } = self;
271
272        let Ident {
273            value: other_value,
274            quote_style: other_quote_style,
275            // exhaustiveness check; we ignore spans in ordering
276            span: _,
277        } = other;
278
279        // First compare by value, then by quote_style
280        value
281            .cmp(other_value)
282            .then_with(|| quote_style.cmp(other_quote_style))
283    }
284}
285
286impl Ident {
287    /// Create a new identifier with the given value and no quotes and an empty span.
288    pub fn new<S>(value: S) -> Self
289    where
290        S: Into<String>,
291    {
292        Ident {
293            value: value.into(),
294            quote_style: None,
295            span: Span::empty(),
296        }
297    }
298
299    /// Create a new quoted identifier with the given quote and value. This function
300    /// panics if the given quote is not a valid quote character.
301    pub fn with_quote<S>(quote: char, value: S) -> Self
302    where
303        S: Into<String>,
304    {
305        assert!(quote == '\'' || quote == '"' || quote == '`' || quote == '[');
306        Ident {
307            value: value.into(),
308            quote_style: Some(quote),
309            span: Span::empty(),
310        }
311    }
312
313    /// Create an `Ident` with the given `span` and `value` (unquoted).
314    pub fn with_span<S>(span: Span, value: S) -> Self
315    where
316        S: Into<String>,
317    {
318        Ident {
319            value: value.into(),
320            quote_style: None,
321            span,
322        }
323    }
324
325    /// Create a quoted `Ident` with the given `quote` and `span`.
326    pub fn with_quote_and_span<S>(quote: char, span: Span, value: S) -> Self
327    where
328        S: Into<String>,
329    {
330        assert!(quote == '\'' || quote == '"' || quote == '`' || quote == '[');
331        Ident {
332            value: value.into(),
333            quote_style: Some(quote),
334            span,
335        }
336    }
337}
338
339impl From<&str> for Ident {
340    fn from(value: &str) -> Self {
341        Ident {
342            value: value.to_string(),
343            quote_style: None,
344            span: Span::empty(),
345        }
346    }
347}
348
349impl fmt::Display for Ident {
350    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
351        match self.quote_style {
352            Some(q) if q == '"' || q == '\'' || q == '`' => {
353                let escaped = value::escape_quoted_string(&self.value, q);
354                write!(f, "{q}{escaped}{q}")
355            }
356            Some('[') => write!(f, "[{}]", self.value),
357            None => f.write_str(&self.value),
358            _ => panic!("unexpected quote style"),
359        }
360    }
361}
362
363/// A name of a table, view, custom type, etc., possibly multi-part, i.e. db.schema.obj
364#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
365#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
366#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
367pub struct ObjectName(pub Vec<ObjectNamePart>);
368
369impl From<Vec<Ident>> for ObjectName {
370    fn from(idents: Vec<Ident>) -> Self {
371        ObjectName(idents.into_iter().map(ObjectNamePart::Identifier).collect())
372    }
373}
374
375impl From<Ident> for ObjectName {
376    fn from(ident: Ident) -> Self {
377        ObjectName(vec![ObjectNamePart::Identifier(ident)])
378    }
379}
380
381impl fmt::Display for ObjectName {
382    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
383        write!(f, "{}", display_separated(&self.0, "."))
384    }
385}
386
387/// A single part of an ObjectName
388#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
389#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
390#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
391pub enum ObjectNamePart {
392    /// A single identifier part, e.g. `schema` or `table`.
393    Identifier(Ident),
394    /// A function that returns an identifier (dialect-specific).
395    Function(ObjectNamePartFunction),
396}
397
398impl ObjectNamePart {
399    /// Return the identifier if this is an `Identifier` variant.
400    pub fn as_ident(&self) -> Option<&Ident> {
401        match self {
402            ObjectNamePart::Identifier(ident) => Some(ident),
403            ObjectNamePart::Function(_) => None,
404        }
405    }
406}
407
408impl fmt::Display for ObjectNamePart {
409    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
410        match self {
411            ObjectNamePart::Identifier(ident) => write!(f, "{ident}"),
412            ObjectNamePart::Function(func) => write!(f, "{func}"),
413        }
414    }
415}
416
417/// An object name part that consists of a function that dynamically
418/// constructs identifiers.
419///
420/// - [Snowflake](https://docs.snowflake.com/en/sql-reference/identifier-literal)
421#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
422#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
423#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
424pub struct ObjectNamePartFunction {
425    /// The function name that produces the object name part.
426    pub name: Ident,
427    /// Function arguments used to compute the identifier.
428    pub args: Vec<FunctionArg>,
429}
430
431impl fmt::Display for ObjectNamePartFunction {
432    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
433        write!(f, "{}(", self.name)?;
434        write!(f, "{})", display_comma_separated(&self.args))
435    }
436}
437
438/// Represents an Array Expression, either
439/// `ARRAY[..]`, or `[..]`
440#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
441#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
442#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
443pub struct Array {
444    /// The list of expressions between brackets
445    pub elem: Vec<Expr>,
446
447    /// `true` for  `ARRAY[..]`, `false` for `[..]`
448    pub named: bool,
449}
450
451impl fmt::Display for Array {
452    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
453        write!(
454            f,
455            "{}[{}]",
456            if self.named { "ARRAY" } else { "" },
457            display_comma_separated(&self.elem)
458        )
459    }
460}
461
462/// Represents an INTERVAL expression, roughly in the following format:
463/// `INTERVAL '<value>' [ <leading_field> [ (<leading_precision>) ] ]
464/// [ TO <last_field> [ (<fractional_seconds_precision>) ] ]`,
465/// e.g. `INTERVAL '123:45.67' MINUTE(3) TO SECOND(2)`.
466///
467/// The parser does not validate the `<value>`, nor does it ensure
468/// that the `<leading_field>` units >= the units in `<last_field>`,
469/// so the user will have to reject intervals like `HOUR TO YEAR`.
470#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
471#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
472#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
473pub struct Interval {
474    /// The interval value expression (commonly a string literal).
475    pub value: Box<Expr>,
476    /// Optional leading time unit (e.g., `HOUR`, `MINUTE`).
477    pub leading_field: Option<DateTimeField>,
478    /// Optional leading precision for the leading field.
479    pub leading_precision: Option<u64>,
480    /// Optional trailing time unit for a range (e.g., `SECOND`).
481    pub last_field: Option<DateTimeField>,
482    /// The fractional seconds precision, when specified.
483    ///
484    /// See SQL `SECOND(n)` or `SECOND(m, n)` forms.
485    pub fractional_seconds_precision: Option<u64>,
486}
487
488impl fmt::Display for Interval {
489    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
490        let value = self.value.as_ref();
491        match (
492            &self.leading_field,
493            self.leading_precision,
494            self.fractional_seconds_precision,
495        ) {
496            (
497                Some(DateTimeField::Second),
498                Some(leading_precision),
499                Some(fractional_seconds_precision),
500            ) => {
501                // When the leading field is SECOND, the parser guarantees that
502                // the last field is None.
503                assert!(self.last_field.is_none());
504                write!(
505                    f,
506                    "INTERVAL {value} SECOND ({leading_precision}, {fractional_seconds_precision})"
507                )
508            }
509            _ => {
510                write!(f, "INTERVAL {value}")?;
511                if let Some(leading_field) = &self.leading_field {
512                    write!(f, " {leading_field}")?;
513                }
514                if let Some(leading_precision) = self.leading_precision {
515                    write!(f, " ({leading_precision})")?;
516                }
517                if let Some(last_field) = &self.last_field {
518                    write!(f, " TO {last_field}")?;
519                }
520                if let Some(fractional_seconds_precision) = self.fractional_seconds_precision {
521                    write!(f, " ({fractional_seconds_precision})")?;
522                }
523                Ok(())
524            }
525        }
526    }
527}
528
529/// A field definition within a struct
530///
531/// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-types#struct_type
532#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
533#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
534#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
535pub struct StructField {
536    /// Optional name of the struct field.
537    pub field_name: Option<Ident>,
538    /// The field data type.
539    pub field_type: DataType,
540    /// Struct field options (e.g., `OPTIONS(...)` on BigQuery).
541    /// See [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#column_name_and_column_schema)
542    pub options: Option<Vec<SqlOption>>,
543}
544
545impl fmt::Display for StructField {
546    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
547        if let Some(name) = &self.field_name {
548            write!(f, "{name} {}", self.field_type)?;
549        } else {
550            write!(f, "{}", self.field_type)?;
551        }
552        if let Some(options) = &self.options {
553            write!(f, " OPTIONS({})", display_separated(options, ", "))
554        } else {
555            Ok(())
556        }
557    }
558}
559
560/// A field definition within a union
561///
562/// [DuckDB]: https://duckdb.org/docs/sql/data_types/union.html
563#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
564#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
565#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
566pub struct UnionField {
567    /// Name of the union field.
568    pub field_name: Ident,
569    /// Type of the union field.
570    pub field_type: DataType,
571}
572
573impl fmt::Display for UnionField {
574    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
575        write!(f, "{} {}", self.field_name, self.field_type)
576    }
577}
578
579/// A dictionary field within a dictionary.
580///
581/// [DuckDB]: https://duckdb.org/docs/sql/data_types/struct#creating-structs
582#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
583#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
584#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
585pub struct DictionaryField {
586    /// Dictionary key identifier.
587    pub key: Ident,
588    /// Value expression for the dictionary entry.
589    pub value: Box<Expr>,
590}
591
592impl fmt::Display for DictionaryField {
593    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
594        write!(f, "{}: {}", self.key, self.value)
595    }
596}
597
598/// Represents a Map expression.
599#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
600#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
601#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
602pub struct Map {
603    /// Entries of the map as key/value pairs.
604    pub entries: Vec<MapEntry>,
605}
606
607impl Display for Map {
608    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
609        write!(f, "MAP {{{}}}", display_comma_separated(&self.entries))
610    }
611}
612
613/// A map field within a map.
614///
615/// [DuckDB]: https://duckdb.org/docs/sql/data_types/map.html#creating-maps
616#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
617#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
618#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
619pub struct MapEntry {
620    /// Key expression of the map entry.
621    pub key: Box<Expr>,
622    /// Value expression of the map entry.
623    pub value: Box<Expr>,
624}
625
626impl fmt::Display for MapEntry {
627    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
628        write!(f, "{}: {}", self.key, self.value)
629    }
630}
631
632/// Options for `CAST` / `TRY_CAST`
633/// BigQuery: <https://cloud.google.com/bigquery/docs/reference/standard-sql/format-elements#formatting_syntax>
634#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
635#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
636#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
637pub enum CastFormat {
638    /// A simple cast format specified by a `Value`.
639    Value(ValueWithSpan),
640    /// A cast format with an explicit time zone: `(format, timezone)`.
641    ValueAtTimeZone(ValueWithSpan, ValueWithSpan),
642}
643
644/// An element of a JSON path.
645#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
646#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
647#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
648pub enum JsonPathElem {
649    /// Accesses an object field using dot notation, e.g. `obj:foo.bar.baz`.
650    ///
651    /// See <https://docs.snowflake.com/en/user-guide/querying-semistructured#dot-notation>.
652    Dot {
653        /// The object key text (without quotes).
654        key: String,
655        /// `true` when the key was quoted in the source.
656        quoted: bool,
657    },
658    /// Accesses an object field or array element using bracket notation,
659    /// e.g. `obj['foo']`.
660    ///
661    /// See <https://docs.snowflake.com/en/user-guide/querying-semistructured#bracket-notation>.
662    Bracket {
663        /// The expression used as the bracket key (string or numeric expression).
664        key: Expr,
665    },
666    /// Access an object field using colon bracket notation
667    /// e.g. `obj:['foo']`
668    ///
669    /// See <https://docs.databricks.com/en/sql/language-manual/functions/colonsign.html>
670    ColonBracket {
671        /// The expression used as the bracket key (string or numeric expression).
672        key: Expr,
673    },
674}
675
676/// A JSON path.
677///
678/// See <https://docs.snowflake.com/en/user-guide/querying-semistructured>.
679/// See <https://docs.databricks.com/en/sql/language-manual/sql-ref-json-path-expression.html>.
680#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
681#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
682#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
683pub struct JsonPath {
684    /// Sequence of path elements that form the JSON path.
685    pub path: Vec<JsonPathElem>,
686}
687
688impl fmt::Display for JsonPath {
689    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
690        for (i, elem) in self.path.iter().enumerate() {
691            match elem {
692                JsonPathElem::Dot { key, quoted } => {
693                    if i == 0 {
694                        write!(f, ":")?;
695                    } else {
696                        write!(f, ".")?;
697                    }
698
699                    if *quoted {
700                        write!(f, "\"{}\"", escape_double_quote_string(key))?;
701                    } else {
702                        write!(f, "{key}")?;
703                    }
704                }
705                JsonPathElem::Bracket { key } => {
706                    write!(f, "[{key}]")?;
707                }
708                JsonPathElem::ColonBracket { key } => {
709                    write!(f, ":[{key}]")?;
710                }
711            }
712        }
713        Ok(())
714    }
715}
716
717/// The syntax used for in a cast expression.
718#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
719#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
720#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
721pub enum CastKind {
722    /// The standard SQL cast syntax, e.g. `CAST(<expr> as <datatype>)`
723    Cast,
724    /// A cast that returns `NULL` on failure, e.g. `TRY_CAST(<expr> as <datatype>)`.
725    ///
726    /// See <https://docs.snowflake.com/en/sql-reference/functions/try_cast>.
727    /// See <https://learn.microsoft.com/en-us/sql/t-sql/functions/try-cast-transact-sql>.
728    TryCast,
729    /// A cast that returns `NULL` on failure, bigQuery-specific ,  e.g. `SAFE_CAST(<expr> as <datatype>)`.
730    ///
731    /// See <https://cloud.google.com/bigquery/docs/reference/standard-sql/functions-and-operators#safe_casting>.
732    SafeCast,
733    /// `<expr> :: <datatype>`
734    DoubleColon,
735}
736
737/// `MATCH` type for constraint references
738///
739/// See: <https://www.postgresql.org/docs/current/sql-createtable.html#SQL-CREATETABLE-PARMS-REFERENCES>
740#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
741#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
742#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
743pub enum ConstraintReferenceMatchKind {
744    /// `MATCH FULL`
745    Full,
746    /// `MATCH PARTIAL`
747    Partial,
748    /// `MATCH SIMPLE`
749    Simple,
750}
751
752impl fmt::Display for ConstraintReferenceMatchKind {
753    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
754        match self {
755            Self::Full => write!(f, "MATCH FULL"),
756            Self::Partial => write!(f, "MATCH PARTIAL"),
757            Self::Simple => write!(f, "MATCH SIMPLE"),
758        }
759    }
760}
761
762/// `EXTRACT` syntax variants.
763///
764/// In Snowflake dialect, the `EXTRACT` expression can support either the `from` syntax
765/// or the comma syntax.
766///
767/// See <https://docs.snowflake.com/en/sql-reference/functions/extract>
768#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
769#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
770#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
771pub enum ExtractSyntax {
772    /// `EXTRACT( <date_or_time_part> FROM <date_or_time_expr> )`
773    From,
774    /// `EXTRACT( <date_or_time_part> , <date_or_timestamp_expr> )`
775    Comma,
776}
777
778/// The syntax used in a CEIL or FLOOR expression.
779///
780/// The `CEIL/FLOOR(<datetime value expression> TO <time unit>)` is an Amazon Kinesis Data Analytics extension.
781/// See <https://docs.aws.amazon.com/kinesisanalytics/latest/sqlref/sql-reference-ceil.html> for
782/// details.
783///
784/// Other dialects either support `CEIL/FLOOR( <expr> [, <scale>])` format or just
785/// `CEIL/FLOOR(<expr>)`.
786#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
787#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
788#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
789pub enum CeilFloorKind {
790    /// `CEIL( <expr> TO <DateTimeField>)`
791    DateTimeField(DateTimeField),
792    /// `CEIL( <expr> [, <scale>])`
793    Scale(ValueWithSpan),
794}
795
796/// A WHEN clause in a CASE expression containing both
797/// the condition and its corresponding result
798#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
799#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
800#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
801pub struct CaseWhen {
802    /// The `WHEN` condition expression.
803    pub condition: Expr,
804    /// The expression returned when `condition` matches.
805    pub result: Expr,
806}
807
808impl fmt::Display for CaseWhen {
809    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
810        f.write_str("WHEN ")?;
811        self.condition.fmt(f)?;
812        f.write_str(" THEN")?;
813        SpaceOrNewline.fmt(f)?;
814        Indent(&self.result).fmt(f)?;
815        Ok(())
816    }
817}
818
819/// An SQL expression of any type.
820///
821/// # Semantics / Type Checking
822///
823/// The parser does not distinguish between expressions of different types
824/// (e.g. boolean vs string). The caller is responsible for detecting and
825/// validating types as necessary (for example  `WHERE 1` vs `SELECT 1=1`)
826/// See the [README.md] for more details.
827///
828/// [README.md]: https://github.com/apache/datafusion-sqlparser-rs/blob/main/README.md#syntax-vs-semantics
829///
830/// # Equality and Hashing Does not Include Source Locations
831///
832/// The `Expr` type implements `PartialEq` and `Eq` based on the semantic value
833/// of the expression (not bitwise comparison). This means that `Expr` instances
834/// that are semantically equivalent but have different spans (locations in the
835/// source tree) will compare as equal.
836#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
837#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
838#[cfg_attr(
839    feature = "visitor",
840    derive(Visit, VisitMut),
841    visit(with = "visit_expr")
842)]
843pub enum Expr {
844    /// Identifier e.g. table name or column name
845    Identifier(Ident),
846    /// Multi-part identifier, e.g. `table_alias.column` or `schema.table.col`
847    CompoundIdentifier(Vec<Ident>),
848    /// Multi-part expression access.
849    ///
850    /// This structure represents an access chain in structured / nested types
851    /// such as maps, arrays, and lists:
852    /// - Array
853    ///     - A 1-dim array `a[1]` will be represented like:
854    ///       `CompoundFieldAccess(Ident('a'), vec![Subscript(1)]`
855    ///     - A 2-dim array `a[1][2]` will be represented like:
856    ///       `CompoundFieldAccess(Ident('a'), vec![Subscript(1), Subscript(2)]`
857    /// - Map or Struct (Bracket-style)
858    ///     - A map `a['field1']` will be represented like:
859    ///       `CompoundFieldAccess(Ident('a'), vec![Subscript('field')]`
860    ///     - A 2-dim map `a['field1']['field2']` will be represented like:
861    ///       `CompoundFieldAccess(Ident('a'), vec![Subscript('field1'), Subscript('field2')]`
862    /// - Struct (Dot-style) (only effect when the chain contains both subscript and expr)
863    ///     - A struct access `a[field1].field2` will be represented like:
864    ///       `CompoundFieldAccess(Ident('a'), vec![Subscript('field1'), Ident('field2')]`
865    /// - If a struct access likes `a.field1.field2`, it will be represented by CompoundIdentifier([a, field1, field2])
866    CompoundFieldAccess {
867        /// The base expression being accessed.
868        root: Box<Expr>,
869        /// Sequence of access operations (subscript or identifier accesses).
870        access_chain: Vec<AccessExpr>,
871    },
872    /// Access data nested in a value containing semi-structured data, such as
873    /// the `VARIANT` type on Snowflake. for example `src:customer[0].name`.
874    ///
875    /// See <https://docs.snowflake.com/en/user-guide/querying-semistructured>.
876    /// See <https://docs.databricks.com/en/sql/language-manual/functions/colonsign.html>.
877    JsonAccess {
878        /// The value being queried.
879        value: Box<Expr>,
880        /// The path to the data to extract.
881        path: JsonPath,
882    },
883    /// `IS FALSE` operator
884    IsFalse(Box<Expr>),
885    /// `IS NOT FALSE` operator
886    IsNotFalse(Box<Expr>),
887    /// `IS TRUE` operator
888    IsTrue(Box<Expr>),
889    /// `IS NOT TRUE` operator
890    IsNotTrue(Box<Expr>),
891    /// `IS NULL` operator
892    IsNull(Box<Expr>),
893    /// `IS NOT NULL` operator
894    IsNotNull(Box<Expr>),
895    /// `IS UNKNOWN` operator
896    IsUnknown(Box<Expr>),
897    /// `IS NOT UNKNOWN` operator
898    IsNotUnknown(Box<Expr>),
899    /// `IS DISTINCT FROM` operator
900    IsDistinctFrom(Box<Expr>, Box<Expr>),
901    /// `IS NOT DISTINCT FROM` operator
902    IsNotDistinctFrom(Box<Expr>, Box<Expr>),
903    /// `<expr> IS [ NOT ] [ form ] NORMALIZED`
904    IsNormalized {
905        /// Expression being tested.
906        expr: Box<Expr>,
907        /// Optional normalization `form` (e.g., NFC, NFD).
908        form: Option<NormalizationForm>,
909        /// `true` when `NOT` is present.
910        negated: bool,
911    },
912    /// `[ NOT ] IN (val1, val2, ...)`
913    InList {
914        /// Left-hand expression to test for membership.
915        expr: Box<Expr>,
916        /// Literal list of expressions to check against.
917        list: Vec<Expr>,
918        /// `true` when the `NOT` modifier is present.
919        negated: bool,
920    },
921    /// `[ NOT ] IN (SELECT ...)`
922    InSubquery {
923        /// Left-hand expression to test for membership.
924        expr: Box<Expr>,
925        /// The subquery providing the candidate values.
926        subquery: Box<Query>,
927        /// `true` when the `NOT` modifier is present.
928        negated: bool,
929    },
930    /// `[ NOT ] IN UNNEST(array_expression)`
931    InUnnest {
932        /// Left-hand expression to test for membership.
933        expr: Box<Expr>,
934        /// Array expression being unnested.
935        array_expr: Box<Expr>,
936        /// `true` when the `NOT` modifier is present.
937        negated: bool,
938    },
939    /// `<expr> [ NOT ] BETWEEN <low> AND <high>`
940    Between {
941        /// Expression being compared.
942        expr: Box<Expr>,
943        /// `true` when the `NOT` modifier is present.
944        negated: bool,
945        /// Lower bound.
946        low: Box<Expr>,
947        /// Upper bound.
948        high: Box<Expr>,
949    },
950    /// Binary operation e.g. `1 + 1` or `foo > bar`
951    BinaryOp {
952        /// Left operand.
953        left: Box<Expr>,
954        /// Operator between operands.
955        op: BinaryOperator,
956        /// Right operand.
957        right: Box<Expr>,
958    },
959    /// `[NOT] LIKE <pattern> [ESCAPE <escape_character>]`
960    Like {
961        /// `true` when `NOT` is present.
962        negated: bool,
963        /// Snowflake supports the ANY keyword to match against a list of patterns
964        /// <https://docs.snowflake.com/en/sql-reference/functions/like_any>
965        any: bool,
966        /// Expression to match.
967        expr: Box<Expr>,
968        /// Pattern expression.
969        pattern: Box<Expr>,
970        /// Optional escape character.
971        escape_char: Option<ValueWithSpan>,
972    },
973    /// `ILIKE` (case-insensitive `LIKE`)
974    ILike {
975        /// `true` when `NOT` is present.
976        negated: bool,
977        /// Snowflake supports the ANY keyword to match against a list of patterns
978        /// <https://docs.snowflake.com/en/sql-reference/functions/like_any>
979        any: bool,
980        /// Expression to match.
981        expr: Box<Expr>,
982        /// Pattern expression.
983        pattern: Box<Expr>,
984        /// Optional escape character.
985        escape_char: Option<ValueWithSpan>,
986    },
987    /// `SIMILAR TO` regex
988    SimilarTo {
989        /// `true` when `NOT` is present.
990        negated: bool,
991        /// Expression to test.
992        expr: Box<Expr>,
993        /// Pattern expression.
994        pattern: Box<Expr>,
995        /// Optional escape character.
996        escape_char: Option<ValueWithSpan>,
997    },
998    /// MySQL: `RLIKE` regex or `REGEXP` regex
999    RLike {
1000        /// `true` when `NOT` is present.
1001        negated: bool,
1002        /// Expression to test.
1003        expr: Box<Expr>,
1004        /// Pattern expression.
1005        pattern: Box<Expr>,
1006        /// true for REGEXP, false for RLIKE (no difference in semantics)
1007        regexp: bool,
1008    },
1009    /// `ANY` operation e.g. `foo > ANY(bar)`, comparison operator is one of `[=, >, <, =>, =<, !=]`
1010    /// <https://docs.snowflake.com/en/sql-reference/operators-subquery#all-any>
1011    AnyOp {
1012        /// Left operand.
1013        left: Box<Expr>,
1014        /// Comparison operator.
1015        compare_op: BinaryOperator,
1016        /// Right-hand subquery expression.
1017        right: Box<Expr>,
1018        /// ANY and SOME are synonymous: <https://docs.cloudera.com/cdw-runtime/cloud/using-hiveql/topics/hive_comparison_predicates.html>
1019        is_some: bool,
1020    },
1021    /// `ALL` operation e.g. `foo > ALL(bar)`, comparison operator is one of `[=, >, <, =>, =<, !=]`
1022    /// <https://docs.snowflake.com/en/sql-reference/operators-subquery#all-any>
1023    AllOp {
1024        /// Left operand.
1025        left: Box<Expr>,
1026        /// Comparison operator.
1027        compare_op: BinaryOperator,
1028        /// Right-hand subquery expression.
1029        right: Box<Expr>,
1030    },
1031
1032    /// Unary operation e.g. `NOT foo`
1033    UnaryOp {
1034        /// The unary operator (e.g., `NOT`, `-`).
1035        op: UnaryOperator,
1036        /// Operand expression.
1037        expr: Box<Expr>,
1038    },
1039    /// CONVERT a value to a different data type or character encoding. e.g. `CONVERT(foo USING utf8mb4)`
1040    Convert {
1041        /// CONVERT (false) or TRY_CONVERT (true)
1042        /// <https://learn.microsoft.com/en-us/sql/t-sql/functions/try-convert-transact-sql?view=sql-server-ver16>
1043        is_try: bool,
1044        /// The expression to convert.
1045        expr: Box<Expr>,
1046        /// The target data type, if provided.
1047        data_type: Option<DataType>,
1048        /// Optional target character encoding (e.g., `utf8mb4`).
1049        charset: Option<ObjectName>,
1050        /// `true` when target precedes the value (MSSQL syntax).
1051        target_before_value: bool,
1052        /// How to translate the expression.
1053        ///
1054        /// [MSSQL]: https://learn.microsoft.com/en-us/sql/t-sql/functions/cast-and-convert-transact-sql?view=sql-server-ver16#style
1055        styles: Vec<Expr>,
1056    },
1057    /// `CAST` an expression to a different data type e.g. `CAST(foo AS VARCHAR(123))`
1058    Cast {
1059        /// The cast kind (e.g., `CAST`, `TRY_CAST`).
1060        kind: CastKind,
1061        /// Expression being cast.
1062        expr: Box<Expr>,
1063        /// Target data type.
1064        data_type: DataType,
1065        /// [MySQL] allows CAST(... AS type ARRAY) in functional index definitions for InnoDB
1066        /// multi-valued indices. It's not really a datatype, and is only allowed in `CAST` in key
1067        /// specifications, so it's a flag here.
1068        ///
1069        /// [MySQL]: https://dev.mysql.com/doc/refman/8.4/en/cast-functions.html#function_cast
1070        array: bool,
1071        /// Optional CAST(string_expression AS type FORMAT format_string_expression) as used by [BigQuery]
1072        ///
1073        /// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/format-elements#formatting_syntax
1074        format: Option<CastFormat>,
1075    },
1076    /// AT a timestamp to a different timezone e.g. `FROM_UNIXTIME(0) AT TIME ZONE 'UTC-06:00'`
1077    AtTimeZone {
1078        /// Timestamp expression to shift.
1079        timestamp: Box<Expr>,
1080        /// Time zone expression to apply.
1081        time_zone: Box<Expr>,
1082    },
1083    /// Extract a field from a timestamp e.g. `EXTRACT(MONTH FROM foo)`
1084    /// Or `EXTRACT(MONTH, foo)`
1085    ///
1086    /// Syntax:
1087    /// ```sql
1088    /// EXTRACT(DateTimeField FROM <expr>) | EXTRACT(DateTimeField, <expr>)
1089    /// ```
1090    Extract {
1091        /// Which datetime field is being extracted.
1092        field: DateTimeField,
1093        /// Syntax variant used (`From` or `Comma`).
1094        syntax: ExtractSyntax,
1095        /// Expression to extract from.
1096        expr: Box<Expr>,
1097    },
1098    /// ```sql
1099    /// CEIL(<expr> [TO DateTimeField])
1100    /// ```
1101    /// ```sql
1102    /// CEIL( <input_expr> [, <scale_expr> ] )
1103    /// ```
1104    Ceil {
1105        /// Expression to ceil.
1106        expr: Box<Expr>,
1107        /// The CEIL/FLOOR kind (datetime field or scale).
1108        field: CeilFloorKind,
1109    },
1110    /// ```sql
1111    /// FLOOR(<expr> [TO DateTimeField])
1112    /// ```
1113    /// ```sql
1114    /// FLOOR( <input_expr> [, <scale_expr> ] )
1115    ///
1116    Floor {
1117        /// Expression to floor.
1118        expr: Box<Expr>,
1119        /// The CEIL/FLOOR kind (datetime field or scale).
1120        field: CeilFloorKind,
1121    },
1122    /// ```sql
1123    /// POSITION(<expr> in <expr>)
1124    /// ```
1125    Position {
1126        /// Expression to search for.
1127        expr: Box<Expr>,
1128        /// Expression to search in.
1129        r#in: Box<Expr>,
1130    },
1131    /// ```sql
1132    /// SUBSTRING(<expr> [FROM <expr>] [FOR <expr>])
1133    /// ```
1134    /// or
1135    /// ```sql
1136    /// SUBSTRING(<expr>, <expr>, <expr>)
1137    /// ```
1138    Substring {
1139        /// Source expression.
1140        expr: Box<Expr>,
1141        /// Optional `FROM` expression.
1142        substring_from: Option<Box<Expr>>,
1143        /// Optional `FOR` expression.
1144        substring_for: Option<Box<Expr>>,
1145
1146        /// false if the expression is represented using the `SUBSTRING(expr [FROM start] [FOR len])` syntax
1147        /// true if the expression is represented using the `SUBSTRING(expr, start, len)` syntax
1148        /// This flag is used for formatting.
1149        special: bool,
1150
1151        /// true if the expression is represented using the `SUBSTR` shorthand
1152        /// This flag is used for formatting.
1153        shorthand: bool,
1154    },
1155    /// ```sql
1156    /// TRIM([BOTH | LEADING | TRAILING] [<expr> FROM] <expr>)
1157    /// TRIM(<expr>)
1158    /// TRIM(<expr>, [, characters]) -- PostgreSQL, DuckDB, Snowflake, BigQuery, Generic
1159    /// ```
1160    Trim {
1161        /// Which side to trim: `BOTH`, `LEADING`, or `TRAILING`.
1162        trim_where: Option<TrimWhereField>,
1163        /// Optional expression specifying what to trim from the value `expr`.
1164        trim_what: Option<Box<Expr>>,
1165        /// The expression to trim from.
1166        expr: Box<Expr>,
1167        /// Optional list of characters to trim (dialect-specific).
1168        trim_characters: Option<Vec<Expr>>,
1169    },
1170    /// ```sql
1171    /// OVERLAY(<expr> PLACING <expr> FROM <expr>[ FOR <expr> ]
1172    /// ```
1173    Overlay {
1174        /// The target expression being overlayed.
1175        expr: Box<Expr>,
1176        /// The expression to place into the target.
1177        overlay_what: Box<Expr>,
1178        /// The `FROM` position expression indicating where to start overlay.
1179        overlay_from: Box<Expr>,
1180        /// Optional `FOR` length expression limiting the overlay span.
1181        overlay_for: Option<Box<Expr>>,
1182    },
1183    /// `expr COLLATE collation`
1184    Collate {
1185        /// The expression being collated.
1186        expr: Box<Expr>,
1187        /// The collation name to apply to the expression.
1188        collation: ObjectName,
1189    },
1190    /// Nested expression e.g. `(foo > bar)` or `(1)`
1191    Nested(Box<Expr>),
1192    /// A literal value, such as string, number, date or NULL
1193    Value(ValueWithSpan),
1194    /// Prefixed expression, e.g. introducer strings, projection prefix
1195    /// <https://dev.mysql.com/doc/refman/8.0/en/charset-introducer.html>
1196    /// <https://docs.snowflake.com/en/sql-reference/constructs/connect-by>
1197    Prefixed {
1198        /// The prefix identifier (introducer or projection prefix).
1199        prefix: Ident,
1200        /// The value expression being prefixed.
1201        /// Hint: you can unwrap the string value using `value.into_string()`.
1202        value: Box<Expr>,
1203    },
1204    /// A constant of form `<data_type> 'value'`.
1205    /// This can represent ANSI SQL `DATE`, `TIME`, and `TIMESTAMP` literals (such as `DATE '2020-01-01'`),
1206    /// as well as constants of other types (a non-standard PostgreSQL extension).
1207    TypedString(TypedString),
1208    /// Scalar function call e.g. `LEFT(foo, 5)`
1209    Function(Function),
1210    /// `CASE [<operand>] WHEN <condition> THEN <result> ... [ELSE <result>] END`
1211    ///
1212    /// Note we only recognize a complete single expression as `<condition>`,
1213    /// not `< 0` nor `1, 2, 3` as allowed in a `<simple when clause>` per
1214    /// <https://jakewheat.github.io/sql-overview/sql-2011-foundation-grammar.html#simple-when-clause>
1215    Case {
1216        /// The attached `CASE` token (keeps original spacing/comments).
1217        case_token: AttachedToken,
1218        /// The attached `END` token (keeps original spacing/comments).
1219        end_token: AttachedToken,
1220        /// Optional operand expression after `CASE` (for simple CASE).
1221        operand: Option<Box<Expr>>,
1222        /// The `WHEN ... THEN` conditions and results.
1223        conditions: Vec<CaseWhen>,
1224        /// Optional `ELSE` result expression.
1225        else_result: Option<Box<Expr>>,
1226    },
1227    /// An exists expression `[ NOT ] EXISTS(SELECT ...)`, used in expressions like
1228    /// `WHERE [ NOT ] EXISTS (SELECT ...)`.
1229    Exists {
1230        /// The subquery checked by `EXISTS`.
1231        subquery: Box<Query>,
1232        /// Whether the `EXISTS` is negated (`NOT EXISTS`).
1233        negated: bool,
1234    },
1235    /// A parenthesized subquery `(SELECT ...)`, used in expression like
1236    /// `SELECT (subquery) AS x` or `WHERE (subquery) = x`
1237    Subquery(Box<Query>),
1238    /// The `GROUPING SETS` expr.
1239    GroupingSets(Vec<Vec<Expr>>),
1240    /// The `CUBE` expr.
1241    Cube(Vec<Vec<Expr>>),
1242    /// The `ROLLUP` expr.
1243    Rollup(Vec<Vec<Expr>>),
1244    /// ROW / TUPLE a single value, such as `SELECT (1, 2)`
1245    Tuple(Vec<Expr>),
1246    /// `Struct` literal expression
1247    /// Syntax:
1248    /// ```sql
1249    /// STRUCT<[field_name] field_type, ...>( expr1 [, ... ])
1250    ///
1251    /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-types#struct_type)
1252    /// [Databricks](https://docs.databricks.com/en/sql/language-manual/functions/struct.html)
1253    /// ```
1254    Struct {
1255        /// Struct values.
1256        values: Vec<Expr>,
1257        /// Struct field definitions.
1258        fields: Vec<StructField>,
1259    },
1260    /// `BigQuery` specific: An named expression in a typeless struct [1]
1261    ///
1262    /// Syntax
1263    /// ```sql
1264    /// 1 AS A
1265    /// ```
1266    /// [1]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-types#struct_type
1267    Named {
1268        /// The expression being named.
1269        expr: Box<Expr>,
1270        /// The assigned identifier name for the expression.
1271        name: Ident,
1272    },
1273    /// `DuckDB` specific `Struct` literal expression [1]
1274    ///
1275    /// Syntax:
1276    /// ```sql
1277    /// syntax: {'field_name': expr1[, ... ]}
1278    /// ```
1279    /// [1]: https://duckdb.org/docs/sql/data_types/struct#creating-structs
1280    Dictionary(Vec<DictionaryField>),
1281    /// `DuckDB` specific `Map` literal expression [1]
1282    ///
1283    /// Syntax:
1284    /// ```sql
1285    /// syntax: Map {key1: value1[, ... ]}
1286    /// ```
1287    /// [1]: https://duckdb.org/docs/sql/data_types/map#creating-maps
1288    Map(Map),
1289    /// An array expression e.g. `ARRAY[1, 2]`
1290    Array(Array),
1291    /// An interval expression e.g. `INTERVAL '1' YEAR`
1292    Interval(Interval),
1293    /// `MySQL` specific text search function [(1)].
1294    ///
1295    /// Syntax:
1296    /// ```sql
1297    /// MATCH (<col>, <col>, ...) AGAINST (<expr> [<search modifier>])
1298    ///
1299    /// <col> = CompoundIdentifier
1300    /// <expr> = String literal
1301    /// ```
1302    /// [(1)]: https://dev.mysql.com/doc/refman/8.0/en/fulltext-search.html#function_match
1303    MatchAgainst {
1304        /// `(<col>, <col>, ...)`.
1305        columns: Vec<ObjectName>,
1306        /// `<expr>`.
1307        match_value: ValueWithSpan,
1308        /// `<search modifier>`
1309        opt_search_modifier: Option<SearchModifier>,
1310    },
1311    /// An unqualified `*` wildcard token (e.g. `*`).
1312    Wildcard(AttachedToken),
1313    /// Qualified wildcard, e.g. `alias.*` or `schema.table.*`.
1314    /// (Same caveats apply to `QualifiedWildcard` as to `Wildcard`.)
1315    QualifiedWildcard(ObjectName, AttachedToken),
1316    /// Some dialects support an older syntax for outer joins where columns are
1317    /// marked with the `(+)` operator in the WHERE clause, for example:
1318    ///
1319    /// ```sql
1320    /// SELECT t1.c1, t2.c2 FROM t1, t2 WHERE t1.c1 = t2.c2 (+)
1321    /// ```
1322    ///
1323    /// which is equivalent to
1324    ///
1325    /// ```sql
1326    /// SELECT t1.c1, t2.c2 FROM t1 LEFT OUTER JOIN t2 ON t1.c1 = t2.c2
1327    /// ```
1328    ///
1329    /// See <https://docs.snowflake.com/en/sql-reference/constructs/where#joins-in-the-where-clause>.
1330    OuterJoin(Box<Expr>),
1331    /// A reference to the prior level in a CONNECT BY clause.
1332    Prior(Box<Expr>),
1333    /// A lambda function.
1334    ///
1335    /// Syntax:
1336    /// ```plaintext
1337    /// param -> expr | (param1, ...) -> expr
1338    /// ```
1339    ///
1340    /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/functions#higher-order-functions---operator-and-lambdaparams-expr-function)
1341    /// [Databricks](https://docs.databricks.com/en/sql/language-manual/sql-ref-lambda-functions.html)
1342    /// [DuckDB](https://duckdb.org/docs/stable/sql/functions/lambda)
1343    Lambda(LambdaFunction),
1344    /// Checks membership of a value in a JSON array
1345    MemberOf(MemberOf),
1346}
1347
1348impl Expr {
1349    /// Creates a new [`Expr::Value`]
1350    pub fn value(value: impl Into<ValueWithSpan>) -> Self {
1351        Expr::Value(value.into())
1352    }
1353}
1354
1355/// The contents inside the `[` and `]` in a subscript expression.
1356#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1357#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1358#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1359pub enum Subscript {
1360    /// Accesses the element of the array at the given index.
1361    Index {
1362        /// The index expression used to access the array element.
1363        index: Expr,
1364    },
1365
1366    /// Accesses a slice of an array on PostgreSQL, e.g.
1367    ///
1368    /// ```plaintext
1369    /// => select (array[1,2,3,4,5,6])[2:5];
1370    /// -----------
1371    /// {2,3,4,5}
1372    /// ```
1373    ///
1374    /// The lower and/or upper bound can be omitted to slice from the start or
1375    /// end of the array respectively.
1376    ///
1377    /// See <https://www.postgresql.org/docs/current/arrays.html#ARRAYS-ACCESSING>.
1378    ///
1379    /// Also supports an optional "stride" as the last element (this is not
1380    /// supported by postgres), e.g.
1381    ///
1382    /// ```plaintext
1383    /// => select (array[1,2,3,4,5,6])[1:6:2];
1384    /// -----------
1385    /// {1,3,5}
1386    /// ```
1387    Slice {
1388        /// Optional lower bound for the slice (inclusive).
1389        lower_bound: Option<Expr>,
1390        /// Optional upper bound for the slice (inclusive).
1391        upper_bound: Option<Expr>,
1392        /// Optional stride for the slice (step size).
1393        stride: Option<Expr>,
1394    },
1395}
1396
1397impl fmt::Display for Subscript {
1398    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1399        match self {
1400            Subscript::Index { index } => write!(f, "{index}"),
1401            Subscript::Slice {
1402                lower_bound,
1403                upper_bound,
1404                stride,
1405            } => {
1406                if let Some(lower) = lower_bound {
1407                    write!(f, "{lower}")?;
1408                }
1409                write!(f, ":")?;
1410                if let Some(upper) = upper_bound {
1411                    write!(f, "{upper}")?;
1412                }
1413                if let Some(stride) = stride {
1414                    write!(f, ":")?;
1415                    write!(f, "{stride}")?;
1416                }
1417                Ok(())
1418            }
1419        }
1420    }
1421}
1422
1423/// An element of a [`Expr::CompoundFieldAccess`].
1424/// It can be an expression or a subscript.
1425#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1426#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1427#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1428pub enum AccessExpr {
1429    /// Accesses a field using dot notation, e.g. `foo.bar.baz`.
1430    Dot(Expr),
1431    /// Accesses a field or array element using bracket notation, e.g. `foo['bar']`.
1432    Subscript(Subscript),
1433}
1434
1435impl fmt::Display for AccessExpr {
1436    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1437        match self {
1438            AccessExpr::Dot(expr) => write!(f, ".{expr}"),
1439            AccessExpr::Subscript(subscript) => write!(f, "[{subscript}]"),
1440        }
1441    }
1442}
1443
1444/// A lambda function.
1445#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1446#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1447#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1448pub struct LambdaFunction {
1449    /// The parameters to the lambda function.
1450    pub params: OneOrManyWithParens<LambdaFunctionParameter>,
1451    /// The body of the lambda function.
1452    pub body: Box<Expr>,
1453    /// The syntax style used to write the lambda function.
1454    pub syntax: LambdaSyntax,
1455}
1456
1457impl fmt::Display for LambdaFunction {
1458    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1459        match self.syntax {
1460            LambdaSyntax::Arrow => write!(f, "{} -> {}", self.params, self.body),
1461            LambdaSyntax::LambdaKeyword => {
1462                // For lambda keyword syntax, display params without parentheses
1463                // e.g., `lambda x, y : expr` not `lambda (x, y) : expr`
1464                write!(f, "lambda ")?;
1465                match &self.params {
1466                    OneOrManyWithParens::One(p) => write!(f, "{p}")?,
1467                    OneOrManyWithParens::Many(ps) => write!(f, "{}", display_comma_separated(ps))?,
1468                };
1469                write!(f, " : {}", self.body)
1470            }
1471        }
1472    }
1473}
1474
1475/// A parameter to a lambda function, optionally with a data type.
1476#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1477#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1478#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1479pub struct LambdaFunctionParameter {
1480    /// The name of the parameter
1481    pub name: Ident,
1482    /// The optional data type of the parameter
1483    /// [Snowflake Syntax](https://docs.snowflake.com/en/sql-reference/functions/filter#arguments)
1484    pub data_type: Option<DataType>,
1485}
1486
1487impl fmt::Display for LambdaFunctionParameter {
1488    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1489        match &self.data_type {
1490            Some(dt) => write!(f, "{} {}", self.name, dt),
1491            None => write!(f, "{}", self.name),
1492        }
1493    }
1494}
1495
1496/// The syntax style for a lambda function.
1497#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Copy)]
1498#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1499#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1500pub enum LambdaSyntax {
1501    /// Arrow syntax: `param -> expr` or `(param1, param2) -> expr`
1502    ///
1503    /// <https://docs.databricks.com/aws/en/sql/language-manual/sql-ref-lambda-functions>
1504    ///
1505    /// Supported, but deprecated in DuckDB:
1506    /// <https://duckdb.org/docs/stable/sql/functions/lambda>
1507    Arrow,
1508    /// Lambda keyword syntax: `lambda param : expr` or `lambda param1, param2 : expr`
1509    ///
1510    /// Recommended in DuckDB:
1511    /// <https://duckdb.org/docs/stable/sql/functions/lambda>
1512    LambdaKeyword,
1513}
1514
1515/// Encapsulates the common pattern in SQL where either one unparenthesized item
1516/// such as an identifier or expression is permitted, or multiple of the same
1517/// item in a parenthesized list. For accessing items regardless of the form,
1518/// `OneOrManyWithParens` implements `Deref<Target = [T]>` and `IntoIterator`,
1519/// so you can call slice methods on it and iterate over items
1520/// # Examples
1521/// Accessing as a slice:
1522/// ```
1523/// # use sqlparser::ast::OneOrManyWithParens;
1524/// let one = OneOrManyWithParens::One("a");
1525///
1526/// assert_eq!(one[0], "a");
1527/// assert_eq!(one.len(), 1);
1528/// ```
1529/// Iterating:
1530/// ```
1531/// # use sqlparser::ast::OneOrManyWithParens;
1532/// let one = OneOrManyWithParens::One("a");
1533/// let many = OneOrManyWithParens::Many(vec!["a", "b"]);
1534///
1535/// assert_eq!(one.into_iter().chain(many).collect::<Vec<_>>(), vec!["a", "a", "b"] );
1536/// ```
1537#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1538#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1539#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1540pub enum OneOrManyWithParens<T> {
1541    /// A single `T`, unparenthesized.
1542    One(T),
1543    /// One or more `T`s, parenthesized.
1544    Many(Vec<T>),
1545}
1546
1547impl<T> Deref for OneOrManyWithParens<T> {
1548    type Target = [T];
1549
1550    fn deref(&self) -> &[T] {
1551        match self {
1552            OneOrManyWithParens::One(one) => core::slice::from_ref(one),
1553            OneOrManyWithParens::Many(many) => many,
1554        }
1555    }
1556}
1557
1558impl<T> AsRef<[T]> for OneOrManyWithParens<T> {
1559    fn as_ref(&self) -> &[T] {
1560        self
1561    }
1562}
1563
1564impl<'a, T> IntoIterator for &'a OneOrManyWithParens<T> {
1565    type Item = &'a T;
1566    type IntoIter = core::slice::Iter<'a, T>;
1567
1568    fn into_iter(self) -> Self::IntoIter {
1569        self.iter()
1570    }
1571}
1572
1573/// Owned iterator implementation of `OneOrManyWithParens`
1574#[derive(Debug, Clone)]
1575pub struct OneOrManyWithParensIntoIter<T> {
1576    inner: OneOrManyWithParensIntoIterInner<T>,
1577}
1578
1579#[derive(Debug, Clone)]
1580enum OneOrManyWithParensIntoIterInner<T> {
1581    One(core::iter::Once<T>),
1582    Many(<Vec<T> as IntoIterator>::IntoIter),
1583}
1584
1585impl<T> core::iter::FusedIterator for OneOrManyWithParensIntoIter<T>
1586where
1587    core::iter::Once<T>: core::iter::FusedIterator,
1588    <Vec<T> as IntoIterator>::IntoIter: core::iter::FusedIterator,
1589{
1590}
1591
1592impl<T> core::iter::ExactSizeIterator for OneOrManyWithParensIntoIter<T>
1593where
1594    core::iter::Once<T>: core::iter::ExactSizeIterator,
1595    <Vec<T> as IntoIterator>::IntoIter: core::iter::ExactSizeIterator,
1596{
1597}
1598
1599impl<T> core::iter::Iterator for OneOrManyWithParensIntoIter<T> {
1600    type Item = T;
1601
1602    fn next(&mut self) -> Option<Self::Item> {
1603        match &mut self.inner {
1604            OneOrManyWithParensIntoIterInner::One(one) => one.next(),
1605            OneOrManyWithParensIntoIterInner::Many(many) => many.next(),
1606        }
1607    }
1608
1609    fn size_hint(&self) -> (usize, Option<usize>) {
1610        match &self.inner {
1611            OneOrManyWithParensIntoIterInner::One(one) => one.size_hint(),
1612            OneOrManyWithParensIntoIterInner::Many(many) => many.size_hint(),
1613        }
1614    }
1615
1616    fn count(self) -> usize
1617    where
1618        Self: Sized,
1619    {
1620        match self.inner {
1621            OneOrManyWithParensIntoIterInner::One(one) => one.count(),
1622            OneOrManyWithParensIntoIterInner::Many(many) => many.count(),
1623        }
1624    }
1625
1626    fn fold<B, F>(mut self, init: B, f: F) -> B
1627    where
1628        Self: Sized,
1629        F: FnMut(B, Self::Item) -> B,
1630    {
1631        match &mut self.inner {
1632            OneOrManyWithParensIntoIterInner::One(one) => one.fold(init, f),
1633            OneOrManyWithParensIntoIterInner::Many(many) => many.fold(init, f),
1634        }
1635    }
1636}
1637
1638impl<T> core::iter::DoubleEndedIterator for OneOrManyWithParensIntoIter<T> {
1639    fn next_back(&mut self) -> Option<Self::Item> {
1640        match &mut self.inner {
1641            OneOrManyWithParensIntoIterInner::One(one) => one.next_back(),
1642            OneOrManyWithParensIntoIterInner::Many(many) => many.next_back(),
1643        }
1644    }
1645}
1646
1647impl<T> IntoIterator for OneOrManyWithParens<T> {
1648    type Item = T;
1649
1650    type IntoIter = OneOrManyWithParensIntoIter<T>;
1651
1652    fn into_iter(self) -> Self::IntoIter {
1653        let inner = match self {
1654            OneOrManyWithParens::One(one) => {
1655                OneOrManyWithParensIntoIterInner::One(core::iter::once(one))
1656            }
1657            OneOrManyWithParens::Many(many) => {
1658                OneOrManyWithParensIntoIterInner::Many(many.into_iter())
1659            }
1660        };
1661
1662        OneOrManyWithParensIntoIter { inner }
1663    }
1664}
1665
1666impl<T> fmt::Display for OneOrManyWithParens<T>
1667where
1668    T: fmt::Display,
1669{
1670    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1671        match self {
1672            OneOrManyWithParens::One(value) => write!(f, "{value}"),
1673            OneOrManyWithParens::Many(values) => {
1674                write!(f, "({})", display_comma_separated(values))
1675            }
1676        }
1677    }
1678}
1679
1680impl fmt::Display for CastFormat {
1681    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1682        match self {
1683            CastFormat::Value(v) => write!(f, "{v}"),
1684            CastFormat::ValueAtTimeZone(v, tz) => write!(f, "{v} AT TIME ZONE {tz}"),
1685        }
1686    }
1687}
1688
1689impl fmt::Display for Expr {
1690    #[cfg_attr(feature = "recursive-protection", recursive::recursive)]
1691    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1692        match self {
1693            Expr::Identifier(s) => write!(f, "{s}"),
1694            Expr::Wildcard(_) => f.write_str("*"),
1695            Expr::QualifiedWildcard(prefix, _) => write!(f, "{prefix}.*"),
1696            Expr::CompoundIdentifier(s) => write!(f, "{}", display_separated(s, ".")),
1697            Expr::CompoundFieldAccess { root, access_chain } => {
1698                write!(f, "{root}")?;
1699                for field in access_chain {
1700                    write!(f, "{field}")?;
1701                }
1702                Ok(())
1703            }
1704            Expr::IsTrue(ast) => write!(f, "{ast} IS TRUE"),
1705            Expr::IsNotTrue(ast) => write!(f, "{ast} IS NOT TRUE"),
1706            Expr::IsFalse(ast) => write!(f, "{ast} IS FALSE"),
1707            Expr::IsNotFalse(ast) => write!(f, "{ast} IS NOT FALSE"),
1708            Expr::IsNull(ast) => write!(f, "{ast} IS NULL"),
1709            Expr::IsNotNull(ast) => write!(f, "{ast} IS NOT NULL"),
1710            Expr::IsUnknown(ast) => write!(f, "{ast} IS UNKNOWN"),
1711            Expr::IsNotUnknown(ast) => write!(f, "{ast} IS NOT UNKNOWN"),
1712            Expr::InList {
1713                expr,
1714                list,
1715                negated,
1716            } => write!(
1717                f,
1718                "{} {}IN ({})",
1719                expr,
1720                if *negated { "NOT " } else { "" },
1721                display_comma_separated(list)
1722            ),
1723            Expr::InSubquery {
1724                expr,
1725                subquery,
1726                negated,
1727            } => write!(
1728                f,
1729                "{} {}IN ({})",
1730                expr,
1731                if *negated { "NOT " } else { "" },
1732                subquery
1733            ),
1734            Expr::InUnnest {
1735                expr,
1736                array_expr,
1737                negated,
1738            } => write!(
1739                f,
1740                "{} {}IN UNNEST({})",
1741                expr,
1742                if *negated { "NOT " } else { "" },
1743                array_expr
1744            ),
1745            Expr::Between {
1746                expr,
1747                negated,
1748                low,
1749                high,
1750            } => write!(
1751                f,
1752                "{} {}BETWEEN {} AND {}",
1753                expr,
1754                if *negated { "NOT " } else { "" },
1755                low,
1756                high
1757            ),
1758            Expr::BinaryOp { left, op, right } => write!(f, "{left} {op} {right}"),
1759            Expr::Like {
1760                negated,
1761                expr,
1762                pattern,
1763                escape_char,
1764                any,
1765            } => match escape_char {
1766                Some(ch) => write!(
1767                    f,
1768                    "{} {}LIKE {}{} ESCAPE {}",
1769                    expr,
1770                    if *negated { "NOT " } else { "" },
1771                    if *any { "ANY " } else { "" },
1772                    pattern,
1773                    ch
1774                ),
1775                _ => write!(
1776                    f,
1777                    "{} {}LIKE {}{}",
1778                    expr,
1779                    if *negated { "NOT " } else { "" },
1780                    if *any { "ANY " } else { "" },
1781                    pattern
1782                ),
1783            },
1784            Expr::ILike {
1785                negated,
1786                expr,
1787                pattern,
1788                escape_char,
1789                any,
1790            } => match escape_char {
1791                Some(ch) => write!(
1792                    f,
1793                    "{} {}ILIKE {}{} ESCAPE {}",
1794                    expr,
1795                    if *negated { "NOT " } else { "" },
1796                    if *any { "ANY" } else { "" },
1797                    pattern,
1798                    ch
1799                ),
1800                _ => write!(
1801                    f,
1802                    "{} {}ILIKE {}{}",
1803                    expr,
1804                    if *negated { "NOT " } else { "" },
1805                    if *any { "ANY " } else { "" },
1806                    pattern
1807                ),
1808            },
1809            Expr::RLike {
1810                negated,
1811                expr,
1812                pattern,
1813                regexp,
1814            } => write!(
1815                f,
1816                "{} {}{} {}",
1817                expr,
1818                if *negated { "NOT " } else { "" },
1819                if *regexp { "REGEXP" } else { "RLIKE" },
1820                pattern
1821            ),
1822            Expr::IsNormalized {
1823                expr,
1824                form,
1825                negated,
1826            } => {
1827                let not_ = if *negated { "NOT " } else { "" };
1828                if form.is_none() {
1829                    write!(f, "{expr} IS {not_}NORMALIZED")
1830                } else {
1831                    write!(
1832                        f,
1833                        "{} IS {}{} NORMALIZED",
1834                        expr,
1835                        not_,
1836                        form.as_ref().unwrap()
1837                    )
1838                }
1839            }
1840            Expr::SimilarTo {
1841                negated,
1842                expr,
1843                pattern,
1844                escape_char,
1845            } => match escape_char {
1846                Some(ch) => write!(
1847                    f,
1848                    "{} {}SIMILAR TO {} ESCAPE {}",
1849                    expr,
1850                    if *negated { "NOT " } else { "" },
1851                    pattern,
1852                    ch
1853                ),
1854                _ => write!(
1855                    f,
1856                    "{} {}SIMILAR TO {}",
1857                    expr,
1858                    if *negated { "NOT " } else { "" },
1859                    pattern
1860                ),
1861            },
1862            Expr::AnyOp {
1863                left,
1864                compare_op,
1865                right,
1866                is_some,
1867            } => {
1868                let add_parens = !matches!(right.as_ref(), Expr::Subquery(_));
1869                write!(
1870                    f,
1871                    "{left} {compare_op} {}{}{right}{}",
1872                    if *is_some { "SOME" } else { "ANY" },
1873                    if add_parens { "(" } else { "" },
1874                    if add_parens { ")" } else { "" },
1875                )
1876            }
1877            Expr::AllOp {
1878                left,
1879                compare_op,
1880                right,
1881            } => {
1882                let add_parens = !matches!(right.as_ref(), Expr::Subquery(_));
1883                write!(
1884                    f,
1885                    "{left} {compare_op} ALL{}{right}{}",
1886                    if add_parens { "(" } else { "" },
1887                    if add_parens { ")" } else { "" },
1888                )
1889            }
1890            Expr::UnaryOp { op, expr } => {
1891                if op == &UnaryOperator::PGPostfixFactorial {
1892                    write!(f, "{expr}{op}")
1893                } else if matches!(
1894                    op,
1895                    UnaryOperator::Not
1896                        | UnaryOperator::Hash
1897                        | UnaryOperator::AtDashAt
1898                        | UnaryOperator::DoubleAt
1899                        | UnaryOperator::QuestionDash
1900                        | UnaryOperator::QuestionPipe
1901                ) {
1902                    write!(f, "{op} {expr}")
1903                } else {
1904                    write!(f, "{op}{expr}")
1905                }
1906            }
1907            Expr::Convert {
1908                is_try,
1909                expr,
1910                target_before_value,
1911                data_type,
1912                charset,
1913                styles,
1914            } => {
1915                write!(f, "{}CONVERT(", if *is_try { "TRY_" } else { "" })?;
1916                if let Some(data_type) = data_type {
1917                    if let Some(charset) = charset {
1918                        write!(f, "{expr}, {data_type} CHARACTER SET {charset}")
1919                    } else if *target_before_value {
1920                        write!(f, "{data_type}, {expr}")
1921                    } else {
1922                        write!(f, "{expr}, {data_type}")
1923                    }
1924                } else if let Some(charset) = charset {
1925                    write!(f, "{expr} USING {charset}")
1926                } else {
1927                    write!(f, "{expr}") // This should never happen
1928                }?;
1929                if !styles.is_empty() {
1930                    write!(f, ", {}", display_comma_separated(styles))?;
1931                }
1932                write!(f, ")")
1933            }
1934            Expr::Cast {
1935                kind,
1936                expr,
1937                data_type,
1938                array,
1939                format,
1940            } => match kind {
1941                CastKind::Cast => {
1942                    write!(f, "CAST({expr} AS {data_type}")?;
1943                    if *array {
1944                        write!(f, " ARRAY")?;
1945                    }
1946                    if let Some(format) = format {
1947                        write!(f, " FORMAT {format}")?;
1948                    }
1949                    write!(f, ")")
1950                }
1951                CastKind::TryCast => {
1952                    if let Some(format) = format {
1953                        write!(f, "TRY_CAST({expr} AS {data_type} FORMAT {format})")
1954                    } else {
1955                        write!(f, "TRY_CAST({expr} AS {data_type})")
1956                    }
1957                }
1958                CastKind::SafeCast => {
1959                    if let Some(format) = format {
1960                        write!(f, "SAFE_CAST({expr} AS {data_type} FORMAT {format})")
1961                    } else {
1962                        write!(f, "SAFE_CAST({expr} AS {data_type})")
1963                    }
1964                }
1965                CastKind::DoubleColon => {
1966                    write!(f, "{expr}::{data_type}")
1967                }
1968            },
1969            Expr::Extract {
1970                field,
1971                syntax,
1972                expr,
1973            } => match syntax {
1974                ExtractSyntax::From => write!(f, "EXTRACT({field} FROM {expr})"),
1975                ExtractSyntax::Comma => write!(f, "EXTRACT({field}, {expr})"),
1976            },
1977            Expr::Ceil { expr, field } => match field {
1978                CeilFloorKind::DateTimeField(DateTimeField::NoDateTime) => {
1979                    write!(f, "CEIL({expr})")
1980                }
1981                CeilFloorKind::DateTimeField(dt_field) => write!(f, "CEIL({expr} TO {dt_field})"),
1982                CeilFloorKind::Scale(s) => write!(f, "CEIL({expr}, {s})"),
1983            },
1984            Expr::Floor { expr, field } => match field {
1985                CeilFloorKind::DateTimeField(DateTimeField::NoDateTime) => {
1986                    write!(f, "FLOOR({expr})")
1987                }
1988                CeilFloorKind::DateTimeField(dt_field) => write!(f, "FLOOR({expr} TO {dt_field})"),
1989                CeilFloorKind::Scale(s) => write!(f, "FLOOR({expr}, {s})"),
1990            },
1991            Expr::Position { expr, r#in } => write!(f, "POSITION({expr} IN {in})"),
1992            Expr::Collate { expr, collation } => write!(f, "{expr} COLLATE {collation}"),
1993            Expr::Nested(ast) => write!(f, "({ast})"),
1994            Expr::Value(v) => write!(f, "{v}"),
1995            Expr::Prefixed { prefix, value } => write!(f, "{prefix} {value}"),
1996            Expr::TypedString(ts) => ts.fmt(f),
1997            Expr::Function(fun) => fun.fmt(f),
1998            Expr::Case {
1999                case_token: _,
2000                end_token: _,
2001                operand,
2002                conditions,
2003                else_result,
2004            } => {
2005                f.write_str("CASE")?;
2006                if let Some(operand) = operand {
2007                    f.write_str(" ")?;
2008                    operand.fmt(f)?;
2009                }
2010                for when in conditions {
2011                    SpaceOrNewline.fmt(f)?;
2012                    Indent(when).fmt(f)?;
2013                }
2014                if let Some(else_result) = else_result {
2015                    SpaceOrNewline.fmt(f)?;
2016                    Indent("ELSE").fmt(f)?;
2017                    SpaceOrNewline.fmt(f)?;
2018                    Indent(Indent(else_result)).fmt(f)?;
2019                }
2020                SpaceOrNewline.fmt(f)?;
2021                f.write_str("END")
2022            }
2023            Expr::Exists { subquery, negated } => write!(
2024                f,
2025                "{}EXISTS ({})",
2026                if *negated { "NOT " } else { "" },
2027                subquery
2028            ),
2029            Expr::Subquery(s) => write!(f, "({s})"),
2030            Expr::GroupingSets(sets) => {
2031                write!(f, "GROUPING SETS (")?;
2032                let mut sep = "";
2033                for set in sets {
2034                    write!(f, "{sep}")?;
2035                    sep = ", ";
2036                    write!(f, "({})", display_comma_separated(set))?;
2037                }
2038                write!(f, ")")
2039            }
2040            Expr::Cube(sets) => {
2041                write!(f, "CUBE (")?;
2042                let mut sep = "";
2043                for set in sets {
2044                    write!(f, "{sep}")?;
2045                    sep = ", ";
2046                    if set.len() == 1 {
2047                        write!(f, "{}", set[0])?;
2048                    } else {
2049                        write!(f, "({})", display_comma_separated(set))?;
2050                    }
2051                }
2052                write!(f, ")")
2053            }
2054            Expr::Rollup(sets) => {
2055                write!(f, "ROLLUP (")?;
2056                let mut sep = "";
2057                for set in sets {
2058                    write!(f, "{sep}")?;
2059                    sep = ", ";
2060                    if set.len() == 1 {
2061                        write!(f, "{}", set[0])?;
2062                    } else {
2063                        write!(f, "({})", display_comma_separated(set))?;
2064                    }
2065                }
2066                write!(f, ")")
2067            }
2068            Expr::Substring {
2069                expr,
2070                substring_from,
2071                substring_for,
2072                special,
2073                shorthand,
2074            } => {
2075                f.write_str("SUBSTR")?;
2076                if !*shorthand {
2077                    f.write_str("ING")?;
2078                }
2079                write!(f, "({expr}")?;
2080                if let Some(from_part) = substring_from {
2081                    if *special {
2082                        write!(f, ", {from_part}")?;
2083                    } else {
2084                        write!(f, " FROM {from_part}")?;
2085                    }
2086                }
2087                if let Some(for_part) = substring_for {
2088                    if *special {
2089                        write!(f, ", {for_part}")?;
2090                    } else {
2091                        write!(f, " FOR {for_part}")?;
2092                    }
2093                }
2094
2095                write!(f, ")")
2096            }
2097            Expr::Overlay {
2098                expr,
2099                overlay_what,
2100                overlay_from,
2101                overlay_for,
2102            } => {
2103                write!(
2104                    f,
2105                    "OVERLAY({expr} PLACING {overlay_what} FROM {overlay_from}"
2106                )?;
2107                if let Some(for_part) = overlay_for {
2108                    write!(f, " FOR {for_part}")?;
2109                }
2110
2111                write!(f, ")")
2112            }
2113            Expr::IsDistinctFrom(a, b) => write!(f, "{a} IS DISTINCT FROM {b}"),
2114            Expr::IsNotDistinctFrom(a, b) => write!(f, "{a} IS NOT DISTINCT FROM {b}"),
2115            Expr::Trim {
2116                expr,
2117                trim_where,
2118                trim_what,
2119                trim_characters,
2120            } => {
2121                write!(f, "TRIM(")?;
2122                if let Some(ident) = trim_where {
2123                    write!(f, "{ident} ")?;
2124                }
2125                if let Some(trim_char) = trim_what {
2126                    write!(f, "{trim_char} FROM {expr}")?;
2127                } else {
2128                    write!(f, "{expr}")?;
2129                }
2130                if let Some(characters) = trim_characters {
2131                    write!(f, ", {}", display_comma_separated(characters))?;
2132                }
2133
2134                write!(f, ")")
2135            }
2136            Expr::Tuple(exprs) => {
2137                write!(f, "({})", display_comma_separated(exprs))
2138            }
2139            Expr::Struct { values, fields } => {
2140                if !fields.is_empty() {
2141                    write!(
2142                        f,
2143                        "STRUCT<{}>({})",
2144                        display_comma_separated(fields),
2145                        display_comma_separated(values)
2146                    )
2147                } else {
2148                    write!(f, "STRUCT({})", display_comma_separated(values))
2149                }
2150            }
2151            Expr::Named { expr, name } => {
2152                write!(f, "{expr} AS {name}")
2153            }
2154            Expr::Dictionary(fields) => {
2155                write!(f, "{{{}}}", display_comma_separated(fields))
2156            }
2157            Expr::Map(map) => {
2158                write!(f, "{map}")
2159            }
2160            Expr::Array(set) => {
2161                write!(f, "{set}")
2162            }
2163            Expr::JsonAccess { value, path } => {
2164                write!(f, "{value}{path}")
2165            }
2166            Expr::AtTimeZone {
2167                timestamp,
2168                time_zone,
2169            } => {
2170                write!(f, "{timestamp} AT TIME ZONE {time_zone}")
2171            }
2172            Expr::Interval(interval) => {
2173                write!(f, "{interval}")
2174            }
2175            Expr::MatchAgainst {
2176                columns,
2177                match_value: match_expr,
2178                opt_search_modifier,
2179            } => {
2180                write!(f, "MATCH ({}) AGAINST ", display_comma_separated(columns),)?;
2181
2182                if let Some(search_modifier) = opt_search_modifier {
2183                    write!(f, "({match_expr} {search_modifier})")?;
2184                } else {
2185                    write!(f, "({match_expr})")?;
2186                }
2187
2188                Ok(())
2189            }
2190            Expr::OuterJoin(expr) => {
2191                write!(f, "{expr} (+)")
2192            }
2193            Expr::Prior(expr) => write!(f, "PRIOR {expr}"),
2194            Expr::Lambda(lambda) => write!(f, "{lambda}"),
2195            Expr::MemberOf(member_of) => write!(f, "{member_of}"),
2196        }
2197    }
2198}
2199
2200/// The type of a window used in `OVER` clauses.
2201///
2202/// A window can be either an inline specification (`WindowSpec`) or a
2203/// reference to a previously defined named window.
2204///
2205/// - `WindowSpec(WindowSpec)`: An inline window specification, e.g.
2206///   `OVER (PARTITION BY ... ORDER BY ...)`.
2207/// - `NamedWindow(Ident)`: A reference to a named window declared elsewhere.
2208#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2209#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2210#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2211pub enum WindowType {
2212    /// An inline window specification.
2213    WindowSpec(WindowSpec),
2214    /// A reference to a previously defined named window.
2215    NamedWindow(Ident),
2216}
2217
2218impl Display for WindowType {
2219    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2220        match self {
2221            WindowType::WindowSpec(spec) => {
2222                f.write_str("(")?;
2223                NewLine.fmt(f)?;
2224                Indent(spec).fmt(f)?;
2225                NewLine.fmt(f)?;
2226                f.write_str(")")
2227            }
2228            WindowType::NamedWindow(name) => name.fmt(f),
2229        }
2230    }
2231}
2232
2233/// A window specification (i.e. `OVER ([window_name] PARTITION BY .. ORDER BY .. etc.)`)
2234#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2235#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2236#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2237pub struct WindowSpec {
2238    /// Optional window name.
2239    ///
2240    /// You can find it at least in [MySQL][1], [BigQuery][2], [PostgreSQL][3]
2241    ///
2242    /// [1]: https://dev.mysql.com/doc/refman/8.0/en/window-functions-named-windows.html
2243    /// [2]: https://cloud.google.com/bigquery/docs/reference/standard-sql/window-function-calls
2244    /// [3]: https://www.postgresql.org/docs/current/sql-expressions.html#SYNTAX-WINDOW-FUNCTIONS
2245    pub window_name: Option<Ident>,
2246    /// `OVER (PARTITION BY ...)`
2247    pub partition_by: Vec<Expr>,
2248    /// `OVER (ORDER BY ...)`
2249    pub order_by: Vec<OrderByExpr>,
2250    /// `OVER (window frame)`
2251    pub window_frame: Option<WindowFrame>,
2252}
2253
2254impl fmt::Display for WindowSpec {
2255    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2256        let mut is_first = true;
2257        if let Some(window_name) = &self.window_name {
2258            if !is_first {
2259                SpaceOrNewline.fmt(f)?;
2260            }
2261            is_first = false;
2262            write!(f, "{window_name}")?;
2263        }
2264        if !self.partition_by.is_empty() {
2265            if !is_first {
2266                SpaceOrNewline.fmt(f)?;
2267            }
2268            is_first = false;
2269            write!(
2270                f,
2271                "PARTITION BY {}",
2272                display_comma_separated(&self.partition_by)
2273            )?;
2274        }
2275        if !self.order_by.is_empty() {
2276            if !is_first {
2277                SpaceOrNewline.fmt(f)?;
2278            }
2279            is_first = false;
2280            write!(f, "ORDER BY {}", display_comma_separated(&self.order_by))?;
2281        }
2282        if let Some(window_frame) = &self.window_frame {
2283            if !is_first {
2284                SpaceOrNewline.fmt(f)?;
2285            }
2286            if let Some(end_bound) = &window_frame.end_bound {
2287                write!(
2288                    f,
2289                    "{} BETWEEN {} AND {}",
2290                    window_frame.units, window_frame.start_bound, end_bound
2291                )?;
2292            } else {
2293                write!(f, "{} {}", window_frame.units, window_frame.start_bound)?;
2294            }
2295        }
2296        Ok(())
2297    }
2298}
2299
2300/// Specifies the data processed by a window function, e.g.
2301/// `RANGE UNBOUNDED PRECEDING` or `ROWS BETWEEN 5 PRECEDING AND CURRENT ROW`.
2302///
2303/// Note: The parser does not validate the specified bounds; the caller should
2304/// reject invalid bounds like `ROWS UNBOUNDED FOLLOWING` before execution.
2305#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2306#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2307#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2308pub struct WindowFrame {
2309    /// Units for the frame (e.g. `ROWS`, `RANGE`, `GROUPS`).
2310    pub units: WindowFrameUnits,
2311    /// The start bound of the window frame.
2312    pub start_bound: WindowFrameBound,
2313    /// The right bound of the `BETWEEN .. AND` clause. The end bound of `None`
2314    /// indicates the shorthand form (e.g. `ROWS 1 PRECEDING`), which must
2315    /// behave the same as `end_bound = WindowFrameBound::CurrentRow`.
2316    pub end_bound: Option<WindowFrameBound>,
2317    // TBD: EXCLUDE
2318}
2319
2320impl Default for WindowFrame {
2321    /// Returns default value for window frame
2322    ///
2323    /// See [this page](https://www.sqlite.org/windowfunctions.html#frame_specifications) for more details.
2324    fn default() -> Self {
2325        Self {
2326            units: WindowFrameUnits::Range,
2327            start_bound: WindowFrameBound::Preceding(None),
2328            end_bound: None,
2329        }
2330    }
2331}
2332
2333#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2334#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2335#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2336/// Units used to describe the window frame scope.
2337pub enum WindowFrameUnits {
2338    /// `ROWS` unit.
2339    Rows,
2340    /// `RANGE` unit.
2341    Range,
2342    /// `GROUPS` unit.
2343    Groups,
2344}
2345
2346impl fmt::Display for WindowFrameUnits {
2347    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2348        f.write_str(match self {
2349            WindowFrameUnits::Rows => "ROWS",
2350            WindowFrameUnits::Range => "RANGE",
2351            WindowFrameUnits::Groups => "GROUPS",
2352        })
2353    }
2354}
2355
2356/// Specifies Ignore / Respect NULL within window functions.
2357/// For example
2358/// `FIRST_VALUE(column2) IGNORE NULLS OVER (PARTITION BY column1)`
2359#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2360#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2361#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2362/// How NULL values are treated in certain window functions.
2363pub enum NullTreatment {
2364    /// Ignore NULL values (e.g. `IGNORE NULLS`).
2365    IgnoreNulls,
2366    /// Respect NULL values (e.g. `RESPECT NULLS`).
2367    RespectNulls,
2368}
2369
2370impl fmt::Display for NullTreatment {
2371    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2372        f.write_str(match self {
2373            NullTreatment::IgnoreNulls => "IGNORE NULLS",
2374            NullTreatment::RespectNulls => "RESPECT NULLS",
2375        })
2376    }
2377}
2378
2379/// Specifies [WindowFrame]'s `start_bound` and `end_bound`
2380#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2381#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2382#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2383pub enum WindowFrameBound {
2384    /// `CURRENT ROW`
2385    CurrentRow,
2386    /// `<N> PRECEDING` or `UNBOUNDED PRECEDING`
2387    Preceding(Option<Box<Expr>>),
2388    /// `<N> FOLLOWING` or `UNBOUNDED FOLLOWING`.
2389    Following(Option<Box<Expr>>),
2390}
2391
2392impl fmt::Display for WindowFrameBound {
2393    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2394        match self {
2395            WindowFrameBound::CurrentRow => f.write_str("CURRENT ROW"),
2396            WindowFrameBound::Preceding(None) => f.write_str("UNBOUNDED PRECEDING"),
2397            WindowFrameBound::Following(None) => f.write_str("UNBOUNDED FOLLOWING"),
2398            WindowFrameBound::Preceding(Some(n)) => write!(f, "{n} PRECEDING"),
2399            WindowFrameBound::Following(Some(n)) => write!(f, "{n} FOLLOWING"),
2400        }
2401    }
2402}
2403
2404#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2405#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2406#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2407/// Indicates partition operation type for partition management statements.
2408pub enum AddDropSync {
2409    /// Add partitions.
2410    ADD,
2411    /// Drop partitions.
2412    DROP,
2413    /// Sync partitions.
2414    SYNC,
2415}
2416
2417impl fmt::Display for AddDropSync {
2418    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2419        match self {
2420            AddDropSync::SYNC => f.write_str("SYNC PARTITIONS"),
2421            AddDropSync::DROP => f.write_str("DROP PARTITIONS"),
2422            AddDropSync::ADD => f.write_str("ADD PARTITIONS"),
2423        }
2424    }
2425}
2426
2427#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2428#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2429#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2430/// Object kinds supported by `SHOW CREATE` statements.
2431pub enum ShowCreateObject {
2432    /// An event object for `SHOW CREATE EVENT`.
2433    Event,
2434    /// A function object for `SHOW CREATE FUNCTION`.
2435    Function,
2436    /// A procedure object for `SHOW CREATE PROCEDURE`.
2437    Procedure,
2438    /// A table object for `SHOW CREATE TABLE`.
2439    Table,
2440    /// A trigger object for `SHOW CREATE TRIGGER`.
2441    Trigger,
2442    /// A view object for `SHOW CREATE VIEW`.
2443    View,
2444}
2445
2446impl fmt::Display for ShowCreateObject {
2447    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2448        match self {
2449            ShowCreateObject::Event => f.write_str("EVENT"),
2450            ShowCreateObject::Function => f.write_str("FUNCTION"),
2451            ShowCreateObject::Procedure => f.write_str("PROCEDURE"),
2452            ShowCreateObject::Table => f.write_str("TABLE"),
2453            ShowCreateObject::Trigger => f.write_str("TRIGGER"),
2454            ShowCreateObject::View => f.write_str("VIEW"),
2455        }
2456    }
2457}
2458
2459#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2460#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2461#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2462/// Objects that can be targeted by a `COMMENT` statement.
2463pub enum CommentObject {
2464    /// An aggregate function.
2465    Aggregate,
2466    /// A collation.
2467    Collation,
2468    /// A table column.
2469    Column,
2470    /// A table or domain constraint.
2471    Constraint,
2472    /// A database.
2473    Database,
2474    /// A domain.
2475    Domain,
2476    /// An extension.
2477    Extension,
2478    /// A function.
2479    Function,
2480    /// An index.
2481    Index,
2482    /// A materialized view.
2483    MaterializedView,
2484    /// A user-defined operator.
2485    Operator,
2486    /// A row-level security policy.
2487    Policy,
2488    /// A procedure.
2489    Procedure,
2490    /// A role.
2491    Role,
2492    /// A query rewrite rule.
2493    Rule,
2494    /// A schema.
2495    Schema,
2496    /// A sequence.
2497    Sequence,
2498    /// A table.
2499    Table,
2500    /// A trigger.
2501    Trigger,
2502    /// A type.
2503    Type,
2504    /// A user.
2505    User,
2506    /// A view.
2507    View,
2508}
2509
2510impl CommentObject {
2511    pub(crate) fn keyword_str(&self) -> &'static str {
2512        match self {
2513            CommentObject::Aggregate => "AGGREGATE",
2514            CommentObject::Collation => "COLLATION",
2515            CommentObject::Column => "COLUMN",
2516            CommentObject::Constraint => "CONSTRAINT",
2517            CommentObject::Database => "DATABASE",
2518            CommentObject::Domain => "DOMAIN",
2519            CommentObject::Extension => "EXTENSION",
2520            CommentObject::Function => "FUNCTION",
2521            CommentObject::Index => "INDEX",
2522            CommentObject::MaterializedView => "MATERIALIZED VIEW",
2523            CommentObject::Operator => "OPERATOR",
2524            CommentObject::Policy => "POLICY",
2525            CommentObject::Procedure => "PROCEDURE",
2526            CommentObject::Role => "ROLE",
2527            CommentObject::Rule => "RULE",
2528            CommentObject::Schema => "SCHEMA",
2529            CommentObject::Sequence => "SEQUENCE",
2530            CommentObject::Table => "TABLE",
2531            CommentObject::Trigger => "TRIGGER",
2532            CommentObject::Type => "TYPE",
2533            CommentObject::User => "USER",
2534            CommentObject::View => "VIEW",
2535        }
2536    }
2537
2538    /// Map a single keyword to its [`CommentObject`].
2539    ///
2540    /// `MATERIALIZED VIEW` is the only multi-keyword case and must be handled
2541    /// by the caller.
2542    pub(crate) fn from_keyword(keyword: Keyword) -> Option<Self> {
2543        Some(match keyword {
2544            Keyword::AGGREGATE => CommentObject::Aggregate,
2545            Keyword::COLLATION => CommentObject::Collation,
2546            Keyword::COLUMN => CommentObject::Column,
2547            Keyword::CONSTRAINT => CommentObject::Constraint,
2548            Keyword::DATABASE => CommentObject::Database,
2549            Keyword::DOMAIN => CommentObject::Domain,
2550            Keyword::EXTENSION => CommentObject::Extension,
2551            Keyword::FUNCTION => CommentObject::Function,
2552            Keyword::INDEX => CommentObject::Index,
2553            Keyword::OPERATOR => CommentObject::Operator,
2554            Keyword::POLICY => CommentObject::Policy,
2555            Keyword::PROCEDURE => CommentObject::Procedure,
2556            Keyword::ROLE => CommentObject::Role,
2557            Keyword::RULE => CommentObject::Rule,
2558            Keyword::SCHEMA => CommentObject::Schema,
2559            Keyword::SEQUENCE => CommentObject::Sequence,
2560            Keyword::TABLE => CommentObject::Table,
2561            Keyword::TRIGGER => CommentObject::Trigger,
2562            Keyword::TYPE => CommentObject::Type,
2563            Keyword::USER => CommentObject::User,
2564            Keyword::VIEW => CommentObject::View,
2565            _ => return None,
2566        })
2567    }
2568}
2569
2570impl fmt::Display for CommentObject {
2571    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2572        f.write_str(self.keyword_str())
2573    }
2574}
2575
2576/// Operand types for `COMMENT ON OPERATOR name (left, right)`.
2577///
2578/// Each side may be `NONE` for prefix or postfix unary operators, mirroring
2579/// the syntax allowed by `DROP OPERATOR` / `ALTER OPERATOR`. Both sides are
2580/// optional independently because PostgreSQL accepts unary operators in
2581/// either direction.
2582#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2583#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2584#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2585pub struct CommentOperatorArgs {
2586    /// Left-hand operand type, or `None` for `NONE` (prefix operator).
2587    pub left: Option<DataType>,
2588    /// Right-hand operand type, or `None` for `NONE` (postfix operator).
2589    pub right: Option<DataType>,
2590}
2591
2592impl fmt::Display for CommentOperatorArgs {
2593    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2594        let write_side = |opt: &Option<DataType>, f: &mut fmt::Formatter| -> fmt::Result {
2595            match opt {
2596                Some(dt) => write!(f, "{dt}"),
2597                None => f.write_str("NONE"),
2598            }
2599        };
2600        f.write_str("(")?;
2601        write_side(&self.left, f)?;
2602        f.write_str(", ")?;
2603        write_side(&self.right, f)?;
2604        f.write_str(")")
2605    }
2606}
2607
2608#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2609#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2610#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2611/// Password specification variants used in user-related statements.
2612pub enum Password {
2613    /// A concrete password expression.
2614    Password(Expr),
2615    /// Represents a `NULL` password.
2616    NullPassword,
2617}
2618
2619/// A `CASE` statement.
2620///
2621/// Examples:
2622/// ```sql
2623/// CASE
2624///     WHEN EXISTS(SELECT 1)
2625///         THEN SELECT 1 FROM T;
2626///     WHEN EXISTS(SELECT 2)
2627///         THEN SELECT 1 FROM U;
2628///     ELSE
2629///         SELECT 1 FROM V;
2630/// END CASE;
2631/// ```
2632///
2633/// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#case_search_expression)
2634/// [Snowflake](https://docs.snowflake.com/en/sql-reference/snowflake-scripting/case)
2635#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2636#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2637#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2638pub struct CaseStatement {
2639    /// The `CASE` token that starts the statement.
2640    pub case_token: AttachedToken,
2641    /// Optional expression to match against in `CASE ... WHEN`.
2642    pub match_expr: Option<Expr>,
2643    /// The `WHEN ... THEN` blocks of the `CASE` statement.
2644    pub when_blocks: Vec<ConditionalStatementBlock>,
2645    /// Optional `ELSE` block for the `CASE` statement.
2646    pub else_block: Option<ConditionalStatementBlock>,
2647    /// The last token of the statement (`END` or `CASE`).
2648    pub end_case_token: AttachedToken,
2649}
2650
2651impl fmt::Display for CaseStatement {
2652    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2653        let CaseStatement {
2654            case_token: _,
2655            match_expr,
2656            when_blocks,
2657            else_block,
2658            end_case_token: AttachedToken(end),
2659        } = self;
2660
2661        write!(f, "CASE")?;
2662
2663        if let Some(expr) = match_expr {
2664            write!(f, " {expr}")?;
2665        }
2666
2667        if !when_blocks.is_empty() {
2668            write!(f, " {}", display_separated(when_blocks, " "))?;
2669        }
2670
2671        if let Some(else_block) = else_block {
2672            write!(f, " {else_block}")?;
2673        }
2674
2675        write!(f, " END")?;
2676
2677        if let Token::Word(w) = &end.token {
2678            if w.keyword == Keyword::CASE {
2679                write!(f, " CASE")?;
2680            }
2681        }
2682
2683        Ok(())
2684    }
2685}
2686
2687/// An `IF` statement.
2688///
2689/// Example (BigQuery or Snowflake):
2690/// ```sql
2691/// IF TRUE THEN
2692///     SELECT 1;
2693///     SELECT 2;
2694/// ELSEIF TRUE THEN
2695///     SELECT 3;
2696/// ELSE
2697///     SELECT 4;
2698/// END IF
2699/// ```
2700/// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#if)
2701/// [Snowflake](https://docs.snowflake.com/en/sql-reference/snowflake-scripting/if)
2702///
2703/// Example (MSSQL):
2704/// ```sql
2705/// IF 1=1 SELECT 1 ELSE SELECT 2
2706/// ```
2707/// [MSSQL](https://learn.microsoft.com/en-us/sql/t-sql/language-elements/if-else-transact-sql?view=sql-server-ver16)
2708#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2709#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2710#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2711pub struct IfStatement {
2712    /// The initial `IF` block containing the condition and statements.
2713    pub if_block: ConditionalStatementBlock,
2714    /// Additional `ELSEIF` blocks.
2715    pub elseif_blocks: Vec<ConditionalStatementBlock>,
2716    /// Optional `ELSE` block.
2717    pub else_block: Option<ConditionalStatementBlock>,
2718    /// Optional trailing `END` token for the `IF` statement.
2719    pub end_token: Option<AttachedToken>,
2720}
2721
2722impl fmt::Display for IfStatement {
2723    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2724        let IfStatement {
2725            if_block,
2726            elseif_blocks,
2727            else_block,
2728            end_token,
2729        } = self;
2730
2731        write!(f, "{if_block}")?;
2732
2733        for elseif_block in elseif_blocks {
2734            write!(f, " {elseif_block}")?;
2735        }
2736
2737        if let Some(else_block) = else_block {
2738            write!(f, " {else_block}")?;
2739        }
2740
2741        if let Some(AttachedToken(end_token)) = end_token {
2742            write!(f, " END {end_token}")?;
2743        }
2744
2745        Ok(())
2746    }
2747}
2748
2749/// A `WHILE` statement.
2750///
2751/// Example:
2752/// ```sql
2753/// WHILE @@FETCH_STATUS = 0
2754/// BEGIN
2755///    FETCH NEXT FROM c1 INTO @var1, @var2;
2756/// END
2757/// ```
2758///
2759/// [MsSql](https://learn.microsoft.com/en-us/sql/t-sql/language-elements/while-transact-sql)
2760#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2761#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2762#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2763pub struct WhileStatement {
2764    /// Block executed while the condition holds.
2765    pub while_block: ConditionalStatementBlock,
2766}
2767
2768impl fmt::Display for WhileStatement {
2769    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2770        let WhileStatement { while_block } = self;
2771        write!(f, "{while_block}")?;
2772        Ok(())
2773    }
2774}
2775
2776/// A block within a [Statement::Case] or [Statement::If] or [Statement::While]-like statement
2777///
2778/// Example 1:
2779/// ```sql
2780/// WHEN EXISTS(SELECT 1) THEN SELECT 1;
2781/// ```
2782///
2783/// Example 2:
2784/// ```sql
2785/// IF TRUE THEN SELECT 1; SELECT 2;
2786/// ```
2787///
2788/// Example 3:
2789/// ```sql
2790/// ELSE SELECT 1; SELECT 2;
2791/// ```
2792///
2793/// Example 4:
2794/// ```sql
2795/// WHILE @@FETCH_STATUS = 0
2796/// BEGIN
2797///    FETCH NEXT FROM c1 INTO @var1, @var2;
2798/// END
2799/// ```
2800#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2801#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2802#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2803pub struct ConditionalStatementBlock {
2804    /// Token representing the start of the block (e.g., WHEN/IF/WHILE).
2805    pub start_token: AttachedToken,
2806    /// Optional condition expression for the block.
2807    pub condition: Option<Expr>,
2808    /// Optional token for the `THEN` keyword.
2809    pub then_token: Option<AttachedToken>,
2810    /// The statements contained in this conditional block.
2811    pub conditional_statements: ConditionalStatements,
2812}
2813
2814impl ConditionalStatementBlock {
2815    /// Get the statements in this conditional block.
2816    pub fn statements(&self) -> &Vec<Statement> {
2817        self.conditional_statements.statements()
2818    }
2819}
2820
2821impl fmt::Display for ConditionalStatementBlock {
2822    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2823        let ConditionalStatementBlock {
2824            start_token: AttachedToken(start_token),
2825            condition,
2826            then_token,
2827            conditional_statements,
2828        } = self;
2829
2830        write!(f, "{start_token}")?;
2831
2832        if let Some(condition) = condition {
2833            write!(f, " {condition}")?;
2834        }
2835
2836        if then_token.is_some() {
2837            write!(f, " THEN")?;
2838        }
2839
2840        if !conditional_statements.statements().is_empty() {
2841            write!(f, " {conditional_statements}")?;
2842        }
2843
2844        Ok(())
2845    }
2846}
2847
2848/// A list of statements in a [ConditionalStatementBlock].
2849#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2850#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2851#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2852/// Statements used inside conditional blocks (`IF`, `WHEN`, `WHILE`).
2853pub enum ConditionalStatements {
2854    /// Simple sequence of statements (no `BEGIN`/`END`).
2855    Sequence {
2856        /// The statements in the sequence.
2857        statements: Vec<Statement>,
2858    },
2859    /// Block enclosed by `BEGIN` and `END`.
2860    BeginEnd(BeginEndStatements),
2861}
2862
2863impl ConditionalStatements {
2864    /// Get the statements in this conditional statements block.
2865    pub fn statements(&self) -> &Vec<Statement> {
2866        match self {
2867            ConditionalStatements::Sequence { statements } => statements,
2868            ConditionalStatements::BeginEnd(bes) => &bes.statements,
2869        }
2870    }
2871}
2872
2873impl fmt::Display for ConditionalStatements {
2874    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2875        match self {
2876            ConditionalStatements::Sequence { statements } => {
2877                if !statements.is_empty() {
2878                    format_statement_list(f, statements)?;
2879                }
2880                Ok(())
2881            }
2882            ConditionalStatements::BeginEnd(bes) => write!(f, "{bes}"),
2883        }
2884    }
2885}
2886
2887/// Represents a list of statements enclosed within `BEGIN` and `END` keywords.
2888/// Example:
2889/// ```sql
2890/// BEGIN
2891///     SELECT 1;
2892///     SELECT 2;
2893/// END
2894/// ```
2895#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2896#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2897#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2898pub struct BeginEndStatements {
2899    /// Token representing the `BEGIN` keyword (may include span info).
2900    pub begin_token: AttachedToken,
2901    /// Statements contained within the block.
2902    pub statements: Vec<Statement>,
2903    /// Token representing the `END` keyword (may include span info).
2904    pub end_token: AttachedToken,
2905}
2906
2907impl fmt::Display for BeginEndStatements {
2908    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2909        let BeginEndStatements {
2910            begin_token: AttachedToken(begin_token),
2911            statements,
2912            end_token: AttachedToken(end_token),
2913        } = self;
2914
2915        if begin_token.token != Token::EOF {
2916            write!(f, "{begin_token} ")?;
2917        }
2918        if !statements.is_empty() {
2919            format_statement_list(f, statements)?;
2920        }
2921        if end_token.token != Token::EOF {
2922            write!(f, " {end_token}")?;
2923        }
2924        Ok(())
2925    }
2926}
2927
2928/// A `RAISE` statement.
2929///
2930/// Examples:
2931/// ```sql
2932/// RAISE USING MESSAGE = 'error';
2933///
2934/// RAISE myerror;
2935/// ```
2936///
2937/// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#raise)
2938/// [Snowflake](https://docs.snowflake.com/en/sql-reference/snowflake-scripting/raise)
2939#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2940#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2941#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2942pub struct RaiseStatement {
2943    /// Optional value provided to the RAISE statement.
2944    pub value: Option<RaiseStatementValue>,
2945}
2946
2947impl fmt::Display for RaiseStatement {
2948    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2949        let RaiseStatement { value } = self;
2950
2951        write!(f, "RAISE")?;
2952        if let Some(value) = value {
2953            write!(f, " {value}")?;
2954        }
2955
2956        Ok(())
2957    }
2958}
2959
2960/// Represents the error value of a [RaiseStatement].
2961#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2962#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2963#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2964pub enum RaiseStatementValue {
2965    /// `RAISE USING MESSAGE = 'error'`
2966    UsingMessage(Expr),
2967    /// `RAISE myerror`
2968    Expr(Expr),
2969}
2970
2971impl fmt::Display for RaiseStatementValue {
2972    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2973        match self {
2974            RaiseStatementValue::Expr(expr) => write!(f, "{expr}"),
2975            RaiseStatementValue::UsingMessage(expr) => write!(f, "USING MESSAGE = {expr}"),
2976        }
2977    }
2978}
2979
2980/// A MSSQL `THROW` statement.
2981///
2982/// ```sql
2983/// THROW [ error_number, message, state ]
2984/// ```
2985///
2986/// [MSSQL](https://learn.microsoft.com/en-us/sql/t-sql/language-elements/throw-transact-sql)
2987#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2988#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2989#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2990pub struct ThrowStatement {
2991    /// Error number expression.
2992    pub error_number: Option<Box<Expr>>,
2993    /// Error message expression.
2994    pub message: Option<Box<Expr>>,
2995    /// State expression.
2996    pub state: Option<Box<Expr>>,
2997}
2998
2999impl fmt::Display for ThrowStatement {
3000    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3001        let ThrowStatement {
3002            error_number,
3003            message,
3004            state,
3005        } = self;
3006
3007        write!(f, "THROW")?;
3008        if let (Some(error_number), Some(message), Some(state)) = (error_number, message, state) {
3009            write!(f, " {error_number}, {message}, {state}")?;
3010        }
3011        Ok(())
3012    }
3013}
3014
3015/// Represents an expression assignment within a variable `DECLARE` statement.
3016///
3017/// Examples:
3018/// ```sql
3019/// DECLARE variable_name := 42
3020/// DECLARE variable_name DEFAULT 42
3021/// ```
3022#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3023#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3024#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3025pub enum DeclareAssignment {
3026    /// Plain expression specified.
3027    Expr(Box<Expr>),
3028
3029    /// Expression assigned via the `DEFAULT` keyword
3030    Default(Box<Expr>),
3031
3032    /// Expression assigned via the `:=` syntax
3033    ///
3034    /// Example:
3035    /// ```sql
3036    /// DECLARE variable_name := 42;
3037    /// ```
3038    DuckAssignment(Box<Expr>),
3039
3040    /// Expression via the `FOR` keyword
3041    ///
3042    /// Example:
3043    /// ```sql
3044    /// DECLARE c1 CURSOR FOR res
3045    /// ```
3046    For(Box<Expr>),
3047
3048    /// Expression via the `=` syntax.
3049    ///
3050    /// Example:
3051    /// ```sql
3052    /// DECLARE @variable AS INT = 100
3053    /// ```
3054    MsSqlAssignment(Box<Expr>),
3055}
3056
3057impl fmt::Display for DeclareAssignment {
3058    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3059        match self {
3060            DeclareAssignment::Expr(expr) => {
3061                write!(f, "{expr}")
3062            }
3063            DeclareAssignment::Default(expr) => {
3064                write!(f, "DEFAULT {expr}")
3065            }
3066            DeclareAssignment::DuckAssignment(expr) => {
3067                write!(f, ":= {expr}")
3068            }
3069            DeclareAssignment::MsSqlAssignment(expr) => {
3070                write!(f, "= {expr}")
3071            }
3072            DeclareAssignment::For(expr) => {
3073                write!(f, "FOR {expr}")
3074            }
3075        }
3076    }
3077}
3078
3079/// Represents the type of a `DECLARE` statement.
3080#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3081#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3082#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3083pub enum DeclareType {
3084    /// Cursor variable type. e.g. [Snowflake] [PostgreSQL] [MsSql]
3085    ///
3086    /// [Snowflake]: https://docs.snowflake.com/en/developer-guide/snowflake-scripting/cursors#declaring-a-cursor
3087    /// [PostgreSQL]: https://www.postgresql.org/docs/current/plpgsql-cursors.html
3088    /// [MsSql]: https://learn.microsoft.com/en-us/sql/t-sql/language-elements/declare-cursor-transact-sql
3089    Cursor,
3090
3091    /// Result set variable type. [Snowflake]
3092    ///
3093    /// Syntax:
3094    /// ```text
3095    /// <resultset_name> RESULTSET [ { DEFAULT | := } ( <query> ) ] ;
3096    /// ```
3097    /// [Snowflake]: https://docs.snowflake.com/en/sql-reference/snowflake-scripting/declare#resultset-declaration-syntax
3098    ResultSet,
3099
3100    /// Exception declaration syntax. [Snowflake]
3101    ///
3102    /// Syntax:
3103    /// ```text
3104    /// <exception_name> EXCEPTION [ ( <exception_number> , '<exception_message>' ) ] ;
3105    /// ```
3106    /// [Snowflake]: https://docs.snowflake.com/en/sql-reference/snowflake-scripting/declare#exception-declaration-syntax
3107    Exception,
3108}
3109
3110impl fmt::Display for DeclareType {
3111    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3112        match self {
3113            DeclareType::Cursor => {
3114                write!(f, "CURSOR")
3115            }
3116            DeclareType::ResultSet => {
3117                write!(f, "RESULTSET")
3118            }
3119            DeclareType::Exception => {
3120                write!(f, "EXCEPTION")
3121            }
3122        }
3123    }
3124}
3125
3126/// A `DECLARE` statement.
3127/// [PostgreSQL] [Snowflake] [BigQuery]
3128///
3129/// Examples:
3130/// ```sql
3131/// DECLARE variable_name := 42
3132/// DECLARE liahona CURSOR FOR SELECT * FROM films;
3133/// ```
3134///
3135/// [PostgreSQL]: https://www.postgresql.org/docs/current/sql-declare.html
3136/// [Snowflake]: https://docs.snowflake.com/en/sql-reference/snowflake-scripting/declare
3137/// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#declare
3138#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3139#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3140#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3141pub struct Declare {
3142    /// The name(s) being declared.
3143    /// Example: `DECLARE a, b, c DEFAULT 42;
3144    pub names: Vec<Ident>,
3145    /// Data-type assigned to the declared variable.
3146    /// Example: `DECLARE x INT64 DEFAULT 42;
3147    pub data_type: Option<DataType>,
3148    /// Expression being assigned to the declared variable.
3149    pub assignment: Option<DeclareAssignment>,
3150    /// Represents the type of the declared variable.
3151    pub declare_type: Option<DeclareType>,
3152    /// Causes the cursor to return data in binary rather than in text format.
3153    pub binary: Option<bool>,
3154    /// None = Not specified
3155    /// Some(true) = INSENSITIVE
3156    /// Some(false) = ASENSITIVE
3157    pub sensitive: Option<bool>,
3158    /// None = Not specified
3159    /// Some(true) = SCROLL
3160    /// Some(false) = NO SCROLL
3161    pub scroll: Option<bool>,
3162    /// None = Not specified
3163    /// Some(true) = WITH HOLD, specifies that the cursor can continue to be used after the transaction that created it successfully commits
3164    /// Some(false) = WITHOUT HOLD, specifies that the cursor cannot be used outside of the transaction that created it
3165    pub hold: Option<bool>,
3166    /// `FOR <query>` clause in a CURSOR declaration.
3167    pub for_query: Option<Box<Query>>,
3168}
3169
3170impl fmt::Display for Declare {
3171    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3172        let Declare {
3173            names,
3174            data_type,
3175            assignment,
3176            declare_type,
3177            binary,
3178            sensitive,
3179            scroll,
3180            hold,
3181            for_query,
3182        } = self;
3183        write!(f, "{}", display_comma_separated(names))?;
3184
3185        if let Some(true) = binary {
3186            write!(f, " BINARY")?;
3187        }
3188
3189        if let Some(sensitive) = sensitive {
3190            if *sensitive {
3191                write!(f, " INSENSITIVE")?;
3192            } else {
3193                write!(f, " ASENSITIVE")?;
3194            }
3195        }
3196
3197        if let Some(scroll) = scroll {
3198            if *scroll {
3199                write!(f, " SCROLL")?;
3200            } else {
3201                write!(f, " NO SCROLL")?;
3202            }
3203        }
3204
3205        if let Some(declare_type) = declare_type {
3206            write!(f, " {declare_type}")?;
3207        }
3208
3209        if let Some(hold) = hold {
3210            if *hold {
3211                write!(f, " WITH HOLD")?;
3212            } else {
3213                write!(f, " WITHOUT HOLD")?;
3214            }
3215        }
3216
3217        if let Some(query) = for_query {
3218            write!(f, " FOR {query}")?;
3219        }
3220
3221        if let Some(data_type) = data_type {
3222            write!(f, " {data_type}")?;
3223        }
3224
3225        if let Some(expr) = assignment {
3226            write!(f, " {expr}")?;
3227        }
3228        Ok(())
3229    }
3230}
3231
3232/// Sql options of a `CREATE TABLE` statement.
3233#[derive(Debug, Default, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3234#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3235#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3236/// Options allowed within a `CREATE TABLE` statement.
3237pub enum CreateTableOptions {
3238    /// No options specified.
3239    #[default]
3240    None,
3241    /// Options specified using the `WITH` keyword, e.g. `WITH (k = v)`.
3242    With(Vec<SqlOption>),
3243    /// Options specified using the `OPTIONS(...)` clause.
3244    Options(Vec<SqlOption>),
3245    /// Plain space-separated options.
3246    Plain(Vec<SqlOption>),
3247    /// Table properties (e.g., TBLPROPERTIES / storage properties).
3248    TableProperties(Vec<SqlOption>),
3249}
3250
3251impl fmt::Display for CreateTableOptions {
3252    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3253        match self {
3254            CreateTableOptions::With(with_options) => {
3255                write!(f, "WITH ({})", display_comma_separated(with_options))
3256            }
3257            CreateTableOptions::Options(options) => {
3258                write!(f, "OPTIONS({})", display_comma_separated(options))
3259            }
3260            CreateTableOptions::TableProperties(options) => {
3261                write!(f, "TBLPROPERTIES ({})", display_comma_separated(options))
3262            }
3263            CreateTableOptions::Plain(options) => {
3264                write!(f, "{}", display_separated(options, " "))
3265            }
3266            CreateTableOptions::None => Ok(()),
3267        }
3268    }
3269}
3270
3271/// A `FROM` clause within a `DELETE` statement.
3272///
3273/// Syntax
3274/// ```sql
3275/// [FROM] table
3276/// ```
3277#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3278#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3279#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3280pub enum FromTable {
3281    /// An explicit `FROM` keyword was specified.
3282    WithFromKeyword(Vec<TableWithJoins>),
3283    /// BigQuery: `FROM` keyword was omitted.
3284    /// <https://cloud.google.com/bigquery/docs/reference/standard-sql/dml-syntax#delete_statement>
3285    WithoutKeyword(Vec<TableWithJoins>),
3286}
3287impl Display for FromTable {
3288    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3289        match self {
3290            FromTable::WithFromKeyword(tables) => {
3291                write!(f, "FROM {}", display_comma_separated(tables))
3292            }
3293            FromTable::WithoutKeyword(tables) => {
3294                write!(f, "{}", display_comma_separated(tables))
3295            }
3296        }
3297    }
3298}
3299
3300#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3301#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3302#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3303/// Variants for the `SET` family of statements.
3304pub enum Set {
3305    /// SQL Standard-style
3306    /// SET a = 1;
3307    /// `SET var = value` (standard SQL-style assignment).
3308    SingleAssignment {
3309        /// Optional scope modifier (`SESSION` / `LOCAL`).
3310        scope: Option<ContextModifier>,
3311        /// Whether this is a Hive-style `HIVEVAR:` assignment.
3312        hivevar: bool,
3313        /// Variable name to assign.
3314        variable: ObjectName,
3315        /// Values assigned to the variable.
3316        values: Vec<Expr>,
3317    },
3318    /// Snowflake-style
3319    /// SET (a, b, ..) = (1, 2, ..);
3320    /// `SET (a, b) = (1, 2)` (tuple assignment syntax).
3321    ParenthesizedAssignments {
3322        /// Variables being assigned in tuple form.
3323        variables: Vec<ObjectName>,
3324        /// Corresponding values for the variables.
3325        values: Vec<Expr>,
3326    },
3327    /// MySQL-style
3328    /// SET a = 1, b = 2, ..;
3329    /// `SET a = 1, b = 2` (MySQL-style comma-separated assignments).
3330    MultipleAssignments {
3331        /// List of `SET` assignments (MySQL-style comma-separated).
3332        assignments: Vec<SetAssignment>,
3333    },
3334    /// Session authorization for Postgres/Redshift
3335    ///
3336    /// ```sql
3337    /// SET SESSION AUTHORIZATION { user_name | DEFAULT }
3338    /// ```
3339    ///
3340    /// See <https://www.postgresql.org/docs/current/sql-set-session-authorization.html>
3341    /// See <https://docs.aws.amazon.com/redshift/latest/dg/r_SET_SESSION_AUTHORIZATION.html>
3342    SetSessionAuthorization(SetSessionAuthorizationParam),
3343    /// MS-SQL session
3344    ///
3345    /// See <https://learn.microsoft.com/en-us/sql/t-sql/statements/set-statements-transact-sql>
3346    SetSessionParam(SetSessionParamKind),
3347    /// ```sql
3348    /// SET [ SESSION | LOCAL ] ROLE role_name
3349    /// ```
3350    ///
3351    /// Sets session state. Examples: [ANSI][1], [Postgresql][2], [MySQL][3], and [Oracle][4]
3352    ///
3353    /// [1]: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#set-role-statement
3354    /// [2]: https://www.postgresql.org/docs/14/sql-set-role.html
3355    /// [3]: https://dev.mysql.com/doc/refman/8.0/en/set-role.html
3356    /// [4]: https://docs.oracle.com/cd/B19306_01/server.102/b14200/statements_10004.htm
3357    SetRole {
3358        /// Non-ANSI optional identifier to inform if the role is defined inside the current session (`SESSION`) or transaction (`LOCAL`).
3359        context_modifier: Option<ContextModifier>,
3360        /// Role name. If NONE is specified, then the current role name is removed.
3361        role_name: Option<Ident>,
3362    },
3363    /// ```sql
3364    /// SET TIME ZONE <value>
3365    /// ```
3366    ///
3367    /// Note: this is a PostgreSQL-specific statements
3368    /// `SET TIME ZONE <value>` is an alias for `SET timezone TO <value>` in PostgreSQL
3369    /// However, we allow it for all dialects.
3370    /// `SET TIME ZONE` statement. `local` indicates the `LOCAL` keyword.
3371    /// `SET TIME ZONE <value>` statement.
3372    SetTimeZone {
3373        /// Whether the `LOCAL` keyword was specified.
3374        local: bool,
3375        /// Time zone expression value.
3376        value: Expr,
3377    },
3378    /// ```sql
3379    /// SET NAMES 'charset_name' [COLLATE 'collation_name']
3380    /// ```
3381    SetNames {
3382        /// Character set name to set.
3383        charset_name: Ident,
3384        /// Optional collation name.
3385        collation_name: Option<String>,
3386    },
3387    /// ```sql
3388    /// SET NAMES DEFAULT
3389    /// ```
3390    ///
3391    /// Note: this is a MySQL-specific statement.
3392    SetNamesDefault {},
3393    /// ```sql
3394    /// SET TRANSACTION ...
3395    /// ```
3396    SetTransaction {
3397        /// Transaction modes (e.g., ISOLATION LEVEL, READ ONLY).
3398        modes: Vec<TransactionMode>,
3399        /// Optional snapshot value for transaction snapshot control.
3400        snapshot: Option<ValueWithSpan>,
3401        /// `true` when the `SESSION` keyword was used.
3402        session: bool,
3403    },
3404}
3405
3406impl Display for Set {
3407    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3408        match self {
3409            Self::ParenthesizedAssignments { variables, values } => write!(
3410                f,
3411                "SET ({}) = ({})",
3412                display_comma_separated(variables),
3413                display_comma_separated(values)
3414            ),
3415            Self::MultipleAssignments { assignments } => {
3416                write!(f, "SET {}", display_comma_separated(assignments))
3417            }
3418            Self::SetRole {
3419                context_modifier,
3420                role_name,
3421            } => {
3422                let role_name = role_name.clone().unwrap_or_else(|| Ident::new("NONE"));
3423                write!(
3424                    f,
3425                    "SET {modifier}ROLE {role_name}",
3426                    modifier = context_modifier.map(|m| format!("{m}")).unwrap_or_default()
3427                )
3428            }
3429            Self::SetSessionAuthorization(kind) => write!(f, "SET SESSION AUTHORIZATION {kind}"),
3430            Self::SetSessionParam(kind) => write!(f, "SET {kind}"),
3431            Self::SetTransaction {
3432                modes,
3433                snapshot,
3434                session,
3435            } => {
3436                if *session {
3437                    write!(f, "SET SESSION CHARACTERISTICS AS TRANSACTION")?;
3438                } else {
3439                    write!(f, "SET TRANSACTION")?;
3440                }
3441                if !modes.is_empty() {
3442                    write!(f, " {}", display_comma_separated(modes))?;
3443                }
3444                if let Some(snapshot_id) = snapshot {
3445                    write!(f, " SNAPSHOT {snapshot_id}")?;
3446                }
3447                Ok(())
3448            }
3449            Self::SetTimeZone { local, value } => {
3450                f.write_str("SET ")?;
3451                if *local {
3452                    f.write_str("LOCAL ")?;
3453                }
3454                write!(f, "TIME ZONE {value}")
3455            }
3456            Self::SetNames {
3457                charset_name,
3458                collation_name,
3459            } => {
3460                write!(f, "SET NAMES {charset_name}")?;
3461
3462                if let Some(collation) = collation_name {
3463                    f.write_str(" COLLATE ")?;
3464                    f.write_str(collation)?;
3465                };
3466
3467                Ok(())
3468            }
3469            Self::SetNamesDefault {} => {
3470                f.write_str("SET NAMES DEFAULT")?;
3471
3472                Ok(())
3473            }
3474            Set::SingleAssignment {
3475                scope,
3476                hivevar,
3477                variable,
3478                values,
3479            } => {
3480                write!(
3481                    f,
3482                    "SET {}{}{} = {}",
3483                    scope.map(|s| format!("{s}")).unwrap_or_default(),
3484                    if *hivevar { "HIVEVAR:" } else { "" },
3485                    variable,
3486                    display_comma_separated(values)
3487                )
3488            }
3489        }
3490    }
3491}
3492
3493/// A representation of a `WHEN` arm with all the identifiers catched and the statements to execute
3494/// for the arm.
3495///
3496/// Snowflake: <https://docs.snowflake.com/en/sql-reference/snowflake-scripting/exception>
3497/// BigQuery: <https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#beginexceptionend>
3498#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3499#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3500#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3501pub struct ExceptionWhen {
3502    /// Identifiers that trigger this branch (error conditions).
3503    pub idents: Vec<Ident>,
3504    /// Statements to execute when the condition matches.
3505    pub statements: Vec<Statement>,
3506}
3507
3508impl Display for ExceptionWhen {
3509    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3510        write!(
3511            f,
3512            "WHEN {idents} THEN",
3513            idents = display_separated(&self.idents, " OR ")
3514        )?;
3515
3516        if !self.statements.is_empty() {
3517            write!(f, " ")?;
3518            format_statement_list(f, &self.statements)?;
3519        }
3520
3521        Ok(())
3522    }
3523}
3524
3525/// ANALYZE statement
3526///
3527/// Supported syntax varies by dialect:
3528/// - Hive: `ANALYZE TABLE t [PARTITION (...)] COMPUTE STATISTICS [NOSCAN] [FOR COLUMNS [col1, ...]] [CACHE METADATA]`
3529/// - PostgreSQL: `ANALYZE [VERBOSE] [t [(col1, ...)]]` See <https://www.postgresql.org/docs/current/sql-analyze.html>
3530/// - General: `ANALYZE [TABLE] t`
3531#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3532#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3533#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3534pub struct Analyze {
3535    #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
3536    /// Name of the table to analyze. `None` for bare `ANALYZE`.
3537    pub table_name: Option<ObjectName>,
3538    /// Optional partition expressions to restrict the analysis.
3539    pub partitions: Option<Vec<Expr>>,
3540    /// `true` when analyzing specific columns (Hive `FOR COLUMNS` syntax).
3541    pub for_columns: bool,
3542    /// Columns to analyze.
3543    pub columns: Vec<Ident>,
3544    /// Whether to cache metadata before analyzing.
3545    pub cache_metadata: bool,
3546    /// Whether to skip scanning the table.
3547    pub noscan: bool,
3548    /// Whether to compute statistics during analysis.
3549    pub compute_statistics: bool,
3550    /// Whether the `TABLE` keyword was present.
3551    pub has_table_keyword: bool,
3552}
3553
3554impl fmt::Display for Analyze {
3555    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3556        write!(f, "ANALYZE")?;
3557        if let Some(ref table_name) = self.table_name {
3558            if self.has_table_keyword {
3559                write!(f, " TABLE")?;
3560            }
3561            write!(f, " {table_name}")?;
3562        }
3563        if !self.for_columns && !self.columns.is_empty() {
3564            write!(f, " ({})", display_comma_separated(&self.columns))?;
3565        }
3566        if let Some(ref parts) = self.partitions {
3567            if !parts.is_empty() {
3568                write!(f, " PARTITION ({})", display_comma_separated(parts))?;
3569            }
3570        }
3571        if self.compute_statistics {
3572            write!(f, " COMPUTE STATISTICS")?;
3573        }
3574        if self.noscan {
3575            write!(f, " NOSCAN")?;
3576        }
3577        if self.cache_metadata {
3578            write!(f, " CACHE METADATA")?;
3579        }
3580        if self.for_columns {
3581            write!(f, " FOR COLUMNS")?;
3582            if !self.columns.is_empty() {
3583                write!(f, " {}", display_comma_separated(&self.columns))?;
3584            }
3585        }
3586        Ok(())
3587    }
3588}
3589
3590/// A top-level statement (SELECT, INSERT, CREATE, etc.)
3591#[allow(clippy::large_enum_variant)]
3592#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3593#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3594#[cfg_attr(
3595    feature = "visitor",
3596    derive(Visit, VisitMut),
3597    visit(with = "visit_statement")
3598)]
3599pub enum Statement {
3600    /// ```sql
3601    /// ANALYZE
3602    /// ```
3603    /// Analyze (Hive)
3604    Analyze(Analyze),
3605    /// `SET` statements (session, transaction, timezone, etc.).
3606    Set(Set),
3607    /// ```sql
3608    /// TRUNCATE
3609    /// ```
3610    /// Truncate (Hive)
3611    Truncate(Truncate),
3612    /// ```sql
3613    /// MSCK
3614    /// ```
3615    /// Msck (Hive)
3616    Msck(Msck),
3617    /// ```sql
3618    /// SELECT
3619    /// ```
3620    Query(Box<Query>),
3621    /// ```sql
3622    /// INSERT
3623    /// ```
3624    Insert(Insert),
3625    /// ```sql
3626    /// INSTALL
3627    /// ```
3628    Install {
3629        /// Only for DuckDB
3630        extension_name: Ident,
3631    },
3632    /// ```sql
3633    /// LOAD
3634    /// ```
3635    Load {
3636        /// Only for DuckDB
3637        extension_name: Ident,
3638    },
3639    // TODO: Support ROW FORMAT
3640    /// LOAD DATA from a directory or query source.
3641    Directory {
3642        /// Whether to overwrite existing files.
3643        overwrite: bool,
3644        /// Whether the directory is local to the server.
3645        local: bool,
3646        /// Path to the directory or files.
3647        path: String,
3648        /// Optional file format for the data.
3649        file_format: Option<FileFormat>,
3650        /// Source query providing data to load.
3651        source: Box<Query>,
3652    },
3653    /// A `CASE` statement.
3654    Case(CaseStatement),
3655    /// An `IF` statement.
3656    If(IfStatement),
3657    /// A `WHILE` statement.
3658    While(WhileStatement),
3659    /// A `RAISE` statement.
3660    Raise(RaiseStatement),
3661    /// ```sql
3662    /// CALL <function>
3663    /// ```
3664    Call(Function),
3665    /// ```sql
3666    /// COPY [TO | FROM] ...
3667    /// ```
3668    Copy {
3669        /// The source of 'COPY TO', or the target of 'COPY FROM'
3670        source: CopySource,
3671        /// If true, is a 'COPY TO' statement. If false is a 'COPY FROM'
3672        to: bool,
3673        /// The target of 'COPY TO', or the source of 'COPY FROM'
3674        target: CopyTarget,
3675        /// WITH options (from PostgreSQL version 9.0)
3676        options: Vec<CopyOption>,
3677        /// WITH options (before PostgreSQL version 9.0)
3678        legacy_options: Vec<CopyLegacyOption>,
3679        /// VALUES a vector of values to be copied
3680        values: Vec<Option<String>>,
3681    },
3682    /// ```sql
3683    /// COPY INTO <table> | <location>
3684    /// ```
3685    /// See:
3686    /// <https://docs.snowflake.com/en/sql-reference/sql/copy-into-table>
3687    /// <https://docs.snowflake.com/en/sql-reference/sql/copy-into-location>
3688    ///
3689    /// Copy Into syntax available for Snowflake is different than the one implemented in
3690    /// Postgres. Although they share common prefix, it is reasonable to implement them
3691    /// in different enums. This can be refactored later once custom dialects
3692    /// are allowed to have custom Statements.
3693    CopyIntoSnowflake {
3694        /// Kind of COPY INTO operation (table or location).
3695        kind: CopyIntoSnowflakeKind,
3696        /// Target object for the COPY INTO operation.
3697        into: ObjectName,
3698        /// Optional list of target columns.
3699        into_columns: Option<Vec<Ident>>,
3700        /// Optional source object name (staged data).
3701        from_obj: Option<ObjectName>,
3702        /// Optional alias for the source object.
3703        from_obj_alias: Option<Ident>,
3704        /// Stage-specific parameters (e.g., credentials, path).
3705        stage_params: StageParamsObject,
3706        /// Optional list of transformations applied when loading.
3707        from_transformations: Option<Vec<StageLoadSelectItemKind>>,
3708        /// Optional source query instead of a staged object.
3709        from_query: Option<Box<Query>>,
3710        /// Optional list of specific file names to load.
3711        files: Option<Vec<String>>,
3712        /// Optional filename matching pattern.
3713        pattern: Option<String>,
3714        /// File format options.
3715        file_format: KeyValueOptions,
3716        /// Additional copy options.
3717        copy_options: KeyValueOptions,
3718        /// Optional validation mode string.
3719        validation_mode: Option<String>,
3720        /// Optional partition expression for loading.
3721        partition: Option<Box<Expr>>,
3722    },
3723    /// ```sql
3724    /// OPEN cursor_name
3725    /// ```
3726    /// Opens a cursor.
3727    Open(OpenStatement),
3728    /// ```sql
3729    /// CLOSE
3730    /// ```
3731    /// Closes the portal underlying an open cursor.
3732    Close {
3733        /// Cursor name
3734        cursor: CloseCursor,
3735    },
3736    /// ```sql
3737    /// UPDATE
3738    /// ```
3739    Update(Update),
3740    /// ```sql
3741    /// DELETE
3742    /// ```
3743    Delete(Delete),
3744    /// ```sql
3745    /// CREATE VIEW
3746    /// ```
3747    CreateView(CreateView),
3748    /// ```sql
3749    /// CREATE TABLE
3750    /// ```
3751    CreateTable(CreateTable),
3752    /// ```sql
3753    /// CREATE VIRTUAL TABLE .. USING <module_name> (<module_args>)`
3754    /// ```
3755    /// Sqlite specific statement
3756    CreateVirtualTable {
3757        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
3758        /// Name of the virtual table module instance.
3759        name: ObjectName,
3760        /// `true` when `IF NOT EXISTS` was specified.
3761        if_not_exists: bool,
3762        /// Module name used by the virtual table.
3763        module_name: Ident,
3764        /// Arguments passed to the module.
3765        module_args: Vec<Ident>,
3766    },
3767    /// ```sql
3768    /// `CREATE INDEX`
3769    /// ```
3770    CreateIndex(CreateIndex),
3771    /// ```sql
3772    /// CREATE ROLE
3773    /// ```
3774    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createrole.html)
3775    CreateRole(CreateRole),
3776    /// ```sql
3777    /// CREATE SECRET
3778    /// ```
3779    /// See [DuckDB](https://duckdb.org/docs/sql/statements/create_secret.html)
3780    CreateSecret {
3781        /// `true` when `OR REPLACE` was specified.
3782        or_replace: bool,
3783        /// Optional `TEMPORARY` flag.
3784        temporary: Option<bool>,
3785        /// `true` when `IF NOT EXISTS` was present.
3786        if_not_exists: bool,
3787        /// Optional secret name.
3788        name: Option<Ident>,
3789        /// Optional storage specifier identifier.
3790        storage_specifier: Option<Ident>,
3791        /// The secret type identifier.
3792        secret_type: Ident,
3793        /// Additional secret options.
3794        options: Vec<SecretOption>,
3795    },
3796    /// A `CREATE SERVER` statement.
3797    CreateServer(CreateServerStatement),
3798    /// ```sql
3799    /// CREATE FOREIGN DATA WRAPPER
3800    /// ```
3801    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createforeigndatawrapper.html)
3802    CreateForeignDataWrapper(CreateForeignDataWrapper),
3803    /// ```sql
3804    /// CREATE FOREIGN TABLE
3805    /// ```
3806    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createforeigntable.html)
3807    CreateForeignTable(CreateForeignTable),
3808    /// ```sql
3809    /// CREATE POLICY
3810    /// ```
3811    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createpolicy.html)
3812    CreatePolicy(CreatePolicy),
3813    /// ```sql
3814    /// CREATE CONNECTOR
3815    /// ```
3816    /// See [Hive](https://cwiki.apache.org/confluence/pages/viewpage.action?pageId=27362034#LanguageManualDDL-CreateDataConnectorCreateConnector)
3817    CreateConnector(CreateConnector),
3818    /// ```sql
3819    /// CREATE OPERATOR
3820    /// ```
3821    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createoperator.html)
3822    CreateOperator(CreateOperator),
3823    /// ```sql
3824    /// CREATE OPERATOR FAMILY
3825    /// ```
3826    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createopfamily.html)
3827    CreateOperatorFamily(CreateOperatorFamily),
3828    /// ```sql
3829    /// CREATE OPERATOR CLASS
3830    /// ```
3831    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createopclass.html)
3832    CreateOperatorClass(CreateOperatorClass),
3833    /// ```sql
3834    /// CREATE AGGREGATE
3835    /// ```
3836    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createaggregate.html)
3837    CreateAggregate(CreateAggregate),
3838    /// ```sql
3839    /// ALTER TABLE
3840    /// ```
3841    AlterTable(AlterTable),
3842    /// ```sql
3843    /// ALTER SCHEMA
3844    /// ```
3845    /// See [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#alter_schema_collate_statement)
3846    AlterSchema(AlterSchema),
3847    /// ```sql
3848    /// ALTER INDEX
3849    /// ```
3850    AlterIndex {
3851        /// Name of the index to alter.
3852        name: ObjectName,
3853        /// The operation to perform on the index.
3854        operation: AlterIndexOperation,
3855    },
3856    /// ```sql
3857    /// ALTER VIEW
3858    /// ```
3859    AlterView {
3860        /// View name being altered.
3861        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
3862        name: ObjectName,
3863        /// Optional new column list for the view.
3864        columns: Vec<Ident>,
3865        /// Replacement query for the view definition.
3866        query: Box<Query>,
3867        /// Additional WITH options for the view.
3868        with_options: Vec<SqlOption>,
3869    },
3870    /// ```sql
3871    /// ALTER DOMAIN
3872    /// ```
3873    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-alterdomain.html)
3874    AlterDomain(AlterDomain),
3875    /// ```sql
3876    /// ALTER EXTENSION
3877    /// ```
3878    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-alterextension.html)
3879    AlterExtension(AlterExtension),
3880    /// ```sql
3881    /// ALTER FUNCTION
3882    /// ALTER AGGREGATE
3883    /// ALTER PROCEDURE
3884    /// ```
3885    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-alterfunction.html)
3886    /// and [PostgreSQL](https://www.postgresql.org/docs/current/sql-alteraggregate.html)
3887    /// and [PostgreSQL](https://www.postgresql.org/docs/current/sql-alterprocedure.html)
3888    AlterFunction(AlterFunction),
3889    /// ```sql
3890    /// ALTER TYPE
3891    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-altertype.html)
3892    /// ```
3893    AlterType(AlterType),
3894    /// ```sql
3895    /// ALTER TRIGGER
3896    /// ```
3897    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-altertrigger.html)
3898    AlterTrigger(AlterTrigger),
3899    /// ```sql
3900    /// ALTER COLLATION
3901    /// ```
3902    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-altercollation.html)
3903    AlterCollation(AlterCollation),
3904    /// ```sql
3905    /// ALTER DEFAULT PRIVILEGES
3906    ///     [ FOR { ROLE | USER } target_role [, ...] ]
3907    ///     [ IN SCHEMA schema_name [, ...] ]
3908    ///     abbreviated_grant_or_revoke
3909    /// ```
3910    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-alterdefaultprivileges.html)
3911    AlterDefaultPrivileges(AlterDefaultPrivileges),
3912    /// ```sql
3913    /// ALTER OPERATOR
3914    /// ```
3915    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-alteroperator.html)
3916    AlterOperator(AlterOperator),
3917    /// ```sql
3918    /// ALTER OPERATOR FAMILY
3919    /// ```
3920    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-alteropfamily.html)
3921    AlterOperatorFamily(AlterOperatorFamily),
3922    /// ```sql
3923    /// ALTER OPERATOR CLASS
3924    /// ```
3925    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-alteropclass.html)
3926    AlterOperatorClass(AlterOperatorClass),
3927    /// ```sql
3928    /// ALTER ROLE
3929    /// ```
3930    AlterRole {
3931        /// Role name being altered.
3932        name: Ident,
3933        /// Operation to perform on the role.
3934        operation: AlterRoleOperation,
3935    },
3936    /// ```sql
3937    /// ALTER POLICY <NAME> ON <TABLE NAME> [<OPERATION>]
3938    /// ```
3939    /// (Postgresql-specific)
3940    AlterPolicy(AlterPolicy),
3941    /// ```sql
3942    /// ALTER CONNECTOR connector_name SET DCPROPERTIES(property_name=property_value, ...);
3943    /// or
3944    /// ALTER CONNECTOR connector_name SET URL new_url;
3945    /// or
3946    /// ALTER CONNECTOR connector_name SET OWNER [USER|ROLE] user_or_role;
3947    /// ```
3948    /// (Hive-specific)
3949    AlterConnector {
3950        /// Name of the connector to alter.
3951        name: Ident,
3952        /// Optional connector properties to set.
3953        properties: Option<Vec<SqlOption>>,
3954        /// Optional new URL for the connector.
3955        url: Option<String>,
3956        /// Optional new owner specification.
3957        owner: Option<ddl::AlterConnectorOwner>,
3958    },
3959    /// ```sql
3960    /// ALTER SESSION SET sessionParam
3961    /// ALTER SESSION UNSET <param_name> [ , <param_name> , ... ]
3962    /// ```
3963    /// See <https://docs.snowflake.com/en/sql-reference/sql/alter-session>
3964    AlterSession {
3965        /// true is to set for the session parameters, false is to unset
3966        set: bool,
3967        /// The session parameters to set or unset
3968        session_params: KeyValueOptions,
3969    },
3970    /// ```sql
3971    /// ATTACH DATABASE 'path/to/file' AS alias
3972    /// ```
3973    /// (SQLite-specific)
3974    AttachDatabase {
3975        /// The name to bind to the newly attached database
3976        schema_name: Ident,
3977        /// An expression that indicates the path to the database file
3978        database_file_name: Expr,
3979        /// true if the syntax is 'ATTACH DATABASE', false if it's just 'ATTACH'
3980        database: bool,
3981    },
3982    /// (DuckDB-specific)
3983    /// ```sql
3984    /// ATTACH 'sqlite_file.db' AS sqlite_db (READ_ONLY, TYPE SQLITE);
3985    /// ```
3986    /// See <https://duckdb.org/docs/sql/statements/attach.html>
3987    AttachDuckDBDatabase {
3988        /// `true` when `IF NOT EXISTS` was present.
3989        if_not_exists: bool,
3990        /// `true` if the syntax used `ATTACH DATABASE` rather than `ATTACH`.
3991        database: bool,
3992        /// The path identifier to the database file being attached.
3993        database_path: Ident,
3994        /// Optional alias assigned to the attached database.
3995        database_alias: Option<Ident>,
3996        /// Dialect-specific attach options (e.g., `READ_ONLY`).
3997        attach_options: Vec<AttachDuckDBDatabaseOption>,
3998    },
3999    /// (DuckDB-specific)
4000    /// ```sql
4001    /// DETACH db_alias;
4002    /// ```
4003    /// See <https://duckdb.org/docs/sql/statements/attach.html>
4004    DetachDuckDBDatabase {
4005        /// `true` when `IF EXISTS` was present.
4006        if_exists: bool,
4007        /// `true` if the syntax used `DETACH DATABASE` rather than `DETACH`.
4008        database: bool,
4009        /// Alias of the database to detach.
4010        database_alias: Ident,
4011    },
4012    /// ```sql
4013    /// DROP [TABLE, VIEW, ...]
4014    /// ```
4015    Drop {
4016        /// The type of the object to drop: TABLE, VIEW, etc.
4017        object_type: ObjectType,
4018        /// An optional `IF EXISTS` clause. (Non-standard.)
4019        if_exists: bool,
4020        /// One or more objects to drop. (ANSI SQL requires exactly one.)
4021        names: Vec<ObjectName>,
4022        /// Whether `CASCADE` was specified. This will be `false` when
4023        /// `RESTRICT` or no drop behavior at all was specified.
4024        cascade: bool,
4025        /// Whether `RESTRICT` was specified. This will be `false` when
4026        /// `CASCADE` or no drop behavior at all was specified.
4027        restrict: bool,
4028        /// Hive allows you specify whether the table's stored data will be
4029        /// deleted along with the dropped table
4030        purge: bool,
4031        /// MySQL-specific "TEMPORARY" keyword
4032        temporary: bool,
4033        /// MySQL-specific drop index syntax, which requires table specification
4034        /// See <https://dev.mysql.com/doc/refman/8.4/en/drop-index.html>
4035        table: Option<ObjectName>,
4036    },
4037    /// ```sql
4038    /// DROP FUNCTION
4039    /// ```
4040    DropFunction(DropFunction),
4041    /// ```sql
4042    /// DROP DOMAIN
4043    /// ```
4044    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-dropdomain.html)
4045    ///
4046    /// DROP DOMAIN [ IF EXISTS ] name [, ...] [ CASCADE | RESTRICT ]
4047    ///
4048    DropDomain(DropDomain),
4049    /// ```sql
4050    /// DROP PROCEDURE
4051    /// ```
4052    DropProcedure {
4053        /// `true` when `IF EXISTS` was present.
4054        if_exists: bool,
4055        /// One or more functions/procedures to drop.
4056        proc_desc: Vec<FunctionDesc>,
4057        /// Optional drop behavior (`CASCADE` or `RESTRICT`).
4058        drop_behavior: Option<DropBehavior>,
4059    },
4060    /// ```sql
4061    /// DROP SECRET
4062    /// ```
4063    DropSecret {
4064        /// `true` when `IF EXISTS` was present.
4065        if_exists: bool,
4066        /// Optional `TEMPORARY` marker.
4067        temporary: Option<bool>,
4068        /// Name of the secret to drop.
4069        name: Ident,
4070        /// Optional storage specifier identifier.
4071        storage_specifier: Option<Ident>,
4072    },
4073    ///```sql
4074    /// DROP POLICY
4075    /// ```
4076    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-droppolicy.html)
4077    DropPolicy(DropPolicy),
4078    /// ```sql
4079    /// DROP CONNECTOR
4080    /// ```
4081    /// See [Hive](https://cwiki.apache.org/confluence/pages/viewpage.action?pageId=27362034#LanguageManualDDL-DropConnector)
4082    DropConnector {
4083        /// `true` when `IF EXISTS` was present.
4084        if_exists: bool,
4085        /// Name of the connector to drop.
4086        name: Ident,
4087    },
4088    /// ```sql
4089    /// DECLARE
4090    /// ```
4091    /// Declare Cursor Variables
4092    ///
4093    /// Note: this is a PostgreSQL-specific statement,
4094    /// but may also compatible with other SQL.
4095    Declare {
4096        /// Cursor declaration statements collected by `DECLARE`.
4097        stmts: Vec<Declare>,
4098    },
4099    /// ```sql
4100    /// CREATE EXTENSION [ IF NOT EXISTS ] extension_name
4101    ///     [ WITH ] [ SCHEMA schema_name ]
4102    ///              [ VERSION version ]
4103    ///              [ CASCADE ]
4104    /// ```
4105    ///
4106    /// Note: this is a PostgreSQL-specific statement,
4107    CreateExtension(CreateExtension),
4108    /// ```sql
4109    /// CREATE COLLATION
4110    /// ```
4111    /// Note: this is a PostgreSQL-specific statement.
4112    /// <https://www.postgresql.org/docs/current/sql-createcollation.html>
4113    CreateCollation(CreateCollation),
4114    /// ```sql
4115    /// CREATE TEXT SEARCH CONFIGURATION name ( PARSER = parser_name )
4116    /// ```
4117    /// Note: this is a PostgreSQL-specific statement.
4118    /// <https://www.postgresql.org/docs/current/sql-createtsconfig.html>
4119    CreateTextSearchConfiguration(CreateTextSearchConfiguration),
4120    /// ```sql
4121    /// CREATE TEXT SEARCH DICTIONARY name ( TEMPLATE = template_name [, option = value, ...] )
4122    /// ```
4123    /// Note: this is a PostgreSQL-specific statement.
4124    /// <https://www.postgresql.org/docs/current/sql-createtsdictionary.html>
4125    CreateTextSearchDictionary(CreateTextSearchDictionary),
4126    /// ```sql
4127    /// CREATE TEXT SEARCH PARSER name ( START = start_fn, GETTOKEN = gettoken_fn, END = end_fn, LEXTYPES = lextypes_fn [, HEADLINE = headline_fn] )
4128    /// ```
4129    /// Note: this is a PostgreSQL-specific statement.
4130    /// <https://www.postgresql.org/docs/current/sql-createtsparser.html>
4131    CreateTextSearchParser(CreateTextSearchParser),
4132    /// ```sql
4133    /// CREATE TEXT SEARCH TEMPLATE name ( [INIT = init_fn,] LEXIZE = lexize_fn )
4134    /// ```
4135    /// Note: this is a PostgreSQL-specific statement.
4136    /// <https://www.postgresql.org/docs/current/sql-createtstemplate.html>
4137    CreateTextSearchTemplate(CreateTextSearchTemplate),
4138    /// ```sql
4139    /// CREATE PUBLICATION name [ FOR ALL TABLES | FOR TABLE table [, ...] | FOR TABLES IN SCHEMA schema [, ...] ] [ WITH ( option = value [, ...] ) ]
4140    /// ```
4141    /// Note: this is a PostgreSQL-specific statement.
4142    /// <https://www.postgresql.org/docs/current/sql-createpublication.html>
4143    CreatePublication(CreatePublication),
4144    /// ```sql
4145    /// CREATE SUBSCRIPTION name CONNECTION 'conninfo' PUBLICATION publication_name [, ...] [ WITH ( option = value [, ...] ) ]
4146    /// ```
4147    /// Note: this is a PostgreSQL-specific statement.
4148    /// <https://www.postgresql.org/docs/current/sql-createsubscription.html>
4149    CreateSubscription(CreateSubscription),
4150    /// ```sql
4151    /// CREATE CAST (source_type AS target_type) WITH FUNCTION func_name [(arg_types)] [AS ASSIGNMENT | AS IMPLICIT]
4152    /// CREATE CAST (source_type AS target_type) WITHOUT FUNCTION [AS ASSIGNMENT | AS IMPLICIT]
4153    /// CREATE CAST (source_type AS target_type) WITH INOUT [AS ASSIGNMENT | AS IMPLICIT]
4154    /// ```
4155    /// Note: this is a PostgreSQL-specific statement.
4156    /// <https://www.postgresql.org/docs/current/sql-createcast.html>
4157    CreateCast(CreateCast),
4158    /// ```sql
4159    /// CREATE [DEFAULT] CONVERSION name FOR 'source_encoding' TO 'dest_encoding' FROM function_name
4160    /// ```
4161    /// Note: this is a PostgreSQL-specific statement.
4162    /// <https://www.postgresql.org/docs/current/sql-createconversion.html>
4163    CreateConversion(CreateConversion),
4164    /// ```sql
4165    /// CREATE [OR REPLACE] [TRUSTED] [PROCEDURAL] LANGUAGE name [HANDLER handler_func] [INLINE inline_func] [VALIDATOR validator_func | NO VALIDATOR]
4166    /// ```
4167    /// Note: this is a PostgreSQL-specific statement.
4168    /// <https://www.postgresql.org/docs/current/sql-createlanguage.html>
4169    CreateLanguage(CreateLanguage),
4170    /// ```sql
4171    /// CREATE RULE name AS ON event TO table [WHERE condition] DO [ALSO | INSTEAD] { NOTHING | command | (command ; ...) }
4172    /// ```
4173    /// Note: this is a PostgreSQL-specific statement.
4174    /// <https://www.postgresql.org/docs/current/sql-createrule.html>
4175    CreateRule(CreateRule),
4176    /// ```sql
4177    /// CREATE STATISTICS [ IF NOT EXISTS ] name [ ( kind [, ...] ) ] ON expr [, ...] FROM table_name
4178    /// ```
4179    /// Note: this is a PostgreSQL-specific statement.
4180    /// <https://www.postgresql.org/docs/current/sql-createstatistics.html>
4181    CreateStatistics(CreateStatistics),
4182    /// ```sql
4183    /// CREATE ACCESS METHOD name TYPE INDEX | TABLE HANDLER handler_function
4184    /// ```
4185    /// Note: this is a PostgreSQL-specific statement.
4186    /// <https://www.postgresql.org/docs/current/sql-create-access-method.html>
4187    CreateAccessMethod(CreateAccessMethod),
4188    /// ```sql
4189    /// CREATE EVENT TRIGGER name ON event [ WHEN TAG IN ( 'tag' [, ...] ) ] EXECUTE FUNCTION | PROCEDURE function_name()
4190    /// ```
4191    /// Note: this is a PostgreSQL-specific statement.
4192    /// <https://www.postgresql.org/docs/current/sql-createeventtrigger.html>
4193    CreateEventTrigger(CreateEventTrigger),
4194    /// ```sql
4195    /// CREATE [ OR REPLACE ] TRANSFORM FOR type_name LANGUAGE lang_name ( transform_element_list )
4196    /// ```
4197    /// Note: this is a PostgreSQL-specific statement.
4198    /// <https://www.postgresql.org/docs/current/sql-createtransform.html>
4199    CreateTransform(CreateTransform),
4200    /// ```sql
4201    /// SECURITY LABEL [ FOR provider_name ] ON object_type object_name IS { 'label' | NULL }
4202    /// ```
4203    /// Note: this is a PostgreSQL-specific statement.
4204    /// <https://www.postgresql.org/docs/current/sql-securitylabel.html>
4205    SecurityLabel(SecurityLabel),
4206    /// ```sql
4207    /// CREATE USER MAPPING [ IF NOT EXISTS ] FOR { role | USER | CURRENT_ROLE | CURRENT_USER | PUBLIC } SERVER server_name [ OPTIONS (...) ]
4208    /// ```
4209    /// Note: this is a PostgreSQL-specific statement.
4210    /// <https://www.postgresql.org/docs/current/sql-createusermapping.html>
4211    CreateUserMapping(CreateUserMapping),
4212    /// ```sql
4213    /// CREATE TABLESPACE name [ OWNER role ] LOCATION 'directory' [ WITH (options) ]
4214    /// ```
4215    /// Note: this is a PostgreSQL-specific statement.
4216    /// <https://www.postgresql.org/docs/current/sql-createtablespace.html>
4217    CreateTablespace(CreateTablespace),
4218    /// ```sql
4219    /// DROP EXTENSION [ IF EXISTS ] name [, ...] [ CASCADE | RESTRICT ]
4220    /// ```
4221    /// Note: this is a PostgreSQL-specific statement.
4222    /// <https://www.postgresql.org/docs/current/sql-dropextension.html>
4223    DropExtension(DropExtension),
4224    /// ```sql
4225    /// DROP OPERATOR [ IF EXISTS ] name ( { left_type | NONE } , right_type ) [, ...] [ CASCADE | RESTRICT ]
4226    /// ```
4227    /// Note: this is a PostgreSQL-specific statement.
4228    /// <https://www.postgresql.org/docs/current/sql-dropoperator.html>
4229    DropOperator(DropOperator),
4230    /// ```sql
4231    /// DROP OPERATOR FAMILY [ IF EXISTS ] name USING index_method [ CASCADE | RESTRICT ]
4232    /// ```
4233    /// Note: this is a PostgreSQL-specific statement.
4234    /// <https://www.postgresql.org/docs/current/sql-dropopfamily.html>
4235    DropOperatorFamily(DropOperatorFamily),
4236    /// ```sql
4237    /// DROP OPERATOR CLASS [ IF EXISTS ] name USING index_method [ CASCADE | RESTRICT ]
4238    /// ```
4239    /// Note: this is a PostgreSQL-specific statement.
4240    /// <https://www.postgresql.org/docs/current/sql-dropopclass.html>
4241    DropOperatorClass(DropOperatorClass),
4242    /// ```sql
4243    /// FETCH
4244    /// ```
4245    /// Retrieve rows from a query using a cursor
4246    ///
4247    /// Note: this is a PostgreSQL-specific statement,
4248    /// but may also compatible with other SQL.
4249    Fetch {
4250        /// Cursor name
4251        name: Ident,
4252        /// The fetch direction (e.g., `FORWARD`, `BACKWARD`).
4253        direction: FetchDirection,
4254        /// The fetch position (e.g., `ALL`, `NEXT`, `ABSOLUTE`).
4255        position: FetchPosition,
4256        /// Optional target table to fetch rows into.
4257        into: Option<ObjectName>,
4258    },
4259    /// ```sql
4260    /// FLUSH [NO_WRITE_TO_BINLOG | LOCAL] flush_option [, flush_option] ... | tables_option
4261    /// ```
4262    ///
4263    /// Note: this is a Mysql-specific statement,
4264    /// but may also compatible with other SQL.
4265    Flush {
4266        /// The specific flush option or object to flush.
4267        object_type: FlushType,
4268        /// Optional flush location (dialect-specific).
4269        location: Option<FlushLocation>,
4270        /// Optional channel name used for flush operations.
4271        channel: Option<String>,
4272        /// Whether a read lock was requested.
4273        read_lock: bool,
4274        /// Whether this is an export flush operation.
4275        export: bool,
4276        /// Optional list of tables involved in the flush.
4277        tables: Vec<ObjectName>,
4278    },
4279    /// ```sql
4280    /// DISCARD [ ALL | PLANS | SEQUENCES | TEMPORARY | TEMP ]
4281    /// ```
4282    ///
4283    /// Note: this is a PostgreSQL-specific statement,
4284    /// but may also compatible with other SQL.
4285    Discard {
4286        /// The kind of object(s) to discard (ALL, PLANS, etc.).
4287        object_type: DiscardObject,
4288    },
4289    /// `SHOW FUNCTIONS`
4290    ///
4291    /// Note: this is a Presto-specific statement.
4292    ShowFunctions {
4293        /// Optional filter for which functions to display.
4294        filter: Option<ShowStatementFilter>,
4295    },
4296    /// ```sql
4297    /// SHOW <variable>
4298    /// ```
4299    ///
4300    /// Note: this is a PostgreSQL-specific statement.
4301    ShowVariable {
4302        /// Variable name as one or more identifiers.
4303        variable: Vec<Ident>,
4304    },
4305    /// ```sql
4306    /// SHOW [GLOBAL | SESSION] STATUS [LIKE 'pattern' | WHERE expr]
4307    /// ```
4308    ///
4309    /// Note: this is a MySQL-specific statement.
4310    ShowStatus {
4311        /// Optional filter for which status entries to display.
4312        filter: Option<ShowStatementFilter>,
4313        /// `true` when `GLOBAL` scope was requested.
4314        global: bool,
4315        /// `true` when `SESSION` scope was requested.
4316        session: bool,
4317    },
4318    /// ```sql
4319    /// SHOW VARIABLES
4320    /// ```
4321    ///
4322    /// Note: this is a MySQL-specific statement.
4323    ShowVariables {
4324        /// Optional filter for which variables to display.
4325        filter: Option<ShowStatementFilter>,
4326        /// `true` when `GLOBAL` scope was requested.
4327        global: bool,
4328        /// `true` when `SESSION` scope was requested.
4329        session: bool,
4330    },
4331    /// ```sql
4332    /// SHOW CREATE TABLE
4333    /// ```
4334    ///
4335    /// Note: this is a MySQL-specific statement.
4336    ShowCreate {
4337        /// The kind of object being shown (TABLE, VIEW, etc.).
4338        obj_type: ShowCreateObject,
4339        /// The name of the object to show create statement for.
4340        obj_name: ObjectName,
4341    },
4342    /// ```sql
4343    /// SHOW COLUMNS
4344    /// ```
4345    ShowColumns {
4346        /// `true` when extended column information was requested.
4347        extended: bool,
4348        /// `true` when full column details were requested.
4349        full: bool,
4350        /// Additional options for `SHOW COLUMNS`.
4351        show_options: ShowStatementOptions,
4352    },
4353    /// ```sql
4354    /// SHOW CATALOGS
4355    /// ```
4356    ShowCatalogs {
4357        /// `true` when terse output format was requested.
4358        terse: bool,
4359        /// `true` when history information was requested.
4360        history: bool,
4361        /// Additional options for `SHOW CATALOGS`.
4362        show_options: ShowStatementOptions,
4363    },
4364    /// ```sql
4365    /// SHOW DATABASES
4366    /// ```
4367    ShowDatabases {
4368        /// `true` when terse output format was requested.
4369        terse: bool,
4370        /// `true` when history information was requested.
4371        history: bool,
4372        /// Additional options for `SHOW DATABASES`.
4373        show_options: ShowStatementOptions,
4374    },
4375    /// ```sql
4376    /// SHOW [FULL] PROCESSLIST
4377    /// ```
4378    ///
4379    /// Note: this is a MySQL-specific statement.
4380    ShowProcessList {
4381        /// `true` when full process information was requested.
4382        full: bool,
4383    },
4384    /// ```sql
4385    /// SHOW SCHEMAS
4386    /// ```
4387    ShowSchemas {
4388        /// `true` when terse (compact) output was requested.
4389        terse: bool,
4390        /// `true` when history information was requested.
4391        history: bool,
4392        /// Additional options for `SHOW SCHEMAS`.
4393        show_options: ShowStatementOptions,
4394    },
4395    // ```sql
4396    // SHOW {CHARACTER SET | CHARSET}
4397    // ```
4398    // [MySQL]:
4399    // <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>
4400    /// Show the available character sets (alias `CHARSET`).
4401    ShowCharset(ShowCharset),
4402    /// ```sql
4403    /// SHOW OBJECTS LIKE 'line%' IN mydb.public
4404    /// ```
4405    /// Snowflake-specific statement
4406    /// <https://docs.snowflake.com/en/sql-reference/sql/show-objects>
4407    ShowObjects(ShowObjects),
4408    /// ```sql
4409    /// SHOW TABLES
4410    /// ```
4411    ShowTables {
4412        /// `true` when terse output format was requested (compact listing).
4413        terse: bool,
4414        /// `true` when history rows are requested.
4415        history: bool,
4416        /// `true` when extended information should be shown.
4417        extended: bool,
4418        /// `true` when a full listing was requested.
4419        full: bool,
4420        /// `true` when external tables should be included.
4421        external: bool,
4422        /// Additional options for `SHOW` statements.
4423        show_options: ShowStatementOptions,
4424    },
4425    /// ```sql
4426    /// SHOW VIEWS
4427    /// ```
4428    ShowViews {
4429        /// `true` when terse output format was requested.
4430        terse: bool,
4431        /// `true` when materialized views should be included.
4432        materialized: bool,
4433        /// Additional options for `SHOW` statements.
4434        show_options: ShowStatementOptions,
4435    },
4436    /// ```sql
4437    /// SHOW COLLATION
4438    /// ```
4439    ///
4440    /// Note: this is a MySQL-specific statement.
4441    ShowCollation {
4442        /// Optional filter for which collations to display.
4443        filter: Option<ShowStatementFilter>,
4444    },
4445    /// ```sql
4446    /// `USE ...`
4447    /// ```
4448    Use(Use),
4449    /// ```sql
4450    /// START  [ TRANSACTION | WORK ] | START TRANSACTION } ...
4451    /// ```
4452    /// If `begin` is false.
4453    ///
4454    /// ```sql
4455    /// `BEGIN  [ TRANSACTION | WORK ] | START TRANSACTION } ...`
4456    /// ```
4457    /// If `begin` is true
4458    StartTransaction {
4459        /// Transaction modes such as `ISOLATION LEVEL` or `READ WRITE`.
4460        modes: Vec<TransactionMode>,
4461        /// `true` when this was parsed as `BEGIN` instead of `START`.
4462        begin: bool,
4463        /// Optional specific keyword used: `TRANSACTION` or `WORK`.
4464        transaction: Option<BeginTransactionKind>,
4465        /// Optional transaction modifier (e.g., `AND NO CHAIN`).
4466        modifier: Option<TransactionModifier>,
4467        /// List of statements belonging to the `BEGIN` block.
4468        /// Example:
4469        /// ```sql
4470        /// BEGIN
4471        ///     SELECT 1;
4472        ///     SELECT 2;
4473        /// END;
4474        /// ```
4475        statements: Vec<Statement>,
4476        /// Exception handling with exception clauses.
4477        /// Example:
4478        /// ```sql
4479        /// EXCEPTION
4480        ///     WHEN EXCEPTION_1 THEN
4481        ///         SELECT 2;
4482        ///     WHEN EXCEPTION_2 OR EXCEPTION_3 THEN
4483        ///         SELECT 3;
4484        ///     WHEN OTHER THEN
4485        ///         SELECT 4;
4486        /// ```
4487        /// <https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#beginexceptionend>
4488        /// <https://docs.snowflake.com/en/sql-reference/snowflake-scripting/exception>
4489        exception: Option<Vec<ExceptionWhen>>,
4490        /// TRUE if the statement has an `END` keyword.
4491        has_end_keyword: bool,
4492    },
4493    /// ```sql
4494    /// COMMENT ON ...
4495    /// ```
4496    ///
4497    /// Note: this is a PostgreSQL-specific statement.
4498    Comment {
4499        /// Type of object being commented (table, column, etc.).
4500        object_type: CommentObject,
4501        /// Name of the object the comment applies to.
4502        object_name: ObjectName,
4503        /// Argument types for overloaded objects. `Some(vec![])` represents an
4504        /// empty `()` parameter list (e.g. `COMMENT ON FUNCTION f() IS '…'`),
4505        /// while `None` means no parameter list was provided. Used for
4506        /// `FUNCTION`, `PROCEDURE`, and `AGGREGATE` targets.
4507        arguments: Option<Vec<DataType>>,
4508        /// Operand signature for `COMMENT ON OPERATOR name (left, right)`.
4509        /// Always `Some(_)` for `Operator`, `None` for every other variant.
4510        /// Modeled separately from `arguments` because operator slots may be
4511        /// `NONE` (unary operators), which `Vec<DataType>` cannot express.
4512        operator_args: Option<CommentOperatorArgs>,
4513        /// Partner relation for objects scoped to a relation, i.e. the
4514        /// `ON <table>` (or `ON DOMAIN <domain>`) tail in
4515        /// `COMMENT ON TRIGGER t ON tbl IS '…'`,
4516        /// `COMMENT ON POLICY p ON tbl IS '…'`,
4517        /// `COMMENT ON RULE r ON tbl IS '…'`, or
4518        /// `COMMENT ON CONSTRAINT c ON [DOMAIN] tbl IS '…'`.
4519        table_name: Option<ObjectName>,
4520        /// `true` when the relation tail used the `ON DOMAIN <domain>` form.
4521        /// Only meaningful for `Constraint`; always `false` otherwise.
4522        on_domain: bool,
4523        /// Optional comment text, always the DECODED value (None to remove
4524        /// comment). Downstream consumers read this field regardless of the
4525        /// original quoting style.
4526        comment: Option<String>,
4527        /// Preserves the original dollar-quote delimiter so Display can
4528        /// round-trip `IS $$body$$` / `IS $tag$body$tag$`. `None` means the
4529        /// body was single-quoted (or `NULL`); `comment` still carries the
4530        /// decoded value in that case.
4531        comment_dollar_quote: Option<DollarQuotedString>,
4532        /// An optional `IF EXISTS` clause. (Non-standard.)
4533        /// See <https://docs.snowflake.com/en/sql-reference/sql/comment>
4534        if_exists: bool,
4535    },
4536    /// ```sql
4537    /// COMMIT [ TRANSACTION | WORK ] [ AND [ NO ] CHAIN ]
4538    /// ```
4539    /// If `end` is false
4540    ///
4541    /// ```sql
4542    /// END [ TRY | CATCH ]
4543    /// ```
4544    /// If `end` is true
4545    Commit {
4546        /// `true` when `AND [ NO ] CHAIN` was present.
4547        chain: bool,
4548        /// `true` when this `COMMIT` was parsed as an `END` block terminator.
4549        end: bool,
4550        /// Optional transaction modifier for commit semantics.
4551        modifier: Option<TransactionModifier>,
4552    },
4553    /// ```sql
4554    /// ROLLBACK [ TRANSACTION | WORK ] [ AND [ NO ] CHAIN ] [ TO [ SAVEPOINT ] savepoint_name ]
4555    /// ```
4556    Rollback {
4557        /// `true` when `AND [ NO ] CHAIN` was present.
4558        chain: bool,
4559        /// Optional savepoint name to roll back to.
4560        savepoint: Option<Ident>,
4561    },
4562    /// ```sql
4563    /// CREATE SCHEMA
4564    /// ```
4565    CreateSchema {
4566        /// `<schema name> | AUTHORIZATION <schema authorization identifier>  | <schema name>  AUTHORIZATION <schema authorization identifier>`
4567        schema_name: SchemaName,
4568        /// `true` when `IF NOT EXISTS` was present.
4569        if_not_exists: bool,
4570        /// Schema properties.
4571        ///
4572        /// ```sql
4573        /// CREATE SCHEMA myschema WITH (key1='value1');
4574        /// ```
4575        ///
4576        /// [Trino](https://trino.io/docs/current/sql/create-schema.html)
4577        with: Option<Vec<SqlOption>>,
4578        /// Schema options.
4579        ///
4580        /// ```sql
4581        /// CREATE SCHEMA myschema OPTIONS(key1='value1');
4582        /// ```
4583        ///
4584        /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_schema_statement)
4585        options: Option<Vec<SqlOption>>,
4586        /// Default collation specification for the schema.
4587        ///
4588        /// ```sql
4589        /// CREATE SCHEMA myschema DEFAULT COLLATE 'und:ci';
4590        /// ```
4591        ///
4592        /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_schema_statement)
4593        default_collate_spec: Option<Expr>,
4594        /// Clones a schema
4595        ///
4596        /// ```sql
4597        /// CREATE SCHEMA myschema CLONE otherschema
4598        /// ```
4599        ///
4600        /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-clone#databases-schemas)
4601        clone: Option<ObjectName>,
4602    },
4603    /// ```sql
4604    /// CREATE DATABASE
4605    /// ```
4606    /// See:
4607    /// <https://docs.snowflake.com/en/sql-reference/sql/create-database>
4608    CreateDatabase {
4609        /// Database name.
4610        db_name: ObjectName,
4611        /// `IF NOT EXISTS` flag.
4612        if_not_exists: bool,
4613        /// Optional location URI.
4614        location: Option<String>,
4615        /// Optional managed location.
4616        managed_location: Option<String>,
4617        /// `OR REPLACE` flag.
4618        or_replace: bool,
4619        /// `TRANSIENT` flag.
4620        transient: bool,
4621        /// Optional clone source.
4622        clone: Option<ObjectName>,
4623        /// Optional data retention time in days.
4624        data_retention_time_in_days: Option<u64>,
4625        /// Optional maximum data extension time in days.
4626        max_data_extension_time_in_days: Option<u64>,
4627        /// Optional external volume identifier.
4628        external_volume: Option<String>,
4629        /// Optional catalog name.
4630        catalog: Option<String>,
4631        /// Whether to replace invalid characters.
4632        replace_invalid_characters: Option<bool>,
4633        /// Default DDL collation string.
4634        default_ddl_collation: Option<String>,
4635        /// Storage serialization policy.
4636        storage_serialization_policy: Option<StorageSerializationPolicy>,
4637        /// Optional comment.
4638        comment: Option<String>,
4639        /// Optional default character set (MySQL).
4640        default_charset: Option<String>,
4641        /// Optional default collation (MySQL).
4642        default_collation: Option<String>,
4643        /// Optional catalog sync identifier.
4644        catalog_sync: Option<String>,
4645        /// Catalog sync namespace mode.
4646        catalog_sync_namespace_mode: Option<CatalogSyncNamespaceMode>,
4647        /// Optional flatten delimiter for namespace sync.
4648        catalog_sync_namespace_flatten_delimiter: Option<String>,
4649        /// Optional tags for the database.
4650        with_tags: Option<Vec<Tag>>,
4651        /// Optional contact entries for the database.
4652        with_contacts: Option<Vec<ContactEntry>>,
4653    },
4654    /// ```sql
4655    /// CREATE FUNCTION
4656    /// ```
4657    ///
4658    /// Supported variants:
4659    /// 1. [Hive](https://cwiki.apache.org/confluence/display/hive/languagemanual+ddl#LanguageManualDDL-Create/Drop/ReloadFunction)
4660    /// 2. [PostgreSQL](https://www.postgresql.org/docs/15/sql-createfunction.html)
4661    /// 3. [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_function_statement)
4662    /// 4. [MsSql](https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql)
4663    CreateFunction(CreateFunction),
4664    /// CREATE TRIGGER statement. See struct [CreateTrigger] for details.
4665    CreateTrigger(CreateTrigger),
4666    /// DROP TRIGGER statement. See struct [DropTrigger] for details.
4667    DropTrigger(DropTrigger),
4668    /// ```sql
4669    /// CREATE PROCEDURE
4670    /// ```
4671    CreateProcedure {
4672        /// `OR ALTER` flag.
4673        or_alter: bool,
4674        /// Procedure name.
4675        name: ObjectName,
4676        /// Optional procedure parameters.
4677        params: Option<Vec<ProcedureParam>>,
4678        /// Optional language identifier.
4679        language: Option<Ident>,
4680        /// Procedure body statements.
4681        body: ConditionalStatements,
4682    },
4683    /// ```sql
4684    /// CREATE MACRO
4685    /// ```
4686    ///
4687    /// Supported variants:
4688    /// 1. [DuckDB](https://duckdb.org/docs/sql/statements/create_macro)
4689    CreateMacro {
4690        /// `OR REPLACE` flag.
4691        or_replace: bool,
4692        /// Whether macro is temporary.
4693        temporary: bool,
4694        /// Macro name.
4695        name: ObjectName,
4696        /// Optional macro arguments.
4697        args: Option<Vec<MacroArg>>,
4698        /// Macro definition body.
4699        definition: MacroDefinition,
4700    },
4701    /// ```sql
4702    /// CREATE STAGE
4703    /// ```
4704    /// See <https://docs.snowflake.com/en/sql-reference/sql/create-stage>
4705    CreateStage {
4706        /// `OR REPLACE` flag for stage.
4707        or_replace: bool,
4708        /// Whether stage is temporary.
4709        temporary: bool,
4710        /// `IF NOT EXISTS` flag.
4711        if_not_exists: bool,
4712        /// Stage name.
4713        name: ObjectName,
4714        /// Stage parameters.
4715        stage_params: StageParamsObject,
4716        /// Directory table parameters.
4717        directory_table_params: KeyValueOptions,
4718        /// File format options.
4719        file_format: KeyValueOptions,
4720        /// Copy options for stage.
4721        copy_options: KeyValueOptions,
4722        /// Optional comment.
4723        comment: Option<String>,
4724    },
4725    /// ```sql
4726    /// ASSERT <condition> [AS <message>]
4727    /// ```
4728    Assert {
4729        /// Assertion condition expression.
4730        condition: Expr,
4731        /// Optional message expression.
4732        message: Option<Expr>,
4733    },
4734    /// ```sql
4735    /// GRANT privileges ON objects TO grantees
4736    /// ```
4737    Grant(Grant),
4738    /// ```sql
4739    /// DENY privileges ON object TO grantees
4740    /// ```
4741    Deny(DenyStatement),
4742    /// ```sql
4743    /// REVOKE privileges ON objects FROM grantees
4744    /// ```
4745    Revoke(Revoke),
4746    /// ```sql
4747    /// DEALLOCATE [ PREPARE ] { name | ALL }
4748    /// ```
4749    ///
4750    /// Note: this is a PostgreSQL-specific statement.
4751    Deallocate {
4752        /// Name to deallocate (or `ALL`).
4753        name: Ident,
4754        /// Whether `PREPARE` keyword was present.
4755        prepare: bool,
4756    },
4757    /// ```sql
4758    /// An `EXECUTE` statement
4759    /// ```
4760    ///
4761    /// Postgres: <https://www.postgresql.org/docs/current/sql-execute.html>
4762    /// MSSQL: <https://learn.microsoft.com/en-us/sql/relational-databases/stored-procedures/execute-a-stored-procedure>
4763    /// BigQuery: <https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#execute_immediate>
4764    /// Snowflake: <https://docs.snowflake.com/en/sql-reference/sql/execute-immediate>
4765    Execute {
4766        /// Optional function/procedure name.
4767        name: Option<ObjectName>,
4768        /// Parameter expressions passed to execute.
4769        parameters: Vec<Expr>,
4770        /// Whether parentheses were present around `parameters`.
4771        has_parentheses: bool,
4772        /// Is this an `EXECUTE IMMEDIATE`.
4773        immediate: bool,
4774        /// Identifiers to capture results into.
4775        into: Vec<Ident>,
4776        /// `USING` expressions with optional aliases.
4777        using: Vec<ExprWithAlias>,
4778        /// Whether the last parameter is the return value of the procedure
4779        /// MSSQL: <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/execute-transact-sql?view=sql-server-ver17#output>
4780        output: bool,
4781        /// Whether to invoke the procedure with the default parameter values
4782        /// MSSQL: <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/execute-transact-sql?view=sql-server-ver17#default>
4783        default: bool,
4784    },
4785    /// ```sql
4786    /// PREPARE name [ ( data_type [, ...] ) ] AS statement
4787    /// ```
4788    ///
4789    /// Note: this is a PostgreSQL-specific statement.
4790    Prepare {
4791        /// Name of the prepared statement.
4792        name: Ident,
4793        /// Optional data types for parameters.
4794        data_types: Vec<DataType>,
4795        /// Statement being prepared.
4796        statement: Box<Statement>,
4797    },
4798    /// ```sql
4799    /// KILL [CONNECTION | QUERY | MUTATION]
4800    /// ```
4801    ///
4802    /// See <https://clickhouse.com/docs/en/sql-reference/statements/kill/>
4803    /// See <https://dev.mysql.com/doc/refman/8.0/en/kill.html>
4804    Kill {
4805        /// Optional kill modifier (CONNECTION, QUERY, MUTATION).
4806        modifier: Option<KillType>,
4807        // processlist_id
4808        /// The id of the process to kill.
4809        id: u64,
4810    },
4811    /// ```sql
4812    /// [EXPLAIN | DESC | DESCRIBE] TABLE
4813    /// ```
4814    /// Note: this is a MySQL-specific statement. See <https://dev.mysql.com/doc/refman/8.0/en/explain.html>
4815    ExplainTable {
4816        /// `EXPLAIN | DESC | DESCRIBE`
4817        describe_alias: DescribeAlias,
4818        /// Hive style `FORMATTED | EXTENDED`
4819        hive_format: Option<HiveDescribeFormat>,
4820        /// Snowflake and ClickHouse support `DESC|DESCRIBE TABLE <table_name>` syntax
4821        ///
4822        /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/desc-table.html)
4823        /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/describe-table)
4824        has_table_keyword: bool,
4825        /// Table name
4826        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
4827        table_name: ObjectName,
4828    },
4829    /// ```sql
4830    /// [EXPLAIN | DESC | DESCRIBE]  <statement>
4831    /// ```
4832    Explain {
4833        /// `EXPLAIN | DESC | DESCRIBE`
4834        describe_alias: DescribeAlias,
4835        /// Carry out the command and show actual run times and other statistics.
4836        analyze: bool,
4837        /// Display additional information regarding the plan.
4838        verbose: bool,
4839        /// `EXPLAIN QUERY PLAN`
4840        /// Display the query plan without running the query.
4841        ///
4842        /// [SQLite](https://sqlite.org/lang_explain.html)
4843        query_plan: bool,
4844        /// `EXPLAIN ESTIMATE`
4845        /// [Clickhouse](https://clickhouse.com/docs/en/sql-reference/statements/explain#explain-estimate)
4846        estimate: bool,
4847        /// A SQL query that specifies what to explain
4848        statement: Box<Statement>,
4849        /// Optional output format of explain
4850        format: Option<AnalyzeFormatKind>,
4851        /// Postgres style utility options, `(analyze, verbose true)`
4852        options: Option<Vec<UtilityOption>>,
4853    },
4854    /// ```sql
4855    /// SAVEPOINT
4856    /// ```
4857    /// Define a new savepoint within the current transaction
4858    Savepoint {
4859        /// Name of the savepoint being defined.
4860        name: Ident,
4861    },
4862    /// ```sql
4863    /// RELEASE [ SAVEPOINT ] savepoint_name
4864    /// ```
4865    ReleaseSavepoint {
4866        /// Name of the savepoint to release.
4867        name: Ident,
4868    },
4869    /// A `MERGE` statement.
4870    ///
4871    /// ```sql
4872    /// MERGE INTO <target_table> USING <source> ON <join_expr> { matchedClause | notMatchedClause } [ ... ]
4873    /// ```
4874    /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/merge)
4875    /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/dml-syntax#merge_statement)
4876    /// [MSSQL](https://learn.microsoft.com/en-us/sql/t-sql/statements/merge-transact-sql?view=sql-server-ver16)
4877    Merge(Merge),
4878    /// ```sql
4879    /// CACHE [ FLAG ] TABLE <table_name> [ OPTIONS('K1' = 'V1', 'K2' = V2) ] [ AS ] [ <query> ]
4880    /// ```
4881    ///
4882    /// See [Spark SQL docs] for more details.
4883    ///
4884    /// [Spark SQL docs]: https://docs.databricks.com/spark/latest/spark-sql/language-manual/sql-ref-syntax-aux-cache-cache-table.html
4885    Cache {
4886        /// Table flag
4887        table_flag: Option<ObjectName>,
4888        /// Table name
4889        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
4890        table_name: ObjectName,
4891        /// `true` if `AS` keyword was present before the query.
4892        has_as: bool,
4893        /// Table confs
4894        options: Vec<SqlOption>,
4895        /// Cache table as a Query
4896        query: Option<Box<Query>>,
4897    },
4898    /// ```sql
4899    /// UNCACHE TABLE [ IF EXISTS ]  <table_name>
4900    /// ```
4901    UNCache {
4902        /// Table name
4903        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
4904        table_name: ObjectName,
4905        /// `true` when `IF EXISTS` was present.
4906        if_exists: bool,
4907    },
4908    /// ```sql
4909    /// CREATE [ { TEMPORARY | TEMP } ] SEQUENCE [ IF NOT EXISTS ] <sequence_name>
4910    /// ```
4911    /// Define a new sequence:
4912    CreateSequence {
4913        /// Whether the sequence is temporary.
4914        temporary: bool,
4915        /// `IF NOT EXISTS` flag.
4916        if_not_exists: bool,
4917        /// Sequence name.
4918        name: ObjectName,
4919        /// Optional data type for the sequence.
4920        data_type: Option<DataType>,
4921        /// Sequence options (INCREMENT, MINVALUE, etc.).
4922        sequence_options: Vec<SequenceOptions>,
4923        /// Optional `OWNED BY` target.
4924        owned_by: Option<ObjectName>,
4925    },
4926    /// A `CREATE DOMAIN` statement.
4927    CreateDomain(CreateDomain),
4928    /// ```sql
4929    /// CREATE TYPE <name>
4930    /// ```
4931    CreateType {
4932        /// Type name to create.
4933        name: ObjectName,
4934        /// Optional type representation details.
4935        representation: Option<UserDefinedTypeRepresentation>,
4936    },
4937    /// ```sql
4938    /// PRAGMA <schema-name>.<pragma-name> = <pragma-value>
4939    /// ```
4940    Pragma {
4941        /// Pragma name (possibly qualified).
4942        name: ObjectName,
4943        /// Optional pragma value.
4944        value: Option<ValueWithSpan>,
4945        /// Whether the pragma used `=`.
4946        is_eq: bool,
4947    },
4948    /// ```sql
4949    /// LOCK [ TABLE ] [ ONLY ] name [ * ] [, ...] [ IN lockmode MODE ] [ NOWAIT ]
4950    /// ```
4951    ///
4952    /// See <https://www.postgresql.org/docs/current/sql-lock.html>
4953    Lock(Lock),
4954    /// ```sql
4955    /// LOCK TABLES <table_name> [READ [LOCAL] | [LOW_PRIORITY] WRITE]
4956    /// ```
4957    /// Note: this is a MySQL-specific statement. See <https://dev.mysql.com/doc/refman/8.0/en/lock-tables.html>
4958    LockTables {
4959        /// List of tables to lock with modes.
4960        tables: Vec<LockTable>,
4961    },
4962    /// ```sql
4963    /// UNLOCK TABLES
4964    /// ```
4965    /// Note: this is a MySQL-specific statement. See <https://dev.mysql.com/doc/refman/8.0/en/lock-tables.html>
4966    UnlockTables,
4967    /// Unloads the result of a query to file
4968    ///
4969    /// [Athena](https://docs.aws.amazon.com/athena/latest/ug/unload.html):
4970    /// ```sql
4971    /// UNLOAD(statement) TO <destination> [ WITH options ]
4972    /// ```
4973    ///
4974    /// [Redshift](https://docs.aws.amazon.com/redshift/latest/dg/r_UNLOAD.html):
4975    /// ```sql
4976    /// UNLOAD('statement') TO <destination> [ OPTIONS ]
4977    /// ```
4978    Unload {
4979        /// Optional query AST to unload.
4980        query: Option<Box<Query>>,
4981        /// Optional original query text.
4982        query_text: Option<String>,
4983        /// Destination identifier.
4984        to: Ident,
4985        /// Optional IAM role/auth information.
4986        auth: Option<IamRoleKind>,
4987        /// Additional `WITH` options.
4988        with: Vec<SqlOption>,
4989        /// Legacy copy-style options.
4990        options: Vec<CopyLegacyOption>,
4991    },
4992    /// ClickHouse:
4993    /// ```sql
4994    /// OPTIMIZE TABLE [db.]name [ON CLUSTER cluster] [PARTITION partition | PARTITION ID 'partition_id'] [FINAL] [DEDUPLICATE [BY expression]]
4995    /// ```
4996    /// See ClickHouse <https://clickhouse.com/docs/en/sql-reference/statements/optimize>
4997    ///
4998    /// Databricks:
4999    /// ```sql
5000    /// OPTIMIZE table_name [WHERE predicate] [ZORDER BY (col_name1 [, ...])]
5001    /// ```
5002    /// See Databricks <https://docs.databricks.com/en/sql/language-manual/delta-optimize.html>
5003    OptimizeTable {
5004        /// Table name to optimize.
5005        name: ObjectName,
5006        /// Whether the `TABLE` keyword was present (ClickHouse uses `OPTIMIZE TABLE`, Databricks uses `OPTIMIZE`).
5007        has_table_keyword: bool,
5008        /// Optional cluster identifier.
5009        /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/optimize)
5010        on_cluster: Option<Ident>,
5011        /// Optional partition spec.
5012        /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/optimize)
5013        partition: Option<Partition>,
5014        /// Whether `FINAL` was specified.
5015        /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/optimize)
5016        include_final: bool,
5017        /// Optional deduplication settings.
5018        /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/optimize)
5019        deduplicate: Option<Deduplicate>,
5020        /// Optional WHERE predicate.
5021        /// [Databricks](https://docs.databricks.com/en/sql/language-manual/delta-optimize.html)
5022        predicate: Option<Expr>,
5023        /// Optional ZORDER BY columns.
5024        /// [Databricks](https://docs.databricks.com/en/sql/language-manual/delta-optimize.html)
5025        zorder: Option<Vec<Expr>>,
5026    },
5027    /// ```sql
5028    /// LISTEN
5029    /// ```
5030    /// listen for a notification channel
5031    ///
5032    /// See Postgres <https://www.postgresql.org/docs/current/sql-listen.html>
5033    LISTEN {
5034        /// Notification channel identifier.
5035        channel: Ident,
5036    },
5037    /// ```sql
5038    /// UNLISTEN
5039    /// ```
5040    /// stop listening for a notification
5041    ///
5042    /// See Postgres <https://www.postgresql.org/docs/current/sql-unlisten.html>
5043    UNLISTEN {
5044        /// Notification channel identifier.
5045        channel: Ident,
5046    },
5047    /// ```sql
5048    /// NOTIFY channel [ , payload ]
5049    /// ```
5050    /// send a notification event together with an optional "payload" string to channel
5051    ///
5052    /// See Postgres <https://www.postgresql.org/docs/current/sql-notify.html>
5053    NOTIFY {
5054        /// Notification channel identifier.
5055        channel: Ident,
5056        /// Optional payload string.
5057        payload: Option<String>,
5058    },
5059    /// ```sql
5060    /// LOAD DATA [LOCAL] INPATH 'filepath' [OVERWRITE] INTO TABLE tablename
5061    /// [PARTITION (partcol1=val1, partcol2=val2 ...)]
5062    /// [INPUTFORMAT 'inputformat' SERDE 'serde']
5063    /// ```
5064    /// Loading files into tables
5065    ///
5066    /// See Hive <https://cwiki.apache.org/confluence/pages/viewpage.action?pageId=27362036#LanguageManualDML-Loadingfilesintotables>
5067    LoadData {
5068        /// Whether `LOCAL` is present.
5069        local: bool,
5070        /// Input path for files to load.
5071        inpath: String,
5072        /// Whether `OVERWRITE` was specified.
5073        overwrite: bool,
5074        /// Target table name to load into.
5075        table_name: ObjectName,
5076        /// Optional partition specification.
5077        partitioned: Option<Vec<Expr>>,
5078        /// Optional table format information.
5079        table_format: Option<HiveLoadDataFormat>,
5080    },
5081    /// ```sql
5082    /// Rename TABLE tbl_name TO new_tbl_name[, tbl_name2 TO new_tbl_name2] ...
5083    /// ```
5084    /// Renames one or more tables
5085    ///
5086    /// See Mysql <https://dev.mysql.com/doc/refman/9.1/en/rename-table.html>
5087    RenameTable(Vec<RenameTable>),
5088    /// Snowflake `LIST`
5089    /// See: <https://docs.snowflake.com/en/sql-reference/sql/list>
5090    List(FileStagingCommand),
5091    /// Snowflake `REMOVE`
5092    /// See: <https://docs.snowflake.com/en/sql-reference/sql/remove>
5093    Remove(FileStagingCommand),
5094    /// RaiseError (MSSQL)
5095    /// RAISERROR ( { msg_id | msg_str | @local_variable }
5096    /// { , severity , state }
5097    /// [ , argument [ , ...n ] ] )
5098    /// [ WITH option [ , ...n ] ]
5099    /// See <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/raiserror-transact-sql?view=sql-server-ver16>
5100    RaisError {
5101        /// Error message expression or identifier.
5102        message: Box<Expr>,
5103        /// Severity expression.
5104        severity: Box<Expr>,
5105        /// State expression.
5106        state: Box<Expr>,
5107        /// Substitution arguments for the message.
5108        arguments: Vec<Expr>,
5109        /// Additional `WITH` options for RAISERROR.
5110        options: Vec<RaisErrorOption>,
5111    },
5112    /// A MSSQL `THROW` statement.
5113    Throw(ThrowStatement),
5114    /// ```sql
5115    /// PRINT msg_str | @local_variable | string_expr
5116    /// ```
5117    ///
5118    /// See: <https://learn.microsoft.com/en-us/sql/t-sql/statements/print-transact-sql>
5119    Print(PrintStatement),
5120    /// MSSQL `WAITFOR` statement.
5121    ///
5122    /// See: <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/waitfor-transact-sql>
5123    WaitFor(WaitForStatement),
5124    /// ```sql
5125    /// RETURN [ expression ]
5126    /// ```
5127    ///
5128    /// See [ReturnStatement]
5129    Return(ReturnStatement),
5130    /// Export data statement
5131    ///
5132    /// Example:
5133    /// ```sql
5134    /// EXPORT DATA OPTIONS(uri='gs://bucket/folder/*', format='PARQUET', overwrite=true) AS
5135    /// SELECT field1, field2 FROM mydataset.table1 ORDER BY field1 LIMIT 10
5136    /// ```
5137    /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/export-statements)
5138    ExportData(ExportData),
5139    /// ```sql
5140    /// CREATE [OR REPLACE] USER <user> [IF NOT EXISTS]
5141    /// ```
5142    /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-user)
5143    CreateUser(CreateUser),
5144    /// ```sql
5145    /// ALTER USER \[ IF EXISTS \] \[ <name> \]
5146    /// ```
5147    /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/alter-user)
5148    AlterUser(AlterUser),
5149    /// Re-sorts rows and reclaims space in either a specified table or all tables in the current database
5150    ///
5151    /// ```sql
5152    /// VACUUM tbl
5153    /// ```
5154    /// [Redshift](https://docs.aws.amazon.com/redshift/latest/dg/r_VACUUM_command.html)
5155    Vacuum(VacuumStatement),
5156    /// Restore the value of a run-time parameter to the default value.
5157    ///
5158    /// ```sql
5159    /// RESET configuration_parameter;
5160    /// RESET ALL;
5161    /// ```
5162    /// [PostgreSQL](https://www.postgresql.org/docs/current/sql-reset.html)
5163    Reset(ResetStatement),
5164}
5165
5166impl From<Analyze> for Statement {
5167    fn from(analyze: Analyze) -> Self {
5168        Statement::Analyze(analyze)
5169    }
5170}
5171
5172impl From<ddl::Truncate> for Statement {
5173    fn from(truncate: ddl::Truncate) -> Self {
5174        Statement::Truncate(truncate)
5175    }
5176}
5177
5178impl From<Lock> for Statement {
5179    fn from(lock: Lock) -> Self {
5180        Statement::Lock(lock)
5181    }
5182}
5183
5184impl From<ddl::Msck> for Statement {
5185    fn from(msck: ddl::Msck) -> Self {
5186        Statement::Msck(msck)
5187    }
5188}
5189
5190/// ```sql
5191/// {COPY | REVOKE} CURRENT GRANTS
5192/// ```
5193///
5194/// - [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/grant-ownership#optional-parameters)
5195#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
5196#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
5197#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
5198pub enum CurrentGrantsKind {
5199    /// `COPY CURRENT GRANTS` (copy current grants to target).
5200    CopyCurrentGrants,
5201    /// `REVOKE CURRENT GRANTS` (revoke current grants from target).
5202    RevokeCurrentGrants,
5203}
5204
5205impl fmt::Display for CurrentGrantsKind {
5206    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
5207        match self {
5208            CurrentGrantsKind::CopyCurrentGrants => write!(f, "COPY CURRENT GRANTS"),
5209            CurrentGrantsKind::RevokeCurrentGrants => write!(f, "REVOKE CURRENT GRANTS"),
5210        }
5211    }
5212}
5213
5214#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
5215#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
5216#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
5217/// `RAISERROR` options
5218/// See <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/raiserror-transact-sql?view=sql-server-ver16#options>
5219pub enum RaisErrorOption {
5220    /// Log the error.
5221    Log,
5222    /// Do not wait for completion.
5223    NoWait,
5224    /// Set the error state.
5225    SetError,
5226}
5227
5228impl fmt::Display for RaisErrorOption {
5229    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
5230        match self {
5231            RaisErrorOption::Log => write!(f, "LOG"),
5232            RaisErrorOption::NoWait => write!(f, "NOWAIT"),
5233            RaisErrorOption::SetError => write!(f, "SETERROR"),
5234        }
5235    }
5236}
5237
5238impl fmt::Display for Statement {
5239    /// Formats a SQL statement with support for pretty printing.
5240    ///
5241    /// When using the alternate flag (`{:#}`), the statement will be formatted with proper
5242    /// indentation and line breaks. For example:
5243    ///
5244    /// ```
5245    /// # use sqlparser::dialect::GenericDialect;
5246    /// # use sqlparser::parser::Parser;
5247    /// let sql = "SELECT a, b FROM table_1";
5248    /// let ast = Parser::parse_sql(&GenericDialect, sql).unwrap();
5249    ///
5250    /// // Regular formatting
5251    /// assert_eq!(format!("{}", ast[0]), "SELECT a, b FROM table_1");
5252    ///
5253    /// // Pretty printing
5254    /// assert_eq!(format!("{:#}", ast[0]),
5255    /// r#"SELECT
5256    ///   a,
5257    ///   b
5258    /// FROM
5259    ///   table_1"#);
5260    /// ```
5261    // Clippy thinks this function is too complicated, but it is painful to
5262    // split up without extracting structs for each `Statement` variant.
5263    #[allow(clippy::cognitive_complexity)]
5264    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
5265        match self {
5266            Statement::Flush {
5267                object_type,
5268                location,
5269                channel,
5270                read_lock,
5271                export,
5272                tables,
5273            } => {
5274                write!(f, "FLUSH")?;
5275                if let Some(location) = location {
5276                    f.write_str(" ")?;
5277                    location.fmt(f)?;
5278                }
5279                write!(f, " {object_type}")?;
5280
5281                if let Some(channel) = channel {
5282                    write!(f, " FOR CHANNEL {channel}")?;
5283                }
5284
5285                write!(
5286                    f,
5287                    "{tables}{read}{export}",
5288                    tables = if !tables.is_empty() {
5289                        format!(" {}", display_comma_separated(tables))
5290                    } else {
5291                        String::new()
5292                    },
5293                    export = if *export { " FOR EXPORT" } else { "" },
5294                    read = if *read_lock { " WITH READ LOCK" } else { "" }
5295                )
5296            }
5297            Statement::Kill { modifier, id } => {
5298                write!(f, "KILL ")?;
5299
5300                if let Some(m) = modifier {
5301                    write!(f, "{m} ")?;
5302                }
5303
5304                write!(f, "{id}")
5305            }
5306            Statement::ExplainTable {
5307                describe_alias,
5308                hive_format,
5309                has_table_keyword,
5310                table_name,
5311            } => {
5312                write!(f, "{describe_alias} ")?;
5313
5314                if let Some(format) = hive_format {
5315                    write!(f, "{format} ")?;
5316                }
5317                if *has_table_keyword {
5318                    write!(f, "TABLE ")?;
5319                }
5320
5321                write!(f, "{table_name}")
5322            }
5323            Statement::Explain {
5324                describe_alias,
5325                verbose,
5326                analyze,
5327                query_plan,
5328                estimate,
5329                statement,
5330                format,
5331                options,
5332            } => {
5333                write!(f, "{describe_alias} ")?;
5334
5335                if *query_plan {
5336                    write!(f, "QUERY PLAN ")?;
5337                }
5338                if *analyze {
5339                    write!(f, "ANALYZE ")?;
5340                }
5341                if *estimate {
5342                    write!(f, "ESTIMATE ")?;
5343                }
5344
5345                if *verbose {
5346                    write!(f, "VERBOSE ")?;
5347                }
5348
5349                if let Some(format) = format {
5350                    write!(f, "{format} ")?;
5351                }
5352
5353                if let Some(options) = options {
5354                    write!(f, "({}) ", display_comma_separated(options))?;
5355                }
5356
5357                write!(f, "{statement}")
5358            }
5359            Statement::Query(s) => s.fmt(f),
5360            Statement::Declare { stmts } => {
5361                write!(f, "DECLARE ")?;
5362                write!(f, "{}", display_separated(stmts, "; "))
5363            }
5364            Statement::Fetch {
5365                name,
5366                direction,
5367                position,
5368                into,
5369            } => {
5370                write!(f, "FETCH {direction} {position} {name}")?;
5371
5372                if let Some(into) = into {
5373                    write!(f, " INTO {into}")?;
5374                }
5375
5376                Ok(())
5377            }
5378            Statement::Directory {
5379                overwrite,
5380                local,
5381                path,
5382                file_format,
5383                source,
5384            } => {
5385                write!(
5386                    f,
5387                    "INSERT{overwrite}{local} DIRECTORY '{path}'",
5388                    overwrite = if *overwrite { " OVERWRITE" } else { "" },
5389                    local = if *local { " LOCAL" } else { "" },
5390                    path = path
5391                )?;
5392                if let Some(ref ff) = file_format {
5393                    write!(f, " STORED AS {ff}")?
5394                }
5395                write!(f, " {source}")
5396            }
5397            Statement::Msck(msck) => msck.fmt(f),
5398            Statement::Truncate(truncate) => truncate.fmt(f),
5399            Statement::Case(stmt) => {
5400                write!(f, "{stmt}")
5401            }
5402            Statement::If(stmt) => {
5403                write!(f, "{stmt}")
5404            }
5405            Statement::While(stmt) => {
5406                write!(f, "{stmt}")
5407            }
5408            Statement::Raise(stmt) => {
5409                write!(f, "{stmt}")
5410            }
5411            Statement::AttachDatabase {
5412                schema_name,
5413                database_file_name,
5414                database,
5415            } => {
5416                let keyword = if *database { "DATABASE " } else { "" };
5417                write!(f, "ATTACH {keyword}{database_file_name} AS {schema_name}")
5418            }
5419            Statement::AttachDuckDBDatabase {
5420                if_not_exists,
5421                database,
5422                database_path,
5423                database_alias,
5424                attach_options,
5425            } => {
5426                write!(
5427                    f,
5428                    "ATTACH{database}{if_not_exists} {database_path}",
5429                    database = if *database { " DATABASE" } else { "" },
5430                    if_not_exists = if *if_not_exists { " IF NOT EXISTS" } else { "" },
5431                )?;
5432                if let Some(alias) = database_alias {
5433                    write!(f, " AS {alias}")?;
5434                }
5435                if !attach_options.is_empty() {
5436                    write!(f, " ({})", display_comma_separated(attach_options))?;
5437                }
5438                Ok(())
5439            }
5440            Statement::DetachDuckDBDatabase {
5441                if_exists,
5442                database,
5443                database_alias,
5444            } => {
5445                write!(
5446                    f,
5447                    "DETACH{database}{if_exists} {database_alias}",
5448                    database = if *database { " DATABASE" } else { "" },
5449                    if_exists = if *if_exists { " IF EXISTS" } else { "" },
5450                )?;
5451                Ok(())
5452            }
5453            Statement::Analyze(analyze) => analyze.fmt(f),
5454            Statement::Insert(insert) => insert.fmt(f),
5455            Statement::Install {
5456                extension_name: name,
5457            } => write!(f, "INSTALL {name}"),
5458
5459            Statement::Load {
5460                extension_name: name,
5461            } => write!(f, "LOAD {name}"),
5462
5463            Statement::Call(function) => write!(f, "CALL {function}"),
5464
5465            Statement::Copy {
5466                source,
5467                to,
5468                target,
5469                options,
5470                legacy_options,
5471                values,
5472            } => {
5473                write!(f, "COPY")?;
5474                match source {
5475                    CopySource::Query(query) => write!(f, " ({query})")?,
5476                    CopySource::Table {
5477                        table_name,
5478                        columns,
5479                    } => {
5480                        write!(f, " {table_name}")?;
5481                        if !columns.is_empty() {
5482                            write!(f, " ({})", display_comma_separated(columns))?;
5483                        }
5484                    }
5485                }
5486                write!(f, " {} {}", if *to { "TO" } else { "FROM" }, target)?;
5487                if !options.is_empty() {
5488                    write!(f, " ({})", display_comma_separated(options))?;
5489                }
5490                if !legacy_options.is_empty() {
5491                    write!(f, " {}", display_separated(legacy_options, " "))?;
5492                }
5493                if !values.is_empty() {
5494                    writeln!(f, ";")?;
5495                    let mut delim = "";
5496                    for v in values {
5497                        write!(f, "{delim}")?;
5498                        delim = "\t";
5499                        if let Some(v) = v {
5500                            write!(f, "{v}")?;
5501                        } else {
5502                            write!(f, "\\N")?;
5503                        }
5504                    }
5505                    write!(f, "\n\\.")?;
5506                }
5507                Ok(())
5508            }
5509            Statement::Update(update) => update.fmt(f),
5510            Statement::Delete(delete) => delete.fmt(f),
5511            Statement::Open(open) => open.fmt(f),
5512            Statement::Close { cursor } => {
5513                write!(f, "CLOSE {cursor}")?;
5514
5515                Ok(())
5516            }
5517            Statement::CreateDatabase {
5518                db_name,
5519                if_not_exists,
5520                location,
5521                managed_location,
5522                or_replace,
5523                transient,
5524                clone,
5525                data_retention_time_in_days,
5526                max_data_extension_time_in_days,
5527                external_volume,
5528                catalog,
5529                replace_invalid_characters,
5530                default_ddl_collation,
5531                storage_serialization_policy,
5532                comment,
5533                default_charset,
5534                default_collation,
5535                catalog_sync,
5536                catalog_sync_namespace_mode,
5537                catalog_sync_namespace_flatten_delimiter,
5538                with_tags,
5539                with_contacts,
5540            } => {
5541                write!(
5542                    f,
5543                    "CREATE {or_replace}{transient}DATABASE {if_not_exists}{name}",
5544                    or_replace = if *or_replace { "OR REPLACE " } else { "" },
5545                    transient = if *transient { "TRANSIENT " } else { "" },
5546                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
5547                    name = db_name,
5548                )?;
5549
5550                if let Some(l) = location {
5551                    write!(f, " LOCATION '{l}'")?;
5552                }
5553                if let Some(ml) = managed_location {
5554                    write!(f, " MANAGEDLOCATION '{ml}'")?;
5555                }
5556                if let Some(clone) = clone {
5557                    write!(f, " CLONE {clone}")?;
5558                }
5559
5560                if let Some(value) = data_retention_time_in_days {
5561                    write!(f, " DATA_RETENTION_TIME_IN_DAYS = {value}")?;
5562                }
5563
5564                if let Some(value) = max_data_extension_time_in_days {
5565                    write!(f, " MAX_DATA_EXTENSION_TIME_IN_DAYS = {value}")?;
5566                }
5567
5568                if let Some(vol) = external_volume {
5569                    write!(f, " EXTERNAL_VOLUME = '{vol}'")?;
5570                }
5571
5572                if let Some(cat) = catalog {
5573                    write!(f, " CATALOG = '{cat}'")?;
5574                }
5575
5576                if let Some(true) = replace_invalid_characters {
5577                    write!(f, " REPLACE_INVALID_CHARACTERS = TRUE")?;
5578                } else if let Some(false) = replace_invalid_characters {
5579                    write!(f, " REPLACE_INVALID_CHARACTERS = FALSE")?;
5580                }
5581
5582                if let Some(collation) = default_ddl_collation {
5583                    write!(f, " DEFAULT_DDL_COLLATION = '{collation}'")?;
5584                }
5585
5586                if let Some(policy) = storage_serialization_policy {
5587                    write!(f, " STORAGE_SERIALIZATION_POLICY = {policy}")?;
5588                }
5589
5590                if let Some(comment) = comment {
5591                    write!(f, " COMMENT = '{comment}'")?;
5592                }
5593
5594                if let Some(charset) = default_charset {
5595                    write!(f, " DEFAULT CHARACTER SET {charset}")?;
5596                }
5597
5598                if let Some(collation) = default_collation {
5599                    write!(f, " DEFAULT COLLATE {collation}")?;
5600                }
5601
5602                if let Some(sync) = catalog_sync {
5603                    write!(f, " CATALOG_SYNC = '{sync}'")?;
5604                }
5605
5606                if let Some(mode) = catalog_sync_namespace_mode {
5607                    write!(f, " CATALOG_SYNC_NAMESPACE_MODE = {mode}")?;
5608                }
5609
5610                if let Some(delim) = catalog_sync_namespace_flatten_delimiter {
5611                    write!(f, " CATALOG_SYNC_NAMESPACE_FLATTEN_DELIMITER = '{delim}'")?;
5612                }
5613
5614                if let Some(tags) = with_tags {
5615                    write!(f, " WITH TAG ({})", display_comma_separated(tags))?;
5616                }
5617
5618                if let Some(contacts) = with_contacts {
5619                    write!(f, " WITH CONTACT ({})", display_comma_separated(contacts))?;
5620                }
5621                Ok(())
5622            }
5623            Statement::CreateFunction(create_function) => create_function.fmt(f),
5624            Statement::CreateDomain(create_domain) => create_domain.fmt(f),
5625            Statement::CreateTrigger(create_trigger) => create_trigger.fmt(f),
5626            Statement::DropTrigger(drop_trigger) => drop_trigger.fmt(f),
5627            Statement::CreateProcedure {
5628                name,
5629                or_alter,
5630                params,
5631                language,
5632                body,
5633            } => {
5634                write!(
5635                    f,
5636                    "CREATE {or_alter}PROCEDURE {name}",
5637                    or_alter = if *or_alter { "OR ALTER " } else { "" },
5638                    name = name
5639                )?;
5640
5641                if let Some(p) = params {
5642                    if !p.is_empty() {
5643                        write!(f, " ({})", display_comma_separated(p))?;
5644                    }
5645                }
5646
5647                if let Some(language) = language {
5648                    write!(f, " LANGUAGE {language}")?;
5649                }
5650
5651                write!(f, " AS {body}")
5652            }
5653            Statement::CreateMacro {
5654                or_replace,
5655                temporary,
5656                name,
5657                args,
5658                definition,
5659            } => {
5660                write!(
5661                    f,
5662                    "CREATE {or_replace}{temp}MACRO {name}",
5663                    temp = if *temporary { "TEMPORARY " } else { "" },
5664                    or_replace = if *or_replace { "OR REPLACE " } else { "" },
5665                )?;
5666                if let Some(args) = args {
5667                    write!(f, "({})", display_comma_separated(args))?;
5668                }
5669                match definition {
5670                    MacroDefinition::Expr(expr) => write!(f, " AS {expr}")?,
5671                    MacroDefinition::Table(query) => write!(f, " AS TABLE {query}")?,
5672                }
5673                Ok(())
5674            }
5675            Statement::CreateView(create_view) => create_view.fmt(f),
5676            Statement::CreateTable(create_table) => create_table.fmt(f),
5677            Statement::LoadData {
5678                local,
5679                inpath,
5680                overwrite,
5681                table_name,
5682                partitioned,
5683                table_format,
5684            } => {
5685                write!(
5686                    f,
5687                    "LOAD DATA {local}INPATH '{inpath}' {overwrite}INTO TABLE {table_name}",
5688                    local = if *local { "LOCAL " } else { "" },
5689                    inpath = inpath,
5690                    overwrite = if *overwrite { "OVERWRITE " } else { "" },
5691                    table_name = table_name,
5692                )?;
5693                if let Some(ref parts) = &partitioned {
5694                    if !parts.is_empty() {
5695                        write!(f, " PARTITION ({})", display_comma_separated(parts))?;
5696                    }
5697                }
5698                if let Some(HiveLoadDataFormat {
5699                    serde,
5700                    input_format,
5701                }) = &table_format
5702                {
5703                    write!(f, " INPUTFORMAT {input_format} SERDE {serde}")?;
5704                }
5705                Ok(())
5706            }
5707            Statement::CreateVirtualTable {
5708                name,
5709                if_not_exists,
5710                module_name,
5711                module_args,
5712            } => {
5713                write!(
5714                    f,
5715                    "CREATE VIRTUAL TABLE {if_not_exists}{name} USING {module_name}",
5716                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
5717                    name = name,
5718                    module_name = module_name
5719                )?;
5720                if !module_args.is_empty() {
5721                    write!(f, " ({})", display_comma_separated(module_args))?;
5722                }
5723                Ok(())
5724            }
5725            Statement::CreateIndex(create_index) => create_index.fmt(f),
5726            Statement::CreateExtension(create_extension) => write!(f, "{create_extension}"),
5727            Statement::CreateCollation(create_collation) => write!(f, "{create_collation}"),
5728            Statement::CreateTextSearchConfiguration(v) => write!(f, "{v}"),
5729            Statement::CreateTextSearchDictionary(v) => write!(f, "{v}"),
5730            Statement::CreateTextSearchParser(v) => write!(f, "{v}"),
5731            Statement::CreateTextSearchTemplate(v) => write!(f, "{v}"),
5732            Statement::CreatePublication(v) => write!(f, "{v}"),
5733            Statement::CreateSubscription(v) => write!(f, "{v}"),
5734            Statement::CreateCast(v) => write!(f, "{v}"),
5735            Statement::CreateConversion(v) => write!(f, "{v}"),
5736            Statement::CreateLanguage(v) => write!(f, "{v}"),
5737            Statement::CreateRule(v) => write!(f, "{v}"),
5738            Statement::CreateStatistics(v) => write!(f, "{v}"),
5739            Statement::CreateAccessMethod(v) => write!(f, "{v}"),
5740            Statement::CreateEventTrigger(v) => write!(f, "{v}"),
5741            Statement::CreateTransform(v) => write!(f, "{v}"),
5742            Statement::SecurityLabel(v) => write!(f, "{v}"),
5743            Statement::CreateUserMapping(v) => write!(f, "{v}"),
5744            Statement::CreateTablespace(v) => write!(f, "{v}"),
5745            Statement::DropExtension(drop_extension) => write!(f, "{drop_extension}"),
5746            Statement::DropOperator(drop_operator) => write!(f, "{drop_operator}"),
5747            Statement::DropOperatorFamily(drop_operator_family) => {
5748                write!(f, "{drop_operator_family}")
5749            }
5750            Statement::DropOperatorClass(drop_operator_class) => {
5751                write!(f, "{drop_operator_class}")
5752            }
5753            Statement::CreateRole(create_role) => write!(f, "{create_role}"),
5754            Statement::CreateSecret {
5755                or_replace,
5756                temporary,
5757                if_not_exists,
5758                name,
5759                storage_specifier,
5760                secret_type,
5761                options,
5762            } => {
5763                write!(
5764                    f,
5765                    "CREATE {or_replace}",
5766                    or_replace = if *or_replace { "OR REPLACE " } else { "" },
5767                )?;
5768                if let Some(t) = temporary {
5769                    write!(f, "{}", if *t { "TEMPORARY " } else { "PERSISTENT " })?;
5770                }
5771                write!(
5772                    f,
5773                    "SECRET {if_not_exists}",
5774                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
5775                )?;
5776                if let Some(n) = name {
5777                    write!(f, "{n} ")?;
5778                };
5779                if let Some(s) = storage_specifier {
5780                    write!(f, "IN {s} ")?;
5781                }
5782                write!(f, "( TYPE {secret_type}",)?;
5783                if !options.is_empty() {
5784                    write!(f, ", {o}", o = display_comma_separated(options))?;
5785                }
5786                write!(f, " )")?;
5787                Ok(())
5788            }
5789            Statement::CreateServer(stmt) => {
5790                write!(f, "{stmt}")
5791            }
5792            Statement::CreateForeignDataWrapper(stmt) => write!(f, "{stmt}"),
5793            Statement::CreateForeignTable(stmt) => write!(f, "{stmt}"),
5794            Statement::CreatePolicy(policy) => write!(f, "{policy}"),
5795            Statement::CreateConnector(create_connector) => create_connector.fmt(f),
5796            Statement::CreateOperator(create_operator) => create_operator.fmt(f),
5797            Statement::CreateOperatorFamily(create_operator_family) => {
5798                create_operator_family.fmt(f)
5799            }
5800            Statement::CreateOperatorClass(create_operator_class) => create_operator_class.fmt(f),
5801            Statement::CreateAggregate(create_aggregate) => create_aggregate.fmt(f),
5802            Statement::AlterTable(alter_table) => write!(f, "{alter_table}"),
5803            Statement::AlterIndex { name, operation } => {
5804                write!(f, "ALTER INDEX {name} {operation}")
5805            }
5806            Statement::AlterView {
5807                name,
5808                columns,
5809                query,
5810                with_options,
5811            } => {
5812                write!(f, "ALTER VIEW {name}")?;
5813                if !with_options.is_empty() {
5814                    write!(f, " WITH ({})", display_comma_separated(with_options))?;
5815                }
5816                if !columns.is_empty() {
5817                    write!(f, " ({})", display_comma_separated(columns))?;
5818                }
5819                write!(f, " AS {query}")
5820            }
5821            Statement::AlterDomain(alter_domain) => write!(f, "{alter_domain}"),
5822            Statement::AlterExtension(alter_extension) => write!(f, "{alter_extension}"),
5823            Statement::AlterFunction(alter_function) => write!(f, "{alter_function}"),
5824            Statement::AlterTrigger(alter_trigger) => write!(f, "{alter_trigger}"),
5825            Statement::AlterType(AlterType { name, operation }) => {
5826                write!(f, "ALTER TYPE {name} {operation}")
5827            }
5828            Statement::AlterCollation(alter_collation) => write!(f, "{alter_collation}"),
5829            Statement::AlterDefaultPrivileges(alter_default_privileges) => {
5830                write!(f, "{alter_default_privileges}")
5831            }
5832            Statement::AlterOperator(alter_operator) => write!(f, "{alter_operator}"),
5833            Statement::AlterOperatorFamily(alter_operator_family) => {
5834                write!(f, "{alter_operator_family}")
5835            }
5836            Statement::AlterOperatorClass(alter_operator_class) => {
5837                write!(f, "{alter_operator_class}")
5838            }
5839            Statement::AlterRole { name, operation } => {
5840                write!(f, "ALTER ROLE {name} {operation}")
5841            }
5842            Statement::AlterPolicy(alter_policy) => write!(f, "{alter_policy}"),
5843            Statement::AlterConnector {
5844                name,
5845                properties,
5846                url,
5847                owner,
5848            } => {
5849                write!(f, "ALTER CONNECTOR {name}")?;
5850                if let Some(properties) = properties {
5851                    write!(
5852                        f,
5853                        " SET DCPROPERTIES({})",
5854                        display_comma_separated(properties)
5855                    )?;
5856                }
5857                if let Some(url) = url {
5858                    write!(f, " SET URL '{url}'")?;
5859                }
5860                if let Some(owner) = owner {
5861                    write!(f, " SET OWNER {owner}")?;
5862                }
5863                Ok(())
5864            }
5865            Statement::AlterSession {
5866                set,
5867                session_params,
5868            } => {
5869                write!(
5870                    f,
5871                    "ALTER SESSION {set}",
5872                    set = if *set { "SET" } else { "UNSET" }
5873                )?;
5874                if !session_params.options.is_empty() {
5875                    if *set {
5876                        write!(f, " {session_params}")?;
5877                    } else {
5878                        let options = session_params
5879                            .options
5880                            .iter()
5881                            .map(|p| p.option_name.clone())
5882                            .collect::<Vec<_>>();
5883                        write!(f, " {}", display_separated(&options, ", "))?;
5884                    }
5885                }
5886                Ok(())
5887            }
5888            Statement::Drop {
5889                object_type,
5890                if_exists,
5891                names,
5892                cascade,
5893                restrict,
5894                purge,
5895                temporary,
5896                table,
5897            } => {
5898                write!(
5899                    f,
5900                    "DROP {}{}{} {}{}{}{}",
5901                    if *temporary { "TEMPORARY " } else { "" },
5902                    object_type,
5903                    if *if_exists { " IF EXISTS" } else { "" },
5904                    display_comma_separated(names),
5905                    if *cascade { " CASCADE" } else { "" },
5906                    if *restrict { " RESTRICT" } else { "" },
5907                    if *purge { " PURGE" } else { "" },
5908                )?;
5909                if let Some(table_name) = table.as_ref() {
5910                    write!(f, " ON {table_name}")?;
5911                };
5912                Ok(())
5913            }
5914            Statement::DropFunction(drop_function) => write!(f, "{drop_function}"),
5915            Statement::DropDomain(DropDomain {
5916                if_exists,
5917                name,
5918                drop_behavior,
5919            }) => {
5920                write!(
5921                    f,
5922                    "DROP DOMAIN{} {name}",
5923                    if *if_exists { " IF EXISTS" } else { "" },
5924                )?;
5925                if let Some(op) = drop_behavior {
5926                    write!(f, " {op}")?;
5927                }
5928                Ok(())
5929            }
5930            Statement::DropProcedure {
5931                if_exists,
5932                proc_desc,
5933                drop_behavior,
5934            } => {
5935                write!(
5936                    f,
5937                    "DROP PROCEDURE{} {}",
5938                    if *if_exists { " IF EXISTS" } else { "" },
5939                    display_comma_separated(proc_desc),
5940                )?;
5941                if let Some(op) = drop_behavior {
5942                    write!(f, " {op}")?;
5943                }
5944                Ok(())
5945            }
5946            Statement::DropSecret {
5947                if_exists,
5948                temporary,
5949                name,
5950                storage_specifier,
5951            } => {
5952                write!(f, "DROP ")?;
5953                if let Some(t) = temporary {
5954                    write!(f, "{}", if *t { "TEMPORARY " } else { "PERSISTENT " })?;
5955                }
5956                write!(
5957                    f,
5958                    "SECRET {if_exists}{name}",
5959                    if_exists = if *if_exists { "IF EXISTS " } else { "" },
5960                )?;
5961                if let Some(s) = storage_specifier {
5962                    write!(f, " FROM {s}")?;
5963                }
5964                Ok(())
5965            }
5966            Statement::DropPolicy(policy) => write!(f, "{policy}"),
5967            Statement::DropConnector { if_exists, name } => {
5968                write!(
5969                    f,
5970                    "DROP CONNECTOR {if_exists}{name}",
5971                    if_exists = if *if_exists { "IF EXISTS " } else { "" }
5972                )?;
5973                Ok(())
5974            }
5975            Statement::Discard { object_type } => {
5976                write!(f, "DISCARD {object_type}")?;
5977                Ok(())
5978            }
5979            Self::Set(set) => write!(f, "{set}"),
5980            Statement::ShowVariable { variable } => {
5981                write!(f, "SHOW")?;
5982                if !variable.is_empty() {
5983                    write!(f, " {}", display_separated(variable, " "))?;
5984                }
5985                Ok(())
5986            }
5987            Statement::ShowStatus {
5988                filter,
5989                global,
5990                session,
5991            } => {
5992                write!(f, "SHOW")?;
5993                if *global {
5994                    write!(f, " GLOBAL")?;
5995                }
5996                if *session {
5997                    write!(f, " SESSION")?;
5998                }
5999                write!(f, " STATUS")?;
6000                if filter.is_some() {
6001                    write!(f, " {}", filter.as_ref().unwrap())?;
6002                }
6003                Ok(())
6004            }
6005            Statement::ShowVariables {
6006                filter,
6007                global,
6008                session,
6009            } => {
6010                write!(f, "SHOW")?;
6011                if *global {
6012                    write!(f, " GLOBAL")?;
6013                }
6014                if *session {
6015                    write!(f, " SESSION")?;
6016                }
6017                write!(f, " VARIABLES")?;
6018                if filter.is_some() {
6019                    write!(f, " {}", filter.as_ref().unwrap())?;
6020                }
6021                Ok(())
6022            }
6023            Statement::ShowCreate { obj_type, obj_name } => {
6024                write!(f, "SHOW CREATE {obj_type} {obj_name}",)?;
6025                Ok(())
6026            }
6027            Statement::ShowColumns {
6028                extended,
6029                full,
6030                show_options,
6031            } => {
6032                write!(
6033                    f,
6034                    "SHOW {extended}{full}COLUMNS{show_options}",
6035                    extended = if *extended { "EXTENDED " } else { "" },
6036                    full = if *full { "FULL " } else { "" },
6037                )?;
6038                Ok(())
6039            }
6040            Statement::ShowDatabases {
6041                terse,
6042                history,
6043                show_options,
6044            } => {
6045                write!(
6046                    f,
6047                    "SHOW {terse}DATABASES{history}{show_options}",
6048                    terse = if *terse { "TERSE " } else { "" },
6049                    history = if *history { " HISTORY" } else { "" },
6050                )?;
6051                Ok(())
6052            }
6053            Statement::ShowCatalogs {
6054                terse,
6055                history,
6056                show_options,
6057            } => {
6058                write!(
6059                    f,
6060                    "SHOW {terse}CATALOGS{history}{show_options}",
6061                    terse = if *terse { "TERSE " } else { "" },
6062                    history = if *history { " HISTORY" } else { "" },
6063                )?;
6064                Ok(())
6065            }
6066            Statement::ShowProcessList { full } => {
6067                write!(
6068                    f,
6069                    "SHOW {full}PROCESSLIST",
6070                    full = if *full { "FULL " } else { "" },
6071                )?;
6072                Ok(())
6073            }
6074            Statement::ShowSchemas {
6075                terse,
6076                history,
6077                show_options,
6078            } => {
6079                write!(
6080                    f,
6081                    "SHOW {terse}SCHEMAS{history}{show_options}",
6082                    terse = if *terse { "TERSE " } else { "" },
6083                    history = if *history { " HISTORY" } else { "" },
6084                )?;
6085                Ok(())
6086            }
6087            Statement::ShowObjects(ShowObjects {
6088                terse,
6089                show_options,
6090            }) => {
6091                write!(
6092                    f,
6093                    "SHOW {terse}OBJECTS{show_options}",
6094                    terse = if *terse { "TERSE " } else { "" },
6095                )?;
6096                Ok(())
6097            }
6098            Statement::ShowTables {
6099                terse,
6100                history,
6101                extended,
6102                full,
6103                external,
6104                show_options,
6105            } => {
6106                write!(
6107                    f,
6108                    "SHOW {terse}{extended}{full}{external}TABLES{history}{show_options}",
6109                    terse = if *terse { "TERSE " } else { "" },
6110                    extended = if *extended { "EXTENDED " } else { "" },
6111                    full = if *full { "FULL " } else { "" },
6112                    external = if *external { "EXTERNAL " } else { "" },
6113                    history = if *history { " HISTORY" } else { "" },
6114                )?;
6115                Ok(())
6116            }
6117            Statement::ShowViews {
6118                terse,
6119                materialized,
6120                show_options,
6121            } => {
6122                write!(
6123                    f,
6124                    "SHOW {terse}{materialized}VIEWS{show_options}",
6125                    terse = if *terse { "TERSE " } else { "" },
6126                    materialized = if *materialized { "MATERIALIZED " } else { "" }
6127                )?;
6128                Ok(())
6129            }
6130            Statement::ShowFunctions { filter } => {
6131                write!(f, "SHOW FUNCTIONS")?;
6132                if let Some(filter) = filter {
6133                    write!(f, " {filter}")?;
6134                }
6135                Ok(())
6136            }
6137            Statement::Use(use_expr) => use_expr.fmt(f),
6138            Statement::ShowCollation { filter } => {
6139                write!(f, "SHOW COLLATION")?;
6140                if let Some(filter) = filter {
6141                    write!(f, " {filter}")?;
6142                }
6143                Ok(())
6144            }
6145            Statement::ShowCharset(show_stm) => show_stm.fmt(f),
6146            Statement::StartTransaction {
6147                modes,
6148                begin: syntax_begin,
6149                transaction,
6150                modifier,
6151                statements,
6152                exception,
6153                has_end_keyword,
6154            } => {
6155                if *syntax_begin {
6156                    if let Some(modifier) = *modifier {
6157                        write!(f, "BEGIN {modifier}")?;
6158                    } else {
6159                        write!(f, "BEGIN")?;
6160                    }
6161                } else {
6162                    write!(f, "START")?;
6163                }
6164                if let Some(transaction) = transaction {
6165                    write!(f, " {transaction}")?;
6166                }
6167                if !modes.is_empty() {
6168                    write!(f, " {}", display_comma_separated(modes))?;
6169                }
6170                if !statements.is_empty() {
6171                    write!(f, " ")?;
6172                    format_statement_list(f, statements)?;
6173                }
6174                if let Some(exception_when) = exception {
6175                    write!(f, " EXCEPTION")?;
6176                    for when in exception_when {
6177                        write!(f, " {when}")?;
6178                    }
6179                }
6180                if *has_end_keyword {
6181                    write!(f, " END")?;
6182                }
6183                Ok(())
6184            }
6185            Statement::Commit {
6186                chain,
6187                end: end_syntax,
6188                modifier,
6189            } => {
6190                if *end_syntax {
6191                    write!(f, "END")?;
6192                    if let Some(modifier) = *modifier {
6193                        write!(f, " {modifier}")?;
6194                    }
6195                    if *chain {
6196                        write!(f, " AND CHAIN")?;
6197                    }
6198                } else {
6199                    write!(f, "COMMIT{}", if *chain { " AND CHAIN" } else { "" })?;
6200                }
6201                Ok(())
6202            }
6203            Statement::Rollback { chain, savepoint } => {
6204                write!(f, "ROLLBACK")?;
6205
6206                if *chain {
6207                    write!(f, " AND CHAIN")?;
6208                }
6209
6210                if let Some(savepoint) = savepoint {
6211                    write!(f, " TO SAVEPOINT {savepoint}")?;
6212                }
6213
6214                Ok(())
6215            }
6216            Statement::CreateSchema {
6217                schema_name,
6218                if_not_exists,
6219                with,
6220                options,
6221                default_collate_spec,
6222                clone,
6223            } => {
6224                write!(
6225                    f,
6226                    "CREATE SCHEMA {if_not_exists}{name}",
6227                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
6228                    name = schema_name
6229                )?;
6230
6231                if let Some(collate) = default_collate_spec {
6232                    write!(f, " DEFAULT COLLATE {collate}")?;
6233                }
6234
6235                if let Some(with) = with {
6236                    write!(f, " WITH ({})", display_comma_separated(with))?;
6237                }
6238
6239                if let Some(options) = options {
6240                    write!(f, " OPTIONS({})", display_comma_separated(options))?;
6241                }
6242
6243                if let Some(clone) = clone {
6244                    write!(f, " CLONE {clone}")?;
6245                }
6246                Ok(())
6247            }
6248            Statement::Assert { condition, message } => {
6249                write!(f, "ASSERT {condition}")?;
6250                if let Some(m) = message {
6251                    write!(f, " AS {m}")?;
6252                }
6253                Ok(())
6254            }
6255            Statement::Grant(grant) => write!(f, "{grant}"),
6256            Statement::Deny(s) => write!(f, "{s}"),
6257            Statement::Revoke(revoke) => write!(f, "{revoke}"),
6258            Statement::Deallocate { name, prepare } => write!(
6259                f,
6260                "DEALLOCATE {prepare}{name}",
6261                prepare = if *prepare { "PREPARE " } else { "" },
6262                name = name,
6263            ),
6264            Statement::Execute {
6265                name,
6266                parameters,
6267                has_parentheses,
6268                immediate,
6269                into,
6270                using,
6271                output,
6272                default,
6273            } => {
6274                let (open, close) = if *has_parentheses {
6275                    // Space before `(` only when there is no name directly preceding it.
6276                    (if name.is_some() { "(" } else { " (" }, ")")
6277                } else {
6278                    (if parameters.is_empty() { "" } else { " " }, "")
6279                };
6280                write!(f, "EXECUTE")?;
6281                if *immediate {
6282                    write!(f, " IMMEDIATE")?;
6283                }
6284                if let Some(name) = name {
6285                    write!(f, " {name}")?;
6286                }
6287                write!(f, "{open}{}{close}", display_comma_separated(parameters),)?;
6288                if !into.is_empty() {
6289                    write!(f, " INTO {}", display_comma_separated(into))?;
6290                }
6291                if !using.is_empty() {
6292                    write!(f, " USING {}", display_comma_separated(using))?;
6293                };
6294                if *output {
6295                    write!(f, " OUTPUT")?;
6296                }
6297                if *default {
6298                    write!(f, " DEFAULT")?;
6299                }
6300                Ok(())
6301            }
6302            Statement::Prepare {
6303                name,
6304                data_types,
6305                statement,
6306            } => {
6307                write!(f, "PREPARE {name} ")?;
6308                if !data_types.is_empty() {
6309                    write!(f, "({}) ", display_comma_separated(data_types))?;
6310                }
6311                write!(f, "AS {statement}")
6312            }
6313            Statement::Comment {
6314                object_type,
6315                object_name,
6316                arguments,
6317                operator_args,
6318                table_name,
6319                on_domain,
6320                comment,
6321                comment_dollar_quote,
6322                if_exists,
6323            } => {
6324                write!(f, "COMMENT ")?;
6325                if *if_exists {
6326                    write!(f, "IF EXISTS ")?;
6327                }
6328                write!(f, "ON {object_type} {object_name}")?;
6329                if let Some(args) = arguments {
6330                    write!(f, "({})", display_comma_separated(args))?;
6331                }
6332                if let Some(operator_args) = operator_args {
6333                    write!(f, "{operator_args}")?;
6334                }
6335                if let Some(table_name) = table_name {
6336                    let prefix = if *on_domain { " ON DOMAIN " } else { " ON " };
6337                    write!(f, "{prefix}{table_name}")?;
6338                }
6339                write!(f, " IS ")?;
6340                if let Some(dq) = comment_dollar_quote {
6341                    write!(f, "{dq}")
6342                } else if let Some(c) = comment {
6343                    write!(f, "'{}'", value::escape_single_quote_string(c))
6344                } else {
6345                    write!(f, "NULL")
6346                }
6347            }
6348            Statement::Savepoint { name } => {
6349                write!(f, "SAVEPOINT ")?;
6350                write!(f, "{name}")
6351            }
6352            Statement::ReleaseSavepoint { name } => {
6353                write!(f, "RELEASE SAVEPOINT {name}")
6354            }
6355            Statement::Merge(merge) => merge.fmt(f),
6356            Statement::Cache {
6357                table_name,
6358                table_flag,
6359                has_as,
6360                options,
6361                query,
6362            } => {
6363                if let Some(table_flag) = table_flag {
6364                    write!(f, "CACHE {table_flag} TABLE {table_name}")?;
6365                } else {
6366                    write!(f, "CACHE TABLE {table_name}")?;
6367                }
6368
6369                if !options.is_empty() {
6370                    write!(f, " OPTIONS({})", display_comma_separated(options))?;
6371                }
6372
6373                match (*has_as, query) {
6374                    (true, Some(query)) => write!(f, " AS {query}"),
6375                    (true, None) => f.write_str(" AS"),
6376                    (false, Some(query)) => write!(f, " {query}"),
6377                    (false, None) => Ok(()),
6378                }
6379            }
6380            Statement::UNCache {
6381                table_name,
6382                if_exists,
6383            } => {
6384                if *if_exists {
6385                    write!(f, "UNCACHE TABLE IF EXISTS {table_name}")
6386                } else {
6387                    write!(f, "UNCACHE TABLE {table_name}")
6388                }
6389            }
6390            Statement::CreateSequence {
6391                temporary,
6392                if_not_exists,
6393                name,
6394                data_type,
6395                sequence_options,
6396                owned_by,
6397            } => {
6398                let as_type: String = if let Some(dt) = data_type.as_ref() {
6399                    //Cannot use format!(" AS {}", dt), due to format! is not available in --target thumbv6m-none-eabi
6400                    // " AS ".to_owned() + &dt.to_string()
6401                    [" AS ", &dt.to_string()].concat()
6402                } else {
6403                    "".to_string()
6404                };
6405                write!(
6406                    f,
6407                    "CREATE {temporary}SEQUENCE {if_not_exists}{name}{as_type}",
6408                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
6409                    temporary = if *temporary { "TEMPORARY " } else { "" },
6410                    name = name,
6411                    as_type = as_type
6412                )?;
6413                for sequence_option in sequence_options {
6414                    write!(f, "{sequence_option}")?;
6415                }
6416                if let Some(ob) = owned_by.as_ref() {
6417                    write!(f, " OWNED BY {ob}")?;
6418                }
6419                write!(f, "")
6420            }
6421            Statement::CreateStage {
6422                or_replace,
6423                temporary,
6424                if_not_exists,
6425                name,
6426                stage_params,
6427                directory_table_params,
6428                file_format,
6429                copy_options,
6430                comment,
6431                ..
6432            } => {
6433                write!(
6434                    f,
6435                    "CREATE {or_replace}{temp}STAGE {if_not_exists}{name}{stage_params}",
6436                    temp = if *temporary { "TEMPORARY " } else { "" },
6437                    or_replace = if *or_replace { "OR REPLACE " } else { "" },
6438                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
6439                )?;
6440                if !directory_table_params.options.is_empty() {
6441                    write!(f, " DIRECTORY=({directory_table_params})")?;
6442                }
6443                if !file_format.options.is_empty() {
6444                    write!(f, " FILE_FORMAT=({file_format})")?;
6445                }
6446                if !copy_options.options.is_empty() {
6447                    write!(f, " COPY_OPTIONS=({copy_options})")?;
6448                }
6449                if comment.is_some() {
6450                    write!(f, " COMMENT='{}'", comment.as_ref().unwrap())?;
6451                }
6452                Ok(())
6453            }
6454            Statement::CopyIntoSnowflake {
6455                kind,
6456                into,
6457                into_columns,
6458                from_obj,
6459                from_obj_alias,
6460                stage_params,
6461                from_transformations,
6462                from_query,
6463                files,
6464                pattern,
6465                file_format,
6466                copy_options,
6467                validation_mode,
6468                partition,
6469            } => {
6470                write!(f, "COPY INTO {into}")?;
6471                if let Some(into_columns) = into_columns {
6472                    write!(f, " ({})", display_comma_separated(into_columns))?;
6473                }
6474                if let Some(from_transformations) = from_transformations {
6475                    // Data load with transformation
6476                    if let Some(from_stage) = from_obj {
6477                        write!(
6478                            f,
6479                            " FROM (SELECT {} FROM {}{}",
6480                            display_separated(from_transformations, ", "),
6481                            from_stage,
6482                            stage_params
6483                        )?;
6484                    }
6485                    if let Some(from_obj_alias) = from_obj_alias {
6486                        write!(f, " AS {from_obj_alias}")?;
6487                    }
6488                    write!(f, ")")?;
6489                } else if let Some(from_obj) = from_obj {
6490                    // Standard data load
6491                    write!(f, " FROM {from_obj}{stage_params}")?;
6492                    if let Some(from_obj_alias) = from_obj_alias {
6493                        write!(f, " AS {from_obj_alias}")?;
6494                    }
6495                } else if let Some(from_query) = from_query {
6496                    // Data unload from query
6497                    write!(f, " FROM ({from_query})")?;
6498                }
6499
6500                if let Some(files) = files {
6501                    write!(f, " FILES = ('{}')", display_separated(files, "', '"))?;
6502                }
6503                if let Some(pattern) = pattern {
6504                    write!(f, " PATTERN = '{pattern}'")?;
6505                }
6506                if let Some(partition) = partition {
6507                    write!(f, " PARTITION BY {partition}")?;
6508                }
6509                if !file_format.options.is_empty() {
6510                    write!(f, " FILE_FORMAT=({file_format})")?;
6511                }
6512                if !copy_options.options.is_empty() {
6513                    match kind {
6514                        CopyIntoSnowflakeKind::Table => {
6515                            write!(f, " COPY_OPTIONS=({copy_options})")?
6516                        }
6517                        CopyIntoSnowflakeKind::Location => write!(f, " {copy_options}")?,
6518                    }
6519                }
6520                if let Some(validation_mode) = validation_mode {
6521                    write!(f, " VALIDATION_MODE = {validation_mode}")?;
6522                }
6523                Ok(())
6524            }
6525            Statement::CreateType {
6526                name,
6527                representation,
6528            } => {
6529                write!(f, "CREATE TYPE {name}")?;
6530                if let Some(repr) = representation {
6531                    write!(f, " {repr}")?;
6532                }
6533                Ok(())
6534            }
6535            Statement::Pragma { name, value, is_eq } => {
6536                write!(f, "PRAGMA {name}")?;
6537                if value.is_some() {
6538                    let val = value.as_ref().unwrap();
6539                    if *is_eq {
6540                        write!(f, " = {val}")?;
6541                    } else {
6542                        write!(f, "({val})")?;
6543                    }
6544                }
6545                Ok(())
6546            }
6547            Statement::Lock(lock) => lock.fmt(f),
6548            Statement::LockTables { tables } => {
6549                write!(f, "LOCK TABLES {}", display_comma_separated(tables))
6550            }
6551            Statement::UnlockTables => {
6552                write!(f, "UNLOCK TABLES")
6553            }
6554            Statement::Unload {
6555                query,
6556                query_text,
6557                to,
6558                auth,
6559                with,
6560                options,
6561            } => {
6562                write!(f, "UNLOAD(")?;
6563                if let Some(query) = query {
6564                    write!(f, "{query}")?;
6565                }
6566                if let Some(query_text) = query_text {
6567                    write!(f, "'{query_text}'")?;
6568                }
6569                write!(f, ") TO {to}")?;
6570                if let Some(auth) = auth {
6571                    write!(f, " IAM_ROLE {auth}")?;
6572                }
6573                if !with.is_empty() {
6574                    write!(f, " WITH ({})", display_comma_separated(with))?;
6575                }
6576                if !options.is_empty() {
6577                    write!(f, " {}", display_separated(options, " "))?;
6578                }
6579                Ok(())
6580            }
6581            Statement::OptimizeTable {
6582                name,
6583                has_table_keyword,
6584                on_cluster,
6585                partition,
6586                include_final,
6587                deduplicate,
6588                predicate,
6589                zorder,
6590            } => {
6591                write!(f, "OPTIMIZE")?;
6592                if *has_table_keyword {
6593                    write!(f, " TABLE")?;
6594                }
6595                write!(f, " {name}")?;
6596                if let Some(on_cluster) = on_cluster {
6597                    write!(f, " ON CLUSTER {on_cluster}")?;
6598                }
6599                if let Some(partition) = partition {
6600                    write!(f, " {partition}")?;
6601                }
6602                if *include_final {
6603                    write!(f, " FINAL")?;
6604                }
6605                if let Some(deduplicate) = deduplicate {
6606                    write!(f, " {deduplicate}")?;
6607                }
6608                if let Some(predicate) = predicate {
6609                    write!(f, " WHERE {predicate}")?;
6610                }
6611                if let Some(zorder) = zorder {
6612                    write!(f, " ZORDER BY ({})", display_comma_separated(zorder))?;
6613                }
6614                Ok(())
6615            }
6616            Statement::LISTEN { channel } => {
6617                write!(f, "LISTEN {channel}")?;
6618                Ok(())
6619            }
6620            Statement::UNLISTEN { channel } => {
6621                write!(f, "UNLISTEN {channel}")?;
6622                Ok(())
6623            }
6624            Statement::NOTIFY { channel, payload } => {
6625                write!(f, "NOTIFY {channel}")?;
6626                if let Some(payload) = payload {
6627                    write!(f, ", '{payload}'")?;
6628                }
6629                Ok(())
6630            }
6631            Statement::RenameTable(rename_tables) => {
6632                write!(f, "RENAME TABLE {}", display_comma_separated(rename_tables))
6633            }
6634            Statement::RaisError {
6635                message,
6636                severity,
6637                state,
6638                arguments,
6639                options,
6640            } => {
6641                write!(f, "RAISERROR({message}, {severity}, {state}")?;
6642                if !arguments.is_empty() {
6643                    write!(f, ", {}", display_comma_separated(arguments))?;
6644                }
6645                write!(f, ")")?;
6646                if !options.is_empty() {
6647                    write!(f, " WITH {}", display_comma_separated(options))?;
6648                }
6649                Ok(())
6650            }
6651            Statement::Throw(s) => write!(f, "{s}"),
6652            Statement::Print(s) => write!(f, "{s}"),
6653            Statement::WaitFor(s) => write!(f, "{s}"),
6654            Statement::Return(r) => write!(f, "{r}"),
6655            Statement::List(command) => write!(f, "LIST {command}"),
6656            Statement::Remove(command) => write!(f, "REMOVE {command}"),
6657            Statement::ExportData(e) => write!(f, "{e}"),
6658            Statement::CreateUser(s) => write!(f, "{s}"),
6659            Statement::AlterSchema(s) => write!(f, "{s}"),
6660            Statement::Vacuum(s) => write!(f, "{s}"),
6661            Statement::AlterUser(s) => write!(f, "{s}"),
6662            Statement::Reset(s) => write!(f, "{s}"),
6663        }
6664    }
6665}
6666
6667/// Can use to describe options in create sequence or table column type identity
6668/// ```sql
6669/// [ INCREMENT [ BY ] increment ]
6670///     [ MINVALUE minvalue | NO MINVALUE ] [ MAXVALUE maxvalue | NO MAXVALUE ]
6671///     [ START [ WITH ] start ] [ CACHE cache ] [ [ NO ] CYCLE ]
6672/// ```
6673#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6674#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6675#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6676pub enum SequenceOptions {
6677    /// `INCREMENT [BY] <expr>` option; second value indicates presence of `BY` keyword.
6678    IncrementBy(Expr, bool),
6679    /// `MINVALUE <expr>` or `NO MINVALUE`.
6680    MinValue(Option<Expr>),
6681    /// `MAXVALUE <expr>` or `NO MAXVALUE`.
6682    MaxValue(Option<Expr>),
6683    /// `START [WITH] <expr>`; second value indicates presence of `WITH`.
6684    StartWith(Expr, bool),
6685    /// `CACHE <expr>` option.
6686    Cache(Expr),
6687    /// `CYCLE` or `NO CYCLE` option.
6688    Cycle(bool),
6689}
6690
6691impl fmt::Display for SequenceOptions {
6692    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6693        match self {
6694            SequenceOptions::IncrementBy(increment, by) => {
6695                write!(
6696                    f,
6697                    " INCREMENT{by} {increment}",
6698                    by = if *by { " BY" } else { "" },
6699                    increment = increment
6700                )
6701            }
6702            SequenceOptions::MinValue(Some(expr)) => {
6703                write!(f, " MINVALUE {expr}")
6704            }
6705            SequenceOptions::MinValue(None) => {
6706                write!(f, " NO MINVALUE")
6707            }
6708            SequenceOptions::MaxValue(Some(expr)) => {
6709                write!(f, " MAXVALUE {expr}")
6710            }
6711            SequenceOptions::MaxValue(None) => {
6712                write!(f, " NO MAXVALUE")
6713            }
6714            SequenceOptions::StartWith(start, with) => {
6715                write!(
6716                    f,
6717                    " START{with} {start}",
6718                    with = if *with { " WITH" } else { "" },
6719                    start = start
6720                )
6721            }
6722            SequenceOptions::Cache(cache) => {
6723                write!(f, " CACHE {}", *cache)
6724            }
6725            SequenceOptions::Cycle(no) => {
6726                write!(f, " {}CYCLE", if *no { "NO " } else { "" })
6727            }
6728        }
6729    }
6730}
6731
6732/// Assignment for a `SET` statement (name [=|TO] value)
6733#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6734#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6735#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6736pub struct SetAssignment {
6737    /// Optional context scope (e.g., SESSION or LOCAL).
6738    pub scope: Option<ContextModifier>,
6739    /// Assignment target name.
6740    pub name: ObjectName,
6741    /// Assigned expression value.
6742    pub value: Expr,
6743}
6744
6745impl fmt::Display for SetAssignment {
6746    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6747        write!(
6748            f,
6749            "{}{} = {}",
6750            self.scope.map(|s| format!("{s}")).unwrap_or_default(),
6751            self.name,
6752            self.value
6753        )
6754    }
6755}
6756
6757/// Target of a `TRUNCATE TABLE` command
6758///
6759/// Note this is its own struct because `visit_relation` requires an `ObjectName` (not a `Vec<ObjectName>`)
6760#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6761#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6762#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6763pub struct TruncateTableTarget {
6764    /// name of the table being truncated
6765    #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
6766    pub name: ObjectName,
6767    /// Postgres-specific option: explicitly exclude descendants (also default without ONLY)
6768    /// ```sql
6769    /// TRUNCATE TABLE ONLY name
6770    /// ```
6771    /// <https://www.postgresql.org/docs/current/sql-truncate.html>
6772    pub only: bool,
6773    /// Postgres-specific option: asterisk after table name to explicitly indicate descendants
6774    /// ```sql
6775    /// TRUNCATE TABLE name [ * ]
6776    /// ```
6777    /// <https://www.postgresql.org/docs/current/sql-truncate.html>
6778    pub has_asterisk: bool,
6779}
6780
6781impl fmt::Display for TruncateTableTarget {
6782    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6783        if self.only {
6784            write!(f, "ONLY ")?;
6785        };
6786        write!(f, "{}", self.name)?;
6787        if self.has_asterisk {
6788            write!(f, " *")?;
6789        };
6790        Ok(())
6791    }
6792}
6793
6794/// A `LOCK` statement.
6795///
6796/// See <https://www.postgresql.org/docs/current/sql-lock.html>
6797#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6798#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6799#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6800pub struct Lock {
6801    /// List of tables to lock.
6802    pub tables: Vec<LockTableTarget>,
6803    /// Lock mode.
6804    pub lock_mode: Option<LockTableMode>,
6805    /// Whether `NOWAIT` was specified.
6806    pub nowait: bool,
6807}
6808
6809impl fmt::Display for Lock {
6810    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6811        write!(f, "LOCK TABLE {}", display_comma_separated(&self.tables))?;
6812        if let Some(lock_mode) = &self.lock_mode {
6813            write!(f, " IN {lock_mode} MODE")?;
6814        }
6815        if self.nowait {
6816            write!(f, " NOWAIT")?;
6817        }
6818        Ok(())
6819    }
6820}
6821
6822/// Target of a `LOCK TABLE` command
6823///
6824/// See <https://www.postgresql.org/docs/current/sql-lock.html>
6825#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6826#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6827#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6828pub struct LockTableTarget {
6829    /// Name of the table being locked.
6830    #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
6831    pub name: ObjectName,
6832    /// Whether `ONLY` was specified to exclude descendant tables.
6833    pub only: bool,
6834    /// Whether `*` was specified to explicitly include descendant tables.
6835    pub has_asterisk: bool,
6836}
6837
6838impl fmt::Display for LockTableTarget {
6839    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6840        if self.only {
6841            write!(f, "ONLY ")?;
6842        }
6843        write!(f, "{}", self.name)?;
6844        if self.has_asterisk {
6845            write!(f, " *")?;
6846        }
6847        Ok(())
6848    }
6849}
6850
6851/// PostgreSQL lock modes for `LOCK TABLE`.
6852///
6853/// See <https://www.postgresql.org/docs/current/sql-lock.html>
6854#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6855#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6856#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6857pub enum LockTableMode {
6858    /// `ACCESS SHARE`
6859    AccessShare,
6860    /// `ROW SHARE`
6861    RowShare,
6862    /// `ROW EXCLUSIVE`
6863    RowExclusive,
6864    /// `SHARE UPDATE EXCLUSIVE`
6865    ShareUpdateExclusive,
6866    /// `SHARE`
6867    Share,
6868    /// `SHARE ROW EXCLUSIVE`
6869    ShareRowExclusive,
6870    /// `EXCLUSIVE`
6871    Exclusive,
6872    /// `ACCESS EXCLUSIVE`
6873    AccessExclusive,
6874}
6875
6876impl fmt::Display for LockTableMode {
6877    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
6878        let text = match self {
6879            Self::AccessShare => "ACCESS SHARE",
6880            Self::RowShare => "ROW SHARE",
6881            Self::RowExclusive => "ROW EXCLUSIVE",
6882            Self::ShareUpdateExclusive => "SHARE UPDATE EXCLUSIVE",
6883            Self::Share => "SHARE",
6884            Self::ShareRowExclusive => "SHARE ROW EXCLUSIVE",
6885            Self::Exclusive => "EXCLUSIVE",
6886            Self::AccessExclusive => "ACCESS EXCLUSIVE",
6887        };
6888        write!(f, "{text}")
6889    }
6890}
6891
6892/// PostgreSQL identity option for TRUNCATE table
6893/// [ RESTART IDENTITY | CONTINUE IDENTITY ]
6894#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6895#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6896#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6897pub enum TruncateIdentityOption {
6898    /// Restart identity values (RESTART IDENTITY).
6899    Restart,
6900    /// Continue identity values (CONTINUE IDENTITY).
6901    Continue,
6902}
6903
6904/// Cascade/restrict option for Postgres TRUNCATE table, MySQL GRANT/REVOKE, etc.
6905/// [ CASCADE | RESTRICT ]
6906#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6907#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6908#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6909pub enum CascadeOption {
6910    /// Apply cascading action (e.g., CASCADE).
6911    Cascade,
6912    /// Restrict the action (e.g., RESTRICT).
6913    Restrict,
6914}
6915
6916impl Display for CascadeOption {
6917    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6918        match self {
6919            CascadeOption::Cascade => write!(f, "CASCADE"),
6920            CascadeOption::Restrict => write!(f, "RESTRICT"),
6921        }
6922    }
6923}
6924
6925/// Transaction started with [ TRANSACTION | WORK | TRAN ]
6926#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6927#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6928#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6929pub enum BeginTransactionKind {
6930    /// Standard `TRANSACTION` keyword.
6931    Transaction,
6932    /// Alternate `WORK` keyword.
6933    Work,
6934    /// MSSQL shorthand `TRAN` keyword.
6935    /// See <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/begin-transaction-transact-sql>
6936    Tran,
6937}
6938
6939impl Display for BeginTransactionKind {
6940    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6941        match self {
6942            BeginTransactionKind::Transaction => write!(f, "TRANSACTION"),
6943            BeginTransactionKind::Work => write!(f, "WORK"),
6944            BeginTransactionKind::Tran => write!(f, "TRAN"),
6945        }
6946    }
6947}
6948
6949/// Can use to describe options in  create sequence or table column type identity
6950/// [ MINVALUE minvalue | NO MINVALUE ] [ MAXVALUE maxvalue | NO MAXVALUE ]
6951#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6952#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6953#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6954pub enum MinMaxValue {
6955    /// Clause is not specified.
6956    Empty,
6957    /// NO MINVALUE / NO MAXVALUE.
6958    None,
6959    /// `MINVALUE <expr>` / `MAXVALUE <expr>`.
6960    Some(Expr),
6961}
6962
6963#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6964#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6965#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6966#[non_exhaustive]
6967/// Behavior to apply for `INSERT` when a conflict occurs.
6968pub enum OnInsert {
6969    /// ON DUPLICATE KEY UPDATE (MySQL when the key already exists, then execute an update instead)
6970    DuplicateKeyUpdate(Vec<Assignment>),
6971    /// ON CONFLICT is a PostgreSQL and Sqlite extension
6972    OnConflict(OnConflict),
6973}
6974
6975#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6976#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6977#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6978/// Optional aliases for `INSERT` targets: row alias and optional column aliases.
6979pub struct InsertAliases {
6980    /// Row alias (table-style alias) for the inserted values.
6981    pub row_alias: ObjectName,
6982    /// Optional list of column aliases for the inserted values.
6983    pub col_aliases: Option<Vec<Ident>>,
6984}
6985
6986#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6987#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6988#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6989/// Optional alias for an `INSERT` table; i.e. the table to be inserted into
6990pub struct TableAliasWithoutColumns {
6991    /// `true` if the aliases was explicitly introduced with the "AS" keyword
6992    pub explicit: bool,
6993    /// the alias name itself
6994    pub alias: Ident,
6995}
6996
6997#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6998#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6999#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7000/// `ON CONFLICT` clause representation.
7001pub struct OnConflict {
7002    /// Optional conflict target specifying columns or constraint.
7003    pub conflict_target: Option<ConflictTarget>,
7004    /// Action to take when a conflict occurs.
7005    pub action: OnConflictAction,
7006}
7007#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7008#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7009#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7010/// Target specification for an `ON CONFLICT` clause.
7011pub enum ConflictTarget {
7012    /// Target specified as a list of columns.
7013    Columns(Vec<Ident>),
7014    /// Target specified as a named constraint.
7015    OnConstraint(ObjectName),
7016}
7017#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7018#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7019#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7020/// Action to perform when an `ON CONFLICT` target is matched.
7021pub enum OnConflictAction {
7022    /// Do nothing on conflict.
7023    DoNothing,
7024    /// Perform an update on conflict.
7025    DoUpdate(DoUpdate),
7026}
7027
7028#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7029#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7030#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7031/// Details for `DO UPDATE` action of an `ON CONFLICT` clause.
7032pub struct DoUpdate {
7033    /// Column assignments to perform on update.
7034    pub assignments: Vec<Assignment>,
7035    /// Optional WHERE clause limiting the update.
7036    pub selection: Option<Expr>,
7037}
7038
7039impl fmt::Display for OnInsert {
7040    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7041        match self {
7042            Self::DuplicateKeyUpdate(expr) => write!(
7043                f,
7044                " ON DUPLICATE KEY UPDATE {}",
7045                display_comma_separated(expr)
7046            ),
7047            Self::OnConflict(o) => write!(f, "{o}"),
7048        }
7049    }
7050}
7051impl fmt::Display for OnConflict {
7052    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7053        write!(f, " ON CONFLICT")?;
7054        if let Some(target) = &self.conflict_target {
7055            write!(f, "{target}")?;
7056        }
7057        write!(f, " {}", self.action)
7058    }
7059}
7060impl fmt::Display for ConflictTarget {
7061    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7062        match self {
7063            ConflictTarget::Columns(cols) => write!(f, "({})", display_comma_separated(cols)),
7064            ConflictTarget::OnConstraint(name) => write!(f, " ON CONSTRAINT {name}"),
7065        }
7066    }
7067}
7068impl fmt::Display for OnConflictAction {
7069    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7070        match self {
7071            Self::DoNothing => write!(f, "DO NOTHING"),
7072            Self::DoUpdate(do_update) => {
7073                write!(f, "DO UPDATE")?;
7074                if !do_update.assignments.is_empty() {
7075                    write!(
7076                        f,
7077                        " SET {}",
7078                        display_comma_separated(&do_update.assignments)
7079                    )?;
7080                }
7081                if let Some(selection) = &do_update.selection {
7082                    write!(f, " WHERE {selection}")?;
7083                }
7084                Ok(())
7085            }
7086        }
7087    }
7088}
7089
7090/// Privileges granted in a GRANT statement or revoked in a REVOKE statement.
7091#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7092#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7093#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7094pub enum Privileges {
7095    /// All privileges applicable to the object type
7096    All {
7097        /// Optional keyword from the spec, ignored in practice
7098        with_privileges_keyword: bool,
7099    },
7100    /// Specific privileges (e.g. `SELECT`, `INSERT`)
7101    Actions(Vec<Action>),
7102}
7103
7104impl fmt::Display for Privileges {
7105    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7106        match self {
7107            Privileges::All {
7108                with_privileges_keyword,
7109            } => {
7110                write!(
7111                    f,
7112                    "ALL{}",
7113                    if *with_privileges_keyword {
7114                        " PRIVILEGES"
7115                    } else {
7116                        ""
7117                    }
7118                )
7119            }
7120            Privileges::Actions(actions) => {
7121                write!(f, "{}", display_comma_separated(actions))
7122            }
7123        }
7124    }
7125}
7126
7127/// Specific direction for FETCH statement
7128#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7129#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7130#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7131pub enum FetchDirection {
7132    /// Fetch a specific count of rows.
7133    Count {
7134        /// The limit value for the count.
7135        limit: ValueWithSpan,
7136    },
7137    /// Fetch the next row.
7138    Next,
7139    /// Fetch the prior row.
7140    Prior,
7141    /// Fetch the first row.
7142    First,
7143    /// Fetch the last row.
7144    Last,
7145    /// Fetch an absolute row by index.
7146    Absolute {
7147        /// The absolute index value.
7148        limit: ValueWithSpan,
7149    },
7150    /// Fetch a row relative to the current position.
7151    Relative {
7152        /// The relative offset value.
7153        limit: ValueWithSpan,
7154    },
7155    /// Fetch all rows.
7156    All,
7157    // FORWARD
7158    // FORWARD count
7159    /// Fetch forward by an optional limit.
7160    Forward {
7161        /// Optional forward limit.
7162        limit: Option<ValueWithSpan>,
7163    },
7164    /// Fetch all forward rows.
7165    ForwardAll,
7166    // BACKWARD
7167    // BACKWARD count
7168    /// Fetch backward by an optional limit.
7169    Backward {
7170        /// Optional backward limit.
7171        limit: Option<ValueWithSpan>,
7172    },
7173    /// Fetch all backward rows.
7174    BackwardAll,
7175}
7176
7177impl fmt::Display for FetchDirection {
7178    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7179        match self {
7180            FetchDirection::Count { limit } => f.write_str(&limit.to_string())?,
7181            FetchDirection::Next => f.write_str("NEXT")?,
7182            FetchDirection::Prior => f.write_str("PRIOR")?,
7183            FetchDirection::First => f.write_str("FIRST")?,
7184            FetchDirection::Last => f.write_str("LAST")?,
7185            FetchDirection::Absolute { limit } => {
7186                f.write_str("ABSOLUTE ")?;
7187                f.write_str(&limit.to_string())?;
7188            }
7189            FetchDirection::Relative { limit } => {
7190                f.write_str("RELATIVE ")?;
7191                f.write_str(&limit.to_string())?;
7192            }
7193            FetchDirection::All => f.write_str("ALL")?,
7194            FetchDirection::Forward { limit } => {
7195                f.write_str("FORWARD")?;
7196
7197                if let Some(l) = limit {
7198                    f.write_str(" ")?;
7199                    f.write_str(&l.to_string())?;
7200                }
7201            }
7202            FetchDirection::ForwardAll => f.write_str("FORWARD ALL")?,
7203            FetchDirection::Backward { limit } => {
7204                f.write_str("BACKWARD")?;
7205
7206                if let Some(l) = limit {
7207                    f.write_str(" ")?;
7208                    f.write_str(&l.to_string())?;
7209                }
7210            }
7211            FetchDirection::BackwardAll => f.write_str("BACKWARD ALL")?,
7212        };
7213
7214        Ok(())
7215    }
7216}
7217
7218/// The "position" for a FETCH statement.
7219///
7220/// [MsSql](https://learn.microsoft.com/en-us/sql/t-sql/language-elements/fetch-transact-sql)
7221#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7222#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7223#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7224pub enum FetchPosition {
7225    /// Use `FROM <pos>` position specifier.
7226    From,
7227    /// Use `IN <pos>` position specifier.
7228    In,
7229}
7230
7231impl fmt::Display for FetchPosition {
7232    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7233        match self {
7234            FetchPosition::From => f.write_str("FROM")?,
7235            FetchPosition::In => f.write_str("IN")?,
7236        };
7237
7238        Ok(())
7239    }
7240}
7241
7242/// A privilege on a database object (table, sequence, etc.).
7243#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7244#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7245#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7246pub enum Action {
7247    /// Add a search optimization.
7248    AddSearchOptimization,
7249    /// Apply an `APPLY` operation with a specific type.
7250    Apply {
7251        /// The type of apply operation.
7252        apply_type: ActionApplyType,
7253    },
7254    /// Apply a budget operation.
7255    ApplyBudget,
7256    /// Attach a listing.
7257    AttachListing,
7258    /// Attach a policy.
7259    AttachPolicy,
7260    /// Audit operation.
7261    Audit,
7262    /// Bind a service endpoint.
7263    BindServiceEndpoint,
7264    /// Connect permission.
7265    Connect,
7266    /// Create action, optionally specifying an object type.
7267    Create {
7268        /// Optional object type to create.
7269        obj_type: Option<ActionCreateObjectType>,
7270    },
7271    /// Actions related to database roles.
7272    DatabaseRole {
7273        /// The role name.
7274        role: ObjectName,
7275    },
7276    /// Delete permission.
7277    Delete,
7278    /// Drop permission.
7279    Drop,
7280    /// Evolve schema permission.
7281    EvolveSchema,
7282    /// Exec action (execute) with optional object type.
7283    Exec {
7284        /// Optional execute object type.
7285        obj_type: Option<ActionExecuteObjectType>,
7286    },
7287    /// Execute action with optional object type.
7288    Execute {
7289        /// Optional execute object type.
7290        obj_type: Option<ActionExecuteObjectType>,
7291    },
7292    /// Failover operation.
7293    Failover,
7294    /// Use imported privileges.
7295    ImportedPrivileges,
7296    /// Import a share.
7297    ImportShare,
7298    /// Insert rows with optional column list.
7299    Insert {
7300        /// Optional list of target columns for insert.
7301        columns: Option<Vec<Ident>>,
7302    },
7303    /// Manage operation with a specific manage type.
7304    Manage {
7305        /// The specific manage sub-type.
7306        manage_type: ActionManageType,
7307    },
7308    /// Manage releases.
7309    ManageReleases,
7310    /// Manage versions.
7311    ManageVersions,
7312    /// Modify operation with an optional modify type.
7313    Modify {
7314        /// The optional modify sub-type.
7315        modify_type: Option<ActionModifyType>,
7316    },
7317    /// Monitor operation with an optional monitor type.
7318    Monitor {
7319        /// The optional monitor sub-type.
7320        monitor_type: Option<ActionMonitorType>,
7321    },
7322    /// Operate permission.
7323    Operate,
7324    /// Override share restrictions.
7325    OverrideShareRestrictions,
7326    /// Ownership permission.
7327    Ownership,
7328    /// Purchase a data exchange listing.
7329    PurchaseDataExchangeListing,
7330
7331    /// Read access.
7332    Read,
7333    /// Read session-level access.
7334    ReadSession,
7335    /// References with optional column list.
7336    References {
7337        /// Optional list of referenced column identifiers.
7338        columns: Option<Vec<Ident>>,
7339    },
7340    /// Replication permission.
7341    Replicate,
7342    /// Resolve all references.
7343    ResolveAll,
7344    /// Role-related permission with target role name.
7345    Role {
7346        /// The target role name.
7347        role: ObjectName,
7348    },
7349    /// Select permission with optional column list.
7350    Select {
7351        /// Optional list of selected columns.
7352        columns: Option<Vec<Ident>>,
7353    },
7354    /// Temporary object permission.
7355    Temporary,
7356    /// Trigger-related permission.
7357    Trigger,
7358    /// Truncate permission.
7359    Truncate,
7360    /// Update permission with optional affected columns.
7361    Update {
7362        /// Optional list of columns affected by update.
7363        columns: Option<Vec<Ident>>,
7364    },
7365    /// Usage permission.
7366    Usage,
7367}
7368
7369impl fmt::Display for Action {
7370    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7371        match self {
7372            Action::AddSearchOptimization => f.write_str("ADD SEARCH OPTIMIZATION")?,
7373            Action::Apply { apply_type } => write!(f, "APPLY {apply_type}")?,
7374            Action::ApplyBudget => f.write_str("APPLYBUDGET")?,
7375            Action::AttachListing => f.write_str("ATTACH LISTING")?,
7376            Action::AttachPolicy => f.write_str("ATTACH POLICY")?,
7377            Action::Audit => f.write_str("AUDIT")?,
7378            Action::BindServiceEndpoint => f.write_str("BIND SERVICE ENDPOINT")?,
7379            Action::Connect => f.write_str("CONNECT")?,
7380            Action::Create { obj_type } => {
7381                f.write_str("CREATE")?;
7382                if let Some(obj_type) = obj_type {
7383                    write!(f, " {obj_type}")?
7384                }
7385            }
7386            Action::DatabaseRole { role } => write!(f, "DATABASE ROLE {role}")?,
7387            Action::Delete => f.write_str("DELETE")?,
7388            Action::Drop => f.write_str("DROP")?,
7389            Action::EvolveSchema => f.write_str("EVOLVE SCHEMA")?,
7390            Action::Exec { obj_type } => {
7391                f.write_str("EXEC")?;
7392                if let Some(obj_type) = obj_type {
7393                    write!(f, " {obj_type}")?
7394                }
7395            }
7396            Action::Execute { obj_type } => {
7397                f.write_str("EXECUTE")?;
7398                if let Some(obj_type) = obj_type {
7399                    write!(f, " {obj_type}")?
7400                }
7401            }
7402            Action::Failover => f.write_str("FAILOVER")?,
7403            Action::ImportedPrivileges => f.write_str("IMPORTED PRIVILEGES")?,
7404            Action::ImportShare => f.write_str("IMPORT SHARE")?,
7405            Action::Insert { .. } => f.write_str("INSERT")?,
7406            Action::Manage { manage_type } => write!(f, "MANAGE {manage_type}")?,
7407            Action::ManageReleases => f.write_str("MANAGE RELEASES")?,
7408            Action::ManageVersions => f.write_str("MANAGE VERSIONS")?,
7409            Action::Modify { modify_type } => {
7410                write!(f, "MODIFY")?;
7411                if let Some(modify_type) = modify_type {
7412                    write!(f, " {modify_type}")?;
7413                }
7414            }
7415            Action::Monitor { monitor_type } => {
7416                write!(f, "MONITOR")?;
7417                if let Some(monitor_type) = monitor_type {
7418                    write!(f, " {monitor_type}")?
7419                }
7420            }
7421            Action::Operate => f.write_str("OPERATE")?,
7422            Action::OverrideShareRestrictions => f.write_str("OVERRIDE SHARE RESTRICTIONS")?,
7423            Action::Ownership => f.write_str("OWNERSHIP")?,
7424            Action::PurchaseDataExchangeListing => f.write_str("PURCHASE DATA EXCHANGE LISTING")?,
7425            Action::Read => f.write_str("READ")?,
7426            Action::ReadSession => f.write_str("READ SESSION")?,
7427            Action::References { .. } => f.write_str("REFERENCES")?,
7428            Action::Replicate => f.write_str("REPLICATE")?,
7429            Action::ResolveAll => f.write_str("RESOLVE ALL")?,
7430            Action::Role { role } => write!(f, "ROLE {role}")?,
7431            Action::Select { .. } => f.write_str("SELECT")?,
7432            Action::Temporary => f.write_str("TEMPORARY")?,
7433            Action::Trigger => f.write_str("TRIGGER")?,
7434            Action::Truncate => f.write_str("TRUNCATE")?,
7435            Action::Update { .. } => f.write_str("UPDATE")?,
7436            Action::Usage => f.write_str("USAGE")?,
7437        };
7438        match self {
7439            Action::Insert { columns }
7440            | Action::References { columns }
7441            | Action::Select { columns }
7442            | Action::Update { columns } => {
7443                if let Some(columns) = columns {
7444                    write!(f, " ({})", display_comma_separated(columns))?;
7445                }
7446            }
7447            _ => (),
7448        };
7449        Ok(())
7450    }
7451}
7452
7453#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7454#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7455#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7456/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
7457/// under `globalPrivileges` in the `CREATE` privilege.
7458pub enum ActionCreateObjectType {
7459    /// An account-level object.
7460    Account,
7461    /// An application object.
7462    Application,
7463    /// An application package object.
7464    ApplicationPackage,
7465    /// A compute pool object.
7466    ComputePool,
7467    /// A data exchange listing.
7468    DataExchangeListing,
7469    /// A database object.
7470    Database,
7471    /// An external volume object.
7472    ExternalVolume,
7473    /// A failover group object.
7474    FailoverGroup,
7475    /// An integration object.
7476    Integration,
7477    /// A network policy object.
7478    NetworkPolicy,
7479    /// An organization listing.
7480    OrganiationListing,
7481    /// A replication group object.
7482    ReplicationGroup,
7483    /// A role object.
7484    Role,
7485    /// A schema object.
7486    Schema,
7487    /// A share object.
7488    Share,
7489    /// A user object.
7490    User,
7491    /// A warehouse object.
7492    Warehouse,
7493}
7494
7495impl fmt::Display for ActionCreateObjectType {
7496    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7497        match self {
7498            ActionCreateObjectType::Account => write!(f, "ACCOUNT"),
7499            ActionCreateObjectType::Application => write!(f, "APPLICATION"),
7500            ActionCreateObjectType::ApplicationPackage => write!(f, "APPLICATION PACKAGE"),
7501            ActionCreateObjectType::ComputePool => write!(f, "COMPUTE POOL"),
7502            ActionCreateObjectType::DataExchangeListing => write!(f, "DATA EXCHANGE LISTING"),
7503            ActionCreateObjectType::Database => write!(f, "DATABASE"),
7504            ActionCreateObjectType::ExternalVolume => write!(f, "EXTERNAL VOLUME"),
7505            ActionCreateObjectType::FailoverGroup => write!(f, "FAILOVER GROUP"),
7506            ActionCreateObjectType::Integration => write!(f, "INTEGRATION"),
7507            ActionCreateObjectType::NetworkPolicy => write!(f, "NETWORK POLICY"),
7508            ActionCreateObjectType::OrganiationListing => write!(f, "ORGANIZATION LISTING"),
7509            ActionCreateObjectType::ReplicationGroup => write!(f, "REPLICATION GROUP"),
7510            ActionCreateObjectType::Role => write!(f, "ROLE"),
7511            ActionCreateObjectType::Schema => write!(f, "SCHEMA"),
7512            ActionCreateObjectType::Share => write!(f, "SHARE"),
7513            ActionCreateObjectType::User => write!(f, "USER"),
7514            ActionCreateObjectType::Warehouse => write!(f, "WAREHOUSE"),
7515        }
7516    }
7517}
7518
7519#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7520#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7521#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7522/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
7523/// under `globalPrivileges` in the `APPLY` privilege.
7524pub enum ActionApplyType {
7525    /// Apply an aggregation policy.
7526    AggregationPolicy,
7527    /// Apply an authentication policy.
7528    AuthenticationPolicy,
7529    /// Apply a join policy.
7530    JoinPolicy,
7531    /// Apply a masking policy.
7532    MaskingPolicy,
7533    /// Apply a packages policy.
7534    PackagesPolicy,
7535    /// Apply a password policy.
7536    PasswordPolicy,
7537    /// Apply a projection policy.
7538    ProjectionPolicy,
7539    /// Apply a row access policy.
7540    RowAccessPolicy,
7541    /// Apply a session policy.
7542    SessionPolicy,
7543    /// Apply a tag.
7544    Tag,
7545}
7546
7547impl fmt::Display for ActionApplyType {
7548    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7549        match self {
7550            ActionApplyType::AggregationPolicy => write!(f, "AGGREGATION POLICY"),
7551            ActionApplyType::AuthenticationPolicy => write!(f, "AUTHENTICATION POLICY"),
7552            ActionApplyType::JoinPolicy => write!(f, "JOIN POLICY"),
7553            ActionApplyType::MaskingPolicy => write!(f, "MASKING POLICY"),
7554            ActionApplyType::PackagesPolicy => write!(f, "PACKAGES POLICY"),
7555            ActionApplyType::PasswordPolicy => write!(f, "PASSWORD POLICY"),
7556            ActionApplyType::ProjectionPolicy => write!(f, "PROJECTION POLICY"),
7557            ActionApplyType::RowAccessPolicy => write!(f, "ROW ACCESS POLICY"),
7558            ActionApplyType::SessionPolicy => write!(f, "SESSION POLICY"),
7559            ActionApplyType::Tag => write!(f, "TAG"),
7560        }
7561    }
7562}
7563
7564#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7565#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7566#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7567/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
7568/// under `globalPrivileges` in the `EXECUTE` privilege.
7569pub enum ActionExecuteObjectType {
7570    /// Alert object.
7571    Alert,
7572    /// Data metric function object.
7573    DataMetricFunction,
7574    /// Managed alert object.
7575    ManagedAlert,
7576    /// Managed task object.
7577    ManagedTask,
7578    /// Task object.
7579    Task,
7580}
7581
7582impl fmt::Display for ActionExecuteObjectType {
7583    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7584        match self {
7585            ActionExecuteObjectType::Alert => write!(f, "ALERT"),
7586            ActionExecuteObjectType::DataMetricFunction => write!(f, "DATA METRIC FUNCTION"),
7587            ActionExecuteObjectType::ManagedAlert => write!(f, "MANAGED ALERT"),
7588            ActionExecuteObjectType::ManagedTask => write!(f, "MANAGED TASK"),
7589            ActionExecuteObjectType::Task => write!(f, "TASK"),
7590        }
7591    }
7592}
7593
7594#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7595#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7596#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7597/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
7598/// under `globalPrivileges` in the `MANAGE` privilege.
7599pub enum ActionManageType {
7600    /// Account support cases management.
7601    AccountSupportCases,
7602    /// Event sharing management.
7603    EventSharing,
7604    /// Grants management.
7605    Grants,
7606    /// Listing auto-fulfillment management.
7607    ListingAutoFulfillment,
7608    /// Organization support cases management.
7609    OrganizationSupportCases,
7610    /// User support cases management.
7611    UserSupportCases,
7612    /// Warehouses management.
7613    Warehouses,
7614}
7615
7616impl fmt::Display for ActionManageType {
7617    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7618        match self {
7619            ActionManageType::AccountSupportCases => write!(f, "ACCOUNT SUPPORT CASES"),
7620            ActionManageType::EventSharing => write!(f, "EVENT SHARING"),
7621            ActionManageType::Grants => write!(f, "GRANTS"),
7622            ActionManageType::ListingAutoFulfillment => write!(f, "LISTING AUTO FULFILLMENT"),
7623            ActionManageType::OrganizationSupportCases => write!(f, "ORGANIZATION SUPPORT CASES"),
7624            ActionManageType::UserSupportCases => write!(f, "USER SUPPORT CASES"),
7625            ActionManageType::Warehouses => write!(f, "WAREHOUSES"),
7626        }
7627    }
7628}
7629
7630#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7631#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7632#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7633/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
7634/// under `globalPrivileges` in the `MODIFY` privilege.
7635pub enum ActionModifyType {
7636    /// Modify log level.
7637    LogLevel,
7638    /// Modify trace level.
7639    TraceLevel,
7640    /// Modify session log level.
7641    SessionLogLevel,
7642    /// Modify session trace level.
7643    SessionTraceLevel,
7644}
7645
7646impl fmt::Display for ActionModifyType {
7647    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7648        match self {
7649            ActionModifyType::LogLevel => write!(f, "LOG LEVEL"),
7650            ActionModifyType::TraceLevel => write!(f, "TRACE LEVEL"),
7651            ActionModifyType::SessionLogLevel => write!(f, "SESSION LOG LEVEL"),
7652            ActionModifyType::SessionTraceLevel => write!(f, "SESSION TRACE LEVEL"),
7653        }
7654    }
7655}
7656
7657#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7658#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7659#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7660/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
7661/// under `globalPrivileges` in the `MONITOR` privilege.
7662pub enum ActionMonitorType {
7663    /// Monitor execution.
7664    Execution,
7665    /// Monitor security.
7666    Security,
7667    /// Monitor usage.
7668    Usage,
7669}
7670
7671impl fmt::Display for ActionMonitorType {
7672    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7673        match self {
7674            ActionMonitorType::Execution => write!(f, "EXECUTION"),
7675            ActionMonitorType::Security => write!(f, "SECURITY"),
7676            ActionMonitorType::Usage => write!(f, "USAGE"),
7677        }
7678    }
7679}
7680
7681/// The principal that receives the privileges
7682#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7683#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7684#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7685pub struct Grantee {
7686    /// The category/type of grantee (role, user, share, etc.).
7687    pub grantee_type: GranteesType,
7688    /// Optional name of the grantee (identifier or user@host).
7689    pub name: Option<GranteeName>,
7690}
7691
7692impl fmt::Display for Grantee {
7693    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7694        if matches!(self.grantee_type, GranteesType::Public) {
7695            return write!(f, "PUBLIC");
7696        }
7697        match self.grantee_type {
7698            GranteesType::Role => {
7699                write!(f, "ROLE ")?;
7700            }
7701            GranteesType::Share => {
7702                write!(f, "SHARE ")?;
7703            }
7704            GranteesType::User => {
7705                write!(f, "USER ")?;
7706            }
7707            GranteesType::Group => {
7708                write!(f, "GROUP ")?;
7709            }
7710            GranteesType::Public => {}
7711            GranteesType::DatabaseRole => {
7712                write!(f, "DATABASE ROLE ")?;
7713            }
7714            GranteesType::Application => {
7715                write!(f, "APPLICATION ")?;
7716            }
7717            GranteesType::ApplicationRole => {
7718                write!(f, "APPLICATION ROLE ")?;
7719            }
7720            GranteesType::None => (),
7721        }
7722        if let Some(ref name) = self.name {
7723            name.fmt(f)?;
7724        }
7725        Ok(())
7726    }
7727}
7728
7729#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7730#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7731#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7732/// The kind of principal receiving privileges.
7733pub enum GranteesType {
7734    /// A role principal.
7735    Role,
7736    /// A share principal.
7737    Share,
7738    /// A user principal.
7739    User,
7740    /// A group principal.
7741    Group,
7742    /// The public principal.
7743    Public,
7744    /// A database role principal.
7745    DatabaseRole,
7746    /// An application principal.
7747    Application,
7748    /// An application role principal.
7749    ApplicationRole,
7750    /// No specific principal (e.g. `NONE`).
7751    None,
7752}
7753
7754/// Users/roles designated in a GRANT/REVOKE
7755#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7756#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7757#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7758pub enum GranteeName {
7759    /// A bare identifier
7760    ObjectName(ObjectName),
7761    /// A MySQL user/host pair such as 'root'@'%'
7762    UserHost {
7763        /// The user identifier portion.
7764        user: Ident,
7765        /// The host identifier portion.
7766        host: Ident,
7767    },
7768}
7769
7770impl fmt::Display for GranteeName {
7771    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7772        match self {
7773            GranteeName::ObjectName(name) => name.fmt(f),
7774            GranteeName::UserHost { user, host } => {
7775                write!(f, "{user}@{host}")
7776            }
7777        }
7778    }
7779}
7780
7781/// Objects on which privileges are granted in a GRANT statement.
7782#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7783#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7784#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7785pub enum GrantObjects {
7786    /// Grant privileges on `ALL SEQUENCES IN SCHEMA <schema_name> [, ...]`
7787    AllSequencesInSchema {
7788        /// The target schema names.
7789        schemas: Vec<ObjectName>,
7790    },
7791    /// Grant privileges on `ALL TABLES IN SCHEMA <schema_name> [, ...]`
7792    AllTablesInSchema {
7793        /// The target schema names.
7794        schemas: Vec<ObjectName>,
7795    },
7796    /// Grant privileges on `ALL VIEWS IN SCHEMA <schema_name> [, ...]`
7797    AllViewsInSchema {
7798        /// The target schema names.
7799        schemas: Vec<ObjectName>,
7800    },
7801    /// Grant privileges on `ALL MATERIALIZED VIEWS IN SCHEMA <schema_name> [, ...]`
7802    AllMaterializedViewsInSchema {
7803        /// The target schema names.
7804        schemas: Vec<ObjectName>,
7805    },
7806    /// Grant privileges on `ALL EXTERNAL TABLES IN SCHEMA <schema_name> [, ...]`
7807    AllExternalTablesInSchema {
7808        /// The target schema names.
7809        schemas: Vec<ObjectName>,
7810    },
7811    /// Grant privileges on `ALL FUNCTIONS IN SCHEMA <schema_name> [, ...]`
7812    AllFunctionsInSchema {
7813        /// The target schema names.
7814        schemas: Vec<ObjectName>,
7815    },
7816    /// Grant privileges on `FUTURE SCHEMAS IN DATABASE <database_name> [, ...]`
7817    FutureSchemasInDatabase {
7818        /// The target database names.
7819        databases: Vec<ObjectName>,
7820    },
7821    /// Grant privileges on `FUTURE TABLES IN SCHEMA <schema_name> [, ...]`
7822    FutureTablesInSchema {
7823        /// The target schema names.
7824        schemas: Vec<ObjectName>,
7825    },
7826    /// Grant privileges on `FUTURE VIEWS IN SCHEMA <schema_name> [, ...]`
7827    FutureViewsInSchema {
7828        /// The target schema names.
7829        schemas: Vec<ObjectName>,
7830    },
7831    /// Grant privileges on `FUTURE EXTERNAL TABLES IN SCHEMA <schema_name> [, ...]`
7832    FutureExternalTablesInSchema {
7833        /// The target schema names.
7834        schemas: Vec<ObjectName>,
7835    },
7836    /// Grant privileges on `FUTURE MATERIALIZED VIEWS IN SCHEMA <schema_name> [, ...]`
7837    FutureMaterializedViewsInSchema {
7838        /// The target schema names.
7839        schemas: Vec<ObjectName>,
7840    },
7841    /// Grant privileges on `FUTURE SEQUENCES IN SCHEMA <schema_name> [, ...]`
7842    FutureSequencesInSchema {
7843        /// The target schema names.
7844        schemas: Vec<ObjectName>,
7845    },
7846    /// Grant privileges on specific databases
7847    Databases(Vec<ObjectName>),
7848    /// Grant privileges on specific schemas
7849    Schemas(Vec<ObjectName>),
7850    /// Grant privileges on specific sequences
7851    Sequences(Vec<ObjectName>),
7852    /// Grant privileges on specific tables
7853    Tables(Vec<ObjectName>),
7854    /// Grant privileges on specific views
7855    Views(Vec<ObjectName>),
7856    /// Grant privileges on specific warehouses
7857    Warehouses(Vec<ObjectName>),
7858    /// Grant privileges on specific integrations
7859    Integrations(Vec<ObjectName>),
7860    /// Grant privileges on resource monitors
7861    ResourceMonitors(Vec<ObjectName>),
7862    /// Grant privileges on users
7863    Users(Vec<ObjectName>),
7864    /// Grant privileges on compute pools
7865    ComputePools(Vec<ObjectName>),
7866    /// Grant privileges on connections
7867    Connections(Vec<ObjectName>),
7868    /// Grant privileges on failover groups
7869    FailoverGroup(Vec<ObjectName>),
7870    /// Grant privileges on replication group
7871    ReplicationGroup(Vec<ObjectName>),
7872    /// Grant privileges on external volumes
7873    ExternalVolumes(Vec<ObjectName>),
7874    /// Grant privileges on a procedure. In dialects that
7875    /// support overloading, the argument types must be specified.
7876    ///
7877    /// For example:
7878    /// `GRANT USAGE ON PROCEDURE foo(varchar) TO ROLE role1`
7879    Procedure {
7880        /// The procedure name.
7881        name: ObjectName,
7882        /// Optional argument types for overloaded procedures.
7883        arg_types: Vec<DataType>,
7884    },
7885
7886    /// Grant privileges on a function. In dialects that
7887    /// support overloading, the argument types must be specified.
7888    ///
7889    /// For example:
7890    /// `GRANT USAGE ON FUNCTION foo(varchar) TO ROLE role1`
7891    Function {
7892        /// The function name.
7893        name: ObjectName,
7894        /// Optional argument types for overloaded functions.
7895        arg_types: Vec<DataType>,
7896    },
7897
7898    /// Grant privileges on specific user-defined types (PostgreSQL).
7899    ///
7900    /// For example:
7901    /// `GRANT USAGE ON TYPE user_role TO app_user`
7902    Types(Vec<ObjectName>),
7903
7904    /// Grant privileges on specific domains (PostgreSQL).
7905    ///
7906    /// For example:
7907    /// `GRANT USAGE ON DOMAIN email_addr TO app_user`
7908    Domains(Vec<ObjectName>),
7909}
7910
7911impl fmt::Display for GrantObjects {
7912    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7913        match self {
7914            GrantObjects::Sequences(sequences) => {
7915                write!(f, "SEQUENCE {}", display_comma_separated(sequences))
7916            }
7917            GrantObjects::Databases(databases) => {
7918                write!(f, "DATABASE {}", display_comma_separated(databases))
7919            }
7920            GrantObjects::Schemas(schemas) => {
7921                write!(f, "SCHEMA {}", display_comma_separated(schemas))
7922            }
7923            GrantObjects::Tables(tables) => {
7924                write!(f, "{}", display_comma_separated(tables))
7925            }
7926            GrantObjects::Views(views) => {
7927                write!(f, "VIEW {}", display_comma_separated(views))
7928            }
7929            GrantObjects::Warehouses(warehouses) => {
7930                write!(f, "WAREHOUSE {}", display_comma_separated(warehouses))
7931            }
7932            GrantObjects::Integrations(integrations) => {
7933                write!(f, "INTEGRATION {}", display_comma_separated(integrations))
7934            }
7935            GrantObjects::AllSequencesInSchema { schemas } => {
7936                write!(
7937                    f,
7938                    "ALL SEQUENCES IN SCHEMA {}",
7939                    display_comma_separated(schemas)
7940                )
7941            }
7942            GrantObjects::AllTablesInSchema { schemas } => {
7943                write!(
7944                    f,
7945                    "ALL TABLES IN SCHEMA {}",
7946                    display_comma_separated(schemas)
7947                )
7948            }
7949            GrantObjects::AllExternalTablesInSchema { schemas } => {
7950                write!(
7951                    f,
7952                    "ALL EXTERNAL TABLES IN SCHEMA {}",
7953                    display_comma_separated(schemas)
7954                )
7955            }
7956            GrantObjects::AllViewsInSchema { schemas } => {
7957                write!(
7958                    f,
7959                    "ALL VIEWS IN SCHEMA {}",
7960                    display_comma_separated(schemas)
7961                )
7962            }
7963            GrantObjects::AllMaterializedViewsInSchema { schemas } => {
7964                write!(
7965                    f,
7966                    "ALL MATERIALIZED VIEWS IN SCHEMA {}",
7967                    display_comma_separated(schemas)
7968                )
7969            }
7970            GrantObjects::AllFunctionsInSchema { schemas } => {
7971                write!(
7972                    f,
7973                    "ALL FUNCTIONS IN SCHEMA {}",
7974                    display_comma_separated(schemas)
7975                )
7976            }
7977            GrantObjects::FutureSchemasInDatabase { databases } => {
7978                write!(
7979                    f,
7980                    "FUTURE SCHEMAS IN DATABASE {}",
7981                    display_comma_separated(databases)
7982                )
7983            }
7984            GrantObjects::FutureTablesInSchema { schemas } => {
7985                write!(
7986                    f,
7987                    "FUTURE TABLES IN SCHEMA {}",
7988                    display_comma_separated(schemas)
7989                )
7990            }
7991            GrantObjects::FutureExternalTablesInSchema { schemas } => {
7992                write!(
7993                    f,
7994                    "FUTURE EXTERNAL TABLES IN SCHEMA {}",
7995                    display_comma_separated(schemas)
7996                )
7997            }
7998            GrantObjects::FutureViewsInSchema { schemas } => {
7999                write!(
8000                    f,
8001                    "FUTURE VIEWS IN SCHEMA {}",
8002                    display_comma_separated(schemas)
8003                )
8004            }
8005            GrantObjects::FutureMaterializedViewsInSchema { schemas } => {
8006                write!(
8007                    f,
8008                    "FUTURE MATERIALIZED VIEWS IN SCHEMA {}",
8009                    display_comma_separated(schemas)
8010                )
8011            }
8012            GrantObjects::FutureSequencesInSchema { schemas } => {
8013                write!(
8014                    f,
8015                    "FUTURE SEQUENCES IN SCHEMA {}",
8016                    display_comma_separated(schemas)
8017                )
8018            }
8019            GrantObjects::ResourceMonitors(objects) => {
8020                write!(f, "RESOURCE MONITOR {}", display_comma_separated(objects))
8021            }
8022            GrantObjects::Users(objects) => {
8023                write!(f, "USER {}", display_comma_separated(objects))
8024            }
8025            GrantObjects::ComputePools(objects) => {
8026                write!(f, "COMPUTE POOL {}", display_comma_separated(objects))
8027            }
8028            GrantObjects::Connections(objects) => {
8029                write!(f, "CONNECTION {}", display_comma_separated(objects))
8030            }
8031            GrantObjects::FailoverGroup(objects) => {
8032                write!(f, "FAILOVER GROUP {}", display_comma_separated(objects))
8033            }
8034            GrantObjects::ReplicationGroup(objects) => {
8035                write!(f, "REPLICATION GROUP {}", display_comma_separated(objects))
8036            }
8037            GrantObjects::ExternalVolumes(objects) => {
8038                write!(f, "EXTERNAL VOLUME {}", display_comma_separated(objects))
8039            }
8040            GrantObjects::Procedure { name, arg_types } => {
8041                write!(f, "PROCEDURE {name}")?;
8042                if !arg_types.is_empty() {
8043                    write!(f, "({})", display_comma_separated(arg_types))?;
8044                }
8045                Ok(())
8046            }
8047            GrantObjects::Function { name, arg_types } => {
8048                write!(f, "FUNCTION {name}")?;
8049                if !arg_types.is_empty() {
8050                    write!(f, "({})", display_comma_separated(arg_types))?;
8051                }
8052                Ok(())
8053            }
8054            GrantObjects::Types(types) => {
8055                write!(f, "TYPE {}", display_comma_separated(types))
8056            }
8057            GrantObjects::Domains(domains) => {
8058                write!(f, "DOMAIN {}", display_comma_separated(domains))
8059            }
8060        }
8061    }
8062}
8063
8064/// A `DENY` statement
8065///
8066/// [MsSql](https://learn.microsoft.com/en-us/sql/t-sql/statements/deny-transact-sql)
8067#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8068#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8069#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8070pub struct DenyStatement {
8071    /// The privileges to deny.
8072    pub privileges: Privileges,
8073    /// The objects the privileges apply to.
8074    pub objects: GrantObjects,
8075    /// The grantees (users/roles) to whom the denial applies.
8076    pub grantees: Vec<Grantee>,
8077    /// Optional identifier of the principal that performed the grant.
8078    pub granted_by: Option<Ident>,
8079    /// Optional cascade option controlling dependent objects.
8080    pub cascade: Option<CascadeOption>,
8081}
8082
8083impl fmt::Display for DenyStatement {
8084    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8085        write!(f, "DENY {}", self.privileges)?;
8086        write!(f, " ON {}", self.objects)?;
8087        if !self.grantees.is_empty() {
8088            write!(f, " TO {}", display_comma_separated(&self.grantees))?;
8089        }
8090        if let Some(cascade) = &self.cascade {
8091            write!(f, " {cascade}")?;
8092        }
8093        if let Some(granted_by) = &self.granted_by {
8094            write!(f, " AS {granted_by}")?;
8095        }
8096        Ok(())
8097    }
8098}
8099
8100/// SQL assignment `foo = expr` as used in SQLUpdate
8101#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8102#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8103#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8104pub struct Assignment {
8105    /// The left-hand side of the assignment.
8106    pub target: AssignmentTarget,
8107    /// The expression assigned to the target.
8108    pub value: Expr,
8109}
8110
8111impl fmt::Display for Assignment {
8112    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8113        write!(f, "{} = {}", self.target, self.value)
8114    }
8115}
8116
8117/// Left-hand side of an assignment in an UPDATE statement,
8118/// e.g. `foo` in `foo = 5` (ColumnName assignment) or
8119/// `(a, b)` in `(a, b) = (1, 2)` (Tuple assignment).
8120#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8121#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8122#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8123pub enum AssignmentTarget {
8124    /// A single column
8125    ColumnName(ObjectName),
8126    /// A tuple of columns
8127    Tuple(Vec<ObjectName>),
8128}
8129
8130impl fmt::Display for AssignmentTarget {
8131    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8132        match self {
8133            AssignmentTarget::ColumnName(column) => write!(f, "{column}"),
8134            AssignmentTarget::Tuple(columns) => write!(f, "({})", display_comma_separated(columns)),
8135        }
8136    }
8137}
8138
8139#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8140#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8141#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8142/// Expression forms allowed as a function argument.
8143pub enum FunctionArgExpr {
8144    /// A normal expression argument.
8145    Expr(Expr),
8146    /// Qualified wildcard, e.g. `alias.*` or `schema.table.*`.
8147    QualifiedWildcard(ObjectName),
8148    /// An unqualified `*` wildcard.
8149    Wildcard,
8150    /// An unqualified `*` wildcard with additional options, e.g. `* EXCLUDE(col)`.
8151    ///
8152    /// Used in Snowflake to support expressions like `HASH(* EXCLUDE(col))`.
8153    WildcardWithOptions(WildcardAdditionalOptions),
8154}
8155
8156impl From<Expr> for FunctionArgExpr {
8157    fn from(wildcard_expr: Expr) -> Self {
8158        match wildcard_expr {
8159            Expr::QualifiedWildcard(prefix, _) => Self::QualifiedWildcard(prefix),
8160            Expr::Wildcard(_) => Self::Wildcard,
8161            expr => Self::Expr(expr),
8162        }
8163    }
8164}
8165
8166impl fmt::Display for FunctionArgExpr {
8167    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8168        match self {
8169            FunctionArgExpr::Expr(expr) => write!(f, "{expr}"),
8170            FunctionArgExpr::QualifiedWildcard(prefix) => write!(f, "{prefix}.*"),
8171            FunctionArgExpr::Wildcard => f.write_str("*"),
8172            FunctionArgExpr::WildcardWithOptions(opts) => write!(f, "*{opts}"),
8173        }
8174    }
8175}
8176
8177#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8178#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8179#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8180/// Operator used to separate function arguments
8181pub enum FunctionArgOperator {
8182    /// function(arg1 = value1)
8183    Equals,
8184    /// function(arg1 => value1)
8185    RightArrow,
8186    /// function(arg1 := value1)
8187    Assignment,
8188    /// function(arg1 : value1)
8189    Colon,
8190    /// function(arg1 VALUE value1)
8191    Value,
8192}
8193
8194impl fmt::Display for FunctionArgOperator {
8195    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8196        match self {
8197            FunctionArgOperator::Equals => f.write_str("="),
8198            FunctionArgOperator::RightArrow => f.write_str("=>"),
8199            FunctionArgOperator::Assignment => f.write_str(":="),
8200            FunctionArgOperator::Colon => f.write_str(":"),
8201            FunctionArgOperator::Value => f.write_str("VALUE"),
8202        }
8203    }
8204}
8205
8206#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8207#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8208#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8209/// Forms of function arguments (named, expression-named, or positional).
8210pub enum FunctionArg {
8211    /// `name` is identifier
8212    ///
8213    /// Enabled when `Dialect::supports_named_fn_args_with_expr_name` returns 'false'
8214    Named {
8215        /// The identifier name of the argument.
8216        name: Ident,
8217        /// The argument expression or wildcard form.
8218        arg: FunctionArgExpr,
8219        /// The operator separating name and value.
8220        operator: FunctionArgOperator,
8221    },
8222    /// `name` is arbitrary expression
8223    ///
8224    /// Enabled when `Dialect::supports_named_fn_args_with_expr_name` returns 'true'
8225    ExprNamed {
8226        /// The expression used as the argument name.
8227        name: Expr,
8228        /// The argument expression or wildcard form.
8229        arg: FunctionArgExpr,
8230        /// The operator separating name and value.
8231        operator: FunctionArgOperator,
8232    },
8233    /// An unnamed argument (positional), given by expression or wildcard.
8234    Unnamed(FunctionArgExpr),
8235}
8236
8237impl fmt::Display for FunctionArg {
8238    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8239        match self {
8240            FunctionArg::Named {
8241                name,
8242                arg,
8243                operator,
8244            } => write!(f, "{name} {operator} {arg}"),
8245            FunctionArg::ExprNamed {
8246                name,
8247                arg,
8248                operator,
8249            } => write!(f, "{name} {operator} {arg}"),
8250            FunctionArg::Unnamed(unnamed_arg) => write!(f, "{unnamed_arg}"),
8251        }
8252    }
8253}
8254
8255#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8256#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8257#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8258/// Which cursor(s) to close.
8259pub enum CloseCursor {
8260    /// Close all cursors.
8261    All,
8262    /// Close a specific cursor by name.
8263    Specific {
8264        /// The name of the cursor to close.
8265        name: Ident,
8266    },
8267}
8268
8269impl fmt::Display for CloseCursor {
8270    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8271        match self {
8272            CloseCursor::All => write!(f, "ALL"),
8273            CloseCursor::Specific { name } => write!(f, "{name}"),
8274        }
8275    }
8276}
8277
8278/// A Drop Domain statement
8279#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8280#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8281#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8282pub struct DropDomain {
8283    /// Whether to drop the domain if it exists
8284    pub if_exists: bool,
8285    /// The name of the domain to drop
8286    pub name: ObjectName,
8287    /// The behavior to apply when dropping the domain
8288    pub drop_behavior: Option<DropBehavior>,
8289}
8290
8291/// A constant of form `<data_type> 'value'`.
8292/// This can represent ANSI SQL `DATE`, `TIME`, and `TIMESTAMP` literals (such as `DATE '2020-01-01'`),
8293/// as well as constants of other types (a non-standard PostgreSQL extension).
8294#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8295#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8296#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8297pub struct TypedString {
8298    /// The data type of the typed string (e.g. DATE, TIME, TIMESTAMP).
8299    pub data_type: DataType,
8300    /// The value of the constant.
8301    /// Hint: you can unwrap the string value using `value.into_string()`.
8302    pub value: ValueWithSpan,
8303    /// Flags whether this TypedString uses the [ODBC syntax].
8304    ///
8305    /// Example:
8306    /// ```sql
8307    /// -- An ODBC date literal:
8308    /// SELECT {d '2025-07-16'}
8309    /// -- This is equivalent to the standard ANSI SQL literal:
8310    /// SELECT DATE '2025-07-16'
8311    ///
8312    /// [ODBC syntax]: https://learn.microsoft.com/en-us/sql/odbc/reference/develop-app/date-time-and-timestamp-literals?view=sql-server-2017
8313    pub uses_odbc_syntax: bool,
8314}
8315
8316impl fmt::Display for TypedString {
8317    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8318        let data_type = &self.data_type;
8319        let value = &self.value;
8320        match self.uses_odbc_syntax {
8321            false => {
8322                write!(f, "{data_type}")?;
8323                write!(f, " {value}")
8324            }
8325            true => {
8326                let prefix = match data_type {
8327                    DataType::Date => "d",
8328                    DataType::Time(..) => "t",
8329                    DataType::Timestamp(..) => "ts",
8330                    _ => "?",
8331                };
8332                write!(f, "{{{prefix} {value}}}")
8333            }
8334        }
8335    }
8336}
8337
8338/// A function call
8339#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8340#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8341#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8342pub struct Function {
8343    /// The function name (may be qualified).
8344    pub name: ObjectName,
8345    /// Flags whether this function call uses the [ODBC syntax].
8346    ///
8347    /// Example:
8348    /// ```sql
8349    /// SELECT {fn CONCAT('foo', 'bar')}
8350    /// ```
8351    ///
8352    /// [ODBC syntax]: https://learn.microsoft.com/en-us/sql/odbc/reference/develop-app/scalar-function-calls?view=sql-server-2017
8353    pub uses_odbc_syntax: bool,
8354    /// The parameters to the function, including any options specified within the
8355    /// delimiting parentheses.
8356    ///
8357    /// Example:
8358    /// ```plaintext
8359    /// HISTOGRAM(0.5, 0.6)(x, y)
8360    /// ```
8361    ///
8362    /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/aggregate-functions/parametric-functions)
8363    pub parameters: FunctionArguments,
8364    /// The arguments to the function, including any options specified within the
8365    /// delimiting parentheses.
8366    pub args: FunctionArguments,
8367    /// e.g. `x > 5` in `COUNT(x) FILTER (WHERE x > 5)`
8368    pub filter: Option<Box<Expr>>,
8369    /// Indicates how `NULL`s should be handled in the calculation.
8370    ///
8371    /// Example:
8372    /// ```plaintext
8373    /// FIRST_VALUE( <expr> ) [ { IGNORE | RESPECT } NULLS ] OVER ...
8374    /// ```
8375    ///
8376    /// [Snowflake](https://docs.snowflake.com/en/sql-reference/functions/first_value)
8377    pub null_treatment: Option<NullTreatment>,
8378    /// The `OVER` clause, indicating a window function call.
8379    pub over: Option<WindowType>,
8380    /// A clause used with certain aggregate functions to control the ordering
8381    /// within grouped sets before the function is applied.
8382    ///
8383    /// Syntax:
8384    /// ```plaintext
8385    /// <aggregate_function>(expression) WITHIN GROUP (ORDER BY key [ASC | DESC], ...)
8386    /// ```
8387    pub within_group: Vec<OrderByExpr>,
8388}
8389
8390impl fmt::Display for Function {
8391    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8392        if self.uses_odbc_syntax {
8393            write!(f, "{{fn ")?;
8394        }
8395
8396        write!(f, "{}{}{}", self.name, self.parameters, self.args)?;
8397
8398        if !self.within_group.is_empty() {
8399            write!(
8400                f,
8401                " WITHIN GROUP (ORDER BY {})",
8402                display_comma_separated(&self.within_group)
8403            )?;
8404        }
8405
8406        if let Some(filter_cond) = &self.filter {
8407            write!(f, " FILTER (WHERE {filter_cond})")?;
8408        }
8409
8410        if let Some(null_treatment) = &self.null_treatment {
8411            write!(f, " {null_treatment}")?;
8412        }
8413
8414        if let Some(o) = &self.over {
8415            f.write_str(" OVER ")?;
8416            o.fmt(f)?;
8417        }
8418
8419        if self.uses_odbc_syntax {
8420            write!(f, "}}")?;
8421        }
8422
8423        Ok(())
8424    }
8425}
8426
8427/// The arguments passed to a function call.
8428#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8429#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8430#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8431pub enum FunctionArguments {
8432    /// Used for special functions like `CURRENT_TIMESTAMP` that are invoked
8433    /// without parentheses.
8434    None,
8435    /// On some dialects, a subquery can be passed without surrounding
8436    /// parentheses if it's the sole argument to the function.
8437    Subquery(Box<Query>),
8438    /// A normal function argument list, including any clauses within it such as
8439    /// `DISTINCT` or `ORDER BY`.
8440    List(FunctionArgumentList),
8441}
8442
8443impl fmt::Display for FunctionArguments {
8444    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8445        match self {
8446            FunctionArguments::None => Ok(()),
8447            FunctionArguments::Subquery(query) => write!(f, "({query})"),
8448            FunctionArguments::List(args) => write!(f, "({args})"),
8449        }
8450    }
8451}
8452
8453/// This represents everything inside the parentheses when calling a function.
8454#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8455#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8456#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8457pub struct FunctionArgumentList {
8458    /// `[ ALL | DISTINCT ]`
8459    pub duplicate_treatment: Option<DuplicateTreatment>,
8460    /// The function arguments.
8461    pub args: Vec<FunctionArg>,
8462    /// Additional clauses specified within the argument list.
8463    pub clauses: Vec<FunctionArgumentClause>,
8464}
8465
8466impl fmt::Display for FunctionArgumentList {
8467    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8468        if let Some(duplicate_treatment) = self.duplicate_treatment {
8469            write!(f, "{duplicate_treatment} ")?;
8470        }
8471        write!(f, "{}", display_comma_separated(&self.args))?;
8472        if !self.clauses.is_empty() {
8473            if !self.args.is_empty() {
8474                write!(f, " ")?;
8475            }
8476            write!(f, "{}", display_separated(&self.clauses, " "))?;
8477        }
8478        Ok(())
8479    }
8480}
8481
8482#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8483#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8484#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8485/// Clauses that can appear inside a function argument list.
8486pub enum FunctionArgumentClause {
8487    /// Indicates how `NULL`s should be handled in the calculation, e.g. in `FIRST_VALUE` on [BigQuery].
8488    ///
8489    /// Syntax:
8490    /// ```plaintext
8491    /// { IGNORE | RESPECT } NULLS ]
8492    /// ```
8493    ///
8494    /// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/navigation_functions#first_value
8495    IgnoreOrRespectNulls(NullTreatment),
8496    /// Specifies the the ordering for some ordered set aggregates, e.g. `ARRAY_AGG` on [BigQuery].
8497    ///
8498    /// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/aggregate_functions#array_agg
8499    OrderBy(Vec<OrderByExpr>),
8500    /// Specifies a limit for the `ARRAY_AGG` and `ARRAY_CONCAT_AGG` functions on BigQuery.
8501    Limit(Expr),
8502    /// Specifies the behavior on overflow of the `LISTAGG` function.
8503    ///
8504    /// See <https://trino.io/docs/current/functions/aggregate.html>.
8505    OnOverflow(ListAggOnOverflow),
8506    /// Specifies a minimum or maximum bound on the input to [`ANY_VALUE`] on BigQuery.
8507    ///
8508    /// Syntax:
8509    /// ```plaintext
8510    /// HAVING { MAX | MIN } expression
8511    /// ```
8512    ///
8513    /// [`ANY_VALUE`]: https://cloud.google.com/bigquery/docs/reference/standard-sql/aggregate_functions#any_value
8514    Having(HavingBound),
8515    /// The `SEPARATOR` clause to the [`GROUP_CONCAT`] function in MySQL.
8516    ///
8517    /// [`GROUP_CONCAT`]: https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html#function_group-concat
8518    Separator(ValueWithSpan),
8519    /// The `ON NULL` clause for some JSON functions.
8520    ///
8521    /// [MSSQL `JSON_ARRAY`](https://learn.microsoft.com/en-us/sql/t-sql/functions/json-array-transact-sql?view=sql-server-ver16)
8522    /// [MSSQL `JSON_OBJECT`](https://learn.microsoft.com/en-us/sql/t-sql/functions/json-object-transact-sql?view=sql-server-ver16>)
8523    /// [PostgreSQL JSON functions](https://www.postgresql.org/docs/current/functions-json.html#FUNCTIONS-JSON-PROCESSING)
8524    JsonNullClause(JsonNullClause),
8525    /// The `RETURNING` clause for some JSON functions in PostgreSQL
8526    ///
8527    /// [`JSON_OBJECT`](https://www.postgresql.org/docs/current/functions-json.html#:~:text=json_object)
8528    JsonReturningClause(JsonReturningClause),
8529}
8530
8531impl fmt::Display for FunctionArgumentClause {
8532    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8533        match self {
8534            FunctionArgumentClause::IgnoreOrRespectNulls(null_treatment) => {
8535                write!(f, "{null_treatment}")
8536            }
8537            FunctionArgumentClause::OrderBy(order_by) => {
8538                write!(f, "ORDER BY {}", display_comma_separated(order_by))
8539            }
8540            FunctionArgumentClause::Limit(limit) => write!(f, "LIMIT {limit}"),
8541            FunctionArgumentClause::OnOverflow(on_overflow) => write!(f, "{on_overflow}"),
8542            FunctionArgumentClause::Having(bound) => write!(f, "{bound}"),
8543            FunctionArgumentClause::Separator(sep) => write!(f, "SEPARATOR {sep}"),
8544            FunctionArgumentClause::JsonNullClause(null_clause) => write!(f, "{null_clause}"),
8545            FunctionArgumentClause::JsonReturningClause(returning_clause) => {
8546                write!(f, "{returning_clause}")
8547            }
8548        }
8549    }
8550}
8551
8552/// A method call
8553#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8554#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8555#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8556pub struct Method {
8557    /// The expression on which the method is invoked.
8558    pub expr: Box<Expr>,
8559    // always non-empty
8560    /// The sequence of chained method calls.
8561    pub method_chain: Vec<Function>,
8562}
8563
8564impl fmt::Display for Method {
8565    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8566        write!(
8567            f,
8568            "{}.{}",
8569            self.expr,
8570            display_separated(&self.method_chain, ".")
8571        )
8572    }
8573}
8574
8575#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8576#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8577#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8578/// How duplicate values are treated inside function argument lists.
8579pub enum DuplicateTreatment {
8580    /// Consider only unique values.
8581    Distinct,
8582    /// Retain all duplicate values (the default).
8583    All,
8584}
8585
8586impl fmt::Display for DuplicateTreatment {
8587    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8588        match self {
8589            DuplicateTreatment::Distinct => write!(f, "DISTINCT"),
8590            DuplicateTreatment::All => write!(f, "ALL"),
8591        }
8592    }
8593}
8594
8595#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8596#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8597#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8598/// How the `ANALYZE`/`EXPLAIN ANALYZE` format is specified.
8599pub enum AnalyzeFormatKind {
8600    /// Format provided as a keyword, e.g. `FORMAT JSON`.
8601    Keyword(AnalyzeFormat),
8602    /// Format provided as an assignment, e.g. `FORMAT=JSON`.
8603    Assignment(AnalyzeFormat),
8604}
8605
8606impl fmt::Display for AnalyzeFormatKind {
8607    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
8608        match self {
8609            AnalyzeFormatKind::Keyword(format) => write!(f, "FORMAT {format}"),
8610            AnalyzeFormatKind::Assignment(format) => write!(f, "FORMAT={format}"),
8611        }
8612    }
8613}
8614
8615#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8616#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8617#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8618/// Output formats supported for `ANALYZE`/`EXPLAIN ANALYZE`.
8619pub enum AnalyzeFormat {
8620    /// Plain text format.
8621    TEXT,
8622    /// Graphviz DOT format.
8623    GRAPHVIZ,
8624    /// JSON format.
8625    JSON,
8626    /// Traditional explain output.
8627    TRADITIONAL,
8628    /// Tree-style explain output.
8629    TREE,
8630}
8631
8632impl fmt::Display for AnalyzeFormat {
8633    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
8634        f.write_str(match self {
8635            AnalyzeFormat::TEXT => "TEXT",
8636            AnalyzeFormat::GRAPHVIZ => "GRAPHVIZ",
8637            AnalyzeFormat::JSON => "JSON",
8638            AnalyzeFormat::TRADITIONAL => "TRADITIONAL",
8639            AnalyzeFormat::TREE => "TREE",
8640        })
8641    }
8642}
8643
8644/// External table's available file format
8645#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8646#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8647#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8648pub enum FileFormat {
8649    /// Text file format.
8650    TEXTFILE,
8651    /// Sequence file format.
8652    SEQUENCEFILE,
8653    /// ORC file format.
8654    ORC,
8655    /// Parquet file format.
8656    PARQUET,
8657    /// Avro file format.
8658    AVRO,
8659    /// RCFile format.
8660    RCFILE,
8661    /// JSON file format.
8662    JSONFILE,
8663}
8664
8665impl fmt::Display for FileFormat {
8666    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8667        use self::FileFormat::*;
8668        f.write_str(match self {
8669            TEXTFILE => "TEXTFILE",
8670            SEQUENCEFILE => "SEQUENCEFILE",
8671            ORC => "ORC",
8672            PARQUET => "PARQUET",
8673            AVRO => "AVRO",
8674            RCFILE => "RCFILE",
8675            JSONFILE => "JSONFILE",
8676        })
8677    }
8678}
8679
8680/// The `ON OVERFLOW` clause of a LISTAGG invocation
8681#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8682#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8683#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8684pub enum ListAggOnOverflow {
8685    /// `ON OVERFLOW ERROR`
8686    Error,
8687
8688    /// `ON OVERFLOW TRUNCATE [ <filler> ] WITH[OUT] COUNT`
8689    Truncate {
8690        /// Optional filler expression used when truncating.
8691        filler: Option<Box<Expr>>,
8692        /// Whether to include a count when truncating.
8693        with_count: bool,
8694    },
8695}
8696
8697impl fmt::Display for ListAggOnOverflow {
8698    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8699        write!(f, "ON OVERFLOW")?;
8700        match self {
8701            ListAggOnOverflow::Error => write!(f, " ERROR"),
8702            ListAggOnOverflow::Truncate { filler, with_count } => {
8703                write!(f, " TRUNCATE")?;
8704                if let Some(filler) = filler {
8705                    write!(f, " {filler}")?;
8706                }
8707                if *with_count {
8708                    write!(f, " WITH")?;
8709                } else {
8710                    write!(f, " WITHOUT")?;
8711                }
8712                write!(f, " COUNT")
8713            }
8714        }
8715    }
8716}
8717
8718/// The `HAVING` clause in a call to `ANY_VALUE` on BigQuery.
8719#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8720#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8721#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8722pub struct HavingBound(pub HavingBoundKind, pub Expr);
8723
8724impl fmt::Display for HavingBound {
8725    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8726        write!(f, "HAVING {} {}", self.0, self.1)
8727    }
8728}
8729
8730#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8731#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8732#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8733/// Which bound is used in a HAVING clause for ANY_VALUE on BigQuery.
8734pub enum HavingBoundKind {
8735    /// The minimum bound.
8736    Min,
8737    /// The maximum bound.
8738    Max,
8739}
8740
8741impl fmt::Display for HavingBoundKind {
8742    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8743        match self {
8744            HavingBoundKind::Min => write!(f, "MIN"),
8745            HavingBoundKind::Max => write!(f, "MAX"),
8746        }
8747    }
8748}
8749
8750#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8751#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8752#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8753/// Types of database objects referenced by DDL statements.
8754pub enum ObjectType {
8755    /// A collation.
8756    Collation,
8757    /// A table.
8758    Table,
8759    /// A view.
8760    View,
8761    /// A materialized view.
8762    MaterializedView,
8763    /// An index.
8764    Index,
8765    /// A schema.
8766    Schema,
8767    /// A database.
8768    Database,
8769    /// A role.
8770    Role,
8771    /// A sequence.
8772    Sequence,
8773    /// A stage.
8774    Stage,
8775    /// A type definition.
8776    Type,
8777    /// A user.
8778    User,
8779    /// A stream.
8780    Stream,
8781}
8782
8783impl fmt::Display for ObjectType {
8784    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8785        f.write_str(match self {
8786            ObjectType::Collation => "COLLATION",
8787            ObjectType::Table => "TABLE",
8788            ObjectType::View => "VIEW",
8789            ObjectType::MaterializedView => "MATERIALIZED VIEW",
8790            ObjectType::Index => "INDEX",
8791            ObjectType::Schema => "SCHEMA",
8792            ObjectType::Database => "DATABASE",
8793            ObjectType::Role => "ROLE",
8794            ObjectType::Sequence => "SEQUENCE",
8795            ObjectType::Stage => "STAGE",
8796            ObjectType::Type => "TYPE",
8797            ObjectType::User => "USER",
8798            ObjectType::Stream => "STREAM",
8799        })
8800    }
8801}
8802
8803#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8804#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8805#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8806/// Types supported by `KILL` statements.
8807pub enum KillType {
8808    /// Kill a connection.
8809    Connection,
8810    /// Kill a running query.
8811    Query,
8812    /// Kill a mutation (ClickHouse).
8813    Mutation,
8814}
8815
8816impl fmt::Display for KillType {
8817    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8818        f.write_str(match self {
8819            // MySQL
8820            KillType::Connection => "CONNECTION",
8821            KillType::Query => "QUERY",
8822            // Clickhouse supports Mutation
8823            KillType::Mutation => "MUTATION",
8824        })
8825    }
8826}
8827
8828#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8829#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8830#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8831/// Distribution style options for Hive tables.
8832pub enum HiveDistributionStyle {
8833    /// Partitioned distribution with the given columns.
8834    PARTITIONED {
8835        /// Columns used for partitioning.
8836        columns: Vec<ColumnDef>,
8837    },
8838    /// Skewed distribution definition.
8839    SKEWED {
8840        /// Columns participating in the skew definition.
8841        columns: Vec<ColumnDef>,
8842        /// Columns listed in the `ON` clause for skewing.
8843        on: Vec<ColumnDef>,
8844        /// Whether skewed data is stored as directories.
8845        stored_as_directories: bool,
8846    },
8847    /// No distribution style specified.
8848    NONE,
8849}
8850
8851#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8852#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8853#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8854/// Row format specification for Hive tables (SERDE or DELIMITED).
8855pub enum HiveRowFormat {
8856    /// SerDe class specification with the implementing class name.
8857    SERDE {
8858        /// The SerDe implementation class name.
8859        class: String,
8860    },
8861    /// Delimited row format with one or more delimiter specifications.
8862    DELIMITED {
8863        /// The list of delimiters used for delimiting fields/lines.
8864        delimiters: Vec<HiveRowDelimiter>,
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/// Format specification for `LOAD DATA` Hive operations.
8872pub struct HiveLoadDataFormat {
8873    /// SerDe expression used for the table.
8874    pub serde: Expr,
8875    /// Input format expression.
8876    pub input_format: Expr,
8877}
8878
8879#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8880#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8881#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8882/// A single row delimiter specification for Hive `ROW FORMAT`.
8883pub struct HiveRowDelimiter {
8884    /// The delimiter kind (fields/lines/etc.).
8885    pub delimiter: HiveDelimiter,
8886    /// The delimiter character identifier.
8887    pub char: Ident,
8888}
8889
8890impl fmt::Display for HiveRowDelimiter {
8891    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8892        write!(f, "{} ", self.delimiter)?;
8893        write!(f, "{}", self.char)
8894    }
8895}
8896
8897#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8898#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8899#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8900/// Kind of delimiter used in Hive `ROW FORMAT` definitions.
8901pub enum HiveDelimiter {
8902    /// Fields terminated by a delimiter.
8903    FieldsTerminatedBy,
8904    /// Fields escaped by a character.
8905    FieldsEscapedBy,
8906    /// Collection items terminated by a delimiter.
8907    CollectionItemsTerminatedBy,
8908    /// Map keys terminated by a delimiter.
8909    MapKeysTerminatedBy,
8910    /// Lines terminated by a delimiter.
8911    LinesTerminatedBy,
8912    /// Null represented by a specific token.
8913    NullDefinedAs,
8914}
8915
8916impl fmt::Display for HiveDelimiter {
8917    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8918        use HiveDelimiter::*;
8919        f.write_str(match self {
8920            FieldsTerminatedBy => "FIELDS TERMINATED BY",
8921            FieldsEscapedBy => "ESCAPED BY",
8922            CollectionItemsTerminatedBy => "COLLECTION ITEMS TERMINATED BY",
8923            MapKeysTerminatedBy => "MAP KEYS TERMINATED BY",
8924            LinesTerminatedBy => "LINES TERMINATED BY",
8925            NullDefinedAs => "NULL DEFINED AS",
8926        })
8927    }
8928}
8929
8930#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8931#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8932#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8933/// Describe output format options for Hive `DESCRIBE`/`EXPLAIN`.
8934pub enum HiveDescribeFormat {
8935    /// Extended describe output.
8936    Extended,
8937    /// Formatted describe output.
8938    Formatted,
8939}
8940
8941impl fmt::Display for HiveDescribeFormat {
8942    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8943        use HiveDescribeFormat::*;
8944        f.write_str(match self {
8945            Extended => "EXTENDED",
8946            Formatted => "FORMATTED",
8947        })
8948    }
8949}
8950
8951#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8952#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8953#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8954/// Aliases accepted for describe-style commands.
8955pub enum DescribeAlias {
8956    /// `DESCRIBE` alias.
8957    Describe,
8958    /// `EXPLAIN` alias.
8959    Explain,
8960    /// `DESC` alias.
8961    Desc,
8962}
8963
8964impl fmt::Display for DescribeAlias {
8965    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8966        use DescribeAlias::*;
8967        f.write_str(match self {
8968            Describe => "DESCRIBE",
8969            Explain => "EXPLAIN",
8970            Desc => "DESC",
8971        })
8972    }
8973}
8974
8975#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8976#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8977#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8978#[allow(clippy::large_enum_variant)]
8979/// Hive input/output format specification used in `CREATE TABLE`.
8980pub enum HiveIOFormat {
8981    /// Generic IO format with separate input and output expressions.
8982    IOF {
8983        /// Expression for the input format.
8984        input_format: Expr,
8985        /// Expression for the output format.
8986        output_format: Expr,
8987    },
8988    /// File format wrapper referencing a `FileFormat` variant.
8989    FileFormat {
8990        /// The file format used for storage.
8991        format: FileFormat,
8992    },
8993}
8994
8995#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Default)]
8996#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8997#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8998/// Hive table format and storage-related options.
8999pub struct HiveFormat {
9000    /// Optional row format specification.
9001    pub row_format: Option<HiveRowFormat>,
9002    /// Optional SerDe properties expressed as SQL options.
9003    pub serde_properties: Option<Vec<SqlOption>>,
9004    /// Optional input/output storage format details.
9005    pub storage: Option<HiveIOFormat>,
9006    /// Optional location (URI or path) for table data.
9007    pub location: Option<String>,
9008}
9009
9010#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9011#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9012#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9013/// A clustered index column specification.
9014pub struct ClusteredIndex {
9015    /// Column identifier for the clustered index entry.
9016    pub name: Ident,
9017    /// Optional sort direction: `Some(true)` for ASC, `Some(false)` for DESC, `None` for unspecified.
9018    pub asc: Option<bool>,
9019}
9020
9021impl fmt::Display for ClusteredIndex {
9022    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9023        write!(f, "{}", self.name)?;
9024        match self.asc {
9025            Some(true) => write!(f, " ASC"),
9026            Some(false) => write!(f, " DESC"),
9027            _ => Ok(()),
9028        }
9029    }
9030}
9031
9032#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9033#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9034#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9035/// Clustered options used for `CREATE TABLE` clustered/indexed storage.
9036pub enum TableOptionsClustered {
9037    /// Use a columnstore index.
9038    ColumnstoreIndex,
9039    /// Columnstore index with an explicit ordering of columns.
9040    ColumnstoreIndexOrder(Vec<Ident>),
9041    /// A named clustered index with one or more columns.
9042    Index(Vec<ClusteredIndex>),
9043}
9044
9045impl fmt::Display for TableOptionsClustered {
9046    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9047        match self {
9048            TableOptionsClustered::ColumnstoreIndex => {
9049                write!(f, "CLUSTERED COLUMNSTORE INDEX")
9050            }
9051            TableOptionsClustered::ColumnstoreIndexOrder(values) => {
9052                write!(
9053                    f,
9054                    "CLUSTERED COLUMNSTORE INDEX ORDER ({})",
9055                    display_comma_separated(values)
9056                )
9057            }
9058            TableOptionsClustered::Index(values) => {
9059                write!(f, "CLUSTERED INDEX ({})", display_comma_separated(values))
9060            }
9061        }
9062    }
9063}
9064
9065/// Specifies which partition the boundary values on table partitioning belongs to.
9066#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash)]
9067#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9068#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9069pub enum PartitionRangeDirection {
9070    /// LEFT range direction.
9071    Left,
9072    /// RIGHT range direction.
9073    Right,
9074}
9075
9076#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9077#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9078#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9079/// SQL option syntax used in table and server definitions.
9080pub enum SqlOption {
9081    /// Clustered represents the clustered version of table storage for MSSQL.
9082    ///
9083    /// <https://learn.microsoft.com/en-us/sql/t-sql/statements/create-table-azure-sql-data-warehouse?view=aps-pdw-2016-au7#TableOptions>
9084    Clustered(TableOptionsClustered),
9085    /// Single identifier options, e.g. `HEAP` for MSSQL.
9086    ///
9087    /// <https://learn.microsoft.com/en-us/sql/t-sql/statements/create-table-azure-sql-data-warehouse?view=aps-pdw-2016-au7#TableOptions>
9088    Ident(Ident),
9089    /// Any option that consists of a key value pair where the value is an expression. e.g.
9090    ///
9091    ///   WITH(DISTRIBUTION = ROUND_ROBIN)
9092    KeyValue {
9093        /// The option key identifier.
9094        key: Ident,
9095        /// The expression value for the option.
9096        value: Expr,
9097    },
9098    /// One or more table partitions and represents which partition the boundary values belong to,
9099    /// e.g.
9100    ///
9101    ///   PARTITION (id RANGE LEFT FOR VALUES (10, 20, 30, 40))
9102    ///
9103    /// <https://learn.microsoft.com/en-us/sql/t-sql/statements/create-table-azure-sql-data-warehouse?view=aps-pdw-2016-au7#TablePartitionOptions>
9104    Partition {
9105        /// The partition column name.
9106        column_name: Ident,
9107        /// Optional direction for the partition range (LEFT/RIGHT).
9108        range_direction: Option<PartitionRangeDirection>,
9109        /// Values that define the partition boundaries.
9110        for_values: Vec<Expr>,
9111    },
9112    /// Comment parameter (supports `=` and no `=` syntax)
9113    Comment(CommentDef),
9114    /// MySQL TableSpace option
9115    /// <https://dev.mysql.com/doc/refman/8.4/en/create-table.html>
9116    TableSpace(TablespaceOption),
9117    /// An option representing a key value pair, where the value is a parenthesized list and with an optional name
9118    /// e.g.
9119    ///
9120    ///   UNION  = (tbl_name\[,tbl_name\]...) <https://dev.mysql.com/doc/refman/8.4/en/create-table.html>
9121    ///   ENGINE = ReplicatedMergeTree('/table_name','{replica}', ver) <https://clickhouse.com/docs/engines/table-engines/mergetree-family/replication>
9122    ///   ENGINE = SummingMergeTree(\[columns\]) <https://clickhouse.com/docs/engines/table-engines/mergetree-family/summingmergetree>
9123    NamedParenthesizedList(NamedParenthesizedList),
9124}
9125
9126impl fmt::Display for SqlOption {
9127    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9128        match self {
9129            SqlOption::Clustered(c) => write!(f, "{c}"),
9130            SqlOption::Ident(ident) => {
9131                write!(f, "{ident}")
9132            }
9133            SqlOption::KeyValue { key: name, value } => {
9134                write!(f, "{name} = {value}")
9135            }
9136            SqlOption::Partition {
9137                column_name,
9138                range_direction,
9139                for_values,
9140            } => {
9141                let direction = match range_direction {
9142                    Some(PartitionRangeDirection::Left) => " LEFT",
9143                    Some(PartitionRangeDirection::Right) => " RIGHT",
9144                    None => "",
9145                };
9146
9147                write!(
9148                    f,
9149                    "PARTITION ({} RANGE{} FOR VALUES ({}))",
9150                    column_name,
9151                    direction,
9152                    display_comma_separated(for_values)
9153                )
9154            }
9155            SqlOption::TableSpace(tablespace_option) => {
9156                write!(f, "TABLESPACE {}", tablespace_option.name)?;
9157                match tablespace_option.storage {
9158                    Some(StorageType::Disk) => write!(f, " STORAGE DISK"),
9159                    Some(StorageType::Memory) => write!(f, " STORAGE MEMORY"),
9160                    None => Ok(()),
9161                }
9162            }
9163            SqlOption::Comment(comment) => match comment {
9164                CommentDef::WithEq(comment) => {
9165                    write!(f, "COMMENT = '{comment}'")
9166                }
9167                CommentDef::WithoutEq(comment) => {
9168                    write!(f, "COMMENT '{comment}'")
9169                }
9170            },
9171            SqlOption::NamedParenthesizedList(value) => {
9172                write!(f, "{} = ", value.key)?;
9173                if let Some(key) = &value.name {
9174                    write!(f, "{key}")?;
9175                }
9176                if !value.values.is_empty() {
9177                    write!(f, "({})", display_comma_separated(&value.values))?
9178                }
9179                Ok(())
9180            }
9181        }
9182    }
9183}
9184
9185#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
9186#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9187#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9188/// Storage type options for a tablespace.
9189pub enum StorageType {
9190    /// Store on disk.
9191    Disk,
9192    /// Store in memory.
9193    Memory,
9194}
9195
9196#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
9197#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9198#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9199/// MySql TableSpace option
9200/// <https://dev.mysql.com/doc/refman/8.4/en/create-table.html>
9201pub struct TablespaceOption {
9202    /// Name of the tablespace.
9203    pub name: String,
9204    /// Optional storage type for the tablespace.
9205    pub storage: Option<StorageType>,
9206}
9207
9208#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9209#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9210#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9211/// A key/value identifier pair used for secret or key-based options.
9212pub struct SecretOption {
9213    /// The option key identifier.
9214    pub key: Ident,
9215    /// The option value identifier.
9216    pub value: Ident,
9217}
9218
9219impl fmt::Display for SecretOption {
9220    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9221        write!(f, "{} {}", self.key, self.value)
9222    }
9223}
9224
9225/// A `CREATE SERVER` statement.
9226///
9227/// [PostgreSQL Documentation](https://www.postgresql.org/docs/current/sql-createserver.html)
9228#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9229#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9230#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9231pub struct CreateServerStatement {
9232    /// The server name.
9233    pub name: ObjectName,
9234    /// Whether `IF NOT EXISTS` was specified.
9235    pub if_not_exists: bool,
9236    /// Optional server type identifier.
9237    pub server_type: Option<Ident>,
9238    /// Optional server version identifier.
9239    pub version: Option<Ident>,
9240    /// Foreign-data wrapper object name.
9241    pub foreign_data_wrapper: ObjectName,
9242    /// Optional list of server options.
9243    pub options: Option<Vec<CreateServerOption>>,
9244}
9245
9246impl fmt::Display for CreateServerStatement {
9247    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
9248        let CreateServerStatement {
9249            name,
9250            if_not_exists,
9251            server_type,
9252            version,
9253            foreign_data_wrapper,
9254            options,
9255        } = self;
9256
9257        write!(
9258            f,
9259            "CREATE SERVER {if_not_exists}{name} ",
9260            if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
9261        )?;
9262
9263        if let Some(st) = server_type {
9264            write!(f, "TYPE {st} ")?;
9265        }
9266
9267        if let Some(v) = version {
9268            write!(f, "VERSION {v} ")?;
9269        }
9270
9271        write!(f, "FOREIGN DATA WRAPPER {foreign_data_wrapper}")?;
9272
9273        if let Some(o) = options {
9274            write!(f, " OPTIONS ({o})", o = display_comma_separated(o))?;
9275        }
9276
9277        Ok(())
9278    }
9279}
9280
9281/// A key/value option for `CREATE SERVER`.
9282#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9283#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9284#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9285pub struct CreateServerOption {
9286    /// Option key identifier.
9287    pub key: Ident,
9288    /// Option value identifier.
9289    pub value: Ident,
9290}
9291
9292impl fmt::Display for CreateServerOption {
9293    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9294        write!(f, "{} {}", self.key, self.value)
9295    }
9296}
9297
9298#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9299#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9300#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9301/// Options supported by DuckDB for `ATTACH DATABASE`.
9302pub enum AttachDuckDBDatabaseOption {
9303    /// READ_ONLY option, optional boolean value.
9304    ReadOnly(Option<bool>),
9305    /// TYPE option specifying a database type identifier.
9306    Type(Ident),
9307}
9308
9309impl fmt::Display for AttachDuckDBDatabaseOption {
9310    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9311        match self {
9312            AttachDuckDBDatabaseOption::ReadOnly(Some(true)) => write!(f, "READ_ONLY true"),
9313            AttachDuckDBDatabaseOption::ReadOnly(Some(false)) => write!(f, "READ_ONLY false"),
9314            AttachDuckDBDatabaseOption::ReadOnly(None) => write!(f, "READ_ONLY"),
9315            AttachDuckDBDatabaseOption::Type(t) => write!(f, "TYPE {t}"),
9316        }
9317    }
9318}
9319
9320#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9321#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9322#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9323/// Mode for transactions: access mode or isolation level.
9324pub enum TransactionMode {
9325    /// Access mode for a transaction (e.g. `READ ONLY` / `READ WRITE`).
9326    AccessMode(TransactionAccessMode),
9327    /// Isolation level for a transaction (e.g. `SERIALIZABLE`).
9328    IsolationLevel(TransactionIsolationLevel),
9329}
9330
9331impl fmt::Display for TransactionMode {
9332    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9333        use TransactionMode::*;
9334        match self {
9335            AccessMode(access_mode) => write!(f, "{access_mode}"),
9336            IsolationLevel(iso_level) => write!(f, "ISOLATION LEVEL {iso_level}"),
9337        }
9338    }
9339}
9340
9341#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9342#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9343#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9344/// Transaction access mode (READ ONLY / READ WRITE).
9345pub enum TransactionAccessMode {
9346    /// READ ONLY access mode.
9347    ReadOnly,
9348    /// READ WRITE access mode.
9349    ReadWrite,
9350}
9351
9352impl fmt::Display for TransactionAccessMode {
9353    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9354        use TransactionAccessMode::*;
9355        f.write_str(match self {
9356            ReadOnly => "READ ONLY",
9357            ReadWrite => "READ WRITE",
9358        })
9359    }
9360}
9361
9362#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9363#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9364#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9365/// Transaction isolation levels.
9366pub enum TransactionIsolationLevel {
9367    /// READ UNCOMMITTED isolation level.
9368    ReadUncommitted,
9369    /// READ COMMITTED isolation level.
9370    ReadCommitted,
9371    /// REPEATABLE READ isolation level.
9372    RepeatableRead,
9373    /// SERIALIZABLE isolation level.
9374    Serializable,
9375    /// SNAPSHOT isolation level.
9376    Snapshot,
9377}
9378
9379impl fmt::Display for TransactionIsolationLevel {
9380    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9381        use TransactionIsolationLevel::*;
9382        f.write_str(match self {
9383            ReadUncommitted => "READ UNCOMMITTED",
9384            ReadCommitted => "READ COMMITTED",
9385            RepeatableRead => "REPEATABLE READ",
9386            Serializable => "SERIALIZABLE",
9387            Snapshot => "SNAPSHOT",
9388        })
9389    }
9390}
9391
9392/// Modifier for the transaction in the `BEGIN` syntax
9393///
9394/// SQLite: <https://sqlite.org/lang_transaction.html>
9395/// MS-SQL: <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/try-catch-transact-sql>
9396#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9397#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9398#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9399pub enum TransactionModifier {
9400    /// DEFERRED transaction modifier.
9401    Deferred,
9402    /// IMMEDIATE transaction modifier.
9403    Immediate,
9404    /// EXCLUSIVE transaction modifier.
9405    Exclusive,
9406    /// TRY block modifier (MS-SQL style TRY/CATCH).
9407    Try,
9408    /// CATCH block modifier (MS-SQL style TRY/CATCH).
9409    Catch,
9410}
9411
9412impl fmt::Display for TransactionModifier {
9413    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9414        use TransactionModifier::*;
9415        f.write_str(match self {
9416            Deferred => "DEFERRED",
9417            Immediate => "IMMEDIATE",
9418            Exclusive => "EXCLUSIVE",
9419            Try => "TRY",
9420            Catch => "CATCH",
9421        })
9422    }
9423}
9424
9425#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9426#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9427#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9428/// Filter forms usable in SHOW statements.
9429pub enum ShowStatementFilter {
9430    /// Filter using LIKE pattern.
9431    Like(String),
9432    /// Filter using ILIKE pattern.
9433    ILike(String),
9434    /// Filter using a WHERE expression.
9435    Where(Expr),
9436    /// Filter provided without a keyword (raw string).
9437    NoKeyword(String),
9438}
9439
9440impl fmt::Display for ShowStatementFilter {
9441    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9442        use ShowStatementFilter::*;
9443        match self {
9444            Like(pattern) => write!(f, "LIKE '{}'", value::escape_single_quote_string(pattern)),
9445            ILike(pattern) => write!(f, "ILIKE {}", value::escape_single_quote_string(pattern)),
9446            Where(expr) => write!(f, "WHERE {expr}"),
9447            NoKeyword(pattern) => write!(f, "'{}'", value::escape_single_quote_string(pattern)),
9448        }
9449    }
9450}
9451
9452#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9453#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9454#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9455/// Clause types used with SHOW ... IN/FROM.
9456pub enum ShowStatementInClause {
9457    /// Use the `IN` clause.
9458    IN,
9459    /// Use the `FROM` clause.
9460    FROM,
9461}
9462
9463impl fmt::Display for ShowStatementInClause {
9464    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9465        use ShowStatementInClause::*;
9466        match self {
9467            FROM => write!(f, "FROM"),
9468            IN => write!(f, "IN"),
9469        }
9470    }
9471}
9472
9473/// Sqlite specific syntax
9474///
9475/// See [Sqlite documentation](https://sqlite.org/lang_conflict.html)
9476/// for more details.
9477#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9478#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9479#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9480pub enum SqliteOnConflict {
9481    /// Use ROLLBACK on conflict.
9482    Rollback,
9483    /// Use ABORT on conflict.
9484    Abort,
9485    /// Use FAIL on conflict.
9486    Fail,
9487    /// Use IGNORE on conflict.
9488    Ignore,
9489    /// Use REPLACE on conflict.
9490    Replace,
9491}
9492
9493impl fmt::Display for SqliteOnConflict {
9494    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9495        use SqliteOnConflict::*;
9496        match self {
9497            Rollback => write!(f, "OR ROLLBACK"),
9498            Abort => write!(f, "OR ABORT"),
9499            Fail => write!(f, "OR FAIL"),
9500            Ignore => write!(f, "OR IGNORE"),
9501            Replace => write!(f, "OR REPLACE"),
9502        }
9503    }
9504}
9505
9506/// Mysql specific syntax
9507///
9508/// See [Mysql documentation](https://dev.mysql.com/doc/refman/8.0/en/replace.html)
9509/// See [Mysql documentation](https://dev.mysql.com/doc/refman/8.0/en/insert.html)
9510/// for more details.
9511#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9512#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9513#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9514pub enum MysqlInsertPriority {
9515    /// LOW_PRIORITY modifier for INSERT/REPLACE.
9516    LowPriority,
9517    /// DELAYED modifier for INSERT/REPLACE.
9518    Delayed,
9519    /// HIGH_PRIORITY modifier for INSERT/REPLACE.
9520    HighPriority,
9521}
9522
9523impl fmt::Display for crate::ast::MysqlInsertPriority {
9524    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9525        use MysqlInsertPriority::*;
9526        match self {
9527            LowPriority => write!(f, "LOW_PRIORITY"),
9528            Delayed => write!(f, "DELAYED"),
9529            HighPriority => write!(f, "HIGH_PRIORITY"),
9530        }
9531    }
9532}
9533
9534#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9535#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9536#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9537/// Source for the `COPY` command: a table or a query.
9538pub enum CopySource {
9539    /// Copy from a table with optional column list.
9540    Table {
9541        /// The name of the table to copy from.
9542        table_name: ObjectName,
9543        /// A list of column names to copy. Empty list means that all columns
9544        /// are copied.
9545        columns: Vec<Ident>,
9546    },
9547    /// Copy from the results of a query.
9548    Query(Box<Query>),
9549}
9550
9551#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9552#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9553#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9554/// Target for the `COPY` command: STDIN, STDOUT, a file, or a program.
9555pub enum CopyTarget {
9556    /// Use standard input as the source.
9557    Stdin,
9558    /// Use standard output as the target.
9559    Stdout,
9560    /// Read from or write to a file.
9561    File {
9562        /// The path name of the input or output file.
9563        filename: String,
9564    },
9565    /// Use a program as the source or target (shell command).
9566    Program {
9567        /// A command to execute
9568        command: String,
9569    },
9570}
9571
9572impl fmt::Display for CopyTarget {
9573    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9574        use CopyTarget::*;
9575        match self {
9576            Stdin => write!(f, "STDIN"),
9577            Stdout => write!(f, "STDOUT"),
9578            File { filename } => write!(f, "'{}'", value::escape_single_quote_string(filename)),
9579            Program { command } => write!(
9580                f,
9581                "PROGRAM '{}'",
9582                value::escape_single_quote_string(command)
9583            ),
9584        }
9585    }
9586}
9587
9588#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9589#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9590#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9591/// Action to take `ON COMMIT` for temporary tables.
9592pub enum OnCommit {
9593    /// Delete rows on commit.
9594    DeleteRows,
9595    /// Preserve rows on commit.
9596    PreserveRows,
9597    /// Drop the table on commit.
9598    Drop,
9599}
9600
9601/// An option in `COPY` statement.
9602///
9603/// <https://www.postgresql.org/docs/14/sql-copy.html>
9604#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9605#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9606#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9607pub enum CopyOption {
9608    /// FORMAT format_name
9609    Format(Ident),
9610    /// FREEZE \[ boolean \]
9611    Freeze(bool),
9612    /// DELIMITER 'delimiter_character'
9613    Delimiter(char),
9614    /// NULL 'null_string'
9615    Null(String),
9616    /// HEADER \[ boolean \]
9617    Header(bool),
9618    /// QUOTE 'quote_character'
9619    Quote(char),
9620    /// ESCAPE 'escape_character'
9621    Escape(char),
9622    /// FORCE_QUOTE { ( column_name [, ...] ) | * }
9623    ForceQuote(Vec<Ident>),
9624    /// FORCE_NOT_NULL ( column_name [, ...] )
9625    ForceNotNull(Vec<Ident>),
9626    /// FORCE_NULL ( column_name [, ...] )
9627    ForceNull(Vec<Ident>),
9628    /// ENCODING 'encoding_name'
9629    Encoding(String),
9630}
9631
9632impl fmt::Display for CopyOption {
9633    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9634        use CopyOption::*;
9635        match self {
9636            Format(name) => write!(f, "FORMAT {name}"),
9637            Freeze(true) => write!(f, "FREEZE"),
9638            Freeze(false) => write!(f, "FREEZE FALSE"),
9639            Delimiter(char) => write!(f, "DELIMITER '{char}'"),
9640            Null(string) => write!(f, "NULL '{}'", value::escape_single_quote_string(string)),
9641            Header(true) => write!(f, "HEADER"),
9642            Header(false) => write!(f, "HEADER FALSE"),
9643            Quote(char) => write!(f, "QUOTE '{char}'"),
9644            Escape(char) => write!(f, "ESCAPE '{char}'"),
9645            ForceQuote(columns) => write!(f, "FORCE_QUOTE ({})", display_comma_separated(columns)),
9646            ForceNotNull(columns) => {
9647                write!(f, "FORCE_NOT_NULL ({})", display_comma_separated(columns))
9648            }
9649            ForceNull(columns) => write!(f, "FORCE_NULL ({})", display_comma_separated(columns)),
9650            Encoding(name) => write!(f, "ENCODING '{}'", value::escape_single_quote_string(name)),
9651        }
9652    }
9653}
9654
9655/// An option in `COPY` statement before PostgreSQL version 9.0.
9656///
9657/// [PostgreSQL](https://www.postgresql.org/docs/8.4/sql-copy.html)
9658/// [Redshift](https://docs.aws.amazon.com/redshift/latest/dg/r_COPY-alphabetical-parm-list.html)
9659#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9660#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9661#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9662pub enum CopyLegacyOption {
9663    /// ACCEPTANYDATE
9664    AcceptAnyDate,
9665    /// ACCEPTINVCHARS
9666    AcceptInvChars(Option<String>),
9667    /// ADDQUOTES
9668    AddQuotes,
9669    /// ALLOWOVERWRITE
9670    AllowOverwrite,
9671    /// BINARY
9672    Binary,
9673    /// BLANKSASNULL
9674    BlankAsNull,
9675    /// BZIP2
9676    Bzip2,
9677    /// CLEANPATH
9678    CleanPath,
9679    /// COMPUPDATE [ PRESET | { ON | TRUE } | { OFF | FALSE } ]
9680    CompUpdate {
9681        /// Whether the COMPUPDATE PRESET option was used.
9682        preset: bool,
9683        /// Optional enabled flag for COMPUPDATE.
9684        enabled: Option<bool>,
9685    },
9686    /// CSV ...
9687    Csv(Vec<CopyLegacyCsvOption>),
9688    /// DATEFORMAT \[ AS \] {'dateformat_string' | 'auto' }
9689    DateFormat(Option<String>),
9690    /// DELIMITER \[ AS \] 'delimiter_character'
9691    Delimiter(char),
9692    /// EMPTYASNULL
9693    EmptyAsNull,
9694    /// `ENCRYPTED \[ AUTO \]`
9695    Encrypted {
9696        /// Whether `AUTO` was specified for encryption.
9697        auto: bool,
9698    },
9699    /// ESCAPE
9700    Escape,
9701    /// EXTENSION 'extension-name'
9702    Extension(String),
9703    /// FIXEDWIDTH \[ AS \] 'fixedwidth-spec'
9704    FixedWidth(String),
9705    /// GZIP
9706    Gzip,
9707    /// HEADER
9708    Header,
9709    /// IAM_ROLE { DEFAULT | 'arn:aws:iam::123456789:role/role1' }
9710    IamRole(IamRoleKind),
9711    /// IGNOREHEADER \[ AS \] number_rows
9712    IgnoreHeader(u64),
9713    /// JSON \[ AS \] 'json_option'
9714    Json(Option<String>),
9715    /// MANIFEST \[ VERBOSE \]
9716    Manifest {
9717        /// Whether the MANIFEST is verbose.
9718        verbose: bool,
9719    },
9720    /// MAXFILESIZE \[ AS \] max-size \[ MB | GB \]
9721    MaxFileSize(FileSize),
9722    /// `NULL \[ AS \] 'null_string'`
9723    Null(String),
9724    /// `PARALLEL [ { ON | TRUE } | { OFF | FALSE } ]`
9725    Parallel(Option<bool>),
9726    /// PARQUET
9727    Parquet,
9728    /// PARTITION BY ( column_name [, ... ] ) \[ INCLUDE \]
9729    PartitionBy(UnloadPartitionBy),
9730    /// REGION \[ AS \] 'aws-region' }
9731    Region(String),
9732    /// REMOVEQUOTES
9733    RemoveQuotes,
9734    /// ROWGROUPSIZE \[ AS \] size \[ MB | GB \]
9735    RowGroupSize(FileSize),
9736    /// STATUPDATE [ { ON | TRUE } | { OFF | FALSE } ]
9737    StatUpdate(Option<bool>),
9738    /// TIMEFORMAT \[ AS \] {'timeformat_string' | 'auto' | 'epochsecs' | 'epochmillisecs' }
9739    TimeFormat(Option<String>),
9740    /// TRUNCATECOLUMNS
9741    TruncateColumns,
9742    /// ZSTD
9743    Zstd,
9744    /// Redshift `CREDENTIALS 'auth-args'`
9745    /// <https://docs.aws.amazon.com/redshift/latest/dg/copy-parameters-authorization.html>
9746    Credentials(String),
9747}
9748
9749impl fmt::Display for CopyLegacyOption {
9750    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9751        use CopyLegacyOption::*;
9752        match self {
9753            AcceptAnyDate => write!(f, "ACCEPTANYDATE"),
9754            AcceptInvChars(ch) => {
9755                write!(f, "ACCEPTINVCHARS")?;
9756                if let Some(ch) = ch {
9757                    write!(f, " '{}'", value::escape_single_quote_string(ch))?;
9758                }
9759                Ok(())
9760            }
9761            AddQuotes => write!(f, "ADDQUOTES"),
9762            AllowOverwrite => write!(f, "ALLOWOVERWRITE"),
9763            Binary => write!(f, "BINARY"),
9764            BlankAsNull => write!(f, "BLANKSASNULL"),
9765            Bzip2 => write!(f, "BZIP2"),
9766            CleanPath => write!(f, "CLEANPATH"),
9767            CompUpdate { preset, enabled } => {
9768                write!(f, "COMPUPDATE")?;
9769                if *preset {
9770                    write!(f, " PRESET")?;
9771                } else if let Some(enabled) = enabled {
9772                    write!(
9773                        f,
9774                        "{}",
9775                        match enabled {
9776                            true => " TRUE",
9777                            false => " FALSE",
9778                        }
9779                    )?;
9780                }
9781                Ok(())
9782            }
9783            Csv(opts) => {
9784                write!(f, "CSV")?;
9785                if !opts.is_empty() {
9786                    write!(f, " {}", display_separated(opts, " "))?;
9787                }
9788                Ok(())
9789            }
9790            DateFormat(fmt) => {
9791                write!(f, "DATEFORMAT")?;
9792                if let Some(fmt) = fmt {
9793                    write!(f, " '{}'", value::escape_single_quote_string(fmt))?;
9794                }
9795                Ok(())
9796            }
9797            Delimiter(char) => write!(f, "DELIMITER '{char}'"),
9798            EmptyAsNull => write!(f, "EMPTYASNULL"),
9799            Encrypted { auto } => write!(f, "ENCRYPTED{}", if *auto { " AUTO" } else { "" }),
9800            Escape => write!(f, "ESCAPE"),
9801            Extension(ext) => write!(f, "EXTENSION '{}'", value::escape_single_quote_string(ext)),
9802            FixedWidth(spec) => write!(
9803                f,
9804                "FIXEDWIDTH '{}'",
9805                value::escape_single_quote_string(spec)
9806            ),
9807            Gzip => write!(f, "GZIP"),
9808            Header => write!(f, "HEADER"),
9809            IamRole(role) => write!(f, "IAM_ROLE {role}"),
9810            IgnoreHeader(num_rows) => write!(f, "IGNOREHEADER {num_rows}"),
9811            Json(opt) => {
9812                write!(f, "JSON")?;
9813                if let Some(opt) = opt {
9814                    write!(f, " AS '{}'", value::escape_single_quote_string(opt))?;
9815                }
9816                Ok(())
9817            }
9818            Manifest { verbose } => write!(f, "MANIFEST{}", if *verbose { " VERBOSE" } else { "" }),
9819            MaxFileSize(file_size) => write!(f, "MAXFILESIZE {file_size}"),
9820            Null(string) => write!(f, "NULL '{}'", value::escape_single_quote_string(string)),
9821            Parallel(enabled) => {
9822                write!(
9823                    f,
9824                    "PARALLEL{}",
9825                    match enabled {
9826                        Some(true) => " TRUE",
9827                        Some(false) => " FALSE",
9828                        _ => "",
9829                    }
9830                )
9831            }
9832            Parquet => write!(f, "PARQUET"),
9833            PartitionBy(p) => write!(f, "{p}"),
9834            Region(region) => write!(f, "REGION '{}'", value::escape_single_quote_string(region)),
9835            RemoveQuotes => write!(f, "REMOVEQUOTES"),
9836            RowGroupSize(file_size) => write!(f, "ROWGROUPSIZE {file_size}"),
9837            StatUpdate(enabled) => {
9838                write!(
9839                    f,
9840                    "STATUPDATE{}",
9841                    match enabled {
9842                        Some(true) => " TRUE",
9843                        Some(false) => " FALSE",
9844                        _ => "",
9845                    }
9846                )
9847            }
9848            TimeFormat(fmt) => {
9849                write!(f, "TIMEFORMAT")?;
9850                if let Some(fmt) = fmt {
9851                    write!(f, " '{}'", value::escape_single_quote_string(fmt))?;
9852                }
9853                Ok(())
9854            }
9855            TruncateColumns => write!(f, "TRUNCATECOLUMNS"),
9856            Zstd => write!(f, "ZSTD"),
9857            Credentials(s) => write!(f, "CREDENTIALS '{}'", value::escape_single_quote_string(s)),
9858        }
9859    }
9860}
9861
9862/// ```sql
9863/// SIZE \[ MB | GB \]
9864/// ```
9865#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9866#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9867#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9868pub struct FileSize {
9869    /// Numeric size value.
9870    pub size: ValueWithSpan,
9871    /// Optional unit for the size (MB or GB).
9872    pub unit: Option<FileSizeUnit>,
9873}
9874
9875impl fmt::Display for FileSize {
9876    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9877        write!(f, "{}", self.size)?;
9878        if let Some(unit) = &self.unit {
9879            write!(f, " {unit}")?;
9880        }
9881        Ok(())
9882    }
9883}
9884
9885/// Units for `FileSize` (MB or GB).
9886#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9887#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9888#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9889pub enum FileSizeUnit {
9890    /// Megabytes.
9891    MB,
9892    /// Gigabytes.
9893    GB,
9894}
9895
9896impl fmt::Display for FileSizeUnit {
9897    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9898        match self {
9899            FileSizeUnit::MB => write!(f, "MB"),
9900            FileSizeUnit::GB => write!(f, "GB"),
9901        }
9902    }
9903}
9904
9905/// Specifies the partition keys for the unload operation
9906///
9907/// ```sql
9908/// PARTITION BY ( column_name [, ... ] ) [ INCLUDE ]
9909/// ```
9910#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9911#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9912#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9913pub struct UnloadPartitionBy {
9914    /// Columns used to partition the unload output.
9915    pub columns: Vec<Ident>,
9916    /// Whether to include the partition in the output.
9917    pub include: bool,
9918}
9919
9920impl fmt::Display for UnloadPartitionBy {
9921    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9922        write!(
9923            f,
9924            "PARTITION BY ({}){}",
9925            display_comma_separated(&self.columns),
9926            if self.include { " INCLUDE" } else { "" }
9927        )
9928    }
9929}
9930
9931/// An `IAM_ROLE` option in the AWS ecosystem
9932///
9933/// [Redshift COPY](https://docs.aws.amazon.com/redshift/latest/dg/copy-parameters-authorization.html#copy-iam-role)
9934#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9935#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9936#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9937pub enum IamRoleKind {
9938    /// Default role
9939    Default,
9940    /// Specific role ARN, for example: `arn:aws:iam::123456789:role/role1`
9941    Arn(String),
9942}
9943
9944impl fmt::Display for IamRoleKind {
9945    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9946        match self {
9947            IamRoleKind::Default => write!(f, "DEFAULT"),
9948            IamRoleKind::Arn(arn) => write!(f, "'{arn}'"),
9949        }
9950    }
9951}
9952
9953/// A `CSV` option in `COPY` statement before PostgreSQL version 9.0.
9954///
9955/// <https://www.postgresql.org/docs/8.4/sql-copy.html>
9956#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9957#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9958#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9959pub enum CopyLegacyCsvOption {
9960    /// HEADER
9961    Header,
9962    /// QUOTE \[ AS \] 'quote_character'
9963    Quote(char),
9964    /// ESCAPE \[ AS \] 'escape_character'
9965    Escape(char),
9966    /// FORCE QUOTE { column_name [, ...] | * }
9967    ForceQuote(Vec<Ident>),
9968    /// FORCE NOT NULL column_name [, ...]
9969    ForceNotNull(Vec<Ident>),
9970}
9971
9972impl fmt::Display for CopyLegacyCsvOption {
9973    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9974        use CopyLegacyCsvOption::*;
9975        match self {
9976            Header => write!(f, "HEADER"),
9977            Quote(char) => write!(f, "QUOTE '{char}'"),
9978            Escape(char) => write!(f, "ESCAPE '{char}'"),
9979            ForceQuote(columns) => write!(f, "FORCE QUOTE {}", display_comma_separated(columns)),
9980            ForceNotNull(columns) => {
9981                write!(f, "FORCE NOT NULL {}", display_comma_separated(columns))
9982            }
9983        }
9984    }
9985}
9986
9987/// Objects that can be discarded with `DISCARD`.
9988#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9989#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9990#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9991pub enum DiscardObject {
9992    /// Discard all session state.
9993    ALL,
9994    /// Discard cached plans.
9995    PLANS,
9996    /// Discard sequence values.
9997    SEQUENCES,
9998    /// Discard temporary objects.
9999    TEMP,
10000}
10001
10002impl fmt::Display for DiscardObject {
10003    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10004        match self {
10005            DiscardObject::ALL => f.write_str("ALL"),
10006            DiscardObject::PLANS => f.write_str("PLANS"),
10007            DiscardObject::SEQUENCES => f.write_str("SEQUENCES"),
10008            DiscardObject::TEMP => f.write_str("TEMP"),
10009        }
10010    }
10011}
10012
10013/// Types of flush operations supported by `FLUSH`.
10014#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10015#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10016#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10017pub enum FlushType {
10018    /// Flush binary logs.
10019    BinaryLogs,
10020    /// Flush engine logs.
10021    EngineLogs,
10022    /// Flush error logs.
10023    ErrorLogs,
10024    /// Flush general logs.
10025    GeneralLogs,
10026    /// Flush hosts information.
10027    Hosts,
10028    /// Flush logs.
10029    Logs,
10030    /// Flush privileges.
10031    Privileges,
10032    /// Flush optimizer costs.
10033    OptimizerCosts,
10034    /// Flush relay logs.
10035    RelayLogs,
10036    /// Flush slow logs.
10037    SlowLogs,
10038    /// Flush status.
10039    Status,
10040    /// Flush user resources.
10041    UserResources,
10042    /// Flush table data.
10043    Tables,
10044}
10045
10046impl fmt::Display for FlushType {
10047    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10048        match self {
10049            FlushType::BinaryLogs => f.write_str("BINARY LOGS"),
10050            FlushType::EngineLogs => f.write_str("ENGINE LOGS"),
10051            FlushType::ErrorLogs => f.write_str("ERROR LOGS"),
10052            FlushType::GeneralLogs => f.write_str("GENERAL LOGS"),
10053            FlushType::Hosts => f.write_str("HOSTS"),
10054            FlushType::Logs => f.write_str("LOGS"),
10055            FlushType::Privileges => f.write_str("PRIVILEGES"),
10056            FlushType::OptimizerCosts => f.write_str("OPTIMIZER_COSTS"),
10057            FlushType::RelayLogs => f.write_str("RELAY LOGS"),
10058            FlushType::SlowLogs => f.write_str("SLOW LOGS"),
10059            FlushType::Status => f.write_str("STATUS"),
10060            FlushType::UserResources => f.write_str("USER_RESOURCES"),
10061            FlushType::Tables => f.write_str("TABLES"),
10062        }
10063    }
10064}
10065
10066/// Location modifier for flush commands.
10067#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10068#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10069#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10070pub enum FlushLocation {
10071    /// Do not write changes to the binary log.
10072    NoWriteToBinlog,
10073    /// Apply flush locally.
10074    Local,
10075}
10076
10077impl fmt::Display for FlushLocation {
10078    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10079        match self {
10080            FlushLocation::NoWriteToBinlog => f.write_str("NO_WRITE_TO_BINLOG"),
10081            FlushLocation::Local => f.write_str("LOCAL"),
10082        }
10083    }
10084}
10085
10086/// Optional context modifier for statements that can be or `LOCAL`, `GLOBAL`, or `SESSION`.
10087#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10088#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10089#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10090pub enum ContextModifier {
10091    /// `LOCAL` identifier, usually related to transactional states.
10092    Local,
10093    /// `SESSION` identifier
10094    Session,
10095    /// `GLOBAL` identifier
10096    Global,
10097}
10098
10099impl fmt::Display for ContextModifier {
10100    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10101        match self {
10102            Self::Local => {
10103                write!(f, "LOCAL ")
10104            }
10105            Self::Session => {
10106                write!(f, "SESSION ")
10107            }
10108            Self::Global => {
10109                write!(f, "GLOBAL ")
10110            }
10111        }
10112    }
10113}
10114
10115/// Function describe in DROP FUNCTION.
10116#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10117#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10118pub enum DropFunctionOption {
10119    /// `RESTRICT` option for DROP FUNCTION.
10120    Restrict,
10121    /// `CASCADE` option for DROP FUNCTION.
10122    Cascade,
10123}
10124
10125impl fmt::Display for DropFunctionOption {
10126    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10127        match self {
10128            DropFunctionOption::Restrict => write!(f, "RESTRICT "),
10129            DropFunctionOption::Cascade => write!(f, "CASCADE  "),
10130        }
10131    }
10132}
10133
10134/// Generic function description for DROP FUNCTION and CREATE TRIGGER.
10135#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10136#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10137#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10138pub struct FunctionDesc {
10139    /// The function name.
10140    pub name: ObjectName,
10141    /// Optional list of function arguments.
10142    pub args: Option<Vec<OperateFunctionArg>>,
10143}
10144
10145impl fmt::Display for FunctionDesc {
10146    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10147        write!(f, "{}", self.name)?;
10148        if let Some(args) = &self.args {
10149            write!(f, "({})", display_comma_separated(args))?;
10150        }
10151        Ok(())
10152    }
10153}
10154
10155/// Function argument in CREATE OR DROP FUNCTION.
10156#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10157#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10158#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10159pub struct OperateFunctionArg {
10160    /// Optional argument mode (`IN`, `OUT`, `INOUT`).
10161    pub mode: Option<ArgMode>,
10162    /// Optional argument identifier/name.
10163    pub name: Option<Ident>,
10164    /// The data type of the argument.
10165    pub data_type: DataType,
10166    /// Optional default expression for the argument.
10167    pub default_expr: Option<Expr>,
10168}
10169
10170impl OperateFunctionArg {
10171    /// Returns an unnamed argument.
10172    pub fn unnamed(data_type: DataType) -> Self {
10173        Self {
10174            mode: None,
10175            name: None,
10176            data_type,
10177            default_expr: None,
10178        }
10179    }
10180
10181    /// Returns an argument with name.
10182    pub fn with_name(name: &str, data_type: DataType) -> Self {
10183        Self {
10184            mode: None,
10185            name: Some(name.into()),
10186            data_type,
10187            default_expr: None,
10188        }
10189    }
10190}
10191
10192impl fmt::Display for OperateFunctionArg {
10193    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10194        if let Some(mode) = &self.mode {
10195            write!(f, "{mode} ")?;
10196        }
10197        if let Some(name) = &self.name {
10198            write!(f, "{name} ")?;
10199        }
10200        write!(f, "{}", self.data_type)?;
10201        if let Some(default_expr) = &self.default_expr {
10202            write!(f, " = {default_expr}")?;
10203        }
10204        Ok(())
10205    }
10206}
10207
10208/// The mode of an argument in CREATE FUNCTION.
10209#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10210#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10211#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10212pub enum ArgMode {
10213    /// `IN` mode.
10214    In,
10215    /// `OUT` mode.
10216    Out,
10217    /// `INOUT` mode.
10218    InOut,
10219    /// `VARIADIC` mode.
10220    Variadic,
10221}
10222
10223impl fmt::Display for ArgMode {
10224    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10225        match self {
10226            ArgMode::In => write!(f, "IN"),
10227            ArgMode::Out => write!(f, "OUT"),
10228            ArgMode::InOut => write!(f, "INOUT"),
10229            ArgMode::Variadic => write!(f, "VARIADIC"),
10230        }
10231    }
10232}
10233
10234/// These attributes inform the query optimizer about the behavior of the function.
10235#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10236#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10237#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10238pub enum FunctionBehavior {
10239    /// Function is immutable.
10240    Immutable,
10241    /// Function is stable.
10242    Stable,
10243    /// Function is volatile.
10244    Volatile,
10245}
10246
10247impl fmt::Display for FunctionBehavior {
10248    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10249        match self {
10250            FunctionBehavior::Immutable => write!(f, "IMMUTABLE"),
10251            FunctionBehavior::Stable => write!(f, "STABLE"),
10252            FunctionBehavior::Volatile => write!(f, "VOLATILE"),
10253        }
10254    }
10255}
10256
10257/// Security attribute for functions: SECURITY DEFINER or SECURITY INVOKER.
10258///
10259/// [PostgreSQL](https://www.postgresql.org/docs/current/sql-createfunction.html)
10260#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10261#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10262#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10263pub enum FunctionSecurity {
10264    /// Execute the function with the privileges of the user who defined it.
10265    Definer,
10266    /// Execute the function with the privileges of the user who invokes it.
10267    Invoker,
10268}
10269
10270impl fmt::Display for FunctionSecurity {
10271    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10272        match self {
10273            FunctionSecurity::Definer => write!(f, "SECURITY DEFINER"),
10274            FunctionSecurity::Invoker => write!(f, "SECURITY INVOKER"),
10275        }
10276    }
10277}
10278
10279/// Value for a SET configuration parameter in a CREATE FUNCTION statement.
10280///
10281/// [PostgreSQL](https://www.postgresql.org/docs/current/sql-createfunction.html)
10282#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10283#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10284#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10285pub enum FunctionSetValue {
10286    /// SET param = DEFAULT / SET param TO DEFAULT
10287    Default,
10288    /// SET param = value1, value2, ...
10289    Values(Vec<Expr>),
10290    /// SET param FROM CURRENT
10291    FromCurrent,
10292}
10293
10294/// A SET configuration_parameter clause in a CREATE FUNCTION statement.
10295///
10296/// [PostgreSQL](https://www.postgresql.org/docs/current/sql-createfunction.html)
10297#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10298#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10299#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10300pub struct FunctionDefinitionSetParam {
10301    /// The name of the configuration parameter.
10302    pub name: ObjectName,
10303    /// The value to set for the parameter.
10304    pub value: FunctionSetValue,
10305}
10306
10307impl fmt::Display for FunctionDefinitionSetParam {
10308    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10309        write!(f, "SET {} ", self.name)?;
10310        match &self.value {
10311            FunctionSetValue::Default => write!(f, "= DEFAULT"),
10312            FunctionSetValue::Values(values) => {
10313                write!(f, "= {}", display_comma_separated(values))
10314            }
10315            FunctionSetValue::FromCurrent => write!(f, "FROM CURRENT"),
10316        }
10317    }
10318}
10319
10320/// These attributes describe the behavior of the function when called with a null argument.
10321#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10322#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10323#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10324pub enum FunctionCalledOnNull {
10325    /// Function is called even when inputs are null.
10326    CalledOnNullInput,
10327    /// Function returns null when any input is null.
10328    ReturnsNullOnNullInput,
10329    /// Function is strict about null inputs.
10330    Strict,
10331}
10332
10333impl fmt::Display for FunctionCalledOnNull {
10334    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10335        match self {
10336            FunctionCalledOnNull::CalledOnNullInput => write!(f, "CALLED ON NULL INPUT"),
10337            FunctionCalledOnNull::ReturnsNullOnNullInput => write!(f, "RETURNS NULL ON NULL INPUT"),
10338            FunctionCalledOnNull::Strict => write!(f, "STRICT"),
10339        }
10340    }
10341}
10342
10343/// If it is safe for PostgreSQL to call the function from multiple threads at once
10344#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10345#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10346#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10347pub enum FunctionParallel {
10348    /// The function is not safe to run in parallel.
10349    Unsafe,
10350    /// The function is restricted for parallel execution.
10351    Restricted,
10352    /// The function is safe to run in parallel.
10353    Safe,
10354}
10355
10356impl fmt::Display for FunctionParallel {
10357    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10358        match self {
10359            FunctionParallel::Unsafe => write!(f, "PARALLEL UNSAFE"),
10360            FunctionParallel::Restricted => write!(f, "PARALLEL RESTRICTED"),
10361            FunctionParallel::Safe => write!(f, "PARALLEL SAFE"),
10362        }
10363    }
10364}
10365
10366/// [BigQuery] Determinism specifier used in a UDF definition.
10367///
10368/// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#syntax_11
10369#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10370#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10371#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10372pub enum FunctionDeterminismSpecifier {
10373    /// Function is deterministic.
10374    Deterministic,
10375    /// Function is not deterministic.
10376    NotDeterministic,
10377}
10378
10379impl fmt::Display for FunctionDeterminismSpecifier {
10380    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10381        match self {
10382            FunctionDeterminismSpecifier::Deterministic => {
10383                write!(f, "DETERMINISTIC")
10384            }
10385            FunctionDeterminismSpecifier::NotDeterministic => {
10386                write!(f, "NOT DETERMINISTIC")
10387            }
10388        }
10389    }
10390}
10391
10392/// Represent the expression body of a `CREATE FUNCTION` statement as well as
10393/// where within the statement, the body shows up.
10394///
10395/// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#syntax_11
10396/// [PostgreSQL]: https://www.postgresql.org/docs/15/sql-createfunction.html
10397/// [MsSql]: https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql
10398#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10399#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10400#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10401pub enum CreateFunctionBody {
10402    /// A function body expression using the 'AS' keyword and shows up
10403    /// before any `OPTIONS` clause.
10404    ///
10405    /// Example:
10406    /// ```sql
10407    /// CREATE FUNCTION myfunc(x FLOAT64, y FLOAT64) RETURNS FLOAT64
10408    /// AS (x * y)
10409    /// OPTIONS(description="desc");
10410    /// ```
10411    ///
10412    /// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#syntax_11
10413    /// [PostgreSQL]: https://www.postgresql.org/docs/current/sql-createfunction.html
10414    AsBeforeOptions {
10415        /// The primary expression.
10416        body: Expr,
10417        /// Link symbol if the primary expression contains the name of shared library file.
10418        ///
10419        /// Example:
10420        /// ```sql
10421        /// CREATE FUNCTION cas_in(input cstring) RETURNS cas
10422        /// AS 'MODULE_PATHNAME', 'cas_in_wrapper'
10423        /// ```
10424        /// [PostgreSQL]: https://www.postgresql.org/docs/current/sql-createfunction.html
10425        link_symbol: Option<Expr>,
10426    },
10427    /// A function body expression using the 'AS' keyword and shows up
10428    /// after any `OPTIONS` clause.
10429    ///
10430    /// Example:
10431    /// ```sql
10432    /// CREATE FUNCTION myfunc(x FLOAT64, y FLOAT64) RETURNS FLOAT64
10433    /// OPTIONS(description="desc")
10434    /// AS (x * y);
10435    /// ```
10436    ///
10437    /// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#syntax_11
10438    AsAfterOptions(Expr),
10439    /// Function body with statements before the `RETURN` keyword.
10440    ///
10441    /// Example:
10442    /// ```sql
10443    /// CREATE FUNCTION my_scalar_udf(a INT, b INT)
10444    /// RETURNS INT
10445    /// AS
10446    /// BEGIN
10447    ///     DECLARE c INT;
10448    ///     SET c = a + b;
10449    ///     RETURN c;
10450    /// END
10451    /// ```
10452    ///
10453    /// [MsSql]: https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql
10454    AsBeginEnd(BeginEndStatements),
10455    /// Function body expression using the 'RETURN' keyword.
10456    ///
10457    /// Example:
10458    /// ```sql
10459    /// CREATE FUNCTION myfunc(a INTEGER, IN b INTEGER = 1) RETURNS INTEGER
10460    /// LANGUAGE SQL
10461    /// RETURN a + b;
10462    /// ```
10463    ///
10464    /// [PostgreSQL]: https://www.postgresql.org/docs/current/sql-createfunction.html
10465    Return(Expr),
10466
10467    /// Function body expression using the 'AS RETURN' keywords
10468    ///
10469    /// Example:
10470    /// ```sql
10471    /// CREATE FUNCTION myfunc(a INT, b INT)
10472    /// RETURNS TABLE
10473    /// AS RETURN (SELECT a + b AS sum);
10474    /// ```
10475    ///
10476    /// [MsSql]: https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql
10477    AsReturnExpr(Expr),
10478
10479    /// Function body expression using the 'AS RETURN' keywords, with an un-parenthesized SELECT query
10480    ///
10481    /// Example:
10482    /// ```sql
10483    /// CREATE FUNCTION myfunc(a INT, b INT)
10484    /// RETURNS TABLE
10485    /// AS RETURN SELECT a + b AS sum;
10486    /// ```
10487    ///
10488    /// [MsSql]: https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql?view=sql-server-ver16#select_stmt
10489    AsReturnSelect(Select),
10490}
10491
10492#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10493#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10494#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10495/// `USING` clause options for `CREATE FUNCTION` (e.g., JAR, FILE, ARCHIVE).
10496pub enum CreateFunctionUsing {
10497    /// Use a JAR file located at the given URI.
10498    Jar(String),
10499    /// Use a file located at the given URI.
10500    File(String),
10501    /// Use an archive located at the given URI.
10502    Archive(String),
10503}
10504
10505impl fmt::Display for CreateFunctionUsing {
10506    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10507        write!(f, "USING ")?;
10508        match self {
10509            CreateFunctionUsing::Jar(uri) => write!(f, "JAR '{uri}'"),
10510            CreateFunctionUsing::File(uri) => write!(f, "FILE '{uri}'"),
10511            CreateFunctionUsing::Archive(uri) => write!(f, "ARCHIVE '{uri}'"),
10512        }
10513    }
10514}
10515
10516/// `NAME = <EXPR>` arguments for DuckDB macros
10517///
10518/// See [Create Macro - DuckDB](https://duckdb.org/docs/sql/statements/create_macro)
10519/// for more details
10520#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10521#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10522#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10523pub struct MacroArg {
10524    /// The argument name.
10525    pub name: Ident,
10526    /// Optional default expression for the argument.
10527    pub default_expr: Option<Expr>,
10528}
10529
10530impl MacroArg {
10531    /// Returns an argument with name.
10532    pub fn new(name: &str) -> Self {
10533        Self {
10534            name: name.into(),
10535            default_expr: None,
10536        }
10537    }
10538}
10539
10540impl fmt::Display for MacroArg {
10541    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10542        write!(f, "{}", self.name)?;
10543        if let Some(default_expr) = &self.default_expr {
10544            write!(f, " := {default_expr}")?;
10545        }
10546        Ok(())
10547    }
10548}
10549
10550#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10551#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10552#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10553/// Definition for a DuckDB macro: either an expression or a table-producing query.
10554pub enum MacroDefinition {
10555    /// The macro is defined as an expression.
10556    Expr(Expr),
10557    /// The macro is defined as a table (query).
10558    Table(Box<Query>),
10559}
10560
10561impl fmt::Display for MacroDefinition {
10562    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10563        match self {
10564            MacroDefinition::Expr(expr) => write!(f, "{expr}")?,
10565            MacroDefinition::Table(query) => write!(f, "{query}")?,
10566        }
10567        Ok(())
10568    }
10569}
10570
10571/// Schema possible naming variants ([1]).
10572///
10573/// [1]: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#schema-definition
10574#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10575#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10576#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10577pub enum SchemaName {
10578    /// Only schema name specified: `<schema name>`.
10579    Simple(ObjectName),
10580    /// Only authorization identifier specified: `AUTHORIZATION <schema authorization identifier>`.
10581    UnnamedAuthorization(Ident),
10582    /// Both schema name and authorization identifier specified: `<schema name>  AUTHORIZATION <schema authorization identifier>`.
10583    NamedAuthorization(ObjectName, Ident),
10584}
10585
10586impl fmt::Display for SchemaName {
10587    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10588        match self {
10589            SchemaName::Simple(name) => {
10590                write!(f, "{name}")
10591            }
10592            SchemaName::UnnamedAuthorization(authorization) => {
10593                write!(f, "AUTHORIZATION {authorization}")
10594            }
10595            SchemaName::NamedAuthorization(name, authorization) => {
10596                write!(f, "{name} AUTHORIZATION {authorization}")
10597            }
10598        }
10599    }
10600}
10601
10602/// Fulltext search modifiers ([1]).
10603///
10604/// [1]: https://dev.mysql.com/doc/refman/8.0/en/fulltext-search.html#function_match
10605#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10606#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10607#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10608pub enum SearchModifier {
10609    /// `IN NATURAL LANGUAGE MODE`.
10610    InNaturalLanguageMode,
10611    /// `IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION`.
10612    InNaturalLanguageModeWithQueryExpansion,
10613    ///`IN BOOLEAN MODE`.
10614    InBooleanMode,
10615    ///`WITH QUERY EXPANSION`.
10616    WithQueryExpansion,
10617}
10618
10619impl fmt::Display for SearchModifier {
10620    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10621        match self {
10622            Self::InNaturalLanguageMode => {
10623                write!(f, "IN NATURAL LANGUAGE MODE")?;
10624            }
10625            Self::InNaturalLanguageModeWithQueryExpansion => {
10626                write!(f, "IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION")?;
10627            }
10628            Self::InBooleanMode => {
10629                write!(f, "IN BOOLEAN MODE")?;
10630            }
10631            Self::WithQueryExpansion => {
10632                write!(f, "WITH QUERY EXPANSION")?;
10633            }
10634        }
10635
10636        Ok(())
10637    }
10638}
10639
10640/// Represents a `LOCK TABLE` clause with optional alias and lock type.
10641#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10642#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10643#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10644pub struct LockTable {
10645    /// The table identifier to lock.
10646    pub table: Ident,
10647    /// Optional alias for the table.
10648    pub alias: Option<Ident>,
10649    /// The type of lock to apply to the table.
10650    pub lock_type: LockTableType,
10651}
10652
10653impl fmt::Display for LockTable {
10654    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10655        let Self {
10656            table: tbl_name,
10657            alias,
10658            lock_type,
10659        } = self;
10660
10661        write!(f, "{tbl_name} ")?;
10662        if let Some(alias) = alias {
10663            write!(f, "AS {alias} ")?;
10664        }
10665        write!(f, "{lock_type}")?;
10666        Ok(())
10667    }
10668}
10669
10670#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10671#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10672#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10673/// The type of lock used in `LOCK TABLE` statements.
10674pub enum LockTableType {
10675    /// Shared/read lock. If `local` is true, it's a local read lock.
10676    Read {
10677        /// Whether the read lock is local.
10678        local: bool,
10679    },
10680    /// Exclusive/write lock. If `low_priority` is true, the write is low priority.
10681    Write {
10682        /// Whether the write lock is low priority.
10683        low_priority: bool,
10684    },
10685}
10686
10687impl fmt::Display for LockTableType {
10688    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10689        match self {
10690            Self::Read { local } => {
10691                write!(f, "READ")?;
10692                if *local {
10693                    write!(f, " LOCAL")?;
10694                }
10695            }
10696            Self::Write { low_priority } => {
10697                if *low_priority {
10698                    write!(f, "LOW_PRIORITY ")?;
10699                }
10700                write!(f, "WRITE")?;
10701            }
10702        }
10703
10704        Ok(())
10705    }
10706}
10707
10708#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10709#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10710#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10711/// Hive-specific `SET LOCATION` helper used in some `LOAD DATA` statements.
10712pub struct HiveSetLocation {
10713    /// Whether the `SET` keyword was present.
10714    pub has_set: bool,
10715    /// The location identifier.
10716    pub location: Ident,
10717}
10718
10719impl fmt::Display for HiveSetLocation {
10720    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10721        if self.has_set {
10722            write!(f, "SET ")?;
10723        }
10724        write!(f, "LOCATION {}", self.location)
10725    }
10726}
10727
10728/// MySQL `ALTER TABLE` only  [FIRST | AFTER column_name]
10729#[allow(clippy::large_enum_variant)]
10730#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10731#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10732#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10733/// MySQL `ALTER TABLE` column position specifier: `FIRST` or `AFTER <column>`.
10734pub enum MySQLColumnPosition {
10735    /// Place the column first in the table.
10736    First,
10737    /// Place the column after the specified identifier.
10738    After(Ident),
10739}
10740
10741impl Display for MySQLColumnPosition {
10742    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10743        match self {
10744            MySQLColumnPosition::First => write!(f, "FIRST"),
10745            MySQLColumnPosition::After(ident) => {
10746                let column_name = &ident.value;
10747                write!(f, "AFTER {column_name}")
10748            }
10749        }
10750    }
10751}
10752
10753/// MySQL `CREATE VIEW` algorithm parameter: [ALGORITHM = {UNDEFINED | MERGE | TEMPTABLE}]
10754#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10755#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10756#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10757/// MySQL `CREATE VIEW` algorithm options.
10758pub enum CreateViewAlgorithm {
10759    /// `UNDEFINED` algorithm.
10760    Undefined,
10761    /// `MERGE` algorithm.
10762    Merge,
10763    /// `TEMPTABLE` algorithm.
10764    TempTable,
10765}
10766
10767impl Display for CreateViewAlgorithm {
10768    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10769        match self {
10770            CreateViewAlgorithm::Undefined => write!(f, "UNDEFINED"),
10771            CreateViewAlgorithm::Merge => write!(f, "MERGE"),
10772            CreateViewAlgorithm::TempTable => write!(f, "TEMPTABLE"),
10773        }
10774    }
10775}
10776/// MySQL `CREATE VIEW` security parameter: [SQL SECURITY { DEFINER | INVOKER }]
10777#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10778#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10779#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10780/// MySQL `CREATE VIEW` SQL SECURITY options.
10781pub enum CreateViewSecurity {
10782    /// The view runs with the privileges of the definer.
10783    Definer,
10784    /// The view runs with the privileges of the invoker.
10785    Invoker,
10786}
10787
10788impl Display for CreateViewSecurity {
10789    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10790        match self {
10791            CreateViewSecurity::Definer => write!(f, "DEFINER"),
10792            CreateViewSecurity::Invoker => write!(f, "INVOKER"),
10793        }
10794    }
10795}
10796
10797/// [MySQL] `CREATE VIEW` additional parameters
10798///
10799/// [MySQL]: https://dev.mysql.com/doc/refman/9.1/en/create-view.html
10800#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10801#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10802#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10803pub struct CreateViewParams {
10804    /// Optional view algorithm (e.g., MERGE, TEMPTABLE).
10805    pub algorithm: Option<CreateViewAlgorithm>,
10806    /// Optional definer (the security principal that will own the view).
10807    pub definer: Option<GranteeName>,
10808    /// Optional SQL SECURITY setting for the view.
10809    pub security: Option<CreateViewSecurity>,
10810}
10811
10812impl Display for CreateViewParams {
10813    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10814        let CreateViewParams {
10815            algorithm,
10816            definer,
10817            security,
10818        } = self;
10819        if let Some(algorithm) = algorithm {
10820            write!(f, "ALGORITHM = {algorithm} ")?;
10821        }
10822        if let Some(definers) = definer {
10823            write!(f, "DEFINER = {definers} ")?;
10824        }
10825        if let Some(security) = security {
10826            write!(f, "SQL SECURITY {security} ")?;
10827        }
10828        Ok(())
10829    }
10830}
10831
10832#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10833#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10834#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10835/// Key/Value, where the value is a (optionally named) list of identifiers
10836///
10837/// ```sql
10838/// UNION = (tbl_name[,tbl_name]...)
10839/// ENGINE = ReplicatedMergeTree('/table_name','{replica}', ver)
10840/// ENGINE = SummingMergeTree([columns])
10841/// ```
10842pub struct NamedParenthesizedList {
10843    /// The option key (identifier) for this named list.
10844    pub key: Ident,
10845    /// Optional secondary name associated with the key.
10846    pub name: Option<Ident>,
10847    /// The list of identifier values for the key.
10848    pub values: Vec<Ident>,
10849}
10850
10851/// Snowflake `WITH ROW ACCESS POLICY policy_name ON (identifier, ...)`
10852///
10853/// <https://docs.snowflake.com/en/sql-reference/sql/create-table>
10854/// <https://docs.snowflake.com/en/user-guide/security-row-intro>
10855#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10856#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10857#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10858pub struct RowAccessPolicy {
10859    /// The fully-qualified policy object name.
10860    pub policy: ObjectName,
10861    /// Identifiers for the columns or objects the policy applies to.
10862    pub on: Vec<Ident>,
10863}
10864
10865impl RowAccessPolicy {
10866    /// Create a new `RowAccessPolicy` for the given `policy` and `on` identifiers.
10867    pub fn new(policy: ObjectName, on: Vec<Ident>) -> Self {
10868        Self { policy, on }
10869    }
10870}
10871
10872impl Display for RowAccessPolicy {
10873    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10874        write!(
10875            f,
10876            "WITH ROW ACCESS POLICY {} ON ({})",
10877            self.policy,
10878            display_comma_separated(self.on.as_slice())
10879        )
10880    }
10881}
10882
10883/// Snowflake `[ WITH ] STORAGE LIFECYCLE POLICY <policy_name> ON ( <col_name> [ , ... ] )`
10884///
10885/// <https://docs.snowflake.com/en/sql-reference/sql/create-table>
10886#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10887#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10888#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10889pub struct StorageLifecyclePolicy {
10890    /// The fully-qualified policy object name.
10891    pub policy: ObjectName,
10892    /// Column names the policy applies to.
10893    pub on: Vec<Ident>,
10894}
10895
10896impl Display for StorageLifecyclePolicy {
10897    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10898        write!(
10899            f,
10900            "WITH STORAGE LIFECYCLE POLICY {} ON ({})",
10901            self.policy,
10902            display_comma_separated(self.on.as_slice())
10903        )
10904    }
10905}
10906
10907/// Snowflake `WITH TAG ( tag_name = '<tag_value>', ...)`
10908///
10909/// <https://docs.snowflake.com/en/sql-reference/sql/create-table>
10910#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10911#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10912#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10913pub struct Tag {
10914    /// The tag key (can be qualified).
10915    pub key: ObjectName,
10916    /// The tag value as a string.
10917    pub value: String,
10918}
10919
10920impl Tag {
10921    /// Create a new `Tag` with the given key and value.
10922    pub fn new(key: ObjectName, value: String) -> Self {
10923        Self { key, value }
10924    }
10925}
10926
10927impl Display for Tag {
10928    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10929        write!(f, "{}='{}'", self.key, self.value)
10930    }
10931}
10932
10933/// Snowflake `WITH CONTACT ( purpose = contact [ , purpose = contact ...] )`
10934///
10935/// <https://docs.snowflake.com/en/sql-reference/sql/create-database>
10936#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10937#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10938#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10939pub struct ContactEntry {
10940    /// The purpose label for the contact entry.
10941    pub purpose: String,
10942    /// The contact information associated with the purpose.
10943    pub contact: String,
10944}
10945
10946impl Display for ContactEntry {
10947    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10948        write!(f, "{} = {}", self.purpose, self.contact)
10949    }
10950}
10951
10952/// Helper to indicate if a comment includes the `=` in the display form
10953#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10954#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10955#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10956pub enum CommentDef {
10957    /// Includes `=` when printing the comment, as `COMMENT = 'comment'`
10958    /// Does not include `=` when printing the comment, as `COMMENT 'comment'`
10959    WithEq(String),
10960    /// Comment variant that omits the `=` when displayed.
10961    WithoutEq(String),
10962}
10963
10964impl Display for CommentDef {
10965    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10966        match self {
10967            CommentDef::WithEq(comment) | CommentDef::WithoutEq(comment) => write!(f, "{comment}"),
10968        }
10969    }
10970}
10971
10972/// Helper to indicate if a collection should be wrapped by a symbol in the display form
10973///
10974/// [`Display`] is implemented for every [`Vec<T>`] where `T: Display`.
10975/// The string output is a comma separated list for the vec items
10976///
10977/// # Examples
10978/// ```
10979/// # use sqlparser::ast::WrappedCollection;
10980/// let items = WrappedCollection::Parentheses(vec!["one", "two", "three"]);
10981/// assert_eq!("(one, two, three)", items.to_string());
10982///
10983/// let items = WrappedCollection::NoWrapping(vec!["one", "two", "three"]);
10984/// assert_eq!("one, two, three", items.to_string());
10985/// ```
10986#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10987#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10988#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10989pub enum WrappedCollection<T> {
10990    /// Print the collection without wrapping symbols, as `item, item, item`
10991    NoWrapping(T),
10992    /// Wraps the collection in Parentheses, as `(item, item, item)`
10993    Parentheses(T),
10994}
10995
10996impl<T> Display for WrappedCollection<Vec<T>>
10997where
10998    T: Display,
10999{
11000    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
11001        match self {
11002            WrappedCollection::NoWrapping(inner) => {
11003                write!(f, "{}", display_comma_separated(inner.as_slice()))
11004            }
11005            WrappedCollection::Parentheses(inner) => {
11006                write!(f, "({})", display_comma_separated(inner.as_slice()))
11007            }
11008        }
11009    }
11010}
11011
11012/// Represents a single PostgreSQL utility option.
11013///
11014/// A utility option is a key-value pair where the key is an identifier (IDENT) and the value
11015/// can be one of the following:
11016/// - A number with an optional sign (`+` or `-`). Example: `+10`, `-10.2`, `3`
11017/// - A non-keyword string. Example: `option1`, `'option2'`, `"option3"`
11018/// - keyword: `TRUE`, `FALSE`, `ON` (`off` is also accept).
11019/// - Empty. Example: `ANALYZE` (identifier only)
11020///
11021/// Utility options are used in various PostgreSQL DDL statements, including statements such as
11022/// `CLUSTER`, `EXPLAIN`, `VACUUM`, and `REINDEX`. These statements format options as `( option [, ...] )`.
11023///
11024/// [CLUSTER](https://www.postgresql.org/docs/current/sql-cluster.html)
11025/// [EXPLAIN](https://www.postgresql.org/docs/current/sql-explain.html)
11026/// [VACUUM](https://www.postgresql.org/docs/current/sql-vacuum.html)
11027/// [REINDEX](https://www.postgresql.org/docs/current/sql-reindex.html)
11028///
11029/// For example, the `EXPLAIN` AND `VACUUM` statements with options might look like this:
11030/// ```sql
11031/// EXPLAIN (ANALYZE, VERBOSE TRUE, FORMAT TEXT) SELECT * FROM my_table;
11032///
11033/// VACUUM (VERBOSE, ANALYZE ON, PARALLEL 10) my_table;
11034/// ```
11035#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11036#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11037#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11038pub struct UtilityOption {
11039    /// The option name (identifier).
11040    pub name: Ident,
11041    /// Optional argument for the option (number, string, keyword, etc.).
11042    pub arg: Option<Expr>,
11043}
11044
11045impl Display for UtilityOption {
11046    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
11047        if let Some(ref arg) = self.arg {
11048            write!(f, "{} {}", self.name, arg)
11049        } else {
11050            write!(f, "{}", self.name)
11051        }
11052    }
11053}
11054
11055/// Represents the different options available for `SHOW`
11056/// statements to filter the results. Example from Snowflake:
11057/// <https://docs.snowflake.com/en/sql-reference/sql/show-tables>
11058#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11059#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11060#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11061pub struct ShowStatementOptions {
11062    /// Optional scope to show in (for example: TABLE, SCHEMA).
11063    pub show_in: Option<ShowStatementIn>,
11064    /// Optional `STARTS WITH` filter value.
11065    pub starts_with: Option<ValueWithSpan>,
11066    /// Optional `LIMIT` expression.
11067    pub limit: Option<Expr>,
11068    /// Optional `FROM` value used with `LIMIT`.
11069    pub limit_from: Option<ValueWithSpan>,
11070    /// Optional filter position (infix or suffix) for `LIKE`/`FILTER`.
11071    pub filter_position: Option<ShowStatementFilterPosition>,
11072}
11073
11074impl Display for ShowStatementOptions {
11075    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
11076        let (like_in_infix, like_in_suffix) = match &self.filter_position {
11077            Some(ShowStatementFilterPosition::Infix(filter)) => {
11078                (format!(" {filter}"), "".to_string())
11079            }
11080            Some(ShowStatementFilterPosition::Suffix(filter)) => {
11081                ("".to_string(), format!(" {filter}"))
11082            }
11083            None => ("".to_string(), "".to_string()),
11084        };
11085        write!(
11086            f,
11087            "{like_in_infix}{show_in}{starts_with}{limit}{from}{like_in_suffix}",
11088            show_in = match &self.show_in {
11089                Some(i) => format!(" {i}"),
11090                None => String::new(),
11091            },
11092            starts_with = match &self.starts_with {
11093                Some(s) => format!(" STARTS WITH {s}"),
11094                None => String::new(),
11095            },
11096            limit = match &self.limit {
11097                Some(l) => format!(" LIMIT {l}"),
11098                None => String::new(),
11099            },
11100            from = match &self.limit_from {
11101                Some(f) => format!(" FROM {f}"),
11102                None => String::new(),
11103            }
11104        )?;
11105        Ok(())
11106    }
11107}
11108
11109#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11110#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11111#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11112/// Where a `SHOW` filter appears relative to the main clause.
11113pub enum ShowStatementFilterPosition {
11114    /// Put the filter in an infix position (e.g. `SHOW COLUMNS LIKE '%name%' IN TABLE tbl`).
11115    Infix(ShowStatementFilter), // For example: SHOW COLUMNS LIKE '%name%' IN TABLE tbl
11116    /// Put the filter in a suffix position (e.g. `SHOW COLUMNS IN tbl LIKE '%name%'`).
11117    Suffix(ShowStatementFilter), // For example: SHOW COLUMNS IN tbl LIKE '%name%'
11118}
11119
11120#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11121#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11122#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11123/// Parent object types usable with `SHOW ... IN <parent>` clauses.
11124pub enum ShowStatementInParentType {
11125    /// ACCOUNT parent type for SHOW statements.
11126    Account,
11127    /// DATABASE parent type for SHOW statements.
11128    Database,
11129    /// SCHEMA parent type for SHOW statements.
11130    Schema,
11131    /// TABLE parent type for SHOW statements.
11132    Table,
11133    /// VIEW parent type for SHOW statements.
11134    View,
11135}
11136
11137impl fmt::Display for ShowStatementInParentType {
11138    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11139        match self {
11140            ShowStatementInParentType::Account => write!(f, "ACCOUNT"),
11141            ShowStatementInParentType::Database => write!(f, "DATABASE"),
11142            ShowStatementInParentType::Schema => write!(f, "SCHEMA"),
11143            ShowStatementInParentType::Table => write!(f, "TABLE"),
11144            ShowStatementInParentType::View => write!(f, "VIEW"),
11145        }
11146    }
11147}
11148
11149#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11150#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11151#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11152/// Represents a `SHOW ... IN` clause with optional parent qualifier and name.
11153pub struct ShowStatementIn {
11154    /// The clause that specifies what to show (e.g. COLUMNS, TABLES).
11155    pub clause: ShowStatementInClause,
11156    /// Optional parent type qualifier (ACCOUNT/DATABASE/...).
11157    pub parent_type: Option<ShowStatementInParentType>,
11158    /// Optional parent object name for the SHOW clause.
11159    #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
11160    pub parent_name: Option<ObjectName>,
11161}
11162
11163impl fmt::Display for ShowStatementIn {
11164    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11165        write!(f, "{}", self.clause)?;
11166        if let Some(parent_type) = &self.parent_type {
11167            write!(f, " {parent_type}")?;
11168        }
11169        if let Some(parent_name) = &self.parent_name {
11170            write!(f, " {parent_name}")?;
11171        }
11172        Ok(())
11173    }
11174}
11175
11176/// A Show Charset statement
11177#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11178#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11179#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11180pub struct ShowCharset {
11181    /// The statement can be written as `SHOW CHARSET` or `SHOW CHARACTER SET`
11182    /// true means CHARSET was used and false means CHARACTER SET was used
11183    pub is_shorthand: bool,
11184    /// Optional `LIKE`/`WHERE`-style filter for the statement.
11185    pub filter: Option<ShowStatementFilter>,
11186}
11187
11188impl fmt::Display for ShowCharset {
11189    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11190        write!(f, "SHOW")?;
11191        if self.is_shorthand {
11192            write!(f, " CHARSET")?;
11193        } else {
11194            write!(f, " CHARACTER SET")?;
11195        }
11196        if let Some(filter) = &self.filter {
11197            write!(f, " {filter}")?;
11198        }
11199        Ok(())
11200    }
11201}
11202
11203#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11204#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11205#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11206/// Options for a `SHOW OBJECTS` statement.
11207pub struct ShowObjects {
11208    /// Whether to show terse output.
11209    pub terse: bool,
11210    /// Additional options controlling the SHOW output.
11211    pub show_options: ShowStatementOptions,
11212}
11213
11214/// MSSQL's json null clause
11215///
11216/// ```plaintext
11217/// <json_null_clause> ::=
11218///       NULL ON NULL
11219///     | ABSENT ON NULL
11220/// ```
11221///
11222/// <https://learn.microsoft.com/en-us/sql/t-sql/functions/json-object-transact-sql?view=sql-server-ver16#json_null_clause>
11223#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11224#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11225#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11226pub enum JsonNullClause {
11227    /// `NULL ON NULL` behavior for JSON functions.
11228    NullOnNull,
11229    /// `ABSENT ON NULL` behavior for JSON functions.
11230    AbsentOnNull,
11231}
11232
11233impl Display for JsonNullClause {
11234    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
11235        match self {
11236            JsonNullClause::NullOnNull => write!(f, "NULL ON NULL"),
11237            JsonNullClause::AbsentOnNull => write!(f, "ABSENT ON NULL"),
11238        }
11239    }
11240}
11241
11242/// PostgreSQL JSON function RETURNING clause
11243///
11244/// Example:
11245/// ```sql
11246/// JSON_OBJECT('a': 1 RETURNING jsonb)
11247/// ```
11248#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11249#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11250#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11251pub struct JsonReturningClause {
11252    /// The data type to return from the JSON function (e.g. JSON/JSONB).
11253    pub data_type: DataType,
11254}
11255
11256impl Display for JsonReturningClause {
11257    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
11258        write!(f, "RETURNING {}", self.data_type)
11259    }
11260}
11261
11262/// rename object definition
11263#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11264#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11265#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11266pub struct RenameTable {
11267    /// The current name of the object to rename.
11268    pub old_name: ObjectName,
11269    /// The new name for the object.
11270    pub new_name: ObjectName,
11271}
11272
11273impl fmt::Display for RenameTable {
11274    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11275        write!(f, "{} TO {}", self.old_name, self.new_name)?;
11276        Ok(())
11277    }
11278}
11279
11280/// Represents the referenced table in an `INSERT INTO` statement
11281#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11282#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11283#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11284pub enum TableObject {
11285    /// Table specified by name.
11286    /// Example:
11287    /// ```sql
11288    /// INSERT INTO my_table
11289    /// ```
11290    TableName(#[cfg_attr(feature = "visitor", visit(with = "visit_relation"))] ObjectName),
11291
11292    /// Table specified as a function.
11293    /// Example:
11294    /// ```sql
11295    /// INSERT INTO TABLE FUNCTION remote('localhost', default.simple_table)
11296    /// ```
11297    /// [Clickhouse](https://clickhouse.com/docs/en/sql-reference/table-functions)
11298    TableFunction(Function),
11299
11300    /// Table specified through a sub-query
11301    /// Example:
11302    /// ```sql
11303    /// INSERT INTO
11304    /// (SELECT employee_id, last_name, email, hire_date, job_id,  salary, commission_pct FROM employees)
11305    /// VALUES (207, 'Gregory', 'pgregory@example.com', sysdate, 'PU_CLERK', 1.2E3, NULL);
11306    /// ```
11307    /// [Oracle](https://docs.oracle.com/en/database/oracle/oracle-database/21/sqlrf/INSERT.html#GUID-903F8043-0254-4EE9-ACC1-CB8AC0AF3423__I2126242)
11308    TableQuery(Box<Query>),
11309}
11310
11311impl fmt::Display for TableObject {
11312    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11313        match self {
11314            Self::TableName(table_name) => write!(f, "{table_name}"),
11315            Self::TableFunction(func) => write!(f, "FUNCTION {func}"),
11316            Self::TableQuery(table_query) => write!(f, "({table_query})"),
11317        }
11318    }
11319}
11320
11321/// Represents a SET SESSION AUTHORIZATION statement
11322#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11323#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11324#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11325pub struct SetSessionAuthorizationParam {
11326    /// The scope for the `SET SESSION AUTHORIZATION` (e.g., GLOBAL/SESSION).
11327    pub scope: ContextModifier,
11328    /// The specific authorization parameter kind.
11329    pub kind: SetSessionAuthorizationParamKind,
11330}
11331
11332impl fmt::Display for SetSessionAuthorizationParam {
11333    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11334        write!(f, "{}", self.kind)
11335    }
11336}
11337
11338/// Represents the parameter kind for SET SESSION AUTHORIZATION
11339#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11340#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11341#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11342pub enum SetSessionAuthorizationParamKind {
11343    /// Default authorization
11344    Default,
11345
11346    /// User name
11347    User(Ident),
11348}
11349
11350impl fmt::Display for SetSessionAuthorizationParamKind {
11351    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11352        match self {
11353            SetSessionAuthorizationParamKind::Default => write!(f, "DEFAULT"),
11354            SetSessionAuthorizationParamKind::User(name) => write!(f, "{}", name),
11355        }
11356    }
11357}
11358
11359#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11360#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11361#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11362/// Kind of session parameter being set by `SET SESSION`.
11363pub enum SetSessionParamKind {
11364    /// Generic session parameter (name/value pair).
11365    Generic(SetSessionParamGeneric),
11366    /// Identity insert related parameter.
11367    IdentityInsert(SetSessionParamIdentityInsert),
11368    /// Offsets-related parameter.
11369    Offsets(SetSessionParamOffsets),
11370    /// Statistics-related parameter.
11371    Statistics(SetSessionParamStatistics),
11372}
11373
11374impl fmt::Display for SetSessionParamKind {
11375    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11376        match self {
11377            SetSessionParamKind::Generic(x) => write!(f, "{x}"),
11378            SetSessionParamKind::IdentityInsert(x) => write!(f, "{x}"),
11379            SetSessionParamKind::Offsets(x) => write!(f, "{x}"),
11380            SetSessionParamKind::Statistics(x) => write!(f, "{x}"),
11381        }
11382    }
11383}
11384
11385#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11386#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11387#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11388/// Generic `SET SESSION` parameter represented as name(s) and value.
11389pub struct SetSessionParamGeneric {
11390    /// Names of the session parameters being set.
11391    pub names: Vec<String>,
11392    /// The value to assign to the parameter(s).
11393    pub value: String,
11394}
11395
11396impl fmt::Display for SetSessionParamGeneric {
11397    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11398        write!(f, "{} {}", display_comma_separated(&self.names), self.value)
11399    }
11400}
11401
11402#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11403#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11404#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11405/// `IDENTITY_INSERT` session parameter for a specific object.
11406pub struct SetSessionParamIdentityInsert {
11407    /// Object name targeted by `IDENTITY_INSERT`.
11408    pub obj: ObjectName,
11409    /// Value (ON/OFF) for the identity insert setting.
11410    pub value: SessionParamValue,
11411}
11412
11413impl fmt::Display for SetSessionParamIdentityInsert {
11414    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11415        write!(f, "IDENTITY_INSERT {} {}", self.obj, self.value)
11416    }
11417}
11418
11419#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11420#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11421#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11422/// Offsets-related session parameter with keywords and a value.
11423pub struct SetSessionParamOffsets {
11424    /// Keywords specifying which offsets to modify.
11425    pub keywords: Vec<String>,
11426    /// Value (ON/OFF) for the offsets setting.
11427    pub value: SessionParamValue,
11428}
11429
11430impl fmt::Display for SetSessionParamOffsets {
11431    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11432        write!(
11433            f,
11434            "OFFSETS {} {}",
11435            display_comma_separated(&self.keywords),
11436            self.value
11437        )
11438    }
11439}
11440
11441#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11442#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11443#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11444/// Statistics-related session parameter specifying topic and value.
11445pub struct SetSessionParamStatistics {
11446    /// Statistics topic to set (IO/PROFILE/TIME/XML).
11447    pub topic: SessionParamStatsTopic,
11448    /// Value (ON/OFF) for the statistics topic.
11449    pub value: SessionParamValue,
11450}
11451
11452impl fmt::Display for SetSessionParamStatistics {
11453    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11454        write!(f, "STATISTICS {} {}", self.topic, self.value)
11455    }
11456}
11457
11458#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11459#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11460#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11461/// Topics available for session statistics configuration.
11462pub enum SessionParamStatsTopic {
11463    /// Input/output statistics.
11464    IO,
11465    /// Profile statistics.
11466    Profile,
11467    /// Time statistics.
11468    Time,
11469    /// XML-related statistics.
11470    Xml,
11471}
11472
11473impl fmt::Display for SessionParamStatsTopic {
11474    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11475        match self {
11476            SessionParamStatsTopic::IO => write!(f, "IO"),
11477            SessionParamStatsTopic::Profile => write!(f, "PROFILE"),
11478            SessionParamStatsTopic::Time => write!(f, "TIME"),
11479            SessionParamStatsTopic::Xml => write!(f, "XML"),
11480        }
11481    }
11482}
11483
11484#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11485#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11486#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11487/// Value for a session boolean-like parameter (ON/OFF).
11488pub enum SessionParamValue {
11489    /// Session parameter enabled.
11490    On,
11491    /// Session parameter disabled.
11492    Off,
11493}
11494
11495impl fmt::Display for SessionParamValue {
11496    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11497        match self {
11498            SessionParamValue::On => write!(f, "ON"),
11499            SessionParamValue::Off => write!(f, "OFF"),
11500        }
11501    }
11502}
11503
11504/// Snowflake StorageSerializationPolicy for Iceberg Tables
11505/// ```sql
11506/// [ STORAGE_SERIALIZATION_POLICY = { COMPATIBLE | OPTIMIZED } ]
11507/// ```
11508///
11509/// <https://docs.snowflake.com/en/sql-reference/sql/create-iceberg-table>
11510#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11511#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11512#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11513pub enum StorageSerializationPolicy {
11514    /// Use compatible serialization mode.
11515    Compatible,
11516    /// Use optimized serialization mode.
11517    Optimized,
11518}
11519
11520impl Display for StorageSerializationPolicy {
11521    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
11522        match self {
11523            StorageSerializationPolicy::Compatible => write!(f, "COMPATIBLE"),
11524            StorageSerializationPolicy::Optimized => write!(f, "OPTIMIZED"),
11525        }
11526    }
11527}
11528
11529/// Snowflake CatalogSyncNamespaceMode
11530/// ```sql
11531/// [ CATALOG_SYNC_NAMESPACE_MODE = { NEST | FLATTEN } ]
11532/// ```
11533///
11534/// <https://docs.snowflake.com/en/sql-reference/sql/create-database>
11535#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11536#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11537#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11538pub enum CatalogSyncNamespaceMode {
11539    /// Nest namespaces when syncing catalog.
11540    Nest,
11541    /// Flatten namespaces when syncing catalog.
11542    Flatten,
11543}
11544
11545impl Display for CatalogSyncNamespaceMode {
11546    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
11547        match self {
11548            CatalogSyncNamespaceMode::Nest => write!(f, "NEST"),
11549            CatalogSyncNamespaceMode::Flatten => write!(f, "FLATTEN"),
11550        }
11551    }
11552}
11553
11554/// Variants of the Snowflake `COPY INTO` statement
11555#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11556#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11557#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11558pub enum CopyIntoSnowflakeKind {
11559    /// Loads data from files to a table
11560    /// See: <https://docs.snowflake.com/en/sql-reference/sql/copy-into-table>
11561    Table,
11562    /// Unloads data from a table or query to external files
11563    /// See: <https://docs.snowflake.com/en/sql-reference/sql/copy-into-location>
11564    Location,
11565}
11566
11567#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11568#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11569#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11570/// `PRINT` statement for producing debug/output messages.
11571pub struct PrintStatement {
11572    /// The expression producing the message to print.
11573    pub message: Box<Expr>,
11574}
11575
11576impl fmt::Display for PrintStatement {
11577    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11578        write!(f, "PRINT {}", self.message)
11579    }
11580}
11581
11582/// The type of `WAITFOR` statement (MSSQL).
11583///
11584/// See: <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/waitfor-transact-sql>
11585#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11586#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11587#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11588pub enum WaitForType {
11589    /// `WAITFOR DELAY 'time_to_pass'`
11590    Delay,
11591    /// `WAITFOR TIME 'time_to_execute'`
11592    Time,
11593}
11594
11595impl fmt::Display for WaitForType {
11596    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11597        match self {
11598            WaitForType::Delay => write!(f, "DELAY"),
11599            WaitForType::Time => write!(f, "TIME"),
11600        }
11601    }
11602}
11603
11604/// MSSQL `WAITFOR` statement.
11605///
11606/// See: <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/waitfor-transact-sql>
11607#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11608#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11609#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11610pub struct WaitForStatement {
11611    /// `DELAY` or `TIME`.
11612    pub wait_type: WaitForType,
11613    /// The time expression.
11614    pub expr: Expr,
11615}
11616
11617impl fmt::Display for WaitForStatement {
11618    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11619        write!(f, "WAITFOR {} {}", self.wait_type, self.expr)
11620    }
11621}
11622
11623/// Represents a `Return` statement.
11624///
11625/// [MsSql triggers](https://learn.microsoft.com/en-us/sql/t-sql/statements/create-trigger-transact-sql)
11626/// [MsSql functions](https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql)
11627#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11628#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11629#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11630pub struct ReturnStatement {
11631    /// Optional return value expression.
11632    pub value: Option<ReturnStatementValue>,
11633}
11634
11635impl fmt::Display for ReturnStatement {
11636    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11637        match &self.value {
11638            Some(ReturnStatementValue::Expr(expr)) => write!(f, "RETURN {expr}"),
11639            None => write!(f, "RETURN"),
11640        }
11641    }
11642}
11643
11644/// Variants of a `RETURN` statement
11645#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11646#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11647#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11648pub enum ReturnStatementValue {
11649    /// Return an expression from a function or trigger.
11650    Expr(Expr),
11651}
11652
11653/// Represents an `OPEN` statement.
11654#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11655#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11656#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11657pub struct OpenStatement {
11658    /// Cursor name
11659    pub cursor_name: Ident,
11660}
11661
11662impl fmt::Display for OpenStatement {
11663    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11664        write!(f, "OPEN {}", self.cursor_name)
11665    }
11666}
11667
11668/// Specifies Include / Exclude NULL within UNPIVOT command.
11669/// For example
11670/// `UNPIVOT (column1 FOR new_column IN (col3, col4, col5, col6))`
11671#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11672#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11673#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11674pub enum NullInclusion {
11675    /// Include NULL values in the UNPIVOT output.
11676    IncludeNulls,
11677    /// Exclude NULL values from the UNPIVOT output.
11678    ExcludeNulls,
11679}
11680
11681impl fmt::Display for NullInclusion {
11682    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11683        match self {
11684            NullInclusion::IncludeNulls => write!(f, "INCLUDE NULLS"),
11685            NullInclusion::ExcludeNulls => write!(f, "EXCLUDE NULLS"),
11686        }
11687    }
11688}
11689
11690/// Checks membership of a value in a JSON array
11691///
11692/// Syntax:
11693/// ```sql
11694/// <value> MEMBER OF(<array>)
11695/// ```
11696/// [MySQL](https://dev.mysql.com/doc/refman/8.4/en/json-search-functions.html#operator_member-of)
11697#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11698#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11699#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11700pub struct MemberOf {
11701    /// The value to check for membership.
11702    pub value: Box<Expr>,
11703    /// The JSON array expression to check against.
11704    pub array: Box<Expr>,
11705}
11706
11707impl fmt::Display for MemberOf {
11708    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11709        write!(f, "{} MEMBER OF({})", self.value, self.array)
11710    }
11711}
11712
11713#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11714#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11715#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11716/// Represents an `EXPORT DATA` statement.
11717pub struct ExportData {
11718    /// Options for the export operation.
11719    pub options: Vec<SqlOption>,
11720    /// The query producing the data to export.
11721    pub query: Box<Query>,
11722    /// Optional named connection to use for export.
11723    pub connection: Option<ObjectName>,
11724}
11725
11726impl fmt::Display for ExportData {
11727    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11728        if let Some(connection) = &self.connection {
11729            write!(
11730                f,
11731                "EXPORT DATA WITH CONNECTION {connection} OPTIONS({}) AS {}",
11732                display_comma_separated(&self.options),
11733                self.query
11734            )
11735        } else {
11736            write!(
11737                f,
11738                "EXPORT DATA OPTIONS({}) AS {}",
11739                display_comma_separated(&self.options),
11740                self.query
11741            )
11742        }
11743    }
11744}
11745/// Creates a user
11746///
11747/// Syntax:
11748/// ```sql
11749/// CREATE [OR REPLACE] USER [IF NOT EXISTS] <name> [OPTIONS]
11750/// ```
11751///
11752/// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-user)
11753#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11754#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11755#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11756pub struct CreateUser {
11757    /// Replace existing user if present.
11758    pub or_replace: bool,
11759    /// Only create the user if it does not already exist.
11760    pub if_not_exists: bool,
11761    /// The name of the user to create.
11762    pub name: Ident,
11763    /// Key/value options for user creation.
11764    pub options: KeyValueOptions,
11765    /// Whether tags are specified using `WITH TAG`.
11766    pub with_tags: bool,
11767    /// Tags for the user.
11768    pub tags: KeyValueOptions,
11769}
11770
11771impl fmt::Display for CreateUser {
11772    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11773        write!(f, "CREATE")?;
11774        if self.or_replace {
11775            write!(f, " OR REPLACE")?;
11776        }
11777        write!(f, " USER")?;
11778        if self.if_not_exists {
11779            write!(f, " IF NOT EXISTS")?;
11780        }
11781        write!(f, " {}", self.name)?;
11782        if !self.options.options.is_empty() {
11783            write!(f, " {}", self.options)?;
11784        }
11785        if !self.tags.options.is_empty() {
11786            if self.with_tags {
11787                write!(f, " WITH")?;
11788            }
11789            write!(f, " TAG ({})", self.tags)?;
11790        }
11791        Ok(())
11792    }
11793}
11794
11795/// Modifies the properties of a user
11796///
11797/// [Snowflake Syntax:](https://docs.snowflake.com/en/sql-reference/sql/alter-user)
11798/// ```sql
11799/// ALTER USER [ IF EXISTS ] [ <name> ] [ OPTIONS ]
11800/// ```
11801///
11802/// [PostgreSQL Syntax:](https://www.postgresql.org/docs/current/sql-alteruser.html)
11803/// ```sql
11804/// ALTER USER <role_specification> [ WITH ] option [ ... ]
11805/// ```
11806#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11807#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11808#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11809pub struct AlterUser {
11810    /// Whether to only alter the user if it exists.
11811    pub if_exists: bool,
11812    /// The name of the user to alter.
11813    pub name: Ident,
11814    /// Optional new name for the user (Snowflake-specific).
11815    /// See: <https://docs.snowflake.com/en/sql-reference/sql/alter-user#syntax>
11816    pub rename_to: Option<Ident>,
11817    /// Reset the user's password.
11818    pub reset_password: bool,
11819    /// Abort all running queries for the user.
11820    pub abort_all_queries: bool,
11821    /// Optionally add a delegated role authorization.
11822    pub add_role_delegation: Option<AlterUserAddRoleDelegation>,
11823    /// Optionally remove a delegated role authorization.
11824    pub remove_role_delegation: Option<AlterUserRemoveRoleDelegation>,
11825    /// Enroll the user in MFA.
11826    pub enroll_mfa: bool,
11827    /// Set the default MFA method for the user.
11828    pub set_default_mfa_method: Option<MfaMethodKind>,
11829    /// Remove the user's default MFA method.
11830    pub remove_mfa_method: Option<MfaMethodKind>,
11831    /// Modify an MFA method for the user.
11832    pub modify_mfa_method: Option<AlterUserModifyMfaMethod>,
11833    /// Add an MFA OTP method with optional count.
11834    pub add_mfa_method_otp: Option<AlterUserAddMfaMethodOtp>,
11835    /// Set a user policy.
11836    pub set_policy: Option<AlterUserSetPolicy>,
11837    /// Unset a user policy.
11838    pub unset_policy: Option<UserPolicyKind>,
11839    /// Key/value tag options to set on the user.
11840    pub set_tag: KeyValueOptions,
11841    /// Tags to unset on the user.
11842    pub unset_tag: Vec<String>,
11843    /// Key/value properties to set on the user.
11844    pub set_props: KeyValueOptions,
11845    /// Properties to unset on the user.
11846    pub unset_props: Vec<String>,
11847    /// The following options are PostgreSQL-specific: <https://www.postgresql.org/docs/current/sql-alteruser.html>
11848    pub password: Option<AlterUserPassword>,
11849}
11850
11851/// ```sql
11852/// ALTER USER [ IF EXISTS ] [ <name> ] ADD DELEGATED AUTHORIZATION OF ROLE <role_name> TO SECURITY INTEGRATION <integration_name>
11853/// ```
11854#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11855#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11856#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11857pub struct AlterUserAddRoleDelegation {
11858    /// Role name to delegate.
11859    pub role: Ident,
11860    /// Security integration receiving the delegation.
11861    pub integration: Ident,
11862}
11863
11864/// ```sql
11865/// ALTER USER [ IF EXISTS ] [ <name> ] REMOVE DELEGATED { AUTHORIZATION OF ROLE <role_name> | AUTHORIZATIONS } FROM SECURITY INTEGRATION <integration_name>
11866/// ```
11867#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11868#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11869#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11870pub struct AlterUserRemoveRoleDelegation {
11871    /// Optional role name to remove delegation for.
11872    pub role: Option<Ident>,
11873    /// Security integration from which to remove delegation.
11874    pub integration: Ident,
11875}
11876
11877/// ```sql
11878/// ADD MFA METHOD OTP [ COUNT = number ]
11879/// ```
11880#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11881#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11882#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11883pub struct AlterUserAddMfaMethodOtp {
11884    /// Optional OTP count parameter.
11885    pub count: Option<ValueWithSpan>,
11886}
11887
11888/// ```sql
11889/// ALTER USER [ IF EXISTS ] [ <name> ] MODIFY MFA METHOD <mfa_method> SET COMMENT = '<string>'
11890/// ```
11891#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11892#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11893#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11894pub struct AlterUserModifyMfaMethod {
11895    /// The MFA method being modified.
11896    pub method: MfaMethodKind,
11897    /// The new comment for the MFA method.
11898    pub comment: String,
11899}
11900
11901/// Types of MFA methods
11902#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11903#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11904#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11905pub enum MfaMethodKind {
11906    /// PassKey (hardware or platform passkey) MFA method.
11907    PassKey,
11908    /// Time-based One-Time Password (TOTP) MFA method.
11909    Totp,
11910    /// Duo Security MFA method.
11911    Duo,
11912}
11913
11914impl fmt::Display for MfaMethodKind {
11915    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11916        match self {
11917            MfaMethodKind::PassKey => write!(f, "PASSKEY"),
11918            MfaMethodKind::Totp => write!(f, "TOTP"),
11919            MfaMethodKind::Duo => write!(f, "DUO"),
11920        }
11921    }
11922}
11923
11924/// ```sql
11925/// ALTER USER [ IF EXISTS ] [ <name> ] SET { AUTHENTICATION | PASSWORD | SESSION } POLICY <policy_name>
11926/// ```
11927#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11928#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11929#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11930pub struct AlterUserSetPolicy {
11931    /// The kind of user policy being set (authentication/password/session).
11932    pub policy_kind: UserPolicyKind,
11933    /// The identifier of the policy to apply.
11934    pub policy: Ident,
11935}
11936
11937/// Types of user-based policies
11938#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11939#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11940#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11941pub enum UserPolicyKind {
11942    /// Authentication policy.
11943    Authentication,
11944    /// Password policy.
11945    Password,
11946    /// Session policy.
11947    Session,
11948}
11949
11950impl fmt::Display for UserPolicyKind {
11951    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11952        match self {
11953            UserPolicyKind::Authentication => write!(f, "AUTHENTICATION"),
11954            UserPolicyKind::Password => write!(f, "PASSWORD"),
11955            UserPolicyKind::Session => write!(f, "SESSION"),
11956        }
11957    }
11958}
11959
11960impl fmt::Display for AlterUser {
11961    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11962        write!(f, "ALTER")?;
11963        write!(f, " USER")?;
11964        if self.if_exists {
11965            write!(f, " IF EXISTS")?;
11966        }
11967        write!(f, " {}", self.name)?;
11968        if let Some(new_name) = &self.rename_to {
11969            write!(f, " RENAME TO {new_name}")?;
11970        }
11971        if self.reset_password {
11972            write!(f, " RESET PASSWORD")?;
11973        }
11974        if self.abort_all_queries {
11975            write!(f, " ABORT ALL QUERIES")?;
11976        }
11977        if let Some(role_delegation) = &self.add_role_delegation {
11978            let role = &role_delegation.role;
11979            let integration = &role_delegation.integration;
11980            write!(
11981                f,
11982                " ADD DELEGATED AUTHORIZATION OF ROLE {role} TO SECURITY INTEGRATION {integration}"
11983            )?;
11984        }
11985        if let Some(role_delegation) = &self.remove_role_delegation {
11986            write!(f, " REMOVE DELEGATED")?;
11987            match &role_delegation.role {
11988                Some(role) => write!(f, " AUTHORIZATION OF ROLE {role}")?,
11989                None => write!(f, " AUTHORIZATIONS")?,
11990            }
11991            let integration = &role_delegation.integration;
11992            write!(f, " FROM SECURITY INTEGRATION {integration}")?;
11993        }
11994        if self.enroll_mfa {
11995            write!(f, " ENROLL MFA")?;
11996        }
11997        if let Some(method) = &self.set_default_mfa_method {
11998            write!(f, " SET DEFAULT_MFA_METHOD {method}")?
11999        }
12000        if let Some(method) = &self.remove_mfa_method {
12001            write!(f, " REMOVE MFA METHOD {method}")?;
12002        }
12003        if let Some(modify) = &self.modify_mfa_method {
12004            let method = &modify.method;
12005            let comment = &modify.comment;
12006            write!(
12007                f,
12008                " MODIFY MFA METHOD {method} SET COMMENT '{}'",
12009                value::escape_single_quote_string(comment)
12010            )?;
12011        }
12012        if let Some(add_mfa_method_otp) = &self.add_mfa_method_otp {
12013            write!(f, " ADD MFA METHOD OTP")?;
12014            if let Some(count) = &add_mfa_method_otp.count {
12015                write!(f, " COUNT = {count}")?;
12016            }
12017        }
12018        if let Some(policy) = &self.set_policy {
12019            let policy_kind = &policy.policy_kind;
12020            let name = &policy.policy;
12021            write!(f, " SET {policy_kind} POLICY {name}")?;
12022        }
12023        if let Some(policy_kind) = &self.unset_policy {
12024            write!(f, " UNSET {policy_kind} POLICY")?;
12025        }
12026        if !self.set_tag.options.is_empty() {
12027            write!(f, " SET TAG {}", self.set_tag)?;
12028        }
12029        if !self.unset_tag.is_empty() {
12030            write!(f, " UNSET TAG {}", display_comma_separated(&self.unset_tag))?;
12031        }
12032        let has_props = !self.set_props.options.is_empty();
12033        if has_props {
12034            write!(f, " SET")?;
12035            write!(f, " {}", &self.set_props)?;
12036        }
12037        if !self.unset_props.is_empty() {
12038            write!(f, " UNSET {}", display_comma_separated(&self.unset_props))?;
12039        }
12040        if let Some(password) = &self.password {
12041            write!(f, " {}", password)?;
12042        }
12043        Ok(())
12044    }
12045}
12046
12047/// ```sql
12048/// ALTER USER <role_specification> [ WITH ] PASSWORD { 'password' | NULL }``
12049/// ```
12050#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
12051#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
12052#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
12053pub struct AlterUserPassword {
12054    /// Whether the password is encrypted.
12055    pub encrypted: bool,
12056    /// The password string, or `None` for `NULL`.
12057    pub password: Option<String>,
12058}
12059
12060impl Display for AlterUserPassword {
12061    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
12062        if self.encrypted {
12063            write!(f, "ENCRYPTED ")?;
12064        }
12065        write!(f, "PASSWORD")?;
12066        match &self.password {
12067            None => write!(f, " NULL")?,
12068            Some(password) => write!(f, " '{}'", value::escape_single_quote_string(password))?,
12069        }
12070        Ok(())
12071    }
12072}
12073
12074/// Specifies how to create a new table based on an existing table's schema.
12075/// '''sql
12076/// CREATE TABLE new LIKE old ...
12077/// '''
12078#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
12079#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
12080#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
12081pub enum CreateTableLikeKind {
12082    /// '''sql
12083    /// CREATE TABLE new (LIKE old ...)
12084    /// '''
12085    /// [Redshift](https://docs.aws.amazon.com/redshift/latest/dg/r_CREATE_TABLE_NEW.html)
12086    Parenthesized(CreateTableLike),
12087    /// '''sql
12088    /// CREATE TABLE new LIKE old ...
12089    /// '''
12090    /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-table#label-create-table-like)
12091    /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_table_like)
12092    Plain(CreateTableLike),
12093}
12094
12095#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
12096#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
12097#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
12098/// Controls whether defaults are included when creating a table FROM/LILE another.
12099pub enum CreateTableLikeDefaults {
12100    /// Include default values from the source table.
12101    Including,
12102    /// Exclude default values from the source table.
12103    Excluding,
12104}
12105
12106impl fmt::Display for CreateTableLikeDefaults {
12107    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
12108        match self {
12109            CreateTableLikeDefaults::Including => write!(f, "INCLUDING DEFAULTS"),
12110            CreateTableLikeDefaults::Excluding => write!(f, "EXCLUDING DEFAULTS"),
12111        }
12112    }
12113}
12114
12115#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
12116#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
12117#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
12118/// Represents the `LIKE` clause of a `CREATE TABLE` statement.
12119pub struct CreateTableLike {
12120    /// The source table name to copy the schema from.
12121    pub name: ObjectName,
12122    /// Optional behavior controlling whether defaults are copied.
12123    pub defaults: Option<CreateTableLikeDefaults>,
12124}
12125
12126impl fmt::Display for CreateTableLike {
12127    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
12128        write!(f, "LIKE {}", self.name)?;
12129        if let Some(defaults) = &self.defaults {
12130            write!(f, " {defaults}")?;
12131        }
12132        Ok(())
12133    }
12134}
12135
12136/// Specifies the refresh mode for the dynamic table.
12137///
12138/// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-dynamic-table)
12139#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
12140#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
12141#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
12142pub enum RefreshModeKind {
12143    /// Automatic refresh mode (`AUTO`).
12144    Auto,
12145    /// Full refresh mode (`FULL`).
12146    Full,
12147    /// Incremental refresh mode (`INCREMENTAL`).
12148    Incremental,
12149}
12150
12151impl fmt::Display for RefreshModeKind {
12152    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
12153        match self {
12154            RefreshModeKind::Auto => write!(f, "AUTO"),
12155            RefreshModeKind::Full => write!(f, "FULL"),
12156            RefreshModeKind::Incremental => write!(f, "INCREMENTAL"),
12157        }
12158    }
12159}
12160
12161/// Specifies the behavior of the initial refresh of the dynamic table.
12162///
12163/// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-dynamic-table)
12164#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
12165#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
12166#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
12167pub enum InitializeKind {
12168    /// Initialize on creation (`ON CREATE`).
12169    OnCreate,
12170    /// Initialize on schedule (`ON SCHEDULE`).
12171    OnSchedule,
12172}
12173
12174impl fmt::Display for InitializeKind {
12175    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
12176        match self {
12177            InitializeKind::OnCreate => write!(f, "ON_CREATE"),
12178            InitializeKind::OnSchedule => write!(f, "ON_SCHEDULE"),
12179        }
12180    }
12181}
12182
12183/// Re-sorts rows and reclaims space in either a specified table or all tables in the current database
12184///
12185/// '''sql
12186/// VACUUM [ FULL | SORT ONLY | DELETE ONLY | REINDEX | RECLUSTER ] [ \[ table_name \] [ TO threshold PERCENT ] \[ BOOST \] ]
12187/// '''
12188/// [Redshift](https://docs.aws.amazon.com/redshift/latest/dg/r_VACUUM_command.html)
12189#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
12190#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
12191#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
12192pub struct VacuumStatement {
12193    /// Whether `FULL` was specified.
12194    pub full: bool,
12195    /// Whether `SORT ONLY` was specified.
12196    pub sort_only: bool,
12197    /// Whether `DELETE ONLY` was specified.
12198    pub delete_only: bool,
12199    /// Whether `REINDEX` was specified.
12200    pub reindex: bool,
12201    /// Whether `RECLUSTER` was specified.
12202    pub recluster: bool,
12203    /// Optional table to run `VACUUM` on.
12204    pub table_name: Option<ObjectName>,
12205    /// Optional threshold value (percent) for `TO threshold PERCENT`.
12206    pub threshold: Option<ValueWithSpan>,
12207    /// Whether `BOOST` was specified.
12208    pub boost: bool,
12209}
12210
12211impl fmt::Display for VacuumStatement {
12212    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
12213        write!(
12214            f,
12215            "VACUUM{}{}{}{}{}",
12216            if self.full { " FULL" } else { "" },
12217            if self.sort_only { " SORT ONLY" } else { "" },
12218            if self.delete_only { " DELETE ONLY" } else { "" },
12219            if self.reindex { " REINDEX" } else { "" },
12220            if self.recluster { " RECLUSTER" } else { "" },
12221        )?;
12222        if let Some(table_name) = &self.table_name {
12223            write!(f, " {table_name}")?;
12224        }
12225        if let Some(threshold) = &self.threshold {
12226            write!(f, " TO {threshold} PERCENT")?;
12227        }
12228        if self.boost {
12229            write!(f, " BOOST")?;
12230        }
12231        Ok(())
12232    }
12233}
12234
12235/// Variants of the RESET statement
12236#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
12237#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
12238#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
12239pub enum Reset {
12240    /// Resets all session parameters to their default values.
12241    ALL,
12242
12243    /// Resets a specific session parameter to its default value.
12244    ConfigurationParameter(ObjectName),
12245}
12246
12247/// Resets a session parameter to its default value.
12248/// ```sql
12249/// RESET { ALL | <configuration_parameter> }
12250/// ```
12251#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
12252#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
12253#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
12254pub struct ResetStatement {
12255    /// The reset action to perform (either `ALL` or a specific configuration parameter).
12256    pub reset: Reset,
12257}
12258
12259/// Query optimizer hints are optionally supported comments after the
12260/// `SELECT`, `INSERT`, `UPDATE`, `REPLACE`, `MERGE`, and `DELETE` keywords in
12261/// the corresponding statements.
12262///
12263/// See [Select::optimizer_hints]
12264#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
12265#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
12266#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
12267pub struct OptimizerHint {
12268    /// An optional prefix between the comment marker and `+`.
12269    ///
12270    /// Standard optimizer hints like `/*+ ... */` have an empty prefix,
12271    /// while system-specific hints like `/*abc+ ... */` have `prefix = "abc"`.
12272    /// The prefix is any sequence of ASCII alphanumeric characters
12273    /// immediately before the `+` marker.
12274    pub prefix: String,
12275    /// the raw text of the optimizer hint without its markers
12276    pub text: String,
12277    /// the style of the comment which `text` was extracted from,
12278    /// e.g. `/*+...*/` or `--+...`
12279    ///
12280    /// Not all dialects support all styles, though.
12281    pub style: OptimizerHintStyle,
12282}
12283
12284/// The commentary style of an [optimizer hint](OptimizerHint)
12285#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
12286#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
12287#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
12288pub enum OptimizerHintStyle {
12289    /// A hint corresponding to a single line comment,
12290    /// e.g. `--+ LEADING(v.e v.d t)`
12291    SingleLine {
12292        /// the comment prefix, e.g. `--`
12293        prefix: String,
12294    },
12295    /// A hint corresponding to a multi line comment,
12296    /// e.g. `/*+ LEADING(v.e v.d t) */`
12297    MultiLine,
12298}
12299
12300impl fmt::Display for OptimizerHint {
12301    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
12302        match &self.style {
12303            OptimizerHintStyle::SingleLine { prefix } => {
12304                f.write_str(prefix)?;
12305                f.write_str(&self.prefix)?;
12306                f.write_str("+")?;
12307                f.write_str(&self.text)
12308            }
12309            OptimizerHintStyle::MultiLine => {
12310                f.write_str("/*")?;
12311                f.write_str(&self.prefix)?;
12312                f.write_str("+")?;
12313                f.write_str(&self.text)?;
12314                f.write_str("*/")
12315            }
12316        }
12317    }
12318}
12319
12320impl fmt::Display for ResetStatement {
12321    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
12322        match &self.reset {
12323            Reset::ALL => write!(f, "RESET ALL"),
12324            Reset::ConfigurationParameter(param) => write!(f, "RESET {}", param),
12325        }
12326    }
12327}
12328
12329impl From<Set> for Statement {
12330    fn from(s: Set) -> Self {
12331        Self::Set(s)
12332    }
12333}
12334
12335impl From<Query> for Statement {
12336    fn from(q: Query) -> Self {
12337        Box::new(q).into()
12338    }
12339}
12340
12341impl From<Box<Query>> for Statement {
12342    fn from(q: Box<Query>) -> Self {
12343        Self::Query(q)
12344    }
12345}
12346
12347impl From<Insert> for Statement {
12348    fn from(i: Insert) -> Self {
12349        Self::Insert(i)
12350    }
12351}
12352
12353impl From<Update> for Statement {
12354    fn from(u: Update) -> Self {
12355        Self::Update(u)
12356    }
12357}
12358
12359impl From<CreateView> for Statement {
12360    fn from(cv: CreateView) -> Self {
12361        Self::CreateView(cv)
12362    }
12363}
12364
12365impl From<CreateRole> for Statement {
12366    fn from(cr: CreateRole) -> Self {
12367        Self::CreateRole(cr)
12368    }
12369}
12370
12371impl From<AlterTable> for Statement {
12372    fn from(at: AlterTable) -> Self {
12373        Self::AlterTable(at)
12374    }
12375}
12376
12377impl From<DropFunction> for Statement {
12378    fn from(df: DropFunction) -> Self {
12379        Self::DropFunction(df)
12380    }
12381}
12382
12383impl From<CreateExtension> for Statement {
12384    fn from(ce: CreateExtension) -> Self {
12385        Self::CreateExtension(ce)
12386    }
12387}
12388
12389impl From<CreateCollation> for Statement {
12390    fn from(c: CreateCollation) -> Self {
12391        Self::CreateCollation(c)
12392    }
12393}
12394
12395impl From<DropExtension> for Statement {
12396    fn from(de: DropExtension) -> Self {
12397        Self::DropExtension(de)
12398    }
12399}
12400
12401impl From<CaseStatement> for Statement {
12402    fn from(c: CaseStatement) -> Self {
12403        Self::Case(c)
12404    }
12405}
12406
12407impl From<IfStatement> for Statement {
12408    fn from(i: IfStatement) -> Self {
12409        Self::If(i)
12410    }
12411}
12412
12413impl From<WhileStatement> for Statement {
12414    fn from(w: WhileStatement) -> Self {
12415        Self::While(w)
12416    }
12417}
12418
12419impl From<RaiseStatement> for Statement {
12420    fn from(r: RaiseStatement) -> Self {
12421        Self::Raise(r)
12422    }
12423}
12424
12425impl From<ThrowStatement> for Statement {
12426    fn from(t: ThrowStatement) -> Self {
12427        Self::Throw(t)
12428    }
12429}
12430
12431impl From<Function> for Statement {
12432    fn from(f: Function) -> Self {
12433        Self::Call(f)
12434    }
12435}
12436
12437impl From<OpenStatement> for Statement {
12438    fn from(o: OpenStatement) -> Self {
12439        Self::Open(o)
12440    }
12441}
12442
12443impl From<Delete> for Statement {
12444    fn from(d: Delete) -> Self {
12445        Self::Delete(d)
12446    }
12447}
12448
12449impl From<CreateTable> for Statement {
12450    fn from(c: CreateTable) -> Self {
12451        Self::CreateTable(c)
12452    }
12453}
12454
12455impl From<CreateIndex> for Statement {
12456    fn from(c: CreateIndex) -> Self {
12457        Self::CreateIndex(c)
12458    }
12459}
12460
12461impl From<CreateServerStatement> for Statement {
12462    fn from(c: CreateServerStatement) -> Self {
12463        Self::CreateServer(c)
12464    }
12465}
12466
12467impl From<CreateConnector> for Statement {
12468    fn from(c: CreateConnector) -> Self {
12469        Self::CreateConnector(c)
12470    }
12471}
12472
12473impl From<CreateOperator> for Statement {
12474    fn from(c: CreateOperator) -> Self {
12475        Self::CreateOperator(c)
12476    }
12477}
12478
12479impl From<CreateOperatorFamily> for Statement {
12480    fn from(c: CreateOperatorFamily) -> Self {
12481        Self::CreateOperatorFamily(c)
12482    }
12483}
12484
12485impl From<CreateOperatorClass> for Statement {
12486    fn from(c: CreateOperatorClass) -> Self {
12487        Self::CreateOperatorClass(c)
12488    }
12489}
12490
12491impl From<AlterSchema> for Statement {
12492    fn from(a: AlterSchema) -> Self {
12493        Self::AlterSchema(a)
12494    }
12495}
12496
12497impl From<AlterFunction> for Statement {
12498    fn from(a: AlterFunction) -> Self {
12499        Self::AlterFunction(a)
12500    }
12501}
12502
12503impl From<AlterType> for Statement {
12504    fn from(a: AlterType) -> Self {
12505        Self::AlterType(a)
12506    }
12507}
12508
12509impl From<AlterCollation> for Statement {
12510    fn from(a: AlterCollation) -> Self {
12511        Self::AlterCollation(a)
12512    }
12513}
12514
12515impl From<AlterOperator> for Statement {
12516    fn from(a: AlterOperator) -> Self {
12517        Self::AlterOperator(a)
12518    }
12519}
12520
12521impl From<AlterOperatorFamily> for Statement {
12522    fn from(a: AlterOperatorFamily) -> Self {
12523        Self::AlterOperatorFamily(a)
12524    }
12525}
12526
12527impl From<AlterOperatorClass> for Statement {
12528    fn from(a: AlterOperatorClass) -> Self {
12529        Self::AlterOperatorClass(a)
12530    }
12531}
12532
12533impl From<Merge> for Statement {
12534    fn from(m: Merge) -> Self {
12535        Self::Merge(m)
12536    }
12537}
12538
12539impl From<AlterUser> for Statement {
12540    fn from(a: AlterUser) -> Self {
12541        Self::AlterUser(a)
12542    }
12543}
12544
12545impl From<DropDomain> for Statement {
12546    fn from(d: DropDomain) -> Self {
12547        Self::DropDomain(d)
12548    }
12549}
12550
12551impl From<ShowCharset> for Statement {
12552    fn from(s: ShowCharset) -> Self {
12553        Self::ShowCharset(s)
12554    }
12555}
12556
12557impl From<ShowObjects> for Statement {
12558    fn from(s: ShowObjects) -> Self {
12559        Self::ShowObjects(s)
12560    }
12561}
12562
12563impl From<Use> for Statement {
12564    fn from(u: Use) -> Self {
12565        Self::Use(u)
12566    }
12567}
12568
12569impl From<CreateFunction> for Statement {
12570    fn from(c: CreateFunction) -> Self {
12571        Self::CreateFunction(c)
12572    }
12573}
12574
12575impl From<CreateTrigger> for Statement {
12576    fn from(c: CreateTrigger) -> Self {
12577        Self::CreateTrigger(c)
12578    }
12579}
12580
12581impl From<DropTrigger> for Statement {
12582    fn from(d: DropTrigger) -> Self {
12583        Self::DropTrigger(d)
12584    }
12585}
12586
12587impl From<DropOperator> for Statement {
12588    fn from(d: DropOperator) -> Self {
12589        Self::DropOperator(d)
12590    }
12591}
12592
12593impl From<DropOperatorFamily> for Statement {
12594    fn from(d: DropOperatorFamily) -> Self {
12595        Self::DropOperatorFamily(d)
12596    }
12597}
12598
12599impl From<DropOperatorClass> for Statement {
12600    fn from(d: DropOperatorClass) -> Self {
12601        Self::DropOperatorClass(d)
12602    }
12603}
12604
12605impl From<DenyStatement> for Statement {
12606    fn from(d: DenyStatement) -> Self {
12607        Self::Deny(d)
12608    }
12609}
12610
12611impl From<CreateDomain> for Statement {
12612    fn from(c: CreateDomain) -> Self {
12613        Self::CreateDomain(c)
12614    }
12615}
12616
12617impl From<RenameTable> for Statement {
12618    fn from(r: RenameTable) -> Self {
12619        vec![r].into()
12620    }
12621}
12622
12623impl From<Vec<RenameTable>> for Statement {
12624    fn from(r: Vec<RenameTable>) -> Self {
12625        Self::RenameTable(r)
12626    }
12627}
12628
12629impl From<PrintStatement> for Statement {
12630    fn from(p: PrintStatement) -> Self {
12631        Self::Print(p)
12632    }
12633}
12634
12635impl From<ReturnStatement> for Statement {
12636    fn from(r: ReturnStatement) -> Self {
12637        Self::Return(r)
12638    }
12639}
12640
12641impl From<ExportData> for Statement {
12642    fn from(e: ExportData) -> Self {
12643        Self::ExportData(e)
12644    }
12645}
12646
12647impl From<CreateUser> for Statement {
12648    fn from(c: CreateUser) -> Self {
12649        Self::CreateUser(c)
12650    }
12651}
12652
12653impl From<VacuumStatement> for Statement {
12654    fn from(v: VacuumStatement) -> Self {
12655        Self::Vacuum(v)
12656    }
12657}
12658
12659impl From<ResetStatement> for Statement {
12660    fn from(r: ResetStatement) -> Self {
12661        Self::Reset(r)
12662    }
12663}
12664
12665#[cfg(test)]
12666mod tests {
12667    use crate::tokenizer::Location;
12668
12669    use super::*;
12670
12671    #[test]
12672    fn test_window_frame_default() {
12673        let window_frame = WindowFrame::default();
12674        assert_eq!(WindowFrameBound::Preceding(None), window_frame.start_bound);
12675    }
12676
12677    #[test]
12678    fn test_grouping_sets_display() {
12679        // a and b in different group
12680        let grouping_sets = Expr::GroupingSets(vec![
12681            vec![Expr::Identifier(Ident::new("a"))],
12682            vec![Expr::Identifier(Ident::new("b"))],
12683        ]);
12684        assert_eq!("GROUPING SETS ((a), (b))", format!("{grouping_sets}"));
12685
12686        // a and b in the same group
12687        let grouping_sets = Expr::GroupingSets(vec![vec![
12688            Expr::Identifier(Ident::new("a")),
12689            Expr::Identifier(Ident::new("b")),
12690        ]]);
12691        assert_eq!("GROUPING SETS ((a, b))", format!("{grouping_sets}"));
12692
12693        // (a, b) and (c, d) in different group
12694        let grouping_sets = Expr::GroupingSets(vec![
12695            vec![
12696                Expr::Identifier(Ident::new("a")),
12697                Expr::Identifier(Ident::new("b")),
12698            ],
12699            vec![
12700                Expr::Identifier(Ident::new("c")),
12701                Expr::Identifier(Ident::new("d")),
12702            ],
12703        ]);
12704        assert_eq!("GROUPING SETS ((a, b), (c, d))", format!("{grouping_sets}"));
12705    }
12706
12707    #[test]
12708    fn test_rollup_display() {
12709        let rollup = Expr::Rollup(vec![vec![Expr::Identifier(Ident::new("a"))]]);
12710        assert_eq!("ROLLUP (a)", format!("{rollup}"));
12711
12712        let rollup = Expr::Rollup(vec![vec![
12713            Expr::Identifier(Ident::new("a")),
12714            Expr::Identifier(Ident::new("b")),
12715        ]]);
12716        assert_eq!("ROLLUP ((a, b))", format!("{rollup}"));
12717
12718        let rollup = Expr::Rollup(vec![
12719            vec![Expr::Identifier(Ident::new("a"))],
12720            vec![Expr::Identifier(Ident::new("b"))],
12721        ]);
12722        assert_eq!("ROLLUP (a, b)", format!("{rollup}"));
12723
12724        let rollup = Expr::Rollup(vec![
12725            vec![Expr::Identifier(Ident::new("a"))],
12726            vec![
12727                Expr::Identifier(Ident::new("b")),
12728                Expr::Identifier(Ident::new("c")),
12729            ],
12730            vec![Expr::Identifier(Ident::new("d"))],
12731        ]);
12732        assert_eq!("ROLLUP (a, (b, c), d)", format!("{rollup}"));
12733    }
12734
12735    #[test]
12736    fn test_cube_display() {
12737        let cube = Expr::Cube(vec![vec![Expr::Identifier(Ident::new("a"))]]);
12738        assert_eq!("CUBE (a)", format!("{cube}"));
12739
12740        let cube = Expr::Cube(vec![vec![
12741            Expr::Identifier(Ident::new("a")),
12742            Expr::Identifier(Ident::new("b")),
12743        ]]);
12744        assert_eq!("CUBE ((a, b))", format!("{cube}"));
12745
12746        let cube = Expr::Cube(vec![
12747            vec![Expr::Identifier(Ident::new("a"))],
12748            vec![Expr::Identifier(Ident::new("b"))],
12749        ]);
12750        assert_eq!("CUBE (a, b)", format!("{cube}"));
12751
12752        let cube = Expr::Cube(vec![
12753            vec![Expr::Identifier(Ident::new("a"))],
12754            vec![
12755                Expr::Identifier(Ident::new("b")),
12756                Expr::Identifier(Ident::new("c")),
12757            ],
12758            vec![Expr::Identifier(Ident::new("d"))],
12759        ]);
12760        assert_eq!("CUBE (a, (b, c), d)", format!("{cube}"));
12761    }
12762
12763    #[test]
12764    fn test_interval_display() {
12765        let interval = Expr::Interval(Interval {
12766            value: Box::new(Expr::Value(
12767                Value::SingleQuotedString(String::from("123:45.67")).with_empty_span(),
12768            )),
12769            leading_field: Some(DateTimeField::Minute),
12770            leading_precision: Some(10),
12771            last_field: Some(DateTimeField::Second),
12772            fractional_seconds_precision: Some(9),
12773        });
12774        assert_eq!(
12775            "INTERVAL '123:45.67' MINUTE (10) TO SECOND (9)",
12776            format!("{interval}"),
12777        );
12778
12779        let interval = Expr::Interval(Interval {
12780            value: Box::new(Expr::Value(
12781                Value::SingleQuotedString(String::from("5")).with_empty_span(),
12782            )),
12783            leading_field: Some(DateTimeField::Second),
12784            leading_precision: Some(1),
12785            last_field: None,
12786            fractional_seconds_precision: Some(3),
12787        });
12788        assert_eq!("INTERVAL '5' SECOND (1, 3)", format!("{interval}"));
12789    }
12790
12791    #[test]
12792    fn test_one_or_many_with_parens_deref() {
12793        use core::ops::Index;
12794
12795        let one = OneOrManyWithParens::One("a");
12796
12797        assert_eq!(one.deref(), &["a"]);
12798        assert_eq!(<OneOrManyWithParens<_> as Deref>::deref(&one), &["a"]);
12799
12800        assert_eq!(one[0], "a");
12801        assert_eq!(one.index(0), &"a");
12802        assert_eq!(
12803            <<OneOrManyWithParens<_> as Deref>::Target as Index<usize>>::index(&one, 0),
12804            &"a"
12805        );
12806
12807        assert_eq!(one.len(), 1);
12808        assert_eq!(<OneOrManyWithParens<_> as Deref>::Target::len(&one), 1);
12809
12810        let many1 = OneOrManyWithParens::Many(vec!["b"]);
12811
12812        assert_eq!(many1.deref(), &["b"]);
12813        assert_eq!(<OneOrManyWithParens<_> as Deref>::deref(&many1), &["b"]);
12814
12815        assert_eq!(many1[0], "b");
12816        assert_eq!(many1.index(0), &"b");
12817        assert_eq!(
12818            <<OneOrManyWithParens<_> as Deref>::Target as Index<usize>>::index(&many1, 0),
12819            &"b"
12820        );
12821
12822        assert_eq!(many1.len(), 1);
12823        assert_eq!(<OneOrManyWithParens<_> as Deref>::Target::len(&many1), 1);
12824
12825        let many2 = OneOrManyWithParens::Many(vec!["c", "d"]);
12826
12827        assert_eq!(many2.deref(), &["c", "d"]);
12828        assert_eq!(
12829            <OneOrManyWithParens<_> as Deref>::deref(&many2),
12830            &["c", "d"]
12831        );
12832
12833        assert_eq!(many2[0], "c");
12834        assert_eq!(many2.index(0), &"c");
12835        assert_eq!(
12836            <<OneOrManyWithParens<_> as Deref>::Target as Index<usize>>::index(&many2, 0),
12837            &"c"
12838        );
12839
12840        assert_eq!(many2[1], "d");
12841        assert_eq!(many2.index(1), &"d");
12842        assert_eq!(
12843            <<OneOrManyWithParens<_> as Deref>::Target as Index<usize>>::index(&many2, 1),
12844            &"d"
12845        );
12846
12847        assert_eq!(many2.len(), 2);
12848        assert_eq!(<OneOrManyWithParens<_> as Deref>::Target::len(&many2), 2);
12849    }
12850
12851    #[test]
12852    fn test_one_or_many_with_parens_as_ref() {
12853        let one = OneOrManyWithParens::One("a");
12854
12855        assert_eq!(one.as_ref(), &["a"]);
12856        assert_eq!(<OneOrManyWithParens<_> as AsRef<_>>::as_ref(&one), &["a"]);
12857
12858        let many1 = OneOrManyWithParens::Many(vec!["b"]);
12859
12860        assert_eq!(many1.as_ref(), &["b"]);
12861        assert_eq!(<OneOrManyWithParens<_> as AsRef<_>>::as_ref(&many1), &["b"]);
12862
12863        let many2 = OneOrManyWithParens::Many(vec!["c", "d"]);
12864
12865        assert_eq!(many2.as_ref(), &["c", "d"]);
12866        assert_eq!(
12867            <OneOrManyWithParens<_> as AsRef<_>>::as_ref(&many2),
12868            &["c", "d"]
12869        );
12870    }
12871
12872    #[test]
12873    fn test_one_or_many_with_parens_ref_into_iter() {
12874        let one = OneOrManyWithParens::One("a");
12875
12876        assert_eq!(Vec::from_iter(&one), vec![&"a"]);
12877
12878        let many1 = OneOrManyWithParens::Many(vec!["b"]);
12879
12880        assert_eq!(Vec::from_iter(&many1), vec![&"b"]);
12881
12882        let many2 = OneOrManyWithParens::Many(vec!["c", "d"]);
12883
12884        assert_eq!(Vec::from_iter(&many2), vec![&"c", &"d"]);
12885    }
12886
12887    #[test]
12888    fn test_one_or_many_with_parens_value_into_iter() {
12889        use core::iter::once;
12890
12891        //tests that our iterator implemented methods behaves exactly as it's inner iterator, at every step up to n calls to next/next_back
12892        fn test_steps<I>(ours: OneOrManyWithParens<usize>, inner: I, n: usize)
12893        where
12894            I: IntoIterator<Item = usize, IntoIter: DoubleEndedIterator + Clone> + Clone,
12895        {
12896            fn checks<I>(ours: OneOrManyWithParensIntoIter<usize>, inner: I)
12897            where
12898                I: Iterator<Item = usize> + Clone + DoubleEndedIterator,
12899            {
12900                assert_eq!(ours.size_hint(), inner.size_hint());
12901                assert_eq!(ours.clone().count(), inner.clone().count());
12902
12903                assert_eq!(
12904                    ours.clone().fold(1, |a, v| a + v),
12905                    inner.clone().fold(1, |a, v| a + v)
12906                );
12907
12908                assert_eq!(Vec::from_iter(ours.clone()), Vec::from_iter(inner.clone()));
12909                assert_eq!(
12910                    Vec::from_iter(ours.clone().rev()),
12911                    Vec::from_iter(inner.clone().rev())
12912                );
12913            }
12914
12915            let mut ours_next = ours.clone().into_iter();
12916            let mut inner_next = inner.clone().into_iter();
12917
12918            for _ in 0..n {
12919                checks(ours_next.clone(), inner_next.clone());
12920
12921                assert_eq!(ours_next.next(), inner_next.next());
12922            }
12923
12924            let mut ours_next_back = ours.clone().into_iter();
12925            let mut inner_next_back = inner.clone().into_iter();
12926
12927            for _ in 0..n {
12928                checks(ours_next_back.clone(), inner_next_back.clone());
12929
12930                assert_eq!(ours_next_back.next_back(), inner_next_back.next_back());
12931            }
12932
12933            let mut ours_mixed = ours.clone().into_iter();
12934            let mut inner_mixed = inner.clone().into_iter();
12935
12936            for i in 0..n {
12937                checks(ours_mixed.clone(), inner_mixed.clone());
12938
12939                if i % 2 == 0 {
12940                    assert_eq!(ours_mixed.next_back(), inner_mixed.next_back());
12941                } else {
12942                    assert_eq!(ours_mixed.next(), inner_mixed.next());
12943                }
12944            }
12945
12946            let mut ours_mixed2 = ours.into_iter();
12947            let mut inner_mixed2 = inner.into_iter();
12948
12949            for i in 0..n {
12950                checks(ours_mixed2.clone(), inner_mixed2.clone());
12951
12952                if i % 2 == 0 {
12953                    assert_eq!(ours_mixed2.next(), inner_mixed2.next());
12954                } else {
12955                    assert_eq!(ours_mixed2.next_back(), inner_mixed2.next_back());
12956                }
12957            }
12958        }
12959
12960        test_steps(OneOrManyWithParens::One(1), once(1), 3);
12961        test_steps(OneOrManyWithParens::Many(vec![2]), vec![2], 3);
12962        test_steps(OneOrManyWithParens::Many(vec![3, 4]), vec![3, 4], 4);
12963    }
12964
12965    // Tests that the position in the code of an `Ident` does not affect its
12966    // ordering.
12967    #[test]
12968    fn test_ident_ord() {
12969        let mut a = Ident::with_span(Span::new(Location::new(1, 1), Location::new(1, 1)), "a");
12970        let mut b = Ident::with_span(Span::new(Location::new(2, 2), Location::new(2, 2)), "b");
12971
12972        assert!(a < b);
12973        std::mem::swap(&mut a.span, &mut b.span);
12974        assert!(a < b);
12975    }
12976}