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::Vec,
25};
26use helpers::{
27    attached_token::AttachedToken,
28    stmt_data_loading::{FileStagingCommand, StageLoadSelectItemKind},
29};
30
31use core::cmp::Ordering;
32use core::ops::Deref;
33use core::{
34    fmt::{self, Display},
35    hash,
36};
37
38#[cfg(feature = "serde")]
39use serde::{Deserialize, Serialize};
40
41#[cfg(feature = "visitor")]
42use sqlparser_derive::{Visit, VisitMut};
43
44use crate::{
45    display_utils::{indented_list, SpaceOrNewline},
46    tokenizer::{Span, Token},
47};
48use crate::{
49    display_utils::{Indent, NewLine},
50    keywords::Keyword,
51};
52
53pub use self::data_type::{
54    ArrayElemTypeDef, BinaryLength, CharLengthUnits, CharacterLength, DataType, EnumMember,
55    ExactNumberInfo, StructBracketKind, TimezoneInfo,
56};
57pub use self::dcl::{
58    AlterRoleOperation, ResetConfig, RoleOption, SecondaryRoles, SetConfigValue, Use,
59};
60pub use self::ddl::{
61    AlterColumnOperation, AlterConnectorOwner, AlterIndexOperation, AlterPolicyOperation,
62    AlterTableAlgorithm, AlterTableLock, AlterTableOperation, AlterType, AlterTypeAddValue,
63    AlterTypeAddValuePosition, AlterTypeOperation, AlterTypeRename, AlterTypeRenameValue,
64    ClusteredBy, ColumnDef, ColumnOption, ColumnOptionDef, ColumnOptions, ColumnPolicy,
65    ColumnPolicyProperty, ConstraintCharacteristics, CreateConnector, CreateDomain, CreateFunction,
66    Deduplicate, DeferrableInitial, DropBehavior, GeneratedAs, GeneratedExpressionMode,
67    IdentityParameters, IdentityProperty, IdentityPropertyFormatKind, IdentityPropertyKind,
68    IdentityPropertyOrder, IndexOption, IndexType, KeyOrIndexDisplay, NullsDistinctOption, Owner,
69    Partition, ProcedureParam, ReferentialAction, ReplicaIdentity, TableConstraint,
70    TagsColumnOption, UserDefinedTypeCompositeAttributeDef, UserDefinedTypeRepresentation,
71    ViewColumnDef,
72};
73pub use self::dml::{CreateIndex, CreateTable, Delete, IndexColumn, Insert};
74pub use self::operator::{BinaryOperator, UnaryOperator};
75pub use self::query::{
76    AfterMatchSkip, ConnectBy, Cte, CteAsMaterialized, Distinct, EmptyMatchesMode,
77    ExceptSelectItem, ExcludeSelectItem, ExprWithAlias, ExprWithAliasAndOrderBy, Fetch, ForClause,
78    ForJson, ForXml, FormatClause, GroupByExpr, GroupByWithModifier, IdentWithAlias,
79    IlikeSelectItem, InputFormatClause, Interpolate, InterpolateExpr, Join, JoinConstraint,
80    JoinOperator, JsonTableColumn, JsonTableColumnErrorHandling, JsonTableNamedColumn,
81    JsonTableNestedColumn, LateralView, LimitClause, LockClause, LockType, MatchRecognizePattern,
82    MatchRecognizeSymbol, Measure, NamedWindowDefinition, NamedWindowExpr, NonBlock, Offset,
83    OffsetRows, OpenJsonTableColumn, OrderBy, OrderByExpr, OrderByKind, OrderByOptions,
84    PipeOperator, PivotValueSource, ProjectionSelect, Query, RenameSelectItem,
85    RepetitionQuantifier, ReplaceSelectElement, ReplaceSelectItem, RowsPerMatch, Select,
86    SelectFlavor, SelectInto, SelectItem, SelectItemQualifiedWildcardKind, SetExpr, SetOperator,
87    SetQuantifier, Setting, SymbolDefinition, Table, TableAlias, TableAliasColumnDef, TableFactor,
88    TableFunctionArgs, TableIndexHintForClause, TableIndexHintType, TableIndexHints,
89    TableIndexType, TableSample, TableSampleBucket, TableSampleKind, TableSampleMethod,
90    TableSampleModifier, TableSampleQuantity, TableSampleSeed, TableSampleSeedModifier,
91    TableSampleUnit, TableVersion, TableWithJoins, Top, TopQuantity, UpdateTableFromKind,
92    ValueTableMode, Values, WildcardAdditionalOptions, With, WithFill, XmlNamespaceDefinition,
93    XmlPassingArgument, XmlPassingClause, XmlTableColumn, XmlTableColumnOption,
94};
95
96pub use self::trigger::{
97    TriggerEvent, TriggerExecBody, TriggerExecBodyType, TriggerObject, TriggerPeriod,
98    TriggerReferencing, TriggerReferencingType,
99};
100
101pub use self::value::{
102    escape_double_quote_string, escape_quoted_string, DateTimeField, DollarQuotedString,
103    NormalizationForm, TrimWhereField, Value, ValueWithSpan,
104};
105
106use crate::ast::helpers::key_value_options::KeyValueOptions;
107use crate::ast::helpers::stmt_data_loading::StageParamsObject;
108
109#[cfg(feature = "visitor")]
110pub use visitor::*;
111
112pub use self::data_type::GeometricTypeKind;
113
114mod data_type;
115mod dcl;
116mod ddl;
117mod dml;
118pub mod helpers;
119mod operator;
120mod query;
121mod spans;
122pub use spans::Spanned;
123
124mod trigger;
125mod value;
126
127#[cfg(feature = "visitor")]
128mod visitor;
129
130pub struct DisplaySeparated<'a, T>
131where
132    T: fmt::Display,
133{
134    slice: &'a [T],
135    sep: &'static str,
136}
137
138impl<T> fmt::Display for DisplaySeparated<'_, T>
139where
140    T: fmt::Display,
141{
142    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
143        let mut delim = "";
144        for t in self.slice {
145            f.write_str(delim)?;
146            delim = self.sep;
147            t.fmt(f)?;
148        }
149        Ok(())
150    }
151}
152
153pub fn display_separated<'a, T>(slice: &'a [T], sep: &'static str) -> DisplaySeparated<'a, T>
154where
155    T: fmt::Display,
156{
157    DisplaySeparated { slice, sep }
158}
159
160pub fn display_comma_separated<T>(slice: &[T]) -> DisplaySeparated<'_, T>
161where
162    T: fmt::Display,
163{
164    DisplaySeparated { slice, sep: ", " }
165}
166
167/// Writes the given statements to the formatter, each ending with
168/// a semicolon and space separated.
169fn format_statement_list(f: &mut fmt::Formatter, statements: &[Statement]) -> fmt::Result {
170    write!(f, "{}", display_separated(statements, "; "))?;
171    // We manually insert semicolon for the last statement,
172    // since display_separated doesn't handle that case.
173    write!(f, ";")
174}
175
176/// An identifier, decomposed into its value or character data and the quote style.
177#[derive(Debug, Clone)]
178#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
179#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
180pub struct Ident {
181    /// The value of the identifier without quotes.
182    pub value: String,
183    /// The starting quote if any. Valid quote characters are the single quote,
184    /// double quote, backtick, and opening square bracket.
185    pub quote_style: Option<char>,
186    /// The span of the identifier in the original SQL string.
187    pub span: Span,
188}
189
190impl PartialEq for Ident {
191    fn eq(&self, other: &Self) -> bool {
192        let Ident {
193            value,
194            quote_style,
195            // exhaustiveness check; we ignore spans in comparisons
196            span: _,
197        } = self;
198
199        value == &other.value && quote_style == &other.quote_style
200    }
201}
202
203impl core::hash::Hash for Ident {
204    fn hash<H: hash::Hasher>(&self, state: &mut H) {
205        let Ident {
206            value,
207            quote_style,
208            // exhaustiveness check; we ignore spans in hashes
209            span: _,
210        } = self;
211
212        value.hash(state);
213        quote_style.hash(state);
214    }
215}
216
217impl Eq for Ident {}
218
219impl PartialOrd for Ident {
220    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
221        Some(self.cmp(other))
222    }
223}
224
225impl Ord for Ident {
226    fn cmp(&self, other: &Self) -> Ordering {
227        let Ident {
228            value,
229            quote_style,
230            // exhaustiveness check; we ignore spans in ordering
231            span: _,
232        } = self;
233
234        let Ident {
235            value: other_value,
236            quote_style: other_quote_style,
237            // exhaustiveness check; we ignore spans in ordering
238            span: _,
239        } = other;
240
241        // First compare by value, then by quote_style
242        value
243            .cmp(other_value)
244            .then_with(|| quote_style.cmp(other_quote_style))
245    }
246}
247
248impl Ident {
249    /// Create a new identifier with the given value and no quotes and an empty span.
250    pub fn new<S>(value: S) -> Self
251    where
252        S: Into<String>,
253    {
254        Ident {
255            value: value.into(),
256            quote_style: None,
257            span: Span::empty(),
258        }
259    }
260
261    /// Create a new quoted identifier with the given quote and value. This function
262    /// panics if the given quote is not a valid quote character.
263    pub fn with_quote<S>(quote: char, value: S) -> Self
264    where
265        S: Into<String>,
266    {
267        assert!(quote == '\'' || quote == '"' || quote == '`' || quote == '[');
268        Ident {
269            value: value.into(),
270            quote_style: Some(quote),
271            span: Span::empty(),
272        }
273    }
274
275    pub fn with_span<S>(span: Span, value: S) -> Self
276    where
277        S: Into<String>,
278    {
279        Ident {
280            value: value.into(),
281            quote_style: None,
282            span,
283        }
284    }
285
286    pub fn with_quote_and_span<S>(quote: char, span: Span, value: S) -> Self
287    where
288        S: Into<String>,
289    {
290        assert!(quote == '\'' || quote == '"' || quote == '`' || quote == '[');
291        Ident {
292            value: value.into(),
293            quote_style: Some(quote),
294            span,
295        }
296    }
297}
298
299impl From<&str> for Ident {
300    fn from(value: &str) -> Self {
301        Ident {
302            value: value.to_string(),
303            quote_style: None,
304            span: Span::empty(),
305        }
306    }
307}
308
309impl fmt::Display for Ident {
310    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
311        match self.quote_style {
312            Some(q) if q == '"' || q == '\'' || q == '`' => {
313                let escaped = value::escape_quoted_string(&self.value, q);
314                write!(f, "{q}{escaped}{q}")
315            }
316            Some('[') => write!(f, "[{}]", self.value),
317            None => f.write_str(&self.value),
318            _ => panic!("unexpected quote style"),
319        }
320    }
321}
322
323/// A name of a table, view, custom type, etc., possibly multi-part, i.e. db.schema.obj
324#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
325#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
326#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
327pub struct ObjectName(pub Vec<ObjectNamePart>);
328
329impl From<Vec<Ident>> for ObjectName {
330    fn from(idents: Vec<Ident>) -> Self {
331        ObjectName(idents.into_iter().map(ObjectNamePart::Identifier).collect())
332    }
333}
334
335impl fmt::Display for ObjectName {
336    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
337        write!(f, "{}", display_separated(&self.0, "."))
338    }
339}
340
341/// A single part of an ObjectName
342#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
343#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
344#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
345pub enum ObjectNamePart {
346    Identifier(Ident),
347    Function(ObjectNamePartFunction),
348}
349
350impl ObjectNamePart {
351    pub fn as_ident(&self) -> Option<&Ident> {
352        match self {
353            ObjectNamePart::Identifier(ident) => Some(ident),
354            ObjectNamePart::Function(_) => None,
355        }
356    }
357}
358
359impl fmt::Display for ObjectNamePart {
360    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
361        match self {
362            ObjectNamePart::Identifier(ident) => write!(f, "{ident}"),
363            ObjectNamePart::Function(func) => write!(f, "{func}"),
364        }
365    }
366}
367
368/// An object name part that consists of a function that dynamically
369/// constructs identifiers.
370///
371/// - [Snowflake](https://docs.snowflake.com/en/sql-reference/identifier-literal)
372#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
373#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
374#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
375pub struct ObjectNamePartFunction {
376    pub name: Ident,
377    pub args: Vec<FunctionArg>,
378}
379
380impl fmt::Display for ObjectNamePartFunction {
381    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
382        write!(f, "{}(", self.name)?;
383        write!(f, "{})", display_comma_separated(&self.args))
384    }
385}
386
387/// Represents an Array Expression, either
388/// `ARRAY[..]`, or `[..]`
389#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
390#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
391#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
392pub struct Array {
393    /// The list of expressions between brackets
394    pub elem: Vec<Expr>,
395
396    /// `true` for  `ARRAY[..]`, `false` for `[..]`
397    pub named: bool,
398}
399
400impl fmt::Display for Array {
401    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
402        write!(
403            f,
404            "{}[{}]",
405            if self.named { "ARRAY" } else { "" },
406            display_comma_separated(&self.elem)
407        )
408    }
409}
410
411/// Represents an INTERVAL expression, roughly in the following format:
412/// `INTERVAL '<value>' [ <leading_field> [ (<leading_precision>) ] ]
413/// [ TO <last_field> [ (<fractional_seconds_precision>) ] ]`,
414/// e.g. `INTERVAL '123:45.67' MINUTE(3) TO SECOND(2)`.
415///
416/// The parser does not validate the `<value>`, nor does it ensure
417/// that the `<leading_field>` units >= the units in `<last_field>`,
418/// so the user will have to reject intervals like `HOUR TO YEAR`.
419#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
420#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
421#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
422pub struct Interval {
423    pub value: Box<Expr>,
424    pub leading_field: Option<DateTimeField>,
425    pub leading_precision: Option<u64>,
426    pub last_field: Option<DateTimeField>,
427    /// The seconds precision can be specified in SQL source as
428    /// `INTERVAL '__' SECOND(_, x)` (in which case the `leading_field`
429    /// will be `Second` and the `last_field` will be `None`),
430    /// or as `__ TO SECOND(x)`.
431    pub fractional_seconds_precision: Option<u64>,
432}
433
434impl fmt::Display for Interval {
435    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
436        let value = self.value.as_ref();
437        match (
438            &self.leading_field,
439            self.leading_precision,
440            self.fractional_seconds_precision,
441        ) {
442            (
443                Some(DateTimeField::Second),
444                Some(leading_precision),
445                Some(fractional_seconds_precision),
446            ) => {
447                // When the leading field is SECOND, the parser guarantees that
448                // the last field is None.
449                assert!(self.last_field.is_none());
450                write!(
451                    f,
452                    "INTERVAL {value} SECOND ({leading_precision}, {fractional_seconds_precision})"
453                )
454            }
455            _ => {
456                write!(f, "INTERVAL {value}")?;
457                if let Some(leading_field) = &self.leading_field {
458                    write!(f, " {leading_field}")?;
459                }
460                if let Some(leading_precision) = self.leading_precision {
461                    write!(f, " ({leading_precision})")?;
462                }
463                if let Some(last_field) = &self.last_field {
464                    write!(f, " TO {last_field}")?;
465                }
466                if let Some(fractional_seconds_precision) = self.fractional_seconds_precision {
467                    write!(f, " ({fractional_seconds_precision})")?;
468                }
469                Ok(())
470            }
471        }
472    }
473}
474
475/// A field definition within a struct
476///
477/// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-types#struct_type
478#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
479#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
480#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
481pub struct StructField {
482    pub field_name: Option<Ident>,
483    pub field_type: DataType,
484    /// Struct field options.
485    /// See [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#column_name_and_column_schema)
486    pub options: Option<Vec<SqlOption>>,
487}
488
489impl fmt::Display for StructField {
490    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
491        if let Some(name) = &self.field_name {
492            write!(f, "{name} {}", self.field_type)?;
493        } else {
494            write!(f, "{}", self.field_type)?;
495        }
496        if let Some(options) = &self.options {
497            write!(f, " OPTIONS({})", display_separated(options, ", "))
498        } else {
499            Ok(())
500        }
501    }
502}
503
504/// A field definition within a union
505///
506/// [DuckDB]: https://duckdb.org/docs/sql/data_types/union.html
507#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
508#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
509#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
510pub struct UnionField {
511    pub field_name: Ident,
512    pub field_type: DataType,
513}
514
515impl fmt::Display for UnionField {
516    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
517        write!(f, "{} {}", self.field_name, self.field_type)
518    }
519}
520
521/// A dictionary field within a dictionary.
522///
523/// [DuckDB]: https://duckdb.org/docs/sql/data_types/struct#creating-structs
524#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
525#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
526#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
527pub struct DictionaryField {
528    pub key: Ident,
529    pub value: Box<Expr>,
530}
531
532impl fmt::Display for DictionaryField {
533    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
534        write!(f, "{}: {}", self.key, self.value)
535    }
536}
537
538/// Represents a Map expression.
539#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
540#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
541#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
542pub struct Map {
543    pub entries: Vec<MapEntry>,
544}
545
546impl Display for Map {
547    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
548        write!(f, "MAP {{{}}}", display_comma_separated(&self.entries))
549    }
550}
551
552/// A map field within a map.
553///
554/// [DuckDB]: https://duckdb.org/docs/sql/data_types/map.html#creating-maps
555#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
556#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
557#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
558pub struct MapEntry {
559    pub key: Box<Expr>,
560    pub value: Box<Expr>,
561}
562
563impl fmt::Display for MapEntry {
564    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
565        write!(f, "{}: {}", self.key, self.value)
566    }
567}
568
569/// Options for `CAST` / `TRY_CAST`
570/// BigQuery: <https://cloud.google.com/bigquery/docs/reference/standard-sql/format-elements#formatting_syntax>
571#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
572#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
573#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
574pub enum CastFormat {
575    Value(Value),
576    ValueAtTimeZone(Value, Value),
577}
578
579/// An element of a JSON path.
580#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
581#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
582#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
583pub enum JsonPathElem {
584    /// Accesses an object field using dot notation, e.g. `obj:foo.bar.baz`.
585    ///
586    /// See <https://docs.snowflake.com/en/user-guide/querying-semistructured#dot-notation>.
587    Dot { key: String, quoted: bool },
588    /// Accesses an object field or array element using bracket notation,
589    /// e.g. `obj['foo']`.
590    ///
591    /// See <https://docs.snowflake.com/en/user-guide/querying-semistructured#bracket-notation>.
592    Bracket { key: Expr },
593}
594
595/// A JSON path.
596///
597/// See <https://docs.snowflake.com/en/user-guide/querying-semistructured>.
598/// See <https://docs.databricks.com/en/sql/language-manual/sql-ref-json-path-expression.html>.
599#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
600#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
601#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
602pub struct JsonPath {
603    pub path: Vec<JsonPathElem>,
604}
605
606impl fmt::Display for JsonPath {
607    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
608        for (i, elem) in self.path.iter().enumerate() {
609            match elem {
610                JsonPathElem::Dot { key, quoted } => {
611                    if i == 0 {
612                        write!(f, ":")?;
613                    } else {
614                        write!(f, ".")?;
615                    }
616
617                    if *quoted {
618                        write!(f, "\"{}\"", escape_double_quote_string(key))?;
619                    } else {
620                        write!(f, "{key}")?;
621                    }
622                }
623                JsonPathElem::Bracket { key } => {
624                    write!(f, "[{key}]")?;
625                }
626            }
627        }
628        Ok(())
629    }
630}
631
632/// The syntax used for in a cast expression.
633#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
634#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
635#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
636pub enum CastKind {
637    /// The standard SQL cast syntax, e.g. `CAST(<expr> as <datatype>)`
638    Cast,
639    /// A cast that returns `NULL` on failure, e.g. `TRY_CAST(<expr> as <datatype>)`.
640    ///
641    /// See <https://docs.snowflake.com/en/sql-reference/functions/try_cast>.
642    /// See <https://learn.microsoft.com/en-us/sql/t-sql/functions/try-cast-transact-sql>.
643    TryCast,
644    /// A cast that returns `NULL` on failure, bigQuery-specific ,  e.g. `SAFE_CAST(<expr> as <datatype>)`.
645    ///
646    /// See <https://cloud.google.com/bigquery/docs/reference/standard-sql/functions-and-operators#safe_casting>.
647    SafeCast,
648    /// `<expr> :: <datatype>`
649    DoubleColon,
650}
651
652/// `EXTRACT` syntax variants.
653///
654/// In Snowflake dialect, the `EXTRACT` expression can support either the `from` syntax
655/// or the comma syntax.
656///
657/// See <https://docs.snowflake.com/en/sql-reference/functions/extract>
658#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
659#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
660#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
661pub enum ExtractSyntax {
662    /// `EXTRACT( <date_or_time_part> FROM <date_or_time_expr> )`
663    From,
664    /// `EXTRACT( <date_or_time_part> , <date_or_timestamp_expr> )`
665    Comma,
666}
667
668/// The syntax used in a CEIL or FLOOR expression.
669///
670/// The `CEIL/FLOOR(<datetime value expression> TO <time unit>)` is an Amazon Kinesis Data Analytics extension.
671/// See <https://docs.aws.amazon.com/kinesisanalytics/latest/sqlref/sql-reference-ceil.html> for
672/// details.
673///
674/// Other dialects either support `CEIL/FLOOR( <expr> [, <scale>])` format or just
675/// `CEIL/FLOOR(<expr>)`.
676#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
677#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
678#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
679pub enum CeilFloorKind {
680    /// `CEIL( <expr> TO <DateTimeField>)`
681    DateTimeField(DateTimeField),
682    /// `CEIL( <expr> [, <scale>])`
683    Scale(Value),
684}
685
686/// A WHEN clause in a CASE expression containing both
687/// the condition and its corresponding result
688#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
689#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
690#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
691pub struct CaseWhen {
692    pub condition: Expr,
693    pub result: Expr,
694}
695
696impl fmt::Display for CaseWhen {
697    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
698        f.write_str("WHEN ")?;
699        self.condition.fmt(f)?;
700        f.write_str(" THEN")?;
701        SpaceOrNewline.fmt(f)?;
702        Indent(&self.result).fmt(f)?;
703        Ok(())
704    }
705}
706
707/// An SQL expression of any type.
708///
709/// # Semantics / Type Checking
710///
711/// The parser does not distinguish between expressions of different types
712/// (e.g. boolean vs string). The caller is responsible for detecting and
713/// validating types as necessary (for example  `WHERE 1` vs `SELECT 1=1`)
714/// See the [README.md] for more details.
715///
716/// [README.md]: https://github.com/apache/datafusion-sqlparser-rs/blob/main/README.md#syntax-vs-semantics
717///
718/// # Equality and Hashing Does not Include Source Locations
719///
720/// The `Expr` type implements `PartialEq` and `Eq` based on the semantic value
721/// of the expression (not bitwise comparison). This means that `Expr` instances
722/// that are semantically equivalent but have different spans (locations in the
723/// source tree) will compare as equal.
724#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
725#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
726#[cfg_attr(
727    feature = "visitor",
728    derive(Visit, VisitMut),
729    visit(with = "visit_expr")
730)]
731pub enum Expr {
732    /// Identifier e.g. table name or column name
733    Identifier(Ident),
734    /// Multi-part identifier, e.g. `table_alias.column` or `schema.table.col`
735    CompoundIdentifier(Vec<Ident>),
736    /// Multi-part expression access.
737    ///
738    /// This structure represents an access chain in structured / nested types
739    /// such as maps, arrays, and lists:
740    /// - Array
741    ///     - A 1-dim array `a[1]` will be represented like:
742    ///       `CompoundFieldAccess(Ident('a'), vec![Subscript(1)]`
743    ///     - A 2-dim array `a[1][2]` will be represented like:
744    ///       `CompoundFieldAccess(Ident('a'), vec![Subscript(1), Subscript(2)]`
745    /// - Map or Struct (Bracket-style)
746    ///     - A map `a['field1']` will be represented like:
747    ///       `CompoundFieldAccess(Ident('a'), vec![Subscript('field')]`
748    ///     - A 2-dim map `a['field1']['field2']` will be represented like:
749    ///       `CompoundFieldAccess(Ident('a'), vec![Subscript('field1'), Subscript('field2')]`
750    /// - Struct (Dot-style) (only effect when the chain contains both subscript and expr)
751    ///     - A struct access `a[field1].field2` will be represented like:
752    ///       `CompoundFieldAccess(Ident('a'), vec![Subscript('field1'), Ident('field2')]`
753    /// - If a struct access likes `a.field1.field2`, it will be represented by CompoundIdentifier([a, field1, field2])
754    CompoundFieldAccess {
755        root: Box<Expr>,
756        access_chain: Vec<AccessExpr>,
757    },
758    /// Access data nested in a value containing semi-structured data, such as
759    /// the `VARIANT` type on Snowflake. for example `src:customer[0].name`.
760    ///
761    /// See <https://docs.snowflake.com/en/user-guide/querying-semistructured>.
762    /// See <https://docs.databricks.com/en/sql/language-manual/functions/colonsign.html>.
763    JsonAccess {
764        /// The value being queried.
765        value: Box<Expr>,
766        /// The path to the data to extract.
767        path: JsonPath,
768    },
769    /// `IS FALSE` operator
770    IsFalse(Box<Expr>),
771    /// `IS NOT FALSE` operator
772    IsNotFalse(Box<Expr>),
773    /// `IS TRUE` operator
774    IsTrue(Box<Expr>),
775    /// `IS NOT TRUE` operator
776    IsNotTrue(Box<Expr>),
777    /// `IS NULL` operator
778    IsNull(Box<Expr>),
779    /// `IS NOT NULL` operator
780    IsNotNull(Box<Expr>),
781    /// `IS UNKNOWN` operator
782    IsUnknown(Box<Expr>),
783    /// `IS NOT UNKNOWN` operator
784    IsNotUnknown(Box<Expr>),
785    /// `IS DISTINCT FROM` operator
786    IsDistinctFrom(Box<Expr>, Box<Expr>),
787    /// `IS NOT DISTINCT FROM` operator
788    IsNotDistinctFrom(Box<Expr>, Box<Expr>),
789    /// `<expr> IS [ NOT ] [ form ] NORMALIZED`
790    IsNormalized {
791        expr: Box<Expr>,
792        form: Option<NormalizationForm>,
793        negated: bool,
794    },
795    /// `[ NOT ] IN (val1, val2, ...)`
796    InList {
797        expr: Box<Expr>,
798        list: Vec<Expr>,
799        negated: bool,
800    },
801    /// `[ NOT ] IN (SELECT ...)`
802    InSubquery {
803        expr: Box<Expr>,
804        subquery: Box<Query>,
805        negated: bool,
806    },
807    /// `[ NOT ] IN UNNEST(array_expression)`
808    InUnnest {
809        expr: Box<Expr>,
810        array_expr: Box<Expr>,
811        negated: bool,
812    },
813    /// `<expr> [ NOT ] BETWEEN <low> AND <high>`
814    Between {
815        expr: Box<Expr>,
816        negated: bool,
817        low: Box<Expr>,
818        high: Box<Expr>,
819    },
820    /// Binary operation e.g. `1 + 1` or `foo > bar`
821    BinaryOp {
822        left: Box<Expr>,
823        op: BinaryOperator,
824        right: Box<Expr>,
825    },
826    /// `[NOT] LIKE <pattern> [ESCAPE <escape_character>]`
827    Like {
828        negated: bool,
829        // Snowflake supports the ANY keyword to match against a list of patterns
830        // https://docs.snowflake.com/en/sql-reference/functions/like_any
831        any: bool,
832        expr: Box<Expr>,
833        pattern: Box<Expr>,
834        escape_char: Option<Value>,
835    },
836    /// `ILIKE` (case-insensitive `LIKE`)
837    ILike {
838        negated: bool,
839        // Snowflake supports the ANY keyword to match against a list of patterns
840        // https://docs.snowflake.com/en/sql-reference/functions/like_any
841        any: bool,
842        expr: Box<Expr>,
843        pattern: Box<Expr>,
844        escape_char: Option<Value>,
845    },
846    /// SIMILAR TO regex
847    SimilarTo {
848        negated: bool,
849        expr: Box<Expr>,
850        pattern: Box<Expr>,
851        escape_char: Option<Value>,
852    },
853    /// MySQL: RLIKE regex or REGEXP regex
854    RLike {
855        negated: bool,
856        expr: Box<Expr>,
857        pattern: Box<Expr>,
858        // true for REGEXP, false for RLIKE (no difference in semantics)
859        regexp: bool,
860    },
861    /// `ANY` operation e.g. `foo > ANY(bar)`, comparison operator is one of `[=, >, <, =>, =<, !=]`
862    /// <https://docs.snowflake.com/en/sql-reference/operators-subquery#all-any>
863    AnyOp {
864        left: Box<Expr>,
865        compare_op: BinaryOperator,
866        right: Box<Expr>,
867        // ANY and SOME are synonymous: https://docs.cloudera.com/cdw-runtime/cloud/using-hiveql/topics/hive_comparison_predicates.html
868        is_some: bool,
869    },
870    /// `ALL` operation e.g. `foo > ALL(bar)`, comparison operator is one of `[=, >, <, =>, =<, !=]`
871    /// <https://docs.snowflake.com/en/sql-reference/operators-subquery#all-any>
872    AllOp {
873        left: Box<Expr>,
874        compare_op: BinaryOperator,
875        right: Box<Expr>,
876    },
877    /// Unary operation e.g. `NOT foo`
878    UnaryOp {
879        op: UnaryOperator,
880        expr: Box<Expr>,
881    },
882    /// CONVERT a value to a different data type or character encoding. e.g. `CONVERT(foo USING utf8mb4)`
883    Convert {
884        /// CONVERT (false) or TRY_CONVERT (true)
885        /// <https://learn.microsoft.com/en-us/sql/t-sql/functions/try-convert-transact-sql?view=sql-server-ver16>
886        is_try: bool,
887        /// The expression to convert
888        expr: Box<Expr>,
889        /// The target data type
890        data_type: Option<DataType>,
891        /// The target character encoding
892        charset: Option<ObjectName>,
893        /// whether the target comes before the expr (MSSQL syntax)
894        target_before_value: bool,
895        /// How to translate the expression.
896        ///
897        /// [MSSQL]: https://learn.microsoft.com/en-us/sql/t-sql/functions/cast-and-convert-transact-sql?view=sql-server-ver16#style
898        styles: Vec<Expr>,
899    },
900    /// `CAST` an expression to a different data type e.g. `CAST(foo AS VARCHAR(123))`
901    Cast {
902        kind: CastKind,
903        expr: Box<Expr>,
904        data_type: DataType,
905        /// Optional CAST(string_expression AS type FORMAT format_string_expression) as used by [BigQuery]
906        ///
907        /// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/format-elements#formatting_syntax
908        format: Option<CastFormat>,
909    },
910    /// AT a timestamp to a different timezone e.g. `FROM_UNIXTIME(0) AT TIME ZONE 'UTC-06:00'`
911    AtTimeZone {
912        timestamp: Box<Expr>,
913        time_zone: Box<Expr>,
914    },
915    /// Extract a field from a timestamp e.g. `EXTRACT(MONTH FROM foo)`
916    /// Or `EXTRACT(MONTH, foo)`
917    ///
918    /// Syntax:
919    /// ```sql
920    /// EXTRACT(DateTimeField FROM <expr>) | EXTRACT(DateTimeField, <expr>)
921    /// ```
922    Extract {
923        field: DateTimeField,
924        syntax: ExtractSyntax,
925        expr: Box<Expr>,
926    },
927    /// ```sql
928    /// CEIL(<expr> [TO DateTimeField])
929    /// ```
930    /// ```sql
931    /// CEIL( <input_expr> [, <scale_expr> ] )
932    /// ```
933    Ceil {
934        expr: Box<Expr>,
935        field: CeilFloorKind,
936    },
937    /// ```sql
938    /// FLOOR(<expr> [TO DateTimeField])
939    /// ```
940    /// ```sql
941    /// FLOOR( <input_expr> [, <scale_expr> ] )
942    ///
943    Floor {
944        expr: Box<Expr>,
945        field: CeilFloorKind,
946    },
947    /// ```sql
948    /// POSITION(<expr> in <expr>)
949    /// ```
950    Position {
951        expr: Box<Expr>,
952        r#in: Box<Expr>,
953    },
954    /// ```sql
955    /// SUBSTRING(<expr> [FROM <expr>] [FOR <expr>])
956    /// ```
957    /// or
958    /// ```sql
959    /// SUBSTRING(<expr>, <expr>, <expr>)
960    /// ```
961    Substring {
962        expr: Box<Expr>,
963        substring_from: Option<Box<Expr>>,
964        substring_for: Option<Box<Expr>>,
965
966        /// false if the expression is represented using the `SUBSTRING(expr [FROM start] [FOR len])` syntax
967        /// true if the expression is represented using the `SUBSTRING(expr, start, len)` syntax
968        /// This flag is used for formatting.
969        special: bool,
970
971        /// true if the expression is represented using the `SUBSTR` shorthand
972        /// This flag is used for formatting.
973        shorthand: bool,
974    },
975    /// ```sql
976    /// TRIM([BOTH | LEADING | TRAILING] [<expr> FROM] <expr>)
977    /// TRIM(<expr>)
978    /// TRIM(<expr>, [, characters]) -- only Snowflake or Bigquery
979    /// ```
980    Trim {
981        expr: Box<Expr>,
982        // ([BOTH | LEADING | TRAILING]
983        trim_where: Option<TrimWhereField>,
984        trim_what: Option<Box<Expr>>,
985        trim_characters: Option<Vec<Expr>>,
986    },
987    /// ```sql
988    /// OVERLAY(<expr> PLACING <expr> FROM <expr>[ FOR <expr> ]
989    /// ```
990    Overlay {
991        expr: Box<Expr>,
992        overlay_what: Box<Expr>,
993        overlay_from: Box<Expr>,
994        overlay_for: Option<Box<Expr>>,
995    },
996    /// `expr COLLATE collation`
997    Collate {
998        expr: Box<Expr>,
999        collation: ObjectName,
1000    },
1001    /// Nested expression e.g. `(foo > bar)` or `(1)`
1002    Nested(Box<Expr>),
1003    /// A literal value, such as string, number, date or NULL
1004    Value(ValueWithSpan),
1005    /// Prefixed expression, e.g. introducer strings, projection prefix
1006    /// <https://dev.mysql.com/doc/refman/8.0/en/charset-introducer.html>
1007    /// <https://docs.snowflake.com/en/sql-reference/constructs/connect-by>
1008    Prefixed {
1009        prefix: Ident,
1010        /// The value of the constant.
1011        /// Hint: you can unwrap the string value using `value.into_string()`.
1012        value: Box<Expr>,
1013    },
1014    /// A constant of form `<data_type> 'value'`.
1015    /// This can represent ANSI SQL `DATE`, `TIME`, and `TIMESTAMP` literals (such as `DATE '2020-01-01'`),
1016    /// as well as constants of other types (a non-standard PostgreSQL extension).
1017    TypedString {
1018        data_type: DataType,
1019        /// The value of the constant.
1020        /// Hint: you can unwrap the string value using `value.into_string()`.
1021        value: ValueWithSpan,
1022    },
1023    /// Scalar function call e.g. `LEFT(foo, 5)`
1024    Function(Function),
1025    /// `CASE [<operand>] WHEN <condition> THEN <result> ... [ELSE <result>] END`
1026    ///
1027    /// Note we only recognize a complete single expression as `<condition>`,
1028    /// not `< 0` nor `1, 2, 3` as allowed in a `<simple when clause>` per
1029    /// <https://jakewheat.github.io/sql-overview/sql-2011-foundation-grammar.html#simple-when-clause>
1030    Case {
1031        case_token: AttachedToken,
1032        end_token: AttachedToken,
1033        operand: Option<Box<Expr>>,
1034        conditions: Vec<CaseWhen>,
1035        else_result: Option<Box<Expr>>,
1036    },
1037    /// An exists expression `[ NOT ] EXISTS(SELECT ...)`, used in expressions like
1038    /// `WHERE [ NOT ] EXISTS (SELECT ...)`.
1039    Exists {
1040        subquery: Box<Query>,
1041        negated: bool,
1042    },
1043    /// A parenthesized subquery `(SELECT ...)`, used in expression like
1044    /// `SELECT (subquery) AS x` or `WHERE (subquery) = x`
1045    Subquery(Box<Query>),
1046    /// The `GROUPING SETS` expr.
1047    GroupingSets(Vec<Vec<Expr>>),
1048    /// The `CUBE` expr.
1049    Cube(Vec<Vec<Expr>>),
1050    /// The `ROLLUP` expr.
1051    Rollup(Vec<Vec<Expr>>),
1052    /// ROW / TUPLE a single value, such as `SELECT (1, 2)`
1053    Tuple(Vec<Expr>),
1054    /// `Struct` literal expression
1055    /// Syntax:
1056    /// ```sql
1057    /// STRUCT<[field_name] field_type, ...>( expr1 [, ... ])
1058    ///
1059    /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-types#struct_type)
1060    /// [Databricks](https://docs.databricks.com/en/sql/language-manual/functions/struct.html)
1061    /// ```
1062    Struct {
1063        /// Struct values.
1064        values: Vec<Expr>,
1065        /// Struct field definitions.
1066        fields: Vec<StructField>,
1067    },
1068    /// `BigQuery` specific: An named expression in a typeless struct [1]
1069    ///
1070    /// Syntax
1071    /// ```sql
1072    /// 1 AS A
1073    /// ```
1074    /// [1]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-types#struct_type
1075    Named {
1076        expr: Box<Expr>,
1077        name: Ident,
1078    },
1079    /// `DuckDB` specific `Struct` literal expression [1]
1080    ///
1081    /// Syntax:
1082    /// ```sql
1083    /// syntax: {'field_name': expr1[, ... ]}
1084    /// ```
1085    /// [1]: https://duckdb.org/docs/sql/data_types/struct#creating-structs
1086    Dictionary(Vec<DictionaryField>),
1087    /// `DuckDB` specific `Map` literal expression [1]
1088    ///
1089    /// Syntax:
1090    /// ```sql
1091    /// syntax: Map {key1: value1[, ... ]}
1092    /// ```
1093    /// [1]: https://duckdb.org/docs/sql/data_types/map#creating-maps
1094    Map(Map),
1095    /// An array expression e.g. `ARRAY[1, 2]`
1096    Array(Array),
1097    /// An interval expression e.g. `INTERVAL '1' YEAR`
1098    Interval(Interval),
1099    /// `MySQL` specific text search function [(1)].
1100    ///
1101    /// Syntax:
1102    /// ```sql
1103    /// MATCH (<col>, <col>, ...) AGAINST (<expr> [<search modifier>])
1104    ///
1105    /// <col> = CompoundIdentifier
1106    /// <expr> = String literal
1107    /// ```
1108    /// [(1)]: https://dev.mysql.com/doc/refman/8.0/en/fulltext-search.html#function_match
1109    MatchAgainst {
1110        /// `(<col>, <col>, ...)`.
1111        columns: Vec<ObjectName>,
1112        /// `<expr>`.
1113        match_value: Value,
1114        /// `<search modifier>`
1115        opt_search_modifier: Option<SearchModifier>,
1116    },
1117    Wildcard(AttachedToken),
1118    /// Qualified wildcard, e.g. `alias.*` or `schema.table.*`.
1119    /// (Same caveats apply to `QualifiedWildcard` as to `Wildcard`.)
1120    QualifiedWildcard(ObjectName, AttachedToken),
1121    /// Some dialects support an older syntax for outer joins where columns are
1122    /// marked with the `(+)` operator in the WHERE clause, for example:
1123    ///
1124    /// ```sql
1125    /// SELECT t1.c1, t2.c2 FROM t1, t2 WHERE t1.c1 = t2.c2 (+)
1126    /// ```
1127    ///
1128    /// which is equivalent to
1129    ///
1130    /// ```sql
1131    /// SELECT t1.c1, t2.c2 FROM t1 LEFT OUTER JOIN t2 ON t1.c1 = t2.c2
1132    /// ```
1133    ///
1134    /// See <https://docs.snowflake.com/en/sql-reference/constructs/where#joins-in-the-where-clause>.
1135    OuterJoin(Box<Expr>),
1136    /// A reference to the prior level in a CONNECT BY clause.
1137    Prior(Box<Expr>),
1138    /// A lambda function.
1139    ///
1140    /// Syntax:
1141    /// ```plaintext
1142    /// param -> expr | (param1, ...) -> expr
1143    /// ```
1144    ///
1145    /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/functions#higher-order-functions---operator-and-lambdaparams-expr-function)
1146    /// [Databricks](https://docs.databricks.com/en/sql/language-manual/sql-ref-lambda-functions.html)
1147    /// [DuckDb](https://duckdb.org/docs/sql/functions/lambda.html)
1148    Lambda(LambdaFunction),
1149    /// Checks membership of a value in a JSON array
1150    MemberOf(MemberOf),
1151}
1152
1153impl Expr {
1154    /// Creates a new [`Expr::Value`]
1155    pub fn value(value: impl Into<ValueWithSpan>) -> Self {
1156        Expr::Value(value.into())
1157    }
1158}
1159
1160/// The contents inside the `[` and `]` in a subscript expression.
1161#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1162#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1163#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1164pub enum Subscript {
1165    /// Accesses the element of the array at the given index.
1166    Index { index: Expr },
1167
1168    /// Accesses a slice of an array on PostgreSQL, e.g.
1169    ///
1170    /// ```plaintext
1171    /// => select (array[1,2,3,4,5,6])[2:5];
1172    /// -----------
1173    /// {2,3,4,5}
1174    /// ```
1175    ///
1176    /// The lower and/or upper bound can be omitted to slice from the start or
1177    /// end of the array respectively.
1178    ///
1179    /// See <https://www.postgresql.org/docs/current/arrays.html#ARRAYS-ACCESSING>.
1180    ///
1181    /// Also supports an optional "stride" as the last element (this is not
1182    /// supported by postgres), e.g.
1183    ///
1184    /// ```plaintext
1185    /// => select (array[1,2,3,4,5,6])[1:6:2];
1186    /// -----------
1187    /// {1,3,5}
1188    /// ```
1189    Slice {
1190        lower_bound: Option<Expr>,
1191        upper_bound: Option<Expr>,
1192        stride: Option<Expr>,
1193    },
1194}
1195
1196impl fmt::Display for Subscript {
1197    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1198        match self {
1199            Subscript::Index { index } => write!(f, "{index}"),
1200            Subscript::Slice {
1201                lower_bound,
1202                upper_bound,
1203                stride,
1204            } => {
1205                if let Some(lower) = lower_bound {
1206                    write!(f, "{lower}")?;
1207                }
1208                write!(f, ":")?;
1209                if let Some(upper) = upper_bound {
1210                    write!(f, "{upper}")?;
1211                }
1212                if let Some(stride) = stride {
1213                    write!(f, ":")?;
1214                    write!(f, "{stride}")?;
1215                }
1216                Ok(())
1217            }
1218        }
1219    }
1220}
1221
1222/// An element of a [`Expr::CompoundFieldAccess`].
1223/// It can be an expression or a subscript.
1224#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1225#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1226#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1227pub enum AccessExpr {
1228    /// Accesses a field using dot notation, e.g. `foo.bar.baz`.
1229    Dot(Expr),
1230    /// Accesses a field or array element using bracket notation, e.g. `foo['bar']`.
1231    Subscript(Subscript),
1232}
1233
1234impl fmt::Display for AccessExpr {
1235    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1236        match self {
1237            AccessExpr::Dot(expr) => write!(f, ".{expr}"),
1238            AccessExpr::Subscript(subscript) => write!(f, "[{subscript}]"),
1239        }
1240    }
1241}
1242
1243/// A lambda function.
1244#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1245#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1246#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1247pub struct LambdaFunction {
1248    /// The parameters to the lambda function.
1249    pub params: OneOrManyWithParens<Ident>,
1250    /// The body of the lambda function.
1251    pub body: Box<Expr>,
1252}
1253
1254impl fmt::Display for LambdaFunction {
1255    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1256        write!(f, "{} -> {}", self.params, self.body)
1257    }
1258}
1259
1260/// Encapsulates the common pattern in SQL where either one unparenthesized item
1261/// such as an identifier or expression is permitted, or multiple of the same
1262/// item in a parenthesized list. For accessing items regardless of the form,
1263/// `OneOrManyWithParens` implements `Deref<Target = [T]>` and `IntoIterator`,
1264/// so you can call slice methods on it and iterate over items
1265/// # Examples
1266/// Accessing as a slice:
1267/// ```
1268/// # use sqlparser::ast::OneOrManyWithParens;
1269/// let one = OneOrManyWithParens::One("a");
1270///
1271/// assert_eq!(one[0], "a");
1272/// assert_eq!(one.len(), 1);
1273/// ```
1274/// Iterating:
1275/// ```
1276/// # use sqlparser::ast::OneOrManyWithParens;
1277/// let one = OneOrManyWithParens::One("a");
1278/// let many = OneOrManyWithParens::Many(vec!["a", "b"]);
1279///
1280/// assert_eq!(one.into_iter().chain(many).collect::<Vec<_>>(), vec!["a", "a", "b"] );
1281/// ```
1282#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1283#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1284#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1285pub enum OneOrManyWithParens<T> {
1286    /// A single `T`, unparenthesized.
1287    One(T),
1288    /// One or more `T`s, parenthesized.
1289    Many(Vec<T>),
1290}
1291
1292impl<T> Deref for OneOrManyWithParens<T> {
1293    type Target = [T];
1294
1295    fn deref(&self) -> &[T] {
1296        match self {
1297            OneOrManyWithParens::One(one) => core::slice::from_ref(one),
1298            OneOrManyWithParens::Many(many) => many,
1299        }
1300    }
1301}
1302
1303impl<T> AsRef<[T]> for OneOrManyWithParens<T> {
1304    fn as_ref(&self) -> &[T] {
1305        self
1306    }
1307}
1308
1309impl<'a, T> IntoIterator for &'a OneOrManyWithParens<T> {
1310    type Item = &'a T;
1311    type IntoIter = core::slice::Iter<'a, T>;
1312
1313    fn into_iter(self) -> Self::IntoIter {
1314        self.iter()
1315    }
1316}
1317
1318/// Owned iterator implementation of `OneOrManyWithParens`
1319#[derive(Debug, Clone)]
1320pub struct OneOrManyWithParensIntoIter<T> {
1321    inner: OneOrManyWithParensIntoIterInner<T>,
1322}
1323
1324#[derive(Debug, Clone)]
1325enum OneOrManyWithParensIntoIterInner<T> {
1326    One(core::iter::Once<T>),
1327    Many(<Vec<T> as IntoIterator>::IntoIter),
1328}
1329
1330impl<T> core::iter::FusedIterator for OneOrManyWithParensIntoIter<T>
1331where
1332    core::iter::Once<T>: core::iter::FusedIterator,
1333    <Vec<T> as IntoIterator>::IntoIter: core::iter::FusedIterator,
1334{
1335}
1336
1337impl<T> core::iter::ExactSizeIterator for OneOrManyWithParensIntoIter<T>
1338where
1339    core::iter::Once<T>: core::iter::ExactSizeIterator,
1340    <Vec<T> as IntoIterator>::IntoIter: core::iter::ExactSizeIterator,
1341{
1342}
1343
1344impl<T> core::iter::Iterator for OneOrManyWithParensIntoIter<T> {
1345    type Item = T;
1346
1347    fn next(&mut self) -> Option<Self::Item> {
1348        match &mut self.inner {
1349            OneOrManyWithParensIntoIterInner::One(one) => one.next(),
1350            OneOrManyWithParensIntoIterInner::Many(many) => many.next(),
1351        }
1352    }
1353
1354    fn size_hint(&self) -> (usize, Option<usize>) {
1355        match &self.inner {
1356            OneOrManyWithParensIntoIterInner::One(one) => one.size_hint(),
1357            OneOrManyWithParensIntoIterInner::Many(many) => many.size_hint(),
1358        }
1359    }
1360
1361    fn count(self) -> usize
1362    where
1363        Self: Sized,
1364    {
1365        match self.inner {
1366            OneOrManyWithParensIntoIterInner::One(one) => one.count(),
1367            OneOrManyWithParensIntoIterInner::Many(many) => many.count(),
1368        }
1369    }
1370
1371    fn fold<B, F>(mut self, init: B, f: F) -> B
1372    where
1373        Self: Sized,
1374        F: FnMut(B, Self::Item) -> B,
1375    {
1376        match &mut self.inner {
1377            OneOrManyWithParensIntoIterInner::One(one) => one.fold(init, f),
1378            OneOrManyWithParensIntoIterInner::Many(many) => many.fold(init, f),
1379        }
1380    }
1381}
1382
1383impl<T> core::iter::DoubleEndedIterator for OneOrManyWithParensIntoIter<T> {
1384    fn next_back(&mut self) -> Option<Self::Item> {
1385        match &mut self.inner {
1386            OneOrManyWithParensIntoIterInner::One(one) => one.next_back(),
1387            OneOrManyWithParensIntoIterInner::Many(many) => many.next_back(),
1388        }
1389    }
1390}
1391
1392impl<T> IntoIterator for OneOrManyWithParens<T> {
1393    type Item = T;
1394
1395    type IntoIter = OneOrManyWithParensIntoIter<T>;
1396
1397    fn into_iter(self) -> Self::IntoIter {
1398        let inner = match self {
1399            OneOrManyWithParens::One(one) => {
1400                OneOrManyWithParensIntoIterInner::One(core::iter::once(one))
1401            }
1402            OneOrManyWithParens::Many(many) => {
1403                OneOrManyWithParensIntoIterInner::Many(many.into_iter())
1404            }
1405        };
1406
1407        OneOrManyWithParensIntoIter { inner }
1408    }
1409}
1410
1411impl<T> fmt::Display for OneOrManyWithParens<T>
1412where
1413    T: fmt::Display,
1414{
1415    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1416        match self {
1417            OneOrManyWithParens::One(value) => write!(f, "{value}"),
1418            OneOrManyWithParens::Many(values) => {
1419                write!(f, "({})", display_comma_separated(values))
1420            }
1421        }
1422    }
1423}
1424
1425impl fmt::Display for CastFormat {
1426    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1427        match self {
1428            CastFormat::Value(v) => write!(f, "{v}"),
1429            CastFormat::ValueAtTimeZone(v, tz) => write!(f, "{v} AT TIME ZONE {tz}"),
1430        }
1431    }
1432}
1433
1434impl fmt::Display for Expr {
1435    #[cfg_attr(feature = "recursive-protection", recursive::recursive)]
1436    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1437        match self {
1438            Expr::Identifier(s) => write!(f, "{s}"),
1439            Expr::Wildcard(_) => f.write_str("*"),
1440            Expr::QualifiedWildcard(prefix, _) => write!(f, "{prefix}.*"),
1441            Expr::CompoundIdentifier(s) => write!(f, "{}", display_separated(s, ".")),
1442            Expr::CompoundFieldAccess { root, access_chain } => {
1443                write!(f, "{root}")?;
1444                for field in access_chain {
1445                    write!(f, "{field}")?;
1446                }
1447                Ok(())
1448            }
1449            Expr::IsTrue(ast) => write!(f, "{ast} IS TRUE"),
1450            Expr::IsNotTrue(ast) => write!(f, "{ast} IS NOT TRUE"),
1451            Expr::IsFalse(ast) => write!(f, "{ast} IS FALSE"),
1452            Expr::IsNotFalse(ast) => write!(f, "{ast} IS NOT FALSE"),
1453            Expr::IsNull(ast) => write!(f, "{ast} IS NULL"),
1454            Expr::IsNotNull(ast) => write!(f, "{ast} IS NOT NULL"),
1455            Expr::IsUnknown(ast) => write!(f, "{ast} IS UNKNOWN"),
1456            Expr::IsNotUnknown(ast) => write!(f, "{ast} IS NOT UNKNOWN"),
1457            Expr::InList {
1458                expr,
1459                list,
1460                negated,
1461            } => write!(
1462                f,
1463                "{} {}IN ({})",
1464                expr,
1465                if *negated { "NOT " } else { "" },
1466                display_comma_separated(list)
1467            ),
1468            Expr::InSubquery {
1469                expr,
1470                subquery,
1471                negated,
1472            } => write!(
1473                f,
1474                "{} {}IN ({})",
1475                expr,
1476                if *negated { "NOT " } else { "" },
1477                subquery
1478            ),
1479            Expr::InUnnest {
1480                expr,
1481                array_expr,
1482                negated,
1483            } => write!(
1484                f,
1485                "{} {}IN UNNEST({})",
1486                expr,
1487                if *negated { "NOT " } else { "" },
1488                array_expr
1489            ),
1490            Expr::Between {
1491                expr,
1492                negated,
1493                low,
1494                high,
1495            } => write!(
1496                f,
1497                "{} {}BETWEEN {} AND {}",
1498                expr,
1499                if *negated { "NOT " } else { "" },
1500                low,
1501                high
1502            ),
1503            Expr::BinaryOp { left, op, right } => write!(f, "{left} {op} {right}"),
1504            Expr::Like {
1505                negated,
1506                expr,
1507                pattern,
1508                escape_char,
1509                any,
1510            } => match escape_char {
1511                Some(ch) => write!(
1512                    f,
1513                    "{} {}LIKE {}{} ESCAPE {}",
1514                    expr,
1515                    if *negated { "NOT " } else { "" },
1516                    if *any { "ANY " } else { "" },
1517                    pattern,
1518                    ch
1519                ),
1520                _ => write!(
1521                    f,
1522                    "{} {}LIKE {}{}",
1523                    expr,
1524                    if *negated { "NOT " } else { "" },
1525                    if *any { "ANY " } else { "" },
1526                    pattern
1527                ),
1528            },
1529            Expr::ILike {
1530                negated,
1531                expr,
1532                pattern,
1533                escape_char,
1534                any,
1535            } => match escape_char {
1536                Some(ch) => write!(
1537                    f,
1538                    "{} {}ILIKE {}{} ESCAPE {}",
1539                    expr,
1540                    if *negated { "NOT " } else { "" },
1541                    if *any { "ANY" } else { "" },
1542                    pattern,
1543                    ch
1544                ),
1545                _ => write!(
1546                    f,
1547                    "{} {}ILIKE {}{}",
1548                    expr,
1549                    if *negated { "NOT " } else { "" },
1550                    if *any { "ANY " } else { "" },
1551                    pattern
1552                ),
1553            },
1554            Expr::RLike {
1555                negated,
1556                expr,
1557                pattern,
1558                regexp,
1559            } => write!(
1560                f,
1561                "{} {}{} {}",
1562                expr,
1563                if *negated { "NOT " } else { "" },
1564                if *regexp { "REGEXP" } else { "RLIKE" },
1565                pattern
1566            ),
1567            Expr::IsNormalized {
1568                expr,
1569                form,
1570                negated,
1571            } => {
1572                let not_ = if *negated { "NOT " } else { "" };
1573                if form.is_none() {
1574                    write!(f, "{expr} IS {not_}NORMALIZED")
1575                } else {
1576                    write!(
1577                        f,
1578                        "{} IS {}{} NORMALIZED",
1579                        expr,
1580                        not_,
1581                        form.as_ref().unwrap()
1582                    )
1583                }
1584            }
1585            Expr::SimilarTo {
1586                negated,
1587                expr,
1588                pattern,
1589                escape_char,
1590            } => match escape_char {
1591                Some(ch) => write!(
1592                    f,
1593                    "{} {}SIMILAR TO {} ESCAPE {}",
1594                    expr,
1595                    if *negated { "NOT " } else { "" },
1596                    pattern,
1597                    ch
1598                ),
1599                _ => write!(
1600                    f,
1601                    "{} {}SIMILAR TO {}",
1602                    expr,
1603                    if *negated { "NOT " } else { "" },
1604                    pattern
1605                ),
1606            },
1607            Expr::AnyOp {
1608                left,
1609                compare_op,
1610                right,
1611                is_some,
1612            } => {
1613                let add_parens = !matches!(right.as_ref(), Expr::Subquery(_));
1614                write!(
1615                    f,
1616                    "{left} {compare_op} {}{}{right}{}",
1617                    if *is_some { "SOME" } else { "ANY" },
1618                    if add_parens { "(" } else { "" },
1619                    if add_parens { ")" } else { "" },
1620                )
1621            }
1622            Expr::AllOp {
1623                left,
1624                compare_op,
1625                right,
1626            } => {
1627                let add_parens = !matches!(right.as_ref(), Expr::Subquery(_));
1628                write!(
1629                    f,
1630                    "{left} {compare_op} ALL{}{right}{}",
1631                    if add_parens { "(" } else { "" },
1632                    if add_parens { ")" } else { "" },
1633                )
1634            }
1635            Expr::UnaryOp { op, expr } => {
1636                if op == &UnaryOperator::PGPostfixFactorial {
1637                    write!(f, "{expr}{op}")
1638                } else if matches!(
1639                    op,
1640                    UnaryOperator::Not
1641                        | UnaryOperator::Hash
1642                        | UnaryOperator::AtDashAt
1643                        | UnaryOperator::DoubleAt
1644                        | UnaryOperator::QuestionDash
1645                        | UnaryOperator::QuestionPipe
1646                ) {
1647                    write!(f, "{op} {expr}")
1648                } else {
1649                    write!(f, "{op}{expr}")
1650                }
1651            }
1652            Expr::Convert {
1653                is_try,
1654                expr,
1655                target_before_value,
1656                data_type,
1657                charset,
1658                styles,
1659            } => {
1660                write!(f, "{}CONVERT(", if *is_try { "TRY_" } else { "" })?;
1661                if let Some(data_type) = data_type {
1662                    if let Some(charset) = charset {
1663                        write!(f, "{expr}, {data_type} CHARACTER SET {charset}")
1664                    } else if *target_before_value {
1665                        write!(f, "{data_type}, {expr}")
1666                    } else {
1667                        write!(f, "{expr}, {data_type}")
1668                    }
1669                } else if let Some(charset) = charset {
1670                    write!(f, "{expr} USING {charset}")
1671                } else {
1672                    write!(f, "{expr}") // This should never happen
1673                }?;
1674                if !styles.is_empty() {
1675                    write!(f, ", {}", display_comma_separated(styles))?;
1676                }
1677                write!(f, ")")
1678            }
1679            Expr::Cast {
1680                kind,
1681                expr,
1682                data_type,
1683                format,
1684            } => match kind {
1685                CastKind::Cast => {
1686                    if let Some(format) = format {
1687                        write!(f, "CAST({expr} AS {data_type} FORMAT {format})")
1688                    } else {
1689                        write!(f, "CAST({expr} AS {data_type})")
1690                    }
1691                }
1692                CastKind::TryCast => {
1693                    if let Some(format) = format {
1694                        write!(f, "TRY_CAST({expr} AS {data_type} FORMAT {format})")
1695                    } else {
1696                        write!(f, "TRY_CAST({expr} AS {data_type})")
1697                    }
1698                }
1699                CastKind::SafeCast => {
1700                    if let Some(format) = format {
1701                        write!(f, "SAFE_CAST({expr} AS {data_type} FORMAT {format})")
1702                    } else {
1703                        write!(f, "SAFE_CAST({expr} AS {data_type})")
1704                    }
1705                }
1706                CastKind::DoubleColon => {
1707                    write!(f, "{expr}::{data_type}")
1708                }
1709            },
1710            Expr::Extract {
1711                field,
1712                syntax,
1713                expr,
1714            } => match syntax {
1715                ExtractSyntax::From => write!(f, "EXTRACT({field} FROM {expr})"),
1716                ExtractSyntax::Comma => write!(f, "EXTRACT({field}, {expr})"),
1717            },
1718            Expr::Ceil { expr, field } => match field {
1719                CeilFloorKind::DateTimeField(DateTimeField::NoDateTime) => {
1720                    write!(f, "CEIL({expr})")
1721                }
1722                CeilFloorKind::DateTimeField(dt_field) => write!(f, "CEIL({expr} TO {dt_field})"),
1723                CeilFloorKind::Scale(s) => write!(f, "CEIL({expr}, {s})"),
1724            },
1725            Expr::Floor { expr, field } => match field {
1726                CeilFloorKind::DateTimeField(DateTimeField::NoDateTime) => {
1727                    write!(f, "FLOOR({expr})")
1728                }
1729                CeilFloorKind::DateTimeField(dt_field) => write!(f, "FLOOR({expr} TO {dt_field})"),
1730                CeilFloorKind::Scale(s) => write!(f, "FLOOR({expr}, {s})"),
1731            },
1732            Expr::Position { expr, r#in } => write!(f, "POSITION({expr} IN {in})"),
1733            Expr::Collate { expr, collation } => write!(f, "{expr} COLLATE {collation}"),
1734            Expr::Nested(ast) => write!(f, "({ast})"),
1735            Expr::Value(v) => write!(f, "{v}"),
1736            Expr::Prefixed { prefix, value } => write!(f, "{prefix} {value}"),
1737            Expr::TypedString { data_type, value } => {
1738                write!(f, "{data_type}")?;
1739                write!(f, " {value}")
1740            }
1741            Expr::Function(fun) => fun.fmt(f),
1742            Expr::Case {
1743                case_token: _,
1744                end_token: _,
1745                operand,
1746                conditions,
1747                else_result,
1748            } => {
1749                f.write_str("CASE")?;
1750                if let Some(operand) = operand {
1751                    f.write_str(" ")?;
1752                    operand.fmt(f)?;
1753                }
1754                for when in conditions {
1755                    SpaceOrNewline.fmt(f)?;
1756                    Indent(when).fmt(f)?;
1757                }
1758                if let Some(else_result) = else_result {
1759                    SpaceOrNewline.fmt(f)?;
1760                    Indent("ELSE").fmt(f)?;
1761                    SpaceOrNewline.fmt(f)?;
1762                    Indent(Indent(else_result)).fmt(f)?;
1763                }
1764                SpaceOrNewline.fmt(f)?;
1765                f.write_str("END")
1766            }
1767            Expr::Exists { subquery, negated } => write!(
1768                f,
1769                "{}EXISTS ({})",
1770                if *negated { "NOT " } else { "" },
1771                subquery
1772            ),
1773            Expr::Subquery(s) => write!(f, "({s})"),
1774            Expr::GroupingSets(sets) => {
1775                write!(f, "GROUPING SETS (")?;
1776                let mut sep = "";
1777                for set in sets {
1778                    write!(f, "{sep}")?;
1779                    sep = ", ";
1780                    write!(f, "({})", display_comma_separated(set))?;
1781                }
1782                write!(f, ")")
1783            }
1784            Expr::Cube(sets) => {
1785                write!(f, "CUBE (")?;
1786                let mut sep = "";
1787                for set in sets {
1788                    write!(f, "{sep}")?;
1789                    sep = ", ";
1790                    if set.len() == 1 {
1791                        write!(f, "{}", set[0])?;
1792                    } else {
1793                        write!(f, "({})", display_comma_separated(set))?;
1794                    }
1795                }
1796                write!(f, ")")
1797            }
1798            Expr::Rollup(sets) => {
1799                write!(f, "ROLLUP (")?;
1800                let mut sep = "";
1801                for set in sets {
1802                    write!(f, "{sep}")?;
1803                    sep = ", ";
1804                    if set.len() == 1 {
1805                        write!(f, "{}", set[0])?;
1806                    } else {
1807                        write!(f, "({})", display_comma_separated(set))?;
1808                    }
1809                }
1810                write!(f, ")")
1811            }
1812            Expr::Substring {
1813                expr,
1814                substring_from,
1815                substring_for,
1816                special,
1817                shorthand,
1818            } => {
1819                f.write_str("SUBSTR")?;
1820                if !*shorthand {
1821                    f.write_str("ING")?;
1822                }
1823                write!(f, "({expr}")?;
1824                if let Some(from_part) = substring_from {
1825                    if *special {
1826                        write!(f, ", {from_part}")?;
1827                    } else {
1828                        write!(f, " FROM {from_part}")?;
1829                    }
1830                }
1831                if let Some(for_part) = substring_for {
1832                    if *special {
1833                        write!(f, ", {for_part}")?;
1834                    } else {
1835                        write!(f, " FOR {for_part}")?;
1836                    }
1837                }
1838
1839                write!(f, ")")
1840            }
1841            Expr::Overlay {
1842                expr,
1843                overlay_what,
1844                overlay_from,
1845                overlay_for,
1846            } => {
1847                write!(
1848                    f,
1849                    "OVERLAY({expr} PLACING {overlay_what} FROM {overlay_from}"
1850                )?;
1851                if let Some(for_part) = overlay_for {
1852                    write!(f, " FOR {for_part}")?;
1853                }
1854
1855                write!(f, ")")
1856            }
1857            Expr::IsDistinctFrom(a, b) => write!(f, "{a} IS DISTINCT FROM {b}"),
1858            Expr::IsNotDistinctFrom(a, b) => write!(f, "{a} IS NOT DISTINCT FROM {b}"),
1859            Expr::Trim {
1860                expr,
1861                trim_where,
1862                trim_what,
1863                trim_characters,
1864            } => {
1865                write!(f, "TRIM(")?;
1866                if let Some(ident) = trim_where {
1867                    write!(f, "{ident} ")?;
1868                }
1869                if let Some(trim_char) = trim_what {
1870                    write!(f, "{trim_char} FROM {expr}")?;
1871                } else {
1872                    write!(f, "{expr}")?;
1873                }
1874                if let Some(characters) = trim_characters {
1875                    write!(f, ", {}", display_comma_separated(characters))?;
1876                }
1877
1878                write!(f, ")")
1879            }
1880            Expr::Tuple(exprs) => {
1881                write!(f, "({})", display_comma_separated(exprs))
1882            }
1883            Expr::Struct { values, fields } => {
1884                if !fields.is_empty() {
1885                    write!(
1886                        f,
1887                        "STRUCT<{}>({})",
1888                        display_comma_separated(fields),
1889                        display_comma_separated(values)
1890                    )
1891                } else {
1892                    write!(f, "STRUCT({})", display_comma_separated(values))
1893                }
1894            }
1895            Expr::Named { expr, name } => {
1896                write!(f, "{expr} AS {name}")
1897            }
1898            Expr::Dictionary(fields) => {
1899                write!(f, "{{{}}}", display_comma_separated(fields))
1900            }
1901            Expr::Map(map) => {
1902                write!(f, "{map}")
1903            }
1904            Expr::Array(set) => {
1905                write!(f, "{set}")
1906            }
1907            Expr::JsonAccess { value, path } => {
1908                write!(f, "{value}{path}")
1909            }
1910            Expr::AtTimeZone {
1911                timestamp,
1912                time_zone,
1913            } => {
1914                write!(f, "{timestamp} AT TIME ZONE {time_zone}")
1915            }
1916            Expr::Interval(interval) => {
1917                write!(f, "{interval}")
1918            }
1919            Expr::MatchAgainst {
1920                columns,
1921                match_value: match_expr,
1922                opt_search_modifier,
1923            } => {
1924                write!(f, "MATCH ({}) AGAINST ", display_comma_separated(columns),)?;
1925
1926                if let Some(search_modifier) = opt_search_modifier {
1927                    write!(f, "({match_expr} {search_modifier})")?;
1928                } else {
1929                    write!(f, "({match_expr})")?;
1930                }
1931
1932                Ok(())
1933            }
1934            Expr::OuterJoin(expr) => {
1935                write!(f, "{expr} (+)")
1936            }
1937            Expr::Prior(expr) => write!(f, "PRIOR {expr}"),
1938            Expr::Lambda(lambda) => write!(f, "{lambda}"),
1939            Expr::MemberOf(member_of) => write!(f, "{member_of}"),
1940        }
1941    }
1942}
1943
1944#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1945#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1946#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1947pub enum WindowType {
1948    WindowSpec(WindowSpec),
1949    NamedWindow(Ident),
1950}
1951
1952impl Display for WindowType {
1953    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1954        match self {
1955            WindowType::WindowSpec(spec) => {
1956                f.write_str("(")?;
1957                NewLine.fmt(f)?;
1958                Indent(spec).fmt(f)?;
1959                NewLine.fmt(f)?;
1960                f.write_str(")")
1961            }
1962            WindowType::NamedWindow(name) => name.fmt(f),
1963        }
1964    }
1965}
1966
1967/// A window specification (i.e. `OVER ([window_name] PARTITION BY .. ORDER BY .. etc.)`)
1968#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1969#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1970#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1971pub struct WindowSpec {
1972    /// Optional window name.
1973    ///
1974    /// You can find it at least in [MySQL][1], [BigQuery][2], [PostgreSQL][3]
1975    ///
1976    /// [1]: https://dev.mysql.com/doc/refman/8.0/en/window-functions-named-windows.html
1977    /// [2]: https://cloud.google.com/bigquery/docs/reference/standard-sql/window-function-calls
1978    /// [3]: https://www.postgresql.org/docs/current/sql-expressions.html#SYNTAX-WINDOW-FUNCTIONS
1979    pub window_name: Option<Ident>,
1980    /// `OVER (PARTITION BY ...)`
1981    pub partition_by: Vec<Expr>,
1982    /// `OVER (ORDER BY ...)`
1983    pub order_by: Vec<OrderByExpr>,
1984    /// `OVER (window frame)`
1985    pub window_frame: Option<WindowFrame>,
1986}
1987
1988impl fmt::Display for WindowSpec {
1989    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1990        let mut is_first = true;
1991        if let Some(window_name) = &self.window_name {
1992            if !is_first {
1993                SpaceOrNewline.fmt(f)?;
1994            }
1995            is_first = false;
1996            write!(f, "{window_name}")?;
1997        }
1998        if !self.partition_by.is_empty() {
1999            if !is_first {
2000                SpaceOrNewline.fmt(f)?;
2001            }
2002            is_first = false;
2003            write!(
2004                f,
2005                "PARTITION BY {}",
2006                display_comma_separated(&self.partition_by)
2007            )?;
2008        }
2009        if !self.order_by.is_empty() {
2010            if !is_first {
2011                SpaceOrNewline.fmt(f)?;
2012            }
2013            is_first = false;
2014            write!(f, "ORDER BY {}", display_comma_separated(&self.order_by))?;
2015        }
2016        if let Some(window_frame) = &self.window_frame {
2017            if !is_first {
2018                SpaceOrNewline.fmt(f)?;
2019            }
2020            if let Some(end_bound) = &window_frame.end_bound {
2021                write!(
2022                    f,
2023                    "{} BETWEEN {} AND {}",
2024                    window_frame.units, window_frame.start_bound, end_bound
2025                )?;
2026            } else {
2027                write!(f, "{} {}", window_frame.units, window_frame.start_bound)?;
2028            }
2029        }
2030        Ok(())
2031    }
2032}
2033
2034/// Specifies the data processed by a window function, e.g.
2035/// `RANGE UNBOUNDED PRECEDING` or `ROWS BETWEEN 5 PRECEDING AND CURRENT ROW`.
2036///
2037/// Note: The parser does not validate the specified bounds; the caller should
2038/// reject invalid bounds like `ROWS UNBOUNDED FOLLOWING` before execution.
2039#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2040#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2041#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2042pub struct WindowFrame {
2043    pub units: WindowFrameUnits,
2044    pub start_bound: WindowFrameBound,
2045    /// The right bound of the `BETWEEN .. AND` clause. The end bound of `None`
2046    /// indicates the shorthand form (e.g. `ROWS 1 PRECEDING`), which must
2047    /// behave the same as `end_bound = WindowFrameBound::CurrentRow`.
2048    pub end_bound: Option<WindowFrameBound>,
2049    // TBD: EXCLUDE
2050}
2051
2052impl Default for WindowFrame {
2053    /// Returns default value for window frame
2054    ///
2055    /// See [this page](https://www.sqlite.org/windowfunctions.html#frame_specifications) for more details.
2056    fn default() -> Self {
2057        Self {
2058            units: WindowFrameUnits::Range,
2059            start_bound: WindowFrameBound::Preceding(None),
2060            end_bound: None,
2061        }
2062    }
2063}
2064
2065#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2066#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2067#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2068pub enum WindowFrameUnits {
2069    Rows,
2070    Range,
2071    Groups,
2072}
2073
2074impl fmt::Display for WindowFrameUnits {
2075    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2076        f.write_str(match self {
2077            WindowFrameUnits::Rows => "ROWS",
2078            WindowFrameUnits::Range => "RANGE",
2079            WindowFrameUnits::Groups => "GROUPS",
2080        })
2081    }
2082}
2083
2084/// Specifies Ignore / Respect NULL within window functions.
2085/// For example
2086/// `FIRST_VALUE(column2) IGNORE NULLS OVER (PARTITION BY column1)`
2087#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2088#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2089#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2090pub enum NullTreatment {
2091    IgnoreNulls,
2092    RespectNulls,
2093}
2094
2095impl fmt::Display for NullTreatment {
2096    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2097        f.write_str(match self {
2098            NullTreatment::IgnoreNulls => "IGNORE NULLS",
2099            NullTreatment::RespectNulls => "RESPECT NULLS",
2100        })
2101    }
2102}
2103
2104/// Specifies [WindowFrame]'s `start_bound` and `end_bound`
2105#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2106#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2107#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2108pub enum WindowFrameBound {
2109    /// `CURRENT ROW`
2110    CurrentRow,
2111    /// `<N> PRECEDING` or `UNBOUNDED PRECEDING`
2112    Preceding(Option<Box<Expr>>),
2113    /// `<N> FOLLOWING` or `UNBOUNDED FOLLOWING`.
2114    Following(Option<Box<Expr>>),
2115}
2116
2117impl fmt::Display for WindowFrameBound {
2118    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2119        match self {
2120            WindowFrameBound::CurrentRow => f.write_str("CURRENT ROW"),
2121            WindowFrameBound::Preceding(None) => f.write_str("UNBOUNDED PRECEDING"),
2122            WindowFrameBound::Following(None) => f.write_str("UNBOUNDED FOLLOWING"),
2123            WindowFrameBound::Preceding(Some(n)) => write!(f, "{n} PRECEDING"),
2124            WindowFrameBound::Following(Some(n)) => write!(f, "{n} FOLLOWING"),
2125        }
2126    }
2127}
2128
2129#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2130#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2131#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2132pub enum AddDropSync {
2133    ADD,
2134    DROP,
2135    SYNC,
2136}
2137
2138impl fmt::Display for AddDropSync {
2139    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2140        match self {
2141            AddDropSync::SYNC => f.write_str("SYNC PARTITIONS"),
2142            AddDropSync::DROP => f.write_str("DROP PARTITIONS"),
2143            AddDropSync::ADD => f.write_str("ADD PARTITIONS"),
2144        }
2145    }
2146}
2147
2148#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2149#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2150#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2151pub enum ShowCreateObject {
2152    Event,
2153    Function,
2154    Procedure,
2155    Table,
2156    Trigger,
2157    View,
2158}
2159
2160impl fmt::Display for ShowCreateObject {
2161    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2162        match self {
2163            ShowCreateObject::Event => f.write_str("EVENT"),
2164            ShowCreateObject::Function => f.write_str("FUNCTION"),
2165            ShowCreateObject::Procedure => f.write_str("PROCEDURE"),
2166            ShowCreateObject::Table => f.write_str("TABLE"),
2167            ShowCreateObject::Trigger => f.write_str("TRIGGER"),
2168            ShowCreateObject::View => f.write_str("VIEW"),
2169        }
2170    }
2171}
2172
2173#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2174#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2175#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2176pub enum CommentObject {
2177    Column,
2178    Table,
2179    Extension,
2180    Schema,
2181    Database,
2182    User,
2183    Role,
2184}
2185
2186impl fmt::Display for CommentObject {
2187    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2188        match self {
2189            CommentObject::Column => f.write_str("COLUMN"),
2190            CommentObject::Table => f.write_str("TABLE"),
2191            CommentObject::Extension => f.write_str("EXTENSION"),
2192            CommentObject::Schema => f.write_str("SCHEMA"),
2193            CommentObject::Database => f.write_str("DATABASE"),
2194            CommentObject::User => f.write_str("USER"),
2195            CommentObject::Role => f.write_str("ROLE"),
2196        }
2197    }
2198}
2199
2200#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2201#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2202#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2203pub enum Password {
2204    Password(Expr),
2205    NullPassword,
2206}
2207
2208/// A `CASE` statement.
2209///
2210/// Examples:
2211/// ```sql
2212/// CASE
2213///     WHEN EXISTS(SELECT 1)
2214///         THEN SELECT 1 FROM T;
2215///     WHEN EXISTS(SELECT 2)
2216///         THEN SELECT 1 FROM U;
2217///     ELSE
2218///         SELECT 1 FROM V;
2219/// END CASE;
2220/// ```
2221///
2222/// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#case_search_expression)
2223/// [Snowflake](https://docs.snowflake.com/en/sql-reference/snowflake-scripting/case)
2224#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2225#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2226#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2227pub struct CaseStatement {
2228    /// The `CASE` token that starts the statement.
2229    pub case_token: AttachedToken,
2230    pub match_expr: Option<Expr>,
2231    pub when_blocks: Vec<ConditionalStatementBlock>,
2232    pub else_block: Option<ConditionalStatementBlock>,
2233    /// The last token of the statement (`END` or `CASE`).
2234    pub end_case_token: AttachedToken,
2235}
2236
2237impl fmt::Display for CaseStatement {
2238    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2239        let CaseStatement {
2240            case_token: _,
2241            match_expr,
2242            when_blocks,
2243            else_block,
2244            end_case_token: AttachedToken(end),
2245        } = self;
2246
2247        write!(f, "CASE")?;
2248
2249        if let Some(expr) = match_expr {
2250            write!(f, " {expr}")?;
2251        }
2252
2253        if !when_blocks.is_empty() {
2254            write!(f, " {}", display_separated(when_blocks, " "))?;
2255        }
2256
2257        if let Some(else_block) = else_block {
2258            write!(f, " {else_block}")?;
2259        }
2260
2261        write!(f, " END")?;
2262
2263        if let Token::Word(w) = &end.token {
2264            if w.keyword == Keyword::CASE {
2265                write!(f, " CASE")?;
2266            }
2267        }
2268
2269        Ok(())
2270    }
2271}
2272
2273/// An `IF` statement.
2274///
2275/// Example (BigQuery or Snowflake):
2276/// ```sql
2277/// IF TRUE THEN
2278///     SELECT 1;
2279///     SELECT 2;
2280/// ELSEIF TRUE THEN
2281///     SELECT 3;
2282/// ELSE
2283///     SELECT 4;
2284/// END IF
2285/// ```
2286/// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#if)
2287/// [Snowflake](https://docs.snowflake.com/en/sql-reference/snowflake-scripting/if)
2288///
2289/// Example (MSSQL):
2290/// ```sql
2291/// IF 1=1 SELECT 1 ELSE SELECT 2
2292/// ```
2293/// [MSSQL](https://learn.microsoft.com/en-us/sql/t-sql/language-elements/if-else-transact-sql?view=sql-server-ver16)
2294#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2295#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2296#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2297pub struct IfStatement {
2298    pub if_block: ConditionalStatementBlock,
2299    pub elseif_blocks: Vec<ConditionalStatementBlock>,
2300    pub else_block: Option<ConditionalStatementBlock>,
2301    pub end_token: Option<AttachedToken>,
2302}
2303
2304impl fmt::Display for IfStatement {
2305    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2306        let IfStatement {
2307            if_block,
2308            elseif_blocks,
2309            else_block,
2310            end_token,
2311        } = self;
2312
2313        write!(f, "{if_block}")?;
2314
2315        for elseif_block in elseif_blocks {
2316            write!(f, " {elseif_block}")?;
2317        }
2318
2319        if let Some(else_block) = else_block {
2320            write!(f, " {else_block}")?;
2321        }
2322
2323        if let Some(AttachedToken(end_token)) = end_token {
2324            write!(f, " END {end_token}")?;
2325        }
2326
2327        Ok(())
2328    }
2329}
2330
2331/// A `WHILE` statement.
2332///
2333/// Example:
2334/// ```sql
2335/// WHILE @@FETCH_STATUS = 0
2336/// BEGIN
2337///    FETCH NEXT FROM c1 INTO @var1, @var2;
2338/// END
2339/// ```
2340///
2341/// [MsSql](https://learn.microsoft.com/en-us/sql/t-sql/language-elements/while-transact-sql)
2342#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2343#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2344#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2345pub struct WhileStatement {
2346    pub while_block: ConditionalStatementBlock,
2347}
2348
2349impl fmt::Display for WhileStatement {
2350    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2351        let WhileStatement { while_block } = self;
2352        write!(f, "{while_block}")?;
2353        Ok(())
2354    }
2355}
2356
2357/// A block within a [Statement::Case] or [Statement::If] or [Statement::While]-like statement
2358///
2359/// Example 1:
2360/// ```sql
2361/// WHEN EXISTS(SELECT 1) THEN SELECT 1;
2362/// ```
2363///
2364/// Example 2:
2365/// ```sql
2366/// IF TRUE THEN SELECT 1; SELECT 2;
2367/// ```
2368///
2369/// Example 3:
2370/// ```sql
2371/// ELSE SELECT 1; SELECT 2;
2372/// ```
2373///
2374/// Example 4:
2375/// ```sql
2376/// WHILE @@FETCH_STATUS = 0
2377/// BEGIN
2378///    FETCH NEXT FROM c1 INTO @var1, @var2;
2379/// END
2380/// ```
2381#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2382#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2383#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2384pub struct ConditionalStatementBlock {
2385    pub start_token: AttachedToken,
2386    pub condition: Option<Expr>,
2387    pub then_token: Option<AttachedToken>,
2388    pub conditional_statements: ConditionalStatements,
2389}
2390
2391impl ConditionalStatementBlock {
2392    pub fn statements(&self) -> &Vec<Statement> {
2393        self.conditional_statements.statements()
2394    }
2395}
2396
2397impl fmt::Display for ConditionalStatementBlock {
2398    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2399        let ConditionalStatementBlock {
2400            start_token: AttachedToken(start_token),
2401            condition,
2402            then_token,
2403            conditional_statements,
2404        } = self;
2405
2406        write!(f, "{start_token}")?;
2407
2408        if let Some(condition) = condition {
2409            write!(f, " {condition}")?;
2410        }
2411
2412        if then_token.is_some() {
2413            write!(f, " THEN")?;
2414        }
2415
2416        if !conditional_statements.statements().is_empty() {
2417            write!(f, " {conditional_statements}")?;
2418        }
2419
2420        Ok(())
2421    }
2422}
2423
2424/// A list of statements in a [ConditionalStatementBlock].
2425#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2426#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2427#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2428pub enum ConditionalStatements {
2429    /// SELECT 1; SELECT 2; SELECT 3; ...
2430    Sequence { statements: Vec<Statement> },
2431    /// BEGIN SELECT 1; SELECT 2; SELECT 3; ... END
2432    BeginEnd(BeginEndStatements),
2433}
2434
2435impl ConditionalStatements {
2436    pub fn statements(&self) -> &Vec<Statement> {
2437        match self {
2438            ConditionalStatements::Sequence { statements } => statements,
2439            ConditionalStatements::BeginEnd(bes) => &bes.statements,
2440        }
2441    }
2442}
2443
2444impl fmt::Display for ConditionalStatements {
2445    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2446        match self {
2447            ConditionalStatements::Sequence { statements } => {
2448                if !statements.is_empty() {
2449                    format_statement_list(f, statements)?;
2450                }
2451                Ok(())
2452            }
2453            ConditionalStatements::BeginEnd(bes) => write!(f, "{bes}"),
2454        }
2455    }
2456}
2457
2458/// Represents a list of statements enclosed within `BEGIN` and `END` keywords.
2459/// Example:
2460/// ```sql
2461/// BEGIN
2462///     SELECT 1;
2463///     SELECT 2;
2464/// END
2465/// ```
2466#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2467#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2468#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2469pub struct BeginEndStatements {
2470    pub begin_token: AttachedToken,
2471    pub statements: Vec<Statement>,
2472    pub end_token: AttachedToken,
2473}
2474
2475impl fmt::Display for BeginEndStatements {
2476    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2477        let BeginEndStatements {
2478            begin_token: AttachedToken(begin_token),
2479            statements,
2480            end_token: AttachedToken(end_token),
2481        } = self;
2482
2483        if begin_token.token != Token::EOF {
2484            write!(f, "{begin_token} ")?;
2485        }
2486        if !statements.is_empty() {
2487            format_statement_list(f, statements)?;
2488        }
2489        if end_token.token != Token::EOF {
2490            write!(f, " {end_token}")?;
2491        }
2492        Ok(())
2493    }
2494}
2495
2496/// A `RAISE` statement.
2497///
2498/// Examples:
2499/// ```sql
2500/// RAISE USING MESSAGE = 'error';
2501///
2502/// RAISE myerror;
2503/// ```
2504///
2505/// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#raise)
2506/// [Snowflake](https://docs.snowflake.com/en/sql-reference/snowflake-scripting/raise)
2507#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2508#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2509#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2510pub struct RaiseStatement {
2511    pub value: Option<RaiseStatementValue>,
2512}
2513
2514impl fmt::Display for RaiseStatement {
2515    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2516        let RaiseStatement { value } = self;
2517
2518        write!(f, "RAISE")?;
2519        if let Some(value) = value {
2520            write!(f, " {value}")?;
2521        }
2522
2523        Ok(())
2524    }
2525}
2526
2527/// Represents the error value of a [RaiseStatement].
2528#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2529#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2530#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2531pub enum RaiseStatementValue {
2532    /// `RAISE USING MESSAGE = 'error'`
2533    UsingMessage(Expr),
2534    /// `RAISE myerror`
2535    Expr(Expr),
2536}
2537
2538impl fmt::Display for RaiseStatementValue {
2539    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2540        match self {
2541            RaiseStatementValue::Expr(expr) => write!(f, "{expr}"),
2542            RaiseStatementValue::UsingMessage(expr) => write!(f, "USING MESSAGE = {expr}"),
2543        }
2544    }
2545}
2546
2547/// Represents an expression assignment within a variable `DECLARE` statement.
2548///
2549/// Examples:
2550/// ```sql
2551/// DECLARE variable_name := 42
2552/// DECLARE variable_name DEFAULT 42
2553/// ```
2554#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2555#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2556#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2557pub enum DeclareAssignment {
2558    /// Plain expression specified.
2559    Expr(Box<Expr>),
2560
2561    /// Expression assigned via the `DEFAULT` keyword
2562    Default(Box<Expr>),
2563
2564    /// Expression assigned via the `:=` syntax
2565    ///
2566    /// Example:
2567    /// ```sql
2568    /// DECLARE variable_name := 42;
2569    /// ```
2570    DuckAssignment(Box<Expr>),
2571
2572    /// Expression via the `FOR` keyword
2573    ///
2574    /// Example:
2575    /// ```sql
2576    /// DECLARE c1 CURSOR FOR res
2577    /// ```
2578    For(Box<Expr>),
2579
2580    /// Expression via the `=` syntax.
2581    ///
2582    /// Example:
2583    /// ```sql
2584    /// DECLARE @variable AS INT = 100
2585    /// ```
2586    MsSqlAssignment(Box<Expr>),
2587}
2588
2589impl fmt::Display for DeclareAssignment {
2590    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2591        match self {
2592            DeclareAssignment::Expr(expr) => {
2593                write!(f, "{expr}")
2594            }
2595            DeclareAssignment::Default(expr) => {
2596                write!(f, "DEFAULT {expr}")
2597            }
2598            DeclareAssignment::DuckAssignment(expr) => {
2599                write!(f, ":= {expr}")
2600            }
2601            DeclareAssignment::MsSqlAssignment(expr) => {
2602                write!(f, "= {expr}")
2603            }
2604            DeclareAssignment::For(expr) => {
2605                write!(f, "FOR {expr}")
2606            }
2607        }
2608    }
2609}
2610
2611/// Represents the type of a `DECLARE` statement.
2612#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2613#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2614#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2615pub enum DeclareType {
2616    /// Cursor variable type. e.g. [Snowflake] [PostgreSQL] [MsSql]
2617    ///
2618    /// [Snowflake]: https://docs.snowflake.com/en/developer-guide/snowflake-scripting/cursors#declaring-a-cursor
2619    /// [PostgreSQL]: https://www.postgresql.org/docs/current/plpgsql-cursors.html
2620    /// [MsSql]: https://learn.microsoft.com/en-us/sql/t-sql/language-elements/declare-cursor-transact-sql
2621    Cursor,
2622
2623    /// Result set variable type. [Snowflake]
2624    ///
2625    /// Syntax:
2626    /// ```text
2627    /// <resultset_name> RESULTSET [ { DEFAULT | := } ( <query> ) ] ;
2628    /// ```
2629    /// [Snowflake]: https://docs.snowflake.com/en/sql-reference/snowflake-scripting/declare#resultset-declaration-syntax
2630    ResultSet,
2631
2632    /// Exception declaration syntax. [Snowflake]
2633    ///
2634    /// Syntax:
2635    /// ```text
2636    /// <exception_name> EXCEPTION [ ( <exception_number> , '<exception_message>' ) ] ;
2637    /// ```
2638    /// [Snowflake]: https://docs.snowflake.com/en/sql-reference/snowflake-scripting/declare#exception-declaration-syntax
2639    Exception,
2640}
2641
2642impl fmt::Display for DeclareType {
2643    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2644        match self {
2645            DeclareType::Cursor => {
2646                write!(f, "CURSOR")
2647            }
2648            DeclareType::ResultSet => {
2649                write!(f, "RESULTSET")
2650            }
2651            DeclareType::Exception => {
2652                write!(f, "EXCEPTION")
2653            }
2654        }
2655    }
2656}
2657
2658/// A `DECLARE` statement.
2659/// [PostgreSQL] [Snowflake] [BigQuery]
2660///
2661/// Examples:
2662/// ```sql
2663/// DECLARE variable_name := 42
2664/// DECLARE liahona CURSOR FOR SELECT * FROM films;
2665/// ```
2666///
2667/// [PostgreSQL]: https://www.postgresql.org/docs/current/sql-declare.html
2668/// [Snowflake]: https://docs.snowflake.com/en/sql-reference/snowflake-scripting/declare
2669/// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#declare
2670#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2671#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2672#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2673pub struct Declare {
2674    /// The name(s) being declared.
2675    /// Example: `DECLARE a, b, c DEFAULT 42;
2676    pub names: Vec<Ident>,
2677    /// Data-type assigned to the declared variable.
2678    /// Example: `DECLARE x INT64 DEFAULT 42;
2679    pub data_type: Option<DataType>,
2680    /// Expression being assigned to the declared variable.
2681    pub assignment: Option<DeclareAssignment>,
2682    /// Represents the type of the declared variable.
2683    pub declare_type: Option<DeclareType>,
2684    /// Causes the cursor to return data in binary rather than in text format.
2685    pub binary: Option<bool>,
2686    /// None = Not specified
2687    /// Some(true) = INSENSITIVE
2688    /// Some(false) = ASENSITIVE
2689    pub sensitive: Option<bool>,
2690    /// None = Not specified
2691    /// Some(true) = SCROLL
2692    /// Some(false) = NO SCROLL
2693    pub scroll: Option<bool>,
2694    /// None = Not specified
2695    /// Some(true) = WITH HOLD, specifies that the cursor can continue to be used after the transaction that created it successfully commits
2696    /// Some(false) = WITHOUT HOLD, specifies that the cursor cannot be used outside of the transaction that created it
2697    pub hold: Option<bool>,
2698    /// `FOR <query>` clause in a CURSOR declaration.
2699    pub for_query: Option<Box<Query>>,
2700}
2701
2702impl fmt::Display for Declare {
2703    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2704        let Declare {
2705            names,
2706            data_type,
2707            assignment,
2708            declare_type,
2709            binary,
2710            sensitive,
2711            scroll,
2712            hold,
2713            for_query,
2714        } = self;
2715        write!(f, "{}", display_comma_separated(names))?;
2716
2717        if let Some(true) = binary {
2718            write!(f, " BINARY")?;
2719        }
2720
2721        if let Some(sensitive) = sensitive {
2722            if *sensitive {
2723                write!(f, " INSENSITIVE")?;
2724            } else {
2725                write!(f, " ASENSITIVE")?;
2726            }
2727        }
2728
2729        if let Some(scroll) = scroll {
2730            if *scroll {
2731                write!(f, " SCROLL")?;
2732            } else {
2733                write!(f, " NO SCROLL")?;
2734            }
2735        }
2736
2737        if let Some(declare_type) = declare_type {
2738            write!(f, " {declare_type}")?;
2739        }
2740
2741        if let Some(hold) = hold {
2742            if *hold {
2743                write!(f, " WITH HOLD")?;
2744            } else {
2745                write!(f, " WITHOUT HOLD")?;
2746            }
2747        }
2748
2749        if let Some(query) = for_query {
2750            write!(f, " FOR {query}")?;
2751        }
2752
2753        if let Some(data_type) = data_type {
2754            write!(f, " {data_type}")?;
2755        }
2756
2757        if let Some(expr) = assignment {
2758            write!(f, " {expr}")?;
2759        }
2760        Ok(())
2761    }
2762}
2763
2764/// Sql options of a `CREATE TABLE` statement.
2765#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2766#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2767#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2768pub enum CreateTableOptions {
2769    None,
2770    /// Options specified using the `WITH` keyword.
2771    /// e.g. `WITH (description = "123")`
2772    ///
2773    /// <https://www.postgresql.org/docs/current/sql-createtable.html>
2774    ///
2775    /// MSSQL supports more specific options that's not only key-value pairs.
2776    ///
2777    /// WITH (
2778    ///     DISTRIBUTION = ROUND_ROBIN,
2779    ///     CLUSTERED INDEX (column_a DESC, column_b)
2780    /// )
2781    ///
2782    /// <https://learn.microsoft.com/en-us/sql/t-sql/statements/create-table-azure-sql-data-warehouse?view=aps-pdw-2016-au7#syntax>
2783    With(Vec<SqlOption>),
2784    /// Options specified using the `OPTIONS` keyword.
2785    /// e.g. `OPTIONS(description = "123")`
2786    ///
2787    /// <https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#table_option_list>
2788    Options(Vec<SqlOption>),
2789
2790    /// Plain options, options which are not part on any declerative statement e.g. WITH/OPTIONS/...
2791    /// <https://dev.mysql.com/doc/refman/8.4/en/create-table.html>
2792    Plain(Vec<SqlOption>),
2793
2794    TableProperties(Vec<SqlOption>),
2795}
2796
2797impl Default for CreateTableOptions {
2798    fn default() -> Self {
2799        Self::None
2800    }
2801}
2802
2803impl fmt::Display for CreateTableOptions {
2804    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2805        match self {
2806            CreateTableOptions::With(with_options) => {
2807                write!(f, "WITH ({})", display_comma_separated(with_options))
2808            }
2809            CreateTableOptions::Options(options) => {
2810                write!(f, "OPTIONS({})", display_comma_separated(options))
2811            }
2812            CreateTableOptions::TableProperties(options) => {
2813                write!(f, "TBLPROPERTIES ({})", display_comma_separated(options))
2814            }
2815            CreateTableOptions::Plain(options) => {
2816                write!(f, "{}", display_separated(options, " "))
2817            }
2818            CreateTableOptions::None => Ok(()),
2819        }
2820    }
2821}
2822
2823/// A `FROM` clause within a `DELETE` statement.
2824///
2825/// Syntax
2826/// ```sql
2827/// [FROM] table
2828/// ```
2829#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2830#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2831#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2832pub enum FromTable {
2833    /// An explicit `FROM` keyword was specified.
2834    WithFromKeyword(Vec<TableWithJoins>),
2835    /// BigQuery: `FROM` keyword was omitted.
2836    /// <https://cloud.google.com/bigquery/docs/reference/standard-sql/dml-syntax#delete_statement>
2837    WithoutKeyword(Vec<TableWithJoins>),
2838}
2839impl Display for FromTable {
2840    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2841        match self {
2842            FromTable::WithFromKeyword(tables) => {
2843                write!(f, "FROM {}", display_comma_separated(tables))
2844            }
2845            FromTable::WithoutKeyword(tables) => {
2846                write!(f, "{}", display_comma_separated(tables))
2847            }
2848        }
2849    }
2850}
2851
2852/// Policy type for a `CREATE POLICY` statement.
2853/// ```sql
2854/// AS [ PERMISSIVE | RESTRICTIVE ]
2855/// ```
2856/// [PostgreSQL](https://www.postgresql.org/docs/current/sql-createpolicy.html)
2857#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2858#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2859#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2860pub enum CreatePolicyType {
2861    Permissive,
2862    Restrictive,
2863}
2864
2865/// Policy command for a `CREATE POLICY` statement.
2866/// ```sql
2867/// FOR [ALL | SELECT | INSERT | UPDATE | DELETE]
2868/// ```
2869/// [PostgreSQL](https://www.postgresql.org/docs/current/sql-createpolicy.html)
2870#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2871#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2872#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2873pub enum CreatePolicyCommand {
2874    All,
2875    Select,
2876    Insert,
2877    Update,
2878    Delete,
2879}
2880
2881#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2882#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2883#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2884pub enum Set {
2885    /// SQL Standard-style
2886    /// SET a = 1;
2887    SingleAssignment {
2888        scope: Option<ContextModifier>,
2889        hivevar: bool,
2890        variable: ObjectName,
2891        values: Vec<Expr>,
2892    },
2893    /// Snowflake-style
2894    /// SET (a, b, ..) = (1, 2, ..);
2895    ParenthesizedAssignments {
2896        variables: Vec<ObjectName>,
2897        values: Vec<Expr>,
2898    },
2899    /// MySQL-style
2900    /// SET a = 1, b = 2, ..;
2901    MultipleAssignments { assignments: Vec<SetAssignment> },
2902    /// MS-SQL session
2903    ///
2904    /// See <https://learn.microsoft.com/en-us/sql/t-sql/statements/set-statements-transact-sql>
2905    SetSessionParam(SetSessionParamKind),
2906    /// ```sql
2907    /// SET [ SESSION | LOCAL ] ROLE role_name
2908    /// ```
2909    ///
2910    /// Sets session state. Examples: [ANSI][1], [Postgresql][2], [MySQL][3], and [Oracle][4]
2911    ///
2912    /// [1]: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#set-role-statement
2913    /// [2]: https://www.postgresql.org/docs/14/sql-set-role.html
2914    /// [3]: https://dev.mysql.com/doc/refman/8.0/en/set-role.html
2915    /// [4]: https://docs.oracle.com/cd/B19306_01/server.102/b14200/statements_10004.htm
2916    SetRole {
2917        /// Non-ANSI optional identifier to inform if the role is defined inside the current session (`SESSION`) or transaction (`LOCAL`).
2918        context_modifier: Option<ContextModifier>,
2919        /// Role name. If NONE is specified, then the current role name is removed.
2920        role_name: Option<Ident>,
2921    },
2922    /// ```sql
2923    /// SET TIME ZONE <value>
2924    /// ```
2925    ///
2926    /// Note: this is a PostgreSQL-specific statements
2927    /// `SET TIME ZONE <value>` is an alias for `SET timezone TO <value>` in PostgreSQL
2928    /// However, we allow it for all dialects.
2929    SetTimeZone { local: bool, value: Expr },
2930    /// ```sql
2931    /// SET NAMES 'charset_name' [COLLATE 'collation_name']
2932    /// ```
2933    SetNames {
2934        charset_name: Ident,
2935        collation_name: Option<String>,
2936    },
2937    /// ```sql
2938    /// SET NAMES DEFAULT
2939    /// ```
2940    ///
2941    /// Note: this is a MySQL-specific statement.
2942    SetNamesDefault {},
2943    /// ```sql
2944    /// SET TRANSACTION ...
2945    /// ```
2946    SetTransaction {
2947        modes: Vec<TransactionMode>,
2948        snapshot: Option<Value>,
2949        session: bool,
2950    },
2951}
2952
2953impl Display for Set {
2954    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2955        match self {
2956            Self::ParenthesizedAssignments { variables, values } => write!(
2957                f,
2958                "SET ({}) = ({})",
2959                display_comma_separated(variables),
2960                display_comma_separated(values)
2961            ),
2962            Self::MultipleAssignments { assignments } => {
2963                write!(f, "SET {}", display_comma_separated(assignments))
2964            }
2965            Self::SetRole {
2966                context_modifier,
2967                role_name,
2968            } => {
2969                let role_name = role_name.clone().unwrap_or_else(|| Ident::new("NONE"));
2970                write!(
2971                    f,
2972                    "SET {modifier}ROLE {role_name}",
2973                    modifier = context_modifier.map(|m| format!("{m}")).unwrap_or_default()
2974                )
2975            }
2976            Self::SetSessionParam(kind) => write!(f, "SET {kind}"),
2977            Self::SetTransaction {
2978                modes,
2979                snapshot,
2980                session,
2981            } => {
2982                if *session {
2983                    write!(f, "SET SESSION CHARACTERISTICS AS TRANSACTION")?;
2984                } else {
2985                    write!(f, "SET TRANSACTION")?;
2986                }
2987                if !modes.is_empty() {
2988                    write!(f, " {}", display_comma_separated(modes))?;
2989                }
2990                if let Some(snapshot_id) = snapshot {
2991                    write!(f, " SNAPSHOT {snapshot_id}")?;
2992                }
2993                Ok(())
2994            }
2995            Self::SetTimeZone { local, value } => {
2996                f.write_str("SET ")?;
2997                if *local {
2998                    f.write_str("LOCAL ")?;
2999                }
3000                write!(f, "TIME ZONE {value}")
3001            }
3002            Self::SetNames {
3003                charset_name,
3004                collation_name,
3005            } => {
3006                write!(f, "SET NAMES {charset_name}")?;
3007
3008                if let Some(collation) = collation_name {
3009                    f.write_str(" COLLATE ")?;
3010                    f.write_str(collation)?;
3011                };
3012
3013                Ok(())
3014            }
3015            Self::SetNamesDefault {} => {
3016                f.write_str("SET NAMES DEFAULT")?;
3017
3018                Ok(())
3019            }
3020            Set::SingleAssignment {
3021                scope,
3022                hivevar,
3023                variable,
3024                values,
3025            } => {
3026                write!(
3027                    f,
3028                    "SET {}{}{} = {}",
3029                    scope.map(|s| format!("{s}")).unwrap_or_default(),
3030                    if *hivevar { "HIVEVAR:" } else { "" },
3031                    variable,
3032                    display_comma_separated(values)
3033                )
3034            }
3035        }
3036    }
3037}
3038
3039/// Convert a `Set` into a `Statement`.
3040/// Convenience function, instead of writing `Statement::Set(Set::Set...{...})`
3041impl From<Set> for Statement {
3042    fn from(set: Set) -> Self {
3043        Statement::Set(set)
3044    }
3045}
3046
3047/// A representation of a `WHEN` arm with all the identifiers catched and the statements to execute
3048/// for the arm.
3049///
3050/// Snowflake: <https://docs.snowflake.com/en/sql-reference/snowflake-scripting/exception>
3051/// BigQuery: <https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#beginexceptionend>
3052#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3053#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3054#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3055pub struct ExceptionWhen {
3056    pub idents: Vec<Ident>,
3057    pub statements: Vec<Statement>,
3058}
3059
3060impl Display for ExceptionWhen {
3061    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3062        write!(
3063            f,
3064            "WHEN {idents} THEN",
3065            idents = display_separated(&self.idents, " OR ")
3066        )?;
3067
3068        if !self.statements.is_empty() {
3069            write!(f, " ")?;
3070            format_statement_list(f, &self.statements)?;
3071        }
3072
3073        Ok(())
3074    }
3075}
3076
3077/// A top-level statement (SELECT, INSERT, CREATE, etc.)
3078#[allow(clippy::large_enum_variant)]
3079#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3080#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3081#[cfg_attr(
3082    feature = "visitor",
3083    derive(Visit, VisitMut),
3084    visit(with = "visit_statement")
3085)]
3086pub enum Statement {
3087    /// ```sql
3088    /// ANALYZE
3089    /// ```
3090    /// Analyze (Hive)
3091    Analyze {
3092        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
3093        table_name: ObjectName,
3094        partitions: Option<Vec<Expr>>,
3095        for_columns: bool,
3096        columns: Vec<Ident>,
3097        cache_metadata: bool,
3098        noscan: bool,
3099        compute_statistics: bool,
3100        has_table_keyword: bool,
3101    },
3102    Set(Set),
3103    /// ```sql
3104    /// TRUNCATE
3105    /// ```
3106    /// Truncate (Hive)
3107    Truncate {
3108        table_names: Vec<TruncateTableTarget>,
3109        partitions: Option<Vec<Expr>>,
3110        /// TABLE - optional keyword;
3111        table: bool,
3112        /// Postgres-specific option
3113        /// [ RESTART IDENTITY | CONTINUE IDENTITY ]
3114        identity: Option<TruncateIdentityOption>,
3115        /// Postgres-specific option
3116        /// [ CASCADE | RESTRICT ]
3117        cascade: Option<CascadeOption>,
3118        /// ClickHouse-specific option
3119        /// [ ON CLUSTER cluster_name ]
3120        ///
3121        /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/truncate/)
3122        on_cluster: Option<Ident>,
3123    },
3124    /// ```sql
3125    /// MSCK
3126    /// ```
3127    /// Msck (Hive)
3128    Msck {
3129        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
3130        table_name: ObjectName,
3131        repair: bool,
3132        partition_action: Option<AddDropSync>,
3133    },
3134    /// ```sql
3135    /// SELECT
3136    /// ```
3137    Query(Box<Query>),
3138    /// ```sql
3139    /// INSERT
3140    /// ```
3141    Insert(Insert),
3142    /// ```sql
3143    /// INSTALL
3144    /// ```
3145    Install {
3146        /// Only for DuckDB
3147        extension_name: Ident,
3148    },
3149    /// ```sql
3150    /// LOAD
3151    /// ```
3152    Load {
3153        /// Only for DuckDB
3154        extension_name: Ident,
3155    },
3156    // TODO: Support ROW FORMAT
3157    Directory {
3158        overwrite: bool,
3159        local: bool,
3160        path: String,
3161        file_format: Option<FileFormat>,
3162        source: Box<Query>,
3163    },
3164    /// A `CASE` statement.
3165    Case(CaseStatement),
3166    /// An `IF` statement.
3167    If(IfStatement),
3168    /// A `WHILE` statement.
3169    While(WhileStatement),
3170    /// A `RAISE` statement.
3171    Raise(RaiseStatement),
3172    /// ```sql
3173    /// CALL <function>
3174    /// ```
3175    Call(Function),
3176    /// ```sql
3177    /// COPY [TO | FROM] ...
3178    /// ```
3179    Copy {
3180        /// The source of 'COPY TO', or the target of 'COPY FROM'
3181        source: CopySource,
3182        /// If true, is a 'COPY TO' statement. If false is a 'COPY FROM'
3183        to: bool,
3184        /// The target of 'COPY TO', or the source of 'COPY FROM'
3185        target: CopyTarget,
3186        /// WITH options (from PostgreSQL version 9.0)
3187        options: Vec<CopyOption>,
3188        /// WITH options (before PostgreSQL version 9.0)
3189        legacy_options: Vec<CopyLegacyOption>,
3190        /// VALUES a vector of values to be copied
3191        values: Vec<Option<String>>,
3192    },
3193    /// ```sql
3194    /// COPY INTO <table> | <location>
3195    /// ```
3196    /// See:
3197    /// <https://docs.snowflake.com/en/sql-reference/sql/copy-into-table>
3198    /// <https://docs.snowflake.com/en/sql-reference/sql/copy-into-location>
3199    ///
3200    /// Copy Into syntax available for Snowflake is different than the one implemented in
3201    /// Postgres. Although they share common prefix, it is reasonable to implement them
3202    /// in different enums. This can be refactored later once custom dialects
3203    /// are allowed to have custom Statements.
3204    CopyIntoSnowflake {
3205        kind: CopyIntoSnowflakeKind,
3206        into: ObjectName,
3207        into_columns: Option<Vec<Ident>>,
3208        from_obj: Option<ObjectName>,
3209        from_obj_alias: Option<Ident>,
3210        stage_params: StageParamsObject,
3211        from_transformations: Option<Vec<StageLoadSelectItemKind>>,
3212        from_query: Option<Box<Query>>,
3213        files: Option<Vec<String>>,
3214        pattern: Option<String>,
3215        file_format: KeyValueOptions,
3216        copy_options: KeyValueOptions,
3217        validation_mode: Option<String>,
3218        partition: Option<Box<Expr>>,
3219    },
3220    /// ```sql
3221    /// OPEN cursor_name
3222    /// ```
3223    /// Opens a cursor.
3224    Open(OpenStatement),
3225    /// ```sql
3226    /// CLOSE
3227    /// ```
3228    /// Closes the portal underlying an open cursor.
3229    Close {
3230        /// Cursor name
3231        cursor: CloseCursor,
3232    },
3233    /// ```sql
3234    /// UPDATE
3235    /// ```
3236    Update {
3237        /// TABLE
3238        table: TableWithJoins,
3239        /// Column assignments
3240        assignments: Vec<Assignment>,
3241        /// Table which provide value to be set
3242        from: Option<UpdateTableFromKind>,
3243        /// WHERE
3244        selection: Option<Expr>,
3245        /// RETURNING
3246        returning: Option<Vec<SelectItem>>,
3247        /// SQLite-specific conflict resolution clause
3248        or: Option<SqliteOnConflict>,
3249    },
3250    /// ```sql
3251    /// DELETE
3252    /// ```
3253    Delete(Delete),
3254    /// ```sql
3255    /// CREATE VIEW
3256    /// ```
3257    CreateView {
3258        /// True if this is a `CREATE OR ALTER VIEW` statement
3259        ///
3260        /// [MsSql](https://learn.microsoft.com/en-us/sql/t-sql/statements/create-view-transact-sql)
3261        or_alter: bool,
3262        or_replace: bool,
3263        materialized: bool,
3264        /// View name
3265        name: ObjectName,
3266        columns: Vec<ViewColumnDef>,
3267        query: Box<Query>,
3268        options: CreateTableOptions,
3269        cluster_by: Vec<Ident>,
3270        /// Snowflake: Views can have comments in Snowflake.
3271        /// <https://docs.snowflake.com/en/sql-reference/sql/create-view#syntax>
3272        comment: Option<String>,
3273        /// if true, has RedShift [`WITH NO SCHEMA BINDING`] clause <https://docs.aws.amazon.com/redshift/latest/dg/r_CREATE_VIEW.html>
3274        with_no_schema_binding: bool,
3275        /// if true, has SQLite `IF NOT EXISTS` clause <https://www.sqlite.org/lang_createview.html>
3276        if_not_exists: bool,
3277        /// if true, has SQLite `TEMP` or `TEMPORARY` clause <https://www.sqlite.org/lang_createview.html>
3278        temporary: bool,
3279        /// if not None, has Clickhouse `TO` clause, specify the table into which to insert results
3280        /// <https://clickhouse.com/docs/en/sql-reference/statements/create/view#materialized-view>
3281        to: Option<ObjectName>,
3282        /// MySQL: Optional parameters for the view algorithm, definer, and security context
3283        params: Option<CreateViewParams>,
3284    },
3285    /// ```sql
3286    /// CREATE TABLE
3287    /// ```
3288    CreateTable(CreateTable),
3289    /// ```sql
3290    /// CREATE VIRTUAL TABLE .. USING <module_name> (<module_args>)`
3291    /// ```
3292    /// Sqlite specific statement
3293    CreateVirtualTable {
3294        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
3295        name: ObjectName,
3296        if_not_exists: bool,
3297        module_name: Ident,
3298        module_args: Vec<Ident>,
3299    },
3300    /// ```sql
3301    /// `CREATE INDEX`
3302    /// ```
3303    CreateIndex(CreateIndex),
3304    /// ```sql
3305    /// CREATE ROLE
3306    /// ```
3307    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createrole.html)
3308    CreateRole {
3309        names: Vec<ObjectName>,
3310        if_not_exists: bool,
3311        // Postgres
3312        login: Option<bool>,
3313        inherit: Option<bool>,
3314        bypassrls: Option<bool>,
3315        password: Option<Password>,
3316        superuser: Option<bool>,
3317        create_db: Option<bool>,
3318        create_role: Option<bool>,
3319        replication: Option<bool>,
3320        connection_limit: Option<Expr>,
3321        valid_until: Option<Expr>,
3322        in_role: Vec<Ident>,
3323        in_group: Vec<Ident>,
3324        role: Vec<Ident>,
3325        user: Vec<Ident>,
3326        admin: Vec<Ident>,
3327        // MSSQL
3328        authorization_owner: Option<ObjectName>,
3329    },
3330    /// ```sql
3331    /// CREATE SECRET
3332    /// ```
3333    /// See [DuckDB](https://duckdb.org/docs/sql/statements/create_secret.html)
3334    CreateSecret {
3335        or_replace: bool,
3336        temporary: Option<bool>,
3337        if_not_exists: bool,
3338        name: Option<Ident>,
3339        storage_specifier: Option<Ident>,
3340        secret_type: Ident,
3341        options: Vec<SecretOption>,
3342    },
3343    /// A `CREATE SERVER` statement.
3344    CreateServer(CreateServerStatement),
3345    /// ```sql
3346    /// CREATE POLICY
3347    /// ```
3348    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createpolicy.html)
3349    CreatePolicy {
3350        name: Ident,
3351        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
3352        table_name: ObjectName,
3353        policy_type: Option<CreatePolicyType>,
3354        command: Option<CreatePolicyCommand>,
3355        to: Option<Vec<Owner>>,
3356        using: Option<Expr>,
3357        with_check: Option<Expr>,
3358    },
3359    /// ```sql
3360    /// CREATE CONNECTOR
3361    /// ```
3362    /// See [Hive](https://cwiki.apache.org/confluence/pages/viewpage.action?pageId=27362034#LanguageManualDDL-CreateDataConnectorCreateConnector)
3363    CreateConnector(CreateConnector),
3364    /// ```sql
3365    /// ALTER TABLE
3366    /// ```
3367    AlterTable {
3368        /// Table name
3369        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
3370        name: ObjectName,
3371        if_exists: bool,
3372        only: bool,
3373        operations: Vec<AlterTableOperation>,
3374        location: Option<HiveSetLocation>,
3375        /// ClickHouse dialect supports `ON CLUSTER` clause for ALTER TABLE
3376        /// For example: `ALTER TABLE table_name ON CLUSTER cluster_name ADD COLUMN c UInt32`
3377        /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/alter/update)
3378        on_cluster: Option<Ident>,
3379        /// Snowflake "ICEBERG" clause for Iceberg tables
3380        /// <https://docs.snowflake.com/en/sql-reference/sql/alter-iceberg-table>
3381        iceberg: bool,
3382    },
3383    /// ```sql
3384    /// ALTER INDEX
3385    /// ```
3386    AlterIndex {
3387        name: ObjectName,
3388        operation: AlterIndexOperation,
3389    },
3390    /// ```sql
3391    /// ALTER VIEW
3392    /// ```
3393    AlterView {
3394        /// View name
3395        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
3396        name: ObjectName,
3397        columns: Vec<Ident>,
3398        query: Box<Query>,
3399        with_options: Vec<SqlOption>,
3400    },
3401    /// ```sql
3402    /// ALTER TYPE
3403    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-altertype.html)
3404    /// ```
3405    AlterType(AlterType),
3406    /// ```sql
3407    /// ALTER ROLE
3408    /// ```
3409    AlterRole {
3410        name: Ident,
3411        operation: AlterRoleOperation,
3412    },
3413    /// ```sql
3414    /// ALTER POLICY <NAME> ON <TABLE NAME> [<OPERATION>]
3415    /// ```
3416    /// (Postgresql-specific)
3417    AlterPolicy {
3418        name: Ident,
3419        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
3420        table_name: ObjectName,
3421        operation: AlterPolicyOperation,
3422    },
3423    /// ```sql
3424    /// ALTER CONNECTOR connector_name SET DCPROPERTIES(property_name=property_value, ...);
3425    /// or
3426    /// ALTER CONNECTOR connector_name SET URL new_url;
3427    /// or
3428    /// ALTER CONNECTOR connector_name SET OWNER [USER|ROLE] user_or_role;
3429    /// ```
3430    /// (Hive-specific)
3431    AlterConnector {
3432        name: Ident,
3433        properties: Option<Vec<SqlOption>>,
3434        url: Option<String>,
3435        owner: Option<ddl::AlterConnectorOwner>,
3436    },
3437    /// ```sql
3438    /// ALTER SESSION SET sessionParam
3439    /// ALTER SESSION UNSET <param_name> [ , <param_name> , ... ]
3440    /// ```
3441    /// See <https://docs.snowflake.com/en/sql-reference/sql/alter-session>
3442    AlterSession {
3443        /// true is to set for the session parameters, false is to unset
3444        set: bool,
3445        /// The session parameters to set or unset
3446        session_params: KeyValueOptions,
3447    },
3448    /// ```sql
3449    /// ATTACH DATABASE 'path/to/file' AS alias
3450    /// ```
3451    /// (SQLite-specific)
3452    AttachDatabase {
3453        /// The name to bind to the newly attached database
3454        schema_name: Ident,
3455        /// An expression that indicates the path to the database file
3456        database_file_name: Expr,
3457        /// true if the syntax is 'ATTACH DATABASE', false if it's just 'ATTACH'
3458        database: bool,
3459    },
3460    /// (DuckDB-specific)
3461    /// ```sql
3462    /// ATTACH 'sqlite_file.db' AS sqlite_db (READ_ONLY, TYPE SQLITE);
3463    /// ```
3464    /// See <https://duckdb.org/docs/sql/statements/attach.html>
3465    AttachDuckDBDatabase {
3466        if_not_exists: bool,
3467        /// true if the syntax is 'ATTACH DATABASE', false if it's just 'ATTACH'
3468        database: bool,
3469        /// An expression that indicates the path to the database file
3470        database_path: Ident,
3471        database_alias: Option<Ident>,
3472        attach_options: Vec<AttachDuckDBDatabaseOption>,
3473    },
3474    /// (DuckDB-specific)
3475    /// ```sql
3476    /// DETACH db_alias;
3477    /// ```
3478    /// See <https://duckdb.org/docs/sql/statements/attach.html>
3479    DetachDuckDBDatabase {
3480        if_exists: bool,
3481        /// true if the syntax is 'DETACH DATABASE', false if it's just 'DETACH'
3482        database: bool,
3483        database_alias: Ident,
3484    },
3485    /// ```sql
3486    /// DROP [TABLE, VIEW, ...]
3487    /// ```
3488    Drop {
3489        /// The type of the object to drop: TABLE, VIEW, etc.
3490        object_type: ObjectType,
3491        /// An optional `IF EXISTS` clause. (Non-standard.)
3492        if_exists: bool,
3493        /// One or more objects to drop. (ANSI SQL requires exactly one.)
3494        names: Vec<ObjectName>,
3495        /// Whether `CASCADE` was specified. This will be `false` when
3496        /// `RESTRICT` or no drop behavior at all was specified.
3497        cascade: bool,
3498        /// Whether `RESTRICT` was specified. This will be `false` when
3499        /// `CASCADE` or no drop behavior at all was specified.
3500        restrict: bool,
3501        /// Hive allows you specify whether the table's stored data will be
3502        /// deleted along with the dropped table
3503        purge: bool,
3504        /// MySQL-specific "TEMPORARY" keyword
3505        temporary: bool,
3506        /// MySQL-specific drop index syntax, which requires table specification
3507        /// See <https://dev.mysql.com/doc/refman/8.4/en/drop-index.html>
3508        table: Option<ObjectName>,
3509    },
3510    /// ```sql
3511    /// DROP FUNCTION
3512    /// ```
3513    DropFunction {
3514        if_exists: bool,
3515        /// One or more function to drop
3516        func_desc: Vec<FunctionDesc>,
3517        /// `CASCADE` or `RESTRICT`
3518        drop_behavior: Option<DropBehavior>,
3519    },
3520    /// ```sql
3521    /// DROP DOMAIN
3522    /// ```
3523    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-dropdomain.html)
3524    ///
3525    /// DROP DOMAIN [ IF EXISTS ] name [, ...] [ CASCADE | RESTRICT ]
3526    ///
3527    DropDomain(DropDomain),
3528    /// ```sql
3529    /// DROP PROCEDURE
3530    /// ```
3531    DropProcedure {
3532        if_exists: bool,
3533        /// One or more function to drop
3534        proc_desc: Vec<FunctionDesc>,
3535        /// `CASCADE` or `RESTRICT`
3536        drop_behavior: Option<DropBehavior>,
3537    },
3538    /// ```sql
3539    /// DROP SECRET
3540    /// ```
3541    DropSecret {
3542        if_exists: bool,
3543        temporary: Option<bool>,
3544        name: Ident,
3545        storage_specifier: Option<Ident>,
3546    },
3547    ///```sql
3548    /// DROP POLICY
3549    /// ```
3550    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-droppolicy.html)
3551    DropPolicy {
3552        if_exists: bool,
3553        name: Ident,
3554        table_name: ObjectName,
3555        drop_behavior: Option<DropBehavior>,
3556    },
3557    /// ```sql
3558    /// DROP CONNECTOR
3559    /// ```
3560    /// See [Hive](https://cwiki.apache.org/confluence/pages/viewpage.action?pageId=27362034#LanguageManualDDL-DropConnector)
3561    DropConnector {
3562        if_exists: bool,
3563        name: Ident,
3564    },
3565    /// ```sql
3566    /// DECLARE
3567    /// ```
3568    /// Declare Cursor Variables
3569    ///
3570    /// Note: this is a PostgreSQL-specific statement,
3571    /// but may also compatible with other SQL.
3572    Declare {
3573        stmts: Vec<Declare>,
3574    },
3575    /// ```sql
3576    /// CREATE EXTENSION [ IF NOT EXISTS ] extension_name
3577    ///     [ WITH ] [ SCHEMA schema_name ]
3578    ///              [ VERSION version ]
3579    ///              [ CASCADE ]
3580    /// ```
3581    ///
3582    /// Note: this is a PostgreSQL-specific statement,
3583    CreateExtension {
3584        name: Ident,
3585        if_not_exists: bool,
3586        cascade: bool,
3587        schema: Option<Ident>,
3588        version: Option<Ident>,
3589    },
3590    /// ```sql
3591    /// DROP EXTENSION [ IF EXISTS ] name [, ...] [ CASCADE | RESTRICT ]
3592    ///
3593    /// Note: this is a PostgreSQL-specific statement.
3594    /// https://www.postgresql.org/docs/current/sql-dropextension.html
3595    /// ```
3596    DropExtension {
3597        names: Vec<Ident>,
3598        if_exists: bool,
3599        /// `CASCADE` or `RESTRICT`
3600        cascade_or_restrict: Option<ReferentialAction>,
3601    },
3602    /// ```sql
3603    /// FETCH
3604    /// ```
3605    /// Retrieve rows from a query using a cursor
3606    ///
3607    /// Note: this is a PostgreSQL-specific statement,
3608    /// but may also compatible with other SQL.
3609    Fetch {
3610        /// Cursor name
3611        name: Ident,
3612        direction: FetchDirection,
3613        position: FetchPosition,
3614        /// Optional, It's possible to fetch rows form cursor to the table
3615        into: Option<ObjectName>,
3616    },
3617    /// ```sql
3618    /// FLUSH [NO_WRITE_TO_BINLOG | LOCAL] flush_option [, flush_option] ... | tables_option
3619    /// ```
3620    ///
3621    /// Note: this is a Mysql-specific statement,
3622    /// but may also compatible with other SQL.
3623    Flush {
3624        object_type: FlushType,
3625        location: Option<FlushLocation>,
3626        channel: Option<String>,
3627        read_lock: bool,
3628        export: bool,
3629        tables: Vec<ObjectName>,
3630    },
3631    /// ```sql
3632    /// DISCARD [ ALL | PLANS | SEQUENCES | TEMPORARY | TEMP ]
3633    /// ```
3634    ///
3635    /// Note: this is a PostgreSQL-specific statement,
3636    /// but may also compatible with other SQL.
3637    Discard {
3638        object_type: DiscardObject,
3639    },
3640    /// `SHOW FUNCTIONS`
3641    ///
3642    /// Note: this is a Presto-specific statement.
3643    ShowFunctions {
3644        filter: Option<ShowStatementFilter>,
3645    },
3646    /// ```sql
3647    /// SHOW <variable>
3648    /// ```
3649    ///
3650    /// Note: this is a PostgreSQL-specific statement.
3651    ShowVariable {
3652        variable: Vec<Ident>,
3653    },
3654    /// ```sql
3655    /// SHOW [GLOBAL | SESSION] STATUS [LIKE 'pattern' | WHERE expr]
3656    /// ```
3657    ///
3658    /// Note: this is a MySQL-specific statement.
3659    ShowStatus {
3660        filter: Option<ShowStatementFilter>,
3661        global: bool,
3662        session: bool,
3663    },
3664    /// ```sql
3665    /// SHOW VARIABLES
3666    /// ```
3667    ///
3668    /// Note: this is a MySQL-specific statement.
3669    ShowVariables {
3670        filter: Option<ShowStatementFilter>,
3671        global: bool,
3672        session: bool,
3673    },
3674    /// ```sql
3675    /// SHOW CREATE TABLE
3676    /// ```
3677    ///
3678    /// Note: this is a MySQL-specific statement.
3679    ShowCreate {
3680        obj_type: ShowCreateObject,
3681        obj_name: ObjectName,
3682    },
3683    /// ```sql
3684    /// SHOW COLUMNS
3685    /// ```
3686    ShowColumns {
3687        extended: bool,
3688        full: bool,
3689        show_options: ShowStatementOptions,
3690    },
3691    /// ```sql
3692    /// SHOW DATABASES
3693    /// ```
3694    ShowDatabases {
3695        terse: bool,
3696        history: bool,
3697        show_options: ShowStatementOptions,
3698    },
3699    /// ```sql
3700    /// SHOW SCHEMAS
3701    /// ```
3702    ShowSchemas {
3703        terse: bool,
3704        history: bool,
3705        show_options: ShowStatementOptions,
3706    },
3707    /// ```sql
3708    /// SHOW OBJECTS LIKE 'line%' IN mydb.public
3709    /// ```
3710    /// Snowflake-specific statement
3711    /// <https://docs.snowflake.com/en/sql-reference/sql/show-objects>
3712    ShowObjects(ShowObjects),
3713    /// ```sql
3714    /// SHOW TABLES
3715    /// ```
3716    ShowTables {
3717        terse: bool,
3718        history: bool,
3719        extended: bool,
3720        full: bool,
3721        external: bool,
3722        show_options: ShowStatementOptions,
3723    },
3724    /// ```sql
3725    /// SHOW VIEWS
3726    /// ```
3727    ShowViews {
3728        terse: bool,
3729        materialized: bool,
3730        show_options: ShowStatementOptions,
3731    },
3732    /// ```sql
3733    /// SHOW COLLATION
3734    /// ```
3735    ///
3736    /// Note: this is a MySQL-specific statement.
3737    ShowCollation {
3738        filter: Option<ShowStatementFilter>,
3739    },
3740    /// ```sql
3741    /// `USE ...`
3742    /// ```
3743    Use(Use),
3744    /// ```sql
3745    /// START  [ TRANSACTION | WORK ] | START TRANSACTION } ...
3746    /// ```
3747    /// If `begin` is false.
3748    ///
3749    /// ```sql
3750    /// `BEGIN  [ TRANSACTION | WORK ] | START TRANSACTION } ...`
3751    /// ```
3752    /// If `begin` is true
3753    StartTransaction {
3754        modes: Vec<TransactionMode>,
3755        begin: bool,
3756        transaction: Option<BeginTransactionKind>,
3757        modifier: Option<TransactionModifier>,
3758        /// List of statements belonging to the `BEGIN` block.
3759        /// Example:
3760        /// ```sql
3761        /// BEGIN
3762        ///     SELECT 1;
3763        ///     SELECT 2;
3764        /// END;
3765        /// ```
3766        statements: Vec<Statement>,
3767        /// Exception handling with exception clauses.
3768        /// Example:
3769        /// ```sql
3770        /// EXCEPTION
3771        ///     WHEN EXCEPTION_1 THEN
3772        ///         SELECT 2;
3773        ///     WHEN EXCEPTION_2 OR EXCEPTION_3 THEN
3774        ///         SELECT 3;
3775        ///     WHEN OTHER THEN
3776        ///         SELECT 4;
3777        /// ```
3778        /// <https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#beginexceptionend>
3779        /// <https://docs.snowflake.com/en/sql-reference/snowflake-scripting/exception>
3780        exception: Option<Vec<ExceptionWhen>>,
3781        /// TRUE if the statement has an `END` keyword.
3782        has_end_keyword: bool,
3783    },
3784    /// ```sql
3785    /// COMMENT ON ...
3786    /// ```
3787    ///
3788    /// Note: this is a PostgreSQL-specific statement.
3789    Comment {
3790        object_type: CommentObject,
3791        object_name: ObjectName,
3792        comment: Option<String>,
3793        /// An optional `IF EXISTS` clause. (Non-standard.)
3794        /// See <https://docs.snowflake.com/en/sql-reference/sql/comment>
3795        if_exists: bool,
3796    },
3797    /// ```sql
3798    /// COMMIT [ TRANSACTION | WORK ] [ AND [ NO ] CHAIN ]
3799    /// ```
3800    /// If `end` is false
3801    ///
3802    /// ```sql
3803    /// END [ TRY | CATCH ]
3804    /// ```
3805    /// If `end` is true
3806    Commit {
3807        chain: bool,
3808        end: bool,
3809        modifier: Option<TransactionModifier>,
3810    },
3811    /// ```sql
3812    /// ROLLBACK [ TRANSACTION | WORK ] [ AND [ NO ] CHAIN ] [ TO [ SAVEPOINT ] savepoint_name ]
3813    /// ```
3814    Rollback {
3815        chain: bool,
3816        savepoint: Option<Ident>,
3817    },
3818    /// ```sql
3819    /// CREATE SCHEMA
3820    /// ```
3821    CreateSchema {
3822        /// `<schema name> | AUTHORIZATION <schema authorization identifier>  | <schema name>  AUTHORIZATION <schema authorization identifier>`
3823        schema_name: SchemaName,
3824        if_not_exists: bool,
3825        /// Schema properties.
3826        ///
3827        /// ```sql
3828        /// CREATE SCHEMA myschema WITH (key1='value1');
3829        /// ```
3830        ///
3831        /// [Trino](https://trino.io/docs/current/sql/create-schema.html)
3832        with: Option<Vec<SqlOption>>,
3833        /// Schema options.
3834        ///
3835        /// ```sql
3836        /// CREATE SCHEMA myschema OPTIONS(key1='value1');
3837        /// ```
3838        ///
3839        /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_schema_statement)
3840        options: Option<Vec<SqlOption>>,
3841        /// Default collation specification for the schema.
3842        ///
3843        /// ```sql
3844        /// CREATE SCHEMA myschema DEFAULT COLLATE 'und:ci';
3845        /// ```
3846        ///
3847        /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_schema_statement)
3848        default_collate_spec: Option<Expr>,
3849    },
3850    /// ```sql
3851    /// CREATE DATABASE
3852    /// ```
3853    CreateDatabase {
3854        db_name: ObjectName,
3855        if_not_exists: bool,
3856        location: Option<String>,
3857        managed_location: Option<String>,
3858    },
3859    /// ```sql
3860    /// CREATE FUNCTION
3861    /// ```
3862    ///
3863    /// Supported variants:
3864    /// 1. [Hive](https://cwiki.apache.org/confluence/display/hive/languagemanual+ddl#LanguageManualDDL-Create/Drop/ReloadFunction)
3865    /// 2. [PostgreSQL](https://www.postgresql.org/docs/15/sql-createfunction.html)
3866    /// 3. [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_function_statement)
3867    /// 4. [MsSql](https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql)
3868    CreateFunction(CreateFunction),
3869    /// CREATE TRIGGER
3870    ///
3871    /// Examples:
3872    ///
3873    /// ```sql
3874    /// CREATE TRIGGER trigger_name
3875    /// BEFORE INSERT ON table_name
3876    /// FOR EACH ROW
3877    /// EXECUTE FUNCTION trigger_function();
3878    /// ```
3879    ///
3880    /// Postgres: <https://www.postgresql.org/docs/current/sql-createtrigger.html>
3881    /// SQL Server: <https://learn.microsoft.com/en-us/sql/t-sql/statements/create-trigger-transact-sql>
3882    CreateTrigger {
3883        /// True if this is a `CREATE OR ALTER TRIGGER` statement
3884        ///
3885        /// [MsSql](https://learn.microsoft.com/en-us/sql/t-sql/statements/create-trigger-transact-sql?view=sql-server-ver16#arguments)
3886        or_alter: bool,
3887        /// The `OR REPLACE` clause is used to re-create the trigger if it already exists.
3888        ///
3889        /// Example:
3890        /// ```sql
3891        /// CREATE OR REPLACE TRIGGER trigger_name
3892        /// AFTER INSERT ON table_name
3893        /// FOR EACH ROW
3894        /// EXECUTE FUNCTION trigger_function();
3895        /// ```
3896        or_replace: bool,
3897        /// The `CONSTRAINT` keyword is used to create a trigger as a constraint.
3898        is_constraint: bool,
3899        /// The name of the trigger to be created.
3900        name: ObjectName,
3901        /// Determines whether the function is called before, after, or instead of the event.
3902        ///
3903        /// Example of BEFORE:
3904        ///
3905        /// ```sql
3906        /// CREATE TRIGGER trigger_name
3907        /// BEFORE INSERT ON table_name
3908        /// FOR EACH ROW
3909        /// EXECUTE FUNCTION trigger_function();
3910        /// ```
3911        ///
3912        /// Example of AFTER:
3913        ///
3914        /// ```sql
3915        /// CREATE TRIGGER trigger_name
3916        /// AFTER INSERT ON table_name
3917        /// FOR EACH ROW
3918        /// EXECUTE FUNCTION trigger_function();
3919        /// ```
3920        ///
3921        /// Example of INSTEAD OF:
3922        ///
3923        /// ```sql
3924        /// CREATE TRIGGER trigger_name
3925        /// INSTEAD OF INSERT ON table_name
3926        /// FOR EACH ROW
3927        /// EXECUTE FUNCTION trigger_function();
3928        /// ```
3929        period: TriggerPeriod,
3930        /// Multiple events can be specified using OR, such as `INSERT`, `UPDATE`, `DELETE`, or `TRUNCATE`.
3931        events: Vec<TriggerEvent>,
3932        /// The table on which the trigger is to be created.
3933        table_name: ObjectName,
3934        /// The optional referenced table name that can be referenced via
3935        /// the `FROM` keyword.
3936        referenced_table_name: Option<ObjectName>,
3937        /// This keyword immediately precedes the declaration of one or two relation names that provide access to the transition relations of the triggering statement.
3938        referencing: Vec<TriggerReferencing>,
3939        /// This specifies whether the trigger function should be fired once for
3940        /// every row affected by the trigger event, or just once per SQL statement.
3941        trigger_object: TriggerObject,
3942        /// Whether to include the `EACH` term of the `FOR EACH`, as it is optional syntax.
3943        include_each: bool,
3944        ///  Triggering conditions
3945        condition: Option<Expr>,
3946        /// Execute logic block
3947        exec_body: Option<TriggerExecBody>,
3948        /// For SQL dialects with statement(s) for a body
3949        statements: Option<ConditionalStatements>,
3950        /// The characteristic of the trigger, which include whether the trigger is `DEFERRABLE`, `INITIALLY DEFERRED`, or `INITIALLY IMMEDIATE`,
3951        characteristics: Option<ConstraintCharacteristics>,
3952    },
3953    /// DROP TRIGGER
3954    ///
3955    /// ```sql
3956    /// DROP TRIGGER [ IF EXISTS ] name ON table_name [ CASCADE | RESTRICT ]
3957    /// ```
3958    ///
3959    DropTrigger {
3960        if_exists: bool,
3961        trigger_name: ObjectName,
3962        table_name: Option<ObjectName>,
3963        /// `CASCADE` or `RESTRICT`
3964        option: Option<ReferentialAction>,
3965    },
3966    /// ```sql
3967    /// CREATE PROCEDURE
3968    /// ```
3969    CreateProcedure {
3970        or_alter: bool,
3971        name: ObjectName,
3972        params: Option<Vec<ProcedureParam>>,
3973        language: Option<Ident>,
3974        body: ConditionalStatements,
3975    },
3976    /// ```sql
3977    /// CREATE MACRO
3978    /// ```
3979    ///
3980    /// Supported variants:
3981    /// 1. [DuckDB](https://duckdb.org/docs/sql/statements/create_macro)
3982    CreateMacro {
3983        or_replace: bool,
3984        temporary: bool,
3985        name: ObjectName,
3986        args: Option<Vec<MacroArg>>,
3987        definition: MacroDefinition,
3988    },
3989    /// ```sql
3990    /// CREATE STAGE
3991    /// ```
3992    /// See <https://docs.snowflake.com/en/sql-reference/sql/create-stage>
3993    CreateStage {
3994        or_replace: bool,
3995        temporary: bool,
3996        if_not_exists: bool,
3997        name: ObjectName,
3998        stage_params: StageParamsObject,
3999        directory_table_params: KeyValueOptions,
4000        file_format: KeyValueOptions,
4001        copy_options: KeyValueOptions,
4002        comment: Option<String>,
4003    },
4004    /// ```sql
4005    /// ASSERT <condition> [AS <message>]
4006    /// ```
4007    Assert {
4008        condition: Expr,
4009        message: Option<Expr>,
4010    },
4011    /// ```sql
4012    /// GRANT privileges ON objects TO grantees
4013    /// ```
4014    Grant {
4015        privileges: Privileges,
4016        objects: Option<GrantObjects>,
4017        grantees: Vec<Grantee>,
4018        with_grant_option: bool,
4019        as_grantor: Option<Ident>,
4020        granted_by: Option<Ident>,
4021        current_grants: Option<CurrentGrantsKind>,
4022    },
4023    /// ```sql
4024    /// DENY privileges ON object TO grantees
4025    /// ```
4026    Deny(DenyStatement),
4027    /// ```sql
4028    /// REVOKE privileges ON objects FROM grantees
4029    /// ```
4030    Revoke {
4031        privileges: Privileges,
4032        objects: Option<GrantObjects>,
4033        grantees: Vec<Grantee>,
4034        granted_by: Option<Ident>,
4035        cascade: Option<CascadeOption>,
4036    },
4037    /// ```sql
4038    /// DEALLOCATE [ PREPARE ] { name | ALL }
4039    /// ```
4040    ///
4041    /// Note: this is a PostgreSQL-specific statement.
4042    Deallocate {
4043        name: Ident,
4044        prepare: bool,
4045    },
4046    /// ```sql
4047    /// An `EXECUTE` statement
4048    /// ```
4049    ///
4050    /// Postgres: <https://www.postgresql.org/docs/current/sql-execute.html>
4051    /// MSSQL: <https://learn.microsoft.com/en-us/sql/relational-databases/stored-procedures/execute-a-stored-procedure>
4052    /// BigQuery: <https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#execute_immediate>
4053    /// Snowflake: <https://docs.snowflake.com/en/sql-reference/sql/execute-immediate>
4054    Execute {
4055        name: Option<ObjectName>,
4056        parameters: Vec<Expr>,
4057        has_parentheses: bool,
4058        /// Is this an `EXECUTE IMMEDIATE`
4059        immediate: bool,
4060        into: Vec<Ident>,
4061        using: Vec<ExprWithAlias>,
4062        /// Whether the last parameter is the return value of the procedure
4063        /// MSSQL: <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/execute-transact-sql?view=sql-server-ver17#output>
4064        output: bool,
4065        /// Whether to invoke the procedure with the default parameter values
4066        /// MSSQL: <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/execute-transact-sql?view=sql-server-ver17#default>
4067        default: bool,
4068    },
4069    /// ```sql
4070    /// PREPARE name [ ( data_type [, ...] ) ] AS statement
4071    /// ```
4072    ///
4073    /// Note: this is a PostgreSQL-specific statement.
4074    Prepare {
4075        name: Ident,
4076        data_types: Vec<DataType>,
4077        statement: Box<Statement>,
4078    },
4079    /// ```sql
4080    /// KILL [CONNECTION | QUERY | MUTATION]
4081    /// ```
4082    ///
4083    /// See <https://clickhouse.com/docs/en/sql-reference/statements/kill/>
4084    /// See <https://dev.mysql.com/doc/refman/8.0/en/kill.html>
4085    Kill {
4086        modifier: Option<KillType>,
4087        // processlist_id
4088        id: u64,
4089    },
4090    /// ```sql
4091    /// [EXPLAIN | DESC | DESCRIBE] TABLE
4092    /// ```
4093    /// Note: this is a MySQL-specific statement. See <https://dev.mysql.com/doc/refman/8.0/en/explain.html>
4094    ExplainTable {
4095        /// `EXPLAIN | DESC | DESCRIBE`
4096        describe_alias: DescribeAlias,
4097        /// Hive style `FORMATTED | EXTENDED`
4098        hive_format: Option<HiveDescribeFormat>,
4099        /// Snowflake and ClickHouse support `DESC|DESCRIBE TABLE <table_name>` syntax
4100        ///
4101        /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/desc-table.html)
4102        /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/describe-table)
4103        has_table_keyword: bool,
4104        /// Table name
4105        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
4106        table_name: ObjectName,
4107    },
4108    /// ```sql
4109    /// [EXPLAIN | DESC | DESCRIBE]  <statement>
4110    /// ```
4111    Explain {
4112        /// `EXPLAIN | DESC | DESCRIBE`
4113        describe_alias: DescribeAlias,
4114        /// Carry out the command and show actual run times and other statistics.
4115        analyze: bool,
4116        // Display additional information regarding the plan.
4117        verbose: bool,
4118        /// `EXPLAIN QUERY PLAN`
4119        /// Display the query plan without running the query.
4120        ///
4121        /// [SQLite](https://sqlite.org/lang_explain.html)
4122        query_plan: bool,
4123        /// `EXPLAIN ESTIMATE`
4124        /// [Clickhouse](https://clickhouse.com/docs/en/sql-reference/statements/explain#explain-estimate)
4125        estimate: bool,
4126        /// A SQL query that specifies what to explain
4127        statement: Box<Statement>,
4128        /// Optional output format of explain
4129        format: Option<AnalyzeFormat>,
4130        /// Postgres style utility options, `(analyze, verbose true)`
4131        options: Option<Vec<UtilityOption>>,
4132    },
4133    /// ```sql
4134    /// SAVEPOINT
4135    /// ```
4136    /// Define a new savepoint within the current transaction
4137    Savepoint {
4138        name: Ident,
4139    },
4140    /// ```sql
4141    /// RELEASE [ SAVEPOINT ] savepoint_name
4142    /// ```
4143    ReleaseSavepoint {
4144        name: Ident,
4145    },
4146    /// A `MERGE` statement.
4147    ///
4148    /// ```sql
4149    /// MERGE INTO <target_table> USING <source> ON <join_expr> { matchedClause | notMatchedClause } [ ... ]
4150    /// ```
4151    /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/merge)
4152    /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/dml-syntax#merge_statement)
4153    /// [MSSQL](https://learn.microsoft.com/en-us/sql/t-sql/statements/merge-transact-sql?view=sql-server-ver16)
4154    Merge {
4155        /// optional INTO keyword
4156        into: bool,
4157        /// Specifies the table to merge
4158        table: TableFactor,
4159        /// Specifies the table or subquery to join with the target table
4160        source: TableFactor,
4161        /// Specifies the expression on which to join the target table and source
4162        on: Box<Expr>,
4163        /// Specifies the actions to perform when values match or do not match.
4164        clauses: Vec<MergeClause>,
4165        // Specifies the output to save changes in MSSQL
4166        output: Option<OutputClause>,
4167    },
4168    /// ```sql
4169    /// CACHE [ FLAG ] TABLE <table_name> [ OPTIONS('K1' = 'V1', 'K2' = V2) ] [ AS ] [ <query> ]
4170    /// ```
4171    ///
4172    /// See [Spark SQL docs] for more details.
4173    ///
4174    /// [Spark SQL docs]: https://docs.databricks.com/spark/latest/spark-sql/language-manual/sql-ref-syntax-aux-cache-cache-table.html
4175    Cache {
4176        /// Table flag
4177        table_flag: Option<ObjectName>,
4178        /// Table name
4179
4180        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
4181        table_name: ObjectName,
4182        has_as: bool,
4183        /// Table confs
4184        options: Vec<SqlOption>,
4185        /// Cache table as a Query
4186        query: Option<Box<Query>>,
4187    },
4188    /// ```sql
4189    /// UNCACHE TABLE [ IF EXISTS ]  <table_name>
4190    /// ```
4191    UNCache {
4192        /// Table name
4193        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
4194        table_name: ObjectName,
4195        if_exists: bool,
4196    },
4197    /// ```sql
4198    /// CREATE [ { TEMPORARY | TEMP } ] SEQUENCE [ IF NOT EXISTS ] <sequence_name>
4199    /// ```
4200    /// Define a new sequence:
4201    CreateSequence {
4202        temporary: bool,
4203        if_not_exists: bool,
4204        name: ObjectName,
4205        data_type: Option<DataType>,
4206        sequence_options: Vec<SequenceOptions>,
4207        owned_by: Option<ObjectName>,
4208    },
4209    /// A `CREATE DOMAIN` statement.
4210    CreateDomain(CreateDomain),
4211    /// ```sql
4212    /// CREATE TYPE <name>
4213    /// ```
4214    CreateType {
4215        name: ObjectName,
4216        representation: UserDefinedTypeRepresentation,
4217    },
4218    /// ```sql
4219    /// PRAGMA <schema-name>.<pragma-name> = <pragma-value>
4220    /// ```
4221    Pragma {
4222        name: ObjectName,
4223        value: Option<Value>,
4224        is_eq: bool,
4225    },
4226    /// ```sql
4227    /// LOCK TABLES <table_name> [READ [LOCAL] | [LOW_PRIORITY] WRITE]
4228    /// ```
4229    /// Note: this is a MySQL-specific statement. See <https://dev.mysql.com/doc/refman/8.0/en/lock-tables.html>
4230    LockTables {
4231        tables: Vec<LockTable>,
4232    },
4233    /// ```sql
4234    /// UNLOCK TABLES
4235    /// ```
4236    /// Note: this is a MySQL-specific statement. See <https://dev.mysql.com/doc/refman/8.0/en/lock-tables.html>
4237    UnlockTables,
4238    /// ```sql
4239    /// UNLOAD(statement) TO <destination> [ WITH options ]
4240    /// ```
4241    /// See Redshift <https://docs.aws.amazon.com/redshift/latest/dg/r_UNLOAD.html> and
4242    // Athena <https://docs.aws.amazon.com/athena/latest/ug/unload.html>
4243    Unload {
4244        query: Box<Query>,
4245        to: Ident,
4246        with: Vec<SqlOption>,
4247    },
4248    /// ```sql
4249    /// OPTIMIZE TABLE [db.]name [ON CLUSTER cluster] [PARTITION partition | PARTITION ID 'partition_id'] [FINAL] [DEDUPLICATE [BY expression]]
4250    /// ```
4251    ///
4252    /// See ClickHouse <https://clickhouse.com/docs/en/sql-reference/statements/optimize>
4253    OptimizeTable {
4254        name: ObjectName,
4255        on_cluster: Option<Ident>,
4256        partition: Option<Partition>,
4257        include_final: bool,
4258        deduplicate: Option<Deduplicate>,
4259    },
4260    /// ```sql
4261    /// LISTEN
4262    /// ```
4263    /// listen for a notification channel
4264    ///
4265    /// See Postgres <https://www.postgresql.org/docs/current/sql-listen.html>
4266    LISTEN {
4267        channel: Ident,
4268    },
4269    /// ```sql
4270    /// UNLISTEN
4271    /// ```
4272    /// stop listening for a notification
4273    ///
4274    /// See Postgres <https://www.postgresql.org/docs/current/sql-unlisten.html>
4275    UNLISTEN {
4276        channel: Ident,
4277    },
4278    /// ```sql
4279    /// NOTIFY channel [ , payload ]
4280    /// ```
4281    /// send a notification event together with an optional "payload" string to channel
4282    ///
4283    /// See Postgres <https://www.postgresql.org/docs/current/sql-notify.html>
4284    NOTIFY {
4285        channel: Ident,
4286        payload: Option<String>,
4287    },
4288    /// ```sql
4289    /// LOAD DATA [LOCAL] INPATH 'filepath' [OVERWRITE] INTO TABLE tablename
4290    /// [PARTITION (partcol1=val1, partcol2=val2 ...)]
4291    /// [INPUTFORMAT 'inputformat' SERDE 'serde']
4292    /// ```
4293    /// Loading files into tables
4294    ///
4295    /// See Hive <https://cwiki.apache.org/confluence/pages/viewpage.action?pageId=27362036#LanguageManualDML-Loadingfilesintotables>
4296    LoadData {
4297        local: bool,
4298        inpath: String,
4299        overwrite: bool,
4300        table_name: ObjectName,
4301        partitioned: Option<Vec<Expr>>,
4302        table_format: Option<HiveLoadDataFormat>,
4303    },
4304    /// ```sql
4305    /// Rename TABLE tbl_name TO new_tbl_name[, tbl_name2 TO new_tbl_name2] ...
4306    /// ```
4307    /// Renames one or more tables
4308    ///
4309    /// See Mysql <https://dev.mysql.com/doc/refman/9.1/en/rename-table.html>
4310    RenameTable(Vec<RenameTable>),
4311    /// Snowflake `LIST`
4312    /// See: <https://docs.snowflake.com/en/sql-reference/sql/list>
4313    List(FileStagingCommand),
4314    /// Snowflake `REMOVE`
4315    /// See: <https://docs.snowflake.com/en/sql-reference/sql/remove>
4316    Remove(FileStagingCommand),
4317    /// RaiseError (MSSQL)
4318    /// RAISERROR ( { msg_id | msg_str | @local_variable }
4319    /// { , severity , state }
4320    /// [ , argument [ , ...n ] ] )
4321    /// [ WITH option [ , ...n ] ]
4322    /// See <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/raiserror-transact-sql?view=sql-server-ver16>
4323    RaisError {
4324        message: Box<Expr>,
4325        severity: Box<Expr>,
4326        state: Box<Expr>,
4327        arguments: Vec<Expr>,
4328        options: Vec<RaisErrorOption>,
4329    },
4330    /// ```sql
4331    /// PRINT msg_str | @local_variable | string_expr
4332    /// ```
4333    ///
4334    /// See: <https://learn.microsoft.com/en-us/sql/t-sql/statements/print-transact-sql>
4335    Print(PrintStatement),
4336    /// ```sql
4337    /// RETURN [ expression ]
4338    /// ```
4339    ///
4340    /// See [ReturnStatement]
4341    Return(ReturnStatement),
4342}
4343
4344/// ```sql
4345/// {COPY | REVOKE} CURRENT GRANTS
4346/// ```
4347///
4348/// - [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/grant-ownership#optional-parameters)
4349#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
4350#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4351#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
4352pub enum CurrentGrantsKind {
4353    CopyCurrentGrants,
4354    RevokeCurrentGrants,
4355}
4356
4357impl fmt::Display for CurrentGrantsKind {
4358    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
4359        match self {
4360            CurrentGrantsKind::CopyCurrentGrants => write!(f, "COPY CURRENT GRANTS"),
4361            CurrentGrantsKind::RevokeCurrentGrants => write!(f, "REVOKE CURRENT GRANTS"),
4362        }
4363    }
4364}
4365
4366#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
4367#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4368#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
4369pub enum RaisErrorOption {
4370    Log,
4371    NoWait,
4372    SetError,
4373}
4374
4375impl fmt::Display for RaisErrorOption {
4376    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
4377        match self {
4378            RaisErrorOption::Log => write!(f, "LOG"),
4379            RaisErrorOption::NoWait => write!(f, "NOWAIT"),
4380            RaisErrorOption::SetError => write!(f, "SETERROR"),
4381        }
4382    }
4383}
4384
4385impl fmt::Display for Statement {
4386    /// Formats a SQL statement with support for pretty printing.
4387    ///
4388    /// When using the alternate flag (`{:#}`), the statement will be formatted with proper
4389    /// indentation and line breaks. For example:
4390    ///
4391    /// ```
4392    /// # use sqlparser::dialect::GenericDialect;
4393    /// # use sqlparser::parser::Parser;
4394    /// let sql = "SELECT a, b FROM table_1";
4395    /// let ast = Parser::parse_sql(&GenericDialect, sql).unwrap();
4396    ///
4397    /// // Regular formatting
4398    /// assert_eq!(format!("{}", ast[0]), "SELECT a, b FROM table_1");
4399    ///
4400    /// // Pretty printing
4401    /// assert_eq!(format!("{:#}", ast[0]),
4402    /// r#"SELECT
4403    ///   a,
4404    ///   b
4405    /// FROM
4406    ///   table_1"#);
4407    /// ```
4408    // Clippy thinks this function is too complicated, but it is painful to
4409    // split up without extracting structs for each `Statement` variant.
4410    #[allow(clippy::cognitive_complexity)]
4411    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
4412        match self {
4413            Statement::Flush {
4414                object_type,
4415                location,
4416                channel,
4417                read_lock,
4418                export,
4419                tables,
4420            } => {
4421                write!(f, "FLUSH")?;
4422                if let Some(location) = location {
4423                    f.write_str(" ")?;
4424                    location.fmt(f)?;
4425                }
4426                write!(f, " {object_type}")?;
4427
4428                if let Some(channel) = channel {
4429                    write!(f, " FOR CHANNEL {channel}")?;
4430                }
4431
4432                write!(
4433                    f,
4434                    "{tables}{read}{export}",
4435                    tables = if !tables.is_empty() {
4436                        " ".to_string() + &display_comma_separated(tables).to_string()
4437                    } else {
4438                        "".to_string()
4439                    },
4440                    export = if *export { " FOR EXPORT" } else { "" },
4441                    read = if *read_lock { " WITH READ LOCK" } else { "" }
4442                )
4443            }
4444            Statement::Kill { modifier, id } => {
4445                write!(f, "KILL ")?;
4446
4447                if let Some(m) = modifier {
4448                    write!(f, "{m} ")?;
4449                }
4450
4451                write!(f, "{id}")
4452            }
4453            Statement::ExplainTable {
4454                describe_alias,
4455                hive_format,
4456                has_table_keyword,
4457                table_name,
4458            } => {
4459                write!(f, "{describe_alias} ")?;
4460
4461                if let Some(format) = hive_format {
4462                    write!(f, "{format} ")?;
4463                }
4464                if *has_table_keyword {
4465                    write!(f, "TABLE ")?;
4466                }
4467
4468                write!(f, "{table_name}")
4469            }
4470            Statement::Explain {
4471                describe_alias,
4472                verbose,
4473                analyze,
4474                query_plan,
4475                estimate,
4476                statement,
4477                format,
4478                options,
4479            } => {
4480                write!(f, "{describe_alias} ")?;
4481
4482                if *query_plan {
4483                    write!(f, "QUERY PLAN ")?;
4484                }
4485                if *analyze {
4486                    write!(f, "ANALYZE ")?;
4487                }
4488                if *estimate {
4489                    write!(f, "ESTIMATE ")?;
4490                }
4491
4492                if *verbose {
4493                    write!(f, "VERBOSE ")?;
4494                }
4495
4496                if let Some(format) = format {
4497                    write!(f, "FORMAT {format} ")?;
4498                }
4499
4500                if let Some(options) = options {
4501                    write!(f, "({}) ", display_comma_separated(options))?;
4502                }
4503
4504                write!(f, "{statement}")
4505            }
4506            Statement::Query(s) => s.fmt(f),
4507            Statement::Declare { stmts } => {
4508                write!(f, "DECLARE ")?;
4509                write!(f, "{}", display_separated(stmts, "; "))
4510            }
4511            Statement::Fetch {
4512                name,
4513                direction,
4514                position,
4515                into,
4516            } => {
4517                write!(f, "FETCH {direction} {position} {name}")?;
4518
4519                if let Some(into) = into {
4520                    write!(f, " INTO {into}")?;
4521                }
4522
4523                Ok(())
4524            }
4525            Statement::Directory {
4526                overwrite,
4527                local,
4528                path,
4529                file_format,
4530                source,
4531            } => {
4532                write!(
4533                    f,
4534                    "INSERT{overwrite}{local} DIRECTORY '{path}'",
4535                    overwrite = if *overwrite { " OVERWRITE" } else { "" },
4536                    local = if *local { " LOCAL" } else { "" },
4537                    path = path
4538                )?;
4539                if let Some(ref ff) = file_format {
4540                    write!(f, " STORED AS {ff}")?
4541                }
4542                write!(f, " {source}")
4543            }
4544            Statement::Msck {
4545                table_name,
4546                repair,
4547                partition_action,
4548            } => {
4549                write!(
4550                    f,
4551                    "MSCK {repair}TABLE {table}",
4552                    repair = if *repair { "REPAIR " } else { "" },
4553                    table = table_name
4554                )?;
4555                if let Some(pa) = partition_action {
4556                    write!(f, " {pa}")?;
4557                }
4558                Ok(())
4559            }
4560            Statement::Truncate {
4561                table_names,
4562                partitions,
4563                table,
4564                identity,
4565                cascade,
4566                on_cluster,
4567            } => {
4568                let table = if *table { "TABLE " } else { "" };
4569
4570                write!(
4571                    f,
4572                    "TRUNCATE {table}{table_names}",
4573                    table_names = display_comma_separated(table_names)
4574                )?;
4575
4576                if let Some(identity) = identity {
4577                    match identity {
4578                        TruncateIdentityOption::Restart => write!(f, " RESTART IDENTITY")?,
4579                        TruncateIdentityOption::Continue => write!(f, " CONTINUE IDENTITY")?,
4580                    }
4581                }
4582                if let Some(cascade) = cascade {
4583                    match cascade {
4584                        CascadeOption::Cascade => write!(f, " CASCADE")?,
4585                        CascadeOption::Restrict => write!(f, " RESTRICT")?,
4586                    }
4587                }
4588
4589                if let Some(ref parts) = partitions {
4590                    if !parts.is_empty() {
4591                        write!(f, " PARTITION ({})", display_comma_separated(parts))?;
4592                    }
4593                }
4594                if let Some(on_cluster) = on_cluster {
4595                    write!(f, " ON CLUSTER {on_cluster}")?;
4596                }
4597                Ok(())
4598            }
4599            Statement::Case(stmt) => {
4600                write!(f, "{stmt}")
4601            }
4602            Statement::If(stmt) => {
4603                write!(f, "{stmt}")
4604            }
4605            Statement::While(stmt) => {
4606                write!(f, "{stmt}")
4607            }
4608            Statement::Raise(stmt) => {
4609                write!(f, "{stmt}")
4610            }
4611            Statement::AttachDatabase {
4612                schema_name,
4613                database_file_name,
4614                database,
4615            } => {
4616                let keyword = if *database { "DATABASE " } else { "" };
4617                write!(f, "ATTACH {keyword}{database_file_name} AS {schema_name}")
4618            }
4619            Statement::AttachDuckDBDatabase {
4620                if_not_exists,
4621                database,
4622                database_path,
4623                database_alias,
4624                attach_options,
4625            } => {
4626                write!(
4627                    f,
4628                    "ATTACH{database}{if_not_exists} {database_path}",
4629                    database = if *database { " DATABASE" } else { "" },
4630                    if_not_exists = if *if_not_exists { " IF NOT EXISTS" } else { "" },
4631                )?;
4632                if let Some(alias) = database_alias {
4633                    write!(f, " AS {alias}")?;
4634                }
4635                if !attach_options.is_empty() {
4636                    write!(f, " ({})", display_comma_separated(attach_options))?;
4637                }
4638                Ok(())
4639            }
4640            Statement::DetachDuckDBDatabase {
4641                if_exists,
4642                database,
4643                database_alias,
4644            } => {
4645                write!(
4646                    f,
4647                    "DETACH{database}{if_exists} {database_alias}",
4648                    database = if *database { " DATABASE" } else { "" },
4649                    if_exists = if *if_exists { " IF EXISTS" } else { "" },
4650                )?;
4651                Ok(())
4652            }
4653            Statement::Analyze {
4654                table_name,
4655                partitions,
4656                for_columns,
4657                columns,
4658                cache_metadata,
4659                noscan,
4660                compute_statistics,
4661                has_table_keyword,
4662            } => {
4663                write!(
4664                    f,
4665                    "ANALYZE{}{table_name}",
4666                    if *has_table_keyword { " TABLE " } else { " " }
4667                )?;
4668                if let Some(ref parts) = partitions {
4669                    if !parts.is_empty() {
4670                        write!(f, " PARTITION ({})", display_comma_separated(parts))?;
4671                    }
4672                }
4673
4674                if *compute_statistics {
4675                    write!(f, " COMPUTE STATISTICS")?;
4676                }
4677                if *noscan {
4678                    write!(f, " NOSCAN")?;
4679                }
4680                if *cache_metadata {
4681                    write!(f, " CACHE METADATA")?;
4682                }
4683                if *for_columns {
4684                    write!(f, " FOR COLUMNS")?;
4685                    if !columns.is_empty() {
4686                        write!(f, " {}", display_comma_separated(columns))?;
4687                    }
4688                }
4689                Ok(())
4690            }
4691            Statement::Insert(insert) => insert.fmt(f),
4692            Statement::Install {
4693                extension_name: name,
4694            } => write!(f, "INSTALL {name}"),
4695
4696            Statement::Load {
4697                extension_name: name,
4698            } => write!(f, "LOAD {name}"),
4699
4700            Statement::Call(function) => write!(f, "CALL {function}"),
4701
4702            Statement::Copy {
4703                source,
4704                to,
4705                target,
4706                options,
4707                legacy_options,
4708                values,
4709            } => {
4710                write!(f, "COPY")?;
4711                match source {
4712                    CopySource::Query(query) => write!(f, " ({query})")?,
4713                    CopySource::Table {
4714                        table_name,
4715                        columns,
4716                    } => {
4717                        write!(f, " {table_name}")?;
4718                        if !columns.is_empty() {
4719                            write!(f, " ({})", display_comma_separated(columns))?;
4720                        }
4721                    }
4722                }
4723                write!(f, " {} {}", if *to { "TO" } else { "FROM" }, target)?;
4724                if !options.is_empty() {
4725                    write!(f, " ({})", display_comma_separated(options))?;
4726                }
4727                if !legacy_options.is_empty() {
4728                    write!(f, " {}", display_separated(legacy_options, " "))?;
4729                }
4730                if !values.is_empty() {
4731                    writeln!(f, ";")?;
4732                    let mut delim = "";
4733                    for v in values {
4734                        write!(f, "{delim}")?;
4735                        delim = "\t";
4736                        if let Some(v) = v {
4737                            write!(f, "{v}")?;
4738                        } else {
4739                            write!(f, "\\N")?;
4740                        }
4741                    }
4742                    write!(f, "\n\\.")?;
4743                }
4744                Ok(())
4745            }
4746            Statement::Update {
4747                table,
4748                assignments,
4749                from,
4750                selection,
4751                returning,
4752                or,
4753            } => {
4754                f.write_str("UPDATE ")?;
4755                if let Some(or) = or {
4756                    or.fmt(f)?;
4757                    f.write_str(" ")?;
4758                }
4759                table.fmt(f)?;
4760                if let Some(UpdateTableFromKind::BeforeSet(from)) = from {
4761                    SpaceOrNewline.fmt(f)?;
4762                    f.write_str("FROM")?;
4763                    indented_list(f, from)?;
4764                }
4765                if !assignments.is_empty() {
4766                    SpaceOrNewline.fmt(f)?;
4767                    f.write_str("SET")?;
4768                    indented_list(f, assignments)?;
4769                }
4770                if let Some(UpdateTableFromKind::AfterSet(from)) = from {
4771                    SpaceOrNewline.fmt(f)?;
4772                    f.write_str("FROM")?;
4773                    indented_list(f, from)?;
4774                }
4775                if let Some(selection) = selection {
4776                    SpaceOrNewline.fmt(f)?;
4777                    f.write_str("WHERE")?;
4778                    SpaceOrNewline.fmt(f)?;
4779                    Indent(selection).fmt(f)?;
4780                }
4781                if let Some(returning) = returning {
4782                    SpaceOrNewline.fmt(f)?;
4783                    f.write_str("RETURNING")?;
4784                    indented_list(f, returning)?;
4785                }
4786                Ok(())
4787            }
4788            Statement::Delete(delete) => delete.fmt(f),
4789            Statement::Open(open) => open.fmt(f),
4790            Statement::Close { cursor } => {
4791                write!(f, "CLOSE {cursor}")?;
4792
4793                Ok(())
4794            }
4795            Statement::CreateDatabase {
4796                db_name,
4797                if_not_exists,
4798                location,
4799                managed_location,
4800            } => {
4801                write!(f, "CREATE DATABASE")?;
4802                if *if_not_exists {
4803                    write!(f, " IF NOT EXISTS")?;
4804                }
4805                write!(f, " {db_name}")?;
4806                if let Some(l) = location {
4807                    write!(f, " LOCATION '{l}'")?;
4808                }
4809                if let Some(ml) = managed_location {
4810                    write!(f, " MANAGEDLOCATION '{ml}'")?;
4811                }
4812                Ok(())
4813            }
4814            Statement::CreateFunction(create_function) => create_function.fmt(f),
4815            Statement::CreateDomain(create_domain) => create_domain.fmt(f),
4816            Statement::CreateTrigger {
4817                or_alter,
4818                or_replace,
4819                is_constraint,
4820                name,
4821                period,
4822                events,
4823                table_name,
4824                referenced_table_name,
4825                referencing,
4826                trigger_object,
4827                condition,
4828                include_each,
4829                exec_body,
4830                statements,
4831                characteristics,
4832            } => {
4833                write!(
4834                    f,
4835                    "CREATE {or_alter}{or_replace}{is_constraint}TRIGGER {name} ",
4836                    or_alter = if *or_alter { "OR ALTER " } else { "" },
4837                    or_replace = if *or_replace { "OR REPLACE " } else { "" },
4838                    is_constraint = if *is_constraint { "CONSTRAINT " } else { "" },
4839                )?;
4840
4841                if exec_body.is_some() {
4842                    write!(f, "{period}")?;
4843                    if !events.is_empty() {
4844                        write!(f, " {}", display_separated(events, " OR "))?;
4845                    }
4846                    write!(f, " ON {table_name}")?;
4847                } else {
4848                    write!(f, "ON {table_name}")?;
4849                    write!(f, " {period}")?;
4850                    if !events.is_empty() {
4851                        write!(f, " {}", display_separated(events, ", "))?;
4852                    }
4853                }
4854
4855                if let Some(referenced_table_name) = referenced_table_name {
4856                    write!(f, " FROM {referenced_table_name}")?;
4857                }
4858
4859                if let Some(characteristics) = characteristics {
4860                    write!(f, " {characteristics}")?;
4861                }
4862
4863                if !referencing.is_empty() {
4864                    write!(f, " REFERENCING {}", display_separated(referencing, " "))?;
4865                }
4866
4867                if *include_each {
4868                    write!(f, " FOR EACH {trigger_object}")?;
4869                } else if exec_body.is_some() {
4870                    write!(f, " FOR {trigger_object}")?;
4871                }
4872                if let Some(condition) = condition {
4873                    write!(f, " WHEN {condition}")?;
4874                }
4875                if let Some(exec_body) = exec_body {
4876                    write!(f, " EXECUTE {exec_body}")?;
4877                }
4878                if let Some(statements) = statements {
4879                    write!(f, " AS {statements}")?;
4880                }
4881                Ok(())
4882            }
4883            Statement::DropTrigger {
4884                if_exists,
4885                trigger_name,
4886                table_name,
4887                option,
4888            } => {
4889                write!(f, "DROP TRIGGER")?;
4890                if *if_exists {
4891                    write!(f, " IF EXISTS")?;
4892                }
4893                match &table_name {
4894                    Some(table_name) => write!(f, " {trigger_name} ON {table_name}")?,
4895                    None => write!(f, " {trigger_name}")?,
4896                };
4897                if let Some(option) = option {
4898                    write!(f, " {option}")?;
4899                }
4900                Ok(())
4901            }
4902            Statement::CreateProcedure {
4903                name,
4904                or_alter,
4905                params,
4906                language,
4907                body,
4908            } => {
4909                write!(
4910                    f,
4911                    "CREATE {or_alter}PROCEDURE {name}",
4912                    or_alter = if *or_alter { "OR ALTER " } else { "" },
4913                    name = name
4914                )?;
4915
4916                if let Some(p) = params {
4917                    if !p.is_empty() {
4918                        write!(f, " ({})", display_comma_separated(p))?;
4919                    }
4920                }
4921
4922                if let Some(language) = language {
4923                    write!(f, " LANGUAGE {language}")?;
4924                }
4925
4926                write!(f, " AS {body}")
4927            }
4928            Statement::CreateMacro {
4929                or_replace,
4930                temporary,
4931                name,
4932                args,
4933                definition,
4934            } => {
4935                write!(
4936                    f,
4937                    "CREATE {or_replace}{temp}MACRO {name}",
4938                    temp = if *temporary { "TEMPORARY " } else { "" },
4939                    or_replace = if *or_replace { "OR REPLACE " } else { "" },
4940                )?;
4941                if let Some(args) = args {
4942                    write!(f, "({})", display_comma_separated(args))?;
4943                }
4944                match definition {
4945                    MacroDefinition::Expr(expr) => write!(f, " AS {expr}")?,
4946                    MacroDefinition::Table(query) => write!(f, " AS TABLE {query}")?,
4947                }
4948                Ok(())
4949            }
4950            Statement::CreateView {
4951                or_alter,
4952                name,
4953                or_replace,
4954                columns,
4955                query,
4956                materialized,
4957                options,
4958                cluster_by,
4959                comment,
4960                with_no_schema_binding,
4961                if_not_exists,
4962                temporary,
4963                to,
4964                params,
4965            } => {
4966                write!(
4967                    f,
4968                    "CREATE {or_alter}{or_replace}",
4969                    or_alter = if *or_alter { "OR ALTER " } else { "" },
4970                    or_replace = if *or_replace { "OR REPLACE " } else { "" },
4971                )?;
4972                if let Some(params) = params {
4973                    params.fmt(f)?;
4974                }
4975                write!(
4976                    f,
4977                    "{materialized}{temporary}VIEW {if_not_exists}{name}{to}",
4978                    materialized = if *materialized { "MATERIALIZED " } else { "" },
4979                    name = name,
4980                    temporary = if *temporary { "TEMPORARY " } else { "" },
4981                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
4982                    to = to
4983                        .as_ref()
4984                        .map(|to| format!(" TO {to}"))
4985                        .unwrap_or_default()
4986                )?;
4987                if !columns.is_empty() {
4988                    write!(f, " ({})", display_comma_separated(columns))?;
4989                }
4990                if matches!(options, CreateTableOptions::With(_)) {
4991                    write!(f, " {options}")?;
4992                }
4993                if let Some(comment) = comment {
4994                    write!(
4995                        f,
4996                        " COMMENT = '{}'",
4997                        value::escape_single_quote_string(comment)
4998                    )?;
4999                }
5000                if !cluster_by.is_empty() {
5001                    write!(f, " CLUSTER BY ({})", display_comma_separated(cluster_by))?;
5002                }
5003                if matches!(options, CreateTableOptions::Options(_)) {
5004                    write!(f, " {options}")?;
5005                }
5006                f.write_str(" AS")?;
5007                SpaceOrNewline.fmt(f)?;
5008                query.fmt(f)?;
5009                if *with_no_schema_binding {
5010                    write!(f, " WITH NO SCHEMA BINDING")?;
5011                }
5012                Ok(())
5013            }
5014            Statement::CreateTable(create_table) => create_table.fmt(f),
5015            Statement::LoadData {
5016                local,
5017                inpath,
5018                overwrite,
5019                table_name,
5020                partitioned,
5021                table_format,
5022            } => {
5023                write!(
5024                    f,
5025                    "LOAD DATA {local}INPATH '{inpath}' {overwrite}INTO TABLE {table_name}",
5026                    local = if *local { "LOCAL " } else { "" },
5027                    inpath = inpath,
5028                    overwrite = if *overwrite { "OVERWRITE " } else { "" },
5029                    table_name = table_name,
5030                )?;
5031                if let Some(ref parts) = &partitioned {
5032                    if !parts.is_empty() {
5033                        write!(f, " PARTITION ({})", display_comma_separated(parts))?;
5034                    }
5035                }
5036                if let Some(HiveLoadDataFormat {
5037                    serde,
5038                    input_format,
5039                }) = &table_format
5040                {
5041                    write!(f, " INPUTFORMAT {input_format} SERDE {serde}")?;
5042                }
5043                Ok(())
5044            }
5045            Statement::CreateVirtualTable {
5046                name,
5047                if_not_exists,
5048                module_name,
5049                module_args,
5050            } => {
5051                write!(
5052                    f,
5053                    "CREATE VIRTUAL TABLE {if_not_exists}{name} USING {module_name}",
5054                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
5055                    name = name,
5056                    module_name = module_name
5057                )?;
5058                if !module_args.is_empty() {
5059                    write!(f, " ({})", display_comma_separated(module_args))?;
5060                }
5061                Ok(())
5062            }
5063            Statement::CreateIndex(create_index) => create_index.fmt(f),
5064            Statement::CreateExtension {
5065                name,
5066                if_not_exists,
5067                cascade,
5068                schema,
5069                version,
5070            } => {
5071                write!(
5072                    f,
5073                    "CREATE EXTENSION {if_not_exists}{name}",
5074                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" }
5075                )?;
5076                if *cascade || schema.is_some() || version.is_some() {
5077                    write!(f, " WITH")?;
5078
5079                    if let Some(name) = schema {
5080                        write!(f, " SCHEMA {name}")?;
5081                    }
5082                    if let Some(version) = version {
5083                        write!(f, " VERSION {version}")?;
5084                    }
5085                    if *cascade {
5086                        write!(f, " CASCADE")?;
5087                    }
5088                }
5089
5090                Ok(())
5091            }
5092            Statement::DropExtension {
5093                names,
5094                if_exists,
5095                cascade_or_restrict,
5096            } => {
5097                write!(f, "DROP EXTENSION")?;
5098                if *if_exists {
5099                    write!(f, " IF EXISTS")?;
5100                }
5101                write!(f, " {}", display_comma_separated(names))?;
5102                if let Some(cascade_or_restrict) = cascade_or_restrict {
5103                    write!(f, " {cascade_or_restrict}")?;
5104                }
5105                Ok(())
5106            }
5107            Statement::CreateRole {
5108                names,
5109                if_not_exists,
5110                inherit,
5111                login,
5112                bypassrls,
5113                password,
5114                create_db,
5115                create_role,
5116                superuser,
5117                replication,
5118                connection_limit,
5119                valid_until,
5120                in_role,
5121                in_group,
5122                role,
5123                user,
5124                admin,
5125                authorization_owner,
5126            } => {
5127                write!(
5128                    f,
5129                    "CREATE ROLE {if_not_exists}{names}{superuser}{create_db}{create_role}{inherit}{login}{replication}{bypassrls}",
5130                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
5131                    names = display_separated(names, ", "),
5132                    superuser = match *superuser {
5133                        Some(true) => " SUPERUSER",
5134                        Some(false) => " NOSUPERUSER",
5135                        None => ""
5136                    },
5137                    create_db = match *create_db {
5138                        Some(true) => " CREATEDB",
5139                        Some(false) => " NOCREATEDB",
5140                        None => ""
5141                    },
5142                    create_role = match *create_role {
5143                        Some(true) => " CREATEROLE",
5144                        Some(false) => " NOCREATEROLE",
5145                        None => ""
5146                    },
5147                    inherit = match *inherit {
5148                        Some(true) => " INHERIT",
5149                        Some(false) => " NOINHERIT",
5150                        None => ""
5151                    },
5152                    login = match *login {
5153                        Some(true) => " LOGIN",
5154                        Some(false) => " NOLOGIN",
5155                        None => ""
5156                    },
5157                    replication = match *replication {
5158                        Some(true) => " REPLICATION",
5159                        Some(false) => " NOREPLICATION",
5160                        None => ""
5161                    },
5162                    bypassrls = match *bypassrls {
5163                        Some(true) => " BYPASSRLS",
5164                        Some(false) => " NOBYPASSRLS",
5165                        None => ""
5166                    }
5167                )?;
5168                if let Some(limit) = connection_limit {
5169                    write!(f, " CONNECTION LIMIT {limit}")?;
5170                }
5171                match password {
5172                    Some(Password::Password(pass)) => write!(f, " PASSWORD {pass}"),
5173                    Some(Password::NullPassword) => write!(f, " PASSWORD NULL"),
5174                    None => Ok(()),
5175                }?;
5176                if let Some(until) = valid_until {
5177                    write!(f, " VALID UNTIL {until}")?;
5178                }
5179                if !in_role.is_empty() {
5180                    write!(f, " IN ROLE {}", display_comma_separated(in_role))?;
5181                }
5182                if !in_group.is_empty() {
5183                    write!(f, " IN GROUP {}", display_comma_separated(in_group))?;
5184                }
5185                if !role.is_empty() {
5186                    write!(f, " ROLE {}", display_comma_separated(role))?;
5187                }
5188                if !user.is_empty() {
5189                    write!(f, " USER {}", display_comma_separated(user))?;
5190                }
5191                if !admin.is_empty() {
5192                    write!(f, " ADMIN {}", display_comma_separated(admin))?;
5193                }
5194                if let Some(owner) = authorization_owner {
5195                    write!(f, " AUTHORIZATION {owner}")?;
5196                }
5197                Ok(())
5198            }
5199            Statement::CreateSecret {
5200                or_replace,
5201                temporary,
5202                if_not_exists,
5203                name,
5204                storage_specifier,
5205                secret_type,
5206                options,
5207            } => {
5208                write!(
5209                    f,
5210                    "CREATE {or_replace}",
5211                    or_replace = if *or_replace { "OR REPLACE " } else { "" },
5212                )?;
5213                if let Some(t) = temporary {
5214                    write!(f, "{}", if *t { "TEMPORARY " } else { "PERSISTENT " })?;
5215                }
5216                write!(
5217                    f,
5218                    "SECRET {if_not_exists}",
5219                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
5220                )?;
5221                if let Some(n) = name {
5222                    write!(f, "{n} ")?;
5223                };
5224                if let Some(s) = storage_specifier {
5225                    write!(f, "IN {s} ")?;
5226                }
5227                write!(f, "( TYPE {secret_type}",)?;
5228                if !options.is_empty() {
5229                    write!(f, ", {o}", o = display_comma_separated(options))?;
5230                }
5231                write!(f, " )")?;
5232                Ok(())
5233            }
5234            Statement::CreateServer(stmt) => {
5235                write!(f, "{stmt}")
5236            }
5237            Statement::CreatePolicy {
5238                name,
5239                table_name,
5240                policy_type,
5241                command,
5242                to,
5243                using,
5244                with_check,
5245            } => {
5246                write!(f, "CREATE POLICY {name} ON {table_name}")?;
5247
5248                if let Some(policy_type) = policy_type {
5249                    match policy_type {
5250                        CreatePolicyType::Permissive => write!(f, " AS PERMISSIVE")?,
5251                        CreatePolicyType::Restrictive => write!(f, " AS RESTRICTIVE")?,
5252                    }
5253                }
5254
5255                if let Some(command) = command {
5256                    match command {
5257                        CreatePolicyCommand::All => write!(f, " FOR ALL")?,
5258                        CreatePolicyCommand::Select => write!(f, " FOR SELECT")?,
5259                        CreatePolicyCommand::Insert => write!(f, " FOR INSERT")?,
5260                        CreatePolicyCommand::Update => write!(f, " FOR UPDATE")?,
5261                        CreatePolicyCommand::Delete => write!(f, " FOR DELETE")?,
5262                    }
5263                }
5264
5265                if let Some(to) = to {
5266                    write!(f, " TO {}", display_comma_separated(to))?;
5267                }
5268
5269                if let Some(using) = using {
5270                    write!(f, " USING ({using})")?;
5271                }
5272
5273                if let Some(with_check) = with_check {
5274                    write!(f, " WITH CHECK ({with_check})")?;
5275                }
5276
5277                Ok(())
5278            }
5279            Statement::CreateConnector(create_connector) => create_connector.fmt(f),
5280            Statement::AlterTable {
5281                name,
5282                if_exists,
5283                only,
5284                operations,
5285                location,
5286                on_cluster,
5287                iceberg,
5288            } => {
5289                if *iceberg {
5290                    write!(f, "ALTER ICEBERG TABLE ")?;
5291                } else {
5292                    write!(f, "ALTER TABLE ")?;
5293                }
5294
5295                if *if_exists {
5296                    write!(f, "IF EXISTS ")?;
5297                }
5298                if *only {
5299                    write!(f, "ONLY ")?;
5300                }
5301                write!(f, "{name} ")?;
5302                if let Some(cluster) = on_cluster {
5303                    write!(f, "ON CLUSTER {cluster} ")?;
5304                }
5305                write!(
5306                    f,
5307                    "{operations}",
5308                    operations = display_comma_separated(operations)
5309                )?;
5310                if let Some(loc) = location {
5311                    write!(f, " {loc}")?
5312                }
5313                Ok(())
5314            }
5315            Statement::AlterIndex { name, operation } => {
5316                write!(f, "ALTER INDEX {name} {operation}")
5317            }
5318            Statement::AlterView {
5319                name,
5320                columns,
5321                query,
5322                with_options,
5323            } => {
5324                write!(f, "ALTER VIEW {name}")?;
5325                if !with_options.is_empty() {
5326                    write!(f, " WITH ({})", display_comma_separated(with_options))?;
5327                }
5328                if !columns.is_empty() {
5329                    write!(f, " ({})", display_comma_separated(columns))?;
5330                }
5331                write!(f, " AS {query}")
5332            }
5333            Statement::AlterType(AlterType { name, operation }) => {
5334                write!(f, "ALTER TYPE {name} {operation}")
5335            }
5336            Statement::AlterRole { name, operation } => {
5337                write!(f, "ALTER ROLE {name} {operation}")
5338            }
5339            Statement::AlterPolicy {
5340                name,
5341                table_name,
5342                operation,
5343            } => {
5344                write!(f, "ALTER POLICY {name} ON {table_name}{operation}")
5345            }
5346            Statement::AlterConnector {
5347                name,
5348                properties,
5349                url,
5350                owner,
5351            } => {
5352                write!(f, "ALTER CONNECTOR {name}")?;
5353                if let Some(properties) = properties {
5354                    write!(
5355                        f,
5356                        " SET DCPROPERTIES({})",
5357                        display_comma_separated(properties)
5358                    )?;
5359                }
5360                if let Some(url) = url {
5361                    write!(f, " SET URL '{url}'")?;
5362                }
5363                if let Some(owner) = owner {
5364                    write!(f, " SET OWNER {owner}")?;
5365                }
5366                Ok(())
5367            }
5368            Statement::AlterSession {
5369                set,
5370                session_params,
5371            } => {
5372                write!(
5373                    f,
5374                    "ALTER SESSION {set}",
5375                    set = if *set { "SET" } else { "UNSET" }
5376                )?;
5377                if !session_params.options.is_empty() {
5378                    if *set {
5379                        write!(f, " {session_params}")?;
5380                    } else {
5381                        let options = session_params
5382                            .options
5383                            .iter()
5384                            .map(|p| p.option_name.clone())
5385                            .collect::<Vec<_>>();
5386                        write!(f, " {}", display_separated(&options, ", "))?;
5387                    }
5388                }
5389                Ok(())
5390            }
5391            Statement::Drop {
5392                object_type,
5393                if_exists,
5394                names,
5395                cascade,
5396                restrict,
5397                purge,
5398                temporary,
5399                table,
5400            } => {
5401                write!(
5402                    f,
5403                    "DROP {}{}{} {}{}{}{}",
5404                    if *temporary { "TEMPORARY " } else { "" },
5405                    object_type,
5406                    if *if_exists { " IF EXISTS" } else { "" },
5407                    display_comma_separated(names),
5408                    if *cascade { " CASCADE" } else { "" },
5409                    if *restrict { " RESTRICT" } else { "" },
5410                    if *purge { " PURGE" } else { "" },
5411                )?;
5412                if let Some(table_name) = table.as_ref() {
5413                    write!(f, " ON {table_name}")?;
5414                };
5415                Ok(())
5416            }
5417            Statement::DropFunction {
5418                if_exists,
5419                func_desc,
5420                drop_behavior,
5421            } => {
5422                write!(
5423                    f,
5424                    "DROP FUNCTION{} {}",
5425                    if *if_exists { " IF EXISTS" } else { "" },
5426                    display_comma_separated(func_desc),
5427                )?;
5428                if let Some(op) = drop_behavior {
5429                    write!(f, " {op}")?;
5430                }
5431                Ok(())
5432            }
5433            Statement::DropDomain(DropDomain {
5434                if_exists,
5435                name,
5436                drop_behavior,
5437            }) => {
5438                write!(
5439                    f,
5440                    "DROP DOMAIN{} {name}",
5441                    if *if_exists { " IF EXISTS" } else { "" },
5442                )?;
5443                if let Some(op) = drop_behavior {
5444                    write!(f, " {op}")?;
5445                }
5446                Ok(())
5447            }
5448            Statement::DropProcedure {
5449                if_exists,
5450                proc_desc,
5451                drop_behavior,
5452            } => {
5453                write!(
5454                    f,
5455                    "DROP PROCEDURE{} {}",
5456                    if *if_exists { " IF EXISTS" } else { "" },
5457                    display_comma_separated(proc_desc),
5458                )?;
5459                if let Some(op) = drop_behavior {
5460                    write!(f, " {op}")?;
5461                }
5462                Ok(())
5463            }
5464            Statement::DropSecret {
5465                if_exists,
5466                temporary,
5467                name,
5468                storage_specifier,
5469            } => {
5470                write!(f, "DROP ")?;
5471                if let Some(t) = temporary {
5472                    write!(f, "{}", if *t { "TEMPORARY " } else { "PERSISTENT " })?;
5473                }
5474                write!(
5475                    f,
5476                    "SECRET {if_exists}{name}",
5477                    if_exists = if *if_exists { "IF EXISTS " } else { "" },
5478                )?;
5479                if let Some(s) = storage_specifier {
5480                    write!(f, " FROM {s}")?;
5481                }
5482                Ok(())
5483            }
5484            Statement::DropPolicy {
5485                if_exists,
5486                name,
5487                table_name,
5488                drop_behavior,
5489            } => {
5490                write!(f, "DROP POLICY")?;
5491                if *if_exists {
5492                    write!(f, " IF EXISTS")?;
5493                }
5494                write!(f, " {name} ON {table_name}")?;
5495                if let Some(drop_behavior) = drop_behavior {
5496                    write!(f, " {drop_behavior}")?;
5497                }
5498                Ok(())
5499            }
5500            Statement::DropConnector { if_exists, name } => {
5501                write!(
5502                    f,
5503                    "DROP CONNECTOR {if_exists}{name}",
5504                    if_exists = if *if_exists { "IF EXISTS " } else { "" }
5505                )?;
5506                Ok(())
5507            }
5508            Statement::Discard { object_type } => {
5509                write!(f, "DISCARD {object_type}")?;
5510                Ok(())
5511            }
5512            Self::Set(set) => write!(f, "{set}"),
5513            Statement::ShowVariable { variable } => {
5514                write!(f, "SHOW")?;
5515                if !variable.is_empty() {
5516                    write!(f, " {}", display_separated(variable, " "))?;
5517                }
5518                Ok(())
5519            }
5520            Statement::ShowStatus {
5521                filter,
5522                global,
5523                session,
5524            } => {
5525                write!(f, "SHOW")?;
5526                if *global {
5527                    write!(f, " GLOBAL")?;
5528                }
5529                if *session {
5530                    write!(f, " SESSION")?;
5531                }
5532                write!(f, " STATUS")?;
5533                if filter.is_some() {
5534                    write!(f, " {}", filter.as_ref().unwrap())?;
5535                }
5536                Ok(())
5537            }
5538            Statement::ShowVariables {
5539                filter,
5540                global,
5541                session,
5542            } => {
5543                write!(f, "SHOW")?;
5544                if *global {
5545                    write!(f, " GLOBAL")?;
5546                }
5547                if *session {
5548                    write!(f, " SESSION")?;
5549                }
5550                write!(f, " VARIABLES")?;
5551                if filter.is_some() {
5552                    write!(f, " {}", filter.as_ref().unwrap())?;
5553                }
5554                Ok(())
5555            }
5556            Statement::ShowCreate { obj_type, obj_name } => {
5557                write!(f, "SHOW CREATE {obj_type} {obj_name}",)?;
5558                Ok(())
5559            }
5560            Statement::ShowColumns {
5561                extended,
5562                full,
5563                show_options,
5564            } => {
5565                write!(
5566                    f,
5567                    "SHOW {extended}{full}COLUMNS{show_options}",
5568                    extended = if *extended { "EXTENDED " } else { "" },
5569                    full = if *full { "FULL " } else { "" },
5570                )?;
5571                Ok(())
5572            }
5573            Statement::ShowDatabases {
5574                terse,
5575                history,
5576                show_options,
5577            } => {
5578                write!(
5579                    f,
5580                    "SHOW {terse}DATABASES{history}{show_options}",
5581                    terse = if *terse { "TERSE " } else { "" },
5582                    history = if *history { " HISTORY" } else { "" },
5583                )?;
5584                Ok(())
5585            }
5586            Statement::ShowSchemas {
5587                terse,
5588                history,
5589                show_options,
5590            } => {
5591                write!(
5592                    f,
5593                    "SHOW {terse}SCHEMAS{history}{show_options}",
5594                    terse = if *terse { "TERSE " } else { "" },
5595                    history = if *history { " HISTORY" } else { "" },
5596                )?;
5597                Ok(())
5598            }
5599            Statement::ShowObjects(ShowObjects {
5600                terse,
5601                show_options,
5602            }) => {
5603                write!(
5604                    f,
5605                    "SHOW {terse}OBJECTS{show_options}",
5606                    terse = if *terse { "TERSE " } else { "" },
5607                )?;
5608                Ok(())
5609            }
5610            Statement::ShowTables {
5611                terse,
5612                history,
5613                extended,
5614                full,
5615                external,
5616                show_options,
5617            } => {
5618                write!(
5619                    f,
5620                    "SHOW {terse}{extended}{full}{external}TABLES{history}{show_options}",
5621                    terse = if *terse { "TERSE " } else { "" },
5622                    extended = if *extended { "EXTENDED " } else { "" },
5623                    full = if *full { "FULL " } else { "" },
5624                    external = if *external { "EXTERNAL " } else { "" },
5625                    history = if *history { " HISTORY" } else { "" },
5626                )?;
5627                Ok(())
5628            }
5629            Statement::ShowViews {
5630                terse,
5631                materialized,
5632                show_options,
5633            } => {
5634                write!(
5635                    f,
5636                    "SHOW {terse}{materialized}VIEWS{show_options}",
5637                    terse = if *terse { "TERSE " } else { "" },
5638                    materialized = if *materialized { "MATERIALIZED " } else { "" }
5639                )?;
5640                Ok(())
5641            }
5642            Statement::ShowFunctions { filter } => {
5643                write!(f, "SHOW FUNCTIONS")?;
5644                if let Some(filter) = filter {
5645                    write!(f, " {filter}")?;
5646                }
5647                Ok(())
5648            }
5649            Statement::Use(use_expr) => use_expr.fmt(f),
5650            Statement::ShowCollation { filter } => {
5651                write!(f, "SHOW COLLATION")?;
5652                if let Some(filter) = filter {
5653                    write!(f, " {filter}")?;
5654                }
5655                Ok(())
5656            }
5657            Statement::StartTransaction {
5658                modes,
5659                begin: syntax_begin,
5660                transaction,
5661                modifier,
5662                statements,
5663                exception,
5664                has_end_keyword,
5665            } => {
5666                if *syntax_begin {
5667                    if let Some(modifier) = *modifier {
5668                        write!(f, "BEGIN {modifier}")?;
5669                    } else {
5670                        write!(f, "BEGIN")?;
5671                    }
5672                } else {
5673                    write!(f, "START")?;
5674                }
5675                if let Some(transaction) = transaction {
5676                    write!(f, " {transaction}")?;
5677                }
5678                if !modes.is_empty() {
5679                    write!(f, " {}", display_comma_separated(modes))?;
5680                }
5681                if !statements.is_empty() {
5682                    write!(f, " ")?;
5683                    format_statement_list(f, statements)?;
5684                }
5685                if let Some(exception_when) = exception {
5686                    write!(f, " EXCEPTION")?;
5687                    for when in exception_when {
5688                        write!(f, " {when}")?;
5689                    }
5690                }
5691                if *has_end_keyword {
5692                    write!(f, " END")?;
5693                }
5694                Ok(())
5695            }
5696            Statement::Commit {
5697                chain,
5698                end: end_syntax,
5699                modifier,
5700            } => {
5701                if *end_syntax {
5702                    write!(f, "END")?;
5703                    if let Some(modifier) = *modifier {
5704                        write!(f, " {modifier}")?;
5705                    }
5706                    if *chain {
5707                        write!(f, " AND CHAIN")?;
5708                    }
5709                } else {
5710                    write!(f, "COMMIT{}", if *chain { " AND CHAIN" } else { "" })?;
5711                }
5712                Ok(())
5713            }
5714            Statement::Rollback { chain, savepoint } => {
5715                write!(f, "ROLLBACK")?;
5716
5717                if *chain {
5718                    write!(f, " AND CHAIN")?;
5719                }
5720
5721                if let Some(savepoint) = savepoint {
5722                    write!(f, " TO SAVEPOINT {savepoint}")?;
5723                }
5724
5725                Ok(())
5726            }
5727            Statement::CreateSchema {
5728                schema_name,
5729                if_not_exists,
5730                with,
5731                options,
5732                default_collate_spec,
5733            } => {
5734                write!(
5735                    f,
5736                    "CREATE SCHEMA {if_not_exists}{name}",
5737                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
5738                    name = schema_name
5739                )?;
5740
5741                if let Some(collate) = default_collate_spec {
5742                    write!(f, " DEFAULT COLLATE {collate}")?;
5743                }
5744
5745                if let Some(with) = with {
5746                    write!(f, " WITH ({})", display_comma_separated(with))?;
5747                }
5748
5749                if let Some(options) = options {
5750                    write!(f, " OPTIONS({})", display_comma_separated(options))?;
5751                }
5752
5753                Ok(())
5754            }
5755            Statement::Assert { condition, message } => {
5756                write!(f, "ASSERT {condition}")?;
5757                if let Some(m) = message {
5758                    write!(f, " AS {m}")?;
5759                }
5760                Ok(())
5761            }
5762            Statement::Grant {
5763                privileges,
5764                objects,
5765                grantees,
5766                with_grant_option,
5767                as_grantor,
5768                granted_by,
5769                current_grants,
5770            } => {
5771                write!(f, "GRANT {privileges} ")?;
5772                if let Some(objects) = objects {
5773                    write!(f, "ON {objects} ")?;
5774                }
5775                write!(f, "TO {}", display_comma_separated(grantees))?;
5776                if *with_grant_option {
5777                    write!(f, " WITH GRANT OPTION")?;
5778                }
5779                if let Some(current_grants) = current_grants {
5780                    write!(f, " {current_grants}")?;
5781                }
5782                if let Some(grantor) = as_grantor {
5783                    write!(f, " AS {grantor}")?;
5784                }
5785                if let Some(grantor) = granted_by {
5786                    write!(f, " GRANTED BY {grantor}")?;
5787                }
5788                Ok(())
5789            }
5790            Statement::Deny(s) => write!(f, "{s}"),
5791            Statement::Revoke {
5792                privileges,
5793                objects,
5794                grantees,
5795                granted_by,
5796                cascade,
5797            } => {
5798                write!(f, "REVOKE {privileges} ")?;
5799                if let Some(objects) = objects {
5800                    write!(f, "ON {objects} ")?;
5801                }
5802                write!(f, "FROM {}", display_comma_separated(grantees))?;
5803                if let Some(grantor) = granted_by {
5804                    write!(f, " GRANTED BY {grantor}")?;
5805                }
5806                if let Some(cascade) = cascade {
5807                    write!(f, " {cascade}")?;
5808                }
5809                Ok(())
5810            }
5811            Statement::Deallocate { name, prepare } => write!(
5812                f,
5813                "DEALLOCATE {prepare}{name}",
5814                prepare = if *prepare { "PREPARE " } else { "" },
5815                name = name,
5816            ),
5817            Statement::Execute {
5818                name,
5819                parameters,
5820                has_parentheses,
5821                immediate,
5822                into,
5823                using,
5824                output,
5825                default,
5826            } => {
5827                let (open, close) = if *has_parentheses {
5828                    ("(", ")")
5829                } else {
5830                    (if parameters.is_empty() { "" } else { " " }, "")
5831                };
5832                write!(f, "EXECUTE")?;
5833                if *immediate {
5834                    write!(f, " IMMEDIATE")?;
5835                }
5836                if let Some(name) = name {
5837                    write!(f, " {name}")?;
5838                }
5839                write!(f, "{open}{}{close}", display_comma_separated(parameters),)?;
5840                if !into.is_empty() {
5841                    write!(f, " INTO {}", display_comma_separated(into))?;
5842                }
5843                if !using.is_empty() {
5844                    write!(f, " USING {}", display_comma_separated(using))?;
5845                };
5846                if *output {
5847                    write!(f, " OUTPUT")?;
5848                }
5849                if *default {
5850                    write!(f, " DEFAULT")?;
5851                }
5852                Ok(())
5853            }
5854            Statement::Prepare {
5855                name,
5856                data_types,
5857                statement,
5858            } => {
5859                write!(f, "PREPARE {name} ")?;
5860                if !data_types.is_empty() {
5861                    write!(f, "({}) ", display_comma_separated(data_types))?;
5862                }
5863                write!(f, "AS {statement}")
5864            }
5865            Statement::Comment {
5866                object_type,
5867                object_name,
5868                comment,
5869                if_exists,
5870            } => {
5871                write!(f, "COMMENT ")?;
5872                if *if_exists {
5873                    write!(f, "IF EXISTS ")?
5874                };
5875                write!(f, "ON {object_type} {object_name} IS ")?;
5876                if let Some(c) = comment {
5877                    write!(f, "'{c}'")
5878                } else {
5879                    write!(f, "NULL")
5880                }
5881            }
5882            Statement::Savepoint { name } => {
5883                write!(f, "SAVEPOINT ")?;
5884                write!(f, "{name}")
5885            }
5886            Statement::ReleaseSavepoint { name } => {
5887                write!(f, "RELEASE SAVEPOINT {name}")
5888            }
5889            Statement::Merge {
5890                into,
5891                table,
5892                source,
5893                on,
5894                clauses,
5895                output,
5896            } => {
5897                write!(
5898                    f,
5899                    "MERGE{int} {table} USING {source} ",
5900                    int = if *into { " INTO" } else { "" }
5901                )?;
5902                write!(f, "ON {on} ")?;
5903                write!(f, "{}", display_separated(clauses, " "))?;
5904                if let Some(output) = output {
5905                    write!(f, " {output}")?;
5906                }
5907                Ok(())
5908            }
5909            Statement::Cache {
5910                table_name,
5911                table_flag,
5912                has_as,
5913                options,
5914                query,
5915            } => {
5916                if let Some(table_flag) = table_flag {
5917                    write!(f, "CACHE {table_flag} TABLE {table_name}")?;
5918                } else {
5919                    write!(f, "CACHE TABLE {table_name}")?;
5920                }
5921
5922                if !options.is_empty() {
5923                    write!(f, " OPTIONS({})", display_comma_separated(options))?;
5924                }
5925
5926                match (*has_as, query) {
5927                    (true, Some(query)) => write!(f, " AS {query}"),
5928                    (true, None) => f.write_str(" AS"),
5929                    (false, Some(query)) => write!(f, " {query}"),
5930                    (false, None) => Ok(()),
5931                }
5932            }
5933            Statement::UNCache {
5934                table_name,
5935                if_exists,
5936            } => {
5937                if *if_exists {
5938                    write!(f, "UNCACHE TABLE IF EXISTS {table_name}")
5939                } else {
5940                    write!(f, "UNCACHE TABLE {table_name}")
5941                }
5942            }
5943            Statement::CreateSequence {
5944                temporary,
5945                if_not_exists,
5946                name,
5947                data_type,
5948                sequence_options,
5949                owned_by,
5950            } => {
5951                let as_type: String = if let Some(dt) = data_type.as_ref() {
5952                    //Cannot use format!(" AS {}", dt), due to format! is not available in --target thumbv6m-none-eabi
5953                    // " AS ".to_owned() + &dt.to_string()
5954                    [" AS ", &dt.to_string()].concat()
5955                } else {
5956                    "".to_string()
5957                };
5958                write!(
5959                    f,
5960                    "CREATE {temporary}SEQUENCE {if_not_exists}{name}{as_type}",
5961                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
5962                    temporary = if *temporary { "TEMPORARY " } else { "" },
5963                    name = name,
5964                    as_type = as_type
5965                )?;
5966                for sequence_option in sequence_options {
5967                    write!(f, "{sequence_option}")?;
5968                }
5969                if let Some(ob) = owned_by.as_ref() {
5970                    write!(f, " OWNED BY {ob}")?;
5971                }
5972                write!(f, "")
5973            }
5974            Statement::CreateStage {
5975                or_replace,
5976                temporary,
5977                if_not_exists,
5978                name,
5979                stage_params,
5980                directory_table_params,
5981                file_format,
5982                copy_options,
5983                comment,
5984                ..
5985            } => {
5986                write!(
5987                    f,
5988                    "CREATE {or_replace}{temp}STAGE {if_not_exists}{name}{stage_params}",
5989                    temp = if *temporary { "TEMPORARY " } else { "" },
5990                    or_replace = if *or_replace { "OR REPLACE " } else { "" },
5991                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
5992                )?;
5993                if !directory_table_params.options.is_empty() {
5994                    write!(f, " DIRECTORY=({directory_table_params})")?;
5995                }
5996                if !file_format.options.is_empty() {
5997                    write!(f, " FILE_FORMAT=({file_format})")?;
5998                }
5999                if !copy_options.options.is_empty() {
6000                    write!(f, " COPY_OPTIONS=({copy_options})")?;
6001                }
6002                if comment.is_some() {
6003                    write!(f, " COMMENT='{}'", comment.as_ref().unwrap())?;
6004                }
6005                Ok(())
6006            }
6007            Statement::CopyIntoSnowflake {
6008                kind,
6009                into,
6010                into_columns,
6011                from_obj,
6012                from_obj_alias,
6013                stage_params,
6014                from_transformations,
6015                from_query,
6016                files,
6017                pattern,
6018                file_format,
6019                copy_options,
6020                validation_mode,
6021                partition,
6022            } => {
6023                write!(f, "COPY INTO {into}")?;
6024                if let Some(into_columns) = into_columns {
6025                    write!(f, " ({})", display_comma_separated(into_columns))?;
6026                }
6027                if let Some(from_transformations) = from_transformations {
6028                    // Data load with transformation
6029                    if let Some(from_stage) = from_obj {
6030                        write!(
6031                            f,
6032                            " FROM (SELECT {} FROM {}{}",
6033                            display_separated(from_transformations, ", "),
6034                            from_stage,
6035                            stage_params
6036                        )?;
6037                    }
6038                    if let Some(from_obj_alias) = from_obj_alias {
6039                        write!(f, " AS {from_obj_alias}")?;
6040                    }
6041                    write!(f, ")")?;
6042                } else if let Some(from_obj) = from_obj {
6043                    // Standard data load
6044                    write!(f, " FROM {from_obj}{stage_params}")?;
6045                    if let Some(from_obj_alias) = from_obj_alias {
6046                        write!(f, " AS {from_obj_alias}")?;
6047                    }
6048                } else if let Some(from_query) = from_query {
6049                    // Data unload from query
6050                    write!(f, " FROM ({from_query})")?;
6051                }
6052
6053                if let Some(files) = files {
6054                    write!(f, " FILES = ('{}')", display_separated(files, "', '"))?;
6055                }
6056                if let Some(pattern) = pattern {
6057                    write!(f, " PATTERN = '{pattern}'")?;
6058                }
6059                if let Some(partition) = partition {
6060                    write!(f, " PARTITION BY {partition}")?;
6061                }
6062                if !file_format.options.is_empty() {
6063                    write!(f, " FILE_FORMAT=({file_format})")?;
6064                }
6065                if !copy_options.options.is_empty() {
6066                    match kind {
6067                        CopyIntoSnowflakeKind::Table => {
6068                            write!(f, " COPY_OPTIONS=({copy_options})")?
6069                        }
6070                        CopyIntoSnowflakeKind::Location => write!(f, " {copy_options}")?,
6071                    }
6072                }
6073                if let Some(validation_mode) = validation_mode {
6074                    write!(f, " VALIDATION_MODE = {validation_mode}")?;
6075                }
6076                Ok(())
6077            }
6078            Statement::CreateType {
6079                name,
6080                representation,
6081            } => {
6082                write!(f, "CREATE TYPE {name} AS {representation}")
6083            }
6084            Statement::Pragma { name, value, is_eq } => {
6085                write!(f, "PRAGMA {name}")?;
6086                if value.is_some() {
6087                    let val = value.as_ref().unwrap();
6088                    if *is_eq {
6089                        write!(f, " = {val}")?;
6090                    } else {
6091                        write!(f, "({val})")?;
6092                    }
6093                }
6094                Ok(())
6095            }
6096            Statement::LockTables { tables } => {
6097                write!(f, "LOCK TABLES {}", display_comma_separated(tables))
6098            }
6099            Statement::UnlockTables => {
6100                write!(f, "UNLOCK TABLES")
6101            }
6102            Statement::Unload { query, to, with } => {
6103                write!(f, "UNLOAD({query}) TO {to}")?;
6104
6105                if !with.is_empty() {
6106                    write!(f, " WITH ({})", display_comma_separated(with))?;
6107                }
6108
6109                Ok(())
6110            }
6111            Statement::OptimizeTable {
6112                name,
6113                on_cluster,
6114                partition,
6115                include_final,
6116                deduplicate,
6117            } => {
6118                write!(f, "OPTIMIZE TABLE {name}")?;
6119                if let Some(on_cluster) = on_cluster {
6120                    write!(f, " ON CLUSTER {on_cluster}")?;
6121                }
6122                if let Some(partition) = partition {
6123                    write!(f, " {partition}")?;
6124                }
6125                if *include_final {
6126                    write!(f, " FINAL")?;
6127                }
6128                if let Some(deduplicate) = deduplicate {
6129                    write!(f, " {deduplicate}")?;
6130                }
6131                Ok(())
6132            }
6133            Statement::LISTEN { channel } => {
6134                write!(f, "LISTEN {channel}")?;
6135                Ok(())
6136            }
6137            Statement::UNLISTEN { channel } => {
6138                write!(f, "UNLISTEN {channel}")?;
6139                Ok(())
6140            }
6141            Statement::NOTIFY { channel, payload } => {
6142                write!(f, "NOTIFY {channel}")?;
6143                if let Some(payload) = payload {
6144                    write!(f, ", '{payload}'")?;
6145                }
6146                Ok(())
6147            }
6148            Statement::RenameTable(rename_tables) => {
6149                write!(f, "RENAME TABLE {}", display_comma_separated(rename_tables))
6150            }
6151            Statement::RaisError {
6152                message,
6153                severity,
6154                state,
6155                arguments,
6156                options,
6157            } => {
6158                write!(f, "RAISERROR({message}, {severity}, {state}")?;
6159                if !arguments.is_empty() {
6160                    write!(f, ", {}", display_comma_separated(arguments))?;
6161                }
6162                write!(f, ")")?;
6163                if !options.is_empty() {
6164                    write!(f, " WITH {}", display_comma_separated(options))?;
6165                }
6166                Ok(())
6167            }
6168            Statement::Print(s) => write!(f, "{s}"),
6169            Statement::Return(r) => write!(f, "{r}"),
6170            Statement::List(command) => write!(f, "LIST {command}"),
6171            Statement::Remove(command) => write!(f, "REMOVE {command}"),
6172        }
6173    }
6174}
6175
6176/// Can use to describe options in create sequence or table column type identity
6177/// ```sql
6178/// [ INCREMENT [ BY ] increment ]
6179///     [ MINVALUE minvalue | NO MINVALUE ] [ MAXVALUE maxvalue | NO MAXVALUE ]
6180///     [ START [ WITH ] start ] [ CACHE cache ] [ [ NO ] CYCLE ]
6181/// ```
6182#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6183#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6184#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6185pub enum SequenceOptions {
6186    IncrementBy(Expr, bool),
6187    MinValue(Option<Expr>),
6188    MaxValue(Option<Expr>),
6189    StartWith(Expr, bool),
6190    Cache(Expr),
6191    Cycle(bool),
6192}
6193
6194impl fmt::Display for SequenceOptions {
6195    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6196        match self {
6197            SequenceOptions::IncrementBy(increment, by) => {
6198                write!(
6199                    f,
6200                    " INCREMENT{by} {increment}",
6201                    by = if *by { " BY" } else { "" },
6202                    increment = increment
6203                )
6204            }
6205            SequenceOptions::MinValue(Some(expr)) => {
6206                write!(f, " MINVALUE {expr}")
6207            }
6208            SequenceOptions::MinValue(None) => {
6209                write!(f, " NO MINVALUE")
6210            }
6211            SequenceOptions::MaxValue(Some(expr)) => {
6212                write!(f, " MAXVALUE {expr}")
6213            }
6214            SequenceOptions::MaxValue(None) => {
6215                write!(f, " NO MAXVALUE")
6216            }
6217            SequenceOptions::StartWith(start, with) => {
6218                write!(
6219                    f,
6220                    " START{with} {start}",
6221                    with = if *with { " WITH" } else { "" },
6222                    start = start
6223                )
6224            }
6225            SequenceOptions::Cache(cache) => {
6226                write!(f, " CACHE {}", *cache)
6227            }
6228            SequenceOptions::Cycle(no) => {
6229                write!(f, " {}CYCLE", if *no { "NO " } else { "" })
6230            }
6231        }
6232    }
6233}
6234
6235/// Assignment for a `SET` statement (name [=|TO] value)
6236#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6237#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6238#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6239pub struct SetAssignment {
6240    pub scope: Option<ContextModifier>,
6241    pub name: ObjectName,
6242    pub value: Expr,
6243}
6244
6245impl fmt::Display for SetAssignment {
6246    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6247        write!(
6248            f,
6249            "{}{} = {}",
6250            self.scope.map(|s| format!("{s}")).unwrap_or_default(),
6251            self.name,
6252            self.value
6253        )
6254    }
6255}
6256
6257/// Target of a `TRUNCATE TABLE` command
6258///
6259/// Note this is its own struct because `visit_relation` requires an `ObjectName` (not a `Vec<ObjectName>`)
6260#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6261#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6262#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6263pub struct TruncateTableTarget {
6264    /// name of the table being truncated
6265    #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
6266    pub name: ObjectName,
6267    /// Postgres-specific option
6268    /// [ TRUNCATE TABLE ONLY ]
6269    /// <https://www.postgresql.org/docs/current/sql-truncate.html>
6270    pub only: bool,
6271}
6272
6273impl fmt::Display for TruncateTableTarget {
6274    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6275        if self.only {
6276            write!(f, "ONLY ")?;
6277        };
6278        write!(f, "{}", self.name)
6279    }
6280}
6281
6282/// PostgreSQL identity option for TRUNCATE table
6283/// [ RESTART IDENTITY | CONTINUE IDENTITY ]
6284#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6285#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6286#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6287pub enum TruncateIdentityOption {
6288    Restart,
6289    Continue,
6290}
6291
6292/// Cascade/restrict option for Postgres TRUNCATE table, MySQL GRANT/REVOKE, etc.
6293/// [ CASCADE | RESTRICT ]
6294#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6295#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6296#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6297pub enum CascadeOption {
6298    Cascade,
6299    Restrict,
6300}
6301
6302impl Display for CascadeOption {
6303    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6304        match self {
6305            CascadeOption::Cascade => write!(f, "CASCADE"),
6306            CascadeOption::Restrict => write!(f, "RESTRICT"),
6307        }
6308    }
6309}
6310
6311/// Transaction started with [ TRANSACTION | WORK ]
6312#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6313#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6314#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6315pub enum BeginTransactionKind {
6316    Transaction,
6317    Work,
6318}
6319
6320impl Display for BeginTransactionKind {
6321    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6322        match self {
6323            BeginTransactionKind::Transaction => write!(f, "TRANSACTION"),
6324            BeginTransactionKind::Work => write!(f, "WORK"),
6325        }
6326    }
6327}
6328
6329/// Can use to describe options in  create sequence or table column type identity
6330/// [ MINVALUE minvalue | NO MINVALUE ] [ MAXVALUE maxvalue | NO MAXVALUE ]
6331#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6332#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6333#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6334pub enum MinMaxValue {
6335    // clause is not specified
6336    Empty,
6337    // NO MINVALUE/NO MAXVALUE
6338    None,
6339    // MINVALUE <expr> / MAXVALUE <expr>
6340    Some(Expr),
6341}
6342
6343#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6344#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6345#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6346#[non_exhaustive]
6347pub enum OnInsert {
6348    /// ON DUPLICATE KEY UPDATE (MySQL when the key already exists, then execute an update instead)
6349    DuplicateKeyUpdate(Vec<Assignment>),
6350    /// ON CONFLICT is a PostgreSQL and Sqlite extension
6351    OnConflict(OnConflict),
6352}
6353
6354#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6355#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6356#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6357pub struct InsertAliases {
6358    pub row_alias: ObjectName,
6359    pub col_aliases: Option<Vec<Ident>>,
6360}
6361
6362#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6363#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6364#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6365pub struct OnConflict {
6366    pub conflict_target: Option<ConflictTarget>,
6367    pub action: OnConflictAction,
6368}
6369#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6370#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6371#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6372pub enum ConflictTarget {
6373    Columns(Vec<Ident>),
6374    OnConstraint(ObjectName),
6375}
6376#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6377#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6378#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6379pub enum OnConflictAction {
6380    DoNothing,
6381    DoUpdate(DoUpdate),
6382}
6383
6384#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6385#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6386#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6387pub struct DoUpdate {
6388    /// Column assignments
6389    pub assignments: Vec<Assignment>,
6390    /// WHERE
6391    pub selection: Option<Expr>,
6392}
6393
6394impl fmt::Display for OnInsert {
6395    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6396        match self {
6397            Self::DuplicateKeyUpdate(expr) => write!(
6398                f,
6399                " ON DUPLICATE KEY UPDATE {}",
6400                display_comma_separated(expr)
6401            ),
6402            Self::OnConflict(o) => write!(f, "{o}"),
6403        }
6404    }
6405}
6406impl fmt::Display for OnConflict {
6407    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6408        write!(f, " ON CONFLICT")?;
6409        if let Some(target) = &self.conflict_target {
6410            write!(f, "{target}")?;
6411        }
6412        write!(f, " {}", self.action)
6413    }
6414}
6415impl fmt::Display for ConflictTarget {
6416    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6417        match self {
6418            ConflictTarget::Columns(cols) => write!(f, "({})", display_comma_separated(cols)),
6419            ConflictTarget::OnConstraint(name) => write!(f, " ON CONSTRAINT {name}"),
6420        }
6421    }
6422}
6423impl fmt::Display for OnConflictAction {
6424    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6425        match self {
6426            Self::DoNothing => write!(f, "DO NOTHING"),
6427            Self::DoUpdate(do_update) => {
6428                write!(f, "DO UPDATE")?;
6429                if !do_update.assignments.is_empty() {
6430                    write!(
6431                        f,
6432                        " SET {}",
6433                        display_comma_separated(&do_update.assignments)
6434                    )?;
6435                }
6436                if let Some(selection) = &do_update.selection {
6437                    write!(f, " WHERE {selection}")?;
6438                }
6439                Ok(())
6440            }
6441        }
6442    }
6443}
6444
6445/// Privileges granted in a GRANT statement or revoked in a REVOKE statement.
6446#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6447#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6448#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6449pub enum Privileges {
6450    /// All privileges applicable to the object type
6451    All {
6452        /// Optional keyword from the spec, ignored in practice
6453        with_privileges_keyword: bool,
6454    },
6455    /// Specific privileges (e.g. `SELECT`, `INSERT`)
6456    Actions(Vec<Action>),
6457}
6458
6459impl fmt::Display for Privileges {
6460    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6461        match self {
6462            Privileges::All {
6463                with_privileges_keyword,
6464            } => {
6465                write!(
6466                    f,
6467                    "ALL{}",
6468                    if *with_privileges_keyword {
6469                        " PRIVILEGES"
6470                    } else {
6471                        ""
6472                    }
6473                )
6474            }
6475            Privileges::Actions(actions) => {
6476                write!(f, "{}", display_comma_separated(actions))
6477            }
6478        }
6479    }
6480}
6481
6482/// Specific direction for FETCH statement
6483#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6484#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6485#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6486pub enum FetchDirection {
6487    Count { limit: Value },
6488    Next,
6489    Prior,
6490    First,
6491    Last,
6492    Absolute { limit: Value },
6493    Relative { limit: Value },
6494    All,
6495    // FORWARD
6496    // FORWARD count
6497    Forward { limit: Option<Value> },
6498    ForwardAll,
6499    // BACKWARD
6500    // BACKWARD count
6501    Backward { limit: Option<Value> },
6502    BackwardAll,
6503}
6504
6505impl fmt::Display for FetchDirection {
6506    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6507        match self {
6508            FetchDirection::Count { limit } => f.write_str(&limit.to_string())?,
6509            FetchDirection::Next => f.write_str("NEXT")?,
6510            FetchDirection::Prior => f.write_str("PRIOR")?,
6511            FetchDirection::First => f.write_str("FIRST")?,
6512            FetchDirection::Last => f.write_str("LAST")?,
6513            FetchDirection::Absolute { limit } => {
6514                f.write_str("ABSOLUTE ")?;
6515                f.write_str(&limit.to_string())?;
6516            }
6517            FetchDirection::Relative { limit } => {
6518                f.write_str("RELATIVE ")?;
6519                f.write_str(&limit.to_string())?;
6520            }
6521            FetchDirection::All => f.write_str("ALL")?,
6522            FetchDirection::Forward { limit } => {
6523                f.write_str("FORWARD")?;
6524
6525                if let Some(l) = limit {
6526                    f.write_str(" ")?;
6527                    f.write_str(&l.to_string())?;
6528                }
6529            }
6530            FetchDirection::ForwardAll => f.write_str("FORWARD ALL")?,
6531            FetchDirection::Backward { limit } => {
6532                f.write_str("BACKWARD")?;
6533
6534                if let Some(l) = limit {
6535                    f.write_str(" ")?;
6536                    f.write_str(&l.to_string())?;
6537                }
6538            }
6539            FetchDirection::BackwardAll => f.write_str("BACKWARD ALL")?,
6540        };
6541
6542        Ok(())
6543    }
6544}
6545
6546/// The "position" for a FETCH statement.
6547///
6548/// [MsSql](https://learn.microsoft.com/en-us/sql/t-sql/language-elements/fetch-transact-sql)
6549#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6550#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6551#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6552pub enum FetchPosition {
6553    From,
6554    In,
6555}
6556
6557impl fmt::Display for FetchPosition {
6558    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6559        match self {
6560            FetchPosition::From => f.write_str("FROM")?,
6561            FetchPosition::In => f.write_str("IN")?,
6562        };
6563
6564        Ok(())
6565    }
6566}
6567
6568/// A privilege on a database object (table, sequence, etc.).
6569#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6570#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6571#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6572pub enum Action {
6573    AddSearchOptimization,
6574    Apply {
6575        apply_type: ActionApplyType,
6576    },
6577    ApplyBudget,
6578    AttachListing,
6579    AttachPolicy,
6580    Audit,
6581    BindServiceEndpoint,
6582    Connect,
6583    Create {
6584        obj_type: Option<ActionCreateObjectType>,
6585    },
6586    DatabaseRole {
6587        role: ObjectName,
6588    },
6589    Delete,
6590    EvolveSchema,
6591    Exec {
6592        obj_type: Option<ActionExecuteObjectType>,
6593    },
6594    Execute {
6595        obj_type: Option<ActionExecuteObjectType>,
6596    },
6597    Failover,
6598    ImportedPrivileges,
6599    ImportShare,
6600    Insert {
6601        columns: Option<Vec<Ident>>,
6602    },
6603    Manage {
6604        manage_type: ActionManageType,
6605    },
6606    ManageReleases,
6607    ManageVersions,
6608    Modify {
6609        modify_type: Option<ActionModifyType>,
6610    },
6611    Monitor {
6612        monitor_type: Option<ActionMonitorType>,
6613    },
6614    Operate,
6615    OverrideShareRestrictions,
6616    Ownership,
6617    PurchaseDataExchangeListing,
6618    Read,
6619    ReadSession,
6620    References {
6621        columns: Option<Vec<Ident>>,
6622    },
6623    Replicate,
6624    ResolveAll,
6625    Role {
6626        role: Ident,
6627    },
6628    Select {
6629        columns: Option<Vec<Ident>>,
6630    },
6631    Temporary,
6632    Trigger,
6633    Truncate,
6634    Update {
6635        columns: Option<Vec<Ident>>,
6636    },
6637    Usage,
6638}
6639
6640impl fmt::Display for Action {
6641    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6642        match self {
6643            Action::AddSearchOptimization => f.write_str("ADD SEARCH OPTIMIZATION")?,
6644            Action::Apply { apply_type } => write!(f, "APPLY {apply_type}")?,
6645            Action::ApplyBudget => f.write_str("APPLYBUDGET")?,
6646            Action::AttachListing => f.write_str("ATTACH LISTING")?,
6647            Action::AttachPolicy => f.write_str("ATTACH POLICY")?,
6648            Action::Audit => f.write_str("AUDIT")?,
6649            Action::BindServiceEndpoint => f.write_str("BIND SERVICE ENDPOINT")?,
6650            Action::Connect => f.write_str("CONNECT")?,
6651            Action::Create { obj_type } => {
6652                f.write_str("CREATE")?;
6653                if let Some(obj_type) = obj_type {
6654                    write!(f, " {obj_type}")?
6655                }
6656            }
6657            Action::DatabaseRole { role } => write!(f, "DATABASE ROLE {role}")?,
6658            Action::Delete => f.write_str("DELETE")?,
6659            Action::EvolveSchema => f.write_str("EVOLVE SCHEMA")?,
6660            Action::Exec { obj_type } => {
6661                f.write_str("EXEC")?;
6662                if let Some(obj_type) = obj_type {
6663                    write!(f, " {obj_type}")?
6664                }
6665            }
6666            Action::Execute { obj_type } => {
6667                f.write_str("EXECUTE")?;
6668                if let Some(obj_type) = obj_type {
6669                    write!(f, " {obj_type}")?
6670                }
6671            }
6672            Action::Failover => f.write_str("FAILOVER")?,
6673            Action::ImportedPrivileges => f.write_str("IMPORTED PRIVILEGES")?,
6674            Action::ImportShare => f.write_str("IMPORT SHARE")?,
6675            Action::Insert { .. } => f.write_str("INSERT")?,
6676            Action::Manage { manage_type } => write!(f, "MANAGE {manage_type}")?,
6677            Action::ManageReleases => f.write_str("MANAGE RELEASES")?,
6678            Action::ManageVersions => f.write_str("MANAGE VERSIONS")?,
6679            Action::Modify { modify_type } => {
6680                write!(f, "MODIFY")?;
6681                if let Some(modify_type) = modify_type {
6682                    write!(f, " {modify_type}")?;
6683                }
6684            }
6685            Action::Monitor { monitor_type } => {
6686                write!(f, "MONITOR")?;
6687                if let Some(monitor_type) = monitor_type {
6688                    write!(f, " {monitor_type}")?
6689                }
6690            }
6691            Action::Operate => f.write_str("OPERATE")?,
6692            Action::OverrideShareRestrictions => f.write_str("OVERRIDE SHARE RESTRICTIONS")?,
6693            Action::Ownership => f.write_str("OWNERSHIP")?,
6694            Action::PurchaseDataExchangeListing => f.write_str("PURCHASE DATA EXCHANGE LISTING")?,
6695            Action::Read => f.write_str("READ")?,
6696            Action::ReadSession => f.write_str("READ SESSION")?,
6697            Action::References { .. } => f.write_str("REFERENCES")?,
6698            Action::Replicate => f.write_str("REPLICATE")?,
6699            Action::ResolveAll => f.write_str("RESOLVE ALL")?,
6700            Action::Role { role } => write!(f, "ROLE {role}")?,
6701            Action::Select { .. } => f.write_str("SELECT")?,
6702            Action::Temporary => f.write_str("TEMPORARY")?,
6703            Action::Trigger => f.write_str("TRIGGER")?,
6704            Action::Truncate => f.write_str("TRUNCATE")?,
6705            Action::Update { .. } => f.write_str("UPDATE")?,
6706            Action::Usage => f.write_str("USAGE")?,
6707        };
6708        match self {
6709            Action::Insert { columns }
6710            | Action::References { columns }
6711            | Action::Select { columns }
6712            | Action::Update { columns } => {
6713                if let Some(columns) = columns {
6714                    write!(f, " ({})", display_comma_separated(columns))?;
6715                }
6716            }
6717            _ => (),
6718        };
6719        Ok(())
6720    }
6721}
6722
6723#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6724#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6725#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6726/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
6727/// under `globalPrivileges` in the `CREATE` privilege.
6728pub enum ActionCreateObjectType {
6729    Account,
6730    Application,
6731    ApplicationPackage,
6732    ComputePool,
6733    DataExchangeListing,
6734    Database,
6735    ExternalVolume,
6736    FailoverGroup,
6737    Integration,
6738    NetworkPolicy,
6739    OrganiationListing,
6740    ReplicationGroup,
6741    Role,
6742    Share,
6743    User,
6744    Warehouse,
6745}
6746
6747impl fmt::Display for ActionCreateObjectType {
6748    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6749        match self {
6750            ActionCreateObjectType::Account => write!(f, "ACCOUNT"),
6751            ActionCreateObjectType::Application => write!(f, "APPLICATION"),
6752            ActionCreateObjectType::ApplicationPackage => write!(f, "APPLICATION PACKAGE"),
6753            ActionCreateObjectType::ComputePool => write!(f, "COMPUTE POOL"),
6754            ActionCreateObjectType::DataExchangeListing => write!(f, "DATA EXCHANGE LISTING"),
6755            ActionCreateObjectType::Database => write!(f, "DATABASE"),
6756            ActionCreateObjectType::ExternalVolume => write!(f, "EXTERNAL VOLUME"),
6757            ActionCreateObjectType::FailoverGroup => write!(f, "FAILOVER GROUP"),
6758            ActionCreateObjectType::Integration => write!(f, "INTEGRATION"),
6759            ActionCreateObjectType::NetworkPolicy => write!(f, "NETWORK POLICY"),
6760            ActionCreateObjectType::OrganiationListing => write!(f, "ORGANIZATION LISTING"),
6761            ActionCreateObjectType::ReplicationGroup => write!(f, "REPLICATION GROUP"),
6762            ActionCreateObjectType::Role => write!(f, "ROLE"),
6763            ActionCreateObjectType::Share => write!(f, "SHARE"),
6764            ActionCreateObjectType::User => write!(f, "USER"),
6765            ActionCreateObjectType::Warehouse => write!(f, "WAREHOUSE"),
6766        }
6767    }
6768}
6769
6770#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6771#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6772#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6773/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
6774/// under `globalPrivileges` in the `APPLY` privilege.
6775pub enum ActionApplyType {
6776    AggregationPolicy,
6777    AuthenticationPolicy,
6778    JoinPolicy,
6779    MaskingPolicy,
6780    PackagesPolicy,
6781    PasswordPolicy,
6782    ProjectionPolicy,
6783    RowAccessPolicy,
6784    SessionPolicy,
6785    Tag,
6786}
6787
6788impl fmt::Display for ActionApplyType {
6789    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6790        match self {
6791            ActionApplyType::AggregationPolicy => write!(f, "AGGREGATION POLICY"),
6792            ActionApplyType::AuthenticationPolicy => write!(f, "AUTHENTICATION POLICY"),
6793            ActionApplyType::JoinPolicy => write!(f, "JOIN POLICY"),
6794            ActionApplyType::MaskingPolicy => write!(f, "MASKING POLICY"),
6795            ActionApplyType::PackagesPolicy => write!(f, "PACKAGES POLICY"),
6796            ActionApplyType::PasswordPolicy => write!(f, "PASSWORD POLICY"),
6797            ActionApplyType::ProjectionPolicy => write!(f, "PROJECTION POLICY"),
6798            ActionApplyType::RowAccessPolicy => write!(f, "ROW ACCESS POLICY"),
6799            ActionApplyType::SessionPolicy => write!(f, "SESSION POLICY"),
6800            ActionApplyType::Tag => write!(f, "TAG"),
6801        }
6802    }
6803}
6804
6805#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6806#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6807#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6808/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
6809/// under `globalPrivileges` in the `EXECUTE` privilege.
6810pub enum ActionExecuteObjectType {
6811    Alert,
6812    DataMetricFunction,
6813    ManagedAlert,
6814    ManagedTask,
6815    Task,
6816}
6817
6818impl fmt::Display for ActionExecuteObjectType {
6819    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6820        match self {
6821            ActionExecuteObjectType::Alert => write!(f, "ALERT"),
6822            ActionExecuteObjectType::DataMetricFunction => write!(f, "DATA METRIC FUNCTION"),
6823            ActionExecuteObjectType::ManagedAlert => write!(f, "MANAGED ALERT"),
6824            ActionExecuteObjectType::ManagedTask => write!(f, "MANAGED TASK"),
6825            ActionExecuteObjectType::Task => write!(f, "TASK"),
6826        }
6827    }
6828}
6829
6830#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6831#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6832#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6833/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
6834/// under `globalPrivileges` in the `MANAGE` privilege.
6835pub enum ActionManageType {
6836    AccountSupportCases,
6837    EventSharing,
6838    Grants,
6839    ListingAutoFulfillment,
6840    OrganizationSupportCases,
6841    UserSupportCases,
6842    Warehouses,
6843}
6844
6845impl fmt::Display for ActionManageType {
6846    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6847        match self {
6848            ActionManageType::AccountSupportCases => write!(f, "ACCOUNT SUPPORT CASES"),
6849            ActionManageType::EventSharing => write!(f, "EVENT SHARING"),
6850            ActionManageType::Grants => write!(f, "GRANTS"),
6851            ActionManageType::ListingAutoFulfillment => write!(f, "LISTING AUTO FULFILLMENT"),
6852            ActionManageType::OrganizationSupportCases => write!(f, "ORGANIZATION SUPPORT CASES"),
6853            ActionManageType::UserSupportCases => write!(f, "USER SUPPORT CASES"),
6854            ActionManageType::Warehouses => write!(f, "WAREHOUSES"),
6855        }
6856    }
6857}
6858
6859#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6860#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6861#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6862/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
6863/// under `globalPrivileges` in the `MODIFY` privilege.
6864pub enum ActionModifyType {
6865    LogLevel,
6866    TraceLevel,
6867    SessionLogLevel,
6868    SessionTraceLevel,
6869}
6870
6871impl fmt::Display for ActionModifyType {
6872    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6873        match self {
6874            ActionModifyType::LogLevel => write!(f, "LOG LEVEL"),
6875            ActionModifyType::TraceLevel => write!(f, "TRACE LEVEL"),
6876            ActionModifyType::SessionLogLevel => write!(f, "SESSION LOG LEVEL"),
6877            ActionModifyType::SessionTraceLevel => write!(f, "SESSION TRACE LEVEL"),
6878        }
6879    }
6880}
6881
6882#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6883#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6884#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6885/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
6886/// under `globalPrivileges` in the `MONITOR` privilege.
6887pub enum ActionMonitorType {
6888    Execution,
6889    Security,
6890    Usage,
6891}
6892
6893impl fmt::Display for ActionMonitorType {
6894    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6895        match self {
6896            ActionMonitorType::Execution => write!(f, "EXECUTION"),
6897            ActionMonitorType::Security => write!(f, "SECURITY"),
6898            ActionMonitorType::Usage => write!(f, "USAGE"),
6899        }
6900    }
6901}
6902
6903/// The principal that receives the privileges
6904#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6905#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6906#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6907pub struct Grantee {
6908    pub grantee_type: GranteesType,
6909    pub name: Option<GranteeName>,
6910}
6911
6912impl fmt::Display for Grantee {
6913    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6914        match self.grantee_type {
6915            GranteesType::Role => {
6916                write!(f, "ROLE ")?;
6917            }
6918            GranteesType::Share => {
6919                write!(f, "SHARE ")?;
6920            }
6921            GranteesType::User => {
6922                write!(f, "USER ")?;
6923            }
6924            GranteesType::Group => {
6925                write!(f, "GROUP ")?;
6926            }
6927            GranteesType::Public => {
6928                write!(f, "PUBLIC ")?;
6929            }
6930            GranteesType::DatabaseRole => {
6931                write!(f, "DATABASE ROLE ")?;
6932            }
6933            GranteesType::Application => {
6934                write!(f, "APPLICATION ")?;
6935            }
6936            GranteesType::ApplicationRole => {
6937                write!(f, "APPLICATION ROLE ")?;
6938            }
6939            GranteesType::None => (),
6940        }
6941        if let Some(ref name) = self.name {
6942            name.fmt(f)?;
6943        }
6944        Ok(())
6945    }
6946}
6947
6948#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6949#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6950#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6951pub enum GranteesType {
6952    Role,
6953    Share,
6954    User,
6955    Group,
6956    Public,
6957    DatabaseRole,
6958    Application,
6959    ApplicationRole,
6960    None,
6961}
6962
6963/// Users/roles designated in a GRANT/REVOKE
6964#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6965#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6966#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6967pub enum GranteeName {
6968    /// A bare identifier
6969    ObjectName(ObjectName),
6970    /// A MySQL user/host pair such as 'root'@'%'
6971    UserHost { user: Ident, host: Ident },
6972}
6973
6974impl fmt::Display for GranteeName {
6975    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6976        match self {
6977            GranteeName::ObjectName(name) => name.fmt(f),
6978            GranteeName::UserHost { user, host } => {
6979                write!(f, "{user}@{host}")
6980            }
6981        }
6982    }
6983}
6984
6985/// Objects on which privileges are granted in a GRANT statement.
6986#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6987#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6988#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6989pub enum GrantObjects {
6990    /// Grant privileges on `ALL SEQUENCES IN SCHEMA <schema_name> [, ...]`
6991    AllSequencesInSchema { schemas: Vec<ObjectName> },
6992    /// Grant privileges on `ALL TABLES IN SCHEMA <schema_name> [, ...]`
6993    AllTablesInSchema { schemas: Vec<ObjectName> },
6994    /// Grant privileges on `ALL VIEWS IN SCHEMA <schema_name> [, ...]`
6995    AllViewsInSchema { schemas: Vec<ObjectName> },
6996    /// Grant privileges on `ALL MATERIALIZED VIEWS IN SCHEMA <schema_name> [, ...]`
6997    AllMaterializedViewsInSchema { schemas: Vec<ObjectName> },
6998    /// Grant privileges on `ALL EXTERNAL TABLES IN SCHEMA <schema_name> [, ...]`
6999    AllExternalTablesInSchema { schemas: Vec<ObjectName> },
7000    /// Grant privileges on `FUTURE SCHEMAS IN DATABASE <database_name> [, ...]`
7001    FutureSchemasInDatabase { databases: Vec<ObjectName> },
7002    /// Grant privileges on `FUTURE TABLES IN SCHEMA <schema_name> [, ...]`
7003    FutureTablesInSchema { schemas: Vec<ObjectName> },
7004    /// Grant privileges on `FUTURE VIEWS IN SCHEMA <schema_name> [, ...]`
7005    FutureViewsInSchema { schemas: Vec<ObjectName> },
7006    /// Grant privileges on `FUTURE EXTERNAL TABLES IN SCHEMA <schema_name> [, ...]`
7007    FutureExternalTablesInSchema { schemas: Vec<ObjectName> },
7008    /// Grant privileges on `FUTURE MATERIALIZED VIEWS IN SCHEMA <schema_name> [, ...]`
7009    FutureMaterializedViewsInSchema { schemas: Vec<ObjectName> },
7010    /// Grant privileges on `FUTURE SEQUENCES IN SCHEMA <schema_name> [, ...]`
7011    FutureSequencesInSchema { schemas: Vec<ObjectName> },
7012    /// Grant privileges on specific databases
7013    Databases(Vec<ObjectName>),
7014    /// Grant privileges on specific schemas
7015    Schemas(Vec<ObjectName>),
7016    /// Grant privileges on specific sequences
7017    Sequences(Vec<ObjectName>),
7018    /// Grant privileges on specific tables
7019    Tables(Vec<ObjectName>),
7020    /// Grant privileges on specific views
7021    Views(Vec<ObjectName>),
7022    /// Grant privileges on specific warehouses
7023    Warehouses(Vec<ObjectName>),
7024    /// Grant privileges on specific integrations
7025    Integrations(Vec<ObjectName>),
7026    /// Grant privileges on resource monitors
7027    ResourceMonitors(Vec<ObjectName>),
7028    /// Grant privileges on users
7029    Users(Vec<ObjectName>),
7030    /// Grant privileges on compute pools
7031    ComputePools(Vec<ObjectName>),
7032    /// Grant privileges on connections
7033    Connections(Vec<ObjectName>),
7034    /// Grant privileges on failover groups
7035    FailoverGroup(Vec<ObjectName>),
7036    /// Grant privileges on replication group
7037    ReplicationGroup(Vec<ObjectName>),
7038    /// Grant privileges on external volumes
7039    ExternalVolumes(Vec<ObjectName>),
7040    /// Grant privileges on a procedure. In dialects that
7041    /// support overloading, the argument types must be specified.
7042    ///
7043    /// For example:
7044    /// `GRANT USAGE ON PROCEDURE foo(varchar) TO ROLE role1`
7045    Procedure {
7046        name: ObjectName,
7047        arg_types: Vec<DataType>,
7048    },
7049
7050    /// Grant privileges on a function. In dialects that
7051    /// support overloading, the argument types must be specified.
7052    ///
7053    /// For example:
7054    /// `GRANT USAGE ON FUNCTION foo(varchar) TO ROLE role1`
7055    Function {
7056        name: ObjectName,
7057        arg_types: Vec<DataType>,
7058    },
7059}
7060
7061impl fmt::Display for GrantObjects {
7062    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7063        match self {
7064            GrantObjects::Sequences(sequences) => {
7065                write!(f, "SEQUENCE {}", display_comma_separated(sequences))
7066            }
7067            GrantObjects::Databases(databases) => {
7068                write!(f, "DATABASE {}", display_comma_separated(databases))
7069            }
7070            GrantObjects::Schemas(schemas) => {
7071                write!(f, "SCHEMA {}", display_comma_separated(schemas))
7072            }
7073            GrantObjects::Tables(tables) => {
7074                write!(f, "{}", display_comma_separated(tables))
7075            }
7076            GrantObjects::Views(views) => {
7077                write!(f, "VIEW {}", display_comma_separated(views))
7078            }
7079            GrantObjects::Warehouses(warehouses) => {
7080                write!(f, "WAREHOUSE {}", display_comma_separated(warehouses))
7081            }
7082            GrantObjects::Integrations(integrations) => {
7083                write!(f, "INTEGRATION {}", display_comma_separated(integrations))
7084            }
7085            GrantObjects::AllSequencesInSchema { schemas } => {
7086                write!(
7087                    f,
7088                    "ALL SEQUENCES IN SCHEMA {}",
7089                    display_comma_separated(schemas)
7090                )
7091            }
7092            GrantObjects::AllTablesInSchema { schemas } => {
7093                write!(
7094                    f,
7095                    "ALL TABLES IN SCHEMA {}",
7096                    display_comma_separated(schemas)
7097                )
7098            }
7099            GrantObjects::AllExternalTablesInSchema { schemas } => {
7100                write!(
7101                    f,
7102                    "ALL EXTERNAL TABLES IN SCHEMA {}",
7103                    display_comma_separated(schemas)
7104                )
7105            }
7106            GrantObjects::AllViewsInSchema { schemas } => {
7107                write!(
7108                    f,
7109                    "ALL VIEWS IN SCHEMA {}",
7110                    display_comma_separated(schemas)
7111                )
7112            }
7113            GrantObjects::AllMaterializedViewsInSchema { schemas } => {
7114                write!(
7115                    f,
7116                    "ALL MATERIALIZED VIEWS IN SCHEMA {}",
7117                    display_comma_separated(schemas)
7118                )
7119            }
7120            GrantObjects::FutureSchemasInDatabase { databases } => {
7121                write!(
7122                    f,
7123                    "FUTURE SCHEMAS IN DATABASE {}",
7124                    display_comma_separated(databases)
7125                )
7126            }
7127            GrantObjects::FutureTablesInSchema { schemas } => {
7128                write!(
7129                    f,
7130                    "FUTURE TABLES IN SCHEMA {}",
7131                    display_comma_separated(schemas)
7132                )
7133            }
7134            GrantObjects::FutureExternalTablesInSchema { schemas } => {
7135                write!(
7136                    f,
7137                    "FUTURE EXTERNAL TABLES IN SCHEMA {}",
7138                    display_comma_separated(schemas)
7139                )
7140            }
7141            GrantObjects::FutureViewsInSchema { schemas } => {
7142                write!(
7143                    f,
7144                    "FUTURE VIEWS IN SCHEMA {}",
7145                    display_comma_separated(schemas)
7146                )
7147            }
7148            GrantObjects::FutureMaterializedViewsInSchema { schemas } => {
7149                write!(
7150                    f,
7151                    "FUTURE MATERIALIZED VIEWS IN SCHEMA {}",
7152                    display_comma_separated(schemas)
7153                )
7154            }
7155            GrantObjects::FutureSequencesInSchema { schemas } => {
7156                write!(
7157                    f,
7158                    "FUTURE SEQUENCES IN SCHEMA {}",
7159                    display_comma_separated(schemas)
7160                )
7161            }
7162            GrantObjects::ResourceMonitors(objects) => {
7163                write!(f, "RESOURCE MONITOR {}", display_comma_separated(objects))
7164            }
7165            GrantObjects::Users(objects) => {
7166                write!(f, "USER {}", display_comma_separated(objects))
7167            }
7168            GrantObjects::ComputePools(objects) => {
7169                write!(f, "COMPUTE POOL {}", display_comma_separated(objects))
7170            }
7171            GrantObjects::Connections(objects) => {
7172                write!(f, "CONNECTION {}", display_comma_separated(objects))
7173            }
7174            GrantObjects::FailoverGroup(objects) => {
7175                write!(f, "FAILOVER GROUP {}", display_comma_separated(objects))
7176            }
7177            GrantObjects::ReplicationGroup(objects) => {
7178                write!(f, "REPLICATION GROUP {}", display_comma_separated(objects))
7179            }
7180            GrantObjects::ExternalVolumes(objects) => {
7181                write!(f, "EXTERNAL VOLUME {}", display_comma_separated(objects))
7182            }
7183            GrantObjects::Procedure { name, arg_types } => {
7184                write!(f, "PROCEDURE {name}")?;
7185                if !arg_types.is_empty() {
7186                    write!(f, "({})", display_comma_separated(arg_types))?;
7187                }
7188                Ok(())
7189            }
7190            GrantObjects::Function { name, arg_types } => {
7191                write!(f, "FUNCTION {name}")?;
7192                if !arg_types.is_empty() {
7193                    write!(f, "({})", display_comma_separated(arg_types))?;
7194                }
7195                Ok(())
7196            }
7197        }
7198    }
7199}
7200
7201/// A `DENY` statement
7202///
7203/// [MsSql](https://learn.microsoft.com/en-us/sql/t-sql/statements/deny-transact-sql)
7204#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7205#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7206#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7207pub struct DenyStatement {
7208    pub privileges: Privileges,
7209    pub objects: GrantObjects,
7210    pub grantees: Vec<Grantee>,
7211    pub granted_by: Option<Ident>,
7212    pub cascade: Option<CascadeOption>,
7213}
7214
7215impl fmt::Display for DenyStatement {
7216    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7217        write!(f, "DENY {}", self.privileges)?;
7218        write!(f, " ON {}", self.objects)?;
7219        if !self.grantees.is_empty() {
7220            write!(f, " TO {}", display_comma_separated(&self.grantees))?;
7221        }
7222        if let Some(cascade) = &self.cascade {
7223            write!(f, " {cascade}")?;
7224        }
7225        if let Some(granted_by) = &self.granted_by {
7226            write!(f, " AS {granted_by}")?;
7227        }
7228        Ok(())
7229    }
7230}
7231
7232/// SQL assignment `foo = expr` as used in SQLUpdate
7233#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7234#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7235#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7236pub struct Assignment {
7237    pub target: AssignmentTarget,
7238    pub value: Expr,
7239}
7240
7241impl fmt::Display for Assignment {
7242    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7243        write!(f, "{} = {}", self.target, self.value)
7244    }
7245}
7246
7247/// Left-hand side of an assignment in an UPDATE statement,
7248/// e.g. `foo` in `foo = 5` (ColumnName assignment) or
7249/// `(a, b)` in `(a, b) = (1, 2)` (Tuple assignment).
7250#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7251#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7252#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7253pub enum AssignmentTarget {
7254    /// A single column
7255    ColumnName(ObjectName),
7256    /// A tuple of columns
7257    Tuple(Vec<ObjectName>),
7258}
7259
7260impl fmt::Display for AssignmentTarget {
7261    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7262        match self {
7263            AssignmentTarget::ColumnName(column) => write!(f, "{column}"),
7264            AssignmentTarget::Tuple(columns) => write!(f, "({})", display_comma_separated(columns)),
7265        }
7266    }
7267}
7268
7269#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7270#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7271#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7272pub enum FunctionArgExpr {
7273    Expr(Expr),
7274    /// Qualified wildcard, e.g. `alias.*` or `schema.table.*`.
7275    QualifiedWildcard(ObjectName),
7276    /// An unqualified `*`
7277    Wildcard,
7278}
7279
7280impl From<Expr> for FunctionArgExpr {
7281    fn from(wildcard_expr: Expr) -> Self {
7282        match wildcard_expr {
7283            Expr::QualifiedWildcard(prefix, _) => Self::QualifiedWildcard(prefix),
7284            Expr::Wildcard(_) => Self::Wildcard,
7285            expr => Self::Expr(expr),
7286        }
7287    }
7288}
7289
7290impl fmt::Display for FunctionArgExpr {
7291    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7292        match self {
7293            FunctionArgExpr::Expr(expr) => write!(f, "{expr}"),
7294            FunctionArgExpr::QualifiedWildcard(prefix) => write!(f, "{prefix}.*"),
7295            FunctionArgExpr::Wildcard => f.write_str("*"),
7296        }
7297    }
7298}
7299
7300#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7301#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7302#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7303/// Operator used to separate function arguments
7304pub enum FunctionArgOperator {
7305    /// function(arg1 = value1)
7306    Equals,
7307    /// function(arg1 => value1)
7308    RightArrow,
7309    /// function(arg1 := value1)
7310    Assignment,
7311    /// function(arg1 : value1)
7312    Colon,
7313    /// function(arg1 VALUE value1)
7314    Value,
7315}
7316
7317impl fmt::Display for FunctionArgOperator {
7318    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7319        match self {
7320            FunctionArgOperator::Equals => f.write_str("="),
7321            FunctionArgOperator::RightArrow => f.write_str("=>"),
7322            FunctionArgOperator::Assignment => f.write_str(":="),
7323            FunctionArgOperator::Colon => f.write_str(":"),
7324            FunctionArgOperator::Value => f.write_str("VALUE"),
7325        }
7326    }
7327}
7328
7329#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7330#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7331#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7332pub enum FunctionArg {
7333    /// `name` is identifier
7334    ///
7335    /// Enabled when `Dialect::supports_named_fn_args_with_expr_name` returns 'false'
7336    Named {
7337        name: Ident,
7338        arg: FunctionArgExpr,
7339        operator: FunctionArgOperator,
7340    },
7341    /// `name` is arbitrary expression
7342    ///
7343    /// Enabled when `Dialect::supports_named_fn_args_with_expr_name` returns 'true'
7344    ExprNamed {
7345        name: Expr,
7346        arg: FunctionArgExpr,
7347        operator: FunctionArgOperator,
7348    },
7349    Unnamed(FunctionArgExpr),
7350}
7351
7352impl fmt::Display for FunctionArg {
7353    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7354        match self {
7355            FunctionArg::Named {
7356                name,
7357                arg,
7358                operator,
7359            } => write!(f, "{name} {operator} {arg}"),
7360            FunctionArg::ExprNamed {
7361                name,
7362                arg,
7363                operator,
7364            } => write!(f, "{name} {operator} {arg}"),
7365            FunctionArg::Unnamed(unnamed_arg) => write!(f, "{unnamed_arg}"),
7366        }
7367    }
7368}
7369
7370#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7371#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7372#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7373pub enum CloseCursor {
7374    All,
7375    Specific { name: Ident },
7376}
7377
7378impl fmt::Display for CloseCursor {
7379    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7380        match self {
7381            CloseCursor::All => write!(f, "ALL"),
7382            CloseCursor::Specific { name } => write!(f, "{name}"),
7383        }
7384    }
7385}
7386
7387/// A Drop Domain statement
7388#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7389#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7390#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7391pub struct DropDomain {
7392    /// Whether to drop the domain if it exists
7393    pub if_exists: bool,
7394    /// The name of the domain to drop
7395    pub name: ObjectName,
7396    /// The behavior to apply when dropping the domain
7397    pub drop_behavior: Option<DropBehavior>,
7398}
7399
7400/// A function call
7401#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7402#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7403#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7404pub struct Function {
7405    pub name: ObjectName,
7406    /// Flags whether this function call uses the [ODBC syntax].
7407    ///
7408    /// Example:
7409    /// ```sql
7410    /// SELECT {fn CONCAT('foo', 'bar')}
7411    /// ```
7412    ///
7413    /// [ODBC syntax]: https://learn.microsoft.com/en-us/sql/odbc/reference/develop-app/scalar-function-calls?view=sql-server-2017
7414    pub uses_odbc_syntax: bool,
7415    /// The parameters to the function, including any options specified within the
7416    /// delimiting parentheses.
7417    ///
7418    /// Example:
7419    /// ```plaintext
7420    /// HISTOGRAM(0.5, 0.6)(x, y)
7421    /// ```
7422    ///
7423    /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/aggregate-functions/parametric-functions)
7424    pub parameters: FunctionArguments,
7425    /// The arguments to the function, including any options specified within the
7426    /// delimiting parentheses.
7427    pub args: FunctionArguments,
7428    /// e.g. `x > 5` in `COUNT(x) FILTER (WHERE x > 5)`
7429    pub filter: Option<Box<Expr>>,
7430    /// Indicates how `NULL`s should be handled in the calculation.
7431    ///
7432    /// Example:
7433    /// ```plaintext
7434    /// FIRST_VALUE( <expr> ) [ { IGNORE | RESPECT } NULLS ] OVER ...
7435    /// ```
7436    ///
7437    /// [Snowflake](https://docs.snowflake.com/en/sql-reference/functions/first_value)
7438    pub null_treatment: Option<NullTreatment>,
7439    /// The `OVER` clause, indicating a window function call.
7440    pub over: Option<WindowType>,
7441    /// A clause used with certain aggregate functions to control the ordering
7442    /// within grouped sets before the function is applied.
7443    ///
7444    /// Syntax:
7445    /// ```plaintext
7446    /// <aggregate_function>(expression) WITHIN GROUP (ORDER BY key [ASC | DESC], ...)
7447    /// ```
7448    pub within_group: Vec<OrderByExpr>,
7449}
7450
7451impl fmt::Display for Function {
7452    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7453        if self.uses_odbc_syntax {
7454            write!(f, "{{fn ")?;
7455        }
7456
7457        write!(f, "{}{}{}", self.name, self.parameters, self.args)?;
7458
7459        if !self.within_group.is_empty() {
7460            write!(
7461                f,
7462                " WITHIN GROUP (ORDER BY {})",
7463                display_comma_separated(&self.within_group)
7464            )?;
7465        }
7466
7467        if let Some(filter_cond) = &self.filter {
7468            write!(f, " FILTER (WHERE {filter_cond})")?;
7469        }
7470
7471        if let Some(null_treatment) = &self.null_treatment {
7472            write!(f, " {null_treatment}")?;
7473        }
7474
7475        if let Some(o) = &self.over {
7476            f.write_str(" OVER ")?;
7477            o.fmt(f)?;
7478        }
7479
7480        if self.uses_odbc_syntax {
7481            write!(f, "}}")?;
7482        }
7483
7484        Ok(())
7485    }
7486}
7487
7488/// The arguments passed to a function call.
7489#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7490#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7491#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7492pub enum FunctionArguments {
7493    /// Used for special functions like `CURRENT_TIMESTAMP` that are invoked
7494    /// without parentheses.
7495    None,
7496    /// On some dialects, a subquery can be passed without surrounding
7497    /// parentheses if it's the sole argument to the function.
7498    Subquery(Box<Query>),
7499    /// A normal function argument list, including any clauses within it such as
7500    /// `DISTINCT` or `ORDER BY`.
7501    List(FunctionArgumentList),
7502}
7503
7504impl fmt::Display for FunctionArguments {
7505    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
7506        match self {
7507            FunctionArguments::None => Ok(()),
7508            FunctionArguments::Subquery(query) => write!(f, "({query})"),
7509            FunctionArguments::List(args) => write!(f, "({args})"),
7510        }
7511    }
7512}
7513
7514/// This represents everything inside the parentheses when calling a function.
7515#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7516#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7517#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7518pub struct FunctionArgumentList {
7519    /// `[ ALL | DISTINCT ]`
7520    pub duplicate_treatment: Option<DuplicateTreatment>,
7521    /// The function arguments.
7522    pub args: Vec<FunctionArg>,
7523    /// Additional clauses specified within the argument list.
7524    pub clauses: Vec<FunctionArgumentClause>,
7525}
7526
7527impl fmt::Display for FunctionArgumentList {
7528    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7529        if let Some(duplicate_treatment) = self.duplicate_treatment {
7530            write!(f, "{duplicate_treatment} ")?;
7531        }
7532        write!(f, "{}", display_comma_separated(&self.args))?;
7533        if !self.clauses.is_empty() {
7534            if !self.args.is_empty() {
7535                write!(f, " ")?;
7536            }
7537            write!(f, "{}", display_separated(&self.clauses, " "))?;
7538        }
7539        Ok(())
7540    }
7541}
7542
7543#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7544#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7545#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7546pub enum FunctionArgumentClause {
7547    /// Indicates how `NULL`s should be handled in the calculation, e.g. in `FIRST_VALUE` on [BigQuery].
7548    ///
7549    /// Syntax:
7550    /// ```plaintext
7551    /// { IGNORE | RESPECT } NULLS ]
7552    /// ```
7553    ///
7554    /// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/navigation_functions#first_value
7555    IgnoreOrRespectNulls(NullTreatment),
7556    /// Specifies the the ordering for some ordered set aggregates, e.g. `ARRAY_AGG` on [BigQuery].
7557    ///
7558    /// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/aggregate_functions#array_agg
7559    OrderBy(Vec<OrderByExpr>),
7560    /// Specifies a limit for the `ARRAY_AGG` and `ARRAY_CONCAT_AGG` functions on BigQuery.
7561    Limit(Expr),
7562    /// Specifies the behavior on overflow of the `LISTAGG` function.
7563    ///
7564    /// See <https://trino.io/docs/current/functions/aggregate.html>.
7565    OnOverflow(ListAggOnOverflow),
7566    /// Specifies a minimum or maximum bound on the input to [`ANY_VALUE`] on BigQuery.
7567    ///
7568    /// Syntax:
7569    /// ```plaintext
7570    /// HAVING { MAX | MIN } expression
7571    /// ```
7572    ///
7573    /// [`ANY_VALUE`]: https://cloud.google.com/bigquery/docs/reference/standard-sql/aggregate_functions#any_value
7574    Having(HavingBound),
7575    /// The `SEPARATOR` clause to the [`GROUP_CONCAT`] function in MySQL.
7576    ///
7577    /// [`GROUP_CONCAT`]: https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html#function_group-concat
7578    Separator(Value),
7579    /// The json-null-clause to the [`JSON_ARRAY`]/[`JSON_OBJECT`] function in MSSQL.
7580    ///
7581    /// [`JSON_ARRAY`]: <https://learn.microsoft.com/en-us/sql/t-sql/functions/json-array-transact-sql?view=sql-server-ver16>
7582    /// [`JSON_OBJECT`]: <https://learn.microsoft.com/en-us/sql/t-sql/functions/json-object-transact-sql?view=sql-server-ver16>
7583    JsonNullClause(JsonNullClause),
7584}
7585
7586impl fmt::Display for FunctionArgumentClause {
7587    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
7588        match self {
7589            FunctionArgumentClause::IgnoreOrRespectNulls(null_treatment) => {
7590                write!(f, "{null_treatment}")
7591            }
7592            FunctionArgumentClause::OrderBy(order_by) => {
7593                write!(f, "ORDER BY {}", display_comma_separated(order_by))
7594            }
7595            FunctionArgumentClause::Limit(limit) => write!(f, "LIMIT {limit}"),
7596            FunctionArgumentClause::OnOverflow(on_overflow) => write!(f, "{on_overflow}"),
7597            FunctionArgumentClause::Having(bound) => write!(f, "{bound}"),
7598            FunctionArgumentClause::Separator(sep) => write!(f, "SEPARATOR {sep}"),
7599            FunctionArgumentClause::JsonNullClause(null_clause) => write!(f, "{null_clause}"),
7600        }
7601    }
7602}
7603
7604/// A method call
7605#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7606#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7607#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7608pub struct Method {
7609    pub expr: Box<Expr>,
7610    // always non-empty
7611    pub method_chain: Vec<Function>,
7612}
7613
7614impl fmt::Display for Method {
7615    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7616        write!(
7617            f,
7618            "{}.{}",
7619            self.expr,
7620            display_separated(&self.method_chain, ".")
7621        )
7622    }
7623}
7624
7625#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7626#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7627#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7628pub enum DuplicateTreatment {
7629    /// Perform the calculation only unique values.
7630    Distinct,
7631    /// Retain all duplicate values (the default).
7632    All,
7633}
7634
7635impl fmt::Display for DuplicateTreatment {
7636    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
7637        match self {
7638            DuplicateTreatment::Distinct => write!(f, "DISTINCT"),
7639            DuplicateTreatment::All => write!(f, "ALL"),
7640        }
7641    }
7642}
7643
7644#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7645#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7646#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7647pub enum AnalyzeFormat {
7648    TEXT,
7649    GRAPHVIZ,
7650    JSON,
7651}
7652
7653impl fmt::Display for AnalyzeFormat {
7654    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
7655        f.write_str(match self {
7656            AnalyzeFormat::TEXT => "TEXT",
7657            AnalyzeFormat::GRAPHVIZ => "GRAPHVIZ",
7658            AnalyzeFormat::JSON => "JSON",
7659        })
7660    }
7661}
7662
7663/// External table's available file format
7664#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7665#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7666#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7667pub enum FileFormat {
7668    TEXTFILE,
7669    SEQUENCEFILE,
7670    ORC,
7671    PARQUET,
7672    AVRO,
7673    RCFILE,
7674    JSONFILE,
7675}
7676
7677impl fmt::Display for FileFormat {
7678    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7679        use self::FileFormat::*;
7680        f.write_str(match self {
7681            TEXTFILE => "TEXTFILE",
7682            SEQUENCEFILE => "SEQUENCEFILE",
7683            ORC => "ORC",
7684            PARQUET => "PARQUET",
7685            AVRO => "AVRO",
7686            RCFILE => "RCFILE",
7687            JSONFILE => "JSONFILE",
7688        })
7689    }
7690}
7691
7692/// The `ON OVERFLOW` clause of a LISTAGG invocation
7693#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7694#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7695#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7696pub enum ListAggOnOverflow {
7697    /// `ON OVERFLOW ERROR`
7698    Error,
7699
7700    /// `ON OVERFLOW TRUNCATE [ <filler> ] WITH[OUT] COUNT`
7701    Truncate {
7702        filler: Option<Box<Expr>>,
7703        with_count: bool,
7704    },
7705}
7706
7707impl fmt::Display for ListAggOnOverflow {
7708    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7709        write!(f, "ON OVERFLOW")?;
7710        match self {
7711            ListAggOnOverflow::Error => write!(f, " ERROR"),
7712            ListAggOnOverflow::Truncate { filler, with_count } => {
7713                write!(f, " TRUNCATE")?;
7714                if let Some(filler) = filler {
7715                    write!(f, " {filler}")?;
7716                }
7717                if *with_count {
7718                    write!(f, " WITH")?;
7719                } else {
7720                    write!(f, " WITHOUT")?;
7721                }
7722                write!(f, " COUNT")
7723            }
7724        }
7725    }
7726}
7727
7728/// The `HAVING` clause in a call to `ANY_VALUE` on BigQuery.
7729#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7730#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7731#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7732pub struct HavingBound(pub HavingBoundKind, pub Expr);
7733
7734impl fmt::Display for HavingBound {
7735    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
7736        write!(f, "HAVING {} {}", self.0, self.1)
7737    }
7738}
7739
7740#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7741#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7742#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7743pub enum HavingBoundKind {
7744    Min,
7745    Max,
7746}
7747
7748impl fmt::Display for HavingBoundKind {
7749    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
7750        match self {
7751            HavingBoundKind::Min => write!(f, "MIN"),
7752            HavingBoundKind::Max => write!(f, "MAX"),
7753        }
7754    }
7755}
7756
7757#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7758#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7759#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7760pub enum ObjectType {
7761    Table,
7762    View,
7763    MaterializedView,
7764    Index,
7765    Schema,
7766    Database,
7767    Role,
7768    Sequence,
7769    Stage,
7770    Type,
7771    User,
7772}
7773
7774impl fmt::Display for ObjectType {
7775    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7776        f.write_str(match self {
7777            ObjectType::Table => "TABLE",
7778            ObjectType::View => "VIEW",
7779            ObjectType::MaterializedView => "MATERIALIZED VIEW",
7780            ObjectType::Index => "INDEX",
7781            ObjectType::Schema => "SCHEMA",
7782            ObjectType::Database => "DATABASE",
7783            ObjectType::Role => "ROLE",
7784            ObjectType::Sequence => "SEQUENCE",
7785            ObjectType::Stage => "STAGE",
7786            ObjectType::Type => "TYPE",
7787            ObjectType::User => "USER",
7788        })
7789    }
7790}
7791
7792#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7793#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7794#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7795pub enum KillType {
7796    Connection,
7797    Query,
7798    Mutation,
7799}
7800
7801impl fmt::Display for KillType {
7802    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7803        f.write_str(match self {
7804            // MySQL
7805            KillType::Connection => "CONNECTION",
7806            KillType::Query => "QUERY",
7807            // Clickhouse supports Mutation
7808            KillType::Mutation => "MUTATION",
7809        })
7810    }
7811}
7812
7813#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7814#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7815#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7816pub enum HiveDistributionStyle {
7817    PARTITIONED {
7818        columns: Vec<ColumnDef>,
7819    },
7820    SKEWED {
7821        columns: Vec<ColumnDef>,
7822        on: Vec<ColumnDef>,
7823        stored_as_directories: bool,
7824    },
7825    NONE,
7826}
7827
7828#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7829#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7830#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7831pub enum HiveRowFormat {
7832    SERDE { class: String },
7833    DELIMITED { delimiters: Vec<HiveRowDelimiter> },
7834}
7835
7836#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7837#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7838#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7839pub struct HiveLoadDataFormat {
7840    pub serde: Expr,
7841    pub input_format: Expr,
7842}
7843
7844#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7845#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7846#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7847pub struct HiveRowDelimiter {
7848    pub delimiter: HiveDelimiter,
7849    pub char: Ident,
7850}
7851
7852impl fmt::Display for HiveRowDelimiter {
7853    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
7854        write!(f, "{} ", self.delimiter)?;
7855        write!(f, "{}", self.char)
7856    }
7857}
7858
7859#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7860#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7861#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7862pub enum HiveDelimiter {
7863    FieldsTerminatedBy,
7864    FieldsEscapedBy,
7865    CollectionItemsTerminatedBy,
7866    MapKeysTerminatedBy,
7867    LinesTerminatedBy,
7868    NullDefinedAs,
7869}
7870
7871impl fmt::Display for HiveDelimiter {
7872    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
7873        use HiveDelimiter::*;
7874        f.write_str(match self {
7875            FieldsTerminatedBy => "FIELDS TERMINATED BY",
7876            FieldsEscapedBy => "ESCAPED BY",
7877            CollectionItemsTerminatedBy => "COLLECTION ITEMS TERMINATED BY",
7878            MapKeysTerminatedBy => "MAP KEYS TERMINATED BY",
7879            LinesTerminatedBy => "LINES TERMINATED BY",
7880            NullDefinedAs => "NULL DEFINED AS",
7881        })
7882    }
7883}
7884
7885#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7886#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7887#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7888pub enum HiveDescribeFormat {
7889    Extended,
7890    Formatted,
7891}
7892
7893impl fmt::Display for HiveDescribeFormat {
7894    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
7895        use HiveDescribeFormat::*;
7896        f.write_str(match self {
7897            Extended => "EXTENDED",
7898            Formatted => "FORMATTED",
7899        })
7900    }
7901}
7902
7903#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7904#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7905#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7906pub enum DescribeAlias {
7907    Describe,
7908    Explain,
7909    Desc,
7910}
7911
7912impl fmt::Display for DescribeAlias {
7913    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
7914        use DescribeAlias::*;
7915        f.write_str(match self {
7916            Describe => "DESCRIBE",
7917            Explain => "EXPLAIN",
7918            Desc => "DESC",
7919        })
7920    }
7921}
7922
7923#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7924#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7925#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7926#[allow(clippy::large_enum_variant)]
7927pub enum HiveIOFormat {
7928    IOF {
7929        input_format: Expr,
7930        output_format: Expr,
7931    },
7932    FileFormat {
7933        format: FileFormat,
7934    },
7935}
7936
7937#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Default)]
7938#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7939#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7940pub struct HiveFormat {
7941    pub row_format: Option<HiveRowFormat>,
7942    pub serde_properties: Option<Vec<SqlOption>>,
7943    pub storage: Option<HiveIOFormat>,
7944    pub location: Option<String>,
7945}
7946
7947#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7948#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7949#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7950pub struct ClusteredIndex {
7951    pub name: Ident,
7952    pub asc: Option<bool>,
7953}
7954
7955impl fmt::Display for ClusteredIndex {
7956    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7957        write!(f, "{}", self.name)?;
7958        match self.asc {
7959            Some(true) => write!(f, " ASC"),
7960            Some(false) => write!(f, " DESC"),
7961            _ => Ok(()),
7962        }
7963    }
7964}
7965
7966#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7967#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7968#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7969pub enum TableOptionsClustered {
7970    ColumnstoreIndex,
7971    ColumnstoreIndexOrder(Vec<Ident>),
7972    Index(Vec<ClusteredIndex>),
7973}
7974
7975impl fmt::Display for TableOptionsClustered {
7976    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7977        match self {
7978            TableOptionsClustered::ColumnstoreIndex => {
7979                write!(f, "CLUSTERED COLUMNSTORE INDEX")
7980            }
7981            TableOptionsClustered::ColumnstoreIndexOrder(values) => {
7982                write!(
7983                    f,
7984                    "CLUSTERED COLUMNSTORE INDEX ORDER ({})",
7985                    display_comma_separated(values)
7986                )
7987            }
7988            TableOptionsClustered::Index(values) => {
7989                write!(f, "CLUSTERED INDEX ({})", display_comma_separated(values))
7990            }
7991        }
7992    }
7993}
7994
7995/// Specifies which partition the boundary values on table partitioning belongs to.
7996#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7997#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7998#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7999pub enum PartitionRangeDirection {
8000    Left,
8001    Right,
8002}
8003
8004#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8005#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8006#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8007pub enum SqlOption {
8008    /// Clustered represents the clustered version of table storage for MSSQL.
8009    ///
8010    /// <https://learn.microsoft.com/en-us/sql/t-sql/statements/create-table-azure-sql-data-warehouse?view=aps-pdw-2016-au7#TableOptions>
8011    Clustered(TableOptionsClustered),
8012    /// Single identifier options, e.g. `HEAP` for MSSQL.
8013    ///
8014    /// <https://learn.microsoft.com/en-us/sql/t-sql/statements/create-table-azure-sql-data-warehouse?view=aps-pdw-2016-au7#TableOptions>
8015    Ident(Ident),
8016    /// Any option that consists of a key value pair where the value is an expression. e.g.
8017    ///
8018    ///   WITH(DISTRIBUTION = ROUND_ROBIN)
8019    KeyValue { key: Ident, value: Expr },
8020    /// One or more table partitions and represents which partition the boundary values belong to,
8021    /// e.g.
8022    ///
8023    ///   PARTITION (id RANGE LEFT FOR VALUES (10, 20, 30, 40))
8024    ///
8025    /// <https://learn.microsoft.com/en-us/sql/t-sql/statements/create-table-azure-sql-data-warehouse?view=aps-pdw-2016-au7#TablePartitionOptions>
8026    Partition {
8027        column_name: Ident,
8028        range_direction: Option<PartitionRangeDirection>,
8029        for_values: Vec<Expr>,
8030    },
8031    /// Comment parameter (supports `=` and no `=` syntax)
8032    Comment(CommentDef),
8033    /// MySQL TableSpace option
8034    /// <https://dev.mysql.com/doc/refman/8.4/en/create-table.html>
8035    TableSpace(TablespaceOption),
8036    /// An option representing a key value pair, where the value is a parenthesized list and with an optional name
8037    /// e.g.
8038    ///
8039    ///   UNION  = (tbl_name\[,tbl_name\]...) <https://dev.mysql.com/doc/refman/8.4/en/create-table.html>
8040    ///   ENGINE = ReplicatedMergeTree('/table_name','{replica}', ver) <https://clickhouse.com/docs/engines/table-engines/mergetree-family/replication>
8041    ///   ENGINE = SummingMergeTree(\[columns\]) <https://clickhouse.com/docs/engines/table-engines/mergetree-family/summingmergetree>
8042    NamedParenthesizedList(NamedParenthesizedList),
8043}
8044
8045impl fmt::Display for SqlOption {
8046    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8047        match self {
8048            SqlOption::Clustered(c) => write!(f, "{c}"),
8049            SqlOption::Ident(ident) => {
8050                write!(f, "{ident}")
8051            }
8052            SqlOption::KeyValue { key: name, value } => {
8053                write!(f, "{name} = {value}")
8054            }
8055            SqlOption::Partition {
8056                column_name,
8057                range_direction,
8058                for_values,
8059            } => {
8060                let direction = match range_direction {
8061                    Some(PartitionRangeDirection::Left) => " LEFT",
8062                    Some(PartitionRangeDirection::Right) => " RIGHT",
8063                    None => "",
8064                };
8065
8066                write!(
8067                    f,
8068                    "PARTITION ({} RANGE{} FOR VALUES ({}))",
8069                    column_name,
8070                    direction,
8071                    display_comma_separated(for_values)
8072                )
8073            }
8074            SqlOption::TableSpace(tablespace_option) => {
8075                write!(f, "TABLESPACE {}", tablespace_option.name)?;
8076                match tablespace_option.storage {
8077                    Some(StorageType::Disk) => write!(f, " STORAGE DISK"),
8078                    Some(StorageType::Memory) => write!(f, " STORAGE MEMORY"),
8079                    None => Ok(()),
8080                }
8081            }
8082            SqlOption::Comment(comment) => match comment {
8083                CommentDef::WithEq(comment) => {
8084                    write!(f, "COMMENT = '{comment}'")
8085                }
8086                CommentDef::WithoutEq(comment) => {
8087                    write!(f, "COMMENT '{comment}'")
8088                }
8089            },
8090            SqlOption::NamedParenthesizedList(value) => {
8091                write!(f, "{} = ", value.key)?;
8092                if let Some(key) = &value.name {
8093                    write!(f, "{key}")?;
8094                }
8095                if !value.values.is_empty() {
8096                    write!(f, "({})", display_comma_separated(&value.values))?
8097                }
8098                Ok(())
8099            }
8100        }
8101    }
8102}
8103
8104#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
8105#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8106#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8107pub enum StorageType {
8108    Disk,
8109    Memory,
8110}
8111
8112#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
8113#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8114#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8115/// MySql TableSpace option
8116/// <https://dev.mysql.com/doc/refman/8.4/en/create-table.html>
8117pub struct TablespaceOption {
8118    pub name: String,
8119    pub storage: Option<StorageType>,
8120}
8121
8122#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8123#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8124#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8125pub struct SecretOption {
8126    pub key: Ident,
8127    pub value: Ident,
8128}
8129
8130impl fmt::Display for SecretOption {
8131    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8132        write!(f, "{} {}", self.key, self.value)
8133    }
8134}
8135
8136/// A `CREATE SERVER` statement.
8137///
8138/// [PostgreSQL Documentation](https://www.postgresql.org/docs/current/sql-createserver.html)
8139#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8140#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8141#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8142pub struct CreateServerStatement {
8143    pub name: ObjectName,
8144    pub if_not_exists: bool,
8145    pub server_type: Option<Ident>,
8146    pub version: Option<Ident>,
8147    pub foreign_data_wrapper: ObjectName,
8148    pub options: Option<Vec<CreateServerOption>>,
8149}
8150
8151impl fmt::Display for CreateServerStatement {
8152    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8153        let CreateServerStatement {
8154            name,
8155            if_not_exists,
8156            server_type,
8157            version,
8158            foreign_data_wrapper,
8159            options,
8160        } = self;
8161
8162        write!(
8163            f,
8164            "CREATE SERVER {if_not_exists}{name} ",
8165            if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
8166        )?;
8167
8168        if let Some(st) = server_type {
8169            write!(f, "TYPE {st} ")?;
8170        }
8171
8172        if let Some(v) = version {
8173            write!(f, "VERSION {v} ")?;
8174        }
8175
8176        write!(f, "FOREIGN DATA WRAPPER {foreign_data_wrapper}")?;
8177
8178        if let Some(o) = options {
8179            write!(f, " OPTIONS ({o})", o = display_comma_separated(o))?;
8180        }
8181
8182        Ok(())
8183    }
8184}
8185
8186#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8187#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8188#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8189pub struct CreateServerOption {
8190    pub key: Ident,
8191    pub value: Ident,
8192}
8193
8194impl fmt::Display for CreateServerOption {
8195    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8196        write!(f, "{} {}", self.key, self.value)
8197    }
8198}
8199
8200#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8201#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8202#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8203pub enum AttachDuckDBDatabaseOption {
8204    ReadOnly(Option<bool>),
8205    Type(Ident),
8206}
8207
8208impl fmt::Display for AttachDuckDBDatabaseOption {
8209    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8210        match self {
8211            AttachDuckDBDatabaseOption::ReadOnly(Some(true)) => write!(f, "READ_ONLY true"),
8212            AttachDuckDBDatabaseOption::ReadOnly(Some(false)) => write!(f, "READ_ONLY false"),
8213            AttachDuckDBDatabaseOption::ReadOnly(None) => write!(f, "READ_ONLY"),
8214            AttachDuckDBDatabaseOption::Type(t) => write!(f, "TYPE {t}"),
8215        }
8216    }
8217}
8218
8219#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8220#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8221#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8222pub enum TransactionMode {
8223    AccessMode(TransactionAccessMode),
8224    IsolationLevel(TransactionIsolationLevel),
8225}
8226
8227impl fmt::Display for TransactionMode {
8228    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8229        use TransactionMode::*;
8230        match self {
8231            AccessMode(access_mode) => write!(f, "{access_mode}"),
8232            IsolationLevel(iso_level) => write!(f, "ISOLATION LEVEL {iso_level}"),
8233        }
8234    }
8235}
8236
8237#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8238#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8239#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8240pub enum TransactionAccessMode {
8241    ReadOnly,
8242    ReadWrite,
8243}
8244
8245impl fmt::Display for TransactionAccessMode {
8246    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8247        use TransactionAccessMode::*;
8248        f.write_str(match self {
8249            ReadOnly => "READ ONLY",
8250            ReadWrite => "READ WRITE",
8251        })
8252    }
8253}
8254
8255#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8256#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8257#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8258pub enum TransactionIsolationLevel {
8259    ReadUncommitted,
8260    ReadCommitted,
8261    RepeatableRead,
8262    Serializable,
8263    Snapshot,
8264}
8265
8266impl fmt::Display for TransactionIsolationLevel {
8267    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8268        use TransactionIsolationLevel::*;
8269        f.write_str(match self {
8270            ReadUncommitted => "READ UNCOMMITTED",
8271            ReadCommitted => "READ COMMITTED",
8272            RepeatableRead => "REPEATABLE READ",
8273            Serializable => "SERIALIZABLE",
8274            Snapshot => "SNAPSHOT",
8275        })
8276    }
8277}
8278
8279/// Modifier for the transaction in the `BEGIN` syntax
8280///
8281/// SQLite: <https://sqlite.org/lang_transaction.html>
8282/// MS-SQL: <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/try-catch-transact-sql>
8283#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8284#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8285#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8286pub enum TransactionModifier {
8287    Deferred,
8288    Immediate,
8289    Exclusive,
8290    Try,
8291    Catch,
8292}
8293
8294impl fmt::Display for TransactionModifier {
8295    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8296        use TransactionModifier::*;
8297        f.write_str(match self {
8298            Deferred => "DEFERRED",
8299            Immediate => "IMMEDIATE",
8300            Exclusive => "EXCLUSIVE",
8301            Try => "TRY",
8302            Catch => "CATCH",
8303        })
8304    }
8305}
8306
8307#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8308#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8309#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8310pub enum ShowStatementFilter {
8311    Like(String),
8312    ILike(String),
8313    Where(Expr),
8314    NoKeyword(String),
8315}
8316
8317impl fmt::Display for ShowStatementFilter {
8318    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8319        use ShowStatementFilter::*;
8320        match self {
8321            Like(pattern) => write!(f, "LIKE '{}'", value::escape_single_quote_string(pattern)),
8322            ILike(pattern) => write!(f, "ILIKE {}", value::escape_single_quote_string(pattern)),
8323            Where(expr) => write!(f, "WHERE {expr}"),
8324            NoKeyword(pattern) => write!(f, "'{}'", value::escape_single_quote_string(pattern)),
8325        }
8326    }
8327}
8328
8329#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8330#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8331#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8332pub enum ShowStatementInClause {
8333    IN,
8334    FROM,
8335}
8336
8337impl fmt::Display for ShowStatementInClause {
8338    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8339        use ShowStatementInClause::*;
8340        match self {
8341            FROM => write!(f, "FROM"),
8342            IN => write!(f, "IN"),
8343        }
8344    }
8345}
8346
8347/// Sqlite specific syntax
8348///
8349/// See [Sqlite documentation](https://sqlite.org/lang_conflict.html)
8350/// for more details.
8351#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8352#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8353#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8354pub enum SqliteOnConflict {
8355    Rollback,
8356    Abort,
8357    Fail,
8358    Ignore,
8359    Replace,
8360}
8361
8362impl fmt::Display for SqliteOnConflict {
8363    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8364        use SqliteOnConflict::*;
8365        match self {
8366            Rollback => write!(f, "OR ROLLBACK"),
8367            Abort => write!(f, "OR ABORT"),
8368            Fail => write!(f, "OR FAIL"),
8369            Ignore => write!(f, "OR IGNORE"),
8370            Replace => write!(f, "OR REPLACE"),
8371        }
8372    }
8373}
8374
8375/// Mysql specific syntax
8376///
8377/// See [Mysql documentation](https://dev.mysql.com/doc/refman/8.0/en/replace.html)
8378/// See [Mysql documentation](https://dev.mysql.com/doc/refman/8.0/en/insert.html)
8379/// for more details.
8380#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8381#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8382#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8383pub enum MysqlInsertPriority {
8384    LowPriority,
8385    Delayed,
8386    HighPriority,
8387}
8388
8389impl fmt::Display for crate::ast::MysqlInsertPriority {
8390    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8391        use MysqlInsertPriority::*;
8392        match self {
8393            LowPriority => write!(f, "LOW_PRIORITY"),
8394            Delayed => write!(f, "DELAYED"),
8395            HighPriority => write!(f, "HIGH_PRIORITY"),
8396        }
8397    }
8398}
8399
8400#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8401#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8402#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8403pub enum CopySource {
8404    Table {
8405        /// The name of the table to copy from.
8406        table_name: ObjectName,
8407        /// A list of column names to copy. Empty list means that all columns
8408        /// are copied.
8409        columns: Vec<Ident>,
8410    },
8411    Query(Box<Query>),
8412}
8413
8414#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8415#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8416#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8417pub enum CopyTarget {
8418    Stdin,
8419    Stdout,
8420    File {
8421        /// The path name of the input or output file.
8422        filename: String,
8423    },
8424    Program {
8425        /// A command to execute
8426        command: String,
8427    },
8428}
8429
8430impl fmt::Display for CopyTarget {
8431    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8432        use CopyTarget::*;
8433        match self {
8434            Stdin => write!(f, "STDIN"),
8435            Stdout => write!(f, "STDOUT"),
8436            File { filename } => write!(f, "'{}'", value::escape_single_quote_string(filename)),
8437            Program { command } => write!(
8438                f,
8439                "PROGRAM '{}'",
8440                value::escape_single_quote_string(command)
8441            ),
8442        }
8443    }
8444}
8445
8446#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8447#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8448#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8449pub enum OnCommit {
8450    DeleteRows,
8451    PreserveRows,
8452    Drop,
8453}
8454
8455/// An option in `COPY` statement.
8456///
8457/// <https://www.postgresql.org/docs/14/sql-copy.html>
8458#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8459#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8460#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8461pub enum CopyOption {
8462    /// FORMAT format_name
8463    Format(Ident),
8464    /// FREEZE \[ boolean \]
8465    Freeze(bool),
8466    /// DELIMITER 'delimiter_character'
8467    Delimiter(char),
8468    /// NULL 'null_string'
8469    Null(String),
8470    /// HEADER \[ boolean \]
8471    Header(bool),
8472    /// QUOTE 'quote_character'
8473    Quote(char),
8474    /// ESCAPE 'escape_character'
8475    Escape(char),
8476    /// FORCE_QUOTE { ( column_name [, ...] ) | * }
8477    ForceQuote(Vec<Ident>),
8478    /// FORCE_NOT_NULL ( column_name [, ...] )
8479    ForceNotNull(Vec<Ident>),
8480    /// FORCE_NULL ( column_name [, ...] )
8481    ForceNull(Vec<Ident>),
8482    /// ENCODING 'encoding_name'
8483    Encoding(String),
8484}
8485
8486impl fmt::Display for CopyOption {
8487    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8488        use CopyOption::*;
8489        match self {
8490            Format(name) => write!(f, "FORMAT {name}"),
8491            Freeze(true) => write!(f, "FREEZE"),
8492            Freeze(false) => write!(f, "FREEZE FALSE"),
8493            Delimiter(char) => write!(f, "DELIMITER '{char}'"),
8494            Null(string) => write!(f, "NULL '{}'", value::escape_single_quote_string(string)),
8495            Header(true) => write!(f, "HEADER"),
8496            Header(false) => write!(f, "HEADER FALSE"),
8497            Quote(char) => write!(f, "QUOTE '{char}'"),
8498            Escape(char) => write!(f, "ESCAPE '{char}'"),
8499            ForceQuote(columns) => write!(f, "FORCE_QUOTE ({})", display_comma_separated(columns)),
8500            ForceNotNull(columns) => {
8501                write!(f, "FORCE_NOT_NULL ({})", display_comma_separated(columns))
8502            }
8503            ForceNull(columns) => write!(f, "FORCE_NULL ({})", display_comma_separated(columns)),
8504            Encoding(name) => write!(f, "ENCODING '{}'", value::escape_single_quote_string(name)),
8505        }
8506    }
8507}
8508
8509/// An option in `COPY` statement before PostgreSQL version 9.0.
8510///
8511/// <https://www.postgresql.org/docs/8.4/sql-copy.html>
8512#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8513#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8514#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8515pub enum CopyLegacyOption {
8516    /// BINARY
8517    Binary,
8518    /// DELIMITER \[ AS \] 'delimiter_character'
8519    Delimiter(char),
8520    /// NULL \[ AS \] 'null_string'
8521    Null(String),
8522    /// CSV ...
8523    Csv(Vec<CopyLegacyCsvOption>),
8524}
8525
8526impl fmt::Display for CopyLegacyOption {
8527    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8528        use CopyLegacyOption::*;
8529        match self {
8530            Binary => write!(f, "BINARY"),
8531            Delimiter(char) => write!(f, "DELIMITER '{char}'"),
8532            Null(string) => write!(f, "NULL '{}'", value::escape_single_quote_string(string)),
8533            Csv(opts) => write!(f, "CSV {}", display_separated(opts, " ")),
8534        }
8535    }
8536}
8537
8538/// A `CSV` option in `COPY` statement before PostgreSQL version 9.0.
8539///
8540/// <https://www.postgresql.org/docs/8.4/sql-copy.html>
8541#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8542#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8543#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8544pub enum CopyLegacyCsvOption {
8545    /// HEADER
8546    Header,
8547    /// QUOTE \[ AS \] 'quote_character'
8548    Quote(char),
8549    /// ESCAPE \[ AS \] 'escape_character'
8550    Escape(char),
8551    /// FORCE QUOTE { column_name [, ...] | * }
8552    ForceQuote(Vec<Ident>),
8553    /// FORCE NOT NULL column_name [, ...]
8554    ForceNotNull(Vec<Ident>),
8555}
8556
8557impl fmt::Display for CopyLegacyCsvOption {
8558    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8559        use CopyLegacyCsvOption::*;
8560        match self {
8561            Header => write!(f, "HEADER"),
8562            Quote(char) => write!(f, "QUOTE '{char}'"),
8563            Escape(char) => write!(f, "ESCAPE '{char}'"),
8564            ForceQuote(columns) => write!(f, "FORCE QUOTE {}", display_comma_separated(columns)),
8565            ForceNotNull(columns) => {
8566                write!(f, "FORCE NOT NULL {}", display_comma_separated(columns))
8567            }
8568        }
8569    }
8570}
8571
8572/// Variant of `WHEN` clause used within a `MERGE` Statement.
8573///
8574/// Example:
8575/// ```sql
8576/// MERGE INTO T USING U ON FALSE WHEN MATCHED THEN DELETE
8577/// ```
8578/// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/merge)
8579/// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/dml-syntax#merge_statement)
8580#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8581#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8582#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8583pub enum MergeClauseKind {
8584    /// `WHEN MATCHED`
8585    Matched,
8586    /// `WHEN NOT MATCHED`
8587    NotMatched,
8588    /// `WHEN MATCHED BY TARGET`
8589    ///
8590    /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/dml-syntax#merge_statement)
8591    NotMatchedByTarget,
8592    /// `WHEN MATCHED BY SOURCE`
8593    ///
8594    /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/dml-syntax#merge_statement)
8595    NotMatchedBySource,
8596}
8597
8598impl Display for MergeClauseKind {
8599    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8600        match self {
8601            MergeClauseKind::Matched => write!(f, "MATCHED"),
8602            MergeClauseKind::NotMatched => write!(f, "NOT MATCHED"),
8603            MergeClauseKind::NotMatchedByTarget => write!(f, "NOT MATCHED BY TARGET"),
8604            MergeClauseKind::NotMatchedBySource => write!(f, "NOT MATCHED BY SOURCE"),
8605        }
8606    }
8607}
8608
8609/// The type of expression used to insert rows within a `MERGE` statement.
8610///
8611/// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/merge)
8612/// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/dml-syntax#merge_statement)
8613#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8614#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8615#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8616pub enum MergeInsertKind {
8617    /// The insert expression is defined from an explicit `VALUES` clause
8618    ///
8619    /// Example:
8620    /// ```sql
8621    /// INSERT VALUES(product, quantity)
8622    /// ```
8623    Values(Values),
8624    /// The insert expression is defined using only the `ROW` keyword.
8625    ///
8626    /// Example:
8627    /// ```sql
8628    /// INSERT ROW
8629    /// ```
8630    /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/dml-syntax#merge_statement)
8631    Row,
8632}
8633
8634impl Display for MergeInsertKind {
8635    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8636        match self {
8637            MergeInsertKind::Values(values) => {
8638                write!(f, "{values}")
8639            }
8640            MergeInsertKind::Row => {
8641                write!(f, "ROW")
8642            }
8643        }
8644    }
8645}
8646
8647/// The expression used to insert rows within a `MERGE` statement.
8648///
8649/// Examples
8650/// ```sql
8651/// INSERT (product, quantity) VALUES(product, quantity)
8652/// INSERT ROW
8653/// ```
8654///
8655/// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/merge)
8656/// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/dml-syntax#merge_statement)
8657#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8658#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8659#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8660pub struct MergeInsertExpr {
8661    /// Columns (if any) specified by the insert.
8662    ///
8663    /// Example:
8664    /// ```sql
8665    /// INSERT (product, quantity) VALUES(product, quantity)
8666    /// INSERT (product, quantity) ROW
8667    /// ```
8668    pub columns: Vec<Ident>,
8669    /// The insert type used by the statement.
8670    pub kind: MergeInsertKind,
8671}
8672
8673impl Display for MergeInsertExpr {
8674    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8675        if !self.columns.is_empty() {
8676            write!(f, "({}) ", display_comma_separated(self.columns.as_slice()))?;
8677        }
8678        write!(f, "{}", self.kind)
8679    }
8680}
8681
8682/// Underlying statement of a when clause within a `MERGE` Statement
8683///
8684/// Example
8685/// ```sql
8686/// INSERT (product, quantity) VALUES(product, quantity)
8687/// ```
8688///
8689/// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/merge)
8690/// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/dml-syntax#merge_statement)
8691#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8692#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8693#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8694pub enum MergeAction {
8695    /// An `INSERT` clause
8696    ///
8697    /// Example:
8698    /// ```sql
8699    /// INSERT (product, quantity) VALUES(product, quantity)
8700    /// ```
8701    Insert(MergeInsertExpr),
8702    /// An `UPDATE` clause
8703    ///
8704    /// Example:
8705    /// ```sql
8706    /// UPDATE SET quantity = T.quantity + S.quantity
8707    /// ```
8708    Update { assignments: Vec<Assignment> },
8709    /// A plain `DELETE` clause
8710    Delete,
8711}
8712
8713impl Display for MergeAction {
8714    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8715        match self {
8716            MergeAction::Insert(insert) => {
8717                write!(f, "INSERT {insert}")
8718            }
8719            MergeAction::Update { assignments } => {
8720                write!(f, "UPDATE SET {}", display_comma_separated(assignments))
8721            }
8722            MergeAction::Delete => {
8723                write!(f, "DELETE")
8724            }
8725        }
8726    }
8727}
8728
8729/// A when clause within a `MERGE` Statement
8730///
8731/// Example:
8732/// ```sql
8733/// WHEN NOT MATCHED BY SOURCE AND product LIKE '%washer%' THEN DELETE
8734/// ```
8735/// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/merge)
8736/// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/dml-syntax#merge_statement)
8737#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8738#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8739#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8740pub struct MergeClause {
8741    pub clause_kind: MergeClauseKind,
8742    pub predicate: Option<Expr>,
8743    pub action: MergeAction,
8744}
8745
8746impl Display for MergeClause {
8747    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8748        let MergeClause {
8749            clause_kind,
8750            predicate,
8751            action,
8752        } = self;
8753
8754        write!(f, "WHEN {clause_kind}")?;
8755        if let Some(pred) = predicate {
8756            write!(f, " AND {pred}")?;
8757        }
8758        write!(f, " THEN {action}")
8759    }
8760}
8761
8762/// A Output Clause in the end of a 'MERGE' Statement
8763///
8764/// Example:
8765/// OUTPUT $action, deleted.* INTO dbo.temp_products;
8766/// [mssql](https://learn.microsoft.com/en-us/sql/t-sql/queries/output-clause-transact-sql)
8767#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8768#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8769#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8770pub struct OutputClause {
8771    pub select_items: Vec<SelectItem>,
8772    pub into_table: SelectInto,
8773}
8774
8775impl fmt::Display for OutputClause {
8776    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8777        let OutputClause {
8778            select_items,
8779            into_table,
8780        } = self;
8781
8782        write!(
8783            f,
8784            "OUTPUT {} {}",
8785            display_comma_separated(select_items),
8786            into_table
8787        )
8788    }
8789}
8790
8791#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8792#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8793#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8794pub enum DiscardObject {
8795    ALL,
8796    PLANS,
8797    SEQUENCES,
8798    TEMP,
8799}
8800
8801impl fmt::Display for DiscardObject {
8802    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8803        match self {
8804            DiscardObject::ALL => f.write_str("ALL"),
8805            DiscardObject::PLANS => f.write_str("PLANS"),
8806            DiscardObject::SEQUENCES => f.write_str("SEQUENCES"),
8807            DiscardObject::TEMP => f.write_str("TEMP"),
8808        }
8809    }
8810}
8811
8812#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8813#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8814#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8815pub enum FlushType {
8816    BinaryLogs,
8817    EngineLogs,
8818    ErrorLogs,
8819    GeneralLogs,
8820    Hosts,
8821    Logs,
8822    Privileges,
8823    OptimizerCosts,
8824    RelayLogs,
8825    SlowLogs,
8826    Status,
8827    UserResources,
8828    Tables,
8829}
8830
8831impl fmt::Display for FlushType {
8832    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8833        match self {
8834            FlushType::BinaryLogs => f.write_str("BINARY LOGS"),
8835            FlushType::EngineLogs => f.write_str("ENGINE LOGS"),
8836            FlushType::ErrorLogs => f.write_str("ERROR LOGS"),
8837            FlushType::GeneralLogs => f.write_str("GENERAL LOGS"),
8838            FlushType::Hosts => f.write_str("HOSTS"),
8839            FlushType::Logs => f.write_str("LOGS"),
8840            FlushType::Privileges => f.write_str("PRIVILEGES"),
8841            FlushType::OptimizerCosts => f.write_str("OPTIMIZER_COSTS"),
8842            FlushType::RelayLogs => f.write_str("RELAY LOGS"),
8843            FlushType::SlowLogs => f.write_str("SLOW LOGS"),
8844            FlushType::Status => f.write_str("STATUS"),
8845            FlushType::UserResources => f.write_str("USER_RESOURCES"),
8846            FlushType::Tables => f.write_str("TABLES"),
8847        }
8848    }
8849}
8850
8851#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8852#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8853#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8854pub enum FlushLocation {
8855    NoWriteToBinlog,
8856    Local,
8857}
8858
8859impl fmt::Display for FlushLocation {
8860    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8861        match self {
8862            FlushLocation::NoWriteToBinlog => f.write_str("NO_WRITE_TO_BINLOG"),
8863            FlushLocation::Local => f.write_str("LOCAL"),
8864        }
8865    }
8866}
8867
8868/// Optional context modifier for statements that can be or `LOCAL`, `GLOBAL`, or `SESSION`.
8869#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8870#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8871#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8872pub enum ContextModifier {
8873    /// `LOCAL` identifier, usually related to transactional states.
8874    Local,
8875    /// `SESSION` identifier
8876    Session,
8877    /// `GLOBAL` identifier
8878    Global,
8879}
8880
8881impl fmt::Display for ContextModifier {
8882    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8883        match self {
8884            Self::Local => {
8885                write!(f, "LOCAL ")
8886            }
8887            Self::Session => {
8888                write!(f, "SESSION ")
8889            }
8890            Self::Global => {
8891                write!(f, "GLOBAL ")
8892            }
8893        }
8894    }
8895}
8896
8897/// Function describe in DROP FUNCTION.
8898#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8899#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8900pub enum DropFunctionOption {
8901    Restrict,
8902    Cascade,
8903}
8904
8905impl fmt::Display for DropFunctionOption {
8906    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8907        match self {
8908            DropFunctionOption::Restrict => write!(f, "RESTRICT "),
8909            DropFunctionOption::Cascade => write!(f, "CASCADE  "),
8910        }
8911    }
8912}
8913
8914/// Generic function description for DROP FUNCTION and CREATE TRIGGER.
8915#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8916#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8917#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8918pub struct FunctionDesc {
8919    pub name: ObjectName,
8920    pub args: Option<Vec<OperateFunctionArg>>,
8921}
8922
8923impl fmt::Display for FunctionDesc {
8924    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8925        write!(f, "{}", self.name)?;
8926        if let Some(args) = &self.args {
8927            write!(f, "({})", display_comma_separated(args))?;
8928        }
8929        Ok(())
8930    }
8931}
8932
8933/// Function argument in CREATE OR DROP FUNCTION.
8934#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8935#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8936#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8937pub struct OperateFunctionArg {
8938    pub mode: Option<ArgMode>,
8939    pub name: Option<Ident>,
8940    pub data_type: DataType,
8941    pub default_expr: Option<Expr>,
8942}
8943
8944impl OperateFunctionArg {
8945    /// Returns an unnamed argument.
8946    pub fn unnamed(data_type: DataType) -> Self {
8947        Self {
8948            mode: None,
8949            name: None,
8950            data_type,
8951            default_expr: None,
8952        }
8953    }
8954
8955    /// Returns an argument with name.
8956    pub fn with_name(name: &str, data_type: DataType) -> Self {
8957        Self {
8958            mode: None,
8959            name: Some(name.into()),
8960            data_type,
8961            default_expr: None,
8962        }
8963    }
8964}
8965
8966impl fmt::Display for OperateFunctionArg {
8967    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8968        if let Some(mode) = &self.mode {
8969            write!(f, "{mode} ")?;
8970        }
8971        if let Some(name) = &self.name {
8972            write!(f, "{name} ")?;
8973        }
8974        write!(f, "{}", self.data_type)?;
8975        if let Some(default_expr) = &self.default_expr {
8976            write!(f, " = {default_expr}")?;
8977        }
8978        Ok(())
8979    }
8980}
8981
8982/// The mode of an argument in CREATE FUNCTION.
8983#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8984#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8985#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8986pub enum ArgMode {
8987    In,
8988    Out,
8989    InOut,
8990}
8991
8992impl fmt::Display for ArgMode {
8993    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8994        match self {
8995            ArgMode::In => write!(f, "IN"),
8996            ArgMode::Out => write!(f, "OUT"),
8997            ArgMode::InOut => write!(f, "INOUT"),
8998        }
8999    }
9000}
9001
9002/// These attributes inform the query optimizer about the behavior of the function.
9003#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9004#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9005#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9006pub enum FunctionBehavior {
9007    Immutable,
9008    Stable,
9009    Volatile,
9010}
9011
9012impl fmt::Display for FunctionBehavior {
9013    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9014        match self {
9015            FunctionBehavior::Immutable => write!(f, "IMMUTABLE"),
9016            FunctionBehavior::Stable => write!(f, "STABLE"),
9017            FunctionBehavior::Volatile => write!(f, "VOLATILE"),
9018        }
9019    }
9020}
9021
9022/// These attributes describe the behavior of the function when called with a null argument.
9023#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9024#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9025#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9026pub enum FunctionCalledOnNull {
9027    CalledOnNullInput,
9028    ReturnsNullOnNullInput,
9029    Strict,
9030}
9031
9032impl fmt::Display for FunctionCalledOnNull {
9033    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9034        match self {
9035            FunctionCalledOnNull::CalledOnNullInput => write!(f, "CALLED ON NULL INPUT"),
9036            FunctionCalledOnNull::ReturnsNullOnNullInput => write!(f, "RETURNS NULL ON NULL INPUT"),
9037            FunctionCalledOnNull::Strict => write!(f, "STRICT"),
9038        }
9039    }
9040}
9041
9042/// If it is safe for PostgreSQL to call the function from multiple threads at once
9043#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9044#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9045#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9046pub enum FunctionParallel {
9047    Unsafe,
9048    Restricted,
9049    Safe,
9050}
9051
9052impl fmt::Display for FunctionParallel {
9053    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9054        match self {
9055            FunctionParallel::Unsafe => write!(f, "PARALLEL UNSAFE"),
9056            FunctionParallel::Restricted => write!(f, "PARALLEL RESTRICTED"),
9057            FunctionParallel::Safe => write!(f, "PARALLEL SAFE"),
9058        }
9059    }
9060}
9061
9062/// [BigQuery] Determinism specifier used in a UDF definition.
9063///
9064/// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#syntax_11
9065#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9066#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9067#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9068pub enum FunctionDeterminismSpecifier {
9069    Deterministic,
9070    NotDeterministic,
9071}
9072
9073impl fmt::Display for FunctionDeterminismSpecifier {
9074    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9075        match self {
9076            FunctionDeterminismSpecifier::Deterministic => {
9077                write!(f, "DETERMINISTIC")
9078            }
9079            FunctionDeterminismSpecifier::NotDeterministic => {
9080                write!(f, "NOT DETERMINISTIC")
9081            }
9082        }
9083    }
9084}
9085
9086/// Represent the expression body of a `CREATE FUNCTION` statement as well as
9087/// where within the statement, the body shows up.
9088///
9089/// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#syntax_11
9090/// [PostgreSQL]: https://www.postgresql.org/docs/15/sql-createfunction.html
9091/// [MsSql]: https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql
9092#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9093#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9094#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9095pub enum CreateFunctionBody {
9096    /// A function body expression using the 'AS' keyword and shows up
9097    /// before any `OPTIONS` clause.
9098    ///
9099    /// Example:
9100    /// ```sql
9101    /// CREATE FUNCTION myfunc(x FLOAT64, y FLOAT64) RETURNS FLOAT64
9102    /// AS (x * y)
9103    /// OPTIONS(description="desc");
9104    /// ```
9105    ///
9106    /// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#syntax_11
9107    AsBeforeOptions(Expr),
9108    /// A function body expression using the 'AS' keyword and shows up
9109    /// after any `OPTIONS` clause.
9110    ///
9111    /// Example:
9112    /// ```sql
9113    /// CREATE FUNCTION myfunc(x FLOAT64, y FLOAT64) RETURNS FLOAT64
9114    /// OPTIONS(description="desc")
9115    /// AS (x * y);
9116    /// ```
9117    ///
9118    /// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#syntax_11
9119    AsAfterOptions(Expr),
9120    /// Function body with statements before the `RETURN` keyword.
9121    ///
9122    /// Example:
9123    /// ```sql
9124    /// CREATE FUNCTION my_scalar_udf(a INT, b INT)
9125    /// RETURNS INT
9126    /// AS
9127    /// BEGIN
9128    ///     DECLARE c INT;
9129    ///     SET c = a + b;
9130    ///     RETURN c;
9131    /// END
9132    /// ```
9133    ///
9134    /// [MsSql]: https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql
9135    AsBeginEnd(BeginEndStatements),
9136    /// Function body expression using the 'RETURN' keyword.
9137    ///
9138    /// Example:
9139    /// ```sql
9140    /// CREATE FUNCTION myfunc(a INTEGER, IN b INTEGER = 1) RETURNS INTEGER
9141    /// LANGUAGE SQL
9142    /// RETURN a + b;
9143    /// ```
9144    ///
9145    /// [PostgreSQL]: https://www.postgresql.org/docs/current/sql-createfunction.html
9146    Return(Expr),
9147
9148    /// Function body expression using the 'AS RETURN' keywords
9149    ///
9150    /// Example:
9151    /// ```sql
9152    /// CREATE FUNCTION myfunc(a INT, b INT)
9153    /// RETURNS TABLE
9154    /// AS RETURN (SELECT a + b AS sum);
9155    /// ```
9156    ///
9157    /// [MsSql]: https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql
9158    AsReturnExpr(Expr),
9159
9160    /// Function body expression using the 'AS RETURN' keywords, with an un-parenthesized SELECT query
9161    ///
9162    /// Example:
9163    /// ```sql
9164    /// CREATE FUNCTION myfunc(a INT, b INT)
9165    /// RETURNS TABLE
9166    /// AS RETURN SELECT a + b AS sum;
9167    /// ```
9168    ///
9169    /// [MsSql]: https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql?view=sql-server-ver16#select_stmt
9170    AsReturnSelect(Select),
9171}
9172
9173#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9174#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9175#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9176pub enum CreateFunctionUsing {
9177    Jar(String),
9178    File(String),
9179    Archive(String),
9180}
9181
9182impl fmt::Display for CreateFunctionUsing {
9183    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9184        write!(f, "USING ")?;
9185        match self {
9186            CreateFunctionUsing::Jar(uri) => write!(f, "JAR '{uri}'"),
9187            CreateFunctionUsing::File(uri) => write!(f, "FILE '{uri}'"),
9188            CreateFunctionUsing::Archive(uri) => write!(f, "ARCHIVE '{uri}'"),
9189        }
9190    }
9191}
9192
9193/// `NAME = <EXPR>` arguments for DuckDB macros
9194///
9195/// See [Create Macro - DuckDB](https://duckdb.org/docs/sql/statements/create_macro)
9196/// for more details
9197#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9198#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9199#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9200pub struct MacroArg {
9201    pub name: Ident,
9202    pub default_expr: Option<Expr>,
9203}
9204
9205impl MacroArg {
9206    /// Returns an argument with name.
9207    pub fn new(name: &str) -> Self {
9208        Self {
9209            name: name.into(),
9210            default_expr: None,
9211        }
9212    }
9213}
9214
9215impl fmt::Display for MacroArg {
9216    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9217        write!(f, "{}", self.name)?;
9218        if let Some(default_expr) = &self.default_expr {
9219            write!(f, " := {default_expr}")?;
9220        }
9221        Ok(())
9222    }
9223}
9224
9225#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9226#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9227#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9228pub enum MacroDefinition {
9229    Expr(Expr),
9230    Table(Box<Query>),
9231}
9232
9233impl fmt::Display for MacroDefinition {
9234    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9235        match self {
9236            MacroDefinition::Expr(expr) => write!(f, "{expr}")?,
9237            MacroDefinition::Table(query) => write!(f, "{query}")?,
9238        }
9239        Ok(())
9240    }
9241}
9242
9243/// Schema possible naming variants ([1]).
9244///
9245/// [1]: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#schema-definition
9246#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9247#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9248#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9249pub enum SchemaName {
9250    /// Only schema name specified: `<schema name>`.
9251    Simple(ObjectName),
9252    /// Only authorization identifier specified: `AUTHORIZATION <schema authorization identifier>`.
9253    UnnamedAuthorization(Ident),
9254    /// Both schema name and authorization identifier specified: `<schema name>  AUTHORIZATION <schema authorization identifier>`.
9255    NamedAuthorization(ObjectName, Ident),
9256}
9257
9258impl fmt::Display for SchemaName {
9259    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
9260        match self {
9261            SchemaName::Simple(name) => {
9262                write!(f, "{name}")
9263            }
9264            SchemaName::UnnamedAuthorization(authorization) => {
9265                write!(f, "AUTHORIZATION {authorization}")
9266            }
9267            SchemaName::NamedAuthorization(name, authorization) => {
9268                write!(f, "{name} AUTHORIZATION {authorization}")
9269            }
9270        }
9271    }
9272}
9273
9274/// Fulltext search modifiers ([1]).
9275///
9276/// [1]: https://dev.mysql.com/doc/refman/8.0/en/fulltext-search.html#function_match
9277#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9278#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9279#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9280pub enum SearchModifier {
9281    /// `IN NATURAL LANGUAGE MODE`.
9282    InNaturalLanguageMode,
9283    /// `IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION`.
9284    InNaturalLanguageModeWithQueryExpansion,
9285    ///`IN BOOLEAN MODE`.
9286    InBooleanMode,
9287    ///`WITH QUERY EXPANSION`.
9288    WithQueryExpansion,
9289}
9290
9291impl fmt::Display for SearchModifier {
9292    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
9293        match self {
9294            Self::InNaturalLanguageMode => {
9295                write!(f, "IN NATURAL LANGUAGE MODE")?;
9296            }
9297            Self::InNaturalLanguageModeWithQueryExpansion => {
9298                write!(f, "IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION")?;
9299            }
9300            Self::InBooleanMode => {
9301                write!(f, "IN BOOLEAN MODE")?;
9302            }
9303            Self::WithQueryExpansion => {
9304                write!(f, "WITH QUERY EXPANSION")?;
9305            }
9306        }
9307
9308        Ok(())
9309    }
9310}
9311
9312#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9313#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9314#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9315pub struct LockTable {
9316    pub table: Ident,
9317    pub alias: Option<Ident>,
9318    pub lock_type: LockTableType,
9319}
9320
9321impl fmt::Display for LockTable {
9322    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
9323        let Self {
9324            table: tbl_name,
9325            alias,
9326            lock_type,
9327        } = self;
9328
9329        write!(f, "{tbl_name} ")?;
9330        if let Some(alias) = alias {
9331            write!(f, "AS {alias} ")?;
9332        }
9333        write!(f, "{lock_type}")?;
9334        Ok(())
9335    }
9336}
9337
9338#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9339#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9340#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9341pub enum LockTableType {
9342    Read { local: bool },
9343    Write { low_priority: bool },
9344}
9345
9346impl fmt::Display for LockTableType {
9347    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
9348        match self {
9349            Self::Read { local } => {
9350                write!(f, "READ")?;
9351                if *local {
9352                    write!(f, " LOCAL")?;
9353                }
9354            }
9355            Self::Write { low_priority } => {
9356                if *low_priority {
9357                    write!(f, "LOW_PRIORITY ")?;
9358                }
9359                write!(f, "WRITE")?;
9360            }
9361        }
9362
9363        Ok(())
9364    }
9365}
9366
9367#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9368#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9369#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9370pub struct HiveSetLocation {
9371    pub has_set: bool,
9372    pub location: Ident,
9373}
9374
9375impl fmt::Display for HiveSetLocation {
9376    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
9377        if self.has_set {
9378            write!(f, "SET ")?;
9379        }
9380        write!(f, "LOCATION {}", self.location)
9381    }
9382}
9383
9384/// MySQL `ALTER TABLE` only  [FIRST | AFTER column_name]
9385#[allow(clippy::large_enum_variant)]
9386#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9387#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9388#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9389pub enum MySQLColumnPosition {
9390    First,
9391    After(Ident),
9392}
9393
9394impl Display for MySQLColumnPosition {
9395    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9396        match self {
9397            MySQLColumnPosition::First => write!(f, "FIRST"),
9398            MySQLColumnPosition::After(ident) => {
9399                let column_name = &ident.value;
9400                write!(f, "AFTER {column_name}")
9401            }
9402        }
9403    }
9404}
9405
9406/// MySQL `CREATE VIEW` algorithm parameter: [ALGORITHM = {UNDEFINED | MERGE | TEMPTABLE}]
9407#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9408#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9409#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9410pub enum CreateViewAlgorithm {
9411    Undefined,
9412    Merge,
9413    TempTable,
9414}
9415
9416impl Display for CreateViewAlgorithm {
9417    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9418        match self {
9419            CreateViewAlgorithm::Undefined => write!(f, "UNDEFINED"),
9420            CreateViewAlgorithm::Merge => write!(f, "MERGE"),
9421            CreateViewAlgorithm::TempTable => write!(f, "TEMPTABLE"),
9422        }
9423    }
9424}
9425/// MySQL `CREATE VIEW` security parameter: [SQL SECURITY { DEFINER | INVOKER }]
9426#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9427#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9428#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9429pub enum CreateViewSecurity {
9430    Definer,
9431    Invoker,
9432}
9433
9434impl Display for CreateViewSecurity {
9435    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9436        match self {
9437            CreateViewSecurity::Definer => write!(f, "DEFINER"),
9438            CreateViewSecurity::Invoker => write!(f, "INVOKER"),
9439        }
9440    }
9441}
9442
9443/// [MySQL] `CREATE VIEW` additional parameters
9444///
9445/// [MySQL]: https://dev.mysql.com/doc/refman/9.1/en/create-view.html
9446#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9447#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9448#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9449pub struct CreateViewParams {
9450    pub algorithm: Option<CreateViewAlgorithm>,
9451    pub definer: Option<GranteeName>,
9452    pub security: Option<CreateViewSecurity>,
9453}
9454
9455impl Display for CreateViewParams {
9456    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
9457        let CreateViewParams {
9458            algorithm,
9459            definer,
9460            security,
9461        } = self;
9462        if let Some(algorithm) = algorithm {
9463            write!(f, "ALGORITHM = {algorithm} ")?;
9464        }
9465        if let Some(definers) = definer {
9466            write!(f, "DEFINER = {definers} ")?;
9467        }
9468        if let Some(security) = security {
9469            write!(f, "SQL SECURITY {security} ")?;
9470        }
9471        Ok(())
9472    }
9473}
9474
9475#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9476#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9477#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9478/// Key/Value, where the value is a (optionally named) list of identifiers
9479///
9480/// ```sql
9481/// UNION = (tbl_name[,tbl_name]...)
9482/// ENGINE = ReplicatedMergeTree('/table_name','{replica}', ver)
9483/// ENGINE = SummingMergeTree([columns])
9484/// ```
9485pub struct NamedParenthesizedList {
9486    pub key: Ident,
9487    pub name: Option<Ident>,
9488    pub values: Vec<Ident>,
9489}
9490
9491/// Snowflake `WITH ROW ACCESS POLICY policy_name ON (identifier, ...)`
9492///
9493/// <https://docs.snowflake.com/en/sql-reference/sql/create-table>
9494/// <https://docs.snowflake.com/en/user-guide/security-row-intro>
9495#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9496#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9497#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9498pub struct RowAccessPolicy {
9499    pub policy: ObjectName,
9500    pub on: Vec<Ident>,
9501}
9502
9503impl RowAccessPolicy {
9504    pub fn new(policy: ObjectName, on: Vec<Ident>) -> Self {
9505        Self { policy, on }
9506    }
9507}
9508
9509impl Display for RowAccessPolicy {
9510    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9511        write!(
9512            f,
9513            "WITH ROW ACCESS POLICY {} ON ({})",
9514            self.policy,
9515            display_comma_separated(self.on.as_slice())
9516        )
9517    }
9518}
9519
9520/// Snowflake `WITH TAG ( tag_name = '<tag_value>', ...)`
9521///
9522/// <https://docs.snowflake.com/en/sql-reference/sql/create-table>
9523#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9524#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9525#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9526pub struct Tag {
9527    pub key: ObjectName,
9528    pub value: String,
9529}
9530
9531impl Tag {
9532    pub fn new(key: ObjectName, value: String) -> Self {
9533        Self { key, value }
9534    }
9535}
9536
9537impl Display for Tag {
9538    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
9539        write!(f, "{}='{}'", self.key, self.value)
9540    }
9541}
9542
9543/// Helper to indicate if a comment includes the `=` in the display form
9544#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9545#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9546#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9547pub enum CommentDef {
9548    /// Includes `=` when printing the comment, as `COMMENT = 'comment'`
9549    /// Does not include `=` when printing the comment, as `COMMENT 'comment'`
9550    WithEq(String),
9551    WithoutEq(String),
9552}
9553
9554impl Display for CommentDef {
9555    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
9556        match self {
9557            CommentDef::WithEq(comment) | CommentDef::WithoutEq(comment) => write!(f, "{comment}"),
9558        }
9559    }
9560}
9561
9562/// Helper to indicate if a collection should be wrapped by a symbol in the display form
9563///
9564/// [`Display`] is implemented for every [`Vec<T>`] where `T: Display`.
9565/// The string output is a comma separated list for the vec items
9566///
9567/// # Examples
9568/// ```
9569/// # use sqlparser::ast::WrappedCollection;
9570/// let items = WrappedCollection::Parentheses(vec!["one", "two", "three"]);
9571/// assert_eq!("(one, two, three)", items.to_string());
9572///
9573/// let items = WrappedCollection::NoWrapping(vec!["one", "two", "three"]);
9574/// assert_eq!("one, two, three", items.to_string());
9575/// ```
9576#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9577#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9578#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9579pub enum WrappedCollection<T> {
9580    /// Print the collection without wrapping symbols, as `item, item, item`
9581    NoWrapping(T),
9582    /// Wraps the collection in Parentheses, as `(item, item, item)`
9583    Parentheses(T),
9584}
9585
9586impl<T> Display for WrappedCollection<Vec<T>>
9587where
9588    T: Display,
9589{
9590    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
9591        match self {
9592            WrappedCollection::NoWrapping(inner) => {
9593                write!(f, "{}", display_comma_separated(inner.as_slice()))
9594            }
9595            WrappedCollection::Parentheses(inner) => {
9596                write!(f, "({})", display_comma_separated(inner.as_slice()))
9597            }
9598        }
9599    }
9600}
9601
9602/// Represents a single PostgreSQL utility option.
9603///
9604/// A utility option is a key-value pair where the key is an identifier (IDENT) and the value
9605/// can be one of the following:
9606/// - A number with an optional sign (`+` or `-`). Example: `+10`, `-10.2`, `3`
9607/// - A non-keyword string. Example: `option1`, `'option2'`, `"option3"`
9608/// - keyword: `TRUE`, `FALSE`, `ON` (`off` is also accept).
9609/// - Empty. Example: `ANALYZE` (identifier only)
9610///
9611/// Utility options are used in various PostgreSQL DDL statements, including statements such as
9612/// `CLUSTER`, `EXPLAIN`, `VACUUM`, and `REINDEX`. These statements format options as `( option [, ...] )`.
9613///
9614/// [CLUSTER](https://www.postgresql.org/docs/current/sql-cluster.html)
9615/// [EXPLAIN](https://www.postgresql.org/docs/current/sql-explain.html)
9616/// [VACUUM](https://www.postgresql.org/docs/current/sql-vacuum.html)
9617/// [REINDEX](https://www.postgresql.org/docs/current/sql-reindex.html)
9618///
9619/// For example, the `EXPLAIN` AND `VACUUM` statements with options might look like this:
9620/// ```sql
9621/// EXPLAIN (ANALYZE, VERBOSE TRUE, FORMAT TEXT) SELECT * FROM my_table;
9622///
9623/// VACUUM (VERBOSE, ANALYZE ON, PARALLEL 10) my_table;
9624/// ```
9625#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9626#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9627#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9628pub struct UtilityOption {
9629    pub name: Ident,
9630    pub arg: Option<Expr>,
9631}
9632
9633impl Display for UtilityOption {
9634    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
9635        if let Some(ref arg) = self.arg {
9636            write!(f, "{} {}", self.name, arg)
9637        } else {
9638            write!(f, "{}", self.name)
9639        }
9640    }
9641}
9642
9643/// Represents the different options available for `SHOW`
9644/// statements to filter the results. Example from Snowflake:
9645/// <https://docs.snowflake.com/en/sql-reference/sql/show-tables>
9646#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9647#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9648#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9649pub struct ShowStatementOptions {
9650    pub show_in: Option<ShowStatementIn>,
9651    pub starts_with: Option<Value>,
9652    pub limit: Option<Expr>,
9653    pub limit_from: Option<Value>,
9654    pub filter_position: Option<ShowStatementFilterPosition>,
9655}
9656
9657impl Display for ShowStatementOptions {
9658    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
9659        let (like_in_infix, like_in_suffix) = match &self.filter_position {
9660            Some(ShowStatementFilterPosition::Infix(filter)) => {
9661                (format!(" {filter}"), "".to_string())
9662            }
9663            Some(ShowStatementFilterPosition::Suffix(filter)) => {
9664                ("".to_string(), format!(" {filter}"))
9665            }
9666            None => ("".to_string(), "".to_string()),
9667        };
9668        write!(
9669            f,
9670            "{like_in_infix}{show_in}{starts_with}{limit}{from}{like_in_suffix}",
9671            show_in = match &self.show_in {
9672                Some(i) => format!(" {i}"),
9673                None => String::new(),
9674            },
9675            starts_with = match &self.starts_with {
9676                Some(s) => format!(" STARTS WITH {s}"),
9677                None => String::new(),
9678            },
9679            limit = match &self.limit {
9680                Some(l) => format!(" LIMIT {l}"),
9681                None => String::new(),
9682            },
9683            from = match &self.limit_from {
9684                Some(f) => format!(" FROM {f}"),
9685                None => String::new(),
9686            }
9687        )?;
9688        Ok(())
9689    }
9690}
9691
9692#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9693#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9694#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9695pub enum ShowStatementFilterPosition {
9696    Infix(ShowStatementFilter), // For example: SHOW COLUMNS LIKE '%name%' IN TABLE tbl
9697    Suffix(ShowStatementFilter), // For example: SHOW COLUMNS IN tbl LIKE '%name%'
9698}
9699
9700#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9701#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9702#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9703pub enum ShowStatementInParentType {
9704    Account,
9705    Database,
9706    Schema,
9707    Table,
9708    View,
9709}
9710
9711impl fmt::Display for ShowStatementInParentType {
9712    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9713        match self {
9714            ShowStatementInParentType::Account => write!(f, "ACCOUNT"),
9715            ShowStatementInParentType::Database => write!(f, "DATABASE"),
9716            ShowStatementInParentType::Schema => write!(f, "SCHEMA"),
9717            ShowStatementInParentType::Table => write!(f, "TABLE"),
9718            ShowStatementInParentType::View => write!(f, "VIEW"),
9719        }
9720    }
9721}
9722
9723#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9724#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9725#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9726pub struct ShowStatementIn {
9727    pub clause: ShowStatementInClause,
9728    pub parent_type: Option<ShowStatementInParentType>,
9729    #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
9730    pub parent_name: Option<ObjectName>,
9731}
9732
9733impl fmt::Display for ShowStatementIn {
9734    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9735        write!(f, "{}", self.clause)?;
9736        if let Some(parent_type) = &self.parent_type {
9737            write!(f, " {parent_type}")?;
9738        }
9739        if let Some(parent_name) = &self.parent_name {
9740            write!(f, " {parent_name}")?;
9741        }
9742        Ok(())
9743    }
9744}
9745
9746#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9747#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9748#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9749pub struct ShowObjects {
9750    pub terse: bool,
9751    pub show_options: ShowStatementOptions,
9752}
9753
9754/// MSSQL's json null clause
9755///
9756/// ```plaintext
9757/// <json_null_clause> ::=
9758///       NULL ON NULL
9759///     | ABSENT ON NULL
9760/// ```
9761///
9762/// <https://learn.microsoft.com/en-us/sql/t-sql/functions/json-object-transact-sql?view=sql-server-ver16#json_null_clause>
9763#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9764#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9765#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9766pub enum JsonNullClause {
9767    NullOnNull,
9768    AbsentOnNull,
9769}
9770
9771impl Display for JsonNullClause {
9772    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
9773        match self {
9774            JsonNullClause::NullOnNull => write!(f, "NULL ON NULL"),
9775            JsonNullClause::AbsentOnNull => write!(f, "ABSENT ON NULL"),
9776        }
9777    }
9778}
9779
9780/// rename object definition
9781#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9782#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9783#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9784pub struct RenameTable {
9785    pub old_name: ObjectName,
9786    pub new_name: ObjectName,
9787}
9788
9789impl fmt::Display for RenameTable {
9790    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9791        write!(f, "{} TO {}", self.old_name, self.new_name)?;
9792        Ok(())
9793    }
9794}
9795
9796/// Represents the referenced table in an `INSERT INTO` statement
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 TableObject {
9801    /// Table specified by name.
9802    /// Example:
9803    /// ```sql
9804    /// INSERT INTO my_table
9805    /// ```
9806    TableName(#[cfg_attr(feature = "visitor", visit(with = "visit_relation"))] ObjectName),
9807
9808    /// Table specified as a function.
9809    /// Example:
9810    /// ```sql
9811    /// INSERT INTO TABLE FUNCTION remote('localhost', default.simple_table)
9812    /// ```
9813    /// [Clickhouse](https://clickhouse.com/docs/en/sql-reference/table-functions)
9814    TableFunction(Function),
9815}
9816
9817impl fmt::Display for TableObject {
9818    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9819        match self {
9820            Self::TableName(table_name) => write!(f, "{table_name}"),
9821            Self::TableFunction(func) => write!(f, "FUNCTION {func}"),
9822        }
9823    }
9824}
9825
9826#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9827#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9828#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9829pub enum SetSessionParamKind {
9830    Generic(SetSessionParamGeneric),
9831    IdentityInsert(SetSessionParamIdentityInsert),
9832    Offsets(SetSessionParamOffsets),
9833    Statistics(SetSessionParamStatistics),
9834}
9835
9836impl fmt::Display for SetSessionParamKind {
9837    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9838        match self {
9839            SetSessionParamKind::Generic(x) => write!(f, "{x}"),
9840            SetSessionParamKind::IdentityInsert(x) => write!(f, "{x}"),
9841            SetSessionParamKind::Offsets(x) => write!(f, "{x}"),
9842            SetSessionParamKind::Statistics(x) => write!(f, "{x}"),
9843        }
9844    }
9845}
9846
9847#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9848#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9849#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9850pub struct SetSessionParamGeneric {
9851    pub names: Vec<String>,
9852    pub value: String,
9853}
9854
9855impl fmt::Display for SetSessionParamGeneric {
9856    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9857        write!(f, "{} {}", display_comma_separated(&self.names), self.value)
9858    }
9859}
9860
9861#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9862#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9863#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9864pub struct SetSessionParamIdentityInsert {
9865    pub obj: ObjectName,
9866    pub value: SessionParamValue,
9867}
9868
9869impl fmt::Display for SetSessionParamIdentityInsert {
9870    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9871        write!(f, "IDENTITY_INSERT {} {}", self.obj, self.value)
9872    }
9873}
9874
9875#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9876#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9877#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9878pub struct SetSessionParamOffsets {
9879    pub keywords: Vec<String>,
9880    pub value: SessionParamValue,
9881}
9882
9883impl fmt::Display for SetSessionParamOffsets {
9884    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9885        write!(
9886            f,
9887            "OFFSETS {} {}",
9888            display_comma_separated(&self.keywords),
9889            self.value
9890        )
9891    }
9892}
9893
9894#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9895#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9896#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9897pub struct SetSessionParamStatistics {
9898    pub topic: SessionParamStatsTopic,
9899    pub value: SessionParamValue,
9900}
9901
9902impl fmt::Display for SetSessionParamStatistics {
9903    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9904        write!(f, "STATISTICS {} {}", self.topic, self.value)
9905    }
9906}
9907
9908#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9909#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9910#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9911pub enum SessionParamStatsTopic {
9912    IO,
9913    Profile,
9914    Time,
9915    Xml,
9916}
9917
9918impl fmt::Display for SessionParamStatsTopic {
9919    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9920        match self {
9921            SessionParamStatsTopic::IO => write!(f, "IO"),
9922            SessionParamStatsTopic::Profile => write!(f, "PROFILE"),
9923            SessionParamStatsTopic::Time => write!(f, "TIME"),
9924            SessionParamStatsTopic::Xml => write!(f, "XML"),
9925        }
9926    }
9927}
9928
9929#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9930#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9931#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9932pub enum SessionParamValue {
9933    On,
9934    Off,
9935}
9936
9937impl fmt::Display for SessionParamValue {
9938    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9939        match self {
9940            SessionParamValue::On => write!(f, "ON"),
9941            SessionParamValue::Off => write!(f, "OFF"),
9942        }
9943    }
9944}
9945
9946/// Snowflake StorageSerializationPolicy for Iceberg Tables
9947/// ```sql
9948/// [ STORAGE_SERIALIZATION_POLICY = { COMPATIBLE | OPTIMIZED } ]
9949/// ```
9950///
9951/// <https://docs.snowflake.com/en/sql-reference/sql/create-iceberg-table>
9952#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9953#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9954#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9955pub enum StorageSerializationPolicy {
9956    Compatible,
9957    Optimized,
9958}
9959
9960impl Display for StorageSerializationPolicy {
9961    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
9962        match self {
9963            StorageSerializationPolicy::Compatible => write!(f, "COMPATIBLE"),
9964            StorageSerializationPolicy::Optimized => write!(f, "OPTIMIZED"),
9965        }
9966    }
9967}
9968
9969/// Variants of the Snowflake `COPY INTO` statement
9970#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9971#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9972#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9973pub enum CopyIntoSnowflakeKind {
9974    /// Loads data from files to a table
9975    /// See: <https://docs.snowflake.com/en/sql-reference/sql/copy-into-table>
9976    Table,
9977    /// Unloads data from a table or query to external files
9978    /// See: <https://docs.snowflake.com/en/sql-reference/sql/copy-into-location>
9979    Location,
9980}
9981
9982#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9983#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9984#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9985pub struct PrintStatement {
9986    pub message: Box<Expr>,
9987}
9988
9989impl fmt::Display for PrintStatement {
9990    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9991        write!(f, "PRINT {}", self.message)
9992    }
9993}
9994
9995/// Represents a `Return` statement.
9996///
9997/// [MsSql triggers](https://learn.microsoft.com/en-us/sql/t-sql/statements/create-trigger-transact-sql)
9998/// [MsSql functions](https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql)
9999#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10000#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10001#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10002pub struct ReturnStatement {
10003    pub value: Option<ReturnStatementValue>,
10004}
10005
10006impl fmt::Display for ReturnStatement {
10007    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10008        match &self.value {
10009            Some(ReturnStatementValue::Expr(expr)) => write!(f, "RETURN {expr}"),
10010            None => write!(f, "RETURN"),
10011        }
10012    }
10013}
10014
10015/// Variants of a `RETURN` statement
10016#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10017#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10018#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10019pub enum ReturnStatementValue {
10020    Expr(Expr),
10021}
10022
10023/// Represents an `OPEN` statement.
10024#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10025#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10026#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10027pub struct OpenStatement {
10028    /// Cursor name
10029    pub cursor_name: Ident,
10030}
10031
10032impl fmt::Display for OpenStatement {
10033    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10034        write!(f, "OPEN {}", self.cursor_name)
10035    }
10036}
10037
10038/// Specifies Include / Exclude NULL within UNPIVOT command.
10039/// For example
10040/// `UNPIVOT (column1 FOR new_column IN (col3, col4, col5, col6))`
10041#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10042#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10043#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10044pub enum NullInclusion {
10045    IncludeNulls,
10046    ExcludeNulls,
10047}
10048
10049impl fmt::Display for NullInclusion {
10050    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10051        match self {
10052            NullInclusion::IncludeNulls => write!(f, "INCLUDE NULLS"),
10053            NullInclusion::ExcludeNulls => write!(f, "EXCLUDE NULLS"),
10054        }
10055    }
10056}
10057
10058/// Checks membership of a value in a JSON array
10059///
10060/// Syntax:
10061/// ```sql
10062/// <value> MEMBER OF(<array>)
10063/// ```
10064/// [MySQL](https://dev.mysql.com/doc/refman/8.4/en/json-search-functions.html#operator_member-of)
10065#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10066#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10067#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10068pub struct MemberOf {
10069    pub value: Box<Expr>,
10070    pub array: Box<Expr>,
10071}
10072
10073impl fmt::Display for MemberOf {
10074    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10075        write!(f, "{} MEMBER OF({})", self.value, self.array)
10076    }
10077}
10078
10079#[cfg(test)]
10080mod tests {
10081    use crate::tokenizer::Location;
10082
10083    use super::*;
10084
10085    #[test]
10086    fn test_window_frame_default() {
10087        let window_frame = WindowFrame::default();
10088        assert_eq!(WindowFrameBound::Preceding(None), window_frame.start_bound);
10089    }
10090
10091    #[test]
10092    fn test_grouping_sets_display() {
10093        // a and b in different group
10094        let grouping_sets = Expr::GroupingSets(vec![
10095            vec![Expr::Identifier(Ident::new("a"))],
10096            vec![Expr::Identifier(Ident::new("b"))],
10097        ]);
10098        assert_eq!("GROUPING SETS ((a), (b))", format!("{grouping_sets}"));
10099
10100        // a and b in the same group
10101        let grouping_sets = Expr::GroupingSets(vec![vec![
10102            Expr::Identifier(Ident::new("a")),
10103            Expr::Identifier(Ident::new("b")),
10104        ]]);
10105        assert_eq!("GROUPING SETS ((a, b))", format!("{grouping_sets}"));
10106
10107        // (a, b) and (c, d) in different group
10108        let grouping_sets = Expr::GroupingSets(vec![
10109            vec![
10110                Expr::Identifier(Ident::new("a")),
10111                Expr::Identifier(Ident::new("b")),
10112            ],
10113            vec![
10114                Expr::Identifier(Ident::new("c")),
10115                Expr::Identifier(Ident::new("d")),
10116            ],
10117        ]);
10118        assert_eq!("GROUPING SETS ((a, b), (c, d))", format!("{grouping_sets}"));
10119    }
10120
10121    #[test]
10122    fn test_rollup_display() {
10123        let rollup = Expr::Rollup(vec![vec![Expr::Identifier(Ident::new("a"))]]);
10124        assert_eq!("ROLLUP (a)", format!("{rollup}"));
10125
10126        let rollup = Expr::Rollup(vec![vec![
10127            Expr::Identifier(Ident::new("a")),
10128            Expr::Identifier(Ident::new("b")),
10129        ]]);
10130        assert_eq!("ROLLUP ((a, b))", format!("{rollup}"));
10131
10132        let rollup = Expr::Rollup(vec![
10133            vec![Expr::Identifier(Ident::new("a"))],
10134            vec![Expr::Identifier(Ident::new("b"))],
10135        ]);
10136        assert_eq!("ROLLUP (a, b)", format!("{rollup}"));
10137
10138        let rollup = Expr::Rollup(vec![
10139            vec![Expr::Identifier(Ident::new("a"))],
10140            vec![
10141                Expr::Identifier(Ident::new("b")),
10142                Expr::Identifier(Ident::new("c")),
10143            ],
10144            vec![Expr::Identifier(Ident::new("d"))],
10145        ]);
10146        assert_eq!("ROLLUP (a, (b, c), d)", format!("{rollup}"));
10147    }
10148
10149    #[test]
10150    fn test_cube_display() {
10151        let cube = Expr::Cube(vec![vec![Expr::Identifier(Ident::new("a"))]]);
10152        assert_eq!("CUBE (a)", format!("{cube}"));
10153
10154        let cube = Expr::Cube(vec![vec![
10155            Expr::Identifier(Ident::new("a")),
10156            Expr::Identifier(Ident::new("b")),
10157        ]]);
10158        assert_eq!("CUBE ((a, b))", format!("{cube}"));
10159
10160        let cube = Expr::Cube(vec![
10161            vec![Expr::Identifier(Ident::new("a"))],
10162            vec![Expr::Identifier(Ident::new("b"))],
10163        ]);
10164        assert_eq!("CUBE (a, b)", format!("{cube}"));
10165
10166        let cube = Expr::Cube(vec![
10167            vec![Expr::Identifier(Ident::new("a"))],
10168            vec![
10169                Expr::Identifier(Ident::new("b")),
10170                Expr::Identifier(Ident::new("c")),
10171            ],
10172            vec![Expr::Identifier(Ident::new("d"))],
10173        ]);
10174        assert_eq!("CUBE (a, (b, c), d)", format!("{cube}"));
10175    }
10176
10177    #[test]
10178    fn test_interval_display() {
10179        let interval = Expr::Interval(Interval {
10180            value: Box::new(Expr::Value(
10181                Value::SingleQuotedString(String::from("123:45.67")).with_empty_span(),
10182            )),
10183            leading_field: Some(DateTimeField::Minute),
10184            leading_precision: Some(10),
10185            last_field: Some(DateTimeField::Second),
10186            fractional_seconds_precision: Some(9),
10187        });
10188        assert_eq!(
10189            "INTERVAL '123:45.67' MINUTE (10) TO SECOND (9)",
10190            format!("{interval}"),
10191        );
10192
10193        let interval = Expr::Interval(Interval {
10194            value: Box::new(Expr::Value(
10195                Value::SingleQuotedString(String::from("5")).with_empty_span(),
10196            )),
10197            leading_field: Some(DateTimeField::Second),
10198            leading_precision: Some(1),
10199            last_field: None,
10200            fractional_seconds_precision: Some(3),
10201        });
10202        assert_eq!("INTERVAL '5' SECOND (1, 3)", format!("{interval}"));
10203    }
10204
10205    #[test]
10206    fn test_one_or_many_with_parens_deref() {
10207        use core::ops::Index;
10208
10209        let one = OneOrManyWithParens::One("a");
10210
10211        assert_eq!(one.deref(), &["a"]);
10212        assert_eq!(<OneOrManyWithParens<_> as Deref>::deref(&one), &["a"]);
10213
10214        assert_eq!(one[0], "a");
10215        assert_eq!(one.index(0), &"a");
10216        assert_eq!(
10217            <<OneOrManyWithParens<_> as Deref>::Target as Index<usize>>::index(&one, 0),
10218            &"a"
10219        );
10220
10221        assert_eq!(one.len(), 1);
10222        assert_eq!(<OneOrManyWithParens<_> as Deref>::Target::len(&one), 1);
10223
10224        let many1 = OneOrManyWithParens::Many(vec!["b"]);
10225
10226        assert_eq!(many1.deref(), &["b"]);
10227        assert_eq!(<OneOrManyWithParens<_> as Deref>::deref(&many1), &["b"]);
10228
10229        assert_eq!(many1[0], "b");
10230        assert_eq!(many1.index(0), &"b");
10231        assert_eq!(
10232            <<OneOrManyWithParens<_> as Deref>::Target as Index<usize>>::index(&many1, 0),
10233            &"b"
10234        );
10235
10236        assert_eq!(many1.len(), 1);
10237        assert_eq!(<OneOrManyWithParens<_> as Deref>::Target::len(&many1), 1);
10238
10239        let many2 = OneOrManyWithParens::Many(vec!["c", "d"]);
10240
10241        assert_eq!(many2.deref(), &["c", "d"]);
10242        assert_eq!(
10243            <OneOrManyWithParens<_> as Deref>::deref(&many2),
10244            &["c", "d"]
10245        );
10246
10247        assert_eq!(many2[0], "c");
10248        assert_eq!(many2.index(0), &"c");
10249        assert_eq!(
10250            <<OneOrManyWithParens<_> as Deref>::Target as Index<usize>>::index(&many2, 0),
10251            &"c"
10252        );
10253
10254        assert_eq!(many2[1], "d");
10255        assert_eq!(many2.index(1), &"d");
10256        assert_eq!(
10257            <<OneOrManyWithParens<_> as Deref>::Target as Index<usize>>::index(&many2, 1),
10258            &"d"
10259        );
10260
10261        assert_eq!(many2.len(), 2);
10262        assert_eq!(<OneOrManyWithParens<_> as Deref>::Target::len(&many2), 2);
10263    }
10264
10265    #[test]
10266    fn test_one_or_many_with_parens_as_ref() {
10267        let one = OneOrManyWithParens::One("a");
10268
10269        assert_eq!(one.as_ref(), &["a"]);
10270        assert_eq!(<OneOrManyWithParens<_> as AsRef<_>>::as_ref(&one), &["a"]);
10271
10272        let many1 = OneOrManyWithParens::Many(vec!["b"]);
10273
10274        assert_eq!(many1.as_ref(), &["b"]);
10275        assert_eq!(<OneOrManyWithParens<_> as AsRef<_>>::as_ref(&many1), &["b"]);
10276
10277        let many2 = OneOrManyWithParens::Many(vec!["c", "d"]);
10278
10279        assert_eq!(many2.as_ref(), &["c", "d"]);
10280        assert_eq!(
10281            <OneOrManyWithParens<_> as AsRef<_>>::as_ref(&many2),
10282            &["c", "d"]
10283        );
10284    }
10285
10286    #[test]
10287    fn test_one_or_many_with_parens_ref_into_iter() {
10288        let one = OneOrManyWithParens::One("a");
10289
10290        assert_eq!(Vec::from_iter(&one), vec![&"a"]);
10291
10292        let many1 = OneOrManyWithParens::Many(vec!["b"]);
10293
10294        assert_eq!(Vec::from_iter(&many1), vec![&"b"]);
10295
10296        let many2 = OneOrManyWithParens::Many(vec!["c", "d"]);
10297
10298        assert_eq!(Vec::from_iter(&many2), vec![&"c", &"d"]);
10299    }
10300
10301    #[test]
10302    fn test_one_or_many_with_parens_value_into_iter() {
10303        use core::iter::once;
10304
10305        //tests that our iterator implemented methods behaves exactly as it's inner iterator, at every step up to n calls to next/next_back
10306        fn test_steps<I>(ours: OneOrManyWithParens<usize>, inner: I, n: usize)
10307        where
10308            I: IntoIterator<Item = usize, IntoIter: DoubleEndedIterator + Clone> + Clone,
10309        {
10310            fn checks<I>(ours: OneOrManyWithParensIntoIter<usize>, inner: I)
10311            where
10312                I: Iterator<Item = usize> + Clone + DoubleEndedIterator,
10313            {
10314                assert_eq!(ours.size_hint(), inner.size_hint());
10315                assert_eq!(ours.clone().count(), inner.clone().count());
10316
10317                assert_eq!(
10318                    ours.clone().fold(1, |a, v| a + v),
10319                    inner.clone().fold(1, |a, v| a + v)
10320                );
10321
10322                assert_eq!(Vec::from_iter(ours.clone()), Vec::from_iter(inner.clone()));
10323                assert_eq!(
10324                    Vec::from_iter(ours.clone().rev()),
10325                    Vec::from_iter(inner.clone().rev())
10326                );
10327            }
10328
10329            let mut ours_next = ours.clone().into_iter();
10330            let mut inner_next = inner.clone().into_iter();
10331
10332            for _ in 0..n {
10333                checks(ours_next.clone(), inner_next.clone());
10334
10335                assert_eq!(ours_next.next(), inner_next.next());
10336            }
10337
10338            let mut ours_next_back = ours.clone().into_iter();
10339            let mut inner_next_back = inner.clone().into_iter();
10340
10341            for _ in 0..n {
10342                checks(ours_next_back.clone(), inner_next_back.clone());
10343
10344                assert_eq!(ours_next_back.next_back(), inner_next_back.next_back());
10345            }
10346
10347            let mut ours_mixed = ours.clone().into_iter();
10348            let mut inner_mixed = inner.clone().into_iter();
10349
10350            for i in 0..n {
10351                checks(ours_mixed.clone(), inner_mixed.clone());
10352
10353                if i % 2 == 0 {
10354                    assert_eq!(ours_mixed.next_back(), inner_mixed.next_back());
10355                } else {
10356                    assert_eq!(ours_mixed.next(), inner_mixed.next());
10357                }
10358            }
10359
10360            let mut ours_mixed2 = ours.into_iter();
10361            let mut inner_mixed2 = inner.into_iter();
10362
10363            for i in 0..n {
10364                checks(ours_mixed2.clone(), inner_mixed2.clone());
10365
10366                if i % 2 == 0 {
10367                    assert_eq!(ours_mixed2.next(), inner_mixed2.next());
10368                } else {
10369                    assert_eq!(ours_mixed2.next_back(), inner_mixed2.next_back());
10370                }
10371            }
10372        }
10373
10374        test_steps(OneOrManyWithParens::One(1), once(1), 3);
10375        test_steps(OneOrManyWithParens::Many(vec![2]), vec![2], 3);
10376        test_steps(OneOrManyWithParens::Many(vec![3, 4]), vec![3, 4], 4);
10377    }
10378
10379    // Tests that the position in the code of an `Ident` does not affect its
10380    // ordering.
10381    #[test]
10382    fn test_ident_ord() {
10383        let mut a = Ident::with_span(Span::new(Location::new(1, 1), Location::new(1, 1)), "a");
10384        let mut b = Ident::with_span(Span::new(Location::new(2, 2), Location::new(2, 2)), "b");
10385
10386        assert!(a < b);
10387        std::mem::swap(&mut a.span, &mut b.span);
10388        assert!(a < b);
10389    }
10390}