Skip to main content

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