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