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