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