risingwave_sqlparser/ast/
mod.rs

1// Licensed under the Apache License, Version 2.0 (the "License");
2// you may not use this file except in compliance with the License.
3// You may obtain a copy of the License at
4//
5//     http://www.apache.org/licenses/LICENSE-2.0
6//
7// Unless required by applicable law or agreed to in writing, software
8// distributed under the License is distributed on an "AS IS" BASIS,
9// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10// See the License for the specific language governing permissions and
11// limitations under the License.
12
13//! SQL Abstract Syntax Tree (AST) types
14mod analyze;
15mod data_type;
16pub(crate) mod ddl;
17mod legacy_source;
18mod operator;
19mod query;
20mod statement;
21mod value;
22
23#[cfg(not(feature = "std"))]
24use alloc::{
25    boxed::Box,
26    string::{String, ToString},
27    vec::Vec,
28};
29use core::fmt;
30use core::fmt::Display;
31use std::collections::HashSet;
32use std::sync::Arc;
33
34use itertools::Itertools;
35#[cfg(feature = "serde")]
36use serde::{Deserialize, Serialize};
37use winnow::ModalResult;
38
39pub use self::data_type::{DataType, StructField};
40pub use self::ddl::{
41    AlterColumnOperation, AlterConnectionOperation, AlterDatabaseOperation, AlterFragmentOperation,
42    AlterFunctionOperation, AlterSchemaOperation, AlterSecretOperation, AlterTableOperation,
43    ColumnDef, ColumnOption, ColumnOptionDef, ReferentialAction, SourceWatermark, TableConstraint,
44    WebhookSourceInfo,
45};
46pub use self::legacy_source::{CompatibleFormatEncode, get_delimiter};
47pub use self::operator::{BinaryOperator, QualifiedOperator, UnaryOperator};
48pub use self::query::{
49    Corresponding, Cte, CteInner, Distinct, Fetch, Join, JoinConstraint, JoinOperator, LateralView,
50    NamedWindow, OrderByExpr, Query, Select, SelectItem, SetExpr, SetOperator, TableAlias,
51    TableFactor, TableWithJoins, Top, Values, With,
52};
53pub use self::statement::*;
54pub use self::value::{
55    ConnectionRefValue, CstyleEscapedString, DateTimeField, DollarQuotedString, JsonPredicateType,
56    SecretRefAsType, SecretRefValue, TrimWhereField, Value,
57};
58pub use crate::ast::analyze::AnalyzeTarget;
59pub use crate::ast::ddl::{
60    AlterIndexOperation, AlterSinkOperation, AlterSourceOperation, AlterSubscriptionOperation,
61    AlterViewOperation,
62};
63use crate::keywords::Keyword;
64use crate::parser::{IncludeOption, IncludeOptionItem, Parser, ParserError, StrError};
65use crate::tokenizer::Tokenizer;
66
67pub type RedactSqlOptionKeywordsRef = Arc<HashSet<String>>;
68
69task_local::task_local! {
70    pub static REDACT_SQL_OPTION_KEYWORDS: RedactSqlOptionKeywordsRef;
71}
72
73pub struct DisplaySeparated<'a, T>
74where
75    T: fmt::Display,
76{
77    slice: &'a [T],
78    sep: &'static str,
79}
80
81impl<T> fmt::Display for DisplaySeparated<'_, T>
82where
83    T: fmt::Display,
84{
85    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
86        let mut delim = "";
87        for t in self.slice {
88            write!(f, "{}", delim)?;
89            delim = self.sep;
90            write!(f, "{}", t)?;
91        }
92        Ok(())
93    }
94}
95
96pub fn display_separated<'a, T>(slice: &'a [T], sep: &'static str) -> DisplaySeparated<'a, T>
97where
98    T: fmt::Display,
99{
100    DisplaySeparated { slice, sep }
101}
102
103pub fn display_comma_separated<T>(slice: &[T]) -> DisplaySeparated<'_, T>
104where
105    T: fmt::Display,
106{
107    DisplaySeparated { slice, sep: ", " }
108}
109
110/// An identifier, decomposed into its value or character data and the quote style.
111#[derive(Debug, Clone, PartialEq, Eq, Hash)]
112#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
113pub struct Ident {
114    /// The value of the identifier without quotes.
115    pub(crate) value: String,
116    /// The starting quote if any. Valid quote characters are the single quote,
117    /// double quote, backtick, and opening square bracket.
118    pub(crate) quote_style: Option<char>,
119}
120
121impl Ident {
122    /// Create a new identifier with the given value and no quotes.
123    /// the given value must not be a empty string.
124    // FIXME: should avoid using this function unless it's a literal or for testing.
125    pub fn new_unchecked<S>(value: S) -> Self
126    where
127        S: Into<String>,
128    {
129        Ident {
130            value: value.into(),
131            quote_style: None,
132        }
133    }
134
135    /// Create a new quoted identifier with the given quote and value.
136    /// the given value must not be a empty string and the given quote must be in ['\'', '"', '`',
137    /// '['].
138    pub fn with_quote_unchecked<S>(quote: char, value: S) -> Self
139    where
140        S: Into<String>,
141    {
142        Ident {
143            value: value.into(),
144            quote_style: Some(quote),
145        }
146    }
147
148    /// Create a new quoted identifier with the given quote and value.
149    /// returns ParserError when the given string is empty or the given quote is illegal.
150    pub fn with_quote_check<S>(quote: char, value: S) -> Result<Ident, ParserError>
151    where
152        S: Into<String>,
153    {
154        let value_str = value.into();
155        if value_str.is_empty() {
156            return Err(ParserError::ParserError(format!(
157                "zero-length delimited identifier at or near \"{value_str}\""
158            )));
159        }
160
161        if !(quote == '\'' || quote == '"' || quote == '`' || quote == '[') {
162            return Err(ParserError::ParserError(
163                "unexpected quote style".to_owned(),
164            ));
165        }
166
167        Ok(Ident {
168            value: value_str,
169            quote_style: Some(quote),
170        })
171    }
172
173    /// Value after considering quote style
174    /// In certain places, double quotes can force case-sensitive, but not always
175    /// e.g. session variables.
176    pub fn real_value(&self) -> String {
177        match self.quote_style {
178            Some('"') => self.value.clone(),
179            _ => self.value.to_lowercase(),
180        }
181    }
182
183    /// Convert a real value back to Ident. Behaves the same as SQL function `quote_ident` or
184    /// `QuoteIdent` wrapper in `common` crate.
185    pub fn from_real_value(value: &str) -> Self {
186        let needs_quotes = value
187            .chars()
188            .any(|c| !matches!(c, 'a'..='z' | '0'..='9' | '_'));
189
190        if needs_quotes {
191            Self::with_quote_unchecked('"', value.replace('"', "\"\""))
192        } else {
193            Self::new_unchecked(value)
194        }
195    }
196
197    pub fn quote_style(&self) -> Option<char> {
198        self.quote_style
199    }
200}
201
202impl From<&str> for Ident {
203    fn from(value: &str) -> Self {
204        Self::from_real_value(value)
205    }
206}
207
208impl ParseTo for Ident {
209    fn parse_to(parser: &mut Parser<'_>) -> ModalResult<Self> {
210        parser.parse_identifier()
211    }
212}
213
214impl fmt::Display for Ident {
215    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
216        match self.quote_style {
217            Some(q) if q == '"' || q == '\'' || q == '`' => write!(f, "{}{}{}", q, self.value, q),
218            Some('[') => write!(f, "[{}]", self.value),
219            None => f.write_str(&self.value),
220            _ => panic!("unexpected quote style"),
221        }
222    }
223}
224
225/// A name of a table, view, custom type, etc., possibly multi-part, i.e. db.schema.obj
226///
227/// Is is ensured to be non-empty.
228#[derive(Debug, Clone, PartialEq, Eq, Hash)]
229#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
230pub struct ObjectName(pub Vec<Ident>);
231
232impl ObjectName {
233    pub fn real_value(&self) -> String {
234        self.0
235            .iter()
236            .map(|ident| ident.real_value())
237            .collect::<Vec<_>>()
238            .join(".")
239    }
240
241    pub fn from_test_str(s: &str) -> Self {
242        ObjectName::from(vec![s.into()])
243    }
244
245    pub fn base_name(&self) -> String {
246        self.0
247            .iter()
248            .last()
249            .expect("should have base name")
250            .real_value()
251    }
252}
253
254impl fmt::Display for ObjectName {
255    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
256        write!(f, "{}", display_separated(&self.0, "."))
257    }
258}
259
260impl ParseTo for ObjectName {
261    fn parse_to(p: &mut Parser<'_>) -> ModalResult<Self> {
262        p.parse_object_name()
263    }
264}
265
266impl From<Vec<Ident>> for ObjectName {
267    fn from(value: Vec<Ident>) -> Self {
268        Self(value)
269    }
270}
271
272/// For array type `ARRAY[..]` or `[..]`
273#[derive(Debug, Clone, PartialEq, Eq, Hash)]
274#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
275pub struct Array {
276    /// The list of expressions between brackets
277    pub elem: Vec<Expr>,
278
279    /// `true` for  `ARRAY[..]`, `false` for `[..]`
280    pub named: bool,
281}
282
283impl fmt::Display for Array {
284    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
285        write!(
286            f,
287            "{}[{}]",
288            if self.named { "ARRAY" } else { "" },
289            display_comma_separated(&self.elem)
290        )
291    }
292}
293
294/// An escape character, to represent '' or a single character.
295#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
296#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
297pub struct EscapeChar(Option<char>);
298
299impl EscapeChar {
300    pub fn escape(ch: char) -> Self {
301        Self(Some(ch))
302    }
303
304    pub fn empty() -> Self {
305        Self(None)
306    }
307}
308
309impl fmt::Display for EscapeChar {
310    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
311        match self.0 {
312            Some(ch) => write!(f, "{}", ch),
313            None => f.write_str(""),
314        }
315    }
316}
317
318/// An SQL expression of any type.
319///
320/// The parser does not distinguish between expressions of different types
321/// (e.g. boolean vs string), so the caller must handle expressions of
322/// inappropriate type, like `WHERE 1` or `SELECT 1=1`, as necessary.
323#[derive(Debug, Clone, PartialEq, Eq, Hash)]
324#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
325pub enum Expr {
326    /// Identifier e.g. table name or column name
327    Identifier(Ident),
328    /// Multi-part identifier, e.g. `table_alias.column` or `schema.table.col`
329    CompoundIdentifier(Vec<Ident>),
330    /// Struct-field identifier.
331    /// Expr is an arbitrary expression, returning either a table or a column.
332    /// Idents are consecutive field accesses.
333    /// e.g. `(table.v1).v2` or `(table).v1.v2`
334    ///
335    /// It must contain parentheses to be distinguished from a [`Expr::CompoundIdentifier`].
336    /// See also <https://www.postgresql.org/docs/current/rowtypes.html#ROWTYPES-ACCESSING>
337    ///
338    /// The left parentheses must be put at the beginning of the expression.
339    /// The first parenthesized part is the `expr` part, and the rest are flattened into `idents`.
340    /// e.g., `((v1).v2.v3).v4` is equivalent to `(v1).v2.v3.v4`.
341    FieldIdentifier(Box<Expr>, Vec<Ident>),
342    /// `IS NULL` operator
343    IsNull(Box<Expr>),
344    /// `IS NOT NULL` operator
345    IsNotNull(Box<Expr>),
346    /// `IS TRUE` operator
347    IsTrue(Box<Expr>),
348    /// `IS NOT TRUE` operator
349    IsNotTrue(Box<Expr>),
350    /// `IS FALSE` operator
351    IsFalse(Box<Expr>),
352    /// `IS NOT FALSE` operator
353    IsNotFalse(Box<Expr>),
354    /// `IS UNKNOWN` operator
355    IsUnknown(Box<Expr>),
356    /// `IS NOT UNKNOWN` operator
357    IsNotUnknown(Box<Expr>),
358    /// `IS DISTINCT FROM` operator
359    IsDistinctFrom(Box<Expr>, Box<Expr>),
360    /// `IS NOT DISTINCT FROM` operator
361    IsNotDistinctFrom(Box<Expr>, Box<Expr>),
362    /// ```text
363    /// IS [ NOT ] JSON [ VALUE | ARRAY | OBJECT | SCALAR ]
364    /// [ { WITH | WITHOUT } UNIQUE [ KEYS ] ]
365    /// ```
366    IsJson {
367        expr: Box<Expr>,
368        negated: bool,
369        item_type: JsonPredicateType,
370        unique_keys: bool,
371    },
372    /// `[ NOT ] IN (val1, val2, ...)`
373    InList {
374        expr: Box<Expr>,
375        list: Vec<Expr>,
376        negated: bool,
377    },
378    /// `[ NOT ] IN (SELECT ...)`
379    InSubquery {
380        expr: Box<Expr>,
381        subquery: Box<Query>,
382        negated: bool,
383    },
384    /// `<expr> [ NOT ] BETWEEN <low> AND <high>`
385    Between {
386        expr: Box<Expr>,
387        negated: bool,
388        low: Box<Expr>,
389        high: Box<Expr>,
390    },
391    /// LIKE
392    Like {
393        negated: bool,
394        expr: Box<Expr>,
395        pattern: Box<Expr>,
396        escape_char: Option<EscapeChar>,
397    },
398    /// ILIKE (case-insensitive LIKE)
399    ILike {
400        negated: bool,
401        expr: Box<Expr>,
402        pattern: Box<Expr>,
403        escape_char: Option<EscapeChar>,
404    },
405    /// `<expr> [ NOT ] SIMILAR TO <pat> ESCAPE <esc_text>`
406    SimilarTo {
407        negated: bool,
408        expr: Box<Expr>,
409        pattern: Box<Expr>,
410        escape_char: Option<EscapeChar>,
411    },
412    /// Binary operation e.g. `1 + 1` or `foo > bar`
413    BinaryOp {
414        left: Box<Expr>,
415        op: BinaryOperator,
416        right: Box<Expr>,
417    },
418    /// Some operation e.g. `foo > Some(bar)`, It will be wrapped in the right side of BinaryExpr
419    SomeOp(Box<Expr>),
420    /// ALL operation e.g. `foo > ALL(bar)`, It will be wrapped in the right side of BinaryExpr
421    AllOp(Box<Expr>),
422    /// Unary operation e.g. `NOT foo`
423    UnaryOp {
424        op: UnaryOperator,
425        expr: Box<Expr>,
426    },
427    /// CAST an expression to a different data type e.g. `CAST(foo AS VARCHAR)`
428    Cast {
429        expr: Box<Expr>,
430        data_type: DataType,
431    },
432    /// TRY_CAST an expression to a different data type e.g. `TRY_CAST(foo AS VARCHAR)`
433    //  this differs from CAST in the choice of how to implement invalid conversions
434    TryCast {
435        expr: Box<Expr>,
436        data_type: DataType,
437    },
438    /// AT TIME ZONE converts `timestamp without time zone` to/from `timestamp with time zone` with
439    /// explicitly specified zone
440    AtTimeZone {
441        timestamp: Box<Expr>,
442        time_zone: Box<Expr>,
443    },
444    /// `EXTRACT(DateTimeField FROM <expr>)`
445    Extract {
446        field: String,
447        expr: Box<Expr>,
448    },
449    /// `SUBSTRING(<expr> [FROM <expr>] [FOR <expr>])`
450    Substring {
451        expr: Box<Expr>,
452        substring_from: Option<Box<Expr>>,
453        substring_for: Option<Box<Expr>>,
454    },
455    /// `POSITION(<expr> IN <expr>)`
456    Position {
457        substring: Box<Expr>,
458        string: Box<Expr>,
459    },
460    /// `OVERLAY(<expr> PLACING <expr> FROM <expr> [ FOR <expr> ])`
461    Overlay {
462        expr: Box<Expr>,
463        new_substring: Box<Expr>,
464        start: Box<Expr>,
465        count: Option<Box<Expr>>,
466    },
467    /// `TRIM([BOTH | LEADING | TRAILING] [<expr>] FROM <expr>)`\
468    /// Or\
469    /// `TRIM([BOTH | LEADING | TRAILING] [FROM] <expr> [, <expr>])`
470    Trim {
471        expr: Box<Expr>,
472        // ([BOTH | LEADING | TRAILING], <expr>)
473        trim_where: Option<TrimWhereField>,
474        trim_what: Option<Box<Expr>>,
475    },
476    /// `expr COLLATE collation`
477    Collate {
478        expr: Box<Expr>,
479        collation: ObjectName,
480    },
481    /// Nested expression e.g. `(foo > bar)` or `(1)`
482    Nested(Box<Expr>),
483    /// A literal value, such as string, number, date or NULL
484    Value(Value),
485    /// Parameter Symbol e.g. `$1`, `$1::int`
486    Parameter {
487        index: u64,
488    },
489    /// A constant of form `<data_type> 'value'`.
490    /// This can represent ANSI SQL `DATE`, `TIME`, and `TIMESTAMP` literals (such as `DATE
491    /// '2020-01-01'`), as well as constants of other types (a non-standard PostgreSQL extension).
492    TypedString {
493        data_type: DataType,
494        value: String,
495    },
496    /// Scalar function call e.g. `LEFT(foo, 5)`
497    Function(Function),
498    /// `CASE [<operand>] WHEN <condition> THEN <result> ... [ELSE <result>] END`
499    ///
500    /// Note we only recognize a complete single expression as `<condition>`,
501    /// not `< 0` nor `1, 2, 3` as allowed in a `<simple when clause>` per
502    /// <https://jakewheat.github.io/sql-overview/sql-2011-foundation-grammar.html#simple-when-clause>
503    Case {
504        operand: Option<Box<Expr>>,
505        conditions: Vec<Expr>,
506        results: Vec<Expr>,
507        else_result: Option<Box<Expr>>,
508    },
509    /// An exists expression `EXISTS(SELECT ...)`, used in expressions like
510    /// `WHERE EXISTS (SELECT ...)`.
511    Exists(Box<Query>),
512    /// A parenthesized subquery `(SELECT ...)`, used in expression like
513    /// `SELECT (subquery) AS x` or `WHERE (subquery) = x`
514    Subquery(Box<Query>),
515    /// The `GROUPING SETS` expr.
516    GroupingSets(Vec<Vec<Expr>>),
517    /// The `CUBE` expr.
518    Cube(Vec<Vec<Expr>>),
519    /// The `ROLLUP` expr.
520    Rollup(Vec<Vec<Expr>>),
521    /// The `ROW` expr. The `ROW` keyword can be omitted,
522    Row(Vec<Expr>),
523    /// An array constructor `ARRAY[[2,3,4],[5,6,7]]`
524    Array(Array),
525    /// An array constructing subquery `ARRAY(SELECT 2 UNION SELECT 3)`
526    ArraySubquery(Box<Query>),
527    /// A subscript expression `arr[1]` or `map['a']`
528    Index {
529        obj: Box<Expr>,
530        index: Box<Expr>,
531    },
532    /// A slice expression `arr[1:3]`
533    ArrayRangeIndex {
534        obj: Box<Expr>,
535        start: Option<Box<Expr>>,
536        end: Option<Box<Expr>>,
537    },
538    LambdaFunction {
539        args: Vec<Ident>,
540        body: Box<Expr>,
541    },
542    Map {
543        entries: Vec<(Expr, Expr)>,
544    },
545}
546
547impl fmt::Display for Expr {
548    #[expect(clippy::disallowed_methods, reason = "use zip_eq")]
549    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
550        match self {
551            Expr::Identifier(s) => write!(f, "{}", s),
552            Expr::CompoundIdentifier(s) => write!(f, "{}", display_separated(s, ".")),
553            Expr::FieldIdentifier(ast, s) => write!(f, "({}).{}", ast, display_separated(s, ".")),
554            Expr::IsNull(ast) => write!(f, "{} IS NULL", ast),
555            Expr::IsNotNull(ast) => write!(f, "{} IS NOT NULL", ast),
556            Expr::IsTrue(ast) => write!(f, "{} IS TRUE", ast),
557            Expr::IsNotTrue(ast) => write!(f, "{} IS NOT TRUE", ast),
558            Expr::IsFalse(ast) => write!(f, "{} IS FALSE", ast),
559            Expr::IsNotFalse(ast) => write!(f, "{} IS NOT FALSE", ast),
560            Expr::IsUnknown(ast) => write!(f, "{} IS UNKNOWN", ast),
561            Expr::IsNotUnknown(ast) => write!(f, "{} IS NOT UNKNOWN", ast),
562            Expr::IsJson {
563                expr,
564                negated,
565                item_type,
566                unique_keys,
567            } => write!(
568                f,
569                "{} IS {}JSON{}{}",
570                expr,
571                if *negated { "NOT " } else { "" },
572                item_type,
573                if *unique_keys {
574                    " WITH UNIQUE KEYS"
575                } else {
576                    ""
577                },
578            ),
579            Expr::InList {
580                expr,
581                list,
582                negated,
583            } => write!(
584                f,
585                "{} {}IN ({})",
586                expr,
587                if *negated { "NOT " } else { "" },
588                display_comma_separated(list)
589            ),
590            Expr::InSubquery {
591                expr,
592                subquery,
593                negated,
594            } => write!(
595                f,
596                "{} {}IN ({})",
597                expr,
598                if *negated { "NOT " } else { "" },
599                subquery
600            ),
601            Expr::Between {
602                expr,
603                negated,
604                low,
605                high,
606            } => write!(
607                f,
608                "{} {}BETWEEN {} AND {}",
609                expr,
610                if *negated { "NOT " } else { "" },
611                low,
612                high
613            ),
614            Expr::Like {
615                negated,
616                expr,
617                pattern,
618                escape_char,
619            } => match escape_char {
620                Some(ch) => write!(
621                    f,
622                    "{} {}LIKE {} ESCAPE '{}'",
623                    expr,
624                    if *negated { "NOT " } else { "" },
625                    pattern,
626                    ch
627                ),
628                _ => write!(
629                    f,
630                    "{} {}LIKE {}",
631                    expr,
632                    if *negated { "NOT " } else { "" },
633                    pattern
634                ),
635            },
636            Expr::ILike {
637                negated,
638                expr,
639                pattern,
640                escape_char,
641            } => match escape_char {
642                Some(ch) => write!(
643                    f,
644                    "{} {}ILIKE {} ESCAPE '{}'",
645                    expr,
646                    if *negated { "NOT " } else { "" },
647                    pattern,
648                    ch
649                ),
650                _ => write!(
651                    f,
652                    "{} {}ILIKE {}",
653                    expr,
654                    if *negated { "NOT " } else { "" },
655                    pattern
656                ),
657            },
658            Expr::SimilarTo {
659                negated,
660                expr,
661                pattern,
662                escape_char,
663            } => match escape_char {
664                Some(ch) => write!(
665                    f,
666                    "{} {}SIMILAR TO {} ESCAPE '{}'",
667                    expr,
668                    if *negated { "NOT " } else { "" },
669                    pattern,
670                    ch
671                ),
672                _ => write!(
673                    f,
674                    "{} {}SIMILAR TO {}",
675                    expr,
676                    if *negated { "NOT " } else { "" },
677                    pattern
678                ),
679            },
680            Expr::BinaryOp { left, op, right } => write!(f, "{} {} {}", left, op, right),
681            Expr::SomeOp(expr) => write!(f, "SOME({})", expr),
682            Expr::AllOp(expr) => write!(f, "ALL({})", expr),
683            Expr::UnaryOp { op, expr } => {
684                write!(f, "{} {}", op, expr)
685            }
686            Expr::Cast { expr, data_type } => write!(f, "CAST({} AS {})", expr, data_type),
687            Expr::TryCast { expr, data_type } => write!(f, "TRY_CAST({} AS {})", expr, data_type),
688            Expr::AtTimeZone {
689                timestamp,
690                time_zone,
691            } => write!(f, "{} AT TIME ZONE {}", timestamp, time_zone),
692            Expr::Extract { field, expr } => write!(f, "EXTRACT({} FROM {})", field, expr),
693            Expr::Collate { expr, collation } => write!(f, "{} COLLATE {}", expr, collation),
694            Expr::Nested(ast) => write!(f, "({})", ast),
695            Expr::Value(v) => write!(f, "{}", v),
696            Expr::Parameter { index } => write!(f, "${}", index),
697            Expr::TypedString { data_type, value } => {
698                write!(f, "{}", data_type)?;
699                write!(f, " '{}'", &value::escape_single_quote_string(value))
700            }
701            Expr::Function(fun) => write!(f, "{}", fun),
702            Expr::Case {
703                operand,
704                conditions,
705                results,
706                else_result,
707            } => {
708                write!(f, "CASE")?;
709                if let Some(operand) = operand {
710                    write!(f, " {}", operand)?;
711                }
712                for (c, r) in conditions.iter().zip_eq(results) {
713                    write!(f, " WHEN {} THEN {}", c, r)?;
714                }
715
716                if let Some(else_result) = else_result {
717                    write!(f, " ELSE {}", else_result)?;
718                }
719                write!(f, " END")
720            }
721            Expr::Exists(s) => write!(f, "EXISTS ({})", s),
722            Expr::Subquery(s) => write!(f, "({})", s),
723            Expr::GroupingSets(sets) => {
724                write!(f, "GROUPING SETS (")?;
725                let mut sep = "";
726                for set in sets {
727                    write!(f, "{}", sep)?;
728                    sep = ", ";
729                    write!(f, "({})", display_comma_separated(set))?;
730                }
731                write!(f, ")")
732            }
733            Expr::Cube(sets) => {
734                write!(f, "CUBE (")?;
735                let mut sep = "";
736                for set in sets {
737                    write!(f, "{}", sep)?;
738                    sep = ", ";
739                    if set.len() == 1 {
740                        write!(f, "{}", set[0])?;
741                    } else {
742                        write!(f, "({})", display_comma_separated(set))?;
743                    }
744                }
745                write!(f, ")")
746            }
747            Expr::Rollup(sets) => {
748                write!(f, "ROLLUP (")?;
749                let mut sep = "";
750                for set in sets {
751                    write!(f, "{}", sep)?;
752                    sep = ", ";
753                    if set.len() == 1 {
754                        write!(f, "{}", set[0])?;
755                    } else {
756                        write!(f, "({})", display_comma_separated(set))?;
757                    }
758                }
759                write!(f, ")")
760            }
761            Expr::Substring {
762                expr,
763                substring_from,
764                substring_for,
765            } => {
766                write!(f, "SUBSTRING({}", expr)?;
767                if let Some(from_part) = substring_from {
768                    write!(f, " FROM {}", from_part)?;
769                }
770                if let Some(from_part) = substring_for {
771                    write!(f, " FOR {}", from_part)?;
772                }
773
774                write!(f, ")")
775            }
776            Expr::Position { substring, string } => {
777                write!(f, "POSITION({} IN {})", substring, string)
778            }
779            Expr::Overlay {
780                expr,
781                new_substring,
782                start,
783                count,
784            } => {
785                write!(f, "OVERLAY({}", expr)?;
786                write!(f, " PLACING {}", new_substring)?;
787                write!(f, " FROM {}", start)?;
788
789                if let Some(count_expr) = count {
790                    write!(f, " FOR {}", count_expr)?;
791                }
792
793                write!(f, ")")
794            }
795            Expr::IsDistinctFrom(a, b) => write!(f, "{} IS DISTINCT FROM {}", a, b),
796            Expr::IsNotDistinctFrom(a, b) => write!(f, "{} IS NOT DISTINCT FROM {}", a, b),
797            Expr::Trim {
798                expr,
799                trim_where,
800                trim_what,
801            } => {
802                write!(f, "TRIM(")?;
803                if let Some(ident) = trim_where {
804                    write!(f, "{} ", ident)?;
805                }
806                if let Some(trim_char) = trim_what {
807                    write!(f, "{} ", trim_char)?;
808                }
809                write!(f, "FROM {})", expr)
810            }
811            Expr::Row(exprs) => write!(
812                f,
813                "ROW({})",
814                exprs
815                    .iter()
816                    .map(|v| v.to_string())
817                    .collect::<Vec<String>>()
818                    .as_slice()
819                    .join(", ")
820            ),
821            Expr::Index { obj, index } => {
822                write!(f, "{}[{}]", obj, index)?;
823                Ok(())
824            }
825            Expr::ArrayRangeIndex { obj, start, end } => {
826                let start_str = match start {
827                    None => "".to_owned(),
828                    Some(start) => format!("{}", start),
829                };
830                let end_str = match end {
831                    None => "".to_owned(),
832                    Some(end) => format!("{}", end),
833                };
834                write!(f, "{}[{}:{}]", obj, start_str, end_str)?;
835                Ok(())
836            }
837            Expr::Array(exprs) => write!(f, "{}", exprs),
838            Expr::ArraySubquery(s) => write!(f, "ARRAY ({})", s),
839            Expr::LambdaFunction { args, body } => {
840                write!(
841                    f,
842                    "|{}| {}",
843                    args.iter().map(ToString::to_string).join(", "),
844                    body
845                )
846            }
847            Expr::Map { entries } => {
848                write!(
849                    f,
850                    "MAP {{{}}}",
851                    entries
852                        .iter()
853                        .map(|(k, v)| format!("{}: {}", k, v))
854                        .join(", ")
855                )
856            }
857        }
858    }
859}
860
861/// A window specification (i.e. `OVER (PARTITION BY .. ORDER BY .. etc.)`).
862/// This is used both for named window definitions and inline window specifications.
863#[derive(Debug, Clone, PartialEq, Eq, Hash)]
864#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
865pub struct WindowSpec {
866    pub partition_by: Vec<Expr>,
867    pub order_by: Vec<OrderByExpr>,
868    pub window_frame: Option<WindowFrame>,
869}
870
871/// A window definition that can appear in the OVER clause of a window function.
872/// This can be either an inline window specification or a reference to a named window.
873#[derive(Debug, Clone, PartialEq, Eq, Hash)]
874#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
875pub enum Window {
876    /// Inline window specification: `OVER (PARTITION BY ... ORDER BY ...)`
877    Spec(WindowSpec),
878    /// Named window reference: `OVER window_name`
879    Name(Ident),
880}
881
882impl fmt::Display for WindowSpec {
883    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
884        let mut delim = "";
885        if !self.partition_by.is_empty() {
886            delim = " ";
887            write!(
888                f,
889                "PARTITION BY {}",
890                display_comma_separated(&self.partition_by)
891            )?;
892        }
893        if !self.order_by.is_empty() {
894            f.write_str(delim)?;
895            delim = " ";
896            write!(f, "ORDER BY {}", display_comma_separated(&self.order_by))?;
897        }
898        if let Some(window_frame) = &self.window_frame {
899            f.write_str(delim)?;
900            window_frame.fmt(f)?;
901        }
902        Ok(())
903    }
904}
905
906impl fmt::Display for Window {
907    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
908        match self {
909            Window::Spec(spec) => write!(f, "({})", spec),
910            Window::Name(name) => write!(f, "{}", name),
911        }
912    }
913}
914
915/// Specifies the data processed by a window function, e.g.
916/// `RANGE UNBOUNDED PRECEDING` or `ROWS BETWEEN 5 PRECEDING AND CURRENT ROW`.
917///
918/// Note: The parser does not validate the specified bounds; the caller should
919/// reject invalid bounds like `ROWS UNBOUNDED FOLLOWING` before execution.
920#[derive(Debug, Clone, PartialEq, Eq, Hash)]
921#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
922pub struct WindowFrame {
923    pub units: WindowFrameUnits,
924    pub bounds: WindowFrameBounds,
925    pub exclusion: Option<WindowFrameExclusion>,
926}
927
928#[derive(Debug, Clone, PartialEq, Eq, Hash)]
929#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
930pub enum WindowFrameUnits {
931    Rows,
932    Range,
933    Groups,
934    Session,
935}
936
937#[derive(Debug, Clone, PartialEq, Eq, Hash)]
938#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
939pub enum WindowFrameBounds {
940    Bounds {
941        start: WindowFrameBound,
942        /// The right bound of the `BETWEEN .. AND` clause. The end bound of `None`
943        /// indicates the shorthand form (e.g. `ROWS 1 PRECEDING`), which must
944        /// behave the same as `end_bound = WindowFrameBound::CurrentRow`.
945        end: Option<WindowFrameBound>,
946    },
947    Gap(Box<Expr>),
948}
949
950impl fmt::Display for WindowFrame {
951    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
952        write!(f, "{} ", self.units)?;
953        match &self.bounds {
954            WindowFrameBounds::Bounds { start, end } => {
955                if let Some(end) = end {
956                    write!(f, "BETWEEN {} AND {}", start, end)
957                } else {
958                    write!(f, "{}", start)
959                }
960            }
961            WindowFrameBounds::Gap(gap) => {
962                write!(f, "WITH GAP {}", gap)
963            }
964        }
965    }
966}
967
968impl fmt::Display for WindowFrameUnits {
969    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
970        f.write_str(match self {
971            WindowFrameUnits::Rows => "ROWS",
972            WindowFrameUnits::Range => "RANGE",
973            WindowFrameUnits::Groups => "GROUPS",
974            WindowFrameUnits::Session => "SESSION",
975        })
976    }
977}
978
979/// Specifies [WindowFrame]'s `start_bound` and `end_bound`
980#[derive(Debug, Clone, PartialEq, Eq, Hash)]
981#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
982pub enum WindowFrameBound {
983    /// `CURRENT ROW`
984    CurrentRow,
985    /// `<offset> PRECEDING` or `UNBOUNDED PRECEDING`
986    Preceding(Option<Box<Expr>>),
987    /// `<offset> FOLLOWING` or `UNBOUNDED FOLLOWING`.
988    Following(Option<Box<Expr>>),
989}
990
991impl fmt::Display for WindowFrameBound {
992    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
993        match self {
994            WindowFrameBound::CurrentRow => f.write_str("CURRENT ROW"),
995            WindowFrameBound::Preceding(None) => f.write_str("UNBOUNDED PRECEDING"),
996            WindowFrameBound::Following(None) => f.write_str("UNBOUNDED FOLLOWING"),
997            WindowFrameBound::Preceding(Some(n)) => write!(f, "{} PRECEDING", n),
998            WindowFrameBound::Following(Some(n)) => write!(f, "{} FOLLOWING", n),
999        }
1000    }
1001}
1002
1003/// Frame exclusion option of [WindowFrame].
1004#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
1005#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1006pub enum WindowFrameExclusion {
1007    CurrentRow,
1008    Group,
1009    Ties,
1010    NoOthers,
1011}
1012
1013impl fmt::Display for WindowFrameExclusion {
1014    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1015        match self {
1016            WindowFrameExclusion::CurrentRow => f.write_str("EXCLUDE CURRENT ROW"),
1017            WindowFrameExclusion::Group => f.write_str("EXCLUDE GROUP"),
1018            WindowFrameExclusion::Ties => f.write_str("EXCLUDE TIES"),
1019            WindowFrameExclusion::NoOthers => f.write_str("EXCLUDE NO OTHERS"),
1020        }
1021    }
1022}
1023
1024#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1025#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1026pub enum AddDropSync {
1027    ADD,
1028    DROP,
1029    SYNC,
1030}
1031
1032impl fmt::Display for AddDropSync {
1033    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1034        match self {
1035            AddDropSync::SYNC => f.write_str("SYNC PARTITIONS"),
1036            AddDropSync::DROP => f.write_str("DROP PARTITIONS"),
1037            AddDropSync::ADD => f.write_str("ADD PARTITIONS"),
1038        }
1039    }
1040}
1041
1042#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1043#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1044pub enum ShowObject {
1045    Table { schema: Option<Ident> },
1046    InternalTable { schema: Option<Ident> },
1047    Database,
1048    Schema,
1049    View { schema: Option<Ident> },
1050    MaterializedView { schema: Option<Ident> },
1051    Source { schema: Option<Ident> },
1052    Sink { schema: Option<Ident> },
1053    Subscription { schema: Option<Ident> },
1054    Columns { table: ObjectName },
1055    Connection { schema: Option<Ident> },
1056    Secret { schema: Option<Ident> },
1057    Function { schema: Option<Ident> },
1058    Indexes { table: ObjectName },
1059    Cluster,
1060    Jobs,
1061    ProcessList,
1062    Cursor,
1063    SubscriptionCursor,
1064}
1065
1066#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1067#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1068pub struct JobIdents(pub Vec<u32>);
1069
1070impl fmt::Display for ShowObject {
1071    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1072        fn fmt_schema(schema: &Option<Ident>) -> String {
1073            if let Some(schema) = schema {
1074                format!(" FROM {}", schema.value)
1075            } else {
1076                "".to_owned()
1077            }
1078        }
1079
1080        match self {
1081            ShowObject::Database => f.write_str("DATABASES"),
1082            ShowObject::Schema => f.write_str("SCHEMAS"),
1083            ShowObject::Table { schema } => {
1084                write!(f, "TABLES{}", fmt_schema(schema))
1085            }
1086            ShowObject::InternalTable { schema } => {
1087                write!(f, "INTERNAL TABLES{}", fmt_schema(schema))
1088            }
1089            ShowObject::View { schema } => {
1090                write!(f, "VIEWS{}", fmt_schema(schema))
1091            }
1092            ShowObject::MaterializedView { schema } => {
1093                write!(f, "MATERIALIZED VIEWS{}", fmt_schema(schema))
1094            }
1095            ShowObject::Source { schema } => write!(f, "SOURCES{}", fmt_schema(schema)),
1096            ShowObject::Sink { schema } => write!(f, "SINKS{}", fmt_schema(schema)),
1097            ShowObject::Columns { table } => write!(f, "COLUMNS FROM {}", table),
1098            ShowObject::Connection { schema } => write!(f, "CONNECTIONS{}", fmt_schema(schema)),
1099            ShowObject::Function { schema } => write!(f, "FUNCTIONS{}", fmt_schema(schema)),
1100            ShowObject::Indexes { table } => write!(f, "INDEXES FROM {}", table),
1101            ShowObject::Cluster => {
1102                write!(f, "CLUSTER")
1103            }
1104            ShowObject::Jobs => write!(f, "JOBS"),
1105            ShowObject::ProcessList => write!(f, "PROCESSLIST"),
1106            ShowObject::Subscription { schema } => write!(f, "SUBSCRIPTIONS{}", fmt_schema(schema)),
1107            ShowObject::Secret { schema } => write!(f, "SECRETS{}", fmt_schema(schema)),
1108            ShowObject::Cursor => write!(f, "CURSORS"),
1109            ShowObject::SubscriptionCursor => write!(f, "SUBSCRIPTION CURSORS"),
1110        }
1111    }
1112}
1113
1114#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1115#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1116pub enum ShowCreateType {
1117    Table,
1118    MaterializedView,
1119    View,
1120    Index,
1121    Source,
1122    Sink,
1123    Function,
1124    Subscription,
1125}
1126
1127impl fmt::Display for ShowCreateType {
1128    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1129        match self {
1130            ShowCreateType::Table => f.write_str("TABLE"),
1131            ShowCreateType::MaterializedView => f.write_str("MATERIALIZED VIEW"),
1132            ShowCreateType::View => f.write_str("VIEW"),
1133            ShowCreateType::Index => f.write_str("INDEX"),
1134            ShowCreateType::Source => f.write_str("SOURCE"),
1135            ShowCreateType::Sink => f.write_str("SINK"),
1136            ShowCreateType::Function => f.write_str("FUNCTION"),
1137            ShowCreateType::Subscription => f.write_str("SUBSCRIPTION"),
1138        }
1139    }
1140}
1141
1142#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1143#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1144pub enum CommentObject {
1145    Column,
1146    Table,
1147}
1148
1149impl fmt::Display for CommentObject {
1150    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1151        match self {
1152            CommentObject::Column => f.write_str("COLUMN"),
1153            CommentObject::Table => f.write_str("TABLE"),
1154        }
1155    }
1156}
1157
1158#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
1159#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1160pub enum ExplainType {
1161    Logical,
1162    Physical,
1163    DistSql,
1164}
1165
1166impl fmt::Display for ExplainType {
1167    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1168        match self {
1169            ExplainType::Logical => f.write_str("Logical"),
1170            ExplainType::Physical => f.write_str("Physical"),
1171            ExplainType::DistSql => f.write_str("DistSQL"),
1172        }
1173    }
1174}
1175
1176#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
1177#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1178pub enum ExplainFormat {
1179    Text,
1180    Json,
1181    Xml,
1182    Yaml,
1183    Dot,
1184}
1185
1186impl fmt::Display for ExplainFormat {
1187    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1188        match self {
1189            ExplainFormat::Text => f.write_str("TEXT"),
1190            ExplainFormat::Json => f.write_str("JSON"),
1191            ExplainFormat::Xml => f.write_str("XML"),
1192            ExplainFormat::Yaml => f.write_str("YAML"),
1193            ExplainFormat::Dot => f.write_str("DOT"),
1194        }
1195    }
1196}
1197
1198#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
1199#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1200pub struct ExplainOptions {
1201    /// Display additional information regarding the plan.
1202    pub verbose: bool,
1203    // Trace plan transformation of the optimizer step by step
1204    pub trace: bool,
1205    // Display backfill order
1206    pub backfill: bool,
1207    // explain's plan type
1208    pub explain_type: ExplainType,
1209    // explain's plan format
1210    pub explain_format: ExplainFormat,
1211}
1212
1213impl Default for ExplainOptions {
1214    fn default() -> Self {
1215        Self {
1216            verbose: false,
1217            trace: false,
1218            backfill: false,
1219            explain_type: ExplainType::Physical,
1220            explain_format: ExplainFormat::Text,
1221        }
1222    }
1223}
1224
1225impl fmt::Display for ExplainOptions {
1226    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1227        let default = Self::default();
1228        if *self == default {
1229            Ok(())
1230        } else {
1231            let mut option_strs = vec![];
1232            if self.verbose {
1233                option_strs.push("VERBOSE".to_owned());
1234            }
1235            if self.trace {
1236                option_strs.push("TRACE".to_owned());
1237            }
1238            if self.backfill {
1239                option_strs.push("BACKFILL".to_owned());
1240            }
1241            if self.explain_type == default.explain_type {
1242                option_strs.push(self.explain_type.to_string());
1243            }
1244            if self.explain_format == default.explain_format {
1245                option_strs.push(self.explain_format.to_string());
1246            }
1247            write!(f, "{}", option_strs.iter().format(","))
1248        }
1249    }
1250}
1251
1252#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1253#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1254pub struct CdcTableInfo {
1255    pub source_name: ObjectName,
1256    pub external_table_name: String,
1257}
1258
1259#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1260#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1261pub enum CopyEntity {
1262    Query(Box<Query>),
1263    Table {
1264        /// TABLE
1265        table_name: ObjectName,
1266        /// COLUMNS
1267        columns: Vec<Ident>,
1268    },
1269}
1270
1271#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1272#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1273pub enum CopyTarget {
1274    Stdin {
1275        /// VALUES a vector of values to be copied
1276        values: Vec<Option<String>>,
1277    },
1278    Stdout,
1279}
1280
1281/// A top-level statement (SELECT, INSERT, CREATE, etc.)
1282#[allow(clippy::large_enum_variant)]
1283#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1284#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1285pub enum Statement {
1286    /// Analyze (Hive)
1287    Analyze {
1288        table_name: ObjectName,
1289    },
1290    /// Truncate (Hive)
1291    Truncate {
1292        table_name: ObjectName,
1293    },
1294    /// Refresh table
1295    Refresh {
1296        table_name: ObjectName,
1297    },
1298    /// SELECT
1299    Query(Box<Query>),
1300    /// INSERT
1301    Insert {
1302        /// TABLE
1303        table_name: ObjectName,
1304        /// COLUMNS
1305        columns: Vec<Ident>,
1306        /// A SQL query that specifies what to insert
1307        source: Box<Query>,
1308        /// Define output of this insert statement
1309        returning: Vec<SelectItem>,
1310    },
1311    Copy {
1312        entity: CopyEntity,
1313        target: CopyTarget,
1314    },
1315    /// UPDATE
1316    Update {
1317        /// TABLE
1318        table_name: ObjectName,
1319        /// Column assignments
1320        assignments: Vec<Assignment>,
1321        /// WHERE
1322        selection: Option<Expr>,
1323        /// RETURNING
1324        returning: Vec<SelectItem>,
1325    },
1326    /// DELETE
1327    Delete {
1328        /// FROM
1329        table_name: ObjectName,
1330        /// WHERE
1331        selection: Option<Expr>,
1332        /// RETURNING
1333        returning: Vec<SelectItem>,
1334    },
1335    /// DISCARD
1336    Discard(DiscardType),
1337    /// CREATE VIEW
1338    CreateView {
1339        or_replace: bool,
1340        materialized: bool,
1341        if_not_exists: bool,
1342        /// View name
1343        name: ObjectName,
1344        columns: Vec<Ident>,
1345        query: Box<Query>,
1346        emit_mode: Option<EmitMode>,
1347        with_options: Vec<SqlOption>,
1348    },
1349    /// CREATE TABLE
1350    CreateTable {
1351        or_replace: bool,
1352        temporary: bool,
1353        if_not_exists: bool,
1354        /// Table name
1355        name: ObjectName,
1356        /// Optional schema
1357        columns: Vec<ColumnDef>,
1358        // The wildchar position in columns defined in sql. Only exist when using external schema.
1359        wildcard_idx: Option<usize>,
1360        constraints: Vec<TableConstraint>,
1361        with_options: Vec<SqlOption>,
1362        /// `FORMAT ... ENCODE ...` for table with connector
1363        format_encode: Option<CompatibleFormatEncode>,
1364        /// The watermark defined on source.
1365        source_watermarks: Vec<SourceWatermark>,
1366        /// Append only table.
1367        append_only: bool,
1368        /// On conflict behavior
1369        on_conflict: Option<OnConflict>,
1370        /// with_version_columns behind on conflict - supports multiple version columns
1371        with_version_columns: Vec<Ident>,
1372        /// `AS ( query )`
1373        query: Option<Box<Query>>,
1374        /// `FROM cdc_source TABLE database_name.table_name`
1375        cdc_table_info: Option<CdcTableInfo>,
1376        /// `INCLUDE a AS b INCLUDE c`
1377        include_column_options: IncludeOption,
1378        /// `VALIDATE SECRET secure_secret_name AS secure_compare ()`
1379        webhook_info: Option<WebhookSourceInfo>,
1380        /// `Engine = [hummock | iceberg]`
1381        engine: Engine,
1382    },
1383    /// CREATE INDEX
1384    CreateIndex {
1385        /// index name
1386        name: ObjectName,
1387        table_name: ObjectName,
1388        columns: Vec<OrderByExpr>,
1389        method: Option<Ident>,
1390        include: Vec<Ident>,
1391        distributed_by: Vec<Expr>,
1392        unique: bool,
1393        if_not_exists: bool,
1394        with_properties: WithProperties,
1395    },
1396    /// CREATE SOURCE
1397    CreateSource {
1398        stmt: CreateSourceStatement,
1399    },
1400    /// CREATE SINK
1401    CreateSink {
1402        stmt: CreateSinkStatement,
1403    },
1404    /// CREATE SUBSCRIPTION
1405    CreateSubscription {
1406        stmt: CreateSubscriptionStatement,
1407    },
1408    /// CREATE CONNECTION
1409    CreateConnection {
1410        stmt: CreateConnectionStatement,
1411    },
1412    CreateSecret {
1413        stmt: CreateSecretStatement,
1414    },
1415    /// CREATE FUNCTION
1416    ///
1417    /// Postgres: <https://www.postgresql.org/docs/15/sql-createfunction.html>
1418    CreateFunction {
1419        or_replace: bool,
1420        temporary: bool,
1421        if_not_exists: bool,
1422        name: ObjectName,
1423        args: Option<Vec<OperateFunctionArg>>,
1424        returns: Option<CreateFunctionReturns>,
1425        /// Optional parameters.
1426        params: CreateFunctionBody,
1427        with_options: CreateFunctionWithOptions, // FIXME(eric): use Option<>
1428    },
1429    /// CREATE AGGREGATE
1430    ///
1431    /// Postgres: <https://www.postgresql.org/docs/15/sql-createaggregate.html>
1432    CreateAggregate {
1433        or_replace: bool,
1434        if_not_exists: bool,
1435        name: ObjectName,
1436        args: Vec<OperateFunctionArg>,
1437        returns: DataType,
1438        /// Optional parameters.
1439        append_only: bool,
1440        params: CreateFunctionBody,
1441    },
1442
1443    /// DECLARE CURSOR
1444    DeclareCursor {
1445        stmt: DeclareCursorStatement,
1446    },
1447
1448    // FETCH CURSOR
1449    FetchCursor {
1450        stmt: FetchCursorStatement,
1451    },
1452
1453    // CLOSE CURSOR
1454    CloseCursor {
1455        stmt: CloseCursorStatement,
1456    },
1457
1458    /// ALTER DATABASE
1459    AlterDatabase {
1460        name: ObjectName,
1461        operation: AlterDatabaseOperation,
1462    },
1463    /// ALTER SCHEMA
1464    AlterSchema {
1465        name: ObjectName,
1466        operation: AlterSchemaOperation,
1467    },
1468    /// ALTER TABLE
1469    AlterTable {
1470        /// Table name
1471        name: ObjectName,
1472        operation: AlterTableOperation,
1473    },
1474    /// ALTER INDEX
1475    AlterIndex {
1476        /// Index name
1477        name: ObjectName,
1478        operation: AlterIndexOperation,
1479    },
1480    /// ALTER VIEW
1481    AlterView {
1482        /// View name
1483        name: ObjectName,
1484        materialized: bool,
1485        operation: AlterViewOperation,
1486    },
1487    /// ALTER SINK
1488    AlterSink {
1489        /// Sink name
1490        name: ObjectName,
1491        operation: AlterSinkOperation,
1492    },
1493    AlterSubscription {
1494        name: ObjectName,
1495        operation: AlterSubscriptionOperation,
1496    },
1497    /// ALTER SOURCE
1498    AlterSource {
1499        /// Source name
1500        name: ObjectName,
1501        operation: AlterSourceOperation,
1502    },
1503    /// ALTER FUNCTION
1504    AlterFunction {
1505        /// Function name
1506        name: ObjectName,
1507        args: Option<Vec<OperateFunctionArg>>,
1508        operation: AlterFunctionOperation,
1509    },
1510    /// ALTER CONNECTION
1511    AlterConnection {
1512        /// Connection name
1513        name: ObjectName,
1514        operation: AlterConnectionOperation,
1515    },
1516    /// ALTER SECRET
1517    AlterSecret {
1518        /// Secret name
1519        name: ObjectName,
1520        with_options: Vec<SqlOption>,
1521        operation: AlterSecretOperation,
1522    },
1523    /// ALTER FRAGMENT
1524    AlterFragment {
1525        fragment_ids: Vec<u32>,
1526        operation: AlterFragmentOperation,
1527    },
1528    /// DESCRIBE relation
1529    /// ALTER DEFAULT PRIVILEGES
1530    AlterDefaultPrivileges {
1531        target_users: Option<Vec<Ident>>,
1532        schema_names: Option<Vec<ObjectName>>,
1533        operation: DefaultPrivilegeOperation,
1534    },
1535    /// DESCRIBE relation
1536    Describe {
1537        /// relation name
1538        name: ObjectName,
1539        kind: DescribeKind,
1540    },
1541    /// DESCRIBE FRAGMENT <fragment_id>
1542    DescribeFragment {
1543        fragment_id: u32,
1544    },
1545    /// SHOW OBJECT COMMAND
1546    ShowObjects {
1547        object: ShowObject,
1548        filter: Option<ShowStatementFilter>,
1549    },
1550    /// SHOW CREATE COMMAND
1551    ShowCreateObject {
1552        /// Show create object type
1553        create_type: ShowCreateType,
1554        /// Show create object name
1555        name: ObjectName,
1556    },
1557    ShowTransactionIsolationLevel,
1558    /// CANCEL JOBS COMMAND
1559    CancelJobs(JobIdents),
1560    /// KILL COMMAND
1561    /// Kill process in the show processlist.
1562    Kill(String),
1563    /// DROP
1564    Drop(DropStatement),
1565    /// DROP FUNCTION
1566    DropFunction {
1567        if_exists: bool,
1568        /// One or more function to drop
1569        func_desc: Vec<FunctionDesc>,
1570        /// `CASCADE` or `RESTRICT`
1571        option: Option<ReferentialAction>,
1572    },
1573    /// DROP AGGREGATE
1574    DropAggregate {
1575        if_exists: bool,
1576        /// One or more function to drop
1577        func_desc: Vec<FunctionDesc>,
1578        /// `CASCADE` or `RESTRICT`
1579        option: Option<ReferentialAction>,
1580    },
1581    /// `SET <variable>`
1582    ///
1583    /// Note: this is not a standard SQL statement, but it is supported by at
1584    /// least MySQL and PostgreSQL. Not all MySQL-specific syntactic forms are
1585    /// supported yet.
1586    SetVariable {
1587        local: bool,
1588        variable: Ident,
1589        value: SetVariableValue,
1590    },
1591    /// `SHOW <variable>`
1592    ///
1593    /// Note: this is a PostgreSQL-specific statement.
1594    ShowVariable {
1595        variable: Vec<Ident>,
1596    },
1597    /// `START TRANSACTION ...`
1598    StartTransaction {
1599        modes: Vec<TransactionMode>,
1600    },
1601    /// `BEGIN [ TRANSACTION | WORK ]`
1602    Begin {
1603        modes: Vec<TransactionMode>,
1604    },
1605    /// ABORT
1606    Abort,
1607    /// `SET TRANSACTION ...`
1608    SetTransaction {
1609        modes: Vec<TransactionMode>,
1610        snapshot: Option<Value>,
1611        session: bool,
1612    },
1613    /// `SET [ SESSION | LOCAL ] TIME ZONE { value | 'value' | LOCAL | DEFAULT }`
1614    SetTimeZone {
1615        local: bool,
1616        value: SetTimeZoneValue,
1617    },
1618    /// `COMMENT ON ...`
1619    ///
1620    /// Note: this is a PostgreSQL-specific statement.
1621    Comment {
1622        object_type: CommentObject,
1623        object_name: ObjectName,
1624        comment: Option<String>,
1625    },
1626    /// `COMMIT [ TRANSACTION | WORK ] [ AND [ NO ] CHAIN ]`
1627    Commit {
1628        chain: bool,
1629    },
1630    /// `ROLLBACK [ TRANSACTION | WORK ] [ AND [ NO ] CHAIN ]`
1631    Rollback {
1632        chain: bool,
1633    },
1634    /// CREATE SCHEMA
1635    CreateSchema {
1636        schema_name: ObjectName,
1637        if_not_exists: bool,
1638        owner: Option<ObjectName>,
1639    },
1640    /// CREATE DATABASE
1641    CreateDatabase {
1642        db_name: ObjectName,
1643        if_not_exists: bool,
1644        owner: Option<ObjectName>,
1645        resource_group: Option<SetVariableValue>,
1646        barrier_interval_ms: Option<u32>,
1647        checkpoint_frequency: Option<u64>,
1648    },
1649    /// GRANT privileges ON objects TO grantees
1650    Grant {
1651        privileges: Privileges,
1652        objects: GrantObjects,
1653        grantees: Vec<Ident>,
1654        with_grant_option: bool,
1655        granted_by: Option<Ident>,
1656    },
1657    /// REVOKE privileges ON objects FROM grantees
1658    Revoke {
1659        privileges: Privileges,
1660        objects: GrantObjects,
1661        grantees: Vec<Ident>,
1662        granted_by: Option<Ident>,
1663        revoke_grant_option: bool,
1664        cascade: bool,
1665    },
1666    /// `DEALLOCATE [ PREPARE ] { name | ALL }`
1667    ///
1668    /// Note: this is a PostgreSQL-specific statement.
1669    Deallocate {
1670        name: Option<Ident>,
1671        prepare: bool,
1672    },
1673    /// `EXECUTE name [ ( parameter [, ...] ) ]`
1674    ///
1675    /// Note: this is a PostgreSQL-specific statement.
1676    Execute {
1677        name: Ident,
1678        parameters: Vec<Expr>,
1679    },
1680    /// `PREPARE name [ ( data_type [, ...] ) ] AS statement`
1681    ///
1682    /// Note: this is a PostgreSQL-specific statement.
1683    Prepare {
1684        name: Ident,
1685        data_types: Vec<DataType>,
1686        statement: Box<Statement>,
1687    },
1688    /// EXPLAIN / DESCRIBE for select_statement
1689    Explain {
1690        /// Carry out the command and show actual run times and other statistics.
1691        analyze: bool,
1692        /// A SQL query that specifies what to explain
1693        statement: Box<Statement>,
1694        /// options of the explain statement
1695        options: ExplainOptions,
1696    },
1697    /// EXPLAIN ANALYZE for stream job
1698    /// We introduce a new statement rather than reuse `EXPLAIN` because
1699    /// the body of the statement is not an SQL query.
1700    /// TODO(kwannoel): Make profiling duration configurable: EXPLAIN ANALYZE (DURATION 1s) ...
1701    ExplainAnalyzeStreamJob {
1702        target: AnalyzeTarget,
1703        duration_secs: Option<u64>,
1704    },
1705    /// CREATE USER
1706    CreateUser(CreateUserStatement),
1707    /// ALTER USER
1708    AlterUser(AlterUserStatement),
1709    /// ALTER SYSTEM SET configuration_parameter { TO | = } { value | 'value' | DEFAULT }
1710    AlterSystem {
1711        param: Ident,
1712        value: SetVariableValue,
1713    },
1714    /// FLUSH the current barrier.
1715    ///
1716    /// Note: RisingWave specific statement.
1717    Flush,
1718    /// WAIT for ALL running stream jobs to finish.
1719    /// It will block the current session the condition is met.
1720    Wait,
1721    /// Trigger stream job recover
1722    Recover,
1723    /// `USE <db_name>`
1724    ///
1725    /// Note: this is a RisingWave specific statement and used to switch the current database.
1726    Use {
1727        db_name: ObjectName,
1728    },
1729    /// `VACUUM [FULL] [database_name][schema_name][object_name]`
1730    ///
1731    /// Note: this is a RisingWave specific statement for iceberg table/sink compaction.
1732    Vacuum {
1733        object_name: ObjectName,
1734        full: bool,
1735    },
1736}
1737
1738#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1739#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1740pub enum DescribeKind {
1741    /// `DESCRIBE <name>`
1742    Plain,
1743
1744    /// `DESCRIBE FRAGMENTS <name>`
1745    Fragments,
1746}
1747
1748impl fmt::Display for Statement {
1749    /// Converts(unparses) the statement to a SQL string.
1750    ///
1751    /// If the resulting SQL is not valid, this function will panic. Use
1752    /// [`Statement::try_to_string`] to get a `Result` instead.
1753    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1754        // Note: we ignore formatting options here.
1755        let sql = self
1756            .try_to_string()
1757            .expect("normalized SQL should be parsable");
1758        f.write_str(&sql)
1759    }
1760}
1761
1762impl Statement {
1763    /// Converts(unparses) the statement to a SQL string.
1764    ///
1765    /// If the resulting SQL is not valid, returns an error.
1766    pub fn try_to_string(&self) -> Result<String, ParserError> {
1767        let sql = self.to_string_unchecked();
1768
1769        // TODO(#20713): expand this check to all statements
1770        if matches!(
1771            self,
1772            Statement::CreateTable { .. } | Statement::CreateSource { .. }
1773        ) {
1774            let _ = Parser::parse_sql(&sql)?;
1775        }
1776        Ok(sql)
1777    }
1778
1779    /// Converts(unparses) the statement to a SQL string.
1780    ///
1781    /// The result may not be valid SQL if there's an implementation bug in the `Display`
1782    /// trait of any AST node. To avoid this, always prefer [`Statement::try_to_string`]
1783    /// to get a `Result`, or `to_string` which panics if the SQL is invalid.
1784    pub fn to_string_unchecked(&self) -> String {
1785        let mut buf = String::new();
1786        self.fmt_unchecked(&mut buf).unwrap();
1787        buf
1788    }
1789
1790    // NOTE: This function should not check the validity of the unparsed SQL (and panic).
1791    //       Thus, do not directly format a statement with `write!` or `format!`. Recursively
1792    //       call `fmt_unchecked` on the inner statements instead.
1793    //
1794    // Clippy thinks this function is too complicated, but it is painful to
1795    // split up without extracting structs for each `Statement` variant.
1796    #[allow(clippy::cognitive_complexity)]
1797    fn fmt_unchecked(&self, mut f: impl std::fmt::Write) -> fmt::Result {
1798        match self {
1799            Statement::Explain {
1800                analyze,
1801                statement,
1802                options,
1803            } => {
1804                write!(f, "EXPLAIN ")?;
1805
1806                if *analyze {
1807                    write!(f, "ANALYZE ")?;
1808                }
1809                write!(f, "{}", options)?;
1810
1811                statement.fmt_unchecked(f)
1812            }
1813            Statement::ExplainAnalyzeStreamJob {
1814                target,
1815                duration_secs,
1816            } => {
1817                write!(f, "EXPLAIN ANALYZE {}", target)?;
1818                if let Some(duration_secs) = duration_secs {
1819                    write!(f, " (DURATION_SECS {})", duration_secs)?;
1820                }
1821                Ok(())
1822            }
1823            Statement::Query(s) => write!(f, "{}", s),
1824            Statement::Truncate { table_name } => {
1825                write!(f, "TRUNCATE TABLE {}", table_name)?;
1826                Ok(())
1827            }
1828            Statement::Refresh { table_name } => {
1829                write!(f, "REFRESH TABLE {}", table_name)?;
1830                Ok(())
1831            }
1832            Statement::Analyze { table_name } => {
1833                write!(f, "ANALYZE TABLE {}", table_name)?;
1834                Ok(())
1835            }
1836            Statement::Describe { name, kind } => {
1837                write!(f, "DESCRIBE {}", name)?;
1838                match kind {
1839                    DescribeKind::Plain => {}
1840
1841                    DescribeKind::Fragments => {
1842                        write!(f, " FRAGMENTS")?;
1843                    }
1844                }
1845                Ok(())
1846            }
1847            Statement::DescribeFragment { fragment_id } => {
1848                write!(f, "DESCRIBE FRAGMENT {}", fragment_id)?;
1849                Ok(())
1850            }
1851            Statement::ShowObjects {
1852                object: show_object,
1853                filter,
1854            } => {
1855                write!(f, "SHOW {}", show_object)?;
1856                if let Some(filter) = filter {
1857                    write!(f, " {}", filter)?;
1858                }
1859                Ok(())
1860            }
1861            Statement::ShowCreateObject {
1862                create_type: show_type,
1863                name,
1864            } => {
1865                write!(f, "SHOW CREATE {} {}", show_type, name)?;
1866                Ok(())
1867            }
1868            Statement::ShowTransactionIsolationLevel => {
1869                write!(f, "SHOW TRANSACTION ISOLATION LEVEL")?;
1870                Ok(())
1871            }
1872            Statement::Insert {
1873                table_name,
1874                columns,
1875                source,
1876                returning,
1877            } => {
1878                write!(f, "INSERT INTO {table_name} ", table_name = table_name,)?;
1879                if !columns.is_empty() {
1880                    write!(f, "({}) ", display_comma_separated(columns))?;
1881                }
1882                write!(f, "{}", source)?;
1883                if !returning.is_empty() {
1884                    write!(f, " RETURNING ({})", display_comma_separated(returning))?;
1885                }
1886                Ok(())
1887            }
1888            Statement::Copy { entity, target } => {
1889                write!(f, "COPY ",)?;
1890                match entity {
1891                    CopyEntity::Query(query) => {
1892                        write!(f, "({})", query)?;
1893                    }
1894                    CopyEntity::Table {
1895                        table_name,
1896                        columns,
1897                    } => {
1898                        write!(f, "{}", table_name)?;
1899                        if !columns.is_empty() {
1900                            write!(f, " ({})", display_comma_separated(columns))?;
1901                        }
1902                    }
1903                }
1904
1905                match target {
1906                    CopyTarget::Stdin { values } => {
1907                        write!(f, " FROM STDIN; ")?;
1908                        if !values.is_empty() {
1909                            writeln!(f)?;
1910                            let mut delim = "";
1911                            for v in values {
1912                                write!(f, "{}", delim)?;
1913                                delim = "\t";
1914                                if let Some(v) = v {
1915                                    write!(f, "{}", v)?;
1916                                } else {
1917                                    write!(f, "\\N")?;
1918                                }
1919                            }
1920                        }
1921                        write!(f, "\n\\.")
1922                    }
1923                    CopyTarget::Stdout => {
1924                        write!(f, " TO STDOUT")
1925                    }
1926                }
1927            }
1928            Statement::Update {
1929                table_name,
1930                assignments,
1931                selection,
1932                returning,
1933            } => {
1934                write!(f, "UPDATE {}", table_name)?;
1935                if !assignments.is_empty() {
1936                    write!(f, " SET {}", display_comma_separated(assignments))?;
1937                }
1938                if let Some(selection) = selection {
1939                    write!(f, " WHERE {}", selection)?;
1940                }
1941                if !returning.is_empty() {
1942                    write!(f, " RETURNING ({})", display_comma_separated(returning))?;
1943                }
1944                Ok(())
1945            }
1946            Statement::Delete {
1947                table_name,
1948                selection,
1949                returning,
1950            } => {
1951                write!(f, "DELETE FROM {}", table_name)?;
1952                if let Some(selection) = selection {
1953                    write!(f, " WHERE {}", selection)?;
1954                }
1955                if !returning.is_empty() {
1956                    write!(f, " RETURNING {}", display_comma_separated(returning))?;
1957                }
1958                Ok(())
1959            }
1960            Statement::CreateDatabase {
1961                db_name,
1962                if_not_exists,
1963                owner,
1964                resource_group,
1965                barrier_interval_ms,
1966                checkpoint_frequency,
1967            } => {
1968                write!(f, "CREATE DATABASE")?;
1969                if *if_not_exists {
1970                    write!(f, " IF NOT EXISTS")?;
1971                }
1972                write!(f, " {}", db_name)?;
1973                if let Some(owner) = owner {
1974                    write!(f, " WITH OWNER = {}", owner)?;
1975                }
1976                if let Some(resource_group) = resource_group {
1977                    write!(f, " RESOURCE_GROUP = {}", resource_group)?;
1978                }
1979                if let Some(barrier_interval_ms) = barrier_interval_ms {
1980                    write!(f, " BARRIER_INTERVAL_MS = {}", barrier_interval_ms)?;
1981                }
1982                if let Some(checkpoint_frequency) = checkpoint_frequency {
1983                    write!(f, " CHECKPOINT_FREQUENCY = {}", checkpoint_frequency)?;
1984                }
1985
1986                Ok(())
1987            }
1988            Statement::CreateFunction {
1989                or_replace,
1990                temporary,
1991                if_not_exists,
1992                name,
1993                args,
1994                returns,
1995                params,
1996                with_options,
1997            } => {
1998                write!(
1999                    f,
2000                    "CREATE {or_replace}{temp}FUNCTION {if_not_exists}{name}",
2001                    temp = if *temporary { "TEMPORARY " } else { "" },
2002                    or_replace = if *or_replace { "OR REPLACE " } else { "" },
2003                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
2004                )?;
2005                if let Some(args) = args {
2006                    write!(f, "({})", display_comma_separated(args))?;
2007                }
2008                if let Some(return_type) = returns {
2009                    write!(f, " {}", return_type)?;
2010                }
2011                write!(f, "{params}")?;
2012                write!(f, "{with_options}")?;
2013                Ok(())
2014            }
2015            Statement::CreateAggregate {
2016                or_replace,
2017                if_not_exists,
2018                name,
2019                args,
2020                returns,
2021                append_only,
2022                params,
2023            } => {
2024                write!(
2025                    f,
2026                    "CREATE {or_replace}AGGREGATE {if_not_exists}{name}",
2027                    or_replace = if *or_replace { "OR REPLACE " } else { "" },
2028                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
2029                )?;
2030                write!(f, "({})", display_comma_separated(args))?;
2031                write!(f, " RETURNS {}", returns)?;
2032                if *append_only {
2033                    write!(f, " APPEND ONLY")?;
2034                }
2035                write!(f, "{params}")?;
2036                Ok(())
2037            }
2038            Statement::CreateView {
2039                name,
2040                or_replace,
2041                if_not_exists,
2042                columns,
2043                query,
2044                materialized,
2045                with_options,
2046                emit_mode,
2047            } => {
2048                write!(
2049                    f,
2050                    "CREATE {or_replace}{materialized}VIEW {if_not_exists}{name}",
2051                    or_replace = if *or_replace { "OR REPLACE " } else { "" },
2052                    materialized = if *materialized { "MATERIALIZED " } else { "" },
2053                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
2054                    name = name
2055                )?;
2056                if !with_options.is_empty() {
2057                    write!(f, " WITH ({})", display_comma_separated(with_options))?;
2058                }
2059                if !columns.is_empty() {
2060                    write!(f, " ({})", display_comma_separated(columns))?;
2061                }
2062                write!(f, " AS {}", query)?;
2063                if let Some(emit_mode) = emit_mode {
2064                    write!(f, " EMIT {}", emit_mode)?;
2065                }
2066                Ok(())
2067            }
2068            Statement::CreateTable {
2069                name,
2070                columns,
2071                wildcard_idx,
2072                constraints,
2073                with_options,
2074                or_replace,
2075                if_not_exists,
2076                temporary,
2077                format_encode,
2078                source_watermarks,
2079                append_only,
2080                on_conflict,
2081                with_version_columns,
2082                query,
2083                cdc_table_info,
2084                include_column_options,
2085                webhook_info,
2086                engine,
2087            } => {
2088                // We want to allow the following options
2089                // Empty column list, allowed by PostgreSQL:
2090                //   `CREATE TABLE t ()`
2091                // No columns provided for CREATE TABLE AS:
2092                //   `CREATE TABLE t AS SELECT a from t2`
2093                // Columns provided for CREATE TABLE AS:
2094                //   `CREATE TABLE t (a INT) AS SELECT a from t2`
2095                write!(
2096                    f,
2097                    "CREATE {or_replace}{temporary}TABLE {if_not_exists}{name}",
2098                    or_replace = if *or_replace { "OR REPLACE " } else { "" },
2099                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
2100                    temporary = if *temporary { "TEMPORARY " } else { "" },
2101                    name = name,
2102                )?;
2103                if !columns.is_empty() || !constraints.is_empty() {
2104                    write!(
2105                        f,
2106                        " {}",
2107                        fmt_create_items(columns, constraints, source_watermarks, *wildcard_idx)?
2108                    )?;
2109                } else if query.is_none() {
2110                    // PostgreSQL allows `CREATE TABLE t ();`, but requires empty parens
2111                    write!(f, " ()")?;
2112                }
2113                if *append_only {
2114                    write!(f, " APPEND ONLY")?;
2115                }
2116
2117                if let Some(on_conflict_behavior) = on_conflict {
2118                    write!(f, " ON CONFLICT {}", on_conflict_behavior)?;
2119                }
2120                if !with_version_columns.is_empty() {
2121                    write!(
2122                        f,
2123                        " WITH VERSION COLUMN({})",
2124                        display_comma_separated(with_version_columns)
2125                    )?;
2126                }
2127                if !include_column_options.is_empty() {
2128                    write!(f, " {}", display_separated(include_column_options, " "))?;
2129                }
2130                if !with_options.is_empty() {
2131                    write!(f, " WITH ({})", display_comma_separated(with_options))?;
2132                }
2133                if let Some(format_encode) = format_encode {
2134                    write!(f, " {}", format_encode)?;
2135                }
2136                if let Some(query) = query {
2137                    write!(f, " AS {}", query)?;
2138                }
2139                if let Some(info) = cdc_table_info {
2140                    write!(f, " FROM {}", info.source_name)?;
2141                    write!(f, " TABLE '{}'", info.external_table_name)?;
2142                }
2143                if let Some(info) = webhook_info {
2144                    if let Some(secret) = &info.secret_ref {
2145                        write!(f, " VALIDATE SECRET {}", secret.secret_name)?;
2146                    } else {
2147                        write!(f, " VALIDATE")?;
2148                    }
2149                    write!(f, " AS {}", info.signature_expr)?;
2150                }
2151                match engine {
2152                    Engine::Hummock => {}
2153                    Engine::Iceberg => {
2154                        write!(f, " ENGINE = {}", engine)?;
2155                    }
2156                }
2157                Ok(())
2158            }
2159            Statement::CreateIndex {
2160                name,
2161                table_name,
2162                columns,
2163                method,
2164                include,
2165                distributed_by,
2166                unique,
2167                if_not_exists,
2168                with_properties,
2169            } => write!(
2170                f,
2171                "CREATE {unique}INDEX {if_not_exists}{name} ON {table_name}{method}({columns}){include}{distributed_by}{with_properties}",
2172                unique = if *unique { "UNIQUE " } else { "" },
2173                if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
2174                name = name,
2175                table_name = table_name,
2176                method = if let Some(method) = method {
2177                    format!(" USING {} ", method)
2178                } else {
2179                    "".to_owned()
2180                },
2181                columns = display_comma_separated(columns),
2182                include = if include.is_empty() {
2183                    "".to_owned()
2184                } else {
2185                    format!(" INCLUDE({})", display_separated(include, ","))
2186                },
2187                distributed_by = if distributed_by.is_empty() {
2188                    "".to_owned()
2189                } else {
2190                    format!(
2191                        " DISTRIBUTED BY({})",
2192                        display_separated(distributed_by, ",")
2193                    )
2194                },
2195                with_properties = if !with_properties.0.is_empty() {
2196                    format!(" {}", with_properties)
2197                } else {
2198                    "".to_owned()
2199                },
2200            ),
2201            Statement::CreateSource { stmt } => write!(f, "CREATE SOURCE {}", stmt,),
2202            Statement::CreateSink { stmt } => write!(f, "CREATE SINK {}", stmt,),
2203            Statement::CreateSubscription { stmt } => write!(f, "CREATE SUBSCRIPTION {}", stmt,),
2204            Statement::CreateConnection { stmt } => write!(f, "CREATE CONNECTION {}", stmt,),
2205            Statement::DeclareCursor { stmt } => write!(f, "DECLARE {}", stmt,),
2206            Statement::FetchCursor { stmt } => write!(f, "FETCH {}", stmt),
2207            Statement::CloseCursor { stmt } => write!(f, "CLOSE {}", stmt),
2208            Statement::CreateSecret { stmt } => write!(f, "CREATE SECRET {}", stmt),
2209            Statement::AlterDatabase { name, operation } => {
2210                write!(f, "ALTER DATABASE {} {}", name, operation)
2211            }
2212            Statement::AlterSchema { name, operation } => {
2213                write!(f, "ALTER SCHEMA {} {}", name, operation)
2214            }
2215            Statement::AlterTable { name, operation } => {
2216                write!(f, "ALTER TABLE {} {}", name, operation)
2217            }
2218            Statement::AlterIndex { name, operation } => {
2219                write!(f, "ALTER INDEX {} {}", name, operation)
2220            }
2221            Statement::AlterView {
2222                materialized,
2223                name,
2224                operation,
2225            } => {
2226                write!(
2227                    f,
2228                    "ALTER {}VIEW {} {}",
2229                    if *materialized { "MATERIALIZED " } else { "" },
2230                    name,
2231                    operation
2232                )
2233            }
2234            Statement::AlterSink { name, operation } => {
2235                write!(f, "ALTER SINK {} {}", name, operation)
2236            }
2237            Statement::AlterSubscription { name, operation } => {
2238                write!(f, "ALTER SUBSCRIPTION {} {}", name, operation)
2239            }
2240            Statement::AlterSource { name, operation } => {
2241                write!(f, "ALTER SOURCE {} {}", name, operation)
2242            }
2243            Statement::AlterFunction {
2244                name,
2245                args,
2246                operation,
2247            } => {
2248                write!(f, "ALTER FUNCTION {}", name)?;
2249                if let Some(args) = args {
2250                    write!(f, "({})", display_comma_separated(args))?;
2251                }
2252                write!(f, " {}", operation)
2253            }
2254            Statement::AlterConnection { name, operation } => {
2255                write!(f, "ALTER CONNECTION {} {}", name, operation)
2256            }
2257            Statement::AlterSecret {
2258                name,
2259                with_options,
2260                operation,
2261            } => {
2262                write!(f, "ALTER SECRET {}", name)?;
2263                if !with_options.is_empty() {
2264                    write!(f, " WITH ({})", display_comma_separated(with_options))?;
2265                }
2266                write!(f, " {}", operation)
2267            }
2268            Statement::Discard(t) => write!(f, "DISCARD {}", t),
2269            Statement::Drop(stmt) => write!(f, "DROP {}", stmt),
2270            Statement::DropFunction {
2271                if_exists,
2272                func_desc,
2273                option,
2274            } => {
2275                write!(
2276                    f,
2277                    "DROP FUNCTION{} {}",
2278                    if *if_exists { " IF EXISTS" } else { "" },
2279                    display_comma_separated(func_desc),
2280                )?;
2281                if let Some(op) = option {
2282                    write!(f, " {}", op)?;
2283                }
2284                Ok(())
2285            }
2286            Statement::DropAggregate {
2287                if_exists,
2288                func_desc,
2289                option,
2290            } => {
2291                write!(
2292                    f,
2293                    "DROP AGGREGATE{} {}",
2294                    if *if_exists { " IF EXISTS" } else { "" },
2295                    display_comma_separated(func_desc),
2296                )?;
2297                if let Some(op) = option {
2298                    write!(f, " {}", op)?;
2299                }
2300                Ok(())
2301            }
2302            Statement::SetVariable {
2303                local,
2304                variable,
2305                value,
2306            } => {
2307                f.write_str("SET ")?;
2308                if *local {
2309                    f.write_str("LOCAL ")?;
2310                }
2311                write!(f, "{name} = {value}", name = variable,)
2312            }
2313            Statement::ShowVariable { variable } => {
2314                write!(f, "SHOW")?;
2315                if !variable.is_empty() {
2316                    write!(f, " {}", display_separated(variable, " "))?;
2317                }
2318                Ok(())
2319            }
2320            Statement::StartTransaction { modes } => {
2321                write!(f, "START TRANSACTION")?;
2322                if !modes.is_empty() {
2323                    write!(f, " {}", display_comma_separated(modes))?;
2324                }
2325                Ok(())
2326            }
2327            Statement::Abort => {
2328                write!(f, "ABORT")?;
2329                Ok(())
2330            }
2331            Statement::SetTransaction {
2332                modes,
2333                snapshot,
2334                session,
2335            } => {
2336                if *session {
2337                    write!(f, "SET SESSION CHARACTERISTICS AS TRANSACTION")?;
2338                } else {
2339                    write!(f, "SET TRANSACTION")?;
2340                }
2341                if !modes.is_empty() {
2342                    write!(f, " {}", display_comma_separated(modes))?;
2343                }
2344                if let Some(snapshot_id) = snapshot {
2345                    write!(f, " SNAPSHOT {}", snapshot_id)?;
2346                }
2347                Ok(())
2348            }
2349            Statement::SetTimeZone { local, value } => {
2350                write!(f, "SET")?;
2351                if *local {
2352                    write!(f, " LOCAL")?;
2353                }
2354                write!(f, " TIME ZONE {}", value)?;
2355                Ok(())
2356            }
2357            Statement::Commit { chain } => {
2358                write!(f, "COMMIT{}", if *chain { " AND CHAIN" } else { "" },)
2359            }
2360            Statement::Rollback { chain } => {
2361                write!(f, "ROLLBACK{}", if *chain { " AND CHAIN" } else { "" },)
2362            }
2363            Statement::CreateSchema {
2364                schema_name,
2365                if_not_exists,
2366                owner,
2367            } => {
2368                write!(
2369                    f,
2370                    "CREATE SCHEMA {if_not_exists}{name}",
2371                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
2372                    name = schema_name
2373                )?;
2374                if let Some(user) = owner {
2375                    write!(f, " AUTHORIZATION {}", user)?;
2376                }
2377                Ok(())
2378            }
2379            Statement::Grant {
2380                privileges,
2381                objects,
2382                grantees,
2383                with_grant_option,
2384                granted_by,
2385            } => {
2386                write!(f, "GRANT {} ", privileges)?;
2387                write!(f, "ON {} ", objects)?;
2388                write!(f, "TO {}", display_comma_separated(grantees))?;
2389                if *with_grant_option {
2390                    write!(f, " WITH GRANT OPTION")?;
2391                }
2392                if let Some(grantor) = granted_by {
2393                    write!(f, " GRANTED BY {}", grantor)?;
2394                }
2395                Ok(())
2396            }
2397            Statement::Revoke {
2398                privileges,
2399                objects,
2400                grantees,
2401                granted_by,
2402                revoke_grant_option,
2403                cascade,
2404            } => {
2405                write!(
2406                    f,
2407                    "REVOKE {}{} ",
2408                    if *revoke_grant_option {
2409                        "GRANT OPTION FOR "
2410                    } else {
2411                        ""
2412                    },
2413                    privileges
2414                )?;
2415                write!(f, "ON {} ", objects)?;
2416                write!(f, "FROM {}", display_comma_separated(grantees))?;
2417                if let Some(grantor) = granted_by {
2418                    write!(f, " GRANTED BY {}", grantor)?;
2419                }
2420                write!(f, " {}", if *cascade { "CASCADE" } else { "RESTRICT" })?;
2421                Ok(())
2422            }
2423            Statement::Deallocate { name, prepare } => {
2424                if let Some(name) = name {
2425                    write!(
2426                        f,
2427                        "DEALLOCATE {prepare}{name}",
2428                        prepare = if *prepare { "PREPARE " } else { "" },
2429                        name = name,
2430                    )
2431                } else {
2432                    write!(
2433                        f,
2434                        "DEALLOCATE {prepare}ALL",
2435                        prepare = if *prepare { "PREPARE " } else { "" },
2436                    )
2437                }
2438            }
2439            Statement::Execute { name, parameters } => {
2440                write!(f, "EXECUTE {}", name)?;
2441                if !parameters.is_empty() {
2442                    write!(f, "({})", display_comma_separated(parameters))?;
2443                }
2444                Ok(())
2445            }
2446            Statement::Prepare {
2447                name,
2448                data_types,
2449                statement,
2450            } => {
2451                write!(f, "PREPARE {} ", name)?;
2452                if !data_types.is_empty() {
2453                    write!(f, "({}) ", display_comma_separated(data_types))?;
2454                }
2455                write!(f, "AS ")?;
2456                statement.fmt_unchecked(f)
2457            }
2458            Statement::Comment {
2459                object_type,
2460                object_name,
2461                comment,
2462            } => {
2463                write!(f, "COMMENT ON {} {} IS ", object_type, object_name)?;
2464                if let Some(c) = comment {
2465                    write!(f, "'{}'", c)
2466                } else {
2467                    write!(f, "NULL")
2468                }
2469            }
2470            Statement::CreateUser(statement) => {
2471                write!(f, "CREATE USER {}", statement)
2472            }
2473            Statement::AlterUser(statement) => {
2474                write!(f, "ALTER USER {}", statement)
2475            }
2476            Statement::AlterSystem { param, value } => {
2477                f.write_str("ALTER SYSTEM SET ")?;
2478                write!(f, "{param} = {value}",)
2479            }
2480            Statement::Flush => {
2481                write!(f, "FLUSH")
2482            }
2483            Statement::Wait => {
2484                write!(f, "WAIT")
2485            }
2486            Statement::Begin { modes } => {
2487                write!(f, "BEGIN")?;
2488                if !modes.is_empty() {
2489                    write!(f, " {}", display_comma_separated(modes))?;
2490                }
2491                Ok(())
2492            }
2493            Statement::CancelJobs(jobs) => {
2494                write!(f, "CANCEL JOBS {}", display_comma_separated(&jobs.0))?;
2495                Ok(())
2496            }
2497            Statement::Kill(worker_process_id) => {
2498                write!(f, "KILL '{}'", worker_process_id)?;
2499                Ok(())
2500            }
2501            Statement::Recover => {
2502                write!(f, "RECOVER")?;
2503                Ok(())
2504            }
2505            Statement::Use { db_name } => {
2506                write!(f, "USE {}", db_name)?;
2507                Ok(())
2508            }
2509            Statement::Vacuum { object_name, full } => {
2510                if *full {
2511                    write!(f, "VACUUM FULL {}", object_name)?;
2512                } else {
2513                    write!(f, "VACUUM {}", object_name)?;
2514                }
2515                Ok(())
2516            }
2517            Statement::AlterFragment {
2518                fragment_ids,
2519                operation,
2520            } => {
2521                write!(
2522                    f,
2523                    "ALTER FRAGMENT {} {}",
2524                    display_comma_separated(fragment_ids),
2525                    operation
2526                )
2527            }
2528            Statement::AlterDefaultPrivileges {
2529                target_users,
2530                schema_names,
2531                operation,
2532            } => {
2533                write!(f, "ALTER DEFAULT PRIVILEGES")?;
2534                if let Some(target_users) = target_users {
2535                    write!(f, " FOR {}", display_comma_separated(target_users))?;
2536                }
2537                if let Some(schema_names) = schema_names {
2538                    write!(f, " IN SCHEMA {}", display_comma_separated(schema_names))?;
2539                }
2540                write!(f, " {}", operation)
2541            }
2542        }
2543    }
2544
2545    pub fn is_create(&self) -> bool {
2546        matches!(
2547            self,
2548            Statement::CreateTable { .. }
2549                | Statement::CreateView { .. }
2550                | Statement::CreateSource { .. }
2551                | Statement::CreateSink { .. }
2552                | Statement::CreateSubscription { .. }
2553                | Statement::CreateConnection { .. }
2554                | Statement::CreateSecret { .. }
2555                | Statement::CreateUser { .. }
2556                | Statement::CreateDatabase { .. }
2557                | Statement::CreateFunction { .. }
2558                | Statement::CreateAggregate { .. }
2559                | Statement::CreateIndex { .. }
2560                | Statement::CreateSchema { .. }
2561        )
2562    }
2563}
2564
2565impl Display for IncludeOptionItem {
2566    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2567        let Self {
2568            column_type,
2569            inner_field,
2570            header_inner_expect_type,
2571            column_alias,
2572        } = self;
2573        write!(f, "INCLUDE {}", column_type)?;
2574        if let Some(inner_field) = inner_field {
2575            write!(f, " '{}'", value::escape_single_quote_string(inner_field))?;
2576            if let Some(expected_type) = header_inner_expect_type {
2577                write!(f, " {}", expected_type)?;
2578            }
2579        }
2580        if let Some(alias) = column_alias {
2581            write!(f, " AS {}", alias)?;
2582        }
2583        Ok(())
2584    }
2585}
2586
2587#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2588#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2589#[non_exhaustive]
2590pub enum OnInsert {
2591    /// ON DUPLICATE KEY UPDATE (MySQL when the key already exists, then execute an update instead)
2592    DuplicateKeyUpdate(Vec<Assignment>),
2593}
2594
2595impl fmt::Display for OnInsert {
2596    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2597        match self {
2598            Self::DuplicateKeyUpdate(expr) => write!(
2599                f,
2600                " ON DUPLICATE KEY UPDATE {}",
2601                display_comma_separated(expr)
2602            ),
2603        }
2604    }
2605}
2606
2607/// Privileges granted in a GRANT statement or revoked in a REVOKE statement.
2608#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2609#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2610pub enum Privileges {
2611    /// All privileges applicable to the object type
2612    All {
2613        /// Optional keyword from the spec, ignored in practice
2614        with_privileges_keyword: bool,
2615    },
2616    /// Specific privileges (e.g. `SELECT`, `INSERT`)
2617    Actions(Vec<Action>),
2618}
2619
2620impl fmt::Display for Privileges {
2621    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2622        match self {
2623            Privileges::All {
2624                with_privileges_keyword,
2625            } => {
2626                write!(
2627                    f,
2628                    "ALL{}",
2629                    if *with_privileges_keyword {
2630                        " PRIVILEGES"
2631                    } else {
2632                        ""
2633                    }
2634                )
2635            }
2636            Privileges::Actions(actions) => {
2637                write!(f, "{}", display_comma_separated(actions))
2638            }
2639        }
2640    }
2641}
2642
2643/// A privilege on a database object (table, sequence, etc.).
2644#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2645#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2646pub enum Action {
2647    Connect,
2648    Create,
2649    Delete,
2650    Execute,
2651    Insert { columns: Option<Vec<Ident>> },
2652    References { columns: Option<Vec<Ident>> },
2653    Select { columns: Option<Vec<Ident>> },
2654    Temporary,
2655    Trigger,
2656    Truncate,
2657    Update { columns: Option<Vec<Ident>> },
2658    Usage,
2659}
2660
2661impl fmt::Display for Action {
2662    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2663        match self {
2664            Action::Connect => f.write_str("CONNECT")?,
2665            Action::Create => f.write_str("CREATE")?,
2666            Action::Delete => f.write_str("DELETE")?,
2667            Action::Execute => f.write_str("EXECUTE")?,
2668            Action::Insert { .. } => f.write_str("INSERT")?,
2669            Action::References { .. } => f.write_str("REFERENCES")?,
2670            Action::Select { .. } => f.write_str("SELECT")?,
2671            Action::Temporary => f.write_str("TEMPORARY")?,
2672            Action::Trigger => f.write_str("TRIGGER")?,
2673            Action::Truncate => f.write_str("TRUNCATE")?,
2674            Action::Update { .. } => f.write_str("UPDATE")?,
2675            Action::Usage => f.write_str("USAGE")?,
2676        };
2677        match self {
2678            Action::Insert { columns }
2679            | Action::References { columns }
2680            | Action::Select { columns }
2681            | Action::Update { columns } => {
2682                if let Some(columns) = columns {
2683                    write!(f, " ({})", display_comma_separated(columns))?;
2684                }
2685            }
2686            _ => (),
2687        };
2688        Ok(())
2689    }
2690}
2691
2692/// Objects on which privileges are granted in a GRANT statement.
2693#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2694#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2695pub enum GrantObjects {
2696    /// Grant privileges on `ALL SEQUENCES IN SCHEMA <schema_name> [, ...]`
2697    AllSequencesInSchema { schemas: Vec<ObjectName> },
2698    /// Grant privileges on `ALL TABLES IN SCHEMA <schema_name> [, ...]`
2699    AllTablesInSchema { schemas: Vec<ObjectName> },
2700    /// Grant privileges on `ALL SOURCES IN SCHEMA <schema_name> [, ...]`
2701    AllSourcesInSchema { schemas: Vec<ObjectName> },
2702    /// Grant privileges on `ALL SINKS IN SCHEMA <schema_name> [, ...]`
2703    AllSinksInSchema { schemas: Vec<ObjectName> },
2704    /// Grant privileges on `ALL MATERIALIZED VIEWS IN SCHEMA <schema_name> [, ...]`
2705    AllMviewsInSchema { schemas: Vec<ObjectName> },
2706    /// Grant privileges on `ALL VIEWS IN SCHEMA <schema_name> [, ...]`
2707    AllViewsInSchema { schemas: Vec<ObjectName> },
2708    /// Grant privileges on `ALL FUNCTIONS IN SCHEMA <schema_name> [, ...]`
2709    AllFunctionsInSchema { schemas: Vec<ObjectName> },
2710    /// Grant privileges on `ALL SECRETS IN SCHEMA <schema_name> [, ...]`
2711    AllSecretsInSchema { schemas: Vec<ObjectName> },
2712    /// Grant privileges on `ALL SUBSCRIPTIONS IN SCHEMA <schema_name> [, ...]`
2713    AllSubscriptionsInSchema { schemas: Vec<ObjectName> },
2714    /// Grant privileges on `ALL CONNECTIONS IN SCHEMA <schema_name> [, ...]`
2715    AllConnectionsInSchema { schemas: Vec<ObjectName> },
2716    /// Grant privileges on specific databases
2717    Databases(Vec<ObjectName>),
2718    /// Grant privileges on specific schemas
2719    Schemas(Vec<ObjectName>),
2720    /// Grant privileges on specific sources
2721    Sources(Vec<ObjectName>),
2722    /// Grant privileges on specific materialized views
2723    Mviews(Vec<ObjectName>),
2724    /// Grant privileges on specific sequences
2725    Sequences(Vec<ObjectName>),
2726    /// Grant privileges on specific tables
2727    Tables(Vec<ObjectName>),
2728    /// Grant privileges on specific sinks
2729    Sinks(Vec<ObjectName>),
2730    /// Grant privileges on specific views
2731    Views(Vec<ObjectName>),
2732    /// Grant privileges on specific connections
2733    Connections(Vec<ObjectName>),
2734    /// Grant privileges on specific subscriptions
2735    Subscriptions(Vec<ObjectName>),
2736    /// Grant privileges on specific functions
2737    Functions(Vec<FunctionDesc>),
2738    /// Grant privileges on specific secrets
2739    Secrets(Vec<ObjectName>),
2740}
2741
2742impl fmt::Display for GrantObjects {
2743    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2744        match self {
2745            GrantObjects::Sequences(sequences) => {
2746                write!(f, "SEQUENCE {}", display_comma_separated(sequences))
2747            }
2748            GrantObjects::Schemas(schemas) => {
2749                write!(f, "SCHEMA {}", display_comma_separated(schemas))
2750            }
2751            GrantObjects::Tables(tables) => {
2752                write!(f, "{}", display_comma_separated(tables))
2753            }
2754            GrantObjects::AllSequencesInSchema { schemas } => {
2755                write!(
2756                    f,
2757                    "ALL SEQUENCES IN SCHEMA {}",
2758                    display_comma_separated(schemas)
2759                )
2760            }
2761            GrantObjects::AllTablesInSchema { schemas } => {
2762                write!(
2763                    f,
2764                    "ALL TABLES IN SCHEMA {}",
2765                    display_comma_separated(schemas)
2766                )
2767            }
2768            GrantObjects::AllSourcesInSchema { schemas } => {
2769                write!(
2770                    f,
2771                    "ALL SOURCES IN SCHEMA {}",
2772                    display_comma_separated(schemas)
2773                )
2774            }
2775            GrantObjects::AllMviewsInSchema { schemas } => {
2776                write!(
2777                    f,
2778                    "ALL MATERIALIZED VIEWS IN SCHEMA {}",
2779                    display_comma_separated(schemas)
2780                )
2781            }
2782            GrantObjects::AllSinksInSchema { schemas } => {
2783                write!(
2784                    f,
2785                    "ALL SINKS IN SCHEMA {}",
2786                    display_comma_separated(schemas)
2787                )
2788            }
2789            GrantObjects::AllViewsInSchema { schemas } => {
2790                write!(
2791                    f,
2792                    "ALL VIEWS IN SCHEMA {}",
2793                    display_comma_separated(schemas)
2794                )
2795            }
2796            GrantObjects::AllFunctionsInSchema { schemas } => {
2797                write!(
2798                    f,
2799                    "ALL FUNCTIONS IN SCHEMA {}",
2800                    display_comma_separated(schemas)
2801                )
2802            }
2803            GrantObjects::AllSecretsInSchema { schemas } => {
2804                write!(
2805                    f,
2806                    "ALL SECRETS IN SCHEMA {}",
2807                    display_comma_separated(schemas)
2808                )
2809            }
2810            GrantObjects::AllSubscriptionsInSchema { schemas } => {
2811                write!(
2812                    f,
2813                    "ALL SUBSCRIPTIONS IN SCHEMA {}",
2814                    display_comma_separated(schemas)
2815                )
2816            }
2817            GrantObjects::AllConnectionsInSchema { schemas } => {
2818                write!(
2819                    f,
2820                    "ALL CONNECTIONS IN SCHEMA {}",
2821                    display_comma_separated(schemas)
2822                )
2823            }
2824            GrantObjects::Databases(databases) => {
2825                write!(f, "DATABASE {}", display_comma_separated(databases))
2826            }
2827            GrantObjects::Sources(sources) => {
2828                write!(f, "SOURCE {}", display_comma_separated(sources))
2829            }
2830            GrantObjects::Mviews(mviews) => {
2831                write!(f, "MATERIALIZED VIEW {}", display_comma_separated(mviews))
2832            }
2833            GrantObjects::Sinks(sinks) => {
2834                write!(f, "SINK {}", display_comma_separated(sinks))
2835            }
2836            GrantObjects::Views(views) => {
2837                write!(f, "VIEW {}", display_comma_separated(views))
2838            }
2839            GrantObjects::Connections(connections) => {
2840                write!(f, "CONNECTION {}", display_comma_separated(connections))
2841            }
2842            GrantObjects::Subscriptions(subscriptions) => {
2843                write!(f, "SUBSCRIPTION {}", display_comma_separated(subscriptions))
2844            }
2845            GrantObjects::Functions(func_descs) => {
2846                write!(f, "FUNCTION {}", display_comma_separated(func_descs))
2847            }
2848            GrantObjects::Secrets(secrets) => {
2849                write!(f, "SECRET {}", display_comma_separated(secrets))
2850            }
2851        }
2852    }
2853}
2854
2855#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2856#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2857pub enum PrivilegeObjectType {
2858    Tables,
2859    Sources,
2860    Sinks,
2861    Mviews,
2862    Views,
2863    Functions,
2864    Connections,
2865    Secrets,
2866    Subscriptions,
2867    Schemas,
2868}
2869
2870impl fmt::Display for PrivilegeObjectType {
2871    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2872        match self {
2873            PrivilegeObjectType::Tables => f.write_str("TABLES")?,
2874            PrivilegeObjectType::Sources => f.write_str("SOURCES")?,
2875            PrivilegeObjectType::Sinks => f.write_str("SINKS")?,
2876            PrivilegeObjectType::Mviews => f.write_str("MATERIALIZED VIEWS")?,
2877            PrivilegeObjectType::Views => f.write_str("VIEWS")?,
2878            PrivilegeObjectType::Functions => f.write_str("FUNCTIONS")?,
2879            PrivilegeObjectType::Connections => f.write_str("CONNECTIONS")?,
2880            PrivilegeObjectType::Secrets => f.write_str("SECRETS")?,
2881            PrivilegeObjectType::Subscriptions => f.write_str("SUBSCRIPTIONS")?,
2882            PrivilegeObjectType::Schemas => f.write_str("SCHEMAS")?,
2883        };
2884        Ok(())
2885    }
2886}
2887
2888#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2889#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2890pub enum DefaultPrivilegeOperation {
2891    Grant {
2892        privileges: Privileges,
2893        object_type: PrivilegeObjectType,
2894        grantees: Vec<Ident>,
2895        with_grant_option: bool,
2896    },
2897    Revoke {
2898        privileges: Privileges,
2899        object_type: PrivilegeObjectType,
2900        grantees: Vec<Ident>,
2901        revoke_grant_option: bool,
2902        cascade: bool,
2903    },
2904}
2905
2906impl fmt::Display for DefaultPrivilegeOperation {
2907    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2908        match self {
2909            DefaultPrivilegeOperation::Grant {
2910                privileges,
2911                object_type,
2912                grantees,
2913                with_grant_option,
2914            } => {
2915                write!(
2916                    f,
2917                    "GRANT {} ON {} TO {}",
2918                    privileges,
2919                    object_type,
2920                    display_comma_separated(grantees)
2921                )?;
2922                if *with_grant_option {
2923                    write!(f, " WITH GRANT OPTION")?;
2924                }
2925            }
2926            DefaultPrivilegeOperation::Revoke {
2927                privileges,
2928                object_type,
2929                grantees,
2930                revoke_grant_option,
2931                cascade,
2932            } => {
2933                write!(f, "REVOKE")?;
2934                if *revoke_grant_option {
2935                    write!(f, " GRANT OPTION FOR")?;
2936                }
2937                write!(
2938                    f,
2939                    " {} ON {} FROM {}",
2940                    privileges,
2941                    object_type,
2942                    display_comma_separated(grantees)
2943                )?;
2944                write!(f, " {}", if *cascade { "CASCADE" } else { "RESTRICT" })?;
2945            }
2946        }
2947        Ok(())
2948    }
2949}
2950
2951impl DefaultPrivilegeOperation {
2952    pub fn for_schemas(&self) -> bool {
2953        match &self {
2954            DefaultPrivilegeOperation::Grant { object_type, .. } => {
2955                object_type == &PrivilegeObjectType::Schemas
2956            }
2957            DefaultPrivilegeOperation::Revoke { object_type, .. } => {
2958                object_type == &PrivilegeObjectType::Schemas
2959            }
2960        }
2961    }
2962}
2963
2964#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2965#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2966pub enum AssignmentValue {
2967    /// An expression, e.g. `foo = 1`
2968    Expr(Expr),
2969    /// The `DEFAULT` keyword, e.g. `foo = DEFAULT`
2970    Default,
2971}
2972
2973impl fmt::Display for AssignmentValue {
2974    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2975        match self {
2976            AssignmentValue::Expr(expr) => write!(f, "{}", expr),
2977            AssignmentValue::Default => f.write_str("DEFAULT"),
2978        }
2979    }
2980}
2981
2982/// SQL assignment `foo = { expr | DEFAULT }` as used in SQLUpdate
2983#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2984#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2985pub struct Assignment {
2986    pub id: Vec<Ident>,
2987    pub value: AssignmentValue,
2988}
2989
2990impl fmt::Display for Assignment {
2991    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2992        write!(f, "{} = {}", display_separated(&self.id, "."), self.value)
2993    }
2994}
2995
2996#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2997#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2998pub enum FunctionArgExpr {
2999    Expr(Expr),
3000    /// Expr is an arbitrary expression, returning either a table or a column.
3001    /// Idents are the prefix of `*`, which are consecutive field accesses.
3002    /// e.g. `(table.v1).*` or `(table).v1.*`
3003    ExprQualifiedWildcard(Expr, Vec<Ident>),
3004    /// Qualified wildcard, e.g. `alias.*` or `schema.table.*`, followed by optional
3005    /// except syntax
3006    QualifiedWildcard(ObjectName, Option<Vec<Expr>>),
3007    /// An unqualified `*` or `* except (columns)`
3008    Wildcard(Option<Vec<Expr>>),
3009}
3010
3011impl fmt::Display for FunctionArgExpr {
3012    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3013        match self {
3014            FunctionArgExpr::Expr(expr) => write!(f, "{}", expr),
3015            FunctionArgExpr::ExprQualifiedWildcard(expr, prefix) => {
3016                write!(
3017                    f,
3018                    "({}){}.*",
3019                    expr,
3020                    prefix
3021                        .iter()
3022                        .format_with("", |i, f| f(&format_args!(".{i}")))
3023                )
3024            }
3025            FunctionArgExpr::QualifiedWildcard(prefix, except) => match except {
3026                Some(exprs) => write!(
3027                    f,
3028                    "{}.* EXCEPT ({})",
3029                    prefix,
3030                    exprs
3031                        .iter()
3032                        .map(|v| v.to_string())
3033                        .collect::<Vec<String>>()
3034                        .as_slice()
3035                        .join(", ")
3036                ),
3037                None => write!(f, "{}.*", prefix),
3038            },
3039
3040            FunctionArgExpr::Wildcard(except) => match except {
3041                Some(exprs) => write!(
3042                    f,
3043                    "* EXCEPT ({})",
3044                    exprs
3045                        .iter()
3046                        .map(|v| v.to_string())
3047                        .collect::<Vec<String>>()
3048                        .as_slice()
3049                        .join(", ")
3050                ),
3051                None => f.write_str("*"),
3052            },
3053        }
3054    }
3055}
3056
3057#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3058#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3059pub enum FunctionArg {
3060    Named { name: Ident, arg: FunctionArgExpr },
3061    Unnamed(FunctionArgExpr),
3062}
3063
3064impl FunctionArg {
3065    pub fn get_expr(&self) -> FunctionArgExpr {
3066        match self {
3067            FunctionArg::Named { name: _, arg } => arg.clone(),
3068            FunctionArg::Unnamed(arg) => arg.clone(),
3069        }
3070    }
3071}
3072
3073impl fmt::Display for FunctionArg {
3074    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3075        match self {
3076            FunctionArg::Named { name, arg } => write!(f, "{} => {}", name, arg),
3077            FunctionArg::Unnamed(unnamed_arg) => write!(f, "{}", unnamed_arg),
3078        }
3079    }
3080}
3081
3082/// A list of function arguments, including additional modifiers like `DISTINCT` or `ORDER BY`.
3083/// This basically holds all the information between the `(` and `)` in a function call.
3084#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3085#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3086pub struct FunctionArgList {
3087    /// Aggregate function calls may have a `DISTINCT`, e.g. `count(DISTINCT x)`.
3088    pub distinct: bool,
3089    pub args: Vec<FunctionArg>,
3090    /// Whether the last argument is variadic, e.g. `foo(a, b, VARIADIC c)`.
3091    pub variadic: bool,
3092    /// Aggregate function calls may have an `ORDER BY`, e.g. `array_agg(x ORDER BY y)`.
3093    pub order_by: Vec<OrderByExpr>,
3094    /// Window function calls may have an `IGNORE NULLS`, e.g. `first_value(x IGNORE NULLS)`.
3095    pub ignore_nulls: bool,
3096}
3097
3098impl fmt::Display for FunctionArgList {
3099    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3100        write!(f, "(")?;
3101        if self.distinct {
3102            write!(f, "DISTINCT ")?;
3103        }
3104        if self.variadic {
3105            for arg in &self.args[0..self.args.len() - 1] {
3106                write!(f, "{}, ", arg)?;
3107            }
3108            write!(f, "VARIADIC {}", self.args.last().unwrap())?;
3109        } else {
3110            write!(f, "{}", display_comma_separated(&self.args))?;
3111        }
3112        if !self.order_by.is_empty() {
3113            write!(f, " ORDER BY {}", display_comma_separated(&self.order_by))?;
3114        }
3115        if self.ignore_nulls {
3116            write!(f, " IGNORE NULLS")?;
3117        }
3118        write!(f, ")")?;
3119        Ok(())
3120    }
3121}
3122
3123impl FunctionArgList {
3124    pub fn empty() -> Self {
3125        Self {
3126            distinct: false,
3127            args: vec![],
3128            variadic: false,
3129            order_by: vec![],
3130            ignore_nulls: false,
3131        }
3132    }
3133
3134    pub fn args_only(args: Vec<FunctionArg>) -> Self {
3135        Self {
3136            distinct: false,
3137            args,
3138            variadic: false,
3139            order_by: vec![],
3140            ignore_nulls: false,
3141        }
3142    }
3143
3144    pub fn is_args_only(&self) -> bool {
3145        !self.distinct && !self.variadic && self.order_by.is_empty() && !self.ignore_nulls
3146    }
3147
3148    pub fn for_agg(distinct: bool, args: Vec<FunctionArg>, order_by: Vec<OrderByExpr>) -> Self {
3149        Self {
3150            distinct,
3151            args,
3152            variadic: false,
3153            order_by,
3154            ignore_nulls: false,
3155        }
3156    }
3157}
3158
3159/// A function call
3160#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3161#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3162pub struct Function {
3163    /// Whether the function is prefixed with `AGGREGATE:`
3164    pub scalar_as_agg: bool,
3165    /// Function name.
3166    pub name: ObjectName,
3167    /// Argument list of the function call, i.e. things in `()`.
3168    pub arg_list: FunctionArgList,
3169    /// `WITHIN GROUP` clause of the function call, for ordered-set aggregate functions.
3170    /// FIXME(rc): why we only support one expression here?
3171    pub within_group: Option<Box<OrderByExpr>>,
3172    /// `FILTER` clause of the function call, for aggregate and window (not supported yet) functions.
3173    pub filter: Option<Box<Expr>>,
3174    /// `OVER` clause of the function call, for window functions.
3175    pub over: Option<Window>,
3176}
3177
3178impl Function {
3179    pub fn no_arg(name: ObjectName) -> Self {
3180        Self {
3181            scalar_as_agg: false,
3182            name,
3183            arg_list: FunctionArgList::empty(),
3184            within_group: None,
3185            filter: None,
3186            over: None,
3187        }
3188    }
3189}
3190
3191impl fmt::Display for Function {
3192    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3193        if self.scalar_as_agg {
3194            write!(f, "AGGREGATE:")?;
3195        }
3196        write!(f, "{}{}", self.name, self.arg_list)?;
3197        if let Some(within_group) = &self.within_group {
3198            write!(f, " WITHIN GROUP (ORDER BY {})", within_group)?;
3199        }
3200        if let Some(filter) = &self.filter {
3201            write!(f, " FILTER (WHERE {})", filter)?;
3202        }
3203        if let Some(o) = &self.over {
3204            write!(f, " OVER {}", o)?;
3205        }
3206        Ok(())
3207    }
3208}
3209
3210#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3211#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3212pub enum ObjectType {
3213    Table,
3214    View,
3215    MaterializedView,
3216    Index,
3217    Schema,
3218    Source,
3219    Sink,
3220    Database,
3221    User,
3222    Connection,
3223    Secret,
3224    Subscription,
3225}
3226
3227impl fmt::Display for ObjectType {
3228    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3229        f.write_str(match self {
3230            ObjectType::Table => "TABLE",
3231            ObjectType::View => "VIEW",
3232            ObjectType::MaterializedView => "MATERIALIZED VIEW",
3233            ObjectType::Index => "INDEX",
3234            ObjectType::Schema => "SCHEMA",
3235            ObjectType::Source => "SOURCE",
3236            ObjectType::Sink => "SINK",
3237            ObjectType::Database => "DATABASE",
3238            ObjectType::User => "USER",
3239            ObjectType::Secret => "SECRET",
3240            ObjectType::Connection => "CONNECTION",
3241            ObjectType::Subscription => "SUBSCRIPTION",
3242        })
3243    }
3244}
3245
3246impl ParseTo for ObjectType {
3247    fn parse_to(parser: &mut Parser<'_>) -> ModalResult<Self> {
3248        let object_type = if parser.parse_keyword(Keyword::TABLE) {
3249            ObjectType::Table
3250        } else if parser.parse_keyword(Keyword::VIEW) {
3251            ObjectType::View
3252        } else if parser.parse_keywords(&[Keyword::MATERIALIZED, Keyword::VIEW]) {
3253            ObjectType::MaterializedView
3254        } else if parser.parse_keyword(Keyword::SOURCE) {
3255            ObjectType::Source
3256        } else if parser.parse_keyword(Keyword::SINK) {
3257            ObjectType::Sink
3258        } else if parser.parse_keyword(Keyword::INDEX) {
3259            ObjectType::Index
3260        } else if parser.parse_keyword(Keyword::SCHEMA) {
3261            ObjectType::Schema
3262        } else if parser.parse_keyword(Keyword::DATABASE) {
3263            ObjectType::Database
3264        } else if parser.parse_keyword(Keyword::USER) {
3265            ObjectType::User
3266        } else if parser.parse_keyword(Keyword::CONNECTION) {
3267            ObjectType::Connection
3268        } else if parser.parse_keyword(Keyword::SECRET) {
3269            ObjectType::Secret
3270        } else if parser.parse_keyword(Keyword::SUBSCRIPTION) {
3271            ObjectType::Subscription
3272        } else {
3273            return parser.expected(
3274                "TABLE, VIEW, INDEX, MATERIALIZED VIEW, SOURCE, SINK, SUBSCRIPTION, SCHEMA, DATABASE, USER, SECRET or CONNECTION after DROP",
3275            );
3276        };
3277        Ok(object_type)
3278    }
3279}
3280
3281#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3282#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3283pub struct SqlOption {
3284    pub name: ObjectName,
3285    pub value: SqlOptionValue,
3286}
3287
3288impl fmt::Display for SqlOption {
3289    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3290        let should_redact = REDACT_SQL_OPTION_KEYWORDS
3291            .try_with(|keywords| {
3292                let sql_option_name = self.name.real_value().to_lowercase();
3293                keywords.iter().any(|k| sql_option_name.contains(k))
3294            })
3295            .unwrap_or(false);
3296        if should_redact {
3297            write!(f, "{} = [REDACTED]", self.name)
3298        } else {
3299            write!(f, "{} = {}", self.name, self.value)
3300        }
3301    }
3302}
3303
3304impl TryFrom<(&String, &String)> for SqlOption {
3305    type Error = ParserError;
3306
3307    fn try_from((name, value): (&String, &String)) -> Result<Self, Self::Error> {
3308        let query = format!("{} = {}", name, value);
3309        let mut tokenizer = Tokenizer::new(query.as_str());
3310        let tokens = tokenizer.tokenize_with_location()?;
3311        let mut parser = Parser(&tokens);
3312        parser
3313            .parse_sql_option()
3314            .map_err(|e| ParserError::ParserError(e.to_string()))
3315    }
3316}
3317
3318#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3319#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3320pub enum SqlOptionValue {
3321    Value(Value),
3322    SecretRef(SecretRefValue),
3323    ConnectionRef(ConnectionRefValue),
3324    BackfillOrder(BackfillOrderStrategy),
3325}
3326
3327impl fmt::Display for SqlOptionValue {
3328    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3329        match self {
3330            SqlOptionValue::Value(value) => write!(f, "{}", value),
3331            SqlOptionValue::SecretRef(secret_ref) => write!(f, "secret {}", secret_ref),
3332            SqlOptionValue::ConnectionRef(connection_ref) => {
3333                write!(f, "{}", connection_ref)
3334            }
3335            SqlOptionValue::BackfillOrder(order) => {
3336                write!(f, "{}", order)
3337            }
3338        }
3339    }
3340}
3341
3342impl From<Value> for SqlOptionValue {
3343    fn from(value: Value) -> Self {
3344        SqlOptionValue::Value(value)
3345    }
3346}
3347
3348#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3349#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3350pub enum EmitMode {
3351    Immediately,
3352    OnWindowClose,
3353}
3354
3355impl fmt::Display for EmitMode {
3356    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3357        f.write_str(match self {
3358            EmitMode::Immediately => "IMMEDIATELY",
3359            EmitMode::OnWindowClose => "ON WINDOW CLOSE",
3360        })
3361    }
3362}
3363
3364#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
3365#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3366pub enum OnConflict {
3367    UpdateFull,
3368    Nothing,
3369    UpdateIfNotNull,
3370}
3371
3372impl fmt::Display for OnConflict {
3373    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3374        f.write_str(match self {
3375            OnConflict::UpdateFull => "DO UPDATE FULL",
3376            OnConflict::Nothing => "DO NOTHING",
3377            OnConflict::UpdateIfNotNull => "DO UPDATE IF NOT NULL",
3378        })
3379    }
3380}
3381
3382#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3383#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3384pub enum Engine {
3385    Hummock,
3386    Iceberg,
3387}
3388
3389impl fmt::Display for crate::ast::Engine {
3390    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3391        f.write_str(match self {
3392            crate::ast::Engine::Hummock => "HUMMOCK",
3393            crate::ast::Engine::Iceberg => "ICEBERG",
3394        })
3395    }
3396}
3397
3398#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3399#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3400pub enum SetTimeZoneValue {
3401    Ident(Ident),
3402    Literal(Value),
3403    Local,
3404    Default,
3405}
3406
3407impl fmt::Display for SetTimeZoneValue {
3408    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3409        match self {
3410            SetTimeZoneValue::Ident(ident) => write!(f, "{}", ident),
3411            SetTimeZoneValue::Literal(value) => write!(f, "{}", value),
3412            SetTimeZoneValue::Local => f.write_str("LOCAL"),
3413            SetTimeZoneValue::Default => f.write_str("DEFAULT"),
3414        }
3415    }
3416}
3417
3418#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3419#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3420pub enum TransactionMode {
3421    AccessMode(TransactionAccessMode),
3422    IsolationLevel(TransactionIsolationLevel),
3423}
3424
3425impl fmt::Display for TransactionMode {
3426    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3427        use TransactionMode::*;
3428        match self {
3429            AccessMode(access_mode) => write!(f, "{}", access_mode),
3430            IsolationLevel(iso_level) => write!(f, "ISOLATION LEVEL {}", iso_level),
3431        }
3432    }
3433}
3434
3435#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3436#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3437pub enum TransactionAccessMode {
3438    ReadOnly,
3439    ReadWrite,
3440}
3441
3442impl fmt::Display for TransactionAccessMode {
3443    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3444        use TransactionAccessMode::*;
3445        f.write_str(match self {
3446            ReadOnly => "READ ONLY",
3447            ReadWrite => "READ WRITE",
3448        })
3449    }
3450}
3451
3452#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3453#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3454pub enum TransactionIsolationLevel {
3455    ReadUncommitted,
3456    ReadCommitted,
3457    RepeatableRead,
3458    Serializable,
3459}
3460
3461impl fmt::Display for TransactionIsolationLevel {
3462    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3463        use TransactionIsolationLevel::*;
3464        f.write_str(match self {
3465            ReadUncommitted => "READ UNCOMMITTED",
3466            ReadCommitted => "READ COMMITTED",
3467            RepeatableRead => "REPEATABLE READ",
3468            Serializable => "SERIALIZABLE",
3469        })
3470    }
3471}
3472
3473#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3474#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3475pub enum ShowStatementFilter {
3476    Like(String),
3477    ILike(String),
3478    Where(Expr),
3479}
3480
3481impl fmt::Display for ShowStatementFilter {
3482    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3483        use ShowStatementFilter::*;
3484        match self {
3485            Like(pattern) => write!(f, "LIKE '{}'", value::escape_single_quote_string(pattern)),
3486            ILike(pattern) => write!(f, "ILIKE {}", value::escape_single_quote_string(pattern)),
3487            Where(expr) => write!(f, "WHERE {}", expr),
3488        }
3489    }
3490}
3491
3492/// Function describe in DROP FUNCTION.
3493#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3494#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3495pub enum DropFunctionOption {
3496    Restrict,
3497    Cascade,
3498}
3499
3500impl fmt::Display for DropFunctionOption {
3501    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3502        match self {
3503            DropFunctionOption::Restrict => write!(f, "RESTRICT "),
3504            DropFunctionOption::Cascade => write!(f, "CASCADE  "),
3505        }
3506    }
3507}
3508
3509/// Function describe in DROP FUNCTION.
3510#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3511#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3512pub struct FunctionDesc {
3513    pub name: ObjectName,
3514    pub args: Option<Vec<OperateFunctionArg>>,
3515}
3516
3517impl fmt::Display for FunctionDesc {
3518    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3519        write!(f, "{}", self.name)?;
3520        if let Some(args) = &self.args {
3521            write!(f, "({})", display_comma_separated(args))?;
3522        }
3523        Ok(())
3524    }
3525}
3526
3527/// Function argument in CREATE FUNCTION.
3528#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3529#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3530pub struct OperateFunctionArg {
3531    pub mode: Option<ArgMode>,
3532    pub name: Option<Ident>,
3533    pub data_type: DataType,
3534    pub default_expr: Option<Expr>,
3535}
3536
3537impl OperateFunctionArg {
3538    /// Returns an unnamed argument.
3539    pub fn unnamed(data_type: DataType) -> Self {
3540        Self {
3541            mode: None,
3542            name: None,
3543            data_type,
3544            default_expr: None,
3545        }
3546    }
3547
3548    /// Returns an argument with name.
3549    pub fn with_name(name: &str, data_type: DataType) -> Self {
3550        Self {
3551            mode: None,
3552            name: Some(name.into()),
3553            data_type,
3554            default_expr: None,
3555        }
3556    }
3557}
3558
3559impl fmt::Display for OperateFunctionArg {
3560    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3561        if let Some(mode) = &self.mode {
3562            write!(f, "{} ", mode)?;
3563        }
3564        if let Some(name) = &self.name {
3565            write!(f, "{} ", name)?;
3566        }
3567        write!(f, "{}", self.data_type)?;
3568        if let Some(default_expr) = &self.default_expr {
3569            write!(f, " = {}", default_expr)?;
3570        }
3571        Ok(())
3572    }
3573}
3574
3575/// The mode of an argument in CREATE FUNCTION.
3576#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3577#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3578pub enum ArgMode {
3579    In,
3580    Out,
3581    InOut,
3582}
3583
3584impl fmt::Display for ArgMode {
3585    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3586        match self {
3587            ArgMode::In => write!(f, "IN"),
3588            ArgMode::Out => write!(f, "OUT"),
3589            ArgMode::InOut => write!(f, "INOUT"),
3590        }
3591    }
3592}
3593
3594/// These attributes inform the query optimizer about the behavior of the function.
3595#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3596#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3597pub enum FunctionBehavior {
3598    Immutable,
3599    Stable,
3600    Volatile,
3601}
3602
3603impl fmt::Display for FunctionBehavior {
3604    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3605        match self {
3606            FunctionBehavior::Immutable => write!(f, "IMMUTABLE"),
3607            FunctionBehavior::Stable => write!(f, "STABLE"),
3608            FunctionBehavior::Volatile => write!(f, "VOLATILE"),
3609        }
3610    }
3611}
3612
3613#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3614#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3615pub enum FunctionDefinition {
3616    Identifier(String),
3617    SingleQuotedDef(String),
3618    DoubleDollarDef(String),
3619}
3620
3621impl fmt::Display for FunctionDefinition {
3622    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3623        match self {
3624            FunctionDefinition::Identifier(s) => write!(f, "{s}")?,
3625            FunctionDefinition::SingleQuotedDef(s) => write!(f, "'{s}'")?,
3626            FunctionDefinition::DoubleDollarDef(s) => write!(f, "$${s}$$")?,
3627        }
3628        Ok(())
3629    }
3630}
3631
3632impl FunctionDefinition {
3633    /// Returns the function definition as a string slice.
3634    pub fn as_str(&self) -> &str {
3635        match self {
3636            FunctionDefinition::Identifier(s) => s,
3637            FunctionDefinition::SingleQuotedDef(s) => s,
3638            FunctionDefinition::DoubleDollarDef(s) => s,
3639        }
3640    }
3641
3642    /// Returns the function definition as a string.
3643    pub fn into_string(self) -> String {
3644        match self {
3645            FunctionDefinition::Identifier(s) => s,
3646            FunctionDefinition::SingleQuotedDef(s) => s,
3647            FunctionDefinition::DoubleDollarDef(s) => s,
3648        }
3649    }
3650}
3651
3652/// Return types of a function.
3653#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3654#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3655pub enum CreateFunctionReturns {
3656    /// RETURNS rettype
3657    Value(DataType),
3658    /// RETURNS TABLE ( column_name column_type [, ...] )
3659    Table(Vec<TableColumnDef>),
3660}
3661
3662impl fmt::Display for CreateFunctionReturns {
3663    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3664        match self {
3665            Self::Value(data_type) => write!(f, "RETURNS {}", data_type),
3666            Self::Table(columns) => {
3667                write!(f, "RETURNS TABLE ({})", display_comma_separated(columns))
3668            }
3669        }
3670    }
3671}
3672
3673/// Table column definition
3674#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3675#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3676pub struct TableColumnDef {
3677    pub name: Ident,
3678    pub data_type: DataType,
3679}
3680
3681impl fmt::Display for TableColumnDef {
3682    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3683        write!(f, "{} {}", self.name, self.data_type)
3684    }
3685}
3686
3687/// Postgres specific feature.
3688///
3689/// See [Postgresdocs](https://www.postgresql.org/docs/15/sql-createfunction.html)
3690/// for more details
3691#[derive(Debug, Default, Clone, PartialEq, Eq, Hash)]
3692#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3693pub struct CreateFunctionBody {
3694    /// LANGUAGE lang_name
3695    pub language: Option<Ident>,
3696    /// RUNTIME runtime_name
3697    pub runtime: Option<Ident>,
3698
3699    /// IMMUTABLE | STABLE | VOLATILE
3700    pub behavior: Option<FunctionBehavior>,
3701    /// AS 'definition'
3702    ///
3703    /// Note that Hive's `AS class_name` is also parsed here.
3704    pub as_: Option<FunctionDefinition>,
3705    /// RETURN expression
3706    pub return_: Option<Expr>,
3707    /// USING ...
3708    pub using: Option<CreateFunctionUsing>,
3709}
3710
3711impl fmt::Display for CreateFunctionBody {
3712    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3713        if let Some(language) = &self.language {
3714            write!(f, " LANGUAGE {language}")?;
3715        }
3716        if let Some(runtime) = &self.runtime {
3717            write!(f, " RUNTIME {runtime}")?;
3718        }
3719        if let Some(behavior) = &self.behavior {
3720            write!(f, " {behavior}")?;
3721        }
3722        if let Some(definition) = &self.as_ {
3723            write!(f, " AS {definition}")?;
3724        }
3725        if let Some(expr) = &self.return_ {
3726            write!(f, " RETURN {expr}")?;
3727        }
3728        if let Some(using) = &self.using {
3729            write!(f, " {using}")?;
3730        }
3731        Ok(())
3732    }
3733}
3734
3735#[derive(Debug, Default, Clone, PartialEq, Eq, Hash)]
3736#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3737pub struct CreateFunctionWithOptions {
3738    /// Always retry on network errors.
3739    pub always_retry_on_network_error: Option<bool>,
3740    /// Use async functions (only available for JS UDF)
3741    pub r#async: Option<bool>,
3742    /// Call in batch mode (only available for JS UDF)
3743    pub batch: Option<bool>,
3744}
3745
3746/// TODO(kwannoel): Generate from the struct definition instead.
3747impl TryFrom<Vec<SqlOption>> for CreateFunctionWithOptions {
3748    type Error = StrError;
3749
3750    fn try_from(with_options: Vec<SqlOption>) -> Result<Self, Self::Error> {
3751        let mut options = Self::default();
3752        for option in with_options {
3753            match option.name.to_string().to_lowercase().as_str() {
3754                "always_retry_on_network_error" => {
3755                    options.always_retry_on_network_error = Some(matches!(
3756                        option.value,
3757                        SqlOptionValue::Value(Value::Boolean(true))
3758                    ));
3759                }
3760                "async" => {
3761                    options.r#async = Some(matches!(
3762                        option.value,
3763                        SqlOptionValue::Value(Value::Boolean(true))
3764                    ))
3765                }
3766                "batch" => {
3767                    options.batch = Some(matches!(
3768                        option.value,
3769                        SqlOptionValue::Value(Value::Boolean(true))
3770                    ))
3771                }
3772                _ => {
3773                    return Err(StrError(format!("unknown option: {}", option.name)));
3774                }
3775            }
3776        }
3777        Ok(options)
3778    }
3779}
3780
3781impl Display for CreateFunctionWithOptions {
3782    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3783        if self == &Self::default() {
3784            return Ok(());
3785        }
3786        let mut options = vec![];
3787        if let Some(v) = self.always_retry_on_network_error {
3788            options.push(format!("always_retry_on_network_error = {}", v));
3789        }
3790        if let Some(v) = self.r#async {
3791            options.push(format!("async = {}", v));
3792        }
3793        if let Some(v) = self.batch {
3794            options.push(format!("batch = {}", v));
3795        }
3796        write!(f, " WITH ( {} )", display_comma_separated(&options))
3797    }
3798}
3799
3800#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3801#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3802pub enum CreateFunctionUsing {
3803    Link(String),
3804    Base64(String),
3805}
3806
3807impl fmt::Display for CreateFunctionUsing {
3808    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3809        write!(f, "USING ")?;
3810        match self {
3811            CreateFunctionUsing::Link(uri) => write!(f, "LINK '{uri}'"),
3812            CreateFunctionUsing::Base64(s) => {
3813                write!(f, "BASE64 '{s}'")
3814            }
3815        }
3816    }
3817}
3818
3819#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3820#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3821pub struct ConfigParam {
3822    pub param: Ident,
3823    pub value: SetVariableValue,
3824}
3825
3826impl fmt::Display for ConfigParam {
3827    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3828        write!(f, "SET {} = {}", self.param, self.value)
3829    }
3830}
3831
3832#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3833#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3834pub enum SetVariableValue {
3835    Single(SetVariableValueSingle),
3836    List(Vec<SetVariableValueSingle>),
3837    Default,
3838}
3839
3840impl From<SetVariableValueSingle> for SetVariableValue {
3841    fn from(value: SetVariableValueSingle) -> Self {
3842        SetVariableValue::Single(value)
3843    }
3844}
3845
3846impl fmt::Display for SetVariableValue {
3847    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3848        use SetVariableValue::*;
3849        match self {
3850            Single(val) => write!(f, "{}", val),
3851            List(list) => write!(f, "{}", display_comma_separated(list),),
3852            Default => write!(f, "DEFAULT"),
3853        }
3854    }
3855}
3856
3857#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3858#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3859pub enum SetVariableValueSingle {
3860    Ident(Ident),
3861    Literal(Value),
3862}
3863
3864impl SetVariableValueSingle {
3865    pub fn to_string_unquoted(&self) -> String {
3866        match self {
3867            Self::Literal(Value::SingleQuotedString(s))
3868            | Self::Literal(Value::DoubleQuotedString(s)) => s.clone(),
3869            _ => self.to_string(),
3870        }
3871    }
3872}
3873
3874impl fmt::Display for SetVariableValueSingle {
3875    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3876        use SetVariableValueSingle::*;
3877        match self {
3878            Ident(ident) => write!(f, "{}", ident),
3879            Literal(literal) => write!(f, "{}", literal),
3880        }
3881    }
3882}
3883
3884#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3885#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3886pub enum AsOf {
3887    ProcessTime,
3888    // used by time travel
3889    ProcessTimeWithInterval((String, DateTimeField)),
3890    // the number of seconds that have elapsed since the Unix epoch, which is January 1, 1970 at 00:00:00 Coordinated Universal Time (UTC).
3891    TimestampNum(i64),
3892    TimestampString(String),
3893    VersionNum(i64),
3894    VersionString(String),
3895}
3896
3897impl fmt::Display for AsOf {
3898    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3899        use AsOf::*;
3900        match self {
3901            ProcessTime => write!(f, " FOR SYSTEM_TIME AS OF PROCTIME()"),
3902            ProcessTimeWithInterval((value, leading_field)) => write!(
3903                f,
3904                " FOR SYSTEM_TIME AS OF NOW() - '{}' {}",
3905                value, leading_field
3906            ),
3907            TimestampNum(ts) => write!(f, " FOR SYSTEM_TIME AS OF {}", ts),
3908            TimestampString(ts) => write!(f, " FOR SYSTEM_TIME AS OF '{}'", ts),
3909            VersionNum(v) => write!(f, " FOR SYSTEM_VERSION AS OF {}", v),
3910            VersionString(v) => write!(f, " FOR SYSTEM_VERSION AS OF '{}'", v),
3911        }
3912    }
3913}
3914
3915#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3916#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3917pub enum DiscardType {
3918    All,
3919}
3920
3921impl fmt::Display for DiscardType {
3922    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3923        use DiscardType::*;
3924        match self {
3925            All => write!(f, "ALL"),
3926        }
3927    }
3928}
3929
3930// We decouple "default" from none,
3931// so we can choose strategies that make the most sense.
3932#[derive(Debug, Default, Clone, PartialEq, Eq, Hash)]
3933#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3934pub enum BackfillOrderStrategy {
3935    #[default]
3936    Default,
3937    None,
3938    Auto,
3939    Fixed(Vec<(ObjectName, ObjectName)>),
3940}
3941
3942impl fmt::Display for BackfillOrderStrategy {
3943    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3944        use BackfillOrderStrategy::*;
3945        match self {
3946            Default => write!(f, "DEFAULT"),
3947            None => write!(f, "NONE"),
3948            Auto => write!(f, "AUTO"),
3949            Fixed(map) => {
3950                let mut parts = vec![];
3951                for (start, end) in map {
3952                    parts.push(format!("{} -> {}", start, end));
3953                }
3954                write!(f, "FIXED({})", display_comma_separated(&parts))
3955            }
3956        }
3957    }
3958}
3959
3960impl Statement {
3961    pub fn to_redacted_string(&self, keywords: RedactSqlOptionKeywordsRef) -> String {
3962        REDACT_SQL_OPTION_KEYWORDS.sync_scope(keywords, || self.to_string_unchecked())
3963    }
3964
3965    /// Create a new `CREATE TABLE` statement with the given `name` and empty fields.
3966    pub fn default_create_table(name: ObjectName) -> Self {
3967        Self::CreateTable {
3968            name,
3969            or_replace: false,
3970            temporary: false,
3971            if_not_exists: false,
3972            columns: Vec::new(),
3973            wildcard_idx: None,
3974            constraints: Vec::new(),
3975            with_options: Vec::new(),
3976            format_encode: None,
3977            source_watermarks: Vec::new(),
3978            append_only: false,
3979            on_conflict: None,
3980            with_version_columns: Vec::new(),
3981            query: None,
3982            cdc_table_info: None,
3983            include_column_options: Vec::new(),
3984            webhook_info: None,
3985            engine: Engine::Hummock,
3986        }
3987    }
3988}
3989
3990#[cfg(test)]
3991mod tests {
3992    use super::*;
3993
3994    #[test]
3995    fn test_grouping_sets_display() {
3996        // a and b in different group
3997        let grouping_sets = Expr::GroupingSets(vec![
3998            vec![Expr::Identifier(Ident::new_unchecked("a"))],
3999            vec![Expr::Identifier(Ident::new_unchecked("b"))],
4000        ]);
4001        assert_eq!("GROUPING SETS ((a), (b))", format!("{}", grouping_sets));
4002
4003        // a and b in the same group
4004        let grouping_sets = Expr::GroupingSets(vec![vec![
4005            Expr::Identifier(Ident::new_unchecked("a")),
4006            Expr::Identifier(Ident::new_unchecked("b")),
4007        ]]);
4008        assert_eq!("GROUPING SETS ((a, b))", format!("{}", grouping_sets));
4009
4010        // (a, b) and (c, d) in different group
4011        let grouping_sets = Expr::GroupingSets(vec![
4012            vec![
4013                Expr::Identifier(Ident::new_unchecked("a")),
4014                Expr::Identifier(Ident::new_unchecked("b")),
4015            ],
4016            vec![
4017                Expr::Identifier(Ident::new_unchecked("c")),
4018                Expr::Identifier(Ident::new_unchecked("d")),
4019            ],
4020        ]);
4021        assert_eq!(
4022            "GROUPING SETS ((a, b), (c, d))",
4023            format!("{}", grouping_sets)
4024        );
4025    }
4026
4027    #[test]
4028    fn test_rollup_display() {
4029        let rollup = Expr::Rollup(vec![vec![Expr::Identifier(Ident::new_unchecked("a"))]]);
4030        assert_eq!("ROLLUP (a)", format!("{}", rollup));
4031
4032        let rollup = Expr::Rollup(vec![vec![
4033            Expr::Identifier(Ident::new_unchecked("a")),
4034            Expr::Identifier(Ident::new_unchecked("b")),
4035        ]]);
4036        assert_eq!("ROLLUP ((a, b))", format!("{}", rollup));
4037
4038        let rollup = Expr::Rollup(vec![
4039            vec![Expr::Identifier(Ident::new_unchecked("a"))],
4040            vec![Expr::Identifier(Ident::new_unchecked("b"))],
4041        ]);
4042        assert_eq!("ROLLUP (a, b)", format!("{}", rollup));
4043
4044        let rollup = Expr::Rollup(vec![
4045            vec![Expr::Identifier(Ident::new_unchecked("a"))],
4046            vec![
4047                Expr::Identifier(Ident::new_unchecked("b")),
4048                Expr::Identifier(Ident::new_unchecked("c")),
4049            ],
4050            vec![Expr::Identifier(Ident::new_unchecked("d"))],
4051        ]);
4052        assert_eq!("ROLLUP (a, (b, c), d)", format!("{}", rollup));
4053    }
4054
4055    #[test]
4056    fn test_cube_display() {
4057        let cube = Expr::Cube(vec![vec![Expr::Identifier(Ident::new_unchecked("a"))]]);
4058        assert_eq!("CUBE (a)", format!("{}", cube));
4059
4060        let cube = Expr::Cube(vec![vec![
4061            Expr::Identifier(Ident::new_unchecked("a")),
4062            Expr::Identifier(Ident::new_unchecked("b")),
4063        ]]);
4064        assert_eq!("CUBE ((a, b))", format!("{}", cube));
4065
4066        let cube = Expr::Cube(vec![
4067            vec![Expr::Identifier(Ident::new_unchecked("a"))],
4068            vec![Expr::Identifier(Ident::new_unchecked("b"))],
4069        ]);
4070        assert_eq!("CUBE (a, b)", format!("{}", cube));
4071
4072        let cube = Expr::Cube(vec![
4073            vec![Expr::Identifier(Ident::new_unchecked("a"))],
4074            vec![
4075                Expr::Identifier(Ident::new_unchecked("b")),
4076                Expr::Identifier(Ident::new_unchecked("c")),
4077            ],
4078            vec![Expr::Identifier(Ident::new_unchecked("d"))],
4079        ]);
4080        assert_eq!("CUBE (a, (b, c), d)", format!("{}", cube));
4081    }
4082
4083    #[test]
4084    fn test_array_index_display() {
4085        let array_index = Expr::Index {
4086            obj: Box::new(Expr::Identifier(Ident::new_unchecked("v1"))),
4087            index: Box::new(Expr::Value(Value::Number("1".into()))),
4088        };
4089        assert_eq!("v1[1]", format!("{}", array_index));
4090
4091        let array_index2 = Expr::Index {
4092            obj: Box::new(array_index),
4093            index: Box::new(Expr::Value(Value::Number("1".into()))),
4094        };
4095        assert_eq!("v1[1][1]", format!("{}", array_index2));
4096    }
4097
4098    #[test]
4099    /// issue: https://github.com/risingwavelabs/risingwave/issues/7635
4100    fn test_nested_op_display() {
4101        let binary_op = Expr::BinaryOp {
4102            left: Box::new(Expr::Value(Value::Boolean(true))),
4103            op: BinaryOperator::Or,
4104            right: Box::new(Expr::IsNotFalse(Box::new(Expr::Value(Value::Boolean(
4105                true,
4106            ))))),
4107        };
4108        assert_eq!("true OR true IS NOT FALSE", format!("{}", binary_op));
4109
4110        let unary_op = Expr::UnaryOp {
4111            op: UnaryOperator::Not,
4112            expr: Box::new(Expr::IsNotFalse(Box::new(Expr::Value(Value::Boolean(
4113                true,
4114            ))))),
4115        };
4116        assert_eq!("NOT true IS NOT FALSE", format!("{}", unary_op));
4117    }
4118
4119    #[test]
4120    fn test_create_function_display() {
4121        let create_function = Statement::CreateFunction {
4122            or_replace: false,
4123            temporary: false,
4124            if_not_exists: false,
4125            name: ObjectName(vec![Ident::new_unchecked("foo")]),
4126            args: Some(vec![OperateFunctionArg::unnamed(DataType::Int)]),
4127            returns: Some(CreateFunctionReturns::Value(DataType::Int)),
4128            params: CreateFunctionBody {
4129                language: Some(Ident::new_unchecked("python")),
4130                runtime: None,
4131                behavior: Some(FunctionBehavior::Immutable),
4132                as_: Some(FunctionDefinition::SingleQuotedDef("SELECT 1".to_owned())),
4133                return_: None,
4134                using: None,
4135            },
4136            with_options: CreateFunctionWithOptions {
4137                always_retry_on_network_error: None,
4138                r#async: None,
4139                batch: None,
4140            },
4141        };
4142        assert_eq!(
4143            "CREATE FUNCTION foo(INT) RETURNS INT LANGUAGE python IMMUTABLE AS 'SELECT 1'",
4144            format!("{}", create_function)
4145        );
4146        let create_function = Statement::CreateFunction {
4147            or_replace: false,
4148            temporary: false,
4149            if_not_exists: false,
4150            name: ObjectName(vec![Ident::new_unchecked("foo")]),
4151            args: Some(vec![OperateFunctionArg::unnamed(DataType::Int)]),
4152            returns: Some(CreateFunctionReturns::Value(DataType::Int)),
4153            params: CreateFunctionBody {
4154                language: Some(Ident::new_unchecked("python")),
4155                runtime: None,
4156                behavior: Some(FunctionBehavior::Immutable),
4157                as_: Some(FunctionDefinition::SingleQuotedDef("SELECT 1".to_owned())),
4158                return_: None,
4159                using: None,
4160            },
4161            with_options: CreateFunctionWithOptions {
4162                always_retry_on_network_error: Some(true),
4163                r#async: None,
4164                batch: None,
4165            },
4166        };
4167        assert_eq!(
4168            "CREATE FUNCTION foo(INT) RETURNS INT LANGUAGE python IMMUTABLE AS 'SELECT 1' WITH ( always_retry_on_network_error = true )",
4169            format!("{}", create_function)
4170        );
4171    }
4172}