Deprecated: The each() function is deprecated. This message will be suppressed on further calls in /home/zhenxiangba/zhenxiangba.com/public_html/phproxy-improved-master/index.php on line 456
mod.rs - source
[go: Go Back, main page]

sqlparser/ast/
mod.rs

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