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::{indented_list, SpaceOrNewline},
47    tokenizer::{Span, Token},
48};
49use crate::{
50    display_utils::{Indent, NewLine},
51    keywords::Keyword,
52};
53
54pub use self::data_type::{
55    ArrayElemTypeDef, BinaryLength, CharLengthUnits, CharacterLength, DataType, EnumMember,
56    ExactNumberInfo, IntervalFields, StructBracketKind, TimezoneInfo,
57};
58pub use self::dcl::{
59    AlterRoleOperation, ResetConfig, RoleOption, SecondaryRoles, SetConfigValue, Use,
60};
61pub use self::ddl::{
62    AlterColumnOperation, AlterConnectorOwner, AlterIndexOperation, AlterPolicyOperation,
63    AlterSchema, AlterSchemaOperation, AlterTableAlgorithm, AlterTableLock, AlterTableOperation,
64    AlterType, AlterTypeAddValue, AlterTypeAddValuePosition, AlterTypeOperation, AlterTypeRename,
65    AlterTypeRenameValue, ClusteredBy, ColumnDef, ColumnOption, ColumnOptionDef, ColumnOptions,
66    ColumnPolicy, ColumnPolicyProperty, ConstraintCharacteristics, CreateConnector, CreateDomain,
67    CreateFunction, CreateIndex, CreateTable, CreateTrigger, Deduplicate, DeferrableInitial,
68    DropBehavior, DropTrigger, GeneratedAs, GeneratedExpressionMode, IdentityParameters,
69    IdentityProperty, IdentityPropertyFormatKind, IdentityPropertyKind, IdentityPropertyOrder,
70    IndexColumn, IndexOption, IndexType, KeyOrIndexDisplay, NullsDistinctOption, Owner, Partition,
71    ProcedureParam, ReferentialAction, RenameTableNameKind, ReplicaIdentity, TableConstraint,
72    TagsColumnOption, UserDefinedTypeCompositeAttributeDef, UserDefinedTypeRepresentation,
73    ViewColumnDef,
74};
75pub use self::dml::{Delete, Insert};
76pub use self::operator::{BinaryOperator, UnaryOperator};
77pub use self::query::{
78    AfterMatchSkip, ConnectBy, Cte, CteAsMaterialized, Distinct, EmptyMatchesMode,
79    ExceptSelectItem, ExcludeSelectItem, ExprWithAlias, ExprWithAliasAndOrderBy, Fetch, ForClause,
80    ForJson, ForXml, FormatClause, GroupByExpr, GroupByWithModifier, IdentWithAlias,
81    IlikeSelectItem, InputFormatClause, Interpolate, InterpolateExpr, Join, JoinConstraint,
82    JoinOperator, JsonTableColumn, JsonTableColumnErrorHandling, JsonTableNamedColumn,
83    JsonTableNestedColumn, LateralView, LimitClause, LockClause, LockType, MatchRecognizePattern,
84    MatchRecognizeSymbol, Measure, NamedWindowDefinition, NamedWindowExpr, NonBlock, Offset,
85    OffsetRows, OpenJsonTableColumn, OrderBy, OrderByExpr, OrderByKind, OrderByOptions,
86    PipeOperator, PivotValueSource, ProjectionSelect, Query, RenameSelectItem,
87    RepetitionQuantifier, ReplaceSelectElement, ReplaceSelectItem, RowsPerMatch, Select,
88    SelectFlavor, SelectInto, SelectItem, SelectItemQualifiedWildcardKind, SetExpr, SetOperator,
89    SetQuantifier, Setting, SymbolDefinition, Table, TableAlias, TableAliasColumnDef, TableFactor,
90    TableFunctionArgs, TableIndexHintForClause, TableIndexHintType, TableIndexHints,
91    TableIndexType, TableSample, TableSampleBucket, TableSampleKind, TableSampleMethod,
92    TableSampleModifier, TableSampleQuantity, TableSampleSeed, TableSampleSeedModifier,
93    TableSampleUnit, TableVersion, TableWithJoins, Top, TopQuantity, UpdateTableFromKind,
94    ValueTableMode, Values, WildcardAdditionalOptions, With, WithFill, XmlNamespaceDefinition,
95    XmlPassingArgument, XmlPassingClause, XmlTableColumn, XmlTableColumnOption,
96};
97
98pub use self::trigger::{
99    TriggerEvent, TriggerExecBody, TriggerExecBodyType, TriggerObject, TriggerPeriod,
100    TriggerReferencing, TriggerReferencingType,
101};
102
103pub use self::value::{
104    escape_double_quote_string, escape_quoted_string, DateTimeField, DollarQuotedString,
105    NormalizationForm, TrimWhereField, Value, ValueWithSpan,
106};
107
108use crate::ast::helpers::key_value_options::KeyValueOptions;
109use crate::ast::helpers::stmt_data_loading::StageParamsObject;
110
111#[cfg(feature = "visitor")]
112pub use visitor::*;
113
114pub use self::data_type::GeometricTypeKind;
115
116mod data_type;
117mod dcl;
118mod ddl;
119mod dml;
120pub mod helpers;
121mod operator;
122mod query;
123mod spans;
124pub use spans::Spanned;
125
126mod trigger;
127mod value;
128
129#[cfg(feature = "visitor")]
130mod visitor;
131
132pub struct DisplaySeparated<'a, T>
133where
134    T: fmt::Display,
135{
136    slice: &'a [T],
137    sep: &'static str,
138}
139
140impl<T> fmt::Display for DisplaySeparated<'_, T>
141where
142    T: fmt::Display,
143{
144    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
145        let mut delim = "";
146        for t in self.slice {
147            f.write_str(delim)?;
148            delim = self.sep;
149            t.fmt(f)?;
150        }
151        Ok(())
152    }
153}
154
155pub fn display_separated<'a, T>(slice: &'a [T], sep: &'static str) -> DisplaySeparated<'a, T>
156where
157    T: fmt::Display,
158{
159    DisplaySeparated { slice, sep }
160}
161
162pub fn display_comma_separated<T>(slice: &[T]) -> DisplaySeparated<'_, T>
163where
164    T: fmt::Display,
165{
166    DisplaySeparated { slice, sep: ", " }
167}
168
169/// Writes the given statements to the formatter, each ending with
170/// a semicolon and space separated.
171fn format_statement_list(f: &mut fmt::Formatter, statements: &[Statement]) -> fmt::Result {
172    write!(f, "{}", display_separated(statements, "; "))?;
173    // We manually insert semicolon for the last statement,
174    // since display_separated doesn't handle that case.
175    write!(f, ";")
176}
177
178/// An identifier, decomposed into its value or character data and the quote style.
179#[derive(Debug, Clone)]
180#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
181#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
182pub struct Ident {
183    /// The value of the identifier without quotes.
184    pub value: String,
185    /// The starting quote if any. Valid quote characters are the single quote,
186    /// double quote, backtick, and opening square bracket.
187    pub quote_style: Option<char>,
188    /// The span of the identifier in the original SQL string.
189    pub span: Span,
190}
191
192impl PartialEq for Ident {
193    fn eq(&self, other: &Self) -> bool {
194        let Ident {
195            value,
196            quote_style,
197            // exhaustiveness check; we ignore spans in comparisons
198            span: _,
199        } = self;
200
201        value == &other.value && quote_style == &other.quote_style
202    }
203}
204
205impl core::hash::Hash for Ident {
206    fn hash<H: hash::Hasher>(&self, state: &mut H) {
207        let Ident {
208            value,
209            quote_style,
210            // exhaustiveness check; we ignore spans in hashes
211            span: _,
212        } = self;
213
214        value.hash(state);
215        quote_style.hash(state);
216    }
217}
218
219impl Eq for Ident {}
220
221impl PartialOrd for Ident {
222    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
223        Some(self.cmp(other))
224    }
225}
226
227impl Ord for Ident {
228    fn cmp(&self, other: &Self) -> Ordering {
229        let Ident {
230            value,
231            quote_style,
232            // exhaustiveness check; we ignore spans in ordering
233            span: _,
234        } = self;
235
236        let Ident {
237            value: other_value,
238            quote_style: other_quote_style,
239            // exhaustiveness check; we ignore spans in ordering
240            span: _,
241        } = other;
242
243        // First compare by value, then by quote_style
244        value
245            .cmp(other_value)
246            .then_with(|| quote_style.cmp(other_quote_style))
247    }
248}
249
250impl Ident {
251    /// Create a new identifier with the given value and no quotes and an empty span.
252    pub fn new<S>(value: S) -> Self
253    where
254        S: Into<String>,
255    {
256        Ident {
257            value: value.into(),
258            quote_style: None,
259            span: Span::empty(),
260        }
261    }
262
263    /// Create a new quoted identifier with the given quote and value. This function
264    /// panics if the given quote is not a valid quote character.
265    pub fn with_quote<S>(quote: char, value: S) -> Self
266    where
267        S: Into<String>,
268    {
269        assert!(quote == '\'' || quote == '"' || quote == '`' || quote == '[');
270        Ident {
271            value: value.into(),
272            quote_style: Some(quote),
273            span: Span::empty(),
274        }
275    }
276
277    pub fn with_span<S>(span: Span, value: S) -> Self
278    where
279        S: Into<String>,
280    {
281        Ident {
282            value: value.into(),
283            quote_style: None,
284            span,
285        }
286    }
287
288    pub fn with_quote_and_span<S>(quote: char, span: Span, value: S) -> Self
289    where
290        S: Into<String>,
291    {
292        assert!(quote == '\'' || quote == '"' || quote == '`' || quote == '[');
293        Ident {
294            value: value.into(),
295            quote_style: Some(quote),
296            span,
297        }
298    }
299}
300
301impl From<&str> for Ident {
302    fn from(value: &str) -> Self {
303        Ident {
304            value: value.to_string(),
305            quote_style: None,
306            span: Span::empty(),
307        }
308    }
309}
310
311impl fmt::Display for Ident {
312    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
313        match self.quote_style {
314            Some(q) if q == '"' || q == '\'' || q == '`' => {
315                let escaped = value::escape_quoted_string(&self.value, q);
316                write!(f, "{q}{escaped}{q}")
317            }
318            Some('[') => write!(f, "[{}]", self.value),
319            None => f.write_str(&self.value),
320            _ => panic!("unexpected quote style"),
321        }
322    }
323}
324
325/// A name of a table, view, custom type, etc., possibly multi-part, i.e. db.schema.obj
326#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
327#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
328#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
329pub struct ObjectName(pub Vec<ObjectNamePart>);
330
331impl From<Vec<Ident>> for ObjectName {
332    fn from(idents: Vec<Ident>) -> Self {
333        ObjectName(idents.into_iter().map(ObjectNamePart::Identifier).collect())
334    }
335}
336
337impl fmt::Display for ObjectName {
338    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
339        write!(f, "{}", display_separated(&self.0, "."))
340    }
341}
342
343/// A single part of an ObjectName
344#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
345#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
346#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
347pub enum ObjectNamePart {
348    Identifier(Ident),
349    Function(ObjectNamePartFunction),
350}
351
352impl ObjectNamePart {
353    pub fn as_ident(&self) -> Option<&Ident> {
354        match self {
355            ObjectNamePart::Identifier(ident) => Some(ident),
356            ObjectNamePart::Function(_) => None,
357        }
358    }
359}
360
361impl fmt::Display for ObjectNamePart {
362    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
363        match self {
364            ObjectNamePart::Identifier(ident) => write!(f, "{ident}"),
365            ObjectNamePart::Function(func) => write!(f, "{func}"),
366        }
367    }
368}
369
370/// An object name part that consists of a function that dynamically
371/// constructs identifiers.
372///
373/// - [Snowflake](https://docs.snowflake.com/en/sql-reference/identifier-literal)
374#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
375#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
376#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
377pub struct ObjectNamePartFunction {
378    pub name: Ident,
379    pub args: Vec<FunctionArg>,
380}
381
382impl fmt::Display for ObjectNamePartFunction {
383    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
384        write!(f, "{}(", self.name)?;
385        write!(f, "{})", display_comma_separated(&self.args))
386    }
387}
388
389/// Represents an Array Expression, either
390/// `ARRAY[..]`, or `[..]`
391#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
392#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
393#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
394pub struct Array {
395    /// The list of expressions between brackets
396    pub elem: Vec<Expr>,
397
398    /// `true` for  `ARRAY[..]`, `false` for `[..]`
399    pub named: bool,
400}
401
402impl fmt::Display for Array {
403    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
404        write!(
405            f,
406            "{}[{}]",
407            if self.named { "ARRAY" } else { "" },
408            display_comma_separated(&self.elem)
409        )
410    }
411}
412
413/// Represents an INTERVAL expression, roughly in the following format:
414/// `INTERVAL '<value>' [ <leading_field> [ (<leading_precision>) ] ]
415/// [ TO <last_field> [ (<fractional_seconds_precision>) ] ]`,
416/// e.g. `INTERVAL '123:45.67' MINUTE(3) TO SECOND(2)`.
417///
418/// The parser does not validate the `<value>`, nor does it ensure
419/// that the `<leading_field>` units >= the units in `<last_field>`,
420/// so the user will have to reject intervals like `HOUR TO YEAR`.
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 Interval {
425    pub value: Box<Expr>,
426    pub leading_field: Option<DateTimeField>,
427    pub leading_precision: Option<u64>,
428    pub last_field: Option<DateTimeField>,
429    /// The seconds precision can be specified in SQL source as
430    /// `INTERVAL '__' SECOND(_, x)` (in which case the `leading_field`
431    /// will be `Second` and the `last_field` will be `None`),
432    /// or as `__ TO SECOND(x)`.
433    pub fractional_seconds_precision: Option<u64>,
434}
435
436impl fmt::Display for Interval {
437    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
438        let value = self.value.as_ref();
439        match (
440            &self.leading_field,
441            self.leading_precision,
442            self.fractional_seconds_precision,
443        ) {
444            (
445                Some(DateTimeField::Second),
446                Some(leading_precision),
447                Some(fractional_seconds_precision),
448            ) => {
449                // When the leading field is SECOND, the parser guarantees that
450                // the last field is None.
451                assert!(self.last_field.is_none());
452                write!(
453                    f,
454                    "INTERVAL {value} SECOND ({leading_precision}, {fractional_seconds_precision})"
455                )
456            }
457            _ => {
458                write!(f, "INTERVAL {value}")?;
459                if let Some(leading_field) = &self.leading_field {
460                    write!(f, " {leading_field}")?;
461                }
462                if let Some(leading_precision) = self.leading_precision {
463                    write!(f, " ({leading_precision})")?;
464                }
465                if let Some(last_field) = &self.last_field {
466                    write!(f, " TO {last_field}")?;
467                }
468                if let Some(fractional_seconds_precision) = self.fractional_seconds_precision {
469                    write!(f, " ({fractional_seconds_precision})")?;
470                }
471                Ok(())
472            }
473        }
474    }
475}
476
477/// A field definition within a struct
478///
479/// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-types#struct_type
480#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
481#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
482#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
483pub struct StructField {
484    pub field_name: Option<Ident>,
485    pub field_type: DataType,
486    /// Struct field options.
487    /// See [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#column_name_and_column_schema)
488    pub options: Option<Vec<SqlOption>>,
489}
490
491impl fmt::Display for StructField {
492    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
493        if let Some(name) = &self.field_name {
494            write!(f, "{name} {}", self.field_type)?;
495        } else {
496            write!(f, "{}", self.field_type)?;
497        }
498        if let Some(options) = &self.options {
499            write!(f, " OPTIONS({})", display_separated(options, ", "))
500        } else {
501            Ok(())
502        }
503    }
504}
505
506/// A field definition within a union
507///
508/// [DuckDB]: https://duckdb.org/docs/sql/data_types/union.html
509#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
510#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
511#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
512pub struct UnionField {
513    pub field_name: Ident,
514    pub field_type: DataType,
515}
516
517impl fmt::Display for UnionField {
518    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
519        write!(f, "{} {}", self.field_name, self.field_type)
520    }
521}
522
523/// A dictionary field within a dictionary.
524///
525/// [DuckDB]: https://duckdb.org/docs/sql/data_types/struct#creating-structs
526#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
527#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
528#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
529pub struct DictionaryField {
530    pub key: Ident,
531    pub value: Box<Expr>,
532}
533
534impl fmt::Display for DictionaryField {
535    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
536        write!(f, "{}: {}", self.key, self.value)
537    }
538}
539
540/// Represents a Map expression.
541#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
542#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
543#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
544pub struct Map {
545    pub entries: Vec<MapEntry>,
546}
547
548impl Display for Map {
549    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
550        write!(f, "MAP {{{}}}", display_comma_separated(&self.entries))
551    }
552}
553
554/// A map field within a map.
555///
556/// [DuckDB]: https://duckdb.org/docs/sql/data_types/map.html#creating-maps
557#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
558#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
559#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
560pub struct MapEntry {
561    pub key: Box<Expr>,
562    pub value: Box<Expr>,
563}
564
565impl fmt::Display for MapEntry {
566    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
567        write!(f, "{}: {}", self.key, self.value)
568    }
569}
570
571/// Options for `CAST` / `TRY_CAST`
572/// BigQuery: <https://cloud.google.com/bigquery/docs/reference/standard-sql/format-elements#formatting_syntax>
573#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
574#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
575#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
576pub enum CastFormat {
577    Value(Value),
578    ValueAtTimeZone(Value, Value),
579}
580
581/// An element of a JSON path.
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 enum JsonPathElem {
586    /// Accesses an object field using dot notation, e.g. `obj:foo.bar.baz`.
587    ///
588    /// See <https://docs.snowflake.com/en/user-guide/querying-semistructured#dot-notation>.
589    Dot { key: String, quoted: bool },
590    /// Accesses an object field or array element using bracket notation,
591    /// e.g. `obj['foo']`.
592    ///
593    /// See <https://docs.snowflake.com/en/user-guide/querying-semistructured#bracket-notation>.
594    Bracket { key: Expr },
595}
596
597/// A JSON path.
598///
599/// See <https://docs.snowflake.com/en/user-guide/querying-semistructured>.
600/// See <https://docs.databricks.com/en/sql/language-manual/sql-ref-json-path-expression.html>.
601#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
602#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
603#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
604pub struct JsonPath {
605    pub path: Vec<JsonPathElem>,
606}
607
608impl fmt::Display for JsonPath {
609    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
610        for (i, elem) in self.path.iter().enumerate() {
611            match elem {
612                JsonPathElem::Dot { key, quoted } => {
613                    if i == 0 {
614                        write!(f, ":")?;
615                    } else {
616                        write!(f, ".")?;
617                    }
618
619                    if *quoted {
620                        write!(f, "\"{}\"", escape_double_quote_string(key))?;
621                    } else {
622                        write!(f, "{key}")?;
623                    }
624                }
625                JsonPathElem::Bracket { key } => {
626                    write!(f, "[{key}]")?;
627                }
628            }
629        }
630        Ok(())
631    }
632}
633
634/// The syntax used for in a cast expression.
635#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
636#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
637#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
638pub enum CastKind {
639    /// The standard SQL cast syntax, e.g. `CAST(<expr> as <datatype>)`
640    Cast,
641    /// A cast that returns `NULL` on failure, e.g. `TRY_CAST(<expr> as <datatype>)`.
642    ///
643    /// See <https://docs.snowflake.com/en/sql-reference/functions/try_cast>.
644    /// See <https://learn.microsoft.com/en-us/sql/t-sql/functions/try-cast-transact-sql>.
645    TryCast,
646    /// A cast that returns `NULL` on failure, bigQuery-specific ,  e.g. `SAFE_CAST(<expr> as <datatype>)`.
647    ///
648    /// See <https://cloud.google.com/bigquery/docs/reference/standard-sql/functions-and-operators#safe_casting>.
649    SafeCast,
650    /// `<expr> :: <datatype>`
651    DoubleColon,
652}
653
654/// `EXTRACT` syntax variants.
655///
656/// In Snowflake dialect, the `EXTRACT` expression can support either the `from` syntax
657/// or the comma syntax.
658///
659/// See <https://docs.snowflake.com/en/sql-reference/functions/extract>
660#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
661#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
662#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
663pub enum ExtractSyntax {
664    /// `EXTRACT( <date_or_time_part> FROM <date_or_time_expr> )`
665    From,
666    /// `EXTRACT( <date_or_time_part> , <date_or_timestamp_expr> )`
667    Comma,
668}
669
670/// The syntax used in a CEIL or FLOOR expression.
671///
672/// The `CEIL/FLOOR(<datetime value expression> TO <time unit>)` is an Amazon Kinesis Data Analytics extension.
673/// See <https://docs.aws.amazon.com/kinesisanalytics/latest/sqlref/sql-reference-ceil.html> for
674/// details.
675///
676/// Other dialects either support `CEIL/FLOOR( <expr> [, <scale>])` format or just
677/// `CEIL/FLOOR(<expr>)`.
678#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
679#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
680#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
681pub enum CeilFloorKind {
682    /// `CEIL( <expr> TO <DateTimeField>)`
683    DateTimeField(DateTimeField),
684    /// `CEIL( <expr> [, <scale>])`
685    Scale(Value),
686}
687
688/// A WHEN clause in a CASE expression containing both
689/// the condition and its corresponding result
690#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
691#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
692#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
693pub struct CaseWhen {
694    pub condition: Expr,
695    pub result: Expr,
696}
697
698impl fmt::Display for CaseWhen {
699    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
700        f.write_str("WHEN ")?;
701        self.condition.fmt(f)?;
702        f.write_str(" THEN")?;
703        SpaceOrNewline.fmt(f)?;
704        Indent(&self.result).fmt(f)?;
705        Ok(())
706    }
707}
708
709/// An SQL expression of any type.
710///
711/// # Semantics / Type Checking
712///
713/// The parser does not distinguish between expressions of different types
714/// (e.g. boolean vs string). The caller is responsible for detecting and
715/// validating types as necessary (for example  `WHERE 1` vs `SELECT 1=1`)
716/// See the [README.md] for more details.
717///
718/// [README.md]: https://github.com/apache/datafusion-sqlparser-rs/blob/main/README.md#syntax-vs-semantics
719///
720/// # Equality and Hashing Does not Include Source Locations
721///
722/// The `Expr` type implements `PartialEq` and `Eq` based on the semantic value
723/// of the expression (not bitwise comparison). This means that `Expr` instances
724/// that are semantically equivalent but have different spans (locations in the
725/// source tree) will compare as equal.
726#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
727#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
728#[cfg_attr(
729    feature = "visitor",
730    derive(Visit, VisitMut),
731    visit(with = "visit_expr")
732)]
733pub enum Expr {
734    /// Identifier e.g. table name or column name
735    Identifier(Ident),
736    /// Multi-part identifier, e.g. `table_alias.column` or `schema.table.col`
737    CompoundIdentifier(Vec<Ident>),
738    /// Multi-part expression access.
739    ///
740    /// This structure represents an access chain in structured / nested types
741    /// such as maps, arrays, and lists:
742    /// - Array
743    ///     - A 1-dim array `a[1]` will be represented like:
744    ///       `CompoundFieldAccess(Ident('a'), vec![Subscript(1)]`
745    ///     - A 2-dim array `a[1][2]` will be represented like:
746    ///       `CompoundFieldAccess(Ident('a'), vec![Subscript(1), Subscript(2)]`
747    /// - Map or Struct (Bracket-style)
748    ///     - A map `a['field1']` will be represented like:
749    ///       `CompoundFieldAccess(Ident('a'), vec![Subscript('field')]`
750    ///     - A 2-dim map `a['field1']['field2']` will be represented like:
751    ///       `CompoundFieldAccess(Ident('a'), vec![Subscript('field1'), Subscript('field2')]`
752    /// - Struct (Dot-style) (only effect when the chain contains both subscript and expr)
753    ///     - A struct access `a[field1].field2` will be represented like:
754    ///       `CompoundFieldAccess(Ident('a'), vec![Subscript('field1'), Ident('field2')]`
755    /// - If a struct access likes `a.field1.field2`, it will be represented by CompoundIdentifier([a, field1, field2])
756    CompoundFieldAccess {
757        root: Box<Expr>,
758        access_chain: Vec<AccessExpr>,
759    },
760    /// Access data nested in a value containing semi-structured data, such as
761    /// the `VARIANT` type on Snowflake. for example `src:customer[0].name`.
762    ///
763    /// See <https://docs.snowflake.com/en/user-guide/querying-semistructured>.
764    /// See <https://docs.databricks.com/en/sql/language-manual/functions/colonsign.html>.
765    JsonAccess {
766        /// The value being queried.
767        value: Box<Expr>,
768        /// The path to the data to extract.
769        path: JsonPath,
770    },
771    /// `IS FALSE` operator
772    IsFalse(Box<Expr>),
773    /// `IS NOT FALSE` operator
774    IsNotFalse(Box<Expr>),
775    /// `IS TRUE` operator
776    IsTrue(Box<Expr>),
777    /// `IS NOT TRUE` operator
778    IsNotTrue(Box<Expr>),
779    /// `IS NULL` operator
780    IsNull(Box<Expr>),
781    /// `IS NOT NULL` operator
782    IsNotNull(Box<Expr>),
783    /// `IS UNKNOWN` operator
784    IsUnknown(Box<Expr>),
785    /// `IS NOT UNKNOWN` operator
786    IsNotUnknown(Box<Expr>),
787    /// `IS DISTINCT FROM` operator
788    IsDistinctFrom(Box<Expr>, Box<Expr>),
789    /// `IS NOT DISTINCT FROM` operator
790    IsNotDistinctFrom(Box<Expr>, Box<Expr>),
791    /// `<expr> IS [ NOT ] [ form ] NORMALIZED`
792    IsNormalized {
793        expr: Box<Expr>,
794        form: Option<NormalizationForm>,
795        negated: bool,
796    },
797    /// `[ NOT ] IN (val1, val2, ...)`
798    InList {
799        expr: Box<Expr>,
800        list: Vec<Expr>,
801        negated: bool,
802    },
803    /// `[ NOT ] IN (SELECT ...)`
804    InSubquery {
805        expr: Box<Expr>,
806        subquery: Box<Query>,
807        negated: bool,
808    },
809    /// `[ NOT ] IN UNNEST(array_expression)`
810    InUnnest {
811        expr: Box<Expr>,
812        array_expr: Box<Expr>,
813        negated: bool,
814    },
815    /// `<expr> [ NOT ] BETWEEN <low> AND <high>`
816    Between {
817        expr: Box<Expr>,
818        negated: bool,
819        low: Box<Expr>,
820        high: Box<Expr>,
821    },
822    /// Binary operation e.g. `1 + 1` or `foo > bar`
823    BinaryOp {
824        left: Box<Expr>,
825        op: BinaryOperator,
826        right: Box<Expr>,
827    },
828    /// `[NOT] LIKE <pattern> [ESCAPE <escape_character>]`
829    Like {
830        negated: bool,
831        // Snowflake supports the ANY keyword to match against a list of patterns
832        // https://docs.snowflake.com/en/sql-reference/functions/like_any
833        any: bool,
834        expr: Box<Expr>,
835        pattern: Box<Expr>,
836        escape_char: Option<Value>,
837    },
838    /// `ILIKE` (case-insensitive `LIKE`)
839    ILike {
840        negated: bool,
841        // Snowflake supports the ANY keyword to match against a list of patterns
842        // https://docs.snowflake.com/en/sql-reference/functions/like_any
843        any: bool,
844        expr: Box<Expr>,
845        pattern: Box<Expr>,
846        escape_char: Option<Value>,
847    },
848    /// SIMILAR TO regex
849    SimilarTo {
850        negated: bool,
851        expr: Box<Expr>,
852        pattern: Box<Expr>,
853        escape_char: Option<Value>,
854    },
855    /// MySQL: RLIKE regex or REGEXP regex
856    RLike {
857        negated: bool,
858        expr: Box<Expr>,
859        pattern: Box<Expr>,
860        // true for REGEXP, false for RLIKE (no difference in semantics)
861        regexp: bool,
862    },
863    /// `ANY` operation e.g. `foo > ANY(bar)`, comparison operator is one of `[=, >, <, =>, =<, !=]`
864    /// <https://docs.snowflake.com/en/sql-reference/operators-subquery#all-any>
865    AnyOp {
866        left: Box<Expr>,
867        compare_op: BinaryOperator,
868        right: Box<Expr>,
869        // ANY and SOME are synonymous: https://docs.cloudera.com/cdw-runtime/cloud/using-hiveql/topics/hive_comparison_predicates.html
870        is_some: bool,
871    },
872    /// `ALL` operation e.g. `foo > ALL(bar)`, comparison operator is one of `[=, >, <, =>, =<, !=]`
873    /// <https://docs.snowflake.com/en/sql-reference/operators-subquery#all-any>
874    AllOp {
875        left: Box<Expr>,
876        compare_op: BinaryOperator,
877        right: Box<Expr>,
878    },
879    /// Unary operation e.g. `NOT foo`
880    UnaryOp {
881        op: UnaryOperator,
882        expr: Box<Expr>,
883    },
884    /// CONVERT a value to a different data type or character encoding. e.g. `CONVERT(foo USING utf8mb4)`
885    Convert {
886        /// CONVERT (false) or TRY_CONVERT (true)
887        /// <https://learn.microsoft.com/en-us/sql/t-sql/functions/try-convert-transact-sql?view=sql-server-ver16>
888        is_try: bool,
889        /// The expression to convert
890        expr: Box<Expr>,
891        /// The target data type
892        data_type: Option<DataType>,
893        /// The target character encoding
894        charset: Option<ObjectName>,
895        /// whether the target comes before the expr (MSSQL syntax)
896        target_before_value: bool,
897        /// How to translate the expression.
898        ///
899        /// [MSSQL]: https://learn.microsoft.com/en-us/sql/t-sql/functions/cast-and-convert-transact-sql?view=sql-server-ver16#style
900        styles: Vec<Expr>,
901    },
902    /// `CAST` an expression to a different data type e.g. `CAST(foo AS VARCHAR(123))`
903    Cast {
904        kind: CastKind,
905        expr: Box<Expr>,
906        data_type: DataType,
907        /// Optional CAST(string_expression AS type FORMAT format_string_expression) as used by [BigQuery]
908        ///
909        /// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/format-elements#formatting_syntax
910        format: Option<CastFormat>,
911    },
912    /// AT a timestamp to a different timezone e.g. `FROM_UNIXTIME(0) AT TIME ZONE 'UTC-06:00'`
913    AtTimeZone {
914        timestamp: Box<Expr>,
915        time_zone: Box<Expr>,
916    },
917    /// Extract a field from a timestamp e.g. `EXTRACT(MONTH FROM foo)`
918    /// Or `EXTRACT(MONTH, foo)`
919    ///
920    /// Syntax:
921    /// ```sql
922    /// EXTRACT(DateTimeField FROM <expr>) | EXTRACT(DateTimeField, <expr>)
923    /// ```
924    Extract {
925        field: DateTimeField,
926        syntax: ExtractSyntax,
927        expr: Box<Expr>,
928    },
929    /// ```sql
930    /// CEIL(<expr> [TO DateTimeField])
931    /// ```
932    /// ```sql
933    /// CEIL( <input_expr> [, <scale_expr> ] )
934    /// ```
935    Ceil {
936        expr: Box<Expr>,
937        field: CeilFloorKind,
938    },
939    /// ```sql
940    /// FLOOR(<expr> [TO DateTimeField])
941    /// ```
942    /// ```sql
943    /// FLOOR( <input_expr> [, <scale_expr> ] )
944    ///
945    Floor {
946        expr: Box<Expr>,
947        field: CeilFloorKind,
948    },
949    /// ```sql
950    /// POSITION(<expr> in <expr>)
951    /// ```
952    Position {
953        expr: Box<Expr>,
954        r#in: Box<Expr>,
955    },
956    /// ```sql
957    /// SUBSTRING(<expr> [FROM <expr>] [FOR <expr>])
958    /// ```
959    /// or
960    /// ```sql
961    /// SUBSTRING(<expr>, <expr>, <expr>)
962    /// ```
963    Substring {
964        expr: Box<Expr>,
965        substring_from: Option<Box<Expr>>,
966        substring_for: Option<Box<Expr>>,
967
968        /// false if the expression is represented using the `SUBSTRING(expr [FROM start] [FOR len])` syntax
969        /// true if the expression is represented using the `SUBSTRING(expr, start, len)` syntax
970        /// This flag is used for formatting.
971        special: bool,
972
973        /// true if the expression is represented using the `SUBSTR` shorthand
974        /// This flag is used for formatting.
975        shorthand: bool,
976    },
977    /// ```sql
978    /// TRIM([BOTH | LEADING | TRAILING] [<expr> FROM] <expr>)
979    /// TRIM(<expr>)
980    /// TRIM(<expr>, [, characters]) -- only Snowflake or Bigquery
981    /// ```
982    Trim {
983        expr: Box<Expr>,
984        // ([BOTH | LEADING | TRAILING]
985        trim_where: Option<TrimWhereField>,
986        trim_what: Option<Box<Expr>>,
987        trim_characters: Option<Vec<Expr>>,
988    },
989    /// ```sql
990    /// OVERLAY(<expr> PLACING <expr> FROM <expr>[ FOR <expr> ]
991    /// ```
992    Overlay {
993        expr: Box<Expr>,
994        overlay_what: Box<Expr>,
995        overlay_from: Box<Expr>,
996        overlay_for: Option<Box<Expr>>,
997    },
998    /// `expr COLLATE collation`
999    Collate {
1000        expr: Box<Expr>,
1001        collation: ObjectName,
1002    },
1003    /// Nested expression e.g. `(foo > bar)` or `(1)`
1004    Nested(Box<Expr>),
1005    /// A literal value, such as string, number, date or NULL
1006    Value(ValueWithSpan),
1007    /// Prefixed expression, e.g. introducer strings, projection prefix
1008    /// <https://dev.mysql.com/doc/refman/8.0/en/charset-introducer.html>
1009    /// <https://docs.snowflake.com/en/sql-reference/constructs/connect-by>
1010    Prefixed {
1011        prefix: Ident,
1012        /// The value of the constant.
1013        /// Hint: you can unwrap the string value using `value.into_string()`.
1014        value: Box<Expr>,
1015    },
1016    /// A constant of form `<data_type> 'value'`.
1017    /// This can represent ANSI SQL `DATE`, `TIME`, and `TIMESTAMP` literals (such as `DATE '2020-01-01'`),
1018    /// as well as constants of other types (a non-standard PostgreSQL extension).
1019    TypedString(TypedString),
1020    /// Scalar function call e.g. `LEFT(foo, 5)`
1021    Function(Function),
1022    /// `CASE [<operand>] WHEN <condition> THEN <result> ... [ELSE <result>] END`
1023    ///
1024    /// Note we only recognize a complete single expression as `<condition>`,
1025    /// not `< 0` nor `1, 2, 3` as allowed in a `<simple when clause>` per
1026    /// <https://jakewheat.github.io/sql-overview/sql-2011-foundation-grammar.html#simple-when-clause>
1027    Case {
1028        case_token: AttachedToken,
1029        end_token: AttachedToken,
1030        operand: Option<Box<Expr>>,
1031        conditions: Vec<CaseWhen>,
1032        else_result: Option<Box<Expr>>,
1033    },
1034    /// An exists expression `[ NOT ] EXISTS(SELECT ...)`, used in expressions like
1035    /// `WHERE [ NOT ] EXISTS (SELECT ...)`.
1036    Exists {
1037        subquery: Box<Query>,
1038        negated: bool,
1039    },
1040    /// A parenthesized subquery `(SELECT ...)`, used in expression like
1041    /// `SELECT (subquery) AS x` or `WHERE (subquery) = x`
1042    Subquery(Box<Query>),
1043    /// The `GROUPING SETS` expr.
1044    GroupingSets(Vec<Vec<Expr>>),
1045    /// The `CUBE` expr.
1046    Cube(Vec<Vec<Expr>>),
1047    /// The `ROLLUP` expr.
1048    Rollup(Vec<Vec<Expr>>),
1049    /// ROW / TUPLE a single value, such as `SELECT (1, 2)`
1050    Tuple(Vec<Expr>),
1051    /// `Struct` literal expression
1052    /// Syntax:
1053    /// ```sql
1054    /// STRUCT<[field_name] field_type, ...>( expr1 [, ... ])
1055    ///
1056    /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-types#struct_type)
1057    /// [Databricks](https://docs.databricks.com/en/sql/language-manual/functions/struct.html)
1058    /// ```
1059    Struct {
1060        /// Struct values.
1061        values: Vec<Expr>,
1062        /// Struct field definitions.
1063        fields: Vec<StructField>,
1064    },
1065    /// `BigQuery` specific: An named expression in a typeless struct [1]
1066    ///
1067    /// Syntax
1068    /// ```sql
1069    /// 1 AS A
1070    /// ```
1071    /// [1]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-types#struct_type
1072    Named {
1073        expr: Box<Expr>,
1074        name: Ident,
1075    },
1076    /// `DuckDB` specific `Struct` literal expression [1]
1077    ///
1078    /// Syntax:
1079    /// ```sql
1080    /// syntax: {'field_name': expr1[, ... ]}
1081    /// ```
1082    /// [1]: https://duckdb.org/docs/sql/data_types/struct#creating-structs
1083    Dictionary(Vec<DictionaryField>),
1084    /// `DuckDB` specific `Map` literal expression [1]
1085    ///
1086    /// Syntax:
1087    /// ```sql
1088    /// syntax: Map {key1: value1[, ... ]}
1089    /// ```
1090    /// [1]: https://duckdb.org/docs/sql/data_types/map#creating-maps
1091    Map(Map),
1092    /// An array expression e.g. `ARRAY[1, 2]`
1093    Array(Array),
1094    /// An interval expression e.g. `INTERVAL '1' YEAR`
1095    Interval(Interval),
1096    /// `MySQL` specific text search function [(1)].
1097    ///
1098    /// Syntax:
1099    /// ```sql
1100    /// MATCH (<col>, <col>, ...) AGAINST (<expr> [<search modifier>])
1101    ///
1102    /// <col> = CompoundIdentifier
1103    /// <expr> = String literal
1104    /// ```
1105    /// [(1)]: https://dev.mysql.com/doc/refman/8.0/en/fulltext-search.html#function_match
1106    MatchAgainst {
1107        /// `(<col>, <col>, ...)`.
1108        columns: Vec<ObjectName>,
1109        /// `<expr>`.
1110        match_value: Value,
1111        /// `<search modifier>`
1112        opt_search_modifier: Option<SearchModifier>,
1113    },
1114    Wildcard(AttachedToken),
1115    /// Qualified wildcard, e.g. `alias.*` or `schema.table.*`.
1116    /// (Same caveats apply to `QualifiedWildcard` as to `Wildcard`.)
1117    QualifiedWildcard(ObjectName, AttachedToken),
1118    /// Some dialects support an older syntax for outer joins where columns are
1119    /// marked with the `(+)` operator in the WHERE clause, for example:
1120    ///
1121    /// ```sql
1122    /// SELECT t1.c1, t2.c2 FROM t1, t2 WHERE t1.c1 = t2.c2 (+)
1123    /// ```
1124    ///
1125    /// which is equivalent to
1126    ///
1127    /// ```sql
1128    /// SELECT t1.c1, t2.c2 FROM t1 LEFT OUTER JOIN t2 ON t1.c1 = t2.c2
1129    /// ```
1130    ///
1131    /// See <https://docs.snowflake.com/en/sql-reference/constructs/where#joins-in-the-where-clause>.
1132    OuterJoin(Box<Expr>),
1133    /// A reference to the prior level in a CONNECT BY clause.
1134    Prior(Box<Expr>),
1135    /// A lambda function.
1136    ///
1137    /// Syntax:
1138    /// ```plaintext
1139    /// param -> expr | (param1, ...) -> expr
1140    /// ```
1141    ///
1142    /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/functions#higher-order-functions---operator-and-lambdaparams-expr-function)
1143    /// [Databricks](https://docs.databricks.com/en/sql/language-manual/sql-ref-lambda-functions.html)
1144    /// [DuckDB](https://duckdb.org/docs/stable/sql/functions/lambda)
1145    Lambda(LambdaFunction),
1146    /// Checks membership of a value in a JSON array
1147    MemberOf(MemberOf),
1148}
1149
1150impl Expr {
1151    /// Creates a new [`Expr::Value`]
1152    pub fn value(value: impl Into<ValueWithSpan>) -> Self {
1153        Expr::Value(value.into())
1154    }
1155}
1156
1157/// The contents inside the `[` and `]` in a subscript expression.
1158#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1159#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1160#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1161pub enum Subscript {
1162    /// Accesses the element of the array at the given index.
1163    Index { index: Expr },
1164
1165    /// Accesses a slice of an array on PostgreSQL, e.g.
1166    ///
1167    /// ```plaintext
1168    /// => select (array[1,2,3,4,5,6])[2:5];
1169    /// -----------
1170    /// {2,3,4,5}
1171    /// ```
1172    ///
1173    /// The lower and/or upper bound can be omitted to slice from the start or
1174    /// end of the array respectively.
1175    ///
1176    /// See <https://www.postgresql.org/docs/current/arrays.html#ARRAYS-ACCESSING>.
1177    ///
1178    /// Also supports an optional "stride" as the last element (this is not
1179    /// supported by postgres), e.g.
1180    ///
1181    /// ```plaintext
1182    /// => select (array[1,2,3,4,5,6])[1:6:2];
1183    /// -----------
1184    /// {1,3,5}
1185    /// ```
1186    Slice {
1187        lower_bound: Option<Expr>,
1188        upper_bound: Option<Expr>,
1189        stride: Option<Expr>,
1190    },
1191}
1192
1193impl fmt::Display for Subscript {
1194    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1195        match self {
1196            Subscript::Index { index } => write!(f, "{index}"),
1197            Subscript::Slice {
1198                lower_bound,
1199                upper_bound,
1200                stride,
1201            } => {
1202                if let Some(lower) = lower_bound {
1203                    write!(f, "{lower}")?;
1204                }
1205                write!(f, ":")?;
1206                if let Some(upper) = upper_bound {
1207                    write!(f, "{upper}")?;
1208                }
1209                if let Some(stride) = stride {
1210                    write!(f, ":")?;
1211                    write!(f, "{stride}")?;
1212                }
1213                Ok(())
1214            }
1215        }
1216    }
1217}
1218
1219/// An element of a [`Expr::CompoundFieldAccess`].
1220/// It can be an expression or a subscript.
1221#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1222#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1223#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1224pub enum AccessExpr {
1225    /// Accesses a field using dot notation, e.g. `foo.bar.baz`.
1226    Dot(Expr),
1227    /// Accesses a field or array element using bracket notation, e.g. `foo['bar']`.
1228    Subscript(Subscript),
1229}
1230
1231impl fmt::Display for AccessExpr {
1232    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1233        match self {
1234            AccessExpr::Dot(expr) => write!(f, ".{expr}"),
1235            AccessExpr::Subscript(subscript) => write!(f, "[{subscript}]"),
1236        }
1237    }
1238}
1239
1240/// A lambda function.
1241#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1242#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1243#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1244pub struct LambdaFunction {
1245    /// The parameters to the lambda function.
1246    pub params: OneOrManyWithParens<Ident>,
1247    /// The body of the lambda function.
1248    pub body: Box<Expr>,
1249}
1250
1251impl fmt::Display for LambdaFunction {
1252    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1253        write!(f, "{} -> {}", self.params, self.body)
1254    }
1255}
1256
1257/// Encapsulates the common pattern in SQL where either one unparenthesized item
1258/// such as an identifier or expression is permitted, or multiple of the same
1259/// item in a parenthesized list. For accessing items regardless of the form,
1260/// `OneOrManyWithParens` implements `Deref<Target = [T]>` and `IntoIterator`,
1261/// so you can call slice methods on it and iterate over items
1262/// # Examples
1263/// Accessing as a slice:
1264/// ```
1265/// # use sqlparser::ast::OneOrManyWithParens;
1266/// let one = OneOrManyWithParens::One("a");
1267///
1268/// assert_eq!(one[0], "a");
1269/// assert_eq!(one.len(), 1);
1270/// ```
1271/// Iterating:
1272/// ```
1273/// # use sqlparser::ast::OneOrManyWithParens;
1274/// let one = OneOrManyWithParens::One("a");
1275/// let many = OneOrManyWithParens::Many(vec!["a", "b"]);
1276///
1277/// assert_eq!(one.into_iter().chain(many).collect::<Vec<_>>(), vec!["a", "a", "b"] );
1278/// ```
1279#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1280#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1281#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1282pub enum OneOrManyWithParens<T> {
1283    /// A single `T`, unparenthesized.
1284    One(T),
1285    /// One or more `T`s, parenthesized.
1286    Many(Vec<T>),
1287}
1288
1289impl<T> Deref for OneOrManyWithParens<T> {
1290    type Target = [T];
1291
1292    fn deref(&self) -> &[T] {
1293        match self {
1294            OneOrManyWithParens::One(one) => core::slice::from_ref(one),
1295            OneOrManyWithParens::Many(many) => many,
1296        }
1297    }
1298}
1299
1300impl<T> AsRef<[T]> for OneOrManyWithParens<T> {
1301    fn as_ref(&self) -> &[T] {
1302        self
1303    }
1304}
1305
1306impl<'a, T> IntoIterator for &'a OneOrManyWithParens<T> {
1307    type Item = &'a T;
1308    type IntoIter = core::slice::Iter<'a, T>;
1309
1310    fn into_iter(self) -> Self::IntoIter {
1311        self.iter()
1312    }
1313}
1314
1315/// Owned iterator implementation of `OneOrManyWithParens`
1316#[derive(Debug, Clone)]
1317pub struct OneOrManyWithParensIntoIter<T> {
1318    inner: OneOrManyWithParensIntoIterInner<T>,
1319}
1320
1321#[derive(Debug, Clone)]
1322enum OneOrManyWithParensIntoIterInner<T> {
1323    One(core::iter::Once<T>),
1324    Many(<Vec<T> as IntoIterator>::IntoIter),
1325}
1326
1327impl<T> core::iter::FusedIterator for OneOrManyWithParensIntoIter<T>
1328where
1329    core::iter::Once<T>: core::iter::FusedIterator,
1330    <Vec<T> as IntoIterator>::IntoIter: core::iter::FusedIterator,
1331{
1332}
1333
1334impl<T> core::iter::ExactSizeIterator for OneOrManyWithParensIntoIter<T>
1335where
1336    core::iter::Once<T>: core::iter::ExactSizeIterator,
1337    <Vec<T> as IntoIterator>::IntoIter: core::iter::ExactSizeIterator,
1338{
1339}
1340
1341impl<T> core::iter::Iterator for OneOrManyWithParensIntoIter<T> {
1342    type Item = T;
1343
1344    fn next(&mut self) -> Option<Self::Item> {
1345        match &mut self.inner {
1346            OneOrManyWithParensIntoIterInner::One(one) => one.next(),
1347            OneOrManyWithParensIntoIterInner::Many(many) => many.next(),
1348        }
1349    }
1350
1351    fn size_hint(&self) -> (usize, Option<usize>) {
1352        match &self.inner {
1353            OneOrManyWithParensIntoIterInner::One(one) => one.size_hint(),
1354            OneOrManyWithParensIntoIterInner::Many(many) => many.size_hint(),
1355        }
1356    }
1357
1358    fn count(self) -> usize
1359    where
1360        Self: Sized,
1361    {
1362        match self.inner {
1363            OneOrManyWithParensIntoIterInner::One(one) => one.count(),
1364            OneOrManyWithParensIntoIterInner::Many(many) => many.count(),
1365        }
1366    }
1367
1368    fn fold<B, F>(mut self, init: B, f: F) -> B
1369    where
1370        Self: Sized,
1371        F: FnMut(B, Self::Item) -> B,
1372    {
1373        match &mut self.inner {
1374            OneOrManyWithParensIntoIterInner::One(one) => one.fold(init, f),
1375            OneOrManyWithParensIntoIterInner::Many(many) => many.fold(init, f),
1376        }
1377    }
1378}
1379
1380impl<T> core::iter::DoubleEndedIterator for OneOrManyWithParensIntoIter<T> {
1381    fn next_back(&mut self) -> Option<Self::Item> {
1382        match &mut self.inner {
1383            OneOrManyWithParensIntoIterInner::One(one) => one.next_back(),
1384            OneOrManyWithParensIntoIterInner::Many(many) => many.next_back(),
1385        }
1386    }
1387}
1388
1389impl<T> IntoIterator for OneOrManyWithParens<T> {
1390    type Item = T;
1391
1392    type IntoIter = OneOrManyWithParensIntoIter<T>;
1393
1394    fn into_iter(self) -> Self::IntoIter {
1395        let inner = match self {
1396            OneOrManyWithParens::One(one) => {
1397                OneOrManyWithParensIntoIterInner::One(core::iter::once(one))
1398            }
1399            OneOrManyWithParens::Many(many) => {
1400                OneOrManyWithParensIntoIterInner::Many(many.into_iter())
1401            }
1402        };
1403
1404        OneOrManyWithParensIntoIter { inner }
1405    }
1406}
1407
1408impl<T> fmt::Display for OneOrManyWithParens<T>
1409where
1410    T: fmt::Display,
1411{
1412    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1413        match self {
1414            OneOrManyWithParens::One(value) => write!(f, "{value}"),
1415            OneOrManyWithParens::Many(values) => {
1416                write!(f, "({})", display_comma_separated(values))
1417            }
1418        }
1419    }
1420}
1421
1422impl fmt::Display for CastFormat {
1423    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1424        match self {
1425            CastFormat::Value(v) => write!(f, "{v}"),
1426            CastFormat::ValueAtTimeZone(v, tz) => write!(f, "{v} AT TIME ZONE {tz}"),
1427        }
1428    }
1429}
1430
1431impl fmt::Display for Expr {
1432    #[cfg_attr(feature = "recursive-protection", recursive::recursive)]
1433    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1434        match self {
1435            Expr::Identifier(s) => write!(f, "{s}"),
1436            Expr::Wildcard(_) => f.write_str("*"),
1437            Expr::QualifiedWildcard(prefix, _) => write!(f, "{prefix}.*"),
1438            Expr::CompoundIdentifier(s) => write!(f, "{}", display_separated(s, ".")),
1439            Expr::CompoundFieldAccess { root, access_chain } => {
1440                write!(f, "{root}")?;
1441                for field in access_chain {
1442                    write!(f, "{field}")?;
1443                }
1444                Ok(())
1445            }
1446            Expr::IsTrue(ast) => write!(f, "{ast} IS TRUE"),
1447            Expr::IsNotTrue(ast) => write!(f, "{ast} IS NOT TRUE"),
1448            Expr::IsFalse(ast) => write!(f, "{ast} IS FALSE"),
1449            Expr::IsNotFalse(ast) => write!(f, "{ast} IS NOT FALSE"),
1450            Expr::IsNull(ast) => write!(f, "{ast} IS NULL"),
1451            Expr::IsNotNull(ast) => write!(f, "{ast} IS NOT NULL"),
1452            Expr::IsUnknown(ast) => write!(f, "{ast} IS UNKNOWN"),
1453            Expr::IsNotUnknown(ast) => write!(f, "{ast} IS NOT UNKNOWN"),
1454            Expr::InList {
1455                expr,
1456                list,
1457                negated,
1458            } => write!(
1459                f,
1460                "{} {}IN ({})",
1461                expr,
1462                if *negated { "NOT " } else { "" },
1463                display_comma_separated(list)
1464            ),
1465            Expr::InSubquery {
1466                expr,
1467                subquery,
1468                negated,
1469            } => write!(
1470                f,
1471                "{} {}IN ({})",
1472                expr,
1473                if *negated { "NOT " } else { "" },
1474                subquery
1475            ),
1476            Expr::InUnnest {
1477                expr,
1478                array_expr,
1479                negated,
1480            } => write!(
1481                f,
1482                "{} {}IN UNNEST({})",
1483                expr,
1484                if *negated { "NOT " } else { "" },
1485                array_expr
1486            ),
1487            Expr::Between {
1488                expr,
1489                negated,
1490                low,
1491                high,
1492            } => write!(
1493                f,
1494                "{} {}BETWEEN {} AND {}",
1495                expr,
1496                if *negated { "NOT " } else { "" },
1497                low,
1498                high
1499            ),
1500            Expr::BinaryOp { left, op, right } => write!(f, "{left} {op} {right}"),
1501            Expr::Like {
1502                negated,
1503                expr,
1504                pattern,
1505                escape_char,
1506                any,
1507            } => match escape_char {
1508                Some(ch) => write!(
1509                    f,
1510                    "{} {}LIKE {}{} ESCAPE {}",
1511                    expr,
1512                    if *negated { "NOT " } else { "" },
1513                    if *any { "ANY " } else { "" },
1514                    pattern,
1515                    ch
1516                ),
1517                _ => write!(
1518                    f,
1519                    "{} {}LIKE {}{}",
1520                    expr,
1521                    if *negated { "NOT " } else { "" },
1522                    if *any { "ANY " } else { "" },
1523                    pattern
1524                ),
1525            },
1526            Expr::ILike {
1527                negated,
1528                expr,
1529                pattern,
1530                escape_char,
1531                any,
1532            } => match escape_char {
1533                Some(ch) => write!(
1534                    f,
1535                    "{} {}ILIKE {}{} ESCAPE {}",
1536                    expr,
1537                    if *negated { "NOT " } else { "" },
1538                    if *any { "ANY" } else { "" },
1539                    pattern,
1540                    ch
1541                ),
1542                _ => write!(
1543                    f,
1544                    "{} {}ILIKE {}{}",
1545                    expr,
1546                    if *negated { "NOT " } else { "" },
1547                    if *any { "ANY " } else { "" },
1548                    pattern
1549                ),
1550            },
1551            Expr::RLike {
1552                negated,
1553                expr,
1554                pattern,
1555                regexp,
1556            } => write!(
1557                f,
1558                "{} {}{} {}",
1559                expr,
1560                if *negated { "NOT " } else { "" },
1561                if *regexp { "REGEXP" } else { "RLIKE" },
1562                pattern
1563            ),
1564            Expr::IsNormalized {
1565                expr,
1566                form,
1567                negated,
1568            } => {
1569                let not_ = if *negated { "NOT " } else { "" };
1570                if form.is_none() {
1571                    write!(f, "{expr} IS {not_}NORMALIZED")
1572                } else {
1573                    write!(
1574                        f,
1575                        "{} IS {}{} NORMALIZED",
1576                        expr,
1577                        not_,
1578                        form.as_ref().unwrap()
1579                    )
1580                }
1581            }
1582            Expr::SimilarTo {
1583                negated,
1584                expr,
1585                pattern,
1586                escape_char,
1587            } => match escape_char {
1588                Some(ch) => write!(
1589                    f,
1590                    "{} {}SIMILAR TO {} ESCAPE {}",
1591                    expr,
1592                    if *negated { "NOT " } else { "" },
1593                    pattern,
1594                    ch
1595                ),
1596                _ => write!(
1597                    f,
1598                    "{} {}SIMILAR TO {}",
1599                    expr,
1600                    if *negated { "NOT " } else { "" },
1601                    pattern
1602                ),
1603            },
1604            Expr::AnyOp {
1605                left,
1606                compare_op,
1607                right,
1608                is_some,
1609            } => {
1610                let add_parens = !matches!(right.as_ref(), Expr::Subquery(_));
1611                write!(
1612                    f,
1613                    "{left} {compare_op} {}{}{right}{}",
1614                    if *is_some { "SOME" } else { "ANY" },
1615                    if add_parens { "(" } else { "" },
1616                    if add_parens { ")" } else { "" },
1617                )
1618            }
1619            Expr::AllOp {
1620                left,
1621                compare_op,
1622                right,
1623            } => {
1624                let add_parens = !matches!(right.as_ref(), Expr::Subquery(_));
1625                write!(
1626                    f,
1627                    "{left} {compare_op} ALL{}{right}{}",
1628                    if add_parens { "(" } else { "" },
1629                    if add_parens { ")" } else { "" },
1630                )
1631            }
1632            Expr::UnaryOp { op, expr } => {
1633                if op == &UnaryOperator::PGPostfixFactorial {
1634                    write!(f, "{expr}{op}")
1635                } else if matches!(
1636                    op,
1637                    UnaryOperator::Not
1638                        | UnaryOperator::Hash
1639                        | UnaryOperator::AtDashAt
1640                        | UnaryOperator::DoubleAt
1641                        | UnaryOperator::QuestionDash
1642                        | UnaryOperator::QuestionPipe
1643                ) {
1644                    write!(f, "{op} {expr}")
1645                } else {
1646                    write!(f, "{op}{expr}")
1647                }
1648            }
1649            Expr::Convert {
1650                is_try,
1651                expr,
1652                target_before_value,
1653                data_type,
1654                charset,
1655                styles,
1656            } => {
1657                write!(f, "{}CONVERT(", if *is_try { "TRY_" } else { "" })?;
1658                if let Some(data_type) = data_type {
1659                    if let Some(charset) = charset {
1660                        write!(f, "{expr}, {data_type} CHARACTER SET {charset}")
1661                    } else if *target_before_value {
1662                        write!(f, "{data_type}, {expr}")
1663                    } else {
1664                        write!(f, "{expr}, {data_type}")
1665                    }
1666                } else if let Some(charset) = charset {
1667                    write!(f, "{expr} USING {charset}")
1668                } else {
1669                    write!(f, "{expr}") // This should never happen
1670                }?;
1671                if !styles.is_empty() {
1672                    write!(f, ", {}", display_comma_separated(styles))?;
1673                }
1674                write!(f, ")")
1675            }
1676            Expr::Cast {
1677                kind,
1678                expr,
1679                data_type,
1680                format,
1681            } => match kind {
1682                CastKind::Cast => {
1683                    if let Some(format) = format {
1684                        write!(f, "CAST({expr} AS {data_type} FORMAT {format})")
1685                    } else {
1686                        write!(f, "CAST({expr} AS {data_type})")
1687                    }
1688                }
1689                CastKind::TryCast => {
1690                    if let Some(format) = format {
1691                        write!(f, "TRY_CAST({expr} AS {data_type} FORMAT {format})")
1692                    } else {
1693                        write!(f, "TRY_CAST({expr} AS {data_type})")
1694                    }
1695                }
1696                CastKind::SafeCast => {
1697                    if let Some(format) = format {
1698                        write!(f, "SAFE_CAST({expr} AS {data_type} FORMAT {format})")
1699                    } else {
1700                        write!(f, "SAFE_CAST({expr} AS {data_type})")
1701                    }
1702                }
1703                CastKind::DoubleColon => {
1704                    write!(f, "{expr}::{data_type}")
1705                }
1706            },
1707            Expr::Extract {
1708                field,
1709                syntax,
1710                expr,
1711            } => match syntax {
1712                ExtractSyntax::From => write!(f, "EXTRACT({field} FROM {expr})"),
1713                ExtractSyntax::Comma => write!(f, "EXTRACT({field}, {expr})"),
1714            },
1715            Expr::Ceil { expr, field } => match field {
1716                CeilFloorKind::DateTimeField(DateTimeField::NoDateTime) => {
1717                    write!(f, "CEIL({expr})")
1718                }
1719                CeilFloorKind::DateTimeField(dt_field) => write!(f, "CEIL({expr} TO {dt_field})"),
1720                CeilFloorKind::Scale(s) => write!(f, "CEIL({expr}, {s})"),
1721            },
1722            Expr::Floor { expr, field } => match field {
1723                CeilFloorKind::DateTimeField(DateTimeField::NoDateTime) => {
1724                    write!(f, "FLOOR({expr})")
1725                }
1726                CeilFloorKind::DateTimeField(dt_field) => write!(f, "FLOOR({expr} TO {dt_field})"),
1727                CeilFloorKind::Scale(s) => write!(f, "FLOOR({expr}, {s})"),
1728            },
1729            Expr::Position { expr, r#in } => write!(f, "POSITION({expr} IN {in})"),
1730            Expr::Collate { expr, collation } => write!(f, "{expr} COLLATE {collation}"),
1731            Expr::Nested(ast) => write!(f, "({ast})"),
1732            Expr::Value(v) => write!(f, "{v}"),
1733            Expr::Prefixed { prefix, value } => write!(f, "{prefix} {value}"),
1734            Expr::TypedString(ts) => ts.fmt(f),
1735            Expr::Function(fun) => fun.fmt(f),
1736            Expr::Case {
1737                case_token: _,
1738                end_token: _,
1739                operand,
1740                conditions,
1741                else_result,
1742            } => {
1743                f.write_str("CASE")?;
1744                if let Some(operand) = operand {
1745                    f.write_str(" ")?;
1746                    operand.fmt(f)?;
1747                }
1748                for when in conditions {
1749                    SpaceOrNewline.fmt(f)?;
1750                    Indent(when).fmt(f)?;
1751                }
1752                if let Some(else_result) = else_result {
1753                    SpaceOrNewline.fmt(f)?;
1754                    Indent("ELSE").fmt(f)?;
1755                    SpaceOrNewline.fmt(f)?;
1756                    Indent(Indent(else_result)).fmt(f)?;
1757                }
1758                SpaceOrNewline.fmt(f)?;
1759                f.write_str("END")
1760            }
1761            Expr::Exists { subquery, negated } => write!(
1762                f,
1763                "{}EXISTS ({})",
1764                if *negated { "NOT " } else { "" },
1765                subquery
1766            ),
1767            Expr::Subquery(s) => write!(f, "({s})"),
1768            Expr::GroupingSets(sets) => {
1769                write!(f, "GROUPING SETS (")?;
1770                let mut sep = "";
1771                for set in sets {
1772                    write!(f, "{sep}")?;
1773                    sep = ", ";
1774                    write!(f, "({})", display_comma_separated(set))?;
1775                }
1776                write!(f, ")")
1777            }
1778            Expr::Cube(sets) => {
1779                write!(f, "CUBE (")?;
1780                let mut sep = "";
1781                for set in sets {
1782                    write!(f, "{sep}")?;
1783                    sep = ", ";
1784                    if set.len() == 1 {
1785                        write!(f, "{}", set[0])?;
1786                    } else {
1787                        write!(f, "({})", display_comma_separated(set))?;
1788                    }
1789                }
1790                write!(f, ")")
1791            }
1792            Expr::Rollup(sets) => {
1793                write!(f, "ROLLUP (")?;
1794                let mut sep = "";
1795                for set in sets {
1796                    write!(f, "{sep}")?;
1797                    sep = ", ";
1798                    if set.len() == 1 {
1799                        write!(f, "{}", set[0])?;
1800                    } else {
1801                        write!(f, "({})", display_comma_separated(set))?;
1802                    }
1803                }
1804                write!(f, ")")
1805            }
1806            Expr::Substring {
1807                expr,
1808                substring_from,
1809                substring_for,
1810                special,
1811                shorthand,
1812            } => {
1813                f.write_str("SUBSTR")?;
1814                if !*shorthand {
1815                    f.write_str("ING")?;
1816                }
1817                write!(f, "({expr}")?;
1818                if let Some(from_part) = substring_from {
1819                    if *special {
1820                        write!(f, ", {from_part}")?;
1821                    } else {
1822                        write!(f, " FROM {from_part}")?;
1823                    }
1824                }
1825                if let Some(for_part) = substring_for {
1826                    if *special {
1827                        write!(f, ", {for_part}")?;
1828                    } else {
1829                        write!(f, " FOR {for_part}")?;
1830                    }
1831                }
1832
1833                write!(f, ")")
1834            }
1835            Expr::Overlay {
1836                expr,
1837                overlay_what,
1838                overlay_from,
1839                overlay_for,
1840            } => {
1841                write!(
1842                    f,
1843                    "OVERLAY({expr} PLACING {overlay_what} FROM {overlay_from}"
1844                )?;
1845                if let Some(for_part) = overlay_for {
1846                    write!(f, " FOR {for_part}")?;
1847                }
1848
1849                write!(f, ")")
1850            }
1851            Expr::IsDistinctFrom(a, b) => write!(f, "{a} IS DISTINCT FROM {b}"),
1852            Expr::IsNotDistinctFrom(a, b) => write!(f, "{a} IS NOT DISTINCT FROM {b}"),
1853            Expr::Trim {
1854                expr,
1855                trim_where,
1856                trim_what,
1857                trim_characters,
1858            } => {
1859                write!(f, "TRIM(")?;
1860                if let Some(ident) = trim_where {
1861                    write!(f, "{ident} ")?;
1862                }
1863                if let Some(trim_char) = trim_what {
1864                    write!(f, "{trim_char} FROM {expr}")?;
1865                } else {
1866                    write!(f, "{expr}")?;
1867                }
1868                if let Some(characters) = trim_characters {
1869                    write!(f, ", {}", display_comma_separated(characters))?;
1870                }
1871
1872                write!(f, ")")
1873            }
1874            Expr::Tuple(exprs) => {
1875                write!(f, "({})", display_comma_separated(exprs))
1876            }
1877            Expr::Struct { values, fields } => {
1878                if !fields.is_empty() {
1879                    write!(
1880                        f,
1881                        "STRUCT<{}>({})",
1882                        display_comma_separated(fields),
1883                        display_comma_separated(values)
1884                    )
1885                } else {
1886                    write!(f, "STRUCT({})", display_comma_separated(values))
1887                }
1888            }
1889            Expr::Named { expr, name } => {
1890                write!(f, "{expr} AS {name}")
1891            }
1892            Expr::Dictionary(fields) => {
1893                write!(f, "{{{}}}", display_comma_separated(fields))
1894            }
1895            Expr::Map(map) => {
1896                write!(f, "{map}")
1897            }
1898            Expr::Array(set) => {
1899                write!(f, "{set}")
1900            }
1901            Expr::JsonAccess { value, path } => {
1902                write!(f, "{value}{path}")
1903            }
1904            Expr::AtTimeZone {
1905                timestamp,
1906                time_zone,
1907            } => {
1908                write!(f, "{timestamp} AT TIME ZONE {time_zone}")
1909            }
1910            Expr::Interval(interval) => {
1911                write!(f, "{interval}")
1912            }
1913            Expr::MatchAgainst {
1914                columns,
1915                match_value: match_expr,
1916                opt_search_modifier,
1917            } => {
1918                write!(f, "MATCH ({}) AGAINST ", display_comma_separated(columns),)?;
1919
1920                if let Some(search_modifier) = opt_search_modifier {
1921                    write!(f, "({match_expr} {search_modifier})")?;
1922                } else {
1923                    write!(f, "({match_expr})")?;
1924                }
1925
1926                Ok(())
1927            }
1928            Expr::OuterJoin(expr) => {
1929                write!(f, "{expr} (+)")
1930            }
1931            Expr::Prior(expr) => write!(f, "PRIOR {expr}"),
1932            Expr::Lambda(lambda) => write!(f, "{lambda}"),
1933            Expr::MemberOf(member_of) => write!(f, "{member_of}"),
1934        }
1935    }
1936}
1937
1938#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1939#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1940#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1941pub enum WindowType {
1942    WindowSpec(WindowSpec),
1943    NamedWindow(Ident),
1944}
1945
1946impl Display for WindowType {
1947    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1948        match self {
1949            WindowType::WindowSpec(spec) => {
1950                f.write_str("(")?;
1951                NewLine.fmt(f)?;
1952                Indent(spec).fmt(f)?;
1953                NewLine.fmt(f)?;
1954                f.write_str(")")
1955            }
1956            WindowType::NamedWindow(name) => name.fmt(f),
1957        }
1958    }
1959}
1960
1961/// A window specification (i.e. `OVER ([window_name] PARTITION BY .. ORDER BY .. etc.)`)
1962#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1963#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1964#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1965pub struct WindowSpec {
1966    /// Optional window name.
1967    ///
1968    /// You can find it at least in [MySQL][1], [BigQuery][2], [PostgreSQL][3]
1969    ///
1970    /// [1]: https://dev.mysql.com/doc/refman/8.0/en/window-functions-named-windows.html
1971    /// [2]: https://cloud.google.com/bigquery/docs/reference/standard-sql/window-function-calls
1972    /// [3]: https://www.postgresql.org/docs/current/sql-expressions.html#SYNTAX-WINDOW-FUNCTIONS
1973    pub window_name: Option<Ident>,
1974    /// `OVER (PARTITION BY ...)`
1975    pub partition_by: Vec<Expr>,
1976    /// `OVER (ORDER BY ...)`
1977    pub order_by: Vec<OrderByExpr>,
1978    /// `OVER (window frame)`
1979    pub window_frame: Option<WindowFrame>,
1980}
1981
1982impl fmt::Display for WindowSpec {
1983    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1984        let mut is_first = true;
1985        if let Some(window_name) = &self.window_name {
1986            if !is_first {
1987                SpaceOrNewline.fmt(f)?;
1988            }
1989            is_first = false;
1990            write!(f, "{window_name}")?;
1991        }
1992        if !self.partition_by.is_empty() {
1993            if !is_first {
1994                SpaceOrNewline.fmt(f)?;
1995            }
1996            is_first = false;
1997            write!(
1998                f,
1999                "PARTITION BY {}",
2000                display_comma_separated(&self.partition_by)
2001            )?;
2002        }
2003        if !self.order_by.is_empty() {
2004            if !is_first {
2005                SpaceOrNewline.fmt(f)?;
2006            }
2007            is_first = false;
2008            write!(f, "ORDER BY {}", display_comma_separated(&self.order_by))?;
2009        }
2010        if let Some(window_frame) = &self.window_frame {
2011            if !is_first {
2012                SpaceOrNewline.fmt(f)?;
2013            }
2014            if let Some(end_bound) = &window_frame.end_bound {
2015                write!(
2016                    f,
2017                    "{} BETWEEN {} AND {}",
2018                    window_frame.units, window_frame.start_bound, end_bound
2019                )?;
2020            } else {
2021                write!(f, "{} {}", window_frame.units, window_frame.start_bound)?;
2022            }
2023        }
2024        Ok(())
2025    }
2026}
2027
2028/// Specifies the data processed by a window function, e.g.
2029/// `RANGE UNBOUNDED PRECEDING` or `ROWS BETWEEN 5 PRECEDING AND CURRENT ROW`.
2030///
2031/// Note: The parser does not validate the specified bounds; the caller should
2032/// reject invalid bounds like `ROWS UNBOUNDED FOLLOWING` before execution.
2033#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2034#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2035#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2036pub struct WindowFrame {
2037    pub units: WindowFrameUnits,
2038    pub start_bound: WindowFrameBound,
2039    /// The right bound of the `BETWEEN .. AND` clause. The end bound of `None`
2040    /// indicates the shorthand form (e.g. `ROWS 1 PRECEDING`), which must
2041    /// behave the same as `end_bound = WindowFrameBound::CurrentRow`.
2042    pub end_bound: Option<WindowFrameBound>,
2043    // TBD: EXCLUDE
2044}
2045
2046impl Default for WindowFrame {
2047    /// Returns default value for window frame
2048    ///
2049    /// See [this page](https://www.sqlite.org/windowfunctions.html#frame_specifications) for more details.
2050    fn default() -> Self {
2051        Self {
2052            units: WindowFrameUnits::Range,
2053            start_bound: WindowFrameBound::Preceding(None),
2054            end_bound: None,
2055        }
2056    }
2057}
2058
2059#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2060#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2061#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2062pub enum WindowFrameUnits {
2063    Rows,
2064    Range,
2065    Groups,
2066}
2067
2068impl fmt::Display for WindowFrameUnits {
2069    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2070        f.write_str(match self {
2071            WindowFrameUnits::Rows => "ROWS",
2072            WindowFrameUnits::Range => "RANGE",
2073            WindowFrameUnits::Groups => "GROUPS",
2074        })
2075    }
2076}
2077
2078/// Specifies Ignore / Respect NULL within window functions.
2079/// For example
2080/// `FIRST_VALUE(column2) IGNORE NULLS OVER (PARTITION BY column1)`
2081#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2082#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2083#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2084pub enum NullTreatment {
2085    IgnoreNulls,
2086    RespectNulls,
2087}
2088
2089impl fmt::Display for NullTreatment {
2090    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2091        f.write_str(match self {
2092            NullTreatment::IgnoreNulls => "IGNORE NULLS",
2093            NullTreatment::RespectNulls => "RESPECT NULLS",
2094        })
2095    }
2096}
2097
2098/// Specifies [WindowFrame]'s `start_bound` and `end_bound`
2099#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2100#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2101#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2102pub enum WindowFrameBound {
2103    /// `CURRENT ROW`
2104    CurrentRow,
2105    /// `<N> PRECEDING` or `UNBOUNDED PRECEDING`
2106    Preceding(Option<Box<Expr>>),
2107    /// `<N> FOLLOWING` or `UNBOUNDED FOLLOWING`.
2108    Following(Option<Box<Expr>>),
2109}
2110
2111impl fmt::Display for WindowFrameBound {
2112    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2113        match self {
2114            WindowFrameBound::CurrentRow => f.write_str("CURRENT ROW"),
2115            WindowFrameBound::Preceding(None) => f.write_str("UNBOUNDED PRECEDING"),
2116            WindowFrameBound::Following(None) => f.write_str("UNBOUNDED FOLLOWING"),
2117            WindowFrameBound::Preceding(Some(n)) => write!(f, "{n} PRECEDING"),
2118            WindowFrameBound::Following(Some(n)) => write!(f, "{n} FOLLOWING"),
2119        }
2120    }
2121}
2122
2123#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2124#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2125#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2126pub enum AddDropSync {
2127    ADD,
2128    DROP,
2129    SYNC,
2130}
2131
2132impl fmt::Display for AddDropSync {
2133    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2134        match self {
2135            AddDropSync::SYNC => f.write_str("SYNC PARTITIONS"),
2136            AddDropSync::DROP => f.write_str("DROP PARTITIONS"),
2137            AddDropSync::ADD => f.write_str("ADD PARTITIONS"),
2138        }
2139    }
2140}
2141
2142#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2143#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2144#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2145pub enum ShowCreateObject {
2146    Event,
2147    Function,
2148    Procedure,
2149    Table,
2150    Trigger,
2151    View,
2152}
2153
2154impl fmt::Display for ShowCreateObject {
2155    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2156        match self {
2157            ShowCreateObject::Event => f.write_str("EVENT"),
2158            ShowCreateObject::Function => f.write_str("FUNCTION"),
2159            ShowCreateObject::Procedure => f.write_str("PROCEDURE"),
2160            ShowCreateObject::Table => f.write_str("TABLE"),
2161            ShowCreateObject::Trigger => f.write_str("TRIGGER"),
2162            ShowCreateObject::View => f.write_str("VIEW"),
2163        }
2164    }
2165}
2166
2167#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2168#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2169#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2170pub enum CommentObject {
2171    Column,
2172    Table,
2173    Extension,
2174    Schema,
2175    Database,
2176    User,
2177    Role,
2178}
2179
2180impl fmt::Display for CommentObject {
2181    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2182        match self {
2183            CommentObject::Column => f.write_str("COLUMN"),
2184            CommentObject::Table => f.write_str("TABLE"),
2185            CommentObject::Extension => f.write_str("EXTENSION"),
2186            CommentObject::Schema => f.write_str("SCHEMA"),
2187            CommentObject::Database => f.write_str("DATABASE"),
2188            CommentObject::User => f.write_str("USER"),
2189            CommentObject::Role => f.write_str("ROLE"),
2190        }
2191    }
2192}
2193
2194#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2195#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2196#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2197pub enum Password {
2198    Password(Expr),
2199    NullPassword,
2200}
2201
2202/// A `CASE` statement.
2203///
2204/// Examples:
2205/// ```sql
2206/// CASE
2207///     WHEN EXISTS(SELECT 1)
2208///         THEN SELECT 1 FROM T;
2209///     WHEN EXISTS(SELECT 2)
2210///         THEN SELECT 1 FROM U;
2211///     ELSE
2212///         SELECT 1 FROM V;
2213/// END CASE;
2214/// ```
2215///
2216/// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#case_search_expression)
2217/// [Snowflake](https://docs.snowflake.com/en/sql-reference/snowflake-scripting/case)
2218#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2219#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2220#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2221pub struct CaseStatement {
2222    /// The `CASE` token that starts the statement.
2223    pub case_token: AttachedToken,
2224    pub match_expr: Option<Expr>,
2225    pub when_blocks: Vec<ConditionalStatementBlock>,
2226    pub else_block: Option<ConditionalStatementBlock>,
2227    /// The last token of the statement (`END` or `CASE`).
2228    pub end_case_token: AttachedToken,
2229}
2230
2231impl fmt::Display for CaseStatement {
2232    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2233        let CaseStatement {
2234            case_token: _,
2235            match_expr,
2236            when_blocks,
2237            else_block,
2238            end_case_token: AttachedToken(end),
2239        } = self;
2240
2241        write!(f, "CASE")?;
2242
2243        if let Some(expr) = match_expr {
2244            write!(f, " {expr}")?;
2245        }
2246
2247        if !when_blocks.is_empty() {
2248            write!(f, " {}", display_separated(when_blocks, " "))?;
2249        }
2250
2251        if let Some(else_block) = else_block {
2252            write!(f, " {else_block}")?;
2253        }
2254
2255        write!(f, " END")?;
2256
2257        if let Token::Word(w) = &end.token {
2258            if w.keyword == Keyword::CASE {
2259                write!(f, " CASE")?;
2260            }
2261        }
2262
2263        Ok(())
2264    }
2265}
2266
2267/// An `IF` statement.
2268///
2269/// Example (BigQuery or Snowflake):
2270/// ```sql
2271/// IF TRUE THEN
2272///     SELECT 1;
2273///     SELECT 2;
2274/// ELSEIF TRUE THEN
2275///     SELECT 3;
2276/// ELSE
2277///     SELECT 4;
2278/// END IF
2279/// ```
2280/// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#if)
2281/// [Snowflake](https://docs.snowflake.com/en/sql-reference/snowflake-scripting/if)
2282///
2283/// Example (MSSQL):
2284/// ```sql
2285/// IF 1=1 SELECT 1 ELSE SELECT 2
2286/// ```
2287/// [MSSQL](https://learn.microsoft.com/en-us/sql/t-sql/language-elements/if-else-transact-sql?view=sql-server-ver16)
2288#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2289#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2290#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2291pub struct IfStatement {
2292    pub if_block: ConditionalStatementBlock,
2293    pub elseif_blocks: Vec<ConditionalStatementBlock>,
2294    pub else_block: Option<ConditionalStatementBlock>,
2295    pub end_token: Option<AttachedToken>,
2296}
2297
2298impl fmt::Display for IfStatement {
2299    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2300        let IfStatement {
2301            if_block,
2302            elseif_blocks,
2303            else_block,
2304            end_token,
2305        } = self;
2306
2307        write!(f, "{if_block}")?;
2308
2309        for elseif_block in elseif_blocks {
2310            write!(f, " {elseif_block}")?;
2311        }
2312
2313        if let Some(else_block) = else_block {
2314            write!(f, " {else_block}")?;
2315        }
2316
2317        if let Some(AttachedToken(end_token)) = end_token {
2318            write!(f, " END {end_token}")?;
2319        }
2320
2321        Ok(())
2322    }
2323}
2324
2325/// A `WHILE` statement.
2326///
2327/// Example:
2328/// ```sql
2329/// WHILE @@FETCH_STATUS = 0
2330/// BEGIN
2331///    FETCH NEXT FROM c1 INTO @var1, @var2;
2332/// END
2333/// ```
2334///
2335/// [MsSql](https://learn.microsoft.com/en-us/sql/t-sql/language-elements/while-transact-sql)
2336#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2337#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2338#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2339pub struct WhileStatement {
2340    pub while_block: ConditionalStatementBlock,
2341}
2342
2343impl fmt::Display for WhileStatement {
2344    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2345        let WhileStatement { while_block } = self;
2346        write!(f, "{while_block}")?;
2347        Ok(())
2348    }
2349}
2350
2351/// A block within a [Statement::Case] or [Statement::If] or [Statement::While]-like statement
2352///
2353/// Example 1:
2354/// ```sql
2355/// WHEN EXISTS(SELECT 1) THEN SELECT 1;
2356/// ```
2357///
2358/// Example 2:
2359/// ```sql
2360/// IF TRUE THEN SELECT 1; SELECT 2;
2361/// ```
2362///
2363/// Example 3:
2364/// ```sql
2365/// ELSE SELECT 1; SELECT 2;
2366/// ```
2367///
2368/// Example 4:
2369/// ```sql
2370/// WHILE @@FETCH_STATUS = 0
2371/// BEGIN
2372///    FETCH NEXT FROM c1 INTO @var1, @var2;
2373/// END
2374/// ```
2375#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2376#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2377#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2378pub struct ConditionalStatementBlock {
2379    pub start_token: AttachedToken,
2380    pub condition: Option<Expr>,
2381    pub then_token: Option<AttachedToken>,
2382    pub conditional_statements: ConditionalStatements,
2383}
2384
2385impl ConditionalStatementBlock {
2386    pub fn statements(&self) -> &Vec<Statement> {
2387        self.conditional_statements.statements()
2388    }
2389}
2390
2391impl fmt::Display for ConditionalStatementBlock {
2392    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2393        let ConditionalStatementBlock {
2394            start_token: AttachedToken(start_token),
2395            condition,
2396            then_token,
2397            conditional_statements,
2398        } = self;
2399
2400        write!(f, "{start_token}")?;
2401
2402        if let Some(condition) = condition {
2403            write!(f, " {condition}")?;
2404        }
2405
2406        if then_token.is_some() {
2407            write!(f, " THEN")?;
2408        }
2409
2410        if !conditional_statements.statements().is_empty() {
2411            write!(f, " {conditional_statements}")?;
2412        }
2413
2414        Ok(())
2415    }
2416}
2417
2418/// A list of statements in a [ConditionalStatementBlock].
2419#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2420#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2421#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2422pub enum ConditionalStatements {
2423    /// SELECT 1; SELECT 2; SELECT 3; ...
2424    Sequence { statements: Vec<Statement> },
2425    /// BEGIN SELECT 1; SELECT 2; SELECT 3; ... END
2426    BeginEnd(BeginEndStatements),
2427}
2428
2429impl ConditionalStatements {
2430    pub fn statements(&self) -> &Vec<Statement> {
2431        match self {
2432            ConditionalStatements::Sequence { statements } => statements,
2433            ConditionalStatements::BeginEnd(bes) => &bes.statements,
2434        }
2435    }
2436}
2437
2438impl fmt::Display for ConditionalStatements {
2439    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2440        match self {
2441            ConditionalStatements::Sequence { statements } => {
2442                if !statements.is_empty() {
2443                    format_statement_list(f, statements)?;
2444                }
2445                Ok(())
2446            }
2447            ConditionalStatements::BeginEnd(bes) => write!(f, "{bes}"),
2448        }
2449    }
2450}
2451
2452/// Represents a list of statements enclosed within `BEGIN` and `END` keywords.
2453/// Example:
2454/// ```sql
2455/// BEGIN
2456///     SELECT 1;
2457///     SELECT 2;
2458/// END
2459/// ```
2460#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2461#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2462#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2463pub struct BeginEndStatements {
2464    pub begin_token: AttachedToken,
2465    pub statements: Vec<Statement>,
2466    pub end_token: AttachedToken,
2467}
2468
2469impl fmt::Display for BeginEndStatements {
2470    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2471        let BeginEndStatements {
2472            begin_token: AttachedToken(begin_token),
2473            statements,
2474            end_token: AttachedToken(end_token),
2475        } = self;
2476
2477        if begin_token.token != Token::EOF {
2478            write!(f, "{begin_token} ")?;
2479        }
2480        if !statements.is_empty() {
2481            format_statement_list(f, statements)?;
2482        }
2483        if end_token.token != Token::EOF {
2484            write!(f, " {end_token}")?;
2485        }
2486        Ok(())
2487    }
2488}
2489
2490/// A `RAISE` statement.
2491///
2492/// Examples:
2493/// ```sql
2494/// RAISE USING MESSAGE = 'error';
2495///
2496/// RAISE myerror;
2497/// ```
2498///
2499/// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#raise)
2500/// [Snowflake](https://docs.snowflake.com/en/sql-reference/snowflake-scripting/raise)
2501#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2502#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2503#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2504pub struct RaiseStatement {
2505    pub value: Option<RaiseStatementValue>,
2506}
2507
2508impl fmt::Display for RaiseStatement {
2509    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2510        let RaiseStatement { value } = self;
2511
2512        write!(f, "RAISE")?;
2513        if let Some(value) = value {
2514            write!(f, " {value}")?;
2515        }
2516
2517        Ok(())
2518    }
2519}
2520
2521/// Represents the error value of a [RaiseStatement].
2522#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2523#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2524#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2525pub enum RaiseStatementValue {
2526    /// `RAISE USING MESSAGE = 'error'`
2527    UsingMessage(Expr),
2528    /// `RAISE myerror`
2529    Expr(Expr),
2530}
2531
2532impl fmt::Display for RaiseStatementValue {
2533    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2534        match self {
2535            RaiseStatementValue::Expr(expr) => write!(f, "{expr}"),
2536            RaiseStatementValue::UsingMessage(expr) => write!(f, "USING MESSAGE = {expr}"),
2537        }
2538    }
2539}
2540
2541/// Represents an expression assignment within a variable `DECLARE` statement.
2542///
2543/// Examples:
2544/// ```sql
2545/// DECLARE variable_name := 42
2546/// DECLARE variable_name DEFAULT 42
2547/// ```
2548#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2549#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2550#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2551pub enum DeclareAssignment {
2552    /// Plain expression specified.
2553    Expr(Box<Expr>),
2554
2555    /// Expression assigned via the `DEFAULT` keyword
2556    Default(Box<Expr>),
2557
2558    /// Expression assigned via the `:=` syntax
2559    ///
2560    /// Example:
2561    /// ```sql
2562    /// DECLARE variable_name := 42;
2563    /// ```
2564    DuckAssignment(Box<Expr>),
2565
2566    /// Expression via the `FOR` keyword
2567    ///
2568    /// Example:
2569    /// ```sql
2570    /// DECLARE c1 CURSOR FOR res
2571    /// ```
2572    For(Box<Expr>),
2573
2574    /// Expression via the `=` syntax.
2575    ///
2576    /// Example:
2577    /// ```sql
2578    /// DECLARE @variable AS INT = 100
2579    /// ```
2580    MsSqlAssignment(Box<Expr>),
2581}
2582
2583impl fmt::Display for DeclareAssignment {
2584    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2585        match self {
2586            DeclareAssignment::Expr(expr) => {
2587                write!(f, "{expr}")
2588            }
2589            DeclareAssignment::Default(expr) => {
2590                write!(f, "DEFAULT {expr}")
2591            }
2592            DeclareAssignment::DuckAssignment(expr) => {
2593                write!(f, ":= {expr}")
2594            }
2595            DeclareAssignment::MsSqlAssignment(expr) => {
2596                write!(f, "= {expr}")
2597            }
2598            DeclareAssignment::For(expr) => {
2599                write!(f, "FOR {expr}")
2600            }
2601        }
2602    }
2603}
2604
2605/// Represents the type of a `DECLARE` statement.
2606#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2607#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2608#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2609pub enum DeclareType {
2610    /// Cursor variable type. e.g. [Snowflake] [PostgreSQL] [MsSql]
2611    ///
2612    /// [Snowflake]: https://docs.snowflake.com/en/developer-guide/snowflake-scripting/cursors#declaring-a-cursor
2613    /// [PostgreSQL]: https://www.postgresql.org/docs/current/plpgsql-cursors.html
2614    /// [MsSql]: https://learn.microsoft.com/en-us/sql/t-sql/language-elements/declare-cursor-transact-sql
2615    Cursor,
2616
2617    /// Result set variable type. [Snowflake]
2618    ///
2619    /// Syntax:
2620    /// ```text
2621    /// <resultset_name> RESULTSET [ { DEFAULT | := } ( <query> ) ] ;
2622    /// ```
2623    /// [Snowflake]: https://docs.snowflake.com/en/sql-reference/snowflake-scripting/declare#resultset-declaration-syntax
2624    ResultSet,
2625
2626    /// Exception declaration syntax. [Snowflake]
2627    ///
2628    /// Syntax:
2629    /// ```text
2630    /// <exception_name> EXCEPTION [ ( <exception_number> , '<exception_message>' ) ] ;
2631    /// ```
2632    /// [Snowflake]: https://docs.snowflake.com/en/sql-reference/snowflake-scripting/declare#exception-declaration-syntax
2633    Exception,
2634}
2635
2636impl fmt::Display for DeclareType {
2637    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2638        match self {
2639            DeclareType::Cursor => {
2640                write!(f, "CURSOR")
2641            }
2642            DeclareType::ResultSet => {
2643                write!(f, "RESULTSET")
2644            }
2645            DeclareType::Exception => {
2646                write!(f, "EXCEPTION")
2647            }
2648        }
2649    }
2650}
2651
2652/// A `DECLARE` statement.
2653/// [PostgreSQL] [Snowflake] [BigQuery]
2654///
2655/// Examples:
2656/// ```sql
2657/// DECLARE variable_name := 42
2658/// DECLARE liahona CURSOR FOR SELECT * FROM films;
2659/// ```
2660///
2661/// [PostgreSQL]: https://www.postgresql.org/docs/current/sql-declare.html
2662/// [Snowflake]: https://docs.snowflake.com/en/sql-reference/snowflake-scripting/declare
2663/// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#declare
2664#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2665#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2666#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2667pub struct Declare {
2668    /// The name(s) being declared.
2669    /// Example: `DECLARE a, b, c DEFAULT 42;
2670    pub names: Vec<Ident>,
2671    /// Data-type assigned to the declared variable.
2672    /// Example: `DECLARE x INT64 DEFAULT 42;
2673    pub data_type: Option<DataType>,
2674    /// Expression being assigned to the declared variable.
2675    pub assignment: Option<DeclareAssignment>,
2676    /// Represents the type of the declared variable.
2677    pub declare_type: Option<DeclareType>,
2678    /// Causes the cursor to return data in binary rather than in text format.
2679    pub binary: Option<bool>,
2680    /// None = Not specified
2681    /// Some(true) = INSENSITIVE
2682    /// Some(false) = ASENSITIVE
2683    pub sensitive: Option<bool>,
2684    /// None = Not specified
2685    /// Some(true) = SCROLL
2686    /// Some(false) = NO SCROLL
2687    pub scroll: Option<bool>,
2688    /// None = Not specified
2689    /// Some(true) = WITH HOLD, specifies that the cursor can continue to be used after the transaction that created it successfully commits
2690    /// Some(false) = WITHOUT HOLD, specifies that the cursor cannot be used outside of the transaction that created it
2691    pub hold: Option<bool>,
2692    /// `FOR <query>` clause in a CURSOR declaration.
2693    pub for_query: Option<Box<Query>>,
2694}
2695
2696impl fmt::Display for Declare {
2697    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2698        let Declare {
2699            names,
2700            data_type,
2701            assignment,
2702            declare_type,
2703            binary,
2704            sensitive,
2705            scroll,
2706            hold,
2707            for_query,
2708        } = self;
2709        write!(f, "{}", display_comma_separated(names))?;
2710
2711        if let Some(true) = binary {
2712            write!(f, " BINARY")?;
2713        }
2714
2715        if let Some(sensitive) = sensitive {
2716            if *sensitive {
2717                write!(f, " INSENSITIVE")?;
2718            } else {
2719                write!(f, " ASENSITIVE")?;
2720            }
2721        }
2722
2723        if let Some(scroll) = scroll {
2724            if *scroll {
2725                write!(f, " SCROLL")?;
2726            } else {
2727                write!(f, " NO SCROLL")?;
2728            }
2729        }
2730
2731        if let Some(declare_type) = declare_type {
2732            write!(f, " {declare_type}")?;
2733        }
2734
2735        if let Some(hold) = hold {
2736            if *hold {
2737                write!(f, " WITH HOLD")?;
2738            } else {
2739                write!(f, " WITHOUT HOLD")?;
2740            }
2741        }
2742
2743        if let Some(query) = for_query {
2744            write!(f, " FOR {query}")?;
2745        }
2746
2747        if let Some(data_type) = data_type {
2748            write!(f, " {data_type}")?;
2749        }
2750
2751        if let Some(expr) = assignment {
2752            write!(f, " {expr}")?;
2753        }
2754        Ok(())
2755    }
2756}
2757
2758/// Sql options of a `CREATE TABLE` statement.
2759#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2760#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2761#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2762pub enum CreateTableOptions {
2763    None,
2764    /// Options specified using the `WITH` keyword.
2765    /// e.g. `WITH (description = "123")`
2766    ///
2767    /// <https://www.postgresql.org/docs/current/sql-createtable.html>
2768    ///
2769    /// MSSQL supports more specific options that's not only key-value pairs.
2770    ///
2771    /// WITH (
2772    ///     DISTRIBUTION = ROUND_ROBIN,
2773    ///     CLUSTERED INDEX (column_a DESC, column_b)
2774    /// )
2775    ///
2776    /// <https://learn.microsoft.com/en-us/sql/t-sql/statements/create-table-azure-sql-data-warehouse?view=aps-pdw-2016-au7#syntax>
2777    With(Vec<SqlOption>),
2778    /// Options specified using the `OPTIONS` keyword.
2779    /// e.g. `OPTIONS(description = "123")`
2780    ///
2781    /// <https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#table_option_list>
2782    Options(Vec<SqlOption>),
2783
2784    /// Plain options, options which are not part on any declerative statement e.g. WITH/OPTIONS/...
2785    /// <https://dev.mysql.com/doc/refman/8.4/en/create-table.html>
2786    Plain(Vec<SqlOption>),
2787
2788    TableProperties(Vec<SqlOption>),
2789}
2790
2791impl Default for CreateTableOptions {
2792    fn default() -> Self {
2793        Self::None
2794    }
2795}
2796
2797impl fmt::Display for CreateTableOptions {
2798    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2799        match self {
2800            CreateTableOptions::With(with_options) => {
2801                write!(f, "WITH ({})", display_comma_separated(with_options))
2802            }
2803            CreateTableOptions::Options(options) => {
2804                write!(f, "OPTIONS({})", display_comma_separated(options))
2805            }
2806            CreateTableOptions::TableProperties(options) => {
2807                write!(f, "TBLPROPERTIES ({})", display_comma_separated(options))
2808            }
2809            CreateTableOptions::Plain(options) => {
2810                write!(f, "{}", display_separated(options, " "))
2811            }
2812            CreateTableOptions::None => Ok(()),
2813        }
2814    }
2815}
2816
2817/// A `FROM` clause within a `DELETE` statement.
2818///
2819/// Syntax
2820/// ```sql
2821/// [FROM] table
2822/// ```
2823#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2824#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2825#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2826pub enum FromTable {
2827    /// An explicit `FROM` keyword was specified.
2828    WithFromKeyword(Vec<TableWithJoins>),
2829    /// BigQuery: `FROM` keyword was omitted.
2830    /// <https://cloud.google.com/bigquery/docs/reference/standard-sql/dml-syntax#delete_statement>
2831    WithoutKeyword(Vec<TableWithJoins>),
2832}
2833impl Display for FromTable {
2834    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2835        match self {
2836            FromTable::WithFromKeyword(tables) => {
2837                write!(f, "FROM {}", display_comma_separated(tables))
2838            }
2839            FromTable::WithoutKeyword(tables) => {
2840                write!(f, "{}", display_comma_separated(tables))
2841            }
2842        }
2843    }
2844}
2845
2846/// Policy type for a `CREATE POLICY` statement.
2847/// ```sql
2848/// AS [ PERMISSIVE | RESTRICTIVE ]
2849/// ```
2850/// [PostgreSQL](https://www.postgresql.org/docs/current/sql-createpolicy.html)
2851#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2852#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2853#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2854pub enum CreatePolicyType {
2855    Permissive,
2856    Restrictive,
2857}
2858
2859/// Policy command for a `CREATE POLICY` statement.
2860/// ```sql
2861/// FOR [ALL | SELECT | INSERT | UPDATE | DELETE]
2862/// ```
2863/// [PostgreSQL](https://www.postgresql.org/docs/current/sql-createpolicy.html)
2864#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2865#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2866#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2867pub enum CreatePolicyCommand {
2868    All,
2869    Select,
2870    Insert,
2871    Update,
2872    Delete,
2873}
2874
2875#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2876#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2877#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2878pub enum Set {
2879    /// SQL Standard-style
2880    /// SET a = 1;
2881    SingleAssignment {
2882        scope: Option<ContextModifier>,
2883        hivevar: bool,
2884        variable: ObjectName,
2885        values: Vec<Expr>,
2886    },
2887    /// Snowflake-style
2888    /// SET (a, b, ..) = (1, 2, ..);
2889    ParenthesizedAssignments {
2890        variables: Vec<ObjectName>,
2891        values: Vec<Expr>,
2892    },
2893    /// MySQL-style
2894    /// SET a = 1, b = 2, ..;
2895    MultipleAssignments { assignments: Vec<SetAssignment> },
2896    /// MS-SQL session
2897    ///
2898    /// See <https://learn.microsoft.com/en-us/sql/t-sql/statements/set-statements-transact-sql>
2899    SetSessionParam(SetSessionParamKind),
2900    /// ```sql
2901    /// SET [ SESSION | LOCAL ] ROLE role_name
2902    /// ```
2903    ///
2904    /// Sets session state. Examples: [ANSI][1], [Postgresql][2], [MySQL][3], and [Oracle][4]
2905    ///
2906    /// [1]: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#set-role-statement
2907    /// [2]: https://www.postgresql.org/docs/14/sql-set-role.html
2908    /// [3]: https://dev.mysql.com/doc/refman/8.0/en/set-role.html
2909    /// [4]: https://docs.oracle.com/cd/B19306_01/server.102/b14200/statements_10004.htm
2910    SetRole {
2911        /// Non-ANSI optional identifier to inform if the role is defined inside the current session (`SESSION`) or transaction (`LOCAL`).
2912        context_modifier: Option<ContextModifier>,
2913        /// Role name. If NONE is specified, then the current role name is removed.
2914        role_name: Option<Ident>,
2915    },
2916    /// ```sql
2917    /// SET TIME ZONE <value>
2918    /// ```
2919    ///
2920    /// Note: this is a PostgreSQL-specific statements
2921    /// `SET TIME ZONE <value>` is an alias for `SET timezone TO <value>` in PostgreSQL
2922    /// However, we allow it for all dialects.
2923    SetTimeZone { local: bool, value: Expr },
2924    /// ```sql
2925    /// SET NAMES 'charset_name' [COLLATE 'collation_name']
2926    /// ```
2927    SetNames {
2928        charset_name: Ident,
2929        collation_name: Option<String>,
2930    },
2931    /// ```sql
2932    /// SET NAMES DEFAULT
2933    /// ```
2934    ///
2935    /// Note: this is a MySQL-specific statement.
2936    SetNamesDefault {},
2937    /// ```sql
2938    /// SET TRANSACTION ...
2939    /// ```
2940    SetTransaction {
2941        modes: Vec<TransactionMode>,
2942        snapshot: Option<Value>,
2943        session: bool,
2944    },
2945}
2946
2947impl Display for Set {
2948    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2949        match self {
2950            Self::ParenthesizedAssignments { variables, values } => write!(
2951                f,
2952                "SET ({}) = ({})",
2953                display_comma_separated(variables),
2954                display_comma_separated(values)
2955            ),
2956            Self::MultipleAssignments { assignments } => {
2957                write!(f, "SET {}", display_comma_separated(assignments))
2958            }
2959            Self::SetRole {
2960                context_modifier,
2961                role_name,
2962            } => {
2963                let role_name = role_name.clone().unwrap_or_else(|| Ident::new("NONE"));
2964                write!(
2965                    f,
2966                    "SET {modifier}ROLE {role_name}",
2967                    modifier = context_modifier.map(|m| format!("{m}")).unwrap_or_default()
2968                )
2969            }
2970            Self::SetSessionParam(kind) => write!(f, "SET {kind}"),
2971            Self::SetTransaction {
2972                modes,
2973                snapshot,
2974                session,
2975            } => {
2976                if *session {
2977                    write!(f, "SET SESSION CHARACTERISTICS AS TRANSACTION")?;
2978                } else {
2979                    write!(f, "SET TRANSACTION")?;
2980                }
2981                if !modes.is_empty() {
2982                    write!(f, " {}", display_comma_separated(modes))?;
2983                }
2984                if let Some(snapshot_id) = snapshot {
2985                    write!(f, " SNAPSHOT {snapshot_id}")?;
2986                }
2987                Ok(())
2988            }
2989            Self::SetTimeZone { local, value } => {
2990                f.write_str("SET ")?;
2991                if *local {
2992                    f.write_str("LOCAL ")?;
2993                }
2994                write!(f, "TIME ZONE {value}")
2995            }
2996            Self::SetNames {
2997                charset_name,
2998                collation_name,
2999            } => {
3000                write!(f, "SET NAMES {charset_name}")?;
3001
3002                if let Some(collation) = collation_name {
3003                    f.write_str(" COLLATE ")?;
3004                    f.write_str(collation)?;
3005                };
3006
3007                Ok(())
3008            }
3009            Self::SetNamesDefault {} => {
3010                f.write_str("SET NAMES DEFAULT")?;
3011
3012                Ok(())
3013            }
3014            Set::SingleAssignment {
3015                scope,
3016                hivevar,
3017                variable,
3018                values,
3019            } => {
3020                write!(
3021                    f,
3022                    "SET {}{}{} = {}",
3023                    scope.map(|s| format!("{s}")).unwrap_or_default(),
3024                    if *hivevar { "HIVEVAR:" } else { "" },
3025                    variable,
3026                    display_comma_separated(values)
3027                )
3028            }
3029        }
3030    }
3031}
3032
3033/// A representation of a `WHEN` arm with all the identifiers catched and the statements to execute
3034/// for the arm.
3035///
3036/// Snowflake: <https://docs.snowflake.com/en/sql-reference/snowflake-scripting/exception>
3037/// BigQuery: <https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#beginexceptionend>
3038#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3039#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3040#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3041pub struct ExceptionWhen {
3042    pub idents: Vec<Ident>,
3043    pub statements: Vec<Statement>,
3044}
3045
3046impl Display for ExceptionWhen {
3047    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3048        write!(
3049            f,
3050            "WHEN {idents} THEN",
3051            idents = display_separated(&self.idents, " OR ")
3052        )?;
3053
3054        if !self.statements.is_empty() {
3055            write!(f, " ")?;
3056            format_statement_list(f, &self.statements)?;
3057        }
3058
3059        Ok(())
3060    }
3061}
3062
3063/// A top-level statement (SELECT, INSERT, CREATE, etc.)
3064#[allow(clippy::large_enum_variant)]
3065#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3066#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3067#[cfg_attr(
3068    feature = "visitor",
3069    derive(Visit, VisitMut),
3070    visit(with = "visit_statement")
3071)]
3072pub enum Statement {
3073    /// ```sql
3074    /// ANALYZE
3075    /// ```
3076    /// Analyze (Hive)
3077    Analyze {
3078        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
3079        table_name: ObjectName,
3080        partitions: Option<Vec<Expr>>,
3081        for_columns: bool,
3082        columns: Vec<Ident>,
3083        cache_metadata: bool,
3084        noscan: bool,
3085        compute_statistics: bool,
3086        has_table_keyword: bool,
3087    },
3088    Set(Set),
3089    /// ```sql
3090    /// TRUNCATE
3091    /// ```
3092    /// Truncate (Hive)
3093    Truncate {
3094        table_names: Vec<TruncateTableTarget>,
3095        partitions: Option<Vec<Expr>>,
3096        /// TABLE - optional keyword;
3097        table: bool,
3098        /// Postgres-specific option
3099        /// [ RESTART IDENTITY | CONTINUE IDENTITY ]
3100        identity: Option<TruncateIdentityOption>,
3101        /// Postgres-specific option
3102        /// [ CASCADE | RESTRICT ]
3103        cascade: Option<CascadeOption>,
3104        /// ClickHouse-specific option
3105        /// [ ON CLUSTER cluster_name ]
3106        ///
3107        /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/truncate/)
3108        on_cluster: Option<Ident>,
3109    },
3110    /// ```sql
3111    /// MSCK
3112    /// ```
3113    /// Msck (Hive)
3114    Msck {
3115        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
3116        table_name: ObjectName,
3117        repair: bool,
3118        partition_action: Option<AddDropSync>,
3119    },
3120    /// ```sql
3121    /// SELECT
3122    /// ```
3123    Query(Box<Query>),
3124    /// ```sql
3125    /// INSERT
3126    /// ```
3127    Insert(Insert),
3128    /// ```sql
3129    /// INSTALL
3130    /// ```
3131    Install {
3132        /// Only for DuckDB
3133        extension_name: Ident,
3134    },
3135    /// ```sql
3136    /// LOAD
3137    /// ```
3138    Load {
3139        /// Only for DuckDB
3140        extension_name: Ident,
3141    },
3142    // TODO: Support ROW FORMAT
3143    Directory {
3144        overwrite: bool,
3145        local: bool,
3146        path: String,
3147        file_format: Option<FileFormat>,
3148        source: Box<Query>,
3149    },
3150    /// A `CASE` statement.
3151    Case(CaseStatement),
3152    /// An `IF` statement.
3153    If(IfStatement),
3154    /// A `WHILE` statement.
3155    While(WhileStatement),
3156    /// A `RAISE` statement.
3157    Raise(RaiseStatement),
3158    /// ```sql
3159    /// CALL <function>
3160    /// ```
3161    Call(Function),
3162    /// ```sql
3163    /// COPY [TO | FROM] ...
3164    /// ```
3165    Copy {
3166        /// The source of 'COPY TO', or the target of 'COPY FROM'
3167        source: CopySource,
3168        /// If true, is a 'COPY TO' statement. If false is a 'COPY FROM'
3169        to: bool,
3170        /// The target of 'COPY TO', or the source of 'COPY FROM'
3171        target: CopyTarget,
3172        /// WITH options (from PostgreSQL version 9.0)
3173        options: Vec<CopyOption>,
3174        /// WITH options (before PostgreSQL version 9.0)
3175        legacy_options: Vec<CopyLegacyOption>,
3176        /// VALUES a vector of values to be copied
3177        values: Vec<Option<String>>,
3178    },
3179    /// ```sql
3180    /// COPY INTO <table> | <location>
3181    /// ```
3182    /// See:
3183    /// <https://docs.snowflake.com/en/sql-reference/sql/copy-into-table>
3184    /// <https://docs.snowflake.com/en/sql-reference/sql/copy-into-location>
3185    ///
3186    /// Copy Into syntax available for Snowflake is different than the one implemented in
3187    /// Postgres. Although they share common prefix, it is reasonable to implement them
3188    /// in different enums. This can be refactored later once custom dialects
3189    /// are allowed to have custom Statements.
3190    CopyIntoSnowflake {
3191        kind: CopyIntoSnowflakeKind,
3192        into: ObjectName,
3193        into_columns: Option<Vec<Ident>>,
3194        from_obj: Option<ObjectName>,
3195        from_obj_alias: Option<Ident>,
3196        stage_params: StageParamsObject,
3197        from_transformations: Option<Vec<StageLoadSelectItemKind>>,
3198        from_query: Option<Box<Query>>,
3199        files: Option<Vec<String>>,
3200        pattern: Option<String>,
3201        file_format: KeyValueOptions,
3202        copy_options: KeyValueOptions,
3203        validation_mode: Option<String>,
3204        partition: Option<Box<Expr>>,
3205    },
3206    /// ```sql
3207    /// OPEN cursor_name
3208    /// ```
3209    /// Opens a cursor.
3210    Open(OpenStatement),
3211    /// ```sql
3212    /// CLOSE
3213    /// ```
3214    /// Closes the portal underlying an open cursor.
3215    Close {
3216        /// Cursor name
3217        cursor: CloseCursor,
3218    },
3219    /// ```sql
3220    /// UPDATE
3221    /// ```
3222    Update {
3223        /// TABLE
3224        table: TableWithJoins,
3225        /// Column assignments
3226        assignments: Vec<Assignment>,
3227        /// Table which provide value to be set
3228        from: Option<UpdateTableFromKind>,
3229        /// WHERE
3230        selection: Option<Expr>,
3231        /// RETURNING
3232        returning: Option<Vec<SelectItem>>,
3233        /// SQLite-specific conflict resolution clause
3234        or: Option<SqliteOnConflict>,
3235        /// LIMIT
3236        limit: Option<Expr>,
3237    },
3238    /// ```sql
3239    /// DELETE
3240    /// ```
3241    Delete(Delete),
3242    /// ```sql
3243    /// CREATE VIEW
3244    /// ```
3245    CreateView {
3246        /// True if this is a `CREATE OR ALTER VIEW` statement
3247        ///
3248        /// [MsSql](https://learn.microsoft.com/en-us/sql/t-sql/statements/create-view-transact-sql)
3249        or_alter: bool,
3250        or_replace: bool,
3251        materialized: bool,
3252        /// Snowflake: SECURE view modifier
3253        /// <https://docs.snowflake.com/en/sql-reference/sql/create-view#syntax>
3254        secure: bool,
3255        /// View name
3256        name: ObjectName,
3257        /// If `if_not_exists` is true, this flag is set to true if the view name comes before the `IF NOT EXISTS` clause.
3258        /// Example:
3259        /// ```sql
3260        /// CREATE VIEW myview IF NOT EXISTS AS SELECT 1`
3261        ///  ```
3262        /// Otherwise, the flag is set to false if the view name comes after the clause
3263        /// Example:
3264        /// ```sql
3265        /// CREATE VIEW IF NOT EXISTS myview AS SELECT 1`
3266        ///  ```
3267        name_before_not_exists: bool,
3268        columns: Vec<ViewColumnDef>,
3269        query: Box<Query>,
3270        options: CreateTableOptions,
3271        cluster_by: Vec<Ident>,
3272        /// Snowflake: Views can have comments in Snowflake.
3273        /// <https://docs.snowflake.com/en/sql-reference/sql/create-view#syntax>
3274        comment: Option<String>,
3275        /// if true, has RedShift [`WITH NO SCHEMA BINDING`] clause <https://docs.aws.amazon.com/redshift/latest/dg/r_CREATE_VIEW.html>
3276        with_no_schema_binding: bool,
3277        /// if true, has SQLite `IF NOT EXISTS` clause <https://www.sqlite.org/lang_createview.html>
3278        if_not_exists: bool,
3279        /// if true, has SQLite `TEMP` or `TEMPORARY` clause <https://www.sqlite.org/lang_createview.html>
3280        temporary: bool,
3281        /// if not None, has Clickhouse `TO` clause, specify the table into which to insert results
3282        /// <https://clickhouse.com/docs/en/sql-reference/statements/create/view#materialized-view>
3283        to: Option<ObjectName>,
3284        /// MySQL: Optional parameters for the view algorithm, definer, and security context
3285        params: Option<CreateViewParams>,
3286    },
3287    /// ```sql
3288    /// CREATE TABLE
3289    /// ```
3290    CreateTable(CreateTable),
3291    /// ```sql
3292    /// CREATE VIRTUAL TABLE .. USING <module_name> (<module_args>)`
3293    /// ```
3294    /// Sqlite specific statement
3295    CreateVirtualTable {
3296        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
3297        name: ObjectName,
3298        if_not_exists: bool,
3299        module_name: Ident,
3300        module_args: Vec<Ident>,
3301    },
3302    /// ```sql
3303    /// `CREATE INDEX`
3304    /// ```
3305    CreateIndex(CreateIndex),
3306    /// ```sql
3307    /// CREATE ROLE
3308    /// ```
3309    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createrole.html)
3310    CreateRole {
3311        names: Vec<ObjectName>,
3312        if_not_exists: bool,
3313        // Postgres
3314        login: Option<bool>,
3315        inherit: Option<bool>,
3316        bypassrls: Option<bool>,
3317        password: Option<Password>,
3318        superuser: Option<bool>,
3319        create_db: Option<bool>,
3320        create_role: Option<bool>,
3321        replication: Option<bool>,
3322        connection_limit: Option<Expr>,
3323        valid_until: Option<Expr>,
3324        in_role: Vec<Ident>,
3325        in_group: Vec<Ident>,
3326        role: Vec<Ident>,
3327        user: Vec<Ident>,
3328        admin: Vec<Ident>,
3329        // MSSQL
3330        authorization_owner: Option<ObjectName>,
3331    },
3332    /// ```sql
3333    /// CREATE SECRET
3334    /// ```
3335    /// See [DuckDB](https://duckdb.org/docs/sql/statements/create_secret.html)
3336    CreateSecret {
3337        or_replace: bool,
3338        temporary: Option<bool>,
3339        if_not_exists: bool,
3340        name: Option<Ident>,
3341        storage_specifier: Option<Ident>,
3342        secret_type: Ident,
3343        options: Vec<SecretOption>,
3344    },
3345    /// A `CREATE SERVER` statement.
3346    CreateServer(CreateServerStatement),
3347    /// ```sql
3348    /// CREATE POLICY
3349    /// ```
3350    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createpolicy.html)
3351    CreatePolicy {
3352        name: Ident,
3353        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
3354        table_name: ObjectName,
3355        policy_type: Option<CreatePolicyType>,
3356        command: Option<CreatePolicyCommand>,
3357        to: Option<Vec<Owner>>,
3358        using: Option<Expr>,
3359        with_check: Option<Expr>,
3360    },
3361    /// ```sql
3362    /// CREATE CONNECTOR
3363    /// ```
3364    /// See [Hive](https://cwiki.apache.org/confluence/pages/viewpage.action?pageId=27362034#LanguageManualDDL-CreateDataConnectorCreateConnector)
3365    CreateConnector(CreateConnector),
3366    /// ```sql
3367    /// ALTER TABLE
3368    /// ```
3369    AlterTable {
3370        /// Table name
3371        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
3372        name: ObjectName,
3373        if_exists: bool,
3374        only: bool,
3375        operations: Vec<AlterTableOperation>,
3376        location: Option<HiveSetLocation>,
3377        /// ClickHouse dialect supports `ON CLUSTER` clause for ALTER TABLE
3378        /// For example: `ALTER TABLE table_name ON CLUSTER cluster_name ADD COLUMN c UInt32`
3379        /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/alter/update)
3380        on_cluster: Option<Ident>,
3381        /// Snowflake "ICEBERG" clause for Iceberg tables
3382        /// <https://docs.snowflake.com/en/sql-reference/sql/alter-iceberg-table>
3383        iceberg: bool,
3384        /// Token that represents the end of the statement (semicolon or EOF)
3385        end_token: AttachedToken,
3386    },
3387    /// ```sql
3388    /// ALTER SCHEMA
3389    /// ```
3390    /// See [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#alter_schema_collate_statement)
3391    AlterSchema(AlterSchema),
3392    /// ```sql
3393    /// ALTER INDEX
3394    /// ```
3395    AlterIndex {
3396        name: ObjectName,
3397        operation: AlterIndexOperation,
3398    },
3399    /// ```sql
3400    /// ALTER VIEW
3401    /// ```
3402    AlterView {
3403        /// View name
3404        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
3405        name: ObjectName,
3406        columns: Vec<Ident>,
3407        query: Box<Query>,
3408        with_options: Vec<SqlOption>,
3409    },
3410    /// ```sql
3411    /// ALTER TYPE
3412    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-altertype.html)
3413    /// ```
3414    AlterType(AlterType),
3415    /// ```sql
3416    /// ALTER ROLE
3417    /// ```
3418    AlterRole {
3419        name: Ident,
3420        operation: AlterRoleOperation,
3421    },
3422    /// ```sql
3423    /// ALTER POLICY <NAME> ON <TABLE NAME> [<OPERATION>]
3424    /// ```
3425    /// (Postgresql-specific)
3426    AlterPolicy {
3427        name: Ident,
3428        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
3429        table_name: ObjectName,
3430        operation: AlterPolicyOperation,
3431    },
3432    /// ```sql
3433    /// ALTER CONNECTOR connector_name SET DCPROPERTIES(property_name=property_value, ...);
3434    /// or
3435    /// ALTER CONNECTOR connector_name SET URL new_url;
3436    /// or
3437    /// ALTER CONNECTOR connector_name SET OWNER [USER|ROLE] user_or_role;
3438    /// ```
3439    /// (Hive-specific)
3440    AlterConnector {
3441        name: Ident,
3442        properties: Option<Vec<SqlOption>>,
3443        url: Option<String>,
3444        owner: Option<ddl::AlterConnectorOwner>,
3445    },
3446    /// ```sql
3447    /// ALTER SESSION SET sessionParam
3448    /// ALTER SESSION UNSET <param_name> [ , <param_name> , ... ]
3449    /// ```
3450    /// See <https://docs.snowflake.com/en/sql-reference/sql/alter-session>
3451    AlterSession {
3452        /// true is to set for the session parameters, false is to unset
3453        set: bool,
3454        /// The session parameters to set or unset
3455        session_params: KeyValueOptions,
3456    },
3457    /// ```sql
3458    /// ATTACH DATABASE 'path/to/file' AS alias
3459    /// ```
3460    /// (SQLite-specific)
3461    AttachDatabase {
3462        /// The name to bind to the newly attached database
3463        schema_name: Ident,
3464        /// An expression that indicates the path to the database file
3465        database_file_name: Expr,
3466        /// true if the syntax is 'ATTACH DATABASE', false if it's just 'ATTACH'
3467        database: bool,
3468    },
3469    /// (DuckDB-specific)
3470    /// ```sql
3471    /// ATTACH 'sqlite_file.db' AS sqlite_db (READ_ONLY, TYPE SQLITE);
3472    /// ```
3473    /// See <https://duckdb.org/docs/sql/statements/attach.html>
3474    AttachDuckDBDatabase {
3475        if_not_exists: bool,
3476        /// true if the syntax is 'ATTACH DATABASE', false if it's just 'ATTACH'
3477        database: bool,
3478        /// An expression that indicates the path to the database file
3479        database_path: Ident,
3480        database_alias: Option<Ident>,
3481        attach_options: Vec<AttachDuckDBDatabaseOption>,
3482    },
3483    /// (DuckDB-specific)
3484    /// ```sql
3485    /// DETACH db_alias;
3486    /// ```
3487    /// See <https://duckdb.org/docs/sql/statements/attach.html>
3488    DetachDuckDBDatabase {
3489        if_exists: bool,
3490        /// true if the syntax is 'DETACH DATABASE', false if it's just 'DETACH'
3491        database: bool,
3492        database_alias: Ident,
3493    },
3494    /// ```sql
3495    /// DROP [TABLE, VIEW, ...]
3496    /// ```
3497    Drop {
3498        /// The type of the object to drop: TABLE, VIEW, etc.
3499        object_type: ObjectType,
3500        /// An optional `IF EXISTS` clause. (Non-standard.)
3501        if_exists: bool,
3502        /// One or more objects to drop. (ANSI SQL requires exactly one.)
3503        names: Vec<ObjectName>,
3504        /// Whether `CASCADE` was specified. This will be `false` when
3505        /// `RESTRICT` or no drop behavior at all was specified.
3506        cascade: bool,
3507        /// Whether `RESTRICT` was specified. This will be `false` when
3508        /// `CASCADE` or no drop behavior at all was specified.
3509        restrict: bool,
3510        /// Hive allows you specify whether the table's stored data will be
3511        /// deleted along with the dropped table
3512        purge: bool,
3513        /// MySQL-specific "TEMPORARY" keyword
3514        temporary: bool,
3515        /// MySQL-specific drop index syntax, which requires table specification
3516        /// See <https://dev.mysql.com/doc/refman/8.4/en/drop-index.html>
3517        table: Option<ObjectName>,
3518    },
3519    /// ```sql
3520    /// DROP FUNCTION
3521    /// ```
3522    DropFunction {
3523        if_exists: bool,
3524        /// One or more function to drop
3525        func_desc: Vec<FunctionDesc>,
3526        /// `CASCADE` or `RESTRICT`
3527        drop_behavior: Option<DropBehavior>,
3528    },
3529    /// ```sql
3530    /// DROP DOMAIN
3531    /// ```
3532    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-dropdomain.html)
3533    ///
3534    /// DROP DOMAIN [ IF EXISTS ] name [, ...] [ CASCADE | RESTRICT ]
3535    ///
3536    DropDomain(DropDomain),
3537    /// ```sql
3538    /// DROP PROCEDURE
3539    /// ```
3540    DropProcedure {
3541        if_exists: bool,
3542        /// One or more function to drop
3543        proc_desc: Vec<FunctionDesc>,
3544        /// `CASCADE` or `RESTRICT`
3545        drop_behavior: Option<DropBehavior>,
3546    },
3547    /// ```sql
3548    /// DROP SECRET
3549    /// ```
3550    DropSecret {
3551        if_exists: bool,
3552        temporary: Option<bool>,
3553        name: Ident,
3554        storage_specifier: Option<Ident>,
3555    },
3556    ///```sql
3557    /// DROP POLICY
3558    /// ```
3559    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-droppolicy.html)
3560    DropPolicy {
3561        if_exists: bool,
3562        name: Ident,
3563        table_name: ObjectName,
3564        drop_behavior: Option<DropBehavior>,
3565    },
3566    /// ```sql
3567    /// DROP CONNECTOR
3568    /// ```
3569    /// See [Hive](https://cwiki.apache.org/confluence/pages/viewpage.action?pageId=27362034#LanguageManualDDL-DropConnector)
3570    DropConnector {
3571        if_exists: bool,
3572        name: Ident,
3573    },
3574    /// ```sql
3575    /// DECLARE
3576    /// ```
3577    /// Declare Cursor Variables
3578    ///
3579    /// Note: this is a PostgreSQL-specific statement,
3580    /// but may also compatible with other SQL.
3581    Declare {
3582        stmts: Vec<Declare>,
3583    },
3584    /// ```sql
3585    /// CREATE EXTENSION [ IF NOT EXISTS ] extension_name
3586    ///     [ WITH ] [ SCHEMA schema_name ]
3587    ///              [ VERSION version ]
3588    ///              [ CASCADE ]
3589    /// ```
3590    ///
3591    /// Note: this is a PostgreSQL-specific statement,
3592    CreateExtension {
3593        name: Ident,
3594        if_not_exists: bool,
3595        cascade: bool,
3596        schema: Option<Ident>,
3597        version: Option<Ident>,
3598    },
3599    /// ```sql
3600    /// DROP EXTENSION [ IF EXISTS ] name [, ...] [ CASCADE | RESTRICT ]
3601    ///
3602    /// Note: this is a PostgreSQL-specific statement.
3603    /// https://www.postgresql.org/docs/current/sql-dropextension.html
3604    /// ```
3605    DropExtension {
3606        names: Vec<Ident>,
3607        if_exists: bool,
3608        /// `CASCADE` or `RESTRICT`
3609        cascade_or_restrict: Option<ReferentialAction>,
3610    },
3611    /// ```sql
3612    /// FETCH
3613    /// ```
3614    /// Retrieve rows from a query using a cursor
3615    ///
3616    /// Note: this is a PostgreSQL-specific statement,
3617    /// but may also compatible with other SQL.
3618    Fetch {
3619        /// Cursor name
3620        name: Ident,
3621        direction: FetchDirection,
3622        position: FetchPosition,
3623        /// Optional, It's possible to fetch rows form cursor to the table
3624        into: Option<ObjectName>,
3625    },
3626    /// ```sql
3627    /// FLUSH [NO_WRITE_TO_BINLOG | LOCAL] flush_option [, flush_option] ... | tables_option
3628    /// ```
3629    ///
3630    /// Note: this is a Mysql-specific statement,
3631    /// but may also compatible with other SQL.
3632    Flush {
3633        object_type: FlushType,
3634        location: Option<FlushLocation>,
3635        channel: Option<String>,
3636        read_lock: bool,
3637        export: bool,
3638        tables: Vec<ObjectName>,
3639    },
3640    /// ```sql
3641    /// DISCARD [ ALL | PLANS | SEQUENCES | TEMPORARY | TEMP ]
3642    /// ```
3643    ///
3644    /// Note: this is a PostgreSQL-specific statement,
3645    /// but may also compatible with other SQL.
3646    Discard {
3647        object_type: DiscardObject,
3648    },
3649    /// `SHOW FUNCTIONS`
3650    ///
3651    /// Note: this is a Presto-specific statement.
3652    ShowFunctions {
3653        filter: Option<ShowStatementFilter>,
3654    },
3655    /// ```sql
3656    /// SHOW <variable>
3657    /// ```
3658    ///
3659    /// Note: this is a PostgreSQL-specific statement.
3660    ShowVariable {
3661        variable: Vec<Ident>,
3662    },
3663    /// ```sql
3664    /// SHOW [GLOBAL | SESSION] STATUS [LIKE 'pattern' | WHERE expr]
3665    /// ```
3666    ///
3667    /// Note: this is a MySQL-specific statement.
3668    ShowStatus {
3669        filter: Option<ShowStatementFilter>,
3670        global: bool,
3671        session: bool,
3672    },
3673    /// ```sql
3674    /// SHOW VARIABLES
3675    /// ```
3676    ///
3677    /// Note: this is a MySQL-specific statement.
3678    ShowVariables {
3679        filter: Option<ShowStatementFilter>,
3680        global: bool,
3681        session: bool,
3682    },
3683    /// ```sql
3684    /// SHOW CREATE TABLE
3685    /// ```
3686    ///
3687    /// Note: this is a MySQL-specific statement.
3688    ShowCreate {
3689        obj_type: ShowCreateObject,
3690        obj_name: ObjectName,
3691    },
3692    /// ```sql
3693    /// SHOW COLUMNS
3694    /// ```
3695    ShowColumns {
3696        extended: bool,
3697        full: bool,
3698        show_options: ShowStatementOptions,
3699    },
3700    /// ```sql
3701    /// SHOW DATABASES
3702    /// ```
3703    ShowDatabases {
3704        terse: bool,
3705        history: bool,
3706        show_options: ShowStatementOptions,
3707    },
3708    /// ```sql
3709    /// SHOW SCHEMAS
3710    /// ```
3711    ShowSchemas {
3712        terse: bool,
3713        history: bool,
3714        show_options: ShowStatementOptions,
3715    },
3716    // ```sql
3717    // SHOW {CHARACTER SET | CHARSET}
3718    // ```
3719    // [MySQL]:
3720    // <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>
3721    ShowCharset(ShowCharset),
3722    /// ```sql
3723    /// SHOW OBJECTS LIKE 'line%' IN mydb.public
3724    /// ```
3725    /// Snowflake-specific statement
3726    /// <https://docs.snowflake.com/en/sql-reference/sql/show-objects>
3727    ShowObjects(ShowObjects),
3728    /// ```sql
3729    /// SHOW TABLES
3730    /// ```
3731    ShowTables {
3732        terse: bool,
3733        history: bool,
3734        extended: bool,
3735        full: bool,
3736        external: bool,
3737        show_options: ShowStatementOptions,
3738    },
3739    /// ```sql
3740    /// SHOW VIEWS
3741    /// ```
3742    ShowViews {
3743        terse: bool,
3744        materialized: bool,
3745        show_options: ShowStatementOptions,
3746    },
3747    /// ```sql
3748    /// SHOW COLLATION
3749    /// ```
3750    ///
3751    /// Note: this is a MySQL-specific statement.
3752    ShowCollation {
3753        filter: Option<ShowStatementFilter>,
3754    },
3755    /// ```sql
3756    /// `USE ...`
3757    /// ```
3758    Use(Use),
3759    /// ```sql
3760    /// START  [ TRANSACTION | WORK ] | START TRANSACTION } ...
3761    /// ```
3762    /// If `begin` is false.
3763    ///
3764    /// ```sql
3765    /// `BEGIN  [ TRANSACTION | WORK ] | START TRANSACTION } ...`
3766    /// ```
3767    /// If `begin` is true
3768    StartTransaction {
3769        modes: Vec<TransactionMode>,
3770        begin: bool,
3771        transaction: Option<BeginTransactionKind>,
3772        modifier: Option<TransactionModifier>,
3773        /// List of statements belonging to the `BEGIN` block.
3774        /// Example:
3775        /// ```sql
3776        /// BEGIN
3777        ///     SELECT 1;
3778        ///     SELECT 2;
3779        /// END;
3780        /// ```
3781        statements: Vec<Statement>,
3782        /// Exception handling with exception clauses.
3783        /// Example:
3784        /// ```sql
3785        /// EXCEPTION
3786        ///     WHEN EXCEPTION_1 THEN
3787        ///         SELECT 2;
3788        ///     WHEN EXCEPTION_2 OR EXCEPTION_3 THEN
3789        ///         SELECT 3;
3790        ///     WHEN OTHER THEN
3791        ///         SELECT 4;
3792        /// ```
3793        /// <https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#beginexceptionend>
3794        /// <https://docs.snowflake.com/en/sql-reference/snowflake-scripting/exception>
3795        exception: Option<Vec<ExceptionWhen>>,
3796        /// TRUE if the statement has an `END` keyword.
3797        has_end_keyword: bool,
3798    },
3799    /// ```sql
3800    /// COMMENT ON ...
3801    /// ```
3802    ///
3803    /// Note: this is a PostgreSQL-specific statement.
3804    Comment {
3805        object_type: CommentObject,
3806        object_name: ObjectName,
3807        comment: Option<String>,
3808        /// An optional `IF EXISTS` clause. (Non-standard.)
3809        /// See <https://docs.snowflake.com/en/sql-reference/sql/comment>
3810        if_exists: bool,
3811    },
3812    /// ```sql
3813    /// COMMIT [ TRANSACTION | WORK ] [ AND [ NO ] CHAIN ]
3814    /// ```
3815    /// If `end` is false
3816    ///
3817    /// ```sql
3818    /// END [ TRY | CATCH ]
3819    /// ```
3820    /// If `end` is true
3821    Commit {
3822        chain: bool,
3823        end: bool,
3824        modifier: Option<TransactionModifier>,
3825    },
3826    /// ```sql
3827    /// ROLLBACK [ TRANSACTION | WORK ] [ AND [ NO ] CHAIN ] [ TO [ SAVEPOINT ] savepoint_name ]
3828    /// ```
3829    Rollback {
3830        chain: bool,
3831        savepoint: Option<Ident>,
3832    },
3833    /// ```sql
3834    /// CREATE SCHEMA
3835    /// ```
3836    CreateSchema {
3837        /// `<schema name> | AUTHORIZATION <schema authorization identifier>  | <schema name>  AUTHORIZATION <schema authorization identifier>`
3838        schema_name: SchemaName,
3839        if_not_exists: bool,
3840        /// Schema properties.
3841        ///
3842        /// ```sql
3843        /// CREATE SCHEMA myschema WITH (key1='value1');
3844        /// ```
3845        ///
3846        /// [Trino](https://trino.io/docs/current/sql/create-schema.html)
3847        with: Option<Vec<SqlOption>>,
3848        /// Schema options.
3849        ///
3850        /// ```sql
3851        /// CREATE SCHEMA myschema OPTIONS(key1='value1');
3852        /// ```
3853        ///
3854        /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_schema_statement)
3855        options: Option<Vec<SqlOption>>,
3856        /// Default collation specification for the schema.
3857        ///
3858        /// ```sql
3859        /// CREATE SCHEMA myschema DEFAULT COLLATE 'und:ci';
3860        /// ```
3861        ///
3862        /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_schema_statement)
3863        default_collate_spec: Option<Expr>,
3864        /// Clones a schema
3865        ///
3866        /// ```sql
3867        /// CREATE SCHEMA myschema CLONE otherschema
3868        /// ```
3869        ///
3870        /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-clone#databases-schemas)
3871        clone: Option<ObjectName>,
3872    },
3873    /// ```sql
3874    /// CREATE DATABASE
3875    /// ```
3876    /// See:
3877    /// <https://docs.snowflake.com/en/sql-reference/sql/create-database>
3878    CreateDatabase {
3879        db_name: ObjectName,
3880        if_not_exists: bool,
3881        location: Option<String>,
3882        managed_location: Option<String>,
3883        or_replace: bool,
3884        transient: bool,
3885        clone: Option<ObjectName>,
3886        data_retention_time_in_days: Option<u64>,
3887        max_data_extension_time_in_days: Option<u64>,
3888        external_volume: Option<String>,
3889        catalog: Option<String>,
3890        replace_invalid_characters: Option<bool>,
3891        default_ddl_collation: Option<String>,
3892        storage_serialization_policy: Option<StorageSerializationPolicy>,
3893        comment: Option<String>,
3894        catalog_sync: Option<String>,
3895        catalog_sync_namespace_mode: Option<CatalogSyncNamespaceMode>,
3896        catalog_sync_namespace_flatten_delimiter: Option<String>,
3897        with_tags: Option<Vec<Tag>>,
3898        with_contacts: Option<Vec<ContactEntry>>,
3899    },
3900    /// ```sql
3901    /// CREATE FUNCTION
3902    /// ```
3903    ///
3904    /// Supported variants:
3905    /// 1. [Hive](https://cwiki.apache.org/confluence/display/hive/languagemanual+ddl#LanguageManualDDL-Create/Drop/ReloadFunction)
3906    /// 2. [PostgreSQL](https://www.postgresql.org/docs/15/sql-createfunction.html)
3907    /// 3. [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_function_statement)
3908    /// 4. [MsSql](https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql)
3909    CreateFunction(CreateFunction),
3910    /// CREATE TRIGGER statement. See struct [CreateTrigger] for details.
3911    CreateTrigger(CreateTrigger),
3912    /// DROP TRIGGER statement. See struct [DropTrigger] for details.
3913    DropTrigger(DropTrigger),
3914    /// ```sql
3915    /// CREATE PROCEDURE
3916    /// ```
3917    CreateProcedure {
3918        or_alter: bool,
3919        name: ObjectName,
3920        params: Option<Vec<ProcedureParam>>,
3921        language: Option<Ident>,
3922        body: ConditionalStatements,
3923    },
3924    /// ```sql
3925    /// CREATE MACRO
3926    /// ```
3927    ///
3928    /// Supported variants:
3929    /// 1. [DuckDB](https://duckdb.org/docs/sql/statements/create_macro)
3930    CreateMacro {
3931        or_replace: bool,
3932        temporary: bool,
3933        name: ObjectName,
3934        args: Option<Vec<MacroArg>>,
3935        definition: MacroDefinition,
3936    },
3937    /// ```sql
3938    /// CREATE STAGE
3939    /// ```
3940    /// See <https://docs.snowflake.com/en/sql-reference/sql/create-stage>
3941    CreateStage {
3942        or_replace: bool,
3943        temporary: bool,
3944        if_not_exists: bool,
3945        name: ObjectName,
3946        stage_params: StageParamsObject,
3947        directory_table_params: KeyValueOptions,
3948        file_format: KeyValueOptions,
3949        copy_options: KeyValueOptions,
3950        comment: Option<String>,
3951    },
3952    /// ```sql
3953    /// ASSERT <condition> [AS <message>]
3954    /// ```
3955    Assert {
3956        condition: Expr,
3957        message: Option<Expr>,
3958    },
3959    /// ```sql
3960    /// GRANT privileges ON objects TO grantees
3961    /// ```
3962    Grant {
3963        privileges: Privileges,
3964        objects: Option<GrantObjects>,
3965        grantees: Vec<Grantee>,
3966        with_grant_option: bool,
3967        as_grantor: Option<Ident>,
3968        granted_by: Option<Ident>,
3969        current_grants: Option<CurrentGrantsKind>,
3970    },
3971    /// ```sql
3972    /// DENY privileges ON object TO grantees
3973    /// ```
3974    Deny(DenyStatement),
3975    /// ```sql
3976    /// REVOKE privileges ON objects FROM grantees
3977    /// ```
3978    Revoke {
3979        privileges: Privileges,
3980        objects: Option<GrantObjects>,
3981        grantees: Vec<Grantee>,
3982        granted_by: Option<Ident>,
3983        cascade: Option<CascadeOption>,
3984    },
3985    /// ```sql
3986    /// DEALLOCATE [ PREPARE ] { name | ALL }
3987    /// ```
3988    ///
3989    /// Note: this is a PostgreSQL-specific statement.
3990    Deallocate {
3991        name: Ident,
3992        prepare: bool,
3993    },
3994    /// ```sql
3995    /// An `EXECUTE` statement
3996    /// ```
3997    ///
3998    /// Postgres: <https://www.postgresql.org/docs/current/sql-execute.html>
3999    /// MSSQL: <https://learn.microsoft.com/en-us/sql/relational-databases/stored-procedures/execute-a-stored-procedure>
4000    /// BigQuery: <https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#execute_immediate>
4001    /// Snowflake: <https://docs.snowflake.com/en/sql-reference/sql/execute-immediate>
4002    Execute {
4003        name: Option<ObjectName>,
4004        parameters: Vec<Expr>,
4005        has_parentheses: bool,
4006        /// Is this an `EXECUTE IMMEDIATE`
4007        immediate: bool,
4008        into: Vec<Ident>,
4009        using: Vec<ExprWithAlias>,
4010        /// Whether the last parameter is the return value of the procedure
4011        /// MSSQL: <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/execute-transact-sql?view=sql-server-ver17#output>
4012        output: bool,
4013        /// Whether to invoke the procedure with the default parameter values
4014        /// MSSQL: <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/execute-transact-sql?view=sql-server-ver17#default>
4015        default: bool,
4016    },
4017    /// ```sql
4018    /// PREPARE name [ ( data_type [, ...] ) ] AS statement
4019    /// ```
4020    ///
4021    /// Note: this is a PostgreSQL-specific statement.
4022    Prepare {
4023        name: Ident,
4024        data_types: Vec<DataType>,
4025        statement: Box<Statement>,
4026    },
4027    /// ```sql
4028    /// KILL [CONNECTION | QUERY | MUTATION]
4029    /// ```
4030    ///
4031    /// See <https://clickhouse.com/docs/en/sql-reference/statements/kill/>
4032    /// See <https://dev.mysql.com/doc/refman/8.0/en/kill.html>
4033    Kill {
4034        modifier: Option<KillType>,
4035        // processlist_id
4036        id: u64,
4037    },
4038    /// ```sql
4039    /// [EXPLAIN | DESC | DESCRIBE] TABLE
4040    /// ```
4041    /// Note: this is a MySQL-specific statement. See <https://dev.mysql.com/doc/refman/8.0/en/explain.html>
4042    ExplainTable {
4043        /// `EXPLAIN | DESC | DESCRIBE`
4044        describe_alias: DescribeAlias,
4045        /// Hive style `FORMATTED | EXTENDED`
4046        hive_format: Option<HiveDescribeFormat>,
4047        /// Snowflake and ClickHouse support `DESC|DESCRIBE TABLE <table_name>` syntax
4048        ///
4049        /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/desc-table.html)
4050        /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/describe-table)
4051        has_table_keyword: bool,
4052        /// Table name
4053        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
4054        table_name: ObjectName,
4055    },
4056    /// ```sql
4057    /// [EXPLAIN | DESC | DESCRIBE]  <statement>
4058    /// ```
4059    Explain {
4060        /// `EXPLAIN | DESC | DESCRIBE`
4061        describe_alias: DescribeAlias,
4062        /// Carry out the command and show actual run times and other statistics.
4063        analyze: bool,
4064        // Display additional information regarding the plan.
4065        verbose: bool,
4066        /// `EXPLAIN QUERY PLAN`
4067        /// Display the query plan without running the query.
4068        ///
4069        /// [SQLite](https://sqlite.org/lang_explain.html)
4070        query_plan: bool,
4071        /// `EXPLAIN ESTIMATE`
4072        /// [Clickhouse](https://clickhouse.com/docs/en/sql-reference/statements/explain#explain-estimate)
4073        estimate: bool,
4074        /// A SQL query that specifies what to explain
4075        statement: Box<Statement>,
4076        /// Optional output format of explain
4077        format: Option<AnalyzeFormatKind>,
4078        /// Postgres style utility options, `(analyze, verbose true)`
4079        options: Option<Vec<UtilityOption>>,
4080    },
4081    /// ```sql
4082    /// SAVEPOINT
4083    /// ```
4084    /// Define a new savepoint within the current transaction
4085    Savepoint {
4086        name: Ident,
4087    },
4088    /// ```sql
4089    /// RELEASE [ SAVEPOINT ] savepoint_name
4090    /// ```
4091    ReleaseSavepoint {
4092        name: Ident,
4093    },
4094    /// A `MERGE` statement.
4095    ///
4096    /// ```sql
4097    /// MERGE INTO <target_table> USING <source> ON <join_expr> { matchedClause | notMatchedClause } [ ... ]
4098    /// ```
4099    /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/merge)
4100    /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/dml-syntax#merge_statement)
4101    /// [MSSQL](https://learn.microsoft.com/en-us/sql/t-sql/statements/merge-transact-sql?view=sql-server-ver16)
4102    Merge {
4103        /// optional INTO keyword
4104        into: bool,
4105        /// Specifies the table to merge
4106        table: TableFactor,
4107        /// Specifies the table or subquery to join with the target table
4108        source: TableFactor,
4109        /// Specifies the expression on which to join the target table and source
4110        on: Box<Expr>,
4111        /// Specifies the actions to perform when values match or do not match.
4112        clauses: Vec<MergeClause>,
4113        // Specifies the output to save changes in MSSQL
4114        output: Option<OutputClause>,
4115    },
4116    /// ```sql
4117    /// CACHE [ FLAG ] TABLE <table_name> [ OPTIONS('K1' = 'V1', 'K2' = V2) ] [ AS ] [ <query> ]
4118    /// ```
4119    ///
4120    /// See [Spark SQL docs] for more details.
4121    ///
4122    /// [Spark SQL docs]: https://docs.databricks.com/spark/latest/spark-sql/language-manual/sql-ref-syntax-aux-cache-cache-table.html
4123    Cache {
4124        /// Table flag
4125        table_flag: Option<ObjectName>,
4126        /// Table name
4127
4128        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
4129        table_name: ObjectName,
4130        has_as: bool,
4131        /// Table confs
4132        options: Vec<SqlOption>,
4133        /// Cache table as a Query
4134        query: Option<Box<Query>>,
4135    },
4136    /// ```sql
4137    /// UNCACHE TABLE [ IF EXISTS ]  <table_name>
4138    /// ```
4139    UNCache {
4140        /// Table name
4141        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
4142        table_name: ObjectName,
4143        if_exists: bool,
4144    },
4145    /// ```sql
4146    /// CREATE [ { TEMPORARY | TEMP } ] SEQUENCE [ IF NOT EXISTS ] <sequence_name>
4147    /// ```
4148    /// Define a new sequence:
4149    CreateSequence {
4150        temporary: bool,
4151        if_not_exists: bool,
4152        name: ObjectName,
4153        data_type: Option<DataType>,
4154        sequence_options: Vec<SequenceOptions>,
4155        owned_by: Option<ObjectName>,
4156    },
4157    /// A `CREATE DOMAIN` statement.
4158    CreateDomain(CreateDomain),
4159    /// ```sql
4160    /// CREATE TYPE <name>
4161    /// ```
4162    CreateType {
4163        name: ObjectName,
4164        representation: UserDefinedTypeRepresentation,
4165    },
4166    /// ```sql
4167    /// PRAGMA <schema-name>.<pragma-name> = <pragma-value>
4168    /// ```
4169    Pragma {
4170        name: ObjectName,
4171        value: Option<Value>,
4172        is_eq: bool,
4173    },
4174    /// ```sql
4175    /// LOCK TABLES <table_name> [READ [LOCAL] | [LOW_PRIORITY] WRITE]
4176    /// ```
4177    /// Note: this is a MySQL-specific statement. See <https://dev.mysql.com/doc/refman/8.0/en/lock-tables.html>
4178    LockTables {
4179        tables: Vec<LockTable>,
4180    },
4181    /// ```sql
4182    /// UNLOCK TABLES
4183    /// ```
4184    /// Note: this is a MySQL-specific statement. See <https://dev.mysql.com/doc/refman/8.0/en/lock-tables.html>
4185    UnlockTables,
4186    /// Unloads the result of a query to file
4187    ///
4188    /// [Athena](https://docs.aws.amazon.com/athena/latest/ug/unload.html):
4189    /// ```sql
4190    /// UNLOAD(statement) TO <destination> [ WITH options ]
4191    /// ```
4192    ///
4193    /// [Redshift](https://docs.aws.amazon.com/redshift/latest/dg/r_UNLOAD.html):
4194    /// ```sql
4195    /// UNLOAD('statement') TO <destination> [ OPTIONS ]
4196    /// ```
4197    Unload {
4198        query: Option<Box<Query>>,
4199        query_text: Option<String>,
4200        to: Ident,
4201        auth: Option<IamRoleKind>,
4202        with: Vec<SqlOption>,
4203        options: Vec<CopyLegacyOption>,
4204    },
4205    /// ```sql
4206    /// OPTIMIZE TABLE [db.]name [ON CLUSTER cluster] [PARTITION partition | PARTITION ID 'partition_id'] [FINAL] [DEDUPLICATE [BY expression]]
4207    /// ```
4208    ///
4209    /// See ClickHouse <https://clickhouse.com/docs/en/sql-reference/statements/optimize>
4210    OptimizeTable {
4211        name: ObjectName,
4212        on_cluster: Option<Ident>,
4213        partition: Option<Partition>,
4214        include_final: bool,
4215        deduplicate: Option<Deduplicate>,
4216    },
4217    /// ```sql
4218    /// LISTEN
4219    /// ```
4220    /// listen for a notification channel
4221    ///
4222    /// See Postgres <https://www.postgresql.org/docs/current/sql-listen.html>
4223    LISTEN {
4224        channel: Ident,
4225    },
4226    /// ```sql
4227    /// UNLISTEN
4228    /// ```
4229    /// stop listening for a notification
4230    ///
4231    /// See Postgres <https://www.postgresql.org/docs/current/sql-unlisten.html>
4232    UNLISTEN {
4233        channel: Ident,
4234    },
4235    /// ```sql
4236    /// NOTIFY channel [ , payload ]
4237    /// ```
4238    /// send a notification event together with an optional "payload" string to channel
4239    ///
4240    /// See Postgres <https://www.postgresql.org/docs/current/sql-notify.html>
4241    NOTIFY {
4242        channel: Ident,
4243        payload: Option<String>,
4244    },
4245    /// ```sql
4246    /// LOAD DATA [LOCAL] INPATH 'filepath' [OVERWRITE] INTO TABLE tablename
4247    /// [PARTITION (partcol1=val1, partcol2=val2 ...)]
4248    /// [INPUTFORMAT 'inputformat' SERDE 'serde']
4249    /// ```
4250    /// Loading files into tables
4251    ///
4252    /// See Hive <https://cwiki.apache.org/confluence/pages/viewpage.action?pageId=27362036#LanguageManualDML-Loadingfilesintotables>
4253    LoadData {
4254        local: bool,
4255        inpath: String,
4256        overwrite: bool,
4257        table_name: ObjectName,
4258        partitioned: Option<Vec<Expr>>,
4259        table_format: Option<HiveLoadDataFormat>,
4260    },
4261    /// ```sql
4262    /// Rename TABLE tbl_name TO new_tbl_name[, tbl_name2 TO new_tbl_name2] ...
4263    /// ```
4264    /// Renames one or more tables
4265    ///
4266    /// See Mysql <https://dev.mysql.com/doc/refman/9.1/en/rename-table.html>
4267    RenameTable(Vec<RenameTable>),
4268    /// Snowflake `LIST`
4269    /// See: <https://docs.snowflake.com/en/sql-reference/sql/list>
4270    List(FileStagingCommand),
4271    /// Snowflake `REMOVE`
4272    /// See: <https://docs.snowflake.com/en/sql-reference/sql/remove>
4273    Remove(FileStagingCommand),
4274    /// RaiseError (MSSQL)
4275    /// RAISERROR ( { msg_id | msg_str | @local_variable }
4276    /// { , severity , state }
4277    /// [ , argument [ , ...n ] ] )
4278    /// [ WITH option [ , ...n ] ]
4279    /// See <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/raiserror-transact-sql?view=sql-server-ver16>
4280    RaisError {
4281        message: Box<Expr>,
4282        severity: Box<Expr>,
4283        state: Box<Expr>,
4284        arguments: Vec<Expr>,
4285        options: Vec<RaisErrorOption>,
4286    },
4287    /// ```sql
4288    /// PRINT msg_str | @local_variable | string_expr
4289    /// ```
4290    ///
4291    /// See: <https://learn.microsoft.com/en-us/sql/t-sql/statements/print-transact-sql>
4292    Print(PrintStatement),
4293    /// ```sql
4294    /// RETURN [ expression ]
4295    /// ```
4296    ///
4297    /// See [ReturnStatement]
4298    Return(ReturnStatement),
4299    /// Export data statement
4300    ///
4301    /// Example:
4302    /// ```sql
4303    /// EXPORT DATA OPTIONS(uri='gs://bucket/folder/*', format='PARQUET', overwrite=true) AS
4304    /// SELECT field1, field2 FROM mydataset.table1 ORDER BY field1 LIMIT 10
4305    /// ```
4306    /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/export-statements)
4307    ExportData(ExportData),
4308    /// ```sql
4309    /// CREATE [OR REPLACE] USER <user> [IF NOT EXISTS]
4310    /// ```
4311    /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-user)
4312    CreateUser(CreateUser),
4313    /// Re-sorts rows and reclaims space in either a specified table or all tables in the current database
4314    ///
4315    /// ```sql
4316    /// VACUUM tbl
4317    /// ```
4318    /// [Redshift](https://docs.aws.amazon.com/redshift/latest/dg/r_VACUUM_command.html)
4319    Vacuum(VacuumStatement),
4320}
4321
4322/// ```sql
4323/// {COPY | REVOKE} CURRENT GRANTS
4324/// ```
4325///
4326/// - [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/grant-ownership#optional-parameters)
4327#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
4328#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4329#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
4330pub enum CurrentGrantsKind {
4331    CopyCurrentGrants,
4332    RevokeCurrentGrants,
4333}
4334
4335impl fmt::Display for CurrentGrantsKind {
4336    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
4337        match self {
4338            CurrentGrantsKind::CopyCurrentGrants => write!(f, "COPY CURRENT GRANTS"),
4339            CurrentGrantsKind::RevokeCurrentGrants => write!(f, "REVOKE CURRENT GRANTS"),
4340        }
4341    }
4342}
4343
4344#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
4345#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4346#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
4347pub enum RaisErrorOption {
4348    Log,
4349    NoWait,
4350    SetError,
4351}
4352
4353impl fmt::Display for RaisErrorOption {
4354    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
4355        match self {
4356            RaisErrorOption::Log => write!(f, "LOG"),
4357            RaisErrorOption::NoWait => write!(f, "NOWAIT"),
4358            RaisErrorOption::SetError => write!(f, "SETERROR"),
4359        }
4360    }
4361}
4362
4363impl fmt::Display for Statement {
4364    /// Formats a SQL statement with support for pretty printing.
4365    ///
4366    /// When using the alternate flag (`{:#}`), the statement will be formatted with proper
4367    /// indentation and line breaks. For example:
4368    ///
4369    /// ```
4370    /// # use sqlparser::dialect::GenericDialect;
4371    /// # use sqlparser::parser::Parser;
4372    /// let sql = "SELECT a, b FROM table_1";
4373    /// let ast = Parser::parse_sql(&GenericDialect, sql).unwrap();
4374    ///
4375    /// // Regular formatting
4376    /// assert_eq!(format!("{}", ast[0]), "SELECT a, b FROM table_1");
4377    ///
4378    /// // Pretty printing
4379    /// assert_eq!(format!("{:#}", ast[0]),
4380    /// r#"SELECT
4381    ///   a,
4382    ///   b
4383    /// FROM
4384    ///   table_1"#);
4385    /// ```
4386    // Clippy thinks this function is too complicated, but it is painful to
4387    // split up without extracting structs for each `Statement` variant.
4388    #[allow(clippy::cognitive_complexity)]
4389    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
4390        match self {
4391            Statement::Flush {
4392                object_type,
4393                location,
4394                channel,
4395                read_lock,
4396                export,
4397                tables,
4398            } => {
4399                write!(f, "FLUSH")?;
4400                if let Some(location) = location {
4401                    f.write_str(" ")?;
4402                    location.fmt(f)?;
4403                }
4404                write!(f, " {object_type}")?;
4405
4406                if let Some(channel) = channel {
4407                    write!(f, " FOR CHANNEL {channel}")?;
4408                }
4409
4410                write!(
4411                    f,
4412                    "{tables}{read}{export}",
4413                    tables = if !tables.is_empty() {
4414                        " ".to_string() + &display_comma_separated(tables).to_string()
4415                    } else {
4416                        "".to_string()
4417                    },
4418                    export = if *export { " FOR EXPORT" } else { "" },
4419                    read = if *read_lock { " WITH READ LOCK" } else { "" }
4420                )
4421            }
4422            Statement::Kill { modifier, id } => {
4423                write!(f, "KILL ")?;
4424
4425                if let Some(m) = modifier {
4426                    write!(f, "{m} ")?;
4427                }
4428
4429                write!(f, "{id}")
4430            }
4431            Statement::ExplainTable {
4432                describe_alias,
4433                hive_format,
4434                has_table_keyword,
4435                table_name,
4436            } => {
4437                write!(f, "{describe_alias} ")?;
4438
4439                if let Some(format) = hive_format {
4440                    write!(f, "{format} ")?;
4441                }
4442                if *has_table_keyword {
4443                    write!(f, "TABLE ")?;
4444                }
4445
4446                write!(f, "{table_name}")
4447            }
4448            Statement::Explain {
4449                describe_alias,
4450                verbose,
4451                analyze,
4452                query_plan,
4453                estimate,
4454                statement,
4455                format,
4456                options,
4457            } => {
4458                write!(f, "{describe_alias} ")?;
4459
4460                if *query_plan {
4461                    write!(f, "QUERY PLAN ")?;
4462                }
4463                if *analyze {
4464                    write!(f, "ANALYZE ")?;
4465                }
4466                if *estimate {
4467                    write!(f, "ESTIMATE ")?;
4468                }
4469
4470                if *verbose {
4471                    write!(f, "VERBOSE ")?;
4472                }
4473
4474                if let Some(format) = format {
4475                    write!(f, "{format} ")?;
4476                }
4477
4478                if let Some(options) = options {
4479                    write!(f, "({}) ", display_comma_separated(options))?;
4480                }
4481
4482                write!(f, "{statement}")
4483            }
4484            Statement::Query(s) => s.fmt(f),
4485            Statement::Declare { stmts } => {
4486                write!(f, "DECLARE ")?;
4487                write!(f, "{}", display_separated(stmts, "; "))
4488            }
4489            Statement::Fetch {
4490                name,
4491                direction,
4492                position,
4493                into,
4494            } => {
4495                write!(f, "FETCH {direction} {position} {name}")?;
4496
4497                if let Some(into) = into {
4498                    write!(f, " INTO {into}")?;
4499                }
4500
4501                Ok(())
4502            }
4503            Statement::Directory {
4504                overwrite,
4505                local,
4506                path,
4507                file_format,
4508                source,
4509            } => {
4510                write!(
4511                    f,
4512                    "INSERT{overwrite}{local} DIRECTORY '{path}'",
4513                    overwrite = if *overwrite { " OVERWRITE" } else { "" },
4514                    local = if *local { " LOCAL" } else { "" },
4515                    path = path
4516                )?;
4517                if let Some(ref ff) = file_format {
4518                    write!(f, " STORED AS {ff}")?
4519                }
4520                write!(f, " {source}")
4521            }
4522            Statement::Msck {
4523                table_name,
4524                repair,
4525                partition_action,
4526            } => {
4527                write!(
4528                    f,
4529                    "MSCK {repair}TABLE {table}",
4530                    repair = if *repair { "REPAIR " } else { "" },
4531                    table = table_name
4532                )?;
4533                if let Some(pa) = partition_action {
4534                    write!(f, " {pa}")?;
4535                }
4536                Ok(())
4537            }
4538            Statement::Truncate {
4539                table_names,
4540                partitions,
4541                table,
4542                identity,
4543                cascade,
4544                on_cluster,
4545            } => {
4546                let table = if *table { "TABLE " } else { "" };
4547
4548                write!(
4549                    f,
4550                    "TRUNCATE {table}{table_names}",
4551                    table_names = display_comma_separated(table_names)
4552                )?;
4553
4554                if let Some(identity) = identity {
4555                    match identity {
4556                        TruncateIdentityOption::Restart => write!(f, " RESTART IDENTITY")?,
4557                        TruncateIdentityOption::Continue => write!(f, " CONTINUE IDENTITY")?,
4558                    }
4559                }
4560                if let Some(cascade) = cascade {
4561                    match cascade {
4562                        CascadeOption::Cascade => write!(f, " CASCADE")?,
4563                        CascadeOption::Restrict => write!(f, " RESTRICT")?,
4564                    }
4565                }
4566
4567                if let Some(ref parts) = partitions {
4568                    if !parts.is_empty() {
4569                        write!(f, " PARTITION ({})", display_comma_separated(parts))?;
4570                    }
4571                }
4572                if let Some(on_cluster) = on_cluster {
4573                    write!(f, " ON CLUSTER {on_cluster}")?;
4574                }
4575                Ok(())
4576            }
4577            Statement::Case(stmt) => {
4578                write!(f, "{stmt}")
4579            }
4580            Statement::If(stmt) => {
4581                write!(f, "{stmt}")
4582            }
4583            Statement::While(stmt) => {
4584                write!(f, "{stmt}")
4585            }
4586            Statement::Raise(stmt) => {
4587                write!(f, "{stmt}")
4588            }
4589            Statement::AttachDatabase {
4590                schema_name,
4591                database_file_name,
4592                database,
4593            } => {
4594                let keyword = if *database { "DATABASE " } else { "" };
4595                write!(f, "ATTACH {keyword}{database_file_name} AS {schema_name}")
4596            }
4597            Statement::AttachDuckDBDatabase {
4598                if_not_exists,
4599                database,
4600                database_path,
4601                database_alias,
4602                attach_options,
4603            } => {
4604                write!(
4605                    f,
4606                    "ATTACH{database}{if_not_exists} {database_path}",
4607                    database = if *database { " DATABASE" } else { "" },
4608                    if_not_exists = if *if_not_exists { " IF NOT EXISTS" } else { "" },
4609                )?;
4610                if let Some(alias) = database_alias {
4611                    write!(f, " AS {alias}")?;
4612                }
4613                if !attach_options.is_empty() {
4614                    write!(f, " ({})", display_comma_separated(attach_options))?;
4615                }
4616                Ok(())
4617            }
4618            Statement::DetachDuckDBDatabase {
4619                if_exists,
4620                database,
4621                database_alias,
4622            } => {
4623                write!(
4624                    f,
4625                    "DETACH{database}{if_exists} {database_alias}",
4626                    database = if *database { " DATABASE" } else { "" },
4627                    if_exists = if *if_exists { " IF EXISTS" } else { "" },
4628                )?;
4629                Ok(())
4630            }
4631            Statement::Analyze {
4632                table_name,
4633                partitions,
4634                for_columns,
4635                columns,
4636                cache_metadata,
4637                noscan,
4638                compute_statistics,
4639                has_table_keyword,
4640            } => {
4641                write!(
4642                    f,
4643                    "ANALYZE{}{table_name}",
4644                    if *has_table_keyword { " TABLE " } else { " " }
4645                )?;
4646                if let Some(ref parts) = partitions {
4647                    if !parts.is_empty() {
4648                        write!(f, " PARTITION ({})", display_comma_separated(parts))?;
4649                    }
4650                }
4651
4652                if *compute_statistics {
4653                    write!(f, " COMPUTE STATISTICS")?;
4654                }
4655                if *noscan {
4656                    write!(f, " NOSCAN")?;
4657                }
4658                if *cache_metadata {
4659                    write!(f, " CACHE METADATA")?;
4660                }
4661                if *for_columns {
4662                    write!(f, " FOR COLUMNS")?;
4663                    if !columns.is_empty() {
4664                        write!(f, " {}", display_comma_separated(columns))?;
4665                    }
4666                }
4667                Ok(())
4668            }
4669            Statement::Insert(insert) => insert.fmt(f),
4670            Statement::Install {
4671                extension_name: name,
4672            } => write!(f, "INSTALL {name}"),
4673
4674            Statement::Load {
4675                extension_name: name,
4676            } => write!(f, "LOAD {name}"),
4677
4678            Statement::Call(function) => write!(f, "CALL {function}"),
4679
4680            Statement::Copy {
4681                source,
4682                to,
4683                target,
4684                options,
4685                legacy_options,
4686                values,
4687            } => {
4688                write!(f, "COPY")?;
4689                match source {
4690                    CopySource::Query(query) => write!(f, " ({query})")?,
4691                    CopySource::Table {
4692                        table_name,
4693                        columns,
4694                    } => {
4695                        write!(f, " {table_name}")?;
4696                        if !columns.is_empty() {
4697                            write!(f, " ({})", display_comma_separated(columns))?;
4698                        }
4699                    }
4700                }
4701                write!(f, " {} {}", if *to { "TO" } else { "FROM" }, target)?;
4702                if !options.is_empty() {
4703                    write!(f, " ({})", display_comma_separated(options))?;
4704                }
4705                if !legacy_options.is_empty() {
4706                    write!(f, " {}", display_separated(legacy_options, " "))?;
4707                }
4708                if !values.is_empty() {
4709                    writeln!(f, ";")?;
4710                    let mut delim = "";
4711                    for v in values {
4712                        write!(f, "{delim}")?;
4713                        delim = "\t";
4714                        if let Some(v) = v {
4715                            write!(f, "{v}")?;
4716                        } else {
4717                            write!(f, "\\N")?;
4718                        }
4719                    }
4720                    write!(f, "\n\\.")?;
4721                }
4722                Ok(())
4723            }
4724            Statement::Update {
4725                table,
4726                assignments,
4727                from,
4728                selection,
4729                returning,
4730                or,
4731                limit,
4732            } => {
4733                f.write_str("UPDATE ")?;
4734                if let Some(or) = or {
4735                    or.fmt(f)?;
4736                    f.write_str(" ")?;
4737                }
4738                table.fmt(f)?;
4739                if let Some(UpdateTableFromKind::BeforeSet(from)) = from {
4740                    SpaceOrNewline.fmt(f)?;
4741                    f.write_str("FROM")?;
4742                    indented_list(f, from)?;
4743                }
4744                if !assignments.is_empty() {
4745                    SpaceOrNewline.fmt(f)?;
4746                    f.write_str("SET")?;
4747                    indented_list(f, assignments)?;
4748                }
4749                if let Some(UpdateTableFromKind::AfterSet(from)) = from {
4750                    SpaceOrNewline.fmt(f)?;
4751                    f.write_str("FROM")?;
4752                    indented_list(f, from)?;
4753                }
4754                if let Some(selection) = selection {
4755                    SpaceOrNewline.fmt(f)?;
4756                    f.write_str("WHERE")?;
4757                    SpaceOrNewline.fmt(f)?;
4758                    Indent(selection).fmt(f)?;
4759                }
4760                if let Some(returning) = returning {
4761                    SpaceOrNewline.fmt(f)?;
4762                    f.write_str("RETURNING")?;
4763                    indented_list(f, returning)?;
4764                }
4765                if let Some(limit) = limit {
4766                    SpaceOrNewline.fmt(f)?;
4767                    write!(f, "LIMIT {limit}")?;
4768                }
4769                Ok(())
4770            }
4771            Statement::Delete(delete) => delete.fmt(f),
4772            Statement::Open(open) => open.fmt(f),
4773            Statement::Close { cursor } => {
4774                write!(f, "CLOSE {cursor}")?;
4775
4776                Ok(())
4777            }
4778            Statement::CreateDatabase {
4779                db_name,
4780                if_not_exists,
4781                location,
4782                managed_location,
4783                or_replace,
4784                transient,
4785                clone,
4786                data_retention_time_in_days,
4787                max_data_extension_time_in_days,
4788                external_volume,
4789                catalog,
4790                replace_invalid_characters,
4791                default_ddl_collation,
4792                storage_serialization_policy,
4793                comment,
4794                catalog_sync,
4795                catalog_sync_namespace_mode,
4796                catalog_sync_namespace_flatten_delimiter,
4797                with_tags,
4798                with_contacts,
4799            } => {
4800                write!(
4801                    f,
4802                    "CREATE {or_replace}{transient}DATABASE {if_not_exists}{name}",
4803                    or_replace = if *or_replace { "OR REPLACE " } else { "" },
4804                    transient = if *transient { "TRANSIENT " } else { "" },
4805                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
4806                    name = db_name,
4807                )?;
4808
4809                if let Some(l) = location {
4810                    write!(f, " LOCATION '{l}'")?;
4811                }
4812                if let Some(ml) = managed_location {
4813                    write!(f, " MANAGEDLOCATION '{ml}'")?;
4814                }
4815                if let Some(clone) = clone {
4816                    write!(f, " CLONE {clone}")?;
4817                }
4818
4819                if let Some(value) = data_retention_time_in_days {
4820                    write!(f, " DATA_RETENTION_TIME_IN_DAYS = {value}")?;
4821                }
4822
4823                if let Some(value) = max_data_extension_time_in_days {
4824                    write!(f, " MAX_DATA_EXTENSION_TIME_IN_DAYS = {value}")?;
4825                }
4826
4827                if let Some(vol) = external_volume {
4828                    write!(f, " EXTERNAL_VOLUME = '{vol}'")?;
4829                }
4830
4831                if let Some(cat) = catalog {
4832                    write!(f, " CATALOG = '{cat}'")?;
4833                }
4834
4835                if let Some(true) = replace_invalid_characters {
4836                    write!(f, " REPLACE_INVALID_CHARACTERS = TRUE")?;
4837                } else if let Some(false) = replace_invalid_characters {
4838                    write!(f, " REPLACE_INVALID_CHARACTERS = FALSE")?;
4839                }
4840
4841                if let Some(collation) = default_ddl_collation {
4842                    write!(f, " DEFAULT_DDL_COLLATION = '{collation}'")?;
4843                }
4844
4845                if let Some(policy) = storage_serialization_policy {
4846                    write!(f, " STORAGE_SERIALIZATION_POLICY = {policy}")?;
4847                }
4848
4849                if let Some(comment) = comment {
4850                    write!(f, " COMMENT = '{comment}'")?;
4851                }
4852
4853                if let Some(sync) = catalog_sync {
4854                    write!(f, " CATALOG_SYNC = '{sync}'")?;
4855                }
4856
4857                if let Some(mode) = catalog_sync_namespace_mode {
4858                    write!(f, " CATALOG_SYNC_NAMESPACE_MODE = {mode}")?;
4859                }
4860
4861                if let Some(delim) = catalog_sync_namespace_flatten_delimiter {
4862                    write!(f, " CATALOG_SYNC_NAMESPACE_FLATTEN_DELIMITER = '{delim}'")?;
4863                }
4864
4865                if let Some(tags) = with_tags {
4866                    write!(f, " WITH TAG ({})", display_comma_separated(tags))?;
4867                }
4868
4869                if let Some(contacts) = with_contacts {
4870                    write!(f, " WITH CONTACT ({})", display_comma_separated(contacts))?;
4871                }
4872                Ok(())
4873            }
4874            Statement::CreateFunction(create_function) => create_function.fmt(f),
4875            Statement::CreateDomain(create_domain) => create_domain.fmt(f),
4876            Statement::CreateTrigger(create_trigger) => create_trigger.fmt(f),
4877            Statement::DropTrigger(drop_trigger) => drop_trigger.fmt(f),
4878            Statement::CreateProcedure {
4879                name,
4880                or_alter,
4881                params,
4882                language,
4883                body,
4884            } => {
4885                write!(
4886                    f,
4887                    "CREATE {or_alter}PROCEDURE {name}",
4888                    or_alter = if *or_alter { "OR ALTER " } else { "" },
4889                    name = name
4890                )?;
4891
4892                if let Some(p) = params {
4893                    if !p.is_empty() {
4894                        write!(f, " ({})", display_comma_separated(p))?;
4895                    }
4896                }
4897
4898                if let Some(language) = language {
4899                    write!(f, " LANGUAGE {language}")?;
4900                }
4901
4902                write!(f, " AS {body}")
4903            }
4904            Statement::CreateMacro {
4905                or_replace,
4906                temporary,
4907                name,
4908                args,
4909                definition,
4910            } => {
4911                write!(
4912                    f,
4913                    "CREATE {or_replace}{temp}MACRO {name}",
4914                    temp = if *temporary { "TEMPORARY " } else { "" },
4915                    or_replace = if *or_replace { "OR REPLACE " } else { "" },
4916                )?;
4917                if let Some(args) = args {
4918                    write!(f, "({})", display_comma_separated(args))?;
4919                }
4920                match definition {
4921                    MacroDefinition::Expr(expr) => write!(f, " AS {expr}")?,
4922                    MacroDefinition::Table(query) => write!(f, " AS TABLE {query}")?,
4923                }
4924                Ok(())
4925            }
4926            Statement::CreateView {
4927                or_alter,
4928                name,
4929                or_replace,
4930                columns,
4931                query,
4932                materialized,
4933                secure,
4934                options,
4935                cluster_by,
4936                comment,
4937                with_no_schema_binding,
4938                if_not_exists,
4939                temporary,
4940                to,
4941                params,
4942                name_before_not_exists,
4943            } => {
4944                write!(
4945                    f,
4946                    "CREATE {or_alter}{or_replace}",
4947                    or_alter = if *or_alter { "OR ALTER " } else { "" },
4948                    or_replace = if *or_replace { "OR REPLACE " } else { "" },
4949                )?;
4950                if let Some(params) = params {
4951                    params.fmt(f)?;
4952                }
4953                write!(
4954                    f,
4955                    "{secure}{materialized}{temporary}VIEW {if_not_and_name}{to}",
4956                    if_not_and_name = if *if_not_exists {
4957                        if *name_before_not_exists {
4958                            format!("{name} IF NOT EXISTS")
4959                        } else {
4960                            format!("IF NOT EXISTS {name}")
4961                        }
4962                    } else {
4963                        format!("{name}")
4964                    },
4965                    secure = if *secure { "SECURE " } else { "" },
4966                    materialized = if *materialized { "MATERIALIZED " } else { "" },
4967                    temporary = if *temporary { "TEMPORARY " } else { "" },
4968                    to = to
4969                        .as_ref()
4970                        .map(|to| format!(" TO {to}"))
4971                        .unwrap_or_default()
4972                )?;
4973                if !columns.is_empty() {
4974                    write!(f, " ({})", display_comma_separated(columns))?;
4975                }
4976                if matches!(options, CreateTableOptions::With(_)) {
4977                    write!(f, " {options}")?;
4978                }
4979                if let Some(comment) = comment {
4980                    write!(
4981                        f,
4982                        " COMMENT = '{}'",
4983                        value::escape_single_quote_string(comment)
4984                    )?;
4985                }
4986                if !cluster_by.is_empty() {
4987                    write!(f, " CLUSTER BY ({})", display_comma_separated(cluster_by))?;
4988                }
4989                if matches!(options, CreateTableOptions::Options(_)) {
4990                    write!(f, " {options}")?;
4991                }
4992                f.write_str(" AS")?;
4993                SpaceOrNewline.fmt(f)?;
4994                query.fmt(f)?;
4995                if *with_no_schema_binding {
4996                    write!(f, " WITH NO SCHEMA BINDING")?;
4997                }
4998                Ok(())
4999            }
5000            Statement::CreateTable(create_table) => create_table.fmt(f),
5001            Statement::LoadData {
5002                local,
5003                inpath,
5004                overwrite,
5005                table_name,
5006                partitioned,
5007                table_format,
5008            } => {
5009                write!(
5010                    f,
5011                    "LOAD DATA {local}INPATH '{inpath}' {overwrite}INTO TABLE {table_name}",
5012                    local = if *local { "LOCAL " } else { "" },
5013                    inpath = inpath,
5014                    overwrite = if *overwrite { "OVERWRITE " } else { "" },
5015                    table_name = table_name,
5016                )?;
5017                if let Some(ref parts) = &partitioned {
5018                    if !parts.is_empty() {
5019                        write!(f, " PARTITION ({})", display_comma_separated(parts))?;
5020                    }
5021                }
5022                if let Some(HiveLoadDataFormat {
5023                    serde,
5024                    input_format,
5025                }) = &table_format
5026                {
5027                    write!(f, " INPUTFORMAT {input_format} SERDE {serde}")?;
5028                }
5029                Ok(())
5030            }
5031            Statement::CreateVirtualTable {
5032                name,
5033                if_not_exists,
5034                module_name,
5035                module_args,
5036            } => {
5037                write!(
5038                    f,
5039                    "CREATE VIRTUAL TABLE {if_not_exists}{name} USING {module_name}",
5040                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
5041                    name = name,
5042                    module_name = module_name
5043                )?;
5044                if !module_args.is_empty() {
5045                    write!(f, " ({})", display_comma_separated(module_args))?;
5046                }
5047                Ok(())
5048            }
5049            Statement::CreateIndex(create_index) => create_index.fmt(f),
5050            Statement::CreateExtension {
5051                name,
5052                if_not_exists,
5053                cascade,
5054                schema,
5055                version,
5056            } => {
5057                write!(
5058                    f,
5059                    "CREATE EXTENSION {if_not_exists}{name}",
5060                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" }
5061                )?;
5062                if *cascade || schema.is_some() || version.is_some() {
5063                    write!(f, " WITH")?;
5064
5065                    if let Some(name) = schema {
5066                        write!(f, " SCHEMA {name}")?;
5067                    }
5068                    if let Some(version) = version {
5069                        write!(f, " VERSION {version}")?;
5070                    }
5071                    if *cascade {
5072                        write!(f, " CASCADE")?;
5073                    }
5074                }
5075
5076                Ok(())
5077            }
5078            Statement::DropExtension {
5079                names,
5080                if_exists,
5081                cascade_or_restrict,
5082            } => {
5083                write!(f, "DROP EXTENSION")?;
5084                if *if_exists {
5085                    write!(f, " IF EXISTS")?;
5086                }
5087                write!(f, " {}", display_comma_separated(names))?;
5088                if let Some(cascade_or_restrict) = cascade_or_restrict {
5089                    write!(f, " {cascade_or_restrict}")?;
5090                }
5091                Ok(())
5092            }
5093            Statement::CreateRole {
5094                names,
5095                if_not_exists,
5096                inherit,
5097                login,
5098                bypassrls,
5099                password,
5100                create_db,
5101                create_role,
5102                superuser,
5103                replication,
5104                connection_limit,
5105                valid_until,
5106                in_role,
5107                in_group,
5108                role,
5109                user,
5110                admin,
5111                authorization_owner,
5112            } => {
5113                write!(
5114                    f,
5115                    "CREATE ROLE {if_not_exists}{names}{superuser}{create_db}{create_role}{inherit}{login}{replication}{bypassrls}",
5116                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
5117                    names = display_separated(names, ", "),
5118                    superuser = match *superuser {
5119                        Some(true) => " SUPERUSER",
5120                        Some(false) => " NOSUPERUSER",
5121                        None => ""
5122                    },
5123                    create_db = match *create_db {
5124                        Some(true) => " CREATEDB",
5125                        Some(false) => " NOCREATEDB",
5126                        None => ""
5127                    },
5128                    create_role = match *create_role {
5129                        Some(true) => " CREATEROLE",
5130                        Some(false) => " NOCREATEROLE",
5131                        None => ""
5132                    },
5133                    inherit = match *inherit {
5134                        Some(true) => " INHERIT",
5135                        Some(false) => " NOINHERIT",
5136                        None => ""
5137                    },
5138                    login = match *login {
5139                        Some(true) => " LOGIN",
5140                        Some(false) => " NOLOGIN",
5141                        None => ""
5142                    },
5143                    replication = match *replication {
5144                        Some(true) => " REPLICATION",
5145                        Some(false) => " NOREPLICATION",
5146                        None => ""
5147                    },
5148                    bypassrls = match *bypassrls {
5149                        Some(true) => " BYPASSRLS",
5150                        Some(false) => " NOBYPASSRLS",
5151                        None => ""
5152                    }
5153                )?;
5154                if let Some(limit) = connection_limit {
5155                    write!(f, " CONNECTION LIMIT {limit}")?;
5156                }
5157                match password {
5158                    Some(Password::Password(pass)) => write!(f, " PASSWORD {pass}"),
5159                    Some(Password::NullPassword) => write!(f, " PASSWORD NULL"),
5160                    None => Ok(()),
5161                }?;
5162                if let Some(until) = valid_until {
5163                    write!(f, " VALID UNTIL {until}")?;
5164                }
5165                if !in_role.is_empty() {
5166                    write!(f, " IN ROLE {}", display_comma_separated(in_role))?;
5167                }
5168                if !in_group.is_empty() {
5169                    write!(f, " IN GROUP {}", display_comma_separated(in_group))?;
5170                }
5171                if !role.is_empty() {
5172                    write!(f, " ROLE {}", display_comma_separated(role))?;
5173                }
5174                if !user.is_empty() {
5175                    write!(f, " USER {}", display_comma_separated(user))?;
5176                }
5177                if !admin.is_empty() {
5178                    write!(f, " ADMIN {}", display_comma_separated(admin))?;
5179                }
5180                if let Some(owner) = authorization_owner {
5181                    write!(f, " AUTHORIZATION {owner}")?;
5182                }
5183                Ok(())
5184            }
5185            Statement::CreateSecret {
5186                or_replace,
5187                temporary,
5188                if_not_exists,
5189                name,
5190                storage_specifier,
5191                secret_type,
5192                options,
5193            } => {
5194                write!(
5195                    f,
5196                    "CREATE {or_replace}",
5197                    or_replace = if *or_replace { "OR REPLACE " } else { "" },
5198                )?;
5199                if let Some(t) = temporary {
5200                    write!(f, "{}", if *t { "TEMPORARY " } else { "PERSISTENT " })?;
5201                }
5202                write!(
5203                    f,
5204                    "SECRET {if_not_exists}",
5205                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
5206                )?;
5207                if let Some(n) = name {
5208                    write!(f, "{n} ")?;
5209                };
5210                if let Some(s) = storage_specifier {
5211                    write!(f, "IN {s} ")?;
5212                }
5213                write!(f, "( TYPE {secret_type}",)?;
5214                if !options.is_empty() {
5215                    write!(f, ", {o}", o = display_comma_separated(options))?;
5216                }
5217                write!(f, " )")?;
5218                Ok(())
5219            }
5220            Statement::CreateServer(stmt) => {
5221                write!(f, "{stmt}")
5222            }
5223            Statement::CreatePolicy {
5224                name,
5225                table_name,
5226                policy_type,
5227                command,
5228                to,
5229                using,
5230                with_check,
5231            } => {
5232                write!(f, "CREATE POLICY {name} ON {table_name}")?;
5233
5234                if let Some(policy_type) = policy_type {
5235                    match policy_type {
5236                        CreatePolicyType::Permissive => write!(f, " AS PERMISSIVE")?,
5237                        CreatePolicyType::Restrictive => write!(f, " AS RESTRICTIVE")?,
5238                    }
5239                }
5240
5241                if let Some(command) = command {
5242                    match command {
5243                        CreatePolicyCommand::All => write!(f, " FOR ALL")?,
5244                        CreatePolicyCommand::Select => write!(f, " FOR SELECT")?,
5245                        CreatePolicyCommand::Insert => write!(f, " FOR INSERT")?,
5246                        CreatePolicyCommand::Update => write!(f, " FOR UPDATE")?,
5247                        CreatePolicyCommand::Delete => write!(f, " FOR DELETE")?,
5248                    }
5249                }
5250
5251                if let Some(to) = to {
5252                    write!(f, " TO {}", display_comma_separated(to))?;
5253                }
5254
5255                if let Some(using) = using {
5256                    write!(f, " USING ({using})")?;
5257                }
5258
5259                if let Some(with_check) = with_check {
5260                    write!(f, " WITH CHECK ({with_check})")?;
5261                }
5262
5263                Ok(())
5264            }
5265            Statement::CreateConnector(create_connector) => create_connector.fmt(f),
5266            Statement::AlterTable {
5267                name,
5268                if_exists,
5269                only,
5270                operations,
5271                location,
5272                on_cluster,
5273                iceberg,
5274                end_token: _,
5275            } => {
5276                if *iceberg {
5277                    write!(f, "ALTER ICEBERG TABLE ")?;
5278                } else {
5279                    write!(f, "ALTER TABLE ")?;
5280                }
5281
5282                if *if_exists {
5283                    write!(f, "IF EXISTS ")?;
5284                }
5285                if *only {
5286                    write!(f, "ONLY ")?;
5287                }
5288                write!(f, "{name} ")?;
5289                if let Some(cluster) = on_cluster {
5290                    write!(f, "ON CLUSTER {cluster} ")?;
5291                }
5292                write!(
5293                    f,
5294                    "{operations}",
5295                    operations = display_comma_separated(operations)
5296                )?;
5297                if let Some(loc) = location {
5298                    write!(f, " {loc}")?
5299                }
5300                Ok(())
5301            }
5302            Statement::AlterIndex { name, operation } => {
5303                write!(f, "ALTER INDEX {name} {operation}")
5304            }
5305            Statement::AlterView {
5306                name,
5307                columns,
5308                query,
5309                with_options,
5310            } => {
5311                write!(f, "ALTER VIEW {name}")?;
5312                if !with_options.is_empty() {
5313                    write!(f, " WITH ({})", display_comma_separated(with_options))?;
5314                }
5315                if !columns.is_empty() {
5316                    write!(f, " ({})", display_comma_separated(columns))?;
5317                }
5318                write!(f, " AS {query}")
5319            }
5320            Statement::AlterType(AlterType { name, operation }) => {
5321                write!(f, "ALTER TYPE {name} {operation}")
5322            }
5323            Statement::AlterRole { name, operation } => {
5324                write!(f, "ALTER ROLE {name} {operation}")
5325            }
5326            Statement::AlterPolicy {
5327                name,
5328                table_name,
5329                operation,
5330            } => {
5331                write!(f, "ALTER POLICY {name} ON {table_name}{operation}")
5332            }
5333            Statement::AlterConnector {
5334                name,
5335                properties,
5336                url,
5337                owner,
5338            } => {
5339                write!(f, "ALTER CONNECTOR {name}")?;
5340                if let Some(properties) = properties {
5341                    write!(
5342                        f,
5343                        " SET DCPROPERTIES({})",
5344                        display_comma_separated(properties)
5345                    )?;
5346                }
5347                if let Some(url) = url {
5348                    write!(f, " SET URL '{url}'")?;
5349                }
5350                if let Some(owner) = owner {
5351                    write!(f, " SET OWNER {owner}")?;
5352                }
5353                Ok(())
5354            }
5355            Statement::AlterSession {
5356                set,
5357                session_params,
5358            } => {
5359                write!(
5360                    f,
5361                    "ALTER SESSION {set}",
5362                    set = if *set { "SET" } else { "UNSET" }
5363                )?;
5364                if !session_params.options.is_empty() {
5365                    if *set {
5366                        write!(f, " {session_params}")?;
5367                    } else {
5368                        let options = session_params
5369                            .options
5370                            .iter()
5371                            .map(|p| p.option_name.clone())
5372                            .collect::<Vec<_>>();
5373                        write!(f, " {}", display_separated(&options, ", "))?;
5374                    }
5375                }
5376                Ok(())
5377            }
5378            Statement::Drop {
5379                object_type,
5380                if_exists,
5381                names,
5382                cascade,
5383                restrict,
5384                purge,
5385                temporary,
5386                table,
5387            } => {
5388                write!(
5389                    f,
5390                    "DROP {}{}{} {}{}{}{}",
5391                    if *temporary { "TEMPORARY " } else { "" },
5392                    object_type,
5393                    if *if_exists { " IF EXISTS" } else { "" },
5394                    display_comma_separated(names),
5395                    if *cascade { " CASCADE" } else { "" },
5396                    if *restrict { " RESTRICT" } else { "" },
5397                    if *purge { " PURGE" } else { "" },
5398                )?;
5399                if let Some(table_name) = table.as_ref() {
5400                    write!(f, " ON {table_name}")?;
5401                };
5402                Ok(())
5403            }
5404            Statement::DropFunction {
5405                if_exists,
5406                func_desc,
5407                drop_behavior,
5408            } => {
5409                write!(
5410                    f,
5411                    "DROP FUNCTION{} {}",
5412                    if *if_exists { " IF EXISTS" } else { "" },
5413                    display_comma_separated(func_desc),
5414                )?;
5415                if let Some(op) = drop_behavior {
5416                    write!(f, " {op}")?;
5417                }
5418                Ok(())
5419            }
5420            Statement::DropDomain(DropDomain {
5421                if_exists,
5422                name,
5423                drop_behavior,
5424            }) => {
5425                write!(
5426                    f,
5427                    "DROP DOMAIN{} {name}",
5428                    if *if_exists { " IF EXISTS" } else { "" },
5429                )?;
5430                if let Some(op) = drop_behavior {
5431                    write!(f, " {op}")?;
5432                }
5433                Ok(())
5434            }
5435            Statement::DropProcedure {
5436                if_exists,
5437                proc_desc,
5438                drop_behavior,
5439            } => {
5440                write!(
5441                    f,
5442                    "DROP PROCEDURE{} {}",
5443                    if *if_exists { " IF EXISTS" } else { "" },
5444                    display_comma_separated(proc_desc),
5445                )?;
5446                if let Some(op) = drop_behavior {
5447                    write!(f, " {op}")?;
5448                }
5449                Ok(())
5450            }
5451            Statement::DropSecret {
5452                if_exists,
5453                temporary,
5454                name,
5455                storage_specifier,
5456            } => {
5457                write!(f, "DROP ")?;
5458                if let Some(t) = temporary {
5459                    write!(f, "{}", if *t { "TEMPORARY " } else { "PERSISTENT " })?;
5460                }
5461                write!(
5462                    f,
5463                    "SECRET {if_exists}{name}",
5464                    if_exists = if *if_exists { "IF EXISTS " } else { "" },
5465                )?;
5466                if let Some(s) = storage_specifier {
5467                    write!(f, " FROM {s}")?;
5468                }
5469                Ok(())
5470            }
5471            Statement::DropPolicy {
5472                if_exists,
5473                name,
5474                table_name,
5475                drop_behavior,
5476            } => {
5477                write!(f, "DROP POLICY")?;
5478                if *if_exists {
5479                    write!(f, " IF EXISTS")?;
5480                }
5481                write!(f, " {name} ON {table_name}")?;
5482                if let Some(drop_behavior) = drop_behavior {
5483                    write!(f, " {drop_behavior}")?;
5484                }
5485                Ok(())
5486            }
5487            Statement::DropConnector { if_exists, name } => {
5488                write!(
5489                    f,
5490                    "DROP CONNECTOR {if_exists}{name}",
5491                    if_exists = if *if_exists { "IF EXISTS " } else { "" }
5492                )?;
5493                Ok(())
5494            }
5495            Statement::Discard { object_type } => {
5496                write!(f, "DISCARD {object_type}")?;
5497                Ok(())
5498            }
5499            Self::Set(set) => write!(f, "{set}"),
5500            Statement::ShowVariable { variable } => {
5501                write!(f, "SHOW")?;
5502                if !variable.is_empty() {
5503                    write!(f, " {}", display_separated(variable, " "))?;
5504                }
5505                Ok(())
5506            }
5507            Statement::ShowStatus {
5508                filter,
5509                global,
5510                session,
5511            } => {
5512                write!(f, "SHOW")?;
5513                if *global {
5514                    write!(f, " GLOBAL")?;
5515                }
5516                if *session {
5517                    write!(f, " SESSION")?;
5518                }
5519                write!(f, " STATUS")?;
5520                if filter.is_some() {
5521                    write!(f, " {}", filter.as_ref().unwrap())?;
5522                }
5523                Ok(())
5524            }
5525            Statement::ShowVariables {
5526                filter,
5527                global,
5528                session,
5529            } => {
5530                write!(f, "SHOW")?;
5531                if *global {
5532                    write!(f, " GLOBAL")?;
5533                }
5534                if *session {
5535                    write!(f, " SESSION")?;
5536                }
5537                write!(f, " VARIABLES")?;
5538                if filter.is_some() {
5539                    write!(f, " {}", filter.as_ref().unwrap())?;
5540                }
5541                Ok(())
5542            }
5543            Statement::ShowCreate { obj_type, obj_name } => {
5544                write!(f, "SHOW CREATE {obj_type} {obj_name}",)?;
5545                Ok(())
5546            }
5547            Statement::ShowColumns {
5548                extended,
5549                full,
5550                show_options,
5551            } => {
5552                write!(
5553                    f,
5554                    "SHOW {extended}{full}COLUMNS{show_options}",
5555                    extended = if *extended { "EXTENDED " } else { "" },
5556                    full = if *full { "FULL " } else { "" },
5557                )?;
5558                Ok(())
5559            }
5560            Statement::ShowDatabases {
5561                terse,
5562                history,
5563                show_options,
5564            } => {
5565                write!(
5566                    f,
5567                    "SHOW {terse}DATABASES{history}{show_options}",
5568                    terse = if *terse { "TERSE " } else { "" },
5569                    history = if *history { " HISTORY" } else { "" },
5570                )?;
5571                Ok(())
5572            }
5573            Statement::ShowSchemas {
5574                terse,
5575                history,
5576                show_options,
5577            } => {
5578                write!(
5579                    f,
5580                    "SHOW {terse}SCHEMAS{history}{show_options}",
5581                    terse = if *terse { "TERSE " } else { "" },
5582                    history = if *history { " HISTORY" } else { "" },
5583                )?;
5584                Ok(())
5585            }
5586            Statement::ShowObjects(ShowObjects {
5587                terse,
5588                show_options,
5589            }) => {
5590                write!(
5591                    f,
5592                    "SHOW {terse}OBJECTS{show_options}",
5593                    terse = if *terse { "TERSE " } else { "" },
5594                )?;
5595                Ok(())
5596            }
5597            Statement::ShowTables {
5598                terse,
5599                history,
5600                extended,
5601                full,
5602                external,
5603                show_options,
5604            } => {
5605                write!(
5606                    f,
5607                    "SHOW {terse}{extended}{full}{external}TABLES{history}{show_options}",
5608                    terse = if *terse { "TERSE " } else { "" },
5609                    extended = if *extended { "EXTENDED " } else { "" },
5610                    full = if *full { "FULL " } else { "" },
5611                    external = if *external { "EXTERNAL " } else { "" },
5612                    history = if *history { " HISTORY" } else { "" },
5613                )?;
5614                Ok(())
5615            }
5616            Statement::ShowViews {
5617                terse,
5618                materialized,
5619                show_options,
5620            } => {
5621                write!(
5622                    f,
5623                    "SHOW {terse}{materialized}VIEWS{show_options}",
5624                    terse = if *terse { "TERSE " } else { "" },
5625                    materialized = if *materialized { "MATERIALIZED " } else { "" }
5626                )?;
5627                Ok(())
5628            }
5629            Statement::ShowFunctions { filter } => {
5630                write!(f, "SHOW FUNCTIONS")?;
5631                if let Some(filter) = filter {
5632                    write!(f, " {filter}")?;
5633                }
5634                Ok(())
5635            }
5636            Statement::Use(use_expr) => use_expr.fmt(f),
5637            Statement::ShowCollation { filter } => {
5638                write!(f, "SHOW COLLATION")?;
5639                if let Some(filter) = filter {
5640                    write!(f, " {filter}")?;
5641                }
5642                Ok(())
5643            }
5644            Statement::ShowCharset(show_stm) => show_stm.fmt(f),
5645            Statement::StartTransaction {
5646                modes,
5647                begin: syntax_begin,
5648                transaction,
5649                modifier,
5650                statements,
5651                exception,
5652                has_end_keyword,
5653            } => {
5654                if *syntax_begin {
5655                    if let Some(modifier) = *modifier {
5656                        write!(f, "BEGIN {modifier}")?;
5657                    } else {
5658                        write!(f, "BEGIN")?;
5659                    }
5660                } else {
5661                    write!(f, "START")?;
5662                }
5663                if let Some(transaction) = transaction {
5664                    write!(f, " {transaction}")?;
5665                }
5666                if !modes.is_empty() {
5667                    write!(f, " {}", display_comma_separated(modes))?;
5668                }
5669                if !statements.is_empty() {
5670                    write!(f, " ")?;
5671                    format_statement_list(f, statements)?;
5672                }
5673                if let Some(exception_when) = exception {
5674                    write!(f, " EXCEPTION")?;
5675                    for when in exception_when {
5676                        write!(f, " {when}")?;
5677                    }
5678                }
5679                if *has_end_keyword {
5680                    write!(f, " END")?;
5681                }
5682                Ok(())
5683            }
5684            Statement::Commit {
5685                chain,
5686                end: end_syntax,
5687                modifier,
5688            } => {
5689                if *end_syntax {
5690                    write!(f, "END")?;
5691                    if let Some(modifier) = *modifier {
5692                        write!(f, " {modifier}")?;
5693                    }
5694                    if *chain {
5695                        write!(f, " AND CHAIN")?;
5696                    }
5697                } else {
5698                    write!(f, "COMMIT{}", if *chain { " AND CHAIN" } else { "" })?;
5699                }
5700                Ok(())
5701            }
5702            Statement::Rollback { chain, savepoint } => {
5703                write!(f, "ROLLBACK")?;
5704
5705                if *chain {
5706                    write!(f, " AND CHAIN")?;
5707                }
5708
5709                if let Some(savepoint) = savepoint {
5710                    write!(f, " TO SAVEPOINT {savepoint}")?;
5711                }
5712
5713                Ok(())
5714            }
5715            Statement::CreateSchema {
5716                schema_name,
5717                if_not_exists,
5718                with,
5719                options,
5720                default_collate_spec,
5721                clone,
5722            } => {
5723                write!(
5724                    f,
5725                    "CREATE SCHEMA {if_not_exists}{name}",
5726                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
5727                    name = schema_name
5728                )?;
5729
5730                if let Some(collate) = default_collate_spec {
5731                    write!(f, " DEFAULT COLLATE {collate}")?;
5732                }
5733
5734                if let Some(with) = with {
5735                    write!(f, " WITH ({})", display_comma_separated(with))?;
5736                }
5737
5738                if let Some(options) = options {
5739                    write!(f, " OPTIONS({})", display_comma_separated(options))?;
5740                }
5741
5742                if let Some(clone) = clone {
5743                    write!(f, " CLONE {clone}")?;
5744                }
5745                Ok(())
5746            }
5747            Statement::Assert { condition, message } => {
5748                write!(f, "ASSERT {condition}")?;
5749                if let Some(m) = message {
5750                    write!(f, " AS {m}")?;
5751                }
5752                Ok(())
5753            }
5754            Statement::Grant {
5755                privileges,
5756                objects,
5757                grantees,
5758                with_grant_option,
5759                as_grantor,
5760                granted_by,
5761                current_grants,
5762            } => {
5763                write!(f, "GRANT {privileges} ")?;
5764                if let Some(objects) = objects {
5765                    write!(f, "ON {objects} ")?;
5766                }
5767                write!(f, "TO {}", display_comma_separated(grantees))?;
5768                if *with_grant_option {
5769                    write!(f, " WITH GRANT OPTION")?;
5770                }
5771                if let Some(current_grants) = current_grants {
5772                    write!(f, " {current_grants}")?;
5773                }
5774                if let Some(grantor) = as_grantor {
5775                    write!(f, " AS {grantor}")?;
5776                }
5777                if let Some(grantor) = granted_by {
5778                    write!(f, " GRANTED BY {grantor}")?;
5779                }
5780                Ok(())
5781            }
5782            Statement::Deny(s) => write!(f, "{s}"),
5783            Statement::Revoke {
5784                privileges,
5785                objects,
5786                grantees,
5787                granted_by,
5788                cascade,
5789            } => {
5790                write!(f, "REVOKE {privileges} ")?;
5791                if let Some(objects) = objects {
5792                    write!(f, "ON {objects} ")?;
5793                }
5794                write!(f, "FROM {}", display_comma_separated(grantees))?;
5795                if let Some(grantor) = granted_by {
5796                    write!(f, " GRANTED BY {grantor}")?;
5797                }
5798                if let Some(cascade) = cascade {
5799                    write!(f, " {cascade}")?;
5800                }
5801                Ok(())
5802            }
5803            Statement::Deallocate { name, prepare } => write!(
5804                f,
5805                "DEALLOCATE {prepare}{name}",
5806                prepare = if *prepare { "PREPARE " } else { "" },
5807                name = name,
5808            ),
5809            Statement::Execute {
5810                name,
5811                parameters,
5812                has_parentheses,
5813                immediate,
5814                into,
5815                using,
5816                output,
5817                default,
5818            } => {
5819                let (open, close) = if *has_parentheses {
5820                    ("(", ")")
5821                } else {
5822                    (if parameters.is_empty() { "" } else { " " }, "")
5823                };
5824                write!(f, "EXECUTE")?;
5825                if *immediate {
5826                    write!(f, " IMMEDIATE")?;
5827                }
5828                if let Some(name) = name {
5829                    write!(f, " {name}")?;
5830                }
5831                write!(f, "{open}{}{close}", display_comma_separated(parameters),)?;
5832                if !into.is_empty() {
5833                    write!(f, " INTO {}", display_comma_separated(into))?;
5834                }
5835                if !using.is_empty() {
5836                    write!(f, " USING {}", display_comma_separated(using))?;
5837                };
5838                if *output {
5839                    write!(f, " OUTPUT")?;
5840                }
5841                if *default {
5842                    write!(f, " DEFAULT")?;
5843                }
5844                Ok(())
5845            }
5846            Statement::Prepare {
5847                name,
5848                data_types,
5849                statement,
5850            } => {
5851                write!(f, "PREPARE {name} ")?;
5852                if !data_types.is_empty() {
5853                    write!(f, "({}) ", display_comma_separated(data_types))?;
5854                }
5855                write!(f, "AS {statement}")
5856            }
5857            Statement::Comment {
5858                object_type,
5859                object_name,
5860                comment,
5861                if_exists,
5862            } => {
5863                write!(f, "COMMENT ")?;
5864                if *if_exists {
5865                    write!(f, "IF EXISTS ")?
5866                };
5867                write!(f, "ON {object_type} {object_name} IS ")?;
5868                if let Some(c) = comment {
5869                    write!(f, "'{c}'")
5870                } else {
5871                    write!(f, "NULL")
5872                }
5873            }
5874            Statement::Savepoint { name } => {
5875                write!(f, "SAVEPOINT ")?;
5876                write!(f, "{name}")
5877            }
5878            Statement::ReleaseSavepoint { name } => {
5879                write!(f, "RELEASE SAVEPOINT {name}")
5880            }
5881            Statement::Merge {
5882                into,
5883                table,
5884                source,
5885                on,
5886                clauses,
5887                output,
5888            } => {
5889                write!(
5890                    f,
5891                    "MERGE{int} {table} USING {source} ",
5892                    int = if *into { " INTO" } else { "" }
5893                )?;
5894                write!(f, "ON {on} ")?;
5895                write!(f, "{}", display_separated(clauses, " "))?;
5896                if let Some(output) = output {
5897                    write!(f, " {output}")?;
5898                }
5899                Ok(())
5900            }
5901            Statement::Cache {
5902                table_name,
5903                table_flag,
5904                has_as,
5905                options,
5906                query,
5907            } => {
5908                if let Some(table_flag) = table_flag {
5909                    write!(f, "CACHE {table_flag} TABLE {table_name}")?;
5910                } else {
5911                    write!(f, "CACHE TABLE {table_name}")?;
5912                }
5913
5914                if !options.is_empty() {
5915                    write!(f, " OPTIONS({})", display_comma_separated(options))?;
5916                }
5917
5918                match (*has_as, query) {
5919                    (true, Some(query)) => write!(f, " AS {query}"),
5920                    (true, None) => f.write_str(" AS"),
5921                    (false, Some(query)) => write!(f, " {query}"),
5922                    (false, None) => Ok(()),
5923                }
5924            }
5925            Statement::UNCache {
5926                table_name,
5927                if_exists,
5928            } => {
5929                if *if_exists {
5930                    write!(f, "UNCACHE TABLE IF EXISTS {table_name}")
5931                } else {
5932                    write!(f, "UNCACHE TABLE {table_name}")
5933                }
5934            }
5935            Statement::CreateSequence {
5936                temporary,
5937                if_not_exists,
5938                name,
5939                data_type,
5940                sequence_options,
5941                owned_by,
5942            } => {
5943                let as_type: String = if let Some(dt) = data_type.as_ref() {
5944                    //Cannot use format!(" AS {}", dt), due to format! is not available in --target thumbv6m-none-eabi
5945                    // " AS ".to_owned() + &dt.to_string()
5946                    [" AS ", &dt.to_string()].concat()
5947                } else {
5948                    "".to_string()
5949                };
5950                write!(
5951                    f,
5952                    "CREATE {temporary}SEQUENCE {if_not_exists}{name}{as_type}",
5953                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
5954                    temporary = if *temporary { "TEMPORARY " } else { "" },
5955                    name = name,
5956                    as_type = as_type
5957                )?;
5958                for sequence_option in sequence_options {
5959                    write!(f, "{sequence_option}")?;
5960                }
5961                if let Some(ob) = owned_by.as_ref() {
5962                    write!(f, " OWNED BY {ob}")?;
5963                }
5964                write!(f, "")
5965            }
5966            Statement::CreateStage {
5967                or_replace,
5968                temporary,
5969                if_not_exists,
5970                name,
5971                stage_params,
5972                directory_table_params,
5973                file_format,
5974                copy_options,
5975                comment,
5976                ..
5977            } => {
5978                write!(
5979                    f,
5980                    "CREATE {or_replace}{temp}STAGE {if_not_exists}{name}{stage_params}",
5981                    temp = if *temporary { "TEMPORARY " } else { "" },
5982                    or_replace = if *or_replace { "OR REPLACE " } else { "" },
5983                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
5984                )?;
5985                if !directory_table_params.options.is_empty() {
5986                    write!(f, " DIRECTORY=({directory_table_params})")?;
5987                }
5988                if !file_format.options.is_empty() {
5989                    write!(f, " FILE_FORMAT=({file_format})")?;
5990                }
5991                if !copy_options.options.is_empty() {
5992                    write!(f, " COPY_OPTIONS=({copy_options})")?;
5993                }
5994                if comment.is_some() {
5995                    write!(f, " COMMENT='{}'", comment.as_ref().unwrap())?;
5996                }
5997                Ok(())
5998            }
5999            Statement::CopyIntoSnowflake {
6000                kind,
6001                into,
6002                into_columns,
6003                from_obj,
6004                from_obj_alias,
6005                stage_params,
6006                from_transformations,
6007                from_query,
6008                files,
6009                pattern,
6010                file_format,
6011                copy_options,
6012                validation_mode,
6013                partition,
6014            } => {
6015                write!(f, "COPY INTO {into}")?;
6016                if let Some(into_columns) = into_columns {
6017                    write!(f, " ({})", display_comma_separated(into_columns))?;
6018                }
6019                if let Some(from_transformations) = from_transformations {
6020                    // Data load with transformation
6021                    if let Some(from_stage) = from_obj {
6022                        write!(
6023                            f,
6024                            " FROM (SELECT {} FROM {}{}",
6025                            display_separated(from_transformations, ", "),
6026                            from_stage,
6027                            stage_params
6028                        )?;
6029                    }
6030                    if let Some(from_obj_alias) = from_obj_alias {
6031                        write!(f, " AS {from_obj_alias}")?;
6032                    }
6033                    write!(f, ")")?;
6034                } else if let Some(from_obj) = from_obj {
6035                    // Standard data load
6036                    write!(f, " FROM {from_obj}{stage_params}")?;
6037                    if let Some(from_obj_alias) = from_obj_alias {
6038                        write!(f, " AS {from_obj_alias}")?;
6039                    }
6040                } else if let Some(from_query) = from_query {
6041                    // Data unload from query
6042                    write!(f, " FROM ({from_query})")?;
6043                }
6044
6045                if let Some(files) = files {
6046                    write!(f, " FILES = ('{}')", display_separated(files, "', '"))?;
6047                }
6048                if let Some(pattern) = pattern {
6049                    write!(f, " PATTERN = '{pattern}'")?;
6050                }
6051                if let Some(partition) = partition {
6052                    write!(f, " PARTITION BY {partition}")?;
6053                }
6054                if !file_format.options.is_empty() {
6055                    write!(f, " FILE_FORMAT=({file_format})")?;
6056                }
6057                if !copy_options.options.is_empty() {
6058                    match kind {
6059                        CopyIntoSnowflakeKind::Table => {
6060                            write!(f, " COPY_OPTIONS=({copy_options})")?
6061                        }
6062                        CopyIntoSnowflakeKind::Location => write!(f, " {copy_options}")?,
6063                    }
6064                }
6065                if let Some(validation_mode) = validation_mode {
6066                    write!(f, " VALIDATION_MODE = {validation_mode}")?;
6067                }
6068                Ok(())
6069            }
6070            Statement::CreateType {
6071                name,
6072                representation,
6073            } => {
6074                write!(f, "CREATE TYPE {name} AS {representation}")
6075            }
6076            Statement::Pragma { name, value, is_eq } => {
6077                write!(f, "PRAGMA {name}")?;
6078                if value.is_some() {
6079                    let val = value.as_ref().unwrap();
6080                    if *is_eq {
6081                        write!(f, " = {val}")?;
6082                    } else {
6083                        write!(f, "({val})")?;
6084                    }
6085                }
6086                Ok(())
6087            }
6088            Statement::LockTables { tables } => {
6089                write!(f, "LOCK TABLES {}", display_comma_separated(tables))
6090            }
6091            Statement::UnlockTables => {
6092                write!(f, "UNLOCK TABLES")
6093            }
6094            Statement::Unload {
6095                query,
6096                query_text,
6097                to,
6098                auth,
6099                with,
6100                options,
6101            } => {
6102                write!(f, "UNLOAD(")?;
6103                if let Some(query) = query {
6104                    write!(f, "{query}")?;
6105                }
6106                if let Some(query_text) = query_text {
6107                    write!(f, "'{query_text}'")?;
6108                }
6109                write!(f, ") TO {to}")?;
6110                if let Some(auth) = auth {
6111                    write!(f, " IAM_ROLE {auth}")?;
6112                }
6113                if !with.is_empty() {
6114                    write!(f, " WITH ({})", display_comma_separated(with))?;
6115                }
6116                if !options.is_empty() {
6117                    write!(f, " {}", display_separated(options, " "))?;
6118                }
6119                Ok(())
6120            }
6121            Statement::OptimizeTable {
6122                name,
6123                on_cluster,
6124                partition,
6125                include_final,
6126                deduplicate,
6127            } => {
6128                write!(f, "OPTIMIZE TABLE {name}")?;
6129                if let Some(on_cluster) = on_cluster {
6130                    write!(f, " ON CLUSTER {on_cluster}")?;
6131                }
6132                if let Some(partition) = partition {
6133                    write!(f, " {partition}")?;
6134                }
6135                if *include_final {
6136                    write!(f, " FINAL")?;
6137                }
6138                if let Some(deduplicate) = deduplicate {
6139                    write!(f, " {deduplicate}")?;
6140                }
6141                Ok(())
6142            }
6143            Statement::LISTEN { channel } => {
6144                write!(f, "LISTEN {channel}")?;
6145                Ok(())
6146            }
6147            Statement::UNLISTEN { channel } => {
6148                write!(f, "UNLISTEN {channel}")?;
6149                Ok(())
6150            }
6151            Statement::NOTIFY { channel, payload } => {
6152                write!(f, "NOTIFY {channel}")?;
6153                if let Some(payload) = payload {
6154                    write!(f, ", '{payload}'")?;
6155                }
6156                Ok(())
6157            }
6158            Statement::RenameTable(rename_tables) => {
6159                write!(f, "RENAME TABLE {}", display_comma_separated(rename_tables))
6160            }
6161            Statement::RaisError {
6162                message,
6163                severity,
6164                state,
6165                arguments,
6166                options,
6167            } => {
6168                write!(f, "RAISERROR({message}, {severity}, {state}")?;
6169                if !arguments.is_empty() {
6170                    write!(f, ", {}", display_comma_separated(arguments))?;
6171                }
6172                write!(f, ")")?;
6173                if !options.is_empty() {
6174                    write!(f, " WITH {}", display_comma_separated(options))?;
6175                }
6176                Ok(())
6177            }
6178            Statement::Print(s) => write!(f, "{s}"),
6179            Statement::Return(r) => write!(f, "{r}"),
6180            Statement::List(command) => write!(f, "LIST {command}"),
6181            Statement::Remove(command) => write!(f, "REMOVE {command}"),
6182            Statement::ExportData(e) => write!(f, "{e}"),
6183            Statement::CreateUser(s) => write!(f, "{s}"),
6184            Statement::AlterSchema(s) => write!(f, "{s}"),
6185            Statement::Vacuum(s) => write!(f, "{s}"),
6186        }
6187    }
6188}
6189
6190/// Can use to describe options in create sequence or table column type identity
6191/// ```sql
6192/// [ INCREMENT [ BY ] increment ]
6193///     [ MINVALUE minvalue | NO MINVALUE ] [ MAXVALUE maxvalue | NO MAXVALUE ]
6194///     [ START [ WITH ] start ] [ CACHE cache ] [ [ NO ] CYCLE ]
6195/// ```
6196#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6197#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6198#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6199pub enum SequenceOptions {
6200    IncrementBy(Expr, bool),
6201    MinValue(Option<Expr>),
6202    MaxValue(Option<Expr>),
6203    StartWith(Expr, bool),
6204    Cache(Expr),
6205    Cycle(bool),
6206}
6207
6208impl fmt::Display for SequenceOptions {
6209    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6210        match self {
6211            SequenceOptions::IncrementBy(increment, by) => {
6212                write!(
6213                    f,
6214                    " INCREMENT{by} {increment}",
6215                    by = if *by { " BY" } else { "" },
6216                    increment = increment
6217                )
6218            }
6219            SequenceOptions::MinValue(Some(expr)) => {
6220                write!(f, " MINVALUE {expr}")
6221            }
6222            SequenceOptions::MinValue(None) => {
6223                write!(f, " NO MINVALUE")
6224            }
6225            SequenceOptions::MaxValue(Some(expr)) => {
6226                write!(f, " MAXVALUE {expr}")
6227            }
6228            SequenceOptions::MaxValue(None) => {
6229                write!(f, " NO MAXVALUE")
6230            }
6231            SequenceOptions::StartWith(start, with) => {
6232                write!(
6233                    f,
6234                    " START{with} {start}",
6235                    with = if *with { " WITH" } else { "" },
6236                    start = start
6237                )
6238            }
6239            SequenceOptions::Cache(cache) => {
6240                write!(f, " CACHE {}", *cache)
6241            }
6242            SequenceOptions::Cycle(no) => {
6243                write!(f, " {}CYCLE", if *no { "NO " } else { "" })
6244            }
6245        }
6246    }
6247}
6248
6249/// Assignment for a `SET` statement (name [=|TO] value)
6250#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6251#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6252#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6253pub struct SetAssignment {
6254    pub scope: Option<ContextModifier>,
6255    pub name: ObjectName,
6256    pub value: Expr,
6257}
6258
6259impl fmt::Display for SetAssignment {
6260    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6261        write!(
6262            f,
6263            "{}{} = {}",
6264            self.scope.map(|s| format!("{s}")).unwrap_or_default(),
6265            self.name,
6266            self.value
6267        )
6268    }
6269}
6270
6271/// Target of a `TRUNCATE TABLE` command
6272///
6273/// Note this is its own struct because `visit_relation` requires an `ObjectName` (not a `Vec<ObjectName>`)
6274#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6275#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6276#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6277pub struct TruncateTableTarget {
6278    /// name of the table being truncated
6279    #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
6280    pub name: ObjectName,
6281    /// Postgres-specific option
6282    /// [ TRUNCATE TABLE ONLY ]
6283    /// <https://www.postgresql.org/docs/current/sql-truncate.html>
6284    pub only: bool,
6285}
6286
6287impl fmt::Display for TruncateTableTarget {
6288    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6289        if self.only {
6290            write!(f, "ONLY ")?;
6291        };
6292        write!(f, "{}", self.name)
6293    }
6294}
6295
6296/// PostgreSQL identity option for TRUNCATE table
6297/// [ RESTART IDENTITY | CONTINUE IDENTITY ]
6298#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6299#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6300#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6301pub enum TruncateIdentityOption {
6302    Restart,
6303    Continue,
6304}
6305
6306/// Cascade/restrict option for Postgres TRUNCATE table, MySQL GRANT/REVOKE, etc.
6307/// [ CASCADE | RESTRICT ]
6308#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6309#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6310#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6311pub enum CascadeOption {
6312    Cascade,
6313    Restrict,
6314}
6315
6316impl Display for CascadeOption {
6317    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6318        match self {
6319            CascadeOption::Cascade => write!(f, "CASCADE"),
6320            CascadeOption::Restrict => write!(f, "RESTRICT"),
6321        }
6322    }
6323}
6324
6325/// Transaction started with [ TRANSACTION | WORK ]
6326#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6327#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6328#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6329pub enum BeginTransactionKind {
6330    Transaction,
6331    Work,
6332}
6333
6334impl Display for BeginTransactionKind {
6335    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6336        match self {
6337            BeginTransactionKind::Transaction => write!(f, "TRANSACTION"),
6338            BeginTransactionKind::Work => write!(f, "WORK"),
6339        }
6340    }
6341}
6342
6343/// Can use to describe options in  create sequence or table column type identity
6344/// [ MINVALUE minvalue | NO MINVALUE ] [ MAXVALUE maxvalue | NO MAXVALUE ]
6345#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6346#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6347#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6348pub enum MinMaxValue {
6349    // clause is not specified
6350    Empty,
6351    // NO MINVALUE/NO MAXVALUE
6352    None,
6353    // MINVALUE <expr> / MAXVALUE <expr>
6354    Some(Expr),
6355}
6356
6357#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6358#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6359#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6360#[non_exhaustive]
6361pub enum OnInsert {
6362    /// ON DUPLICATE KEY UPDATE (MySQL when the key already exists, then execute an update instead)
6363    DuplicateKeyUpdate(Vec<Assignment>),
6364    /// ON CONFLICT is a PostgreSQL and Sqlite extension
6365    OnConflict(OnConflict),
6366}
6367
6368#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6369#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6370#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6371pub struct InsertAliases {
6372    pub row_alias: ObjectName,
6373    pub col_aliases: Option<Vec<Ident>>,
6374}
6375
6376#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6377#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6378#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6379pub struct OnConflict {
6380    pub conflict_target: Option<ConflictTarget>,
6381    pub action: OnConflictAction,
6382}
6383#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6384#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6385#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6386pub enum ConflictTarget {
6387    Columns(Vec<Ident>),
6388    OnConstraint(ObjectName),
6389}
6390#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6391#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6392#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6393pub enum OnConflictAction {
6394    DoNothing,
6395    DoUpdate(DoUpdate),
6396}
6397
6398#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6399#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6400#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6401pub struct DoUpdate {
6402    /// Column assignments
6403    pub assignments: Vec<Assignment>,
6404    /// WHERE
6405    pub selection: Option<Expr>,
6406}
6407
6408impl fmt::Display for OnInsert {
6409    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6410        match self {
6411            Self::DuplicateKeyUpdate(expr) => write!(
6412                f,
6413                " ON DUPLICATE KEY UPDATE {}",
6414                display_comma_separated(expr)
6415            ),
6416            Self::OnConflict(o) => write!(f, "{o}"),
6417        }
6418    }
6419}
6420impl fmt::Display for OnConflict {
6421    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6422        write!(f, " ON CONFLICT")?;
6423        if let Some(target) = &self.conflict_target {
6424            write!(f, "{target}")?;
6425        }
6426        write!(f, " {}", self.action)
6427    }
6428}
6429impl fmt::Display for ConflictTarget {
6430    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6431        match self {
6432            ConflictTarget::Columns(cols) => write!(f, "({})", display_comma_separated(cols)),
6433            ConflictTarget::OnConstraint(name) => write!(f, " ON CONSTRAINT {name}"),
6434        }
6435    }
6436}
6437impl fmt::Display for OnConflictAction {
6438    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6439        match self {
6440            Self::DoNothing => write!(f, "DO NOTHING"),
6441            Self::DoUpdate(do_update) => {
6442                write!(f, "DO UPDATE")?;
6443                if !do_update.assignments.is_empty() {
6444                    write!(
6445                        f,
6446                        " SET {}",
6447                        display_comma_separated(&do_update.assignments)
6448                    )?;
6449                }
6450                if let Some(selection) = &do_update.selection {
6451                    write!(f, " WHERE {selection}")?;
6452                }
6453                Ok(())
6454            }
6455        }
6456    }
6457}
6458
6459/// Privileges granted in a GRANT statement or revoked in a REVOKE statement.
6460#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6461#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6462#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6463pub enum Privileges {
6464    /// All privileges applicable to the object type
6465    All {
6466        /// Optional keyword from the spec, ignored in practice
6467        with_privileges_keyword: bool,
6468    },
6469    /// Specific privileges (e.g. `SELECT`, `INSERT`)
6470    Actions(Vec<Action>),
6471}
6472
6473impl fmt::Display for Privileges {
6474    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6475        match self {
6476            Privileges::All {
6477                with_privileges_keyword,
6478            } => {
6479                write!(
6480                    f,
6481                    "ALL{}",
6482                    if *with_privileges_keyword {
6483                        " PRIVILEGES"
6484                    } else {
6485                        ""
6486                    }
6487                )
6488            }
6489            Privileges::Actions(actions) => {
6490                write!(f, "{}", display_comma_separated(actions))
6491            }
6492        }
6493    }
6494}
6495
6496/// Specific direction for FETCH statement
6497#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6498#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6499#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6500pub enum FetchDirection {
6501    Count { limit: Value },
6502    Next,
6503    Prior,
6504    First,
6505    Last,
6506    Absolute { limit: Value },
6507    Relative { limit: Value },
6508    All,
6509    // FORWARD
6510    // FORWARD count
6511    Forward { limit: Option<Value> },
6512    ForwardAll,
6513    // BACKWARD
6514    // BACKWARD count
6515    Backward { limit: Option<Value> },
6516    BackwardAll,
6517}
6518
6519impl fmt::Display for FetchDirection {
6520    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6521        match self {
6522            FetchDirection::Count { limit } => f.write_str(&limit.to_string())?,
6523            FetchDirection::Next => f.write_str("NEXT")?,
6524            FetchDirection::Prior => f.write_str("PRIOR")?,
6525            FetchDirection::First => f.write_str("FIRST")?,
6526            FetchDirection::Last => f.write_str("LAST")?,
6527            FetchDirection::Absolute { limit } => {
6528                f.write_str("ABSOLUTE ")?;
6529                f.write_str(&limit.to_string())?;
6530            }
6531            FetchDirection::Relative { limit } => {
6532                f.write_str("RELATIVE ")?;
6533                f.write_str(&limit.to_string())?;
6534            }
6535            FetchDirection::All => f.write_str("ALL")?,
6536            FetchDirection::Forward { limit } => {
6537                f.write_str("FORWARD")?;
6538
6539                if let Some(l) = limit {
6540                    f.write_str(" ")?;
6541                    f.write_str(&l.to_string())?;
6542                }
6543            }
6544            FetchDirection::ForwardAll => f.write_str("FORWARD ALL")?,
6545            FetchDirection::Backward { limit } => {
6546                f.write_str("BACKWARD")?;
6547
6548                if let Some(l) = limit {
6549                    f.write_str(" ")?;
6550                    f.write_str(&l.to_string())?;
6551                }
6552            }
6553            FetchDirection::BackwardAll => f.write_str("BACKWARD ALL")?,
6554        };
6555
6556        Ok(())
6557    }
6558}
6559
6560/// The "position" for a FETCH statement.
6561///
6562/// [MsSql](https://learn.microsoft.com/en-us/sql/t-sql/language-elements/fetch-transact-sql)
6563#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6564#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6565#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6566pub enum FetchPosition {
6567    From,
6568    In,
6569}
6570
6571impl fmt::Display for FetchPosition {
6572    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6573        match self {
6574            FetchPosition::From => f.write_str("FROM")?,
6575            FetchPosition::In => f.write_str("IN")?,
6576        };
6577
6578        Ok(())
6579    }
6580}
6581
6582/// A privilege on a database object (table, sequence, etc.).
6583#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6584#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6585#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6586pub enum Action {
6587    AddSearchOptimization,
6588    Apply {
6589        apply_type: ActionApplyType,
6590    },
6591    ApplyBudget,
6592    AttachListing,
6593    AttachPolicy,
6594    Audit,
6595    BindServiceEndpoint,
6596    Connect,
6597    Create {
6598        obj_type: Option<ActionCreateObjectType>,
6599    },
6600    DatabaseRole {
6601        role: ObjectName,
6602    },
6603    Delete,
6604    Drop,
6605    EvolveSchema,
6606    Exec {
6607        obj_type: Option<ActionExecuteObjectType>,
6608    },
6609    Execute {
6610        obj_type: Option<ActionExecuteObjectType>,
6611    },
6612    Failover,
6613    ImportedPrivileges,
6614    ImportShare,
6615    Insert {
6616        columns: Option<Vec<Ident>>,
6617    },
6618    Manage {
6619        manage_type: ActionManageType,
6620    },
6621    ManageReleases,
6622    ManageVersions,
6623    Modify {
6624        modify_type: Option<ActionModifyType>,
6625    },
6626    Monitor {
6627        monitor_type: Option<ActionMonitorType>,
6628    },
6629    Operate,
6630    OverrideShareRestrictions,
6631    Ownership,
6632    PurchaseDataExchangeListing,
6633    Read,
6634    ReadSession,
6635    References {
6636        columns: Option<Vec<Ident>>,
6637    },
6638    Replicate,
6639    ResolveAll,
6640    Role {
6641        role: ObjectName,
6642    },
6643    Select {
6644        columns: Option<Vec<Ident>>,
6645    },
6646    Temporary,
6647    Trigger,
6648    Truncate,
6649    Update {
6650        columns: Option<Vec<Ident>>,
6651    },
6652    Usage,
6653}
6654
6655impl fmt::Display for Action {
6656    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6657        match self {
6658            Action::AddSearchOptimization => f.write_str("ADD SEARCH OPTIMIZATION")?,
6659            Action::Apply { apply_type } => write!(f, "APPLY {apply_type}")?,
6660            Action::ApplyBudget => f.write_str("APPLYBUDGET")?,
6661            Action::AttachListing => f.write_str("ATTACH LISTING")?,
6662            Action::AttachPolicy => f.write_str("ATTACH POLICY")?,
6663            Action::Audit => f.write_str("AUDIT")?,
6664            Action::BindServiceEndpoint => f.write_str("BIND SERVICE ENDPOINT")?,
6665            Action::Connect => f.write_str("CONNECT")?,
6666            Action::Create { obj_type } => {
6667                f.write_str("CREATE")?;
6668                if let Some(obj_type) = obj_type {
6669                    write!(f, " {obj_type}")?
6670                }
6671            }
6672            Action::DatabaseRole { role } => write!(f, "DATABASE ROLE {role}")?,
6673            Action::Delete => f.write_str("DELETE")?,
6674            Action::Drop => f.write_str("DROP")?,
6675            Action::EvolveSchema => f.write_str("EVOLVE SCHEMA")?,
6676            Action::Exec { obj_type } => {
6677                f.write_str("EXEC")?;
6678                if let Some(obj_type) = obj_type {
6679                    write!(f, " {obj_type}")?
6680                }
6681            }
6682            Action::Execute { obj_type } => {
6683                f.write_str("EXECUTE")?;
6684                if let Some(obj_type) = obj_type {
6685                    write!(f, " {obj_type}")?
6686                }
6687            }
6688            Action::Failover => f.write_str("FAILOVER")?,
6689            Action::ImportedPrivileges => f.write_str("IMPORTED PRIVILEGES")?,
6690            Action::ImportShare => f.write_str("IMPORT SHARE")?,
6691            Action::Insert { .. } => f.write_str("INSERT")?,
6692            Action::Manage { manage_type } => write!(f, "MANAGE {manage_type}")?,
6693            Action::ManageReleases => f.write_str("MANAGE RELEASES")?,
6694            Action::ManageVersions => f.write_str("MANAGE VERSIONS")?,
6695            Action::Modify { modify_type } => {
6696                write!(f, "MODIFY")?;
6697                if let Some(modify_type) = modify_type {
6698                    write!(f, " {modify_type}")?;
6699                }
6700            }
6701            Action::Monitor { monitor_type } => {
6702                write!(f, "MONITOR")?;
6703                if let Some(monitor_type) = monitor_type {
6704                    write!(f, " {monitor_type}")?
6705                }
6706            }
6707            Action::Operate => f.write_str("OPERATE")?,
6708            Action::OverrideShareRestrictions => f.write_str("OVERRIDE SHARE RESTRICTIONS")?,
6709            Action::Ownership => f.write_str("OWNERSHIP")?,
6710            Action::PurchaseDataExchangeListing => f.write_str("PURCHASE DATA EXCHANGE LISTING")?,
6711            Action::Read => f.write_str("READ")?,
6712            Action::ReadSession => f.write_str("READ SESSION")?,
6713            Action::References { .. } => f.write_str("REFERENCES")?,
6714            Action::Replicate => f.write_str("REPLICATE")?,
6715            Action::ResolveAll => f.write_str("RESOLVE ALL")?,
6716            Action::Role { role } => write!(f, "ROLE {role}")?,
6717            Action::Select { .. } => f.write_str("SELECT")?,
6718            Action::Temporary => f.write_str("TEMPORARY")?,
6719            Action::Trigger => f.write_str("TRIGGER")?,
6720            Action::Truncate => f.write_str("TRUNCATE")?,
6721            Action::Update { .. } => f.write_str("UPDATE")?,
6722            Action::Usage => f.write_str("USAGE")?,
6723        };
6724        match self {
6725            Action::Insert { columns }
6726            | Action::References { columns }
6727            | Action::Select { columns }
6728            | Action::Update { columns } => {
6729                if let Some(columns) = columns {
6730                    write!(f, " ({})", display_comma_separated(columns))?;
6731                }
6732            }
6733            _ => (),
6734        };
6735        Ok(())
6736    }
6737}
6738
6739#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6740#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6741#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6742/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
6743/// under `globalPrivileges` in the `CREATE` privilege.
6744pub enum ActionCreateObjectType {
6745    Account,
6746    Application,
6747    ApplicationPackage,
6748    ComputePool,
6749    DataExchangeListing,
6750    Database,
6751    ExternalVolume,
6752    FailoverGroup,
6753    Integration,
6754    NetworkPolicy,
6755    OrganiationListing,
6756    ReplicationGroup,
6757    Role,
6758    Schema,
6759    Share,
6760    User,
6761    Warehouse,
6762}
6763
6764impl fmt::Display for ActionCreateObjectType {
6765    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6766        match self {
6767            ActionCreateObjectType::Account => write!(f, "ACCOUNT"),
6768            ActionCreateObjectType::Application => write!(f, "APPLICATION"),
6769            ActionCreateObjectType::ApplicationPackage => write!(f, "APPLICATION PACKAGE"),
6770            ActionCreateObjectType::ComputePool => write!(f, "COMPUTE POOL"),
6771            ActionCreateObjectType::DataExchangeListing => write!(f, "DATA EXCHANGE LISTING"),
6772            ActionCreateObjectType::Database => write!(f, "DATABASE"),
6773            ActionCreateObjectType::ExternalVolume => write!(f, "EXTERNAL VOLUME"),
6774            ActionCreateObjectType::FailoverGroup => write!(f, "FAILOVER GROUP"),
6775            ActionCreateObjectType::Integration => write!(f, "INTEGRATION"),
6776            ActionCreateObjectType::NetworkPolicy => write!(f, "NETWORK POLICY"),
6777            ActionCreateObjectType::OrganiationListing => write!(f, "ORGANIZATION LISTING"),
6778            ActionCreateObjectType::ReplicationGroup => write!(f, "REPLICATION GROUP"),
6779            ActionCreateObjectType::Role => write!(f, "ROLE"),
6780            ActionCreateObjectType::Schema => write!(f, "SCHEMA"),
6781            ActionCreateObjectType::Share => write!(f, "SHARE"),
6782            ActionCreateObjectType::User => write!(f, "USER"),
6783            ActionCreateObjectType::Warehouse => write!(f, "WAREHOUSE"),
6784        }
6785    }
6786}
6787
6788#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6789#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6790#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6791/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
6792/// under `globalPrivileges` in the `APPLY` privilege.
6793pub enum ActionApplyType {
6794    AggregationPolicy,
6795    AuthenticationPolicy,
6796    JoinPolicy,
6797    MaskingPolicy,
6798    PackagesPolicy,
6799    PasswordPolicy,
6800    ProjectionPolicy,
6801    RowAccessPolicy,
6802    SessionPolicy,
6803    Tag,
6804}
6805
6806impl fmt::Display for ActionApplyType {
6807    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6808        match self {
6809            ActionApplyType::AggregationPolicy => write!(f, "AGGREGATION POLICY"),
6810            ActionApplyType::AuthenticationPolicy => write!(f, "AUTHENTICATION POLICY"),
6811            ActionApplyType::JoinPolicy => write!(f, "JOIN POLICY"),
6812            ActionApplyType::MaskingPolicy => write!(f, "MASKING POLICY"),
6813            ActionApplyType::PackagesPolicy => write!(f, "PACKAGES POLICY"),
6814            ActionApplyType::PasswordPolicy => write!(f, "PASSWORD POLICY"),
6815            ActionApplyType::ProjectionPolicy => write!(f, "PROJECTION POLICY"),
6816            ActionApplyType::RowAccessPolicy => write!(f, "ROW ACCESS POLICY"),
6817            ActionApplyType::SessionPolicy => write!(f, "SESSION POLICY"),
6818            ActionApplyType::Tag => write!(f, "TAG"),
6819        }
6820    }
6821}
6822
6823#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6824#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6825#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6826/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
6827/// under `globalPrivileges` in the `EXECUTE` privilege.
6828pub enum ActionExecuteObjectType {
6829    Alert,
6830    DataMetricFunction,
6831    ManagedAlert,
6832    ManagedTask,
6833    Task,
6834}
6835
6836impl fmt::Display for ActionExecuteObjectType {
6837    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6838        match self {
6839            ActionExecuteObjectType::Alert => write!(f, "ALERT"),
6840            ActionExecuteObjectType::DataMetricFunction => write!(f, "DATA METRIC FUNCTION"),
6841            ActionExecuteObjectType::ManagedAlert => write!(f, "MANAGED ALERT"),
6842            ActionExecuteObjectType::ManagedTask => write!(f, "MANAGED TASK"),
6843            ActionExecuteObjectType::Task => write!(f, "TASK"),
6844        }
6845    }
6846}
6847
6848#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6849#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6850#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6851/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
6852/// under `globalPrivileges` in the `MANAGE` privilege.
6853pub enum ActionManageType {
6854    AccountSupportCases,
6855    EventSharing,
6856    Grants,
6857    ListingAutoFulfillment,
6858    OrganizationSupportCases,
6859    UserSupportCases,
6860    Warehouses,
6861}
6862
6863impl fmt::Display for ActionManageType {
6864    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6865        match self {
6866            ActionManageType::AccountSupportCases => write!(f, "ACCOUNT SUPPORT CASES"),
6867            ActionManageType::EventSharing => write!(f, "EVENT SHARING"),
6868            ActionManageType::Grants => write!(f, "GRANTS"),
6869            ActionManageType::ListingAutoFulfillment => write!(f, "LISTING AUTO FULFILLMENT"),
6870            ActionManageType::OrganizationSupportCases => write!(f, "ORGANIZATION SUPPORT CASES"),
6871            ActionManageType::UserSupportCases => write!(f, "USER SUPPORT CASES"),
6872            ActionManageType::Warehouses => write!(f, "WAREHOUSES"),
6873        }
6874    }
6875}
6876
6877#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6878#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6879#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6880/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
6881/// under `globalPrivileges` in the `MODIFY` privilege.
6882pub enum ActionModifyType {
6883    LogLevel,
6884    TraceLevel,
6885    SessionLogLevel,
6886    SessionTraceLevel,
6887}
6888
6889impl fmt::Display for ActionModifyType {
6890    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6891        match self {
6892            ActionModifyType::LogLevel => write!(f, "LOG LEVEL"),
6893            ActionModifyType::TraceLevel => write!(f, "TRACE LEVEL"),
6894            ActionModifyType::SessionLogLevel => write!(f, "SESSION LOG LEVEL"),
6895            ActionModifyType::SessionTraceLevel => write!(f, "SESSION TRACE LEVEL"),
6896        }
6897    }
6898}
6899
6900#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6901#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6902#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6903/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
6904/// under `globalPrivileges` in the `MONITOR` privilege.
6905pub enum ActionMonitorType {
6906    Execution,
6907    Security,
6908    Usage,
6909}
6910
6911impl fmt::Display for ActionMonitorType {
6912    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6913        match self {
6914            ActionMonitorType::Execution => write!(f, "EXECUTION"),
6915            ActionMonitorType::Security => write!(f, "SECURITY"),
6916            ActionMonitorType::Usage => write!(f, "USAGE"),
6917        }
6918    }
6919}
6920
6921/// The principal that receives the privileges
6922#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6923#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6924#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6925pub struct Grantee {
6926    pub grantee_type: GranteesType,
6927    pub name: Option<GranteeName>,
6928}
6929
6930impl fmt::Display for Grantee {
6931    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6932        match self.grantee_type {
6933            GranteesType::Role => {
6934                write!(f, "ROLE ")?;
6935            }
6936            GranteesType::Share => {
6937                write!(f, "SHARE ")?;
6938            }
6939            GranteesType::User => {
6940                write!(f, "USER ")?;
6941            }
6942            GranteesType::Group => {
6943                write!(f, "GROUP ")?;
6944            }
6945            GranteesType::Public => {
6946                write!(f, "PUBLIC ")?;
6947            }
6948            GranteesType::DatabaseRole => {
6949                write!(f, "DATABASE ROLE ")?;
6950            }
6951            GranteesType::Application => {
6952                write!(f, "APPLICATION ")?;
6953            }
6954            GranteesType::ApplicationRole => {
6955                write!(f, "APPLICATION ROLE ")?;
6956            }
6957            GranteesType::None => (),
6958        }
6959        if let Some(ref name) = self.name {
6960            name.fmt(f)?;
6961        }
6962        Ok(())
6963    }
6964}
6965
6966#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6967#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6968#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6969pub enum GranteesType {
6970    Role,
6971    Share,
6972    User,
6973    Group,
6974    Public,
6975    DatabaseRole,
6976    Application,
6977    ApplicationRole,
6978    None,
6979}
6980
6981/// Users/roles designated in a GRANT/REVOKE
6982#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6983#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6984#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6985pub enum GranteeName {
6986    /// A bare identifier
6987    ObjectName(ObjectName),
6988    /// A MySQL user/host pair such as 'root'@'%'
6989    UserHost { user: Ident, host: Ident },
6990}
6991
6992impl fmt::Display for GranteeName {
6993    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6994        match self {
6995            GranteeName::ObjectName(name) => name.fmt(f),
6996            GranteeName::UserHost { user, host } => {
6997                write!(f, "{user}@{host}")
6998            }
6999        }
7000    }
7001}
7002
7003/// Objects on which privileges are granted in a GRANT statement.
7004#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7005#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7006#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7007pub enum GrantObjects {
7008    /// Grant privileges on `ALL SEQUENCES IN SCHEMA <schema_name> [, ...]`
7009    AllSequencesInSchema { schemas: Vec<ObjectName> },
7010    /// Grant privileges on `ALL TABLES IN SCHEMA <schema_name> [, ...]`
7011    AllTablesInSchema { schemas: Vec<ObjectName> },
7012    /// Grant privileges on `ALL VIEWS IN SCHEMA <schema_name> [, ...]`
7013    AllViewsInSchema { schemas: Vec<ObjectName> },
7014    /// Grant privileges on `ALL MATERIALIZED VIEWS IN SCHEMA <schema_name> [, ...]`
7015    AllMaterializedViewsInSchema { schemas: Vec<ObjectName> },
7016    /// Grant privileges on `ALL EXTERNAL TABLES IN SCHEMA <schema_name> [, ...]`
7017    AllExternalTablesInSchema { schemas: Vec<ObjectName> },
7018    /// Grant privileges on `ALL FUNCTIONS IN SCHEMA <schema_name> [, ...]`
7019    AllFunctionsInSchema { schemas: Vec<ObjectName> },
7020    /// Grant privileges on `FUTURE SCHEMAS IN DATABASE <database_name> [, ...]`
7021    FutureSchemasInDatabase { databases: Vec<ObjectName> },
7022    /// Grant privileges on `FUTURE TABLES IN SCHEMA <schema_name> [, ...]`
7023    FutureTablesInSchema { schemas: Vec<ObjectName> },
7024    /// Grant privileges on `FUTURE VIEWS IN SCHEMA <schema_name> [, ...]`
7025    FutureViewsInSchema { schemas: Vec<ObjectName> },
7026    /// Grant privileges on `FUTURE EXTERNAL TABLES IN SCHEMA <schema_name> [, ...]`
7027    FutureExternalTablesInSchema { schemas: Vec<ObjectName> },
7028    /// Grant privileges on `FUTURE MATERIALIZED VIEWS IN SCHEMA <schema_name> [, ...]`
7029    FutureMaterializedViewsInSchema { schemas: Vec<ObjectName> },
7030    /// Grant privileges on `FUTURE SEQUENCES IN SCHEMA <schema_name> [, ...]`
7031    FutureSequencesInSchema { schemas: Vec<ObjectName> },
7032    /// Grant privileges on specific databases
7033    Databases(Vec<ObjectName>),
7034    /// Grant privileges on specific schemas
7035    Schemas(Vec<ObjectName>),
7036    /// Grant privileges on specific sequences
7037    Sequences(Vec<ObjectName>),
7038    /// Grant privileges on specific tables
7039    Tables(Vec<ObjectName>),
7040    /// Grant privileges on specific views
7041    Views(Vec<ObjectName>),
7042    /// Grant privileges on specific warehouses
7043    Warehouses(Vec<ObjectName>),
7044    /// Grant privileges on specific integrations
7045    Integrations(Vec<ObjectName>),
7046    /// Grant privileges on resource monitors
7047    ResourceMonitors(Vec<ObjectName>),
7048    /// Grant privileges on users
7049    Users(Vec<ObjectName>),
7050    /// Grant privileges on compute pools
7051    ComputePools(Vec<ObjectName>),
7052    /// Grant privileges on connections
7053    Connections(Vec<ObjectName>),
7054    /// Grant privileges on failover groups
7055    FailoverGroup(Vec<ObjectName>),
7056    /// Grant privileges on replication group
7057    ReplicationGroup(Vec<ObjectName>),
7058    /// Grant privileges on external volumes
7059    ExternalVolumes(Vec<ObjectName>),
7060    /// Grant privileges on a procedure. In dialects that
7061    /// support overloading, the argument types must be specified.
7062    ///
7063    /// For example:
7064    /// `GRANT USAGE ON PROCEDURE foo(varchar) TO ROLE role1`
7065    Procedure {
7066        name: ObjectName,
7067        arg_types: Vec<DataType>,
7068    },
7069
7070    /// Grant privileges on a function. In dialects that
7071    /// support overloading, the argument types must be specified.
7072    ///
7073    /// For example:
7074    /// `GRANT USAGE ON FUNCTION foo(varchar) TO ROLE role1`
7075    Function {
7076        name: ObjectName,
7077        arg_types: Vec<DataType>,
7078    },
7079}
7080
7081impl fmt::Display for GrantObjects {
7082    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7083        match self {
7084            GrantObjects::Sequences(sequences) => {
7085                write!(f, "SEQUENCE {}", display_comma_separated(sequences))
7086            }
7087            GrantObjects::Databases(databases) => {
7088                write!(f, "DATABASE {}", display_comma_separated(databases))
7089            }
7090            GrantObjects::Schemas(schemas) => {
7091                write!(f, "SCHEMA {}", display_comma_separated(schemas))
7092            }
7093            GrantObjects::Tables(tables) => {
7094                write!(f, "{}", display_comma_separated(tables))
7095            }
7096            GrantObjects::Views(views) => {
7097                write!(f, "VIEW {}", display_comma_separated(views))
7098            }
7099            GrantObjects::Warehouses(warehouses) => {
7100                write!(f, "WAREHOUSE {}", display_comma_separated(warehouses))
7101            }
7102            GrantObjects::Integrations(integrations) => {
7103                write!(f, "INTEGRATION {}", display_comma_separated(integrations))
7104            }
7105            GrantObjects::AllSequencesInSchema { schemas } => {
7106                write!(
7107                    f,
7108                    "ALL SEQUENCES IN SCHEMA {}",
7109                    display_comma_separated(schemas)
7110                )
7111            }
7112            GrantObjects::AllTablesInSchema { schemas } => {
7113                write!(
7114                    f,
7115                    "ALL TABLES IN SCHEMA {}",
7116                    display_comma_separated(schemas)
7117                )
7118            }
7119            GrantObjects::AllExternalTablesInSchema { schemas } => {
7120                write!(
7121                    f,
7122                    "ALL EXTERNAL TABLES IN SCHEMA {}",
7123                    display_comma_separated(schemas)
7124                )
7125            }
7126            GrantObjects::AllViewsInSchema { schemas } => {
7127                write!(
7128                    f,
7129                    "ALL VIEWS IN SCHEMA {}",
7130                    display_comma_separated(schemas)
7131                )
7132            }
7133            GrantObjects::AllMaterializedViewsInSchema { schemas } => {
7134                write!(
7135                    f,
7136                    "ALL MATERIALIZED VIEWS IN SCHEMA {}",
7137                    display_comma_separated(schemas)
7138                )
7139            }
7140            GrantObjects::AllFunctionsInSchema { schemas } => {
7141                write!(
7142                    f,
7143                    "ALL FUNCTIONS IN SCHEMA {}",
7144                    display_comma_separated(schemas)
7145                )
7146            }
7147            GrantObjects::FutureSchemasInDatabase { databases } => {
7148                write!(
7149                    f,
7150                    "FUTURE SCHEMAS IN DATABASE {}",
7151                    display_comma_separated(databases)
7152                )
7153            }
7154            GrantObjects::FutureTablesInSchema { schemas } => {
7155                write!(
7156                    f,
7157                    "FUTURE TABLES IN SCHEMA {}",
7158                    display_comma_separated(schemas)
7159                )
7160            }
7161            GrantObjects::FutureExternalTablesInSchema { schemas } => {
7162                write!(
7163                    f,
7164                    "FUTURE EXTERNAL TABLES IN SCHEMA {}",
7165                    display_comma_separated(schemas)
7166                )
7167            }
7168            GrantObjects::FutureViewsInSchema { schemas } => {
7169                write!(
7170                    f,
7171                    "FUTURE VIEWS IN SCHEMA {}",
7172                    display_comma_separated(schemas)
7173                )
7174            }
7175            GrantObjects::FutureMaterializedViewsInSchema { schemas } => {
7176                write!(
7177                    f,
7178                    "FUTURE MATERIALIZED VIEWS IN SCHEMA {}",
7179                    display_comma_separated(schemas)
7180                )
7181            }
7182            GrantObjects::FutureSequencesInSchema { schemas } => {
7183                write!(
7184                    f,
7185                    "FUTURE SEQUENCES IN SCHEMA {}",
7186                    display_comma_separated(schemas)
7187                )
7188            }
7189            GrantObjects::ResourceMonitors(objects) => {
7190                write!(f, "RESOURCE MONITOR {}", display_comma_separated(objects))
7191            }
7192            GrantObjects::Users(objects) => {
7193                write!(f, "USER {}", display_comma_separated(objects))
7194            }
7195            GrantObjects::ComputePools(objects) => {
7196                write!(f, "COMPUTE POOL {}", display_comma_separated(objects))
7197            }
7198            GrantObjects::Connections(objects) => {
7199                write!(f, "CONNECTION {}", display_comma_separated(objects))
7200            }
7201            GrantObjects::FailoverGroup(objects) => {
7202                write!(f, "FAILOVER GROUP {}", display_comma_separated(objects))
7203            }
7204            GrantObjects::ReplicationGroup(objects) => {
7205                write!(f, "REPLICATION GROUP {}", display_comma_separated(objects))
7206            }
7207            GrantObjects::ExternalVolumes(objects) => {
7208                write!(f, "EXTERNAL VOLUME {}", display_comma_separated(objects))
7209            }
7210            GrantObjects::Procedure { name, arg_types } => {
7211                write!(f, "PROCEDURE {name}")?;
7212                if !arg_types.is_empty() {
7213                    write!(f, "({})", display_comma_separated(arg_types))?;
7214                }
7215                Ok(())
7216            }
7217            GrantObjects::Function { name, arg_types } => {
7218                write!(f, "FUNCTION {name}")?;
7219                if !arg_types.is_empty() {
7220                    write!(f, "({})", display_comma_separated(arg_types))?;
7221                }
7222                Ok(())
7223            }
7224        }
7225    }
7226}
7227
7228/// A `DENY` statement
7229///
7230/// [MsSql](https://learn.microsoft.com/en-us/sql/t-sql/statements/deny-transact-sql)
7231#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7232#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7233#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7234pub struct DenyStatement {
7235    pub privileges: Privileges,
7236    pub objects: GrantObjects,
7237    pub grantees: Vec<Grantee>,
7238    pub granted_by: Option<Ident>,
7239    pub cascade: Option<CascadeOption>,
7240}
7241
7242impl fmt::Display for DenyStatement {
7243    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7244        write!(f, "DENY {}", self.privileges)?;
7245        write!(f, " ON {}", self.objects)?;
7246        if !self.grantees.is_empty() {
7247            write!(f, " TO {}", display_comma_separated(&self.grantees))?;
7248        }
7249        if let Some(cascade) = &self.cascade {
7250            write!(f, " {cascade}")?;
7251        }
7252        if let Some(granted_by) = &self.granted_by {
7253            write!(f, " AS {granted_by}")?;
7254        }
7255        Ok(())
7256    }
7257}
7258
7259/// SQL assignment `foo = expr` as used in SQLUpdate
7260#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7261#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7262#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7263pub struct Assignment {
7264    pub target: AssignmentTarget,
7265    pub value: Expr,
7266}
7267
7268impl fmt::Display for Assignment {
7269    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7270        write!(f, "{} = {}", self.target, self.value)
7271    }
7272}
7273
7274/// Left-hand side of an assignment in an UPDATE statement,
7275/// e.g. `foo` in `foo = 5` (ColumnName assignment) or
7276/// `(a, b)` in `(a, b) = (1, 2)` (Tuple assignment).
7277#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7278#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7279#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7280pub enum AssignmentTarget {
7281    /// A single column
7282    ColumnName(ObjectName),
7283    /// A tuple of columns
7284    Tuple(Vec<ObjectName>),
7285}
7286
7287impl fmt::Display for AssignmentTarget {
7288    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7289        match self {
7290            AssignmentTarget::ColumnName(column) => write!(f, "{column}"),
7291            AssignmentTarget::Tuple(columns) => write!(f, "({})", display_comma_separated(columns)),
7292        }
7293    }
7294}
7295
7296#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7297#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7298#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7299pub enum FunctionArgExpr {
7300    Expr(Expr),
7301    /// Qualified wildcard, e.g. `alias.*` or `schema.table.*`.
7302    QualifiedWildcard(ObjectName),
7303    /// An unqualified `*`
7304    Wildcard,
7305}
7306
7307impl From<Expr> for FunctionArgExpr {
7308    fn from(wildcard_expr: Expr) -> Self {
7309        match wildcard_expr {
7310            Expr::QualifiedWildcard(prefix, _) => Self::QualifiedWildcard(prefix),
7311            Expr::Wildcard(_) => Self::Wildcard,
7312            expr => Self::Expr(expr),
7313        }
7314    }
7315}
7316
7317impl fmt::Display for FunctionArgExpr {
7318    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7319        match self {
7320            FunctionArgExpr::Expr(expr) => write!(f, "{expr}"),
7321            FunctionArgExpr::QualifiedWildcard(prefix) => write!(f, "{prefix}.*"),
7322            FunctionArgExpr::Wildcard => f.write_str("*"),
7323        }
7324    }
7325}
7326
7327#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7328#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7329#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7330/// Operator used to separate function arguments
7331pub enum FunctionArgOperator {
7332    /// function(arg1 = value1)
7333    Equals,
7334    /// function(arg1 => value1)
7335    RightArrow,
7336    /// function(arg1 := value1)
7337    Assignment,
7338    /// function(arg1 : value1)
7339    Colon,
7340    /// function(arg1 VALUE value1)
7341    Value,
7342}
7343
7344impl fmt::Display for FunctionArgOperator {
7345    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7346        match self {
7347            FunctionArgOperator::Equals => f.write_str("="),
7348            FunctionArgOperator::RightArrow => f.write_str("=>"),
7349            FunctionArgOperator::Assignment => f.write_str(":="),
7350            FunctionArgOperator::Colon => f.write_str(":"),
7351            FunctionArgOperator::Value => f.write_str("VALUE"),
7352        }
7353    }
7354}
7355
7356#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7357#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7358#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7359pub enum FunctionArg {
7360    /// `name` is identifier
7361    ///
7362    /// Enabled when `Dialect::supports_named_fn_args_with_expr_name` returns 'false'
7363    Named {
7364        name: Ident,
7365        arg: FunctionArgExpr,
7366        operator: FunctionArgOperator,
7367    },
7368    /// `name` is arbitrary expression
7369    ///
7370    /// Enabled when `Dialect::supports_named_fn_args_with_expr_name` returns 'true'
7371    ExprNamed {
7372        name: Expr,
7373        arg: FunctionArgExpr,
7374        operator: FunctionArgOperator,
7375    },
7376    Unnamed(FunctionArgExpr),
7377}
7378
7379impl fmt::Display for FunctionArg {
7380    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7381        match self {
7382            FunctionArg::Named {
7383                name,
7384                arg,
7385                operator,
7386            } => write!(f, "{name} {operator} {arg}"),
7387            FunctionArg::ExprNamed {
7388                name,
7389                arg,
7390                operator,
7391            } => write!(f, "{name} {operator} {arg}"),
7392            FunctionArg::Unnamed(unnamed_arg) => write!(f, "{unnamed_arg}"),
7393        }
7394    }
7395}
7396
7397#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7398#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7399#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7400pub enum CloseCursor {
7401    All,
7402    Specific { name: Ident },
7403}
7404
7405impl fmt::Display for CloseCursor {
7406    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7407        match self {
7408            CloseCursor::All => write!(f, "ALL"),
7409            CloseCursor::Specific { name } => write!(f, "{name}"),
7410        }
7411    }
7412}
7413
7414/// A Drop Domain statement
7415#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7416#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7417#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7418pub struct DropDomain {
7419    /// Whether to drop the domain if it exists
7420    pub if_exists: bool,
7421    /// The name of the domain to drop
7422    pub name: ObjectName,
7423    /// The behavior to apply when dropping the domain
7424    pub drop_behavior: Option<DropBehavior>,
7425}
7426
7427/// A constant of form `<data_type> 'value'`.
7428/// This can represent ANSI SQL `DATE`, `TIME`, and `TIMESTAMP` literals (such as `DATE '2020-01-01'`),
7429/// as well as constants of other types (a non-standard PostgreSQL extension).
7430#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7431#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7432#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7433pub struct TypedString {
7434    pub data_type: DataType,
7435    /// The value of the constant.
7436    /// Hint: you can unwrap the string value using `value.into_string()`.
7437    pub value: ValueWithSpan,
7438    /// Flags whether this TypedString uses the [ODBC syntax].
7439    ///
7440    /// Example:
7441    /// ```sql
7442    /// -- An ODBC date literal:
7443    /// SELECT {d '2025-07-16'}
7444    /// -- This is equivalent to the standard ANSI SQL literal:
7445    /// SELECT DATE '2025-07-16'
7446    ///
7447    /// [ODBC syntax]: https://learn.microsoft.com/en-us/sql/odbc/reference/develop-app/date-time-and-timestamp-literals?view=sql-server-2017
7448    pub uses_odbc_syntax: bool,
7449}
7450
7451impl fmt::Display for TypedString {
7452    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7453        let data_type = &self.data_type;
7454        let value = &self.value;
7455        match self.uses_odbc_syntax {
7456            false => {
7457                write!(f, "{data_type}")?;
7458                write!(f, " {value}")
7459            }
7460            true => {
7461                let prefix = match data_type {
7462                    DataType::Date => "d",
7463                    DataType::Time(..) => "t",
7464                    DataType::Timestamp(..) => "ts",
7465                    _ => "?",
7466                };
7467                write!(f, "{{{prefix} {value}}}")
7468            }
7469        }
7470    }
7471}
7472
7473/// A function call
7474#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7475#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7476#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7477pub struct Function {
7478    pub name: ObjectName,
7479    /// Flags whether this function call uses the [ODBC syntax].
7480    ///
7481    /// Example:
7482    /// ```sql
7483    /// SELECT {fn CONCAT('foo', 'bar')}
7484    /// ```
7485    ///
7486    /// [ODBC syntax]: https://learn.microsoft.com/en-us/sql/odbc/reference/develop-app/scalar-function-calls?view=sql-server-2017
7487    pub uses_odbc_syntax: bool,
7488    /// The parameters to the function, including any options specified within the
7489    /// delimiting parentheses.
7490    ///
7491    /// Example:
7492    /// ```plaintext
7493    /// HISTOGRAM(0.5, 0.6)(x, y)
7494    /// ```
7495    ///
7496    /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/aggregate-functions/parametric-functions)
7497    pub parameters: FunctionArguments,
7498    /// The arguments to the function, including any options specified within the
7499    /// delimiting parentheses.
7500    pub args: FunctionArguments,
7501    /// e.g. `x > 5` in `COUNT(x) FILTER (WHERE x > 5)`
7502    pub filter: Option<Box<Expr>>,
7503    /// Indicates how `NULL`s should be handled in the calculation.
7504    ///
7505    /// Example:
7506    /// ```plaintext
7507    /// FIRST_VALUE( <expr> ) [ { IGNORE | RESPECT } NULLS ] OVER ...
7508    /// ```
7509    ///
7510    /// [Snowflake](https://docs.snowflake.com/en/sql-reference/functions/first_value)
7511    pub null_treatment: Option<NullTreatment>,
7512    /// The `OVER` clause, indicating a window function call.
7513    pub over: Option<WindowType>,
7514    /// A clause used with certain aggregate functions to control the ordering
7515    /// within grouped sets before the function is applied.
7516    ///
7517    /// Syntax:
7518    /// ```plaintext
7519    /// <aggregate_function>(expression) WITHIN GROUP (ORDER BY key [ASC | DESC], ...)
7520    /// ```
7521    pub within_group: Vec<OrderByExpr>,
7522}
7523
7524impl fmt::Display for Function {
7525    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7526        if self.uses_odbc_syntax {
7527            write!(f, "{{fn ")?;
7528        }
7529
7530        write!(f, "{}{}{}", self.name, self.parameters, self.args)?;
7531
7532        if !self.within_group.is_empty() {
7533            write!(
7534                f,
7535                " WITHIN GROUP (ORDER BY {})",
7536                display_comma_separated(&self.within_group)
7537            )?;
7538        }
7539
7540        if let Some(filter_cond) = &self.filter {
7541            write!(f, " FILTER (WHERE {filter_cond})")?;
7542        }
7543
7544        if let Some(null_treatment) = &self.null_treatment {
7545            write!(f, " {null_treatment}")?;
7546        }
7547
7548        if let Some(o) = &self.over {
7549            f.write_str(" OVER ")?;
7550            o.fmt(f)?;
7551        }
7552
7553        if self.uses_odbc_syntax {
7554            write!(f, "}}")?;
7555        }
7556
7557        Ok(())
7558    }
7559}
7560
7561/// The arguments passed to a function call.
7562#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7563#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7564#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7565pub enum FunctionArguments {
7566    /// Used for special functions like `CURRENT_TIMESTAMP` that are invoked
7567    /// without parentheses.
7568    None,
7569    /// On some dialects, a subquery can be passed without surrounding
7570    /// parentheses if it's the sole argument to the function.
7571    Subquery(Box<Query>),
7572    /// A normal function argument list, including any clauses within it such as
7573    /// `DISTINCT` or `ORDER BY`.
7574    List(FunctionArgumentList),
7575}
7576
7577impl fmt::Display for FunctionArguments {
7578    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
7579        match self {
7580            FunctionArguments::None => Ok(()),
7581            FunctionArguments::Subquery(query) => write!(f, "({query})"),
7582            FunctionArguments::List(args) => write!(f, "({args})"),
7583        }
7584    }
7585}
7586
7587/// This represents everything inside the parentheses when calling a function.
7588#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7589#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7590#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7591pub struct FunctionArgumentList {
7592    /// `[ ALL | DISTINCT ]`
7593    pub duplicate_treatment: Option<DuplicateTreatment>,
7594    /// The function arguments.
7595    pub args: Vec<FunctionArg>,
7596    /// Additional clauses specified within the argument list.
7597    pub clauses: Vec<FunctionArgumentClause>,
7598}
7599
7600impl fmt::Display for FunctionArgumentList {
7601    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7602        if let Some(duplicate_treatment) = self.duplicate_treatment {
7603            write!(f, "{duplicate_treatment} ")?;
7604        }
7605        write!(f, "{}", display_comma_separated(&self.args))?;
7606        if !self.clauses.is_empty() {
7607            if !self.args.is_empty() {
7608                write!(f, " ")?;
7609            }
7610            write!(f, "{}", display_separated(&self.clauses, " "))?;
7611        }
7612        Ok(())
7613    }
7614}
7615
7616#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7617#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7618#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7619pub enum FunctionArgumentClause {
7620    /// Indicates how `NULL`s should be handled in the calculation, e.g. in `FIRST_VALUE` on [BigQuery].
7621    ///
7622    /// Syntax:
7623    /// ```plaintext
7624    /// { IGNORE | RESPECT } NULLS ]
7625    /// ```
7626    ///
7627    /// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/navigation_functions#first_value
7628    IgnoreOrRespectNulls(NullTreatment),
7629    /// Specifies the the ordering for some ordered set aggregates, e.g. `ARRAY_AGG` on [BigQuery].
7630    ///
7631    /// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/aggregate_functions#array_agg
7632    OrderBy(Vec<OrderByExpr>),
7633    /// Specifies a limit for the `ARRAY_AGG` and `ARRAY_CONCAT_AGG` functions on BigQuery.
7634    Limit(Expr),
7635    /// Specifies the behavior on overflow of the `LISTAGG` function.
7636    ///
7637    /// See <https://trino.io/docs/current/functions/aggregate.html>.
7638    OnOverflow(ListAggOnOverflow),
7639    /// Specifies a minimum or maximum bound on the input to [`ANY_VALUE`] on BigQuery.
7640    ///
7641    /// Syntax:
7642    /// ```plaintext
7643    /// HAVING { MAX | MIN } expression
7644    /// ```
7645    ///
7646    /// [`ANY_VALUE`]: https://cloud.google.com/bigquery/docs/reference/standard-sql/aggregate_functions#any_value
7647    Having(HavingBound),
7648    /// The `SEPARATOR` clause to the [`GROUP_CONCAT`] function in MySQL.
7649    ///
7650    /// [`GROUP_CONCAT`]: https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html#function_group-concat
7651    Separator(Value),
7652    /// The `ON NULL` clause for some JSON functions.
7653    ///
7654    /// [MSSQL `JSON_ARRAY`](https://learn.microsoft.com/en-us/sql/t-sql/functions/json-array-transact-sql?view=sql-server-ver16)
7655    /// [MSSQL `JSON_OBJECT`](https://learn.microsoft.com/en-us/sql/t-sql/functions/json-object-transact-sql?view=sql-server-ver16>)
7656    /// [PostgreSQL JSON functions](https://www.postgresql.org/docs/current/functions-json.html#FUNCTIONS-JSON-PROCESSING)
7657    JsonNullClause(JsonNullClause),
7658    /// The `RETURNING` clause for some JSON functions in PostgreSQL
7659    ///
7660    /// [`JSON_OBJECT`](https://www.postgresql.org/docs/current/functions-json.html#:~:text=json_object)
7661    JsonReturningClause(JsonReturningClause),
7662}
7663
7664impl fmt::Display for FunctionArgumentClause {
7665    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
7666        match self {
7667            FunctionArgumentClause::IgnoreOrRespectNulls(null_treatment) => {
7668                write!(f, "{null_treatment}")
7669            }
7670            FunctionArgumentClause::OrderBy(order_by) => {
7671                write!(f, "ORDER BY {}", display_comma_separated(order_by))
7672            }
7673            FunctionArgumentClause::Limit(limit) => write!(f, "LIMIT {limit}"),
7674            FunctionArgumentClause::OnOverflow(on_overflow) => write!(f, "{on_overflow}"),
7675            FunctionArgumentClause::Having(bound) => write!(f, "{bound}"),
7676            FunctionArgumentClause::Separator(sep) => write!(f, "SEPARATOR {sep}"),
7677            FunctionArgumentClause::JsonNullClause(null_clause) => write!(f, "{null_clause}"),
7678            FunctionArgumentClause::JsonReturningClause(returning_clause) => {
7679                write!(f, "{returning_clause}")
7680            }
7681        }
7682    }
7683}
7684
7685/// A method call
7686#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7687#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7688#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7689pub struct Method {
7690    pub expr: Box<Expr>,
7691    // always non-empty
7692    pub method_chain: Vec<Function>,
7693}
7694
7695impl fmt::Display for Method {
7696    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7697        write!(
7698            f,
7699            "{}.{}",
7700            self.expr,
7701            display_separated(&self.method_chain, ".")
7702        )
7703    }
7704}
7705
7706#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7707#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7708#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7709pub enum DuplicateTreatment {
7710    /// Perform the calculation only unique values.
7711    Distinct,
7712    /// Retain all duplicate values (the default).
7713    All,
7714}
7715
7716impl fmt::Display for DuplicateTreatment {
7717    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
7718        match self {
7719            DuplicateTreatment::Distinct => write!(f, "DISTINCT"),
7720            DuplicateTreatment::All => write!(f, "ALL"),
7721        }
7722    }
7723}
7724
7725#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7726#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7727#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7728pub enum AnalyzeFormatKind {
7729    /// e.g. `EXPLAIN ANALYZE FORMAT JSON SELECT * FROM tbl`
7730    Keyword(AnalyzeFormat),
7731    /// e.g. `EXPLAIN ANALYZE FORMAT=JSON SELECT * FROM tbl`
7732    Assignment(AnalyzeFormat),
7733}
7734
7735impl fmt::Display for AnalyzeFormatKind {
7736    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
7737        match self {
7738            AnalyzeFormatKind::Keyword(format) => write!(f, "FORMAT {format}"),
7739            AnalyzeFormatKind::Assignment(format) => write!(f, "FORMAT={format}"),
7740        }
7741    }
7742}
7743
7744#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7745#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7746#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7747pub enum AnalyzeFormat {
7748    TEXT,
7749    GRAPHVIZ,
7750    JSON,
7751    TRADITIONAL,
7752    TREE,
7753}
7754
7755impl fmt::Display for AnalyzeFormat {
7756    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
7757        f.write_str(match self {
7758            AnalyzeFormat::TEXT => "TEXT",
7759            AnalyzeFormat::GRAPHVIZ => "GRAPHVIZ",
7760            AnalyzeFormat::JSON => "JSON",
7761            AnalyzeFormat::TRADITIONAL => "TRADITIONAL",
7762            AnalyzeFormat::TREE => "TREE",
7763        })
7764    }
7765}
7766
7767/// External table's available file format
7768#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7769#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7770#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7771pub enum FileFormat {
7772    TEXTFILE,
7773    SEQUENCEFILE,
7774    ORC,
7775    PARQUET,
7776    AVRO,
7777    RCFILE,
7778    JSONFILE,
7779}
7780
7781impl fmt::Display for FileFormat {
7782    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7783        use self::FileFormat::*;
7784        f.write_str(match self {
7785            TEXTFILE => "TEXTFILE",
7786            SEQUENCEFILE => "SEQUENCEFILE",
7787            ORC => "ORC",
7788            PARQUET => "PARQUET",
7789            AVRO => "AVRO",
7790            RCFILE => "RCFILE",
7791            JSONFILE => "JSONFILE",
7792        })
7793    }
7794}
7795
7796/// The `ON OVERFLOW` clause of a LISTAGG invocation
7797#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7798#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7799#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7800pub enum ListAggOnOverflow {
7801    /// `ON OVERFLOW ERROR`
7802    Error,
7803
7804    /// `ON OVERFLOW TRUNCATE [ <filler> ] WITH[OUT] COUNT`
7805    Truncate {
7806        filler: Option<Box<Expr>>,
7807        with_count: bool,
7808    },
7809}
7810
7811impl fmt::Display for ListAggOnOverflow {
7812    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7813        write!(f, "ON OVERFLOW")?;
7814        match self {
7815            ListAggOnOverflow::Error => write!(f, " ERROR"),
7816            ListAggOnOverflow::Truncate { filler, with_count } => {
7817                write!(f, " TRUNCATE")?;
7818                if let Some(filler) = filler {
7819                    write!(f, " {filler}")?;
7820                }
7821                if *with_count {
7822                    write!(f, " WITH")?;
7823                } else {
7824                    write!(f, " WITHOUT")?;
7825                }
7826                write!(f, " COUNT")
7827            }
7828        }
7829    }
7830}
7831
7832/// The `HAVING` clause in a call to `ANY_VALUE` on BigQuery.
7833#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7834#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7835#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7836pub struct HavingBound(pub HavingBoundKind, pub Expr);
7837
7838impl fmt::Display for HavingBound {
7839    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
7840        write!(f, "HAVING {} {}", self.0, self.1)
7841    }
7842}
7843
7844#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7845#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7846#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7847pub enum HavingBoundKind {
7848    Min,
7849    Max,
7850}
7851
7852impl fmt::Display for HavingBoundKind {
7853    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
7854        match self {
7855            HavingBoundKind::Min => write!(f, "MIN"),
7856            HavingBoundKind::Max => write!(f, "MAX"),
7857        }
7858    }
7859}
7860
7861#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7862#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7863#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7864pub enum ObjectType {
7865    Table,
7866    View,
7867    MaterializedView,
7868    Index,
7869    Schema,
7870    Database,
7871    Role,
7872    Sequence,
7873    Stage,
7874    Type,
7875    User,
7876    Stream,
7877}
7878
7879impl fmt::Display for ObjectType {
7880    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7881        f.write_str(match self {
7882            ObjectType::Table => "TABLE",
7883            ObjectType::View => "VIEW",
7884            ObjectType::MaterializedView => "MATERIALIZED VIEW",
7885            ObjectType::Index => "INDEX",
7886            ObjectType::Schema => "SCHEMA",
7887            ObjectType::Database => "DATABASE",
7888            ObjectType::Role => "ROLE",
7889            ObjectType::Sequence => "SEQUENCE",
7890            ObjectType::Stage => "STAGE",
7891            ObjectType::Type => "TYPE",
7892            ObjectType::User => "USER",
7893            ObjectType::Stream => "STREAM",
7894        })
7895    }
7896}
7897
7898#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7899#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7900#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7901pub enum KillType {
7902    Connection,
7903    Query,
7904    Mutation,
7905}
7906
7907impl fmt::Display for KillType {
7908    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7909        f.write_str(match self {
7910            // MySQL
7911            KillType::Connection => "CONNECTION",
7912            KillType::Query => "QUERY",
7913            // Clickhouse supports Mutation
7914            KillType::Mutation => "MUTATION",
7915        })
7916    }
7917}
7918
7919#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7920#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7921#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7922pub enum HiveDistributionStyle {
7923    PARTITIONED {
7924        columns: Vec<ColumnDef>,
7925    },
7926    SKEWED {
7927        columns: Vec<ColumnDef>,
7928        on: Vec<ColumnDef>,
7929        stored_as_directories: bool,
7930    },
7931    NONE,
7932}
7933
7934#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7935#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7936#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7937pub enum HiveRowFormat {
7938    SERDE { class: String },
7939    DELIMITED { delimiters: Vec<HiveRowDelimiter> },
7940}
7941
7942#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7943#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7944#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7945pub struct HiveLoadDataFormat {
7946    pub serde: Expr,
7947    pub input_format: Expr,
7948}
7949
7950#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7951#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7952#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7953pub struct HiveRowDelimiter {
7954    pub delimiter: HiveDelimiter,
7955    pub char: Ident,
7956}
7957
7958impl fmt::Display for HiveRowDelimiter {
7959    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
7960        write!(f, "{} ", self.delimiter)?;
7961        write!(f, "{}", self.char)
7962    }
7963}
7964
7965#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7966#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7967#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7968pub enum HiveDelimiter {
7969    FieldsTerminatedBy,
7970    FieldsEscapedBy,
7971    CollectionItemsTerminatedBy,
7972    MapKeysTerminatedBy,
7973    LinesTerminatedBy,
7974    NullDefinedAs,
7975}
7976
7977impl fmt::Display for HiveDelimiter {
7978    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
7979        use HiveDelimiter::*;
7980        f.write_str(match self {
7981            FieldsTerminatedBy => "FIELDS TERMINATED BY",
7982            FieldsEscapedBy => "ESCAPED BY",
7983            CollectionItemsTerminatedBy => "COLLECTION ITEMS TERMINATED BY",
7984            MapKeysTerminatedBy => "MAP KEYS TERMINATED BY",
7985            LinesTerminatedBy => "LINES TERMINATED BY",
7986            NullDefinedAs => "NULL DEFINED AS",
7987        })
7988    }
7989}
7990
7991#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7992#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7993#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7994pub enum HiveDescribeFormat {
7995    Extended,
7996    Formatted,
7997}
7998
7999impl fmt::Display for HiveDescribeFormat {
8000    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8001        use HiveDescribeFormat::*;
8002        f.write_str(match self {
8003            Extended => "EXTENDED",
8004            Formatted => "FORMATTED",
8005        })
8006    }
8007}
8008
8009#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8010#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8011#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8012pub enum DescribeAlias {
8013    Describe,
8014    Explain,
8015    Desc,
8016}
8017
8018impl fmt::Display for DescribeAlias {
8019    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8020        use DescribeAlias::*;
8021        f.write_str(match self {
8022            Describe => "DESCRIBE",
8023            Explain => "EXPLAIN",
8024            Desc => "DESC",
8025        })
8026    }
8027}
8028
8029#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8030#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8031#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8032#[allow(clippy::large_enum_variant)]
8033pub enum HiveIOFormat {
8034    IOF {
8035        input_format: Expr,
8036        output_format: Expr,
8037    },
8038    FileFormat {
8039        format: FileFormat,
8040    },
8041}
8042
8043#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Default)]
8044#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8045#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8046pub struct HiveFormat {
8047    pub row_format: Option<HiveRowFormat>,
8048    pub serde_properties: Option<Vec<SqlOption>>,
8049    pub storage: Option<HiveIOFormat>,
8050    pub location: Option<String>,
8051}
8052
8053#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8054#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8055#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8056pub struct ClusteredIndex {
8057    pub name: Ident,
8058    pub asc: Option<bool>,
8059}
8060
8061impl fmt::Display for ClusteredIndex {
8062    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8063        write!(f, "{}", self.name)?;
8064        match self.asc {
8065            Some(true) => write!(f, " ASC"),
8066            Some(false) => write!(f, " DESC"),
8067            _ => Ok(()),
8068        }
8069    }
8070}
8071
8072#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8073#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8074#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8075pub enum TableOptionsClustered {
8076    ColumnstoreIndex,
8077    ColumnstoreIndexOrder(Vec<Ident>),
8078    Index(Vec<ClusteredIndex>),
8079}
8080
8081impl fmt::Display for TableOptionsClustered {
8082    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8083        match self {
8084            TableOptionsClustered::ColumnstoreIndex => {
8085                write!(f, "CLUSTERED COLUMNSTORE INDEX")
8086            }
8087            TableOptionsClustered::ColumnstoreIndexOrder(values) => {
8088                write!(
8089                    f,
8090                    "CLUSTERED COLUMNSTORE INDEX ORDER ({})",
8091                    display_comma_separated(values)
8092                )
8093            }
8094            TableOptionsClustered::Index(values) => {
8095                write!(f, "CLUSTERED INDEX ({})", display_comma_separated(values))
8096            }
8097        }
8098    }
8099}
8100
8101/// Specifies which partition the boundary values on table partitioning belongs to.
8102#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8103#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8104#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8105pub enum PartitionRangeDirection {
8106    Left,
8107    Right,
8108}
8109
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 SqlOption {
8114    /// Clustered represents the clustered version of table storage for MSSQL.
8115    ///
8116    /// <https://learn.microsoft.com/en-us/sql/t-sql/statements/create-table-azure-sql-data-warehouse?view=aps-pdw-2016-au7#TableOptions>
8117    Clustered(TableOptionsClustered),
8118    /// Single identifier options, e.g. `HEAP` for MSSQL.
8119    ///
8120    /// <https://learn.microsoft.com/en-us/sql/t-sql/statements/create-table-azure-sql-data-warehouse?view=aps-pdw-2016-au7#TableOptions>
8121    Ident(Ident),
8122    /// Any option that consists of a key value pair where the value is an expression. e.g.
8123    ///
8124    ///   WITH(DISTRIBUTION = ROUND_ROBIN)
8125    KeyValue { key: Ident, value: Expr },
8126    /// One or more table partitions and represents which partition the boundary values belong to,
8127    /// e.g.
8128    ///
8129    ///   PARTITION (id RANGE LEFT FOR VALUES (10, 20, 30, 40))
8130    ///
8131    /// <https://learn.microsoft.com/en-us/sql/t-sql/statements/create-table-azure-sql-data-warehouse?view=aps-pdw-2016-au7#TablePartitionOptions>
8132    Partition {
8133        column_name: Ident,
8134        range_direction: Option<PartitionRangeDirection>,
8135        for_values: Vec<Expr>,
8136    },
8137    /// Comment parameter (supports `=` and no `=` syntax)
8138    Comment(CommentDef),
8139    /// MySQL TableSpace option
8140    /// <https://dev.mysql.com/doc/refman/8.4/en/create-table.html>
8141    TableSpace(TablespaceOption),
8142    /// An option representing a key value pair, where the value is a parenthesized list and with an optional name
8143    /// e.g.
8144    ///
8145    ///   UNION  = (tbl_name\[,tbl_name\]...) <https://dev.mysql.com/doc/refman/8.4/en/create-table.html>
8146    ///   ENGINE = ReplicatedMergeTree('/table_name','{replica}', ver) <https://clickhouse.com/docs/engines/table-engines/mergetree-family/replication>
8147    ///   ENGINE = SummingMergeTree(\[columns\]) <https://clickhouse.com/docs/engines/table-engines/mergetree-family/summingmergetree>
8148    NamedParenthesizedList(NamedParenthesizedList),
8149}
8150
8151impl fmt::Display for SqlOption {
8152    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8153        match self {
8154            SqlOption::Clustered(c) => write!(f, "{c}"),
8155            SqlOption::Ident(ident) => {
8156                write!(f, "{ident}")
8157            }
8158            SqlOption::KeyValue { key: name, value } => {
8159                write!(f, "{name} = {value}")
8160            }
8161            SqlOption::Partition {
8162                column_name,
8163                range_direction,
8164                for_values,
8165            } => {
8166                let direction = match range_direction {
8167                    Some(PartitionRangeDirection::Left) => " LEFT",
8168                    Some(PartitionRangeDirection::Right) => " RIGHT",
8169                    None => "",
8170                };
8171
8172                write!(
8173                    f,
8174                    "PARTITION ({} RANGE{} FOR VALUES ({}))",
8175                    column_name,
8176                    direction,
8177                    display_comma_separated(for_values)
8178                )
8179            }
8180            SqlOption::TableSpace(tablespace_option) => {
8181                write!(f, "TABLESPACE {}", tablespace_option.name)?;
8182                match tablespace_option.storage {
8183                    Some(StorageType::Disk) => write!(f, " STORAGE DISK"),
8184                    Some(StorageType::Memory) => write!(f, " STORAGE MEMORY"),
8185                    None => Ok(()),
8186                }
8187            }
8188            SqlOption::Comment(comment) => match comment {
8189                CommentDef::WithEq(comment) => {
8190                    write!(f, "COMMENT = '{comment}'")
8191                }
8192                CommentDef::WithoutEq(comment) => {
8193                    write!(f, "COMMENT '{comment}'")
8194                }
8195            },
8196            SqlOption::NamedParenthesizedList(value) => {
8197                write!(f, "{} = ", value.key)?;
8198                if let Some(key) = &value.name {
8199                    write!(f, "{key}")?;
8200                }
8201                if !value.values.is_empty() {
8202                    write!(f, "({})", display_comma_separated(&value.values))?
8203                }
8204                Ok(())
8205            }
8206        }
8207    }
8208}
8209
8210#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
8211#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8212#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8213pub enum StorageType {
8214    Disk,
8215    Memory,
8216}
8217
8218#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
8219#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8220#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8221/// MySql TableSpace option
8222/// <https://dev.mysql.com/doc/refman/8.4/en/create-table.html>
8223pub struct TablespaceOption {
8224    pub name: String,
8225    pub storage: Option<StorageType>,
8226}
8227
8228#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8229#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8230#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8231pub struct SecretOption {
8232    pub key: Ident,
8233    pub value: Ident,
8234}
8235
8236impl fmt::Display for SecretOption {
8237    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8238        write!(f, "{} {}", self.key, self.value)
8239    }
8240}
8241
8242/// A `CREATE SERVER` statement.
8243///
8244/// [PostgreSQL Documentation](https://www.postgresql.org/docs/current/sql-createserver.html)
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))]
8248pub struct CreateServerStatement {
8249    pub name: ObjectName,
8250    pub if_not_exists: bool,
8251    pub server_type: Option<Ident>,
8252    pub version: Option<Ident>,
8253    pub foreign_data_wrapper: ObjectName,
8254    pub options: Option<Vec<CreateServerOption>>,
8255}
8256
8257impl fmt::Display for CreateServerStatement {
8258    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8259        let CreateServerStatement {
8260            name,
8261            if_not_exists,
8262            server_type,
8263            version,
8264            foreign_data_wrapper,
8265            options,
8266        } = self;
8267
8268        write!(
8269            f,
8270            "CREATE SERVER {if_not_exists}{name} ",
8271            if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
8272        )?;
8273
8274        if let Some(st) = server_type {
8275            write!(f, "TYPE {st} ")?;
8276        }
8277
8278        if let Some(v) = version {
8279            write!(f, "VERSION {v} ")?;
8280        }
8281
8282        write!(f, "FOREIGN DATA WRAPPER {foreign_data_wrapper}")?;
8283
8284        if let Some(o) = options {
8285            write!(f, " OPTIONS ({o})", o = display_comma_separated(o))?;
8286        }
8287
8288        Ok(())
8289    }
8290}
8291
8292#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8293#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8294#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8295pub struct CreateServerOption {
8296    pub key: Ident,
8297    pub value: Ident,
8298}
8299
8300impl fmt::Display for CreateServerOption {
8301    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8302        write!(f, "{} {}", self.key, self.value)
8303    }
8304}
8305
8306#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8307#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8308#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8309pub enum AttachDuckDBDatabaseOption {
8310    ReadOnly(Option<bool>),
8311    Type(Ident),
8312}
8313
8314impl fmt::Display for AttachDuckDBDatabaseOption {
8315    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8316        match self {
8317            AttachDuckDBDatabaseOption::ReadOnly(Some(true)) => write!(f, "READ_ONLY true"),
8318            AttachDuckDBDatabaseOption::ReadOnly(Some(false)) => write!(f, "READ_ONLY false"),
8319            AttachDuckDBDatabaseOption::ReadOnly(None) => write!(f, "READ_ONLY"),
8320            AttachDuckDBDatabaseOption::Type(t) => write!(f, "TYPE {t}"),
8321        }
8322    }
8323}
8324
8325#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8326#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8327#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8328pub enum TransactionMode {
8329    AccessMode(TransactionAccessMode),
8330    IsolationLevel(TransactionIsolationLevel),
8331}
8332
8333impl fmt::Display for TransactionMode {
8334    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8335        use TransactionMode::*;
8336        match self {
8337            AccessMode(access_mode) => write!(f, "{access_mode}"),
8338            IsolationLevel(iso_level) => write!(f, "ISOLATION LEVEL {iso_level}"),
8339        }
8340    }
8341}
8342
8343#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8344#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8345#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8346pub enum TransactionAccessMode {
8347    ReadOnly,
8348    ReadWrite,
8349}
8350
8351impl fmt::Display for TransactionAccessMode {
8352    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8353        use TransactionAccessMode::*;
8354        f.write_str(match self {
8355            ReadOnly => "READ ONLY",
8356            ReadWrite => "READ WRITE",
8357        })
8358    }
8359}
8360
8361#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8362#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8363#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8364pub enum TransactionIsolationLevel {
8365    ReadUncommitted,
8366    ReadCommitted,
8367    RepeatableRead,
8368    Serializable,
8369    Snapshot,
8370}
8371
8372impl fmt::Display for TransactionIsolationLevel {
8373    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8374        use TransactionIsolationLevel::*;
8375        f.write_str(match self {
8376            ReadUncommitted => "READ UNCOMMITTED",
8377            ReadCommitted => "READ COMMITTED",
8378            RepeatableRead => "REPEATABLE READ",
8379            Serializable => "SERIALIZABLE",
8380            Snapshot => "SNAPSHOT",
8381        })
8382    }
8383}
8384
8385/// Modifier for the transaction in the `BEGIN` syntax
8386///
8387/// SQLite: <https://sqlite.org/lang_transaction.html>
8388/// MS-SQL: <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/try-catch-transact-sql>
8389#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8390#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8391#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8392pub enum TransactionModifier {
8393    Deferred,
8394    Immediate,
8395    Exclusive,
8396    Try,
8397    Catch,
8398}
8399
8400impl fmt::Display for TransactionModifier {
8401    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8402        use TransactionModifier::*;
8403        f.write_str(match self {
8404            Deferred => "DEFERRED",
8405            Immediate => "IMMEDIATE",
8406            Exclusive => "EXCLUSIVE",
8407            Try => "TRY",
8408            Catch => "CATCH",
8409        })
8410    }
8411}
8412
8413#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8414#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8415#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8416pub enum ShowStatementFilter {
8417    Like(String),
8418    ILike(String),
8419    Where(Expr),
8420    NoKeyword(String),
8421}
8422
8423impl fmt::Display for ShowStatementFilter {
8424    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8425        use ShowStatementFilter::*;
8426        match self {
8427            Like(pattern) => write!(f, "LIKE '{}'", value::escape_single_quote_string(pattern)),
8428            ILike(pattern) => write!(f, "ILIKE {}", value::escape_single_quote_string(pattern)),
8429            Where(expr) => write!(f, "WHERE {expr}"),
8430            NoKeyword(pattern) => write!(f, "'{}'", value::escape_single_quote_string(pattern)),
8431        }
8432    }
8433}
8434
8435#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8436#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8437#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8438pub enum ShowStatementInClause {
8439    IN,
8440    FROM,
8441}
8442
8443impl fmt::Display for ShowStatementInClause {
8444    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8445        use ShowStatementInClause::*;
8446        match self {
8447            FROM => write!(f, "FROM"),
8448            IN => write!(f, "IN"),
8449        }
8450    }
8451}
8452
8453/// Sqlite specific syntax
8454///
8455/// See [Sqlite documentation](https://sqlite.org/lang_conflict.html)
8456/// for more details.
8457#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8458#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8459#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8460pub enum SqliteOnConflict {
8461    Rollback,
8462    Abort,
8463    Fail,
8464    Ignore,
8465    Replace,
8466}
8467
8468impl fmt::Display for SqliteOnConflict {
8469    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8470        use SqliteOnConflict::*;
8471        match self {
8472            Rollback => write!(f, "OR ROLLBACK"),
8473            Abort => write!(f, "OR ABORT"),
8474            Fail => write!(f, "OR FAIL"),
8475            Ignore => write!(f, "OR IGNORE"),
8476            Replace => write!(f, "OR REPLACE"),
8477        }
8478    }
8479}
8480
8481/// Mysql specific syntax
8482///
8483/// See [Mysql documentation](https://dev.mysql.com/doc/refman/8.0/en/replace.html)
8484/// See [Mysql documentation](https://dev.mysql.com/doc/refman/8.0/en/insert.html)
8485/// for more details.
8486#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8487#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8488#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8489pub enum MysqlInsertPriority {
8490    LowPriority,
8491    Delayed,
8492    HighPriority,
8493}
8494
8495impl fmt::Display for crate::ast::MysqlInsertPriority {
8496    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8497        use MysqlInsertPriority::*;
8498        match self {
8499            LowPriority => write!(f, "LOW_PRIORITY"),
8500            Delayed => write!(f, "DELAYED"),
8501            HighPriority => write!(f, "HIGH_PRIORITY"),
8502        }
8503    }
8504}
8505
8506#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8507#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8508#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8509pub enum CopySource {
8510    Table {
8511        /// The name of the table to copy from.
8512        table_name: ObjectName,
8513        /// A list of column names to copy. Empty list means that all columns
8514        /// are copied.
8515        columns: Vec<Ident>,
8516    },
8517    Query(Box<Query>),
8518}
8519
8520#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8521#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8522#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8523pub enum CopyTarget {
8524    Stdin,
8525    Stdout,
8526    File {
8527        /// The path name of the input or output file.
8528        filename: String,
8529    },
8530    Program {
8531        /// A command to execute
8532        command: String,
8533    },
8534}
8535
8536impl fmt::Display for CopyTarget {
8537    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8538        use CopyTarget::*;
8539        match self {
8540            Stdin => write!(f, "STDIN"),
8541            Stdout => write!(f, "STDOUT"),
8542            File { filename } => write!(f, "'{}'", value::escape_single_quote_string(filename)),
8543            Program { command } => write!(
8544                f,
8545                "PROGRAM '{}'",
8546                value::escape_single_quote_string(command)
8547            ),
8548        }
8549    }
8550}
8551
8552#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8553#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8554#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8555pub enum OnCommit {
8556    DeleteRows,
8557    PreserveRows,
8558    Drop,
8559}
8560
8561/// An option in `COPY` statement.
8562///
8563/// <https://www.postgresql.org/docs/14/sql-copy.html>
8564#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8565#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8566#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8567pub enum CopyOption {
8568    /// FORMAT format_name
8569    Format(Ident),
8570    /// FREEZE \[ boolean \]
8571    Freeze(bool),
8572    /// DELIMITER 'delimiter_character'
8573    Delimiter(char),
8574    /// NULL 'null_string'
8575    Null(String),
8576    /// HEADER \[ boolean \]
8577    Header(bool),
8578    /// QUOTE 'quote_character'
8579    Quote(char),
8580    /// ESCAPE 'escape_character'
8581    Escape(char),
8582    /// FORCE_QUOTE { ( column_name [, ...] ) | * }
8583    ForceQuote(Vec<Ident>),
8584    /// FORCE_NOT_NULL ( column_name [, ...] )
8585    ForceNotNull(Vec<Ident>),
8586    /// FORCE_NULL ( column_name [, ...] )
8587    ForceNull(Vec<Ident>),
8588    /// ENCODING 'encoding_name'
8589    Encoding(String),
8590}
8591
8592impl fmt::Display for CopyOption {
8593    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8594        use CopyOption::*;
8595        match self {
8596            Format(name) => write!(f, "FORMAT {name}"),
8597            Freeze(true) => write!(f, "FREEZE"),
8598            Freeze(false) => write!(f, "FREEZE FALSE"),
8599            Delimiter(char) => write!(f, "DELIMITER '{char}'"),
8600            Null(string) => write!(f, "NULL '{}'", value::escape_single_quote_string(string)),
8601            Header(true) => write!(f, "HEADER"),
8602            Header(false) => write!(f, "HEADER FALSE"),
8603            Quote(char) => write!(f, "QUOTE '{char}'"),
8604            Escape(char) => write!(f, "ESCAPE '{char}'"),
8605            ForceQuote(columns) => write!(f, "FORCE_QUOTE ({})", display_comma_separated(columns)),
8606            ForceNotNull(columns) => {
8607                write!(f, "FORCE_NOT_NULL ({})", display_comma_separated(columns))
8608            }
8609            ForceNull(columns) => write!(f, "FORCE_NULL ({})", display_comma_separated(columns)),
8610            Encoding(name) => write!(f, "ENCODING '{}'", value::escape_single_quote_string(name)),
8611        }
8612    }
8613}
8614
8615/// An option in `COPY` statement before PostgreSQL version 9.0.
8616///
8617/// [PostgreSQL](https://www.postgresql.org/docs/8.4/sql-copy.html)
8618/// [Redshift](https://docs.aws.amazon.com/redshift/latest/dg/r_COPY-alphabetical-parm-list.html)
8619#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8620#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8621#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8622pub enum CopyLegacyOption {
8623    /// ACCEPTANYDATE
8624    AcceptAnyDate,
8625    /// ACCEPTINVCHARS
8626    AcceptInvChars(Option<String>),
8627    /// ADDQUOTES
8628    AddQuotes,
8629    /// ALLOWOVERWRITE
8630    AllowOverwrite,
8631    /// BINARY
8632    Binary,
8633    /// BLANKSASNULL
8634    BlankAsNull,
8635    /// BZIP2
8636    Bzip2,
8637    /// CLEANPATH
8638    CleanPath,
8639    /// CSV ...
8640    Csv(Vec<CopyLegacyCsvOption>),
8641    /// DATEFORMAT \[ AS \] {'dateformat_string' | 'auto' }
8642    DateFormat(Option<String>),
8643    /// DELIMITER \[ AS \] 'delimiter_character'
8644    Delimiter(char),
8645    /// EMPTYASNULL
8646    EmptyAsNull,
8647    /// ENCRYPTED \[ AUTO \]
8648    Encrypted { auto: bool },
8649    /// ESCAPE
8650    Escape,
8651    /// EXTENSION 'extension-name'
8652    Extension(String),
8653    /// FIXEDWIDTH \[ AS \] 'fixedwidth-spec'
8654    FixedWidth(String),
8655    /// GZIP
8656    Gzip,
8657    /// HEADER
8658    Header,
8659    /// IAM_ROLE { DEFAULT | 'arn:aws:iam::123456789:role/role1' }
8660    IamRole(IamRoleKind),
8661    /// IGNOREHEADER \[ AS \] number_rows
8662    IgnoreHeader(u64),
8663    /// JSON
8664    Json,
8665    /// MANIFEST \[ VERBOSE \]
8666    Manifest { verbose: bool },
8667    /// MAXFILESIZE \[ AS \] max-size \[ MB | GB \]
8668    MaxFileSize(FileSize),
8669    /// NULL \[ AS \] 'null_string'
8670    Null(String),
8671    /// PARALLEL [ { ON | TRUE } | { OFF | FALSE } ]
8672    Parallel(Option<bool>),
8673    /// PARQUET
8674    Parquet,
8675    /// PARTITION BY ( column_name [, ... ] ) \[ INCLUDE \]
8676    PartitionBy(UnloadPartitionBy),
8677    /// REGION \[ AS \] 'aws-region' }
8678    Region(String),
8679    /// ROWGROUPSIZE \[ AS \] size \[ MB | GB \]
8680    RowGroupSize(FileSize),
8681    /// TIMEFORMAT \[ AS \] {'timeformat_string' | 'auto' | 'epochsecs' | 'epochmillisecs' }
8682    TimeFormat(Option<String>),
8683    /// TRUNCATECOLUMNS
8684    TruncateColumns,
8685    /// ZSTD
8686    Zstd,
8687}
8688
8689impl fmt::Display for CopyLegacyOption {
8690    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8691        use CopyLegacyOption::*;
8692        match self {
8693            AcceptAnyDate => write!(f, "ACCEPTANYDATE"),
8694            AcceptInvChars(ch) => {
8695                write!(f, "ACCEPTINVCHARS")?;
8696                if let Some(ch) = ch {
8697                    write!(f, " '{}'", value::escape_single_quote_string(ch))?;
8698                }
8699                Ok(())
8700            }
8701            AddQuotes => write!(f, "ADDQUOTES"),
8702            AllowOverwrite => write!(f, "ALLOWOVERWRITE"),
8703            Binary => write!(f, "BINARY"),
8704            BlankAsNull => write!(f, "BLANKSASNULL"),
8705            Bzip2 => write!(f, "BZIP2"),
8706            CleanPath => write!(f, "CLEANPATH"),
8707            Csv(opts) => {
8708                write!(f, "CSV")?;
8709                if !opts.is_empty() {
8710                    write!(f, " {}", display_separated(opts, " "))?;
8711                }
8712                Ok(())
8713            }
8714            DateFormat(fmt) => {
8715                write!(f, "DATEFORMAT")?;
8716                if let Some(fmt) = fmt {
8717                    write!(f, " '{}'", value::escape_single_quote_string(fmt))?;
8718                }
8719                Ok(())
8720            }
8721            Delimiter(char) => write!(f, "DELIMITER '{char}'"),
8722            EmptyAsNull => write!(f, "EMPTYASNULL"),
8723            Encrypted { auto } => write!(f, "ENCRYPTED{}", if *auto { " AUTO" } else { "" }),
8724            Escape => write!(f, "ESCAPE"),
8725            Extension(ext) => write!(f, "EXTENSION '{}'", value::escape_single_quote_string(ext)),
8726            FixedWidth(spec) => write!(
8727                f,
8728                "FIXEDWIDTH '{}'",
8729                value::escape_single_quote_string(spec)
8730            ),
8731            Gzip => write!(f, "GZIP"),
8732            Header => write!(f, "HEADER"),
8733            IamRole(role) => write!(f, "IAM_ROLE {role}"),
8734            IgnoreHeader(num_rows) => write!(f, "IGNOREHEADER {num_rows}"),
8735            Json => write!(f, "JSON"),
8736            Manifest { verbose } => write!(f, "MANIFEST{}", if *verbose { " VERBOSE" } else { "" }),
8737            MaxFileSize(file_size) => write!(f, "MAXFILESIZE {file_size}"),
8738            Null(string) => write!(f, "NULL '{}'", value::escape_single_quote_string(string)),
8739            Parallel(enabled) => {
8740                write!(
8741                    f,
8742                    "PARALLEL{}",
8743                    match enabled {
8744                        Some(true) => " TRUE",
8745                        Some(false) => " FALSE",
8746                        _ => "",
8747                    }
8748                )
8749            }
8750            Parquet => write!(f, "PARQUET"),
8751            PartitionBy(p) => write!(f, "{p}"),
8752            Region(region) => write!(f, "REGION '{}'", value::escape_single_quote_string(region)),
8753            RowGroupSize(file_size) => write!(f, "ROWGROUPSIZE {file_size}"),
8754            TimeFormat(fmt) => {
8755                write!(f, "TIMEFORMAT")?;
8756                if let Some(fmt) = fmt {
8757                    write!(f, " '{}'", value::escape_single_quote_string(fmt))?;
8758                }
8759                Ok(())
8760            }
8761            TruncateColumns => write!(f, "TRUNCATECOLUMNS"),
8762            Zstd => write!(f, "ZSTD"),
8763        }
8764    }
8765}
8766
8767/// ```sql
8768/// SIZE \[ MB | GB \]
8769/// ```
8770#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8771#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8772#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8773pub struct FileSize {
8774    pub size: Value,
8775    pub unit: Option<FileSizeUnit>,
8776}
8777
8778impl fmt::Display for FileSize {
8779    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8780        write!(f, "{}", self.size)?;
8781        if let Some(unit) = &self.unit {
8782            write!(f, " {unit}")?;
8783        }
8784        Ok(())
8785    }
8786}
8787
8788#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8789#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8790#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8791pub enum FileSizeUnit {
8792    MB,
8793    GB,
8794}
8795
8796impl fmt::Display for FileSizeUnit {
8797    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8798        match self {
8799            FileSizeUnit::MB => write!(f, "MB"),
8800            FileSizeUnit::GB => write!(f, "GB"),
8801        }
8802    }
8803}
8804
8805/// Specifies the partition keys for the unload operation
8806///
8807/// ```sql
8808/// PARTITION BY ( column_name [, ... ] ) [ INCLUDE ]
8809/// ```
8810#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8811#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8812#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8813pub struct UnloadPartitionBy {
8814    pub columns: Vec<Ident>,
8815    pub include: bool,
8816}
8817
8818impl fmt::Display for UnloadPartitionBy {
8819    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8820        write!(
8821            f,
8822            "PARTITION BY ({}){}",
8823            display_comma_separated(&self.columns),
8824            if self.include { " INCLUDE" } else { "" }
8825        )
8826    }
8827}
8828
8829/// An `IAM_ROLE` option in the AWS ecosystem
8830///
8831/// [Redshift COPY](https://docs.aws.amazon.com/redshift/latest/dg/copy-parameters-authorization.html#copy-iam-role)
8832#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8833#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8834#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8835pub enum IamRoleKind {
8836    /// Default role
8837    Default,
8838    /// Specific role ARN, for example: `arn:aws:iam::123456789:role/role1`
8839    Arn(String),
8840}
8841
8842impl fmt::Display for IamRoleKind {
8843    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8844        match self {
8845            IamRoleKind::Default => write!(f, "DEFAULT"),
8846            IamRoleKind::Arn(arn) => write!(f, "'{arn}'"),
8847        }
8848    }
8849}
8850
8851/// A `CSV` option in `COPY` statement before PostgreSQL version 9.0.
8852///
8853/// <https://www.postgresql.org/docs/8.4/sql-copy.html>
8854#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8855#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8856#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8857pub enum CopyLegacyCsvOption {
8858    /// HEADER
8859    Header,
8860    /// QUOTE \[ AS \] 'quote_character'
8861    Quote(char),
8862    /// ESCAPE \[ AS \] 'escape_character'
8863    Escape(char),
8864    /// FORCE QUOTE { column_name [, ...] | * }
8865    ForceQuote(Vec<Ident>),
8866    /// FORCE NOT NULL column_name [, ...]
8867    ForceNotNull(Vec<Ident>),
8868}
8869
8870impl fmt::Display for CopyLegacyCsvOption {
8871    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8872        use CopyLegacyCsvOption::*;
8873        match self {
8874            Header => write!(f, "HEADER"),
8875            Quote(char) => write!(f, "QUOTE '{char}'"),
8876            Escape(char) => write!(f, "ESCAPE '{char}'"),
8877            ForceQuote(columns) => write!(f, "FORCE QUOTE {}", display_comma_separated(columns)),
8878            ForceNotNull(columns) => {
8879                write!(f, "FORCE NOT NULL {}", display_comma_separated(columns))
8880            }
8881        }
8882    }
8883}
8884
8885/// Variant of `WHEN` clause used within a `MERGE` Statement.
8886///
8887/// Example:
8888/// ```sql
8889/// MERGE INTO T USING U ON FALSE WHEN MATCHED THEN DELETE
8890/// ```
8891/// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/merge)
8892/// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/dml-syntax#merge_statement)
8893#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8894#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8895#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8896pub enum MergeClauseKind {
8897    /// `WHEN MATCHED`
8898    Matched,
8899    /// `WHEN NOT MATCHED`
8900    NotMatched,
8901    /// `WHEN MATCHED BY TARGET`
8902    ///
8903    /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/dml-syntax#merge_statement)
8904    NotMatchedByTarget,
8905    /// `WHEN MATCHED BY SOURCE`
8906    ///
8907    /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/dml-syntax#merge_statement)
8908    NotMatchedBySource,
8909}
8910
8911impl Display for MergeClauseKind {
8912    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8913        match self {
8914            MergeClauseKind::Matched => write!(f, "MATCHED"),
8915            MergeClauseKind::NotMatched => write!(f, "NOT MATCHED"),
8916            MergeClauseKind::NotMatchedByTarget => write!(f, "NOT MATCHED BY TARGET"),
8917            MergeClauseKind::NotMatchedBySource => write!(f, "NOT MATCHED BY SOURCE"),
8918        }
8919    }
8920}
8921
8922/// The type of expression used to insert rows within a `MERGE` statement.
8923///
8924/// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/merge)
8925/// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/dml-syntax#merge_statement)
8926#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8927#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8928#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8929pub enum MergeInsertKind {
8930    /// The insert expression is defined from an explicit `VALUES` clause
8931    ///
8932    /// Example:
8933    /// ```sql
8934    /// INSERT VALUES(product, quantity)
8935    /// ```
8936    Values(Values),
8937    /// The insert expression is defined using only the `ROW` keyword.
8938    ///
8939    /// Example:
8940    /// ```sql
8941    /// INSERT ROW
8942    /// ```
8943    /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/dml-syntax#merge_statement)
8944    Row,
8945}
8946
8947impl Display for MergeInsertKind {
8948    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8949        match self {
8950            MergeInsertKind::Values(values) => {
8951                write!(f, "{values}")
8952            }
8953            MergeInsertKind::Row => {
8954                write!(f, "ROW")
8955            }
8956        }
8957    }
8958}
8959
8960/// The expression used to insert rows within a `MERGE` statement.
8961///
8962/// Examples
8963/// ```sql
8964/// INSERT (product, quantity) VALUES(product, quantity)
8965/// INSERT ROW
8966/// ```
8967///
8968/// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/merge)
8969/// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/dml-syntax#merge_statement)
8970#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8971#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8972#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8973pub struct MergeInsertExpr {
8974    /// Columns (if any) specified by the insert.
8975    ///
8976    /// Example:
8977    /// ```sql
8978    /// INSERT (product, quantity) VALUES(product, quantity)
8979    /// INSERT (product, quantity) ROW
8980    /// ```
8981    pub columns: Vec<Ident>,
8982    /// The insert type used by the statement.
8983    pub kind: MergeInsertKind,
8984}
8985
8986impl Display for MergeInsertExpr {
8987    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8988        if !self.columns.is_empty() {
8989            write!(f, "({}) ", display_comma_separated(self.columns.as_slice()))?;
8990        }
8991        write!(f, "{}", self.kind)
8992    }
8993}
8994
8995/// Underlying statement of a when clause within a `MERGE` Statement
8996///
8997/// Example
8998/// ```sql
8999/// INSERT (product, quantity) VALUES(product, quantity)
9000/// ```
9001///
9002/// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/merge)
9003/// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/dml-syntax#merge_statement)
9004#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9005#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9006#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9007pub enum MergeAction {
9008    /// An `INSERT` clause
9009    ///
9010    /// Example:
9011    /// ```sql
9012    /// INSERT (product, quantity) VALUES(product, quantity)
9013    /// ```
9014    Insert(MergeInsertExpr),
9015    /// An `UPDATE` clause
9016    ///
9017    /// Example:
9018    /// ```sql
9019    /// UPDATE SET quantity = T.quantity + S.quantity
9020    /// ```
9021    Update { assignments: Vec<Assignment> },
9022    /// A plain `DELETE` clause
9023    Delete,
9024}
9025
9026impl Display for MergeAction {
9027    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9028        match self {
9029            MergeAction::Insert(insert) => {
9030                write!(f, "INSERT {insert}")
9031            }
9032            MergeAction::Update { assignments } => {
9033                write!(f, "UPDATE SET {}", display_comma_separated(assignments))
9034            }
9035            MergeAction::Delete => {
9036                write!(f, "DELETE")
9037            }
9038        }
9039    }
9040}
9041
9042/// A when clause within a `MERGE` Statement
9043///
9044/// Example:
9045/// ```sql
9046/// WHEN NOT MATCHED BY SOURCE AND product LIKE '%washer%' THEN DELETE
9047/// ```
9048/// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/merge)
9049/// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/dml-syntax#merge_statement)
9050#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9051#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9052#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9053pub struct MergeClause {
9054    pub clause_kind: MergeClauseKind,
9055    pub predicate: Option<Expr>,
9056    pub action: MergeAction,
9057}
9058
9059impl Display for MergeClause {
9060    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9061        let MergeClause {
9062            clause_kind,
9063            predicate,
9064            action,
9065        } = self;
9066
9067        write!(f, "WHEN {clause_kind}")?;
9068        if let Some(pred) = predicate {
9069            write!(f, " AND {pred}")?;
9070        }
9071        write!(f, " THEN {action}")
9072    }
9073}
9074
9075/// A Output Clause in the end of a 'MERGE' Statement
9076///
9077/// Example:
9078/// OUTPUT $action, deleted.* INTO dbo.temp_products;
9079/// [mssql](https://learn.microsoft.com/en-us/sql/t-sql/queries/output-clause-transact-sql)
9080#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9081#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9082#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9083pub enum OutputClause {
9084    Output {
9085        select_items: Vec<SelectItem>,
9086        into_table: Option<SelectInto>,
9087    },
9088    Returning {
9089        select_items: Vec<SelectItem>,
9090    },
9091}
9092
9093impl fmt::Display for OutputClause {
9094    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9095        match self {
9096            OutputClause::Output {
9097                select_items,
9098                into_table,
9099            } => {
9100                f.write_str("OUTPUT ")?;
9101                display_comma_separated(select_items).fmt(f)?;
9102                if let Some(into_table) = into_table {
9103                    f.write_str(" ")?;
9104                    into_table.fmt(f)?;
9105                }
9106                Ok(())
9107            }
9108            OutputClause::Returning { select_items } => {
9109                f.write_str("RETURNING ")?;
9110                display_comma_separated(select_items).fmt(f)
9111            }
9112        }
9113    }
9114}
9115
9116#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9117#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9118#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9119pub enum DiscardObject {
9120    ALL,
9121    PLANS,
9122    SEQUENCES,
9123    TEMP,
9124}
9125
9126impl fmt::Display for DiscardObject {
9127    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9128        match self {
9129            DiscardObject::ALL => f.write_str("ALL"),
9130            DiscardObject::PLANS => f.write_str("PLANS"),
9131            DiscardObject::SEQUENCES => f.write_str("SEQUENCES"),
9132            DiscardObject::TEMP => f.write_str("TEMP"),
9133        }
9134    }
9135}
9136
9137#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9138#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9139#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9140pub enum FlushType {
9141    BinaryLogs,
9142    EngineLogs,
9143    ErrorLogs,
9144    GeneralLogs,
9145    Hosts,
9146    Logs,
9147    Privileges,
9148    OptimizerCosts,
9149    RelayLogs,
9150    SlowLogs,
9151    Status,
9152    UserResources,
9153    Tables,
9154}
9155
9156impl fmt::Display for FlushType {
9157    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9158        match self {
9159            FlushType::BinaryLogs => f.write_str("BINARY LOGS"),
9160            FlushType::EngineLogs => f.write_str("ENGINE LOGS"),
9161            FlushType::ErrorLogs => f.write_str("ERROR LOGS"),
9162            FlushType::GeneralLogs => f.write_str("GENERAL LOGS"),
9163            FlushType::Hosts => f.write_str("HOSTS"),
9164            FlushType::Logs => f.write_str("LOGS"),
9165            FlushType::Privileges => f.write_str("PRIVILEGES"),
9166            FlushType::OptimizerCosts => f.write_str("OPTIMIZER_COSTS"),
9167            FlushType::RelayLogs => f.write_str("RELAY LOGS"),
9168            FlushType::SlowLogs => f.write_str("SLOW LOGS"),
9169            FlushType::Status => f.write_str("STATUS"),
9170            FlushType::UserResources => f.write_str("USER_RESOURCES"),
9171            FlushType::Tables => f.write_str("TABLES"),
9172        }
9173    }
9174}
9175
9176#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9177#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9178#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9179pub enum FlushLocation {
9180    NoWriteToBinlog,
9181    Local,
9182}
9183
9184impl fmt::Display for FlushLocation {
9185    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9186        match self {
9187            FlushLocation::NoWriteToBinlog => f.write_str("NO_WRITE_TO_BINLOG"),
9188            FlushLocation::Local => f.write_str("LOCAL"),
9189        }
9190    }
9191}
9192
9193/// Optional context modifier for statements that can be or `LOCAL`, `GLOBAL`, or `SESSION`.
9194#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9195#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9196#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9197pub enum ContextModifier {
9198    /// `LOCAL` identifier, usually related to transactional states.
9199    Local,
9200    /// `SESSION` identifier
9201    Session,
9202    /// `GLOBAL` identifier
9203    Global,
9204}
9205
9206impl fmt::Display for ContextModifier {
9207    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9208        match self {
9209            Self::Local => {
9210                write!(f, "LOCAL ")
9211            }
9212            Self::Session => {
9213                write!(f, "SESSION ")
9214            }
9215            Self::Global => {
9216                write!(f, "GLOBAL ")
9217            }
9218        }
9219    }
9220}
9221
9222/// Function describe in DROP FUNCTION.
9223#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9224#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9225pub enum DropFunctionOption {
9226    Restrict,
9227    Cascade,
9228}
9229
9230impl fmt::Display for DropFunctionOption {
9231    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9232        match self {
9233            DropFunctionOption::Restrict => write!(f, "RESTRICT "),
9234            DropFunctionOption::Cascade => write!(f, "CASCADE  "),
9235        }
9236    }
9237}
9238
9239/// Generic function description for DROP FUNCTION and CREATE TRIGGER.
9240#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9241#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9242#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9243pub struct FunctionDesc {
9244    pub name: ObjectName,
9245    pub args: Option<Vec<OperateFunctionArg>>,
9246}
9247
9248impl fmt::Display for FunctionDesc {
9249    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9250        write!(f, "{}", self.name)?;
9251        if let Some(args) = &self.args {
9252            write!(f, "({})", display_comma_separated(args))?;
9253        }
9254        Ok(())
9255    }
9256}
9257
9258/// Function argument in CREATE OR DROP FUNCTION.
9259#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9260#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9261#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9262pub struct OperateFunctionArg {
9263    pub mode: Option<ArgMode>,
9264    pub name: Option<Ident>,
9265    pub data_type: DataType,
9266    pub default_expr: Option<Expr>,
9267}
9268
9269impl OperateFunctionArg {
9270    /// Returns an unnamed argument.
9271    pub fn unnamed(data_type: DataType) -> Self {
9272        Self {
9273            mode: None,
9274            name: None,
9275            data_type,
9276            default_expr: None,
9277        }
9278    }
9279
9280    /// Returns an argument with name.
9281    pub fn with_name(name: &str, data_type: DataType) -> Self {
9282        Self {
9283            mode: None,
9284            name: Some(name.into()),
9285            data_type,
9286            default_expr: None,
9287        }
9288    }
9289}
9290
9291impl fmt::Display for OperateFunctionArg {
9292    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9293        if let Some(mode) = &self.mode {
9294            write!(f, "{mode} ")?;
9295        }
9296        if let Some(name) = &self.name {
9297            write!(f, "{name} ")?;
9298        }
9299        write!(f, "{}", self.data_type)?;
9300        if let Some(default_expr) = &self.default_expr {
9301            write!(f, " = {default_expr}")?;
9302        }
9303        Ok(())
9304    }
9305}
9306
9307/// The mode of an argument in CREATE FUNCTION.
9308#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9309#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9310#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9311pub enum ArgMode {
9312    In,
9313    Out,
9314    InOut,
9315}
9316
9317impl fmt::Display for ArgMode {
9318    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9319        match self {
9320            ArgMode::In => write!(f, "IN"),
9321            ArgMode::Out => write!(f, "OUT"),
9322            ArgMode::InOut => write!(f, "INOUT"),
9323        }
9324    }
9325}
9326
9327/// These attributes inform the query optimizer about the behavior of the function.
9328#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9329#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9330#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9331pub enum FunctionBehavior {
9332    Immutable,
9333    Stable,
9334    Volatile,
9335}
9336
9337impl fmt::Display for FunctionBehavior {
9338    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9339        match self {
9340            FunctionBehavior::Immutable => write!(f, "IMMUTABLE"),
9341            FunctionBehavior::Stable => write!(f, "STABLE"),
9342            FunctionBehavior::Volatile => write!(f, "VOLATILE"),
9343        }
9344    }
9345}
9346
9347/// These attributes describe the behavior of the function when called with a null argument.
9348#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9349#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9350#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9351pub enum FunctionCalledOnNull {
9352    CalledOnNullInput,
9353    ReturnsNullOnNullInput,
9354    Strict,
9355}
9356
9357impl fmt::Display for FunctionCalledOnNull {
9358    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9359        match self {
9360            FunctionCalledOnNull::CalledOnNullInput => write!(f, "CALLED ON NULL INPUT"),
9361            FunctionCalledOnNull::ReturnsNullOnNullInput => write!(f, "RETURNS NULL ON NULL INPUT"),
9362            FunctionCalledOnNull::Strict => write!(f, "STRICT"),
9363        }
9364    }
9365}
9366
9367/// If it is safe for PostgreSQL to call the function from multiple threads at once
9368#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9369#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9370#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9371pub enum FunctionParallel {
9372    Unsafe,
9373    Restricted,
9374    Safe,
9375}
9376
9377impl fmt::Display for FunctionParallel {
9378    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9379        match self {
9380            FunctionParallel::Unsafe => write!(f, "PARALLEL UNSAFE"),
9381            FunctionParallel::Restricted => write!(f, "PARALLEL RESTRICTED"),
9382            FunctionParallel::Safe => write!(f, "PARALLEL SAFE"),
9383        }
9384    }
9385}
9386
9387/// [BigQuery] Determinism specifier used in a UDF definition.
9388///
9389/// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#syntax_11
9390#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9391#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9392#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9393pub enum FunctionDeterminismSpecifier {
9394    Deterministic,
9395    NotDeterministic,
9396}
9397
9398impl fmt::Display for FunctionDeterminismSpecifier {
9399    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9400        match self {
9401            FunctionDeterminismSpecifier::Deterministic => {
9402                write!(f, "DETERMINISTIC")
9403            }
9404            FunctionDeterminismSpecifier::NotDeterministic => {
9405                write!(f, "NOT DETERMINISTIC")
9406            }
9407        }
9408    }
9409}
9410
9411/// Represent the expression body of a `CREATE FUNCTION` statement as well as
9412/// where within the statement, the body shows up.
9413///
9414/// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#syntax_11
9415/// [PostgreSQL]: https://www.postgresql.org/docs/15/sql-createfunction.html
9416/// [MsSql]: https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql
9417#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9418#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9419#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9420pub enum CreateFunctionBody {
9421    /// A function body expression using the 'AS' keyword and shows up
9422    /// before any `OPTIONS` clause.
9423    ///
9424    /// Example:
9425    /// ```sql
9426    /// CREATE FUNCTION myfunc(x FLOAT64, y FLOAT64) RETURNS FLOAT64
9427    /// AS (x * y)
9428    /// OPTIONS(description="desc");
9429    /// ```
9430    ///
9431    /// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#syntax_11
9432    AsBeforeOptions(Expr),
9433    /// A function body expression using the 'AS' keyword and shows up
9434    /// after any `OPTIONS` clause.
9435    ///
9436    /// Example:
9437    /// ```sql
9438    /// CREATE FUNCTION myfunc(x FLOAT64, y FLOAT64) RETURNS FLOAT64
9439    /// OPTIONS(description="desc")
9440    /// AS (x * y);
9441    /// ```
9442    ///
9443    /// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#syntax_11
9444    AsAfterOptions(Expr),
9445    /// Function body with statements before the `RETURN` keyword.
9446    ///
9447    /// Example:
9448    /// ```sql
9449    /// CREATE FUNCTION my_scalar_udf(a INT, b INT)
9450    /// RETURNS INT
9451    /// AS
9452    /// BEGIN
9453    ///     DECLARE c INT;
9454    ///     SET c = a + b;
9455    ///     RETURN c;
9456    /// END
9457    /// ```
9458    ///
9459    /// [MsSql]: https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql
9460    AsBeginEnd(BeginEndStatements),
9461    /// Function body expression using the 'RETURN' keyword.
9462    ///
9463    /// Example:
9464    /// ```sql
9465    /// CREATE FUNCTION myfunc(a INTEGER, IN b INTEGER = 1) RETURNS INTEGER
9466    /// LANGUAGE SQL
9467    /// RETURN a + b;
9468    /// ```
9469    ///
9470    /// [PostgreSQL]: https://www.postgresql.org/docs/current/sql-createfunction.html
9471    Return(Expr),
9472
9473    /// Function body expression using the 'AS RETURN' keywords
9474    ///
9475    /// Example:
9476    /// ```sql
9477    /// CREATE FUNCTION myfunc(a INT, b INT)
9478    /// RETURNS TABLE
9479    /// AS RETURN (SELECT a + b AS sum);
9480    /// ```
9481    ///
9482    /// [MsSql]: https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql
9483    AsReturnExpr(Expr),
9484
9485    /// Function body expression using the 'AS RETURN' keywords, with an un-parenthesized SELECT query
9486    ///
9487    /// Example:
9488    /// ```sql
9489    /// CREATE FUNCTION myfunc(a INT, b INT)
9490    /// RETURNS TABLE
9491    /// AS RETURN SELECT a + b AS sum;
9492    /// ```
9493    ///
9494    /// [MsSql]: https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql?view=sql-server-ver16#select_stmt
9495    AsReturnSelect(Select),
9496}
9497
9498#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9499#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9500#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9501pub enum CreateFunctionUsing {
9502    Jar(String),
9503    File(String),
9504    Archive(String),
9505}
9506
9507impl fmt::Display for CreateFunctionUsing {
9508    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9509        write!(f, "USING ")?;
9510        match self {
9511            CreateFunctionUsing::Jar(uri) => write!(f, "JAR '{uri}'"),
9512            CreateFunctionUsing::File(uri) => write!(f, "FILE '{uri}'"),
9513            CreateFunctionUsing::Archive(uri) => write!(f, "ARCHIVE '{uri}'"),
9514        }
9515    }
9516}
9517
9518/// `NAME = <EXPR>` arguments for DuckDB macros
9519///
9520/// See [Create Macro - DuckDB](https://duckdb.org/docs/sql/statements/create_macro)
9521/// for more details
9522#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9523#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9524#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9525pub struct MacroArg {
9526    pub name: Ident,
9527    pub default_expr: Option<Expr>,
9528}
9529
9530impl MacroArg {
9531    /// Returns an argument with name.
9532    pub fn new(name: &str) -> Self {
9533        Self {
9534            name: name.into(),
9535            default_expr: None,
9536        }
9537    }
9538}
9539
9540impl fmt::Display for MacroArg {
9541    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9542        write!(f, "{}", self.name)?;
9543        if let Some(default_expr) = &self.default_expr {
9544            write!(f, " := {default_expr}")?;
9545        }
9546        Ok(())
9547    }
9548}
9549
9550#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9551#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9552#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9553pub enum MacroDefinition {
9554    Expr(Expr),
9555    Table(Box<Query>),
9556}
9557
9558impl fmt::Display for MacroDefinition {
9559    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9560        match self {
9561            MacroDefinition::Expr(expr) => write!(f, "{expr}")?,
9562            MacroDefinition::Table(query) => write!(f, "{query}")?,
9563        }
9564        Ok(())
9565    }
9566}
9567
9568/// Schema possible naming variants ([1]).
9569///
9570/// [1]: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#schema-definition
9571#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9572#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9573#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9574pub enum SchemaName {
9575    /// Only schema name specified: `<schema name>`.
9576    Simple(ObjectName),
9577    /// Only authorization identifier specified: `AUTHORIZATION <schema authorization identifier>`.
9578    UnnamedAuthorization(Ident),
9579    /// Both schema name and authorization identifier specified: `<schema name>  AUTHORIZATION <schema authorization identifier>`.
9580    NamedAuthorization(ObjectName, Ident),
9581}
9582
9583impl fmt::Display for SchemaName {
9584    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
9585        match self {
9586            SchemaName::Simple(name) => {
9587                write!(f, "{name}")
9588            }
9589            SchemaName::UnnamedAuthorization(authorization) => {
9590                write!(f, "AUTHORIZATION {authorization}")
9591            }
9592            SchemaName::NamedAuthorization(name, authorization) => {
9593                write!(f, "{name} AUTHORIZATION {authorization}")
9594            }
9595        }
9596    }
9597}
9598
9599/// Fulltext search modifiers ([1]).
9600///
9601/// [1]: https://dev.mysql.com/doc/refman/8.0/en/fulltext-search.html#function_match
9602#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9603#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9604#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9605pub enum SearchModifier {
9606    /// `IN NATURAL LANGUAGE MODE`.
9607    InNaturalLanguageMode,
9608    /// `IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION`.
9609    InNaturalLanguageModeWithQueryExpansion,
9610    ///`IN BOOLEAN MODE`.
9611    InBooleanMode,
9612    ///`WITH QUERY EXPANSION`.
9613    WithQueryExpansion,
9614}
9615
9616impl fmt::Display for SearchModifier {
9617    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
9618        match self {
9619            Self::InNaturalLanguageMode => {
9620                write!(f, "IN NATURAL LANGUAGE MODE")?;
9621            }
9622            Self::InNaturalLanguageModeWithQueryExpansion => {
9623                write!(f, "IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION")?;
9624            }
9625            Self::InBooleanMode => {
9626                write!(f, "IN BOOLEAN MODE")?;
9627            }
9628            Self::WithQueryExpansion => {
9629                write!(f, "WITH QUERY EXPANSION")?;
9630            }
9631        }
9632
9633        Ok(())
9634    }
9635}
9636
9637#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9638#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9639#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9640pub struct LockTable {
9641    pub table: Ident,
9642    pub alias: Option<Ident>,
9643    pub lock_type: LockTableType,
9644}
9645
9646impl fmt::Display for LockTable {
9647    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
9648        let Self {
9649            table: tbl_name,
9650            alias,
9651            lock_type,
9652        } = self;
9653
9654        write!(f, "{tbl_name} ")?;
9655        if let Some(alias) = alias {
9656            write!(f, "AS {alias} ")?;
9657        }
9658        write!(f, "{lock_type}")?;
9659        Ok(())
9660    }
9661}
9662
9663#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9664#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9665#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9666pub enum LockTableType {
9667    Read { local: bool },
9668    Write { low_priority: bool },
9669}
9670
9671impl fmt::Display for LockTableType {
9672    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
9673        match self {
9674            Self::Read { local } => {
9675                write!(f, "READ")?;
9676                if *local {
9677                    write!(f, " LOCAL")?;
9678                }
9679            }
9680            Self::Write { low_priority } => {
9681                if *low_priority {
9682                    write!(f, "LOW_PRIORITY ")?;
9683                }
9684                write!(f, "WRITE")?;
9685            }
9686        }
9687
9688        Ok(())
9689    }
9690}
9691
9692#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9693#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9694#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9695pub struct HiveSetLocation {
9696    pub has_set: bool,
9697    pub location: Ident,
9698}
9699
9700impl fmt::Display for HiveSetLocation {
9701    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
9702        if self.has_set {
9703            write!(f, "SET ")?;
9704        }
9705        write!(f, "LOCATION {}", self.location)
9706    }
9707}
9708
9709/// MySQL `ALTER TABLE` only  [FIRST | AFTER column_name]
9710#[allow(clippy::large_enum_variant)]
9711#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9712#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9713#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9714pub enum MySQLColumnPosition {
9715    First,
9716    After(Ident),
9717}
9718
9719impl Display for MySQLColumnPosition {
9720    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9721        match self {
9722            MySQLColumnPosition::First => write!(f, "FIRST"),
9723            MySQLColumnPosition::After(ident) => {
9724                let column_name = &ident.value;
9725                write!(f, "AFTER {column_name}")
9726            }
9727        }
9728    }
9729}
9730
9731/// MySQL `CREATE VIEW` algorithm parameter: [ALGORITHM = {UNDEFINED | MERGE | TEMPTABLE}]
9732#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9733#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9734#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9735pub enum CreateViewAlgorithm {
9736    Undefined,
9737    Merge,
9738    TempTable,
9739}
9740
9741impl Display for CreateViewAlgorithm {
9742    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9743        match self {
9744            CreateViewAlgorithm::Undefined => write!(f, "UNDEFINED"),
9745            CreateViewAlgorithm::Merge => write!(f, "MERGE"),
9746            CreateViewAlgorithm::TempTable => write!(f, "TEMPTABLE"),
9747        }
9748    }
9749}
9750/// MySQL `CREATE VIEW` security parameter: [SQL SECURITY { DEFINER | INVOKER }]
9751#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9752#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9753#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9754pub enum CreateViewSecurity {
9755    Definer,
9756    Invoker,
9757}
9758
9759impl Display for CreateViewSecurity {
9760    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9761        match self {
9762            CreateViewSecurity::Definer => write!(f, "DEFINER"),
9763            CreateViewSecurity::Invoker => write!(f, "INVOKER"),
9764        }
9765    }
9766}
9767
9768/// [MySQL] `CREATE VIEW` additional parameters
9769///
9770/// [MySQL]: https://dev.mysql.com/doc/refman/9.1/en/create-view.html
9771#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9772#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9773#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9774pub struct CreateViewParams {
9775    pub algorithm: Option<CreateViewAlgorithm>,
9776    pub definer: Option<GranteeName>,
9777    pub security: Option<CreateViewSecurity>,
9778}
9779
9780impl Display for CreateViewParams {
9781    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
9782        let CreateViewParams {
9783            algorithm,
9784            definer,
9785            security,
9786        } = self;
9787        if let Some(algorithm) = algorithm {
9788            write!(f, "ALGORITHM = {algorithm} ")?;
9789        }
9790        if let Some(definers) = definer {
9791            write!(f, "DEFINER = {definers} ")?;
9792        }
9793        if let Some(security) = security {
9794            write!(f, "SQL SECURITY {security} ")?;
9795        }
9796        Ok(())
9797    }
9798}
9799
9800#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9801#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9802#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9803/// Key/Value, where the value is a (optionally named) list of identifiers
9804///
9805/// ```sql
9806/// UNION = (tbl_name[,tbl_name]...)
9807/// ENGINE = ReplicatedMergeTree('/table_name','{replica}', ver)
9808/// ENGINE = SummingMergeTree([columns])
9809/// ```
9810pub struct NamedParenthesizedList {
9811    pub key: Ident,
9812    pub name: Option<Ident>,
9813    pub values: Vec<Ident>,
9814}
9815
9816/// Snowflake `WITH ROW ACCESS POLICY policy_name ON (identifier, ...)`
9817///
9818/// <https://docs.snowflake.com/en/sql-reference/sql/create-table>
9819/// <https://docs.snowflake.com/en/user-guide/security-row-intro>
9820#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9821#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9822#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9823pub struct RowAccessPolicy {
9824    pub policy: ObjectName,
9825    pub on: Vec<Ident>,
9826}
9827
9828impl RowAccessPolicy {
9829    pub fn new(policy: ObjectName, on: Vec<Ident>) -> Self {
9830        Self { policy, on }
9831    }
9832}
9833
9834impl Display for RowAccessPolicy {
9835    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9836        write!(
9837            f,
9838            "WITH ROW ACCESS POLICY {} ON ({})",
9839            self.policy,
9840            display_comma_separated(self.on.as_slice())
9841        )
9842    }
9843}
9844
9845/// Snowflake `WITH TAG ( tag_name = '<tag_value>', ...)`
9846///
9847/// <https://docs.snowflake.com/en/sql-reference/sql/create-table>
9848#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9849#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9850#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9851pub struct Tag {
9852    pub key: ObjectName,
9853    pub value: String,
9854}
9855
9856impl Tag {
9857    pub fn new(key: ObjectName, value: String) -> Self {
9858        Self { key, value }
9859    }
9860}
9861
9862impl Display for Tag {
9863    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
9864        write!(f, "{}='{}'", self.key, self.value)
9865    }
9866}
9867
9868/// Snowflake `WITH CONTACT ( purpose = contact [ , purpose = contact ...] )`
9869///
9870/// <https://docs.snowflake.com/en/sql-reference/sql/create-database>
9871#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9872#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9873#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9874pub struct ContactEntry {
9875    pub purpose: String,
9876    pub contact: String,
9877}
9878
9879impl Display for ContactEntry {
9880    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
9881        write!(f, "{} = {}", self.purpose, self.contact)
9882    }
9883}
9884
9885/// Helper to indicate if a comment includes the `=` in the display form
9886#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9887#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9888#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9889pub enum CommentDef {
9890    /// Includes `=` when printing the comment, as `COMMENT = 'comment'`
9891    /// Does not include `=` when printing the comment, as `COMMENT 'comment'`
9892    WithEq(String),
9893    WithoutEq(String),
9894}
9895
9896impl Display for CommentDef {
9897    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
9898        match self {
9899            CommentDef::WithEq(comment) | CommentDef::WithoutEq(comment) => write!(f, "{comment}"),
9900        }
9901    }
9902}
9903
9904/// Helper to indicate if a collection should be wrapped by a symbol in the display form
9905///
9906/// [`Display`] is implemented for every [`Vec<T>`] where `T: Display`.
9907/// The string output is a comma separated list for the vec items
9908///
9909/// # Examples
9910/// ```
9911/// # use sqlparser::ast::WrappedCollection;
9912/// let items = WrappedCollection::Parentheses(vec!["one", "two", "three"]);
9913/// assert_eq!("(one, two, three)", items.to_string());
9914///
9915/// let items = WrappedCollection::NoWrapping(vec!["one", "two", "three"]);
9916/// assert_eq!("one, two, three", items.to_string());
9917/// ```
9918#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9919#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9920#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9921pub enum WrappedCollection<T> {
9922    /// Print the collection without wrapping symbols, as `item, item, item`
9923    NoWrapping(T),
9924    /// Wraps the collection in Parentheses, as `(item, item, item)`
9925    Parentheses(T),
9926}
9927
9928impl<T> Display for WrappedCollection<Vec<T>>
9929where
9930    T: Display,
9931{
9932    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
9933        match self {
9934            WrappedCollection::NoWrapping(inner) => {
9935                write!(f, "{}", display_comma_separated(inner.as_slice()))
9936            }
9937            WrappedCollection::Parentheses(inner) => {
9938                write!(f, "({})", display_comma_separated(inner.as_slice()))
9939            }
9940        }
9941    }
9942}
9943
9944/// Represents a single PostgreSQL utility option.
9945///
9946/// A utility option is a key-value pair where the key is an identifier (IDENT) and the value
9947/// can be one of the following:
9948/// - A number with an optional sign (`+` or `-`). Example: `+10`, `-10.2`, `3`
9949/// - A non-keyword string. Example: `option1`, `'option2'`, `"option3"`
9950/// - keyword: `TRUE`, `FALSE`, `ON` (`off` is also accept).
9951/// - Empty. Example: `ANALYZE` (identifier only)
9952///
9953/// Utility options are used in various PostgreSQL DDL statements, including statements such as
9954/// `CLUSTER`, `EXPLAIN`, `VACUUM`, and `REINDEX`. These statements format options as `( option [, ...] )`.
9955///
9956/// [CLUSTER](https://www.postgresql.org/docs/current/sql-cluster.html)
9957/// [EXPLAIN](https://www.postgresql.org/docs/current/sql-explain.html)
9958/// [VACUUM](https://www.postgresql.org/docs/current/sql-vacuum.html)
9959/// [REINDEX](https://www.postgresql.org/docs/current/sql-reindex.html)
9960///
9961/// For example, the `EXPLAIN` AND `VACUUM` statements with options might look like this:
9962/// ```sql
9963/// EXPLAIN (ANALYZE, VERBOSE TRUE, FORMAT TEXT) SELECT * FROM my_table;
9964///
9965/// VACUUM (VERBOSE, ANALYZE ON, PARALLEL 10) my_table;
9966/// ```
9967#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9968#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9969#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9970pub struct UtilityOption {
9971    pub name: Ident,
9972    pub arg: Option<Expr>,
9973}
9974
9975impl Display for UtilityOption {
9976    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
9977        if let Some(ref arg) = self.arg {
9978            write!(f, "{} {}", self.name, arg)
9979        } else {
9980            write!(f, "{}", self.name)
9981        }
9982    }
9983}
9984
9985/// Represents the different options available for `SHOW`
9986/// statements to filter the results. Example from Snowflake:
9987/// <https://docs.snowflake.com/en/sql-reference/sql/show-tables>
9988#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9989#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9990#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9991pub struct ShowStatementOptions {
9992    pub show_in: Option<ShowStatementIn>,
9993    pub starts_with: Option<Value>,
9994    pub limit: Option<Expr>,
9995    pub limit_from: Option<Value>,
9996    pub filter_position: Option<ShowStatementFilterPosition>,
9997}
9998
9999impl Display for ShowStatementOptions {
10000    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10001        let (like_in_infix, like_in_suffix) = match &self.filter_position {
10002            Some(ShowStatementFilterPosition::Infix(filter)) => {
10003                (format!(" {filter}"), "".to_string())
10004            }
10005            Some(ShowStatementFilterPosition::Suffix(filter)) => {
10006                ("".to_string(), format!(" {filter}"))
10007            }
10008            None => ("".to_string(), "".to_string()),
10009        };
10010        write!(
10011            f,
10012            "{like_in_infix}{show_in}{starts_with}{limit}{from}{like_in_suffix}",
10013            show_in = match &self.show_in {
10014                Some(i) => format!(" {i}"),
10015                None => String::new(),
10016            },
10017            starts_with = match &self.starts_with {
10018                Some(s) => format!(" STARTS WITH {s}"),
10019                None => String::new(),
10020            },
10021            limit = match &self.limit {
10022                Some(l) => format!(" LIMIT {l}"),
10023                None => String::new(),
10024            },
10025            from = match &self.limit_from {
10026                Some(f) => format!(" FROM {f}"),
10027                None => String::new(),
10028            }
10029        )?;
10030        Ok(())
10031    }
10032}
10033
10034#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10035#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10036#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10037pub enum ShowStatementFilterPosition {
10038    Infix(ShowStatementFilter), // For example: SHOW COLUMNS LIKE '%name%' IN TABLE tbl
10039    Suffix(ShowStatementFilter), // For example: SHOW COLUMNS IN tbl LIKE '%name%'
10040}
10041
10042#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10043#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10044#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10045pub enum ShowStatementInParentType {
10046    Account,
10047    Database,
10048    Schema,
10049    Table,
10050    View,
10051}
10052
10053impl fmt::Display for ShowStatementInParentType {
10054    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10055        match self {
10056            ShowStatementInParentType::Account => write!(f, "ACCOUNT"),
10057            ShowStatementInParentType::Database => write!(f, "DATABASE"),
10058            ShowStatementInParentType::Schema => write!(f, "SCHEMA"),
10059            ShowStatementInParentType::Table => write!(f, "TABLE"),
10060            ShowStatementInParentType::View => write!(f, "VIEW"),
10061        }
10062    }
10063}
10064
10065#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10066#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10067#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10068pub struct ShowStatementIn {
10069    pub clause: ShowStatementInClause,
10070    pub parent_type: Option<ShowStatementInParentType>,
10071    #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
10072    pub parent_name: Option<ObjectName>,
10073}
10074
10075impl fmt::Display for ShowStatementIn {
10076    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10077        write!(f, "{}", self.clause)?;
10078        if let Some(parent_type) = &self.parent_type {
10079            write!(f, " {parent_type}")?;
10080        }
10081        if let Some(parent_name) = &self.parent_name {
10082            write!(f, " {parent_name}")?;
10083        }
10084        Ok(())
10085    }
10086}
10087
10088/// A Show Charset statement
10089#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10090#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10091#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10092pub struct ShowCharset {
10093    /// The statement can be written as `SHOW CHARSET` or `SHOW CHARACTER SET`
10094    /// true means CHARSET was used and false means CHARACTER SET was used
10095    pub is_shorthand: bool,
10096    pub filter: Option<ShowStatementFilter>,
10097}
10098
10099impl fmt::Display for ShowCharset {
10100    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10101        write!(f, "SHOW")?;
10102        if self.is_shorthand {
10103            write!(f, " CHARSET")?;
10104        } else {
10105            write!(f, " CHARACTER SET")?;
10106        }
10107        if self.filter.is_some() {
10108            write!(f, " {}", self.filter.as_ref().unwrap())?;
10109        }
10110        Ok(())
10111    }
10112}
10113
10114#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10115#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10116#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10117pub struct ShowObjects {
10118    pub terse: bool,
10119    pub show_options: ShowStatementOptions,
10120}
10121
10122/// MSSQL's json null clause
10123///
10124/// ```plaintext
10125/// <json_null_clause> ::=
10126///       NULL ON NULL
10127///     | ABSENT ON NULL
10128/// ```
10129///
10130/// <https://learn.microsoft.com/en-us/sql/t-sql/functions/json-object-transact-sql?view=sql-server-ver16#json_null_clause>
10131#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10132#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10133#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10134pub enum JsonNullClause {
10135    NullOnNull,
10136    AbsentOnNull,
10137}
10138
10139impl Display for JsonNullClause {
10140    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10141        match self {
10142            JsonNullClause::NullOnNull => write!(f, "NULL ON NULL"),
10143            JsonNullClause::AbsentOnNull => write!(f, "ABSENT ON NULL"),
10144        }
10145    }
10146}
10147
10148/// PostgreSQL JSON function RETURNING clause
10149///
10150/// Example:
10151/// ```sql
10152/// JSON_OBJECT('a': 1 RETURNING jsonb)
10153/// ```
10154#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10155#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10156#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10157pub struct JsonReturningClause {
10158    pub data_type: DataType,
10159}
10160
10161impl Display for JsonReturningClause {
10162    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10163        write!(f, "RETURNING {}", self.data_type)
10164    }
10165}
10166
10167/// rename object definition
10168#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10169#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10170#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10171pub struct RenameTable {
10172    pub old_name: ObjectName,
10173    pub new_name: ObjectName,
10174}
10175
10176impl fmt::Display for RenameTable {
10177    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10178        write!(f, "{} TO {}", self.old_name, self.new_name)?;
10179        Ok(())
10180    }
10181}
10182
10183/// Represents the referenced table in an `INSERT INTO` statement
10184#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10185#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10186#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10187pub enum TableObject {
10188    /// Table specified by name.
10189    /// Example:
10190    /// ```sql
10191    /// INSERT INTO my_table
10192    /// ```
10193    TableName(#[cfg_attr(feature = "visitor", visit(with = "visit_relation"))] ObjectName),
10194
10195    /// Table specified as a function.
10196    /// Example:
10197    /// ```sql
10198    /// INSERT INTO TABLE FUNCTION remote('localhost', default.simple_table)
10199    /// ```
10200    /// [Clickhouse](https://clickhouse.com/docs/en/sql-reference/table-functions)
10201    TableFunction(Function),
10202}
10203
10204impl fmt::Display for TableObject {
10205    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10206        match self {
10207            Self::TableName(table_name) => write!(f, "{table_name}"),
10208            Self::TableFunction(func) => write!(f, "FUNCTION {func}"),
10209        }
10210    }
10211}
10212
10213#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10214#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10215#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10216pub enum SetSessionParamKind {
10217    Generic(SetSessionParamGeneric),
10218    IdentityInsert(SetSessionParamIdentityInsert),
10219    Offsets(SetSessionParamOffsets),
10220    Statistics(SetSessionParamStatistics),
10221}
10222
10223impl fmt::Display for SetSessionParamKind {
10224    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10225        match self {
10226            SetSessionParamKind::Generic(x) => write!(f, "{x}"),
10227            SetSessionParamKind::IdentityInsert(x) => write!(f, "{x}"),
10228            SetSessionParamKind::Offsets(x) => write!(f, "{x}"),
10229            SetSessionParamKind::Statistics(x) => write!(f, "{x}"),
10230        }
10231    }
10232}
10233
10234#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10235#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10236#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10237pub struct SetSessionParamGeneric {
10238    pub names: Vec<String>,
10239    pub value: String,
10240}
10241
10242impl fmt::Display for SetSessionParamGeneric {
10243    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10244        write!(f, "{} {}", display_comma_separated(&self.names), self.value)
10245    }
10246}
10247
10248#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10249#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10250#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10251pub struct SetSessionParamIdentityInsert {
10252    pub obj: ObjectName,
10253    pub value: SessionParamValue,
10254}
10255
10256impl fmt::Display for SetSessionParamIdentityInsert {
10257    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10258        write!(f, "IDENTITY_INSERT {} {}", self.obj, self.value)
10259    }
10260}
10261
10262#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10263#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10264#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10265pub struct SetSessionParamOffsets {
10266    pub keywords: Vec<String>,
10267    pub value: SessionParamValue,
10268}
10269
10270impl fmt::Display for SetSessionParamOffsets {
10271    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10272        write!(
10273            f,
10274            "OFFSETS {} {}",
10275            display_comma_separated(&self.keywords),
10276            self.value
10277        )
10278    }
10279}
10280
10281#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10282#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10283#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10284pub struct SetSessionParamStatistics {
10285    pub topic: SessionParamStatsTopic,
10286    pub value: SessionParamValue,
10287}
10288
10289impl fmt::Display for SetSessionParamStatistics {
10290    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10291        write!(f, "STATISTICS {} {}", self.topic, self.value)
10292    }
10293}
10294
10295#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10296#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10297#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10298pub enum SessionParamStatsTopic {
10299    IO,
10300    Profile,
10301    Time,
10302    Xml,
10303}
10304
10305impl fmt::Display for SessionParamStatsTopic {
10306    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10307        match self {
10308            SessionParamStatsTopic::IO => write!(f, "IO"),
10309            SessionParamStatsTopic::Profile => write!(f, "PROFILE"),
10310            SessionParamStatsTopic::Time => write!(f, "TIME"),
10311            SessionParamStatsTopic::Xml => write!(f, "XML"),
10312        }
10313    }
10314}
10315
10316#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10317#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10318#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10319pub enum SessionParamValue {
10320    On,
10321    Off,
10322}
10323
10324impl fmt::Display for SessionParamValue {
10325    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10326        match self {
10327            SessionParamValue::On => write!(f, "ON"),
10328            SessionParamValue::Off => write!(f, "OFF"),
10329        }
10330    }
10331}
10332
10333/// Snowflake StorageSerializationPolicy for Iceberg Tables
10334/// ```sql
10335/// [ STORAGE_SERIALIZATION_POLICY = { COMPATIBLE | OPTIMIZED } ]
10336/// ```
10337///
10338/// <https://docs.snowflake.com/en/sql-reference/sql/create-iceberg-table>
10339#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10340#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10341#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10342pub enum StorageSerializationPolicy {
10343    Compatible,
10344    Optimized,
10345}
10346
10347impl Display for StorageSerializationPolicy {
10348    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10349        match self {
10350            StorageSerializationPolicy::Compatible => write!(f, "COMPATIBLE"),
10351            StorageSerializationPolicy::Optimized => write!(f, "OPTIMIZED"),
10352        }
10353    }
10354}
10355
10356/// Snowflake CatalogSyncNamespaceMode
10357/// ```sql
10358/// [ CATALOG_SYNC_NAMESPACE_MODE = { NEST | FLATTEN } ]
10359/// ```
10360///
10361/// <https://docs.snowflake.com/en/sql-reference/sql/create-database>
10362#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10363#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10364#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10365pub enum CatalogSyncNamespaceMode {
10366    Nest,
10367    Flatten,
10368}
10369
10370impl Display for CatalogSyncNamespaceMode {
10371    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10372        match self {
10373            CatalogSyncNamespaceMode::Nest => write!(f, "NEST"),
10374            CatalogSyncNamespaceMode::Flatten => write!(f, "FLATTEN"),
10375        }
10376    }
10377}
10378
10379/// Variants of the Snowflake `COPY INTO` statement
10380#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10381#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10382#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10383pub enum CopyIntoSnowflakeKind {
10384    /// Loads data from files to a table
10385    /// See: <https://docs.snowflake.com/en/sql-reference/sql/copy-into-table>
10386    Table,
10387    /// Unloads data from a table or query to external files
10388    /// See: <https://docs.snowflake.com/en/sql-reference/sql/copy-into-location>
10389    Location,
10390}
10391
10392#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10393#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10394#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10395pub struct PrintStatement {
10396    pub message: Box<Expr>,
10397}
10398
10399impl fmt::Display for PrintStatement {
10400    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10401        write!(f, "PRINT {}", self.message)
10402    }
10403}
10404
10405/// Represents a `Return` statement.
10406///
10407/// [MsSql triggers](https://learn.microsoft.com/en-us/sql/t-sql/statements/create-trigger-transact-sql)
10408/// [MsSql functions](https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql)
10409#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10410#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10411#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10412pub struct ReturnStatement {
10413    pub value: Option<ReturnStatementValue>,
10414}
10415
10416impl fmt::Display for ReturnStatement {
10417    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10418        match &self.value {
10419            Some(ReturnStatementValue::Expr(expr)) => write!(f, "RETURN {expr}"),
10420            None => write!(f, "RETURN"),
10421        }
10422    }
10423}
10424
10425/// Variants of a `RETURN` statement
10426#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10427#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10428#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10429pub enum ReturnStatementValue {
10430    Expr(Expr),
10431}
10432
10433/// Represents an `OPEN` statement.
10434#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10435#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10436#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10437pub struct OpenStatement {
10438    /// Cursor name
10439    pub cursor_name: Ident,
10440}
10441
10442impl fmt::Display for OpenStatement {
10443    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10444        write!(f, "OPEN {}", self.cursor_name)
10445    }
10446}
10447
10448/// Specifies Include / Exclude NULL within UNPIVOT command.
10449/// For example
10450/// `UNPIVOT (column1 FOR new_column IN (col3, col4, col5, col6))`
10451#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10452#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10453#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10454pub enum NullInclusion {
10455    IncludeNulls,
10456    ExcludeNulls,
10457}
10458
10459impl fmt::Display for NullInclusion {
10460    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10461        match self {
10462            NullInclusion::IncludeNulls => write!(f, "INCLUDE NULLS"),
10463            NullInclusion::ExcludeNulls => write!(f, "EXCLUDE NULLS"),
10464        }
10465    }
10466}
10467
10468/// Checks membership of a value in a JSON array
10469///
10470/// Syntax:
10471/// ```sql
10472/// <value> MEMBER OF(<array>)
10473/// ```
10474/// [MySQL](https://dev.mysql.com/doc/refman/8.4/en/json-search-functions.html#operator_member-of)
10475#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10476#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10477#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10478pub struct MemberOf {
10479    pub value: Box<Expr>,
10480    pub array: Box<Expr>,
10481}
10482
10483impl fmt::Display for MemberOf {
10484    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10485        write!(f, "{} MEMBER OF({})", self.value, self.array)
10486    }
10487}
10488
10489#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10490#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10491#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10492pub struct ExportData {
10493    pub options: Vec<SqlOption>,
10494    pub query: Box<Query>,
10495    pub connection: Option<ObjectName>,
10496}
10497
10498impl fmt::Display for ExportData {
10499    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10500        if let Some(connection) = &self.connection {
10501            write!(
10502                f,
10503                "EXPORT DATA WITH CONNECTION {connection} OPTIONS({}) AS {}",
10504                display_comma_separated(&self.options),
10505                self.query
10506            )
10507        } else {
10508            write!(
10509                f,
10510                "EXPORT DATA OPTIONS({}) AS {}",
10511                display_comma_separated(&self.options),
10512                self.query
10513            )
10514        }
10515    }
10516}
10517/// Creates a user
10518///
10519/// Syntax:
10520/// ```sql
10521/// CREATE [OR REPLACE] USER [IF NOT EXISTS] <name> [OPTIONS]
10522/// ```
10523///
10524/// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-user)
10525#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10526#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10527#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10528pub struct CreateUser {
10529    pub or_replace: bool,
10530    pub if_not_exists: bool,
10531    pub name: Ident,
10532    pub options: KeyValueOptions,
10533    pub with_tags: bool,
10534    pub tags: KeyValueOptions,
10535}
10536
10537impl fmt::Display for CreateUser {
10538    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10539        write!(f, "CREATE")?;
10540        if self.or_replace {
10541            write!(f, " OR REPLACE")?;
10542        }
10543        write!(f, " USER")?;
10544        if self.if_not_exists {
10545            write!(f, " IF NOT EXISTS")?;
10546        }
10547        write!(f, " {}", self.name)?;
10548        if !self.options.options.is_empty() {
10549            write!(f, " {}", self.options)?;
10550        }
10551        if !self.tags.options.is_empty() {
10552            if self.with_tags {
10553                write!(f, " WITH")?;
10554            }
10555            write!(f, " TAG ({})", self.tags)?;
10556        }
10557        Ok(())
10558    }
10559}
10560
10561/// Specifies how to create a new table based on an existing table's schema.
10562/// '''sql
10563/// CREATE TABLE new LIKE old ...
10564/// '''
10565#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10566#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10567#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10568pub enum CreateTableLikeKind {
10569    /// '''sql
10570    /// CREATE TABLE new (LIKE old ...)
10571    /// '''
10572    /// [Redshift](https://docs.aws.amazon.com/redshift/latest/dg/r_CREATE_TABLE_NEW.html)
10573    Parenthesized(CreateTableLike),
10574    /// '''sql
10575    /// CREATE TABLE new LIKE old ...
10576    /// '''
10577    /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-table#label-create-table-like)
10578    /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_table_like)
10579    Plain(CreateTableLike),
10580}
10581
10582#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10583#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10584#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10585pub enum CreateTableLikeDefaults {
10586    Including,
10587    Excluding,
10588}
10589
10590impl fmt::Display for CreateTableLikeDefaults {
10591    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10592        match self {
10593            CreateTableLikeDefaults::Including => write!(f, "INCLUDING DEFAULTS"),
10594            CreateTableLikeDefaults::Excluding => write!(f, "EXCLUDING DEFAULTS"),
10595        }
10596    }
10597}
10598
10599#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10600#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10601#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10602pub struct CreateTableLike {
10603    pub name: ObjectName,
10604    pub defaults: Option<CreateTableLikeDefaults>,
10605}
10606
10607impl fmt::Display for CreateTableLike {
10608    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10609        write!(f, "LIKE {}", self.name)?;
10610        if let Some(defaults) = &self.defaults {
10611            write!(f, " {defaults}")?;
10612        }
10613        Ok(())
10614    }
10615}
10616
10617/// Specifies the refresh mode for the dynamic table.
10618///
10619/// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-dynamic-table)
10620#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10621#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10622#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10623pub enum RefreshModeKind {
10624    Auto,
10625    Full,
10626    Incremental,
10627}
10628
10629impl fmt::Display for RefreshModeKind {
10630    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10631        match self {
10632            RefreshModeKind::Auto => write!(f, "AUTO"),
10633            RefreshModeKind::Full => write!(f, "FULL"),
10634            RefreshModeKind::Incremental => write!(f, "INCREMENTAL"),
10635        }
10636    }
10637}
10638
10639/// Specifies the behavior of the initial refresh of the dynamic table.
10640///
10641/// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-dynamic-table)
10642#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10643#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10644#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10645pub enum InitializeKind {
10646    OnCreate,
10647    OnSchedule,
10648}
10649
10650impl fmt::Display for InitializeKind {
10651    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10652        match self {
10653            InitializeKind::OnCreate => write!(f, "ON_CREATE"),
10654            InitializeKind::OnSchedule => write!(f, "ON_SCHEDULE"),
10655        }
10656    }
10657}
10658
10659/// Re-sorts rows and reclaims space in either a specified table or all tables in the current database
10660///
10661/// '''sql
10662/// VACUUM [ FULL | SORT ONLY | DELETE ONLY | REINDEX | RECLUSTER ] [ \[ table_name \] [ TO threshold PERCENT ] \[ BOOST \] ]
10663/// '''
10664/// [Redshift](https://docs.aws.amazon.com/redshift/latest/dg/r_VACUUM_command.html)
10665#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10666#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10667#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10668pub struct VacuumStatement {
10669    pub full: bool,
10670    pub sort_only: bool,
10671    pub delete_only: bool,
10672    pub reindex: bool,
10673    pub recluster: bool,
10674    pub table_name: Option<ObjectName>,
10675    pub threshold: Option<Value>,
10676    pub boost: bool,
10677}
10678
10679impl fmt::Display for VacuumStatement {
10680    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10681        write!(
10682            f,
10683            "VACUUM{}{}{}{}{}",
10684            if self.full { " FULL" } else { "" },
10685            if self.sort_only { " SORT ONLY" } else { "" },
10686            if self.delete_only { " DELETE ONLY" } else { "" },
10687            if self.reindex { " REINDEX" } else { "" },
10688            if self.recluster { " RECLUSTER" } else { "" },
10689        )?;
10690        if let Some(table_name) = &self.table_name {
10691            write!(f, " {table_name}")?;
10692        }
10693        if let Some(threshold) = &self.threshold {
10694            write!(f, " TO {threshold} PERCENT")?;
10695        }
10696        if self.boost {
10697            write!(f, " BOOST")?;
10698        }
10699        Ok(())
10700    }
10701}
10702
10703impl From<Set> for Statement {
10704    fn from(s: Set) -> Self {
10705        Self::Set(s)
10706    }
10707}
10708
10709impl From<Query> for Statement {
10710    fn from(q: Query) -> Self {
10711        Box::new(q).into()
10712    }
10713}
10714
10715impl From<Box<Query>> for Statement {
10716    fn from(q: Box<Query>) -> Self {
10717        Self::Query(q)
10718    }
10719}
10720
10721impl From<Insert> for Statement {
10722    fn from(i: Insert) -> Self {
10723        Self::Insert(i)
10724    }
10725}
10726
10727impl From<CaseStatement> for Statement {
10728    fn from(c: CaseStatement) -> Self {
10729        Self::Case(c)
10730    }
10731}
10732
10733impl From<IfStatement> for Statement {
10734    fn from(i: IfStatement) -> Self {
10735        Self::If(i)
10736    }
10737}
10738
10739impl From<WhileStatement> for Statement {
10740    fn from(w: WhileStatement) -> Self {
10741        Self::While(w)
10742    }
10743}
10744
10745impl From<RaiseStatement> for Statement {
10746    fn from(r: RaiseStatement) -> Self {
10747        Self::Raise(r)
10748    }
10749}
10750
10751impl From<Function> for Statement {
10752    fn from(f: Function) -> Self {
10753        Self::Call(f)
10754    }
10755}
10756
10757impl From<OpenStatement> for Statement {
10758    fn from(o: OpenStatement) -> Self {
10759        Self::Open(o)
10760    }
10761}
10762
10763impl From<Delete> for Statement {
10764    fn from(d: Delete) -> Self {
10765        Self::Delete(d)
10766    }
10767}
10768
10769impl From<CreateTable> for Statement {
10770    fn from(c: CreateTable) -> Self {
10771        Self::CreateTable(c)
10772    }
10773}
10774
10775impl From<CreateIndex> for Statement {
10776    fn from(c: CreateIndex) -> Self {
10777        Self::CreateIndex(c)
10778    }
10779}
10780
10781impl From<CreateServerStatement> for Statement {
10782    fn from(c: CreateServerStatement) -> Self {
10783        Self::CreateServer(c)
10784    }
10785}
10786
10787impl From<CreateConnector> for Statement {
10788    fn from(c: CreateConnector) -> Self {
10789        Self::CreateConnector(c)
10790    }
10791}
10792
10793impl From<AlterSchema> for Statement {
10794    fn from(a: AlterSchema) -> Self {
10795        Self::AlterSchema(a)
10796    }
10797}
10798
10799impl From<AlterType> for Statement {
10800    fn from(a: AlterType) -> Self {
10801        Self::AlterType(a)
10802    }
10803}
10804
10805impl From<DropDomain> for Statement {
10806    fn from(d: DropDomain) -> Self {
10807        Self::DropDomain(d)
10808    }
10809}
10810
10811impl From<ShowCharset> for Statement {
10812    fn from(s: ShowCharset) -> Self {
10813        Self::ShowCharset(s)
10814    }
10815}
10816
10817impl From<ShowObjects> for Statement {
10818    fn from(s: ShowObjects) -> Self {
10819        Self::ShowObjects(s)
10820    }
10821}
10822
10823impl From<Use> for Statement {
10824    fn from(u: Use) -> Self {
10825        Self::Use(u)
10826    }
10827}
10828
10829impl From<CreateFunction> for Statement {
10830    fn from(c: CreateFunction) -> Self {
10831        Self::CreateFunction(c)
10832    }
10833}
10834
10835impl From<CreateTrigger> for Statement {
10836    fn from(c: CreateTrigger) -> Self {
10837        Self::CreateTrigger(c)
10838    }
10839}
10840
10841impl From<DropTrigger> for Statement {
10842    fn from(d: DropTrigger) -> Self {
10843        Self::DropTrigger(d)
10844    }
10845}
10846
10847impl From<DenyStatement> for Statement {
10848    fn from(d: DenyStatement) -> Self {
10849        Self::Deny(d)
10850    }
10851}
10852
10853impl From<CreateDomain> for Statement {
10854    fn from(c: CreateDomain) -> Self {
10855        Self::CreateDomain(c)
10856    }
10857}
10858
10859impl From<RenameTable> for Statement {
10860    fn from(r: RenameTable) -> Self {
10861        vec![r].into()
10862    }
10863}
10864
10865impl From<Vec<RenameTable>> for Statement {
10866    fn from(r: Vec<RenameTable>) -> Self {
10867        Self::RenameTable(r)
10868    }
10869}
10870
10871impl From<PrintStatement> for Statement {
10872    fn from(p: PrintStatement) -> Self {
10873        Self::Print(p)
10874    }
10875}
10876
10877impl From<ReturnStatement> for Statement {
10878    fn from(r: ReturnStatement) -> Self {
10879        Self::Return(r)
10880    }
10881}
10882
10883impl From<ExportData> for Statement {
10884    fn from(e: ExportData) -> Self {
10885        Self::ExportData(e)
10886    }
10887}
10888
10889impl From<CreateUser> for Statement {
10890    fn from(c: CreateUser) -> Self {
10891        Self::CreateUser(c)
10892    }
10893}
10894
10895impl From<VacuumStatement> for Statement {
10896    fn from(v: VacuumStatement) -> Self {
10897        Self::Vacuum(v)
10898    }
10899}
10900
10901#[cfg(test)]
10902mod tests {
10903    use crate::tokenizer::Location;
10904
10905    use super::*;
10906
10907    #[test]
10908    fn test_window_frame_default() {
10909        let window_frame = WindowFrame::default();
10910        assert_eq!(WindowFrameBound::Preceding(None), window_frame.start_bound);
10911    }
10912
10913    #[test]
10914    fn test_grouping_sets_display() {
10915        // a and b in different group
10916        let grouping_sets = Expr::GroupingSets(vec![
10917            vec![Expr::Identifier(Ident::new("a"))],
10918            vec![Expr::Identifier(Ident::new("b"))],
10919        ]);
10920        assert_eq!("GROUPING SETS ((a), (b))", format!("{grouping_sets}"));
10921
10922        // a and b in the same group
10923        let grouping_sets = Expr::GroupingSets(vec![vec![
10924            Expr::Identifier(Ident::new("a")),
10925            Expr::Identifier(Ident::new("b")),
10926        ]]);
10927        assert_eq!("GROUPING SETS ((a, b))", format!("{grouping_sets}"));
10928
10929        // (a, b) and (c, d) in different group
10930        let grouping_sets = Expr::GroupingSets(vec![
10931            vec![
10932                Expr::Identifier(Ident::new("a")),
10933                Expr::Identifier(Ident::new("b")),
10934            ],
10935            vec![
10936                Expr::Identifier(Ident::new("c")),
10937                Expr::Identifier(Ident::new("d")),
10938            ],
10939        ]);
10940        assert_eq!("GROUPING SETS ((a, b), (c, d))", format!("{grouping_sets}"));
10941    }
10942
10943    #[test]
10944    fn test_rollup_display() {
10945        let rollup = Expr::Rollup(vec![vec![Expr::Identifier(Ident::new("a"))]]);
10946        assert_eq!("ROLLUP (a)", format!("{rollup}"));
10947
10948        let rollup = Expr::Rollup(vec![vec![
10949            Expr::Identifier(Ident::new("a")),
10950            Expr::Identifier(Ident::new("b")),
10951        ]]);
10952        assert_eq!("ROLLUP ((a, b))", format!("{rollup}"));
10953
10954        let rollup = Expr::Rollup(vec![
10955            vec![Expr::Identifier(Ident::new("a"))],
10956            vec![Expr::Identifier(Ident::new("b"))],
10957        ]);
10958        assert_eq!("ROLLUP (a, b)", format!("{rollup}"));
10959
10960        let rollup = Expr::Rollup(vec![
10961            vec![Expr::Identifier(Ident::new("a"))],
10962            vec![
10963                Expr::Identifier(Ident::new("b")),
10964                Expr::Identifier(Ident::new("c")),
10965            ],
10966            vec![Expr::Identifier(Ident::new("d"))],
10967        ]);
10968        assert_eq!("ROLLUP (a, (b, c), d)", format!("{rollup}"));
10969    }
10970
10971    #[test]
10972    fn test_cube_display() {
10973        let cube = Expr::Cube(vec![vec![Expr::Identifier(Ident::new("a"))]]);
10974        assert_eq!("CUBE (a)", format!("{cube}"));
10975
10976        let cube = Expr::Cube(vec![vec![
10977            Expr::Identifier(Ident::new("a")),
10978            Expr::Identifier(Ident::new("b")),
10979        ]]);
10980        assert_eq!("CUBE ((a, b))", format!("{cube}"));
10981
10982        let cube = Expr::Cube(vec![
10983            vec![Expr::Identifier(Ident::new("a"))],
10984            vec![Expr::Identifier(Ident::new("b"))],
10985        ]);
10986        assert_eq!("CUBE (a, b)", format!("{cube}"));
10987
10988        let cube = Expr::Cube(vec![
10989            vec![Expr::Identifier(Ident::new("a"))],
10990            vec![
10991                Expr::Identifier(Ident::new("b")),
10992                Expr::Identifier(Ident::new("c")),
10993            ],
10994            vec![Expr::Identifier(Ident::new("d"))],
10995        ]);
10996        assert_eq!("CUBE (a, (b, c), d)", format!("{cube}"));
10997    }
10998
10999    #[test]
11000    fn test_interval_display() {
11001        let interval = Expr::Interval(Interval {
11002            value: Box::new(Expr::Value(
11003                Value::SingleQuotedString(String::from("123:45.67")).with_empty_span(),
11004            )),
11005            leading_field: Some(DateTimeField::Minute),
11006            leading_precision: Some(10),
11007            last_field: Some(DateTimeField::Second),
11008            fractional_seconds_precision: Some(9),
11009        });
11010        assert_eq!(
11011            "INTERVAL '123:45.67' MINUTE (10) TO SECOND (9)",
11012            format!("{interval}"),
11013        );
11014
11015        let interval = Expr::Interval(Interval {
11016            value: Box::new(Expr::Value(
11017                Value::SingleQuotedString(String::from("5")).with_empty_span(),
11018            )),
11019            leading_field: Some(DateTimeField::Second),
11020            leading_precision: Some(1),
11021            last_field: None,
11022            fractional_seconds_precision: Some(3),
11023        });
11024        assert_eq!("INTERVAL '5' SECOND (1, 3)", format!("{interval}"));
11025    }
11026
11027    #[test]
11028    fn test_one_or_many_with_parens_deref() {
11029        use core::ops::Index;
11030
11031        let one = OneOrManyWithParens::One("a");
11032
11033        assert_eq!(one.deref(), &["a"]);
11034        assert_eq!(<OneOrManyWithParens<_> as Deref>::deref(&one), &["a"]);
11035
11036        assert_eq!(one[0], "a");
11037        assert_eq!(one.index(0), &"a");
11038        assert_eq!(
11039            <<OneOrManyWithParens<_> as Deref>::Target as Index<usize>>::index(&one, 0),
11040            &"a"
11041        );
11042
11043        assert_eq!(one.len(), 1);
11044        assert_eq!(<OneOrManyWithParens<_> as Deref>::Target::len(&one), 1);
11045
11046        let many1 = OneOrManyWithParens::Many(vec!["b"]);
11047
11048        assert_eq!(many1.deref(), &["b"]);
11049        assert_eq!(<OneOrManyWithParens<_> as Deref>::deref(&many1), &["b"]);
11050
11051        assert_eq!(many1[0], "b");
11052        assert_eq!(many1.index(0), &"b");
11053        assert_eq!(
11054            <<OneOrManyWithParens<_> as Deref>::Target as Index<usize>>::index(&many1, 0),
11055            &"b"
11056        );
11057
11058        assert_eq!(many1.len(), 1);
11059        assert_eq!(<OneOrManyWithParens<_> as Deref>::Target::len(&many1), 1);
11060
11061        let many2 = OneOrManyWithParens::Many(vec!["c", "d"]);
11062
11063        assert_eq!(many2.deref(), &["c", "d"]);
11064        assert_eq!(
11065            <OneOrManyWithParens<_> as Deref>::deref(&many2),
11066            &["c", "d"]
11067        );
11068
11069        assert_eq!(many2[0], "c");
11070        assert_eq!(many2.index(0), &"c");
11071        assert_eq!(
11072            <<OneOrManyWithParens<_> as Deref>::Target as Index<usize>>::index(&many2, 0),
11073            &"c"
11074        );
11075
11076        assert_eq!(many2[1], "d");
11077        assert_eq!(many2.index(1), &"d");
11078        assert_eq!(
11079            <<OneOrManyWithParens<_> as Deref>::Target as Index<usize>>::index(&many2, 1),
11080            &"d"
11081        );
11082
11083        assert_eq!(many2.len(), 2);
11084        assert_eq!(<OneOrManyWithParens<_> as Deref>::Target::len(&many2), 2);
11085    }
11086
11087    #[test]
11088    fn test_one_or_many_with_parens_as_ref() {
11089        let one = OneOrManyWithParens::One("a");
11090
11091        assert_eq!(one.as_ref(), &["a"]);
11092        assert_eq!(<OneOrManyWithParens<_> as AsRef<_>>::as_ref(&one), &["a"]);
11093
11094        let many1 = OneOrManyWithParens::Many(vec!["b"]);
11095
11096        assert_eq!(many1.as_ref(), &["b"]);
11097        assert_eq!(<OneOrManyWithParens<_> as AsRef<_>>::as_ref(&many1), &["b"]);
11098
11099        let many2 = OneOrManyWithParens::Many(vec!["c", "d"]);
11100
11101        assert_eq!(many2.as_ref(), &["c", "d"]);
11102        assert_eq!(
11103            <OneOrManyWithParens<_> as AsRef<_>>::as_ref(&many2),
11104            &["c", "d"]
11105        );
11106    }
11107
11108    #[test]
11109    fn test_one_or_many_with_parens_ref_into_iter() {
11110        let one = OneOrManyWithParens::One("a");
11111
11112        assert_eq!(Vec::from_iter(&one), vec![&"a"]);
11113
11114        let many1 = OneOrManyWithParens::Many(vec!["b"]);
11115
11116        assert_eq!(Vec::from_iter(&many1), vec![&"b"]);
11117
11118        let many2 = OneOrManyWithParens::Many(vec!["c", "d"]);
11119
11120        assert_eq!(Vec::from_iter(&many2), vec![&"c", &"d"]);
11121    }
11122
11123    #[test]
11124    fn test_one_or_many_with_parens_value_into_iter() {
11125        use core::iter::once;
11126
11127        //tests that our iterator implemented methods behaves exactly as it's inner iterator, at every step up to n calls to next/next_back
11128        fn test_steps<I>(ours: OneOrManyWithParens<usize>, inner: I, n: usize)
11129        where
11130            I: IntoIterator<Item = usize, IntoIter: DoubleEndedIterator + Clone> + Clone,
11131        {
11132            fn checks<I>(ours: OneOrManyWithParensIntoIter<usize>, inner: I)
11133            where
11134                I: Iterator<Item = usize> + Clone + DoubleEndedIterator,
11135            {
11136                assert_eq!(ours.size_hint(), inner.size_hint());
11137                assert_eq!(ours.clone().count(), inner.clone().count());
11138
11139                assert_eq!(
11140                    ours.clone().fold(1, |a, v| a + v),
11141                    inner.clone().fold(1, |a, v| a + v)
11142                );
11143
11144                assert_eq!(Vec::from_iter(ours.clone()), Vec::from_iter(inner.clone()));
11145                assert_eq!(
11146                    Vec::from_iter(ours.clone().rev()),
11147                    Vec::from_iter(inner.clone().rev())
11148                );
11149            }
11150
11151            let mut ours_next = ours.clone().into_iter();
11152            let mut inner_next = inner.clone().into_iter();
11153
11154            for _ in 0..n {
11155                checks(ours_next.clone(), inner_next.clone());
11156
11157                assert_eq!(ours_next.next(), inner_next.next());
11158            }
11159
11160            let mut ours_next_back = ours.clone().into_iter();
11161            let mut inner_next_back = inner.clone().into_iter();
11162
11163            for _ in 0..n {
11164                checks(ours_next_back.clone(), inner_next_back.clone());
11165
11166                assert_eq!(ours_next_back.next_back(), inner_next_back.next_back());
11167            }
11168
11169            let mut ours_mixed = ours.clone().into_iter();
11170            let mut inner_mixed = inner.clone().into_iter();
11171
11172            for i in 0..n {
11173                checks(ours_mixed.clone(), inner_mixed.clone());
11174
11175                if i % 2 == 0 {
11176                    assert_eq!(ours_mixed.next_back(), inner_mixed.next_back());
11177                } else {
11178                    assert_eq!(ours_mixed.next(), inner_mixed.next());
11179                }
11180            }
11181
11182            let mut ours_mixed2 = ours.into_iter();
11183            let mut inner_mixed2 = inner.into_iter();
11184
11185            for i in 0..n {
11186                checks(ours_mixed2.clone(), inner_mixed2.clone());
11187
11188                if i % 2 == 0 {
11189                    assert_eq!(ours_mixed2.next(), inner_mixed2.next());
11190                } else {
11191                    assert_eq!(ours_mixed2.next_back(), inner_mixed2.next_back());
11192                }
11193            }
11194        }
11195
11196        test_steps(OneOrManyWithParens::One(1), once(1), 3);
11197        test_steps(OneOrManyWithParens::Many(vec![2]), vec![2], 3);
11198        test_steps(OneOrManyWithParens::Many(vec![3, 4]), vec![3, 4], 4);
11199    }
11200
11201    // Tests that the position in the code of an `Ident` does not affect its
11202    // ordering.
11203    #[test]
11204    fn test_ident_ord() {
11205        let mut a = Ident::with_span(Span::new(Location::new(1, 1), Location::new(1, 1)), "a");
11206        let mut b = Ident::with_span(Span::new(Location::new(2, 2), Location::new(2, 2)), "b");
11207
11208        assert!(a < b);
11209        std::mem::swap(&mut a.span, &mut b.span);
11210        assert!(a < b);
11211    }
11212}