sqltk_parser/ast/
mod.rs

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