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,
25    vec::Vec,
26};
27use helpers::{
28    attached_token::AttachedToken,
29    stmt_data_loading::{FileStagingCommand, StageLoadSelectItemKind},
30};
31
32use core::cmp::Ordering;
33use core::ops::Deref;
34use core::{
35    fmt::{self, Display},
36    hash,
37};
38
39#[cfg(feature = "serde")]
40use serde::{Deserialize, Serialize};
41
42#[cfg(feature = "visitor")]
43use yachtsql_sqlparser_derive::{Visit, VisitMut};
44
45use crate::{
46    display_utils::{indented_list, SpaceOrNewline},
47    tokenizer::{Span, Token},
48};
49use crate::{
50    display_utils::{Indent, NewLine},
51    keywords::Keyword,
52};
53
54pub use self::data_type::{
55    ArrayElemTypeDef, BinaryLength, CharLengthUnits, CharacterLength, DataType, EnumMember,
56    ExactNumberInfo, IntervalFields, StructBracketKind, TimezoneInfo,
57};
58pub use self::dcl::{
59    AlterRoleOperation, ResetConfig, RoleOption, SecondaryRoles, SetConfigValue, Use,
60};
61pub use self::ddl::{
62    AlterColumnOperation, AlterConnectorOwner, AlterIndexOperation, AlterPolicyOperation,
63    AlterSchema, AlterSchemaOperation, AlterTableAlgorithm, AlterTableLock, AlterTableOperation,
64    AlterType, AlterTypeAddValue, AlterTypeAddValuePosition, AlterTypeOperation, AlterTypeRename,
65    AlterTypeRenameValue, ClusteredBy, ColumnDef, ColumnOption, ColumnOptionDef, ColumnOptions,
66    ColumnPolicy, ColumnPolicyProperty, ConstraintCharacteristics, CreateConnector, CreateDomain,
67    CreateFunction, CreateIndex, CreateTable, CreateTrigger, Deduplicate, DeferrableInitial,
68    DropBehavior, DropTrigger, GeneratedAs, GeneratedExpressionMode, IdentityParameters,
69    IdentityProperty, IdentityPropertyFormatKind, IdentityPropertyKind, IdentityPropertyOrder,
70    IndexColumn, IndexOption, IndexType, KeyOrIndexDisplay, NullsDistinctOption, Owner, Partition,
71    ProcedureParam, ReferentialAction, RenameTableNameKind, ReplicaIdentity, TableConstraint,
72    TagsColumnOption, UserDefinedTypeCompositeAttributeDef, UserDefinedTypeRepresentation,
73    ViewColumnDef,
74};
75pub use self::dml::{Delete, Insert};
76pub use self::operator::{BinaryOperator, UnaryOperator};
77pub use self::query::{
78    AfterMatchSkip, ConnectBy, Cte, CteAsMaterialized, Distinct, EmptyMatchesMode,
79    ExceptSelectItem, ExcludeSelectItem, ExprWithAlias, ExprWithAliasAndOrderBy, Fetch, ForClause,
80    ForJson, ForXml, FormatClause, GroupByExpr, GroupByWithModifier, IdentWithAlias,
81    IlikeSelectItem, InputFormatClause, Interpolate, InterpolateExpr, Join, JoinConstraint,
82    JoinOperator, JsonTableColumn, JsonTableColumnErrorHandling, JsonTableNamedColumn,
83    JsonTableNestedColumn, LateralView, LimitClause, LockClause, LockType, MatchRecognizePattern,
84    MatchRecognizeSymbol, Measure, NamedWindowDefinition, NamedWindowExpr, NonBlock, Offset,
85    OffsetRows, OpenJsonTableColumn, OrderBy, OrderByExpr, OrderByKind, OrderByOptions,
86    PipeOperator, PivotValueSource, ProjectionSelect, Query, RenameSelectItem,
87    RepetitionQuantifier, ReplaceSelectElement, ReplaceSelectItem, RowsPerMatch, Select,
88    SelectFlavor, SelectInto, SelectItem, SelectItemQualifiedWildcardKind, SetExpr, SetOperator,
89    SetQuantifier, Setting, SymbolDefinition, Table, TableAlias, TableAliasColumnDef, TableFactor,
90    TableFunctionArgs, TableIndexHintForClause, TableIndexHintType, TableIndexHints,
91    TableIndexType, TableSample, TableSampleBucket, TableSampleKind, TableSampleMethod,
92    TableSampleModifier, TableSampleQuantity, TableSampleSeed, TableSampleSeedModifier,
93    TableSampleUnit, TableVersion, TableWithJoins, Top, TopQuantity, UpdateTableFromKind,
94    ValueTableMode, Values, WildcardAdditionalOptions, With, WithFill, XmlNamespaceDefinition,
95    XmlPassingArgument, XmlPassingClause, XmlTableColumn, XmlTableColumnOption,
96};
97
98pub use self::trigger::{
99    TriggerEvent, TriggerExecBody, TriggerExecBodyType, TriggerObject, TriggerPeriod,
100    TriggerReferencing, TriggerReferencingType,
101};
102
103pub use self::value::{
104    escape_double_quote_string, escape_quoted_string, DateTimeField, DollarQuotedString,
105    NormalizationForm, TrimWhereField, Value, ValueWithSpan,
106};
107
108use crate::ast::helpers::key_value_options::KeyValueOptions;
109use crate::ast::helpers::stmt_data_loading::StageParamsObject;
110
111#[cfg(feature = "visitor")]
112pub use visitor::*;
113
114pub use self::data_type::GeometricTypeKind;
115
116mod data_type;
117mod dcl;
118mod ddl;
119mod dml;
120pub mod helpers;
121mod operator;
122mod query;
123mod spans;
124pub use spans::Spanned;
125
126mod trigger;
127mod value;
128
129#[cfg(feature = "visitor")]
130mod visitor;
131
132pub struct DisplaySeparated<'a, T>
133where
134    T: fmt::Display,
135{
136    slice: &'a [T],
137    sep: &'static str,
138}
139
140impl<T> fmt::Display for DisplaySeparated<'_, T>
141where
142    T: fmt::Display,
143{
144    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
145        let mut delim = "";
146        for t in self.slice {
147            f.write_str(delim)?;
148            delim = self.sep;
149            t.fmt(f)?;
150        }
151        Ok(())
152    }
153}
154
155pub fn display_separated<'a, T>(slice: &'a [T], sep: &'static str) -> DisplaySeparated<'a, T>
156where
157    T: fmt::Display,
158{
159    DisplaySeparated { slice, sep }
160}
161
162pub fn display_comma_separated<T>(slice: &[T]) -> DisplaySeparated<'_, T>
163where
164    T: fmt::Display,
165{
166    DisplaySeparated { slice, sep: ", " }
167}
168
169/// Writes the given statements to the formatter, each ending with
170/// a semicolon and space separated.
171fn format_statement_list(f: &mut fmt::Formatter, statements: &[Statement]) -> fmt::Result {
172    write!(f, "{}", display_separated(statements, "; "))?;
173    // We manually insert semicolon for the last statement,
174    // since display_separated doesn't handle that case.
175    write!(f, ";")
176}
177
178/// An identifier, decomposed into its value or character data and the quote style.
179#[derive(Debug, Clone)]
180#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
181#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
182pub struct Ident {
183    /// The value of the identifier without quotes.
184    pub value: String,
185    /// The starting quote if any. Valid quote characters are the single quote,
186    /// double quote, backtick, and opening square bracket.
187    pub quote_style: Option<char>,
188    /// The span of the identifier in the original SQL string.
189    pub span: Span,
190}
191
192impl PartialEq for Ident {
193    fn eq(&self, other: &Self) -> bool {
194        let Ident {
195            value,
196            quote_style,
197            // exhaustiveness check; we ignore spans in comparisons
198            span: _,
199        } = self;
200
201        value == &other.value && quote_style == &other.quote_style
202    }
203}
204
205impl core::hash::Hash for Ident {
206    fn hash<H: hash::Hasher>(&self, state: &mut H) {
207        let Ident {
208            value,
209            quote_style,
210            // exhaustiveness check; we ignore spans in hashes
211            span: _,
212        } = self;
213
214        value.hash(state);
215        quote_style.hash(state);
216    }
217}
218
219impl Eq for Ident {}
220
221impl PartialOrd for Ident {
222    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
223        Some(self.cmp(other))
224    }
225}
226
227impl Ord for Ident {
228    fn cmp(&self, other: &Self) -> Ordering {
229        let Ident {
230            value,
231            quote_style,
232            // exhaustiveness check; we ignore spans in ordering
233            span: _,
234        } = self;
235
236        let Ident {
237            value: other_value,
238            quote_style: other_quote_style,
239            // exhaustiveness check; we ignore spans in ordering
240            span: _,
241        } = other;
242
243        // First compare by value, then by quote_style
244        value
245            .cmp(other_value)
246            .then_with(|| quote_style.cmp(other_quote_style))
247    }
248}
249
250impl Ident {
251    /// Create a new identifier with the given value and no quotes and an empty span.
252    pub fn new<S>(value: S) -> Self
253    where
254        S: Into<String>,
255    {
256        Ident {
257            value: value.into(),
258            quote_style: None,
259            span: Span::empty(),
260        }
261    }
262
263    /// Create a new quoted identifier with the given quote and value. This function
264    /// panics if the given quote is not a valid quote character.
265    pub fn with_quote<S>(quote: char, value: S) -> Self
266    where
267        S: Into<String>,
268    {
269        assert!(quote == '\'' || quote == '"' || quote == '`' || quote == '[');
270        Ident {
271            value: value.into(),
272            quote_style: Some(quote),
273            span: Span::empty(),
274        }
275    }
276
277    pub fn with_span<S>(span: Span, value: S) -> Self
278    where
279        S: Into<String>,
280    {
281        Ident {
282            value: value.into(),
283            quote_style: None,
284            span,
285        }
286    }
287
288    pub fn with_quote_and_span<S>(quote: char, span: Span, value: S) -> Self
289    where
290        S: Into<String>,
291    {
292        assert!(quote == '\'' || quote == '"' || quote == '`' || quote == '[');
293        Ident {
294            value: value.into(),
295            quote_style: Some(quote),
296            span,
297        }
298    }
299}
300
301impl From<&str> for Ident {
302    fn from(value: &str) -> Self {
303        Ident {
304            value: value.to_string(),
305            quote_style: None,
306            span: Span::empty(),
307        }
308    }
309}
310
311impl fmt::Display for Ident {
312    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
313        match self.quote_style {
314            Some(q) if q == '"' || q == '\'' || q == '`' => {
315                let escaped = value::escape_quoted_string(&self.value, q);
316                write!(f, "{q}{escaped}{q}")
317            }
318            Some('[') => write!(f, "[{}]", self.value),
319            None => f.write_str(&self.value),
320            _ => panic!("unexpected quote style"),
321        }
322    }
323}
324
325/// A name of a table, view, custom type, etc., possibly multi-part, i.e. db.schema.obj
326#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
327#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
328#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
329pub struct ObjectName(pub Vec<ObjectNamePart>);
330
331impl From<Vec<Ident>> for ObjectName {
332    fn from(idents: Vec<Ident>) -> Self {
333        ObjectName(idents.into_iter().map(ObjectNamePart::Identifier).collect())
334    }
335}
336
337impl fmt::Display for ObjectName {
338    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
339        write!(f, "{}", display_separated(&self.0, "."))
340    }
341}
342
343/// A single part of an ObjectName
344#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
345#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
346#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
347pub enum ObjectNamePart {
348    Identifier(Ident),
349    Function(ObjectNamePartFunction),
350}
351
352impl ObjectNamePart {
353    pub fn as_ident(&self) -> Option<&Ident> {
354        match self {
355            ObjectNamePart::Identifier(ident) => Some(ident),
356            ObjectNamePart::Function(_) => None,
357        }
358    }
359}
360
361impl fmt::Display for ObjectNamePart {
362    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
363        match self {
364            ObjectNamePart::Identifier(ident) => write!(f, "{ident}"),
365            ObjectNamePart::Function(func) => write!(f, "{func}"),
366        }
367    }
368}
369
370/// An object name part that consists of a function that dynamically
371/// constructs identifiers.
372///
373/// - [Snowflake](https://docs.snowflake.com/en/sql-reference/identifier-literal)
374#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
375#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
376#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
377pub struct ObjectNamePartFunction {
378    pub name: Ident,
379    pub args: Vec<FunctionArg>,
380}
381
382impl fmt::Display for ObjectNamePartFunction {
383    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
384        write!(f, "{}(", self.name)?;
385        write!(f, "{})", display_comma_separated(&self.args))
386    }
387}
388
389/// Represents an Array Expression, either
390/// `ARRAY[..]`, or `[..]`
391#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
392#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
393#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
394pub struct Array {
395    /// The list of expressions between brackets
396    pub elem: Vec<Expr>,
397
398    /// `true` for  `ARRAY[..]`, `false` for `[..]`
399    pub named: bool,
400}
401
402impl fmt::Display for Array {
403    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
404        write!(
405            f,
406            "{}[{}]",
407            if self.named { "ARRAY" } else { "" },
408            display_comma_separated(&self.elem)
409        )
410    }
411}
412
413/// A typed array expression e.g. `ARRAY<INT64>[1, 2, 3]`
414#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
415#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
416#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
417pub struct TypedArray {
418    /// The data type of the array elements
419    pub data_type: DataType,
420    /// The list of expressions between brackets
421    pub elem: Vec<Expr>,
422}
423
424impl fmt::Display for TypedArray {
425    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
426        write!(
427            f,
428            "ARRAY<{}>[{}]",
429            self.data_type,
430            display_comma_separated(&self.elem)
431        )
432    }
433}
434
435/// Represents an INTERVAL expression, roughly in the following format:
436/// `INTERVAL '<value>' [ <leading_field> [ (<leading_precision>) ] ]
437/// [ TO <last_field> [ (<fractional_seconds_precision>) ] ]`,
438/// e.g. `INTERVAL '123:45.67' MINUTE(3) TO SECOND(2)`.
439///
440/// The parser does not validate the `<value>`, nor does it ensure
441/// that the `<leading_field>` units >= the units in `<last_field>`,
442/// so the user will have to reject intervals like `HOUR TO YEAR`.
443#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
444#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
445#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
446pub struct Interval {
447    pub value: Box<Expr>,
448    pub leading_field: Option<DateTimeField>,
449    pub leading_precision: Option<u64>,
450    pub last_field: Option<DateTimeField>,
451    /// The seconds precision can be specified in SQL source as
452    /// `INTERVAL '__' SECOND(_, x)` (in which case the `leading_field`
453    /// will be `Second` and the `last_field` will be `None`),
454    /// or as `__ TO SECOND(x)`.
455    pub fractional_seconds_precision: Option<u64>,
456}
457
458impl fmt::Display for Interval {
459    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
460        let value = self.value.as_ref();
461        match (
462            &self.leading_field,
463            self.leading_precision,
464            self.fractional_seconds_precision,
465        ) {
466            (
467                Some(DateTimeField::Second),
468                Some(leading_precision),
469                Some(fractional_seconds_precision),
470            ) => {
471                // When the leading field is SECOND, the parser guarantees that
472                // the last field is None.
473                assert!(self.last_field.is_none());
474                write!(
475                    f,
476                    "INTERVAL {value} SECOND ({leading_precision}, {fractional_seconds_precision})"
477                )
478            }
479            _ => {
480                write!(f, "INTERVAL {value}")?;
481                if let Some(leading_field) = &self.leading_field {
482                    write!(f, " {leading_field}")?;
483                }
484                if let Some(leading_precision) = self.leading_precision {
485                    write!(f, " ({leading_precision})")?;
486                }
487                if let Some(last_field) = &self.last_field {
488                    write!(f, " TO {last_field}")?;
489                }
490                if let Some(fractional_seconds_precision) = self.fractional_seconds_precision {
491                    write!(f, " ({fractional_seconds_precision})")?;
492                }
493                Ok(())
494            }
495        }
496    }
497}
498
499/// A field definition within a struct
500///
501/// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-types#struct_type
502#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
503#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
504#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
505pub struct StructField {
506    pub field_name: Option<Ident>,
507    pub field_type: DataType,
508    /// Struct field options.
509    /// See [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#column_name_and_column_schema)
510    pub options: Option<Vec<SqlOption>>,
511}
512
513impl fmt::Display for StructField {
514    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
515        if let Some(name) = &self.field_name {
516            write!(f, "{name} {}", self.field_type)?;
517        } else {
518            write!(f, "{}", self.field_type)?;
519        }
520        if let Some(options) = &self.options {
521            write!(f, " OPTIONS({})", display_separated(options, ", "))
522        } else {
523            Ok(())
524        }
525    }
526}
527
528/// A field definition within a union
529///
530/// [DuckDB]: https://duckdb.org/docs/sql/data_types/union.html
531#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
532#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
533#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
534pub struct UnionField {
535    pub field_name: Ident,
536    pub field_type: DataType,
537}
538
539impl fmt::Display for UnionField {
540    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
541        write!(f, "{} {}", self.field_name, self.field_type)
542    }
543}
544
545/// A dictionary field within a dictionary.
546///
547/// [DuckDB]: https://duckdb.org/docs/sql/data_types/struct#creating-structs
548#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
549#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
550#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
551pub struct DictionaryField {
552    pub key: Ident,
553    pub value: Box<Expr>,
554}
555
556impl fmt::Display for DictionaryField {
557    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
558        write!(f, "{}: {}", self.key, self.value)
559    }
560}
561
562/// Represents a Map expression.
563#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
564#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
565#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
566pub struct Map {
567    pub entries: Vec<MapEntry>,
568}
569
570impl Display for Map {
571    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
572        write!(f, "MAP {{{}}}", display_comma_separated(&self.entries))
573    }
574}
575
576/// A map field within a map.
577///
578/// [DuckDB]: https://duckdb.org/docs/sql/data_types/map.html#creating-maps
579#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
580#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
581#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
582pub struct MapEntry {
583    pub key: Box<Expr>,
584    pub value: Box<Expr>,
585}
586
587impl fmt::Display for MapEntry {
588    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
589        write!(f, "{}: {}", self.key, self.value)
590    }
591}
592
593/// Options for `CAST` / `TRY_CAST`
594/// BigQuery: <https://cloud.google.com/bigquery/docs/reference/standard-sql/format-elements#formatting_syntax>
595#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
596#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
597#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
598pub enum CastFormat {
599    Value(Value),
600    ValueAtTimeZone(Value, Value),
601}
602
603/// An element of a JSON path.
604#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
605#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
606#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
607pub enum JsonPathElem {
608    /// Accesses an object field using dot notation, e.g. `obj:foo.bar.baz`.
609    ///
610    /// See <https://docs.snowflake.com/en/user-guide/querying-semistructured#dot-notation>.
611    Dot { key: String, quoted: bool },
612    /// Accesses an object field or array element using bracket notation,
613    /// e.g. `obj['foo']`.
614    ///
615    /// See <https://docs.snowflake.com/en/user-guide/querying-semistructured#bracket-notation>.
616    Bracket { key: Expr },
617}
618
619/// A JSON path.
620///
621/// See <https://docs.snowflake.com/en/user-guide/querying-semistructured>.
622/// See <https://docs.databricks.com/en/sql/language-manual/sql-ref-json-path-expression.html>.
623#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
624#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
625#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
626pub struct JsonPath {
627    pub path: Vec<JsonPathElem>,
628}
629
630impl fmt::Display for JsonPath {
631    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
632        for (i, elem) in self.path.iter().enumerate() {
633            match elem {
634                JsonPathElem::Dot { key, quoted } => {
635                    if i == 0 {
636                        write!(f, ":")?;
637                    } else {
638                        write!(f, ".")?;
639                    }
640
641                    if *quoted {
642                        write!(f, "\"{}\"", escape_double_quote_string(key))?;
643                    } else {
644                        write!(f, "{key}")?;
645                    }
646                }
647                JsonPathElem::Bracket { key } => {
648                    write!(f, "[{key}]")?;
649                }
650            }
651        }
652        Ok(())
653    }
654}
655
656/// The syntax used for in a cast expression.
657#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
658#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
659#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
660pub enum CastKind {
661    /// The standard SQL cast syntax, e.g. `CAST(<expr> as <datatype>)`
662    Cast,
663    /// A cast that returns `NULL` on failure, e.g. `TRY_CAST(<expr> as <datatype>)`.
664    ///
665    /// See <https://docs.snowflake.com/en/sql-reference/functions/try_cast>.
666    /// See <https://learn.microsoft.com/en-us/sql/t-sql/functions/try-cast-transact-sql>.
667    TryCast,
668    /// A cast that returns `NULL` on failure, bigQuery-specific ,  e.g. `SAFE_CAST(<expr> as <datatype>)`.
669    ///
670    /// See <https://cloud.google.com/bigquery/docs/reference/standard-sql/functions-and-operators#safe_casting>.
671    SafeCast,
672    /// `<expr> :: <datatype>`
673    DoubleColon,
674}
675
676/// `EXTRACT` syntax variants.
677///
678/// In Snowflake dialect, the `EXTRACT` expression can support either the `from` syntax
679/// or the comma syntax.
680///
681/// See <https://docs.snowflake.com/en/sql-reference/functions/extract>
682#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
683#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
684#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
685pub enum ExtractSyntax {
686    /// `EXTRACT( <date_or_time_part> FROM <date_or_time_expr> )`
687    From,
688    /// `EXTRACT( <date_or_time_part> , <date_or_timestamp_expr> )`
689    Comma,
690}
691
692/// The syntax used in a CEIL or FLOOR expression.
693///
694/// The `CEIL/FLOOR(<datetime value expression> TO <time unit>)` is an Amazon Kinesis Data Analytics extension.
695/// See <https://docs.aws.amazon.com/kinesisanalytics/latest/sqlref/sql-reference-ceil.html> for
696/// details.
697///
698/// Other dialects either support `CEIL/FLOOR( <expr> [, <scale>])` format or just
699/// `CEIL/FLOOR(<expr>)`.
700#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
701#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
702#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
703pub enum CeilFloorKind {
704    /// `CEIL( <expr> TO <DateTimeField>)`
705    DateTimeField(DateTimeField),
706    /// `CEIL( <expr> [, <scale>])`
707    Scale(Value),
708}
709
710/// A WHEN clause in a CASE expression containing both
711/// the condition and its corresponding result
712#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
713#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
714#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
715pub struct CaseWhen {
716    pub condition: Expr,
717    pub result: Expr,
718}
719
720impl fmt::Display for CaseWhen {
721    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
722        f.write_str("WHEN ")?;
723        self.condition.fmt(f)?;
724        f.write_str(" THEN")?;
725        SpaceOrNewline.fmt(f)?;
726        Indent(&self.result).fmt(f)?;
727        Ok(())
728    }
729}
730
731/// An SQL expression of any type.
732///
733/// # Semantics / Type Checking
734///
735/// The parser does not distinguish between expressions of different types
736/// (e.g. boolean vs string). The caller is responsible for detecting and
737/// validating types as necessary (for example  `WHERE 1` vs `SELECT 1=1`)
738/// See the [README.md] for more details.
739///
740/// [README.md]: https://github.com/apache/datafusion-sqlparser-rs/blob/main/README.md#syntax-vs-semantics
741///
742/// # Equality and Hashing Does not Include Source Locations
743///
744/// The `Expr` type implements `PartialEq` and `Eq` based on the semantic value
745/// of the expression (not bitwise comparison). This means that `Expr` instances
746/// that are semantically equivalent but have different spans (locations in the
747/// source tree) will compare as equal.
748#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
749#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
750#[cfg_attr(
751    feature = "visitor",
752    derive(Visit, VisitMut),
753    visit(with = "visit_expr")
754)]
755pub enum Expr {
756    /// Identifier e.g. table name or column name
757    Identifier(Ident),
758    /// Multi-part identifier, e.g. `table_alias.column` or `schema.table.col`
759    CompoundIdentifier(Vec<Ident>),
760    /// Multi-part expression access.
761    ///
762    /// This structure represents an access chain in structured / nested types
763    /// such as maps, arrays, and lists:
764    /// - Array
765    ///     - A 1-dim array `a[1]` will be represented like:
766    ///       `CompoundFieldAccess(Ident('a'), vec![Subscript(1)]`
767    ///     - A 2-dim array `a[1][2]` will be represented like:
768    ///       `CompoundFieldAccess(Ident('a'), vec![Subscript(1), Subscript(2)]`
769    /// - Map or Struct (Bracket-style)
770    ///     - A map `a['field1']` will be represented like:
771    ///       `CompoundFieldAccess(Ident('a'), vec![Subscript('field')]`
772    ///     - A 2-dim map `a['field1']['field2']` will be represented like:
773    ///       `CompoundFieldAccess(Ident('a'), vec![Subscript('field1'), Subscript('field2')]`
774    /// - Struct (Dot-style) (only effect when the chain contains both subscript and expr)
775    ///     - A struct access `a[field1].field2` will be represented like:
776    ///       `CompoundFieldAccess(Ident('a'), vec![Subscript('field1'), Ident('field2')]`
777    /// - If a struct access likes `a.field1.field2`, it will be represented by CompoundIdentifier([a, field1, field2])
778    CompoundFieldAccess {
779        root: Box<Expr>,
780        access_chain: Vec<AccessExpr>,
781    },
782    /// Access data nested in a value containing semi-structured data, such as
783    /// the `VARIANT` type on Snowflake. for example `src:customer[0].name`.
784    ///
785    /// See <https://docs.snowflake.com/en/user-guide/querying-semistructured>.
786    /// See <https://docs.databricks.com/en/sql/language-manual/functions/colonsign.html>.
787    JsonAccess {
788        /// The value being queried.
789        value: Box<Expr>,
790        /// The path to the data to extract.
791        path: JsonPath,
792    },
793    /// `IS FALSE` operator
794    IsFalse(Box<Expr>),
795    /// `IS NOT FALSE` operator
796    IsNotFalse(Box<Expr>),
797    /// `IS TRUE` operator
798    IsTrue(Box<Expr>),
799    /// `IS NOT TRUE` operator
800    IsNotTrue(Box<Expr>),
801    /// `IS NULL` operator
802    IsNull(Box<Expr>),
803    /// `IS NOT NULL` operator
804    IsNotNull(Box<Expr>),
805    /// `IS UNKNOWN` operator
806    IsUnknown(Box<Expr>),
807    /// `IS NOT UNKNOWN` operator
808    IsNotUnknown(Box<Expr>),
809    /// `IS DISTINCT FROM` operator
810    IsDistinctFrom(Box<Expr>, Box<Expr>),
811    /// `IS NOT DISTINCT FROM` operator
812    IsNotDistinctFrom(Box<Expr>, Box<Expr>),
813    /// `<expr> IS [ NOT ] [ form ] NORMALIZED`
814    IsNormalized {
815        expr: Box<Expr>,
816        form: Option<NormalizationForm>,
817        negated: bool,
818    },
819    /// `[ NOT ] IN (val1, val2, ...)`
820    InList {
821        expr: Box<Expr>,
822        list: Vec<Expr>,
823        negated: bool,
824    },
825    /// `[ NOT ] IN (SELECT ...)`
826    InSubquery {
827        expr: Box<Expr>,
828        subquery: Box<Query>,
829        negated: bool,
830    },
831    /// `[ NOT ] IN UNNEST(array_expression)`
832    InUnnest {
833        expr: Box<Expr>,
834        array_expr: Box<Expr>,
835        negated: bool,
836    },
837    /// `<expr> [ NOT ] BETWEEN <low> AND <high>`
838    Between {
839        expr: Box<Expr>,
840        negated: bool,
841        low: Box<Expr>,
842        high: Box<Expr>,
843    },
844    /// Binary operation e.g. `1 + 1` or `foo > bar`
845    BinaryOp {
846        left: Box<Expr>,
847        op: BinaryOperator,
848        right: Box<Expr>,
849    },
850    /// `[NOT] LIKE <pattern> [ESCAPE <escape_character>]`
851    Like {
852        negated: bool,
853        // Snowflake supports the ANY keyword to match against a list of patterns
854        // https://docs.snowflake.com/en/sql-reference/functions/like_any
855        any: bool,
856        expr: Box<Expr>,
857        pattern: Box<Expr>,
858        escape_char: Option<Value>,
859    },
860    /// `ILIKE` (case-insensitive `LIKE`)
861    ILike {
862        negated: bool,
863        // Snowflake supports the ANY keyword to match against a list of patterns
864        // https://docs.snowflake.com/en/sql-reference/functions/like_any
865        any: bool,
866        expr: Box<Expr>,
867        pattern: Box<Expr>,
868        escape_char: Option<Value>,
869    },
870    /// SIMILAR TO regex
871    SimilarTo {
872        negated: bool,
873        expr: Box<Expr>,
874        pattern: Box<Expr>,
875        escape_char: Option<Value>,
876    },
877    /// MySQL: RLIKE regex or REGEXP regex
878    RLike {
879        negated: bool,
880        expr: Box<Expr>,
881        pattern: Box<Expr>,
882        // true for REGEXP, false for RLIKE (no difference in semantics)
883        regexp: bool,
884    },
885    /// `ANY` operation e.g. `foo > ANY(bar)`, comparison operator is one of `[=, >, <, =>, =<, !=]`
886    /// <https://docs.snowflake.com/en/sql-reference/operators-subquery#all-any>
887    AnyOp {
888        left: Box<Expr>,
889        compare_op: BinaryOperator,
890        right: Box<Expr>,
891        // ANY and SOME are synonymous: https://docs.cloudera.com/cdw-runtime/cloud/using-hiveql/topics/hive_comparison_predicates.html
892        is_some: bool,
893    },
894    /// `ALL` operation e.g. `foo > ALL(bar)`, comparison operator is one of `[=, >, <, =>, =<, !=]`
895    /// <https://docs.snowflake.com/en/sql-reference/operators-subquery#all-any>
896    AllOp {
897        left: Box<Expr>,
898        compare_op: BinaryOperator,
899        right: Box<Expr>,
900    },
901    /// Unary operation e.g. `NOT foo`
902    UnaryOp {
903        op: UnaryOperator,
904        expr: Box<Expr>,
905    },
906    /// CONVERT a value to a different data type or character encoding. e.g. `CONVERT(foo USING utf8mb4)`
907    Convert {
908        /// CONVERT (false) or TRY_CONVERT (true)
909        /// <https://learn.microsoft.com/en-us/sql/t-sql/functions/try-convert-transact-sql?view=sql-server-ver16>
910        is_try: bool,
911        /// The expression to convert
912        expr: Box<Expr>,
913        /// The target data type
914        data_type: Option<DataType>,
915        /// The target character encoding
916        charset: Option<ObjectName>,
917        /// whether the target comes before the expr (MSSQL syntax)
918        target_before_value: bool,
919        /// How to translate the expression.
920        ///
921        /// [MSSQL]: https://learn.microsoft.com/en-us/sql/t-sql/functions/cast-and-convert-transact-sql?view=sql-server-ver16#style
922        styles: Vec<Expr>,
923    },
924    /// `CAST` an expression to a different data type e.g. `CAST(foo AS VARCHAR(123))`
925    Cast {
926        kind: CastKind,
927        expr: Box<Expr>,
928        data_type: DataType,
929        /// Optional CAST(string_expression AS type FORMAT format_string_expression) as used by [BigQuery]
930        ///
931        /// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/format-elements#formatting_syntax
932        format: Option<CastFormat>,
933    },
934    /// AT a timestamp to a different timezone e.g. `FROM_UNIXTIME(0) AT TIME ZONE 'UTC-06:00'`
935    AtTimeZone {
936        timestamp: Box<Expr>,
937        time_zone: Box<Expr>,
938    },
939    /// Extract a field from a timestamp e.g. `EXTRACT(MONTH FROM foo)`
940    /// Or `EXTRACT(MONTH, foo)`
941    ///
942    /// Syntax:
943    /// ```sql
944    /// EXTRACT(DateTimeField FROM <expr>) | EXTRACT(DateTimeField, <expr>)
945    /// ```
946    Extract {
947        field: DateTimeField,
948        syntax: ExtractSyntax,
949        expr: Box<Expr>,
950    },
951    /// ```sql
952    /// CEIL(<expr> [TO DateTimeField])
953    /// ```
954    /// ```sql
955    /// CEIL( <input_expr> [, <scale_expr> ] )
956    /// ```
957    Ceil {
958        expr: Box<Expr>,
959        field: CeilFloorKind,
960    },
961    /// ```sql
962    /// FLOOR(<expr> [TO DateTimeField])
963    /// ```
964    /// ```sql
965    /// FLOOR( <input_expr> [, <scale_expr> ] )
966    ///
967    Floor {
968        expr: Box<Expr>,
969        field: CeilFloorKind,
970    },
971    /// ```sql
972    /// POSITION(<expr> in <expr>)
973    /// ```
974    Position {
975        expr: Box<Expr>,
976        r#in: Box<Expr>,
977    },
978    /// ```sql
979    /// SUBSTRING(<expr> [FROM <expr>] [FOR <expr>])
980    /// ```
981    /// or
982    /// ```sql
983    /// SUBSTRING(<expr>, <expr>, <expr>)
984    /// ```
985    Substring {
986        expr: Box<Expr>,
987        substring_from: Option<Box<Expr>>,
988        substring_for: Option<Box<Expr>>,
989
990        /// false if the expression is represented using the `SUBSTRING(expr [FROM start] [FOR len])` syntax
991        /// true if the expression is represented using the `SUBSTRING(expr, start, len)` syntax
992        /// This flag is used for formatting.
993        special: bool,
994
995        /// true if the expression is represented using the `SUBSTR` shorthand
996        /// This flag is used for formatting.
997        shorthand: bool,
998    },
999    /// ```sql
1000    /// TRIM([BOTH | LEADING | TRAILING] [<expr> FROM] <expr>)
1001    /// TRIM(<expr>)
1002    /// TRIM(<expr>, [, characters]) -- only Snowflake or Bigquery
1003    /// ```
1004    Trim {
1005        expr: Box<Expr>,
1006        // ([BOTH | LEADING | TRAILING]
1007        trim_where: Option<TrimWhereField>,
1008        trim_what: Option<Box<Expr>>,
1009        trim_characters: Option<Vec<Expr>>,
1010    },
1011    /// ```sql
1012    /// OVERLAY(<expr> PLACING <expr> FROM <expr>[ FOR <expr> ]
1013    /// ```
1014    Overlay {
1015        expr: Box<Expr>,
1016        overlay_what: Box<Expr>,
1017        overlay_from: Box<Expr>,
1018        overlay_for: Option<Box<Expr>>,
1019    },
1020    /// `expr COLLATE collation`
1021    Collate {
1022        expr: Box<Expr>,
1023        collation: ObjectName,
1024    },
1025    /// Nested expression e.g. `(foo > bar)` or `(1)`
1026    Nested(Box<Expr>),
1027    /// A literal value, such as string, number, date or NULL
1028    Value(ValueWithSpan),
1029    /// Prefixed expression, e.g. introducer strings, projection prefix
1030    /// <https://dev.mysql.com/doc/refman/8.0/en/charset-introducer.html>
1031    /// <https://docs.snowflake.com/en/sql-reference/constructs/connect-by>
1032    Prefixed {
1033        prefix: Ident,
1034        /// The value of the constant.
1035        /// Hint: you can unwrap the string value using `value.into_string()`.
1036        value: Box<Expr>,
1037    },
1038    /// A constant of form `<data_type> 'value'`.
1039    /// This can represent ANSI SQL `DATE`, `TIME`, and `TIMESTAMP` literals (such as `DATE '2020-01-01'`),
1040    /// as well as constants of other types (a non-standard PostgreSQL extension).
1041    TypedString(TypedString),
1042    /// Scalar function call e.g. `LEFT(foo, 5)`
1043    Function(Function),
1044    /// `CASE [<operand>] WHEN <condition> THEN <result> ... [ELSE <result>] END`
1045    ///
1046    /// Note we only recognize a complete single expression as `<condition>`,
1047    /// not `< 0` nor `1, 2, 3` as allowed in a `<simple when clause>` per
1048    /// <https://jakewheat.github.io/sql-overview/sql-2011-foundation-grammar.html#simple-when-clause>
1049    Case {
1050        case_token: AttachedToken,
1051        end_token: AttachedToken,
1052        operand: Option<Box<Expr>>,
1053        conditions: Vec<CaseWhen>,
1054        else_result: Option<Box<Expr>>,
1055    },
1056    /// An exists expression `[ NOT ] EXISTS(SELECT ...)`, used in expressions like
1057    /// `WHERE [ NOT ] EXISTS (SELECT ...)`.
1058    Exists {
1059        subquery: Box<Query>,
1060        negated: bool,
1061    },
1062    /// A parenthesized subquery `(SELECT ...)`, used in expression like
1063    /// `SELECT (subquery) AS x` or `WHERE (subquery) = x`
1064    Subquery(Box<Query>),
1065    /// The `GROUPING SETS` expr.
1066    GroupingSets(Vec<Vec<Expr>>),
1067    /// The `CUBE` expr.
1068    Cube(Vec<Vec<Expr>>),
1069    /// The `ROLLUP` expr.
1070    Rollup(Vec<Vec<Expr>>),
1071    /// ROW / TUPLE a single value, such as `SELECT (1, 2)`
1072    Tuple(Vec<Expr>),
1073    /// `Struct` literal expression
1074    /// Syntax:
1075    /// ```sql
1076    /// STRUCT<[field_name] field_type, ...>( expr1 [, ... ])
1077    ///
1078    /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-types#struct_type)
1079    /// [Databricks](https://docs.databricks.com/en/sql/language-manual/functions/struct.html)
1080    /// ```
1081    Struct {
1082        /// Struct values.
1083        values: Vec<Expr>,
1084        /// Struct field definitions.
1085        fields: Vec<StructField>,
1086    },
1087    /// `BigQuery` specific: An named expression in a typeless struct [1]
1088    ///
1089    /// Syntax
1090    /// ```sql
1091    /// 1 AS A
1092    /// ```
1093    /// [1]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-types#struct_type
1094    Named {
1095        expr: Box<Expr>,
1096        name: Ident,
1097    },
1098    /// `DuckDB` specific `Struct` literal expression [1]
1099    ///
1100    /// Syntax:
1101    /// ```sql
1102    /// syntax: {'field_name': expr1[, ... ]}
1103    /// ```
1104    /// [1]: https://duckdb.org/docs/sql/data_types/struct#creating-structs
1105    Dictionary(Vec<DictionaryField>),
1106    /// `DuckDB` specific `Map` literal expression [1]
1107    ///
1108    /// Syntax:
1109    /// ```sql
1110    /// syntax: Map {key1: value1[, ... ]}
1111    /// ```
1112    /// [1]: https://duckdb.org/docs/sql/data_types/map#creating-maps
1113    Map(Map),
1114    /// An array expression e.g. `ARRAY[1, 2]`
1115    Array(Array),
1116    /// A typed array expression e.g. `ARRAY<INT64>[1, 2]`
1117    TypedArray(TypedArray),
1118    /// An interval expression e.g. `INTERVAL '1' YEAR`
1119    Interval(Interval),
1120    /// `MySQL` specific text search function [(1)].
1121    ///
1122    /// Syntax:
1123    /// ```sql
1124    /// MATCH (<col>, <col>, ...) AGAINST (<expr> [<search modifier>])
1125    ///
1126    /// <col> = CompoundIdentifier
1127    /// <expr> = String literal
1128    /// ```
1129    /// [(1)]: https://dev.mysql.com/doc/refman/8.0/en/fulltext-search.html#function_match
1130    MatchAgainst {
1131        /// `(<col>, <col>, ...)`.
1132        columns: Vec<ObjectName>,
1133        /// `<expr>`.
1134        match_value: Value,
1135        /// `<search modifier>`
1136        opt_search_modifier: Option<SearchModifier>,
1137    },
1138    Wildcard(AttachedToken),
1139    /// Qualified wildcard, e.g. `alias.*` or `schema.table.*`.
1140    /// (Same caveats apply to `QualifiedWildcard` as to `Wildcard`.)
1141    QualifiedWildcard(ObjectName, AttachedToken),
1142    /// Some dialects support an older syntax for outer joins where columns are
1143    /// marked with the `(+)` operator in the WHERE clause, for example:
1144    ///
1145    /// ```sql
1146    /// SELECT t1.c1, t2.c2 FROM t1, t2 WHERE t1.c1 = t2.c2 (+)
1147    /// ```
1148    ///
1149    /// which is equivalent to
1150    ///
1151    /// ```sql
1152    /// SELECT t1.c1, t2.c2 FROM t1 LEFT OUTER JOIN t2 ON t1.c1 = t2.c2
1153    /// ```
1154    ///
1155    /// See <https://docs.snowflake.com/en/sql-reference/constructs/where#joins-in-the-where-clause>.
1156    OuterJoin(Box<Expr>),
1157    /// A reference to the prior level in a CONNECT BY clause.
1158    Prior(Box<Expr>),
1159    /// A lambda function.
1160    ///
1161    /// Syntax:
1162    /// ```plaintext
1163    /// param -> expr | (param1, ...) -> expr
1164    /// ```
1165    ///
1166    /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/functions#higher-order-functions---operator-and-lambdaparams-expr-function)
1167    /// [Databricks](https://docs.databricks.com/en/sql/language-manual/sql-ref-lambda-functions.html)
1168    /// [DuckDB](https://duckdb.org/docs/stable/sql/functions/lambda)
1169    Lambda(LambdaFunction),
1170    /// Checks membership of a value in a JSON array
1171    MemberOf(MemberOf),
1172}
1173
1174impl Expr {
1175    /// Creates a new [`Expr::Value`]
1176    pub fn value(value: impl Into<ValueWithSpan>) -> Self {
1177        Expr::Value(value.into())
1178    }
1179}
1180
1181/// The contents inside the `[` and `]` in a subscript expression.
1182#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1183#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1184#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1185pub enum Subscript {
1186    /// Accesses the element of the array at the given index.
1187    Index { index: Expr },
1188
1189    /// Accesses a slice of an array on PostgreSQL, e.g.
1190    ///
1191    /// ```plaintext
1192    /// => select (array[1,2,3,4,5,6])[2:5];
1193    /// -----------
1194    /// {2,3,4,5}
1195    /// ```
1196    ///
1197    /// The lower and/or upper bound can be omitted to slice from the start or
1198    /// end of the array respectively.
1199    ///
1200    /// See <https://www.postgresql.org/docs/current/arrays.html#ARRAYS-ACCESSING>.
1201    ///
1202    /// Also supports an optional "stride" as the last element (this is not
1203    /// supported by postgres), e.g.
1204    ///
1205    /// ```plaintext
1206    /// => select (array[1,2,3,4,5,6])[1:6:2];
1207    /// -----------
1208    /// {1,3,5}
1209    /// ```
1210    Slice {
1211        lower_bound: Option<Expr>,
1212        upper_bound: Option<Expr>,
1213        stride: Option<Expr>,
1214    },
1215}
1216
1217impl fmt::Display for Subscript {
1218    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1219        match self {
1220            Subscript::Index { index } => write!(f, "{index}"),
1221            Subscript::Slice {
1222                lower_bound,
1223                upper_bound,
1224                stride,
1225            } => {
1226                if let Some(lower) = lower_bound {
1227                    write!(f, "{lower}")?;
1228                }
1229                write!(f, ":")?;
1230                if let Some(upper) = upper_bound {
1231                    write!(f, "{upper}")?;
1232                }
1233                if let Some(stride) = stride {
1234                    write!(f, ":")?;
1235                    write!(f, "{stride}")?;
1236                }
1237                Ok(())
1238            }
1239        }
1240    }
1241}
1242
1243/// An element of a [`Expr::CompoundFieldAccess`].
1244/// It can be an expression or a subscript.
1245#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1246#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1247#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1248pub enum AccessExpr {
1249    /// Accesses a field using dot notation, e.g. `foo.bar.baz`.
1250    Dot(Expr),
1251    /// Accesses a field or array element using bracket notation, e.g. `foo['bar']`.
1252    Subscript(Subscript),
1253}
1254
1255impl fmt::Display for AccessExpr {
1256    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1257        match self {
1258            AccessExpr::Dot(expr) => write!(f, ".{expr}"),
1259            AccessExpr::Subscript(subscript) => write!(f, "[{subscript}]"),
1260        }
1261    }
1262}
1263
1264/// A lambda function.
1265#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1266#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1267#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1268pub struct LambdaFunction {
1269    /// The parameters to the lambda function.
1270    pub params: OneOrManyWithParens<Ident>,
1271    /// The body of the lambda function.
1272    pub body: Box<Expr>,
1273}
1274
1275impl fmt::Display for LambdaFunction {
1276    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1277        write!(f, "{} -> {}", self.params, self.body)
1278    }
1279}
1280
1281/// Encapsulates the common pattern in SQL where either one unparenthesized item
1282/// such as an identifier or expression is permitted, or multiple of the same
1283/// item in a parenthesized list. For accessing items regardless of the form,
1284/// `OneOrManyWithParens` implements `Deref<Target = [T]>` and `IntoIterator`,
1285/// so you can call slice methods on it and iterate over items
1286/// # Examples
1287/// Accessing as a slice:
1288/// ```
1289/// # use sqlparser::ast::OneOrManyWithParens;
1290/// let one = OneOrManyWithParens::One("a");
1291///
1292/// assert_eq!(one[0], "a");
1293/// assert_eq!(one.len(), 1);
1294/// ```
1295/// Iterating:
1296/// ```
1297/// # use sqlparser::ast::OneOrManyWithParens;
1298/// let one = OneOrManyWithParens::One("a");
1299/// let many = OneOrManyWithParens::Many(vec!["a", "b"]);
1300///
1301/// assert_eq!(one.into_iter().chain(many).collect::<Vec<_>>(), vec!["a", "a", "b"] );
1302/// ```
1303#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1304#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1305#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1306pub enum OneOrManyWithParens<T> {
1307    /// A single `T`, unparenthesized.
1308    One(T),
1309    /// One or more `T`s, parenthesized.
1310    Many(Vec<T>),
1311}
1312
1313impl<T> Deref for OneOrManyWithParens<T> {
1314    type Target = [T];
1315
1316    fn deref(&self) -> &[T] {
1317        match self {
1318            OneOrManyWithParens::One(one) => core::slice::from_ref(one),
1319            OneOrManyWithParens::Many(many) => many,
1320        }
1321    }
1322}
1323
1324impl<T> AsRef<[T]> for OneOrManyWithParens<T> {
1325    fn as_ref(&self) -> &[T] {
1326        self
1327    }
1328}
1329
1330impl<'a, T> IntoIterator for &'a OneOrManyWithParens<T> {
1331    type Item = &'a T;
1332    type IntoIter = core::slice::Iter<'a, T>;
1333
1334    fn into_iter(self) -> Self::IntoIter {
1335        self.iter()
1336    }
1337}
1338
1339/// Owned iterator implementation of `OneOrManyWithParens`
1340#[derive(Debug, Clone)]
1341pub struct OneOrManyWithParensIntoIter<T> {
1342    inner: OneOrManyWithParensIntoIterInner<T>,
1343}
1344
1345#[derive(Debug, Clone)]
1346enum OneOrManyWithParensIntoIterInner<T> {
1347    One(core::iter::Once<T>),
1348    Many(<Vec<T> as IntoIterator>::IntoIter),
1349}
1350
1351impl<T> core::iter::FusedIterator for OneOrManyWithParensIntoIter<T>
1352where
1353    core::iter::Once<T>: core::iter::FusedIterator,
1354    <Vec<T> as IntoIterator>::IntoIter: core::iter::FusedIterator,
1355{
1356}
1357
1358impl<T> core::iter::ExactSizeIterator for OneOrManyWithParensIntoIter<T>
1359where
1360    core::iter::Once<T>: core::iter::ExactSizeIterator,
1361    <Vec<T> as IntoIterator>::IntoIter: core::iter::ExactSizeIterator,
1362{
1363}
1364
1365impl<T> core::iter::Iterator for OneOrManyWithParensIntoIter<T> {
1366    type Item = T;
1367
1368    fn next(&mut self) -> Option<Self::Item> {
1369        match &mut self.inner {
1370            OneOrManyWithParensIntoIterInner::One(one) => one.next(),
1371            OneOrManyWithParensIntoIterInner::Many(many) => many.next(),
1372        }
1373    }
1374
1375    fn size_hint(&self) -> (usize, Option<usize>) {
1376        match &self.inner {
1377            OneOrManyWithParensIntoIterInner::One(one) => one.size_hint(),
1378            OneOrManyWithParensIntoIterInner::Many(many) => many.size_hint(),
1379        }
1380    }
1381
1382    fn count(self) -> usize
1383    where
1384        Self: Sized,
1385    {
1386        match self.inner {
1387            OneOrManyWithParensIntoIterInner::One(one) => one.count(),
1388            OneOrManyWithParensIntoIterInner::Many(many) => many.count(),
1389        }
1390    }
1391
1392    fn fold<B, F>(mut self, init: B, f: F) -> B
1393    where
1394        Self: Sized,
1395        F: FnMut(B, Self::Item) -> B,
1396    {
1397        match &mut self.inner {
1398            OneOrManyWithParensIntoIterInner::One(one) => one.fold(init, f),
1399            OneOrManyWithParensIntoIterInner::Many(many) => many.fold(init, f),
1400        }
1401    }
1402}
1403
1404impl<T> core::iter::DoubleEndedIterator for OneOrManyWithParensIntoIter<T> {
1405    fn next_back(&mut self) -> Option<Self::Item> {
1406        match &mut self.inner {
1407            OneOrManyWithParensIntoIterInner::One(one) => one.next_back(),
1408            OneOrManyWithParensIntoIterInner::Many(many) => many.next_back(),
1409        }
1410    }
1411}
1412
1413impl<T> IntoIterator for OneOrManyWithParens<T> {
1414    type Item = T;
1415
1416    type IntoIter = OneOrManyWithParensIntoIter<T>;
1417
1418    fn into_iter(self) -> Self::IntoIter {
1419        let inner = match self {
1420            OneOrManyWithParens::One(one) => {
1421                OneOrManyWithParensIntoIterInner::One(core::iter::once(one))
1422            }
1423            OneOrManyWithParens::Many(many) => {
1424                OneOrManyWithParensIntoIterInner::Many(many.into_iter())
1425            }
1426        };
1427
1428        OneOrManyWithParensIntoIter { inner }
1429    }
1430}
1431
1432impl<T> fmt::Display for OneOrManyWithParens<T>
1433where
1434    T: fmt::Display,
1435{
1436    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1437        match self {
1438            OneOrManyWithParens::One(value) => write!(f, "{value}"),
1439            OneOrManyWithParens::Many(values) => {
1440                write!(f, "({})", display_comma_separated(values))
1441            }
1442        }
1443    }
1444}
1445
1446impl fmt::Display for CastFormat {
1447    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1448        match self {
1449            CastFormat::Value(v) => write!(f, "{v}"),
1450            CastFormat::ValueAtTimeZone(v, tz) => write!(f, "{v} AT TIME ZONE {tz}"),
1451        }
1452    }
1453}
1454
1455impl fmt::Display for Expr {
1456    #[cfg_attr(feature = "recursive-protection", recursive::recursive)]
1457    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1458        match self {
1459            Expr::Identifier(s) => write!(f, "{s}"),
1460            Expr::Wildcard(_) => f.write_str("*"),
1461            Expr::QualifiedWildcard(prefix, _) => write!(f, "{prefix}.*"),
1462            Expr::CompoundIdentifier(s) => write!(f, "{}", display_separated(s, ".")),
1463            Expr::CompoundFieldAccess { root, access_chain } => {
1464                write!(f, "{root}")?;
1465                for field in access_chain {
1466                    write!(f, "{field}")?;
1467                }
1468                Ok(())
1469            }
1470            Expr::IsTrue(ast) => write!(f, "{ast} IS TRUE"),
1471            Expr::IsNotTrue(ast) => write!(f, "{ast} IS NOT TRUE"),
1472            Expr::IsFalse(ast) => write!(f, "{ast} IS FALSE"),
1473            Expr::IsNotFalse(ast) => write!(f, "{ast} IS NOT FALSE"),
1474            Expr::IsNull(ast) => write!(f, "{ast} IS NULL"),
1475            Expr::IsNotNull(ast) => write!(f, "{ast} IS NOT NULL"),
1476            Expr::IsUnknown(ast) => write!(f, "{ast} IS UNKNOWN"),
1477            Expr::IsNotUnknown(ast) => write!(f, "{ast} IS NOT UNKNOWN"),
1478            Expr::InList {
1479                expr,
1480                list,
1481                negated,
1482            } => write!(
1483                f,
1484                "{} {}IN ({})",
1485                expr,
1486                if *negated { "NOT " } else { "" },
1487                display_comma_separated(list)
1488            ),
1489            Expr::InSubquery {
1490                expr,
1491                subquery,
1492                negated,
1493            } => write!(
1494                f,
1495                "{} {}IN ({})",
1496                expr,
1497                if *negated { "NOT " } else { "" },
1498                subquery
1499            ),
1500            Expr::InUnnest {
1501                expr,
1502                array_expr,
1503                negated,
1504            } => write!(
1505                f,
1506                "{} {}IN UNNEST({})",
1507                expr,
1508                if *negated { "NOT " } else { "" },
1509                array_expr
1510            ),
1511            Expr::Between {
1512                expr,
1513                negated,
1514                low,
1515                high,
1516            } => write!(
1517                f,
1518                "{} {}BETWEEN {} AND {}",
1519                expr,
1520                if *negated { "NOT " } else { "" },
1521                low,
1522                high
1523            ),
1524            Expr::BinaryOp { left, op, right } => write!(f, "{left} {op} {right}"),
1525            Expr::Like {
1526                negated,
1527                expr,
1528                pattern,
1529                escape_char,
1530                any,
1531            } => match escape_char {
1532                Some(ch) => write!(
1533                    f,
1534                    "{} {}LIKE {}{} ESCAPE {}",
1535                    expr,
1536                    if *negated { "NOT " } else { "" },
1537                    if *any { "ANY " } else { "" },
1538                    pattern,
1539                    ch
1540                ),
1541                _ => write!(
1542                    f,
1543                    "{} {}LIKE {}{}",
1544                    expr,
1545                    if *negated { "NOT " } else { "" },
1546                    if *any { "ANY " } else { "" },
1547                    pattern
1548                ),
1549            },
1550            Expr::ILike {
1551                negated,
1552                expr,
1553                pattern,
1554                escape_char,
1555                any,
1556            } => match escape_char {
1557                Some(ch) => write!(
1558                    f,
1559                    "{} {}ILIKE {}{} ESCAPE {}",
1560                    expr,
1561                    if *negated { "NOT " } else { "" },
1562                    if *any { "ANY" } else { "" },
1563                    pattern,
1564                    ch
1565                ),
1566                _ => write!(
1567                    f,
1568                    "{} {}ILIKE {}{}",
1569                    expr,
1570                    if *negated { "NOT " } else { "" },
1571                    if *any { "ANY " } else { "" },
1572                    pattern
1573                ),
1574            },
1575            Expr::RLike {
1576                negated,
1577                expr,
1578                pattern,
1579                regexp,
1580            } => write!(
1581                f,
1582                "{} {}{} {}",
1583                expr,
1584                if *negated { "NOT " } else { "" },
1585                if *regexp { "REGEXP" } else { "RLIKE" },
1586                pattern
1587            ),
1588            Expr::IsNormalized {
1589                expr,
1590                form,
1591                negated,
1592            } => {
1593                let not_ = if *negated { "NOT " } else { "" };
1594                if form.is_none() {
1595                    write!(f, "{expr} IS {not_}NORMALIZED")
1596                } else {
1597                    write!(
1598                        f,
1599                        "{} IS {}{} NORMALIZED",
1600                        expr,
1601                        not_,
1602                        form.as_ref().unwrap()
1603                    )
1604                }
1605            }
1606            Expr::SimilarTo {
1607                negated,
1608                expr,
1609                pattern,
1610                escape_char,
1611            } => match escape_char {
1612                Some(ch) => write!(
1613                    f,
1614                    "{} {}SIMILAR TO {} ESCAPE {}",
1615                    expr,
1616                    if *negated { "NOT " } else { "" },
1617                    pattern,
1618                    ch
1619                ),
1620                _ => write!(
1621                    f,
1622                    "{} {}SIMILAR TO {}",
1623                    expr,
1624                    if *negated { "NOT " } else { "" },
1625                    pattern
1626                ),
1627            },
1628            Expr::AnyOp {
1629                left,
1630                compare_op,
1631                right,
1632                is_some,
1633            } => {
1634                let add_parens = !matches!(right.as_ref(), Expr::Subquery(_));
1635                write!(
1636                    f,
1637                    "{left} {compare_op} {}{}{right}{}",
1638                    if *is_some { "SOME" } else { "ANY" },
1639                    if add_parens { "(" } else { "" },
1640                    if add_parens { ")" } else { "" },
1641                )
1642            }
1643            Expr::AllOp {
1644                left,
1645                compare_op,
1646                right,
1647            } => {
1648                let add_parens = !matches!(right.as_ref(), Expr::Subquery(_));
1649                write!(
1650                    f,
1651                    "{left} {compare_op} ALL{}{right}{}",
1652                    if add_parens { "(" } else { "" },
1653                    if add_parens { ")" } else { "" },
1654                )
1655            }
1656            Expr::UnaryOp { op, expr } => {
1657                if op == &UnaryOperator::PGPostfixFactorial {
1658                    write!(f, "{expr}{op}")
1659                } else if matches!(
1660                    op,
1661                    UnaryOperator::Not
1662                        | UnaryOperator::Hash
1663                        | UnaryOperator::AtDashAt
1664                        | UnaryOperator::DoubleAt
1665                        | UnaryOperator::QuestionDash
1666                        | UnaryOperator::QuestionPipe
1667                ) {
1668                    write!(f, "{op} {expr}")
1669                } else {
1670                    write!(f, "{op}{expr}")
1671                }
1672            }
1673            Expr::Convert {
1674                is_try,
1675                expr,
1676                target_before_value,
1677                data_type,
1678                charset,
1679                styles,
1680            } => {
1681                write!(f, "{}CONVERT(", if *is_try { "TRY_" } else { "" })?;
1682                if let Some(data_type) = data_type {
1683                    if let Some(charset) = charset {
1684                        write!(f, "{expr}, {data_type} CHARACTER SET {charset}")
1685                    } else if *target_before_value {
1686                        write!(f, "{data_type}, {expr}")
1687                    } else {
1688                        write!(f, "{expr}, {data_type}")
1689                    }
1690                } else if let Some(charset) = charset {
1691                    write!(f, "{expr} USING {charset}")
1692                } else {
1693                    write!(f, "{expr}") // This should never happen
1694                }?;
1695                if !styles.is_empty() {
1696                    write!(f, ", {}", display_comma_separated(styles))?;
1697                }
1698                write!(f, ")")
1699            }
1700            Expr::Cast {
1701                kind,
1702                expr,
1703                data_type,
1704                format,
1705            } => match kind {
1706                CastKind::Cast => {
1707                    if let Some(format) = format {
1708                        write!(f, "CAST({expr} AS {data_type} FORMAT {format})")
1709                    } else {
1710                        write!(f, "CAST({expr} AS {data_type})")
1711                    }
1712                }
1713                CastKind::TryCast => {
1714                    if let Some(format) = format {
1715                        write!(f, "TRY_CAST({expr} AS {data_type} FORMAT {format})")
1716                    } else {
1717                        write!(f, "TRY_CAST({expr} AS {data_type})")
1718                    }
1719                }
1720                CastKind::SafeCast => {
1721                    if let Some(format) = format {
1722                        write!(f, "SAFE_CAST({expr} AS {data_type} FORMAT {format})")
1723                    } else {
1724                        write!(f, "SAFE_CAST({expr} AS {data_type})")
1725                    }
1726                }
1727                CastKind::DoubleColon => {
1728                    write!(f, "{expr}::{data_type}")
1729                }
1730            },
1731            Expr::Extract {
1732                field,
1733                syntax,
1734                expr,
1735            } => match syntax {
1736                ExtractSyntax::From => write!(f, "EXTRACT({field} FROM {expr})"),
1737                ExtractSyntax::Comma => write!(f, "EXTRACT({field}, {expr})"),
1738            },
1739            Expr::Ceil { expr, field } => match field {
1740                CeilFloorKind::DateTimeField(DateTimeField::NoDateTime) => {
1741                    write!(f, "CEIL({expr})")
1742                }
1743                CeilFloorKind::DateTimeField(dt_field) => write!(f, "CEIL({expr} TO {dt_field})"),
1744                CeilFloorKind::Scale(s) => write!(f, "CEIL({expr}, {s})"),
1745            },
1746            Expr::Floor { expr, field } => match field {
1747                CeilFloorKind::DateTimeField(DateTimeField::NoDateTime) => {
1748                    write!(f, "FLOOR({expr})")
1749                }
1750                CeilFloorKind::DateTimeField(dt_field) => write!(f, "FLOOR({expr} TO {dt_field})"),
1751                CeilFloorKind::Scale(s) => write!(f, "FLOOR({expr}, {s})"),
1752            },
1753            Expr::Position { expr, r#in } => write!(f, "POSITION({expr} IN {in})"),
1754            Expr::Collate { expr, collation } => write!(f, "{expr} COLLATE {collation}"),
1755            Expr::Nested(ast) => write!(f, "({ast})"),
1756            Expr::Value(v) => write!(f, "{v}"),
1757            Expr::Prefixed { prefix, value } => write!(f, "{prefix} {value}"),
1758            Expr::TypedString(ts) => ts.fmt(f),
1759            Expr::Function(fun) => fun.fmt(f),
1760            Expr::Case {
1761                case_token: _,
1762                end_token: _,
1763                operand,
1764                conditions,
1765                else_result,
1766            } => {
1767                f.write_str("CASE")?;
1768                if let Some(operand) = operand {
1769                    f.write_str(" ")?;
1770                    operand.fmt(f)?;
1771                }
1772                for when in conditions {
1773                    SpaceOrNewline.fmt(f)?;
1774                    Indent(when).fmt(f)?;
1775                }
1776                if let Some(else_result) = else_result {
1777                    SpaceOrNewline.fmt(f)?;
1778                    Indent("ELSE").fmt(f)?;
1779                    SpaceOrNewline.fmt(f)?;
1780                    Indent(Indent(else_result)).fmt(f)?;
1781                }
1782                SpaceOrNewline.fmt(f)?;
1783                f.write_str("END")
1784            }
1785            Expr::Exists { subquery, negated } => write!(
1786                f,
1787                "{}EXISTS ({})",
1788                if *negated { "NOT " } else { "" },
1789                subquery
1790            ),
1791            Expr::Subquery(s) => write!(f, "({s})"),
1792            Expr::GroupingSets(sets) => {
1793                write!(f, "GROUPING SETS (")?;
1794                let mut sep = "";
1795                for set in sets {
1796                    write!(f, "{sep}")?;
1797                    sep = ", ";
1798                    write!(f, "({})", display_comma_separated(set))?;
1799                }
1800                write!(f, ")")
1801            }
1802            Expr::Cube(sets) => {
1803                write!(f, "CUBE (")?;
1804                let mut sep = "";
1805                for set in sets {
1806                    write!(f, "{sep}")?;
1807                    sep = ", ";
1808                    if set.len() == 1 {
1809                        write!(f, "{}", set[0])?;
1810                    } else {
1811                        write!(f, "({})", display_comma_separated(set))?;
1812                    }
1813                }
1814                write!(f, ")")
1815            }
1816            Expr::Rollup(sets) => {
1817                write!(f, "ROLLUP (")?;
1818                let mut sep = "";
1819                for set in sets {
1820                    write!(f, "{sep}")?;
1821                    sep = ", ";
1822                    if set.len() == 1 {
1823                        write!(f, "{}", set[0])?;
1824                    } else {
1825                        write!(f, "({})", display_comma_separated(set))?;
1826                    }
1827                }
1828                write!(f, ")")
1829            }
1830            Expr::Substring {
1831                expr,
1832                substring_from,
1833                substring_for,
1834                special,
1835                shorthand,
1836            } => {
1837                f.write_str("SUBSTR")?;
1838                if !*shorthand {
1839                    f.write_str("ING")?;
1840                }
1841                write!(f, "({expr}")?;
1842                if let Some(from_part) = substring_from {
1843                    if *special {
1844                        write!(f, ", {from_part}")?;
1845                    } else {
1846                        write!(f, " FROM {from_part}")?;
1847                    }
1848                }
1849                if let Some(for_part) = substring_for {
1850                    if *special {
1851                        write!(f, ", {for_part}")?;
1852                    } else {
1853                        write!(f, " FOR {for_part}")?;
1854                    }
1855                }
1856
1857                write!(f, ")")
1858            }
1859            Expr::Overlay {
1860                expr,
1861                overlay_what,
1862                overlay_from,
1863                overlay_for,
1864            } => {
1865                write!(
1866                    f,
1867                    "OVERLAY({expr} PLACING {overlay_what} FROM {overlay_from}"
1868                )?;
1869                if let Some(for_part) = overlay_for {
1870                    write!(f, " FOR {for_part}")?;
1871                }
1872
1873                write!(f, ")")
1874            }
1875            Expr::IsDistinctFrom(a, b) => write!(f, "{a} IS DISTINCT FROM {b}"),
1876            Expr::IsNotDistinctFrom(a, b) => write!(f, "{a} IS NOT DISTINCT FROM {b}"),
1877            Expr::Trim {
1878                expr,
1879                trim_where,
1880                trim_what,
1881                trim_characters,
1882            } => {
1883                write!(f, "TRIM(")?;
1884                if let Some(ident) = trim_where {
1885                    write!(f, "{ident} ")?;
1886                }
1887                if let Some(trim_char) = trim_what {
1888                    write!(f, "{trim_char} FROM {expr}")?;
1889                } else {
1890                    write!(f, "{expr}")?;
1891                }
1892                if let Some(characters) = trim_characters {
1893                    write!(f, ", {}", display_comma_separated(characters))?;
1894                }
1895
1896                write!(f, ")")
1897            }
1898            Expr::Tuple(exprs) => {
1899                write!(f, "({})", display_comma_separated(exprs))
1900            }
1901            Expr::Struct { values, fields } => {
1902                if !fields.is_empty() {
1903                    write!(
1904                        f,
1905                        "STRUCT<{}>({})",
1906                        display_comma_separated(fields),
1907                        display_comma_separated(values)
1908                    )
1909                } else {
1910                    write!(f, "STRUCT({})", display_comma_separated(values))
1911                }
1912            }
1913            Expr::Named { expr, name } => {
1914                write!(f, "{expr} AS {name}")
1915            }
1916            Expr::Dictionary(fields) => {
1917                write!(f, "{{{}}}", display_comma_separated(fields))
1918            }
1919            Expr::Map(map) => {
1920                write!(f, "{map}")
1921            }
1922            Expr::Array(set) => {
1923                write!(f, "{set}")
1924            }
1925            Expr::TypedArray(set) => {
1926                write!(f, "{set}")
1927            }
1928            Expr::JsonAccess { value, path } => {
1929                write!(f, "{value}{path}")
1930            }
1931            Expr::AtTimeZone {
1932                timestamp,
1933                time_zone,
1934            } => {
1935                write!(f, "{timestamp} AT TIME ZONE {time_zone}")
1936            }
1937            Expr::Interval(interval) => {
1938                write!(f, "{interval}")
1939            }
1940            Expr::MatchAgainst {
1941                columns,
1942                match_value: match_expr,
1943                opt_search_modifier,
1944            } => {
1945                write!(f, "MATCH ({}) AGAINST ", display_comma_separated(columns),)?;
1946
1947                if let Some(search_modifier) = opt_search_modifier {
1948                    write!(f, "({match_expr} {search_modifier})")?;
1949                } else {
1950                    write!(f, "({match_expr})")?;
1951                }
1952
1953                Ok(())
1954            }
1955            Expr::OuterJoin(expr) => {
1956                write!(f, "{expr} (+)")
1957            }
1958            Expr::Prior(expr) => write!(f, "PRIOR {expr}"),
1959            Expr::Lambda(lambda) => write!(f, "{lambda}"),
1960            Expr::MemberOf(member_of) => write!(f, "{member_of}"),
1961        }
1962    }
1963}
1964
1965#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1966#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1967#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1968pub enum WindowType {
1969    WindowSpec(WindowSpec),
1970    NamedWindow(Ident),
1971}
1972
1973impl Display for WindowType {
1974    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1975        match self {
1976            WindowType::WindowSpec(spec) => {
1977                f.write_str("(")?;
1978                NewLine.fmt(f)?;
1979                Indent(spec).fmt(f)?;
1980                NewLine.fmt(f)?;
1981                f.write_str(")")
1982            }
1983            WindowType::NamedWindow(name) => name.fmt(f),
1984        }
1985    }
1986}
1987
1988/// A window specification (i.e. `OVER ([window_name] PARTITION BY .. ORDER BY .. etc.)`)
1989#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1990#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1991#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1992pub struct WindowSpec {
1993    /// Optional window name.
1994    ///
1995    /// You can find it at least in [MySQL][1], [BigQuery][2], [PostgreSQL][3]
1996    ///
1997    /// [1]: https://dev.mysql.com/doc/refman/8.0/en/window-functions-named-windows.html
1998    /// [2]: https://cloud.google.com/bigquery/docs/reference/standard-sql/window-function-calls
1999    /// [3]: https://www.postgresql.org/docs/current/sql-expressions.html#SYNTAX-WINDOW-FUNCTIONS
2000    pub window_name: Option<Ident>,
2001    /// `OVER (PARTITION BY ...)`
2002    pub partition_by: Vec<Expr>,
2003    /// `OVER (ORDER BY ...)`
2004    pub order_by: Vec<OrderByExpr>,
2005    /// `OVER (window frame)`
2006    pub window_frame: Option<WindowFrame>,
2007}
2008
2009impl fmt::Display for WindowSpec {
2010    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2011        let mut is_first = true;
2012        if let Some(window_name) = &self.window_name {
2013            if !is_first {
2014                SpaceOrNewline.fmt(f)?;
2015            }
2016            is_first = false;
2017            write!(f, "{window_name}")?;
2018        }
2019        if !self.partition_by.is_empty() {
2020            if !is_first {
2021                SpaceOrNewline.fmt(f)?;
2022            }
2023            is_first = false;
2024            write!(
2025                f,
2026                "PARTITION BY {}",
2027                display_comma_separated(&self.partition_by)
2028            )?;
2029        }
2030        if !self.order_by.is_empty() {
2031            if !is_first {
2032                SpaceOrNewline.fmt(f)?;
2033            }
2034            is_first = false;
2035            write!(f, "ORDER BY {}", display_comma_separated(&self.order_by))?;
2036        }
2037        if let Some(window_frame) = &self.window_frame {
2038            if !is_first {
2039                SpaceOrNewline.fmt(f)?;
2040            }
2041            if let Some(end_bound) = &window_frame.end_bound {
2042                write!(
2043                    f,
2044                    "{} BETWEEN {} AND {}",
2045                    window_frame.units, window_frame.start_bound, end_bound
2046                )?;
2047            } else {
2048                write!(f, "{} {}", window_frame.units, window_frame.start_bound)?;
2049            }
2050        }
2051        Ok(())
2052    }
2053}
2054
2055/// Specifies the data processed by a window function, e.g.
2056/// `RANGE UNBOUNDED PRECEDING` or `ROWS BETWEEN 5 PRECEDING AND CURRENT ROW`.
2057///
2058/// Note: The parser does not validate the specified bounds; the caller should
2059/// reject invalid bounds like `ROWS UNBOUNDED FOLLOWING` before execution.
2060#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2061#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2062#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2063pub struct WindowFrame {
2064    pub units: WindowFrameUnits,
2065    pub start_bound: WindowFrameBound,
2066    /// The right bound of the `BETWEEN .. AND` clause. The end bound of `None`
2067    /// indicates the shorthand form (e.g. `ROWS 1 PRECEDING`), which must
2068    /// behave the same as `end_bound = WindowFrameBound::CurrentRow`.
2069    pub end_bound: Option<WindowFrameBound>,
2070    // TBD: EXCLUDE
2071}
2072
2073impl Default for WindowFrame {
2074    /// Returns default value for window frame
2075    ///
2076    /// See [this page](https://www.sqlite.org/windowfunctions.html#frame_specifications) for more details.
2077    fn default() -> Self {
2078        Self {
2079            units: WindowFrameUnits::Range,
2080            start_bound: WindowFrameBound::Preceding(None),
2081            end_bound: None,
2082        }
2083    }
2084}
2085
2086#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2087#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2088#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2089pub enum WindowFrameUnits {
2090    Rows,
2091    Range,
2092    Groups,
2093}
2094
2095impl fmt::Display for WindowFrameUnits {
2096    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2097        f.write_str(match self {
2098            WindowFrameUnits::Rows => "ROWS",
2099            WindowFrameUnits::Range => "RANGE",
2100            WindowFrameUnits::Groups => "GROUPS",
2101        })
2102    }
2103}
2104
2105/// Specifies Ignore / Respect NULL within window functions.
2106/// For example
2107/// `FIRST_VALUE(column2) IGNORE NULLS OVER (PARTITION BY column1)`
2108#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2109#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2110#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2111pub enum NullTreatment {
2112    IgnoreNulls,
2113    RespectNulls,
2114}
2115
2116impl fmt::Display for NullTreatment {
2117    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2118        f.write_str(match self {
2119            NullTreatment::IgnoreNulls => "IGNORE NULLS",
2120            NullTreatment::RespectNulls => "RESPECT NULLS",
2121        })
2122    }
2123}
2124
2125/// Specifies [WindowFrame]'s `start_bound` and `end_bound`
2126#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2127#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2128#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2129pub enum WindowFrameBound {
2130    /// `CURRENT ROW`
2131    CurrentRow,
2132    /// `<N> PRECEDING` or `UNBOUNDED PRECEDING`
2133    Preceding(Option<Box<Expr>>),
2134    /// `<N> FOLLOWING` or `UNBOUNDED FOLLOWING`.
2135    Following(Option<Box<Expr>>),
2136}
2137
2138impl fmt::Display for WindowFrameBound {
2139    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2140        match self {
2141            WindowFrameBound::CurrentRow => f.write_str("CURRENT ROW"),
2142            WindowFrameBound::Preceding(None) => f.write_str("UNBOUNDED PRECEDING"),
2143            WindowFrameBound::Following(None) => f.write_str("UNBOUNDED FOLLOWING"),
2144            WindowFrameBound::Preceding(Some(n)) => write!(f, "{n} PRECEDING"),
2145            WindowFrameBound::Following(Some(n)) => write!(f, "{n} FOLLOWING"),
2146        }
2147    }
2148}
2149
2150#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2151#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2152#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2153pub enum AddDropSync {
2154    ADD,
2155    DROP,
2156    SYNC,
2157}
2158
2159impl fmt::Display for AddDropSync {
2160    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2161        match self {
2162            AddDropSync::SYNC => f.write_str("SYNC PARTITIONS"),
2163            AddDropSync::DROP => f.write_str("DROP PARTITIONS"),
2164            AddDropSync::ADD => f.write_str("ADD PARTITIONS"),
2165        }
2166    }
2167}
2168
2169#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2170#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2171#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2172pub enum ShowCreateObject {
2173    Event,
2174    Function,
2175    Procedure,
2176    Table,
2177    Trigger,
2178    View,
2179}
2180
2181impl fmt::Display for ShowCreateObject {
2182    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2183        match self {
2184            ShowCreateObject::Event => f.write_str("EVENT"),
2185            ShowCreateObject::Function => f.write_str("FUNCTION"),
2186            ShowCreateObject::Procedure => f.write_str("PROCEDURE"),
2187            ShowCreateObject::Table => f.write_str("TABLE"),
2188            ShowCreateObject::Trigger => f.write_str("TRIGGER"),
2189            ShowCreateObject::View => f.write_str("VIEW"),
2190        }
2191    }
2192}
2193
2194#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2195#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2196#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2197pub enum CommentObject {
2198    Column,
2199    Table,
2200    Extension,
2201    Schema,
2202    Database,
2203    User,
2204    Role,
2205}
2206
2207impl fmt::Display for CommentObject {
2208    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2209        match self {
2210            CommentObject::Column => f.write_str("COLUMN"),
2211            CommentObject::Table => f.write_str("TABLE"),
2212            CommentObject::Extension => f.write_str("EXTENSION"),
2213            CommentObject::Schema => f.write_str("SCHEMA"),
2214            CommentObject::Database => f.write_str("DATABASE"),
2215            CommentObject::User => f.write_str("USER"),
2216            CommentObject::Role => f.write_str("ROLE"),
2217        }
2218    }
2219}
2220
2221#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2222#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2223#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2224pub enum Password {
2225    Password(Expr),
2226    NullPassword,
2227}
2228
2229/// A `CASE` statement.
2230///
2231/// Examples:
2232/// ```sql
2233/// CASE
2234///     WHEN EXISTS(SELECT 1)
2235///         THEN SELECT 1 FROM T;
2236///     WHEN EXISTS(SELECT 2)
2237///         THEN SELECT 1 FROM U;
2238///     ELSE
2239///         SELECT 1 FROM V;
2240/// END CASE;
2241/// ```
2242///
2243/// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#case_search_expression)
2244/// [Snowflake](https://docs.snowflake.com/en/sql-reference/snowflake-scripting/case)
2245#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2246#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2247#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2248pub struct CaseStatement {
2249    /// The `CASE` token that starts the statement.
2250    pub case_token: AttachedToken,
2251    pub match_expr: Option<Expr>,
2252    pub when_blocks: Vec<ConditionalStatementBlock>,
2253    pub else_block: Option<ConditionalStatementBlock>,
2254    /// The last token of the statement (`END` or `CASE`).
2255    pub end_case_token: AttachedToken,
2256}
2257
2258impl fmt::Display for CaseStatement {
2259    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2260        let CaseStatement {
2261            case_token: _,
2262            match_expr,
2263            when_blocks,
2264            else_block,
2265            end_case_token: AttachedToken(end),
2266        } = self;
2267
2268        write!(f, "CASE")?;
2269
2270        if let Some(expr) = match_expr {
2271            write!(f, " {expr}")?;
2272        }
2273
2274        if !when_blocks.is_empty() {
2275            write!(f, " {}", display_separated(when_blocks, " "))?;
2276        }
2277
2278        if let Some(else_block) = else_block {
2279            write!(f, " {else_block}")?;
2280        }
2281
2282        write!(f, " END")?;
2283
2284        if let Token::Word(w) = &end.token {
2285            if w.keyword == Keyword::CASE {
2286                write!(f, " CASE")?;
2287            }
2288        }
2289
2290        Ok(())
2291    }
2292}
2293
2294/// An `IF` statement.
2295///
2296/// Example (BigQuery or Snowflake):
2297/// ```sql
2298/// IF TRUE THEN
2299///     SELECT 1;
2300///     SELECT 2;
2301/// ELSEIF TRUE THEN
2302///     SELECT 3;
2303/// ELSE
2304///     SELECT 4;
2305/// END IF
2306/// ```
2307/// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#if)
2308/// [Snowflake](https://docs.snowflake.com/en/sql-reference/snowflake-scripting/if)
2309///
2310/// Example (MSSQL):
2311/// ```sql
2312/// IF 1=1 SELECT 1 ELSE SELECT 2
2313/// ```
2314/// [MSSQL](https://learn.microsoft.com/en-us/sql/t-sql/language-elements/if-else-transact-sql?view=sql-server-ver16)
2315#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2316#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2317#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2318pub struct IfStatement {
2319    pub if_block: ConditionalStatementBlock,
2320    pub elseif_blocks: Vec<ConditionalStatementBlock>,
2321    pub else_block: Option<ConditionalStatementBlock>,
2322    pub end_token: Option<AttachedToken>,
2323}
2324
2325impl fmt::Display for IfStatement {
2326    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2327        let IfStatement {
2328            if_block,
2329            elseif_blocks,
2330            else_block,
2331            end_token,
2332        } = self;
2333
2334        write!(f, "{if_block}")?;
2335
2336        for elseif_block in elseif_blocks {
2337            write!(f, " {elseif_block}")?;
2338        }
2339
2340        if let Some(else_block) = else_block {
2341            write!(f, " {else_block}")?;
2342        }
2343
2344        if let Some(AttachedToken(end_token)) = end_token {
2345            write!(f, " END {end_token}")?;
2346        }
2347
2348        Ok(())
2349    }
2350}
2351
2352/// A `WHILE` statement.
2353///
2354/// Example:
2355/// ```sql
2356/// WHILE @@FETCH_STATUS = 0
2357/// BEGIN
2358///    FETCH NEXT FROM c1 INTO @var1, @var2;
2359/// END
2360/// ```
2361///
2362/// [MsSql](https://learn.microsoft.com/en-us/sql/t-sql/language-elements/while-transact-sql)
2363#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2364#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2365#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2366pub struct WhileStatement {
2367    pub while_block: ConditionalStatementBlock,
2368}
2369
2370impl fmt::Display for WhileStatement {
2371    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2372        let WhileStatement { while_block } = self;
2373        write!(f, "{while_block}")?;
2374        Ok(())
2375    }
2376}
2377
2378#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2379#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2380#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2381pub struct LoopStatement {
2382    pub label: Option<Ident>,
2383    pub body: Vec<Statement>,
2384}
2385
2386impl fmt::Display for LoopStatement {
2387    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2388        if let Some(label) = &self.label {
2389            write!(f, "{}: ", label)?;
2390        }
2391        write!(f, "LOOP ")?;
2392        format_statement_list(f, &self.body)?;
2393        write!(f, " END LOOP")?;
2394        if let Some(label) = &self.label {
2395            write!(f, " {}", label)?;
2396        }
2397        Ok(())
2398    }
2399}
2400
2401/// FOR loop statement
2402///
2403/// Example:
2404/// ```sql
2405/// FOR i IN (SELECT val FROM UNNEST([1, 2, 3]) AS val) DO
2406///     SET sum = sum + i.val;
2407/// END FOR
2408/// ```
2409#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2410#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2411#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2412pub struct ForStatement {
2413    pub variable: Ident,
2414    pub query: Box<Query>,
2415    pub body: Vec<Statement>,
2416}
2417
2418impl fmt::Display for ForStatement {
2419    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2420        write!(f, "FOR {} IN ({}) DO ", self.variable, self.query)?;
2421        format_statement_list(f, &self.body)?;
2422        write!(f, " END FOR")?;
2423        Ok(())
2424    }
2425}
2426
2427/// REPEAT loop statement
2428///
2429/// Example:
2430/// ```sql
2431/// REPEAT
2432///     SET i = i + 1;
2433/// UNTIL i >= 5
2434/// END REPEAT
2435/// ```
2436#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2437#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2438#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2439pub struct RepeatStatement {
2440    pub body: Vec<Statement>,
2441    pub until_condition: Expr,
2442}
2443
2444impl fmt::Display for RepeatStatement {
2445    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2446        write!(f, "REPEAT ")?;
2447        format_statement_list(f, &self.body)?;
2448        write!(f, " UNTIL {} END REPEAT", self.until_condition)?;
2449        Ok(())
2450    }
2451}
2452
2453/// A block within a [Statement::Case] or [Statement::If] or [Statement::While]-like statement
2454///
2455/// Example 1:
2456/// ```sql
2457/// WHEN EXISTS(SELECT 1) THEN SELECT 1;
2458/// ```
2459///
2460/// Example 2:
2461/// ```sql
2462/// IF TRUE THEN SELECT 1; SELECT 2;
2463/// ```
2464///
2465/// Example 3:
2466/// ```sql
2467/// ELSE SELECT 1; SELECT 2;
2468/// ```
2469///
2470/// Example 4:
2471/// ```sql
2472/// WHILE @@FETCH_STATUS = 0
2473/// BEGIN
2474///    FETCH NEXT FROM c1 INTO @var1, @var2;
2475/// END
2476/// ```
2477#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2478#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2479#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2480pub struct ConditionalStatementBlock {
2481    pub start_token: AttachedToken,
2482    pub condition: Option<Expr>,
2483    pub then_token: Option<AttachedToken>,
2484    pub conditional_statements: ConditionalStatements,
2485}
2486
2487impl ConditionalStatementBlock {
2488    pub fn statements(&self) -> &Vec<Statement> {
2489        self.conditional_statements.statements()
2490    }
2491}
2492
2493impl fmt::Display for ConditionalStatementBlock {
2494    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2495        let ConditionalStatementBlock {
2496            start_token: AttachedToken(start_token),
2497            condition,
2498            then_token,
2499            conditional_statements,
2500        } = self;
2501
2502        write!(f, "{start_token}")?;
2503
2504        if let Some(condition) = condition {
2505            write!(f, " {condition}")?;
2506        }
2507
2508        if then_token.is_some() {
2509            write!(f, " THEN")?;
2510        }
2511
2512        if !conditional_statements.statements().is_empty() {
2513            write!(f, " {conditional_statements}")?;
2514        }
2515
2516        Ok(())
2517    }
2518}
2519
2520/// A list of statements in a [ConditionalStatementBlock].
2521#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2522#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2523#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2524pub enum ConditionalStatements {
2525    /// SELECT 1; SELECT 2; SELECT 3; ...
2526    Sequence { statements: Vec<Statement> },
2527    /// BEGIN SELECT 1; SELECT 2; SELECT 3; ... END
2528    BeginEnd(BeginEndStatements),
2529}
2530
2531impl ConditionalStatements {
2532    pub fn statements(&self) -> &Vec<Statement> {
2533        match self {
2534            ConditionalStatements::Sequence { statements } => statements,
2535            ConditionalStatements::BeginEnd(bes) => &bes.statements,
2536        }
2537    }
2538}
2539
2540impl fmt::Display for ConditionalStatements {
2541    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2542        match self {
2543            ConditionalStatements::Sequence { statements } => {
2544                if !statements.is_empty() {
2545                    format_statement_list(f, statements)?;
2546                }
2547                Ok(())
2548            }
2549            ConditionalStatements::BeginEnd(bes) => write!(f, "{bes}"),
2550        }
2551    }
2552}
2553
2554/// Represents a list of statements enclosed within `BEGIN` and `END` keywords.
2555/// Example:
2556/// ```sql
2557/// BEGIN
2558///     SELECT 1;
2559///     SELECT 2;
2560/// END
2561/// ```
2562#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2563#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2564#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2565pub struct BeginEndStatements {
2566    pub begin_token: AttachedToken,
2567    pub statements: Vec<Statement>,
2568    pub end_token: AttachedToken,
2569}
2570
2571impl fmt::Display for BeginEndStatements {
2572    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2573        let BeginEndStatements {
2574            begin_token: AttachedToken(begin_token),
2575            statements,
2576            end_token: AttachedToken(end_token),
2577        } = self;
2578
2579        if begin_token.token != Token::EOF {
2580            write!(f, "{begin_token} ")?;
2581        }
2582        if !statements.is_empty() {
2583            format_statement_list(f, statements)?;
2584        }
2585        if end_token.token != Token::EOF {
2586            write!(f, " {end_token}")?;
2587        }
2588        Ok(())
2589    }
2590}
2591
2592/// A `RAISE` statement.
2593///
2594/// Examples:
2595/// ```sql
2596/// RAISE USING MESSAGE = 'error';
2597///
2598/// RAISE myerror;
2599/// ```
2600///
2601/// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#raise)
2602/// [Snowflake](https://docs.snowflake.com/en/sql-reference/snowflake-scripting/raise)
2603#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2604#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2605#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2606pub struct RaiseStatement {
2607    pub value: Option<RaiseStatementValue>,
2608}
2609
2610impl fmt::Display for RaiseStatement {
2611    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2612        let RaiseStatement { value } = self;
2613
2614        write!(f, "RAISE")?;
2615        if let Some(value) = value {
2616            write!(f, " {value}")?;
2617        }
2618
2619        Ok(())
2620    }
2621}
2622
2623/// Represents the error value of a [RaiseStatement].
2624#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2625#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2626#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2627pub enum RaiseStatementValue {
2628    /// `RAISE USING MESSAGE = 'error'`
2629    UsingMessage(Expr),
2630    /// `RAISE myerror`
2631    Expr(Expr),
2632}
2633
2634impl fmt::Display for RaiseStatementValue {
2635    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2636        match self {
2637            RaiseStatementValue::Expr(expr) => write!(f, "{expr}"),
2638            RaiseStatementValue::UsingMessage(expr) => write!(f, "USING MESSAGE = {expr}"),
2639        }
2640    }
2641}
2642
2643/// Represents an expression assignment within a variable `DECLARE` statement.
2644///
2645/// Examples:
2646/// ```sql
2647/// DECLARE variable_name := 42
2648/// DECLARE variable_name DEFAULT 42
2649/// ```
2650#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2651#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2652#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2653pub enum DeclareAssignment {
2654    /// Plain expression specified.
2655    Expr(Box<Expr>),
2656
2657    /// Expression assigned via the `DEFAULT` keyword
2658    Default(Box<Expr>),
2659
2660    /// Expression assigned via the `:=` syntax
2661    ///
2662    /// Example:
2663    /// ```sql
2664    /// DECLARE variable_name := 42;
2665    /// ```
2666    DuckAssignment(Box<Expr>),
2667
2668    /// Expression via the `FOR` keyword
2669    ///
2670    /// Example:
2671    /// ```sql
2672    /// DECLARE c1 CURSOR FOR res
2673    /// ```
2674    For(Box<Expr>),
2675
2676    /// Expression via the `=` syntax.
2677    ///
2678    /// Example:
2679    /// ```sql
2680    /// DECLARE @variable AS INT = 100
2681    /// ```
2682    MsSqlAssignment(Box<Expr>),
2683}
2684
2685impl fmt::Display for DeclareAssignment {
2686    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2687        match self {
2688            DeclareAssignment::Expr(expr) => {
2689                write!(f, "{expr}")
2690            }
2691            DeclareAssignment::Default(expr) => {
2692                write!(f, "DEFAULT {expr}")
2693            }
2694            DeclareAssignment::DuckAssignment(expr) => {
2695                write!(f, ":= {expr}")
2696            }
2697            DeclareAssignment::MsSqlAssignment(expr) => {
2698                write!(f, "= {expr}")
2699            }
2700            DeclareAssignment::For(expr) => {
2701                write!(f, "FOR {expr}")
2702            }
2703        }
2704    }
2705}
2706
2707/// Represents the type of a `DECLARE` statement.
2708#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2709#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2710#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2711pub enum DeclareType {
2712    /// Cursor variable type. e.g. [Snowflake] [PostgreSQL] [MsSql]
2713    ///
2714    /// [Snowflake]: https://docs.snowflake.com/en/developer-guide/snowflake-scripting/cursors#declaring-a-cursor
2715    /// [PostgreSQL]: https://www.postgresql.org/docs/current/plpgsql-cursors.html
2716    /// [MsSql]: https://learn.microsoft.com/en-us/sql/t-sql/language-elements/declare-cursor-transact-sql
2717    Cursor,
2718
2719    /// Result set variable type. [Snowflake]
2720    ///
2721    /// Syntax:
2722    /// ```text
2723    /// <resultset_name> RESULTSET [ { DEFAULT | := } ( <query> ) ] ;
2724    /// ```
2725    /// [Snowflake]: https://docs.snowflake.com/en/sql-reference/snowflake-scripting/declare#resultset-declaration-syntax
2726    ResultSet,
2727
2728    /// Exception declaration syntax. [Snowflake]
2729    ///
2730    /// Syntax:
2731    /// ```text
2732    /// <exception_name> EXCEPTION [ ( <exception_number> , '<exception_message>' ) ] ;
2733    /// ```
2734    /// [Snowflake]: https://docs.snowflake.com/en/sql-reference/snowflake-scripting/declare#exception-declaration-syntax
2735    Exception,
2736}
2737
2738impl fmt::Display for DeclareType {
2739    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2740        match self {
2741            DeclareType::Cursor => {
2742                write!(f, "CURSOR")
2743            }
2744            DeclareType::ResultSet => {
2745                write!(f, "RESULTSET")
2746            }
2747            DeclareType::Exception => {
2748                write!(f, "EXCEPTION")
2749            }
2750        }
2751    }
2752}
2753
2754/// A `DECLARE` statement.
2755/// [PostgreSQL] [Snowflake] [BigQuery]
2756///
2757/// Examples:
2758/// ```sql
2759/// DECLARE variable_name := 42
2760/// DECLARE liahona CURSOR FOR SELECT * FROM films;
2761/// ```
2762///
2763/// [PostgreSQL]: https://www.postgresql.org/docs/current/sql-declare.html
2764/// [Snowflake]: https://docs.snowflake.com/en/sql-reference/snowflake-scripting/declare
2765/// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#declare
2766#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2767#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2768#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2769pub struct Declare {
2770    /// The name(s) being declared.
2771    /// Example: `DECLARE a, b, c DEFAULT 42;
2772    pub names: Vec<Ident>,
2773    /// Data-type assigned to the declared variable.
2774    /// Example: `DECLARE x INT64 DEFAULT 42;
2775    pub data_type: Option<DataType>,
2776    /// Expression being assigned to the declared variable.
2777    pub assignment: Option<DeclareAssignment>,
2778    /// Represents the type of the declared variable.
2779    pub declare_type: Option<DeclareType>,
2780    /// Causes the cursor to return data in binary rather than in text format.
2781    pub binary: Option<bool>,
2782    /// None = Not specified
2783    /// Some(true) = INSENSITIVE
2784    /// Some(false) = ASENSITIVE
2785    pub sensitive: Option<bool>,
2786    /// None = Not specified
2787    /// Some(true) = SCROLL
2788    /// Some(false) = NO SCROLL
2789    pub scroll: Option<bool>,
2790    /// None = Not specified
2791    /// Some(true) = WITH HOLD, specifies that the cursor can continue to be used after the transaction that created it successfully commits
2792    /// Some(false) = WITHOUT HOLD, specifies that the cursor cannot be used outside of the transaction that created it
2793    pub hold: Option<bool>,
2794    /// `FOR <query>` clause in a CURSOR declaration.
2795    pub for_query: Option<Box<Query>>,
2796}
2797
2798impl fmt::Display for Declare {
2799    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2800        let Declare {
2801            names,
2802            data_type,
2803            assignment,
2804            declare_type,
2805            binary,
2806            sensitive,
2807            scroll,
2808            hold,
2809            for_query,
2810        } = self;
2811        write!(f, "{}", display_comma_separated(names))?;
2812
2813        if let Some(true) = binary {
2814            write!(f, " BINARY")?;
2815        }
2816
2817        if let Some(sensitive) = sensitive {
2818            if *sensitive {
2819                write!(f, " INSENSITIVE")?;
2820            } else {
2821                write!(f, " ASENSITIVE")?;
2822            }
2823        }
2824
2825        if let Some(scroll) = scroll {
2826            if *scroll {
2827                write!(f, " SCROLL")?;
2828            } else {
2829                write!(f, " NO SCROLL")?;
2830            }
2831        }
2832
2833        if let Some(declare_type) = declare_type {
2834            write!(f, " {declare_type}")?;
2835        }
2836
2837        if let Some(hold) = hold {
2838            if *hold {
2839                write!(f, " WITH HOLD")?;
2840            } else {
2841                write!(f, " WITHOUT HOLD")?;
2842            }
2843        }
2844
2845        if let Some(query) = for_query {
2846            write!(f, " FOR {query}")?;
2847        }
2848
2849        if let Some(data_type) = data_type {
2850            write!(f, " {data_type}")?;
2851        }
2852
2853        if let Some(expr) = assignment {
2854            write!(f, " {expr}")?;
2855        }
2856        Ok(())
2857    }
2858}
2859
2860/// Sql options of a `CREATE TABLE` statement.
2861#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2862#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2863#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2864pub enum CreateTableOptions {
2865    None,
2866    /// Options specified using the `WITH` keyword.
2867    /// e.g. `WITH (description = "123")`
2868    ///
2869    /// <https://www.postgresql.org/docs/current/sql-createtable.html>
2870    ///
2871    /// MSSQL supports more specific options that's not only key-value pairs.
2872    ///
2873    /// WITH (
2874    ///     DISTRIBUTION = ROUND_ROBIN,
2875    ///     CLUSTERED INDEX (column_a DESC, column_b)
2876    /// )
2877    ///
2878    /// <https://learn.microsoft.com/en-us/sql/t-sql/statements/create-table-azure-sql-data-warehouse?view=aps-pdw-2016-au7#syntax>
2879    With(Vec<SqlOption>),
2880    /// Options specified using the `OPTIONS` keyword.
2881    /// e.g. `OPTIONS(description = "123")`
2882    ///
2883    /// <https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#table_option_list>
2884    Options(Vec<SqlOption>),
2885
2886    /// Plain options, options which are not part on any declerative statement e.g. WITH/OPTIONS/...
2887    /// <https://dev.mysql.com/doc/refman/8.4/en/create-table.html>
2888    Plain(Vec<SqlOption>),
2889
2890    TableProperties(Vec<SqlOption>),
2891}
2892
2893impl Default for CreateTableOptions {
2894    fn default() -> Self {
2895        Self::None
2896    }
2897}
2898
2899impl fmt::Display for CreateTableOptions {
2900    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2901        match self {
2902            CreateTableOptions::With(with_options) => {
2903                write!(f, "WITH ({})", display_comma_separated(with_options))
2904            }
2905            CreateTableOptions::Options(options) => {
2906                write!(f, "OPTIONS({})", display_comma_separated(options))
2907            }
2908            CreateTableOptions::TableProperties(options) => {
2909                write!(f, "TBLPROPERTIES ({})", display_comma_separated(options))
2910            }
2911            CreateTableOptions::Plain(options) => {
2912                write!(f, "{}", display_separated(options, " "))
2913            }
2914            CreateTableOptions::None => Ok(()),
2915        }
2916    }
2917}
2918
2919/// A `FROM` clause within a `DELETE` statement.
2920///
2921/// Syntax
2922/// ```sql
2923/// [FROM] table
2924/// ```
2925#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2926#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2927#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2928pub enum FromTable {
2929    /// An explicit `FROM` keyword was specified.
2930    WithFromKeyword(Vec<TableWithJoins>),
2931    /// BigQuery: `FROM` keyword was omitted.
2932    /// <https://cloud.google.com/bigquery/docs/reference/standard-sql/dml-syntax#delete_statement>
2933    WithoutKeyword(Vec<TableWithJoins>),
2934}
2935impl Display for FromTable {
2936    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2937        match self {
2938            FromTable::WithFromKeyword(tables) => {
2939                write!(f, "FROM {}", display_comma_separated(tables))
2940            }
2941            FromTable::WithoutKeyword(tables) => {
2942                write!(f, "{}", display_comma_separated(tables))
2943            }
2944        }
2945    }
2946}
2947
2948/// Policy type for a `CREATE POLICY` statement.
2949/// ```sql
2950/// AS [ PERMISSIVE | RESTRICTIVE ]
2951/// ```
2952/// [PostgreSQL](https://www.postgresql.org/docs/current/sql-createpolicy.html)
2953#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2954#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2955#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2956pub enum CreatePolicyType {
2957    Permissive,
2958    Restrictive,
2959}
2960
2961/// Policy command for a `CREATE POLICY` statement.
2962/// ```sql
2963/// FOR [ALL | SELECT | INSERT | UPDATE | DELETE]
2964/// ```
2965/// [PostgreSQL](https://www.postgresql.org/docs/current/sql-createpolicy.html)
2966#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2967#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2968#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2969pub enum CreatePolicyCommand {
2970    All,
2971    Select,
2972    Insert,
2973    Update,
2974    Delete,
2975}
2976
2977#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2978#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2979#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2980pub enum Set {
2981    /// SQL Standard-style
2982    /// SET a = 1;
2983    SingleAssignment {
2984        scope: Option<ContextModifier>,
2985        hivevar: bool,
2986        variable: ObjectName,
2987        values: Vec<Expr>,
2988    },
2989    /// Snowflake-style
2990    /// SET (a, b, ..) = (1, 2, ..);
2991    ParenthesizedAssignments {
2992        variables: Vec<ObjectName>,
2993        values: Vec<Expr>,
2994    },
2995    /// MySQL-style
2996    /// SET a = 1, b = 2, ..;
2997    MultipleAssignments { assignments: Vec<SetAssignment> },
2998    /// MS-SQL session
2999    ///
3000    /// See <https://learn.microsoft.com/en-us/sql/t-sql/statements/set-statements-transact-sql>
3001    SetSessionParam(SetSessionParamKind),
3002    /// ```sql
3003    /// SET [ SESSION | LOCAL ] ROLE role_name
3004    /// ```
3005    ///
3006    /// Sets session state. Examples: [ANSI][1], [Postgresql][2], [MySQL][3], and [Oracle][4]
3007    ///
3008    /// [1]: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#set-role-statement
3009    /// [2]: https://www.postgresql.org/docs/14/sql-set-role.html
3010    /// [3]: https://dev.mysql.com/doc/refman/8.0/en/set-role.html
3011    /// [4]: https://docs.oracle.com/cd/B19306_01/server.102/b14200/statements_10004.htm
3012    SetRole {
3013        /// Non-ANSI optional identifier to inform if the role is defined inside the current session (`SESSION`) or transaction (`LOCAL`).
3014        context_modifier: Option<ContextModifier>,
3015        /// Role name. If NONE is specified, then the current role name is removed.
3016        role_name: Option<Ident>,
3017    },
3018    /// ```sql
3019    /// SET TIME ZONE <value>
3020    /// ```
3021    ///
3022    /// Note: this is a PostgreSQL-specific statements
3023    /// `SET TIME ZONE <value>` is an alias for `SET timezone TO <value>` in PostgreSQL
3024    /// However, we allow it for all dialects.
3025    SetTimeZone { local: bool, value: Expr },
3026    /// ```sql
3027    /// SET NAMES 'charset_name' [COLLATE 'collation_name']
3028    /// ```
3029    SetNames {
3030        charset_name: Ident,
3031        collation_name: Option<String>,
3032    },
3033    /// ```sql
3034    /// SET NAMES DEFAULT
3035    /// ```
3036    ///
3037    /// Note: this is a MySQL-specific statement.
3038    SetNamesDefault {},
3039    /// ```sql
3040    /// SET TRANSACTION ...
3041    /// ```
3042    SetTransaction {
3043        modes: Vec<TransactionMode>,
3044        snapshot: Option<Value>,
3045        session: bool,
3046    },
3047}
3048
3049impl Display for Set {
3050    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3051        match self {
3052            Self::ParenthesizedAssignments { variables, values } => write!(
3053                f,
3054                "SET ({}) = ({})",
3055                display_comma_separated(variables),
3056                display_comma_separated(values)
3057            ),
3058            Self::MultipleAssignments { assignments } => {
3059                write!(f, "SET {}", display_comma_separated(assignments))
3060            }
3061            Self::SetRole {
3062                context_modifier,
3063                role_name,
3064            } => {
3065                let role_name = role_name.clone().unwrap_or_else(|| Ident::new("NONE"));
3066                write!(
3067                    f,
3068                    "SET {modifier}ROLE {role_name}",
3069                    modifier = context_modifier.map(|m| format!("{m}")).unwrap_or_default()
3070                )
3071            }
3072            Self::SetSessionParam(kind) => write!(f, "SET {kind}"),
3073            Self::SetTransaction {
3074                modes,
3075                snapshot,
3076                session,
3077            } => {
3078                if *session {
3079                    write!(f, "SET SESSION CHARACTERISTICS AS TRANSACTION")?;
3080                } else {
3081                    write!(f, "SET TRANSACTION")?;
3082                }
3083                if !modes.is_empty() {
3084                    write!(f, " {}", display_comma_separated(modes))?;
3085                }
3086                if let Some(snapshot_id) = snapshot {
3087                    write!(f, " SNAPSHOT {snapshot_id}")?;
3088                }
3089                Ok(())
3090            }
3091            Self::SetTimeZone { local, value } => {
3092                f.write_str("SET ")?;
3093                if *local {
3094                    f.write_str("LOCAL ")?;
3095                }
3096                write!(f, "TIME ZONE {value}")
3097            }
3098            Self::SetNames {
3099                charset_name,
3100                collation_name,
3101            } => {
3102                write!(f, "SET NAMES {charset_name}")?;
3103
3104                if let Some(collation) = collation_name {
3105                    f.write_str(" COLLATE ")?;
3106                    f.write_str(collation)?;
3107                };
3108
3109                Ok(())
3110            }
3111            Self::SetNamesDefault {} => {
3112                f.write_str("SET NAMES DEFAULT")?;
3113
3114                Ok(())
3115            }
3116            Set::SingleAssignment {
3117                scope,
3118                hivevar,
3119                variable,
3120                values,
3121            } => {
3122                write!(
3123                    f,
3124                    "SET {}{}{} = {}",
3125                    scope.map(|s| format!("{s}")).unwrap_or_default(),
3126                    if *hivevar { "HIVEVAR:" } else { "" },
3127                    variable,
3128                    display_comma_separated(values)
3129                )
3130            }
3131        }
3132    }
3133}
3134
3135/// A representation of a `WHEN` arm with all the identifiers catched and the statements to execute
3136/// for the arm.
3137///
3138/// Snowflake: <https://docs.snowflake.com/en/sql-reference/snowflake-scripting/exception>
3139/// BigQuery: <https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#beginexceptionend>
3140#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3141#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3142#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3143pub struct ExceptionWhen {
3144    pub idents: Vec<Ident>,
3145    pub statements: Vec<Statement>,
3146}
3147
3148impl Display for ExceptionWhen {
3149    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3150        write!(
3151            f,
3152            "WHEN {idents} THEN",
3153            idents = display_separated(&self.idents, " OR ")
3154        )?;
3155
3156        if !self.statements.is_empty() {
3157            write!(f, " ")?;
3158            format_statement_list(f, &self.statements)?;
3159        }
3160
3161        Ok(())
3162    }
3163}
3164
3165/// A top-level statement (SELECT, INSERT, CREATE, etc.)
3166#[allow(clippy::large_enum_variant)]
3167#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3168#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3169#[cfg_attr(
3170    feature = "visitor",
3171    derive(Visit, VisitMut),
3172    visit(with = "visit_statement")
3173)]
3174pub enum Statement {
3175    /// ```sql
3176    /// ANALYZE
3177    /// ```
3178    /// Analyze (Hive)
3179    Analyze {
3180        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
3181        table_name: ObjectName,
3182        partitions: Option<Vec<Expr>>,
3183        for_columns: bool,
3184        columns: Vec<Ident>,
3185        cache_metadata: bool,
3186        noscan: bool,
3187        compute_statistics: bool,
3188        has_table_keyword: bool,
3189    },
3190    Set(Set),
3191    /// ```sql
3192    /// TRUNCATE
3193    /// ```
3194    /// Truncate (Hive)
3195    Truncate {
3196        table_names: Vec<TruncateTableTarget>,
3197        partitions: Option<Vec<Expr>>,
3198        /// TABLE - optional keyword;
3199        table: bool,
3200        /// Postgres-specific option
3201        /// [ RESTART IDENTITY | CONTINUE IDENTITY ]
3202        identity: Option<TruncateIdentityOption>,
3203        /// Postgres-specific option
3204        /// [ CASCADE | RESTRICT ]
3205        cascade: Option<CascadeOption>,
3206        /// ClickHouse-specific option
3207        /// [ ON CLUSTER cluster_name ]
3208        ///
3209        /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/truncate/)
3210        on_cluster: Option<Ident>,
3211    },
3212    /// ```sql
3213    /// MSCK
3214    /// ```
3215    /// Msck (Hive)
3216    Msck {
3217        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
3218        table_name: ObjectName,
3219        repair: bool,
3220        partition_action: Option<AddDropSync>,
3221    },
3222    /// ```sql
3223    /// SELECT
3224    /// ```
3225    Query(Box<Query>),
3226    /// ```sql
3227    /// INSERT
3228    /// ```
3229    Insert(Insert),
3230    /// ```sql
3231    /// INSTALL
3232    /// ```
3233    Install {
3234        /// Only for DuckDB
3235        extension_name: Ident,
3236    },
3237    /// ```sql
3238    /// LOAD
3239    /// ```
3240    Load {
3241        /// Only for DuckDB
3242        extension_name: Ident,
3243    },
3244    // TODO: Support ROW FORMAT
3245    Directory {
3246        overwrite: bool,
3247        local: bool,
3248        path: String,
3249        file_format: Option<FileFormat>,
3250        source: Box<Query>,
3251    },
3252    /// A `CASE` statement.
3253    Case(CaseStatement),
3254    /// An `IF` statement.
3255    If(IfStatement),
3256    /// A `WHILE` statement.
3257    While(WhileStatement),
3258    /// A `LOOP` statement (BigQuery).
3259    Loop(LoopStatement),
3260    /// A `FOR` loop statement (BigQuery).
3261    For(ForStatement),
3262    /// A `REPEAT` loop statement (BigQuery).
3263    Repeat(RepeatStatement),
3264    /// A `LEAVE` statement (exits a loop or block).
3265    Leave {
3266        label: Option<Ident>,
3267    },
3268    /// An `ITERATE` statement (continues to next loop iteration).
3269    Iterate {
3270        label: Option<Ident>,
3271    },
3272    /// A `BREAK` statement (exits a loop, alias for LEAVE in BigQuery).
3273    Break {
3274        label: Option<Ident>,
3275    },
3276    /// A `CONTINUE` statement (continues to next loop iteration).
3277    Continue {
3278        label: Option<Ident>,
3279    },
3280    /// A `RAISE` statement.
3281    Raise(RaiseStatement),
3282    /// ```sql
3283    /// CALL <function>
3284    /// ```
3285    Call(Function),
3286    /// ```sql
3287    /// COPY [TO | FROM] ...
3288    /// ```
3289    Copy {
3290        /// The source of 'COPY TO', or the target of 'COPY FROM'
3291        source: CopySource,
3292        /// If true, is a 'COPY TO' statement. If false is a 'COPY FROM'
3293        to: bool,
3294        /// The target of 'COPY TO', or the source of 'COPY FROM'
3295        target: CopyTarget,
3296        /// WITH options (from PostgreSQL version 9.0)
3297        options: Vec<CopyOption>,
3298        /// WITH options (before PostgreSQL version 9.0)
3299        legacy_options: Vec<CopyLegacyOption>,
3300        /// VALUES a vector of values to be copied
3301        values: Vec<Option<String>>,
3302    },
3303    /// ```sql
3304    /// COPY INTO <table> | <location>
3305    /// ```
3306    /// See:
3307    /// <https://docs.snowflake.com/en/sql-reference/sql/copy-into-table>
3308    /// <https://docs.snowflake.com/en/sql-reference/sql/copy-into-location>
3309    ///
3310    /// Copy Into syntax available for Snowflake is different than the one implemented in
3311    /// Postgres. Although they share common prefix, it is reasonable to implement them
3312    /// in different enums. This can be refactored later once custom dialects
3313    /// are allowed to have custom Statements.
3314    CopyIntoSnowflake {
3315        kind: CopyIntoSnowflakeKind,
3316        into: ObjectName,
3317        into_columns: Option<Vec<Ident>>,
3318        from_obj: Option<ObjectName>,
3319        from_obj_alias: Option<Ident>,
3320        stage_params: StageParamsObject,
3321        from_transformations: Option<Vec<StageLoadSelectItemKind>>,
3322        from_query: Option<Box<Query>>,
3323        files: Option<Vec<String>>,
3324        pattern: Option<String>,
3325        file_format: KeyValueOptions,
3326        copy_options: KeyValueOptions,
3327        validation_mode: Option<String>,
3328        partition: Option<Box<Expr>>,
3329    },
3330    /// ```sql
3331    /// OPEN cursor_name
3332    /// ```
3333    /// Opens a cursor.
3334    Open(OpenStatement),
3335    /// ```sql
3336    /// CLOSE
3337    /// ```
3338    /// Closes the portal underlying an open cursor.
3339    Close {
3340        /// Cursor name
3341        cursor: CloseCursor,
3342    },
3343    /// ```sql
3344    /// UPDATE
3345    /// ```
3346    Update {
3347        /// TABLE
3348        table: TableWithJoins,
3349        /// Column assignments
3350        assignments: Vec<Assignment>,
3351        /// Table which provide value to be set
3352        from: Option<UpdateTableFromKind>,
3353        /// WHERE
3354        selection: Option<Expr>,
3355        /// RETURNING
3356        returning: Option<Vec<SelectItem>>,
3357        /// SQLite-specific conflict resolution clause
3358        or: Option<SqliteOnConflict>,
3359        /// LIMIT
3360        limit: Option<Expr>,
3361    },
3362    /// ```sql
3363    /// DELETE
3364    /// ```
3365    Delete(Delete),
3366    /// ```sql
3367    /// CREATE VIEW
3368    /// ```
3369    CreateView {
3370        /// True if this is a `CREATE OR ALTER VIEW` statement
3371        ///
3372        /// [MsSql](https://learn.microsoft.com/en-us/sql/t-sql/statements/create-view-transact-sql)
3373        or_alter: bool,
3374        or_replace: bool,
3375        materialized: bool,
3376        /// Snowflake: SECURE view modifier
3377        /// <https://docs.snowflake.com/en/sql-reference/sql/create-view#syntax>
3378        secure: bool,
3379        /// View name
3380        name: ObjectName,
3381        /// If `if_not_exists` is true, this flag is set to true if the view name comes before the `IF NOT EXISTS` clause.
3382        /// Example:
3383        /// ```sql
3384        /// CREATE VIEW myview IF NOT EXISTS AS SELECT 1`
3385        ///  ```
3386        /// Otherwise, the flag is set to false if the view name comes after the clause
3387        /// Example:
3388        /// ```sql
3389        /// CREATE VIEW IF NOT EXISTS myview AS SELECT 1`
3390        ///  ```
3391        name_before_not_exists: bool,
3392        columns: Vec<ViewColumnDef>,
3393        query: Box<Query>,
3394        options: CreateTableOptions,
3395        cluster_by: Vec<Ident>,
3396        /// Snowflake: Views can have comments in Snowflake.
3397        /// <https://docs.snowflake.com/en/sql-reference/sql/create-view#syntax>
3398        comment: Option<String>,
3399        /// if true, has RedShift [`WITH NO SCHEMA BINDING`] clause <https://docs.aws.amazon.com/redshift/latest/dg/r_CREATE_VIEW.html>
3400        with_no_schema_binding: bool,
3401        /// if true, has SQLite `IF NOT EXISTS` clause <https://www.sqlite.org/lang_createview.html>
3402        if_not_exists: bool,
3403        /// if true, has SQLite `TEMP` or `TEMPORARY` clause <https://www.sqlite.org/lang_createview.html>
3404        temporary: bool,
3405        /// if not None, has Clickhouse `TO` clause, specify the table into which to insert results
3406        /// <https://clickhouse.com/docs/en/sql-reference/statements/create/view#materialized-view>
3407        to: Option<ObjectName>,
3408        /// MySQL: Optional parameters for the view algorithm, definer, and security context
3409        params: Option<CreateViewParams>,
3410    },
3411    /// ```sql
3412    /// CREATE TABLE
3413    /// ```
3414    CreateTable(CreateTable),
3415    /// ```sql
3416    /// CREATE VIRTUAL TABLE .. USING <module_name> (<module_args>)`
3417    /// ```
3418    /// Sqlite specific statement
3419    CreateVirtualTable {
3420        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
3421        name: ObjectName,
3422        if_not_exists: bool,
3423        module_name: Ident,
3424        module_args: Vec<Ident>,
3425    },
3426    /// ```sql
3427    /// `CREATE INDEX`
3428    /// ```
3429    CreateIndex(CreateIndex),
3430    /// ```sql
3431    /// CREATE ROLE
3432    /// ```
3433    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createrole.html)
3434    CreateRole {
3435        names: Vec<ObjectName>,
3436        if_not_exists: bool,
3437        // Postgres
3438        login: Option<bool>,
3439        inherit: Option<bool>,
3440        bypassrls: Option<bool>,
3441        password: Option<Password>,
3442        superuser: Option<bool>,
3443        create_db: Option<bool>,
3444        create_role: Option<bool>,
3445        replication: Option<bool>,
3446        connection_limit: Option<Expr>,
3447        valid_until: Option<Expr>,
3448        in_role: Vec<Ident>,
3449        in_group: Vec<Ident>,
3450        role: Vec<Ident>,
3451        user: Vec<Ident>,
3452        admin: Vec<Ident>,
3453        // MSSQL
3454        authorization_owner: Option<ObjectName>,
3455    },
3456    /// ```sql
3457    /// CREATE SECRET
3458    /// ```
3459    /// See [DuckDB](https://duckdb.org/docs/sql/statements/create_secret.html)
3460    CreateSecret {
3461        or_replace: bool,
3462        temporary: Option<bool>,
3463        if_not_exists: bool,
3464        name: Option<Ident>,
3465        storage_specifier: Option<Ident>,
3466        secret_type: Ident,
3467        options: Vec<SecretOption>,
3468    },
3469    /// A `CREATE SERVER` statement.
3470    CreateServer(CreateServerStatement),
3471    /// ```sql
3472    /// CREATE POLICY
3473    /// ```
3474    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createpolicy.html)
3475    CreatePolicy {
3476        name: Ident,
3477        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
3478        table_name: ObjectName,
3479        policy_type: Option<CreatePolicyType>,
3480        command: Option<CreatePolicyCommand>,
3481        to: Option<Vec<Owner>>,
3482        using: Option<Expr>,
3483        with_check: Option<Expr>,
3484    },
3485    /// ```sql
3486    /// CREATE CONNECTOR
3487    /// ```
3488    /// See [Hive](https://cwiki.apache.org/confluence/pages/viewpage.action?pageId=27362034#LanguageManualDDL-CreateDataConnectorCreateConnector)
3489    CreateConnector(CreateConnector),
3490    /// ```sql
3491    /// ALTER TABLE
3492    /// ```
3493    AlterTable {
3494        /// Table name
3495        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
3496        name: ObjectName,
3497        if_exists: bool,
3498        only: bool,
3499        operations: Vec<AlterTableOperation>,
3500        location: Option<HiveSetLocation>,
3501        /// ClickHouse dialect supports `ON CLUSTER` clause for ALTER TABLE
3502        /// For example: `ALTER TABLE table_name ON CLUSTER cluster_name ADD COLUMN c UInt32`
3503        /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/alter/update)
3504        on_cluster: Option<Ident>,
3505        /// Snowflake "ICEBERG" clause for Iceberg tables
3506        /// <https://docs.snowflake.com/en/sql-reference/sql/alter-iceberg-table>
3507        iceberg: bool,
3508        /// Token that represents the end of the statement (semicolon or EOF)
3509        end_token: AttachedToken,
3510    },
3511    /// ```sql
3512    /// ALTER SCHEMA
3513    /// ```
3514    /// See [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#alter_schema_collate_statement)
3515    AlterSchema(AlterSchema),
3516    /// ```sql
3517    /// ALTER INDEX
3518    /// ```
3519    AlterIndex {
3520        name: ObjectName,
3521        operation: AlterIndexOperation,
3522    },
3523    /// ```sql
3524    /// ALTER VIEW
3525    /// ```
3526    AlterView {
3527        /// View name
3528        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
3529        name: ObjectName,
3530        columns: Vec<Ident>,
3531        query: Box<Query>,
3532        with_options: Vec<SqlOption>,
3533    },
3534    /// ```sql
3535    /// ALTER TYPE
3536    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-altertype.html)
3537    /// ```
3538    AlterType(AlterType),
3539    /// ```sql
3540    /// ALTER ROLE
3541    /// ```
3542    AlterRole {
3543        name: Ident,
3544        operation: AlterRoleOperation,
3545    },
3546    /// ```sql
3547    /// ALTER POLICY <NAME> ON <TABLE NAME> [<OPERATION>]
3548    /// ```
3549    /// (Postgresql-specific)
3550    AlterPolicy {
3551        name: Ident,
3552        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
3553        table_name: ObjectName,
3554        operation: AlterPolicyOperation,
3555    },
3556    /// ```sql
3557    /// ALTER CONNECTOR connector_name SET DCPROPERTIES(property_name=property_value, ...);
3558    /// or
3559    /// ALTER CONNECTOR connector_name SET URL new_url;
3560    /// or
3561    /// ALTER CONNECTOR connector_name SET OWNER [USER|ROLE] user_or_role;
3562    /// ```
3563    /// (Hive-specific)
3564    AlterConnector {
3565        name: Ident,
3566        properties: Option<Vec<SqlOption>>,
3567        url: Option<String>,
3568        owner: Option<ddl::AlterConnectorOwner>,
3569    },
3570    /// ```sql
3571    /// ALTER SESSION SET sessionParam
3572    /// ALTER SESSION UNSET <param_name> [ , <param_name> , ... ]
3573    /// ```
3574    /// See <https://docs.snowflake.com/en/sql-reference/sql/alter-session>
3575    AlterSession {
3576        /// true is to set for the session parameters, false is to unset
3577        set: bool,
3578        /// The session parameters to set or unset
3579        session_params: KeyValueOptions,
3580    },
3581    /// ```sql
3582    /// ATTACH DATABASE 'path/to/file' AS alias
3583    /// ```
3584    /// (SQLite-specific)
3585    AttachDatabase {
3586        /// The name to bind to the newly attached database
3587        schema_name: Ident,
3588        /// An expression that indicates the path to the database file
3589        database_file_name: Expr,
3590        /// true if the syntax is 'ATTACH DATABASE', false if it's just 'ATTACH'
3591        database: bool,
3592    },
3593    /// (DuckDB-specific)
3594    /// ```sql
3595    /// ATTACH 'sqlite_file.db' AS sqlite_db (READ_ONLY, TYPE SQLITE);
3596    /// ```
3597    /// See <https://duckdb.org/docs/sql/statements/attach.html>
3598    AttachDuckDBDatabase {
3599        if_not_exists: bool,
3600        /// true if the syntax is 'ATTACH DATABASE', false if it's just 'ATTACH'
3601        database: bool,
3602        /// An expression that indicates the path to the database file
3603        database_path: Ident,
3604        database_alias: Option<Ident>,
3605        attach_options: Vec<AttachDuckDBDatabaseOption>,
3606    },
3607    /// (DuckDB-specific)
3608    /// ```sql
3609    /// DETACH db_alias;
3610    /// ```
3611    /// See <https://duckdb.org/docs/sql/statements/attach.html>
3612    DetachDuckDBDatabase {
3613        if_exists: bool,
3614        /// true if the syntax is 'DETACH DATABASE', false if it's just 'DETACH'
3615        database: bool,
3616        database_alias: Ident,
3617    },
3618    /// ```sql
3619    /// DROP [TABLE, VIEW, ...]
3620    /// ```
3621    Drop {
3622        /// The type of the object to drop: TABLE, VIEW, etc.
3623        object_type: ObjectType,
3624        /// An optional `IF EXISTS` clause. (Non-standard.)
3625        if_exists: bool,
3626        /// One or more objects to drop. (ANSI SQL requires exactly one.)
3627        names: Vec<ObjectName>,
3628        /// Whether `CASCADE` was specified. This will be `false` when
3629        /// `RESTRICT` or no drop behavior at all was specified.
3630        cascade: bool,
3631        /// Whether `RESTRICT` was specified. This will be `false` when
3632        /// `CASCADE` or no drop behavior at all was specified.
3633        restrict: bool,
3634        /// Hive allows you specify whether the table's stored data will be
3635        /// deleted along with the dropped table
3636        purge: bool,
3637        /// MySQL-specific "TEMPORARY" keyword
3638        temporary: bool,
3639        /// MySQL-specific drop index syntax, which requires table specification
3640        /// See <https://dev.mysql.com/doc/refman/8.4/en/drop-index.html>
3641        table: Option<ObjectName>,
3642    },
3643    /// ```sql
3644    /// DROP FUNCTION
3645    /// ```
3646    DropFunction {
3647        if_exists: bool,
3648        /// One or more function to drop
3649        func_desc: Vec<FunctionDesc>,
3650        /// `CASCADE` or `RESTRICT`
3651        drop_behavior: Option<DropBehavior>,
3652    },
3653    /// ```sql
3654    /// DROP DOMAIN
3655    /// ```
3656    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-dropdomain.html)
3657    ///
3658    /// DROP DOMAIN [ IF EXISTS ] name [, ...] [ CASCADE | RESTRICT ]
3659    ///
3660    DropDomain(DropDomain),
3661    /// ```sql
3662    /// DROP PROCEDURE
3663    /// ```
3664    DropProcedure {
3665        if_exists: bool,
3666        /// One or more function to drop
3667        proc_desc: Vec<FunctionDesc>,
3668        /// `CASCADE` or `RESTRICT`
3669        drop_behavior: Option<DropBehavior>,
3670    },
3671    /// ```sql
3672    /// DROP SECRET
3673    /// ```
3674    DropSecret {
3675        if_exists: bool,
3676        temporary: Option<bool>,
3677        name: Ident,
3678        storage_specifier: Option<Ident>,
3679    },
3680    ///```sql
3681    /// DROP POLICY
3682    /// ```
3683    /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-droppolicy.html)
3684    DropPolicy {
3685        if_exists: bool,
3686        name: Ident,
3687        table_name: ObjectName,
3688        drop_behavior: Option<DropBehavior>,
3689    },
3690    /// ```sql
3691    /// DROP CONNECTOR
3692    /// ```
3693    /// See [Hive](https://cwiki.apache.org/confluence/pages/viewpage.action?pageId=27362034#LanguageManualDDL-DropConnector)
3694    DropConnector {
3695        if_exists: bool,
3696        name: Ident,
3697    },
3698    /// ```sql
3699    /// DECLARE
3700    /// ```
3701    /// Declare Cursor Variables
3702    ///
3703    /// Note: this is a PostgreSQL-specific statement,
3704    /// but may also compatible with other SQL.
3705    Declare {
3706        stmts: Vec<Declare>,
3707    },
3708    /// ```sql
3709    /// CREATE EXTENSION [ IF NOT EXISTS ] extension_name
3710    ///     [ WITH ] [ SCHEMA schema_name ]
3711    ///              [ VERSION version ]
3712    ///              [ CASCADE ]
3713    /// ```
3714    ///
3715    /// Note: this is a PostgreSQL-specific statement,
3716    CreateExtension {
3717        name: Ident,
3718        if_not_exists: bool,
3719        cascade: bool,
3720        schema: Option<Ident>,
3721        version: Option<Ident>,
3722    },
3723    /// ```sql
3724    /// DROP EXTENSION [ IF EXISTS ] name [, ...] [ CASCADE | RESTRICT ]
3725    ///
3726    /// Note: this is a PostgreSQL-specific statement.
3727    /// https://www.postgresql.org/docs/current/sql-dropextension.html
3728    /// ```
3729    DropExtension {
3730        names: Vec<Ident>,
3731        if_exists: bool,
3732        /// `CASCADE` or `RESTRICT`
3733        cascade_or_restrict: Option<ReferentialAction>,
3734    },
3735    /// ```sql
3736    /// FETCH
3737    /// ```
3738    /// Retrieve rows from a query using a cursor
3739    ///
3740    /// Note: this is a PostgreSQL-specific statement,
3741    /// but may also compatible with other SQL.
3742    Fetch {
3743        /// Cursor name
3744        name: Ident,
3745        direction: FetchDirection,
3746        position: FetchPosition,
3747        /// Optional, It's possible to fetch rows form cursor to the table
3748        into: Option<ObjectName>,
3749    },
3750    /// ```sql
3751    /// FLUSH [NO_WRITE_TO_BINLOG | LOCAL] flush_option [, flush_option] ... | tables_option
3752    /// ```
3753    ///
3754    /// Note: this is a Mysql-specific statement,
3755    /// but may also compatible with other SQL.
3756    Flush {
3757        object_type: FlushType,
3758        location: Option<FlushLocation>,
3759        channel: Option<String>,
3760        read_lock: bool,
3761        export: bool,
3762        tables: Vec<ObjectName>,
3763    },
3764    /// ```sql
3765    /// DISCARD [ ALL | PLANS | SEQUENCES | TEMPORARY | TEMP ]
3766    /// ```
3767    ///
3768    /// Note: this is a PostgreSQL-specific statement,
3769    /// but may also compatible with other SQL.
3770    Discard {
3771        object_type: DiscardObject,
3772    },
3773    /// `SHOW FUNCTIONS`
3774    ///
3775    /// Note: this is a Presto-specific statement.
3776    ShowFunctions {
3777        filter: Option<ShowStatementFilter>,
3778    },
3779    /// ```sql
3780    /// SHOW <variable>
3781    /// ```
3782    ///
3783    /// Note: this is a PostgreSQL-specific statement.
3784    ShowVariable {
3785        variable: Vec<Ident>,
3786    },
3787    /// ```sql
3788    /// SHOW [GLOBAL | SESSION] STATUS [LIKE 'pattern' | WHERE expr]
3789    /// ```
3790    ///
3791    /// Note: this is a MySQL-specific statement.
3792    ShowStatus {
3793        filter: Option<ShowStatementFilter>,
3794        global: bool,
3795        session: bool,
3796    },
3797    /// ```sql
3798    /// SHOW VARIABLES
3799    /// ```
3800    ///
3801    /// Note: this is a MySQL-specific statement.
3802    ShowVariables {
3803        filter: Option<ShowStatementFilter>,
3804        global: bool,
3805        session: bool,
3806    },
3807    /// ```sql
3808    /// SHOW CREATE TABLE
3809    /// ```
3810    ///
3811    /// Note: this is a MySQL-specific statement.
3812    ShowCreate {
3813        obj_type: ShowCreateObject,
3814        obj_name: ObjectName,
3815    },
3816    /// ```sql
3817    /// SHOW COLUMNS
3818    /// ```
3819    ShowColumns {
3820        extended: bool,
3821        full: bool,
3822        show_options: ShowStatementOptions,
3823    },
3824    /// ```sql
3825    /// SHOW DATABASES
3826    /// ```
3827    ShowDatabases {
3828        terse: bool,
3829        history: bool,
3830        show_options: ShowStatementOptions,
3831    },
3832    /// ```sql
3833    /// SHOW SCHEMAS
3834    /// ```
3835    ShowSchemas {
3836        terse: bool,
3837        history: bool,
3838        show_options: ShowStatementOptions,
3839    },
3840    // ```sql
3841    // SHOW {CHARACTER SET | CHARSET}
3842    // ```
3843    // [MySQL]:
3844    // <https://dev.mysql.com/doc/refman/8.4/en/show.html#:~:text=SHOW%20%7BCHARACTER%20SET%20%7C%20CHARSET%7D%20%5Blike_or_where%5D>
3845    ShowCharset(ShowCharset),
3846    /// ```sql
3847    /// SHOW OBJECTS LIKE 'line%' IN mydb.public
3848    /// ```
3849    /// Snowflake-specific statement
3850    /// <https://docs.snowflake.com/en/sql-reference/sql/show-objects>
3851    ShowObjects(ShowObjects),
3852    /// ```sql
3853    /// SHOW TABLES
3854    /// ```
3855    ShowTables {
3856        terse: bool,
3857        history: bool,
3858        extended: bool,
3859        full: bool,
3860        external: bool,
3861        show_options: ShowStatementOptions,
3862    },
3863    /// ```sql
3864    /// SHOW VIEWS
3865    /// ```
3866    ShowViews {
3867        terse: bool,
3868        materialized: bool,
3869        show_options: ShowStatementOptions,
3870    },
3871    /// ```sql
3872    /// SHOW COLLATION
3873    /// ```
3874    ///
3875    /// Note: this is a MySQL-specific statement.
3876    ShowCollation {
3877        filter: Option<ShowStatementFilter>,
3878    },
3879    /// ```sql
3880    /// `USE ...`
3881    /// ```
3882    Use(Use),
3883    /// ```sql
3884    /// START  [ TRANSACTION | WORK ] | START TRANSACTION } ...
3885    /// ```
3886    /// If `begin` is false.
3887    ///
3888    /// ```sql
3889    /// `BEGIN  [ TRANSACTION | WORK ] | START TRANSACTION } ...`
3890    /// ```
3891    /// If `begin` is true
3892    StartTransaction {
3893        modes: Vec<TransactionMode>,
3894        begin: bool,
3895        transaction: Option<BeginTransactionKind>,
3896        modifier: Option<TransactionModifier>,
3897        /// List of statements belonging to the `BEGIN` block.
3898        /// Example:
3899        /// ```sql
3900        /// BEGIN
3901        ///     SELECT 1;
3902        ///     SELECT 2;
3903        /// END;
3904        /// ```
3905        statements: Vec<Statement>,
3906        /// Exception handling with exception clauses.
3907        /// Example:
3908        /// ```sql
3909        /// EXCEPTION
3910        ///     WHEN EXCEPTION_1 THEN
3911        ///         SELECT 2;
3912        ///     WHEN EXCEPTION_2 OR EXCEPTION_3 THEN
3913        ///         SELECT 3;
3914        ///     WHEN OTHER THEN
3915        ///         SELECT 4;
3916        /// ```
3917        /// <https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#beginexceptionend>
3918        /// <https://docs.snowflake.com/en/sql-reference/snowflake-scripting/exception>
3919        exception: Option<Vec<ExceptionWhen>>,
3920        /// TRUE if the statement has an `END` keyword.
3921        has_end_keyword: bool,
3922    },
3923    /// ```sql
3924    /// COMMENT ON ...
3925    /// ```
3926    ///
3927    /// Note: this is a PostgreSQL-specific statement.
3928    Comment {
3929        object_type: CommentObject,
3930        object_name: ObjectName,
3931        comment: Option<String>,
3932        /// An optional `IF EXISTS` clause. (Non-standard.)
3933        /// See <https://docs.snowflake.com/en/sql-reference/sql/comment>
3934        if_exists: bool,
3935    },
3936    /// ```sql
3937    /// COMMIT [ TRANSACTION | WORK ] [ AND [ NO ] CHAIN ]
3938    /// ```
3939    /// If `end` is false
3940    ///
3941    /// ```sql
3942    /// END [ TRY | CATCH ]
3943    /// ```
3944    /// If `end` is true
3945    Commit {
3946        chain: bool,
3947        end: bool,
3948        modifier: Option<TransactionModifier>,
3949    },
3950    /// ```sql
3951    /// ROLLBACK [ TRANSACTION | WORK ] [ AND [ NO ] CHAIN ] [ TO [ SAVEPOINT ] savepoint_name ]
3952    /// ```
3953    Rollback {
3954        chain: bool,
3955        savepoint: Option<Ident>,
3956    },
3957    /// ```sql
3958    /// CREATE SCHEMA
3959    /// ```
3960    CreateSchema {
3961        /// `<schema name> | AUTHORIZATION <schema authorization identifier>  | <schema name>  AUTHORIZATION <schema authorization identifier>`
3962        schema_name: SchemaName,
3963        if_not_exists: bool,
3964        /// Schema properties.
3965        ///
3966        /// ```sql
3967        /// CREATE SCHEMA myschema WITH (key1='value1');
3968        /// ```
3969        ///
3970        /// [Trino](https://trino.io/docs/current/sql/create-schema.html)
3971        with: Option<Vec<SqlOption>>,
3972        /// Schema options.
3973        ///
3974        /// ```sql
3975        /// CREATE SCHEMA myschema OPTIONS(key1='value1');
3976        /// ```
3977        ///
3978        /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_schema_statement)
3979        options: Option<Vec<SqlOption>>,
3980        /// Default collation specification for the schema.
3981        ///
3982        /// ```sql
3983        /// CREATE SCHEMA myschema DEFAULT COLLATE 'und:ci';
3984        /// ```
3985        ///
3986        /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_schema_statement)
3987        default_collate_spec: Option<Expr>,
3988        /// Clones a schema
3989        ///
3990        /// ```sql
3991        /// CREATE SCHEMA myschema CLONE otherschema
3992        /// ```
3993        ///
3994        /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-clone#databases-schemas)
3995        clone: Option<ObjectName>,
3996    },
3997    /// ```sql
3998    /// CREATE DATABASE
3999    /// ```
4000    /// See:
4001    /// <https://docs.snowflake.com/en/sql-reference/sql/create-database>
4002    CreateDatabase {
4003        db_name: ObjectName,
4004        if_not_exists: bool,
4005        location: Option<String>,
4006        managed_location: Option<String>,
4007        or_replace: bool,
4008        transient: bool,
4009        clone: Option<ObjectName>,
4010        data_retention_time_in_days: Option<u64>,
4011        max_data_extension_time_in_days: Option<u64>,
4012        external_volume: Option<String>,
4013        catalog: Option<String>,
4014        replace_invalid_characters: Option<bool>,
4015        default_ddl_collation: Option<String>,
4016        storage_serialization_policy: Option<StorageSerializationPolicy>,
4017        comment: Option<String>,
4018        catalog_sync: Option<String>,
4019        catalog_sync_namespace_mode: Option<CatalogSyncNamespaceMode>,
4020        catalog_sync_namespace_flatten_delimiter: Option<String>,
4021        with_tags: Option<Vec<Tag>>,
4022        with_contacts: Option<Vec<ContactEntry>>,
4023    },
4024    /// ```sql
4025    /// CREATE FUNCTION
4026    /// ```
4027    ///
4028    /// Supported variants:
4029    /// 1. [Hive](https://cwiki.apache.org/confluence/display/hive/languagemanual+ddl#LanguageManualDDL-Create/Drop/ReloadFunction)
4030    /// 2. [PostgreSQL](https://www.postgresql.org/docs/15/sql-createfunction.html)
4031    /// 3. [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_function_statement)
4032    /// 4. [MsSql](https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql)
4033    CreateFunction(CreateFunction),
4034    /// CREATE TRIGGER statement. See struct [CreateTrigger] for details.
4035    CreateTrigger(CreateTrigger),
4036    /// DROP TRIGGER statement. See struct [DropTrigger] for details.
4037    DropTrigger(DropTrigger),
4038    /// ```sql
4039    /// CREATE PROCEDURE
4040    /// ```
4041    CreateProcedure {
4042        or_alter: bool,
4043        name: ObjectName,
4044        params: Option<Vec<ProcedureParam>>,
4045        language: Option<Ident>,
4046        body: ConditionalStatements,
4047    },
4048    /// ```sql
4049    /// CREATE MACRO
4050    /// ```
4051    ///
4052    /// Supported variants:
4053    /// 1. [DuckDB](https://duckdb.org/docs/sql/statements/create_macro)
4054    CreateMacro {
4055        or_replace: bool,
4056        temporary: bool,
4057        name: ObjectName,
4058        args: Option<Vec<MacroArg>>,
4059        definition: MacroDefinition,
4060    },
4061    /// ```sql
4062    /// CREATE STAGE
4063    /// ```
4064    /// See <https://docs.snowflake.com/en/sql-reference/sql/create-stage>
4065    CreateStage {
4066        or_replace: bool,
4067        temporary: bool,
4068        if_not_exists: bool,
4069        name: ObjectName,
4070        stage_params: StageParamsObject,
4071        directory_table_params: KeyValueOptions,
4072        file_format: KeyValueOptions,
4073        copy_options: KeyValueOptions,
4074        comment: Option<String>,
4075    },
4076    /// ```sql
4077    /// ASSERT <condition> [AS <message>]
4078    /// ```
4079    Assert {
4080        condition: Expr,
4081        message: Option<Expr>,
4082    },
4083    /// ```sql
4084    /// GRANT privileges ON objects TO grantees
4085    /// ```
4086    Grant {
4087        privileges: Privileges,
4088        objects: Option<GrantObjects>,
4089        grantees: Vec<Grantee>,
4090        with_grant_option: bool,
4091        as_grantor: Option<Ident>,
4092        granted_by: Option<Ident>,
4093        current_grants: Option<CurrentGrantsKind>,
4094    },
4095    /// ```sql
4096    /// DENY privileges ON object TO grantees
4097    /// ```
4098    Deny(DenyStatement),
4099    /// ```sql
4100    /// REVOKE privileges ON objects FROM grantees
4101    /// ```
4102    Revoke {
4103        privileges: Privileges,
4104        objects: Option<GrantObjects>,
4105        grantees: Vec<Grantee>,
4106        granted_by: Option<Ident>,
4107        cascade: Option<CascadeOption>,
4108    },
4109    /// ```sql
4110    /// DEALLOCATE [ PREPARE ] { name | ALL }
4111    /// ```
4112    ///
4113    /// Note: this is a PostgreSQL-specific statement.
4114    Deallocate {
4115        name: Ident,
4116        prepare: bool,
4117    },
4118    /// ```sql
4119    /// An `EXECUTE` statement
4120    /// ```
4121    ///
4122    /// Postgres: <https://www.postgresql.org/docs/current/sql-execute.html>
4123    /// MSSQL: <https://learn.microsoft.com/en-us/sql/relational-databases/stored-procedures/execute-a-stored-procedure>
4124    /// BigQuery: <https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#execute_immediate>
4125    /// Snowflake: <https://docs.snowflake.com/en/sql-reference/sql/execute-immediate>
4126    Execute {
4127        name: Option<ObjectName>,
4128        parameters: Vec<Expr>,
4129        has_parentheses: bool,
4130        /// Is this an `EXECUTE IMMEDIATE`
4131        immediate: bool,
4132        into: Vec<Ident>,
4133        using: Vec<ExprWithAlias>,
4134        /// Whether the last parameter is the return value of the procedure
4135        /// MSSQL: <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/execute-transact-sql?view=sql-server-ver17#output>
4136        output: bool,
4137        /// Whether to invoke the procedure with the default parameter values
4138        /// MSSQL: <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/execute-transact-sql?view=sql-server-ver17#default>
4139        default: bool,
4140    },
4141    /// ```sql
4142    /// PREPARE name [ ( data_type [, ...] ) ] AS statement
4143    /// ```
4144    ///
4145    /// Note: this is a PostgreSQL-specific statement.
4146    Prepare {
4147        name: Ident,
4148        data_types: Vec<DataType>,
4149        statement: Box<Statement>,
4150    },
4151    /// ```sql
4152    /// KILL [CONNECTION | QUERY | MUTATION]
4153    /// ```
4154    ///
4155    /// See <https://clickhouse.com/docs/en/sql-reference/statements/kill/>
4156    /// See <https://dev.mysql.com/doc/refman/8.0/en/kill.html>
4157    Kill {
4158        modifier: Option<KillType>,
4159        // processlist_id
4160        id: u64,
4161    },
4162    /// ```sql
4163    /// [EXPLAIN | DESC | DESCRIBE] TABLE
4164    /// ```
4165    /// Note: this is a MySQL-specific statement. See <https://dev.mysql.com/doc/refman/8.0/en/explain.html>
4166    ExplainTable {
4167        /// `EXPLAIN | DESC | DESCRIBE`
4168        describe_alias: DescribeAlias,
4169        /// Hive style `FORMATTED | EXTENDED`
4170        hive_format: Option<HiveDescribeFormat>,
4171        /// Snowflake and ClickHouse support `DESC|DESCRIBE TABLE <table_name>` syntax
4172        ///
4173        /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/desc-table.html)
4174        /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/describe-table)
4175        has_table_keyword: bool,
4176        /// Table name
4177        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
4178        table_name: ObjectName,
4179    },
4180    /// ```sql
4181    /// [EXPLAIN | DESC | DESCRIBE]  <statement>
4182    /// ```
4183    Explain {
4184        /// `EXPLAIN | DESC | DESCRIBE`
4185        describe_alias: DescribeAlias,
4186        /// Carry out the command and show actual run times and other statistics.
4187        analyze: bool,
4188        // Display additional information regarding the plan.
4189        verbose: bool,
4190        /// `EXPLAIN QUERY PLAN`
4191        /// Display the query plan without running the query.
4192        ///
4193        /// [SQLite](https://sqlite.org/lang_explain.html)
4194        query_plan: bool,
4195        /// `EXPLAIN ESTIMATE`
4196        /// [Clickhouse](https://clickhouse.com/docs/en/sql-reference/statements/explain#explain-estimate)
4197        estimate: bool,
4198        /// A SQL query that specifies what to explain
4199        statement: Box<Statement>,
4200        /// Optional output format of explain
4201        format: Option<AnalyzeFormatKind>,
4202        /// Postgres style utility options, `(analyze, verbose true)`
4203        options: Option<Vec<UtilityOption>>,
4204    },
4205    /// ```sql
4206    /// SAVEPOINT
4207    /// ```
4208    /// Define a new savepoint within the current transaction
4209    Savepoint {
4210        name: Ident,
4211    },
4212    /// ```sql
4213    /// RELEASE [ SAVEPOINT ] savepoint_name
4214    /// ```
4215    ReleaseSavepoint {
4216        name: Ident,
4217    },
4218    /// A `MERGE` statement.
4219    ///
4220    /// ```sql
4221    /// MERGE INTO <target_table> USING <source> ON <join_expr> { matchedClause | notMatchedClause } [ ... ]
4222    /// ```
4223    /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/merge)
4224    /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/dml-syntax#merge_statement)
4225    /// [MSSQL](https://learn.microsoft.com/en-us/sql/t-sql/statements/merge-transact-sql?view=sql-server-ver16)
4226    Merge {
4227        /// optional INTO keyword
4228        into: bool,
4229        /// Specifies the table to merge
4230        table: TableFactor,
4231        /// Specifies the table or subquery to join with the target table
4232        source: TableFactor,
4233        /// Specifies the expression on which to join the target table and source
4234        on: Box<Expr>,
4235        /// Specifies the actions to perform when values match or do not match.
4236        clauses: Vec<MergeClause>,
4237        // Specifies the output to save changes in MSSQL
4238        output: Option<OutputClause>,
4239    },
4240    /// ```sql
4241    /// CACHE [ FLAG ] TABLE <table_name> [ OPTIONS('K1' = 'V1', 'K2' = V2) ] [ AS ] [ <query> ]
4242    /// ```
4243    ///
4244    /// See [Spark SQL docs] for more details.
4245    ///
4246    /// [Spark SQL docs]: https://docs.databricks.com/spark/latest/spark-sql/language-manual/sql-ref-syntax-aux-cache-cache-table.html
4247    Cache {
4248        /// Table flag
4249        table_flag: Option<ObjectName>,
4250        /// Table name
4251
4252        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
4253        table_name: ObjectName,
4254        has_as: bool,
4255        /// Table confs
4256        options: Vec<SqlOption>,
4257        /// Cache table as a Query
4258        query: Option<Box<Query>>,
4259    },
4260    /// ```sql
4261    /// UNCACHE TABLE [ IF EXISTS ]  <table_name>
4262    /// ```
4263    UNCache {
4264        /// Table name
4265        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
4266        table_name: ObjectName,
4267        if_exists: bool,
4268    },
4269    /// ```sql
4270    /// CREATE [ { TEMPORARY | TEMP } ] SEQUENCE [ IF NOT EXISTS ] <sequence_name>
4271    /// ```
4272    /// Define a new sequence:
4273    CreateSequence {
4274        temporary: bool,
4275        if_not_exists: bool,
4276        name: ObjectName,
4277        data_type: Option<DataType>,
4278        sequence_options: Vec<SequenceOptions>,
4279        owned_by: Option<ObjectName>,
4280    },
4281    /// A `CREATE DOMAIN` statement.
4282    CreateDomain(CreateDomain),
4283    /// ```sql
4284    /// CREATE TYPE <name>
4285    /// ```
4286    CreateType {
4287        name: ObjectName,
4288        representation: UserDefinedTypeRepresentation,
4289    },
4290    /// ```sql
4291    /// PRAGMA <schema-name>.<pragma-name> = <pragma-value>
4292    /// ```
4293    Pragma {
4294        name: ObjectName,
4295        value: Option<Value>,
4296        is_eq: bool,
4297    },
4298    /// ```sql
4299    /// LOCK TABLES <table_name> [READ [LOCAL] | [LOW_PRIORITY] WRITE]
4300    /// ```
4301    /// Note: this is a MySQL-specific statement. See <https://dev.mysql.com/doc/refman/8.0/en/lock-tables.html>
4302    LockTables {
4303        tables: Vec<LockTable>,
4304    },
4305    /// ```sql
4306    /// UNLOCK TABLES
4307    /// ```
4308    /// Note: this is a MySQL-specific statement. See <https://dev.mysql.com/doc/refman/8.0/en/lock-tables.html>
4309    UnlockTables,
4310    /// Unloads the result of a query to file
4311    ///
4312    /// [Athena](https://docs.aws.amazon.com/athena/latest/ug/unload.html):
4313    /// ```sql
4314    /// UNLOAD(statement) TO <destination> [ WITH options ]
4315    /// ```
4316    ///
4317    /// [Redshift](https://docs.aws.amazon.com/redshift/latest/dg/r_UNLOAD.html):
4318    /// ```sql
4319    /// UNLOAD('statement') TO <destination> [ OPTIONS ]
4320    /// ```
4321    Unload {
4322        query: Option<Box<Query>>,
4323        query_text: Option<String>,
4324        to: Ident,
4325        auth: Option<IamRoleKind>,
4326        with: Vec<SqlOption>,
4327        options: Vec<CopyLegacyOption>,
4328    },
4329    /// ```sql
4330    /// OPTIMIZE TABLE [db.]name [ON CLUSTER cluster] [PARTITION partition | PARTITION ID 'partition_id'] [FINAL] [DEDUPLICATE [BY expression]]
4331    /// ```
4332    ///
4333    /// See ClickHouse <https://clickhouse.com/docs/en/sql-reference/statements/optimize>
4334    OptimizeTable {
4335        name: ObjectName,
4336        on_cluster: Option<Ident>,
4337        partition: Option<Partition>,
4338        include_final: bool,
4339        deduplicate: Option<Deduplicate>,
4340    },
4341    /// ```sql
4342    /// LISTEN
4343    /// ```
4344    /// listen for a notification channel
4345    ///
4346    /// See Postgres <https://www.postgresql.org/docs/current/sql-listen.html>
4347    LISTEN {
4348        channel: Ident,
4349    },
4350    /// ```sql
4351    /// UNLISTEN
4352    /// ```
4353    /// stop listening for a notification
4354    ///
4355    /// See Postgres <https://www.postgresql.org/docs/current/sql-unlisten.html>
4356    UNLISTEN {
4357        channel: Ident,
4358    },
4359    /// ```sql
4360    /// NOTIFY channel [ , payload ]
4361    /// ```
4362    /// send a notification event together with an optional "payload" string to channel
4363    ///
4364    /// See Postgres <https://www.postgresql.org/docs/current/sql-notify.html>
4365    NOTIFY {
4366        channel: Ident,
4367        payload: Option<String>,
4368    },
4369    /// ```sql
4370    /// LOAD DATA [LOCAL] INPATH 'filepath' [OVERWRITE] INTO TABLE tablename
4371    /// [PARTITION (partcol1=val1, partcol2=val2 ...)]
4372    /// [INPUTFORMAT 'inputformat' SERDE 'serde']
4373    /// ```
4374    /// Loading files into tables
4375    ///
4376    /// See Hive <https://cwiki.apache.org/confluence/pages/viewpage.action?pageId=27362036#LanguageManualDML-Loadingfilesintotables>
4377    LoadData {
4378        local: bool,
4379        inpath: String,
4380        overwrite: bool,
4381        table_name: ObjectName,
4382        partitioned: Option<Vec<Expr>>,
4383        table_format: Option<HiveLoadDataFormat>,
4384    },
4385    /// ```sql
4386    /// Rename TABLE tbl_name TO new_tbl_name[, tbl_name2 TO new_tbl_name2] ...
4387    /// ```
4388    /// Renames one or more tables
4389    ///
4390    /// See Mysql <https://dev.mysql.com/doc/refman/9.1/en/rename-table.html>
4391    RenameTable(Vec<RenameTable>),
4392    /// Snowflake `LIST`
4393    /// See: <https://docs.snowflake.com/en/sql-reference/sql/list>
4394    List(FileStagingCommand),
4395    /// Snowflake `REMOVE`
4396    /// See: <https://docs.snowflake.com/en/sql-reference/sql/remove>
4397    Remove(FileStagingCommand),
4398    /// RaiseError (MSSQL)
4399    /// RAISERROR ( { msg_id | msg_str | @local_variable }
4400    /// { , severity , state }
4401    /// [ , argument [ , ...n ] ] )
4402    /// [ WITH option [ , ...n ] ]
4403    /// See <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/raiserror-transact-sql?view=sql-server-ver16>
4404    RaisError {
4405        message: Box<Expr>,
4406        severity: Box<Expr>,
4407        state: Box<Expr>,
4408        arguments: Vec<Expr>,
4409        options: Vec<RaisErrorOption>,
4410    },
4411    /// ```sql
4412    /// PRINT msg_str | @local_variable | string_expr
4413    /// ```
4414    ///
4415    /// See: <https://learn.microsoft.com/en-us/sql/t-sql/statements/print-transact-sql>
4416    Print(PrintStatement),
4417    /// ```sql
4418    /// RETURN [ expression ]
4419    /// ```
4420    ///
4421    /// See [ReturnStatement]
4422    Return(ReturnStatement),
4423    /// Export data statement
4424    ///
4425    /// Example:
4426    /// ```sql
4427    /// EXPORT DATA OPTIONS(uri='gs://bucket/folder/*', format='PARQUET', overwrite=true) AS
4428    /// SELECT field1, field2 FROM mydataset.table1 ORDER BY field1 LIMIT 10
4429    /// ```
4430    /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/export-statements)
4431    ExportData(ExportData),
4432    /// ```sql
4433    /// CREATE [OR REPLACE] USER <user> [IF NOT EXISTS]
4434    /// ```
4435    /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-user)
4436    CreateUser(CreateUser),
4437    /// Re-sorts rows and reclaims space in either a specified table or all tables in the current database
4438    ///
4439    /// ```sql
4440    /// VACUUM tbl
4441    /// ```
4442    /// [Redshift](https://docs.aws.amazon.com/redshift/latest/dg/r_VACUUM_command.html)
4443    Vacuum(VacuumStatement),
4444}
4445
4446/// ```sql
4447/// {COPY | REVOKE} CURRENT GRANTS
4448/// ```
4449///
4450/// - [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/grant-ownership#optional-parameters)
4451#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
4452#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4453#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
4454pub enum CurrentGrantsKind {
4455    CopyCurrentGrants,
4456    RevokeCurrentGrants,
4457}
4458
4459impl fmt::Display for CurrentGrantsKind {
4460    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
4461        match self {
4462            CurrentGrantsKind::CopyCurrentGrants => write!(f, "COPY CURRENT GRANTS"),
4463            CurrentGrantsKind::RevokeCurrentGrants => write!(f, "REVOKE CURRENT GRANTS"),
4464        }
4465    }
4466}
4467
4468#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
4469#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4470#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
4471pub enum RaisErrorOption {
4472    Log,
4473    NoWait,
4474    SetError,
4475}
4476
4477impl fmt::Display for RaisErrorOption {
4478    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
4479        match self {
4480            RaisErrorOption::Log => write!(f, "LOG"),
4481            RaisErrorOption::NoWait => write!(f, "NOWAIT"),
4482            RaisErrorOption::SetError => write!(f, "SETERROR"),
4483        }
4484    }
4485}
4486
4487impl fmt::Display for Statement {
4488    /// Formats a SQL statement with support for pretty printing.
4489    ///
4490    /// When using the alternate flag (`{:#}`), the statement will be formatted with proper
4491    /// indentation and line breaks. For example:
4492    ///
4493    /// ```
4494    /// # use sqlparser::dialect::GenericDialect;
4495    /// # use sqlparser::parser::Parser;
4496    /// let sql = "SELECT a, b FROM table_1";
4497    /// let ast = Parser::parse_sql(&GenericDialect, sql).unwrap();
4498    ///
4499    /// // Regular formatting
4500    /// assert_eq!(format!("{}", ast[0]), "SELECT a, b FROM table_1");
4501    ///
4502    /// // Pretty printing
4503    /// assert_eq!(format!("{:#}", ast[0]),
4504    /// r#"SELECT
4505    ///   a,
4506    ///   b
4507    /// FROM
4508    ///   table_1"#);
4509    /// ```
4510    // Clippy thinks this function is too complicated, but it is painful to
4511    // split up without extracting structs for each `Statement` variant.
4512    #[allow(clippy::cognitive_complexity)]
4513    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
4514        match self {
4515            Statement::Flush {
4516                object_type,
4517                location,
4518                channel,
4519                read_lock,
4520                export,
4521                tables,
4522            } => {
4523                write!(f, "FLUSH")?;
4524                if let Some(location) = location {
4525                    f.write_str(" ")?;
4526                    location.fmt(f)?;
4527                }
4528                write!(f, " {object_type}")?;
4529
4530                if let Some(channel) = channel {
4531                    write!(f, " FOR CHANNEL {channel}")?;
4532                }
4533
4534                write!(
4535                    f,
4536                    "{tables}{read}{export}",
4537                    tables = if !tables.is_empty() {
4538                        " ".to_string() + &display_comma_separated(tables).to_string()
4539                    } else {
4540                        "".to_string()
4541                    },
4542                    export = if *export { " FOR EXPORT" } else { "" },
4543                    read = if *read_lock { " WITH READ LOCK" } else { "" }
4544                )
4545            }
4546            Statement::Kill { modifier, id } => {
4547                write!(f, "KILL ")?;
4548
4549                if let Some(m) = modifier {
4550                    write!(f, "{m} ")?;
4551                }
4552
4553                write!(f, "{id}")
4554            }
4555            Statement::ExplainTable {
4556                describe_alias,
4557                hive_format,
4558                has_table_keyword,
4559                table_name,
4560            } => {
4561                write!(f, "{describe_alias} ")?;
4562
4563                if let Some(format) = hive_format {
4564                    write!(f, "{format} ")?;
4565                }
4566                if *has_table_keyword {
4567                    write!(f, "TABLE ")?;
4568                }
4569
4570                write!(f, "{table_name}")
4571            }
4572            Statement::Explain {
4573                describe_alias,
4574                verbose,
4575                analyze,
4576                query_plan,
4577                estimate,
4578                statement,
4579                format,
4580                options,
4581            } => {
4582                write!(f, "{describe_alias} ")?;
4583
4584                if *query_plan {
4585                    write!(f, "QUERY PLAN ")?;
4586                }
4587                if *analyze {
4588                    write!(f, "ANALYZE ")?;
4589                }
4590                if *estimate {
4591                    write!(f, "ESTIMATE ")?;
4592                }
4593
4594                if *verbose {
4595                    write!(f, "VERBOSE ")?;
4596                }
4597
4598                if let Some(format) = format {
4599                    write!(f, "{format} ")?;
4600                }
4601
4602                if let Some(options) = options {
4603                    write!(f, "({}) ", display_comma_separated(options))?;
4604                }
4605
4606                write!(f, "{statement}")
4607            }
4608            Statement::Query(s) => s.fmt(f),
4609            Statement::Declare { stmts } => {
4610                write!(f, "DECLARE ")?;
4611                write!(f, "{}", display_separated(stmts, "; "))
4612            }
4613            Statement::Fetch {
4614                name,
4615                direction,
4616                position,
4617                into,
4618            } => {
4619                write!(f, "FETCH {direction} {position} {name}")?;
4620
4621                if let Some(into) = into {
4622                    write!(f, " INTO {into}")?;
4623                }
4624
4625                Ok(())
4626            }
4627            Statement::Directory {
4628                overwrite,
4629                local,
4630                path,
4631                file_format,
4632                source,
4633            } => {
4634                write!(
4635                    f,
4636                    "INSERT{overwrite}{local} DIRECTORY '{path}'",
4637                    overwrite = if *overwrite { " OVERWRITE" } else { "" },
4638                    local = if *local { " LOCAL" } else { "" },
4639                    path = path
4640                )?;
4641                if let Some(ref ff) = file_format {
4642                    write!(f, " STORED AS {ff}")?
4643                }
4644                write!(f, " {source}")
4645            }
4646            Statement::Msck {
4647                table_name,
4648                repair,
4649                partition_action,
4650            } => {
4651                write!(
4652                    f,
4653                    "MSCK {repair}TABLE {table}",
4654                    repair = if *repair { "REPAIR " } else { "" },
4655                    table = table_name
4656                )?;
4657                if let Some(pa) = partition_action {
4658                    write!(f, " {pa}")?;
4659                }
4660                Ok(())
4661            }
4662            Statement::Truncate {
4663                table_names,
4664                partitions,
4665                table,
4666                identity,
4667                cascade,
4668                on_cluster,
4669            } => {
4670                let table = if *table { "TABLE " } else { "" };
4671
4672                write!(
4673                    f,
4674                    "TRUNCATE {table}{table_names}",
4675                    table_names = display_comma_separated(table_names)
4676                )?;
4677
4678                if let Some(identity) = identity {
4679                    match identity {
4680                        TruncateIdentityOption::Restart => write!(f, " RESTART IDENTITY")?,
4681                        TruncateIdentityOption::Continue => write!(f, " CONTINUE IDENTITY")?,
4682                    }
4683                }
4684                if let Some(cascade) = cascade {
4685                    match cascade {
4686                        CascadeOption::Cascade => write!(f, " CASCADE")?,
4687                        CascadeOption::Restrict => write!(f, " RESTRICT")?,
4688                    }
4689                }
4690
4691                if let Some(ref parts) = partitions {
4692                    if !parts.is_empty() {
4693                        write!(f, " PARTITION ({})", display_comma_separated(parts))?;
4694                    }
4695                }
4696                if let Some(on_cluster) = on_cluster {
4697                    write!(f, " ON CLUSTER {on_cluster}")?;
4698                }
4699                Ok(())
4700            }
4701            Statement::Case(stmt) => {
4702                write!(f, "{stmt}")
4703            }
4704            Statement::If(stmt) => {
4705                write!(f, "{stmt}")
4706            }
4707            Statement::While(stmt) => {
4708                write!(f, "{stmt}")
4709            }
4710            Statement::Loop(stmt) => {
4711                write!(f, "{stmt}")
4712            }
4713            Statement::For(stmt) => {
4714                write!(f, "{stmt}")
4715            }
4716            Statement::Repeat(stmt) => {
4717                write!(f, "{stmt}")
4718            }
4719            Statement::Leave { label } => {
4720                write!(f, "LEAVE")?;
4721                if let Some(l) = label {
4722                    write!(f, " {l}")?;
4723                }
4724                Ok(())
4725            }
4726            Statement::Iterate { label } => {
4727                write!(f, "ITERATE")?;
4728                if let Some(l) = label {
4729                    write!(f, " {l}")?;
4730                }
4731                Ok(())
4732            }
4733            Statement::Break { label } => {
4734                write!(f, "BREAK")?;
4735                if let Some(l) = label {
4736                    write!(f, " {l}")?;
4737                }
4738                Ok(())
4739            }
4740            Statement::Continue { label } => {
4741                write!(f, "CONTINUE")?;
4742                if let Some(l) = label {
4743                    write!(f, " {l}")?;
4744                }
4745                Ok(())
4746            }
4747            Statement::Raise(stmt) => {
4748                write!(f, "{stmt}")
4749            }
4750            Statement::AttachDatabase {
4751                schema_name,
4752                database_file_name,
4753                database,
4754            } => {
4755                let keyword = if *database { "DATABASE " } else { "" };
4756                write!(f, "ATTACH {keyword}{database_file_name} AS {schema_name}")
4757            }
4758            Statement::AttachDuckDBDatabase {
4759                if_not_exists,
4760                database,
4761                database_path,
4762                database_alias,
4763                attach_options,
4764            } => {
4765                write!(
4766                    f,
4767                    "ATTACH{database}{if_not_exists} {database_path}",
4768                    database = if *database { " DATABASE" } else { "" },
4769                    if_not_exists = if *if_not_exists { " IF NOT EXISTS" } else { "" },
4770                )?;
4771                if let Some(alias) = database_alias {
4772                    write!(f, " AS {alias}")?;
4773                }
4774                if !attach_options.is_empty() {
4775                    write!(f, " ({})", display_comma_separated(attach_options))?;
4776                }
4777                Ok(())
4778            }
4779            Statement::DetachDuckDBDatabase {
4780                if_exists,
4781                database,
4782                database_alias,
4783            } => {
4784                write!(
4785                    f,
4786                    "DETACH{database}{if_exists} {database_alias}",
4787                    database = if *database { " DATABASE" } else { "" },
4788                    if_exists = if *if_exists { " IF EXISTS" } else { "" },
4789                )?;
4790                Ok(())
4791            }
4792            Statement::Analyze {
4793                table_name,
4794                partitions,
4795                for_columns,
4796                columns,
4797                cache_metadata,
4798                noscan,
4799                compute_statistics,
4800                has_table_keyword,
4801            } => {
4802                write!(
4803                    f,
4804                    "ANALYZE{}{table_name}",
4805                    if *has_table_keyword { " TABLE " } else { " " }
4806                )?;
4807                if let Some(ref parts) = partitions {
4808                    if !parts.is_empty() {
4809                        write!(f, " PARTITION ({})", display_comma_separated(parts))?;
4810                    }
4811                }
4812
4813                if *compute_statistics {
4814                    write!(f, " COMPUTE STATISTICS")?;
4815                }
4816                if *noscan {
4817                    write!(f, " NOSCAN")?;
4818                }
4819                if *cache_metadata {
4820                    write!(f, " CACHE METADATA")?;
4821                }
4822                if *for_columns {
4823                    write!(f, " FOR COLUMNS")?;
4824                    if !columns.is_empty() {
4825                        write!(f, " {}", display_comma_separated(columns))?;
4826                    }
4827                }
4828                Ok(())
4829            }
4830            Statement::Insert(insert) => insert.fmt(f),
4831            Statement::Install {
4832                extension_name: name,
4833            } => write!(f, "INSTALL {name}"),
4834
4835            Statement::Load {
4836                extension_name: name,
4837            } => write!(f, "LOAD {name}"),
4838
4839            Statement::Call(function) => write!(f, "CALL {function}"),
4840
4841            Statement::Copy {
4842                source,
4843                to,
4844                target,
4845                options,
4846                legacy_options,
4847                values,
4848            } => {
4849                write!(f, "COPY")?;
4850                match source {
4851                    CopySource::Query(query) => write!(f, " ({query})")?,
4852                    CopySource::Table {
4853                        table_name,
4854                        columns,
4855                    } => {
4856                        write!(f, " {table_name}")?;
4857                        if !columns.is_empty() {
4858                            write!(f, " ({})", display_comma_separated(columns))?;
4859                        }
4860                    }
4861                }
4862                write!(f, " {} {}", if *to { "TO" } else { "FROM" }, target)?;
4863                if !options.is_empty() {
4864                    write!(f, " ({})", display_comma_separated(options))?;
4865                }
4866                if !legacy_options.is_empty() {
4867                    write!(f, " {}", display_separated(legacy_options, " "))?;
4868                }
4869                if !values.is_empty() {
4870                    writeln!(f, ";")?;
4871                    let mut delim = "";
4872                    for v in values {
4873                        write!(f, "{delim}")?;
4874                        delim = "\t";
4875                        if let Some(v) = v {
4876                            write!(f, "{v}")?;
4877                        } else {
4878                            write!(f, "\\N")?;
4879                        }
4880                    }
4881                    write!(f, "\n\\.")?;
4882                }
4883                Ok(())
4884            }
4885            Statement::Update {
4886                table,
4887                assignments,
4888                from,
4889                selection,
4890                returning,
4891                or,
4892                limit,
4893            } => {
4894                f.write_str("UPDATE ")?;
4895                if let Some(or) = or {
4896                    or.fmt(f)?;
4897                    f.write_str(" ")?;
4898                }
4899                table.fmt(f)?;
4900                if let Some(UpdateTableFromKind::BeforeSet(from)) = from {
4901                    SpaceOrNewline.fmt(f)?;
4902                    f.write_str("FROM")?;
4903                    indented_list(f, from)?;
4904                }
4905                if !assignments.is_empty() {
4906                    SpaceOrNewline.fmt(f)?;
4907                    f.write_str("SET")?;
4908                    indented_list(f, assignments)?;
4909                }
4910                if let Some(UpdateTableFromKind::AfterSet(from)) = from {
4911                    SpaceOrNewline.fmt(f)?;
4912                    f.write_str("FROM")?;
4913                    indented_list(f, from)?;
4914                }
4915                if let Some(selection) = selection {
4916                    SpaceOrNewline.fmt(f)?;
4917                    f.write_str("WHERE")?;
4918                    SpaceOrNewline.fmt(f)?;
4919                    Indent(selection).fmt(f)?;
4920                }
4921                if let Some(returning) = returning {
4922                    SpaceOrNewline.fmt(f)?;
4923                    f.write_str("RETURNING")?;
4924                    indented_list(f, returning)?;
4925                }
4926                if let Some(limit) = limit {
4927                    SpaceOrNewline.fmt(f)?;
4928                    write!(f, "LIMIT {limit}")?;
4929                }
4930                Ok(())
4931            }
4932            Statement::Delete(delete) => delete.fmt(f),
4933            Statement::Open(open) => open.fmt(f),
4934            Statement::Close { cursor } => {
4935                write!(f, "CLOSE {cursor}")?;
4936
4937                Ok(())
4938            }
4939            Statement::CreateDatabase {
4940                db_name,
4941                if_not_exists,
4942                location,
4943                managed_location,
4944                or_replace,
4945                transient,
4946                clone,
4947                data_retention_time_in_days,
4948                max_data_extension_time_in_days,
4949                external_volume,
4950                catalog,
4951                replace_invalid_characters,
4952                default_ddl_collation,
4953                storage_serialization_policy,
4954                comment,
4955                catalog_sync,
4956                catalog_sync_namespace_mode,
4957                catalog_sync_namespace_flatten_delimiter,
4958                with_tags,
4959                with_contacts,
4960            } => {
4961                write!(
4962                    f,
4963                    "CREATE {or_replace}{transient}DATABASE {if_not_exists}{name}",
4964                    or_replace = if *or_replace { "OR REPLACE " } else { "" },
4965                    transient = if *transient { "TRANSIENT " } else { "" },
4966                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
4967                    name = db_name,
4968                )?;
4969
4970                if let Some(l) = location {
4971                    write!(f, " LOCATION '{l}'")?;
4972                }
4973                if let Some(ml) = managed_location {
4974                    write!(f, " MANAGEDLOCATION '{ml}'")?;
4975                }
4976                if let Some(clone) = clone {
4977                    write!(f, " CLONE {clone}")?;
4978                }
4979
4980                if let Some(value) = data_retention_time_in_days {
4981                    write!(f, " DATA_RETENTION_TIME_IN_DAYS = {value}")?;
4982                }
4983
4984                if let Some(value) = max_data_extension_time_in_days {
4985                    write!(f, " MAX_DATA_EXTENSION_TIME_IN_DAYS = {value}")?;
4986                }
4987
4988                if let Some(vol) = external_volume {
4989                    write!(f, " EXTERNAL_VOLUME = '{vol}'")?;
4990                }
4991
4992                if let Some(cat) = catalog {
4993                    write!(f, " CATALOG = '{cat}'")?;
4994                }
4995
4996                if let Some(true) = replace_invalid_characters {
4997                    write!(f, " REPLACE_INVALID_CHARACTERS = TRUE")?;
4998                } else if let Some(false) = replace_invalid_characters {
4999                    write!(f, " REPLACE_INVALID_CHARACTERS = FALSE")?;
5000                }
5001
5002                if let Some(collation) = default_ddl_collation {
5003                    write!(f, " DEFAULT_DDL_COLLATION = '{collation}'")?;
5004                }
5005
5006                if let Some(policy) = storage_serialization_policy {
5007                    write!(f, " STORAGE_SERIALIZATION_POLICY = {policy}")?;
5008                }
5009
5010                if let Some(comment) = comment {
5011                    write!(f, " COMMENT = '{comment}'")?;
5012                }
5013
5014                if let Some(sync) = catalog_sync {
5015                    write!(f, " CATALOG_SYNC = '{sync}'")?;
5016                }
5017
5018                if let Some(mode) = catalog_sync_namespace_mode {
5019                    write!(f, " CATALOG_SYNC_NAMESPACE_MODE = {mode}")?;
5020                }
5021
5022                if let Some(delim) = catalog_sync_namespace_flatten_delimiter {
5023                    write!(f, " CATALOG_SYNC_NAMESPACE_FLATTEN_DELIMITER = '{delim}'")?;
5024                }
5025
5026                if let Some(tags) = with_tags {
5027                    write!(f, " WITH TAG ({})", display_comma_separated(tags))?;
5028                }
5029
5030                if let Some(contacts) = with_contacts {
5031                    write!(f, " WITH CONTACT ({})", display_comma_separated(contacts))?;
5032                }
5033                Ok(())
5034            }
5035            Statement::CreateFunction(create_function) => create_function.fmt(f),
5036            Statement::CreateDomain(create_domain) => create_domain.fmt(f),
5037            Statement::CreateTrigger(create_trigger) => create_trigger.fmt(f),
5038            Statement::DropTrigger(drop_trigger) => drop_trigger.fmt(f),
5039            Statement::CreateProcedure {
5040                name,
5041                or_alter,
5042                params,
5043                language,
5044                body,
5045            } => {
5046                write!(
5047                    f,
5048                    "CREATE {or_alter}PROCEDURE {name}",
5049                    or_alter = if *or_alter { "OR ALTER " } else { "" },
5050                    name = name
5051                )?;
5052
5053                if let Some(p) = params {
5054                    if !p.is_empty() {
5055                        write!(f, " ({})", display_comma_separated(p))?;
5056                    }
5057                }
5058
5059                if let Some(language) = language {
5060                    write!(f, " LANGUAGE {language}")?;
5061                }
5062
5063                write!(f, " AS {body}")
5064            }
5065            Statement::CreateMacro {
5066                or_replace,
5067                temporary,
5068                name,
5069                args,
5070                definition,
5071            } => {
5072                write!(
5073                    f,
5074                    "CREATE {or_replace}{temp}MACRO {name}",
5075                    temp = if *temporary { "TEMPORARY " } else { "" },
5076                    or_replace = if *or_replace { "OR REPLACE " } else { "" },
5077                )?;
5078                if let Some(args) = args {
5079                    write!(f, "({})", display_comma_separated(args))?;
5080                }
5081                match definition {
5082                    MacroDefinition::Expr(expr) => write!(f, " AS {expr}")?,
5083                    MacroDefinition::Table(query) => write!(f, " AS TABLE {query}")?,
5084                }
5085                Ok(())
5086            }
5087            Statement::CreateView {
5088                or_alter,
5089                name,
5090                or_replace,
5091                columns,
5092                query,
5093                materialized,
5094                secure,
5095                options,
5096                cluster_by,
5097                comment,
5098                with_no_schema_binding,
5099                if_not_exists,
5100                temporary,
5101                to,
5102                params,
5103                name_before_not_exists,
5104            } => {
5105                write!(
5106                    f,
5107                    "CREATE {or_alter}{or_replace}",
5108                    or_alter = if *or_alter { "OR ALTER " } else { "" },
5109                    or_replace = if *or_replace { "OR REPLACE " } else { "" },
5110                )?;
5111                if let Some(params) = params {
5112                    params.fmt(f)?;
5113                }
5114                write!(
5115                    f,
5116                    "{secure}{materialized}{temporary}VIEW {if_not_and_name}{to}",
5117                    if_not_and_name = if *if_not_exists {
5118                        if *name_before_not_exists {
5119                            format!("{name} IF NOT EXISTS")
5120                        } else {
5121                            format!("IF NOT EXISTS {name}")
5122                        }
5123                    } else {
5124                        format!("{name}")
5125                    },
5126                    secure = if *secure { "SECURE " } else { "" },
5127                    materialized = if *materialized { "MATERIALIZED " } else { "" },
5128                    temporary = if *temporary { "TEMPORARY " } else { "" },
5129                    to = to
5130                        .as_ref()
5131                        .map(|to| format!(" TO {to}"))
5132                        .unwrap_or_default()
5133                )?;
5134                if !columns.is_empty() {
5135                    write!(f, " ({})", display_comma_separated(columns))?;
5136                }
5137                if matches!(options, CreateTableOptions::With(_)) {
5138                    write!(f, " {options}")?;
5139                }
5140                if let Some(comment) = comment {
5141                    write!(
5142                        f,
5143                        " COMMENT = '{}'",
5144                        value::escape_single_quote_string(comment)
5145                    )?;
5146                }
5147                if !cluster_by.is_empty() {
5148                    write!(f, " CLUSTER BY ({})", display_comma_separated(cluster_by))?;
5149                }
5150                if matches!(options, CreateTableOptions::Options(_)) {
5151                    write!(f, " {options}")?;
5152                }
5153                f.write_str(" AS")?;
5154                SpaceOrNewline.fmt(f)?;
5155                query.fmt(f)?;
5156                if *with_no_schema_binding {
5157                    write!(f, " WITH NO SCHEMA BINDING")?;
5158                }
5159                Ok(())
5160            }
5161            Statement::CreateTable(create_table) => create_table.fmt(f),
5162            Statement::LoadData {
5163                local,
5164                inpath,
5165                overwrite,
5166                table_name,
5167                partitioned,
5168                table_format,
5169            } => {
5170                write!(
5171                    f,
5172                    "LOAD DATA {local}INPATH '{inpath}' {overwrite}INTO TABLE {table_name}",
5173                    local = if *local { "LOCAL " } else { "" },
5174                    inpath = inpath,
5175                    overwrite = if *overwrite { "OVERWRITE " } else { "" },
5176                    table_name = table_name,
5177                )?;
5178                if let Some(ref parts) = &partitioned {
5179                    if !parts.is_empty() {
5180                        write!(f, " PARTITION ({})", display_comma_separated(parts))?;
5181                    }
5182                }
5183                if let Some(HiveLoadDataFormat {
5184                    serde,
5185                    input_format,
5186                }) = &table_format
5187                {
5188                    write!(f, " INPUTFORMAT {input_format} SERDE {serde}")?;
5189                }
5190                Ok(())
5191            }
5192            Statement::CreateVirtualTable {
5193                name,
5194                if_not_exists,
5195                module_name,
5196                module_args,
5197            } => {
5198                write!(
5199                    f,
5200                    "CREATE VIRTUAL TABLE {if_not_exists}{name} USING {module_name}",
5201                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
5202                    name = name,
5203                    module_name = module_name
5204                )?;
5205                if !module_args.is_empty() {
5206                    write!(f, " ({})", display_comma_separated(module_args))?;
5207                }
5208                Ok(())
5209            }
5210            Statement::CreateIndex(create_index) => create_index.fmt(f),
5211            Statement::CreateExtension {
5212                name,
5213                if_not_exists,
5214                cascade,
5215                schema,
5216                version,
5217            } => {
5218                write!(
5219                    f,
5220                    "CREATE EXTENSION {if_not_exists}{name}",
5221                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" }
5222                )?;
5223                if *cascade || schema.is_some() || version.is_some() {
5224                    write!(f, " WITH")?;
5225
5226                    if let Some(name) = schema {
5227                        write!(f, " SCHEMA {name}")?;
5228                    }
5229                    if let Some(version) = version {
5230                        write!(f, " VERSION {version}")?;
5231                    }
5232                    if *cascade {
5233                        write!(f, " CASCADE")?;
5234                    }
5235                }
5236
5237                Ok(())
5238            }
5239            Statement::DropExtension {
5240                names,
5241                if_exists,
5242                cascade_or_restrict,
5243            } => {
5244                write!(f, "DROP EXTENSION")?;
5245                if *if_exists {
5246                    write!(f, " IF EXISTS")?;
5247                }
5248                write!(f, " {}", display_comma_separated(names))?;
5249                if let Some(cascade_or_restrict) = cascade_or_restrict {
5250                    write!(f, " {cascade_or_restrict}")?;
5251                }
5252                Ok(())
5253            }
5254            Statement::CreateRole {
5255                names,
5256                if_not_exists,
5257                inherit,
5258                login,
5259                bypassrls,
5260                password,
5261                create_db,
5262                create_role,
5263                superuser,
5264                replication,
5265                connection_limit,
5266                valid_until,
5267                in_role,
5268                in_group,
5269                role,
5270                user,
5271                admin,
5272                authorization_owner,
5273            } => {
5274                write!(
5275                    f,
5276                    "CREATE ROLE {if_not_exists}{names}{superuser}{create_db}{create_role}{inherit}{login}{replication}{bypassrls}",
5277                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
5278                    names = display_separated(names, ", "),
5279                    superuser = match *superuser {
5280                        Some(true) => " SUPERUSER",
5281                        Some(false) => " NOSUPERUSER",
5282                        None => ""
5283                    },
5284                    create_db = match *create_db {
5285                        Some(true) => " CREATEDB",
5286                        Some(false) => " NOCREATEDB",
5287                        None => ""
5288                    },
5289                    create_role = match *create_role {
5290                        Some(true) => " CREATEROLE",
5291                        Some(false) => " NOCREATEROLE",
5292                        None => ""
5293                    },
5294                    inherit = match *inherit {
5295                        Some(true) => " INHERIT",
5296                        Some(false) => " NOINHERIT",
5297                        None => ""
5298                    },
5299                    login = match *login {
5300                        Some(true) => " LOGIN",
5301                        Some(false) => " NOLOGIN",
5302                        None => ""
5303                    },
5304                    replication = match *replication {
5305                        Some(true) => " REPLICATION",
5306                        Some(false) => " NOREPLICATION",
5307                        None => ""
5308                    },
5309                    bypassrls = match *bypassrls {
5310                        Some(true) => " BYPASSRLS",
5311                        Some(false) => " NOBYPASSRLS",
5312                        None => ""
5313                    }
5314                )?;
5315                if let Some(limit) = connection_limit {
5316                    write!(f, " CONNECTION LIMIT {limit}")?;
5317                }
5318                match password {
5319                    Some(Password::Password(pass)) => write!(f, " PASSWORD {pass}"),
5320                    Some(Password::NullPassword) => write!(f, " PASSWORD NULL"),
5321                    None => Ok(()),
5322                }?;
5323                if let Some(until) = valid_until {
5324                    write!(f, " VALID UNTIL {until}")?;
5325                }
5326                if !in_role.is_empty() {
5327                    write!(f, " IN ROLE {}", display_comma_separated(in_role))?;
5328                }
5329                if !in_group.is_empty() {
5330                    write!(f, " IN GROUP {}", display_comma_separated(in_group))?;
5331                }
5332                if !role.is_empty() {
5333                    write!(f, " ROLE {}", display_comma_separated(role))?;
5334                }
5335                if !user.is_empty() {
5336                    write!(f, " USER {}", display_comma_separated(user))?;
5337                }
5338                if !admin.is_empty() {
5339                    write!(f, " ADMIN {}", display_comma_separated(admin))?;
5340                }
5341                if let Some(owner) = authorization_owner {
5342                    write!(f, " AUTHORIZATION {owner}")?;
5343                }
5344                Ok(())
5345            }
5346            Statement::CreateSecret {
5347                or_replace,
5348                temporary,
5349                if_not_exists,
5350                name,
5351                storage_specifier,
5352                secret_type,
5353                options,
5354            } => {
5355                write!(
5356                    f,
5357                    "CREATE {or_replace}",
5358                    or_replace = if *or_replace { "OR REPLACE " } else { "" },
5359                )?;
5360                if let Some(t) = temporary {
5361                    write!(f, "{}", if *t { "TEMPORARY " } else { "PERSISTENT " })?;
5362                }
5363                write!(
5364                    f,
5365                    "SECRET {if_not_exists}",
5366                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
5367                )?;
5368                if let Some(n) = name {
5369                    write!(f, "{n} ")?;
5370                };
5371                if let Some(s) = storage_specifier {
5372                    write!(f, "IN {s} ")?;
5373                }
5374                write!(f, "( TYPE {secret_type}",)?;
5375                if !options.is_empty() {
5376                    write!(f, ", {o}", o = display_comma_separated(options))?;
5377                }
5378                write!(f, " )")?;
5379                Ok(())
5380            }
5381            Statement::CreateServer(stmt) => {
5382                write!(f, "{stmt}")
5383            }
5384            Statement::CreatePolicy {
5385                name,
5386                table_name,
5387                policy_type,
5388                command,
5389                to,
5390                using,
5391                with_check,
5392            } => {
5393                write!(f, "CREATE POLICY {name} ON {table_name}")?;
5394
5395                if let Some(policy_type) = policy_type {
5396                    match policy_type {
5397                        CreatePolicyType::Permissive => write!(f, " AS PERMISSIVE")?,
5398                        CreatePolicyType::Restrictive => write!(f, " AS RESTRICTIVE")?,
5399                    }
5400                }
5401
5402                if let Some(command) = command {
5403                    match command {
5404                        CreatePolicyCommand::All => write!(f, " FOR ALL")?,
5405                        CreatePolicyCommand::Select => write!(f, " FOR SELECT")?,
5406                        CreatePolicyCommand::Insert => write!(f, " FOR INSERT")?,
5407                        CreatePolicyCommand::Update => write!(f, " FOR UPDATE")?,
5408                        CreatePolicyCommand::Delete => write!(f, " FOR DELETE")?,
5409                    }
5410                }
5411
5412                if let Some(to) = to {
5413                    write!(f, " TO {}", display_comma_separated(to))?;
5414                }
5415
5416                if let Some(using) = using {
5417                    write!(f, " USING ({using})")?;
5418                }
5419
5420                if let Some(with_check) = with_check {
5421                    write!(f, " WITH CHECK ({with_check})")?;
5422                }
5423
5424                Ok(())
5425            }
5426            Statement::CreateConnector(create_connector) => create_connector.fmt(f),
5427            Statement::AlterTable {
5428                name,
5429                if_exists,
5430                only,
5431                operations,
5432                location,
5433                on_cluster,
5434                iceberg,
5435                end_token: _,
5436            } => {
5437                if *iceberg {
5438                    write!(f, "ALTER ICEBERG TABLE ")?;
5439                } else {
5440                    write!(f, "ALTER TABLE ")?;
5441                }
5442
5443                if *if_exists {
5444                    write!(f, "IF EXISTS ")?;
5445                }
5446                if *only {
5447                    write!(f, "ONLY ")?;
5448                }
5449                write!(f, "{name} ")?;
5450                if let Some(cluster) = on_cluster {
5451                    write!(f, "ON CLUSTER {cluster} ")?;
5452                }
5453                write!(
5454                    f,
5455                    "{operations}",
5456                    operations = display_comma_separated(operations)
5457                )?;
5458                if let Some(loc) = location {
5459                    write!(f, " {loc}")?
5460                }
5461                Ok(())
5462            }
5463            Statement::AlterIndex { name, operation } => {
5464                write!(f, "ALTER INDEX {name} {operation}")
5465            }
5466            Statement::AlterView {
5467                name,
5468                columns,
5469                query,
5470                with_options,
5471            } => {
5472                write!(f, "ALTER VIEW {name}")?;
5473                if !with_options.is_empty() {
5474                    write!(f, " WITH ({})", display_comma_separated(with_options))?;
5475                }
5476                if !columns.is_empty() {
5477                    write!(f, " ({})", display_comma_separated(columns))?;
5478                }
5479                write!(f, " AS {query}")
5480            }
5481            Statement::AlterType(AlterType { name, operation }) => {
5482                write!(f, "ALTER TYPE {name} {operation}")
5483            }
5484            Statement::AlterRole { name, operation } => {
5485                write!(f, "ALTER ROLE {name} {operation}")
5486            }
5487            Statement::AlterPolicy {
5488                name,
5489                table_name,
5490                operation,
5491            } => {
5492                write!(f, "ALTER POLICY {name} ON {table_name}{operation}")
5493            }
5494            Statement::AlterConnector {
5495                name,
5496                properties,
5497                url,
5498                owner,
5499            } => {
5500                write!(f, "ALTER CONNECTOR {name}")?;
5501                if let Some(properties) = properties {
5502                    write!(
5503                        f,
5504                        " SET DCPROPERTIES({})",
5505                        display_comma_separated(properties)
5506                    )?;
5507                }
5508                if let Some(url) = url {
5509                    write!(f, " SET URL '{url}'")?;
5510                }
5511                if let Some(owner) = owner {
5512                    write!(f, " SET OWNER {owner}")?;
5513                }
5514                Ok(())
5515            }
5516            Statement::AlterSession {
5517                set,
5518                session_params,
5519            } => {
5520                write!(
5521                    f,
5522                    "ALTER SESSION {set}",
5523                    set = if *set { "SET" } else { "UNSET" }
5524                )?;
5525                if !session_params.options.is_empty() {
5526                    if *set {
5527                        write!(f, " {session_params}")?;
5528                    } else {
5529                        let options = session_params
5530                            .options
5531                            .iter()
5532                            .map(|p| p.option_name.clone())
5533                            .collect::<Vec<_>>();
5534                        write!(f, " {}", display_separated(&options, ", "))?;
5535                    }
5536                }
5537                Ok(())
5538            }
5539            Statement::Drop {
5540                object_type,
5541                if_exists,
5542                names,
5543                cascade,
5544                restrict,
5545                purge,
5546                temporary,
5547                table,
5548            } => {
5549                write!(
5550                    f,
5551                    "DROP {}{}{} {}{}{}{}",
5552                    if *temporary { "TEMPORARY " } else { "" },
5553                    object_type,
5554                    if *if_exists { " IF EXISTS" } else { "" },
5555                    display_comma_separated(names),
5556                    if *cascade { " CASCADE" } else { "" },
5557                    if *restrict { " RESTRICT" } else { "" },
5558                    if *purge { " PURGE" } else { "" },
5559                )?;
5560                if let Some(table_name) = table.as_ref() {
5561                    write!(f, " ON {table_name}")?;
5562                };
5563                Ok(())
5564            }
5565            Statement::DropFunction {
5566                if_exists,
5567                func_desc,
5568                drop_behavior,
5569            } => {
5570                write!(
5571                    f,
5572                    "DROP FUNCTION{} {}",
5573                    if *if_exists { " IF EXISTS" } else { "" },
5574                    display_comma_separated(func_desc),
5575                )?;
5576                if let Some(op) = drop_behavior {
5577                    write!(f, " {op}")?;
5578                }
5579                Ok(())
5580            }
5581            Statement::DropDomain(DropDomain {
5582                if_exists,
5583                name,
5584                drop_behavior,
5585            }) => {
5586                write!(
5587                    f,
5588                    "DROP DOMAIN{} {name}",
5589                    if *if_exists { " IF EXISTS" } else { "" },
5590                )?;
5591                if let Some(op) = drop_behavior {
5592                    write!(f, " {op}")?;
5593                }
5594                Ok(())
5595            }
5596            Statement::DropProcedure {
5597                if_exists,
5598                proc_desc,
5599                drop_behavior,
5600            } => {
5601                write!(
5602                    f,
5603                    "DROP PROCEDURE{} {}",
5604                    if *if_exists { " IF EXISTS" } else { "" },
5605                    display_comma_separated(proc_desc),
5606                )?;
5607                if let Some(op) = drop_behavior {
5608                    write!(f, " {op}")?;
5609                }
5610                Ok(())
5611            }
5612            Statement::DropSecret {
5613                if_exists,
5614                temporary,
5615                name,
5616                storage_specifier,
5617            } => {
5618                write!(f, "DROP ")?;
5619                if let Some(t) = temporary {
5620                    write!(f, "{}", if *t { "TEMPORARY " } else { "PERSISTENT " })?;
5621                }
5622                write!(
5623                    f,
5624                    "SECRET {if_exists}{name}",
5625                    if_exists = if *if_exists { "IF EXISTS " } else { "" },
5626                )?;
5627                if let Some(s) = storage_specifier {
5628                    write!(f, " FROM {s}")?;
5629                }
5630                Ok(())
5631            }
5632            Statement::DropPolicy {
5633                if_exists,
5634                name,
5635                table_name,
5636                drop_behavior,
5637            } => {
5638                write!(f, "DROP POLICY")?;
5639                if *if_exists {
5640                    write!(f, " IF EXISTS")?;
5641                }
5642                write!(f, " {name} ON {table_name}")?;
5643                if let Some(drop_behavior) = drop_behavior {
5644                    write!(f, " {drop_behavior}")?;
5645                }
5646                Ok(())
5647            }
5648            Statement::DropConnector { if_exists, name } => {
5649                write!(
5650                    f,
5651                    "DROP CONNECTOR {if_exists}{name}",
5652                    if_exists = if *if_exists { "IF EXISTS " } else { "" }
5653                )?;
5654                Ok(())
5655            }
5656            Statement::Discard { object_type } => {
5657                write!(f, "DISCARD {object_type}")?;
5658                Ok(())
5659            }
5660            Self::Set(set) => write!(f, "{set}"),
5661            Statement::ShowVariable { variable } => {
5662                write!(f, "SHOW")?;
5663                if !variable.is_empty() {
5664                    write!(f, " {}", display_separated(variable, " "))?;
5665                }
5666                Ok(())
5667            }
5668            Statement::ShowStatus {
5669                filter,
5670                global,
5671                session,
5672            } => {
5673                write!(f, "SHOW")?;
5674                if *global {
5675                    write!(f, " GLOBAL")?;
5676                }
5677                if *session {
5678                    write!(f, " SESSION")?;
5679                }
5680                write!(f, " STATUS")?;
5681                if filter.is_some() {
5682                    write!(f, " {}", filter.as_ref().unwrap())?;
5683                }
5684                Ok(())
5685            }
5686            Statement::ShowVariables {
5687                filter,
5688                global,
5689                session,
5690            } => {
5691                write!(f, "SHOW")?;
5692                if *global {
5693                    write!(f, " GLOBAL")?;
5694                }
5695                if *session {
5696                    write!(f, " SESSION")?;
5697                }
5698                write!(f, " VARIABLES")?;
5699                if filter.is_some() {
5700                    write!(f, " {}", filter.as_ref().unwrap())?;
5701                }
5702                Ok(())
5703            }
5704            Statement::ShowCreate { obj_type, obj_name } => {
5705                write!(f, "SHOW CREATE {obj_type} {obj_name}",)?;
5706                Ok(())
5707            }
5708            Statement::ShowColumns {
5709                extended,
5710                full,
5711                show_options,
5712            } => {
5713                write!(
5714                    f,
5715                    "SHOW {extended}{full}COLUMNS{show_options}",
5716                    extended = if *extended { "EXTENDED " } else { "" },
5717                    full = if *full { "FULL " } else { "" },
5718                )?;
5719                Ok(())
5720            }
5721            Statement::ShowDatabases {
5722                terse,
5723                history,
5724                show_options,
5725            } => {
5726                write!(
5727                    f,
5728                    "SHOW {terse}DATABASES{history}{show_options}",
5729                    terse = if *terse { "TERSE " } else { "" },
5730                    history = if *history { " HISTORY" } else { "" },
5731                )?;
5732                Ok(())
5733            }
5734            Statement::ShowSchemas {
5735                terse,
5736                history,
5737                show_options,
5738            } => {
5739                write!(
5740                    f,
5741                    "SHOW {terse}SCHEMAS{history}{show_options}",
5742                    terse = if *terse { "TERSE " } else { "" },
5743                    history = if *history { " HISTORY" } else { "" },
5744                )?;
5745                Ok(())
5746            }
5747            Statement::ShowObjects(ShowObjects {
5748                terse,
5749                show_options,
5750            }) => {
5751                write!(
5752                    f,
5753                    "SHOW {terse}OBJECTS{show_options}",
5754                    terse = if *terse { "TERSE " } else { "" },
5755                )?;
5756                Ok(())
5757            }
5758            Statement::ShowTables {
5759                terse,
5760                history,
5761                extended,
5762                full,
5763                external,
5764                show_options,
5765            } => {
5766                write!(
5767                    f,
5768                    "SHOW {terse}{extended}{full}{external}TABLES{history}{show_options}",
5769                    terse = if *terse { "TERSE " } else { "" },
5770                    extended = if *extended { "EXTENDED " } else { "" },
5771                    full = if *full { "FULL " } else { "" },
5772                    external = if *external { "EXTERNAL " } else { "" },
5773                    history = if *history { " HISTORY" } else { "" },
5774                )?;
5775                Ok(())
5776            }
5777            Statement::ShowViews {
5778                terse,
5779                materialized,
5780                show_options,
5781            } => {
5782                write!(
5783                    f,
5784                    "SHOW {terse}{materialized}VIEWS{show_options}",
5785                    terse = if *terse { "TERSE " } else { "" },
5786                    materialized = if *materialized { "MATERIALIZED " } else { "" }
5787                )?;
5788                Ok(())
5789            }
5790            Statement::ShowFunctions { filter } => {
5791                write!(f, "SHOW FUNCTIONS")?;
5792                if let Some(filter) = filter {
5793                    write!(f, " {filter}")?;
5794                }
5795                Ok(())
5796            }
5797            Statement::Use(use_expr) => use_expr.fmt(f),
5798            Statement::ShowCollation { filter } => {
5799                write!(f, "SHOW COLLATION")?;
5800                if let Some(filter) = filter {
5801                    write!(f, " {filter}")?;
5802                }
5803                Ok(())
5804            }
5805            Statement::ShowCharset(show_stm) => show_stm.fmt(f),
5806            Statement::StartTransaction {
5807                modes,
5808                begin: syntax_begin,
5809                transaction,
5810                modifier,
5811                statements,
5812                exception,
5813                has_end_keyword,
5814            } => {
5815                if *syntax_begin {
5816                    if let Some(modifier) = *modifier {
5817                        write!(f, "BEGIN {modifier}")?;
5818                    } else {
5819                        write!(f, "BEGIN")?;
5820                    }
5821                } else {
5822                    write!(f, "START")?;
5823                }
5824                if let Some(transaction) = transaction {
5825                    write!(f, " {transaction}")?;
5826                }
5827                if !modes.is_empty() {
5828                    write!(f, " {}", display_comma_separated(modes))?;
5829                }
5830                if !statements.is_empty() {
5831                    write!(f, " ")?;
5832                    format_statement_list(f, statements)?;
5833                }
5834                if let Some(exception_when) = exception {
5835                    write!(f, " EXCEPTION")?;
5836                    for when in exception_when {
5837                        write!(f, " {when}")?;
5838                    }
5839                }
5840                if *has_end_keyword {
5841                    write!(f, " END")?;
5842                }
5843                Ok(())
5844            }
5845            Statement::Commit {
5846                chain,
5847                end: end_syntax,
5848                modifier,
5849            } => {
5850                if *end_syntax {
5851                    write!(f, "END")?;
5852                    if let Some(modifier) = *modifier {
5853                        write!(f, " {modifier}")?;
5854                    }
5855                    if *chain {
5856                        write!(f, " AND CHAIN")?;
5857                    }
5858                } else {
5859                    write!(f, "COMMIT{}", if *chain { " AND CHAIN" } else { "" })?;
5860                }
5861                Ok(())
5862            }
5863            Statement::Rollback { chain, savepoint } => {
5864                write!(f, "ROLLBACK")?;
5865
5866                if *chain {
5867                    write!(f, " AND CHAIN")?;
5868                }
5869
5870                if let Some(savepoint) = savepoint {
5871                    write!(f, " TO SAVEPOINT {savepoint}")?;
5872                }
5873
5874                Ok(())
5875            }
5876            Statement::CreateSchema {
5877                schema_name,
5878                if_not_exists,
5879                with,
5880                options,
5881                default_collate_spec,
5882                clone,
5883            } => {
5884                write!(
5885                    f,
5886                    "CREATE SCHEMA {if_not_exists}{name}",
5887                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
5888                    name = schema_name
5889                )?;
5890
5891                if let Some(collate) = default_collate_spec {
5892                    write!(f, " DEFAULT COLLATE {collate}")?;
5893                }
5894
5895                if let Some(with) = with {
5896                    write!(f, " WITH ({})", display_comma_separated(with))?;
5897                }
5898
5899                if let Some(options) = options {
5900                    write!(f, " OPTIONS({})", display_comma_separated(options))?;
5901                }
5902
5903                if let Some(clone) = clone {
5904                    write!(f, " CLONE {clone}")?;
5905                }
5906                Ok(())
5907            }
5908            Statement::Assert { condition, message } => {
5909                write!(f, "ASSERT {condition}")?;
5910                if let Some(m) = message {
5911                    write!(f, " AS {m}")?;
5912                }
5913                Ok(())
5914            }
5915            Statement::Grant {
5916                privileges,
5917                objects,
5918                grantees,
5919                with_grant_option,
5920                as_grantor,
5921                granted_by,
5922                current_grants,
5923            } => {
5924                write!(f, "GRANT {privileges} ")?;
5925                if let Some(objects) = objects {
5926                    write!(f, "ON {objects} ")?;
5927                }
5928                write!(f, "TO {}", display_comma_separated(grantees))?;
5929                if *with_grant_option {
5930                    write!(f, " WITH GRANT OPTION")?;
5931                }
5932                if let Some(current_grants) = current_grants {
5933                    write!(f, " {current_grants}")?;
5934                }
5935                if let Some(grantor) = as_grantor {
5936                    write!(f, " AS {grantor}")?;
5937                }
5938                if let Some(grantor) = granted_by {
5939                    write!(f, " GRANTED BY {grantor}")?;
5940                }
5941                Ok(())
5942            }
5943            Statement::Deny(s) => write!(f, "{s}"),
5944            Statement::Revoke {
5945                privileges,
5946                objects,
5947                grantees,
5948                granted_by,
5949                cascade,
5950            } => {
5951                write!(f, "REVOKE {privileges} ")?;
5952                if let Some(objects) = objects {
5953                    write!(f, "ON {objects} ")?;
5954                }
5955                write!(f, "FROM {}", display_comma_separated(grantees))?;
5956                if let Some(grantor) = granted_by {
5957                    write!(f, " GRANTED BY {grantor}")?;
5958                }
5959                if let Some(cascade) = cascade {
5960                    write!(f, " {cascade}")?;
5961                }
5962                Ok(())
5963            }
5964            Statement::Deallocate { name, prepare } => write!(
5965                f,
5966                "DEALLOCATE {prepare}{name}",
5967                prepare = if *prepare { "PREPARE " } else { "" },
5968                name = name,
5969            ),
5970            Statement::Execute {
5971                name,
5972                parameters,
5973                has_parentheses,
5974                immediate,
5975                into,
5976                using,
5977                output,
5978                default,
5979            } => {
5980                let (open, close) = if *has_parentheses {
5981                    ("(", ")")
5982                } else {
5983                    (if parameters.is_empty() { "" } else { " " }, "")
5984                };
5985                write!(f, "EXECUTE")?;
5986                if *immediate {
5987                    write!(f, " IMMEDIATE")?;
5988                }
5989                if let Some(name) = name {
5990                    write!(f, " {name}")?;
5991                }
5992                write!(f, "{open}{}{close}", display_comma_separated(parameters),)?;
5993                if !into.is_empty() {
5994                    write!(f, " INTO {}", display_comma_separated(into))?;
5995                }
5996                if !using.is_empty() {
5997                    write!(f, " USING {}", display_comma_separated(using))?;
5998                };
5999                if *output {
6000                    write!(f, " OUTPUT")?;
6001                }
6002                if *default {
6003                    write!(f, " DEFAULT")?;
6004                }
6005                Ok(())
6006            }
6007            Statement::Prepare {
6008                name,
6009                data_types,
6010                statement,
6011            } => {
6012                write!(f, "PREPARE {name} ")?;
6013                if !data_types.is_empty() {
6014                    write!(f, "({}) ", display_comma_separated(data_types))?;
6015                }
6016                write!(f, "AS {statement}")
6017            }
6018            Statement::Comment {
6019                object_type,
6020                object_name,
6021                comment,
6022                if_exists,
6023            } => {
6024                write!(f, "COMMENT ")?;
6025                if *if_exists {
6026                    write!(f, "IF EXISTS ")?
6027                };
6028                write!(f, "ON {object_type} {object_name} IS ")?;
6029                if let Some(c) = comment {
6030                    write!(f, "'{c}'")
6031                } else {
6032                    write!(f, "NULL")
6033                }
6034            }
6035            Statement::Savepoint { name } => {
6036                write!(f, "SAVEPOINT ")?;
6037                write!(f, "{name}")
6038            }
6039            Statement::ReleaseSavepoint { name } => {
6040                write!(f, "RELEASE SAVEPOINT {name}")
6041            }
6042            Statement::Merge {
6043                into,
6044                table,
6045                source,
6046                on,
6047                clauses,
6048                output,
6049            } => {
6050                write!(
6051                    f,
6052                    "MERGE{int} {table} USING {source} ",
6053                    int = if *into { " INTO" } else { "" }
6054                )?;
6055                write!(f, "ON {on} ")?;
6056                write!(f, "{}", display_separated(clauses, " "))?;
6057                if let Some(output) = output {
6058                    write!(f, " {output}")?;
6059                }
6060                Ok(())
6061            }
6062            Statement::Cache {
6063                table_name,
6064                table_flag,
6065                has_as,
6066                options,
6067                query,
6068            } => {
6069                if let Some(table_flag) = table_flag {
6070                    write!(f, "CACHE {table_flag} TABLE {table_name}")?;
6071                } else {
6072                    write!(f, "CACHE TABLE {table_name}")?;
6073                }
6074
6075                if !options.is_empty() {
6076                    write!(f, " OPTIONS({})", display_comma_separated(options))?;
6077                }
6078
6079                match (*has_as, query) {
6080                    (true, Some(query)) => write!(f, " AS {query}"),
6081                    (true, None) => f.write_str(" AS"),
6082                    (false, Some(query)) => write!(f, " {query}"),
6083                    (false, None) => Ok(()),
6084                }
6085            }
6086            Statement::UNCache {
6087                table_name,
6088                if_exists,
6089            } => {
6090                if *if_exists {
6091                    write!(f, "UNCACHE TABLE IF EXISTS {table_name}")
6092                } else {
6093                    write!(f, "UNCACHE TABLE {table_name}")
6094                }
6095            }
6096            Statement::CreateSequence {
6097                temporary,
6098                if_not_exists,
6099                name,
6100                data_type,
6101                sequence_options,
6102                owned_by,
6103            } => {
6104                let as_type: String = if let Some(dt) = data_type.as_ref() {
6105                    //Cannot use format!(" AS {}", dt), due to format! is not available in --target thumbv6m-none-eabi
6106                    // " AS ".to_owned() + &dt.to_string()
6107                    [" AS ", &dt.to_string()].concat()
6108                } else {
6109                    "".to_string()
6110                };
6111                write!(
6112                    f,
6113                    "CREATE {temporary}SEQUENCE {if_not_exists}{name}{as_type}",
6114                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
6115                    temporary = if *temporary { "TEMPORARY " } else { "" },
6116                    name = name,
6117                    as_type = as_type
6118                )?;
6119                for sequence_option in sequence_options {
6120                    write!(f, "{sequence_option}")?;
6121                }
6122                if let Some(ob) = owned_by.as_ref() {
6123                    write!(f, " OWNED BY {ob}")?;
6124                }
6125                write!(f, "")
6126            }
6127            Statement::CreateStage {
6128                or_replace,
6129                temporary,
6130                if_not_exists,
6131                name,
6132                stage_params,
6133                directory_table_params,
6134                file_format,
6135                copy_options,
6136                comment,
6137                ..
6138            } => {
6139                write!(
6140                    f,
6141                    "CREATE {or_replace}{temp}STAGE {if_not_exists}{name}{stage_params}",
6142                    temp = if *temporary { "TEMPORARY " } else { "" },
6143                    or_replace = if *or_replace { "OR REPLACE " } else { "" },
6144                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
6145                )?;
6146                if !directory_table_params.options.is_empty() {
6147                    write!(f, " DIRECTORY=({directory_table_params})")?;
6148                }
6149                if !file_format.options.is_empty() {
6150                    write!(f, " FILE_FORMAT=({file_format})")?;
6151                }
6152                if !copy_options.options.is_empty() {
6153                    write!(f, " COPY_OPTIONS=({copy_options})")?;
6154                }
6155                if comment.is_some() {
6156                    write!(f, " COMMENT='{}'", comment.as_ref().unwrap())?;
6157                }
6158                Ok(())
6159            }
6160            Statement::CopyIntoSnowflake {
6161                kind,
6162                into,
6163                into_columns,
6164                from_obj,
6165                from_obj_alias,
6166                stage_params,
6167                from_transformations,
6168                from_query,
6169                files,
6170                pattern,
6171                file_format,
6172                copy_options,
6173                validation_mode,
6174                partition,
6175            } => {
6176                write!(f, "COPY INTO {into}")?;
6177                if let Some(into_columns) = into_columns {
6178                    write!(f, " ({})", display_comma_separated(into_columns))?;
6179                }
6180                if let Some(from_transformations) = from_transformations {
6181                    // Data load with transformation
6182                    if let Some(from_stage) = from_obj {
6183                        write!(
6184                            f,
6185                            " FROM (SELECT {} FROM {}{}",
6186                            display_separated(from_transformations, ", "),
6187                            from_stage,
6188                            stage_params
6189                        )?;
6190                    }
6191                    if let Some(from_obj_alias) = from_obj_alias {
6192                        write!(f, " AS {from_obj_alias}")?;
6193                    }
6194                    write!(f, ")")?;
6195                } else if let Some(from_obj) = from_obj {
6196                    // Standard data load
6197                    write!(f, " FROM {from_obj}{stage_params}")?;
6198                    if let Some(from_obj_alias) = from_obj_alias {
6199                        write!(f, " AS {from_obj_alias}")?;
6200                    }
6201                } else if let Some(from_query) = from_query {
6202                    // Data unload from query
6203                    write!(f, " FROM ({from_query})")?;
6204                }
6205
6206                if let Some(files) = files {
6207                    write!(f, " FILES = ('{}')", display_separated(files, "', '"))?;
6208                }
6209                if let Some(pattern) = pattern {
6210                    write!(f, " PATTERN = '{pattern}'")?;
6211                }
6212                if let Some(partition) = partition {
6213                    write!(f, " PARTITION BY {partition}")?;
6214                }
6215                if !file_format.options.is_empty() {
6216                    write!(f, " FILE_FORMAT=({file_format})")?;
6217                }
6218                if !copy_options.options.is_empty() {
6219                    match kind {
6220                        CopyIntoSnowflakeKind::Table => {
6221                            write!(f, " COPY_OPTIONS=({copy_options})")?
6222                        }
6223                        CopyIntoSnowflakeKind::Location => write!(f, " {copy_options}")?,
6224                    }
6225                }
6226                if let Some(validation_mode) = validation_mode {
6227                    write!(f, " VALIDATION_MODE = {validation_mode}")?;
6228                }
6229                Ok(())
6230            }
6231            Statement::CreateType {
6232                name,
6233                representation,
6234            } => {
6235                write!(f, "CREATE TYPE {name} AS {representation}")
6236            }
6237            Statement::Pragma { name, value, is_eq } => {
6238                write!(f, "PRAGMA {name}")?;
6239                if value.is_some() {
6240                    let val = value.as_ref().unwrap();
6241                    if *is_eq {
6242                        write!(f, " = {val}")?;
6243                    } else {
6244                        write!(f, "({val})")?;
6245                    }
6246                }
6247                Ok(())
6248            }
6249            Statement::LockTables { tables } => {
6250                write!(f, "LOCK TABLES {}", display_comma_separated(tables))
6251            }
6252            Statement::UnlockTables => {
6253                write!(f, "UNLOCK TABLES")
6254            }
6255            Statement::Unload {
6256                query,
6257                query_text,
6258                to,
6259                auth,
6260                with,
6261                options,
6262            } => {
6263                write!(f, "UNLOAD(")?;
6264                if let Some(query) = query {
6265                    write!(f, "{query}")?;
6266                }
6267                if let Some(query_text) = query_text {
6268                    write!(f, "'{query_text}'")?;
6269                }
6270                write!(f, ") TO {to}")?;
6271                if let Some(auth) = auth {
6272                    write!(f, " IAM_ROLE {auth}")?;
6273                }
6274                if !with.is_empty() {
6275                    write!(f, " WITH ({})", display_comma_separated(with))?;
6276                }
6277                if !options.is_empty() {
6278                    write!(f, " {}", display_separated(options, " "))?;
6279                }
6280                Ok(())
6281            }
6282            Statement::OptimizeTable {
6283                name,
6284                on_cluster,
6285                partition,
6286                include_final,
6287                deduplicate,
6288            } => {
6289                write!(f, "OPTIMIZE TABLE {name}")?;
6290                if let Some(on_cluster) = on_cluster {
6291                    write!(f, " ON CLUSTER {on_cluster}")?;
6292                }
6293                if let Some(partition) = partition {
6294                    write!(f, " {partition}")?;
6295                }
6296                if *include_final {
6297                    write!(f, " FINAL")?;
6298                }
6299                if let Some(deduplicate) = deduplicate {
6300                    write!(f, " {deduplicate}")?;
6301                }
6302                Ok(())
6303            }
6304            Statement::LISTEN { channel } => {
6305                write!(f, "LISTEN {channel}")?;
6306                Ok(())
6307            }
6308            Statement::UNLISTEN { channel } => {
6309                write!(f, "UNLISTEN {channel}")?;
6310                Ok(())
6311            }
6312            Statement::NOTIFY { channel, payload } => {
6313                write!(f, "NOTIFY {channel}")?;
6314                if let Some(payload) = payload {
6315                    write!(f, ", '{payload}'")?;
6316                }
6317                Ok(())
6318            }
6319            Statement::RenameTable(rename_tables) => {
6320                write!(f, "RENAME TABLE {}", display_comma_separated(rename_tables))
6321            }
6322            Statement::RaisError {
6323                message,
6324                severity,
6325                state,
6326                arguments,
6327                options,
6328            } => {
6329                write!(f, "RAISERROR({message}, {severity}, {state}")?;
6330                if !arguments.is_empty() {
6331                    write!(f, ", {}", display_comma_separated(arguments))?;
6332                }
6333                write!(f, ")")?;
6334                if !options.is_empty() {
6335                    write!(f, " WITH {}", display_comma_separated(options))?;
6336                }
6337                Ok(())
6338            }
6339            Statement::Print(s) => write!(f, "{s}"),
6340            Statement::Return(r) => write!(f, "{r}"),
6341            Statement::List(command) => write!(f, "LIST {command}"),
6342            Statement::Remove(command) => write!(f, "REMOVE {command}"),
6343            Statement::ExportData(e) => write!(f, "{e}"),
6344            Statement::CreateUser(s) => write!(f, "{s}"),
6345            Statement::AlterSchema(s) => write!(f, "{s}"),
6346            Statement::Vacuum(s) => write!(f, "{s}"),
6347        }
6348    }
6349}
6350
6351/// Can use to describe options in create sequence or table column type identity
6352/// ```sql
6353/// [ INCREMENT [ BY ] increment ]
6354///     [ MINVALUE minvalue | NO MINVALUE ] [ MAXVALUE maxvalue | NO MAXVALUE ]
6355///     [ START [ WITH ] start ] [ CACHE cache ] [ [ NO ] CYCLE ]
6356/// ```
6357#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6358#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6359#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6360pub enum SequenceOptions {
6361    IncrementBy(Expr, bool),
6362    MinValue(Option<Expr>),
6363    MaxValue(Option<Expr>),
6364    StartWith(Expr, bool),
6365    Cache(Expr),
6366    Cycle(bool),
6367}
6368
6369impl fmt::Display for SequenceOptions {
6370    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6371        match self {
6372            SequenceOptions::IncrementBy(increment, by) => {
6373                write!(
6374                    f,
6375                    " INCREMENT{by} {increment}",
6376                    by = if *by { " BY" } else { "" },
6377                    increment = increment
6378                )
6379            }
6380            SequenceOptions::MinValue(Some(expr)) => {
6381                write!(f, " MINVALUE {expr}")
6382            }
6383            SequenceOptions::MinValue(None) => {
6384                write!(f, " NO MINVALUE")
6385            }
6386            SequenceOptions::MaxValue(Some(expr)) => {
6387                write!(f, " MAXVALUE {expr}")
6388            }
6389            SequenceOptions::MaxValue(None) => {
6390                write!(f, " NO MAXVALUE")
6391            }
6392            SequenceOptions::StartWith(start, with) => {
6393                write!(
6394                    f,
6395                    " START{with} {start}",
6396                    with = if *with { " WITH" } else { "" },
6397                    start = start
6398                )
6399            }
6400            SequenceOptions::Cache(cache) => {
6401                write!(f, " CACHE {}", *cache)
6402            }
6403            SequenceOptions::Cycle(no) => {
6404                write!(f, " {}CYCLE", if *no { "NO " } else { "" })
6405            }
6406        }
6407    }
6408}
6409
6410/// Assignment for a `SET` statement (name [=|TO] value)
6411#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6412#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6413#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6414pub struct SetAssignment {
6415    pub scope: Option<ContextModifier>,
6416    pub name: ObjectName,
6417    pub value: Expr,
6418}
6419
6420impl fmt::Display for SetAssignment {
6421    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6422        write!(
6423            f,
6424            "{}{} = {}",
6425            self.scope.map(|s| format!("{s}")).unwrap_or_default(),
6426            self.name,
6427            self.value
6428        )
6429    }
6430}
6431
6432/// Target of a `TRUNCATE TABLE` command
6433///
6434/// Note this is its own struct because `visit_relation` requires an `ObjectName` (not a `Vec<ObjectName>`)
6435#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6436#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6437#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6438pub struct TruncateTableTarget {
6439    /// name of the table being truncated
6440    #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
6441    pub name: ObjectName,
6442    /// Postgres-specific option
6443    /// [ TRUNCATE TABLE ONLY ]
6444    /// <https://www.postgresql.org/docs/current/sql-truncate.html>
6445    pub only: bool,
6446}
6447
6448impl fmt::Display for TruncateTableTarget {
6449    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6450        if self.only {
6451            write!(f, "ONLY ")?;
6452        };
6453        write!(f, "{}", self.name)
6454    }
6455}
6456
6457/// PostgreSQL identity option for TRUNCATE table
6458/// [ RESTART IDENTITY | CONTINUE IDENTITY ]
6459#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6460#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6461#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6462pub enum TruncateIdentityOption {
6463    Restart,
6464    Continue,
6465}
6466
6467/// Cascade/restrict option for Postgres TRUNCATE table, MySQL GRANT/REVOKE, etc.
6468/// [ CASCADE | RESTRICT ]
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 enum CascadeOption {
6473    Cascade,
6474    Restrict,
6475}
6476
6477impl Display for CascadeOption {
6478    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6479        match self {
6480            CascadeOption::Cascade => write!(f, "CASCADE"),
6481            CascadeOption::Restrict => write!(f, "RESTRICT"),
6482        }
6483    }
6484}
6485
6486/// Transaction started with [ TRANSACTION | WORK ]
6487#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6488#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6489#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6490pub enum BeginTransactionKind {
6491    Transaction,
6492    Work,
6493}
6494
6495impl Display for BeginTransactionKind {
6496    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6497        match self {
6498            BeginTransactionKind::Transaction => write!(f, "TRANSACTION"),
6499            BeginTransactionKind::Work => write!(f, "WORK"),
6500        }
6501    }
6502}
6503
6504/// Can use to describe options in  create sequence or table column type identity
6505/// [ MINVALUE minvalue | NO MINVALUE ] [ MAXVALUE maxvalue | NO MAXVALUE ]
6506#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6507#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6508#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6509pub enum MinMaxValue {
6510    // clause is not specified
6511    Empty,
6512    // NO MINVALUE/NO MAXVALUE
6513    None,
6514    // MINVALUE <expr> / MAXVALUE <expr>
6515    Some(Expr),
6516}
6517
6518#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6519#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6520#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6521#[non_exhaustive]
6522pub enum OnInsert {
6523    /// ON DUPLICATE KEY UPDATE (MySQL when the key already exists, then execute an update instead)
6524    DuplicateKeyUpdate(Vec<Assignment>),
6525    /// ON CONFLICT is a PostgreSQL and Sqlite extension
6526    OnConflict(OnConflict),
6527}
6528
6529#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6530#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6531#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6532pub struct InsertAliases {
6533    pub row_alias: ObjectName,
6534    pub col_aliases: Option<Vec<Ident>>,
6535}
6536
6537#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6538#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6539#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6540pub struct OnConflict {
6541    pub conflict_target: Option<ConflictTarget>,
6542    pub action: OnConflictAction,
6543}
6544#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6545#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6546#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6547pub enum ConflictTarget {
6548    Columns(Vec<Ident>),
6549    OnConstraint(ObjectName),
6550}
6551#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6552#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6553#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6554pub enum OnConflictAction {
6555    DoNothing,
6556    DoUpdate(DoUpdate),
6557}
6558
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 DoUpdate {
6563    /// Column assignments
6564    pub assignments: Vec<Assignment>,
6565    /// WHERE
6566    pub selection: Option<Expr>,
6567}
6568
6569impl fmt::Display for OnInsert {
6570    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6571        match self {
6572            Self::DuplicateKeyUpdate(expr) => write!(
6573                f,
6574                " ON DUPLICATE KEY UPDATE {}",
6575                display_comma_separated(expr)
6576            ),
6577            Self::OnConflict(o) => write!(f, "{o}"),
6578        }
6579    }
6580}
6581impl fmt::Display for OnConflict {
6582    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6583        write!(f, " ON CONFLICT")?;
6584        if let Some(target) = &self.conflict_target {
6585            write!(f, "{target}")?;
6586        }
6587        write!(f, " {}", self.action)
6588    }
6589}
6590impl fmt::Display for ConflictTarget {
6591    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6592        match self {
6593            ConflictTarget::Columns(cols) => write!(f, "({})", display_comma_separated(cols)),
6594            ConflictTarget::OnConstraint(name) => write!(f, " ON CONSTRAINT {name}"),
6595        }
6596    }
6597}
6598impl fmt::Display for OnConflictAction {
6599    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6600        match self {
6601            Self::DoNothing => write!(f, "DO NOTHING"),
6602            Self::DoUpdate(do_update) => {
6603                write!(f, "DO UPDATE")?;
6604                if !do_update.assignments.is_empty() {
6605                    write!(
6606                        f,
6607                        " SET {}",
6608                        display_comma_separated(&do_update.assignments)
6609                    )?;
6610                }
6611                if let Some(selection) = &do_update.selection {
6612                    write!(f, " WHERE {selection}")?;
6613                }
6614                Ok(())
6615            }
6616        }
6617    }
6618}
6619
6620/// Privileges granted in a GRANT statement or revoked in a REVOKE statement.
6621#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6622#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6623#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6624pub enum Privileges {
6625    /// All privileges applicable to the object type
6626    All {
6627        /// Optional keyword from the spec, ignored in practice
6628        with_privileges_keyword: bool,
6629    },
6630    /// Specific privileges (e.g. `SELECT`, `INSERT`)
6631    Actions(Vec<Action>),
6632}
6633
6634impl fmt::Display for Privileges {
6635    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6636        match self {
6637            Privileges::All {
6638                with_privileges_keyword,
6639            } => {
6640                write!(
6641                    f,
6642                    "ALL{}",
6643                    if *with_privileges_keyword {
6644                        " PRIVILEGES"
6645                    } else {
6646                        ""
6647                    }
6648                )
6649            }
6650            Privileges::Actions(actions) => {
6651                write!(f, "{}", display_comma_separated(actions))
6652            }
6653        }
6654    }
6655}
6656
6657/// Specific direction for FETCH statement
6658#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6659#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6660#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6661pub enum FetchDirection {
6662    Count { limit: Value },
6663    Next,
6664    Prior,
6665    First,
6666    Last,
6667    Absolute { limit: Value },
6668    Relative { limit: Value },
6669    All,
6670    // FORWARD
6671    // FORWARD count
6672    Forward { limit: Option<Value> },
6673    ForwardAll,
6674    // BACKWARD
6675    // BACKWARD count
6676    Backward { limit: Option<Value> },
6677    BackwardAll,
6678}
6679
6680impl fmt::Display for FetchDirection {
6681    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6682        match self {
6683            FetchDirection::Count { limit } => f.write_str(&limit.to_string())?,
6684            FetchDirection::Next => f.write_str("NEXT")?,
6685            FetchDirection::Prior => f.write_str("PRIOR")?,
6686            FetchDirection::First => f.write_str("FIRST")?,
6687            FetchDirection::Last => f.write_str("LAST")?,
6688            FetchDirection::Absolute { limit } => {
6689                f.write_str("ABSOLUTE ")?;
6690                f.write_str(&limit.to_string())?;
6691            }
6692            FetchDirection::Relative { limit } => {
6693                f.write_str("RELATIVE ")?;
6694                f.write_str(&limit.to_string())?;
6695            }
6696            FetchDirection::All => f.write_str("ALL")?,
6697            FetchDirection::Forward { limit } => {
6698                f.write_str("FORWARD")?;
6699
6700                if let Some(l) = limit {
6701                    f.write_str(" ")?;
6702                    f.write_str(&l.to_string())?;
6703                }
6704            }
6705            FetchDirection::ForwardAll => f.write_str("FORWARD ALL")?,
6706            FetchDirection::Backward { limit } => {
6707                f.write_str("BACKWARD")?;
6708
6709                if let Some(l) = limit {
6710                    f.write_str(" ")?;
6711                    f.write_str(&l.to_string())?;
6712                }
6713            }
6714            FetchDirection::BackwardAll => f.write_str("BACKWARD ALL")?,
6715        };
6716
6717        Ok(())
6718    }
6719}
6720
6721/// The "position" for a FETCH statement.
6722///
6723/// [MsSql](https://learn.microsoft.com/en-us/sql/t-sql/language-elements/fetch-transact-sql)
6724#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6725#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6726#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6727pub enum FetchPosition {
6728    From,
6729    In,
6730}
6731
6732impl fmt::Display for FetchPosition {
6733    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6734        match self {
6735            FetchPosition::From => f.write_str("FROM")?,
6736            FetchPosition::In => f.write_str("IN")?,
6737        };
6738
6739        Ok(())
6740    }
6741}
6742
6743/// A privilege on a database object (table, sequence, etc.).
6744#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6745#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6746#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6747pub enum Action {
6748    AddSearchOptimization,
6749    Apply {
6750        apply_type: ActionApplyType,
6751    },
6752    ApplyBudget,
6753    AttachListing,
6754    AttachPolicy,
6755    Audit,
6756    BindServiceEndpoint,
6757    Connect,
6758    Create {
6759        obj_type: Option<ActionCreateObjectType>,
6760    },
6761    DatabaseRole {
6762        role: ObjectName,
6763    },
6764    Delete,
6765    Drop,
6766    EvolveSchema,
6767    Exec {
6768        obj_type: Option<ActionExecuteObjectType>,
6769    },
6770    Execute {
6771        obj_type: Option<ActionExecuteObjectType>,
6772    },
6773    Failover,
6774    ImportedPrivileges,
6775    ImportShare,
6776    Insert {
6777        columns: Option<Vec<Ident>>,
6778    },
6779    Manage {
6780        manage_type: ActionManageType,
6781    },
6782    ManageReleases,
6783    ManageVersions,
6784    Modify {
6785        modify_type: Option<ActionModifyType>,
6786    },
6787    Monitor {
6788        monitor_type: Option<ActionMonitorType>,
6789    },
6790    Operate,
6791    OverrideShareRestrictions,
6792    Ownership,
6793    PurchaseDataExchangeListing,
6794    Read,
6795    ReadSession,
6796    References {
6797        columns: Option<Vec<Ident>>,
6798    },
6799    Replicate,
6800    ResolveAll,
6801    Role {
6802        role: ObjectName,
6803    },
6804    Select {
6805        columns: Option<Vec<Ident>>,
6806    },
6807    Temporary,
6808    Trigger,
6809    Truncate,
6810    Update {
6811        columns: Option<Vec<Ident>>,
6812    },
6813    Usage,
6814}
6815
6816impl fmt::Display for Action {
6817    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6818        match self {
6819            Action::AddSearchOptimization => f.write_str("ADD SEARCH OPTIMIZATION")?,
6820            Action::Apply { apply_type } => write!(f, "APPLY {apply_type}")?,
6821            Action::ApplyBudget => f.write_str("APPLYBUDGET")?,
6822            Action::AttachListing => f.write_str("ATTACH LISTING")?,
6823            Action::AttachPolicy => f.write_str("ATTACH POLICY")?,
6824            Action::Audit => f.write_str("AUDIT")?,
6825            Action::BindServiceEndpoint => f.write_str("BIND SERVICE ENDPOINT")?,
6826            Action::Connect => f.write_str("CONNECT")?,
6827            Action::Create { obj_type } => {
6828                f.write_str("CREATE")?;
6829                if let Some(obj_type) = obj_type {
6830                    write!(f, " {obj_type}")?
6831                }
6832            }
6833            Action::DatabaseRole { role } => write!(f, "DATABASE ROLE {role}")?,
6834            Action::Delete => f.write_str("DELETE")?,
6835            Action::Drop => f.write_str("DROP")?,
6836            Action::EvolveSchema => f.write_str("EVOLVE SCHEMA")?,
6837            Action::Exec { obj_type } => {
6838                f.write_str("EXEC")?;
6839                if let Some(obj_type) = obj_type {
6840                    write!(f, " {obj_type}")?
6841                }
6842            }
6843            Action::Execute { obj_type } => {
6844                f.write_str("EXECUTE")?;
6845                if let Some(obj_type) = obj_type {
6846                    write!(f, " {obj_type}")?
6847                }
6848            }
6849            Action::Failover => f.write_str("FAILOVER")?,
6850            Action::ImportedPrivileges => f.write_str("IMPORTED PRIVILEGES")?,
6851            Action::ImportShare => f.write_str("IMPORT SHARE")?,
6852            Action::Insert { .. } => f.write_str("INSERT")?,
6853            Action::Manage { manage_type } => write!(f, "MANAGE {manage_type}")?,
6854            Action::ManageReleases => f.write_str("MANAGE RELEASES")?,
6855            Action::ManageVersions => f.write_str("MANAGE VERSIONS")?,
6856            Action::Modify { modify_type } => {
6857                write!(f, "MODIFY")?;
6858                if let Some(modify_type) = modify_type {
6859                    write!(f, " {modify_type}")?;
6860                }
6861            }
6862            Action::Monitor { monitor_type } => {
6863                write!(f, "MONITOR")?;
6864                if let Some(monitor_type) = monitor_type {
6865                    write!(f, " {monitor_type}")?
6866                }
6867            }
6868            Action::Operate => f.write_str("OPERATE")?,
6869            Action::OverrideShareRestrictions => f.write_str("OVERRIDE SHARE RESTRICTIONS")?,
6870            Action::Ownership => f.write_str("OWNERSHIP")?,
6871            Action::PurchaseDataExchangeListing => f.write_str("PURCHASE DATA EXCHANGE LISTING")?,
6872            Action::Read => f.write_str("READ")?,
6873            Action::ReadSession => f.write_str("READ SESSION")?,
6874            Action::References { .. } => f.write_str("REFERENCES")?,
6875            Action::Replicate => f.write_str("REPLICATE")?,
6876            Action::ResolveAll => f.write_str("RESOLVE ALL")?,
6877            Action::Role { role } => write!(f, "ROLE {role}")?,
6878            Action::Select { .. } => f.write_str("SELECT")?,
6879            Action::Temporary => f.write_str("TEMPORARY")?,
6880            Action::Trigger => f.write_str("TRIGGER")?,
6881            Action::Truncate => f.write_str("TRUNCATE")?,
6882            Action::Update { .. } => f.write_str("UPDATE")?,
6883            Action::Usage => f.write_str("USAGE")?,
6884        };
6885        match self {
6886            Action::Insert { columns }
6887            | Action::References { columns }
6888            | Action::Select { columns }
6889            | Action::Update { columns } => {
6890                if let Some(columns) = columns {
6891                    write!(f, " ({})", display_comma_separated(columns))?;
6892                }
6893            }
6894            _ => (),
6895        };
6896        Ok(())
6897    }
6898}
6899
6900#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6901#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6902#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6903/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
6904/// under `globalPrivileges` in the `CREATE` privilege.
6905pub enum ActionCreateObjectType {
6906    Account,
6907    Application,
6908    ApplicationPackage,
6909    ComputePool,
6910    DataExchangeListing,
6911    Database,
6912    ExternalVolume,
6913    FailoverGroup,
6914    Integration,
6915    NetworkPolicy,
6916    OrganiationListing,
6917    ReplicationGroup,
6918    Role,
6919    Schema,
6920    Share,
6921    User,
6922    Warehouse,
6923}
6924
6925impl fmt::Display for ActionCreateObjectType {
6926    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6927        match self {
6928            ActionCreateObjectType::Account => write!(f, "ACCOUNT"),
6929            ActionCreateObjectType::Application => write!(f, "APPLICATION"),
6930            ActionCreateObjectType::ApplicationPackage => write!(f, "APPLICATION PACKAGE"),
6931            ActionCreateObjectType::ComputePool => write!(f, "COMPUTE POOL"),
6932            ActionCreateObjectType::DataExchangeListing => write!(f, "DATA EXCHANGE LISTING"),
6933            ActionCreateObjectType::Database => write!(f, "DATABASE"),
6934            ActionCreateObjectType::ExternalVolume => write!(f, "EXTERNAL VOLUME"),
6935            ActionCreateObjectType::FailoverGroup => write!(f, "FAILOVER GROUP"),
6936            ActionCreateObjectType::Integration => write!(f, "INTEGRATION"),
6937            ActionCreateObjectType::NetworkPolicy => write!(f, "NETWORK POLICY"),
6938            ActionCreateObjectType::OrganiationListing => write!(f, "ORGANIZATION LISTING"),
6939            ActionCreateObjectType::ReplicationGroup => write!(f, "REPLICATION GROUP"),
6940            ActionCreateObjectType::Role => write!(f, "ROLE"),
6941            ActionCreateObjectType::Schema => write!(f, "SCHEMA"),
6942            ActionCreateObjectType::Share => write!(f, "SHARE"),
6943            ActionCreateObjectType::User => write!(f, "USER"),
6944            ActionCreateObjectType::Warehouse => write!(f, "WAREHOUSE"),
6945        }
6946    }
6947}
6948
6949#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6950#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6951#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6952/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
6953/// under `globalPrivileges` in the `APPLY` privilege.
6954pub enum ActionApplyType {
6955    AggregationPolicy,
6956    AuthenticationPolicy,
6957    JoinPolicy,
6958    MaskingPolicy,
6959    PackagesPolicy,
6960    PasswordPolicy,
6961    ProjectionPolicy,
6962    RowAccessPolicy,
6963    SessionPolicy,
6964    Tag,
6965}
6966
6967impl fmt::Display for ActionApplyType {
6968    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6969        match self {
6970            ActionApplyType::AggregationPolicy => write!(f, "AGGREGATION POLICY"),
6971            ActionApplyType::AuthenticationPolicy => write!(f, "AUTHENTICATION POLICY"),
6972            ActionApplyType::JoinPolicy => write!(f, "JOIN POLICY"),
6973            ActionApplyType::MaskingPolicy => write!(f, "MASKING POLICY"),
6974            ActionApplyType::PackagesPolicy => write!(f, "PACKAGES POLICY"),
6975            ActionApplyType::PasswordPolicy => write!(f, "PASSWORD POLICY"),
6976            ActionApplyType::ProjectionPolicy => write!(f, "PROJECTION POLICY"),
6977            ActionApplyType::RowAccessPolicy => write!(f, "ROW ACCESS POLICY"),
6978            ActionApplyType::SessionPolicy => write!(f, "SESSION POLICY"),
6979            ActionApplyType::Tag => write!(f, "TAG"),
6980        }
6981    }
6982}
6983
6984#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6985#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6986#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6987/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
6988/// under `globalPrivileges` in the `EXECUTE` privilege.
6989pub enum ActionExecuteObjectType {
6990    Alert,
6991    DataMetricFunction,
6992    ManagedAlert,
6993    ManagedTask,
6994    Task,
6995}
6996
6997impl fmt::Display for ActionExecuteObjectType {
6998    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6999        match self {
7000            ActionExecuteObjectType::Alert => write!(f, "ALERT"),
7001            ActionExecuteObjectType::DataMetricFunction => write!(f, "DATA METRIC FUNCTION"),
7002            ActionExecuteObjectType::ManagedAlert => write!(f, "MANAGED ALERT"),
7003            ActionExecuteObjectType::ManagedTask => write!(f, "MANAGED TASK"),
7004            ActionExecuteObjectType::Task => write!(f, "TASK"),
7005        }
7006    }
7007}
7008
7009#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7010#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7011#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7012/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
7013/// under `globalPrivileges` in the `MANAGE` privilege.
7014pub enum ActionManageType {
7015    AccountSupportCases,
7016    EventSharing,
7017    Grants,
7018    ListingAutoFulfillment,
7019    OrganizationSupportCases,
7020    UserSupportCases,
7021    Warehouses,
7022}
7023
7024impl fmt::Display for ActionManageType {
7025    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7026        match self {
7027            ActionManageType::AccountSupportCases => write!(f, "ACCOUNT SUPPORT CASES"),
7028            ActionManageType::EventSharing => write!(f, "EVENT SHARING"),
7029            ActionManageType::Grants => write!(f, "GRANTS"),
7030            ActionManageType::ListingAutoFulfillment => write!(f, "LISTING AUTO FULFILLMENT"),
7031            ActionManageType::OrganizationSupportCases => write!(f, "ORGANIZATION SUPPORT CASES"),
7032            ActionManageType::UserSupportCases => write!(f, "USER SUPPORT CASES"),
7033            ActionManageType::Warehouses => write!(f, "WAREHOUSES"),
7034        }
7035    }
7036}
7037
7038#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7039#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7040#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7041/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
7042/// under `globalPrivileges` in the `MODIFY` privilege.
7043pub enum ActionModifyType {
7044    LogLevel,
7045    TraceLevel,
7046    SessionLogLevel,
7047    SessionTraceLevel,
7048}
7049
7050impl fmt::Display for ActionModifyType {
7051    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7052        match self {
7053            ActionModifyType::LogLevel => write!(f, "LOG LEVEL"),
7054            ActionModifyType::TraceLevel => write!(f, "TRACE LEVEL"),
7055            ActionModifyType::SessionLogLevel => write!(f, "SESSION LOG LEVEL"),
7056            ActionModifyType::SessionTraceLevel => write!(f, "SESSION TRACE LEVEL"),
7057        }
7058    }
7059}
7060
7061#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7062#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7063#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7064/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
7065/// under `globalPrivileges` in the `MONITOR` privilege.
7066pub enum ActionMonitorType {
7067    Execution,
7068    Security,
7069    Usage,
7070}
7071
7072impl fmt::Display for ActionMonitorType {
7073    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7074        match self {
7075            ActionMonitorType::Execution => write!(f, "EXECUTION"),
7076            ActionMonitorType::Security => write!(f, "SECURITY"),
7077            ActionMonitorType::Usage => write!(f, "USAGE"),
7078        }
7079    }
7080}
7081
7082/// The principal that receives the privileges
7083#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7084#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7085#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7086pub struct Grantee {
7087    pub grantee_type: GranteesType,
7088    pub name: Option<GranteeName>,
7089}
7090
7091impl fmt::Display for Grantee {
7092    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7093        match self.grantee_type {
7094            GranteesType::Role => {
7095                write!(f, "ROLE ")?;
7096            }
7097            GranteesType::Share => {
7098                write!(f, "SHARE ")?;
7099            }
7100            GranteesType::User => {
7101                write!(f, "USER ")?;
7102            }
7103            GranteesType::Group => {
7104                write!(f, "GROUP ")?;
7105            }
7106            GranteesType::Public => {
7107                write!(f, "PUBLIC ")?;
7108            }
7109            GranteesType::DatabaseRole => {
7110                write!(f, "DATABASE ROLE ")?;
7111            }
7112            GranteesType::Application => {
7113                write!(f, "APPLICATION ")?;
7114            }
7115            GranteesType::ApplicationRole => {
7116                write!(f, "APPLICATION ROLE ")?;
7117            }
7118            GranteesType::None => (),
7119        }
7120        if let Some(ref name) = self.name {
7121            name.fmt(f)?;
7122        }
7123        Ok(())
7124    }
7125}
7126
7127#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7128#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7129#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7130pub enum GranteesType {
7131    Role,
7132    Share,
7133    User,
7134    Group,
7135    Public,
7136    DatabaseRole,
7137    Application,
7138    ApplicationRole,
7139    None,
7140}
7141
7142/// Users/roles designated in a GRANT/REVOKE
7143#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7144#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7145#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7146pub enum GranteeName {
7147    /// A bare identifier
7148    ObjectName(ObjectName),
7149    /// A MySQL user/host pair such as 'root'@'%'
7150    UserHost { user: Ident, host: Ident },
7151}
7152
7153impl fmt::Display for GranteeName {
7154    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7155        match self {
7156            GranteeName::ObjectName(name) => name.fmt(f),
7157            GranteeName::UserHost { user, host } => {
7158                write!(f, "{user}@{host}")
7159            }
7160        }
7161    }
7162}
7163
7164/// Objects on which privileges are granted in a GRANT statement.
7165#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7166#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7167#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7168pub enum GrantObjects {
7169    /// Grant privileges on `ALL SEQUENCES IN SCHEMA <schema_name> [, ...]`
7170    AllSequencesInSchema { schemas: Vec<ObjectName> },
7171    /// Grant privileges on `ALL TABLES IN SCHEMA <schema_name> [, ...]`
7172    AllTablesInSchema { schemas: Vec<ObjectName> },
7173    /// Grant privileges on `ALL VIEWS IN SCHEMA <schema_name> [, ...]`
7174    AllViewsInSchema { schemas: Vec<ObjectName> },
7175    /// Grant privileges on `ALL MATERIALIZED VIEWS IN SCHEMA <schema_name> [, ...]`
7176    AllMaterializedViewsInSchema { schemas: Vec<ObjectName> },
7177    /// Grant privileges on `ALL EXTERNAL TABLES IN SCHEMA <schema_name> [, ...]`
7178    AllExternalTablesInSchema { schemas: Vec<ObjectName> },
7179    /// Grant privileges on `ALL FUNCTIONS IN SCHEMA <schema_name> [, ...]`
7180    AllFunctionsInSchema { schemas: Vec<ObjectName> },
7181    /// Grant privileges on `FUTURE SCHEMAS IN DATABASE <database_name> [, ...]`
7182    FutureSchemasInDatabase { databases: Vec<ObjectName> },
7183    /// Grant privileges on `FUTURE TABLES IN SCHEMA <schema_name> [, ...]`
7184    FutureTablesInSchema { schemas: Vec<ObjectName> },
7185    /// Grant privileges on `FUTURE VIEWS IN SCHEMA <schema_name> [, ...]`
7186    FutureViewsInSchema { schemas: Vec<ObjectName> },
7187    /// Grant privileges on `FUTURE EXTERNAL TABLES IN SCHEMA <schema_name> [, ...]`
7188    FutureExternalTablesInSchema { schemas: Vec<ObjectName> },
7189    /// Grant privileges on `FUTURE MATERIALIZED VIEWS IN SCHEMA <schema_name> [, ...]`
7190    FutureMaterializedViewsInSchema { schemas: Vec<ObjectName> },
7191    /// Grant privileges on `FUTURE SEQUENCES IN SCHEMA <schema_name> [, ...]`
7192    FutureSequencesInSchema { schemas: Vec<ObjectName> },
7193    /// Grant privileges on specific databases
7194    Databases(Vec<ObjectName>),
7195    /// Grant privileges on specific schemas
7196    Schemas(Vec<ObjectName>),
7197    /// Grant privileges on specific sequences
7198    Sequences(Vec<ObjectName>),
7199    /// Grant privileges on specific tables
7200    Tables(Vec<ObjectName>),
7201    /// Grant privileges on specific views
7202    Views(Vec<ObjectName>),
7203    /// Grant privileges on specific warehouses
7204    Warehouses(Vec<ObjectName>),
7205    /// Grant privileges on specific integrations
7206    Integrations(Vec<ObjectName>),
7207    /// Grant privileges on resource monitors
7208    ResourceMonitors(Vec<ObjectName>),
7209    /// Grant privileges on users
7210    Users(Vec<ObjectName>),
7211    /// Grant privileges on compute pools
7212    ComputePools(Vec<ObjectName>),
7213    /// Grant privileges on connections
7214    Connections(Vec<ObjectName>),
7215    /// Grant privileges on failover groups
7216    FailoverGroup(Vec<ObjectName>),
7217    /// Grant privileges on replication group
7218    ReplicationGroup(Vec<ObjectName>),
7219    /// Grant privileges on external volumes
7220    ExternalVolumes(Vec<ObjectName>),
7221    /// Grant privileges on a procedure. In dialects that
7222    /// support overloading, the argument types must be specified.
7223    ///
7224    /// For example:
7225    /// `GRANT USAGE ON PROCEDURE foo(varchar) TO ROLE role1`
7226    Procedure {
7227        name: ObjectName,
7228        arg_types: Vec<DataType>,
7229    },
7230
7231    /// Grant privileges on a function. In dialects that
7232    /// support overloading, the argument types must be specified.
7233    ///
7234    /// For example:
7235    /// `GRANT USAGE ON FUNCTION foo(varchar) TO ROLE role1`
7236    Function {
7237        name: ObjectName,
7238        arg_types: Vec<DataType>,
7239    },
7240}
7241
7242impl fmt::Display for GrantObjects {
7243    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7244        match self {
7245            GrantObjects::Sequences(sequences) => {
7246                write!(f, "SEQUENCE {}", display_comma_separated(sequences))
7247            }
7248            GrantObjects::Databases(databases) => {
7249                write!(f, "DATABASE {}", display_comma_separated(databases))
7250            }
7251            GrantObjects::Schemas(schemas) => {
7252                write!(f, "SCHEMA {}", display_comma_separated(schemas))
7253            }
7254            GrantObjects::Tables(tables) => {
7255                write!(f, "{}", display_comma_separated(tables))
7256            }
7257            GrantObjects::Views(views) => {
7258                write!(f, "VIEW {}", display_comma_separated(views))
7259            }
7260            GrantObjects::Warehouses(warehouses) => {
7261                write!(f, "WAREHOUSE {}", display_comma_separated(warehouses))
7262            }
7263            GrantObjects::Integrations(integrations) => {
7264                write!(f, "INTEGRATION {}", display_comma_separated(integrations))
7265            }
7266            GrantObjects::AllSequencesInSchema { schemas } => {
7267                write!(
7268                    f,
7269                    "ALL SEQUENCES IN SCHEMA {}",
7270                    display_comma_separated(schemas)
7271                )
7272            }
7273            GrantObjects::AllTablesInSchema { schemas } => {
7274                write!(
7275                    f,
7276                    "ALL TABLES IN SCHEMA {}",
7277                    display_comma_separated(schemas)
7278                )
7279            }
7280            GrantObjects::AllExternalTablesInSchema { schemas } => {
7281                write!(
7282                    f,
7283                    "ALL EXTERNAL TABLES IN SCHEMA {}",
7284                    display_comma_separated(schemas)
7285                )
7286            }
7287            GrantObjects::AllViewsInSchema { schemas } => {
7288                write!(
7289                    f,
7290                    "ALL VIEWS IN SCHEMA {}",
7291                    display_comma_separated(schemas)
7292                )
7293            }
7294            GrantObjects::AllMaterializedViewsInSchema { schemas } => {
7295                write!(
7296                    f,
7297                    "ALL MATERIALIZED VIEWS IN SCHEMA {}",
7298                    display_comma_separated(schemas)
7299                )
7300            }
7301            GrantObjects::AllFunctionsInSchema { schemas } => {
7302                write!(
7303                    f,
7304                    "ALL FUNCTIONS IN SCHEMA {}",
7305                    display_comma_separated(schemas)
7306                )
7307            }
7308            GrantObjects::FutureSchemasInDatabase { databases } => {
7309                write!(
7310                    f,
7311                    "FUTURE SCHEMAS IN DATABASE {}",
7312                    display_comma_separated(databases)
7313                )
7314            }
7315            GrantObjects::FutureTablesInSchema { schemas } => {
7316                write!(
7317                    f,
7318                    "FUTURE TABLES IN SCHEMA {}",
7319                    display_comma_separated(schemas)
7320                )
7321            }
7322            GrantObjects::FutureExternalTablesInSchema { schemas } => {
7323                write!(
7324                    f,
7325                    "FUTURE EXTERNAL TABLES IN SCHEMA {}",
7326                    display_comma_separated(schemas)
7327                )
7328            }
7329            GrantObjects::FutureViewsInSchema { schemas } => {
7330                write!(
7331                    f,
7332                    "FUTURE VIEWS IN SCHEMA {}",
7333                    display_comma_separated(schemas)
7334                )
7335            }
7336            GrantObjects::FutureMaterializedViewsInSchema { schemas } => {
7337                write!(
7338                    f,
7339                    "FUTURE MATERIALIZED VIEWS IN SCHEMA {}",
7340                    display_comma_separated(schemas)
7341                )
7342            }
7343            GrantObjects::FutureSequencesInSchema { schemas } => {
7344                write!(
7345                    f,
7346                    "FUTURE SEQUENCES IN SCHEMA {}",
7347                    display_comma_separated(schemas)
7348                )
7349            }
7350            GrantObjects::ResourceMonitors(objects) => {
7351                write!(f, "RESOURCE MONITOR {}", display_comma_separated(objects))
7352            }
7353            GrantObjects::Users(objects) => {
7354                write!(f, "USER {}", display_comma_separated(objects))
7355            }
7356            GrantObjects::ComputePools(objects) => {
7357                write!(f, "COMPUTE POOL {}", display_comma_separated(objects))
7358            }
7359            GrantObjects::Connections(objects) => {
7360                write!(f, "CONNECTION {}", display_comma_separated(objects))
7361            }
7362            GrantObjects::FailoverGroup(objects) => {
7363                write!(f, "FAILOVER GROUP {}", display_comma_separated(objects))
7364            }
7365            GrantObjects::ReplicationGroup(objects) => {
7366                write!(f, "REPLICATION GROUP {}", display_comma_separated(objects))
7367            }
7368            GrantObjects::ExternalVolumes(objects) => {
7369                write!(f, "EXTERNAL VOLUME {}", display_comma_separated(objects))
7370            }
7371            GrantObjects::Procedure { name, arg_types } => {
7372                write!(f, "PROCEDURE {name}")?;
7373                if !arg_types.is_empty() {
7374                    write!(f, "({})", display_comma_separated(arg_types))?;
7375                }
7376                Ok(())
7377            }
7378            GrantObjects::Function { name, arg_types } => {
7379                write!(f, "FUNCTION {name}")?;
7380                if !arg_types.is_empty() {
7381                    write!(f, "({})", display_comma_separated(arg_types))?;
7382                }
7383                Ok(())
7384            }
7385        }
7386    }
7387}
7388
7389/// A `DENY` statement
7390///
7391/// [MsSql](https://learn.microsoft.com/en-us/sql/t-sql/statements/deny-transact-sql)
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 struct DenyStatement {
7396    pub privileges: Privileges,
7397    pub objects: GrantObjects,
7398    pub grantees: Vec<Grantee>,
7399    pub granted_by: Option<Ident>,
7400    pub cascade: Option<CascadeOption>,
7401}
7402
7403impl fmt::Display for DenyStatement {
7404    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7405        write!(f, "DENY {}", self.privileges)?;
7406        write!(f, " ON {}", self.objects)?;
7407        if !self.grantees.is_empty() {
7408            write!(f, " TO {}", display_comma_separated(&self.grantees))?;
7409        }
7410        if let Some(cascade) = &self.cascade {
7411            write!(f, " {cascade}")?;
7412        }
7413        if let Some(granted_by) = &self.granted_by {
7414            write!(f, " AS {granted_by}")?;
7415        }
7416        Ok(())
7417    }
7418}
7419
7420/// SQL assignment `foo = expr` as used in SQLUpdate
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 struct Assignment {
7425    pub target: AssignmentTarget,
7426    pub value: Expr,
7427}
7428
7429impl fmt::Display for Assignment {
7430    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7431        write!(f, "{} = {}", self.target, self.value)
7432    }
7433}
7434
7435/// Left-hand side of an assignment in an UPDATE statement,
7436/// e.g. `foo` in `foo = 5` (ColumnName assignment) or
7437/// `(a, b)` in `(a, b) = (1, 2)` (Tuple assignment).
7438#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7439#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7440#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7441pub enum AssignmentTarget {
7442    /// A single column
7443    ColumnName(ObjectName),
7444    /// A tuple of columns
7445    Tuple(Vec<ObjectName>),
7446}
7447
7448impl fmt::Display for AssignmentTarget {
7449    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7450        match self {
7451            AssignmentTarget::ColumnName(column) => write!(f, "{column}"),
7452            AssignmentTarget::Tuple(columns) => write!(f, "({})", display_comma_separated(columns)),
7453        }
7454    }
7455}
7456
7457#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7458#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7459#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7460pub enum FunctionArgExpr {
7461    Expr(Expr),
7462    /// Qualified wildcard, e.g. `alias.*` or `schema.table.*`.
7463    QualifiedWildcard(ObjectName),
7464    /// An unqualified `*`
7465    Wildcard,
7466}
7467
7468impl From<Expr> for FunctionArgExpr {
7469    fn from(wildcard_expr: Expr) -> Self {
7470        match wildcard_expr {
7471            Expr::QualifiedWildcard(prefix, _) => Self::QualifiedWildcard(prefix),
7472            Expr::Wildcard(_) => Self::Wildcard,
7473            expr => Self::Expr(expr),
7474        }
7475    }
7476}
7477
7478impl fmt::Display for FunctionArgExpr {
7479    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7480        match self {
7481            FunctionArgExpr::Expr(expr) => write!(f, "{expr}"),
7482            FunctionArgExpr::QualifiedWildcard(prefix) => write!(f, "{prefix}.*"),
7483            FunctionArgExpr::Wildcard => f.write_str("*"),
7484        }
7485    }
7486}
7487
7488#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7489#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7490#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7491/// Operator used to separate function arguments
7492pub enum FunctionArgOperator {
7493    /// function(arg1 = value1)
7494    Equals,
7495    /// function(arg1 => value1)
7496    RightArrow,
7497    /// function(arg1 := value1)
7498    Assignment,
7499    /// function(arg1 : value1)
7500    Colon,
7501    /// function(arg1 VALUE value1)
7502    Value,
7503}
7504
7505impl fmt::Display for FunctionArgOperator {
7506    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7507        match self {
7508            FunctionArgOperator::Equals => f.write_str("="),
7509            FunctionArgOperator::RightArrow => f.write_str("=>"),
7510            FunctionArgOperator::Assignment => f.write_str(":="),
7511            FunctionArgOperator::Colon => f.write_str(":"),
7512            FunctionArgOperator::Value => f.write_str("VALUE"),
7513        }
7514    }
7515}
7516
7517#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7518#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7519#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7520pub enum FunctionArg {
7521    /// `name` is identifier
7522    ///
7523    /// Enabled when `Dialect::supports_named_fn_args_with_expr_name` returns 'false'
7524    Named {
7525        name: Ident,
7526        arg: FunctionArgExpr,
7527        operator: FunctionArgOperator,
7528    },
7529    /// `name` is arbitrary expression
7530    ///
7531    /// Enabled when `Dialect::supports_named_fn_args_with_expr_name` returns 'true'
7532    ExprNamed {
7533        name: Expr,
7534        arg: FunctionArgExpr,
7535        operator: FunctionArgOperator,
7536    },
7537    Unnamed(FunctionArgExpr),
7538}
7539
7540impl fmt::Display for FunctionArg {
7541    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7542        match self {
7543            FunctionArg::Named {
7544                name,
7545                arg,
7546                operator,
7547            } => write!(f, "{name} {operator} {arg}"),
7548            FunctionArg::ExprNamed {
7549                name,
7550                arg,
7551                operator,
7552            } => write!(f, "{name} {operator} {arg}"),
7553            FunctionArg::Unnamed(unnamed_arg) => write!(f, "{unnamed_arg}"),
7554        }
7555    }
7556}
7557
7558#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7559#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7560#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7561pub enum CloseCursor {
7562    All,
7563    Specific { name: Ident },
7564}
7565
7566impl fmt::Display for CloseCursor {
7567    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7568        match self {
7569            CloseCursor::All => write!(f, "ALL"),
7570            CloseCursor::Specific { name } => write!(f, "{name}"),
7571        }
7572    }
7573}
7574
7575/// A Drop Domain statement
7576#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7577#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7578#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7579pub struct DropDomain {
7580    /// Whether to drop the domain if it exists
7581    pub if_exists: bool,
7582    /// The name of the domain to drop
7583    pub name: ObjectName,
7584    /// The behavior to apply when dropping the domain
7585    pub drop_behavior: Option<DropBehavior>,
7586}
7587
7588/// A constant of form `<data_type> 'value'`.
7589/// This can represent ANSI SQL `DATE`, `TIME`, and `TIMESTAMP` literals (such as `DATE '2020-01-01'`),
7590/// as well as constants of other types (a non-standard PostgreSQL extension).
7591#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7592#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7593#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7594pub struct TypedString {
7595    pub data_type: DataType,
7596    /// The value of the constant.
7597    /// Hint: you can unwrap the string value using `value.into_string()`.
7598    pub value: ValueWithSpan,
7599    /// Flags whether this TypedString uses the [ODBC syntax].
7600    ///
7601    /// Example:
7602    /// ```sql
7603    /// -- An ODBC date literal:
7604    /// SELECT {d '2025-07-16'}
7605    /// -- This is equivalent to the standard ANSI SQL literal:
7606    /// SELECT DATE '2025-07-16'
7607    ///
7608    /// [ODBC syntax]: https://learn.microsoft.com/en-us/sql/odbc/reference/develop-app/date-time-and-timestamp-literals?view=sql-server-2017
7609    pub uses_odbc_syntax: bool,
7610}
7611
7612impl fmt::Display for TypedString {
7613    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7614        let data_type = &self.data_type;
7615        let value = &self.value;
7616        match self.uses_odbc_syntax {
7617            false => {
7618                write!(f, "{data_type}")?;
7619                write!(f, " {value}")
7620            }
7621            true => {
7622                let prefix = match data_type {
7623                    DataType::Date => "d",
7624                    DataType::Time(..) => "t",
7625                    DataType::Timestamp(..) => "ts",
7626                    _ => "?",
7627                };
7628                write!(f, "{{{prefix} {value}}}")
7629            }
7630        }
7631    }
7632}
7633
7634/// A function call
7635#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7636#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7637#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7638pub struct Function {
7639    pub name: ObjectName,
7640    /// Flags whether this function call uses the [ODBC syntax].
7641    ///
7642    /// Example:
7643    /// ```sql
7644    /// SELECT {fn CONCAT('foo', 'bar')}
7645    /// ```
7646    ///
7647    /// [ODBC syntax]: https://learn.microsoft.com/en-us/sql/odbc/reference/develop-app/scalar-function-calls?view=sql-server-2017
7648    pub uses_odbc_syntax: bool,
7649    /// The parameters to the function, including any options specified within the
7650    /// delimiting parentheses.
7651    ///
7652    /// Example:
7653    /// ```plaintext
7654    /// HISTOGRAM(0.5, 0.6)(x, y)
7655    /// ```
7656    ///
7657    /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/aggregate-functions/parametric-functions)
7658    pub parameters: FunctionArguments,
7659    /// The arguments to the function, including any options specified within the
7660    /// delimiting parentheses.
7661    pub args: FunctionArguments,
7662    /// e.g. `x > 5` in `COUNT(x) FILTER (WHERE x > 5)`
7663    pub filter: Option<Box<Expr>>,
7664    /// Indicates how `NULL`s should be handled in the calculation.
7665    ///
7666    /// Example:
7667    /// ```plaintext
7668    /// FIRST_VALUE( <expr> ) [ { IGNORE | RESPECT } NULLS ] OVER ...
7669    /// ```
7670    ///
7671    /// [Snowflake](https://docs.snowflake.com/en/sql-reference/functions/first_value)
7672    pub null_treatment: Option<NullTreatment>,
7673    /// The `OVER` clause, indicating a window function call.
7674    pub over: Option<WindowType>,
7675    /// A clause used with certain aggregate functions to control the ordering
7676    /// within grouped sets before the function is applied.
7677    ///
7678    /// Syntax:
7679    /// ```plaintext
7680    /// <aggregate_function>(expression) WITHIN GROUP (ORDER BY key [ASC | DESC], ...)
7681    /// ```
7682    pub within_group: Vec<OrderByExpr>,
7683}
7684
7685impl fmt::Display for Function {
7686    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7687        if self.uses_odbc_syntax {
7688            write!(f, "{{fn ")?;
7689        }
7690
7691        write!(f, "{}{}{}", self.name, self.parameters, self.args)?;
7692
7693        if !self.within_group.is_empty() {
7694            write!(
7695                f,
7696                " WITHIN GROUP (ORDER BY {})",
7697                display_comma_separated(&self.within_group)
7698            )?;
7699        }
7700
7701        if let Some(filter_cond) = &self.filter {
7702            write!(f, " FILTER (WHERE {filter_cond})")?;
7703        }
7704
7705        if let Some(null_treatment) = &self.null_treatment {
7706            write!(f, " {null_treatment}")?;
7707        }
7708
7709        if let Some(o) = &self.over {
7710            f.write_str(" OVER ")?;
7711            o.fmt(f)?;
7712        }
7713
7714        if self.uses_odbc_syntax {
7715            write!(f, "}}")?;
7716        }
7717
7718        Ok(())
7719    }
7720}
7721
7722/// The arguments passed to a function call.
7723#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7724#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7725#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7726pub enum FunctionArguments {
7727    /// Used for special functions like `CURRENT_TIMESTAMP` that are invoked
7728    /// without parentheses.
7729    None,
7730    /// On some dialects, a subquery can be passed without surrounding
7731    /// parentheses if it's the sole argument to the function.
7732    Subquery(Box<Query>),
7733    /// A normal function argument list, including any clauses within it such as
7734    /// `DISTINCT` or `ORDER BY`.
7735    List(FunctionArgumentList),
7736}
7737
7738impl fmt::Display for FunctionArguments {
7739    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
7740        match self {
7741            FunctionArguments::None => Ok(()),
7742            FunctionArguments::Subquery(query) => write!(f, "({query})"),
7743            FunctionArguments::List(args) => write!(f, "({args})"),
7744        }
7745    }
7746}
7747
7748/// This represents everything inside the parentheses when calling a function.
7749#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7750#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7751#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7752pub struct FunctionArgumentList {
7753    /// `[ ALL | DISTINCT ]`
7754    pub duplicate_treatment: Option<DuplicateTreatment>,
7755    /// The function arguments.
7756    pub args: Vec<FunctionArg>,
7757    /// Additional clauses specified within the argument list.
7758    pub clauses: Vec<FunctionArgumentClause>,
7759}
7760
7761impl fmt::Display for FunctionArgumentList {
7762    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7763        if let Some(duplicate_treatment) = self.duplicate_treatment {
7764            write!(f, "{duplicate_treatment} ")?;
7765        }
7766        write!(f, "{}", display_comma_separated(&self.args))?;
7767        if !self.clauses.is_empty() {
7768            if !self.args.is_empty() {
7769                write!(f, " ")?;
7770            }
7771            write!(f, "{}", display_separated(&self.clauses, " "))?;
7772        }
7773        Ok(())
7774    }
7775}
7776
7777#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7778#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7779#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7780pub enum FunctionArgumentClause {
7781    /// Indicates how `NULL`s should be handled in the calculation, e.g. in `FIRST_VALUE` on [BigQuery].
7782    ///
7783    /// Syntax:
7784    /// ```plaintext
7785    /// { IGNORE | RESPECT } NULLS ]
7786    /// ```
7787    ///
7788    /// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/navigation_functions#first_value
7789    IgnoreOrRespectNulls(NullTreatment),
7790    /// Specifies the the ordering for some ordered set aggregates, e.g. `ARRAY_AGG` on [BigQuery].
7791    ///
7792    /// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/aggregate_functions#array_agg
7793    OrderBy(Vec<OrderByExpr>),
7794    /// Specifies a limit for the `ARRAY_AGG` and `ARRAY_CONCAT_AGG` functions on BigQuery.
7795    Limit(Expr),
7796    /// Specifies the behavior on overflow of the `LISTAGG` function.
7797    ///
7798    /// See <https://trino.io/docs/current/functions/aggregate.html>.
7799    OnOverflow(ListAggOnOverflow),
7800    /// Specifies a minimum or maximum bound on the input to [`ANY_VALUE`] on BigQuery.
7801    ///
7802    /// Syntax:
7803    /// ```plaintext
7804    /// HAVING { MAX | MIN } expression
7805    /// ```
7806    ///
7807    /// [`ANY_VALUE`]: https://cloud.google.com/bigquery/docs/reference/standard-sql/aggregate_functions#any_value
7808    Having(HavingBound),
7809    /// The `SEPARATOR` clause to the [`GROUP_CONCAT`] function in MySQL.
7810    ///
7811    /// [`GROUP_CONCAT`]: https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html#function_group-concat
7812    Separator(Value),
7813    /// The `ON NULL` clause for some JSON functions.
7814    ///
7815    /// [MSSQL `JSON_ARRAY`](https://learn.microsoft.com/en-us/sql/t-sql/functions/json-array-transact-sql?view=sql-server-ver16)
7816    /// [MSSQL `JSON_OBJECT`](https://learn.microsoft.com/en-us/sql/t-sql/functions/json-object-transact-sql?view=sql-server-ver16>)
7817    /// [PostgreSQL JSON functions](https://www.postgresql.org/docs/current/functions-json.html#FUNCTIONS-JSON-PROCESSING)
7818    JsonNullClause(JsonNullClause),
7819    /// The `RETURNING` clause for some JSON functions in PostgreSQL
7820    ///
7821    /// [`JSON_OBJECT`](https://www.postgresql.org/docs/current/functions-json.html#:~:text=json_object)
7822    JsonReturningClause(JsonReturningClause),
7823}
7824
7825impl fmt::Display for FunctionArgumentClause {
7826    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
7827        match self {
7828            FunctionArgumentClause::IgnoreOrRespectNulls(null_treatment) => {
7829                write!(f, "{null_treatment}")
7830            }
7831            FunctionArgumentClause::OrderBy(order_by) => {
7832                write!(f, "ORDER BY {}", display_comma_separated(order_by))
7833            }
7834            FunctionArgumentClause::Limit(limit) => write!(f, "LIMIT {limit}"),
7835            FunctionArgumentClause::OnOverflow(on_overflow) => write!(f, "{on_overflow}"),
7836            FunctionArgumentClause::Having(bound) => write!(f, "{bound}"),
7837            FunctionArgumentClause::Separator(sep) => write!(f, "SEPARATOR {sep}"),
7838            FunctionArgumentClause::JsonNullClause(null_clause) => write!(f, "{null_clause}"),
7839            FunctionArgumentClause::JsonReturningClause(returning_clause) => {
7840                write!(f, "{returning_clause}")
7841            }
7842        }
7843    }
7844}
7845
7846/// A method call
7847#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7848#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7849#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7850pub struct Method {
7851    pub expr: Box<Expr>,
7852    // always non-empty
7853    pub method_chain: Vec<Function>,
7854}
7855
7856impl fmt::Display for Method {
7857    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7858        write!(
7859            f,
7860            "{}.{}",
7861            self.expr,
7862            display_separated(&self.method_chain, ".")
7863        )
7864    }
7865}
7866
7867#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7868#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7869#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7870pub enum DuplicateTreatment {
7871    /// Perform the calculation only unique values.
7872    Distinct,
7873    /// Retain all duplicate values (the default).
7874    All,
7875}
7876
7877impl fmt::Display for DuplicateTreatment {
7878    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
7879        match self {
7880            DuplicateTreatment::Distinct => write!(f, "DISTINCT"),
7881            DuplicateTreatment::All => write!(f, "ALL"),
7882        }
7883    }
7884}
7885
7886#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7887#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7888#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7889pub enum AnalyzeFormatKind {
7890    /// e.g. `EXPLAIN ANALYZE FORMAT JSON SELECT * FROM tbl`
7891    Keyword(AnalyzeFormat),
7892    /// e.g. `EXPLAIN ANALYZE FORMAT=JSON SELECT * FROM tbl`
7893    Assignment(AnalyzeFormat),
7894}
7895
7896impl fmt::Display for AnalyzeFormatKind {
7897    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
7898        match self {
7899            AnalyzeFormatKind::Keyword(format) => write!(f, "FORMAT {format}"),
7900            AnalyzeFormatKind::Assignment(format) => write!(f, "FORMAT={format}"),
7901        }
7902    }
7903}
7904
7905#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7906#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7907#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7908pub enum AnalyzeFormat {
7909    TEXT,
7910    GRAPHVIZ,
7911    JSON,
7912    TRADITIONAL,
7913    TREE,
7914}
7915
7916impl fmt::Display for AnalyzeFormat {
7917    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
7918        f.write_str(match self {
7919            AnalyzeFormat::TEXT => "TEXT",
7920            AnalyzeFormat::GRAPHVIZ => "GRAPHVIZ",
7921            AnalyzeFormat::JSON => "JSON",
7922            AnalyzeFormat::TRADITIONAL => "TRADITIONAL",
7923            AnalyzeFormat::TREE => "TREE",
7924        })
7925    }
7926}
7927
7928/// External table's available file format
7929#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7930#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7931#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7932pub enum FileFormat {
7933    TEXTFILE,
7934    SEQUENCEFILE,
7935    ORC,
7936    PARQUET,
7937    AVRO,
7938    RCFILE,
7939    JSONFILE,
7940}
7941
7942impl fmt::Display for FileFormat {
7943    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7944        use self::FileFormat::*;
7945        f.write_str(match self {
7946            TEXTFILE => "TEXTFILE",
7947            SEQUENCEFILE => "SEQUENCEFILE",
7948            ORC => "ORC",
7949            PARQUET => "PARQUET",
7950            AVRO => "AVRO",
7951            RCFILE => "RCFILE",
7952            JSONFILE => "JSONFILE",
7953        })
7954    }
7955}
7956
7957/// The `ON OVERFLOW` clause of a LISTAGG invocation
7958#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7959#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7960#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7961pub enum ListAggOnOverflow {
7962    /// `ON OVERFLOW ERROR`
7963    Error,
7964
7965    /// `ON OVERFLOW TRUNCATE [ <filler> ] WITH[OUT] COUNT`
7966    Truncate {
7967        filler: Option<Box<Expr>>,
7968        with_count: bool,
7969    },
7970}
7971
7972impl fmt::Display for ListAggOnOverflow {
7973    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7974        write!(f, "ON OVERFLOW")?;
7975        match self {
7976            ListAggOnOverflow::Error => write!(f, " ERROR"),
7977            ListAggOnOverflow::Truncate { filler, with_count } => {
7978                write!(f, " TRUNCATE")?;
7979                if let Some(filler) = filler {
7980                    write!(f, " {filler}")?;
7981                }
7982                if *with_count {
7983                    write!(f, " WITH")?;
7984                } else {
7985                    write!(f, " WITHOUT")?;
7986                }
7987                write!(f, " COUNT")
7988            }
7989        }
7990    }
7991}
7992
7993/// The `HAVING` clause in a call to `ANY_VALUE` on BigQuery.
7994#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7995#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7996#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7997pub struct HavingBound(pub HavingBoundKind, pub Expr);
7998
7999impl fmt::Display for HavingBound {
8000    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8001        write!(f, "HAVING {} {}", self.0, self.1)
8002    }
8003}
8004
8005#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8006#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8007#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8008pub enum HavingBoundKind {
8009    Min,
8010    Max,
8011}
8012
8013impl fmt::Display for HavingBoundKind {
8014    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8015        match self {
8016            HavingBoundKind::Min => write!(f, "MIN"),
8017            HavingBoundKind::Max => write!(f, "MAX"),
8018        }
8019    }
8020}
8021
8022#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8023#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8024#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8025pub enum ObjectType {
8026    Table,
8027    View,
8028    MaterializedView,
8029    Index,
8030    Schema,
8031    Database,
8032    Role,
8033    Sequence,
8034    Stage,
8035    Type,
8036    User,
8037    Stream,
8038}
8039
8040impl fmt::Display for ObjectType {
8041    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8042        f.write_str(match self {
8043            ObjectType::Table => "TABLE",
8044            ObjectType::View => "VIEW",
8045            ObjectType::MaterializedView => "MATERIALIZED VIEW",
8046            ObjectType::Index => "INDEX",
8047            ObjectType::Schema => "SCHEMA",
8048            ObjectType::Database => "DATABASE",
8049            ObjectType::Role => "ROLE",
8050            ObjectType::Sequence => "SEQUENCE",
8051            ObjectType::Stage => "STAGE",
8052            ObjectType::Type => "TYPE",
8053            ObjectType::User => "USER",
8054            ObjectType::Stream => "STREAM",
8055        })
8056    }
8057}
8058
8059#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8060#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8061#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8062pub enum KillType {
8063    Connection,
8064    Query,
8065    Mutation,
8066}
8067
8068impl fmt::Display for KillType {
8069    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8070        f.write_str(match self {
8071            // MySQL
8072            KillType::Connection => "CONNECTION",
8073            KillType::Query => "QUERY",
8074            // Clickhouse supports Mutation
8075            KillType::Mutation => "MUTATION",
8076        })
8077    }
8078}
8079
8080#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8081#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8082#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8083pub enum HiveDistributionStyle {
8084    PARTITIONED {
8085        columns: Vec<ColumnDef>,
8086    },
8087    SKEWED {
8088        columns: Vec<ColumnDef>,
8089        on: Vec<ColumnDef>,
8090        stored_as_directories: bool,
8091    },
8092    NONE,
8093}
8094
8095#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8096#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8097#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8098pub enum HiveRowFormat {
8099    SERDE { class: String },
8100    DELIMITED { delimiters: Vec<HiveRowDelimiter> },
8101}
8102
8103#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8104#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8105#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8106pub struct HiveLoadDataFormat {
8107    pub serde: Expr,
8108    pub input_format: Expr,
8109}
8110
8111#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8112#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8113#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8114pub struct HiveRowDelimiter {
8115    pub delimiter: HiveDelimiter,
8116    pub char: Ident,
8117}
8118
8119impl fmt::Display for HiveRowDelimiter {
8120    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8121        write!(f, "{} ", self.delimiter)?;
8122        write!(f, "{}", self.char)
8123    }
8124}
8125
8126#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8127#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8128#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8129pub enum HiveDelimiter {
8130    FieldsTerminatedBy,
8131    FieldsEscapedBy,
8132    CollectionItemsTerminatedBy,
8133    MapKeysTerminatedBy,
8134    LinesTerminatedBy,
8135    NullDefinedAs,
8136}
8137
8138impl fmt::Display for HiveDelimiter {
8139    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8140        use HiveDelimiter::*;
8141        f.write_str(match self {
8142            FieldsTerminatedBy => "FIELDS TERMINATED BY",
8143            FieldsEscapedBy => "ESCAPED BY",
8144            CollectionItemsTerminatedBy => "COLLECTION ITEMS TERMINATED BY",
8145            MapKeysTerminatedBy => "MAP KEYS TERMINATED BY",
8146            LinesTerminatedBy => "LINES TERMINATED BY",
8147            NullDefinedAs => "NULL DEFINED AS",
8148        })
8149    }
8150}
8151
8152#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8153#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8154#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8155pub enum HiveDescribeFormat {
8156    Extended,
8157    Formatted,
8158}
8159
8160impl fmt::Display for HiveDescribeFormat {
8161    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8162        use HiveDescribeFormat::*;
8163        f.write_str(match self {
8164            Extended => "EXTENDED",
8165            Formatted => "FORMATTED",
8166        })
8167    }
8168}
8169
8170#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8171#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8172#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8173pub enum DescribeAlias {
8174    Describe,
8175    Explain,
8176    Desc,
8177}
8178
8179impl fmt::Display for DescribeAlias {
8180    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8181        use DescribeAlias::*;
8182        f.write_str(match self {
8183            Describe => "DESCRIBE",
8184            Explain => "EXPLAIN",
8185            Desc => "DESC",
8186        })
8187    }
8188}
8189
8190#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8191#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8192#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8193#[allow(clippy::large_enum_variant)]
8194pub enum HiveIOFormat {
8195    IOF {
8196        input_format: Expr,
8197        output_format: Expr,
8198    },
8199    FileFormat {
8200        format: FileFormat,
8201    },
8202}
8203
8204#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Default)]
8205#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8206#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8207pub struct HiveFormat {
8208    pub row_format: Option<HiveRowFormat>,
8209    pub serde_properties: Option<Vec<SqlOption>>,
8210    pub storage: Option<HiveIOFormat>,
8211    pub location: Option<String>,
8212}
8213
8214#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8215#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8216#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8217pub struct ClusteredIndex {
8218    pub name: Ident,
8219    pub asc: Option<bool>,
8220}
8221
8222impl fmt::Display for ClusteredIndex {
8223    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8224        write!(f, "{}", self.name)?;
8225        match self.asc {
8226            Some(true) => write!(f, " ASC"),
8227            Some(false) => write!(f, " DESC"),
8228            _ => Ok(()),
8229        }
8230    }
8231}
8232
8233#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8234#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8235#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8236pub enum TableOptionsClustered {
8237    ColumnstoreIndex,
8238    ColumnstoreIndexOrder(Vec<Ident>),
8239    Index(Vec<ClusteredIndex>),
8240}
8241
8242impl fmt::Display for TableOptionsClustered {
8243    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8244        match self {
8245            TableOptionsClustered::ColumnstoreIndex => {
8246                write!(f, "CLUSTERED COLUMNSTORE INDEX")
8247            }
8248            TableOptionsClustered::ColumnstoreIndexOrder(values) => {
8249                write!(
8250                    f,
8251                    "CLUSTERED COLUMNSTORE INDEX ORDER ({})",
8252                    display_comma_separated(values)
8253                )
8254            }
8255            TableOptionsClustered::Index(values) => {
8256                write!(f, "CLUSTERED INDEX ({})", display_comma_separated(values))
8257            }
8258        }
8259    }
8260}
8261
8262/// Specifies which partition the boundary values on table partitioning belongs to.
8263#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8264#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8265#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8266pub enum PartitionRangeDirection {
8267    Left,
8268    Right,
8269}
8270
8271#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8272#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8273#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8274pub enum SqlOption {
8275    /// Clustered represents the clustered version of table storage for MSSQL.
8276    ///
8277    /// <https://learn.microsoft.com/en-us/sql/t-sql/statements/create-table-azure-sql-data-warehouse?view=aps-pdw-2016-au7#TableOptions>
8278    Clustered(TableOptionsClustered),
8279    /// Single identifier options, e.g. `HEAP` for MSSQL.
8280    ///
8281    /// <https://learn.microsoft.com/en-us/sql/t-sql/statements/create-table-azure-sql-data-warehouse?view=aps-pdw-2016-au7#TableOptions>
8282    Ident(Ident),
8283    /// Any option that consists of a key value pair where the value is an expression. e.g.
8284    ///
8285    ///   WITH(DISTRIBUTION = ROUND_ROBIN)
8286    KeyValue { key: Ident, value: Expr },
8287    /// One or more table partitions and represents which partition the boundary values belong to,
8288    /// e.g.
8289    ///
8290    ///   PARTITION (id RANGE LEFT FOR VALUES (10, 20, 30, 40))
8291    ///
8292    /// <https://learn.microsoft.com/en-us/sql/t-sql/statements/create-table-azure-sql-data-warehouse?view=aps-pdw-2016-au7#TablePartitionOptions>
8293    Partition {
8294        column_name: Ident,
8295        range_direction: Option<PartitionRangeDirection>,
8296        for_values: Vec<Expr>,
8297    },
8298    /// Comment parameter (supports `=` and no `=` syntax)
8299    Comment(CommentDef),
8300    /// MySQL TableSpace option
8301    /// <https://dev.mysql.com/doc/refman/8.4/en/create-table.html>
8302    TableSpace(TablespaceOption),
8303    /// An option representing a key value pair, where the value is a parenthesized list and with an optional name
8304    /// e.g.
8305    ///
8306    ///   UNION  = (tbl_name\[,tbl_name\]...) <https://dev.mysql.com/doc/refman/8.4/en/create-table.html>
8307    ///   ENGINE = ReplicatedMergeTree('/table_name','{replica}', ver) <https://clickhouse.com/docs/engines/table-engines/mergetree-family/replication>
8308    ///   ENGINE = SummingMergeTree(\[columns\]) <https://clickhouse.com/docs/engines/table-engines/mergetree-family/summingmergetree>
8309    NamedParenthesizedList(NamedParenthesizedList),
8310}
8311
8312impl fmt::Display for SqlOption {
8313    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8314        match self {
8315            SqlOption::Clustered(c) => write!(f, "{c}"),
8316            SqlOption::Ident(ident) => {
8317                write!(f, "{ident}")
8318            }
8319            SqlOption::KeyValue { key: name, value } => {
8320                write!(f, "{name} = {value}")
8321            }
8322            SqlOption::Partition {
8323                column_name,
8324                range_direction,
8325                for_values,
8326            } => {
8327                let direction = match range_direction {
8328                    Some(PartitionRangeDirection::Left) => " LEFT",
8329                    Some(PartitionRangeDirection::Right) => " RIGHT",
8330                    None => "",
8331                };
8332
8333                write!(
8334                    f,
8335                    "PARTITION ({} RANGE{} FOR VALUES ({}))",
8336                    column_name,
8337                    direction,
8338                    display_comma_separated(for_values)
8339                )
8340            }
8341            SqlOption::TableSpace(tablespace_option) => {
8342                write!(f, "TABLESPACE {}", tablespace_option.name)?;
8343                match tablespace_option.storage {
8344                    Some(StorageType::Disk) => write!(f, " STORAGE DISK"),
8345                    Some(StorageType::Memory) => write!(f, " STORAGE MEMORY"),
8346                    None => Ok(()),
8347                }
8348            }
8349            SqlOption::Comment(comment) => match comment {
8350                CommentDef::WithEq(comment) => {
8351                    write!(f, "COMMENT = '{comment}'")
8352                }
8353                CommentDef::WithoutEq(comment) => {
8354                    write!(f, "COMMENT '{comment}'")
8355                }
8356            },
8357            SqlOption::NamedParenthesizedList(value) => {
8358                write!(f, "{} = ", value.key)?;
8359                if let Some(key) = &value.name {
8360                    write!(f, "{key}")?;
8361                }
8362                if !value.values.is_empty() {
8363                    write!(f, "({})", display_comma_separated(&value.values))?
8364                }
8365                Ok(())
8366            }
8367        }
8368    }
8369}
8370
8371#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
8372#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8373#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8374pub enum StorageType {
8375    Disk,
8376    Memory,
8377}
8378
8379#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
8380#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8381#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8382/// MySql TableSpace option
8383/// <https://dev.mysql.com/doc/refman/8.4/en/create-table.html>
8384pub struct TablespaceOption {
8385    pub name: String,
8386    pub storage: Option<StorageType>,
8387}
8388
8389#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8390#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8391#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8392pub struct SecretOption {
8393    pub key: Ident,
8394    pub value: Ident,
8395}
8396
8397impl fmt::Display for SecretOption {
8398    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8399        write!(f, "{} {}", self.key, self.value)
8400    }
8401}
8402
8403/// A `CREATE SERVER` statement.
8404///
8405/// [PostgreSQL Documentation](https://www.postgresql.org/docs/current/sql-createserver.html)
8406#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8407#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8408#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8409pub struct CreateServerStatement {
8410    pub name: ObjectName,
8411    pub if_not_exists: bool,
8412    pub server_type: Option<Ident>,
8413    pub version: Option<Ident>,
8414    pub foreign_data_wrapper: ObjectName,
8415    pub options: Option<Vec<CreateServerOption>>,
8416}
8417
8418impl fmt::Display for CreateServerStatement {
8419    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8420        let CreateServerStatement {
8421            name,
8422            if_not_exists,
8423            server_type,
8424            version,
8425            foreign_data_wrapper,
8426            options,
8427        } = self;
8428
8429        write!(
8430            f,
8431            "CREATE SERVER {if_not_exists}{name} ",
8432            if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
8433        )?;
8434
8435        if let Some(st) = server_type {
8436            write!(f, "TYPE {st} ")?;
8437        }
8438
8439        if let Some(v) = version {
8440            write!(f, "VERSION {v} ")?;
8441        }
8442
8443        write!(f, "FOREIGN DATA WRAPPER {foreign_data_wrapper}")?;
8444
8445        if let Some(o) = options {
8446            write!(f, " OPTIONS ({o})", o = display_comma_separated(o))?;
8447        }
8448
8449        Ok(())
8450    }
8451}
8452
8453#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8454#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8455#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8456pub struct CreateServerOption {
8457    pub key: Ident,
8458    pub value: Ident,
8459}
8460
8461impl fmt::Display for CreateServerOption {
8462    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8463        write!(f, "{} {}", self.key, self.value)
8464    }
8465}
8466
8467#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8468#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8469#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8470pub enum AttachDuckDBDatabaseOption {
8471    ReadOnly(Option<bool>),
8472    Type(Ident),
8473}
8474
8475impl fmt::Display for AttachDuckDBDatabaseOption {
8476    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8477        match self {
8478            AttachDuckDBDatabaseOption::ReadOnly(Some(true)) => write!(f, "READ_ONLY true"),
8479            AttachDuckDBDatabaseOption::ReadOnly(Some(false)) => write!(f, "READ_ONLY false"),
8480            AttachDuckDBDatabaseOption::ReadOnly(None) => write!(f, "READ_ONLY"),
8481            AttachDuckDBDatabaseOption::Type(t) => write!(f, "TYPE {t}"),
8482        }
8483    }
8484}
8485
8486#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8487#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8488#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8489pub enum TransactionMode {
8490    AccessMode(TransactionAccessMode),
8491    IsolationLevel(TransactionIsolationLevel),
8492}
8493
8494impl fmt::Display for TransactionMode {
8495    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8496        use TransactionMode::*;
8497        match self {
8498            AccessMode(access_mode) => write!(f, "{access_mode}"),
8499            IsolationLevel(iso_level) => write!(f, "ISOLATION LEVEL {iso_level}"),
8500        }
8501    }
8502}
8503
8504#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8505#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8506#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8507pub enum TransactionAccessMode {
8508    ReadOnly,
8509    ReadWrite,
8510}
8511
8512impl fmt::Display for TransactionAccessMode {
8513    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8514        use TransactionAccessMode::*;
8515        f.write_str(match self {
8516            ReadOnly => "READ ONLY",
8517            ReadWrite => "READ WRITE",
8518        })
8519    }
8520}
8521
8522#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8523#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8524#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8525pub enum TransactionIsolationLevel {
8526    ReadUncommitted,
8527    ReadCommitted,
8528    RepeatableRead,
8529    Serializable,
8530    Snapshot,
8531}
8532
8533impl fmt::Display for TransactionIsolationLevel {
8534    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8535        use TransactionIsolationLevel::*;
8536        f.write_str(match self {
8537            ReadUncommitted => "READ UNCOMMITTED",
8538            ReadCommitted => "READ COMMITTED",
8539            RepeatableRead => "REPEATABLE READ",
8540            Serializable => "SERIALIZABLE",
8541            Snapshot => "SNAPSHOT",
8542        })
8543    }
8544}
8545
8546/// Modifier for the transaction in the `BEGIN` syntax
8547///
8548/// SQLite: <https://sqlite.org/lang_transaction.html>
8549/// MS-SQL: <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/try-catch-transact-sql>
8550#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8551#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8552#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8553pub enum TransactionModifier {
8554    Deferred,
8555    Immediate,
8556    Exclusive,
8557    Try,
8558    Catch,
8559}
8560
8561impl fmt::Display for TransactionModifier {
8562    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8563        use TransactionModifier::*;
8564        f.write_str(match self {
8565            Deferred => "DEFERRED",
8566            Immediate => "IMMEDIATE",
8567            Exclusive => "EXCLUSIVE",
8568            Try => "TRY",
8569            Catch => "CATCH",
8570        })
8571    }
8572}
8573
8574#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8575#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8576#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8577pub enum ShowStatementFilter {
8578    Like(String),
8579    ILike(String),
8580    Where(Expr),
8581    NoKeyword(String),
8582}
8583
8584impl fmt::Display for ShowStatementFilter {
8585    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8586        use ShowStatementFilter::*;
8587        match self {
8588            Like(pattern) => write!(f, "LIKE '{}'", value::escape_single_quote_string(pattern)),
8589            ILike(pattern) => write!(f, "ILIKE {}", value::escape_single_quote_string(pattern)),
8590            Where(expr) => write!(f, "WHERE {expr}"),
8591            NoKeyword(pattern) => write!(f, "'{}'", value::escape_single_quote_string(pattern)),
8592        }
8593    }
8594}
8595
8596#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8597#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8598#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8599pub enum ShowStatementInClause {
8600    IN,
8601    FROM,
8602}
8603
8604impl fmt::Display for ShowStatementInClause {
8605    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8606        use ShowStatementInClause::*;
8607        match self {
8608            FROM => write!(f, "FROM"),
8609            IN => write!(f, "IN"),
8610        }
8611    }
8612}
8613
8614/// Sqlite specific syntax
8615///
8616/// See [Sqlite documentation](https://sqlite.org/lang_conflict.html)
8617/// for more details.
8618#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8619#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8620#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8621pub enum SqliteOnConflict {
8622    Rollback,
8623    Abort,
8624    Fail,
8625    Ignore,
8626    Replace,
8627}
8628
8629impl fmt::Display for SqliteOnConflict {
8630    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8631        use SqliteOnConflict::*;
8632        match self {
8633            Rollback => write!(f, "OR ROLLBACK"),
8634            Abort => write!(f, "OR ABORT"),
8635            Fail => write!(f, "OR FAIL"),
8636            Ignore => write!(f, "OR IGNORE"),
8637            Replace => write!(f, "OR REPLACE"),
8638        }
8639    }
8640}
8641
8642/// Mysql specific syntax
8643///
8644/// See [Mysql documentation](https://dev.mysql.com/doc/refman/8.0/en/replace.html)
8645/// See [Mysql documentation](https://dev.mysql.com/doc/refman/8.0/en/insert.html)
8646/// for more details.
8647#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8648#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8649#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8650pub enum MysqlInsertPriority {
8651    LowPriority,
8652    Delayed,
8653    HighPriority,
8654}
8655
8656impl fmt::Display for crate::ast::MysqlInsertPriority {
8657    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8658        use MysqlInsertPriority::*;
8659        match self {
8660            LowPriority => write!(f, "LOW_PRIORITY"),
8661            Delayed => write!(f, "DELAYED"),
8662            HighPriority => write!(f, "HIGH_PRIORITY"),
8663        }
8664    }
8665}
8666
8667#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8668#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8669#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8670pub enum CopySource {
8671    Table {
8672        /// The name of the table to copy from.
8673        table_name: ObjectName,
8674        /// A list of column names to copy. Empty list means that all columns
8675        /// are copied.
8676        columns: Vec<Ident>,
8677    },
8678    Query(Box<Query>),
8679}
8680
8681#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8682#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8683#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8684pub enum CopyTarget {
8685    Stdin,
8686    Stdout,
8687    File {
8688        /// The path name of the input or output file.
8689        filename: String,
8690    },
8691    Program {
8692        /// A command to execute
8693        command: String,
8694    },
8695}
8696
8697impl fmt::Display for CopyTarget {
8698    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8699        use CopyTarget::*;
8700        match self {
8701            Stdin => write!(f, "STDIN"),
8702            Stdout => write!(f, "STDOUT"),
8703            File { filename } => write!(f, "'{}'", value::escape_single_quote_string(filename)),
8704            Program { command } => write!(
8705                f,
8706                "PROGRAM '{}'",
8707                value::escape_single_quote_string(command)
8708            ),
8709        }
8710    }
8711}
8712
8713#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8714#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8715#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8716pub enum OnCommit {
8717    DeleteRows,
8718    PreserveRows,
8719    Drop,
8720}
8721
8722/// An option in `COPY` statement.
8723///
8724/// <https://www.postgresql.org/docs/14/sql-copy.html>
8725#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8726#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8727#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8728pub enum CopyOption {
8729    /// FORMAT format_name
8730    Format(Ident),
8731    /// FREEZE \[ boolean \]
8732    Freeze(bool),
8733    /// DELIMITER 'delimiter_character'
8734    Delimiter(char),
8735    /// NULL 'null_string'
8736    Null(String),
8737    /// HEADER \[ boolean \]
8738    Header(bool),
8739    /// QUOTE 'quote_character'
8740    Quote(char),
8741    /// ESCAPE 'escape_character'
8742    Escape(char),
8743    /// FORCE_QUOTE { ( column_name [, ...] ) | * }
8744    ForceQuote(Vec<Ident>),
8745    /// FORCE_NOT_NULL ( column_name [, ...] )
8746    ForceNotNull(Vec<Ident>),
8747    /// FORCE_NULL ( column_name [, ...] )
8748    ForceNull(Vec<Ident>),
8749    /// ENCODING 'encoding_name'
8750    Encoding(String),
8751}
8752
8753impl fmt::Display for CopyOption {
8754    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8755        use CopyOption::*;
8756        match self {
8757            Format(name) => write!(f, "FORMAT {name}"),
8758            Freeze(true) => write!(f, "FREEZE"),
8759            Freeze(false) => write!(f, "FREEZE FALSE"),
8760            Delimiter(char) => write!(f, "DELIMITER '{char}'"),
8761            Null(string) => write!(f, "NULL '{}'", value::escape_single_quote_string(string)),
8762            Header(true) => write!(f, "HEADER"),
8763            Header(false) => write!(f, "HEADER FALSE"),
8764            Quote(char) => write!(f, "QUOTE '{char}'"),
8765            Escape(char) => write!(f, "ESCAPE '{char}'"),
8766            ForceQuote(columns) => write!(f, "FORCE_QUOTE ({})", display_comma_separated(columns)),
8767            ForceNotNull(columns) => {
8768                write!(f, "FORCE_NOT_NULL ({})", display_comma_separated(columns))
8769            }
8770            ForceNull(columns) => write!(f, "FORCE_NULL ({})", display_comma_separated(columns)),
8771            Encoding(name) => write!(f, "ENCODING '{}'", value::escape_single_quote_string(name)),
8772        }
8773    }
8774}
8775
8776/// An option in `COPY` statement before PostgreSQL version 9.0.
8777///
8778/// [PostgreSQL](https://www.postgresql.org/docs/8.4/sql-copy.html)
8779/// [Redshift](https://docs.aws.amazon.com/redshift/latest/dg/r_COPY-alphabetical-parm-list.html)
8780#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8781#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8782#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8783pub enum CopyLegacyOption {
8784    /// ACCEPTANYDATE
8785    AcceptAnyDate,
8786    /// ACCEPTINVCHARS
8787    AcceptInvChars(Option<String>),
8788    /// ADDQUOTES
8789    AddQuotes,
8790    /// ALLOWOVERWRITE
8791    AllowOverwrite,
8792    /// BINARY
8793    Binary,
8794    /// BLANKSASNULL
8795    BlankAsNull,
8796    /// BZIP2
8797    Bzip2,
8798    /// CLEANPATH
8799    CleanPath,
8800    /// CSV ...
8801    Csv(Vec<CopyLegacyCsvOption>),
8802    /// DATEFORMAT \[ AS \] {'dateformat_string' | 'auto' }
8803    DateFormat(Option<String>),
8804    /// DELIMITER \[ AS \] 'delimiter_character'
8805    Delimiter(char),
8806    /// EMPTYASNULL
8807    EmptyAsNull,
8808    /// ENCRYPTED \[ AUTO \]
8809    Encrypted { auto: bool },
8810    /// ESCAPE
8811    Escape,
8812    /// EXTENSION 'extension-name'
8813    Extension(String),
8814    /// FIXEDWIDTH \[ AS \] 'fixedwidth-spec'
8815    FixedWidth(String),
8816    /// GZIP
8817    Gzip,
8818    /// HEADER
8819    Header,
8820    /// IAM_ROLE { DEFAULT | 'arn:aws:iam::123456789:role/role1' }
8821    IamRole(IamRoleKind),
8822    /// IGNOREHEADER \[ AS \] number_rows
8823    IgnoreHeader(u64),
8824    /// JSON
8825    Json,
8826    /// MANIFEST \[ VERBOSE \]
8827    Manifest { verbose: bool },
8828    /// MAXFILESIZE \[ AS \] max-size \[ MB | GB \]
8829    MaxFileSize(FileSize),
8830    /// NULL \[ AS \] 'null_string'
8831    Null(String),
8832    /// PARALLEL [ { ON | TRUE } | { OFF | FALSE } ]
8833    Parallel(Option<bool>),
8834    /// PARQUET
8835    Parquet,
8836    /// PARTITION BY ( column_name [, ... ] ) \[ INCLUDE \]
8837    PartitionBy(UnloadPartitionBy),
8838    /// REGION \[ AS \] 'aws-region' }
8839    Region(String),
8840    /// ROWGROUPSIZE \[ AS \] size \[ MB | GB \]
8841    RowGroupSize(FileSize),
8842    /// TIMEFORMAT \[ AS \] {'timeformat_string' | 'auto' | 'epochsecs' | 'epochmillisecs' }
8843    TimeFormat(Option<String>),
8844    /// TRUNCATECOLUMNS
8845    TruncateColumns,
8846    /// ZSTD
8847    Zstd,
8848}
8849
8850impl fmt::Display for CopyLegacyOption {
8851    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8852        use CopyLegacyOption::*;
8853        match self {
8854            AcceptAnyDate => write!(f, "ACCEPTANYDATE"),
8855            AcceptInvChars(ch) => {
8856                write!(f, "ACCEPTINVCHARS")?;
8857                if let Some(ch) = ch {
8858                    write!(f, " '{}'", value::escape_single_quote_string(ch))?;
8859                }
8860                Ok(())
8861            }
8862            AddQuotes => write!(f, "ADDQUOTES"),
8863            AllowOverwrite => write!(f, "ALLOWOVERWRITE"),
8864            Binary => write!(f, "BINARY"),
8865            BlankAsNull => write!(f, "BLANKSASNULL"),
8866            Bzip2 => write!(f, "BZIP2"),
8867            CleanPath => write!(f, "CLEANPATH"),
8868            Csv(opts) => {
8869                write!(f, "CSV")?;
8870                if !opts.is_empty() {
8871                    write!(f, " {}", display_separated(opts, " "))?;
8872                }
8873                Ok(())
8874            }
8875            DateFormat(fmt) => {
8876                write!(f, "DATEFORMAT")?;
8877                if let Some(fmt) = fmt {
8878                    write!(f, " '{}'", value::escape_single_quote_string(fmt))?;
8879                }
8880                Ok(())
8881            }
8882            Delimiter(char) => write!(f, "DELIMITER '{char}'"),
8883            EmptyAsNull => write!(f, "EMPTYASNULL"),
8884            Encrypted { auto } => write!(f, "ENCRYPTED{}", if *auto { " AUTO" } else { "" }),
8885            Escape => write!(f, "ESCAPE"),
8886            Extension(ext) => write!(f, "EXTENSION '{}'", value::escape_single_quote_string(ext)),
8887            FixedWidth(spec) => write!(
8888                f,
8889                "FIXEDWIDTH '{}'",
8890                value::escape_single_quote_string(spec)
8891            ),
8892            Gzip => write!(f, "GZIP"),
8893            Header => write!(f, "HEADER"),
8894            IamRole(role) => write!(f, "IAM_ROLE {role}"),
8895            IgnoreHeader(num_rows) => write!(f, "IGNOREHEADER {num_rows}"),
8896            Json => write!(f, "JSON"),
8897            Manifest { verbose } => write!(f, "MANIFEST{}", if *verbose { " VERBOSE" } else { "" }),
8898            MaxFileSize(file_size) => write!(f, "MAXFILESIZE {file_size}"),
8899            Null(string) => write!(f, "NULL '{}'", value::escape_single_quote_string(string)),
8900            Parallel(enabled) => {
8901                write!(
8902                    f,
8903                    "PARALLEL{}",
8904                    match enabled {
8905                        Some(true) => " TRUE",
8906                        Some(false) => " FALSE",
8907                        _ => "",
8908                    }
8909                )
8910            }
8911            Parquet => write!(f, "PARQUET"),
8912            PartitionBy(p) => write!(f, "{p}"),
8913            Region(region) => write!(f, "REGION '{}'", value::escape_single_quote_string(region)),
8914            RowGroupSize(file_size) => write!(f, "ROWGROUPSIZE {file_size}"),
8915            TimeFormat(fmt) => {
8916                write!(f, "TIMEFORMAT")?;
8917                if let Some(fmt) = fmt {
8918                    write!(f, " '{}'", value::escape_single_quote_string(fmt))?;
8919                }
8920                Ok(())
8921            }
8922            TruncateColumns => write!(f, "TRUNCATECOLUMNS"),
8923            Zstd => write!(f, "ZSTD"),
8924        }
8925    }
8926}
8927
8928/// ```sql
8929/// SIZE \[ MB | GB \]
8930/// ```
8931#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8932#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8933#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8934pub struct FileSize {
8935    pub size: Value,
8936    pub unit: Option<FileSizeUnit>,
8937}
8938
8939impl fmt::Display for FileSize {
8940    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8941        write!(f, "{}", self.size)?;
8942        if let Some(unit) = &self.unit {
8943            write!(f, " {unit}")?;
8944        }
8945        Ok(())
8946    }
8947}
8948
8949#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8950#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8951#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8952pub enum FileSizeUnit {
8953    MB,
8954    GB,
8955}
8956
8957impl fmt::Display for FileSizeUnit {
8958    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8959        match self {
8960            FileSizeUnit::MB => write!(f, "MB"),
8961            FileSizeUnit::GB => write!(f, "GB"),
8962        }
8963    }
8964}
8965
8966/// Specifies the partition keys for the unload operation
8967///
8968/// ```sql
8969/// PARTITION BY ( column_name [, ... ] ) [ INCLUDE ]
8970/// ```
8971#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8972#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8973#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8974pub struct UnloadPartitionBy {
8975    pub columns: Vec<Ident>,
8976    pub include: bool,
8977}
8978
8979impl fmt::Display for UnloadPartitionBy {
8980    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8981        write!(
8982            f,
8983            "PARTITION BY ({}){}",
8984            display_comma_separated(&self.columns),
8985            if self.include { " INCLUDE" } else { "" }
8986        )
8987    }
8988}
8989
8990/// An `IAM_ROLE` option in the AWS ecosystem
8991///
8992/// [Redshift COPY](https://docs.aws.amazon.com/redshift/latest/dg/copy-parameters-authorization.html#copy-iam-role)
8993#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8994#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8995#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8996pub enum IamRoleKind {
8997    /// Default role
8998    Default,
8999    /// Specific role ARN, for example: `arn:aws:iam::123456789:role/role1`
9000    Arn(String),
9001}
9002
9003impl fmt::Display for IamRoleKind {
9004    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9005        match self {
9006            IamRoleKind::Default => write!(f, "DEFAULT"),
9007            IamRoleKind::Arn(arn) => write!(f, "'{arn}'"),
9008        }
9009    }
9010}
9011
9012/// A `CSV` option in `COPY` statement before PostgreSQL version 9.0.
9013///
9014/// <https://www.postgresql.org/docs/8.4/sql-copy.html>
9015#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9016#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9017#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9018pub enum CopyLegacyCsvOption {
9019    /// HEADER
9020    Header,
9021    /// QUOTE \[ AS \] 'quote_character'
9022    Quote(char),
9023    /// ESCAPE \[ AS \] 'escape_character'
9024    Escape(char),
9025    /// FORCE QUOTE { column_name [, ...] | * }
9026    ForceQuote(Vec<Ident>),
9027    /// FORCE NOT NULL column_name [, ...]
9028    ForceNotNull(Vec<Ident>),
9029}
9030
9031impl fmt::Display for CopyLegacyCsvOption {
9032    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9033        use CopyLegacyCsvOption::*;
9034        match self {
9035            Header => write!(f, "HEADER"),
9036            Quote(char) => write!(f, "QUOTE '{char}'"),
9037            Escape(char) => write!(f, "ESCAPE '{char}'"),
9038            ForceQuote(columns) => write!(f, "FORCE QUOTE {}", display_comma_separated(columns)),
9039            ForceNotNull(columns) => {
9040                write!(f, "FORCE NOT NULL {}", display_comma_separated(columns))
9041            }
9042        }
9043    }
9044}
9045
9046/// Variant of `WHEN` clause used within a `MERGE` Statement.
9047///
9048/// Example:
9049/// ```sql
9050/// MERGE INTO T USING U ON FALSE WHEN MATCHED THEN DELETE
9051/// ```
9052/// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/merge)
9053/// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/dml-syntax#merge_statement)
9054#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9055#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9056#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9057pub enum MergeClauseKind {
9058    /// `WHEN MATCHED`
9059    Matched,
9060    /// `WHEN NOT MATCHED`
9061    NotMatched,
9062    /// `WHEN MATCHED BY TARGET`
9063    ///
9064    /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/dml-syntax#merge_statement)
9065    NotMatchedByTarget,
9066    /// `WHEN MATCHED BY SOURCE`
9067    ///
9068    /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/dml-syntax#merge_statement)
9069    NotMatchedBySource,
9070}
9071
9072impl Display for MergeClauseKind {
9073    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9074        match self {
9075            MergeClauseKind::Matched => write!(f, "MATCHED"),
9076            MergeClauseKind::NotMatched => write!(f, "NOT MATCHED"),
9077            MergeClauseKind::NotMatchedByTarget => write!(f, "NOT MATCHED BY TARGET"),
9078            MergeClauseKind::NotMatchedBySource => write!(f, "NOT MATCHED BY SOURCE"),
9079        }
9080    }
9081}
9082
9083/// The type of expression used to insert rows within a `MERGE` statement.
9084///
9085/// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/merge)
9086/// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/dml-syntax#merge_statement)
9087#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9088#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9089#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9090pub enum MergeInsertKind {
9091    /// The insert expression is defined from an explicit `VALUES` clause
9092    ///
9093    /// Example:
9094    /// ```sql
9095    /// INSERT VALUES(product, quantity)
9096    /// ```
9097    Values(Values),
9098    /// The insert expression is defined using only the `ROW` keyword.
9099    ///
9100    /// Example:
9101    /// ```sql
9102    /// INSERT ROW
9103    /// ```
9104    /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/dml-syntax#merge_statement)
9105    Row,
9106}
9107
9108impl Display for MergeInsertKind {
9109    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9110        match self {
9111            MergeInsertKind::Values(values) => {
9112                write!(f, "{values}")
9113            }
9114            MergeInsertKind::Row => {
9115                write!(f, "ROW")
9116            }
9117        }
9118    }
9119}
9120
9121/// The expression used to insert rows within a `MERGE` statement.
9122///
9123/// Examples
9124/// ```sql
9125/// INSERT (product, quantity) VALUES(product, quantity)
9126/// INSERT ROW
9127/// ```
9128///
9129/// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/merge)
9130/// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/dml-syntax#merge_statement)
9131#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9132#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9133#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9134pub struct MergeInsertExpr {
9135    /// Columns (if any) specified by the insert.
9136    ///
9137    /// Example:
9138    /// ```sql
9139    /// INSERT (product, quantity) VALUES(product, quantity)
9140    /// INSERT (product, quantity) ROW
9141    /// ```
9142    pub columns: Vec<Ident>,
9143    /// The insert type used by the statement.
9144    pub kind: MergeInsertKind,
9145}
9146
9147impl Display for MergeInsertExpr {
9148    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9149        if !self.columns.is_empty() {
9150            write!(f, "({}) ", display_comma_separated(self.columns.as_slice()))?;
9151        }
9152        write!(f, "{}", self.kind)
9153    }
9154}
9155
9156/// Underlying statement of a when clause within a `MERGE` Statement
9157///
9158/// Example
9159/// ```sql
9160/// INSERT (product, quantity) VALUES(product, quantity)
9161/// ```
9162///
9163/// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/merge)
9164/// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/dml-syntax#merge_statement)
9165#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9166#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9167#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9168pub enum MergeAction {
9169    /// An `INSERT` clause
9170    ///
9171    /// Example:
9172    /// ```sql
9173    /// INSERT (product, quantity) VALUES(product, quantity)
9174    /// ```
9175    Insert(MergeInsertExpr),
9176    /// An `UPDATE` clause
9177    ///
9178    /// Example:
9179    /// ```sql
9180    /// UPDATE SET quantity = T.quantity + S.quantity
9181    /// ```
9182    Update { assignments: Vec<Assignment> },
9183    /// A plain `DELETE` clause
9184    Delete,
9185}
9186
9187impl Display for MergeAction {
9188    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9189        match self {
9190            MergeAction::Insert(insert) => {
9191                write!(f, "INSERT {insert}")
9192            }
9193            MergeAction::Update { assignments } => {
9194                write!(f, "UPDATE SET {}", display_comma_separated(assignments))
9195            }
9196            MergeAction::Delete => {
9197                write!(f, "DELETE")
9198            }
9199        }
9200    }
9201}
9202
9203/// A when clause within a `MERGE` Statement
9204///
9205/// Example:
9206/// ```sql
9207/// WHEN NOT MATCHED BY SOURCE AND product LIKE '%washer%' THEN DELETE
9208/// ```
9209/// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/merge)
9210/// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/dml-syntax#merge_statement)
9211#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9212#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9213#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9214pub struct MergeClause {
9215    pub clause_kind: MergeClauseKind,
9216    pub predicate: Option<Expr>,
9217    pub action: MergeAction,
9218}
9219
9220impl Display for MergeClause {
9221    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9222        let MergeClause {
9223            clause_kind,
9224            predicate,
9225            action,
9226        } = self;
9227
9228        write!(f, "WHEN {clause_kind}")?;
9229        if let Some(pred) = predicate {
9230            write!(f, " AND {pred}")?;
9231        }
9232        write!(f, " THEN {action}")
9233    }
9234}
9235
9236/// A Output Clause in the end of a 'MERGE' Statement
9237///
9238/// Example:
9239/// OUTPUT $action, deleted.* INTO dbo.temp_products;
9240/// [mssql](https://learn.microsoft.com/en-us/sql/t-sql/queries/output-clause-transact-sql)
9241#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9242#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9243#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9244pub enum OutputClause {
9245    Output {
9246        select_items: Vec<SelectItem>,
9247        into_table: Option<SelectInto>,
9248    },
9249    Returning {
9250        select_items: Vec<SelectItem>,
9251    },
9252}
9253
9254impl fmt::Display for OutputClause {
9255    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9256        match self {
9257            OutputClause::Output {
9258                select_items,
9259                into_table,
9260            } => {
9261                f.write_str("OUTPUT ")?;
9262                display_comma_separated(select_items).fmt(f)?;
9263                if let Some(into_table) = into_table {
9264                    f.write_str(" ")?;
9265                    into_table.fmt(f)?;
9266                }
9267                Ok(())
9268            }
9269            OutputClause::Returning { select_items } => {
9270                f.write_str("RETURNING ")?;
9271                display_comma_separated(select_items).fmt(f)
9272            }
9273        }
9274    }
9275}
9276
9277#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9278#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9279#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9280pub enum DiscardObject {
9281    ALL,
9282    PLANS,
9283    SEQUENCES,
9284    TEMP,
9285}
9286
9287impl fmt::Display for DiscardObject {
9288    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9289        match self {
9290            DiscardObject::ALL => f.write_str("ALL"),
9291            DiscardObject::PLANS => f.write_str("PLANS"),
9292            DiscardObject::SEQUENCES => f.write_str("SEQUENCES"),
9293            DiscardObject::TEMP => f.write_str("TEMP"),
9294        }
9295    }
9296}
9297
9298#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9299#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9300#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9301pub enum FlushType {
9302    BinaryLogs,
9303    EngineLogs,
9304    ErrorLogs,
9305    GeneralLogs,
9306    Hosts,
9307    Logs,
9308    Privileges,
9309    OptimizerCosts,
9310    RelayLogs,
9311    SlowLogs,
9312    Status,
9313    UserResources,
9314    Tables,
9315}
9316
9317impl fmt::Display for FlushType {
9318    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9319        match self {
9320            FlushType::BinaryLogs => f.write_str("BINARY LOGS"),
9321            FlushType::EngineLogs => f.write_str("ENGINE LOGS"),
9322            FlushType::ErrorLogs => f.write_str("ERROR LOGS"),
9323            FlushType::GeneralLogs => f.write_str("GENERAL LOGS"),
9324            FlushType::Hosts => f.write_str("HOSTS"),
9325            FlushType::Logs => f.write_str("LOGS"),
9326            FlushType::Privileges => f.write_str("PRIVILEGES"),
9327            FlushType::OptimizerCosts => f.write_str("OPTIMIZER_COSTS"),
9328            FlushType::RelayLogs => f.write_str("RELAY LOGS"),
9329            FlushType::SlowLogs => f.write_str("SLOW LOGS"),
9330            FlushType::Status => f.write_str("STATUS"),
9331            FlushType::UserResources => f.write_str("USER_RESOURCES"),
9332            FlushType::Tables => f.write_str("TABLES"),
9333        }
9334    }
9335}
9336
9337#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9338#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9339#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9340pub enum FlushLocation {
9341    NoWriteToBinlog,
9342    Local,
9343}
9344
9345impl fmt::Display for FlushLocation {
9346    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9347        match self {
9348            FlushLocation::NoWriteToBinlog => f.write_str("NO_WRITE_TO_BINLOG"),
9349            FlushLocation::Local => f.write_str("LOCAL"),
9350        }
9351    }
9352}
9353
9354/// Optional context modifier for statements that can be or `LOCAL`, `GLOBAL`, or `SESSION`.
9355#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9356#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9357#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9358pub enum ContextModifier {
9359    /// `LOCAL` identifier, usually related to transactional states.
9360    Local,
9361    /// `SESSION` identifier
9362    Session,
9363    /// `GLOBAL` identifier
9364    Global,
9365}
9366
9367impl fmt::Display for ContextModifier {
9368    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9369        match self {
9370            Self::Local => {
9371                write!(f, "LOCAL ")
9372            }
9373            Self::Session => {
9374                write!(f, "SESSION ")
9375            }
9376            Self::Global => {
9377                write!(f, "GLOBAL ")
9378            }
9379        }
9380    }
9381}
9382
9383/// Function describe in DROP FUNCTION.
9384#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9385#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9386pub enum DropFunctionOption {
9387    Restrict,
9388    Cascade,
9389}
9390
9391impl fmt::Display for DropFunctionOption {
9392    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9393        match self {
9394            DropFunctionOption::Restrict => write!(f, "RESTRICT "),
9395            DropFunctionOption::Cascade => write!(f, "CASCADE  "),
9396        }
9397    }
9398}
9399
9400/// Generic function description for DROP FUNCTION and CREATE TRIGGER.
9401#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9402#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9403#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9404pub struct FunctionDesc {
9405    pub name: ObjectName,
9406    pub args: Option<Vec<OperateFunctionArg>>,
9407}
9408
9409impl fmt::Display for FunctionDesc {
9410    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9411        write!(f, "{}", self.name)?;
9412        if let Some(args) = &self.args {
9413            write!(f, "({})", display_comma_separated(args))?;
9414        }
9415        Ok(())
9416    }
9417}
9418
9419/// Function argument in CREATE OR DROP FUNCTION.
9420#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9421#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9422#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9423pub struct OperateFunctionArg {
9424    pub mode: Option<ArgMode>,
9425    pub name: Option<Ident>,
9426    pub data_type: DataType,
9427    pub default_expr: Option<Expr>,
9428}
9429
9430impl OperateFunctionArg {
9431    /// Returns an unnamed argument.
9432    pub fn unnamed(data_type: DataType) -> Self {
9433        Self {
9434            mode: None,
9435            name: None,
9436            data_type,
9437            default_expr: None,
9438        }
9439    }
9440
9441    /// Returns an argument with name.
9442    pub fn with_name(name: &str, data_type: DataType) -> Self {
9443        Self {
9444            mode: None,
9445            name: Some(name.into()),
9446            data_type,
9447            default_expr: None,
9448        }
9449    }
9450}
9451
9452impl fmt::Display for OperateFunctionArg {
9453    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9454        if let Some(mode) = &self.mode {
9455            write!(f, "{mode} ")?;
9456        }
9457        if let Some(name) = &self.name {
9458            write!(f, "{name} ")?;
9459        }
9460        write!(f, "{}", self.data_type)?;
9461        if let Some(default_expr) = &self.default_expr {
9462            write!(f, " = {default_expr}")?;
9463        }
9464        Ok(())
9465    }
9466}
9467
9468/// The mode of an argument in CREATE FUNCTION.
9469#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9470#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9471#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9472pub enum ArgMode {
9473    In,
9474    Out,
9475    InOut,
9476}
9477
9478impl fmt::Display for ArgMode {
9479    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9480        match self {
9481            ArgMode::In => write!(f, "IN"),
9482            ArgMode::Out => write!(f, "OUT"),
9483            ArgMode::InOut => write!(f, "INOUT"),
9484        }
9485    }
9486}
9487
9488/// These attributes inform the query optimizer about the behavior of the function.
9489#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9490#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9491#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9492pub enum FunctionBehavior {
9493    Immutable,
9494    Stable,
9495    Volatile,
9496}
9497
9498impl fmt::Display for FunctionBehavior {
9499    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9500        match self {
9501            FunctionBehavior::Immutable => write!(f, "IMMUTABLE"),
9502            FunctionBehavior::Stable => write!(f, "STABLE"),
9503            FunctionBehavior::Volatile => write!(f, "VOLATILE"),
9504        }
9505    }
9506}
9507
9508/// These attributes describe the behavior of the function when called with a null argument.
9509#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9510#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9511#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9512pub enum FunctionCalledOnNull {
9513    CalledOnNullInput,
9514    ReturnsNullOnNullInput,
9515    Strict,
9516}
9517
9518impl fmt::Display for FunctionCalledOnNull {
9519    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9520        match self {
9521            FunctionCalledOnNull::CalledOnNullInput => write!(f, "CALLED ON NULL INPUT"),
9522            FunctionCalledOnNull::ReturnsNullOnNullInput => write!(f, "RETURNS NULL ON NULL INPUT"),
9523            FunctionCalledOnNull::Strict => write!(f, "STRICT"),
9524        }
9525    }
9526}
9527
9528/// If it is safe for PostgreSQL to call the function from multiple threads at once
9529#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9530#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9531#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9532pub enum FunctionParallel {
9533    Unsafe,
9534    Restricted,
9535    Safe,
9536}
9537
9538impl fmt::Display for FunctionParallel {
9539    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9540        match self {
9541            FunctionParallel::Unsafe => write!(f, "PARALLEL UNSAFE"),
9542            FunctionParallel::Restricted => write!(f, "PARALLEL RESTRICTED"),
9543            FunctionParallel::Safe => write!(f, "PARALLEL SAFE"),
9544        }
9545    }
9546}
9547
9548/// [BigQuery] Determinism specifier used in a UDF definition.
9549///
9550/// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#syntax_11
9551#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9552#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9553#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9554pub enum FunctionDeterminismSpecifier {
9555    Deterministic,
9556    NotDeterministic,
9557}
9558
9559impl fmt::Display for FunctionDeterminismSpecifier {
9560    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9561        match self {
9562            FunctionDeterminismSpecifier::Deterministic => {
9563                write!(f, "DETERMINISTIC")
9564            }
9565            FunctionDeterminismSpecifier::NotDeterministic => {
9566                write!(f, "NOT DETERMINISTIC")
9567            }
9568        }
9569    }
9570}
9571
9572/// Represent the expression body of a `CREATE FUNCTION` statement as well as
9573/// where within the statement, the body shows up.
9574///
9575/// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#syntax_11
9576/// [PostgreSQL]: https://www.postgresql.org/docs/15/sql-createfunction.html
9577/// [MsSql]: https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql
9578#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9579#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9580#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9581pub enum CreateFunctionBody {
9582    /// A function body expression using the 'AS' keyword and shows up
9583    /// before any `OPTIONS` clause.
9584    ///
9585    /// Example:
9586    /// ```sql
9587    /// CREATE FUNCTION myfunc(x FLOAT64, y FLOAT64) RETURNS FLOAT64
9588    /// AS (x * y)
9589    /// OPTIONS(description="desc");
9590    /// ```
9591    ///
9592    /// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#syntax_11
9593    AsBeforeOptions(Expr),
9594    /// A function body expression using the 'AS' keyword and shows up
9595    /// after any `OPTIONS` clause.
9596    ///
9597    /// Example:
9598    /// ```sql
9599    /// CREATE FUNCTION myfunc(x FLOAT64, y FLOAT64) RETURNS FLOAT64
9600    /// OPTIONS(description="desc")
9601    /// AS (x * y);
9602    /// ```
9603    ///
9604    /// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#syntax_11
9605    AsAfterOptions(Expr),
9606    /// Function body with statements before the `RETURN` keyword.
9607    ///
9608    /// Example:
9609    /// ```sql
9610    /// CREATE FUNCTION my_scalar_udf(a INT, b INT)
9611    /// RETURNS INT
9612    /// AS
9613    /// BEGIN
9614    ///     DECLARE c INT;
9615    ///     SET c = a + b;
9616    ///     RETURN c;
9617    /// END
9618    /// ```
9619    ///
9620    /// [MsSql]: https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql
9621    AsBeginEnd(BeginEndStatements),
9622    /// Function body expression using the 'RETURN' keyword.
9623    ///
9624    /// Example:
9625    /// ```sql
9626    /// CREATE FUNCTION myfunc(a INTEGER, IN b INTEGER = 1) RETURNS INTEGER
9627    /// LANGUAGE SQL
9628    /// RETURN a + b;
9629    /// ```
9630    ///
9631    /// [PostgreSQL]: https://www.postgresql.org/docs/current/sql-createfunction.html
9632    Return(Expr),
9633
9634    /// Function body expression using the 'AS RETURN' keywords
9635    ///
9636    /// Example:
9637    /// ```sql
9638    /// CREATE FUNCTION myfunc(a INT, b INT)
9639    /// RETURNS TABLE
9640    /// AS RETURN (SELECT a + b AS sum);
9641    /// ```
9642    ///
9643    /// [MsSql]: https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql
9644    AsReturnExpr(Expr),
9645
9646    /// Function body expression using the 'AS RETURN' keywords, with an un-parenthesized SELECT query
9647    ///
9648    /// Example:
9649    /// ```sql
9650    /// CREATE FUNCTION myfunc(a INT, b INT)
9651    /// RETURNS TABLE
9652    /// AS RETURN SELECT a + b AS sum;
9653    /// ```
9654    ///
9655    /// [MsSql]: https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql?view=sql-server-ver16#select_stmt
9656    AsReturnSelect(Select),
9657}
9658
9659#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9660#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9661#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9662pub enum CreateFunctionUsing {
9663    Jar(String),
9664    File(String),
9665    Archive(String),
9666}
9667
9668impl fmt::Display for CreateFunctionUsing {
9669    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9670        write!(f, "USING ")?;
9671        match self {
9672            CreateFunctionUsing::Jar(uri) => write!(f, "JAR '{uri}'"),
9673            CreateFunctionUsing::File(uri) => write!(f, "FILE '{uri}'"),
9674            CreateFunctionUsing::Archive(uri) => write!(f, "ARCHIVE '{uri}'"),
9675        }
9676    }
9677}
9678
9679/// `NAME = <EXPR>` arguments for DuckDB macros
9680///
9681/// See [Create Macro - DuckDB](https://duckdb.org/docs/sql/statements/create_macro)
9682/// for more details
9683#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9684#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9685#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9686pub struct MacroArg {
9687    pub name: Ident,
9688    pub default_expr: Option<Expr>,
9689}
9690
9691impl MacroArg {
9692    /// Returns an argument with name.
9693    pub fn new(name: &str) -> Self {
9694        Self {
9695            name: name.into(),
9696            default_expr: None,
9697        }
9698    }
9699}
9700
9701impl fmt::Display for MacroArg {
9702    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9703        write!(f, "{}", self.name)?;
9704        if let Some(default_expr) = &self.default_expr {
9705            write!(f, " := {default_expr}")?;
9706        }
9707        Ok(())
9708    }
9709}
9710
9711#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9712#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9713#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9714pub enum MacroDefinition {
9715    Expr(Expr),
9716    Table(Box<Query>),
9717}
9718
9719impl fmt::Display for MacroDefinition {
9720    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9721        match self {
9722            MacroDefinition::Expr(expr) => write!(f, "{expr}")?,
9723            MacroDefinition::Table(query) => write!(f, "{query}")?,
9724        }
9725        Ok(())
9726    }
9727}
9728
9729/// Schema possible naming variants ([1]).
9730///
9731/// [1]: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#schema-definition
9732#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9733#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9734#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9735pub enum SchemaName {
9736    /// Only schema name specified: `<schema name>`.
9737    Simple(ObjectName),
9738    /// Only authorization identifier specified: `AUTHORIZATION <schema authorization identifier>`.
9739    UnnamedAuthorization(Ident),
9740    /// Both schema name and authorization identifier specified: `<schema name>  AUTHORIZATION <schema authorization identifier>`.
9741    NamedAuthorization(ObjectName, Ident),
9742}
9743
9744impl fmt::Display for SchemaName {
9745    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
9746        match self {
9747            SchemaName::Simple(name) => {
9748                write!(f, "{name}")
9749            }
9750            SchemaName::UnnamedAuthorization(authorization) => {
9751                write!(f, "AUTHORIZATION {authorization}")
9752            }
9753            SchemaName::NamedAuthorization(name, authorization) => {
9754                write!(f, "{name} AUTHORIZATION {authorization}")
9755            }
9756        }
9757    }
9758}
9759
9760/// Fulltext search modifiers ([1]).
9761///
9762/// [1]: https://dev.mysql.com/doc/refman/8.0/en/fulltext-search.html#function_match
9763#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9764#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9765#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9766pub enum SearchModifier {
9767    /// `IN NATURAL LANGUAGE MODE`.
9768    InNaturalLanguageMode,
9769    /// `IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION`.
9770    InNaturalLanguageModeWithQueryExpansion,
9771    ///`IN BOOLEAN MODE`.
9772    InBooleanMode,
9773    ///`WITH QUERY EXPANSION`.
9774    WithQueryExpansion,
9775}
9776
9777impl fmt::Display for SearchModifier {
9778    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
9779        match self {
9780            Self::InNaturalLanguageMode => {
9781                write!(f, "IN NATURAL LANGUAGE MODE")?;
9782            }
9783            Self::InNaturalLanguageModeWithQueryExpansion => {
9784                write!(f, "IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION")?;
9785            }
9786            Self::InBooleanMode => {
9787                write!(f, "IN BOOLEAN MODE")?;
9788            }
9789            Self::WithQueryExpansion => {
9790                write!(f, "WITH QUERY EXPANSION")?;
9791            }
9792        }
9793
9794        Ok(())
9795    }
9796}
9797
9798#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9799#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9800#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9801pub struct LockTable {
9802    pub table: Ident,
9803    pub alias: Option<Ident>,
9804    pub lock_type: LockTableType,
9805}
9806
9807impl fmt::Display for LockTable {
9808    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
9809        let Self {
9810            table: tbl_name,
9811            alias,
9812            lock_type,
9813        } = self;
9814
9815        write!(f, "{tbl_name} ")?;
9816        if let Some(alias) = alias {
9817            write!(f, "AS {alias} ")?;
9818        }
9819        write!(f, "{lock_type}")?;
9820        Ok(())
9821    }
9822}
9823
9824#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9825#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9826#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9827pub enum LockTableType {
9828    Read { local: bool },
9829    Write { low_priority: bool },
9830}
9831
9832impl fmt::Display for LockTableType {
9833    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
9834        match self {
9835            Self::Read { local } => {
9836                write!(f, "READ")?;
9837                if *local {
9838                    write!(f, " LOCAL")?;
9839                }
9840            }
9841            Self::Write { low_priority } => {
9842                if *low_priority {
9843                    write!(f, "LOW_PRIORITY ")?;
9844                }
9845                write!(f, "WRITE")?;
9846            }
9847        }
9848
9849        Ok(())
9850    }
9851}
9852
9853#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9854#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9855#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9856pub struct HiveSetLocation {
9857    pub has_set: bool,
9858    pub location: Ident,
9859}
9860
9861impl fmt::Display for HiveSetLocation {
9862    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
9863        if self.has_set {
9864            write!(f, "SET ")?;
9865        }
9866        write!(f, "LOCATION {}", self.location)
9867    }
9868}
9869
9870/// MySQL `ALTER TABLE` only  [FIRST | AFTER column_name]
9871#[allow(clippy::large_enum_variant)]
9872#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9873#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9874#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9875pub enum MySQLColumnPosition {
9876    First,
9877    After(Ident),
9878}
9879
9880impl Display for MySQLColumnPosition {
9881    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9882        match self {
9883            MySQLColumnPosition::First => write!(f, "FIRST"),
9884            MySQLColumnPosition::After(ident) => {
9885                let column_name = &ident.value;
9886                write!(f, "AFTER {column_name}")
9887            }
9888        }
9889    }
9890}
9891
9892/// MySQL `CREATE VIEW` algorithm parameter: [ALGORITHM = {UNDEFINED | MERGE | TEMPTABLE}]
9893#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9894#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9895#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9896pub enum CreateViewAlgorithm {
9897    Undefined,
9898    Merge,
9899    TempTable,
9900}
9901
9902impl Display for CreateViewAlgorithm {
9903    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9904        match self {
9905            CreateViewAlgorithm::Undefined => write!(f, "UNDEFINED"),
9906            CreateViewAlgorithm::Merge => write!(f, "MERGE"),
9907            CreateViewAlgorithm::TempTable => write!(f, "TEMPTABLE"),
9908        }
9909    }
9910}
9911/// MySQL `CREATE VIEW` security parameter: [SQL SECURITY { DEFINER | INVOKER }]
9912#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9913#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9914#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9915pub enum CreateViewSecurity {
9916    Definer,
9917    Invoker,
9918}
9919
9920impl Display for CreateViewSecurity {
9921    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9922        match self {
9923            CreateViewSecurity::Definer => write!(f, "DEFINER"),
9924            CreateViewSecurity::Invoker => write!(f, "INVOKER"),
9925        }
9926    }
9927}
9928
9929/// [MySQL] `CREATE VIEW` additional parameters
9930///
9931/// [MySQL]: https://dev.mysql.com/doc/refman/9.1/en/create-view.html
9932#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9933#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9934#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9935pub struct CreateViewParams {
9936    pub algorithm: Option<CreateViewAlgorithm>,
9937    pub definer: Option<GranteeName>,
9938    pub security: Option<CreateViewSecurity>,
9939}
9940
9941impl Display for CreateViewParams {
9942    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
9943        let CreateViewParams {
9944            algorithm,
9945            definer,
9946            security,
9947        } = self;
9948        if let Some(algorithm) = algorithm {
9949            write!(f, "ALGORITHM = {algorithm} ")?;
9950        }
9951        if let Some(definers) = definer {
9952            write!(f, "DEFINER = {definers} ")?;
9953        }
9954        if let Some(security) = security {
9955            write!(f, "SQL SECURITY {security} ")?;
9956        }
9957        Ok(())
9958    }
9959}
9960
9961#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9962#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9963#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9964/// Key/Value, where the value is a (optionally named) list of identifiers
9965///
9966/// ```sql
9967/// UNION = (tbl_name[,tbl_name]...)
9968/// ENGINE = ReplicatedMergeTree('/table_name','{replica}', ver)
9969/// ENGINE = SummingMergeTree([columns])
9970/// ```
9971pub struct NamedParenthesizedList {
9972    pub key: Ident,
9973    pub name: Option<Ident>,
9974    pub values: Vec<Ident>,
9975}
9976
9977/// Snowflake `WITH ROW ACCESS POLICY policy_name ON (identifier, ...)`
9978///
9979/// <https://docs.snowflake.com/en/sql-reference/sql/create-table>
9980/// <https://docs.snowflake.com/en/user-guide/security-row-intro>
9981#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9982#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9983#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9984pub struct RowAccessPolicy {
9985    pub policy: ObjectName,
9986    pub on: Vec<Ident>,
9987}
9988
9989impl RowAccessPolicy {
9990    pub fn new(policy: ObjectName, on: Vec<Ident>) -> Self {
9991        Self { policy, on }
9992    }
9993}
9994
9995impl Display for RowAccessPolicy {
9996    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9997        write!(
9998            f,
9999            "WITH ROW ACCESS POLICY {} ON ({})",
10000            self.policy,
10001            display_comma_separated(self.on.as_slice())
10002        )
10003    }
10004}
10005
10006/// Snowflake `WITH TAG ( tag_name = '<tag_value>', ...)`
10007///
10008/// <https://docs.snowflake.com/en/sql-reference/sql/create-table>
10009#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10010#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10011#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10012pub struct Tag {
10013    pub key: ObjectName,
10014    pub value: String,
10015}
10016
10017impl Tag {
10018    pub fn new(key: ObjectName, value: String) -> Self {
10019        Self { key, value }
10020    }
10021}
10022
10023impl Display for Tag {
10024    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10025        write!(f, "{}='{}'", self.key, self.value)
10026    }
10027}
10028
10029/// Snowflake `WITH CONTACT ( purpose = contact [ , purpose = contact ...] )`
10030///
10031/// <https://docs.snowflake.com/en/sql-reference/sql/create-database>
10032#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10033#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10034#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10035pub struct ContactEntry {
10036    pub purpose: String,
10037    pub contact: String,
10038}
10039
10040impl Display for ContactEntry {
10041    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10042        write!(f, "{} = {}", self.purpose, self.contact)
10043    }
10044}
10045
10046/// Helper to indicate if a comment includes the `=` in the display form
10047#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10048#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10049#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10050pub enum CommentDef {
10051    /// Includes `=` when printing the comment, as `COMMENT = 'comment'`
10052    /// Does not include `=` when printing the comment, as `COMMENT 'comment'`
10053    WithEq(String),
10054    WithoutEq(String),
10055}
10056
10057impl Display for CommentDef {
10058    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10059        match self {
10060            CommentDef::WithEq(comment) | CommentDef::WithoutEq(comment) => write!(f, "{comment}"),
10061        }
10062    }
10063}
10064
10065/// Helper to indicate if a collection should be wrapped by a symbol in the display form
10066///
10067/// [`Display`] is implemented for every [`Vec<T>`] where `T: Display`.
10068/// The string output is a comma separated list for the vec items
10069///
10070/// # Examples
10071/// ```
10072/// # use sqlparser::ast::WrappedCollection;
10073/// let items = WrappedCollection::Parentheses(vec!["one", "two", "three"]);
10074/// assert_eq!("(one, two, three)", items.to_string());
10075///
10076/// let items = WrappedCollection::NoWrapping(vec!["one", "two", "three"]);
10077/// assert_eq!("one, two, three", items.to_string());
10078/// ```
10079#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10080#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10081#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10082pub enum WrappedCollection<T> {
10083    /// Print the collection without wrapping symbols, as `item, item, item`
10084    NoWrapping(T),
10085    /// Wraps the collection in Parentheses, as `(item, item, item)`
10086    Parentheses(T),
10087}
10088
10089impl<T> Display for WrappedCollection<Vec<T>>
10090where
10091    T: Display,
10092{
10093    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10094        match self {
10095            WrappedCollection::NoWrapping(inner) => {
10096                write!(f, "{}", display_comma_separated(inner.as_slice()))
10097            }
10098            WrappedCollection::Parentheses(inner) => {
10099                write!(f, "({})", display_comma_separated(inner.as_slice()))
10100            }
10101        }
10102    }
10103}
10104
10105/// Represents a single PostgreSQL utility option.
10106///
10107/// A utility option is a key-value pair where the key is an identifier (IDENT) and the value
10108/// can be one of the following:
10109/// - A number with an optional sign (`+` or `-`). Example: `+10`, `-10.2`, `3`
10110/// - A non-keyword string. Example: `option1`, `'option2'`, `"option3"`
10111/// - keyword: `TRUE`, `FALSE`, `ON` (`off` is also accept).
10112/// - Empty. Example: `ANALYZE` (identifier only)
10113///
10114/// Utility options are used in various PostgreSQL DDL statements, including statements such as
10115/// `CLUSTER`, `EXPLAIN`, `VACUUM`, and `REINDEX`. These statements format options as `( option [, ...] )`.
10116///
10117/// [CLUSTER](https://www.postgresql.org/docs/current/sql-cluster.html)
10118/// [EXPLAIN](https://www.postgresql.org/docs/current/sql-explain.html)
10119/// [VACUUM](https://www.postgresql.org/docs/current/sql-vacuum.html)
10120/// [REINDEX](https://www.postgresql.org/docs/current/sql-reindex.html)
10121///
10122/// For example, the `EXPLAIN` AND `VACUUM` statements with options might look like this:
10123/// ```sql
10124/// EXPLAIN (ANALYZE, VERBOSE TRUE, FORMAT TEXT) SELECT * FROM my_table;
10125///
10126/// VACUUM (VERBOSE, ANALYZE ON, PARALLEL 10) my_table;
10127/// ```
10128#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10129#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10130#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10131pub struct UtilityOption {
10132    pub name: Ident,
10133    pub arg: Option<Expr>,
10134}
10135
10136impl Display for UtilityOption {
10137    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10138        if let Some(ref arg) = self.arg {
10139            write!(f, "{} {}", self.name, arg)
10140        } else {
10141            write!(f, "{}", self.name)
10142        }
10143    }
10144}
10145
10146/// Represents the different options available for `SHOW`
10147/// statements to filter the results. Example from Snowflake:
10148/// <https://docs.snowflake.com/en/sql-reference/sql/show-tables>
10149#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10150#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10151#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10152pub struct ShowStatementOptions {
10153    pub show_in: Option<ShowStatementIn>,
10154    pub starts_with: Option<Value>,
10155    pub limit: Option<Expr>,
10156    pub limit_from: Option<Value>,
10157    pub filter_position: Option<ShowStatementFilterPosition>,
10158}
10159
10160impl Display for ShowStatementOptions {
10161    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10162        let (like_in_infix, like_in_suffix) = match &self.filter_position {
10163            Some(ShowStatementFilterPosition::Infix(filter)) => {
10164                (format!(" {filter}"), "".to_string())
10165            }
10166            Some(ShowStatementFilterPosition::Suffix(filter)) => {
10167                ("".to_string(), format!(" {filter}"))
10168            }
10169            None => ("".to_string(), "".to_string()),
10170        };
10171        write!(
10172            f,
10173            "{like_in_infix}{show_in}{starts_with}{limit}{from}{like_in_suffix}",
10174            show_in = match &self.show_in {
10175                Some(i) => format!(" {i}"),
10176                None => String::new(),
10177            },
10178            starts_with = match &self.starts_with {
10179                Some(s) => format!(" STARTS WITH {s}"),
10180                None => String::new(),
10181            },
10182            limit = match &self.limit {
10183                Some(l) => format!(" LIMIT {l}"),
10184                None => String::new(),
10185            },
10186            from = match &self.limit_from {
10187                Some(f) => format!(" FROM {f}"),
10188                None => String::new(),
10189            }
10190        )?;
10191        Ok(())
10192    }
10193}
10194
10195#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10196#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10197#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10198pub enum ShowStatementFilterPosition {
10199    Infix(ShowStatementFilter), // For example: SHOW COLUMNS LIKE '%name%' IN TABLE tbl
10200    Suffix(ShowStatementFilter), // For example: SHOW COLUMNS IN tbl LIKE '%name%'
10201}
10202
10203#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10204#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10205#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10206pub enum ShowStatementInParentType {
10207    Account,
10208    Database,
10209    Schema,
10210    Table,
10211    View,
10212}
10213
10214impl fmt::Display for ShowStatementInParentType {
10215    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10216        match self {
10217            ShowStatementInParentType::Account => write!(f, "ACCOUNT"),
10218            ShowStatementInParentType::Database => write!(f, "DATABASE"),
10219            ShowStatementInParentType::Schema => write!(f, "SCHEMA"),
10220            ShowStatementInParentType::Table => write!(f, "TABLE"),
10221            ShowStatementInParentType::View => write!(f, "VIEW"),
10222        }
10223    }
10224}
10225
10226#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10227#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10228#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10229pub struct ShowStatementIn {
10230    pub clause: ShowStatementInClause,
10231    pub parent_type: Option<ShowStatementInParentType>,
10232    #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
10233    pub parent_name: Option<ObjectName>,
10234}
10235
10236impl fmt::Display for ShowStatementIn {
10237    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10238        write!(f, "{}", self.clause)?;
10239        if let Some(parent_type) = &self.parent_type {
10240            write!(f, " {parent_type}")?;
10241        }
10242        if let Some(parent_name) = &self.parent_name {
10243            write!(f, " {parent_name}")?;
10244        }
10245        Ok(())
10246    }
10247}
10248
10249/// A Show Charset statement
10250#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10251#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10252#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10253pub struct ShowCharset {
10254    /// The statement can be written as `SHOW CHARSET` or `SHOW CHARACTER SET`
10255    /// true means CHARSET was used and false means CHARACTER SET was used
10256    pub is_shorthand: bool,
10257    pub filter: Option<ShowStatementFilter>,
10258}
10259
10260impl fmt::Display for ShowCharset {
10261    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10262        write!(f, "SHOW")?;
10263        if self.is_shorthand {
10264            write!(f, " CHARSET")?;
10265        } else {
10266            write!(f, " CHARACTER SET")?;
10267        }
10268        if self.filter.is_some() {
10269            write!(f, " {}", self.filter.as_ref().unwrap())?;
10270        }
10271        Ok(())
10272    }
10273}
10274
10275#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10276#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10277#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10278pub struct ShowObjects {
10279    pub terse: bool,
10280    pub show_options: ShowStatementOptions,
10281}
10282
10283/// MSSQL's json null clause
10284///
10285/// ```plaintext
10286/// <json_null_clause> ::=
10287///       NULL ON NULL
10288///     | ABSENT ON NULL
10289/// ```
10290///
10291/// <https://learn.microsoft.com/en-us/sql/t-sql/functions/json-object-transact-sql?view=sql-server-ver16#json_null_clause>
10292#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10293#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10294#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10295pub enum JsonNullClause {
10296    NullOnNull,
10297    AbsentOnNull,
10298}
10299
10300impl Display for JsonNullClause {
10301    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10302        match self {
10303            JsonNullClause::NullOnNull => write!(f, "NULL ON NULL"),
10304            JsonNullClause::AbsentOnNull => write!(f, "ABSENT ON NULL"),
10305        }
10306    }
10307}
10308
10309/// PostgreSQL JSON function RETURNING clause
10310///
10311/// Example:
10312/// ```sql
10313/// JSON_OBJECT('a': 1 RETURNING jsonb)
10314/// ```
10315#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10316#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10317#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10318pub struct JsonReturningClause {
10319    pub data_type: DataType,
10320}
10321
10322impl Display for JsonReturningClause {
10323    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10324        write!(f, "RETURNING {}", self.data_type)
10325    }
10326}
10327
10328/// rename object definition
10329#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10330#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10331#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10332pub struct RenameTable {
10333    pub old_name: ObjectName,
10334    pub new_name: ObjectName,
10335}
10336
10337impl fmt::Display for RenameTable {
10338    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10339        write!(f, "{} TO {}", self.old_name, self.new_name)?;
10340        Ok(())
10341    }
10342}
10343
10344/// Represents the referenced table in an `INSERT INTO` statement
10345#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10346#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10347#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10348pub enum TableObject {
10349    /// Table specified by name.
10350    /// Example:
10351    /// ```sql
10352    /// INSERT INTO my_table
10353    /// ```
10354    TableName(#[cfg_attr(feature = "visitor", visit(with = "visit_relation"))] ObjectName),
10355
10356    /// Table specified as a function.
10357    /// Example:
10358    /// ```sql
10359    /// INSERT INTO TABLE FUNCTION remote('localhost', default.simple_table)
10360    /// ```
10361    /// [Clickhouse](https://clickhouse.com/docs/en/sql-reference/table-functions)
10362    TableFunction(Function),
10363}
10364
10365impl fmt::Display for TableObject {
10366    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10367        match self {
10368            Self::TableName(table_name) => write!(f, "{table_name}"),
10369            Self::TableFunction(func) => write!(f, "FUNCTION {func}"),
10370        }
10371    }
10372}
10373
10374#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10375#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10376#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10377pub enum SetSessionParamKind {
10378    Generic(SetSessionParamGeneric),
10379    IdentityInsert(SetSessionParamIdentityInsert),
10380    Offsets(SetSessionParamOffsets),
10381    Statistics(SetSessionParamStatistics),
10382}
10383
10384impl fmt::Display for SetSessionParamKind {
10385    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10386        match self {
10387            SetSessionParamKind::Generic(x) => write!(f, "{x}"),
10388            SetSessionParamKind::IdentityInsert(x) => write!(f, "{x}"),
10389            SetSessionParamKind::Offsets(x) => write!(f, "{x}"),
10390            SetSessionParamKind::Statistics(x) => write!(f, "{x}"),
10391        }
10392    }
10393}
10394
10395#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10396#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10397#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10398pub struct SetSessionParamGeneric {
10399    pub names: Vec<String>,
10400    pub value: String,
10401}
10402
10403impl fmt::Display for SetSessionParamGeneric {
10404    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10405        write!(f, "{} {}", display_comma_separated(&self.names), self.value)
10406    }
10407}
10408
10409#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10410#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10411#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10412pub struct SetSessionParamIdentityInsert {
10413    pub obj: ObjectName,
10414    pub value: SessionParamValue,
10415}
10416
10417impl fmt::Display for SetSessionParamIdentityInsert {
10418    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10419        write!(f, "IDENTITY_INSERT {} {}", self.obj, self.value)
10420    }
10421}
10422
10423#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10424#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10425#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10426pub struct SetSessionParamOffsets {
10427    pub keywords: Vec<String>,
10428    pub value: SessionParamValue,
10429}
10430
10431impl fmt::Display for SetSessionParamOffsets {
10432    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10433        write!(
10434            f,
10435            "OFFSETS {} {}",
10436            display_comma_separated(&self.keywords),
10437            self.value
10438        )
10439    }
10440}
10441
10442#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10443#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10444#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10445pub struct SetSessionParamStatistics {
10446    pub topic: SessionParamStatsTopic,
10447    pub value: SessionParamValue,
10448}
10449
10450impl fmt::Display for SetSessionParamStatistics {
10451    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10452        write!(f, "STATISTICS {} {}", self.topic, self.value)
10453    }
10454}
10455
10456#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10457#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10458#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10459pub enum SessionParamStatsTopic {
10460    IO,
10461    Profile,
10462    Time,
10463    Xml,
10464}
10465
10466impl fmt::Display for SessionParamStatsTopic {
10467    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10468        match self {
10469            SessionParamStatsTopic::IO => write!(f, "IO"),
10470            SessionParamStatsTopic::Profile => write!(f, "PROFILE"),
10471            SessionParamStatsTopic::Time => write!(f, "TIME"),
10472            SessionParamStatsTopic::Xml => write!(f, "XML"),
10473        }
10474    }
10475}
10476
10477#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10478#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10479#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10480pub enum SessionParamValue {
10481    On,
10482    Off,
10483}
10484
10485impl fmt::Display for SessionParamValue {
10486    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10487        match self {
10488            SessionParamValue::On => write!(f, "ON"),
10489            SessionParamValue::Off => write!(f, "OFF"),
10490        }
10491    }
10492}
10493
10494/// Snowflake StorageSerializationPolicy for Iceberg Tables
10495/// ```sql
10496/// [ STORAGE_SERIALIZATION_POLICY = { COMPATIBLE | OPTIMIZED } ]
10497/// ```
10498///
10499/// <https://docs.snowflake.com/en/sql-reference/sql/create-iceberg-table>
10500#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10501#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10502#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10503pub enum StorageSerializationPolicy {
10504    Compatible,
10505    Optimized,
10506}
10507
10508impl Display for StorageSerializationPolicy {
10509    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10510        match self {
10511            StorageSerializationPolicy::Compatible => write!(f, "COMPATIBLE"),
10512            StorageSerializationPolicy::Optimized => write!(f, "OPTIMIZED"),
10513        }
10514    }
10515}
10516
10517/// Snowflake CatalogSyncNamespaceMode
10518/// ```sql
10519/// [ CATALOG_SYNC_NAMESPACE_MODE = { NEST | FLATTEN } ]
10520/// ```
10521///
10522/// <https://docs.snowflake.com/en/sql-reference/sql/create-database>
10523#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10524#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10525#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10526pub enum CatalogSyncNamespaceMode {
10527    Nest,
10528    Flatten,
10529}
10530
10531impl Display for CatalogSyncNamespaceMode {
10532    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10533        match self {
10534            CatalogSyncNamespaceMode::Nest => write!(f, "NEST"),
10535            CatalogSyncNamespaceMode::Flatten => write!(f, "FLATTEN"),
10536        }
10537    }
10538}
10539
10540/// Variants of the Snowflake `COPY INTO` statement
10541#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10542#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10543#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10544pub enum CopyIntoSnowflakeKind {
10545    /// Loads data from files to a table
10546    /// See: <https://docs.snowflake.com/en/sql-reference/sql/copy-into-table>
10547    Table,
10548    /// Unloads data from a table or query to external files
10549    /// See: <https://docs.snowflake.com/en/sql-reference/sql/copy-into-location>
10550    Location,
10551}
10552
10553#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10554#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10555#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10556pub struct PrintStatement {
10557    pub message: Box<Expr>,
10558}
10559
10560impl fmt::Display for PrintStatement {
10561    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10562        write!(f, "PRINT {}", self.message)
10563    }
10564}
10565
10566/// Represents a `Return` statement.
10567///
10568/// [MsSql triggers](https://learn.microsoft.com/en-us/sql/t-sql/statements/create-trigger-transact-sql)
10569/// [MsSql functions](https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql)
10570#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10571#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10572#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10573pub struct ReturnStatement {
10574    pub value: Option<ReturnStatementValue>,
10575}
10576
10577impl fmt::Display for ReturnStatement {
10578    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10579        match &self.value {
10580            Some(ReturnStatementValue::Expr(expr)) => write!(f, "RETURN {expr}"),
10581            None => write!(f, "RETURN"),
10582        }
10583    }
10584}
10585
10586/// Variants of a `RETURN` statement
10587#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10588#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10589#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10590pub enum ReturnStatementValue {
10591    Expr(Expr),
10592}
10593
10594/// Represents an `OPEN` statement.
10595#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10596#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10597#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10598pub struct OpenStatement {
10599    /// Cursor name
10600    pub cursor_name: Ident,
10601}
10602
10603impl fmt::Display for OpenStatement {
10604    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10605        write!(f, "OPEN {}", self.cursor_name)
10606    }
10607}
10608
10609/// Specifies Include / Exclude NULL within UNPIVOT command.
10610/// For example
10611/// `UNPIVOT (column1 FOR new_column IN (col3, col4, col5, col6))`
10612#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10613#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10614#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10615pub enum NullInclusion {
10616    IncludeNulls,
10617    ExcludeNulls,
10618}
10619
10620impl fmt::Display for NullInclusion {
10621    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10622        match self {
10623            NullInclusion::IncludeNulls => write!(f, "INCLUDE NULLS"),
10624            NullInclusion::ExcludeNulls => write!(f, "EXCLUDE NULLS"),
10625        }
10626    }
10627}
10628
10629/// Checks membership of a value in a JSON array
10630///
10631/// Syntax:
10632/// ```sql
10633/// <value> MEMBER OF(<array>)
10634/// ```
10635/// [MySQL](https://dev.mysql.com/doc/refman/8.4/en/json-search-functions.html#operator_member-of)
10636#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10637#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10638#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10639pub struct MemberOf {
10640    pub value: Box<Expr>,
10641    pub array: Box<Expr>,
10642}
10643
10644impl fmt::Display for MemberOf {
10645    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10646        write!(f, "{} MEMBER OF({})", self.value, self.array)
10647    }
10648}
10649
10650#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10651#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10652#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10653pub struct ExportData {
10654    pub options: Vec<SqlOption>,
10655    pub query: Box<Query>,
10656    pub connection: Option<ObjectName>,
10657}
10658
10659impl fmt::Display for ExportData {
10660    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10661        if let Some(connection) = &self.connection {
10662            write!(
10663                f,
10664                "EXPORT DATA WITH CONNECTION {connection} OPTIONS({}) AS {}",
10665                display_comma_separated(&self.options),
10666                self.query
10667            )
10668        } else {
10669            write!(
10670                f,
10671                "EXPORT DATA OPTIONS({}) AS {}",
10672                display_comma_separated(&self.options),
10673                self.query
10674            )
10675        }
10676    }
10677}
10678/// Creates a user
10679///
10680/// Syntax:
10681/// ```sql
10682/// CREATE [OR REPLACE] USER [IF NOT EXISTS] <name> [OPTIONS]
10683/// ```
10684///
10685/// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-user)
10686#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10687#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10688#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10689pub struct CreateUser {
10690    pub or_replace: bool,
10691    pub if_not_exists: bool,
10692    pub name: Ident,
10693    pub options: KeyValueOptions,
10694    pub with_tags: bool,
10695    pub tags: KeyValueOptions,
10696}
10697
10698impl fmt::Display for CreateUser {
10699    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10700        write!(f, "CREATE")?;
10701        if self.or_replace {
10702            write!(f, " OR REPLACE")?;
10703        }
10704        write!(f, " USER")?;
10705        if self.if_not_exists {
10706            write!(f, " IF NOT EXISTS")?;
10707        }
10708        write!(f, " {}", self.name)?;
10709        if !self.options.options.is_empty() {
10710            write!(f, " {}", self.options)?;
10711        }
10712        if !self.tags.options.is_empty() {
10713            if self.with_tags {
10714                write!(f, " WITH")?;
10715            }
10716            write!(f, " TAG ({})", self.tags)?;
10717        }
10718        Ok(())
10719    }
10720}
10721
10722/// Specifies how to create a new table based on an existing table's schema.
10723/// '''sql
10724/// CREATE TABLE new LIKE old ...
10725/// '''
10726#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10727#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10728#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10729pub enum CreateTableLikeKind {
10730    /// '''sql
10731    /// CREATE TABLE new (LIKE old ...)
10732    /// '''
10733    /// [Redshift](https://docs.aws.amazon.com/redshift/latest/dg/r_CREATE_TABLE_NEW.html)
10734    Parenthesized(CreateTableLike),
10735    /// '''sql
10736    /// CREATE TABLE new LIKE old ...
10737    /// '''
10738    /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-table#label-create-table-like)
10739    /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_table_like)
10740    Plain(CreateTableLike),
10741}
10742
10743#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10744#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10745#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10746pub enum CreateTableLikeDefaults {
10747    Including,
10748    Excluding,
10749}
10750
10751impl fmt::Display for CreateTableLikeDefaults {
10752    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10753        match self {
10754            CreateTableLikeDefaults::Including => write!(f, "INCLUDING DEFAULTS"),
10755            CreateTableLikeDefaults::Excluding => write!(f, "EXCLUDING DEFAULTS"),
10756        }
10757    }
10758}
10759
10760#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10761#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10762#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10763pub struct CreateTableLike {
10764    pub name: ObjectName,
10765    pub defaults: Option<CreateTableLikeDefaults>,
10766}
10767
10768impl fmt::Display for CreateTableLike {
10769    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10770        write!(f, "LIKE {}", self.name)?;
10771        if let Some(defaults) = &self.defaults {
10772            write!(f, " {defaults}")?;
10773        }
10774        Ok(())
10775    }
10776}
10777
10778/// Specifies the refresh mode for the dynamic table.
10779///
10780/// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-dynamic-table)
10781#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10782#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10783#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10784pub enum RefreshModeKind {
10785    Auto,
10786    Full,
10787    Incremental,
10788}
10789
10790impl fmt::Display for RefreshModeKind {
10791    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10792        match self {
10793            RefreshModeKind::Auto => write!(f, "AUTO"),
10794            RefreshModeKind::Full => write!(f, "FULL"),
10795            RefreshModeKind::Incremental => write!(f, "INCREMENTAL"),
10796        }
10797    }
10798}
10799
10800/// Specifies the behavior of the initial refresh of the dynamic table.
10801///
10802/// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-dynamic-table)
10803#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10804#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10805#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10806pub enum InitializeKind {
10807    OnCreate,
10808    OnSchedule,
10809}
10810
10811impl fmt::Display for InitializeKind {
10812    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10813        match self {
10814            InitializeKind::OnCreate => write!(f, "ON_CREATE"),
10815            InitializeKind::OnSchedule => write!(f, "ON_SCHEDULE"),
10816        }
10817    }
10818}
10819
10820/// Re-sorts rows and reclaims space in either a specified table or all tables in the current database
10821///
10822/// '''sql
10823/// VACUUM [ FULL | SORT ONLY | DELETE ONLY | REINDEX | RECLUSTER ] [ \[ table_name \] [ TO threshold PERCENT ] \[ BOOST \] ]
10824/// '''
10825/// [Redshift](https://docs.aws.amazon.com/redshift/latest/dg/r_VACUUM_command.html)
10826#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10827#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10828#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10829pub struct VacuumStatement {
10830    pub full: bool,
10831    pub sort_only: bool,
10832    pub delete_only: bool,
10833    pub reindex: bool,
10834    pub recluster: bool,
10835    pub table_name: Option<ObjectName>,
10836    pub threshold: Option<Value>,
10837    pub boost: bool,
10838}
10839
10840impl fmt::Display for VacuumStatement {
10841    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10842        write!(
10843            f,
10844            "VACUUM{}{}{}{}{}",
10845            if self.full { " FULL" } else { "" },
10846            if self.sort_only { " SORT ONLY" } else { "" },
10847            if self.delete_only { " DELETE ONLY" } else { "" },
10848            if self.reindex { " REINDEX" } else { "" },
10849            if self.recluster { " RECLUSTER" } else { "" },
10850        )?;
10851        if let Some(table_name) = &self.table_name {
10852            write!(f, " {table_name}")?;
10853        }
10854        if let Some(threshold) = &self.threshold {
10855            write!(f, " TO {threshold} PERCENT")?;
10856        }
10857        if self.boost {
10858            write!(f, " BOOST")?;
10859        }
10860        Ok(())
10861    }
10862}
10863
10864impl From<Set> for Statement {
10865    fn from(s: Set) -> Self {
10866        Self::Set(s)
10867    }
10868}
10869
10870impl From<Query> for Statement {
10871    fn from(q: Query) -> Self {
10872        Box::new(q).into()
10873    }
10874}
10875
10876impl From<Box<Query>> for Statement {
10877    fn from(q: Box<Query>) -> Self {
10878        Self::Query(q)
10879    }
10880}
10881
10882impl From<Insert> for Statement {
10883    fn from(i: Insert) -> Self {
10884        Self::Insert(i)
10885    }
10886}
10887
10888impl From<CaseStatement> for Statement {
10889    fn from(c: CaseStatement) -> Self {
10890        Self::Case(c)
10891    }
10892}
10893
10894impl From<IfStatement> for Statement {
10895    fn from(i: IfStatement) -> Self {
10896        Self::If(i)
10897    }
10898}
10899
10900impl From<WhileStatement> for Statement {
10901    fn from(w: WhileStatement) -> Self {
10902        Self::While(w)
10903    }
10904}
10905
10906impl From<RaiseStatement> for Statement {
10907    fn from(r: RaiseStatement) -> Self {
10908        Self::Raise(r)
10909    }
10910}
10911
10912impl From<Function> for Statement {
10913    fn from(f: Function) -> Self {
10914        Self::Call(f)
10915    }
10916}
10917
10918impl From<OpenStatement> for Statement {
10919    fn from(o: OpenStatement) -> Self {
10920        Self::Open(o)
10921    }
10922}
10923
10924impl From<Delete> for Statement {
10925    fn from(d: Delete) -> Self {
10926        Self::Delete(d)
10927    }
10928}
10929
10930impl From<CreateTable> for Statement {
10931    fn from(c: CreateTable) -> Self {
10932        Self::CreateTable(c)
10933    }
10934}
10935
10936impl From<CreateIndex> for Statement {
10937    fn from(c: CreateIndex) -> Self {
10938        Self::CreateIndex(c)
10939    }
10940}
10941
10942impl From<CreateServerStatement> for Statement {
10943    fn from(c: CreateServerStatement) -> Self {
10944        Self::CreateServer(c)
10945    }
10946}
10947
10948impl From<CreateConnector> for Statement {
10949    fn from(c: CreateConnector) -> Self {
10950        Self::CreateConnector(c)
10951    }
10952}
10953
10954impl From<AlterSchema> for Statement {
10955    fn from(a: AlterSchema) -> Self {
10956        Self::AlterSchema(a)
10957    }
10958}
10959
10960impl From<AlterType> for Statement {
10961    fn from(a: AlterType) -> Self {
10962        Self::AlterType(a)
10963    }
10964}
10965
10966impl From<DropDomain> for Statement {
10967    fn from(d: DropDomain) -> Self {
10968        Self::DropDomain(d)
10969    }
10970}
10971
10972impl From<ShowCharset> for Statement {
10973    fn from(s: ShowCharset) -> Self {
10974        Self::ShowCharset(s)
10975    }
10976}
10977
10978impl From<ShowObjects> for Statement {
10979    fn from(s: ShowObjects) -> Self {
10980        Self::ShowObjects(s)
10981    }
10982}
10983
10984impl From<Use> for Statement {
10985    fn from(u: Use) -> Self {
10986        Self::Use(u)
10987    }
10988}
10989
10990impl From<CreateFunction> for Statement {
10991    fn from(c: CreateFunction) -> Self {
10992        Self::CreateFunction(c)
10993    }
10994}
10995
10996impl From<CreateTrigger> for Statement {
10997    fn from(c: CreateTrigger) -> Self {
10998        Self::CreateTrigger(c)
10999    }
11000}
11001
11002impl From<DropTrigger> for Statement {
11003    fn from(d: DropTrigger) -> Self {
11004        Self::DropTrigger(d)
11005    }
11006}
11007
11008impl From<DenyStatement> for Statement {
11009    fn from(d: DenyStatement) -> Self {
11010        Self::Deny(d)
11011    }
11012}
11013
11014impl From<CreateDomain> for Statement {
11015    fn from(c: CreateDomain) -> Self {
11016        Self::CreateDomain(c)
11017    }
11018}
11019
11020impl From<RenameTable> for Statement {
11021    fn from(r: RenameTable) -> Self {
11022        vec![r].into()
11023    }
11024}
11025
11026impl From<Vec<RenameTable>> for Statement {
11027    fn from(r: Vec<RenameTable>) -> Self {
11028        Self::RenameTable(r)
11029    }
11030}
11031
11032impl From<PrintStatement> for Statement {
11033    fn from(p: PrintStatement) -> Self {
11034        Self::Print(p)
11035    }
11036}
11037
11038impl From<ReturnStatement> for Statement {
11039    fn from(r: ReturnStatement) -> Self {
11040        Self::Return(r)
11041    }
11042}
11043
11044impl From<ExportData> for Statement {
11045    fn from(e: ExportData) -> Self {
11046        Self::ExportData(e)
11047    }
11048}
11049
11050impl From<CreateUser> for Statement {
11051    fn from(c: CreateUser) -> Self {
11052        Self::CreateUser(c)
11053    }
11054}
11055
11056impl From<VacuumStatement> for Statement {
11057    fn from(v: VacuumStatement) -> Self {
11058        Self::Vacuum(v)
11059    }
11060}
11061
11062#[cfg(test)]
11063mod tests {
11064    use crate::tokenizer::Location;
11065
11066    use super::*;
11067
11068    #[test]
11069    fn test_window_frame_default() {
11070        let window_frame = WindowFrame::default();
11071        assert_eq!(WindowFrameBound::Preceding(None), window_frame.start_bound);
11072    }
11073
11074    #[test]
11075    fn test_grouping_sets_display() {
11076        // a and b in different group
11077        let grouping_sets = Expr::GroupingSets(vec![
11078            vec![Expr::Identifier(Ident::new("a"))],
11079            vec![Expr::Identifier(Ident::new("b"))],
11080        ]);
11081        assert_eq!("GROUPING SETS ((a), (b))", format!("{grouping_sets}"));
11082
11083        // a and b in the same group
11084        let grouping_sets = Expr::GroupingSets(vec![vec![
11085            Expr::Identifier(Ident::new("a")),
11086            Expr::Identifier(Ident::new("b")),
11087        ]]);
11088        assert_eq!("GROUPING SETS ((a, b))", format!("{grouping_sets}"));
11089
11090        // (a, b) and (c, d) in different group
11091        let grouping_sets = Expr::GroupingSets(vec![
11092            vec![
11093                Expr::Identifier(Ident::new("a")),
11094                Expr::Identifier(Ident::new("b")),
11095            ],
11096            vec![
11097                Expr::Identifier(Ident::new("c")),
11098                Expr::Identifier(Ident::new("d")),
11099            ],
11100        ]);
11101        assert_eq!("GROUPING SETS ((a, b), (c, d))", format!("{grouping_sets}"));
11102    }
11103
11104    #[test]
11105    fn test_rollup_display() {
11106        let rollup = Expr::Rollup(vec![vec![Expr::Identifier(Ident::new("a"))]]);
11107        assert_eq!("ROLLUP (a)", format!("{rollup}"));
11108
11109        let rollup = Expr::Rollup(vec![vec![
11110            Expr::Identifier(Ident::new("a")),
11111            Expr::Identifier(Ident::new("b")),
11112        ]]);
11113        assert_eq!("ROLLUP ((a, b))", format!("{rollup}"));
11114
11115        let rollup = Expr::Rollup(vec![
11116            vec![Expr::Identifier(Ident::new("a"))],
11117            vec![Expr::Identifier(Ident::new("b"))],
11118        ]);
11119        assert_eq!("ROLLUP (a, b)", format!("{rollup}"));
11120
11121        let rollup = Expr::Rollup(vec![
11122            vec![Expr::Identifier(Ident::new("a"))],
11123            vec![
11124                Expr::Identifier(Ident::new("b")),
11125                Expr::Identifier(Ident::new("c")),
11126            ],
11127            vec![Expr::Identifier(Ident::new("d"))],
11128        ]);
11129        assert_eq!("ROLLUP (a, (b, c), d)", format!("{rollup}"));
11130    }
11131
11132    #[test]
11133    fn test_cube_display() {
11134        let cube = Expr::Cube(vec![vec![Expr::Identifier(Ident::new("a"))]]);
11135        assert_eq!("CUBE (a)", format!("{cube}"));
11136
11137        let cube = Expr::Cube(vec![vec![
11138            Expr::Identifier(Ident::new("a")),
11139            Expr::Identifier(Ident::new("b")),
11140        ]]);
11141        assert_eq!("CUBE ((a, b))", format!("{cube}"));
11142
11143        let cube = Expr::Cube(vec![
11144            vec![Expr::Identifier(Ident::new("a"))],
11145            vec![Expr::Identifier(Ident::new("b"))],
11146        ]);
11147        assert_eq!("CUBE (a, b)", format!("{cube}"));
11148
11149        let cube = Expr::Cube(vec![
11150            vec![Expr::Identifier(Ident::new("a"))],
11151            vec![
11152                Expr::Identifier(Ident::new("b")),
11153                Expr::Identifier(Ident::new("c")),
11154            ],
11155            vec![Expr::Identifier(Ident::new("d"))],
11156        ]);
11157        assert_eq!("CUBE (a, (b, c), d)", format!("{cube}"));
11158    }
11159
11160    #[test]
11161    fn test_interval_display() {
11162        let interval = Expr::Interval(Interval {
11163            value: Box::new(Expr::Value(
11164                Value::SingleQuotedString(String::from("123:45.67")).with_empty_span(),
11165            )),
11166            leading_field: Some(DateTimeField::Minute),
11167            leading_precision: Some(10),
11168            last_field: Some(DateTimeField::Second),
11169            fractional_seconds_precision: Some(9),
11170        });
11171        assert_eq!(
11172            "INTERVAL '123:45.67' MINUTE (10) TO SECOND (9)",
11173            format!("{interval}"),
11174        );
11175
11176        let interval = Expr::Interval(Interval {
11177            value: Box::new(Expr::Value(
11178                Value::SingleQuotedString(String::from("5")).with_empty_span(),
11179            )),
11180            leading_field: Some(DateTimeField::Second),
11181            leading_precision: Some(1),
11182            last_field: None,
11183            fractional_seconds_precision: Some(3),
11184        });
11185        assert_eq!("INTERVAL '5' SECOND (1, 3)", format!("{interval}"));
11186    }
11187
11188    #[test]
11189    fn test_one_or_many_with_parens_deref() {
11190        use core::ops::Index;
11191
11192        let one = OneOrManyWithParens::One("a");
11193
11194        assert_eq!(one.deref(), &["a"]);
11195        assert_eq!(<OneOrManyWithParens<_> as Deref>::deref(&one), &["a"]);
11196
11197        assert_eq!(one[0], "a");
11198        assert_eq!(one.index(0), &"a");
11199        assert_eq!(
11200            <<OneOrManyWithParens<_> as Deref>::Target as Index<usize>>::index(&one, 0),
11201            &"a"
11202        );
11203
11204        assert_eq!(one.len(), 1);
11205        assert_eq!(<OneOrManyWithParens<_> as Deref>::Target::len(&one), 1);
11206
11207        let many1 = OneOrManyWithParens::Many(vec!["b"]);
11208
11209        assert_eq!(many1.deref(), &["b"]);
11210        assert_eq!(<OneOrManyWithParens<_> as Deref>::deref(&many1), &["b"]);
11211
11212        assert_eq!(many1[0], "b");
11213        assert_eq!(many1.index(0), &"b");
11214        assert_eq!(
11215            <<OneOrManyWithParens<_> as Deref>::Target as Index<usize>>::index(&many1, 0),
11216            &"b"
11217        );
11218
11219        assert_eq!(many1.len(), 1);
11220        assert_eq!(<OneOrManyWithParens<_> as Deref>::Target::len(&many1), 1);
11221
11222        let many2 = OneOrManyWithParens::Many(vec!["c", "d"]);
11223
11224        assert_eq!(many2.deref(), &["c", "d"]);
11225        assert_eq!(
11226            <OneOrManyWithParens<_> as Deref>::deref(&many2),
11227            &["c", "d"]
11228        );
11229
11230        assert_eq!(many2[0], "c");
11231        assert_eq!(many2.index(0), &"c");
11232        assert_eq!(
11233            <<OneOrManyWithParens<_> as Deref>::Target as Index<usize>>::index(&many2, 0),
11234            &"c"
11235        );
11236
11237        assert_eq!(many2[1], "d");
11238        assert_eq!(many2.index(1), &"d");
11239        assert_eq!(
11240            <<OneOrManyWithParens<_> as Deref>::Target as Index<usize>>::index(&many2, 1),
11241            &"d"
11242        );
11243
11244        assert_eq!(many2.len(), 2);
11245        assert_eq!(<OneOrManyWithParens<_> as Deref>::Target::len(&many2), 2);
11246    }
11247
11248    #[test]
11249    fn test_one_or_many_with_parens_as_ref() {
11250        let one = OneOrManyWithParens::One("a");
11251
11252        assert_eq!(one.as_ref(), &["a"]);
11253        assert_eq!(<OneOrManyWithParens<_> as AsRef<_>>::as_ref(&one), &["a"]);
11254
11255        let many1 = OneOrManyWithParens::Many(vec!["b"]);
11256
11257        assert_eq!(many1.as_ref(), &["b"]);
11258        assert_eq!(<OneOrManyWithParens<_> as AsRef<_>>::as_ref(&many1), &["b"]);
11259
11260        let many2 = OneOrManyWithParens::Many(vec!["c", "d"]);
11261
11262        assert_eq!(many2.as_ref(), &["c", "d"]);
11263        assert_eq!(
11264            <OneOrManyWithParens<_> as AsRef<_>>::as_ref(&many2),
11265            &["c", "d"]
11266        );
11267    }
11268
11269    #[test]
11270    fn test_one_or_many_with_parens_ref_into_iter() {
11271        let one = OneOrManyWithParens::One("a");
11272
11273        assert_eq!(Vec::from_iter(&one), vec![&"a"]);
11274
11275        let many1 = OneOrManyWithParens::Many(vec!["b"]);
11276
11277        assert_eq!(Vec::from_iter(&many1), vec![&"b"]);
11278
11279        let many2 = OneOrManyWithParens::Many(vec!["c", "d"]);
11280
11281        assert_eq!(Vec::from_iter(&many2), vec![&"c", &"d"]);
11282    }
11283
11284    #[test]
11285    fn test_one_or_many_with_parens_value_into_iter() {
11286        use core::iter::once;
11287
11288        //tests that our iterator implemented methods behaves exactly as it's inner iterator, at every step up to n calls to next/next_back
11289        fn test_steps<I>(ours: OneOrManyWithParens<usize>, inner: I, n: usize)
11290        where
11291            I: IntoIterator<Item = usize, IntoIter: DoubleEndedIterator + Clone> + Clone,
11292        {
11293            fn checks<I>(ours: OneOrManyWithParensIntoIter<usize>, inner: I)
11294            where
11295                I: Iterator<Item = usize> + Clone + DoubleEndedIterator,
11296            {
11297                assert_eq!(ours.size_hint(), inner.size_hint());
11298                assert_eq!(ours.clone().count(), inner.clone().count());
11299
11300                assert_eq!(
11301                    ours.clone().fold(1, |a, v| a + v),
11302                    inner.clone().fold(1, |a, v| a + v)
11303                );
11304
11305                assert_eq!(Vec::from_iter(ours.clone()), Vec::from_iter(inner.clone()));
11306                assert_eq!(
11307                    Vec::from_iter(ours.clone().rev()),
11308                    Vec::from_iter(inner.clone().rev())
11309                );
11310            }
11311
11312            let mut ours_next = ours.clone().into_iter();
11313            let mut inner_next = inner.clone().into_iter();
11314
11315            for _ in 0..n {
11316                checks(ours_next.clone(), inner_next.clone());
11317
11318                assert_eq!(ours_next.next(), inner_next.next());
11319            }
11320
11321            let mut ours_next_back = ours.clone().into_iter();
11322            let mut inner_next_back = inner.clone().into_iter();
11323
11324            for _ in 0..n {
11325                checks(ours_next_back.clone(), inner_next_back.clone());
11326
11327                assert_eq!(ours_next_back.next_back(), inner_next_back.next_back());
11328            }
11329
11330            let mut ours_mixed = ours.clone().into_iter();
11331            let mut inner_mixed = inner.clone().into_iter();
11332
11333            for i in 0..n {
11334                checks(ours_mixed.clone(), inner_mixed.clone());
11335
11336                if i % 2 == 0 {
11337                    assert_eq!(ours_mixed.next_back(), inner_mixed.next_back());
11338                } else {
11339                    assert_eq!(ours_mixed.next(), inner_mixed.next());
11340                }
11341            }
11342
11343            let mut ours_mixed2 = ours.into_iter();
11344            let mut inner_mixed2 = inner.into_iter();
11345
11346            for i in 0..n {
11347                checks(ours_mixed2.clone(), inner_mixed2.clone());
11348
11349                if i % 2 == 0 {
11350                    assert_eq!(ours_mixed2.next(), inner_mixed2.next());
11351                } else {
11352                    assert_eq!(ours_mixed2.next_back(), inner_mixed2.next_back());
11353                }
11354            }
11355        }
11356
11357        test_steps(OneOrManyWithParens::One(1), once(1), 3);
11358        test_steps(OneOrManyWithParens::Many(vec![2]), vec![2], 3);
11359        test_steps(OneOrManyWithParens::Many(vec![3, 4]), vec![3, 4], 4);
11360    }
11361
11362    // Tests that the position in the code of an `Ident` does not affect its
11363    // ordering.
11364    #[test]
11365    fn test_ident_ord() {
11366        let mut a = Ident::with_span(Span::new(Location::new(1, 1), Location::new(1, 1)), "a");
11367        let mut b = Ident::with_span(Span::new(Location::new(2, 2), Location::new(2, 2)), "b");
11368
11369        assert!(a < b);
11370        std::mem::swap(&mut a.span, &mut b.span);
11371        assert!(a < b);
11372    }
11373}