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