sqlparser/ast/
mod.rs

1// Licensed to the Apache Software Foundation (ASF) under one
2// or more contributor license agreements.  See the NOTICE file
3// distributed with this work for additional information
4// regarding copyright ownership.  The ASF licenses this file
5// to you under the Apache License, Version 2.0 (the
6// "License"); you may not use this file except in compliance
7// with the License.  You may obtain a copy of the License at
8//
9//   http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing,
12// software distributed under the License is distributed on an
13// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14// KIND, either express or implied.  See the License for the
15// specific language governing permissions and limitations
16// under the License.
17
18//! SQL Abstract Syntax Tree (AST) types
19#[cfg(not(feature = "std"))]
20use alloc::{
21    boxed::Box,
22    format,
23    string::{String, ToString},
24    vec::Vec,
25};
26use helpers::{
27    attached_token::AttachedToken,
28    stmt_data_loading::{FileStagingCommand, StageLoadSelectItemKind},
29};
30
31use core::ops::Deref;
32use core::{
33    fmt::{self, Display},
34    hash,
35};
36
37#[cfg(feature = "serde")]
38use serde::{Deserialize, Serialize};
39
40#[cfg(feature = "visitor")]
41use sqlparser_derive::{Visit, VisitMut};
42
43use crate::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, CreateFunction, Deduplicate, DeferrableInitial,
59    DropBehavior, GeneratedAs, GeneratedExpressionMode, IdentityParameters, IdentityProperty,
60    IdentityPropertyFormatKind, IdentityPropertyKind, IdentityPropertyOrder, IndexOption,
61    IndexType, KeyOrIndexDisplay, NullsDistinctOption, Owner, Partition, ProcedureParam,
62    ReferentialAction, TableConstraint, TagsColumnOption, UserDefinedTypeCompositeAttributeDef,
63    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, Fetch, ForClause, ForJson, ForXml,
70    FormatClause, GroupByExpr, GroupByWithModifier, IdentWithAlias, IlikeSelectItem,
71    InputFormatClause, Interpolate, InterpolateExpr, Join, JoinConstraint, JoinOperator,
72    JsonTableColumn, JsonTableColumnErrorHandling, JsonTableNamedColumn, JsonTableNestedColumn,
73    LateralView, LimitClause, LockClause, LockType, MatchRecognizePattern, MatchRecognizeSymbol,
74    Measure, NamedWindowDefinition, NamedWindowExpr, NonBlock, Offset, OffsetRows,
75    OpenJsonTableColumn, OrderBy, OrderByExpr, OrderByKind, OrderByOptions, PivotValueSource,
76    ProjectionSelect, Query, RenameSelectItem, RepetitionQuantifier, ReplaceSelectElement,
77    ReplaceSelectItem, RowsPerMatch, Select, SelectFlavor, SelectInto, SelectItem,
78    SelectItemQualifiedWildcardKind, SetExpr, SetOperator, SetQuantifier, Setting,
79    SymbolDefinition, Table, TableAlias, TableAliasColumnDef, TableFactor, TableFunctionArgs,
80    TableIndexHintForClause, TableIndexHintType, TableIndexHints, TableIndexType, TableSample,
81    TableSampleBucket, TableSampleKind, TableSampleMethod, TableSampleModifier,
82    TableSampleQuantity, TableSampleSeed, TableSampleSeedModifier, TableSampleUnit, TableVersion,
83    TableWithJoins, Top, TopQuantity, UpdateTableFromKind, ValueTableMode, Values,
84    WildcardAdditionalOptions, With, WithFill, XmlNamespaceDefinition, XmlPassingArgument,
85    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<SetExpr>,
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 sqlparser::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 sqlparser::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 block within a [Statement::Case] or [Statement::If]-like statement
2232///
2233/// Example 1:
2234/// ```sql
2235/// WHEN EXISTS(SELECT 1) THEN SELECT 1;
2236/// ```
2237///
2238/// Example 2:
2239/// ```sql
2240/// IF TRUE THEN SELECT 1; SELECT 2;
2241/// ```
2242///
2243/// Example 3:
2244/// ```sql
2245/// ELSE SELECT 1; SELECT 2;
2246/// ```
2247#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2248#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2249#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2250pub struct ConditionalStatementBlock {
2251    pub start_token: AttachedToken,
2252    pub condition: Option<Expr>,
2253    pub then_token: Option<AttachedToken>,
2254    pub conditional_statements: ConditionalStatements,
2255}
2256
2257impl ConditionalStatementBlock {
2258    pub fn statements(&self) -> &Vec<Statement> {
2259        self.conditional_statements.statements()
2260    }
2261}
2262
2263impl fmt::Display for ConditionalStatementBlock {
2264    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2265        let ConditionalStatementBlock {
2266            start_token: AttachedToken(start_token),
2267            condition,
2268            then_token,
2269            conditional_statements,
2270        } = self;
2271
2272        write!(f, "{start_token}")?;
2273
2274        if let Some(condition) = condition {
2275            write!(f, " {condition}")?;
2276        }
2277
2278        if then_token.is_some() {
2279            write!(f, " THEN")?;
2280        }
2281
2282        if !conditional_statements.statements().is_empty() {
2283            write!(f, " {conditional_statements}")?;
2284        }
2285
2286        Ok(())
2287    }
2288}
2289
2290/// A list of statements in a [ConditionalStatementBlock].
2291#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2292#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2293#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2294pub enum ConditionalStatements {
2295    /// SELECT 1; SELECT 2; SELECT 3; ...
2296    Sequence { statements: Vec<Statement> },
2297    /// BEGIN SELECT 1; SELECT 2; SELECT 3; ... END
2298    BeginEnd(BeginEndStatements),
2299}
2300
2301impl ConditionalStatements {
2302    pub fn statements(&self) -> &Vec<Statement> {
2303        match self {
2304            ConditionalStatements::Sequence { statements } => statements,
2305            ConditionalStatements::BeginEnd(bes) => &bes.statements,
2306        }
2307    }
2308}
2309
2310impl fmt::Display for ConditionalStatements {
2311    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2312        match self {
2313            ConditionalStatements::Sequence { statements } => {
2314                if !statements.is_empty() {
2315                    format_statement_list(f, statements)?;
2316                }
2317                Ok(())
2318            }
2319            ConditionalStatements::BeginEnd(bes) => write!(f, "{}", bes),
2320        }
2321    }
2322}
2323
2324/// Represents a list of statements enclosed within `BEGIN` and `END` keywords.
2325/// Example:
2326/// ```sql
2327/// BEGIN
2328///     SELECT 1;
2329///     SELECT 2;
2330/// END
2331/// ```
2332#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2333#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2334#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2335pub struct BeginEndStatements {
2336    pub begin_token: AttachedToken,
2337    pub statements: Vec<Statement>,
2338    pub end_token: AttachedToken,
2339}
2340
2341impl fmt::Display for BeginEndStatements {
2342    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2343        let BeginEndStatements {
2344            begin_token: AttachedToken(begin_token),
2345            statements,
2346            end_token: AttachedToken(end_token),
2347        } = self;
2348
2349        write!(f, "{begin_token} ")?;
2350        if !statements.is_empty() {
2351            format_statement_list(f, statements)?;
2352        }
2353        write!(f, " {end_token}")
2354    }
2355}
2356
2357/// A `RAISE` statement.
2358///
2359/// Examples:
2360/// ```sql
2361/// RAISE USING MESSAGE = 'error';
2362///
2363/// RAISE myerror;
2364/// ```
2365///
2366/// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#raise)
2367/// [Snowflake](https://docs.snowflake.com/en/sql-reference/snowflake-scripting/raise)
2368#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2369#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2370#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2371pub struct RaiseStatement {
2372    pub value: Option<RaiseStatementValue>,
2373}
2374
2375impl fmt::Display for RaiseStatement {
2376    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2377        let RaiseStatement { value } = self;
2378
2379        write!(f, "RAISE")?;
2380        if let Some(value) = value {
2381            write!(f, " {value}")?;
2382        }
2383
2384        Ok(())
2385    }
2386}
2387
2388/// Represents the error value of a [RaiseStatement].
2389#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2390#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2391#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2392pub enum RaiseStatementValue {
2393    /// `RAISE USING MESSAGE = 'error'`
2394    UsingMessage(Expr),
2395    /// `RAISE myerror`
2396    Expr(Expr),
2397}
2398
2399impl fmt::Display for RaiseStatementValue {
2400    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2401        match self {
2402            RaiseStatementValue::Expr(expr) => write!(f, "{expr}"),
2403            RaiseStatementValue::UsingMessage(expr) => write!(f, "USING MESSAGE = {expr}"),
2404        }
2405    }
2406}
2407
2408/// Represents an expression assignment within a variable `DECLARE` statement.
2409///
2410/// Examples:
2411/// ```sql
2412/// DECLARE variable_name := 42
2413/// DECLARE variable_name DEFAULT 42
2414/// ```
2415#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2416#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2417#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2418pub enum DeclareAssignment {
2419    /// Plain expression specified.
2420    Expr(Box<Expr>),
2421
2422    /// Expression assigned via the `DEFAULT` keyword
2423    Default(Box<Expr>),
2424
2425    /// Expression assigned via the `:=` syntax
2426    ///
2427    /// Example:
2428    /// ```sql
2429    /// DECLARE variable_name := 42;
2430    /// ```
2431    DuckAssignment(Box<Expr>),
2432
2433    /// Expression via the `FOR` keyword
2434    ///
2435    /// Example:
2436    /// ```sql
2437    /// DECLARE c1 CURSOR FOR res
2438    /// ```
2439    For(Box<Expr>),
2440
2441    /// Expression via the `=` syntax.
2442    ///
2443    /// Example:
2444    /// ```sql
2445    /// DECLARE @variable AS INT = 100
2446    /// ```
2447    MsSqlAssignment(Box<Expr>),
2448}
2449
2450impl fmt::Display for DeclareAssignment {
2451    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2452        match self {
2453            DeclareAssignment::Expr(expr) => {
2454                write!(f, "{expr}")
2455            }
2456            DeclareAssignment::Default(expr) => {
2457                write!(f, "DEFAULT {expr}")
2458            }
2459            DeclareAssignment::DuckAssignment(expr) => {
2460                write!(f, ":= {expr}")
2461            }
2462            DeclareAssignment::MsSqlAssignment(expr) => {
2463                write!(f, "= {expr}")
2464            }
2465            DeclareAssignment::For(expr) => {
2466                write!(f, "FOR {expr}")
2467            }
2468        }
2469    }
2470}
2471
2472/// Represents the type of a `DECLARE` statement.
2473#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2474#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2475#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2476pub enum DeclareType {
2477    /// Cursor variable type. e.g. [Snowflake] [PostgreSQL] [MsSql]
2478    ///
2479    /// [Snowflake]: https://docs.snowflake.com/en/developer-guide/snowflake-scripting/cursors#declaring-a-cursor
2480    /// [PostgreSQL]: https://www.postgresql.org/docs/current/plpgsql-cursors.html
2481    /// [MsSql]: https://learn.microsoft.com/en-us/sql/t-sql/language-elements/declare-cursor-transact-sql
2482    Cursor,
2483
2484    /// Result set variable type. [Snowflake]
2485    ///
2486    /// Syntax:
2487    /// ```text
2488    /// <resultset_name> RESULTSET [ { DEFAULT | := } ( <query> ) ] ;
2489    /// ```
2490    /// [Snowflake]: https://docs.snowflake.com/en/sql-reference/snowflake-scripting/declare#resultset-declaration-syntax
2491    ResultSet,
2492
2493    /// Exception declaration syntax. [Snowflake]
2494    ///
2495    /// Syntax:
2496    /// ```text
2497    /// <exception_name> EXCEPTION [ ( <exception_number> , '<exception_message>' ) ] ;
2498    /// ```
2499    /// [Snowflake]: https://docs.snowflake.com/en/sql-reference/snowflake-scripting/declare#exception-declaration-syntax
2500    Exception,
2501}
2502
2503impl fmt::Display for DeclareType {
2504    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2505        match self {
2506            DeclareType::Cursor => {
2507                write!(f, "CURSOR")
2508            }
2509            DeclareType::ResultSet => {
2510                write!(f, "RESULTSET")
2511            }
2512            DeclareType::Exception => {
2513                write!(f, "EXCEPTION")
2514            }
2515        }
2516    }
2517}
2518
2519/// A `DECLARE` statement.
2520/// [PostgreSQL] [Snowflake] [BigQuery]
2521///
2522/// Examples:
2523/// ```sql
2524/// DECLARE variable_name := 42
2525/// DECLARE liahona CURSOR FOR SELECT * FROM films;
2526/// ```
2527///
2528/// [PostgreSQL]: https://www.postgresql.org/docs/current/sql-declare.html
2529/// [Snowflake]: https://docs.snowflake.com/en/sql-reference/snowflake-scripting/declare
2530/// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#declare
2531#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2532#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2533#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2534pub struct Declare {
2535    /// The name(s) being declared.
2536    /// Example: `DECLARE a, b, c DEFAULT 42;
2537    pub names: Vec<Ident>,
2538    /// Data-type assigned to the declared variable.
2539    /// Example: `DECLARE x INT64 DEFAULT 42;
2540    pub data_type: Option<DataType>,
2541    /// Expression being assigned to the declared variable.
2542    pub assignment: Option<DeclareAssignment>,
2543    /// Represents the type of the declared variable.
2544    pub declare_type: Option<DeclareType>,
2545    /// Causes the cursor to return data in binary rather than in text format.
2546    pub binary: Option<bool>,
2547    /// None = Not specified
2548    /// Some(true) = INSENSITIVE
2549    /// Some(false) = ASENSITIVE
2550    pub sensitive: Option<bool>,
2551    /// None = Not specified
2552    /// Some(true) = SCROLL
2553    /// Some(false) = NO SCROLL
2554    pub scroll: Option<bool>,
2555    /// None = Not specified
2556    /// Some(true) = WITH HOLD, specifies that the cursor can continue to be used after the transaction that created it successfully commits
2557    /// Some(false) = WITHOUT HOLD, specifies that the cursor cannot be used outside of the transaction that created it
2558    pub hold: Option<bool>,
2559    /// `FOR <query>` clause in a CURSOR declaration.
2560    pub for_query: Option<Box<Query>>,
2561}
2562
2563impl fmt::Display for Declare {
2564    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2565        let Declare {
2566            names,
2567            data_type,
2568            assignment,
2569            declare_type,
2570            binary,
2571            sensitive,
2572            scroll,
2573            hold,
2574            for_query,
2575        } = self;
2576        write!(f, "{}", display_comma_separated(names))?;
2577
2578        if let Some(true) = binary {
2579            write!(f, " BINARY")?;
2580        }
2581
2582        if let Some(sensitive) = sensitive {
2583            if *sensitive {
2584                write!(f, " INSENSITIVE")?;
2585            } else {
2586                write!(f, " ASENSITIVE")?;
2587            }
2588        }
2589
2590        if let Some(scroll) = scroll {
2591            if *scroll {
2592                write!(f, " SCROLL")?;
2593            } else {
2594                write!(f, " NO SCROLL")?;
2595            }
2596        }
2597
2598        if let Some(declare_type) = declare_type {
2599            write!(f, " {declare_type}")?;
2600        }
2601
2602        if let Some(hold) = hold {
2603            if *hold {
2604                write!(f, " WITH HOLD")?;
2605            } else {
2606                write!(f, " WITHOUT HOLD")?;
2607            }
2608        }
2609
2610        if let Some(query) = for_query {
2611            write!(f, " FOR {query}")?;
2612        }
2613
2614        if let Some(data_type) = data_type {
2615            write!(f, " {data_type}")?;
2616        }
2617
2618        if let Some(expr) = assignment {
2619            write!(f, " {expr}")?;
2620        }
2621        Ok(())
2622    }
2623}
2624
2625/// Sql options of a `CREATE TABLE` statement.
2626#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2627#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2628#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2629pub enum CreateTableOptions {
2630    None,
2631    /// Options specified using the `WITH` keyword.
2632    /// e.g. `WITH (description = "123")`
2633    ///
2634    /// <https://www.postgresql.org/docs/current/sql-createtable.html>
2635    ///
2636    /// MSSQL supports more specific options that's not only key-value pairs.
2637    ///
2638    /// WITH (
2639    ///     DISTRIBUTION = ROUND_ROBIN,
2640    ///     CLUSTERED INDEX (column_a DESC, column_b)
2641    /// )
2642    ///
2643    /// <https://learn.microsoft.com/en-us/sql/t-sql/statements/create-table-azure-sql-data-warehouse?view=aps-pdw-2016-au7#syntax>
2644    With(Vec<SqlOption>),
2645    /// Options specified using the `OPTIONS` keyword.
2646    /// e.g. `OPTIONS(description = "123")`
2647    ///
2648    /// <https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#table_option_list>
2649    Options(Vec<SqlOption>),
2650}
2651
2652impl fmt::Display for CreateTableOptions {
2653    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2654        match self {
2655            CreateTableOptions::With(with_options) => {
2656                write!(f, "WITH ({})", display_comma_separated(with_options))
2657            }
2658            CreateTableOptions::Options(options) => {
2659                write!(f, "OPTIONS({})", display_comma_separated(options))
2660            }
2661            CreateTableOptions::None => Ok(()),
2662        }
2663    }
2664}
2665
2666/// A `FROM` clause within a `DELETE` statement.
2667///
2668/// Syntax
2669/// ```sql
2670/// [FROM] table
2671/// ```
2672#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2673#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2674#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2675pub enum FromTable {
2676    /// An explicit `FROM` keyword was specified.
2677    WithFromKeyword(Vec<TableWithJoins>),
2678    /// BigQuery: `FROM` keyword was omitted.
2679    /// <https://cloud.google.com/bigquery/docs/reference/standard-sql/dml-syntax#delete_statement>
2680    WithoutKeyword(Vec<TableWithJoins>),
2681}
2682impl Display for FromTable {
2683    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2684        match self {
2685            FromTable::WithFromKeyword(tables) => {
2686                write!(f, "FROM {}", display_comma_separated(tables))
2687            }
2688            FromTable::WithoutKeyword(tables) => {
2689                write!(f, "{}", display_comma_separated(tables))
2690            }
2691        }
2692    }
2693}
2694
2695/// Policy type for a `CREATE POLICY` statement.
2696/// ```sql
2697/// AS [ PERMISSIVE | RESTRICTIVE ]
2698/// ```
2699/// [PostgreSQL](https://www.postgresql.org/docs/current/sql-createpolicy.html)
2700#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2701#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2702#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2703pub enum CreatePolicyType {
2704    Permissive,
2705    Restrictive,
2706}
2707
2708/// Policy command for a `CREATE POLICY` statement.
2709/// ```sql
2710/// FOR [ALL | SELECT | INSERT | UPDATE | DELETE]
2711/// ```
2712/// [PostgreSQL](https://www.postgresql.org/docs/current/sql-createpolicy.html)
2713#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2714#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2715#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2716pub enum CreatePolicyCommand {
2717    All,
2718    Select,
2719    Insert,
2720    Update,
2721    Delete,
2722}
2723
2724#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2725#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2726#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2727pub enum Set {
2728    /// SQL Standard-style
2729    /// SET a = 1;
2730    SingleAssignment {
2731        scope: Option<ContextModifier>,
2732        hivevar: bool,
2733        variable: ObjectName,
2734        values: Vec<Expr>,
2735    },
2736    /// Snowflake-style
2737    /// SET (a, b, ..) = (1, 2, ..);
2738    ParenthesizedAssignments {
2739        variables: Vec<ObjectName>,
2740        values: Vec<Expr>,
2741    },
2742    /// MySQL-style
2743    /// SET a = 1, b = 2, ..;
2744    MultipleAssignments { assignments: Vec<SetAssignment> },
2745    /// MS-SQL session
2746    ///
2747    /// See <https://learn.microsoft.com/en-us/sql/t-sql/statements/set-statements-transact-sql>
2748    SetSessionParam(SetSessionParamKind),
2749    /// ```sql
2750    /// SET [ SESSION | LOCAL ] ROLE role_name
2751    /// ```
2752    ///
2753    /// Sets session state. Examples: [ANSI][1], [Postgresql][2], [MySQL][3], and [Oracle][4]
2754    ///
2755    /// [1]: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#set-role-statement
2756    /// [2]: https://www.postgresql.org/docs/14/sql-set-role.html
2757    /// [3]: https://dev.mysql.com/doc/refman/8.0/en/set-role.html
2758    /// [4]: https://docs.oracle.com/cd/B19306_01/server.102/b14200/statements_10004.htm
2759    SetRole {
2760        /// Non-ANSI optional identifier to inform if the role is defined inside the current session (`SESSION`) or transaction (`LOCAL`).
2761        context_modifier: Option<ContextModifier>,
2762        /// Role name. If NONE is specified, then the current role name is removed.
2763        role_name: Option<Ident>,
2764    },
2765    /// ```sql
2766    /// SET TIME ZONE <value>
2767    /// ```
2768    ///
2769    /// Note: this is a PostgreSQL-specific statements
2770    /// `SET TIME ZONE <value>` is an alias for `SET timezone TO <value>` in PostgreSQL
2771    /// However, we allow it for all dialects.
2772    SetTimeZone { local: bool, value: Expr },
2773    /// ```sql
2774    /// SET NAMES 'charset_name' [COLLATE 'collation_name']
2775    /// ```
2776    SetNames {
2777        charset_name: Ident,
2778        collation_name: Option<String>,
2779    },
2780    /// ```sql
2781    /// SET NAMES DEFAULT
2782    /// ```
2783    ///
2784    /// Note: this is a MySQL-specific statement.
2785    SetNamesDefault {},
2786    /// ```sql
2787    /// SET TRANSACTION ...
2788    /// ```
2789    SetTransaction {
2790        modes: Vec<TransactionMode>,
2791        snapshot: Option<Value>,
2792        session: bool,
2793    },
2794}
2795
2796impl Display for Set {
2797    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2798        match self {
2799            Self::ParenthesizedAssignments { variables, values } => write!(
2800                f,
2801                "SET ({}) = ({})",
2802                display_comma_separated(variables),
2803                display_comma_separated(values)
2804            ),
2805            Self::MultipleAssignments { assignments } => {
2806                write!(f, "SET {}", display_comma_separated(assignments))
2807            }
2808            Self::SetRole {
2809                context_modifier,
2810                role_name,
2811            } => {
2812                let role_name = role_name.clone().unwrap_or_else(|| Ident::new("NONE"));
2813                write!(
2814                    f,
2815                    "SET {modifier}ROLE {role_name}",
2816                    modifier = context_modifier
2817                        .map(|m| format!("{}", m))
2818                        .unwrap_or_default()
2819                )
2820            }
2821            Self::SetSessionParam(kind) => write!(f, "SET {kind}"),
2822            Self::SetTransaction {
2823                modes,
2824                snapshot,
2825                session,
2826            } => {
2827                if *session {
2828                    write!(f, "SET SESSION CHARACTERISTICS AS TRANSACTION")?;
2829                } else {
2830                    write!(f, "SET TRANSACTION")?;
2831                }
2832                if !modes.is_empty() {
2833                    write!(f, " {}", display_comma_separated(modes))?;
2834                }
2835                if let Some(snapshot_id) = snapshot {
2836                    write!(f, " SNAPSHOT {snapshot_id}")?;
2837                }
2838                Ok(())
2839            }
2840            Self::SetTimeZone { local, value } => {
2841                f.write_str("SET ")?;
2842                if *local {
2843                    f.write_str("LOCAL ")?;
2844                }
2845                write!(f, "TIME ZONE {value}")
2846            }
2847            Self::SetNames {
2848                charset_name,
2849                collation_name,
2850            } => {
2851                write!(f, "SET NAMES {}", charset_name)?;
2852
2853                if let Some(collation) = collation_name {
2854                    f.write_str(" COLLATE ")?;
2855                    f.write_str(collation)?;
2856                };
2857
2858                Ok(())
2859            }
2860            Self::SetNamesDefault {} => {
2861                f.write_str("SET NAMES DEFAULT")?;
2862
2863                Ok(())
2864            }
2865            Set::SingleAssignment {
2866                scope,
2867                hivevar,
2868                variable,
2869                values,
2870            } => {
2871                write!(
2872                    f,
2873                    "SET {}{}{} = {}",
2874                    scope.map(|s| format!("{}", s)).unwrap_or_default(),
2875                    if *hivevar { "HIVEVAR:" } else { "" },
2876                    variable,
2877                    display_comma_separated(values)
2878                )
2879            }
2880        }
2881    }
2882}
2883
2884/// Convert a `Set` into a `Statement`.
2885/// Convenience function, instead of writing `Statement::Set(Set::Set...{...})`
2886impl From<Set> for Statement {
2887    fn from(set: Set) -> Self {
2888        Statement::Set(set)
2889    }
2890}
2891
2892/// A top-level statement (SELECT, INSERT, CREATE, etc.)
2893#[allow(clippy::large_enum_variant)]
2894#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2895#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2896#[cfg_attr(
2897    feature = "visitor",
2898    derive(Visit, VisitMut),
2899    visit(with = "visit_statement")
2900)]
2901pub enum Statement {
2902    /// ```sql
2903    /// ANALYZE
2904    /// ```
2905    /// Analyze (Hive)
2906    Analyze {
2907        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
2908        table_name: ObjectName,
2909        partitions: Option<Vec<Expr>>,
2910        for_columns: bool,
2911        columns: Vec<Ident>,
2912        cache_metadata: bool,
2913        noscan: bool,
2914        compute_statistics: bool,
2915        has_table_keyword: bool,
2916    },
2917    Set(Set),
2918    /// ```sql
2919    /// TRUNCATE
2920    /// ```
2921    /// Truncate (Hive)
2922    Truncate {
2923        table_names: Vec<TruncateTableTarget>,
2924        partitions: Option<Vec<Expr>>,
2925        /// TABLE - optional keyword;
2926        table: bool,
2927        /// Postgres-specific option
2928        /// [ TRUNCATE TABLE ONLY ]
2929        only: bool,
2930        /// Postgres-specific option
2931        /// [ RESTART IDENTITY | CONTINUE IDENTITY ]
2932        identity: Option<TruncateIdentityOption>,
2933        /// Postgres-specific option
2934        /// [ CASCADE | RESTRICT ]
2935        cascade: Option<CascadeOption>,
2936        /// ClickHouse-specific option
2937        /// [ ON CLUSTER cluster_name ]
2938        ///
2939        /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/truncate/)
2940        on_cluster: Option<Ident>,
2941    },
2942    /// ```sql
2943    /// MSCK
2944    /// ```
2945    /// Msck (Hive)
2946    Msck {
2947        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
2948        table_name: ObjectName,
2949        repair: bool,
2950        partition_action: Option<AddDropSync>,
2951    },
2952    /// ```sql
2953    /// SELECT
2954    /// ```
2955    Query(Box<Query>),
2956    /// ```sql
2957    /// INSERT
2958    /// ```
2959    Insert(Insert),
2960    /// ```sql
2961    /// INSTALL
2962    /// ```
2963    Install {
2964        /// Only for DuckDB
2965        extension_name: Ident,
2966    },
2967    /// ```sql
2968    /// LOAD
2969    /// ```
2970    Load {
2971        /// Only for DuckDB
2972        extension_name: Ident,
2973    },
2974    // TODO: Support ROW FORMAT
2975    Directory {
2976        overwrite: bool,
2977        local: bool,
2978        path: String,
2979        file_format: Option<FileFormat>,
2980        source: Box<Query>,
2981    },
2982    /// A `CASE` statement.
2983    Case(CaseStatement),
2984    /// An `IF` statement.
2985    If(IfStatement),
2986    /// A `RAISE` statement.
2987    Raise(RaiseStatement),
2988    /// ```sql
2989    /// CALL <function>
2990    /// ```
2991    Call(Function),
2992    /// ```sql
2993    /// COPY [TO | FROM] ...
2994    /// ```
2995    Copy {
2996        /// The source of 'COPY TO', or the target of 'COPY FROM'
2997        source: CopySource,
2998        /// If true, is a 'COPY TO' statement. If false is a 'COPY FROM'
2999        to: bool,
3000        /// The target of 'COPY TO', or the source of 'COPY FROM'
3001        target: CopyTarget,
3002        /// WITH options (from PostgreSQL version 9.0)
3003        options: Vec<CopyOption>,
3004        /// WITH options (before PostgreSQL version 9.0)
3005        legacy_options: Vec<CopyLegacyOption>,
3006        /// VALUES a vector of values to be copied
3007        values: Vec<Option<String>>,
3008    },
3009    /// ```sql
3010    /// COPY INTO <table> | <location>
3011    /// ```
3012    /// See:
3013    /// <https://docs.snowflake.com/en/sql-reference/sql/copy-into-table>
3014    /// <https://docs.snowflake.com/en/sql-reference/sql/copy-into-location>
3015    ///
3016    /// Copy Into syntax available for Snowflake is different than the one implemented in
3017    /// Postgres. Although they share common prefix, it is reasonable to implement them
3018    /// in different enums. This can be refactored later once custom dialects
3019    /// are allowed to have custom Statements.
3020    CopyIntoSnowflake {
3021        kind: CopyIntoSnowflakeKind,
3022        into: ObjectName,
3023        into_columns: Option<Vec<Ident>>,
3024        from_obj: Option<ObjectName>,
3025        from_obj_alias: Option<Ident>,
3026        stage_params: StageParamsObject,
3027        from_transformations: Option<Vec<StageLoadSelectItemKind>>,
3028        from_query: Option<Box<Query>>,
3029        files: Option<Vec<String>>,
3030        pattern: Option<String>,
3031        file_format: KeyValueOptions,
3032        copy_options: KeyValueOptions,
3033        validation_mode: Option<String>,
3034        partition: Option<Box<Expr>>,
3035    },
3036    /// ```sql
3037    /// CLOSE
3038    /// ```
3039    /// Closes the portal underlying an open cursor.
3040    Close {
3041        /// Cursor name
3042        cursor: CloseCursor,
3043    },
3044    /// ```sql
3045    /// UPDATE
3046    /// ```
3047    Update {
3048        /// TABLE
3049        table: TableWithJoins,
3050        /// Column assignments
3051        assignments: Vec<Assignment>,
3052        /// Table which provide value to be set
3053        from: Option<UpdateTableFromKind>,
3054        /// WHERE
3055        selection: Option<Expr>,
3056        /// RETURNING
3057        returning: Option<Vec<SelectItem>>,
3058        /// SQLite-specific conflict resolution clause
3059        or: Option<SqliteOnConflict>,
3060    },
3061    /// ```sql
3062    /// DELETE
3063    /// ```
3064    Delete(Delete),
3065    /// ```sql
3066    /// CREATE VIEW
3067    /// ```
3068    CreateView {
3069        /// True if this is a `CREATE OR ALTER VIEW` statement
3070        ///
3071        /// [MsSql](https://learn.microsoft.com/en-us/sql/t-sql/statements/create-view-transact-sql)
3072        or_alter: bool,
3073        or_replace: bool,
3074        materialized: bool,
3075        /// View name
3076        name: ObjectName,
3077        columns: Vec<ViewColumnDef>,
3078        query: Box<Query>,
3079        options: CreateTableOptions,
3080        cluster_by: Vec<Ident>,
3081        /// Snowflake: Views can have comments in Snowflake.
3082        /// <https://docs.snowflake.com/en/sql-reference/sql/create-view#syntax>
3083        comment: Option<String>,
3084        /// if true, has RedShift [`WITH NO SCHEMA BINDING`] clause <https://docs.aws.amazon.com/redshift/latest/dg/r_CREATE_VIEW.html>
3085        with_no_schema_binding: bool,
3086        /// if true, has SQLite `IF NOT EXISTS` clause <https://www.sqlite.org/lang_createview.html>
3087        if_not_exists: bool,
3088        /// if true, has SQLite `TEMP` or `TEMPORARY` clause <https://www.sqlite.org/lang_createview.html>
3089        temporary: bool,
3090        /// if not None, has Clickhouse `TO` clause, specify the table into which to insert results
3091        /// <https://clickhouse.com/docs/en/sql-reference/statements/create/view#materialized-view>
3092        to: Option<ObjectName>,
3093        /// MySQL: Optional parameters for the view algorithm, definer, and security context
3094        params: Option<CreateViewParams>,
3095    },
3096    /// ```sql
3097    /// CREATE TABLE
3098    /// ```
3099    CreateTable(CreateTable),
3100    /// ```sql
3101    /// CREATE VIRTUAL TABLE .. USING <module_name> (<module_args>)`
3102    /// ```
3103    /// Sqlite specific statement
3104    CreateVirtualTable {
3105        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
3106        name: ObjectName,
3107        if_not_exists: bool,
3108        module_name: Ident,
3109        module_args: Vec<Ident>,
3110    },
3111    /// ```sql
3112    /// `CREATE INDEX`
3113    /// ```
3114    CreateIndex(CreateIndex),
3115    /// ```sql
3116    /// CREATE ROLE
3117    /// ```
3118    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createrole.html)
3119    CreateRole {
3120        names: Vec<ObjectName>,
3121        if_not_exists: bool,
3122        // Postgres
3123        login: Option<bool>,
3124        inherit: Option<bool>,
3125        bypassrls: Option<bool>,
3126        password: Option<Password>,
3127        superuser: Option<bool>,
3128        create_db: Option<bool>,
3129        create_role: Option<bool>,
3130        replication: Option<bool>,
3131        connection_limit: Option<Expr>,
3132        valid_until: Option<Expr>,
3133        in_role: Vec<Ident>,
3134        in_group: Vec<Ident>,
3135        role: Vec<Ident>,
3136        user: Vec<Ident>,
3137        admin: Vec<Ident>,
3138        // MSSQL
3139        authorization_owner: Option<ObjectName>,
3140    },
3141    /// ```sql
3142    /// CREATE SECRET
3143    /// ```
3144    /// See [DuckDB](https://duckdb.org/docs/sql/statements/create_secret.html)
3145    CreateSecret {
3146        or_replace: bool,
3147        temporary: Option<bool>,
3148        if_not_exists: bool,
3149        name: Option<Ident>,
3150        storage_specifier: Option<Ident>,
3151        secret_type: Ident,
3152        options: Vec<SecretOption>,
3153    },
3154    /// ```sql
3155    /// CREATE POLICY
3156    /// ```
3157    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createpolicy.html)
3158    CreatePolicy {
3159        name: Ident,
3160        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
3161        table_name: ObjectName,
3162        policy_type: Option<CreatePolicyType>,
3163        command: Option<CreatePolicyCommand>,
3164        to: Option<Vec<Owner>>,
3165        using: Option<Expr>,
3166        with_check: Option<Expr>,
3167    },
3168    /// ```sql
3169    /// CREATE CONNECTOR
3170    /// ```
3171    /// See [Hive](https://cwiki.apache.org/confluence/pages/viewpage.action?pageId=27362034#LanguageManualDDL-CreateDataConnectorCreateConnector)
3172    CreateConnector(CreateConnector),
3173    /// ```sql
3174    /// ALTER TABLE
3175    /// ```
3176    AlterTable {
3177        /// Table name
3178        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
3179        name: ObjectName,
3180        if_exists: bool,
3181        only: bool,
3182        operations: Vec<AlterTableOperation>,
3183        location: Option<HiveSetLocation>,
3184        /// ClickHouse dialect supports `ON CLUSTER` clause for ALTER TABLE
3185        /// For example: `ALTER TABLE table_name ON CLUSTER cluster_name ADD COLUMN c UInt32`
3186        /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/alter/update)
3187        on_cluster: Option<Ident>,
3188    },
3189    /// ```sql
3190    /// ALTER INDEX
3191    /// ```
3192    AlterIndex {
3193        name: ObjectName,
3194        operation: AlterIndexOperation,
3195    },
3196    /// ```sql
3197    /// ALTER VIEW
3198    /// ```
3199    AlterView {
3200        /// View name
3201        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
3202        name: ObjectName,
3203        columns: Vec<Ident>,
3204        query: Box<Query>,
3205        with_options: Vec<SqlOption>,
3206    },
3207    /// ```sql
3208    /// ALTER TYPE
3209    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-altertype.html)
3210    /// ```
3211    AlterType(AlterType),
3212    /// ```sql
3213    /// ALTER ROLE
3214    /// ```
3215    AlterRole {
3216        name: Ident,
3217        operation: AlterRoleOperation,
3218    },
3219    /// ```sql
3220    /// ALTER POLICY <NAME> ON <TABLE NAME> [<OPERATION>]
3221    /// ```
3222    /// (Postgresql-specific)
3223    AlterPolicy {
3224        name: Ident,
3225        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
3226        table_name: ObjectName,
3227        operation: AlterPolicyOperation,
3228    },
3229    /// ```sql
3230    /// ALTER CONNECTOR connector_name SET DCPROPERTIES(property_name=property_value, ...);
3231    /// or
3232    /// ALTER CONNECTOR connector_name SET URL new_url;
3233    /// or
3234    /// ALTER CONNECTOR connector_name SET OWNER [USER|ROLE] user_or_role;
3235    /// ```
3236    /// (Hive-specific)
3237    AlterConnector {
3238        name: Ident,
3239        properties: Option<Vec<SqlOption>>,
3240        url: Option<String>,
3241        owner: Option<ddl::AlterConnectorOwner>,
3242    },
3243    /// ```sql
3244    /// ALTER SESSION SET sessionParam
3245    /// ALTER SESSION UNSET <param_name> [ , <param_name> , ... ]
3246    /// ```
3247    /// See <https://docs.snowflake.com/en/sql-reference/sql/alter-session>
3248    AlterSession {
3249        /// true is to set for the session parameters, false is to unset
3250        set: bool,
3251        /// The session parameters to set or unset
3252        session_params: KeyValueOptions,
3253    },
3254    /// ```sql
3255    /// ATTACH DATABASE 'path/to/file' AS alias
3256    /// ```
3257    /// (SQLite-specific)
3258    AttachDatabase {
3259        /// The name to bind to the newly attached database
3260        schema_name: Ident,
3261        /// An expression that indicates the path to the database file
3262        database_file_name: Expr,
3263        /// true if the syntax is 'ATTACH DATABASE', false if it's just 'ATTACH'
3264        database: bool,
3265    },
3266    /// (DuckDB-specific)
3267    /// ```sql
3268    /// ATTACH 'sqlite_file.db' AS sqlite_db (READ_ONLY, TYPE SQLITE);
3269    /// ```
3270    /// See <https://duckdb.org/docs/sql/statements/attach.html>
3271    AttachDuckDBDatabase {
3272        if_not_exists: bool,
3273        /// true if the syntax is 'ATTACH DATABASE', false if it's just 'ATTACH'
3274        database: bool,
3275        /// An expression that indicates the path to the database file
3276        database_path: Ident,
3277        database_alias: Option<Ident>,
3278        attach_options: Vec<AttachDuckDBDatabaseOption>,
3279    },
3280    /// (DuckDB-specific)
3281    /// ```sql
3282    /// DETACH db_alias;
3283    /// ```
3284    /// See <https://duckdb.org/docs/sql/statements/attach.html>
3285    DetachDuckDBDatabase {
3286        if_exists: bool,
3287        /// true if the syntax is 'DETACH DATABASE', false if it's just 'DETACH'
3288        database: bool,
3289        database_alias: Ident,
3290    },
3291    /// ```sql
3292    /// DROP [TABLE, VIEW, ...]
3293    /// ```
3294    Drop {
3295        /// The type of the object to drop: TABLE, VIEW, etc.
3296        object_type: ObjectType,
3297        /// An optional `IF EXISTS` clause. (Non-standard.)
3298        if_exists: bool,
3299        /// One or more objects to drop. (ANSI SQL requires exactly one.)
3300        names: Vec<ObjectName>,
3301        /// Whether `CASCADE` was specified. This will be `false` when
3302        /// `RESTRICT` or no drop behavior at all was specified.
3303        cascade: bool,
3304        /// Whether `RESTRICT` was specified. This will be `false` when
3305        /// `CASCADE` or no drop behavior at all was specified.
3306        restrict: bool,
3307        /// Hive allows you specify whether the table's stored data will be
3308        /// deleted along with the dropped table
3309        purge: bool,
3310        /// MySQL-specific "TEMPORARY" keyword
3311        temporary: bool,
3312    },
3313    /// ```sql
3314    /// DROP FUNCTION
3315    /// ```
3316    DropFunction {
3317        if_exists: bool,
3318        /// One or more function to drop
3319        func_desc: Vec<FunctionDesc>,
3320        /// `CASCADE` or `RESTRICT`
3321        drop_behavior: Option<DropBehavior>,
3322    },
3323    /// ```sql
3324    /// DROP PROCEDURE
3325    /// ```
3326    DropProcedure {
3327        if_exists: bool,
3328        /// One or more function to drop
3329        proc_desc: Vec<FunctionDesc>,
3330        /// `CASCADE` or `RESTRICT`
3331        drop_behavior: Option<DropBehavior>,
3332    },
3333    /// ```sql
3334    /// DROP SECRET
3335    /// ```
3336    DropSecret {
3337        if_exists: bool,
3338        temporary: Option<bool>,
3339        name: Ident,
3340        storage_specifier: Option<Ident>,
3341    },
3342    ///```sql
3343    /// DROP POLICY
3344    /// ```
3345    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-droppolicy.html)
3346    DropPolicy {
3347        if_exists: bool,
3348        name: Ident,
3349        table_name: ObjectName,
3350        drop_behavior: Option<DropBehavior>,
3351    },
3352    /// ```sql
3353    /// DROP CONNECTOR
3354    /// ```
3355    /// See [Hive](https://cwiki.apache.org/confluence/pages/viewpage.action?pageId=27362034#LanguageManualDDL-DropConnector)
3356    DropConnector {
3357        if_exists: bool,
3358        name: Ident,
3359    },
3360    /// ```sql
3361    /// DECLARE
3362    /// ```
3363    /// Declare Cursor Variables
3364    ///
3365    /// Note: this is a PostgreSQL-specific statement,
3366    /// but may also compatible with other SQL.
3367    Declare {
3368        stmts: Vec<Declare>,
3369    },
3370    /// ```sql
3371    /// CREATE EXTENSION [ IF NOT EXISTS ] extension_name
3372    ///     [ WITH ] [ SCHEMA schema_name ]
3373    ///              [ VERSION version ]
3374    ///              [ CASCADE ]
3375    /// ```
3376    ///
3377    /// Note: this is a PostgreSQL-specific statement,
3378    CreateExtension {
3379        name: Ident,
3380        if_not_exists: bool,
3381        cascade: bool,
3382        schema: Option<Ident>,
3383        version: Option<Ident>,
3384    },
3385    /// ```sql
3386    /// DROP EXTENSION [ IF EXISTS ] name [, ...] [ CASCADE | RESTRICT ]
3387    ///
3388    /// Note: this is a PostgreSQL-specific statement.
3389    /// https://www.postgresql.org/docs/current/sql-dropextension.html
3390    /// ```
3391    DropExtension {
3392        names: Vec<Ident>,
3393        if_exists: bool,
3394        /// `CASCADE` or `RESTRICT`
3395        cascade_or_restrict: Option<ReferentialAction>,
3396    },
3397    /// ```sql
3398    /// FETCH
3399    /// ```
3400    /// Retrieve rows from a query using a cursor
3401    ///
3402    /// Note: this is a PostgreSQL-specific statement,
3403    /// but may also compatible with other SQL.
3404    Fetch {
3405        /// Cursor name
3406        name: Ident,
3407        direction: FetchDirection,
3408        /// Optional, It's possible to fetch rows form cursor to the table
3409        into: Option<ObjectName>,
3410    },
3411    /// ```sql
3412    /// FLUSH [NO_WRITE_TO_BINLOG | LOCAL] flush_option [, flush_option] ... | tables_option
3413    /// ```
3414    ///
3415    /// Note: this is a Mysql-specific statement,
3416    /// but may also compatible with other SQL.
3417    Flush {
3418        object_type: FlushType,
3419        location: Option<FlushLocation>,
3420        channel: Option<String>,
3421        read_lock: bool,
3422        export: bool,
3423        tables: Vec<ObjectName>,
3424    },
3425    /// ```sql
3426    /// DISCARD [ ALL | PLANS | SEQUENCES | TEMPORARY | TEMP ]
3427    /// ```
3428    ///
3429    /// Note: this is a PostgreSQL-specific statement,
3430    /// but may also compatible with other SQL.
3431    Discard {
3432        object_type: DiscardObject,
3433    },
3434    /// `SHOW FUNCTIONS`
3435    ///
3436    /// Note: this is a Presto-specific statement.
3437    ShowFunctions {
3438        filter: Option<ShowStatementFilter>,
3439    },
3440    /// ```sql
3441    /// SHOW <variable>
3442    /// ```
3443    ///
3444    /// Note: this is a PostgreSQL-specific statement.
3445    ShowVariable {
3446        variable: Vec<Ident>,
3447    },
3448    /// ```sql
3449    /// SHOW [GLOBAL | SESSION] STATUS [LIKE 'pattern' | WHERE expr]
3450    /// ```
3451    ///
3452    /// Note: this is a MySQL-specific statement.
3453    ShowStatus {
3454        filter: Option<ShowStatementFilter>,
3455        global: bool,
3456        session: bool,
3457    },
3458    /// ```sql
3459    /// SHOW VARIABLES
3460    /// ```
3461    ///
3462    /// Note: this is a MySQL-specific statement.
3463    ShowVariables {
3464        filter: Option<ShowStatementFilter>,
3465        global: bool,
3466        session: bool,
3467    },
3468    /// ```sql
3469    /// SHOW CREATE TABLE
3470    /// ```
3471    ///
3472    /// Note: this is a MySQL-specific statement.
3473    ShowCreate {
3474        obj_type: ShowCreateObject,
3475        obj_name: ObjectName,
3476    },
3477    /// ```sql
3478    /// SHOW COLUMNS
3479    /// ```
3480    ShowColumns {
3481        extended: bool,
3482        full: bool,
3483        show_options: ShowStatementOptions,
3484    },
3485    /// ```sql
3486    /// SHOW DATABASES
3487    /// ```
3488    ShowDatabases {
3489        terse: bool,
3490        history: bool,
3491        show_options: ShowStatementOptions,
3492    },
3493    /// ```sql
3494    /// SHOW SCHEMAS
3495    /// ```
3496    ShowSchemas {
3497        terse: bool,
3498        history: bool,
3499        show_options: ShowStatementOptions,
3500    },
3501    /// ```sql
3502    /// SHOW OBJECTS LIKE 'line%' IN mydb.public
3503    /// ```
3504    /// Snowflake-specific statement
3505    /// <https://docs.snowflake.com/en/sql-reference/sql/show-objects>
3506    ShowObjects(ShowObjects),
3507    /// ```sql
3508    /// SHOW TABLES
3509    /// ```
3510    ShowTables {
3511        terse: bool,
3512        history: bool,
3513        extended: bool,
3514        full: bool,
3515        external: bool,
3516        show_options: ShowStatementOptions,
3517    },
3518    /// ```sql
3519    /// SHOW VIEWS
3520    /// ```
3521    ShowViews {
3522        terse: bool,
3523        materialized: bool,
3524        show_options: ShowStatementOptions,
3525    },
3526    /// ```sql
3527    /// SHOW COLLATION
3528    /// ```
3529    ///
3530    /// Note: this is a MySQL-specific statement.
3531    ShowCollation {
3532        filter: Option<ShowStatementFilter>,
3533    },
3534    /// ```sql
3535    /// `USE ...`
3536    /// ```
3537    Use(Use),
3538    /// ```sql
3539    /// START  [ TRANSACTION | WORK ] | START TRANSACTION } ...
3540    /// ```
3541    /// If `begin` is false.
3542    ///
3543    /// ```sql
3544    /// `BEGIN  [ TRANSACTION | WORK ] | START TRANSACTION } ...`
3545    /// ```
3546    /// If `begin` is true
3547    StartTransaction {
3548        modes: Vec<TransactionMode>,
3549        begin: bool,
3550        transaction: Option<BeginTransactionKind>,
3551        modifier: Option<TransactionModifier>,
3552        /// List of statements belonging to the `BEGIN` block.
3553        /// Example:
3554        /// ```sql
3555        /// BEGIN
3556        ///     SELECT 1;
3557        ///     SELECT 2;
3558        /// END;
3559        /// ```
3560        statements: Vec<Statement>,
3561        /// Statements of an exception clause.
3562        /// Example:
3563        /// ```sql
3564        /// BEGIN
3565        ///     SELECT 1;
3566        /// EXCEPTION WHEN ERROR THEN
3567        ///     SELECT 2;
3568        ///     SELECT 3;
3569        /// END;
3570        /// <https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#beginexceptionend>
3571        exception_statements: Option<Vec<Statement>>,
3572        /// TRUE if the statement has an `END` keyword.
3573        has_end_keyword: bool,
3574    },
3575    /// ```sql
3576    /// COMMENT ON ...
3577    /// ```
3578    ///
3579    /// Note: this is a PostgreSQL-specific statement.
3580    Comment {
3581        object_type: CommentObject,
3582        object_name: ObjectName,
3583        comment: Option<String>,
3584        /// An optional `IF EXISTS` clause. (Non-standard.)
3585        /// See <https://docs.snowflake.com/en/sql-reference/sql/comment>
3586        if_exists: bool,
3587    },
3588    /// ```sql
3589    /// COMMIT [ TRANSACTION | WORK ] [ AND [ NO ] CHAIN ]
3590    /// ```
3591    /// If `end` is false
3592    ///
3593    /// ```sql
3594    /// END [ TRY | CATCH ]
3595    /// ```
3596    /// If `end` is true
3597    Commit {
3598        chain: bool,
3599        end: bool,
3600        modifier: Option<TransactionModifier>,
3601    },
3602    /// ```sql
3603    /// ROLLBACK [ TRANSACTION | WORK ] [ AND [ NO ] CHAIN ] [ TO [ SAVEPOINT ] savepoint_name ]
3604    /// ```
3605    Rollback {
3606        chain: bool,
3607        savepoint: Option<Ident>,
3608    },
3609    /// ```sql
3610    /// CREATE SCHEMA
3611    /// ```
3612    CreateSchema {
3613        /// `<schema name> | AUTHORIZATION <schema authorization identifier>  | <schema name>  AUTHORIZATION <schema authorization identifier>`
3614        schema_name: SchemaName,
3615        if_not_exists: bool,
3616        /// Schema options.
3617        ///
3618        /// ```sql
3619        /// CREATE SCHEMA myschema OPTIONS(key1='value1');
3620        /// ```
3621        ///
3622        /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_schema_statement)
3623        options: Option<Vec<SqlOption>>,
3624        /// Default collation specification for the schema.
3625        ///
3626        /// ```sql
3627        /// CREATE SCHEMA myschema DEFAULT COLLATE 'und:ci';
3628        /// ```
3629        ///
3630        /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_schema_statement)
3631        default_collate_spec: Option<Expr>,
3632    },
3633    /// ```sql
3634    /// CREATE DATABASE
3635    /// ```
3636    CreateDatabase {
3637        db_name: ObjectName,
3638        if_not_exists: bool,
3639        location: Option<String>,
3640        managed_location: Option<String>,
3641    },
3642    /// ```sql
3643    /// CREATE FUNCTION
3644    /// ```
3645    ///
3646    /// Supported variants:
3647    /// 1. [Hive](https://cwiki.apache.org/confluence/display/hive/languagemanual+ddl#LanguageManualDDL-Create/Drop/ReloadFunction)
3648    /// 2. [PostgreSQL](https://www.postgresql.org/docs/15/sql-createfunction.html)
3649    /// 3. [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_function_statement)
3650    /// 4. [MsSql](https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql)
3651    CreateFunction(CreateFunction),
3652    /// CREATE TRIGGER
3653    ///
3654    /// Examples:
3655    ///
3656    /// ```sql
3657    /// CREATE TRIGGER trigger_name
3658    /// BEFORE INSERT ON table_name
3659    /// FOR EACH ROW
3660    /// EXECUTE FUNCTION trigger_function();
3661    /// ```
3662    ///
3663    /// Postgres: <https://www.postgresql.org/docs/current/sql-createtrigger.html>
3664    CreateTrigger {
3665        /// The `OR REPLACE` clause is used to re-create the trigger if it already exists.
3666        ///
3667        /// Example:
3668        /// ```sql
3669        /// CREATE OR REPLACE TRIGGER trigger_name
3670        /// AFTER INSERT ON table_name
3671        /// FOR EACH ROW
3672        /// EXECUTE FUNCTION trigger_function();
3673        /// ```
3674        or_replace: bool,
3675        /// The `CONSTRAINT` keyword is used to create a trigger as a constraint.
3676        is_constraint: bool,
3677        /// The name of the trigger to be created.
3678        name: ObjectName,
3679        /// Determines whether the function is called before, after, or instead of the event.
3680        ///
3681        /// Example of BEFORE:
3682        ///
3683        /// ```sql
3684        /// CREATE TRIGGER trigger_name
3685        /// BEFORE INSERT ON table_name
3686        /// FOR EACH ROW
3687        /// EXECUTE FUNCTION trigger_function();
3688        /// ```
3689        ///
3690        /// Example of AFTER:
3691        ///
3692        /// ```sql
3693        /// CREATE TRIGGER trigger_name
3694        /// AFTER INSERT ON table_name
3695        /// FOR EACH ROW
3696        /// EXECUTE FUNCTION trigger_function();
3697        /// ```
3698        ///
3699        /// Example of INSTEAD OF:
3700        ///
3701        /// ```sql
3702        /// CREATE TRIGGER trigger_name
3703        /// INSTEAD OF INSERT ON table_name
3704        /// FOR EACH ROW
3705        /// EXECUTE FUNCTION trigger_function();
3706        /// ```
3707        period: TriggerPeriod,
3708        /// Multiple events can be specified using OR, such as `INSERT`, `UPDATE`, `DELETE`, or `TRUNCATE`.
3709        events: Vec<TriggerEvent>,
3710        /// The table on which the trigger is to be created.
3711        table_name: ObjectName,
3712        /// The optional referenced table name that can be referenced via
3713        /// the `FROM` keyword.
3714        referenced_table_name: Option<ObjectName>,
3715        /// This keyword immediately precedes the declaration of one or two relation names that provide access to the transition relations of the triggering statement.
3716        referencing: Vec<TriggerReferencing>,
3717        /// This specifies whether the trigger function should be fired once for
3718        /// every row affected by the trigger event, or just once per SQL statement.
3719        trigger_object: TriggerObject,
3720        /// Whether to include the `EACH` term of the `FOR EACH`, as it is optional syntax.
3721        include_each: bool,
3722        ///  Triggering conditions
3723        condition: Option<Expr>,
3724        /// Execute logic block
3725        exec_body: TriggerExecBody,
3726        /// The characteristic of the trigger, which include whether the trigger is `DEFERRABLE`, `INITIALLY DEFERRED`, or `INITIALLY IMMEDIATE`,
3727        characteristics: Option<ConstraintCharacteristics>,
3728    },
3729    /// DROP TRIGGER
3730    ///
3731    /// ```sql
3732    /// DROP TRIGGER [ IF EXISTS ] name ON table_name [ CASCADE | RESTRICT ]
3733    /// ```
3734    ///
3735    DropTrigger {
3736        if_exists: bool,
3737        trigger_name: ObjectName,
3738        table_name: Option<ObjectName>,
3739        /// `CASCADE` or `RESTRICT`
3740        option: Option<ReferentialAction>,
3741    },
3742    /// ```sql
3743    /// CREATE PROCEDURE
3744    /// ```
3745    CreateProcedure {
3746        or_alter: bool,
3747        name: ObjectName,
3748        params: Option<Vec<ProcedureParam>>,
3749        body: Vec<Statement>,
3750    },
3751    /// ```sql
3752    /// CREATE MACRO
3753    /// ```
3754    ///
3755    /// Supported variants:
3756    /// 1. [DuckDB](https://duckdb.org/docs/sql/statements/create_macro)
3757    CreateMacro {
3758        or_replace: bool,
3759        temporary: bool,
3760        name: ObjectName,
3761        args: Option<Vec<MacroArg>>,
3762        definition: MacroDefinition,
3763    },
3764    /// ```sql
3765    /// CREATE STAGE
3766    /// ```
3767    /// See <https://docs.snowflake.com/en/sql-reference/sql/create-stage>
3768    CreateStage {
3769        or_replace: bool,
3770        temporary: bool,
3771        if_not_exists: bool,
3772        name: ObjectName,
3773        stage_params: StageParamsObject,
3774        directory_table_params: KeyValueOptions,
3775        file_format: KeyValueOptions,
3776        copy_options: KeyValueOptions,
3777        comment: Option<String>,
3778    },
3779    /// ```sql
3780    /// ASSERT <condition> [AS <message>]
3781    /// ```
3782    Assert {
3783        condition: Expr,
3784        message: Option<Expr>,
3785    },
3786    /// ```sql
3787    /// GRANT privileges ON objects TO grantees
3788    /// ```
3789    Grant {
3790        privileges: Privileges,
3791        objects: Option<GrantObjects>,
3792        grantees: Vec<Grantee>,
3793        with_grant_option: bool,
3794        granted_by: Option<Ident>,
3795    },
3796    /// ```sql
3797    /// REVOKE privileges ON objects FROM grantees
3798    /// ```
3799    Revoke {
3800        privileges: Privileges,
3801        objects: Option<GrantObjects>,
3802        grantees: Vec<Grantee>,
3803        granted_by: Option<Ident>,
3804        cascade: Option<CascadeOption>,
3805    },
3806    /// ```sql
3807    /// DEALLOCATE [ PREPARE ] { name | ALL }
3808    /// ```
3809    ///
3810    /// Note: this is a PostgreSQL-specific statement.
3811    Deallocate {
3812        name: Ident,
3813        prepare: bool,
3814    },
3815    /// ```sql
3816    /// An `EXECUTE` statement
3817    /// ```
3818    ///
3819    /// Postgres: <https://www.postgresql.org/docs/current/sql-execute.html>
3820    /// MSSQL: <https://learn.microsoft.com/en-us/sql/relational-databases/stored-procedures/execute-a-stored-procedure>
3821    /// BigQuery: <https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#execute_immediate>
3822    /// Snowflake: <https://docs.snowflake.com/en/sql-reference/sql/execute-immediate>
3823    Execute {
3824        name: Option<ObjectName>,
3825        parameters: Vec<Expr>,
3826        has_parentheses: bool,
3827        /// Is this an `EXECUTE IMMEDIATE`
3828        immediate: bool,
3829        into: Vec<Ident>,
3830        using: Vec<ExprWithAlias>,
3831    },
3832    /// ```sql
3833    /// PREPARE name [ ( data_type [, ...] ) ] AS statement
3834    /// ```
3835    ///
3836    /// Note: this is a PostgreSQL-specific statement.
3837    Prepare {
3838        name: Ident,
3839        data_types: Vec<DataType>,
3840        statement: Box<Statement>,
3841    },
3842    /// ```sql
3843    /// KILL [CONNECTION | QUERY | MUTATION]
3844    /// ```
3845    ///
3846    /// See <https://clickhouse.com/docs/en/sql-reference/statements/kill/>
3847    /// See <https://dev.mysql.com/doc/refman/8.0/en/kill.html>
3848    Kill {
3849        modifier: Option<KillType>,
3850        // processlist_id
3851        id: u64,
3852    },
3853    /// ```sql
3854    /// [EXPLAIN | DESC | DESCRIBE] TABLE
3855    /// ```
3856    /// Note: this is a MySQL-specific statement. See <https://dev.mysql.com/doc/refman/8.0/en/explain.html>
3857    ExplainTable {
3858        /// `EXPLAIN | DESC | DESCRIBE`
3859        describe_alias: DescribeAlias,
3860        /// Hive style `FORMATTED | EXTENDED`
3861        hive_format: Option<HiveDescribeFormat>,
3862        /// Snowflake and ClickHouse support `DESC|DESCRIBE TABLE <table_name>` syntax
3863        ///
3864        /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/desc-table.html)
3865        /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/describe-table)
3866        has_table_keyword: bool,
3867        /// Table name
3868        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
3869        table_name: ObjectName,
3870    },
3871    /// ```sql
3872    /// [EXPLAIN | DESC | DESCRIBE]  <statement>
3873    /// ```
3874    Explain {
3875        /// `EXPLAIN | DESC | DESCRIBE`
3876        describe_alias: DescribeAlias,
3877        /// Carry out the command and show actual run times and other statistics.
3878        analyze: bool,
3879        // Display additional information regarding the plan.
3880        verbose: bool,
3881        /// `EXPLAIN QUERY PLAN`
3882        /// Display the query plan without running the query.
3883        ///
3884        /// [SQLite](https://sqlite.org/lang_explain.html)
3885        query_plan: bool,
3886        /// `EXPLAIN ESTIMATE`
3887        /// [Clickhouse](https://clickhouse.com/docs/en/sql-reference/statements/explain#explain-estimate)
3888        estimate: bool,
3889        /// A SQL query that specifies what to explain
3890        statement: Box<Statement>,
3891        /// Optional output format of explain
3892        format: Option<AnalyzeFormat>,
3893        /// Postgres style utility options, `(analyze, verbose true)`
3894        options: Option<Vec<UtilityOption>>,
3895    },
3896    /// ```sql
3897    /// SAVEPOINT
3898    /// ```
3899    /// Define a new savepoint within the current transaction
3900    Savepoint {
3901        name: Ident,
3902    },
3903    /// ```sql
3904    /// RELEASE [ SAVEPOINT ] savepoint_name
3905    /// ```
3906    ReleaseSavepoint {
3907        name: Ident,
3908    },
3909    /// A `MERGE` statement.
3910    ///
3911    /// ```sql
3912    /// MERGE INTO <target_table> USING <source> ON <join_expr> { matchedClause | notMatchedClause } [ ... ]
3913    /// ```
3914    /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/merge)
3915    /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/dml-syntax#merge_statement)
3916    /// [MSSQL](https://learn.microsoft.com/en-us/sql/t-sql/statements/merge-transact-sql?view=sql-server-ver16)
3917    Merge {
3918        /// optional INTO keyword
3919        into: bool,
3920        /// Specifies the table to merge
3921        table: TableFactor,
3922        /// Specifies the table or subquery to join with the target table
3923        source: TableFactor,
3924        /// Specifies the expression on which to join the target table and source
3925        on: Box<Expr>,
3926        /// Specifies the actions to perform when values match or do not match.
3927        clauses: Vec<MergeClause>,
3928        // Specifies the output to save changes in MSSQL
3929        output: Option<OutputClause>,
3930    },
3931    /// ```sql
3932    /// CACHE [ FLAG ] TABLE <table_name> [ OPTIONS('K1' = 'V1', 'K2' = V2) ] [ AS ] [ <query> ]
3933    /// ```
3934    ///
3935    /// See [Spark SQL docs] for more details.
3936    ///
3937    /// [Spark SQL docs]: https://docs.databricks.com/spark/latest/spark-sql/language-manual/sql-ref-syntax-aux-cache-cache-table.html
3938    Cache {
3939        /// Table flag
3940        table_flag: Option<ObjectName>,
3941        /// Table name
3942
3943        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
3944        table_name: ObjectName,
3945        has_as: bool,
3946        /// Table confs
3947        options: Vec<SqlOption>,
3948        /// Cache table as a Query
3949        query: Option<Box<Query>>,
3950    },
3951    /// ```sql
3952    /// UNCACHE TABLE [ IF EXISTS ]  <table_name>
3953    /// ```
3954    UNCache {
3955        /// Table name
3956        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
3957        table_name: ObjectName,
3958        if_exists: bool,
3959    },
3960    /// ```sql
3961    /// CREATE [ { TEMPORARY | TEMP } ] SEQUENCE [ IF NOT EXISTS ] <sequence_name>
3962    /// ```
3963    /// Define a new sequence:
3964    CreateSequence {
3965        temporary: bool,
3966        if_not_exists: bool,
3967        name: ObjectName,
3968        data_type: Option<DataType>,
3969        sequence_options: Vec<SequenceOptions>,
3970        owned_by: Option<ObjectName>,
3971    },
3972    /// ```sql
3973    /// CREATE TYPE <name>
3974    /// ```
3975    CreateType {
3976        name: ObjectName,
3977        representation: UserDefinedTypeRepresentation,
3978    },
3979    /// ```sql
3980    /// PRAGMA <schema-name>.<pragma-name> = <pragma-value>
3981    /// ```
3982    Pragma {
3983        name: ObjectName,
3984        value: Option<Value>,
3985        is_eq: bool,
3986    },
3987    /// ```sql
3988    /// LOCK TABLES <table_name> [READ [LOCAL] | [LOW_PRIORITY] WRITE]
3989    /// ```
3990    /// Note: this is a MySQL-specific statement. See <https://dev.mysql.com/doc/refman/8.0/en/lock-tables.html>
3991    LockTables {
3992        tables: Vec<LockTable>,
3993    },
3994    /// ```sql
3995    /// UNLOCK TABLES
3996    /// ```
3997    /// Note: this is a MySQL-specific statement. See <https://dev.mysql.com/doc/refman/8.0/en/lock-tables.html>
3998    UnlockTables,
3999    /// ```sql
4000    /// UNLOAD(statement) TO <destination> [ WITH options ]
4001    /// ```
4002    /// See Redshift <https://docs.aws.amazon.com/redshift/latest/dg/r_UNLOAD.html> and
4003    // Athena <https://docs.aws.amazon.com/athena/latest/ug/unload.html>
4004    Unload {
4005        query: Box<Query>,
4006        to: Ident,
4007        with: Vec<SqlOption>,
4008    },
4009    /// ```sql
4010    /// OPTIMIZE TABLE [db.]name [ON CLUSTER cluster] [PARTITION partition | PARTITION ID 'partition_id'] [FINAL] [DEDUPLICATE [BY expression]]
4011    /// ```
4012    ///
4013    /// See ClickHouse <https://clickhouse.com/docs/en/sql-reference/statements/optimize>
4014    OptimizeTable {
4015        name: ObjectName,
4016        on_cluster: Option<Ident>,
4017        partition: Option<Partition>,
4018        include_final: bool,
4019        deduplicate: Option<Deduplicate>,
4020    },
4021    /// ```sql
4022    /// LISTEN
4023    /// ```
4024    /// listen for a notification channel
4025    ///
4026    /// See Postgres <https://www.postgresql.org/docs/current/sql-listen.html>
4027    LISTEN {
4028        channel: Ident,
4029    },
4030    /// ```sql
4031    /// UNLISTEN
4032    /// ```
4033    /// stop listening for a notification
4034    ///
4035    /// See Postgres <https://www.postgresql.org/docs/current/sql-unlisten.html>
4036    UNLISTEN {
4037        channel: Ident,
4038    },
4039    /// ```sql
4040    /// NOTIFY channel [ , payload ]
4041    /// ```
4042    /// send a notification event together with an optional “payload” string to channel
4043    ///
4044    /// See Postgres <https://www.postgresql.org/docs/current/sql-notify.html>
4045    NOTIFY {
4046        channel: Ident,
4047        payload: Option<String>,
4048    },
4049    /// ```sql
4050    /// LOAD DATA [LOCAL] INPATH 'filepath' [OVERWRITE] INTO TABLE tablename
4051    /// [PARTITION (partcol1=val1, partcol2=val2 ...)]
4052    /// [INPUTFORMAT 'inputformat' SERDE 'serde']
4053    /// ```
4054    /// Loading files into tables
4055    ///
4056    /// See Hive <https://cwiki.apache.org/confluence/pages/viewpage.action?pageId=27362036#LanguageManualDML-Loadingfilesintotables>
4057    LoadData {
4058        local: bool,
4059        inpath: String,
4060        overwrite: bool,
4061        table_name: ObjectName,
4062        partitioned: Option<Vec<Expr>>,
4063        table_format: Option<HiveLoadDataFormat>,
4064    },
4065    /// ```sql
4066    /// Rename TABLE tbl_name TO new_tbl_name[, tbl_name2 TO new_tbl_name2] ...
4067    /// ```
4068    /// Renames one or more tables
4069    ///
4070    /// See Mysql <https://dev.mysql.com/doc/refman/9.1/en/rename-table.html>
4071    RenameTable(Vec<RenameTable>),
4072    /// Snowflake `LIST`
4073    /// See: <https://docs.snowflake.com/en/sql-reference/sql/list>
4074    List(FileStagingCommand),
4075    /// Snowflake `REMOVE`
4076    /// See: <https://docs.snowflake.com/en/sql-reference/sql/remove>
4077    Remove(FileStagingCommand),
4078    /// RaiseError (MSSQL)
4079    /// RAISERROR ( { msg_id | msg_str | @local_variable }
4080    /// { , severity , state }
4081    /// [ , argument [ , ...n ] ] )
4082    /// [ WITH option [ , ...n ] ]
4083    /// See <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/raiserror-transact-sql?view=sql-server-ver16>
4084    RaisError {
4085        message: Box<Expr>,
4086        severity: Box<Expr>,
4087        state: Box<Expr>,
4088        arguments: Vec<Expr>,
4089        options: Vec<RaisErrorOption>,
4090    },
4091    /// ```sql
4092    /// PRINT msg_str | @local_variable | string_expr
4093    /// ```
4094    ///
4095    /// See: <https://learn.microsoft.com/en-us/sql/t-sql/statements/print-transact-sql>
4096    Print(PrintStatement),
4097    /// ```sql
4098    /// RETURN [ expression ]
4099    /// ```
4100    ///
4101    /// See [ReturnStatement]
4102    Return(ReturnStatement),
4103}
4104
4105#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
4106#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4107#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
4108pub enum RaisErrorOption {
4109    Log,
4110    NoWait,
4111    SetError,
4112}
4113
4114impl fmt::Display for RaisErrorOption {
4115    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
4116        match self {
4117            RaisErrorOption::Log => write!(f, "LOG"),
4118            RaisErrorOption::NoWait => write!(f, "NOWAIT"),
4119            RaisErrorOption::SetError => write!(f, "SETERROR"),
4120        }
4121    }
4122}
4123
4124impl fmt::Display for Statement {
4125    // Clippy thinks this function is too complicated, but it is painful to
4126    // split up without extracting structs for each `Statement` variant.
4127    #[allow(clippy::cognitive_complexity)]
4128    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
4129        match self {
4130            Statement::Flush {
4131                object_type,
4132                location,
4133                channel,
4134                read_lock,
4135                export,
4136                tables,
4137            } => {
4138                write!(f, "FLUSH")?;
4139                if let Some(location) = location {
4140                    write!(f, " {location}")?;
4141                }
4142                write!(f, " {object_type}")?;
4143
4144                if let Some(channel) = channel {
4145                    write!(f, " FOR CHANNEL {channel}")?;
4146                }
4147
4148                write!(
4149                    f,
4150                    "{tables}{read}{export}",
4151                    tables = if !tables.is_empty() {
4152                        " ".to_string() + &display_comma_separated(tables).to_string()
4153                    } else {
4154                        "".to_string()
4155                    },
4156                    export = if *export { " FOR EXPORT" } else { "" },
4157                    read = if *read_lock { " WITH READ LOCK" } else { "" }
4158                )
4159            }
4160            Statement::Kill { modifier, id } => {
4161                write!(f, "KILL ")?;
4162
4163                if let Some(m) = modifier {
4164                    write!(f, "{m} ")?;
4165                }
4166
4167                write!(f, "{id}")
4168            }
4169            Statement::ExplainTable {
4170                describe_alias,
4171                hive_format,
4172                has_table_keyword,
4173                table_name,
4174            } => {
4175                write!(f, "{describe_alias} ")?;
4176
4177                if let Some(format) = hive_format {
4178                    write!(f, "{} ", format)?;
4179                }
4180                if *has_table_keyword {
4181                    write!(f, "TABLE ")?;
4182                }
4183
4184                write!(f, "{table_name}")
4185            }
4186            Statement::Explain {
4187                describe_alias,
4188                verbose,
4189                analyze,
4190                query_plan,
4191                estimate,
4192                statement,
4193                format,
4194                options,
4195            } => {
4196                write!(f, "{describe_alias} ")?;
4197
4198                if *query_plan {
4199                    write!(f, "QUERY PLAN ")?;
4200                }
4201                if *analyze {
4202                    write!(f, "ANALYZE ")?;
4203                }
4204                if *estimate {
4205                    write!(f, "ESTIMATE ")?;
4206                }
4207
4208                if *verbose {
4209                    write!(f, "VERBOSE ")?;
4210                }
4211
4212                if let Some(format) = format {
4213                    write!(f, "FORMAT {format} ")?;
4214                }
4215
4216                if let Some(options) = options {
4217                    write!(f, "({}) ", display_comma_separated(options))?;
4218                }
4219
4220                write!(f, "{statement}")
4221            }
4222            Statement::Query(s) => write!(f, "{s}"),
4223            Statement::Declare { stmts } => {
4224                write!(f, "DECLARE ")?;
4225                write!(f, "{}", display_separated(stmts, "; "))
4226            }
4227            Statement::Fetch {
4228                name,
4229                direction,
4230                into,
4231            } => {
4232                write!(f, "FETCH {direction} ")?;
4233
4234                write!(f, "IN {name}")?;
4235
4236                if let Some(into) = into {
4237                    write!(f, " INTO {into}")?;
4238                }
4239
4240                Ok(())
4241            }
4242            Statement::Directory {
4243                overwrite,
4244                local,
4245                path,
4246                file_format,
4247                source,
4248            } => {
4249                write!(
4250                    f,
4251                    "INSERT{overwrite}{local} DIRECTORY '{path}'",
4252                    overwrite = if *overwrite { " OVERWRITE" } else { "" },
4253                    local = if *local { " LOCAL" } else { "" },
4254                    path = path
4255                )?;
4256                if let Some(ref ff) = file_format {
4257                    write!(f, " STORED AS {ff}")?
4258                }
4259                write!(f, " {source}")
4260            }
4261            Statement::Msck {
4262                table_name,
4263                repair,
4264                partition_action,
4265            } => {
4266                write!(
4267                    f,
4268                    "MSCK {repair}TABLE {table}",
4269                    repair = if *repair { "REPAIR " } else { "" },
4270                    table = table_name
4271                )?;
4272                if let Some(pa) = partition_action {
4273                    write!(f, " {pa}")?;
4274                }
4275                Ok(())
4276            }
4277            Statement::Truncate {
4278                table_names,
4279                partitions,
4280                table,
4281                only,
4282                identity,
4283                cascade,
4284                on_cluster,
4285            } => {
4286                let table = if *table { "TABLE " } else { "" };
4287                let only = if *only { "ONLY " } else { "" };
4288
4289                write!(
4290                    f,
4291                    "TRUNCATE {table}{only}{table_names}",
4292                    table_names = display_comma_separated(table_names)
4293                )?;
4294
4295                if let Some(identity) = identity {
4296                    match identity {
4297                        TruncateIdentityOption::Restart => write!(f, " RESTART IDENTITY")?,
4298                        TruncateIdentityOption::Continue => write!(f, " CONTINUE IDENTITY")?,
4299                    }
4300                }
4301                if let Some(cascade) = cascade {
4302                    match cascade {
4303                        CascadeOption::Cascade => write!(f, " CASCADE")?,
4304                        CascadeOption::Restrict => write!(f, " RESTRICT")?,
4305                    }
4306                }
4307
4308                if let Some(ref parts) = partitions {
4309                    if !parts.is_empty() {
4310                        write!(f, " PARTITION ({})", display_comma_separated(parts))?;
4311                    }
4312                }
4313                if let Some(on_cluster) = on_cluster {
4314                    write!(f, " ON CLUSTER {on_cluster}")?;
4315                }
4316                Ok(())
4317            }
4318            Statement::Case(stmt) => {
4319                write!(f, "{stmt}")
4320            }
4321            Statement::If(stmt) => {
4322                write!(f, "{stmt}")
4323            }
4324            Statement::Raise(stmt) => {
4325                write!(f, "{stmt}")
4326            }
4327            Statement::AttachDatabase {
4328                schema_name,
4329                database_file_name,
4330                database,
4331            } => {
4332                let keyword = if *database { "DATABASE " } else { "" };
4333                write!(f, "ATTACH {keyword}{database_file_name} AS {schema_name}")
4334            }
4335            Statement::AttachDuckDBDatabase {
4336                if_not_exists,
4337                database,
4338                database_path,
4339                database_alias,
4340                attach_options,
4341            } => {
4342                write!(
4343                    f,
4344                    "ATTACH{database}{if_not_exists} {database_path}",
4345                    database = if *database { " DATABASE" } else { "" },
4346                    if_not_exists = if *if_not_exists { " IF NOT EXISTS" } else { "" },
4347                )?;
4348                if let Some(alias) = database_alias {
4349                    write!(f, " AS {alias}")?;
4350                }
4351                if !attach_options.is_empty() {
4352                    write!(f, " ({})", display_comma_separated(attach_options))?;
4353                }
4354                Ok(())
4355            }
4356            Statement::DetachDuckDBDatabase {
4357                if_exists,
4358                database,
4359                database_alias,
4360            } => {
4361                write!(
4362                    f,
4363                    "DETACH{database}{if_exists} {database_alias}",
4364                    database = if *database { " DATABASE" } else { "" },
4365                    if_exists = if *if_exists { " IF EXISTS" } else { "" },
4366                )?;
4367                Ok(())
4368            }
4369            Statement::Analyze {
4370                table_name,
4371                partitions,
4372                for_columns,
4373                columns,
4374                cache_metadata,
4375                noscan,
4376                compute_statistics,
4377                has_table_keyword,
4378            } => {
4379                write!(
4380                    f,
4381                    "ANALYZE{}{table_name}",
4382                    if *has_table_keyword { " TABLE " } else { " " }
4383                )?;
4384                if let Some(ref parts) = partitions {
4385                    if !parts.is_empty() {
4386                        write!(f, " PARTITION ({})", display_comma_separated(parts))?;
4387                    }
4388                }
4389
4390                if *compute_statistics {
4391                    write!(f, " COMPUTE STATISTICS")?;
4392                }
4393                if *noscan {
4394                    write!(f, " NOSCAN")?;
4395                }
4396                if *cache_metadata {
4397                    write!(f, " CACHE METADATA")?;
4398                }
4399                if *for_columns {
4400                    write!(f, " FOR COLUMNS")?;
4401                    if !columns.is_empty() {
4402                        write!(f, " {}", display_comma_separated(columns))?;
4403                    }
4404                }
4405                Ok(())
4406            }
4407            Statement::Insert(insert) => write!(f, "{insert}"),
4408            Statement::Install {
4409                extension_name: name,
4410            } => write!(f, "INSTALL {name}"),
4411
4412            Statement::Load {
4413                extension_name: name,
4414            } => write!(f, "LOAD {name}"),
4415
4416            Statement::Call(function) => write!(f, "CALL {function}"),
4417
4418            Statement::Copy {
4419                source,
4420                to,
4421                target,
4422                options,
4423                legacy_options,
4424                values,
4425            } => {
4426                write!(f, "COPY")?;
4427                match source {
4428                    CopySource::Query(query) => write!(f, " ({query})")?,
4429                    CopySource::Table {
4430                        table_name,
4431                        columns,
4432                    } => {
4433                        write!(f, " {table_name}")?;
4434                        if !columns.is_empty() {
4435                            write!(f, " ({})", display_comma_separated(columns))?;
4436                        }
4437                    }
4438                }
4439                write!(f, " {} {}", if *to { "TO" } else { "FROM" }, target)?;
4440                if !options.is_empty() {
4441                    write!(f, " ({})", display_comma_separated(options))?;
4442                }
4443                if !legacy_options.is_empty() {
4444                    write!(f, " {}", display_separated(legacy_options, " "))?;
4445                }
4446                if !values.is_empty() {
4447                    writeln!(f, ";")?;
4448                    let mut delim = "";
4449                    for v in values {
4450                        write!(f, "{delim}")?;
4451                        delim = "\t";
4452                        if let Some(v) = v {
4453                            write!(f, "{v}")?;
4454                        } else {
4455                            write!(f, "\\N")?;
4456                        }
4457                    }
4458                    write!(f, "\n\\.")?;
4459                }
4460                Ok(())
4461            }
4462            Statement::Update {
4463                table,
4464                assignments,
4465                from,
4466                selection,
4467                returning,
4468                or,
4469            } => {
4470                write!(f, "UPDATE ")?;
4471                if let Some(or) = or {
4472                    write!(f, "{or} ")?;
4473                }
4474                write!(f, "{table}")?;
4475                if let Some(UpdateTableFromKind::BeforeSet(from)) = from {
4476                    write!(f, " FROM {}", display_comma_separated(from))?;
4477                }
4478                if !assignments.is_empty() {
4479                    write!(f, " SET {}", display_comma_separated(assignments))?;
4480                }
4481                if let Some(UpdateTableFromKind::AfterSet(from)) = from {
4482                    write!(f, " FROM {}", display_comma_separated(from))?;
4483                }
4484                if let Some(selection) = selection {
4485                    write!(f, " WHERE {selection}")?;
4486                }
4487                if let Some(returning) = returning {
4488                    write!(f, " RETURNING {}", display_comma_separated(returning))?;
4489                }
4490                Ok(())
4491            }
4492            Statement::Delete(delete) => write!(f, "{delete}"),
4493            Statement::Close { cursor } => {
4494                write!(f, "CLOSE {cursor}")?;
4495
4496                Ok(())
4497            }
4498            Statement::CreateDatabase {
4499                db_name,
4500                if_not_exists,
4501                location,
4502                managed_location,
4503            } => {
4504                write!(f, "CREATE DATABASE")?;
4505                if *if_not_exists {
4506                    write!(f, " IF NOT EXISTS")?;
4507                }
4508                write!(f, " {db_name}")?;
4509                if let Some(l) = location {
4510                    write!(f, " LOCATION '{l}'")?;
4511                }
4512                if let Some(ml) = managed_location {
4513                    write!(f, " MANAGEDLOCATION '{ml}'")?;
4514                }
4515                Ok(())
4516            }
4517            Statement::CreateFunction(create_function) => create_function.fmt(f),
4518            Statement::CreateTrigger {
4519                or_replace,
4520                is_constraint,
4521                name,
4522                period,
4523                events,
4524                table_name,
4525                referenced_table_name,
4526                referencing,
4527                trigger_object,
4528                condition,
4529                include_each,
4530                exec_body,
4531                characteristics,
4532            } => {
4533                write!(
4534                    f,
4535                    "CREATE {or_replace}{is_constraint}TRIGGER {name} {period}",
4536                    or_replace = if *or_replace { "OR REPLACE " } else { "" },
4537                    is_constraint = if *is_constraint { "CONSTRAINT " } else { "" },
4538                )?;
4539
4540                if !events.is_empty() {
4541                    write!(f, " {}", display_separated(events, " OR "))?;
4542                }
4543                write!(f, " ON {table_name}")?;
4544
4545                if let Some(referenced_table_name) = referenced_table_name {
4546                    write!(f, " FROM {referenced_table_name}")?;
4547                }
4548
4549                if let Some(characteristics) = characteristics {
4550                    write!(f, " {characteristics}")?;
4551                }
4552
4553                if !referencing.is_empty() {
4554                    write!(f, " REFERENCING {}", display_separated(referencing, " "))?;
4555                }
4556
4557                if *include_each {
4558                    write!(f, " FOR EACH {trigger_object}")?;
4559                } else {
4560                    write!(f, " FOR {trigger_object}")?;
4561                }
4562                if let Some(condition) = condition {
4563                    write!(f, " WHEN {condition}")?;
4564                }
4565                write!(f, " EXECUTE {exec_body}")
4566            }
4567            Statement::DropTrigger {
4568                if_exists,
4569                trigger_name,
4570                table_name,
4571                option,
4572            } => {
4573                write!(f, "DROP TRIGGER")?;
4574                if *if_exists {
4575                    write!(f, " IF EXISTS")?;
4576                }
4577                match &table_name {
4578                    Some(table_name) => write!(f, " {trigger_name} ON {table_name}")?,
4579                    None => write!(f, " {trigger_name}")?,
4580                };
4581                if let Some(option) = option {
4582                    write!(f, " {option}")?;
4583                }
4584                Ok(())
4585            }
4586            Statement::CreateProcedure {
4587                name,
4588                or_alter,
4589                params,
4590                body,
4591            } => {
4592                write!(
4593                    f,
4594                    "CREATE {or_alter}PROCEDURE {name}",
4595                    or_alter = if *or_alter { "OR ALTER " } else { "" },
4596                    name = name
4597                )?;
4598
4599                if let Some(p) = params {
4600                    if !p.is_empty() {
4601                        write!(f, " ({})", display_comma_separated(p))?;
4602                    }
4603                }
4604                write!(
4605                    f,
4606                    " AS BEGIN {body} END",
4607                    body = display_separated(body, "; ")
4608                )
4609            }
4610            Statement::CreateMacro {
4611                or_replace,
4612                temporary,
4613                name,
4614                args,
4615                definition,
4616            } => {
4617                write!(
4618                    f,
4619                    "CREATE {or_replace}{temp}MACRO {name}",
4620                    temp = if *temporary { "TEMPORARY " } else { "" },
4621                    or_replace = if *or_replace { "OR REPLACE " } else { "" },
4622                )?;
4623                if let Some(args) = args {
4624                    write!(f, "({})", display_comma_separated(args))?;
4625                }
4626                match definition {
4627                    MacroDefinition::Expr(expr) => write!(f, " AS {expr}")?,
4628                    MacroDefinition::Table(query) => write!(f, " AS TABLE {query}")?,
4629                }
4630                Ok(())
4631            }
4632            Statement::CreateView {
4633                or_alter,
4634                name,
4635                or_replace,
4636                columns,
4637                query,
4638                materialized,
4639                options,
4640                cluster_by,
4641                comment,
4642                with_no_schema_binding,
4643                if_not_exists,
4644                temporary,
4645                to,
4646                params,
4647            } => {
4648                write!(
4649                    f,
4650                    "CREATE {or_alter}{or_replace}",
4651                    or_alter = if *or_alter { "OR ALTER " } else { "" },
4652                    or_replace = if *or_replace { "OR REPLACE " } else { "" },
4653                )?;
4654                if let Some(params) = params {
4655                    params.fmt(f)?;
4656                }
4657                write!(
4658                    f,
4659                    "{materialized}{temporary}VIEW {if_not_exists}{name}{to}",
4660                    materialized = if *materialized { "MATERIALIZED " } else { "" },
4661                    name = name,
4662                    temporary = if *temporary { "TEMPORARY " } else { "" },
4663                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
4664                    to = to
4665                        .as_ref()
4666                        .map(|to| format!(" TO {to}"))
4667                        .unwrap_or_default()
4668                )?;
4669                if !columns.is_empty() {
4670                    write!(f, " ({})", display_comma_separated(columns))?;
4671                }
4672                if matches!(options, CreateTableOptions::With(_)) {
4673                    write!(f, " {options}")?;
4674                }
4675                if let Some(comment) = comment {
4676                    write!(
4677                        f,
4678                        " COMMENT = '{}'",
4679                        value::escape_single_quote_string(comment)
4680                    )?;
4681                }
4682                if !cluster_by.is_empty() {
4683                    write!(f, " CLUSTER BY ({})", display_comma_separated(cluster_by))?;
4684                }
4685                if matches!(options, CreateTableOptions::Options(_)) {
4686                    write!(f, " {options}")?;
4687                }
4688                write!(f, " AS {query}")?;
4689                if *with_no_schema_binding {
4690                    write!(f, " WITH NO SCHEMA BINDING")?;
4691                }
4692                Ok(())
4693            }
4694            Statement::CreateTable(create_table) => create_table.fmt(f),
4695            Statement::LoadData {
4696                local,
4697                inpath,
4698                overwrite,
4699                table_name,
4700                partitioned,
4701                table_format,
4702            } => {
4703                write!(
4704                    f,
4705                    "LOAD DATA {local}INPATH '{inpath}' {overwrite}INTO TABLE {table_name}",
4706                    local = if *local { "LOCAL " } else { "" },
4707                    inpath = inpath,
4708                    overwrite = if *overwrite { "OVERWRITE " } else { "" },
4709                    table_name = table_name,
4710                )?;
4711                if let Some(ref parts) = &partitioned {
4712                    if !parts.is_empty() {
4713                        write!(f, " PARTITION ({})", display_comma_separated(parts))?;
4714                    }
4715                }
4716                if let Some(HiveLoadDataFormat {
4717                    serde,
4718                    input_format,
4719                }) = &table_format
4720                {
4721                    write!(f, " INPUTFORMAT {input_format} SERDE {serde}")?;
4722                }
4723                Ok(())
4724            }
4725            Statement::CreateVirtualTable {
4726                name,
4727                if_not_exists,
4728                module_name,
4729                module_args,
4730            } => {
4731                write!(
4732                    f,
4733                    "CREATE VIRTUAL TABLE {if_not_exists}{name} USING {module_name}",
4734                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
4735                    name = name,
4736                    module_name = module_name
4737                )?;
4738                if !module_args.is_empty() {
4739                    write!(f, " ({})", display_comma_separated(module_args))?;
4740                }
4741                Ok(())
4742            }
4743            Statement::CreateIndex(create_index) => create_index.fmt(f),
4744            Statement::CreateExtension {
4745                name,
4746                if_not_exists,
4747                cascade,
4748                schema,
4749                version,
4750            } => {
4751                write!(
4752                    f,
4753                    "CREATE EXTENSION {if_not_exists}{name}",
4754                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" }
4755                )?;
4756                if *cascade || schema.is_some() || version.is_some() {
4757                    write!(f, " WITH")?;
4758
4759                    if let Some(name) = schema {
4760                        write!(f, " SCHEMA {name}")?;
4761                    }
4762                    if let Some(version) = version {
4763                        write!(f, " VERSION {version}")?;
4764                    }
4765                    if *cascade {
4766                        write!(f, " CASCADE")?;
4767                    }
4768                }
4769
4770                Ok(())
4771            }
4772            Statement::DropExtension {
4773                names,
4774                if_exists,
4775                cascade_or_restrict,
4776            } => {
4777                write!(f, "DROP EXTENSION")?;
4778                if *if_exists {
4779                    write!(f, " IF EXISTS")?;
4780                }
4781                write!(f, " {}", display_comma_separated(names))?;
4782                if let Some(cascade_or_restrict) = cascade_or_restrict {
4783                    write!(f, " {cascade_or_restrict}")?;
4784                }
4785                Ok(())
4786            }
4787            Statement::CreateRole {
4788                names,
4789                if_not_exists,
4790                inherit,
4791                login,
4792                bypassrls,
4793                password,
4794                create_db,
4795                create_role,
4796                superuser,
4797                replication,
4798                connection_limit,
4799                valid_until,
4800                in_role,
4801                in_group,
4802                role,
4803                user,
4804                admin,
4805                authorization_owner,
4806            } => {
4807                write!(
4808                    f,
4809                    "CREATE ROLE {if_not_exists}{names}{superuser}{create_db}{create_role}{inherit}{login}{replication}{bypassrls}",
4810                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
4811                    names = display_separated(names, ", "),
4812                    superuser = match *superuser {
4813                        Some(true) => " SUPERUSER",
4814                        Some(false) => " NOSUPERUSER",
4815                        None => ""
4816                    },
4817                    create_db = match *create_db {
4818                        Some(true) => " CREATEDB",
4819                        Some(false) => " NOCREATEDB",
4820                        None => ""
4821                    },
4822                    create_role = match *create_role {
4823                        Some(true) => " CREATEROLE",
4824                        Some(false) => " NOCREATEROLE",
4825                        None => ""
4826                    },
4827                    inherit = match *inherit {
4828                        Some(true) => " INHERIT",
4829                        Some(false) => " NOINHERIT",
4830                        None => ""
4831                    },
4832                    login = match *login {
4833                        Some(true) => " LOGIN",
4834                        Some(false) => " NOLOGIN",
4835                        None => ""
4836                    },
4837                    replication = match *replication {
4838                        Some(true) => " REPLICATION",
4839                        Some(false) => " NOREPLICATION",
4840                        None => ""
4841                    },
4842                    bypassrls = match *bypassrls {
4843                        Some(true) => " BYPASSRLS",
4844                        Some(false) => " NOBYPASSRLS",
4845                        None => ""
4846                    }
4847                )?;
4848                if let Some(limit) = connection_limit {
4849                    write!(f, " CONNECTION LIMIT {limit}")?;
4850                }
4851                match password {
4852                    Some(Password::Password(pass)) => write!(f, " PASSWORD {pass}"),
4853                    Some(Password::NullPassword) => write!(f, " PASSWORD NULL"),
4854                    None => Ok(()),
4855                }?;
4856                if let Some(until) = valid_until {
4857                    write!(f, " VALID UNTIL {until}")?;
4858                }
4859                if !in_role.is_empty() {
4860                    write!(f, " IN ROLE {}", display_comma_separated(in_role))?;
4861                }
4862                if !in_group.is_empty() {
4863                    write!(f, " IN GROUP {}", display_comma_separated(in_group))?;
4864                }
4865                if !role.is_empty() {
4866                    write!(f, " ROLE {}", display_comma_separated(role))?;
4867                }
4868                if !user.is_empty() {
4869                    write!(f, " USER {}", display_comma_separated(user))?;
4870                }
4871                if !admin.is_empty() {
4872                    write!(f, " ADMIN {}", display_comma_separated(admin))?;
4873                }
4874                if let Some(owner) = authorization_owner {
4875                    write!(f, " AUTHORIZATION {owner}")?;
4876                }
4877                Ok(())
4878            }
4879            Statement::CreateSecret {
4880                or_replace,
4881                temporary,
4882                if_not_exists,
4883                name,
4884                storage_specifier,
4885                secret_type,
4886                options,
4887            } => {
4888                write!(
4889                    f,
4890                    "CREATE {or_replace}",
4891                    or_replace = if *or_replace { "OR REPLACE " } else { "" },
4892                )?;
4893                if let Some(t) = temporary {
4894                    write!(f, "{}", if *t { "TEMPORARY " } else { "PERSISTENT " })?;
4895                }
4896                write!(
4897                    f,
4898                    "SECRET {if_not_exists}",
4899                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
4900                )?;
4901                if let Some(n) = name {
4902                    write!(f, "{n} ")?;
4903                };
4904                if let Some(s) = storage_specifier {
4905                    write!(f, "IN {s} ")?;
4906                }
4907                write!(f, "( TYPE {secret_type}",)?;
4908                if !options.is_empty() {
4909                    write!(f, ", {o}", o = display_comma_separated(options))?;
4910                }
4911                write!(f, " )")?;
4912                Ok(())
4913            }
4914            Statement::CreatePolicy {
4915                name,
4916                table_name,
4917                policy_type,
4918                command,
4919                to,
4920                using,
4921                with_check,
4922            } => {
4923                write!(f, "CREATE POLICY {name} ON {table_name}")?;
4924
4925                if let Some(policy_type) = policy_type {
4926                    match policy_type {
4927                        CreatePolicyType::Permissive => write!(f, " AS PERMISSIVE")?,
4928                        CreatePolicyType::Restrictive => write!(f, " AS RESTRICTIVE")?,
4929                    }
4930                }
4931
4932                if let Some(command) = command {
4933                    match command {
4934                        CreatePolicyCommand::All => write!(f, " FOR ALL")?,
4935                        CreatePolicyCommand::Select => write!(f, " FOR SELECT")?,
4936                        CreatePolicyCommand::Insert => write!(f, " FOR INSERT")?,
4937                        CreatePolicyCommand::Update => write!(f, " FOR UPDATE")?,
4938                        CreatePolicyCommand::Delete => write!(f, " FOR DELETE")?,
4939                    }
4940                }
4941
4942                if let Some(to) = to {
4943                    write!(f, " TO {}", display_comma_separated(to))?;
4944                }
4945
4946                if let Some(using) = using {
4947                    write!(f, " USING ({using})")?;
4948                }
4949
4950                if let Some(with_check) = with_check {
4951                    write!(f, " WITH CHECK ({with_check})")?;
4952                }
4953
4954                Ok(())
4955            }
4956            Statement::CreateConnector(create_connector) => create_connector.fmt(f),
4957            Statement::AlterTable {
4958                name,
4959                if_exists,
4960                only,
4961                operations,
4962                location,
4963                on_cluster,
4964            } => {
4965                write!(f, "ALTER TABLE ")?;
4966                if *if_exists {
4967                    write!(f, "IF EXISTS ")?;
4968                }
4969                if *only {
4970                    write!(f, "ONLY ")?;
4971                }
4972                write!(f, "{name} ", name = name)?;
4973                if let Some(cluster) = on_cluster {
4974                    write!(f, "ON CLUSTER {cluster} ")?;
4975                }
4976                write!(
4977                    f,
4978                    "{operations}",
4979                    operations = display_comma_separated(operations)
4980                )?;
4981                if let Some(loc) = location {
4982                    write!(f, " {loc}")?
4983                }
4984                Ok(())
4985            }
4986            Statement::AlterIndex { name, operation } => {
4987                write!(f, "ALTER INDEX {name} {operation}")
4988            }
4989            Statement::AlterView {
4990                name,
4991                columns,
4992                query,
4993                with_options,
4994            } => {
4995                write!(f, "ALTER VIEW {name}")?;
4996                if !with_options.is_empty() {
4997                    write!(f, " WITH ({})", display_comma_separated(with_options))?;
4998                }
4999                if !columns.is_empty() {
5000                    write!(f, " ({})", display_comma_separated(columns))?;
5001                }
5002                write!(f, " AS {query}")
5003            }
5004            Statement::AlterType(AlterType { name, operation }) => {
5005                write!(f, "ALTER TYPE {name} {operation}")
5006            }
5007            Statement::AlterRole { name, operation } => {
5008                write!(f, "ALTER ROLE {name} {operation}")
5009            }
5010            Statement::AlterPolicy {
5011                name,
5012                table_name,
5013                operation,
5014            } => {
5015                write!(f, "ALTER POLICY {name} ON {table_name}{operation}")
5016            }
5017            Statement::AlterConnector {
5018                name,
5019                properties,
5020                url,
5021                owner,
5022            } => {
5023                write!(f, "ALTER CONNECTOR {name}")?;
5024                if let Some(properties) = properties {
5025                    write!(
5026                        f,
5027                        " SET DCPROPERTIES({})",
5028                        display_comma_separated(properties)
5029                    )?;
5030                }
5031                if let Some(url) = url {
5032                    write!(f, " SET URL '{url}'")?;
5033                }
5034                if let Some(owner) = owner {
5035                    write!(f, " SET OWNER {owner}")?;
5036                }
5037                Ok(())
5038            }
5039            Statement::AlterSession {
5040                set,
5041                session_params,
5042            } => {
5043                write!(
5044                    f,
5045                    "ALTER SESSION {set}",
5046                    set = if *set { "SET" } else { "UNSET" }
5047                )?;
5048                if !session_params.options.is_empty() {
5049                    if *set {
5050                        write!(f, " {}", session_params)?;
5051                    } else {
5052                        let options = session_params
5053                            .options
5054                            .iter()
5055                            .map(|p| p.option_name.clone())
5056                            .collect::<Vec<_>>();
5057                        write!(f, " {}", display_separated(&options, ", "))?;
5058                    }
5059                }
5060                Ok(())
5061            }
5062            Statement::Drop {
5063                object_type,
5064                if_exists,
5065                names,
5066                cascade,
5067                restrict,
5068                purge,
5069                temporary,
5070            } => write!(
5071                f,
5072                "DROP {}{}{} {}{}{}{}",
5073                if *temporary { "TEMPORARY " } else { "" },
5074                object_type,
5075                if *if_exists { " IF EXISTS" } else { "" },
5076                display_comma_separated(names),
5077                if *cascade { " CASCADE" } else { "" },
5078                if *restrict { " RESTRICT" } else { "" },
5079                if *purge { " PURGE" } else { "" }
5080            ),
5081            Statement::DropFunction {
5082                if_exists,
5083                func_desc,
5084                drop_behavior,
5085            } => {
5086                write!(
5087                    f,
5088                    "DROP FUNCTION{} {}",
5089                    if *if_exists { " IF EXISTS" } else { "" },
5090                    display_comma_separated(func_desc),
5091                )?;
5092                if let Some(op) = drop_behavior {
5093                    write!(f, " {op}")?;
5094                }
5095                Ok(())
5096            }
5097            Statement::DropProcedure {
5098                if_exists,
5099                proc_desc,
5100                drop_behavior,
5101            } => {
5102                write!(
5103                    f,
5104                    "DROP PROCEDURE{} {}",
5105                    if *if_exists { " IF EXISTS" } else { "" },
5106                    display_comma_separated(proc_desc),
5107                )?;
5108                if let Some(op) = drop_behavior {
5109                    write!(f, " {op}")?;
5110                }
5111                Ok(())
5112            }
5113            Statement::DropSecret {
5114                if_exists,
5115                temporary,
5116                name,
5117                storage_specifier,
5118            } => {
5119                write!(f, "DROP ")?;
5120                if let Some(t) = temporary {
5121                    write!(f, "{}", if *t { "TEMPORARY " } else { "PERSISTENT " })?;
5122                }
5123                write!(
5124                    f,
5125                    "SECRET {if_exists}{name}",
5126                    if_exists = if *if_exists { "IF EXISTS " } else { "" },
5127                )?;
5128                if let Some(s) = storage_specifier {
5129                    write!(f, " FROM {s}")?;
5130                }
5131                Ok(())
5132            }
5133            Statement::DropPolicy {
5134                if_exists,
5135                name,
5136                table_name,
5137                drop_behavior,
5138            } => {
5139                write!(f, "DROP POLICY")?;
5140                if *if_exists {
5141                    write!(f, " IF EXISTS")?;
5142                }
5143                write!(f, " {name} ON {table_name}")?;
5144                if let Some(drop_behavior) = drop_behavior {
5145                    write!(f, " {drop_behavior}")?;
5146                }
5147                Ok(())
5148            }
5149            Statement::DropConnector { if_exists, name } => {
5150                write!(
5151                    f,
5152                    "DROP CONNECTOR {if_exists}{name}",
5153                    if_exists = if *if_exists { "IF EXISTS " } else { "" }
5154                )?;
5155                Ok(())
5156            }
5157            Statement::Discard { object_type } => {
5158                write!(f, "DISCARD {object_type}")?;
5159                Ok(())
5160            }
5161            Self::Set(set) => write!(f, "{set}"),
5162            Statement::ShowVariable { variable } => {
5163                write!(f, "SHOW")?;
5164                if !variable.is_empty() {
5165                    write!(f, " {}", display_separated(variable, " "))?;
5166                }
5167                Ok(())
5168            }
5169            Statement::ShowStatus {
5170                filter,
5171                global,
5172                session,
5173            } => {
5174                write!(f, "SHOW")?;
5175                if *global {
5176                    write!(f, " GLOBAL")?;
5177                }
5178                if *session {
5179                    write!(f, " SESSION")?;
5180                }
5181                write!(f, " STATUS")?;
5182                if filter.is_some() {
5183                    write!(f, " {}", filter.as_ref().unwrap())?;
5184                }
5185                Ok(())
5186            }
5187            Statement::ShowVariables {
5188                filter,
5189                global,
5190                session,
5191            } => {
5192                write!(f, "SHOW")?;
5193                if *global {
5194                    write!(f, " GLOBAL")?;
5195                }
5196                if *session {
5197                    write!(f, " SESSION")?;
5198                }
5199                write!(f, " VARIABLES")?;
5200                if filter.is_some() {
5201                    write!(f, " {}", filter.as_ref().unwrap())?;
5202                }
5203                Ok(())
5204            }
5205            Statement::ShowCreate { obj_type, obj_name } => {
5206                write!(f, "SHOW CREATE {obj_type} {obj_name}",)?;
5207                Ok(())
5208            }
5209            Statement::ShowColumns {
5210                extended,
5211                full,
5212                show_options,
5213            } => {
5214                write!(
5215                    f,
5216                    "SHOW {extended}{full}COLUMNS{show_options}",
5217                    extended = if *extended { "EXTENDED " } else { "" },
5218                    full = if *full { "FULL " } else { "" },
5219                )?;
5220                Ok(())
5221            }
5222            Statement::ShowDatabases {
5223                terse,
5224                history,
5225                show_options,
5226            } => {
5227                write!(
5228                    f,
5229                    "SHOW {terse}DATABASES{history}{show_options}",
5230                    terse = if *terse { "TERSE " } else { "" },
5231                    history = if *history { " HISTORY" } else { "" },
5232                )?;
5233                Ok(())
5234            }
5235            Statement::ShowSchemas {
5236                terse,
5237                history,
5238                show_options,
5239            } => {
5240                write!(
5241                    f,
5242                    "SHOW {terse}SCHEMAS{history}{show_options}",
5243                    terse = if *terse { "TERSE " } else { "" },
5244                    history = if *history { " HISTORY" } else { "" },
5245                )?;
5246                Ok(())
5247            }
5248            Statement::ShowObjects(ShowObjects {
5249                terse,
5250                show_options,
5251            }) => {
5252                write!(
5253                    f,
5254                    "SHOW {terse}OBJECTS{show_options}",
5255                    terse = if *terse { "TERSE " } else { "" },
5256                )?;
5257                Ok(())
5258            }
5259            Statement::ShowTables {
5260                terse,
5261                history,
5262                extended,
5263                full,
5264                external,
5265                show_options,
5266            } => {
5267                write!(
5268                    f,
5269                    "SHOW {terse}{extended}{full}{external}TABLES{history}{show_options}",
5270                    terse = if *terse { "TERSE " } else { "" },
5271                    extended = if *extended { "EXTENDED " } else { "" },
5272                    full = if *full { "FULL " } else { "" },
5273                    external = if *external { "EXTERNAL " } else { "" },
5274                    history = if *history { " HISTORY" } else { "" },
5275                )?;
5276                Ok(())
5277            }
5278            Statement::ShowViews {
5279                terse,
5280                materialized,
5281                show_options,
5282            } => {
5283                write!(
5284                    f,
5285                    "SHOW {terse}{materialized}VIEWS{show_options}",
5286                    terse = if *terse { "TERSE " } else { "" },
5287                    materialized = if *materialized { "MATERIALIZED " } else { "" }
5288                )?;
5289                Ok(())
5290            }
5291            Statement::ShowFunctions { filter } => {
5292                write!(f, "SHOW FUNCTIONS")?;
5293                if let Some(filter) = filter {
5294                    write!(f, " {filter}")?;
5295                }
5296                Ok(())
5297            }
5298            Statement::Use(use_expr) => use_expr.fmt(f),
5299            Statement::ShowCollation { filter } => {
5300                write!(f, "SHOW COLLATION")?;
5301                if let Some(filter) = filter {
5302                    write!(f, " {filter}")?;
5303                }
5304                Ok(())
5305            }
5306            Statement::StartTransaction {
5307                modes,
5308                begin: syntax_begin,
5309                transaction,
5310                modifier,
5311                statements,
5312                exception_statements,
5313                has_end_keyword,
5314            } => {
5315                if *syntax_begin {
5316                    if let Some(modifier) = *modifier {
5317                        write!(f, "BEGIN {}", modifier)?;
5318                    } else {
5319                        write!(f, "BEGIN")?;
5320                    }
5321                } else {
5322                    write!(f, "START")?;
5323                }
5324                if let Some(transaction) = transaction {
5325                    write!(f, " {transaction}")?;
5326                }
5327                if !modes.is_empty() {
5328                    write!(f, " {}", display_comma_separated(modes))?;
5329                }
5330                if !statements.is_empty() {
5331                    write!(f, " ")?;
5332                    format_statement_list(f, statements)?;
5333                }
5334                if let Some(exception_statements) = exception_statements {
5335                    write!(f, " EXCEPTION WHEN ERROR THEN")?;
5336                    if !exception_statements.is_empty() {
5337                        write!(f, " ")?;
5338                        format_statement_list(f, exception_statements)?;
5339                    }
5340                }
5341                if *has_end_keyword {
5342                    write!(f, " END")?;
5343                }
5344                Ok(())
5345            }
5346            Statement::Commit {
5347                chain,
5348                end: end_syntax,
5349                modifier,
5350            } => {
5351                if *end_syntax {
5352                    write!(f, "END")?;
5353                    if let Some(modifier) = *modifier {
5354                        write!(f, " {}", modifier)?;
5355                    }
5356                    if *chain {
5357                        write!(f, " AND CHAIN")?;
5358                    }
5359                } else {
5360                    write!(f, "COMMIT{}", if *chain { " AND CHAIN" } else { "" })?;
5361                }
5362                Ok(())
5363            }
5364            Statement::Rollback { chain, savepoint } => {
5365                write!(f, "ROLLBACK")?;
5366
5367                if *chain {
5368                    write!(f, " AND CHAIN")?;
5369                }
5370
5371                if let Some(savepoint) = savepoint {
5372                    write!(f, " TO SAVEPOINT {savepoint}")?;
5373                }
5374
5375                Ok(())
5376            }
5377            Statement::CreateSchema {
5378                schema_name,
5379                if_not_exists,
5380                options,
5381                default_collate_spec,
5382            } => {
5383                write!(
5384                    f,
5385                    "CREATE SCHEMA {if_not_exists}{name}",
5386                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
5387                    name = schema_name
5388                )?;
5389
5390                if let Some(collate) = default_collate_spec {
5391                    write!(f, " DEFAULT COLLATE {collate}")?;
5392                }
5393
5394                if let Some(options) = options {
5395                    write!(f, " OPTIONS({})", display_comma_separated(options))?;
5396                }
5397
5398                Ok(())
5399            }
5400            Statement::Assert { condition, message } => {
5401                write!(f, "ASSERT {condition}")?;
5402                if let Some(m) = message {
5403                    write!(f, " AS {m}")?;
5404                }
5405                Ok(())
5406            }
5407            Statement::Grant {
5408                privileges,
5409                objects,
5410                grantees,
5411                with_grant_option,
5412                granted_by,
5413            } => {
5414                write!(f, "GRANT {privileges} ")?;
5415                if let Some(objects) = objects {
5416                    write!(f, "ON {objects} ")?;
5417                }
5418                write!(f, "TO {}", display_comma_separated(grantees))?;
5419                if *with_grant_option {
5420                    write!(f, " WITH GRANT OPTION")?;
5421                }
5422                if let Some(grantor) = granted_by {
5423                    write!(f, " GRANTED BY {grantor}")?;
5424                }
5425                Ok(())
5426            }
5427            Statement::Revoke {
5428                privileges,
5429                objects,
5430                grantees,
5431                granted_by,
5432                cascade,
5433            } => {
5434                write!(f, "REVOKE {privileges} ")?;
5435                if let Some(objects) = objects {
5436                    write!(f, "ON {objects} ")?;
5437                }
5438                write!(f, "FROM {}", display_comma_separated(grantees))?;
5439                if let Some(grantor) = granted_by {
5440                    write!(f, " GRANTED BY {grantor}")?;
5441                }
5442                if let Some(cascade) = cascade {
5443                    write!(f, " {}", cascade)?;
5444                }
5445                Ok(())
5446            }
5447            Statement::Deallocate { name, prepare } => write!(
5448                f,
5449                "DEALLOCATE {prepare}{name}",
5450                prepare = if *prepare { "PREPARE " } else { "" },
5451                name = name,
5452            ),
5453            Statement::Execute {
5454                name,
5455                parameters,
5456                has_parentheses,
5457                immediate,
5458                into,
5459                using,
5460            } => {
5461                let (open, close) = if *has_parentheses {
5462                    ("(", ")")
5463                } else {
5464                    (if parameters.is_empty() { "" } else { " " }, "")
5465                };
5466                write!(f, "EXECUTE")?;
5467                if *immediate {
5468                    write!(f, " IMMEDIATE")?;
5469                }
5470                if let Some(name) = name {
5471                    write!(f, " {name}")?;
5472                }
5473                write!(f, "{open}{}{close}", display_comma_separated(parameters),)?;
5474                if !into.is_empty() {
5475                    write!(f, " INTO {}", display_comma_separated(into))?;
5476                }
5477                if !using.is_empty() {
5478                    write!(f, " USING {}", display_comma_separated(using))?;
5479                };
5480                Ok(())
5481            }
5482            Statement::Prepare {
5483                name,
5484                data_types,
5485                statement,
5486            } => {
5487                write!(f, "PREPARE {name} ")?;
5488                if !data_types.is_empty() {
5489                    write!(f, "({}) ", display_comma_separated(data_types))?;
5490                }
5491                write!(f, "AS {statement}")
5492            }
5493            Statement::Comment {
5494                object_type,
5495                object_name,
5496                comment,
5497                if_exists,
5498            } => {
5499                write!(f, "COMMENT ")?;
5500                if *if_exists {
5501                    write!(f, "IF EXISTS ")?
5502                };
5503                write!(f, "ON {object_type} {object_name} IS ")?;
5504                if let Some(c) = comment {
5505                    write!(f, "'{c}'")
5506                } else {
5507                    write!(f, "NULL")
5508                }
5509            }
5510            Statement::Savepoint { name } => {
5511                write!(f, "SAVEPOINT ")?;
5512                write!(f, "{name}")
5513            }
5514            Statement::ReleaseSavepoint { name } => {
5515                write!(f, "RELEASE SAVEPOINT {name}")
5516            }
5517            Statement::Merge {
5518                into,
5519                table,
5520                source,
5521                on,
5522                clauses,
5523                output,
5524            } => {
5525                write!(
5526                    f,
5527                    "MERGE{int} {table} USING {source} ",
5528                    int = if *into { " INTO" } else { "" }
5529                )?;
5530                write!(f, "ON {on} ")?;
5531                write!(f, "{}", display_separated(clauses, " "))?;
5532                if let Some(output) = output {
5533                    write!(f, " {output}")?;
5534                }
5535                Ok(())
5536            }
5537            Statement::Cache {
5538                table_name,
5539                table_flag,
5540                has_as,
5541                options,
5542                query,
5543            } => {
5544                if let Some(table_flag) = table_flag {
5545                    write!(f, "CACHE {table_flag} TABLE {table_name}")?;
5546                } else {
5547                    write!(f, "CACHE TABLE {table_name}")?;
5548                }
5549
5550                if !options.is_empty() {
5551                    write!(f, " OPTIONS({})", display_comma_separated(options))?;
5552                }
5553
5554                match (*has_as, query) {
5555                    (true, Some(query)) => write!(f, " AS {query}"),
5556                    (true, None) => f.write_str(" AS"),
5557                    (false, Some(query)) => write!(f, " {query}"),
5558                    (false, None) => Ok(()),
5559                }
5560            }
5561            Statement::UNCache {
5562                table_name,
5563                if_exists,
5564            } => {
5565                if *if_exists {
5566                    write!(f, "UNCACHE TABLE IF EXISTS {table_name}")
5567                } else {
5568                    write!(f, "UNCACHE TABLE {table_name}")
5569                }
5570            }
5571            Statement::CreateSequence {
5572                temporary,
5573                if_not_exists,
5574                name,
5575                data_type,
5576                sequence_options,
5577                owned_by,
5578            } => {
5579                let as_type: String = if let Some(dt) = data_type.as_ref() {
5580                    //Cannot use format!(" AS {}", dt), due to format! is not available in --target thumbv6m-none-eabi
5581                    // " AS ".to_owned() + &dt.to_string()
5582                    [" AS ", &dt.to_string()].concat()
5583                } else {
5584                    "".to_string()
5585                };
5586                write!(
5587                    f,
5588                    "CREATE {temporary}SEQUENCE {if_not_exists}{name}{as_type}",
5589                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
5590                    temporary = if *temporary { "TEMPORARY " } else { "" },
5591                    name = name,
5592                    as_type = as_type
5593                )?;
5594                for sequence_option in sequence_options {
5595                    write!(f, "{sequence_option}")?;
5596                }
5597                if let Some(ob) = owned_by.as_ref() {
5598                    write!(f, " OWNED BY {ob}")?;
5599                }
5600                write!(f, "")
5601            }
5602            Statement::CreateStage {
5603                or_replace,
5604                temporary,
5605                if_not_exists,
5606                name,
5607                stage_params,
5608                directory_table_params,
5609                file_format,
5610                copy_options,
5611                comment,
5612                ..
5613            } => {
5614                write!(
5615                    f,
5616                    "CREATE {or_replace}{temp}STAGE {if_not_exists}{name}{stage_params}",
5617                    temp = if *temporary { "TEMPORARY " } else { "" },
5618                    or_replace = if *or_replace { "OR REPLACE " } else { "" },
5619                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
5620                )?;
5621                if !directory_table_params.options.is_empty() {
5622                    write!(f, " DIRECTORY=({})", directory_table_params)?;
5623                }
5624                if !file_format.options.is_empty() {
5625                    write!(f, " FILE_FORMAT=({})", file_format)?;
5626                }
5627                if !copy_options.options.is_empty() {
5628                    write!(f, " COPY_OPTIONS=({})", copy_options)?;
5629                }
5630                if comment.is_some() {
5631                    write!(f, " COMMENT='{}'", comment.as_ref().unwrap())?;
5632                }
5633                Ok(())
5634            }
5635            Statement::CopyIntoSnowflake {
5636                kind,
5637                into,
5638                into_columns,
5639                from_obj,
5640                from_obj_alias,
5641                stage_params,
5642                from_transformations,
5643                from_query,
5644                files,
5645                pattern,
5646                file_format,
5647                copy_options,
5648                validation_mode,
5649                partition,
5650            } => {
5651                write!(f, "COPY INTO {}", into)?;
5652                if let Some(into_columns) = into_columns {
5653                    write!(f, " ({})", display_comma_separated(into_columns))?;
5654                }
5655                if let Some(from_transformations) = from_transformations {
5656                    // Data load with transformation
5657                    if let Some(from_stage) = from_obj {
5658                        write!(
5659                            f,
5660                            " FROM (SELECT {} FROM {}{}",
5661                            display_separated(from_transformations, ", "),
5662                            from_stage,
5663                            stage_params
5664                        )?;
5665                    }
5666                    if let Some(from_obj_alias) = from_obj_alias {
5667                        write!(f, " AS {}", from_obj_alias)?;
5668                    }
5669                    write!(f, ")")?;
5670                } else if let Some(from_obj) = from_obj {
5671                    // Standard data load
5672                    write!(f, " FROM {}{}", from_obj, stage_params)?;
5673                    if let Some(from_obj_alias) = from_obj_alias {
5674                        write!(f, " AS {from_obj_alias}")?;
5675                    }
5676                } else if let Some(from_query) = from_query {
5677                    // Data unload from query
5678                    write!(f, " FROM ({from_query})")?;
5679                }
5680
5681                if let Some(files) = files {
5682                    write!(f, " FILES = ('{}')", display_separated(files, "', '"))?;
5683                }
5684                if let Some(pattern) = pattern {
5685                    write!(f, " PATTERN = '{}'", pattern)?;
5686                }
5687                if let Some(partition) = partition {
5688                    write!(f, " PARTITION BY {partition}")?;
5689                }
5690                if !file_format.options.is_empty() {
5691                    write!(f, " FILE_FORMAT=({})", file_format)?;
5692                }
5693                if !copy_options.options.is_empty() {
5694                    match kind {
5695                        CopyIntoSnowflakeKind::Table => {
5696                            write!(f, " COPY_OPTIONS=({})", copy_options)?
5697                        }
5698                        CopyIntoSnowflakeKind::Location => write!(f, " {copy_options}")?,
5699                    }
5700                }
5701                if let Some(validation_mode) = validation_mode {
5702                    write!(f, " VALIDATION_MODE = {}", validation_mode)?;
5703                }
5704                Ok(())
5705            }
5706            Statement::CreateType {
5707                name,
5708                representation,
5709            } => {
5710                write!(f, "CREATE TYPE {name} AS {representation}")
5711            }
5712            Statement::Pragma { name, value, is_eq } => {
5713                write!(f, "PRAGMA {name}")?;
5714                if value.is_some() {
5715                    let val = value.as_ref().unwrap();
5716                    if *is_eq {
5717                        write!(f, " = {val}")?;
5718                    } else {
5719                        write!(f, "({val})")?;
5720                    }
5721                }
5722                Ok(())
5723            }
5724            Statement::LockTables { tables } => {
5725                write!(f, "LOCK TABLES {}", display_comma_separated(tables))
5726            }
5727            Statement::UnlockTables => {
5728                write!(f, "UNLOCK TABLES")
5729            }
5730            Statement::Unload { query, to, with } => {
5731                write!(f, "UNLOAD({query}) TO {to}")?;
5732
5733                if !with.is_empty() {
5734                    write!(f, " WITH ({})", display_comma_separated(with))?;
5735                }
5736
5737                Ok(())
5738            }
5739            Statement::OptimizeTable {
5740                name,
5741                on_cluster,
5742                partition,
5743                include_final,
5744                deduplicate,
5745            } => {
5746                write!(f, "OPTIMIZE TABLE {name}")?;
5747                if let Some(on_cluster) = on_cluster {
5748                    write!(f, " ON CLUSTER {on_cluster}", on_cluster = on_cluster)?;
5749                }
5750                if let Some(partition) = partition {
5751                    write!(f, " {partition}", partition = partition)?;
5752                }
5753                if *include_final {
5754                    write!(f, " FINAL")?;
5755                }
5756                if let Some(deduplicate) = deduplicate {
5757                    write!(f, " {deduplicate}")?;
5758                }
5759                Ok(())
5760            }
5761            Statement::LISTEN { channel } => {
5762                write!(f, "LISTEN {channel}")?;
5763                Ok(())
5764            }
5765            Statement::UNLISTEN { channel } => {
5766                write!(f, "UNLISTEN {channel}")?;
5767                Ok(())
5768            }
5769            Statement::NOTIFY { channel, payload } => {
5770                write!(f, "NOTIFY {channel}")?;
5771                if let Some(payload) = payload {
5772                    write!(f, ", '{payload}'")?;
5773                }
5774                Ok(())
5775            }
5776            Statement::RenameTable(rename_tables) => {
5777                write!(f, "RENAME TABLE {}", display_comma_separated(rename_tables))
5778            }
5779            Statement::RaisError {
5780                message,
5781                severity,
5782                state,
5783                arguments,
5784                options,
5785            } => {
5786                write!(f, "RAISERROR({message}, {severity}, {state}")?;
5787                if !arguments.is_empty() {
5788                    write!(f, ", {}", display_comma_separated(arguments))?;
5789                }
5790                write!(f, ")")?;
5791                if !options.is_empty() {
5792                    write!(f, " WITH {}", display_comma_separated(options))?;
5793                }
5794                Ok(())
5795            }
5796            Statement::Print(s) => write!(f, "{s}"),
5797            Statement::Return(r) => write!(f, "{r}"),
5798            Statement::List(command) => write!(f, "LIST {command}"),
5799            Statement::Remove(command) => write!(f, "REMOVE {command}"),
5800        }
5801    }
5802}
5803
5804/// Can use to describe options in create sequence or table column type identity
5805/// ```sql
5806/// [ INCREMENT [ BY ] increment ]
5807///     [ MINVALUE minvalue | NO MINVALUE ] [ MAXVALUE maxvalue | NO MAXVALUE ]
5808///     [ START [ WITH ] start ] [ CACHE cache ] [ [ NO ] CYCLE ]
5809/// ```
5810#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
5811#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
5812#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
5813pub enum SequenceOptions {
5814    IncrementBy(Expr, bool),
5815    MinValue(Option<Expr>),
5816    MaxValue(Option<Expr>),
5817    StartWith(Expr, bool),
5818    Cache(Expr),
5819    Cycle(bool),
5820}
5821
5822impl fmt::Display for SequenceOptions {
5823    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
5824        match self {
5825            SequenceOptions::IncrementBy(increment, by) => {
5826                write!(
5827                    f,
5828                    " INCREMENT{by} {increment}",
5829                    by = if *by { " BY" } else { "" },
5830                    increment = increment
5831                )
5832            }
5833            SequenceOptions::MinValue(Some(expr)) => {
5834                write!(f, " MINVALUE {expr}")
5835            }
5836            SequenceOptions::MinValue(None) => {
5837                write!(f, " NO MINVALUE")
5838            }
5839            SequenceOptions::MaxValue(Some(expr)) => {
5840                write!(f, " MAXVALUE {expr}")
5841            }
5842            SequenceOptions::MaxValue(None) => {
5843                write!(f, " NO MAXVALUE")
5844            }
5845            SequenceOptions::StartWith(start, with) => {
5846                write!(
5847                    f,
5848                    " START{with} {start}",
5849                    with = if *with { " WITH" } else { "" },
5850                    start = start
5851                )
5852            }
5853            SequenceOptions::Cache(cache) => {
5854                write!(f, " CACHE {}", *cache)
5855            }
5856            SequenceOptions::Cycle(no) => {
5857                write!(f, " {}CYCLE", if *no { "NO " } else { "" })
5858            }
5859        }
5860    }
5861}
5862
5863/// Assignment for a `SET` statement (name [=|TO] value)
5864#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
5865#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
5866#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
5867pub struct SetAssignment {
5868    pub scope: Option<ContextModifier>,
5869    pub name: ObjectName,
5870    pub value: Expr,
5871}
5872
5873impl fmt::Display for SetAssignment {
5874    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
5875        write!(
5876            f,
5877            "{}{} = {}",
5878            self.scope.map(|s| format!("{}", s)).unwrap_or_default(),
5879            self.name,
5880            self.value
5881        )
5882    }
5883}
5884
5885/// Target of a `TRUNCATE TABLE` command
5886///
5887/// Note this is its own struct because `visit_relation` requires an `ObjectName` (not a `Vec<ObjectName>`)
5888#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
5889#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
5890#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
5891pub struct TruncateTableTarget {
5892    /// name of the table being truncated
5893    #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
5894    pub name: ObjectName,
5895}
5896
5897impl fmt::Display for TruncateTableTarget {
5898    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
5899        write!(f, "{}", self.name)
5900    }
5901}
5902
5903/// PostgreSQL identity option for TRUNCATE table
5904/// [ RESTART IDENTITY | CONTINUE IDENTITY ]
5905#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
5906#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
5907#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
5908pub enum TruncateIdentityOption {
5909    Restart,
5910    Continue,
5911}
5912
5913/// Cascade/restrict option for Postgres TRUNCATE table, MySQL GRANT/REVOKE, etc.
5914/// [ CASCADE | RESTRICT ]
5915#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
5916#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
5917#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
5918pub enum CascadeOption {
5919    Cascade,
5920    Restrict,
5921}
5922
5923impl Display for CascadeOption {
5924    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
5925        match self {
5926            CascadeOption::Cascade => write!(f, "CASCADE"),
5927            CascadeOption::Restrict => write!(f, "RESTRICT"),
5928        }
5929    }
5930}
5931
5932/// Transaction started with [ TRANSACTION | WORK ]
5933#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
5934#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
5935#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
5936pub enum BeginTransactionKind {
5937    Transaction,
5938    Work,
5939}
5940
5941impl Display for BeginTransactionKind {
5942    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
5943        match self {
5944            BeginTransactionKind::Transaction => write!(f, "TRANSACTION"),
5945            BeginTransactionKind::Work => write!(f, "WORK"),
5946        }
5947    }
5948}
5949
5950/// Can use to describe options in  create sequence or table column type identity
5951/// [ MINVALUE minvalue | NO MINVALUE ] [ MAXVALUE maxvalue | NO MAXVALUE ]
5952#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
5953#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
5954#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
5955pub enum MinMaxValue {
5956    // clause is not specified
5957    Empty,
5958    // NO MINVALUE/NO MAXVALUE
5959    None,
5960    // MINVALUE <expr> / MAXVALUE <expr>
5961    Some(Expr),
5962}
5963
5964#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
5965#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
5966#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
5967#[non_exhaustive]
5968pub enum OnInsert {
5969    /// ON DUPLICATE KEY UPDATE (MySQL when the key already exists, then execute an update instead)
5970    DuplicateKeyUpdate(Vec<Assignment>),
5971    /// ON CONFLICT is a PostgreSQL and Sqlite extension
5972    OnConflict(OnConflict),
5973}
5974
5975#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
5976#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
5977#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
5978pub struct InsertAliases {
5979    pub row_alias: ObjectName,
5980    pub col_aliases: Option<Vec<Ident>>,
5981}
5982
5983#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
5984#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
5985#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
5986pub struct OnConflict {
5987    pub conflict_target: Option<ConflictTarget>,
5988    pub action: OnConflictAction,
5989}
5990#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
5991#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
5992#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
5993pub enum ConflictTarget {
5994    Columns(Vec<Ident>),
5995    OnConstraint(ObjectName),
5996}
5997#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
5998#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
5999#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6000pub enum OnConflictAction {
6001    DoNothing,
6002    DoUpdate(DoUpdate),
6003}
6004
6005#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6006#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6007#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6008pub struct DoUpdate {
6009    /// Column assignments
6010    pub assignments: Vec<Assignment>,
6011    /// WHERE
6012    pub selection: Option<Expr>,
6013}
6014
6015impl fmt::Display for OnInsert {
6016    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6017        match self {
6018            Self::DuplicateKeyUpdate(expr) => write!(
6019                f,
6020                " ON DUPLICATE KEY UPDATE {}",
6021                display_comma_separated(expr)
6022            ),
6023            Self::OnConflict(o) => write!(f, "{o}"),
6024        }
6025    }
6026}
6027impl fmt::Display for OnConflict {
6028    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6029        write!(f, " ON CONFLICT")?;
6030        if let Some(target) = &self.conflict_target {
6031            write!(f, "{target}")?;
6032        }
6033        write!(f, " {}", self.action)
6034    }
6035}
6036impl fmt::Display for ConflictTarget {
6037    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6038        match self {
6039            ConflictTarget::Columns(cols) => write!(f, "({})", display_comma_separated(cols)),
6040            ConflictTarget::OnConstraint(name) => write!(f, " ON CONSTRAINT {name}"),
6041        }
6042    }
6043}
6044impl fmt::Display for OnConflictAction {
6045    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6046        match self {
6047            Self::DoNothing => write!(f, "DO NOTHING"),
6048            Self::DoUpdate(do_update) => {
6049                write!(f, "DO UPDATE")?;
6050                if !do_update.assignments.is_empty() {
6051                    write!(
6052                        f,
6053                        " SET {}",
6054                        display_comma_separated(&do_update.assignments)
6055                    )?;
6056                }
6057                if let Some(selection) = &do_update.selection {
6058                    write!(f, " WHERE {selection}")?;
6059                }
6060                Ok(())
6061            }
6062        }
6063    }
6064}
6065
6066/// Privileges granted in a GRANT statement or revoked in a REVOKE statement.
6067#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6068#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6069#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6070pub enum Privileges {
6071    /// All privileges applicable to the object type
6072    All {
6073        /// Optional keyword from the spec, ignored in practice
6074        with_privileges_keyword: bool,
6075    },
6076    /// Specific privileges (e.g. `SELECT`, `INSERT`)
6077    Actions(Vec<Action>),
6078}
6079
6080impl fmt::Display for Privileges {
6081    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6082        match self {
6083            Privileges::All {
6084                with_privileges_keyword,
6085            } => {
6086                write!(
6087                    f,
6088                    "ALL{}",
6089                    if *with_privileges_keyword {
6090                        " PRIVILEGES"
6091                    } else {
6092                        ""
6093                    }
6094                )
6095            }
6096            Privileges::Actions(actions) => {
6097                write!(f, "{}", display_comma_separated(actions))
6098            }
6099        }
6100    }
6101}
6102
6103/// Specific direction for FETCH statement
6104#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6105#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6106#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6107pub enum FetchDirection {
6108    Count { limit: Value },
6109    Next,
6110    Prior,
6111    First,
6112    Last,
6113    Absolute { limit: Value },
6114    Relative { limit: Value },
6115    All,
6116    // FORWARD
6117    // FORWARD count
6118    Forward { limit: Option<Value> },
6119    ForwardAll,
6120    // BACKWARD
6121    // BACKWARD count
6122    Backward { limit: Option<Value> },
6123    BackwardAll,
6124}
6125
6126impl fmt::Display for FetchDirection {
6127    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6128        match self {
6129            FetchDirection::Count { limit } => f.write_str(&limit.to_string())?,
6130            FetchDirection::Next => f.write_str("NEXT")?,
6131            FetchDirection::Prior => f.write_str("PRIOR")?,
6132            FetchDirection::First => f.write_str("FIRST")?,
6133            FetchDirection::Last => f.write_str("LAST")?,
6134            FetchDirection::Absolute { limit } => {
6135                f.write_str("ABSOLUTE ")?;
6136                f.write_str(&limit.to_string())?;
6137            }
6138            FetchDirection::Relative { limit } => {
6139                f.write_str("RELATIVE ")?;
6140                f.write_str(&limit.to_string())?;
6141            }
6142            FetchDirection::All => f.write_str("ALL")?,
6143            FetchDirection::Forward { limit } => {
6144                f.write_str("FORWARD")?;
6145
6146                if let Some(l) = limit {
6147                    f.write_str(" ")?;
6148                    f.write_str(&l.to_string())?;
6149                }
6150            }
6151            FetchDirection::ForwardAll => f.write_str("FORWARD ALL")?,
6152            FetchDirection::Backward { limit } => {
6153                f.write_str("BACKWARD")?;
6154
6155                if let Some(l) = limit {
6156                    f.write_str(" ")?;
6157                    f.write_str(&l.to_string())?;
6158                }
6159            }
6160            FetchDirection::BackwardAll => f.write_str("BACKWARD ALL")?,
6161        };
6162
6163        Ok(())
6164    }
6165}
6166
6167/// A privilege on a database object (table, sequence, etc.).
6168#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6169#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6170#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6171pub enum Action {
6172    AddSearchOptimization,
6173    Apply {
6174        apply_type: ActionApplyType,
6175    },
6176    ApplyBudget,
6177    AttachListing,
6178    AttachPolicy,
6179    Audit,
6180    BindServiceEndpoint,
6181    Connect,
6182    Create {
6183        obj_type: Option<ActionCreateObjectType>,
6184    },
6185    DatabaseRole {
6186        role: ObjectName,
6187    },
6188    Delete,
6189    EvolveSchema,
6190    Execute {
6191        obj_type: Option<ActionExecuteObjectType>,
6192    },
6193    Failover,
6194    ImportedPrivileges,
6195    ImportShare,
6196    Insert {
6197        columns: Option<Vec<Ident>>,
6198    },
6199    Manage {
6200        manage_type: ActionManageType,
6201    },
6202    ManageReleases,
6203    ManageVersions,
6204    Modify {
6205        modify_type: Option<ActionModifyType>,
6206    },
6207    Monitor {
6208        monitor_type: Option<ActionMonitorType>,
6209    },
6210    Operate,
6211    OverrideShareRestrictions,
6212    Ownership,
6213    PurchaseDataExchangeListing,
6214    Read,
6215    ReadSession,
6216    References {
6217        columns: Option<Vec<Ident>>,
6218    },
6219    Replicate,
6220    ResolveAll,
6221    Role {
6222        role: Ident,
6223    },
6224    Select {
6225        columns: Option<Vec<Ident>>,
6226    },
6227    Temporary,
6228    Trigger,
6229    Truncate,
6230    Update {
6231        columns: Option<Vec<Ident>>,
6232    },
6233    Usage,
6234}
6235
6236impl fmt::Display for Action {
6237    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6238        match self {
6239            Action::AddSearchOptimization => f.write_str("ADD SEARCH OPTIMIZATION")?,
6240            Action::Apply { apply_type } => write!(f, "APPLY {apply_type}")?,
6241            Action::ApplyBudget => f.write_str("APPLYBUDGET")?,
6242            Action::AttachListing => f.write_str("ATTACH LISTING")?,
6243            Action::AttachPolicy => f.write_str("ATTACH POLICY")?,
6244            Action::Audit => f.write_str("AUDIT")?,
6245            Action::BindServiceEndpoint => f.write_str("BIND SERVICE ENDPOINT")?,
6246            Action::Connect => f.write_str("CONNECT")?,
6247            Action::Create { obj_type } => {
6248                f.write_str("CREATE")?;
6249                if let Some(obj_type) = obj_type {
6250                    write!(f, " {obj_type}")?
6251                }
6252            }
6253            Action::DatabaseRole { role } => write!(f, "DATABASE ROLE {role}")?,
6254            Action::Delete => f.write_str("DELETE")?,
6255            Action::EvolveSchema => f.write_str("EVOLVE SCHEMA")?,
6256            Action::Execute { obj_type } => {
6257                f.write_str("EXECUTE")?;
6258                if let Some(obj_type) = obj_type {
6259                    write!(f, " {obj_type}")?
6260                }
6261            }
6262            Action::Failover => f.write_str("FAILOVER")?,
6263            Action::ImportedPrivileges => f.write_str("IMPORTED PRIVILEGES")?,
6264            Action::ImportShare => f.write_str("IMPORT SHARE")?,
6265            Action::Insert { .. } => f.write_str("INSERT")?,
6266            Action::Manage { manage_type } => write!(f, "MANAGE {manage_type}")?,
6267            Action::ManageReleases => f.write_str("MANAGE RELEASES")?,
6268            Action::ManageVersions => f.write_str("MANAGE VERSIONS")?,
6269            Action::Modify { modify_type } => {
6270                write!(f, "MODIFY")?;
6271                if let Some(modify_type) = modify_type {
6272                    write!(f, " {modify_type}")?;
6273                }
6274            }
6275            Action::Monitor { monitor_type } => {
6276                write!(f, "MONITOR")?;
6277                if let Some(monitor_type) = monitor_type {
6278                    write!(f, " {monitor_type}")?
6279                }
6280            }
6281            Action::Operate => f.write_str("OPERATE")?,
6282            Action::OverrideShareRestrictions => f.write_str("OVERRIDE SHARE RESTRICTIONS")?,
6283            Action::Ownership => f.write_str("OWNERSHIP")?,
6284            Action::PurchaseDataExchangeListing => f.write_str("PURCHASE DATA EXCHANGE LISTING")?,
6285            Action::Read => f.write_str("READ")?,
6286            Action::ReadSession => f.write_str("READ SESSION")?,
6287            Action::References { .. } => f.write_str("REFERENCES")?,
6288            Action::Replicate => f.write_str("REPLICATE")?,
6289            Action::ResolveAll => f.write_str("RESOLVE ALL")?,
6290            Action::Role { role } => write!(f, "ROLE {role}")?,
6291            Action::Select { .. } => f.write_str("SELECT")?,
6292            Action::Temporary => f.write_str("TEMPORARY")?,
6293            Action::Trigger => f.write_str("TRIGGER")?,
6294            Action::Truncate => f.write_str("TRUNCATE")?,
6295            Action::Update { .. } => f.write_str("UPDATE")?,
6296            Action::Usage => f.write_str("USAGE")?,
6297        };
6298        match self {
6299            Action::Insert { columns }
6300            | Action::References { columns }
6301            | Action::Select { columns }
6302            | Action::Update { columns } => {
6303                if let Some(columns) = columns {
6304                    write!(f, " ({})", display_comma_separated(columns))?;
6305                }
6306            }
6307            _ => (),
6308        };
6309        Ok(())
6310    }
6311}
6312
6313#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6314#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6315#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6316/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
6317/// under `globalPrivileges` in the `CREATE` privilege.
6318pub enum ActionCreateObjectType {
6319    Account,
6320    Application,
6321    ApplicationPackage,
6322    ComputePool,
6323    DataExchangeListing,
6324    Database,
6325    ExternalVolume,
6326    FailoverGroup,
6327    Integration,
6328    NetworkPolicy,
6329    OrganiationListing,
6330    ReplicationGroup,
6331    Role,
6332    Share,
6333    User,
6334    Warehouse,
6335}
6336
6337impl fmt::Display for ActionCreateObjectType {
6338    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6339        match self {
6340            ActionCreateObjectType::Account => write!(f, "ACCOUNT"),
6341            ActionCreateObjectType::Application => write!(f, "APPLICATION"),
6342            ActionCreateObjectType::ApplicationPackage => write!(f, "APPLICATION PACKAGE"),
6343            ActionCreateObjectType::ComputePool => write!(f, "COMPUTE POOL"),
6344            ActionCreateObjectType::DataExchangeListing => write!(f, "DATA EXCHANGE LISTING"),
6345            ActionCreateObjectType::Database => write!(f, "DATABASE"),
6346            ActionCreateObjectType::ExternalVolume => write!(f, "EXTERNAL VOLUME"),
6347            ActionCreateObjectType::FailoverGroup => write!(f, "FAILOVER GROUP"),
6348            ActionCreateObjectType::Integration => write!(f, "INTEGRATION"),
6349            ActionCreateObjectType::NetworkPolicy => write!(f, "NETWORK POLICY"),
6350            ActionCreateObjectType::OrganiationListing => write!(f, "ORGANIZATION LISTING"),
6351            ActionCreateObjectType::ReplicationGroup => write!(f, "REPLICATION GROUP"),
6352            ActionCreateObjectType::Role => write!(f, "ROLE"),
6353            ActionCreateObjectType::Share => write!(f, "SHARE"),
6354            ActionCreateObjectType::User => write!(f, "USER"),
6355            ActionCreateObjectType::Warehouse => write!(f, "WAREHOUSE"),
6356        }
6357    }
6358}
6359
6360#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6361#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6362#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6363/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
6364/// under `globalPrivileges` in the `APPLY` privilege.
6365pub enum ActionApplyType {
6366    AggregationPolicy,
6367    AuthenticationPolicy,
6368    JoinPolicy,
6369    MaskingPolicy,
6370    PackagesPolicy,
6371    PasswordPolicy,
6372    ProjectionPolicy,
6373    RowAccessPolicy,
6374    SessionPolicy,
6375    Tag,
6376}
6377
6378impl fmt::Display for ActionApplyType {
6379    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6380        match self {
6381            ActionApplyType::AggregationPolicy => write!(f, "AGGREGATION POLICY"),
6382            ActionApplyType::AuthenticationPolicy => write!(f, "AUTHENTICATION POLICY"),
6383            ActionApplyType::JoinPolicy => write!(f, "JOIN POLICY"),
6384            ActionApplyType::MaskingPolicy => write!(f, "MASKING POLICY"),
6385            ActionApplyType::PackagesPolicy => write!(f, "PACKAGES POLICY"),
6386            ActionApplyType::PasswordPolicy => write!(f, "PASSWORD POLICY"),
6387            ActionApplyType::ProjectionPolicy => write!(f, "PROJECTION POLICY"),
6388            ActionApplyType::RowAccessPolicy => write!(f, "ROW ACCESS POLICY"),
6389            ActionApplyType::SessionPolicy => write!(f, "SESSION POLICY"),
6390            ActionApplyType::Tag => write!(f, "TAG"),
6391        }
6392    }
6393}
6394
6395#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6396#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6397#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6398/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
6399/// under `globalPrivileges` in the `EXECUTE` privilege.
6400pub enum ActionExecuteObjectType {
6401    Alert,
6402    DataMetricFunction,
6403    ManagedAlert,
6404    ManagedTask,
6405    Task,
6406}
6407
6408impl fmt::Display for ActionExecuteObjectType {
6409    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6410        match self {
6411            ActionExecuteObjectType::Alert => write!(f, "ALERT"),
6412            ActionExecuteObjectType::DataMetricFunction => write!(f, "DATA METRIC FUNCTION"),
6413            ActionExecuteObjectType::ManagedAlert => write!(f, "MANAGED ALERT"),
6414            ActionExecuteObjectType::ManagedTask => write!(f, "MANAGED TASK"),
6415            ActionExecuteObjectType::Task => write!(f, "TASK"),
6416        }
6417    }
6418}
6419
6420#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6421#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6422#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6423/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
6424/// under `globalPrivileges` in the `MANAGE` privilege.
6425pub enum ActionManageType {
6426    AccountSupportCases,
6427    EventSharing,
6428    Grants,
6429    ListingAutoFulfillment,
6430    OrganizationSupportCases,
6431    UserSupportCases,
6432    Warehouses,
6433}
6434
6435impl fmt::Display for ActionManageType {
6436    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6437        match self {
6438            ActionManageType::AccountSupportCases => write!(f, "ACCOUNT SUPPORT CASES"),
6439            ActionManageType::EventSharing => write!(f, "EVENT SHARING"),
6440            ActionManageType::Grants => write!(f, "GRANTS"),
6441            ActionManageType::ListingAutoFulfillment => write!(f, "LISTING AUTO FULFILLMENT"),
6442            ActionManageType::OrganizationSupportCases => write!(f, "ORGANIZATION SUPPORT CASES"),
6443            ActionManageType::UserSupportCases => write!(f, "USER SUPPORT CASES"),
6444            ActionManageType::Warehouses => write!(f, "WAREHOUSES"),
6445        }
6446    }
6447}
6448
6449#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6450#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6451#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6452/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
6453/// under `globalPrivileges` in the `MODIFY` privilege.
6454pub enum ActionModifyType {
6455    LogLevel,
6456    TraceLevel,
6457    SessionLogLevel,
6458    SessionTraceLevel,
6459}
6460
6461impl fmt::Display for ActionModifyType {
6462    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6463        match self {
6464            ActionModifyType::LogLevel => write!(f, "LOG LEVEL"),
6465            ActionModifyType::TraceLevel => write!(f, "TRACE LEVEL"),
6466            ActionModifyType::SessionLogLevel => write!(f, "SESSION LOG LEVEL"),
6467            ActionModifyType::SessionTraceLevel => write!(f, "SESSION TRACE LEVEL"),
6468        }
6469    }
6470}
6471
6472#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6473#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6474#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6475/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
6476/// under `globalPrivileges` in the `MONITOR` privilege.
6477pub enum ActionMonitorType {
6478    Execution,
6479    Security,
6480    Usage,
6481}
6482
6483impl fmt::Display for ActionMonitorType {
6484    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6485        match self {
6486            ActionMonitorType::Execution => write!(f, "EXECUTION"),
6487            ActionMonitorType::Security => write!(f, "SECURITY"),
6488            ActionMonitorType::Usage => write!(f, "USAGE"),
6489        }
6490    }
6491}
6492
6493/// The principal that receives the privileges
6494#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6495#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6496#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6497pub struct Grantee {
6498    pub grantee_type: GranteesType,
6499    pub name: Option<GranteeName>,
6500}
6501
6502impl fmt::Display for Grantee {
6503    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6504        match self.grantee_type {
6505            GranteesType::Role => {
6506                write!(f, "ROLE ")?;
6507            }
6508            GranteesType::Share => {
6509                write!(f, "SHARE ")?;
6510            }
6511            GranteesType::User => {
6512                write!(f, "USER ")?;
6513            }
6514            GranteesType::Group => {
6515                write!(f, "GROUP ")?;
6516            }
6517            GranteesType::Public => {
6518                write!(f, "PUBLIC ")?;
6519            }
6520            GranteesType::DatabaseRole => {
6521                write!(f, "DATABASE ROLE ")?;
6522            }
6523            GranteesType::Application => {
6524                write!(f, "APPLICATION ")?;
6525            }
6526            GranteesType::ApplicationRole => {
6527                write!(f, "APPLICATION ROLE ")?;
6528            }
6529            GranteesType::None => (),
6530        }
6531        if let Some(ref name) = self.name {
6532            name.fmt(f)?;
6533        }
6534        Ok(())
6535    }
6536}
6537
6538#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6539#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6540#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6541pub enum GranteesType {
6542    Role,
6543    Share,
6544    User,
6545    Group,
6546    Public,
6547    DatabaseRole,
6548    Application,
6549    ApplicationRole,
6550    None,
6551}
6552
6553/// Users/roles designated in a GRANT/REVOKE
6554#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6555#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6556#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6557pub enum GranteeName {
6558    /// A bare identifier
6559    ObjectName(ObjectName),
6560    /// A MySQL user/host pair such as 'root'@'%'
6561    UserHost { user: Ident, host: Ident },
6562}
6563
6564impl fmt::Display for GranteeName {
6565    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6566        match self {
6567            GranteeName::ObjectName(name) => name.fmt(f),
6568            GranteeName::UserHost { user, host } => {
6569                write!(f, "{}@{}", user, host)
6570            }
6571        }
6572    }
6573}
6574
6575/// Objects on which privileges are granted in a GRANT statement.
6576#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6577#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6578#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6579pub enum GrantObjects {
6580    /// Grant privileges on `ALL SEQUENCES IN SCHEMA <schema_name> [, ...]`
6581    AllSequencesInSchema { schemas: Vec<ObjectName> },
6582    /// Grant privileges on `ALL TABLES IN SCHEMA <schema_name> [, ...]`
6583    AllTablesInSchema { schemas: Vec<ObjectName> },
6584    /// Grant privileges on specific databases
6585    Databases(Vec<ObjectName>),
6586    /// Grant privileges on specific schemas
6587    Schemas(Vec<ObjectName>),
6588    /// Grant privileges on specific sequences
6589    Sequences(Vec<ObjectName>),
6590    /// Grant privileges on specific tables
6591    Tables(Vec<ObjectName>),
6592    /// Grant privileges on specific views
6593    Views(Vec<ObjectName>),
6594    /// Grant privileges on specific warehouses
6595    Warehouses(Vec<ObjectName>),
6596    /// Grant privileges on specific integrations
6597    Integrations(Vec<ObjectName>),
6598    /// Grant privileges on resource monitors
6599    ResourceMonitors(Vec<ObjectName>),
6600    /// Grant privileges on users
6601    Users(Vec<ObjectName>),
6602    /// Grant privileges on compute pools
6603    ComputePools(Vec<ObjectName>),
6604    /// Grant privileges on connections
6605    Connections(Vec<ObjectName>),
6606    /// Grant privileges on failover groups
6607    FailoverGroup(Vec<ObjectName>),
6608    /// Grant privileges on replication group
6609    ReplicationGroup(Vec<ObjectName>),
6610    /// Grant privileges on external volumes
6611    ExternalVolumes(Vec<ObjectName>),
6612}
6613
6614impl fmt::Display for GrantObjects {
6615    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6616        match self {
6617            GrantObjects::Sequences(sequences) => {
6618                write!(f, "SEQUENCE {}", display_comma_separated(sequences))
6619            }
6620            GrantObjects::Databases(databases) => {
6621                write!(f, "DATABASE {}", display_comma_separated(databases))
6622            }
6623            GrantObjects::Schemas(schemas) => {
6624                write!(f, "SCHEMA {}", display_comma_separated(schemas))
6625            }
6626            GrantObjects::Tables(tables) => {
6627                write!(f, "{}", display_comma_separated(tables))
6628            }
6629            GrantObjects::Views(views) => {
6630                write!(f, "VIEW {}", display_comma_separated(views))
6631            }
6632            GrantObjects::Warehouses(warehouses) => {
6633                write!(f, "WAREHOUSE {}", display_comma_separated(warehouses))
6634            }
6635            GrantObjects::Integrations(integrations) => {
6636                write!(f, "INTEGRATION {}", display_comma_separated(integrations))
6637            }
6638            GrantObjects::AllSequencesInSchema { schemas } => {
6639                write!(
6640                    f,
6641                    "ALL SEQUENCES IN SCHEMA {}",
6642                    display_comma_separated(schemas)
6643                )
6644            }
6645            GrantObjects::AllTablesInSchema { schemas } => {
6646                write!(
6647                    f,
6648                    "ALL TABLES IN SCHEMA {}",
6649                    display_comma_separated(schemas)
6650                )
6651            }
6652            GrantObjects::ResourceMonitors(objects) => {
6653                write!(f, "RESOURCE MONITOR {}", display_comma_separated(objects))
6654            }
6655            GrantObjects::Users(objects) => {
6656                write!(f, "USER {}", display_comma_separated(objects))
6657            }
6658            GrantObjects::ComputePools(objects) => {
6659                write!(f, "COMPUTE POOL {}", display_comma_separated(objects))
6660            }
6661            GrantObjects::Connections(objects) => {
6662                write!(f, "CONNECTION {}", display_comma_separated(objects))
6663            }
6664            GrantObjects::FailoverGroup(objects) => {
6665                write!(f, "FAILOVER GROUP {}", display_comma_separated(objects))
6666            }
6667            GrantObjects::ReplicationGroup(objects) => {
6668                write!(f, "REPLICATION GROUP {}", display_comma_separated(objects))
6669            }
6670            GrantObjects::ExternalVolumes(objects) => {
6671                write!(f, "EXTERNAL VOLUME {}", display_comma_separated(objects))
6672            }
6673        }
6674    }
6675}
6676
6677/// SQL assignment `foo = expr` as used in SQLUpdate
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 struct Assignment {
6682    pub target: AssignmentTarget,
6683    pub value: Expr,
6684}
6685
6686impl fmt::Display for Assignment {
6687    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6688        write!(f, "{} = {}", self.target, self.value)
6689    }
6690}
6691
6692/// Left-hand side of an assignment in an UPDATE statement,
6693/// e.g. `foo` in `foo = 5` (ColumnName assignment) or
6694/// `(a, b)` in `(a, b) = (1, 2)` (Tuple assignment).
6695#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6696#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6697#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6698pub enum AssignmentTarget {
6699    /// A single column
6700    ColumnName(ObjectName),
6701    /// A tuple of columns
6702    Tuple(Vec<ObjectName>),
6703}
6704
6705impl fmt::Display for AssignmentTarget {
6706    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6707        match self {
6708            AssignmentTarget::ColumnName(column) => write!(f, "{}", column),
6709            AssignmentTarget::Tuple(columns) => write!(f, "({})", display_comma_separated(columns)),
6710        }
6711    }
6712}
6713
6714#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6715#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6716#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6717pub enum FunctionArgExpr {
6718    Expr(Expr),
6719    /// Qualified wildcard, e.g. `alias.*` or `schema.table.*`.
6720    QualifiedWildcard(ObjectName),
6721    /// An unqualified `*`
6722    Wildcard,
6723}
6724
6725impl From<Expr> for FunctionArgExpr {
6726    fn from(wildcard_expr: Expr) -> Self {
6727        match wildcard_expr {
6728            Expr::QualifiedWildcard(prefix, _) => Self::QualifiedWildcard(prefix),
6729            Expr::Wildcard(_) => Self::Wildcard,
6730            expr => Self::Expr(expr),
6731        }
6732    }
6733}
6734
6735impl fmt::Display for FunctionArgExpr {
6736    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6737        match self {
6738            FunctionArgExpr::Expr(expr) => write!(f, "{expr}"),
6739            FunctionArgExpr::QualifiedWildcard(prefix) => write!(f, "{prefix}.*"),
6740            FunctionArgExpr::Wildcard => f.write_str("*"),
6741        }
6742    }
6743}
6744
6745#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6746#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6747#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6748/// Operator used to separate function arguments
6749pub enum FunctionArgOperator {
6750    /// function(arg1 = value1)
6751    Equals,
6752    /// function(arg1 => value1)
6753    RightArrow,
6754    /// function(arg1 := value1)
6755    Assignment,
6756    /// function(arg1 : value1)
6757    Colon,
6758    /// function(arg1 VALUE value1)
6759    Value,
6760}
6761
6762impl fmt::Display for FunctionArgOperator {
6763    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6764        match self {
6765            FunctionArgOperator::Equals => f.write_str("="),
6766            FunctionArgOperator::RightArrow => f.write_str("=>"),
6767            FunctionArgOperator::Assignment => f.write_str(":="),
6768            FunctionArgOperator::Colon => f.write_str(":"),
6769            FunctionArgOperator::Value => f.write_str("VALUE"),
6770        }
6771    }
6772}
6773
6774#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6775#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6776#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6777pub enum FunctionArg {
6778    /// `name` is identifier
6779    ///
6780    /// Enabled when `Dialect::supports_named_fn_args_with_expr_name` returns 'false'
6781    Named {
6782        name: Ident,
6783        arg: FunctionArgExpr,
6784        operator: FunctionArgOperator,
6785    },
6786    /// `name` is arbitrary expression
6787    ///
6788    /// Enabled when `Dialect::supports_named_fn_args_with_expr_name` returns 'true'
6789    ExprNamed {
6790        name: Expr,
6791        arg: FunctionArgExpr,
6792        operator: FunctionArgOperator,
6793    },
6794    Unnamed(FunctionArgExpr),
6795}
6796
6797impl fmt::Display for FunctionArg {
6798    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6799        match self {
6800            FunctionArg::Named {
6801                name,
6802                arg,
6803                operator,
6804            } => write!(f, "{name} {operator} {arg}"),
6805            FunctionArg::ExprNamed {
6806                name,
6807                arg,
6808                operator,
6809            } => write!(f, "{name} {operator} {arg}"),
6810            FunctionArg::Unnamed(unnamed_arg) => write!(f, "{unnamed_arg}"),
6811        }
6812    }
6813}
6814
6815#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6816#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6817#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6818pub enum CloseCursor {
6819    All,
6820    Specific { name: Ident },
6821}
6822
6823impl fmt::Display for CloseCursor {
6824    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6825        match self {
6826            CloseCursor::All => write!(f, "ALL"),
6827            CloseCursor::Specific { name } => write!(f, "{name}"),
6828        }
6829    }
6830}
6831
6832/// A function call
6833#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6834#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6835#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6836pub struct Function {
6837    pub name: ObjectName,
6838    /// Flags whether this function call uses the [ODBC syntax].
6839    ///
6840    /// Example:
6841    /// ```sql
6842    /// SELECT {fn CONCAT('foo', 'bar')}
6843    /// ```
6844    ///
6845    /// [ODBC syntax]: https://learn.microsoft.com/en-us/sql/odbc/reference/develop-app/scalar-function-calls?view=sql-server-2017
6846    pub uses_odbc_syntax: bool,
6847    /// The parameters to the function, including any options specified within the
6848    /// delimiting parentheses.
6849    ///
6850    /// Example:
6851    /// ```plaintext
6852    /// HISTOGRAM(0.5, 0.6)(x, y)
6853    /// ```
6854    ///
6855    /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/aggregate-functions/parametric-functions)
6856    pub parameters: FunctionArguments,
6857    /// The arguments to the function, including any options specified within the
6858    /// delimiting parentheses.
6859    pub args: FunctionArguments,
6860    /// e.g. `x > 5` in `COUNT(x) FILTER (WHERE x > 5)`
6861    pub filter: Option<Box<Expr>>,
6862    /// Indicates how `NULL`s should be handled in the calculation.
6863    ///
6864    /// Example:
6865    /// ```plaintext
6866    /// FIRST_VALUE( <expr> ) [ { IGNORE | RESPECT } NULLS ] OVER ...
6867    /// ```
6868    ///
6869    /// [Snowflake](https://docs.snowflake.com/en/sql-reference/functions/first_value)
6870    pub null_treatment: Option<NullTreatment>,
6871    /// The `OVER` clause, indicating a window function call.
6872    pub over: Option<WindowType>,
6873    /// A clause used with certain aggregate functions to control the ordering
6874    /// within grouped sets before the function is applied.
6875    ///
6876    /// Syntax:
6877    /// ```plaintext
6878    /// <aggregate_function>(expression) WITHIN GROUP (ORDER BY key [ASC | DESC], ...)
6879    /// ```
6880    pub within_group: Vec<OrderByExpr>,
6881}
6882
6883impl fmt::Display for Function {
6884    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6885        if self.uses_odbc_syntax {
6886            write!(f, "{{fn ")?;
6887        }
6888
6889        write!(f, "{}{}{}", self.name, self.parameters, self.args)?;
6890
6891        if !self.within_group.is_empty() {
6892            write!(
6893                f,
6894                " WITHIN GROUP (ORDER BY {})",
6895                display_comma_separated(&self.within_group)
6896            )?;
6897        }
6898
6899        if let Some(filter_cond) = &self.filter {
6900            write!(f, " FILTER (WHERE {filter_cond})")?;
6901        }
6902
6903        if let Some(null_treatment) = &self.null_treatment {
6904            write!(f, " {null_treatment}")?;
6905        }
6906
6907        if let Some(o) = &self.over {
6908            write!(f, " OVER {o}")?;
6909        }
6910
6911        if self.uses_odbc_syntax {
6912            write!(f, "}}")?;
6913        }
6914
6915        Ok(())
6916    }
6917}
6918
6919/// The arguments passed to a function call.
6920#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6921#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6922#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6923pub enum FunctionArguments {
6924    /// Used for special functions like `CURRENT_TIMESTAMP` that are invoked
6925    /// without parentheses.
6926    None,
6927    /// On some dialects, a subquery can be passed without surrounding
6928    /// parentheses if it's the sole argument to the function.
6929    Subquery(Box<Query>),
6930    /// A normal function argument list, including any clauses within it such as
6931    /// `DISTINCT` or `ORDER BY`.
6932    List(FunctionArgumentList),
6933}
6934
6935impl fmt::Display for FunctionArguments {
6936    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
6937        match self {
6938            FunctionArguments::None => Ok(()),
6939            FunctionArguments::Subquery(query) => write!(f, "({})", query),
6940            FunctionArguments::List(args) => write!(f, "({})", args),
6941        }
6942    }
6943}
6944
6945/// This represents everything inside the parentheses when calling a function.
6946#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6947#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6948#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6949pub struct FunctionArgumentList {
6950    /// `[ ALL | DISTINCT ]`
6951    pub duplicate_treatment: Option<DuplicateTreatment>,
6952    /// The function arguments.
6953    pub args: Vec<FunctionArg>,
6954    /// Additional clauses specified within the argument list.
6955    pub clauses: Vec<FunctionArgumentClause>,
6956}
6957
6958impl fmt::Display for FunctionArgumentList {
6959    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6960        if let Some(duplicate_treatment) = self.duplicate_treatment {
6961            write!(f, "{} ", duplicate_treatment)?;
6962        }
6963        write!(f, "{}", display_comma_separated(&self.args))?;
6964        if !self.clauses.is_empty() {
6965            if !self.args.is_empty() {
6966                write!(f, " ")?;
6967            }
6968            write!(f, "{}", display_separated(&self.clauses, " "))?;
6969        }
6970        Ok(())
6971    }
6972}
6973
6974#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6975#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6976#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6977pub enum FunctionArgumentClause {
6978    /// Indicates how `NULL`s should be handled in the calculation, e.g. in `FIRST_VALUE` on [BigQuery].
6979    ///
6980    /// Syntax:
6981    /// ```plaintext
6982    /// { IGNORE | RESPECT } NULLS ]
6983    /// ```
6984    ///
6985    /// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/navigation_functions#first_value
6986    IgnoreOrRespectNulls(NullTreatment),
6987    /// Specifies the the ordering for some ordered set aggregates, e.g. `ARRAY_AGG` on [BigQuery].
6988    ///
6989    /// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/aggregate_functions#array_agg
6990    OrderBy(Vec<OrderByExpr>),
6991    /// Specifies a limit for the `ARRAY_AGG` and `ARRAY_CONCAT_AGG` functions on BigQuery.
6992    Limit(Expr),
6993    /// Specifies the behavior on overflow of the `LISTAGG` function.
6994    ///
6995    /// See <https://trino.io/docs/current/functions/aggregate.html>.
6996    OnOverflow(ListAggOnOverflow),
6997    /// Specifies a minimum or maximum bound on the input to [`ANY_VALUE`] on BigQuery.
6998    ///
6999    /// Syntax:
7000    /// ```plaintext
7001    /// HAVING { MAX | MIN } expression
7002    /// ```
7003    ///
7004    /// [`ANY_VALUE`]: https://cloud.google.com/bigquery/docs/reference/standard-sql/aggregate_functions#any_value
7005    Having(HavingBound),
7006    /// The `SEPARATOR` clause to the [`GROUP_CONCAT`] function in MySQL.
7007    ///
7008    /// [`GROUP_CONCAT`]: https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html#function_group-concat
7009    Separator(Value),
7010    /// The json-null-clause to the [`JSON_ARRAY`]/[`JSON_OBJECT`] function in MSSQL.
7011    ///
7012    /// [`JSON_ARRAY`]: <https://learn.microsoft.com/en-us/sql/t-sql/functions/json-array-transact-sql?view=sql-server-ver16>
7013    /// [`JSON_OBJECT`]: <https://learn.microsoft.com/en-us/sql/t-sql/functions/json-object-transact-sql?view=sql-server-ver16>
7014    JsonNullClause(JsonNullClause),
7015}
7016
7017impl fmt::Display for FunctionArgumentClause {
7018    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
7019        match self {
7020            FunctionArgumentClause::IgnoreOrRespectNulls(null_treatment) => {
7021                write!(f, "{}", null_treatment)
7022            }
7023            FunctionArgumentClause::OrderBy(order_by) => {
7024                write!(f, "ORDER BY {}", display_comma_separated(order_by))
7025            }
7026            FunctionArgumentClause::Limit(limit) => write!(f, "LIMIT {limit}"),
7027            FunctionArgumentClause::OnOverflow(on_overflow) => write!(f, "{on_overflow}"),
7028            FunctionArgumentClause::Having(bound) => write!(f, "{bound}"),
7029            FunctionArgumentClause::Separator(sep) => write!(f, "SEPARATOR {sep}"),
7030            FunctionArgumentClause::JsonNullClause(null_clause) => write!(f, "{null_clause}"),
7031        }
7032    }
7033}
7034
7035/// A method call
7036#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7037#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7038#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7039pub struct Method {
7040    pub expr: Box<Expr>,
7041    // always non-empty
7042    pub method_chain: Vec<Function>,
7043}
7044
7045impl fmt::Display for Method {
7046    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7047        write!(
7048            f,
7049            "{}.{}",
7050            self.expr,
7051            display_separated(&self.method_chain, ".")
7052        )
7053    }
7054}
7055
7056#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7057#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7058#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7059pub enum DuplicateTreatment {
7060    /// Perform the calculation only unique values.
7061    Distinct,
7062    /// Retain all duplicate values (the default).
7063    All,
7064}
7065
7066impl fmt::Display for DuplicateTreatment {
7067    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
7068        match self {
7069            DuplicateTreatment::Distinct => write!(f, "DISTINCT"),
7070            DuplicateTreatment::All => write!(f, "ALL"),
7071        }
7072    }
7073}
7074
7075#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7076#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7077#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7078pub enum AnalyzeFormat {
7079    TEXT,
7080    GRAPHVIZ,
7081    JSON,
7082}
7083
7084impl fmt::Display for AnalyzeFormat {
7085    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
7086        f.write_str(match self {
7087            AnalyzeFormat::TEXT => "TEXT",
7088            AnalyzeFormat::GRAPHVIZ => "GRAPHVIZ",
7089            AnalyzeFormat::JSON => "JSON",
7090        })
7091    }
7092}
7093
7094/// External table's available file format
7095#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7096#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7097#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7098pub enum FileFormat {
7099    TEXTFILE,
7100    SEQUENCEFILE,
7101    ORC,
7102    PARQUET,
7103    AVRO,
7104    RCFILE,
7105    JSONFILE,
7106}
7107
7108impl fmt::Display for FileFormat {
7109    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7110        use self::FileFormat::*;
7111        f.write_str(match self {
7112            TEXTFILE => "TEXTFILE",
7113            SEQUENCEFILE => "SEQUENCEFILE",
7114            ORC => "ORC",
7115            PARQUET => "PARQUET",
7116            AVRO => "AVRO",
7117            RCFILE => "RCFILE",
7118            JSONFILE => "JSONFILE",
7119        })
7120    }
7121}
7122
7123/// The `ON OVERFLOW` clause of a LISTAGG invocation
7124#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7125#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7126#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7127pub enum ListAggOnOverflow {
7128    /// `ON OVERFLOW ERROR`
7129    Error,
7130
7131    /// `ON OVERFLOW TRUNCATE [ <filler> ] WITH[OUT] COUNT`
7132    Truncate {
7133        filler: Option<Box<Expr>>,
7134        with_count: bool,
7135    },
7136}
7137
7138impl fmt::Display for ListAggOnOverflow {
7139    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7140        write!(f, "ON OVERFLOW")?;
7141        match self {
7142            ListAggOnOverflow::Error => write!(f, " ERROR"),
7143            ListAggOnOverflow::Truncate { filler, with_count } => {
7144                write!(f, " TRUNCATE")?;
7145                if let Some(filler) = filler {
7146                    write!(f, " {filler}")?;
7147                }
7148                if *with_count {
7149                    write!(f, " WITH")?;
7150                } else {
7151                    write!(f, " WITHOUT")?;
7152                }
7153                write!(f, " COUNT")
7154            }
7155        }
7156    }
7157}
7158
7159/// The `HAVING` clause in a call to `ANY_VALUE` on BigQuery.
7160#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7161#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7162#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7163pub struct HavingBound(pub HavingBoundKind, pub Expr);
7164
7165impl fmt::Display for HavingBound {
7166    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
7167        write!(f, "HAVING {} {}", self.0, self.1)
7168    }
7169}
7170
7171#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7172#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7173#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7174pub enum HavingBoundKind {
7175    Min,
7176    Max,
7177}
7178
7179impl fmt::Display for HavingBoundKind {
7180    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
7181        match self {
7182            HavingBoundKind::Min => write!(f, "MIN"),
7183            HavingBoundKind::Max => write!(f, "MAX"),
7184        }
7185    }
7186}
7187
7188#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7189#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7190#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7191pub enum ObjectType {
7192    Table,
7193    View,
7194    MaterializedView,
7195    Index,
7196    Schema,
7197    Database,
7198    Role,
7199    Sequence,
7200    Stage,
7201    Type,
7202}
7203
7204impl fmt::Display for ObjectType {
7205    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7206        f.write_str(match self {
7207            ObjectType::Table => "TABLE",
7208            ObjectType::View => "VIEW",
7209            ObjectType::MaterializedView => "MATERIALIZED VIEW",
7210            ObjectType::Index => "INDEX",
7211            ObjectType::Schema => "SCHEMA",
7212            ObjectType::Database => "DATABASE",
7213            ObjectType::Role => "ROLE",
7214            ObjectType::Sequence => "SEQUENCE",
7215            ObjectType::Stage => "STAGE",
7216            ObjectType::Type => "TYPE",
7217        })
7218    }
7219}
7220
7221#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7222#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7223#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7224pub enum KillType {
7225    Connection,
7226    Query,
7227    Mutation,
7228}
7229
7230impl fmt::Display for KillType {
7231    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7232        f.write_str(match self {
7233            // MySQL
7234            KillType::Connection => "CONNECTION",
7235            KillType::Query => "QUERY",
7236            // Clickhouse supports Mutation
7237            KillType::Mutation => "MUTATION",
7238        })
7239    }
7240}
7241
7242#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7243#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7244#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7245pub enum HiveDistributionStyle {
7246    PARTITIONED {
7247        columns: Vec<ColumnDef>,
7248    },
7249    SKEWED {
7250        columns: Vec<ColumnDef>,
7251        on: Vec<ColumnDef>,
7252        stored_as_directories: bool,
7253    },
7254    NONE,
7255}
7256
7257#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7258#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7259#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7260pub enum HiveRowFormat {
7261    SERDE { class: String },
7262    DELIMITED { delimiters: Vec<HiveRowDelimiter> },
7263}
7264
7265#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7266#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7267#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7268pub struct HiveLoadDataFormat {
7269    pub serde: Expr,
7270    pub input_format: Expr,
7271}
7272
7273#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7274#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7275#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7276pub struct HiveRowDelimiter {
7277    pub delimiter: HiveDelimiter,
7278    pub char: Ident,
7279}
7280
7281impl fmt::Display for HiveRowDelimiter {
7282    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
7283        write!(f, "{} ", self.delimiter)?;
7284        write!(f, "{}", self.char)
7285    }
7286}
7287
7288#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7289#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7290#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7291pub enum HiveDelimiter {
7292    FieldsTerminatedBy,
7293    FieldsEscapedBy,
7294    CollectionItemsTerminatedBy,
7295    MapKeysTerminatedBy,
7296    LinesTerminatedBy,
7297    NullDefinedAs,
7298}
7299
7300impl fmt::Display for HiveDelimiter {
7301    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
7302        use HiveDelimiter::*;
7303        f.write_str(match self {
7304            FieldsTerminatedBy => "FIELDS TERMINATED BY",
7305            FieldsEscapedBy => "ESCAPED BY",
7306            CollectionItemsTerminatedBy => "COLLECTION ITEMS TERMINATED BY",
7307            MapKeysTerminatedBy => "MAP KEYS TERMINATED BY",
7308            LinesTerminatedBy => "LINES TERMINATED BY",
7309            NullDefinedAs => "NULL DEFINED AS",
7310        })
7311    }
7312}
7313
7314#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7315#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7316#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7317pub enum HiveDescribeFormat {
7318    Extended,
7319    Formatted,
7320}
7321
7322impl fmt::Display for HiveDescribeFormat {
7323    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
7324        use HiveDescribeFormat::*;
7325        f.write_str(match self {
7326            Extended => "EXTENDED",
7327            Formatted => "FORMATTED",
7328        })
7329    }
7330}
7331
7332#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7333#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7334#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7335pub enum DescribeAlias {
7336    Describe,
7337    Explain,
7338    Desc,
7339}
7340
7341impl fmt::Display for DescribeAlias {
7342    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
7343        use DescribeAlias::*;
7344        f.write_str(match self {
7345            Describe => "DESCRIBE",
7346            Explain => "EXPLAIN",
7347            Desc => "DESC",
7348        })
7349    }
7350}
7351
7352#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7353#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7354#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7355#[allow(clippy::large_enum_variant)]
7356pub enum HiveIOFormat {
7357    IOF {
7358        input_format: Expr,
7359        output_format: Expr,
7360    },
7361    FileFormat {
7362        format: FileFormat,
7363    },
7364}
7365
7366#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Default)]
7367#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7368#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7369pub struct HiveFormat {
7370    pub row_format: Option<HiveRowFormat>,
7371    pub serde_properties: Option<Vec<SqlOption>>,
7372    pub storage: Option<HiveIOFormat>,
7373    pub location: Option<String>,
7374}
7375
7376#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7377#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7378#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7379pub struct ClusteredIndex {
7380    pub name: Ident,
7381    pub asc: Option<bool>,
7382}
7383
7384impl fmt::Display for ClusteredIndex {
7385    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7386        write!(f, "{}", self.name)?;
7387        match self.asc {
7388            Some(true) => write!(f, " ASC"),
7389            Some(false) => write!(f, " DESC"),
7390            _ => Ok(()),
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 TableOptionsClustered {
7399    ColumnstoreIndex,
7400    ColumnstoreIndexOrder(Vec<Ident>),
7401    Index(Vec<ClusteredIndex>),
7402}
7403
7404impl fmt::Display for TableOptionsClustered {
7405    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7406        match self {
7407            TableOptionsClustered::ColumnstoreIndex => {
7408                write!(f, "CLUSTERED COLUMNSTORE INDEX")
7409            }
7410            TableOptionsClustered::ColumnstoreIndexOrder(values) => {
7411                write!(
7412                    f,
7413                    "CLUSTERED COLUMNSTORE INDEX ORDER ({})",
7414                    display_comma_separated(values)
7415                )
7416            }
7417            TableOptionsClustered::Index(values) => {
7418                write!(f, "CLUSTERED INDEX ({})", display_comma_separated(values))
7419            }
7420        }
7421    }
7422}
7423
7424/// Specifies which partition the boundary values on table partitioning belongs to.
7425#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7426#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7427#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7428pub enum PartitionRangeDirection {
7429    Left,
7430    Right,
7431}
7432
7433#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7434#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7435#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7436pub enum SqlOption {
7437    /// Clustered represents the clustered version of table storage for MSSQL.
7438    ///
7439    /// <https://learn.microsoft.com/en-us/sql/t-sql/statements/create-table-azure-sql-data-warehouse?view=aps-pdw-2016-au7#TableOptions>
7440    Clustered(TableOptionsClustered),
7441    /// Single identifier options, e.g. `HEAP` for MSSQL.
7442    ///
7443    /// <https://learn.microsoft.com/en-us/sql/t-sql/statements/create-table-azure-sql-data-warehouse?view=aps-pdw-2016-au7#TableOptions>
7444    Ident(Ident),
7445    /// Any option that consists of a key value pair where the value is an expression. e.g.
7446    ///
7447    ///   WITH(DISTRIBUTION = ROUND_ROBIN)
7448    KeyValue { key: Ident, value: Expr },
7449    /// One or more table partitions and represents which partition the boundary values belong to,
7450    /// e.g.
7451    ///
7452    ///   PARTITION (id RANGE LEFT FOR VALUES (10, 20, 30, 40))
7453    ///
7454    /// <https://learn.microsoft.com/en-us/sql/t-sql/statements/create-table-azure-sql-data-warehouse?view=aps-pdw-2016-au7#TablePartitionOptions>
7455    Partition {
7456        column_name: Ident,
7457        range_direction: Option<PartitionRangeDirection>,
7458        for_values: Vec<Expr>,
7459    },
7460}
7461
7462impl fmt::Display for SqlOption {
7463    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7464        match self {
7465            SqlOption::Clustered(c) => write!(f, "{}", c),
7466            SqlOption::Ident(ident) => {
7467                write!(f, "{}", ident)
7468            }
7469            SqlOption::KeyValue { key: name, value } => {
7470                write!(f, "{} = {}", name, value)
7471            }
7472            SqlOption::Partition {
7473                column_name,
7474                range_direction,
7475                for_values,
7476            } => {
7477                let direction = match range_direction {
7478                    Some(PartitionRangeDirection::Left) => " LEFT",
7479                    Some(PartitionRangeDirection::Right) => " RIGHT",
7480                    None => "",
7481                };
7482
7483                write!(
7484                    f,
7485                    "PARTITION ({} RANGE{} FOR VALUES ({}))",
7486                    column_name,
7487                    direction,
7488                    display_comma_separated(for_values)
7489                )
7490            }
7491        }
7492    }
7493}
7494
7495#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7496#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7497#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7498pub struct SecretOption {
7499    pub key: Ident,
7500    pub value: Ident,
7501}
7502
7503impl fmt::Display for SecretOption {
7504    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7505        write!(f, "{} {}", self.key, self.value)
7506    }
7507}
7508
7509#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7510#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7511#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7512pub enum AttachDuckDBDatabaseOption {
7513    ReadOnly(Option<bool>),
7514    Type(Ident),
7515}
7516
7517impl fmt::Display for AttachDuckDBDatabaseOption {
7518    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7519        match self {
7520            AttachDuckDBDatabaseOption::ReadOnly(Some(true)) => write!(f, "READ_ONLY true"),
7521            AttachDuckDBDatabaseOption::ReadOnly(Some(false)) => write!(f, "READ_ONLY false"),
7522            AttachDuckDBDatabaseOption::ReadOnly(None) => write!(f, "READ_ONLY"),
7523            AttachDuckDBDatabaseOption::Type(t) => write!(f, "TYPE {}", t),
7524        }
7525    }
7526}
7527
7528#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7529#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7530#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7531pub enum TransactionMode {
7532    AccessMode(TransactionAccessMode),
7533    IsolationLevel(TransactionIsolationLevel),
7534}
7535
7536impl fmt::Display for TransactionMode {
7537    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7538        use TransactionMode::*;
7539        match self {
7540            AccessMode(access_mode) => write!(f, "{access_mode}"),
7541            IsolationLevel(iso_level) => write!(f, "ISOLATION LEVEL {iso_level}"),
7542        }
7543    }
7544}
7545
7546#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7547#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7548#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7549pub enum TransactionAccessMode {
7550    ReadOnly,
7551    ReadWrite,
7552}
7553
7554impl fmt::Display for TransactionAccessMode {
7555    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7556        use TransactionAccessMode::*;
7557        f.write_str(match self {
7558            ReadOnly => "READ ONLY",
7559            ReadWrite => "READ WRITE",
7560        })
7561    }
7562}
7563
7564#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7565#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7566#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7567pub enum TransactionIsolationLevel {
7568    ReadUncommitted,
7569    ReadCommitted,
7570    RepeatableRead,
7571    Serializable,
7572    Snapshot,
7573}
7574
7575impl fmt::Display for TransactionIsolationLevel {
7576    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7577        use TransactionIsolationLevel::*;
7578        f.write_str(match self {
7579            ReadUncommitted => "READ UNCOMMITTED",
7580            ReadCommitted => "READ COMMITTED",
7581            RepeatableRead => "REPEATABLE READ",
7582            Serializable => "SERIALIZABLE",
7583            Snapshot => "SNAPSHOT",
7584        })
7585    }
7586}
7587
7588/// Modifier for the transaction in the `BEGIN` syntax
7589///
7590/// SQLite: <https://sqlite.org/lang_transaction.html>
7591/// MS-SQL: <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/try-catch-transact-sql>
7592#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7593#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7594#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7595pub enum TransactionModifier {
7596    Deferred,
7597    Immediate,
7598    Exclusive,
7599    Try,
7600    Catch,
7601}
7602
7603impl fmt::Display for TransactionModifier {
7604    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7605        use TransactionModifier::*;
7606        f.write_str(match self {
7607            Deferred => "DEFERRED",
7608            Immediate => "IMMEDIATE",
7609            Exclusive => "EXCLUSIVE",
7610            Try => "TRY",
7611            Catch => "CATCH",
7612        })
7613    }
7614}
7615
7616#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7617#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7618#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7619pub enum ShowStatementFilter {
7620    Like(String),
7621    ILike(String),
7622    Where(Expr),
7623    NoKeyword(String),
7624}
7625
7626impl fmt::Display for ShowStatementFilter {
7627    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7628        use ShowStatementFilter::*;
7629        match self {
7630            Like(pattern) => write!(f, "LIKE '{}'", value::escape_single_quote_string(pattern)),
7631            ILike(pattern) => write!(f, "ILIKE {}", value::escape_single_quote_string(pattern)),
7632            Where(expr) => write!(f, "WHERE {expr}"),
7633            NoKeyword(pattern) => write!(f, "'{}'", value::escape_single_quote_string(pattern)),
7634        }
7635    }
7636}
7637
7638#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7639#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7640#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7641pub enum ShowStatementInClause {
7642    IN,
7643    FROM,
7644}
7645
7646impl fmt::Display for ShowStatementInClause {
7647    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7648        use ShowStatementInClause::*;
7649        match self {
7650            FROM => write!(f, "FROM"),
7651            IN => write!(f, "IN"),
7652        }
7653    }
7654}
7655
7656/// Sqlite specific syntax
7657///
7658/// See [Sqlite documentation](https://sqlite.org/lang_conflict.html)
7659/// for more details.
7660#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7661#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7662#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7663pub enum SqliteOnConflict {
7664    Rollback,
7665    Abort,
7666    Fail,
7667    Ignore,
7668    Replace,
7669}
7670
7671impl fmt::Display for SqliteOnConflict {
7672    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7673        use SqliteOnConflict::*;
7674        match self {
7675            Rollback => write!(f, "OR ROLLBACK"),
7676            Abort => write!(f, "OR ABORT"),
7677            Fail => write!(f, "OR FAIL"),
7678            Ignore => write!(f, "OR IGNORE"),
7679            Replace => write!(f, "OR REPLACE"),
7680        }
7681    }
7682}
7683
7684/// Mysql specific syntax
7685///
7686/// See [Mysql documentation](https://dev.mysql.com/doc/refman/8.0/en/replace.html)
7687/// See [Mysql documentation](https://dev.mysql.com/doc/refman/8.0/en/insert.html)
7688/// for more details.
7689#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7690#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7691#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7692pub enum MysqlInsertPriority {
7693    LowPriority,
7694    Delayed,
7695    HighPriority,
7696}
7697
7698impl fmt::Display for crate::ast::MysqlInsertPriority {
7699    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7700        use MysqlInsertPriority::*;
7701        match self {
7702            LowPriority => write!(f, "LOW_PRIORITY"),
7703            Delayed => write!(f, "DELAYED"),
7704            HighPriority => write!(f, "HIGH_PRIORITY"),
7705        }
7706    }
7707}
7708
7709#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7710#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7711#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7712pub enum CopySource {
7713    Table {
7714        /// The name of the table to copy from.
7715        table_name: ObjectName,
7716        /// A list of column names to copy. Empty list means that all columns
7717        /// are copied.
7718        columns: Vec<Ident>,
7719    },
7720    Query(Box<Query>),
7721}
7722
7723#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7724#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7725#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7726pub enum CopyTarget {
7727    Stdin,
7728    Stdout,
7729    File {
7730        /// The path name of the input or output file.
7731        filename: String,
7732    },
7733    Program {
7734        /// A command to execute
7735        command: String,
7736    },
7737}
7738
7739impl fmt::Display for CopyTarget {
7740    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7741        use CopyTarget::*;
7742        match self {
7743            Stdin => write!(f, "STDIN"),
7744            Stdout => write!(f, "STDOUT"),
7745            File { filename } => write!(f, "'{}'", value::escape_single_quote_string(filename)),
7746            Program { command } => write!(
7747                f,
7748                "PROGRAM '{}'",
7749                value::escape_single_quote_string(command)
7750            ),
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 OnCommit {
7759    DeleteRows,
7760    PreserveRows,
7761    Drop,
7762}
7763
7764/// An option in `COPY` statement.
7765///
7766/// <https://www.postgresql.org/docs/14/sql-copy.html>
7767#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7768#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7769#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7770pub enum CopyOption {
7771    /// FORMAT format_name
7772    Format(Ident),
7773    /// FREEZE \[ boolean \]
7774    Freeze(bool),
7775    /// DELIMITER 'delimiter_character'
7776    Delimiter(char),
7777    /// NULL 'null_string'
7778    Null(String),
7779    /// HEADER \[ boolean \]
7780    Header(bool),
7781    /// QUOTE 'quote_character'
7782    Quote(char),
7783    /// ESCAPE 'escape_character'
7784    Escape(char),
7785    /// FORCE_QUOTE { ( column_name [, ...] ) | * }
7786    ForceQuote(Vec<Ident>),
7787    /// FORCE_NOT_NULL ( column_name [, ...] )
7788    ForceNotNull(Vec<Ident>),
7789    /// FORCE_NULL ( column_name [, ...] )
7790    ForceNull(Vec<Ident>),
7791    /// ENCODING 'encoding_name'
7792    Encoding(String),
7793}
7794
7795impl fmt::Display for CopyOption {
7796    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7797        use CopyOption::*;
7798        match self {
7799            Format(name) => write!(f, "FORMAT {name}"),
7800            Freeze(true) => write!(f, "FREEZE"),
7801            Freeze(false) => write!(f, "FREEZE FALSE"),
7802            Delimiter(char) => write!(f, "DELIMITER '{char}'"),
7803            Null(string) => write!(f, "NULL '{}'", value::escape_single_quote_string(string)),
7804            Header(true) => write!(f, "HEADER"),
7805            Header(false) => write!(f, "HEADER FALSE"),
7806            Quote(char) => write!(f, "QUOTE '{char}'"),
7807            Escape(char) => write!(f, "ESCAPE '{char}'"),
7808            ForceQuote(columns) => write!(f, "FORCE_QUOTE ({})", display_comma_separated(columns)),
7809            ForceNotNull(columns) => {
7810                write!(f, "FORCE_NOT_NULL ({})", display_comma_separated(columns))
7811            }
7812            ForceNull(columns) => write!(f, "FORCE_NULL ({})", display_comma_separated(columns)),
7813            Encoding(name) => write!(f, "ENCODING '{}'", value::escape_single_quote_string(name)),
7814        }
7815    }
7816}
7817
7818/// An option in `COPY` statement before PostgreSQL version 9.0.
7819///
7820/// <https://www.postgresql.org/docs/8.4/sql-copy.html>
7821#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7822#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7823#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7824pub enum CopyLegacyOption {
7825    /// BINARY
7826    Binary,
7827    /// DELIMITER \[ AS \] 'delimiter_character'
7828    Delimiter(char),
7829    /// NULL \[ AS \] 'null_string'
7830    Null(String),
7831    /// CSV ...
7832    Csv(Vec<CopyLegacyCsvOption>),
7833}
7834
7835impl fmt::Display for CopyLegacyOption {
7836    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7837        use CopyLegacyOption::*;
7838        match self {
7839            Binary => write!(f, "BINARY"),
7840            Delimiter(char) => write!(f, "DELIMITER '{char}'"),
7841            Null(string) => write!(f, "NULL '{}'", value::escape_single_quote_string(string)),
7842            Csv(opts) => write!(f, "CSV {}", display_separated(opts, " ")),
7843        }
7844    }
7845}
7846
7847/// A `CSV` option in `COPY` statement before PostgreSQL version 9.0.
7848///
7849/// <https://www.postgresql.org/docs/8.4/sql-copy.html>
7850#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7851#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7852#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7853pub enum CopyLegacyCsvOption {
7854    /// HEADER
7855    Header,
7856    /// QUOTE \[ AS \] 'quote_character'
7857    Quote(char),
7858    /// ESCAPE \[ AS \] 'escape_character'
7859    Escape(char),
7860    /// FORCE QUOTE { column_name [, ...] | * }
7861    ForceQuote(Vec<Ident>),
7862    /// FORCE NOT NULL column_name [, ...]
7863    ForceNotNull(Vec<Ident>),
7864}
7865
7866impl fmt::Display for CopyLegacyCsvOption {
7867    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7868        use CopyLegacyCsvOption::*;
7869        match self {
7870            Header => write!(f, "HEADER"),
7871            Quote(char) => write!(f, "QUOTE '{char}'"),
7872            Escape(char) => write!(f, "ESCAPE '{char}'"),
7873            ForceQuote(columns) => write!(f, "FORCE QUOTE {}", display_comma_separated(columns)),
7874            ForceNotNull(columns) => {
7875                write!(f, "FORCE NOT NULL {}", display_comma_separated(columns))
7876            }
7877        }
7878    }
7879}
7880
7881/// Variant of `WHEN` clause used within a `MERGE` Statement.
7882///
7883/// Example:
7884/// ```sql
7885/// MERGE INTO T USING U ON FALSE WHEN MATCHED THEN DELETE
7886/// ```
7887/// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/merge)
7888/// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/dml-syntax#merge_statement)
7889#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7890#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7891#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7892pub enum MergeClauseKind {
7893    /// `WHEN MATCHED`
7894    Matched,
7895    /// `WHEN NOT MATCHED`
7896    NotMatched,
7897    /// `WHEN MATCHED BY TARGET`
7898    ///
7899    /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/dml-syntax#merge_statement)
7900    NotMatchedByTarget,
7901    /// `WHEN MATCHED BY SOURCE`
7902    ///
7903    /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/dml-syntax#merge_statement)
7904    NotMatchedBySource,
7905}
7906
7907impl Display for MergeClauseKind {
7908    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7909        match self {
7910            MergeClauseKind::Matched => write!(f, "MATCHED"),
7911            MergeClauseKind::NotMatched => write!(f, "NOT MATCHED"),
7912            MergeClauseKind::NotMatchedByTarget => write!(f, "NOT MATCHED BY TARGET"),
7913            MergeClauseKind::NotMatchedBySource => write!(f, "NOT MATCHED BY SOURCE"),
7914        }
7915    }
7916}
7917
7918/// The type of expression used to insert rows within a `MERGE` statement.
7919///
7920/// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/merge)
7921/// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/dml-syntax#merge_statement)
7922#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7923#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7924#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7925pub enum MergeInsertKind {
7926    /// The insert expression is defined from an explicit `VALUES` clause
7927    ///
7928    /// Example:
7929    /// ```sql
7930    /// INSERT VALUES(product, quantity)
7931    /// ```
7932    Values(Values),
7933    /// The insert expression is defined using only the `ROW` keyword.
7934    ///
7935    /// Example:
7936    /// ```sql
7937    /// INSERT ROW
7938    /// ```
7939    /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/dml-syntax#merge_statement)
7940    Row,
7941}
7942
7943impl Display for MergeInsertKind {
7944    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7945        match self {
7946            MergeInsertKind::Values(values) => {
7947                write!(f, "{values}")
7948            }
7949            MergeInsertKind::Row => {
7950                write!(f, "ROW")
7951            }
7952        }
7953    }
7954}
7955
7956/// The expression used to insert rows within a `MERGE` statement.
7957///
7958/// Examples
7959/// ```sql
7960/// INSERT (product, quantity) VALUES(product, quantity)
7961/// INSERT ROW
7962/// ```
7963///
7964/// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/merge)
7965/// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/dml-syntax#merge_statement)
7966#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7967#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7968#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7969pub struct MergeInsertExpr {
7970    /// Columns (if any) specified by the insert.
7971    ///
7972    /// Example:
7973    /// ```sql
7974    /// INSERT (product, quantity) VALUES(product, quantity)
7975    /// INSERT (product, quantity) ROW
7976    /// ```
7977    pub columns: Vec<Ident>,
7978    /// The insert type used by the statement.
7979    pub kind: MergeInsertKind,
7980}
7981
7982impl Display for MergeInsertExpr {
7983    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7984        if !self.columns.is_empty() {
7985            write!(f, "({}) ", display_comma_separated(self.columns.as_slice()))?;
7986        }
7987        write!(f, "{}", self.kind)
7988    }
7989}
7990
7991/// Underlying statement of a when clause within a `MERGE` Statement
7992///
7993/// Example
7994/// ```sql
7995/// INSERT (product, quantity) VALUES(product, quantity)
7996/// ```
7997///
7998/// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/merge)
7999/// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/dml-syntax#merge_statement)
8000#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8001#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8002#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8003pub enum MergeAction {
8004    /// An `INSERT` clause
8005    ///
8006    /// Example:
8007    /// ```sql
8008    /// INSERT (product, quantity) VALUES(product, quantity)
8009    /// ```
8010    Insert(MergeInsertExpr),
8011    /// An `UPDATE` clause
8012    ///
8013    /// Example:
8014    /// ```sql
8015    /// UPDATE SET quantity = T.quantity + S.quantity
8016    /// ```
8017    Update { assignments: Vec<Assignment> },
8018    /// A plain `DELETE` clause
8019    Delete,
8020}
8021
8022impl Display for MergeAction {
8023    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8024        match self {
8025            MergeAction::Insert(insert) => {
8026                write!(f, "INSERT {insert}")
8027            }
8028            MergeAction::Update { assignments } => {
8029                write!(f, "UPDATE SET {}", display_comma_separated(assignments))
8030            }
8031            MergeAction::Delete => {
8032                write!(f, "DELETE")
8033            }
8034        }
8035    }
8036}
8037
8038/// A when clause within a `MERGE` Statement
8039///
8040/// Example:
8041/// ```sql
8042/// WHEN NOT MATCHED BY SOURCE AND product LIKE '%washer%' THEN DELETE
8043/// ```
8044/// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/merge)
8045/// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/dml-syntax#merge_statement)
8046#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8047#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8048#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8049pub struct MergeClause {
8050    pub clause_kind: MergeClauseKind,
8051    pub predicate: Option<Expr>,
8052    pub action: MergeAction,
8053}
8054
8055impl Display for MergeClause {
8056    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8057        let MergeClause {
8058            clause_kind,
8059            predicate,
8060            action,
8061        } = self;
8062
8063        write!(f, "WHEN {clause_kind}")?;
8064        if let Some(pred) = predicate {
8065            write!(f, " AND {pred}")?;
8066        }
8067        write!(f, " THEN {action}")
8068    }
8069}
8070
8071/// A Output Clause in the end of a 'MERGE' Statement
8072///
8073/// Example:
8074/// OUTPUT $action, deleted.* INTO dbo.temp_products;
8075/// [mssql](https://learn.microsoft.com/en-us/sql/t-sql/queries/output-clause-transact-sql)
8076#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8077#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8078#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8079pub struct OutputClause {
8080    pub select_items: Vec<SelectItem>,
8081    pub into_table: SelectInto,
8082}
8083
8084impl fmt::Display for OutputClause {
8085    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8086        let OutputClause {
8087            select_items,
8088            into_table,
8089        } = self;
8090
8091        write!(
8092            f,
8093            "OUTPUT {} {}",
8094            display_comma_separated(select_items),
8095            into_table
8096        )
8097    }
8098}
8099
8100#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8101#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8102#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8103pub enum DiscardObject {
8104    ALL,
8105    PLANS,
8106    SEQUENCES,
8107    TEMP,
8108}
8109
8110impl fmt::Display for DiscardObject {
8111    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8112        match self {
8113            DiscardObject::ALL => f.write_str("ALL"),
8114            DiscardObject::PLANS => f.write_str("PLANS"),
8115            DiscardObject::SEQUENCES => f.write_str("SEQUENCES"),
8116            DiscardObject::TEMP => f.write_str("TEMP"),
8117        }
8118    }
8119}
8120
8121#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8122#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8123#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8124pub enum FlushType {
8125    BinaryLogs,
8126    EngineLogs,
8127    ErrorLogs,
8128    GeneralLogs,
8129    Hosts,
8130    Logs,
8131    Privileges,
8132    OptimizerCosts,
8133    RelayLogs,
8134    SlowLogs,
8135    Status,
8136    UserResources,
8137    Tables,
8138}
8139
8140impl fmt::Display for FlushType {
8141    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8142        match self {
8143            FlushType::BinaryLogs => f.write_str("BINARY LOGS"),
8144            FlushType::EngineLogs => f.write_str("ENGINE LOGS"),
8145            FlushType::ErrorLogs => f.write_str("ERROR LOGS"),
8146            FlushType::GeneralLogs => f.write_str("GENERAL LOGS"),
8147            FlushType::Hosts => f.write_str("HOSTS"),
8148            FlushType::Logs => f.write_str("LOGS"),
8149            FlushType::Privileges => f.write_str("PRIVILEGES"),
8150            FlushType::OptimizerCosts => f.write_str("OPTIMIZER_COSTS"),
8151            FlushType::RelayLogs => f.write_str("RELAY LOGS"),
8152            FlushType::SlowLogs => f.write_str("SLOW LOGS"),
8153            FlushType::Status => f.write_str("STATUS"),
8154            FlushType::UserResources => f.write_str("USER_RESOURCES"),
8155            FlushType::Tables => f.write_str("TABLES"),
8156        }
8157    }
8158}
8159
8160#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8161#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8162#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8163pub enum FlushLocation {
8164    NoWriteToBinlog,
8165    Local,
8166}
8167
8168impl fmt::Display for FlushLocation {
8169    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8170        match self {
8171            FlushLocation::NoWriteToBinlog => f.write_str("NO_WRITE_TO_BINLOG"),
8172            FlushLocation::Local => f.write_str("LOCAL"),
8173        }
8174    }
8175}
8176
8177/// Optional context modifier for statements that can be or `LOCAL`, `GLOBAL`, or `SESSION`.
8178#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8179#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8180#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8181pub enum ContextModifier {
8182    /// `LOCAL` identifier, usually related to transactional states.
8183    Local,
8184    /// `SESSION` identifier
8185    Session,
8186    /// `GLOBAL` identifier
8187    Global,
8188}
8189
8190impl fmt::Display for ContextModifier {
8191    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8192        match self {
8193            Self::Local => {
8194                write!(f, "LOCAL ")
8195            }
8196            Self::Session => {
8197                write!(f, "SESSION ")
8198            }
8199            Self::Global => {
8200                write!(f, "GLOBAL ")
8201            }
8202        }
8203    }
8204}
8205
8206/// Function describe in DROP FUNCTION.
8207#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8208#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8209pub enum DropFunctionOption {
8210    Restrict,
8211    Cascade,
8212}
8213
8214impl fmt::Display for DropFunctionOption {
8215    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8216        match self {
8217            DropFunctionOption::Restrict => write!(f, "RESTRICT "),
8218            DropFunctionOption::Cascade => write!(f, "CASCADE  "),
8219        }
8220    }
8221}
8222
8223/// Generic function description for DROP FUNCTION and CREATE TRIGGER.
8224#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8225#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8226#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8227pub struct FunctionDesc {
8228    pub name: ObjectName,
8229    pub args: Option<Vec<OperateFunctionArg>>,
8230}
8231
8232impl fmt::Display for FunctionDesc {
8233    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8234        write!(f, "{}", self.name)?;
8235        if let Some(args) = &self.args {
8236            write!(f, "({})", display_comma_separated(args))?;
8237        }
8238        Ok(())
8239    }
8240}
8241
8242/// Function argument in CREATE OR DROP FUNCTION.
8243#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8244#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8245#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8246pub struct OperateFunctionArg {
8247    pub mode: Option<ArgMode>,
8248    pub name: Option<Ident>,
8249    pub data_type: DataType,
8250    pub default_expr: Option<Expr>,
8251}
8252
8253impl OperateFunctionArg {
8254    /// Returns an unnamed argument.
8255    pub fn unnamed(data_type: DataType) -> Self {
8256        Self {
8257            mode: None,
8258            name: None,
8259            data_type,
8260            default_expr: None,
8261        }
8262    }
8263
8264    /// Returns an argument with name.
8265    pub fn with_name(name: &str, data_type: DataType) -> Self {
8266        Self {
8267            mode: None,
8268            name: Some(name.into()),
8269            data_type,
8270            default_expr: None,
8271        }
8272    }
8273}
8274
8275impl fmt::Display for OperateFunctionArg {
8276    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8277        if let Some(mode) = &self.mode {
8278            write!(f, "{mode} ")?;
8279        }
8280        if let Some(name) = &self.name {
8281            write!(f, "{name} ")?;
8282        }
8283        write!(f, "{}", self.data_type)?;
8284        if let Some(default_expr) = &self.default_expr {
8285            write!(f, " = {default_expr}")?;
8286        }
8287        Ok(())
8288    }
8289}
8290
8291/// The mode of an argument in CREATE FUNCTION.
8292#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8293#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8294#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8295pub enum ArgMode {
8296    In,
8297    Out,
8298    InOut,
8299}
8300
8301impl fmt::Display for ArgMode {
8302    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8303        match self {
8304            ArgMode::In => write!(f, "IN"),
8305            ArgMode::Out => write!(f, "OUT"),
8306            ArgMode::InOut => write!(f, "INOUT"),
8307        }
8308    }
8309}
8310
8311/// These attributes inform the query optimizer about the behavior of the function.
8312#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8313#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8314#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8315pub enum FunctionBehavior {
8316    Immutable,
8317    Stable,
8318    Volatile,
8319}
8320
8321impl fmt::Display for FunctionBehavior {
8322    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8323        match self {
8324            FunctionBehavior::Immutable => write!(f, "IMMUTABLE"),
8325            FunctionBehavior::Stable => write!(f, "STABLE"),
8326            FunctionBehavior::Volatile => write!(f, "VOLATILE"),
8327        }
8328    }
8329}
8330
8331/// These attributes describe the behavior of the function when called with a null argument.
8332#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8333#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8334#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8335pub enum FunctionCalledOnNull {
8336    CalledOnNullInput,
8337    ReturnsNullOnNullInput,
8338    Strict,
8339}
8340
8341impl fmt::Display for FunctionCalledOnNull {
8342    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8343        match self {
8344            FunctionCalledOnNull::CalledOnNullInput => write!(f, "CALLED ON NULL INPUT"),
8345            FunctionCalledOnNull::ReturnsNullOnNullInput => write!(f, "RETURNS NULL ON NULL INPUT"),
8346            FunctionCalledOnNull::Strict => write!(f, "STRICT"),
8347        }
8348    }
8349}
8350
8351/// If it is safe for PostgreSQL to call the function from multiple threads at once
8352#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8353#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8354#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8355pub enum FunctionParallel {
8356    Unsafe,
8357    Restricted,
8358    Safe,
8359}
8360
8361impl fmt::Display for FunctionParallel {
8362    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8363        match self {
8364            FunctionParallel::Unsafe => write!(f, "PARALLEL UNSAFE"),
8365            FunctionParallel::Restricted => write!(f, "PARALLEL RESTRICTED"),
8366            FunctionParallel::Safe => write!(f, "PARALLEL SAFE"),
8367        }
8368    }
8369}
8370
8371/// [BigQuery] Determinism specifier used in a UDF definition.
8372///
8373/// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#syntax_11
8374#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8375#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8376#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8377pub enum FunctionDeterminismSpecifier {
8378    Deterministic,
8379    NotDeterministic,
8380}
8381
8382impl fmt::Display for FunctionDeterminismSpecifier {
8383    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8384        match self {
8385            FunctionDeterminismSpecifier::Deterministic => {
8386                write!(f, "DETERMINISTIC")
8387            }
8388            FunctionDeterminismSpecifier::NotDeterministic => {
8389                write!(f, "NOT DETERMINISTIC")
8390            }
8391        }
8392    }
8393}
8394
8395/// Represent the expression body of a `CREATE FUNCTION` statement as well as
8396/// where within the statement, the body shows up.
8397///
8398/// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#syntax_11
8399/// [PostgreSQL]: https://www.postgresql.org/docs/15/sql-createfunction.html
8400/// [MsSql]: https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql
8401#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8402#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8403#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8404pub enum CreateFunctionBody {
8405    /// A function body expression using the 'AS' keyword and shows up
8406    /// before any `OPTIONS` clause.
8407    ///
8408    /// Example:
8409    /// ```sql
8410    /// CREATE FUNCTION myfunc(x FLOAT64, y FLOAT64) RETURNS FLOAT64
8411    /// AS (x * y)
8412    /// OPTIONS(description="desc");
8413    /// ```
8414    ///
8415    /// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#syntax_11
8416    AsBeforeOptions(Expr),
8417    /// A function body expression using the 'AS' keyword and shows up
8418    /// after any `OPTIONS` clause.
8419    ///
8420    /// Example:
8421    /// ```sql
8422    /// CREATE FUNCTION myfunc(x FLOAT64, y FLOAT64) RETURNS FLOAT64
8423    /// OPTIONS(description="desc")
8424    /// AS (x * y);
8425    /// ```
8426    ///
8427    /// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#syntax_11
8428    AsAfterOptions(Expr),
8429    /// Function body with statements before the `RETURN` keyword.
8430    ///
8431    /// Example:
8432    /// ```sql
8433    /// CREATE FUNCTION my_scalar_udf(a INT, b INT)
8434    /// RETURNS INT
8435    /// AS
8436    /// BEGIN
8437    ///     DECLARE c INT;
8438    ///     SET c = a + b;
8439    ///     RETURN c;
8440    /// END
8441    /// ```
8442    ///
8443    /// [MsSql]: https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql
8444    AsBeginEnd(BeginEndStatements),
8445    /// Function body expression using the 'RETURN' keyword.
8446    ///
8447    /// Example:
8448    /// ```sql
8449    /// CREATE FUNCTION myfunc(a INTEGER, IN b INTEGER = 1) RETURNS INTEGER
8450    /// LANGUAGE SQL
8451    /// RETURN a + b;
8452    /// ```
8453    ///
8454    /// [PostgreSQL]: https://www.postgresql.org/docs/current/sql-createfunction.html
8455    Return(Expr),
8456}
8457
8458#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8459#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8460#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8461pub enum CreateFunctionUsing {
8462    Jar(String),
8463    File(String),
8464    Archive(String),
8465}
8466
8467impl fmt::Display for CreateFunctionUsing {
8468    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8469        write!(f, "USING ")?;
8470        match self {
8471            CreateFunctionUsing::Jar(uri) => write!(f, "JAR '{uri}'"),
8472            CreateFunctionUsing::File(uri) => write!(f, "FILE '{uri}'"),
8473            CreateFunctionUsing::Archive(uri) => write!(f, "ARCHIVE '{uri}'"),
8474        }
8475    }
8476}
8477
8478/// `NAME = <EXPR>` arguments for DuckDB macros
8479///
8480/// See [Create Macro - DuckDB](https://duckdb.org/docs/sql/statements/create_macro)
8481/// for more details
8482#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8483#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8484#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8485pub struct MacroArg {
8486    pub name: Ident,
8487    pub default_expr: Option<Expr>,
8488}
8489
8490impl MacroArg {
8491    /// Returns an argument with name.
8492    pub fn new(name: &str) -> Self {
8493        Self {
8494            name: name.into(),
8495            default_expr: None,
8496        }
8497    }
8498}
8499
8500impl fmt::Display for MacroArg {
8501    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8502        write!(f, "{}", self.name)?;
8503        if let Some(default_expr) = &self.default_expr {
8504            write!(f, " := {default_expr}")?;
8505        }
8506        Ok(())
8507    }
8508}
8509
8510#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8511#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8512#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8513pub enum MacroDefinition {
8514    Expr(Expr),
8515    Table(Box<Query>),
8516}
8517
8518impl fmt::Display for MacroDefinition {
8519    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8520        match self {
8521            MacroDefinition::Expr(expr) => write!(f, "{expr}")?,
8522            MacroDefinition::Table(query) => write!(f, "{query}")?,
8523        }
8524        Ok(())
8525    }
8526}
8527
8528/// Schema possible naming variants ([1]).
8529///
8530/// [1]: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#schema-definition
8531#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8532#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8533#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8534pub enum SchemaName {
8535    /// Only schema name specified: `<schema name>`.
8536    Simple(ObjectName),
8537    /// Only authorization identifier specified: `AUTHORIZATION <schema authorization identifier>`.
8538    UnnamedAuthorization(Ident),
8539    /// Both schema name and authorization identifier specified: `<schema name>  AUTHORIZATION <schema authorization identifier>`.
8540    NamedAuthorization(ObjectName, Ident),
8541}
8542
8543impl fmt::Display for SchemaName {
8544    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8545        match self {
8546            SchemaName::Simple(name) => {
8547                write!(f, "{name}")
8548            }
8549            SchemaName::UnnamedAuthorization(authorization) => {
8550                write!(f, "AUTHORIZATION {authorization}")
8551            }
8552            SchemaName::NamedAuthorization(name, authorization) => {
8553                write!(f, "{name} AUTHORIZATION {authorization}")
8554            }
8555        }
8556    }
8557}
8558
8559/// Fulltext search modifiers ([1]).
8560///
8561/// [1]: https://dev.mysql.com/doc/refman/8.0/en/fulltext-search.html#function_match
8562#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8563#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8564#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8565pub enum SearchModifier {
8566    /// `IN NATURAL LANGUAGE MODE`.
8567    InNaturalLanguageMode,
8568    /// `IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION`.
8569    InNaturalLanguageModeWithQueryExpansion,
8570    ///`IN BOOLEAN MODE`.
8571    InBooleanMode,
8572    ///`WITH QUERY EXPANSION`.
8573    WithQueryExpansion,
8574}
8575
8576impl fmt::Display for SearchModifier {
8577    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8578        match self {
8579            Self::InNaturalLanguageMode => {
8580                write!(f, "IN NATURAL LANGUAGE MODE")?;
8581            }
8582            Self::InNaturalLanguageModeWithQueryExpansion => {
8583                write!(f, "IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION")?;
8584            }
8585            Self::InBooleanMode => {
8586                write!(f, "IN BOOLEAN MODE")?;
8587            }
8588            Self::WithQueryExpansion => {
8589                write!(f, "WITH QUERY EXPANSION")?;
8590            }
8591        }
8592
8593        Ok(())
8594    }
8595}
8596
8597#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8598#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8599#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8600pub struct LockTable {
8601    pub table: Ident,
8602    pub alias: Option<Ident>,
8603    pub lock_type: LockTableType,
8604}
8605
8606impl fmt::Display for LockTable {
8607    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8608        let Self {
8609            table: tbl_name,
8610            alias,
8611            lock_type,
8612        } = self;
8613
8614        write!(f, "{tbl_name} ")?;
8615        if let Some(alias) = alias {
8616            write!(f, "AS {alias} ")?;
8617        }
8618        write!(f, "{lock_type}")?;
8619        Ok(())
8620    }
8621}
8622
8623#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8624#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8625#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8626pub enum LockTableType {
8627    Read { local: bool },
8628    Write { low_priority: bool },
8629}
8630
8631impl fmt::Display for LockTableType {
8632    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8633        match self {
8634            Self::Read { local } => {
8635                write!(f, "READ")?;
8636                if *local {
8637                    write!(f, " LOCAL")?;
8638                }
8639            }
8640            Self::Write { low_priority } => {
8641                if *low_priority {
8642                    write!(f, "LOW_PRIORITY ")?;
8643                }
8644                write!(f, "WRITE")?;
8645            }
8646        }
8647
8648        Ok(())
8649    }
8650}
8651
8652#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8653#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8654#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8655pub struct HiveSetLocation {
8656    pub has_set: bool,
8657    pub location: Ident,
8658}
8659
8660impl fmt::Display for HiveSetLocation {
8661    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8662        if self.has_set {
8663            write!(f, "SET ")?;
8664        }
8665        write!(f, "LOCATION {}", self.location)
8666    }
8667}
8668
8669/// MySQL `ALTER TABLE` only  [FIRST | AFTER column_name]
8670#[allow(clippy::large_enum_variant)]
8671#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8672#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8673#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8674pub enum MySQLColumnPosition {
8675    First,
8676    After(Ident),
8677}
8678
8679impl Display for MySQLColumnPosition {
8680    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8681        match self {
8682            MySQLColumnPosition::First => write!(f, "FIRST"),
8683            MySQLColumnPosition::After(ident) => {
8684                let column_name = &ident.value;
8685                write!(f, "AFTER {column_name}")
8686            }
8687        }
8688    }
8689}
8690
8691/// MySQL `CREATE VIEW` algorithm parameter: [ALGORITHM = {UNDEFINED | MERGE | TEMPTABLE}]
8692#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8693#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8694#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8695pub enum CreateViewAlgorithm {
8696    Undefined,
8697    Merge,
8698    TempTable,
8699}
8700
8701impl Display for CreateViewAlgorithm {
8702    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8703        match self {
8704            CreateViewAlgorithm::Undefined => write!(f, "UNDEFINED"),
8705            CreateViewAlgorithm::Merge => write!(f, "MERGE"),
8706            CreateViewAlgorithm::TempTable => write!(f, "TEMPTABLE"),
8707        }
8708    }
8709}
8710/// MySQL `CREATE VIEW` security parameter: [SQL SECURITY { DEFINER | INVOKER }]
8711#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8712#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8713#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8714pub enum CreateViewSecurity {
8715    Definer,
8716    Invoker,
8717}
8718
8719impl Display for CreateViewSecurity {
8720    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8721        match self {
8722            CreateViewSecurity::Definer => write!(f, "DEFINER"),
8723            CreateViewSecurity::Invoker => write!(f, "INVOKER"),
8724        }
8725    }
8726}
8727
8728/// [MySQL] `CREATE VIEW` additional parameters
8729///
8730/// [MySQL]: https://dev.mysql.com/doc/refman/9.1/en/create-view.html
8731#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8732#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8733#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8734pub struct CreateViewParams {
8735    pub algorithm: Option<CreateViewAlgorithm>,
8736    pub definer: Option<GranteeName>,
8737    pub security: Option<CreateViewSecurity>,
8738}
8739
8740impl Display for CreateViewParams {
8741    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8742        let CreateViewParams {
8743            algorithm,
8744            definer,
8745            security,
8746        } = self;
8747        if let Some(algorithm) = algorithm {
8748            write!(f, "ALGORITHM = {algorithm} ")?;
8749        }
8750        if let Some(definers) = definer {
8751            write!(f, "DEFINER = {definers} ")?;
8752        }
8753        if let Some(security) = security {
8754            write!(f, "SQL SECURITY {security} ")?;
8755        }
8756        Ok(())
8757    }
8758}
8759
8760/// Engine of DB. Some warehouse has parameters of engine, e.g. [ClickHouse]
8761///
8762/// [ClickHouse]: https://clickhouse.com/docs/en/engines/table-engines
8763#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8764#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8765#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8766pub struct TableEngine {
8767    pub name: String,
8768    pub parameters: Option<Vec<Ident>>,
8769}
8770
8771impl Display for TableEngine {
8772    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8773        write!(f, "{}", self.name)?;
8774
8775        if let Some(parameters) = self.parameters.as_ref() {
8776            write!(f, "({})", display_comma_separated(parameters))?;
8777        }
8778
8779        Ok(())
8780    }
8781}
8782
8783/// Snowflake `WITH ROW ACCESS POLICY policy_name ON (identifier, ...)`
8784///
8785/// <https://docs.snowflake.com/en/sql-reference/sql/create-table>
8786/// <https://docs.snowflake.com/en/user-guide/security-row-intro>
8787#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8788#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8789#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8790pub struct RowAccessPolicy {
8791    pub policy: ObjectName,
8792    pub on: Vec<Ident>,
8793}
8794
8795impl RowAccessPolicy {
8796    pub fn new(policy: ObjectName, on: Vec<Ident>) -> Self {
8797        Self { policy, on }
8798    }
8799}
8800
8801impl Display for RowAccessPolicy {
8802    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8803        write!(
8804            f,
8805            "WITH ROW ACCESS POLICY {} ON ({})",
8806            self.policy,
8807            display_comma_separated(self.on.as_slice())
8808        )
8809    }
8810}
8811
8812/// Snowflake `WITH TAG ( tag_name = '<tag_value>', ...)`
8813///
8814/// <https://docs.snowflake.com/en/sql-reference/sql/create-table>
8815#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8816#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8817#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8818pub struct Tag {
8819    pub key: Ident,
8820    pub value: String,
8821}
8822
8823impl Tag {
8824    pub fn new(key: Ident, value: String) -> Self {
8825        Self { key, value }
8826    }
8827}
8828
8829impl Display for Tag {
8830    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8831        write!(f, "{}='{}'", self.key, self.value)
8832    }
8833}
8834
8835/// Helper to indicate if a comment includes the `=` in the display form
8836#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8837#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8838#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8839pub enum CommentDef {
8840    /// Includes `=` when printing the comment, as `COMMENT = 'comment'`
8841    /// Does not include `=` when printing the comment, as `COMMENT 'comment'`
8842    WithEq(String),
8843    WithoutEq(String),
8844    // For Hive dialect, the table comment is after the column definitions without `=`,
8845    // so we need to add an extra variant to allow to identify this case when displaying.
8846    // [Hive](https://cwiki.apache.org/confluence/display/Hive/LanguageManual+DDL#LanguageManualDDL-CreateTable)
8847    AfterColumnDefsWithoutEq(String),
8848}
8849
8850impl Display for CommentDef {
8851    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8852        match self {
8853            CommentDef::WithEq(comment)
8854            | CommentDef::WithoutEq(comment)
8855            | CommentDef::AfterColumnDefsWithoutEq(comment) => write!(f, "{comment}"),
8856        }
8857    }
8858}
8859
8860/// Helper to indicate if a collection should be wrapped by a symbol in the display form
8861///
8862/// [`Display`] is implemented for every [`Vec<T>`] where `T: Display`.
8863/// The string output is a comma separated list for the vec items
8864///
8865/// # Examples
8866/// ```
8867/// # use sqlparser::ast::WrappedCollection;
8868/// let items = WrappedCollection::Parentheses(vec!["one", "two", "three"]);
8869/// assert_eq!("(one, two, three)", items.to_string());
8870///
8871/// let items = WrappedCollection::NoWrapping(vec!["one", "two", "three"]);
8872/// assert_eq!("one, two, three", items.to_string());
8873/// ```
8874#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8875#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8876#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8877pub enum WrappedCollection<T> {
8878    /// Print the collection without wrapping symbols, as `item, item, item`
8879    NoWrapping(T),
8880    /// Wraps the collection in Parentheses, as `(item, item, item)`
8881    Parentheses(T),
8882}
8883
8884impl<T> Display for WrappedCollection<Vec<T>>
8885where
8886    T: Display,
8887{
8888    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8889        match self {
8890            WrappedCollection::NoWrapping(inner) => {
8891                write!(f, "{}", display_comma_separated(inner.as_slice()))
8892            }
8893            WrappedCollection::Parentheses(inner) => {
8894                write!(f, "({})", display_comma_separated(inner.as_slice()))
8895            }
8896        }
8897    }
8898}
8899
8900/// Represents a single PostgreSQL utility option.
8901///
8902/// A utility option is a key-value pair where the key is an identifier (IDENT) and the value
8903/// can be one of the following:
8904/// - A number with an optional sign (`+` or `-`). Example: `+10`, `-10.2`, `3`
8905/// - A non-keyword string. Example: `option1`, `'option2'`, `"option3"`
8906/// - keyword: `TRUE`, `FALSE`, `ON` (`off` is also accept).
8907/// - Empty. Example: `ANALYZE` (identifier only)
8908///
8909/// Utility options are used in various PostgreSQL DDL statements, including statements such as
8910/// `CLUSTER`, `EXPLAIN`, `VACUUM`, and `REINDEX`. These statements format options as `( option [, ...] )`.
8911///
8912/// [CLUSTER](https://www.postgresql.org/docs/current/sql-cluster.html)
8913/// [EXPLAIN](https://www.postgresql.org/docs/current/sql-explain.html)
8914/// [VACUUM](https://www.postgresql.org/docs/current/sql-vacuum.html)
8915/// [REINDEX](https://www.postgresql.org/docs/current/sql-reindex.html)
8916///
8917/// For example, the `EXPLAIN` AND `VACUUM` statements with options might look like this:
8918/// ```sql
8919/// EXPLAIN (ANALYZE, VERBOSE TRUE, FORMAT TEXT) SELECT * FROM my_table;
8920///
8921/// VACUUM (VERBOSE, ANALYZE ON, PARALLEL 10) my_table;
8922/// ```
8923#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8924#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8925#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8926pub struct UtilityOption {
8927    pub name: Ident,
8928    pub arg: Option<Expr>,
8929}
8930
8931impl Display for UtilityOption {
8932    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8933        if let Some(ref arg) = self.arg {
8934            write!(f, "{} {}", self.name, arg)
8935        } else {
8936            write!(f, "{}", self.name)
8937        }
8938    }
8939}
8940
8941/// Represents the different options available for `SHOW`
8942/// statements to filter the results. Example from Snowflake:
8943/// <https://docs.snowflake.com/en/sql-reference/sql/show-tables>
8944#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8945#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8946#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8947pub struct ShowStatementOptions {
8948    pub show_in: Option<ShowStatementIn>,
8949    pub starts_with: Option<Value>,
8950    pub limit: Option<Expr>,
8951    pub limit_from: Option<Value>,
8952    pub filter_position: Option<ShowStatementFilterPosition>,
8953}
8954
8955impl Display for ShowStatementOptions {
8956    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8957        let (like_in_infix, like_in_suffix) = match &self.filter_position {
8958            Some(ShowStatementFilterPosition::Infix(filter)) => {
8959                (format!(" {filter}"), "".to_string())
8960            }
8961            Some(ShowStatementFilterPosition::Suffix(filter)) => {
8962                ("".to_string(), format!(" {filter}"))
8963            }
8964            None => ("".to_string(), "".to_string()),
8965        };
8966        write!(
8967            f,
8968            "{like_in_infix}{show_in}{starts_with}{limit}{from}{like_in_suffix}",
8969            show_in = match &self.show_in {
8970                Some(i) => format!(" {i}"),
8971                None => String::new(),
8972            },
8973            starts_with = match &self.starts_with {
8974                Some(s) => format!(" STARTS WITH {s}"),
8975                None => String::new(),
8976            },
8977            limit = match &self.limit {
8978                Some(l) => format!(" LIMIT {l}"),
8979                None => String::new(),
8980            },
8981            from = match &self.limit_from {
8982                Some(f) => format!(" FROM {f}"),
8983                None => String::new(),
8984            }
8985        )?;
8986        Ok(())
8987    }
8988}
8989
8990#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8991#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8992#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8993pub enum ShowStatementFilterPosition {
8994    Infix(ShowStatementFilter), // For example: SHOW COLUMNS LIKE '%name%' IN TABLE tbl
8995    Suffix(ShowStatementFilter), // For example: SHOW COLUMNS IN tbl LIKE '%name%'
8996}
8997
8998#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8999#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9000#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9001pub enum ShowStatementInParentType {
9002    Account,
9003    Database,
9004    Schema,
9005    Table,
9006    View,
9007}
9008
9009impl fmt::Display for ShowStatementInParentType {
9010    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9011        match self {
9012            ShowStatementInParentType::Account => write!(f, "ACCOUNT"),
9013            ShowStatementInParentType::Database => write!(f, "DATABASE"),
9014            ShowStatementInParentType::Schema => write!(f, "SCHEMA"),
9015            ShowStatementInParentType::Table => write!(f, "TABLE"),
9016            ShowStatementInParentType::View => write!(f, "VIEW"),
9017        }
9018    }
9019}
9020
9021#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9022#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9023#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9024pub struct ShowStatementIn {
9025    pub clause: ShowStatementInClause,
9026    pub parent_type: Option<ShowStatementInParentType>,
9027    #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
9028    pub parent_name: Option<ObjectName>,
9029}
9030
9031impl fmt::Display for ShowStatementIn {
9032    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9033        write!(f, "{}", self.clause)?;
9034        if let Some(parent_type) = &self.parent_type {
9035            write!(f, " {}", parent_type)?;
9036        }
9037        if let Some(parent_name) = &self.parent_name {
9038            write!(f, " {}", parent_name)?;
9039        }
9040        Ok(())
9041    }
9042}
9043
9044#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9045#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9046#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9047pub struct ShowObjects {
9048    pub terse: bool,
9049    pub show_options: ShowStatementOptions,
9050}
9051
9052/// MSSQL's json null clause
9053///
9054/// ```plaintext
9055/// <json_null_clause> ::=
9056///       NULL ON NULL
9057///     | ABSENT ON NULL
9058/// ```
9059///
9060/// <https://learn.microsoft.com/en-us/sql/t-sql/functions/json-object-transact-sql?view=sql-server-ver16#json_null_clause>
9061#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9062#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9063#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9064pub enum JsonNullClause {
9065    NullOnNull,
9066    AbsentOnNull,
9067}
9068
9069impl Display for JsonNullClause {
9070    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
9071        match self {
9072            JsonNullClause::NullOnNull => write!(f, "NULL ON NULL"),
9073            JsonNullClause::AbsentOnNull => write!(f, "ABSENT ON NULL"),
9074        }
9075    }
9076}
9077
9078/// rename object definition
9079#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9080#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9081#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9082pub struct RenameTable {
9083    pub old_name: ObjectName,
9084    pub new_name: ObjectName,
9085}
9086
9087impl fmt::Display for RenameTable {
9088    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9089        write!(f, "{} TO {}", self.old_name, self.new_name)?;
9090        Ok(())
9091    }
9092}
9093
9094/// Represents the referenced table in an `INSERT INTO` statement
9095#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9096#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9097#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9098pub enum TableObject {
9099    /// Table specified by name.
9100    /// Example:
9101    /// ```sql
9102    /// INSERT INTO my_table
9103    /// ```
9104    TableName(#[cfg_attr(feature = "visitor", visit(with = "visit_relation"))] ObjectName),
9105
9106    /// Table specified as a function.
9107    /// Example:
9108    /// ```sql
9109    /// INSERT INTO TABLE FUNCTION remote('localhost', default.simple_table)
9110    /// ```
9111    /// [Clickhouse](https://clickhouse.com/docs/en/sql-reference/table-functions)
9112    TableFunction(Function),
9113}
9114
9115impl fmt::Display for TableObject {
9116    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9117        match self {
9118            Self::TableName(table_name) => write!(f, "{table_name}"),
9119            Self::TableFunction(func) => write!(f, "FUNCTION {}", func),
9120        }
9121    }
9122}
9123
9124#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9125#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9126#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9127pub enum SetSessionParamKind {
9128    Generic(SetSessionParamGeneric),
9129    IdentityInsert(SetSessionParamIdentityInsert),
9130    Offsets(SetSessionParamOffsets),
9131    Statistics(SetSessionParamStatistics),
9132}
9133
9134impl fmt::Display for SetSessionParamKind {
9135    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9136        match self {
9137            SetSessionParamKind::Generic(x) => write!(f, "{x}"),
9138            SetSessionParamKind::IdentityInsert(x) => write!(f, "{x}"),
9139            SetSessionParamKind::Offsets(x) => write!(f, "{x}"),
9140            SetSessionParamKind::Statistics(x) => write!(f, "{x}"),
9141        }
9142    }
9143}
9144
9145#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9146#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9147#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9148pub struct SetSessionParamGeneric {
9149    pub names: Vec<String>,
9150    pub value: String,
9151}
9152
9153impl fmt::Display for SetSessionParamGeneric {
9154    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9155        write!(f, "{} {}", display_comma_separated(&self.names), self.value)
9156    }
9157}
9158
9159#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9160#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9161#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9162pub struct SetSessionParamIdentityInsert {
9163    pub obj: ObjectName,
9164    pub value: SessionParamValue,
9165}
9166
9167impl fmt::Display for SetSessionParamIdentityInsert {
9168    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9169        write!(f, "IDENTITY_INSERT {} {}", self.obj, self.value)
9170    }
9171}
9172
9173#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9174#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9175#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9176pub struct SetSessionParamOffsets {
9177    pub keywords: Vec<String>,
9178    pub value: SessionParamValue,
9179}
9180
9181impl fmt::Display for SetSessionParamOffsets {
9182    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9183        write!(
9184            f,
9185            "OFFSETS {} {}",
9186            display_comma_separated(&self.keywords),
9187            self.value
9188        )
9189    }
9190}
9191
9192#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9193#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9194#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9195pub struct SetSessionParamStatistics {
9196    pub topic: SessionParamStatsTopic,
9197    pub value: SessionParamValue,
9198}
9199
9200impl fmt::Display for SetSessionParamStatistics {
9201    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9202        write!(f, "STATISTICS {} {}", self.topic, self.value)
9203    }
9204}
9205
9206#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9207#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9208#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9209pub enum SessionParamStatsTopic {
9210    IO,
9211    Profile,
9212    Time,
9213    Xml,
9214}
9215
9216impl fmt::Display for SessionParamStatsTopic {
9217    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9218        match self {
9219            SessionParamStatsTopic::IO => write!(f, "IO"),
9220            SessionParamStatsTopic::Profile => write!(f, "PROFILE"),
9221            SessionParamStatsTopic::Time => write!(f, "TIME"),
9222            SessionParamStatsTopic::Xml => write!(f, "XML"),
9223        }
9224    }
9225}
9226
9227#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9228#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9229#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9230pub enum SessionParamValue {
9231    On,
9232    Off,
9233}
9234
9235impl fmt::Display for SessionParamValue {
9236    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9237        match self {
9238            SessionParamValue::On => write!(f, "ON"),
9239            SessionParamValue::Off => write!(f, "OFF"),
9240        }
9241    }
9242}
9243
9244/// Snowflake StorageSerializationPolicy for Iceberg Tables
9245/// ```sql
9246/// [ STORAGE_SERIALIZATION_POLICY = { COMPATIBLE | OPTIMIZED } ]
9247/// ```
9248///
9249/// <https://docs.snowflake.com/en/sql-reference/sql/create-iceberg-table>
9250#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9251#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9252#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9253pub enum StorageSerializationPolicy {
9254    Compatible,
9255    Optimized,
9256}
9257
9258impl Display for StorageSerializationPolicy {
9259    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
9260        match self {
9261            StorageSerializationPolicy::Compatible => write!(f, "COMPATIBLE"),
9262            StorageSerializationPolicy::Optimized => write!(f, "OPTIMIZED"),
9263        }
9264    }
9265}
9266
9267/// Variants of the Snowflake `COPY INTO` statement
9268#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9269#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9270#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9271pub enum CopyIntoSnowflakeKind {
9272    /// Loads data from files to a table
9273    /// See: <https://docs.snowflake.com/en/sql-reference/sql/copy-into-table>
9274    Table,
9275    /// Unloads data from a table or query to external files
9276    /// See: <https://docs.snowflake.com/en/sql-reference/sql/copy-into-location>
9277    Location,
9278}
9279
9280#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9281#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9282#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9283pub struct PrintStatement {
9284    pub message: Box<Expr>,
9285}
9286
9287impl fmt::Display for PrintStatement {
9288    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9289        write!(f, "PRINT {}", self.message)
9290    }
9291}
9292
9293/// Represents a `Return` statement.
9294///
9295/// [MsSql triggers](https://learn.microsoft.com/en-us/sql/t-sql/statements/create-trigger-transact-sql)
9296/// [MsSql functions](https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql)
9297#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9298#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9299#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9300pub struct ReturnStatement {
9301    pub value: Option<ReturnStatementValue>,
9302}
9303
9304impl fmt::Display for ReturnStatement {
9305    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9306        match &self.value {
9307            Some(ReturnStatementValue::Expr(expr)) => write!(f, "RETURN {}", expr),
9308            None => write!(f, "RETURN"),
9309        }
9310    }
9311}
9312
9313/// Variants of a `RETURN` statement
9314#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9315#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9316#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9317pub enum ReturnStatementValue {
9318    Expr(Expr),
9319}
9320
9321#[cfg(test)]
9322mod tests {
9323    use super::*;
9324
9325    #[test]
9326    fn test_window_frame_default() {
9327        let window_frame = WindowFrame::default();
9328        assert_eq!(WindowFrameBound::Preceding(None), window_frame.start_bound);
9329    }
9330
9331    #[test]
9332    fn test_grouping_sets_display() {
9333        // a and b in different group
9334        let grouping_sets = Expr::GroupingSets(vec![
9335            vec![Expr::Identifier(Ident::new("a"))],
9336            vec![Expr::Identifier(Ident::new("b"))],
9337        ]);
9338        assert_eq!("GROUPING SETS ((a), (b))", format!("{grouping_sets}"));
9339
9340        // a and b in the same group
9341        let grouping_sets = Expr::GroupingSets(vec![vec![
9342            Expr::Identifier(Ident::new("a")),
9343            Expr::Identifier(Ident::new("b")),
9344        ]]);
9345        assert_eq!("GROUPING SETS ((a, b))", format!("{grouping_sets}"));
9346
9347        // (a, b) and (c, d) in different group
9348        let grouping_sets = Expr::GroupingSets(vec![
9349            vec![
9350                Expr::Identifier(Ident::new("a")),
9351                Expr::Identifier(Ident::new("b")),
9352            ],
9353            vec![
9354                Expr::Identifier(Ident::new("c")),
9355                Expr::Identifier(Ident::new("d")),
9356            ],
9357        ]);
9358        assert_eq!("GROUPING SETS ((a, b), (c, d))", format!("{grouping_sets}"));
9359    }
9360
9361    #[test]
9362    fn test_rollup_display() {
9363        let rollup = Expr::Rollup(vec![vec![Expr::Identifier(Ident::new("a"))]]);
9364        assert_eq!("ROLLUP (a)", format!("{rollup}"));
9365
9366        let rollup = Expr::Rollup(vec![vec![
9367            Expr::Identifier(Ident::new("a")),
9368            Expr::Identifier(Ident::new("b")),
9369        ]]);
9370        assert_eq!("ROLLUP ((a, b))", format!("{rollup}"));
9371
9372        let rollup = Expr::Rollup(vec![
9373            vec![Expr::Identifier(Ident::new("a"))],
9374            vec![Expr::Identifier(Ident::new("b"))],
9375        ]);
9376        assert_eq!("ROLLUP (a, b)", format!("{rollup}"));
9377
9378        let rollup = Expr::Rollup(vec![
9379            vec![Expr::Identifier(Ident::new("a"))],
9380            vec![
9381                Expr::Identifier(Ident::new("b")),
9382                Expr::Identifier(Ident::new("c")),
9383            ],
9384            vec![Expr::Identifier(Ident::new("d"))],
9385        ]);
9386        assert_eq!("ROLLUP (a, (b, c), d)", format!("{rollup}"));
9387    }
9388
9389    #[test]
9390    fn test_cube_display() {
9391        let cube = Expr::Cube(vec![vec![Expr::Identifier(Ident::new("a"))]]);
9392        assert_eq!("CUBE (a)", format!("{cube}"));
9393
9394        let cube = Expr::Cube(vec![vec![
9395            Expr::Identifier(Ident::new("a")),
9396            Expr::Identifier(Ident::new("b")),
9397        ]]);
9398        assert_eq!("CUBE ((a, b))", format!("{cube}"));
9399
9400        let cube = Expr::Cube(vec![
9401            vec![Expr::Identifier(Ident::new("a"))],
9402            vec![Expr::Identifier(Ident::new("b"))],
9403        ]);
9404        assert_eq!("CUBE (a, b)", format!("{cube}"));
9405
9406        let cube = Expr::Cube(vec![
9407            vec![Expr::Identifier(Ident::new("a"))],
9408            vec![
9409                Expr::Identifier(Ident::new("b")),
9410                Expr::Identifier(Ident::new("c")),
9411            ],
9412            vec![Expr::Identifier(Ident::new("d"))],
9413        ]);
9414        assert_eq!("CUBE (a, (b, c), d)", format!("{cube}"));
9415    }
9416
9417    #[test]
9418    fn test_interval_display() {
9419        let interval = Expr::Interval(Interval {
9420            value: Box::new(Expr::Value(
9421                Value::SingleQuotedString(String::from("123:45.67")).with_empty_span(),
9422            )),
9423            leading_field: Some(DateTimeField::Minute),
9424            leading_precision: Some(10),
9425            last_field: Some(DateTimeField::Second),
9426            fractional_seconds_precision: Some(9),
9427        });
9428        assert_eq!(
9429            "INTERVAL '123:45.67' MINUTE (10) TO SECOND (9)",
9430            format!("{interval}"),
9431        );
9432
9433        let interval = Expr::Interval(Interval {
9434            value: Box::new(Expr::Value(
9435                Value::SingleQuotedString(String::from("5")).with_empty_span(),
9436            )),
9437            leading_field: Some(DateTimeField::Second),
9438            leading_precision: Some(1),
9439            last_field: None,
9440            fractional_seconds_precision: Some(3),
9441        });
9442        assert_eq!("INTERVAL '5' SECOND (1, 3)", format!("{interval}"));
9443    }
9444
9445    #[test]
9446    fn test_one_or_many_with_parens_deref() {
9447        use core::ops::Index;
9448
9449        let one = OneOrManyWithParens::One("a");
9450
9451        assert_eq!(one.deref(), &["a"]);
9452        assert_eq!(<OneOrManyWithParens<_> as Deref>::deref(&one), &["a"]);
9453
9454        assert_eq!(one[0], "a");
9455        assert_eq!(one.index(0), &"a");
9456        assert_eq!(
9457            <<OneOrManyWithParens<_> as Deref>::Target as Index<usize>>::index(&one, 0),
9458            &"a"
9459        );
9460
9461        assert_eq!(one.len(), 1);
9462        assert_eq!(<OneOrManyWithParens<_> as Deref>::Target::len(&one), 1);
9463
9464        let many1 = OneOrManyWithParens::Many(vec!["b"]);
9465
9466        assert_eq!(many1.deref(), &["b"]);
9467        assert_eq!(<OneOrManyWithParens<_> as Deref>::deref(&many1), &["b"]);
9468
9469        assert_eq!(many1[0], "b");
9470        assert_eq!(many1.index(0), &"b");
9471        assert_eq!(
9472            <<OneOrManyWithParens<_> as Deref>::Target as Index<usize>>::index(&many1, 0),
9473            &"b"
9474        );
9475
9476        assert_eq!(many1.len(), 1);
9477        assert_eq!(<OneOrManyWithParens<_> as Deref>::Target::len(&many1), 1);
9478
9479        let many2 = OneOrManyWithParens::Many(vec!["c", "d"]);
9480
9481        assert_eq!(many2.deref(), &["c", "d"]);
9482        assert_eq!(
9483            <OneOrManyWithParens<_> as Deref>::deref(&many2),
9484            &["c", "d"]
9485        );
9486
9487        assert_eq!(many2[0], "c");
9488        assert_eq!(many2.index(0), &"c");
9489        assert_eq!(
9490            <<OneOrManyWithParens<_> as Deref>::Target as Index<usize>>::index(&many2, 0),
9491            &"c"
9492        );
9493
9494        assert_eq!(many2[1], "d");
9495        assert_eq!(many2.index(1), &"d");
9496        assert_eq!(
9497            <<OneOrManyWithParens<_> as Deref>::Target as Index<usize>>::index(&many2, 1),
9498            &"d"
9499        );
9500
9501        assert_eq!(many2.len(), 2);
9502        assert_eq!(<OneOrManyWithParens<_> as Deref>::Target::len(&many2), 2);
9503    }
9504
9505    #[test]
9506    fn test_one_or_many_with_parens_as_ref() {
9507        let one = OneOrManyWithParens::One("a");
9508
9509        assert_eq!(one.as_ref(), &["a"]);
9510        assert_eq!(<OneOrManyWithParens<_> as AsRef<_>>::as_ref(&one), &["a"]);
9511
9512        let many1 = OneOrManyWithParens::Many(vec!["b"]);
9513
9514        assert_eq!(many1.as_ref(), &["b"]);
9515        assert_eq!(<OneOrManyWithParens<_> as AsRef<_>>::as_ref(&many1), &["b"]);
9516
9517        let many2 = OneOrManyWithParens::Many(vec!["c", "d"]);
9518
9519        assert_eq!(many2.as_ref(), &["c", "d"]);
9520        assert_eq!(
9521            <OneOrManyWithParens<_> as AsRef<_>>::as_ref(&many2),
9522            &["c", "d"]
9523        );
9524    }
9525
9526    #[test]
9527    fn test_one_or_many_with_parens_ref_into_iter() {
9528        let one = OneOrManyWithParens::One("a");
9529
9530        assert_eq!(Vec::from_iter(&one), vec![&"a"]);
9531
9532        let many1 = OneOrManyWithParens::Many(vec!["b"]);
9533
9534        assert_eq!(Vec::from_iter(&many1), vec![&"b"]);
9535
9536        let many2 = OneOrManyWithParens::Many(vec!["c", "d"]);
9537
9538        assert_eq!(Vec::from_iter(&many2), vec![&"c", &"d"]);
9539    }
9540
9541    #[test]
9542    fn test_one_or_many_with_parens_value_into_iter() {
9543        use core::iter::once;
9544
9545        //tests that our iterator implemented methods behaves exactly as it's inner iterator, at every step up to n calls to next/next_back
9546        fn test_steps<I>(ours: OneOrManyWithParens<usize>, inner: I, n: usize)
9547        where
9548            I: IntoIterator<Item = usize, IntoIter: DoubleEndedIterator + Clone> + Clone,
9549        {
9550            fn checks<I>(ours: OneOrManyWithParensIntoIter<usize>, inner: I)
9551            where
9552                I: Iterator<Item = usize> + Clone + DoubleEndedIterator,
9553            {
9554                assert_eq!(ours.size_hint(), inner.size_hint());
9555                assert_eq!(ours.clone().count(), inner.clone().count());
9556
9557                assert_eq!(
9558                    ours.clone().fold(1, |a, v| a + v),
9559                    inner.clone().fold(1, |a, v| a + v)
9560                );
9561
9562                assert_eq!(Vec::from_iter(ours.clone()), Vec::from_iter(inner.clone()));
9563                assert_eq!(
9564                    Vec::from_iter(ours.clone().rev()),
9565                    Vec::from_iter(inner.clone().rev())
9566                );
9567            }
9568
9569            let mut ours_next = ours.clone().into_iter();
9570            let mut inner_next = inner.clone().into_iter();
9571
9572            for _ in 0..n {
9573                checks(ours_next.clone(), inner_next.clone());
9574
9575                assert_eq!(ours_next.next(), inner_next.next());
9576            }
9577
9578            let mut ours_next_back = ours.clone().into_iter();
9579            let mut inner_next_back = inner.clone().into_iter();
9580
9581            for _ in 0..n {
9582                checks(ours_next_back.clone(), inner_next_back.clone());
9583
9584                assert_eq!(ours_next_back.next_back(), inner_next_back.next_back());
9585            }
9586
9587            let mut ours_mixed = ours.clone().into_iter();
9588            let mut inner_mixed = inner.clone().into_iter();
9589
9590            for i in 0..n {
9591                checks(ours_mixed.clone(), inner_mixed.clone());
9592
9593                if i % 2 == 0 {
9594                    assert_eq!(ours_mixed.next_back(), inner_mixed.next_back());
9595                } else {
9596                    assert_eq!(ours_mixed.next(), inner_mixed.next());
9597                }
9598            }
9599
9600            let mut ours_mixed2 = ours.into_iter();
9601            let mut inner_mixed2 = inner.into_iter();
9602
9603            for i in 0..n {
9604                checks(ours_mixed2.clone(), inner_mixed2.clone());
9605
9606                if i % 2 == 0 {
9607                    assert_eq!(ours_mixed2.next(), inner_mixed2.next());
9608                } else {
9609                    assert_eq!(ours_mixed2.next_back(), inner_mixed2.next_back());
9610                }
9611            }
9612        }
9613
9614        test_steps(OneOrManyWithParens::One(1), once(1), 3);
9615        test_steps(OneOrManyWithParens::Many(vec![2]), vec![2], 3);
9616        test_steps(OneOrManyWithParens::Many(vec![3, 4]), vec![3, 4], 4);
9617    }
9618}