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