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                if op == &UnaryOperator::PGPostfixFactorial {
685                    write!(f, "{}{}", expr, op)
686                } else {
687                    write!(f, "{} {}", op, expr)
688                }
689            }
690            Expr::Cast { expr, data_type } => write!(f, "CAST({} AS {})", expr, data_type),
691            Expr::TryCast { expr, data_type } => write!(f, "TRY_CAST({} AS {})", expr, data_type),
692            Expr::AtTimeZone {
693                timestamp,
694                time_zone,
695            } => write!(f, "{} AT TIME ZONE {}", timestamp, time_zone),
696            Expr::Extract { field, expr } => write!(f, "EXTRACT({} FROM {})", field, expr),
697            Expr::Collate { expr, collation } => write!(f, "{} COLLATE {}", expr, collation),
698            Expr::Nested(ast) => write!(f, "({})", ast),
699            Expr::Value(v) => write!(f, "{}", v),
700            Expr::Parameter { index } => write!(f, "${}", index),
701            Expr::TypedString { data_type, value } => {
702                write!(f, "{}", data_type)?;
703                write!(f, " '{}'", &value::escape_single_quote_string(value))
704            }
705            Expr::Function(fun) => write!(f, "{}", fun),
706            Expr::Case {
707                operand,
708                conditions,
709                results,
710                else_result,
711            } => {
712                write!(f, "CASE")?;
713                if let Some(operand) = operand {
714                    write!(f, " {}", operand)?;
715                }
716                for (c, r) in conditions.iter().zip_eq(results) {
717                    write!(f, " WHEN {} THEN {}", c, r)?;
718                }
719
720                if let Some(else_result) = else_result {
721                    write!(f, " ELSE {}", else_result)?;
722                }
723                write!(f, " END")
724            }
725            Expr::Exists(s) => write!(f, "EXISTS ({})", s),
726            Expr::Subquery(s) => write!(f, "({})", s),
727            Expr::GroupingSets(sets) => {
728                write!(f, "GROUPING SETS (")?;
729                let mut sep = "";
730                for set in sets {
731                    write!(f, "{}", sep)?;
732                    sep = ", ";
733                    write!(f, "({})", display_comma_separated(set))?;
734                }
735                write!(f, ")")
736            }
737            Expr::Cube(sets) => {
738                write!(f, "CUBE (")?;
739                let mut sep = "";
740                for set in sets {
741                    write!(f, "{}", sep)?;
742                    sep = ", ";
743                    if set.len() == 1 {
744                        write!(f, "{}", set[0])?;
745                    } else {
746                        write!(f, "({})", display_comma_separated(set))?;
747                    }
748                }
749                write!(f, ")")
750            }
751            Expr::Rollup(sets) => {
752                write!(f, "ROLLUP (")?;
753                let mut sep = "";
754                for set in sets {
755                    write!(f, "{}", sep)?;
756                    sep = ", ";
757                    if set.len() == 1 {
758                        write!(f, "{}", set[0])?;
759                    } else {
760                        write!(f, "({})", display_comma_separated(set))?;
761                    }
762                }
763                write!(f, ")")
764            }
765            Expr::Substring {
766                expr,
767                substring_from,
768                substring_for,
769            } => {
770                write!(f, "SUBSTRING({}", expr)?;
771                if let Some(from_part) = substring_from {
772                    write!(f, " FROM {}", from_part)?;
773                }
774                if let Some(from_part) = substring_for {
775                    write!(f, " FOR {}", from_part)?;
776                }
777
778                write!(f, ")")
779            }
780            Expr::Position { substring, string } => {
781                write!(f, "POSITION({} IN {})", substring, string)
782            }
783            Expr::Overlay {
784                expr,
785                new_substring,
786                start,
787                count,
788            } => {
789                write!(f, "OVERLAY({}", expr)?;
790                write!(f, " PLACING {}", new_substring)?;
791                write!(f, " FROM {}", start)?;
792
793                if let Some(count_expr) = count {
794                    write!(f, " FOR {}", count_expr)?;
795                }
796
797                write!(f, ")")
798            }
799            Expr::IsDistinctFrom(a, b) => write!(f, "{} IS DISTINCT FROM {}", a, b),
800            Expr::IsNotDistinctFrom(a, b) => write!(f, "{} IS NOT DISTINCT FROM {}", a, b),
801            Expr::Trim {
802                expr,
803                trim_where,
804                trim_what,
805            } => {
806                write!(f, "TRIM(")?;
807                if let Some(ident) = trim_where {
808                    write!(f, "{} ", ident)?;
809                }
810                if let Some(trim_char) = trim_what {
811                    write!(f, "{} ", trim_char)?;
812                }
813                write!(f, "FROM {})", expr)
814            }
815            Expr::Row(exprs) => write!(
816                f,
817                "ROW({})",
818                exprs
819                    .iter()
820                    .map(|v| v.to_string())
821                    .collect::<Vec<String>>()
822                    .as_slice()
823                    .join(", ")
824            ),
825            Expr::Index { obj, index } => {
826                write!(f, "{}[{}]", obj, index)?;
827                Ok(())
828            }
829            Expr::ArrayRangeIndex { obj, start, end } => {
830                let start_str = match start {
831                    None => "".to_owned(),
832                    Some(start) => format!("{}", start),
833                };
834                let end_str = match end {
835                    None => "".to_owned(),
836                    Some(end) => format!("{}", end),
837                };
838                write!(f, "{}[{}:{}]", obj, start_str, end_str)?;
839                Ok(())
840            }
841            Expr::Array(exprs) => write!(f, "{}", exprs),
842            Expr::ArraySubquery(s) => write!(f, "ARRAY ({})", s),
843            Expr::LambdaFunction { args, body } => {
844                write!(
845                    f,
846                    "|{}| {}",
847                    args.iter().map(ToString::to_string).join(", "),
848                    body
849                )
850            }
851            Expr::Map { entries } => {
852                write!(
853                    f,
854                    "MAP {{{}}}",
855                    entries
856                        .iter()
857                        .map(|(k, v)| format!("{}: {}", k, v))
858                        .join(", ")
859                )
860            }
861        }
862    }
863}
864
865/// A window specification (i.e. `OVER (PARTITION BY .. ORDER BY .. etc.)`).
866/// This is used both for named window definitions and inline window specifications.
867#[derive(Debug, Clone, PartialEq, Eq, Hash)]
868#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
869pub struct WindowSpec {
870    pub partition_by: Vec<Expr>,
871    pub order_by: Vec<OrderByExpr>,
872    pub window_frame: Option<WindowFrame>,
873}
874
875/// A window definition that can appear in the OVER clause of a window function.
876/// This can be either an inline window specification or a reference to a named window.
877#[derive(Debug, Clone, PartialEq, Eq, Hash)]
878#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
879pub enum Window {
880    /// Inline window specification: `OVER (PARTITION BY ... ORDER BY ...)`
881    Spec(WindowSpec),
882    /// Named window reference: `OVER window_name`
883    Name(Ident),
884}
885
886impl fmt::Display for WindowSpec {
887    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
888        let mut delim = "";
889        if !self.partition_by.is_empty() {
890            delim = " ";
891            write!(
892                f,
893                "PARTITION BY {}",
894                display_comma_separated(&self.partition_by)
895            )?;
896        }
897        if !self.order_by.is_empty() {
898            f.write_str(delim)?;
899            delim = " ";
900            write!(f, "ORDER BY {}", display_comma_separated(&self.order_by))?;
901        }
902        if let Some(window_frame) = &self.window_frame {
903            f.write_str(delim)?;
904            window_frame.fmt(f)?;
905        }
906        Ok(())
907    }
908}
909
910impl fmt::Display for Window {
911    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
912        match self {
913            Window::Spec(spec) => write!(f, "({})", spec),
914            Window::Name(name) => write!(f, "{}", name),
915        }
916    }
917}
918
919/// Specifies the data processed by a window function, e.g.
920/// `RANGE UNBOUNDED PRECEDING` or `ROWS BETWEEN 5 PRECEDING AND CURRENT ROW`.
921///
922/// Note: The parser does not validate the specified bounds; the caller should
923/// reject invalid bounds like `ROWS UNBOUNDED FOLLOWING` before execution.
924#[derive(Debug, Clone, PartialEq, Eq, Hash)]
925#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
926pub struct WindowFrame {
927    pub units: WindowFrameUnits,
928    pub bounds: WindowFrameBounds,
929    pub exclusion: Option<WindowFrameExclusion>,
930}
931
932#[derive(Debug, Clone, PartialEq, Eq, Hash)]
933#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
934pub enum WindowFrameUnits {
935    Rows,
936    Range,
937    Groups,
938    Session,
939}
940
941#[derive(Debug, Clone, PartialEq, Eq, Hash)]
942#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
943pub enum WindowFrameBounds {
944    Bounds {
945        start: WindowFrameBound,
946        /// The right bound of the `BETWEEN .. AND` clause. The end bound of `None`
947        /// indicates the shorthand form (e.g. `ROWS 1 PRECEDING`), which must
948        /// behave the same as `end_bound = WindowFrameBound::CurrentRow`.
949        end: Option<WindowFrameBound>,
950    },
951    Gap(Box<Expr>),
952}
953
954impl fmt::Display for WindowFrame {
955    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
956        write!(f, "{} ", self.units)?;
957        match &self.bounds {
958            WindowFrameBounds::Bounds { start, end } => {
959                if let Some(end) = end {
960                    write!(f, "BETWEEN {} AND {}", start, end)
961                } else {
962                    write!(f, "{}", start)
963                }
964            }
965            WindowFrameBounds::Gap(gap) => {
966                write!(f, "WITH GAP {}", gap)
967            }
968        }
969    }
970}
971
972impl fmt::Display for WindowFrameUnits {
973    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
974        f.write_str(match self {
975            WindowFrameUnits::Rows => "ROWS",
976            WindowFrameUnits::Range => "RANGE",
977            WindowFrameUnits::Groups => "GROUPS",
978            WindowFrameUnits::Session => "SESSION",
979        })
980    }
981}
982
983/// Specifies [WindowFrame]'s `start_bound` and `end_bound`
984#[derive(Debug, Clone, PartialEq, Eq, Hash)]
985#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
986pub enum WindowFrameBound {
987    /// `CURRENT ROW`
988    CurrentRow,
989    /// `<offset> PRECEDING` or `UNBOUNDED PRECEDING`
990    Preceding(Option<Box<Expr>>),
991    /// `<offset> FOLLOWING` or `UNBOUNDED FOLLOWING`.
992    Following(Option<Box<Expr>>),
993}
994
995impl fmt::Display for WindowFrameBound {
996    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
997        match self {
998            WindowFrameBound::CurrentRow => f.write_str("CURRENT ROW"),
999            WindowFrameBound::Preceding(None) => f.write_str("UNBOUNDED PRECEDING"),
1000            WindowFrameBound::Following(None) => f.write_str("UNBOUNDED FOLLOWING"),
1001            WindowFrameBound::Preceding(Some(n)) => write!(f, "{} PRECEDING", n),
1002            WindowFrameBound::Following(Some(n)) => write!(f, "{} FOLLOWING", n),
1003        }
1004    }
1005}
1006
1007/// Frame exclusion option of [WindowFrame].
1008#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
1009#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1010pub enum WindowFrameExclusion {
1011    CurrentRow,
1012    Group,
1013    Ties,
1014    NoOthers,
1015}
1016
1017impl fmt::Display for WindowFrameExclusion {
1018    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1019        match self {
1020            WindowFrameExclusion::CurrentRow => f.write_str("EXCLUDE CURRENT ROW"),
1021            WindowFrameExclusion::Group => f.write_str("EXCLUDE GROUP"),
1022            WindowFrameExclusion::Ties => f.write_str("EXCLUDE TIES"),
1023            WindowFrameExclusion::NoOthers => f.write_str("EXCLUDE NO OTHERS"),
1024        }
1025    }
1026}
1027
1028#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1029#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1030pub enum AddDropSync {
1031    ADD,
1032    DROP,
1033    SYNC,
1034}
1035
1036impl fmt::Display for AddDropSync {
1037    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1038        match self {
1039            AddDropSync::SYNC => f.write_str("SYNC PARTITIONS"),
1040            AddDropSync::DROP => f.write_str("DROP PARTITIONS"),
1041            AddDropSync::ADD => f.write_str("ADD PARTITIONS"),
1042        }
1043    }
1044}
1045
1046#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1047#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1048pub enum ShowObject {
1049    Table { schema: Option<Ident> },
1050    InternalTable { schema: Option<Ident> },
1051    Database,
1052    Schema,
1053    View { schema: Option<Ident> },
1054    MaterializedView { schema: Option<Ident> },
1055    Source { schema: Option<Ident> },
1056    Sink { schema: Option<Ident> },
1057    Subscription { schema: Option<Ident> },
1058    Columns { table: ObjectName },
1059    Connection { schema: Option<Ident> },
1060    Secret { schema: Option<Ident> },
1061    Function { schema: Option<Ident> },
1062    Indexes { table: ObjectName },
1063    Cluster,
1064    Jobs,
1065    ProcessList,
1066    Cursor,
1067    SubscriptionCursor,
1068}
1069
1070#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1071#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1072pub struct JobIdents(pub Vec<u32>);
1073
1074impl fmt::Display for ShowObject {
1075    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1076        fn fmt_schema(schema: &Option<Ident>) -> String {
1077            if let Some(schema) = schema {
1078                format!(" FROM {}", schema.value)
1079            } else {
1080                "".to_owned()
1081            }
1082        }
1083
1084        match self {
1085            ShowObject::Database => f.write_str("DATABASES"),
1086            ShowObject::Schema => f.write_str("SCHEMAS"),
1087            ShowObject::Table { schema } => {
1088                write!(f, "TABLES{}", fmt_schema(schema))
1089            }
1090            ShowObject::InternalTable { schema } => {
1091                write!(f, "INTERNAL TABLES{}", fmt_schema(schema))
1092            }
1093            ShowObject::View { schema } => {
1094                write!(f, "VIEWS{}", fmt_schema(schema))
1095            }
1096            ShowObject::MaterializedView { schema } => {
1097                write!(f, "MATERIALIZED VIEWS{}", fmt_schema(schema))
1098            }
1099            ShowObject::Source { schema } => write!(f, "SOURCES{}", fmt_schema(schema)),
1100            ShowObject::Sink { schema } => write!(f, "SINKS{}", fmt_schema(schema)),
1101            ShowObject::Columns { table } => write!(f, "COLUMNS FROM {}", table),
1102            ShowObject::Connection { schema } => write!(f, "CONNECTIONS{}", fmt_schema(schema)),
1103            ShowObject::Function { schema } => write!(f, "FUNCTIONS{}", fmt_schema(schema)),
1104            ShowObject::Indexes { table } => write!(f, "INDEXES FROM {}", table),
1105            ShowObject::Cluster => {
1106                write!(f, "CLUSTER")
1107            }
1108            ShowObject::Jobs => write!(f, "JOBS"),
1109            ShowObject::ProcessList => write!(f, "PROCESSLIST"),
1110            ShowObject::Subscription { schema } => write!(f, "SUBSCRIPTIONS{}", fmt_schema(schema)),
1111            ShowObject::Secret { schema } => write!(f, "SECRETS{}", fmt_schema(schema)),
1112            ShowObject::Cursor => write!(f, "CURSORS"),
1113            ShowObject::SubscriptionCursor => write!(f, "SUBSCRIPTION CURSORS"),
1114        }
1115    }
1116}
1117
1118#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1119#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1120pub enum ShowCreateType {
1121    Table,
1122    MaterializedView,
1123    View,
1124    Index,
1125    Source,
1126    Sink,
1127    Function,
1128    Subscription,
1129}
1130
1131impl fmt::Display for ShowCreateType {
1132    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1133        match self {
1134            ShowCreateType::Table => f.write_str("TABLE"),
1135            ShowCreateType::MaterializedView => f.write_str("MATERIALIZED VIEW"),
1136            ShowCreateType::View => f.write_str("VIEW"),
1137            ShowCreateType::Index => f.write_str("INDEX"),
1138            ShowCreateType::Source => f.write_str("SOURCE"),
1139            ShowCreateType::Sink => f.write_str("SINK"),
1140            ShowCreateType::Function => f.write_str("FUNCTION"),
1141            ShowCreateType::Subscription => f.write_str("SUBSCRIPTION"),
1142        }
1143    }
1144}
1145
1146#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1147#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1148pub enum CommentObject {
1149    Column,
1150    Table,
1151}
1152
1153impl fmt::Display for CommentObject {
1154    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1155        match self {
1156            CommentObject::Column => f.write_str("COLUMN"),
1157            CommentObject::Table => f.write_str("TABLE"),
1158        }
1159    }
1160}
1161
1162#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1163#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1164pub enum ExplainType {
1165    Logical,
1166    Physical,
1167    DistSql,
1168}
1169
1170impl fmt::Display for ExplainType {
1171    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1172        match self {
1173            ExplainType::Logical => f.write_str("Logical"),
1174            ExplainType::Physical => f.write_str("Physical"),
1175            ExplainType::DistSql => f.write_str("DistSQL"),
1176        }
1177    }
1178}
1179
1180#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1181#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1182pub enum ExplainFormat {
1183    Text,
1184    Json,
1185    Xml,
1186    Yaml,
1187    Dot,
1188}
1189
1190impl fmt::Display for ExplainFormat {
1191    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1192        match self {
1193            ExplainFormat::Text => f.write_str("TEXT"),
1194            ExplainFormat::Json => f.write_str("JSON"),
1195            ExplainFormat::Xml => f.write_str("XML"),
1196            ExplainFormat::Yaml => f.write_str("YAML"),
1197            ExplainFormat::Dot => f.write_str("DOT"),
1198        }
1199    }
1200}
1201
1202#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1203#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1204pub struct ExplainOptions {
1205    /// Display additional information regarding the plan.
1206    pub verbose: bool,
1207    // Trace plan transformation of the optimizer step by step
1208    pub trace: bool,
1209    // Display backfill order
1210    pub backfill: bool,
1211    // explain's plan type
1212    pub explain_type: ExplainType,
1213    // explain's plan format
1214    pub explain_format: ExplainFormat,
1215}
1216
1217impl Default for ExplainOptions {
1218    fn default() -> Self {
1219        Self {
1220            verbose: false,
1221            trace: false,
1222            backfill: false,
1223            explain_type: ExplainType::Physical,
1224            explain_format: ExplainFormat::Text,
1225        }
1226    }
1227}
1228
1229impl fmt::Display for ExplainOptions {
1230    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1231        let default = Self::default();
1232        if *self == default {
1233            Ok(())
1234        } else {
1235            let mut option_strs = vec![];
1236            if self.verbose {
1237                option_strs.push("VERBOSE".to_owned());
1238            }
1239            if self.trace {
1240                option_strs.push("TRACE".to_owned());
1241            }
1242            if self.backfill {
1243                option_strs.push("BACKFILL".to_owned());
1244            }
1245            if self.explain_type == default.explain_type {
1246                option_strs.push(self.explain_type.to_string());
1247            }
1248            if self.explain_format == default.explain_format {
1249                option_strs.push(self.explain_format.to_string());
1250            }
1251            write!(f, "{}", option_strs.iter().format(","))
1252        }
1253    }
1254}
1255
1256#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1257#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1258pub struct CdcTableInfo {
1259    pub source_name: ObjectName,
1260    pub external_table_name: String,
1261}
1262
1263/// A top-level statement (SELECT, INSERT, CREATE, etc.)
1264#[allow(clippy::large_enum_variant)]
1265#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1266#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1267pub enum Statement {
1268    /// Analyze (Hive)
1269    Analyze {
1270        table_name: ObjectName,
1271    },
1272    /// Truncate (Hive)
1273    Truncate {
1274        table_name: ObjectName,
1275    },
1276    /// SELECT
1277    Query(Box<Query>),
1278    /// INSERT
1279    Insert {
1280        /// TABLE
1281        table_name: ObjectName,
1282        /// COLUMNS
1283        columns: Vec<Ident>,
1284        /// A SQL query that specifies what to insert
1285        source: Box<Query>,
1286        /// Define output of this insert statement
1287        returning: Vec<SelectItem>,
1288    },
1289    Copy {
1290        /// TABLE
1291        table_name: ObjectName,
1292        /// COLUMNS
1293        columns: Vec<Ident>,
1294        /// VALUES a vector of values to be copied
1295        values: Vec<Option<String>>,
1296    },
1297    /// UPDATE
1298    Update {
1299        /// TABLE
1300        table_name: ObjectName,
1301        /// Column assignments
1302        assignments: Vec<Assignment>,
1303        /// WHERE
1304        selection: Option<Expr>,
1305        /// RETURNING
1306        returning: Vec<SelectItem>,
1307    },
1308    /// DELETE
1309    Delete {
1310        /// FROM
1311        table_name: ObjectName,
1312        /// WHERE
1313        selection: Option<Expr>,
1314        /// RETURNING
1315        returning: Vec<SelectItem>,
1316    },
1317    /// DISCARD
1318    Discard(DiscardType),
1319    /// CREATE VIEW
1320    CreateView {
1321        or_replace: bool,
1322        materialized: bool,
1323        if_not_exists: bool,
1324        /// View name
1325        name: ObjectName,
1326        columns: Vec<Ident>,
1327        query: Box<Query>,
1328        emit_mode: Option<EmitMode>,
1329        with_options: Vec<SqlOption>,
1330    },
1331    /// CREATE TABLE
1332    CreateTable {
1333        or_replace: bool,
1334        temporary: bool,
1335        if_not_exists: bool,
1336        /// Table name
1337        name: ObjectName,
1338        /// Optional schema
1339        columns: Vec<ColumnDef>,
1340        // The wildchar position in columns defined in sql. Only exist when using external schema.
1341        wildcard_idx: Option<usize>,
1342        constraints: Vec<TableConstraint>,
1343        with_options: Vec<SqlOption>,
1344        /// `FORMAT ... ENCODE ...` for table with connector
1345        format_encode: Option<CompatibleFormatEncode>,
1346        /// The watermark defined on source.
1347        source_watermarks: Vec<SourceWatermark>,
1348        /// Append only table.
1349        append_only: bool,
1350        /// On conflict behavior
1351        on_conflict: Option<OnConflict>,
1352        /// with_version_column behind on conflict
1353        with_version_column: Option<Ident>,
1354        /// `AS ( query )`
1355        query: Option<Box<Query>>,
1356        /// `FROM cdc_source TABLE database_name.table_name`
1357        cdc_table_info: Option<CdcTableInfo>,
1358        /// `INCLUDE a AS b INCLUDE c`
1359        include_column_options: IncludeOption,
1360        /// `VALIDATE SECRET secure_secret_name AS secure_compare ()`
1361        webhook_info: Option<WebhookSourceInfo>,
1362        /// `Engine = [hummock | iceberg]`
1363        engine: Engine,
1364    },
1365    /// CREATE INDEX
1366    CreateIndex {
1367        /// index name
1368        name: ObjectName,
1369        table_name: ObjectName,
1370        columns: Vec<OrderByExpr>,
1371        include: Vec<Ident>,
1372        distributed_by: Vec<Expr>,
1373        unique: bool,
1374        if_not_exists: bool,
1375    },
1376    /// CREATE SOURCE
1377    CreateSource {
1378        stmt: CreateSourceStatement,
1379    },
1380    /// CREATE SINK
1381    CreateSink {
1382        stmt: CreateSinkStatement,
1383    },
1384    /// CREATE SUBSCRIPTION
1385    CreateSubscription {
1386        stmt: CreateSubscriptionStatement,
1387    },
1388    /// CREATE CONNECTION
1389    CreateConnection {
1390        stmt: CreateConnectionStatement,
1391    },
1392    CreateSecret {
1393        stmt: CreateSecretStatement,
1394    },
1395    /// CREATE FUNCTION
1396    ///
1397    /// Postgres: <https://www.postgresql.org/docs/15/sql-createfunction.html>
1398    CreateFunction {
1399        or_replace: bool,
1400        temporary: bool,
1401        if_not_exists: bool,
1402        name: ObjectName,
1403        args: Option<Vec<OperateFunctionArg>>,
1404        returns: Option<CreateFunctionReturns>,
1405        /// Optional parameters.
1406        params: CreateFunctionBody,
1407        with_options: CreateFunctionWithOptions, // FIXME(eric): use Option<>
1408    },
1409    /// CREATE AGGREGATE
1410    ///
1411    /// Postgres: <https://www.postgresql.org/docs/15/sql-createaggregate.html>
1412    CreateAggregate {
1413        or_replace: bool,
1414        if_not_exists: bool,
1415        name: ObjectName,
1416        args: Vec<OperateFunctionArg>,
1417        returns: DataType,
1418        /// Optional parameters.
1419        append_only: bool,
1420        params: CreateFunctionBody,
1421    },
1422
1423    /// DECLARE CURSOR
1424    DeclareCursor {
1425        stmt: DeclareCursorStatement,
1426    },
1427
1428    // FETCH CURSOR
1429    FetchCursor {
1430        stmt: FetchCursorStatement,
1431    },
1432
1433    // CLOSE CURSOR
1434    CloseCursor {
1435        stmt: CloseCursorStatement,
1436    },
1437
1438    /// ALTER DATABASE
1439    AlterDatabase {
1440        name: ObjectName,
1441        operation: AlterDatabaseOperation,
1442    },
1443    /// ALTER SCHEMA
1444    AlterSchema {
1445        name: ObjectName,
1446        operation: AlterSchemaOperation,
1447    },
1448    /// ALTER TABLE
1449    AlterTable {
1450        /// Table name
1451        name: ObjectName,
1452        operation: AlterTableOperation,
1453    },
1454    /// ALTER INDEX
1455    AlterIndex {
1456        /// Index name
1457        name: ObjectName,
1458        operation: AlterIndexOperation,
1459    },
1460    /// ALTER VIEW
1461    AlterView {
1462        /// View name
1463        name: ObjectName,
1464        materialized: bool,
1465        operation: AlterViewOperation,
1466    },
1467    /// ALTER SINK
1468    AlterSink {
1469        /// Sink name
1470        name: ObjectName,
1471        operation: AlterSinkOperation,
1472    },
1473    AlterSubscription {
1474        name: ObjectName,
1475        operation: AlterSubscriptionOperation,
1476    },
1477    /// ALTER SOURCE
1478    AlterSource {
1479        /// Source name
1480        name: ObjectName,
1481        operation: AlterSourceOperation,
1482    },
1483    /// ALTER FUNCTION
1484    AlterFunction {
1485        /// Function name
1486        name: ObjectName,
1487        args: Option<Vec<OperateFunctionArg>>,
1488        operation: AlterFunctionOperation,
1489    },
1490    /// ALTER CONNECTION
1491    AlterConnection {
1492        /// Connection name
1493        name: ObjectName,
1494        operation: AlterConnectionOperation,
1495    },
1496    /// ALTER SECRET
1497    AlterSecret {
1498        /// Secret name
1499        name: ObjectName,
1500        with_options: Vec<SqlOption>,
1501        operation: AlterSecretOperation,
1502    },
1503    /// ALTER FRAGMENT
1504    AlterFragment {
1505        fragment_id: u32,
1506        operation: AlterFragmentOperation,
1507    },
1508    /// DESCRIBE relation
1509    Describe {
1510        /// relation name
1511        name: ObjectName,
1512        kind: DescribeKind,
1513    },
1514    /// DESCRIBE FRAGMENT <fragment_id>
1515    DescribeFragment {
1516        fragment_id: u32,
1517    },
1518    /// SHOW OBJECT COMMAND
1519    ShowObjects {
1520        object: ShowObject,
1521        filter: Option<ShowStatementFilter>,
1522    },
1523    /// SHOW CREATE COMMAND
1524    ShowCreateObject {
1525        /// Show create object type
1526        create_type: ShowCreateType,
1527        /// Show create object name
1528        name: ObjectName,
1529    },
1530    ShowTransactionIsolationLevel,
1531    /// CANCEL JOBS COMMAND
1532    CancelJobs(JobIdents),
1533    /// KILL COMMAND
1534    /// Kill process in the show processlist.
1535    Kill(String),
1536    /// DROP
1537    Drop(DropStatement),
1538    /// DROP FUNCTION
1539    DropFunction {
1540        if_exists: bool,
1541        /// One or more function to drop
1542        func_desc: Vec<FunctionDesc>,
1543        /// `CASCADE` or `RESTRICT`
1544        option: Option<ReferentialAction>,
1545    },
1546    /// DROP AGGREGATE
1547    DropAggregate {
1548        if_exists: bool,
1549        /// One or more function to drop
1550        func_desc: Vec<FunctionDesc>,
1551        /// `CASCADE` or `RESTRICT`
1552        option: Option<ReferentialAction>,
1553    },
1554    /// `SET <variable>`
1555    ///
1556    /// Note: this is not a standard SQL statement, but it is supported by at
1557    /// least MySQL and PostgreSQL. Not all MySQL-specific syntactic forms are
1558    /// supported yet.
1559    SetVariable {
1560        local: bool,
1561        variable: Ident,
1562        value: SetVariableValue,
1563    },
1564    /// `SHOW <variable>`
1565    ///
1566    /// Note: this is a PostgreSQL-specific statement.
1567    ShowVariable {
1568        variable: Vec<Ident>,
1569    },
1570    /// `START TRANSACTION ...`
1571    StartTransaction {
1572        modes: Vec<TransactionMode>,
1573    },
1574    /// `BEGIN [ TRANSACTION | WORK ]`
1575    Begin {
1576        modes: Vec<TransactionMode>,
1577    },
1578    /// ABORT
1579    Abort,
1580    /// `SET TRANSACTION ...`
1581    SetTransaction {
1582        modes: Vec<TransactionMode>,
1583        snapshot: Option<Value>,
1584        session: bool,
1585    },
1586    /// `SET [ SESSION | LOCAL ] TIME ZONE { value | 'value' | LOCAL | DEFAULT }`
1587    SetTimeZone {
1588        local: bool,
1589        value: SetTimeZoneValue,
1590    },
1591    /// `COMMENT ON ...`
1592    ///
1593    /// Note: this is a PostgreSQL-specific statement.
1594    Comment {
1595        object_type: CommentObject,
1596        object_name: ObjectName,
1597        comment: Option<String>,
1598    },
1599    /// `COMMIT [ TRANSACTION | WORK ] [ AND [ NO ] CHAIN ]`
1600    Commit {
1601        chain: bool,
1602    },
1603    /// `ROLLBACK [ TRANSACTION | WORK ] [ AND [ NO ] CHAIN ]`
1604    Rollback {
1605        chain: bool,
1606    },
1607    /// CREATE SCHEMA
1608    CreateSchema {
1609        schema_name: ObjectName,
1610        if_not_exists: bool,
1611        owner: Option<ObjectName>,
1612    },
1613    /// CREATE DATABASE
1614    CreateDatabase {
1615        db_name: ObjectName,
1616        if_not_exists: bool,
1617        owner: Option<ObjectName>,
1618        resource_group: Option<SetVariableValue>,
1619        barrier_interval_ms: Option<u32>,
1620        checkpoint_frequency: Option<u64>,
1621    },
1622    /// GRANT privileges ON objects TO grantees
1623    Grant {
1624        privileges: Privileges,
1625        objects: GrantObjects,
1626        grantees: Vec<Ident>,
1627        with_grant_option: bool,
1628        granted_by: Option<Ident>,
1629    },
1630    /// REVOKE privileges ON objects FROM grantees
1631    Revoke {
1632        privileges: Privileges,
1633        objects: GrantObjects,
1634        grantees: Vec<Ident>,
1635        granted_by: Option<Ident>,
1636        revoke_grant_option: bool,
1637        cascade: bool,
1638    },
1639    /// `DEALLOCATE [ PREPARE ] { name | ALL }`
1640    ///
1641    /// Note: this is a PostgreSQL-specific statement.
1642    Deallocate {
1643        name: Ident,
1644        prepare: bool,
1645    },
1646    /// `EXECUTE name [ ( parameter [, ...] ) ]`
1647    ///
1648    /// Note: this is a PostgreSQL-specific statement.
1649    Execute {
1650        name: Ident,
1651        parameters: Vec<Expr>,
1652    },
1653    /// `PREPARE name [ ( data_type [, ...] ) ] AS statement`
1654    ///
1655    /// Note: this is a PostgreSQL-specific statement.
1656    Prepare {
1657        name: Ident,
1658        data_types: Vec<DataType>,
1659        statement: Box<Statement>,
1660    },
1661    /// EXPLAIN / DESCRIBE for select_statement
1662    Explain {
1663        /// Carry out the command and show actual run times and other statistics.
1664        analyze: bool,
1665        /// A SQL query that specifies what to explain
1666        statement: Box<Statement>,
1667        /// options of the explain statement
1668        options: ExplainOptions,
1669    },
1670    /// EXPLAIN ANALYZE for stream job
1671    /// We introduce a new statement rather than reuse `EXPLAIN` because
1672    /// the body of the statement is not an SQL query.
1673    /// TODO(kwannoel): Make profiling duration configurable: EXPLAIN ANALYZE (DURATION 1s) ...
1674    ExplainAnalyzeStreamJob {
1675        target: AnalyzeTarget,
1676        duration_secs: Option<u64>,
1677    },
1678    /// CREATE USER
1679    CreateUser(CreateUserStatement),
1680    /// ALTER USER
1681    AlterUser(AlterUserStatement),
1682    /// ALTER SYSTEM SET configuration_parameter { TO | = } { value | 'value' | DEFAULT }
1683    AlterSystem {
1684        param: Ident,
1685        value: SetVariableValue,
1686    },
1687    /// FLUSH the current barrier.
1688    ///
1689    /// Note: RisingWave specific statement.
1690    Flush,
1691    /// WAIT for ALL running stream jobs to finish.
1692    /// It will block the current session the condition is met.
1693    Wait,
1694    /// Trigger stream job recover
1695    Recover,
1696    /// `USE <db_name>`
1697    ///
1698    /// Note: this is a RisingWave specific statement and used to switch the current database.
1699    Use {
1700        db_name: ObjectName,
1701    },
1702}
1703
1704#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1705#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1706pub enum DescribeKind {
1707    /// `DESCRIBE <name>`
1708    Plain,
1709
1710    /// `DESCRIBE FRAGMENTS <name>`
1711    Fragments,
1712}
1713
1714impl fmt::Display for Statement {
1715    /// Converts(unparses) the statement to a SQL string.
1716    ///
1717    /// If the resulting SQL is not valid, this function will panic. Use
1718    /// [`Statement::try_to_string`] to get a `Result` instead.
1719    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1720        // Note: we ignore formatting options here.
1721        let sql = self
1722            .try_to_string()
1723            .expect("normalized SQL should be parsable");
1724        f.write_str(&sql)
1725    }
1726}
1727
1728impl Statement {
1729    /// Converts(unparses) the statement to a SQL string.
1730    ///
1731    /// If the resulting SQL is not valid, returns an error.
1732    pub fn try_to_string(&self) -> Result<String, ParserError> {
1733        let sql = self.to_string_unchecked();
1734
1735        // TODO(#20713): expand this check to all statements
1736        if matches!(
1737            self,
1738            Statement::CreateTable { .. } | Statement::CreateSource { .. }
1739        ) {
1740            let _ = Parser::parse_sql(&sql)?;
1741        }
1742        Ok(sql)
1743    }
1744
1745    /// Converts(unparses) the statement to a SQL string.
1746    ///
1747    /// The result may not be valid SQL if there's an implementation bug in the `Display`
1748    /// trait of any AST node. To avoid this, always prefer [`Statement::try_to_string`]
1749    /// to get a `Result`, or `to_string` which panics if the SQL is invalid.
1750    pub fn to_string_unchecked(&self) -> String {
1751        let mut buf = String::new();
1752        self.fmt_unchecked(&mut buf).unwrap();
1753        buf
1754    }
1755
1756    // NOTE: This function should not check the validity of the unparsed SQL (and panic).
1757    //       Thus, do not directly format a statement with `write!` or `format!`. Recursively
1758    //       call `fmt_unchecked` on the inner statements instead.
1759    //
1760    // Clippy thinks this function is too complicated, but it is painful to
1761    // split up without extracting structs for each `Statement` variant.
1762    #[allow(clippy::cognitive_complexity)]
1763    fn fmt_unchecked(&self, mut f: impl std::fmt::Write) -> fmt::Result {
1764        match self {
1765            Statement::Explain {
1766                analyze,
1767                statement,
1768                options,
1769            } => {
1770                write!(f, "EXPLAIN ")?;
1771
1772                if *analyze {
1773                    write!(f, "ANALYZE ")?;
1774                }
1775                write!(f, "{}", options)?;
1776
1777                statement.fmt_unchecked(f)
1778            }
1779            Statement::ExplainAnalyzeStreamJob {
1780                target,
1781                duration_secs,
1782            } => {
1783                write!(f, "EXPLAIN ANALYZE {}", target)?;
1784                if let Some(duration_secs) = duration_secs {
1785                    write!(f, " (DURATION_SECS {})", duration_secs)?;
1786                }
1787                Ok(())
1788            }
1789            Statement::Query(s) => write!(f, "{}", s),
1790            Statement::Truncate { table_name } => {
1791                write!(f, "TRUNCATE TABLE {}", table_name)?;
1792                Ok(())
1793            }
1794            Statement::Analyze { table_name } => {
1795                write!(f, "ANALYZE TABLE {}", table_name)?;
1796                Ok(())
1797            }
1798            Statement::Describe { name, kind } => {
1799                write!(f, "DESCRIBE {}", name)?;
1800                match kind {
1801                    DescribeKind::Plain => {}
1802
1803                    DescribeKind::Fragments => {
1804                        write!(f, " FRAGMENTS")?;
1805                    }
1806                }
1807                Ok(())
1808            }
1809            Statement::DescribeFragment { fragment_id } => {
1810                write!(f, "DESCRIBE FRAGMENT {}", fragment_id)?;
1811                Ok(())
1812            }
1813            Statement::ShowObjects {
1814                object: show_object,
1815                filter,
1816            } => {
1817                write!(f, "SHOW {}", show_object)?;
1818                if let Some(filter) = filter {
1819                    write!(f, " {}", filter)?;
1820                }
1821                Ok(())
1822            }
1823            Statement::ShowCreateObject {
1824                create_type: show_type,
1825                name,
1826            } => {
1827                write!(f, "SHOW CREATE {} {}", show_type, name)?;
1828                Ok(())
1829            }
1830            Statement::ShowTransactionIsolationLevel => {
1831                write!(f, "SHOW TRANSACTION ISOLATION LEVEL")?;
1832                Ok(())
1833            }
1834            Statement::Insert {
1835                table_name,
1836                columns,
1837                source,
1838                returning,
1839            } => {
1840                write!(f, "INSERT INTO {table_name} ", table_name = table_name,)?;
1841                if !columns.is_empty() {
1842                    write!(f, "({}) ", display_comma_separated(columns))?;
1843                }
1844                write!(f, "{}", source)?;
1845                if !returning.is_empty() {
1846                    write!(f, " RETURNING ({})", display_comma_separated(returning))?;
1847                }
1848                Ok(())
1849            }
1850            Statement::Copy {
1851                table_name,
1852                columns,
1853                values,
1854            } => {
1855                write!(f, "COPY {}", table_name)?;
1856                if !columns.is_empty() {
1857                    write!(f, " ({})", display_comma_separated(columns))?;
1858                }
1859                write!(f, " FROM stdin; ")?;
1860                if !values.is_empty() {
1861                    writeln!(f)?;
1862                    let mut delim = "";
1863                    for v in values {
1864                        write!(f, "{}", delim)?;
1865                        delim = "\t";
1866                        if let Some(v) = v {
1867                            write!(f, "{}", v)?;
1868                        } else {
1869                            write!(f, "\\N")?;
1870                        }
1871                    }
1872                }
1873                write!(f, "\n\\.")
1874            }
1875            Statement::Update {
1876                table_name,
1877                assignments,
1878                selection,
1879                returning,
1880            } => {
1881                write!(f, "UPDATE {}", table_name)?;
1882                if !assignments.is_empty() {
1883                    write!(f, " SET {}", display_comma_separated(assignments))?;
1884                }
1885                if let Some(selection) = selection {
1886                    write!(f, " WHERE {}", selection)?;
1887                }
1888                if !returning.is_empty() {
1889                    write!(f, " RETURNING ({})", display_comma_separated(returning))?;
1890                }
1891                Ok(())
1892            }
1893            Statement::Delete {
1894                table_name,
1895                selection,
1896                returning,
1897            } => {
1898                write!(f, "DELETE FROM {}", table_name)?;
1899                if let Some(selection) = selection {
1900                    write!(f, " WHERE {}", selection)?;
1901                }
1902                if !returning.is_empty() {
1903                    write!(f, " RETURNING {}", display_comma_separated(returning))?;
1904                }
1905                Ok(())
1906            }
1907            Statement::CreateDatabase {
1908                db_name,
1909                if_not_exists,
1910                owner,
1911                resource_group,
1912                barrier_interval_ms,
1913                checkpoint_frequency,
1914            } => {
1915                write!(f, "CREATE DATABASE")?;
1916                if *if_not_exists {
1917                    write!(f, " IF NOT EXISTS")?;
1918                }
1919                write!(f, " {}", db_name)?;
1920                if let Some(owner) = owner {
1921                    write!(f, " WITH OWNER = {}", owner)?;
1922                }
1923                if let Some(resource_group) = resource_group {
1924                    write!(f, " RESOURCE_GROUP = {}", resource_group)?;
1925                }
1926                if let Some(barrier_interval_ms) = barrier_interval_ms {
1927                    write!(f, " BARRIER_INTERVAL_MS = {}", barrier_interval_ms)?;
1928                }
1929                if let Some(checkpoint_frequency) = checkpoint_frequency {
1930                    write!(f, " CHECKPOINT_FREQUENCY = {}", checkpoint_frequency)?;
1931                }
1932
1933                Ok(())
1934            }
1935            Statement::CreateFunction {
1936                or_replace,
1937                temporary,
1938                if_not_exists,
1939                name,
1940                args,
1941                returns,
1942                params,
1943                with_options,
1944            } => {
1945                write!(
1946                    f,
1947                    "CREATE {or_replace}{temp}FUNCTION {if_not_exists}{name}",
1948                    temp = if *temporary { "TEMPORARY " } else { "" },
1949                    or_replace = if *or_replace { "OR REPLACE " } else { "" },
1950                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
1951                )?;
1952                if let Some(args) = args {
1953                    write!(f, "({})", display_comma_separated(args))?;
1954                }
1955                if let Some(return_type) = returns {
1956                    write!(f, " {}", return_type)?;
1957                }
1958                write!(f, "{params}")?;
1959                write!(f, "{with_options}")?;
1960                Ok(())
1961            }
1962            Statement::CreateAggregate {
1963                or_replace,
1964                if_not_exists,
1965                name,
1966                args,
1967                returns,
1968                append_only,
1969                params,
1970            } => {
1971                write!(
1972                    f,
1973                    "CREATE {or_replace}AGGREGATE {if_not_exists}{name}",
1974                    or_replace = if *or_replace { "OR REPLACE " } else { "" },
1975                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
1976                )?;
1977                write!(f, "({})", display_comma_separated(args))?;
1978                write!(f, " RETURNS {}", returns)?;
1979                if *append_only {
1980                    write!(f, " APPEND ONLY")?;
1981                }
1982                write!(f, "{params}")?;
1983                Ok(())
1984            }
1985            Statement::CreateView {
1986                name,
1987                or_replace,
1988                if_not_exists,
1989                columns,
1990                query,
1991                materialized,
1992                with_options,
1993                emit_mode,
1994            } => {
1995                write!(
1996                    f,
1997                    "CREATE {or_replace}{materialized}VIEW {if_not_exists}{name}",
1998                    or_replace = if *or_replace { "OR REPLACE " } else { "" },
1999                    materialized = if *materialized { "MATERIALIZED " } else { "" },
2000                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
2001                    name = name
2002                )?;
2003                if !with_options.is_empty() {
2004                    write!(f, " WITH ({})", display_comma_separated(with_options))?;
2005                }
2006                if !columns.is_empty() {
2007                    write!(f, " ({})", display_comma_separated(columns))?;
2008                }
2009                write!(f, " AS {}", query)?;
2010                if let Some(emit_mode) = emit_mode {
2011                    write!(f, " EMIT {}", emit_mode)?;
2012                }
2013                Ok(())
2014            }
2015            Statement::CreateTable {
2016                name,
2017                columns,
2018                wildcard_idx,
2019                constraints,
2020                with_options,
2021                or_replace,
2022                if_not_exists,
2023                temporary,
2024                format_encode,
2025                source_watermarks,
2026                append_only,
2027                on_conflict,
2028                with_version_column,
2029                query,
2030                cdc_table_info,
2031                include_column_options,
2032                webhook_info,
2033                engine,
2034            } => {
2035                // We want to allow the following options
2036                // Empty column list, allowed by PostgreSQL:
2037                //   `CREATE TABLE t ()`
2038                // No columns provided for CREATE TABLE AS:
2039                //   `CREATE TABLE t AS SELECT a from t2`
2040                // Columns provided for CREATE TABLE AS:
2041                //   `CREATE TABLE t (a INT) AS SELECT a from t2`
2042                write!(
2043                    f,
2044                    "CREATE {or_replace}{temporary}TABLE {if_not_exists}{name}",
2045                    or_replace = if *or_replace { "OR REPLACE " } else { "" },
2046                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
2047                    temporary = if *temporary { "TEMPORARY " } else { "" },
2048                    name = name,
2049                )?;
2050                if !columns.is_empty() || !constraints.is_empty() {
2051                    write!(
2052                        f,
2053                        " {}",
2054                        fmt_create_items(columns, constraints, source_watermarks, *wildcard_idx)?
2055                    )?;
2056                } else if query.is_none() {
2057                    // PostgreSQL allows `CREATE TABLE t ();`, but requires empty parens
2058                    write!(f, " ()")?;
2059                }
2060                if *append_only {
2061                    write!(f, " APPEND ONLY")?;
2062                }
2063
2064                if let Some(on_conflict_behavior) = on_conflict {
2065                    write!(f, " ON CONFLICT {}", on_conflict_behavior)?;
2066                }
2067                if let Some(version_column) = with_version_column {
2068                    write!(f, " WITH VERSION COLUMN({})", version_column)?;
2069                }
2070                if !include_column_options.is_empty() {
2071                    write!(f, " {}", display_separated(include_column_options, " "))?;
2072                }
2073                if !with_options.is_empty() {
2074                    write!(f, " WITH ({})", display_comma_separated(with_options))?;
2075                }
2076                if let Some(format_encode) = format_encode {
2077                    write!(f, " {}", format_encode)?;
2078                }
2079                if let Some(query) = query {
2080                    write!(f, " AS {}", query)?;
2081                }
2082                if let Some(info) = cdc_table_info {
2083                    write!(f, " FROM {}", info.source_name)?;
2084                    write!(f, " TABLE '{}'", info.external_table_name)?;
2085                }
2086                if let Some(info) = webhook_info {
2087                    if let Some(secret) = &info.secret_ref {
2088                        write!(f, " VALIDATE SECRET {}", secret.secret_name)?;
2089                    } else {
2090                        write!(f, " VALIDATE")?;
2091                    }
2092                    write!(f, " AS {}", info.signature_expr)?;
2093                }
2094                match engine {
2095                    Engine::Hummock => {}
2096                    Engine::Iceberg => {
2097                        write!(f, " ENGINE = {}", engine)?;
2098                    }
2099                }
2100                Ok(())
2101            }
2102            Statement::CreateIndex {
2103                name,
2104                table_name,
2105                columns,
2106                include,
2107                distributed_by,
2108                unique,
2109                if_not_exists,
2110            } => write!(
2111                f,
2112                "CREATE {unique}INDEX {if_not_exists}{name} ON {table_name}({columns}){include}{distributed_by}",
2113                unique = if *unique { "UNIQUE " } else { "" },
2114                if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
2115                name = name,
2116                table_name = table_name,
2117                columns = display_comma_separated(columns),
2118                include = if include.is_empty() {
2119                    "".to_owned()
2120                } else {
2121                    format!(" INCLUDE({})", display_separated(include, ","))
2122                },
2123                distributed_by = if distributed_by.is_empty() {
2124                    "".to_owned()
2125                } else {
2126                    format!(
2127                        " DISTRIBUTED BY({})",
2128                        display_separated(distributed_by, ",")
2129                    )
2130                }
2131            ),
2132            Statement::CreateSource { stmt } => write!(f, "CREATE SOURCE {}", stmt,),
2133            Statement::CreateSink { stmt } => write!(f, "CREATE SINK {}", stmt,),
2134            Statement::CreateSubscription { stmt } => write!(f, "CREATE SUBSCRIPTION {}", stmt,),
2135            Statement::CreateConnection { stmt } => write!(f, "CREATE CONNECTION {}", stmt,),
2136            Statement::DeclareCursor { stmt } => write!(f, "DECLARE {}", stmt,),
2137            Statement::FetchCursor { stmt } => write!(f, "FETCH {}", stmt),
2138            Statement::CloseCursor { stmt } => write!(f, "CLOSE {}", stmt),
2139            Statement::CreateSecret { stmt } => write!(f, "CREATE SECRET {}", stmt),
2140            Statement::AlterDatabase { name, operation } => {
2141                write!(f, "ALTER DATABASE {} {}", name, operation)
2142            }
2143            Statement::AlterSchema { name, operation } => {
2144                write!(f, "ALTER SCHEMA {} {}", name, operation)
2145            }
2146            Statement::AlterTable { name, operation } => {
2147                write!(f, "ALTER TABLE {} {}", name, operation)
2148            }
2149            Statement::AlterIndex { name, operation } => {
2150                write!(f, "ALTER INDEX {} {}", name, operation)
2151            }
2152            Statement::AlterView {
2153                materialized,
2154                name,
2155                operation,
2156            } => {
2157                write!(
2158                    f,
2159                    "ALTER {}VIEW {} {}",
2160                    if *materialized { "MATERIALIZED " } else { "" },
2161                    name,
2162                    operation
2163                )
2164            }
2165            Statement::AlterSink { name, operation } => {
2166                write!(f, "ALTER SINK {} {}", name, operation)
2167            }
2168            Statement::AlterSubscription { name, operation } => {
2169                write!(f, "ALTER SUBSCRIPTION {} {}", name, operation)
2170            }
2171            Statement::AlterSource { name, operation } => {
2172                write!(f, "ALTER SOURCE {} {}", name, operation)
2173            }
2174            Statement::AlterFunction {
2175                name,
2176                args,
2177                operation,
2178            } => {
2179                write!(f, "ALTER FUNCTION {}", name)?;
2180                if let Some(args) = args {
2181                    write!(f, "({})", display_comma_separated(args))?;
2182                }
2183                write!(f, " {}", operation)
2184            }
2185            Statement::AlterConnection { name, operation } => {
2186                write!(f, "ALTER CONNECTION {} {}", name, operation)
2187            }
2188            Statement::AlterSecret {
2189                name,
2190                with_options,
2191                operation,
2192            } => {
2193                write!(f, "ALTER SECRET {}", name)?;
2194                if !with_options.is_empty() {
2195                    write!(f, " WITH ({})", display_comma_separated(with_options))?;
2196                }
2197                write!(f, " {}", operation)
2198            }
2199            Statement::Discard(t) => write!(f, "DISCARD {}", t),
2200            Statement::Drop(stmt) => write!(f, "DROP {}", stmt),
2201            Statement::DropFunction {
2202                if_exists,
2203                func_desc,
2204                option,
2205            } => {
2206                write!(
2207                    f,
2208                    "DROP FUNCTION{} {}",
2209                    if *if_exists { " IF EXISTS" } else { "" },
2210                    display_comma_separated(func_desc),
2211                )?;
2212                if let Some(op) = option {
2213                    write!(f, " {}", op)?;
2214                }
2215                Ok(())
2216            }
2217            Statement::DropAggregate {
2218                if_exists,
2219                func_desc,
2220                option,
2221            } => {
2222                write!(
2223                    f,
2224                    "DROP AGGREGATE{} {}",
2225                    if *if_exists { " IF EXISTS" } else { "" },
2226                    display_comma_separated(func_desc),
2227                )?;
2228                if let Some(op) = option {
2229                    write!(f, " {}", op)?;
2230                }
2231                Ok(())
2232            }
2233            Statement::SetVariable {
2234                local,
2235                variable,
2236                value,
2237            } => {
2238                f.write_str("SET ")?;
2239                if *local {
2240                    f.write_str("LOCAL ")?;
2241                }
2242                write!(f, "{name} = {value}", name = variable,)
2243            }
2244            Statement::ShowVariable { variable } => {
2245                write!(f, "SHOW")?;
2246                if !variable.is_empty() {
2247                    write!(f, " {}", display_separated(variable, " "))?;
2248                }
2249                Ok(())
2250            }
2251            Statement::StartTransaction { modes } => {
2252                write!(f, "START TRANSACTION")?;
2253                if !modes.is_empty() {
2254                    write!(f, " {}", display_comma_separated(modes))?;
2255                }
2256                Ok(())
2257            }
2258            Statement::Abort => {
2259                write!(f, "ABORT")?;
2260                Ok(())
2261            }
2262            Statement::SetTransaction {
2263                modes,
2264                snapshot,
2265                session,
2266            } => {
2267                if *session {
2268                    write!(f, "SET SESSION CHARACTERISTICS AS TRANSACTION")?;
2269                } else {
2270                    write!(f, "SET TRANSACTION")?;
2271                }
2272                if !modes.is_empty() {
2273                    write!(f, " {}", display_comma_separated(modes))?;
2274                }
2275                if let Some(snapshot_id) = snapshot {
2276                    write!(f, " SNAPSHOT {}", snapshot_id)?;
2277                }
2278                Ok(())
2279            }
2280            Statement::SetTimeZone { local, value } => {
2281                write!(f, "SET")?;
2282                if *local {
2283                    write!(f, " LOCAL")?;
2284                }
2285                write!(f, " TIME ZONE {}", value)?;
2286                Ok(())
2287            }
2288            Statement::Commit { chain } => {
2289                write!(f, "COMMIT{}", if *chain { " AND CHAIN" } else { "" },)
2290            }
2291            Statement::Rollback { chain } => {
2292                write!(f, "ROLLBACK{}", if *chain { " AND CHAIN" } else { "" },)
2293            }
2294            Statement::CreateSchema {
2295                schema_name,
2296                if_not_exists,
2297                owner,
2298            } => {
2299                write!(
2300                    f,
2301                    "CREATE SCHEMA {if_not_exists}{name}",
2302                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
2303                    name = schema_name
2304                )?;
2305                if let Some(user) = owner {
2306                    write!(f, " AUTHORIZATION {}", user)?;
2307                }
2308                Ok(())
2309            }
2310            Statement::Grant {
2311                privileges,
2312                objects,
2313                grantees,
2314                with_grant_option,
2315                granted_by,
2316            } => {
2317                write!(f, "GRANT {} ", privileges)?;
2318                write!(f, "ON {} ", objects)?;
2319                write!(f, "TO {}", display_comma_separated(grantees))?;
2320                if *with_grant_option {
2321                    write!(f, " WITH GRANT OPTION")?;
2322                }
2323                if let Some(grantor) = granted_by {
2324                    write!(f, " GRANTED BY {}", grantor)?;
2325                }
2326                Ok(())
2327            }
2328            Statement::Revoke {
2329                privileges,
2330                objects,
2331                grantees,
2332                granted_by,
2333                revoke_grant_option,
2334                cascade,
2335            } => {
2336                write!(
2337                    f,
2338                    "REVOKE {}{} ",
2339                    if *revoke_grant_option {
2340                        "GRANT OPTION FOR "
2341                    } else {
2342                        ""
2343                    },
2344                    privileges
2345                )?;
2346                write!(f, "ON {} ", objects)?;
2347                write!(f, "FROM {}", display_comma_separated(grantees))?;
2348                if let Some(grantor) = granted_by {
2349                    write!(f, " GRANTED BY {}", grantor)?;
2350                }
2351                write!(f, " {}", if *cascade { "CASCADE" } else { "RESTRICT" })?;
2352                Ok(())
2353            }
2354            Statement::Deallocate { name, prepare } => write!(
2355                f,
2356                "DEALLOCATE {prepare}{name}",
2357                prepare = if *prepare { "PREPARE " } else { "" },
2358                name = name,
2359            ),
2360            Statement::Execute { name, parameters } => {
2361                write!(f, "EXECUTE {}", name)?;
2362                if !parameters.is_empty() {
2363                    write!(f, "({})", display_comma_separated(parameters))?;
2364                }
2365                Ok(())
2366            }
2367            Statement::Prepare {
2368                name,
2369                data_types,
2370                statement,
2371            } => {
2372                write!(f, "PREPARE {} ", name)?;
2373                if !data_types.is_empty() {
2374                    write!(f, "({}) ", display_comma_separated(data_types))?;
2375                }
2376                write!(f, "AS ")?;
2377                statement.fmt_unchecked(f)
2378            }
2379            Statement::Comment {
2380                object_type,
2381                object_name,
2382                comment,
2383            } => {
2384                write!(f, "COMMENT ON {} {} IS ", object_type, object_name)?;
2385                if let Some(c) = comment {
2386                    write!(f, "'{}'", c)
2387                } else {
2388                    write!(f, "NULL")
2389                }
2390            }
2391            Statement::CreateUser(statement) => {
2392                write!(f, "CREATE USER {}", statement)
2393            }
2394            Statement::AlterUser(statement) => {
2395                write!(f, "ALTER USER {}", statement)
2396            }
2397            Statement::AlterSystem { param, value } => {
2398                f.write_str("ALTER SYSTEM SET ")?;
2399                write!(f, "{param} = {value}",)
2400            }
2401            Statement::Flush => {
2402                write!(f, "FLUSH")
2403            }
2404            Statement::Wait => {
2405                write!(f, "WAIT")
2406            }
2407            Statement::Begin { modes } => {
2408                write!(f, "BEGIN")?;
2409                if !modes.is_empty() {
2410                    write!(f, " {}", display_comma_separated(modes))?;
2411                }
2412                Ok(())
2413            }
2414            Statement::CancelJobs(jobs) => {
2415                write!(f, "CANCEL JOBS {}", display_comma_separated(&jobs.0))?;
2416                Ok(())
2417            }
2418            Statement::Kill(worker_process_id) => {
2419                write!(f, "KILL '{}'", worker_process_id)?;
2420                Ok(())
2421            }
2422            Statement::Recover => {
2423                write!(f, "RECOVER")?;
2424                Ok(())
2425            }
2426            Statement::Use { db_name } => {
2427                write!(f, "USE {}", db_name)?;
2428                Ok(())
2429            }
2430            Statement::AlterFragment {
2431                fragment_id,
2432                operation,
2433            } => {
2434                write!(f, "ALTER FRAGMENT {} {}", fragment_id, operation)
2435            }
2436        }
2437    }
2438
2439    pub fn is_create(&self) -> bool {
2440        matches!(
2441            self,
2442            Statement::CreateTable { .. }
2443                | Statement::CreateView { .. }
2444                | Statement::CreateSource { .. }
2445                | Statement::CreateSink { .. }
2446                | Statement::CreateSubscription { .. }
2447                | Statement::CreateConnection { .. }
2448                | Statement::CreateSecret { .. }
2449                | Statement::CreateUser { .. }
2450                | Statement::CreateDatabase { .. }
2451                | Statement::CreateFunction { .. }
2452                | Statement::CreateAggregate { .. }
2453                | Statement::CreateIndex { .. }
2454                | Statement::CreateSchema { .. }
2455        )
2456    }
2457}
2458
2459impl Display for IncludeOptionItem {
2460    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2461        let Self {
2462            column_type,
2463            inner_field,
2464            header_inner_expect_type,
2465            column_alias,
2466        } = self;
2467        write!(f, "INCLUDE {}", column_type)?;
2468        if let Some(inner_field) = inner_field {
2469            write!(f, " '{}'", value::escape_single_quote_string(inner_field))?;
2470            if let Some(expected_type) = header_inner_expect_type {
2471                write!(f, " {}", expected_type)?;
2472            }
2473        }
2474        if let Some(alias) = column_alias {
2475            write!(f, " AS {}", alias)?;
2476        }
2477        Ok(())
2478    }
2479}
2480
2481#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2482#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2483#[non_exhaustive]
2484pub enum OnInsert {
2485    /// ON DUPLICATE KEY UPDATE (MySQL when the key already exists, then execute an update instead)
2486    DuplicateKeyUpdate(Vec<Assignment>),
2487}
2488
2489impl fmt::Display for OnInsert {
2490    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2491        match self {
2492            Self::DuplicateKeyUpdate(expr) => write!(
2493                f,
2494                " ON DUPLICATE KEY UPDATE {}",
2495                display_comma_separated(expr)
2496            ),
2497        }
2498    }
2499}
2500
2501/// Privileges granted in a GRANT statement or revoked in a REVOKE statement.
2502#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2503#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2504pub enum Privileges {
2505    /// All privileges applicable to the object type
2506    All {
2507        /// Optional keyword from the spec, ignored in practice
2508        with_privileges_keyword: bool,
2509    },
2510    /// Specific privileges (e.g. `SELECT`, `INSERT`)
2511    Actions(Vec<Action>),
2512}
2513
2514impl fmt::Display for Privileges {
2515    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2516        match self {
2517            Privileges::All {
2518                with_privileges_keyword,
2519            } => {
2520                write!(
2521                    f,
2522                    "ALL{}",
2523                    if *with_privileges_keyword {
2524                        " PRIVILEGES"
2525                    } else {
2526                        ""
2527                    }
2528                )
2529            }
2530            Privileges::Actions(actions) => {
2531                write!(f, "{}", display_comma_separated(actions))
2532            }
2533        }
2534    }
2535}
2536
2537/// A privilege on a database object (table, sequence, etc.).
2538#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2539#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2540pub enum Action {
2541    Connect,
2542    Create,
2543    Delete,
2544    Execute,
2545    Insert { columns: Option<Vec<Ident>> },
2546    References { columns: Option<Vec<Ident>> },
2547    Select { columns: Option<Vec<Ident>> },
2548    Temporary,
2549    Trigger,
2550    Truncate,
2551    Update { columns: Option<Vec<Ident>> },
2552    Usage,
2553}
2554
2555impl fmt::Display for Action {
2556    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2557        match self {
2558            Action::Connect => f.write_str("CONNECT")?,
2559            Action::Create => f.write_str("CREATE")?,
2560            Action::Delete => f.write_str("DELETE")?,
2561            Action::Execute => f.write_str("EXECUTE")?,
2562            Action::Insert { .. } => f.write_str("INSERT")?,
2563            Action::References { .. } => f.write_str("REFERENCES")?,
2564            Action::Select { .. } => f.write_str("SELECT")?,
2565            Action::Temporary => f.write_str("TEMPORARY")?,
2566            Action::Trigger => f.write_str("TRIGGER")?,
2567            Action::Truncate => f.write_str("TRUNCATE")?,
2568            Action::Update { .. } => f.write_str("UPDATE")?,
2569            Action::Usage => f.write_str("USAGE")?,
2570        };
2571        match self {
2572            Action::Insert { columns }
2573            | Action::References { columns }
2574            | Action::Select { columns }
2575            | Action::Update { columns } => {
2576                if let Some(columns) = columns {
2577                    write!(f, " ({})", display_comma_separated(columns))?;
2578                }
2579            }
2580            _ => (),
2581        };
2582        Ok(())
2583    }
2584}
2585
2586/// Objects on which privileges are granted in a GRANT statement.
2587#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2588#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2589pub enum GrantObjects {
2590    /// Grant privileges on `ALL SEQUENCES IN SCHEMA <schema_name> [, ...]`
2591    AllSequencesInSchema { schemas: Vec<ObjectName> },
2592    /// Grant privileges on `ALL TABLES IN SCHEMA <schema_name> [, ...]`
2593    AllTablesInSchema { schemas: Vec<ObjectName> },
2594    /// Grant privileges on `ALL SOURCES IN SCHEMA <schema_name> [, ...]`
2595    AllSourcesInSchema { schemas: Vec<ObjectName> },
2596    /// Grant privileges on `ALL SINKS IN SCHEMA <schema_name> [, ...]`
2597    AllSinksInSchema { schemas: Vec<ObjectName> },
2598    /// Grant privileges on `ALL MATERIALIZED VIEWS IN SCHEMA <schema_name> [, ...]`
2599    AllMviewsInSchema { schemas: Vec<ObjectName> },
2600    /// Grant privileges on `ALL VIEWS IN SCHEMA <schema_name> [, ...]`
2601    AllViewsInSchema { schemas: Vec<ObjectName> },
2602    /// Grant privileges on `ALL FUNCTIONS IN SCHEMA <schema_name> [, ...]`
2603    AllFunctionsInSchema { schemas: Vec<ObjectName> },
2604    /// Grant privileges on `ALL SECRETS IN SCHEMA <schema_name> [, ...]`
2605    AllSecretsInSchema { schemas: Vec<ObjectName> },
2606    /// Grant privileges on `ALL SUBSCRIPTIONS IN SCHEMA <schema_name> [, ...]`
2607    AllSubscriptionsInSchema { schemas: Vec<ObjectName> },
2608    /// Grant privileges on `ALL CONNECTIONS IN SCHEMA <schema_name> [, ...]`
2609    AllConnectionsInSchema { schemas: Vec<ObjectName> },
2610    /// Grant privileges on specific databases
2611    Databases(Vec<ObjectName>),
2612    /// Grant privileges on specific schemas
2613    Schemas(Vec<ObjectName>),
2614    /// Grant privileges on specific sources
2615    Sources(Vec<ObjectName>),
2616    /// Grant privileges on specific materialized views
2617    Mviews(Vec<ObjectName>),
2618    /// Grant privileges on specific sequences
2619    Sequences(Vec<ObjectName>),
2620    /// Grant privileges on specific tables
2621    Tables(Vec<ObjectName>),
2622    /// Grant privileges on specific sinks
2623    Sinks(Vec<ObjectName>),
2624    /// Grant privileges on specific views
2625    Views(Vec<ObjectName>),
2626    /// Grant privileges on specific connections
2627    Connections(Vec<ObjectName>),
2628    /// Grant privileges on specific subscriptions
2629    Subscriptions(Vec<ObjectName>),
2630    /// Grant privileges on specific functions
2631    Functions(Vec<FunctionDesc>),
2632    /// Grant privileges on specific secrets
2633    Secrets(Vec<ObjectName>),
2634}
2635
2636impl fmt::Display for GrantObjects {
2637    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2638        match self {
2639            GrantObjects::Sequences(sequences) => {
2640                write!(f, "SEQUENCE {}", display_comma_separated(sequences))
2641            }
2642            GrantObjects::Schemas(schemas) => {
2643                write!(f, "SCHEMA {}", display_comma_separated(schemas))
2644            }
2645            GrantObjects::Tables(tables) => {
2646                write!(f, "{}", display_comma_separated(tables))
2647            }
2648            GrantObjects::AllSequencesInSchema { schemas } => {
2649                write!(
2650                    f,
2651                    "ALL SEQUENCES IN SCHEMA {}",
2652                    display_comma_separated(schemas)
2653                )
2654            }
2655            GrantObjects::AllTablesInSchema { schemas } => {
2656                write!(
2657                    f,
2658                    "ALL TABLES IN SCHEMA {}",
2659                    display_comma_separated(schemas)
2660                )
2661            }
2662            GrantObjects::AllSourcesInSchema { schemas } => {
2663                write!(
2664                    f,
2665                    "ALL SOURCES IN SCHEMA {}",
2666                    display_comma_separated(schemas)
2667                )
2668            }
2669            GrantObjects::AllMviewsInSchema { schemas } => {
2670                write!(
2671                    f,
2672                    "ALL MATERIALIZED VIEWS IN SCHEMA {}",
2673                    display_comma_separated(schemas)
2674                )
2675            }
2676            GrantObjects::AllSinksInSchema { schemas } => {
2677                write!(
2678                    f,
2679                    "ALL SINKS IN SCHEMA {}",
2680                    display_comma_separated(schemas)
2681                )
2682            }
2683            GrantObjects::AllViewsInSchema { schemas } => {
2684                write!(
2685                    f,
2686                    "ALL VIEWS IN SCHEMA {}",
2687                    display_comma_separated(schemas)
2688                )
2689            }
2690            GrantObjects::AllFunctionsInSchema { schemas } => {
2691                write!(
2692                    f,
2693                    "ALL FUNCTIONS IN SCHEMA {}",
2694                    display_comma_separated(schemas)
2695                )
2696            }
2697            GrantObjects::AllSecretsInSchema { schemas } => {
2698                write!(
2699                    f,
2700                    "ALL SECRETS IN SCHEMA {}",
2701                    display_comma_separated(schemas)
2702                )
2703            }
2704            GrantObjects::AllSubscriptionsInSchema { schemas } => {
2705                write!(
2706                    f,
2707                    "ALL SUBSCRIPTIONS IN SCHEMA {}",
2708                    display_comma_separated(schemas)
2709                )
2710            }
2711            GrantObjects::AllConnectionsInSchema { schemas } => {
2712                write!(
2713                    f,
2714                    "ALL CONNECTIONS IN SCHEMA {}",
2715                    display_comma_separated(schemas)
2716                )
2717            }
2718            GrantObjects::Databases(databases) => {
2719                write!(f, "DATABASE {}", display_comma_separated(databases))
2720            }
2721            GrantObjects::Sources(sources) => {
2722                write!(f, "SOURCE {}", display_comma_separated(sources))
2723            }
2724            GrantObjects::Mviews(mviews) => {
2725                write!(f, "MATERIALIZED VIEW {}", display_comma_separated(mviews))
2726            }
2727            GrantObjects::Sinks(sinks) => {
2728                write!(f, "SINK {}", display_comma_separated(sinks))
2729            }
2730            GrantObjects::Views(views) => {
2731                write!(f, "VIEW {}", display_comma_separated(views))
2732            }
2733            GrantObjects::Connections(connections) => {
2734                write!(f, "CONNECTION {}", display_comma_separated(connections))
2735            }
2736            GrantObjects::Subscriptions(subscriptions) => {
2737                write!(f, "SUBSCRIPTION {}", display_comma_separated(subscriptions))
2738            }
2739            GrantObjects::Functions(func_descs) => {
2740                write!(f, "FUNCTION {}", display_comma_separated(func_descs))
2741            }
2742            GrantObjects::Secrets(secrets) => {
2743                write!(f, "SECRET {}", display_comma_separated(secrets))
2744            }
2745        }
2746    }
2747}
2748
2749#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2750#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2751pub enum AssignmentValue {
2752    /// An expression, e.g. `foo = 1`
2753    Expr(Expr),
2754    /// The `DEFAULT` keyword, e.g. `foo = DEFAULT`
2755    Default,
2756}
2757
2758impl fmt::Display for AssignmentValue {
2759    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2760        match self {
2761            AssignmentValue::Expr(expr) => write!(f, "{}", expr),
2762            AssignmentValue::Default => f.write_str("DEFAULT"),
2763        }
2764    }
2765}
2766
2767/// SQL assignment `foo = { expr | DEFAULT }` as used in SQLUpdate
2768#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2769#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2770pub struct Assignment {
2771    pub id: Vec<Ident>,
2772    pub value: AssignmentValue,
2773}
2774
2775impl fmt::Display for Assignment {
2776    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2777        write!(f, "{} = {}", display_separated(&self.id, "."), self.value)
2778    }
2779}
2780
2781#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2782#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2783pub enum FunctionArgExpr {
2784    Expr(Expr),
2785    /// Expr is an arbitrary expression, returning either a table or a column.
2786    /// Idents are the prefix of `*`, which are consecutive field accesses.
2787    /// e.g. `(table.v1).*` or `(table).v1.*`
2788    ExprQualifiedWildcard(Expr, Vec<Ident>),
2789    /// Qualified wildcard, e.g. `alias.*` or `schema.table.*`, followed by optional
2790    /// except syntax
2791    QualifiedWildcard(ObjectName, Option<Vec<Expr>>),
2792    /// An unqualified `*` or `* except (columns)`
2793    Wildcard(Option<Vec<Expr>>),
2794}
2795
2796impl fmt::Display for FunctionArgExpr {
2797    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2798        match self {
2799            FunctionArgExpr::Expr(expr) => write!(f, "{}", expr),
2800            FunctionArgExpr::ExprQualifiedWildcard(expr, prefix) => {
2801                write!(
2802                    f,
2803                    "({}){}.*",
2804                    expr,
2805                    prefix
2806                        .iter()
2807                        .format_with("", |i, f| f(&format_args!(".{i}")))
2808                )
2809            }
2810            FunctionArgExpr::QualifiedWildcard(prefix, except) => match except {
2811                Some(exprs) => write!(
2812                    f,
2813                    "{}.* EXCEPT ({})",
2814                    prefix,
2815                    exprs
2816                        .iter()
2817                        .map(|v| v.to_string())
2818                        .collect::<Vec<String>>()
2819                        .as_slice()
2820                        .join(", ")
2821                ),
2822                None => write!(f, "{}.*", prefix),
2823            },
2824
2825            FunctionArgExpr::Wildcard(except) => match except {
2826                Some(exprs) => write!(
2827                    f,
2828                    "* EXCEPT ({})",
2829                    exprs
2830                        .iter()
2831                        .map(|v| v.to_string())
2832                        .collect::<Vec<String>>()
2833                        .as_slice()
2834                        .join(", ")
2835                ),
2836                None => f.write_str("*"),
2837            },
2838        }
2839    }
2840}
2841
2842#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2843#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2844pub enum FunctionArg {
2845    Named { name: Ident, arg: FunctionArgExpr },
2846    Unnamed(FunctionArgExpr),
2847}
2848
2849impl FunctionArg {
2850    pub fn get_expr(&self) -> FunctionArgExpr {
2851        match self {
2852            FunctionArg::Named { name: _, arg } => arg.clone(),
2853            FunctionArg::Unnamed(arg) => arg.clone(),
2854        }
2855    }
2856}
2857
2858impl fmt::Display for FunctionArg {
2859    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2860        match self {
2861            FunctionArg::Named { name, arg } => write!(f, "{} => {}", name, arg),
2862            FunctionArg::Unnamed(unnamed_arg) => write!(f, "{}", unnamed_arg),
2863        }
2864    }
2865}
2866
2867/// A list of function arguments, including additional modifiers like `DISTINCT` or `ORDER BY`.
2868/// This basically holds all the information between the `(` and `)` in a function call.
2869#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2870#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2871pub struct FunctionArgList {
2872    /// Aggregate function calls may have a `DISTINCT`, e.g. `count(DISTINCT x)`.
2873    pub distinct: bool,
2874    pub args: Vec<FunctionArg>,
2875    /// Whether the last argument is variadic, e.g. `foo(a, b, VARIADIC c)`.
2876    pub variadic: bool,
2877    /// Aggregate function calls may have an `ORDER BY`, e.g. `array_agg(x ORDER BY y)`.
2878    pub order_by: Vec<OrderByExpr>,
2879    /// Window function calls may have an `IGNORE NULLS`, e.g. `first_value(x IGNORE NULLS)`.
2880    pub ignore_nulls: bool,
2881}
2882
2883impl fmt::Display for FunctionArgList {
2884    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2885        write!(f, "(")?;
2886        if self.distinct {
2887            write!(f, "DISTINCT ")?;
2888        }
2889        if self.variadic {
2890            for arg in &self.args[0..self.args.len() - 1] {
2891                write!(f, "{}, ", arg)?;
2892            }
2893            write!(f, "VARIADIC {}", self.args.last().unwrap())?;
2894        } else {
2895            write!(f, "{}", display_comma_separated(&self.args))?;
2896        }
2897        if !self.order_by.is_empty() {
2898            write!(f, " ORDER BY {}", display_comma_separated(&self.order_by))?;
2899        }
2900        if self.ignore_nulls {
2901            write!(f, " IGNORE NULLS")?;
2902        }
2903        write!(f, ")")?;
2904        Ok(())
2905    }
2906}
2907
2908impl FunctionArgList {
2909    pub fn empty() -> Self {
2910        Self {
2911            distinct: false,
2912            args: vec![],
2913            variadic: false,
2914            order_by: vec![],
2915            ignore_nulls: false,
2916        }
2917    }
2918
2919    pub fn args_only(args: Vec<FunctionArg>) -> Self {
2920        Self {
2921            distinct: false,
2922            args,
2923            variadic: false,
2924            order_by: vec![],
2925            ignore_nulls: false,
2926        }
2927    }
2928
2929    pub fn is_args_only(&self) -> bool {
2930        !self.distinct && !self.variadic && self.order_by.is_empty() && !self.ignore_nulls
2931    }
2932
2933    pub fn for_agg(distinct: bool, args: Vec<FunctionArg>, order_by: Vec<OrderByExpr>) -> Self {
2934        Self {
2935            distinct,
2936            args,
2937            variadic: false,
2938            order_by,
2939            ignore_nulls: false,
2940        }
2941    }
2942}
2943
2944/// A function call
2945#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2946#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2947pub struct Function {
2948    /// Whether the function is prefixed with `AGGREGATE:`
2949    pub scalar_as_agg: bool,
2950    /// Function name.
2951    pub name: ObjectName,
2952    /// Argument list of the function call, i.e. things in `()`.
2953    pub arg_list: FunctionArgList,
2954    /// `WITHIN GROUP` clause of the function call, for ordered-set aggregate functions.
2955    /// FIXME(rc): why we only support one expression here?
2956    pub within_group: Option<Box<OrderByExpr>>,
2957    /// `FILTER` clause of the function call, for aggregate and window (not supported yet) functions.
2958    pub filter: Option<Box<Expr>>,
2959    /// `OVER` clause of the function call, for window functions.
2960    pub over: Option<Window>,
2961}
2962
2963impl Function {
2964    pub fn no_arg(name: ObjectName) -> Self {
2965        Self {
2966            scalar_as_agg: false,
2967            name,
2968            arg_list: FunctionArgList::empty(),
2969            within_group: None,
2970            filter: None,
2971            over: None,
2972        }
2973    }
2974}
2975
2976impl fmt::Display for Function {
2977    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2978        if self.scalar_as_agg {
2979            write!(f, "AGGREGATE:")?;
2980        }
2981        write!(f, "{}{}", self.name, self.arg_list)?;
2982        if let Some(within_group) = &self.within_group {
2983            write!(f, " WITHIN GROUP (ORDER BY {})", within_group)?;
2984        }
2985        if let Some(filter) = &self.filter {
2986            write!(f, " FILTER (WHERE {})", filter)?;
2987        }
2988        if let Some(o) = &self.over {
2989            write!(f, " OVER {}", o)?;
2990        }
2991        Ok(())
2992    }
2993}
2994
2995#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2996#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2997pub enum ObjectType {
2998    Table,
2999    View,
3000    MaterializedView,
3001    Index,
3002    Schema,
3003    Source,
3004    Sink,
3005    Database,
3006    User,
3007    Connection,
3008    Secret,
3009    Subscription,
3010}
3011
3012impl fmt::Display for ObjectType {
3013    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3014        f.write_str(match self {
3015            ObjectType::Table => "TABLE",
3016            ObjectType::View => "VIEW",
3017            ObjectType::MaterializedView => "MATERIALIZED VIEW",
3018            ObjectType::Index => "INDEX",
3019            ObjectType::Schema => "SCHEMA",
3020            ObjectType::Source => "SOURCE",
3021            ObjectType::Sink => "SINK",
3022            ObjectType::Database => "DATABASE",
3023            ObjectType::User => "USER",
3024            ObjectType::Secret => "SECRET",
3025            ObjectType::Connection => "CONNECTION",
3026            ObjectType::Subscription => "SUBSCRIPTION",
3027        })
3028    }
3029}
3030
3031impl ParseTo for ObjectType {
3032    fn parse_to(parser: &mut Parser<'_>) -> ModalResult<Self> {
3033        let object_type = if parser.parse_keyword(Keyword::TABLE) {
3034            ObjectType::Table
3035        } else if parser.parse_keyword(Keyword::VIEW) {
3036            ObjectType::View
3037        } else if parser.parse_keywords(&[Keyword::MATERIALIZED, Keyword::VIEW]) {
3038            ObjectType::MaterializedView
3039        } else if parser.parse_keyword(Keyword::SOURCE) {
3040            ObjectType::Source
3041        } else if parser.parse_keyword(Keyword::SINK) {
3042            ObjectType::Sink
3043        } else if parser.parse_keyword(Keyword::INDEX) {
3044            ObjectType::Index
3045        } else if parser.parse_keyword(Keyword::SCHEMA) {
3046            ObjectType::Schema
3047        } else if parser.parse_keyword(Keyword::DATABASE) {
3048            ObjectType::Database
3049        } else if parser.parse_keyword(Keyword::USER) {
3050            ObjectType::User
3051        } else if parser.parse_keyword(Keyword::CONNECTION) {
3052            ObjectType::Connection
3053        } else if parser.parse_keyword(Keyword::SECRET) {
3054            ObjectType::Secret
3055        } else if parser.parse_keyword(Keyword::SUBSCRIPTION) {
3056            ObjectType::Subscription
3057        } else {
3058            return parser.expected(
3059                "TABLE, VIEW, INDEX, MATERIALIZED VIEW, SOURCE, SINK, SUBSCRIPTION, SCHEMA, DATABASE, USER, SECRET or CONNECTION after DROP",
3060            );
3061        };
3062        Ok(object_type)
3063    }
3064}
3065
3066#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3067#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3068pub struct SqlOption {
3069    pub name: ObjectName,
3070    pub value: SqlOptionValue,
3071}
3072
3073impl fmt::Display for SqlOption {
3074    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3075        let should_redact = REDACT_SQL_OPTION_KEYWORDS
3076            .try_with(|keywords| {
3077                let sql_option_name = self.name.real_value().to_lowercase();
3078                keywords.iter().any(|k| sql_option_name.contains(k))
3079            })
3080            .unwrap_or(false);
3081        if should_redact {
3082            write!(f, "{} = [REDACTED]", self.name)
3083        } else {
3084            write!(f, "{} = {}", self.name, self.value)
3085        }
3086    }
3087}
3088
3089impl TryFrom<(&String, &String)> for SqlOption {
3090    type Error = ParserError;
3091
3092    fn try_from((name, value): (&String, &String)) -> Result<Self, Self::Error> {
3093        let query = format!("{} = {}", name, value);
3094        let mut tokenizer = Tokenizer::new(query.as_str());
3095        let tokens = tokenizer.tokenize_with_location()?;
3096        let mut parser = Parser(&tokens);
3097        parser
3098            .parse_sql_option()
3099            .map_err(|e| ParserError::ParserError(e.to_string()))
3100    }
3101}
3102
3103#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3104#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3105pub enum SqlOptionValue {
3106    Value(Value),
3107    SecretRef(SecretRefValue),
3108    ConnectionRef(ConnectionRefValue),
3109    BackfillOrder(BackfillOrderStrategy),
3110}
3111
3112impl fmt::Display for SqlOptionValue {
3113    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3114        match self {
3115            SqlOptionValue::Value(value) => write!(f, "{}", value),
3116            SqlOptionValue::SecretRef(secret_ref) => write!(f, "secret {}", secret_ref),
3117            SqlOptionValue::ConnectionRef(connection_ref) => {
3118                write!(f, "{}", connection_ref)
3119            }
3120            SqlOptionValue::BackfillOrder(order) => {
3121                write!(f, "{}", order)
3122            }
3123        }
3124    }
3125}
3126
3127impl From<Value> for SqlOptionValue {
3128    fn from(value: Value) -> Self {
3129        SqlOptionValue::Value(value)
3130    }
3131}
3132
3133#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3134#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3135pub enum EmitMode {
3136    Immediately,
3137    OnWindowClose,
3138}
3139
3140impl fmt::Display for EmitMode {
3141    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3142        f.write_str(match self {
3143            EmitMode::Immediately => "IMMEDIATELY",
3144            EmitMode::OnWindowClose => "ON WINDOW CLOSE",
3145        })
3146    }
3147}
3148
3149#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
3150#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3151pub enum OnConflict {
3152    UpdateFull,
3153    Nothing,
3154    UpdateIfNotNull,
3155}
3156
3157impl fmt::Display for OnConflict {
3158    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3159        f.write_str(match self {
3160            OnConflict::UpdateFull => "DO UPDATE FULL",
3161            OnConflict::Nothing => "DO NOTHING",
3162            OnConflict::UpdateIfNotNull => "DO UPDATE IF NOT NULL",
3163        })
3164    }
3165}
3166
3167#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3168#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3169pub enum Engine {
3170    Hummock,
3171    Iceberg,
3172}
3173
3174impl fmt::Display for crate::ast::Engine {
3175    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3176        f.write_str(match self {
3177            crate::ast::Engine::Hummock => "HUMMOCK",
3178            crate::ast::Engine::Iceberg => "ICEBERG",
3179        })
3180    }
3181}
3182
3183#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3184#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3185pub enum SetTimeZoneValue {
3186    Ident(Ident),
3187    Literal(Value),
3188    Local,
3189    Default,
3190}
3191
3192impl fmt::Display for SetTimeZoneValue {
3193    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3194        match self {
3195            SetTimeZoneValue::Ident(ident) => write!(f, "{}", ident),
3196            SetTimeZoneValue::Literal(value) => write!(f, "{}", value),
3197            SetTimeZoneValue::Local => f.write_str("LOCAL"),
3198            SetTimeZoneValue::Default => f.write_str("DEFAULT"),
3199        }
3200    }
3201}
3202
3203#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3204#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3205pub enum TransactionMode {
3206    AccessMode(TransactionAccessMode),
3207    IsolationLevel(TransactionIsolationLevel),
3208}
3209
3210impl fmt::Display for TransactionMode {
3211    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3212        use TransactionMode::*;
3213        match self {
3214            AccessMode(access_mode) => write!(f, "{}", access_mode),
3215            IsolationLevel(iso_level) => write!(f, "ISOLATION LEVEL {}", iso_level),
3216        }
3217    }
3218}
3219
3220#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3221#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3222pub enum TransactionAccessMode {
3223    ReadOnly,
3224    ReadWrite,
3225}
3226
3227impl fmt::Display for TransactionAccessMode {
3228    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3229        use TransactionAccessMode::*;
3230        f.write_str(match self {
3231            ReadOnly => "READ ONLY",
3232            ReadWrite => "READ WRITE",
3233        })
3234    }
3235}
3236
3237#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3238#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3239pub enum TransactionIsolationLevel {
3240    ReadUncommitted,
3241    ReadCommitted,
3242    RepeatableRead,
3243    Serializable,
3244}
3245
3246impl fmt::Display for TransactionIsolationLevel {
3247    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3248        use TransactionIsolationLevel::*;
3249        f.write_str(match self {
3250            ReadUncommitted => "READ UNCOMMITTED",
3251            ReadCommitted => "READ COMMITTED",
3252            RepeatableRead => "REPEATABLE READ",
3253            Serializable => "SERIALIZABLE",
3254        })
3255    }
3256}
3257
3258#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3259#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3260pub enum ShowStatementFilter {
3261    Like(String),
3262    ILike(String),
3263    Where(Expr),
3264}
3265
3266impl fmt::Display for ShowStatementFilter {
3267    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3268        use ShowStatementFilter::*;
3269        match self {
3270            Like(pattern) => write!(f, "LIKE '{}'", value::escape_single_quote_string(pattern)),
3271            ILike(pattern) => write!(f, "ILIKE {}", value::escape_single_quote_string(pattern)),
3272            Where(expr) => write!(f, "WHERE {}", expr),
3273        }
3274    }
3275}
3276
3277/// Function describe in DROP FUNCTION.
3278#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3279#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3280pub enum DropFunctionOption {
3281    Restrict,
3282    Cascade,
3283}
3284
3285impl fmt::Display for DropFunctionOption {
3286    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3287        match self {
3288            DropFunctionOption::Restrict => write!(f, "RESTRICT "),
3289            DropFunctionOption::Cascade => write!(f, "CASCADE  "),
3290        }
3291    }
3292}
3293
3294/// Function describe in DROP FUNCTION.
3295#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3296#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3297pub struct FunctionDesc {
3298    pub name: ObjectName,
3299    pub args: Option<Vec<OperateFunctionArg>>,
3300}
3301
3302impl fmt::Display for FunctionDesc {
3303    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3304        write!(f, "{}", self.name)?;
3305        if let Some(args) = &self.args {
3306            write!(f, "({})", display_comma_separated(args))?;
3307        }
3308        Ok(())
3309    }
3310}
3311
3312/// Function argument in CREATE FUNCTION.
3313#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3314#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3315pub struct OperateFunctionArg {
3316    pub mode: Option<ArgMode>,
3317    pub name: Option<Ident>,
3318    pub data_type: DataType,
3319    pub default_expr: Option<Expr>,
3320}
3321
3322impl OperateFunctionArg {
3323    /// Returns an unnamed argument.
3324    pub fn unnamed(data_type: DataType) -> Self {
3325        Self {
3326            mode: None,
3327            name: None,
3328            data_type,
3329            default_expr: None,
3330        }
3331    }
3332
3333    /// Returns an argument with name.
3334    pub fn with_name(name: &str, data_type: DataType) -> Self {
3335        Self {
3336            mode: None,
3337            name: Some(name.into()),
3338            data_type,
3339            default_expr: None,
3340        }
3341    }
3342}
3343
3344impl fmt::Display for OperateFunctionArg {
3345    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3346        if let Some(mode) = &self.mode {
3347            write!(f, "{} ", mode)?;
3348        }
3349        if let Some(name) = &self.name {
3350            write!(f, "{} ", name)?;
3351        }
3352        write!(f, "{}", self.data_type)?;
3353        if let Some(default_expr) = &self.default_expr {
3354            write!(f, " = {}", default_expr)?;
3355        }
3356        Ok(())
3357    }
3358}
3359
3360/// The mode of an argument in CREATE FUNCTION.
3361#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3362#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3363pub enum ArgMode {
3364    In,
3365    Out,
3366    InOut,
3367}
3368
3369impl fmt::Display for ArgMode {
3370    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3371        match self {
3372            ArgMode::In => write!(f, "IN"),
3373            ArgMode::Out => write!(f, "OUT"),
3374            ArgMode::InOut => write!(f, "INOUT"),
3375        }
3376    }
3377}
3378
3379/// These attributes inform the query optimizer about the behavior of the function.
3380#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3381#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3382pub enum FunctionBehavior {
3383    Immutable,
3384    Stable,
3385    Volatile,
3386}
3387
3388impl fmt::Display for FunctionBehavior {
3389    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3390        match self {
3391            FunctionBehavior::Immutable => write!(f, "IMMUTABLE"),
3392            FunctionBehavior::Stable => write!(f, "STABLE"),
3393            FunctionBehavior::Volatile => write!(f, "VOLATILE"),
3394        }
3395    }
3396}
3397
3398#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3399#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3400pub enum FunctionDefinition {
3401    Identifier(String),
3402    SingleQuotedDef(String),
3403    DoubleDollarDef(String),
3404}
3405
3406impl fmt::Display for FunctionDefinition {
3407    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3408        match self {
3409            FunctionDefinition::Identifier(s) => write!(f, "{s}")?,
3410            FunctionDefinition::SingleQuotedDef(s) => write!(f, "'{s}'")?,
3411            FunctionDefinition::DoubleDollarDef(s) => write!(f, "$${s}$$")?,
3412        }
3413        Ok(())
3414    }
3415}
3416
3417impl FunctionDefinition {
3418    /// Returns the function definition as a string slice.
3419    pub fn as_str(&self) -> &str {
3420        match self {
3421            FunctionDefinition::Identifier(s) => s,
3422            FunctionDefinition::SingleQuotedDef(s) => s,
3423            FunctionDefinition::DoubleDollarDef(s) => s,
3424        }
3425    }
3426
3427    /// Returns the function definition as a string.
3428    pub fn into_string(self) -> String {
3429        match self {
3430            FunctionDefinition::Identifier(s) => s,
3431            FunctionDefinition::SingleQuotedDef(s) => s,
3432            FunctionDefinition::DoubleDollarDef(s) => s,
3433        }
3434    }
3435}
3436
3437/// Return types of a function.
3438#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3439#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3440pub enum CreateFunctionReturns {
3441    /// RETURNS rettype
3442    Value(DataType),
3443    /// RETURNS TABLE ( column_name column_type [, ...] )
3444    Table(Vec<TableColumnDef>),
3445}
3446
3447impl fmt::Display for CreateFunctionReturns {
3448    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3449        match self {
3450            Self::Value(data_type) => write!(f, "RETURNS {}", data_type),
3451            Self::Table(columns) => {
3452                write!(f, "RETURNS TABLE ({})", display_comma_separated(columns))
3453            }
3454        }
3455    }
3456}
3457
3458/// Table column definition
3459#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3460#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3461pub struct TableColumnDef {
3462    pub name: Ident,
3463    pub data_type: DataType,
3464}
3465
3466impl fmt::Display for TableColumnDef {
3467    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3468        write!(f, "{} {}", self.name, self.data_type)
3469    }
3470}
3471
3472/// Postgres specific feature.
3473///
3474/// See [Postgresdocs](https://www.postgresql.org/docs/15/sql-createfunction.html)
3475/// for more details
3476#[derive(Debug, Default, Clone, PartialEq, Eq, Hash)]
3477#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3478pub struct CreateFunctionBody {
3479    /// LANGUAGE lang_name
3480    pub language: Option<Ident>,
3481    /// RUNTIME runtime_name
3482    pub runtime: Option<Ident>,
3483
3484    /// IMMUTABLE | STABLE | VOLATILE
3485    pub behavior: Option<FunctionBehavior>,
3486    /// AS 'definition'
3487    ///
3488    /// Note that Hive's `AS class_name` is also parsed here.
3489    pub as_: Option<FunctionDefinition>,
3490    /// RETURN expression
3491    pub return_: Option<Expr>,
3492    /// USING ...
3493    pub using: Option<CreateFunctionUsing>,
3494}
3495
3496impl fmt::Display for CreateFunctionBody {
3497    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3498        if let Some(language) = &self.language {
3499            write!(f, " LANGUAGE {language}")?;
3500        }
3501        if let Some(runtime) = &self.runtime {
3502            write!(f, " RUNTIME {runtime}")?;
3503        }
3504        if let Some(behavior) = &self.behavior {
3505            write!(f, " {behavior}")?;
3506        }
3507        if let Some(definition) = &self.as_ {
3508            write!(f, " AS {definition}")?;
3509        }
3510        if let Some(expr) = &self.return_ {
3511            write!(f, " RETURN {expr}")?;
3512        }
3513        if let Some(using) = &self.using {
3514            write!(f, " {using}")?;
3515        }
3516        Ok(())
3517    }
3518}
3519
3520#[derive(Debug, Default, Clone, PartialEq, Eq, Hash)]
3521#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3522pub struct CreateFunctionWithOptions {
3523    /// Always retry on network errors.
3524    pub always_retry_on_network_error: Option<bool>,
3525    /// Use async functions (only available for JS UDF)
3526    pub r#async: Option<bool>,
3527    /// Call in batch mode (only available for JS UDF)
3528    pub batch: Option<bool>,
3529}
3530
3531/// TODO(kwannoel): Generate from the struct definition instead.
3532impl TryFrom<Vec<SqlOption>> for CreateFunctionWithOptions {
3533    type Error = StrError;
3534
3535    fn try_from(with_options: Vec<SqlOption>) -> Result<Self, Self::Error> {
3536        let mut options = Self::default();
3537        for option in with_options {
3538            match option.name.to_string().to_lowercase().as_str() {
3539                "always_retry_on_network_error" => {
3540                    options.always_retry_on_network_error = Some(matches!(
3541                        option.value,
3542                        SqlOptionValue::Value(Value::Boolean(true))
3543                    ));
3544                }
3545                "async" => {
3546                    options.r#async = Some(matches!(
3547                        option.value,
3548                        SqlOptionValue::Value(Value::Boolean(true))
3549                    ))
3550                }
3551                "batch" => {
3552                    options.batch = Some(matches!(
3553                        option.value,
3554                        SqlOptionValue::Value(Value::Boolean(true))
3555                    ))
3556                }
3557                _ => {
3558                    return Err(StrError(format!("unknown option: {}", option.name)));
3559                }
3560            }
3561        }
3562        Ok(options)
3563    }
3564}
3565
3566impl Display for CreateFunctionWithOptions {
3567    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3568        if self == &Self::default() {
3569            return Ok(());
3570        }
3571        let mut options = vec![];
3572        if let Some(v) = self.always_retry_on_network_error {
3573            options.push(format!("always_retry_on_network_error = {}", v));
3574        }
3575        if let Some(v) = self.r#async {
3576            options.push(format!("async = {}", v));
3577        }
3578        if let Some(v) = self.batch {
3579            options.push(format!("batch = {}", v));
3580        }
3581        write!(f, " WITH ( {} )", display_comma_separated(&options))
3582    }
3583}
3584
3585#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3586#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3587pub enum CreateFunctionUsing {
3588    Link(String),
3589    Base64(String),
3590}
3591
3592impl fmt::Display for CreateFunctionUsing {
3593    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3594        write!(f, "USING ")?;
3595        match self {
3596            CreateFunctionUsing::Link(uri) => write!(f, "LINK '{uri}'"),
3597            CreateFunctionUsing::Base64(s) => {
3598                write!(f, "BASE64 '{s}'")
3599            }
3600        }
3601    }
3602}
3603
3604#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3605#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3606pub struct ConfigParam {
3607    pub param: Ident,
3608    pub value: SetVariableValue,
3609}
3610
3611impl fmt::Display for ConfigParam {
3612    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3613        write!(f, "SET {} = {}", self.param, self.value)
3614    }
3615}
3616
3617#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3618#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3619pub enum SetVariableValue {
3620    Single(SetVariableValueSingle),
3621    List(Vec<SetVariableValueSingle>),
3622    Default,
3623}
3624
3625impl From<SetVariableValueSingle> for SetVariableValue {
3626    fn from(value: SetVariableValueSingle) -> Self {
3627        SetVariableValue::Single(value)
3628    }
3629}
3630
3631impl fmt::Display for SetVariableValue {
3632    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3633        use SetVariableValue::*;
3634        match self {
3635            Single(val) => write!(f, "{}", val),
3636            List(list) => write!(f, "{}", display_comma_separated(list),),
3637            Default => write!(f, "DEFAULT"),
3638        }
3639    }
3640}
3641
3642#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3643#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3644pub enum SetVariableValueSingle {
3645    Ident(Ident),
3646    Literal(Value),
3647}
3648
3649impl SetVariableValueSingle {
3650    pub fn to_string_unquoted(&self) -> String {
3651        match self {
3652            Self::Literal(Value::SingleQuotedString(s))
3653            | Self::Literal(Value::DoubleQuotedString(s)) => s.clone(),
3654            _ => self.to_string(),
3655        }
3656    }
3657}
3658
3659impl fmt::Display for SetVariableValueSingle {
3660    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3661        use SetVariableValueSingle::*;
3662        match self {
3663            Ident(ident) => write!(f, "{}", ident),
3664            Literal(literal) => write!(f, "{}", literal),
3665        }
3666    }
3667}
3668
3669#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3670#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3671pub enum AsOf {
3672    ProcessTime,
3673    // used by time travel
3674    ProcessTimeWithInterval((String, DateTimeField)),
3675    // the number of seconds that have elapsed since the Unix epoch, which is January 1, 1970 at 00:00:00 Coordinated Universal Time (UTC).
3676    TimestampNum(i64),
3677    TimestampString(String),
3678    VersionNum(i64),
3679    VersionString(String),
3680}
3681
3682impl fmt::Display for AsOf {
3683    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3684        use AsOf::*;
3685        match self {
3686            ProcessTime => write!(f, " FOR SYSTEM_TIME AS OF PROCTIME()"),
3687            ProcessTimeWithInterval((value, leading_field)) => write!(
3688                f,
3689                " FOR SYSTEM_TIME AS OF NOW() - {} {}",
3690                value, leading_field
3691            ),
3692            TimestampNum(ts) => write!(f, " FOR SYSTEM_TIME AS OF {}", ts),
3693            TimestampString(ts) => write!(f, " FOR SYSTEM_TIME AS OF '{}'", ts),
3694            VersionNum(v) => write!(f, " FOR SYSTEM_VERSION AS OF {}", v),
3695            VersionString(v) => write!(f, " FOR SYSTEM_VERSION AS OF '{}'", v),
3696        }
3697    }
3698}
3699
3700#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3701#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3702pub enum DiscardType {
3703    All,
3704}
3705
3706impl fmt::Display for DiscardType {
3707    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3708        use DiscardType::*;
3709        match self {
3710            All => write!(f, "ALL"),
3711        }
3712    }
3713}
3714
3715// We decouple "default" from none,
3716// so we can choose strategies that make the most sense.
3717#[derive(Debug, Default, Clone, PartialEq, Eq, Hash)]
3718#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3719pub enum BackfillOrderStrategy {
3720    #[default]
3721    Default,
3722    None,
3723    Auto,
3724    Fixed(Vec<(ObjectName, ObjectName)>),
3725}
3726
3727impl fmt::Display for BackfillOrderStrategy {
3728    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3729        use BackfillOrderStrategy::*;
3730        match self {
3731            Default => write!(f, "DEFAULT"),
3732            None => write!(f, "NONE"),
3733            Auto => write!(f, "AUTO"),
3734            Fixed(map) => {
3735                let mut parts = vec![];
3736                for (start, end) in map {
3737                    parts.push(format!("{} -> {}", start, end));
3738                }
3739                write!(f, "{}", display_comma_separated(&parts))
3740            }
3741        }
3742    }
3743}
3744
3745impl Statement {
3746    pub fn to_redacted_string(&self, keywords: RedactSqlOptionKeywordsRef) -> String {
3747        REDACT_SQL_OPTION_KEYWORDS.sync_scope(keywords, || self.to_string_unchecked())
3748    }
3749
3750    /// Create a new `CREATE TABLE` statement with the given `name` and empty fields.
3751    pub fn default_create_table(name: ObjectName) -> Self {
3752        Self::CreateTable {
3753            name,
3754            or_replace: false,
3755            temporary: false,
3756            if_not_exists: false,
3757            columns: Vec::new(),
3758            wildcard_idx: None,
3759            constraints: Vec::new(),
3760            with_options: Vec::new(),
3761            format_encode: None,
3762            source_watermarks: Vec::new(),
3763            append_only: false,
3764            on_conflict: None,
3765            with_version_column: None,
3766            query: None,
3767            cdc_table_info: None,
3768            include_column_options: Vec::new(),
3769            webhook_info: None,
3770            engine: Engine::Hummock,
3771        }
3772    }
3773}
3774
3775#[cfg(test)]
3776mod tests {
3777    use super::*;
3778
3779    #[test]
3780    fn test_grouping_sets_display() {
3781        // a and b in different group
3782        let grouping_sets = Expr::GroupingSets(vec![
3783            vec![Expr::Identifier(Ident::new_unchecked("a"))],
3784            vec![Expr::Identifier(Ident::new_unchecked("b"))],
3785        ]);
3786        assert_eq!("GROUPING SETS ((a), (b))", format!("{}", grouping_sets));
3787
3788        // a and b in the same group
3789        let grouping_sets = Expr::GroupingSets(vec![vec![
3790            Expr::Identifier(Ident::new_unchecked("a")),
3791            Expr::Identifier(Ident::new_unchecked("b")),
3792        ]]);
3793        assert_eq!("GROUPING SETS ((a, b))", format!("{}", grouping_sets));
3794
3795        // (a, b) and (c, d) in different group
3796        let grouping_sets = Expr::GroupingSets(vec![
3797            vec![
3798                Expr::Identifier(Ident::new_unchecked("a")),
3799                Expr::Identifier(Ident::new_unchecked("b")),
3800            ],
3801            vec![
3802                Expr::Identifier(Ident::new_unchecked("c")),
3803                Expr::Identifier(Ident::new_unchecked("d")),
3804            ],
3805        ]);
3806        assert_eq!(
3807            "GROUPING SETS ((a, b), (c, d))",
3808            format!("{}", grouping_sets)
3809        );
3810    }
3811
3812    #[test]
3813    fn test_rollup_display() {
3814        let rollup = Expr::Rollup(vec![vec![Expr::Identifier(Ident::new_unchecked("a"))]]);
3815        assert_eq!("ROLLUP (a)", format!("{}", rollup));
3816
3817        let rollup = Expr::Rollup(vec![vec![
3818            Expr::Identifier(Ident::new_unchecked("a")),
3819            Expr::Identifier(Ident::new_unchecked("b")),
3820        ]]);
3821        assert_eq!("ROLLUP ((a, b))", format!("{}", rollup));
3822
3823        let rollup = Expr::Rollup(vec![
3824            vec![Expr::Identifier(Ident::new_unchecked("a"))],
3825            vec![Expr::Identifier(Ident::new_unchecked("b"))],
3826        ]);
3827        assert_eq!("ROLLUP (a, b)", format!("{}", rollup));
3828
3829        let rollup = Expr::Rollup(vec![
3830            vec![Expr::Identifier(Ident::new_unchecked("a"))],
3831            vec![
3832                Expr::Identifier(Ident::new_unchecked("b")),
3833                Expr::Identifier(Ident::new_unchecked("c")),
3834            ],
3835            vec![Expr::Identifier(Ident::new_unchecked("d"))],
3836        ]);
3837        assert_eq!("ROLLUP (a, (b, c), d)", format!("{}", rollup));
3838    }
3839
3840    #[test]
3841    fn test_cube_display() {
3842        let cube = Expr::Cube(vec![vec![Expr::Identifier(Ident::new_unchecked("a"))]]);
3843        assert_eq!("CUBE (a)", format!("{}", cube));
3844
3845        let cube = Expr::Cube(vec![vec![
3846            Expr::Identifier(Ident::new_unchecked("a")),
3847            Expr::Identifier(Ident::new_unchecked("b")),
3848        ]]);
3849        assert_eq!("CUBE ((a, b))", format!("{}", cube));
3850
3851        let cube = Expr::Cube(vec![
3852            vec![Expr::Identifier(Ident::new_unchecked("a"))],
3853            vec![Expr::Identifier(Ident::new_unchecked("b"))],
3854        ]);
3855        assert_eq!("CUBE (a, b)", format!("{}", cube));
3856
3857        let cube = Expr::Cube(vec![
3858            vec![Expr::Identifier(Ident::new_unchecked("a"))],
3859            vec![
3860                Expr::Identifier(Ident::new_unchecked("b")),
3861                Expr::Identifier(Ident::new_unchecked("c")),
3862            ],
3863            vec![Expr::Identifier(Ident::new_unchecked("d"))],
3864        ]);
3865        assert_eq!("CUBE (a, (b, c), d)", format!("{}", cube));
3866    }
3867
3868    #[test]
3869    fn test_array_index_display() {
3870        let array_index = Expr::Index {
3871            obj: Box::new(Expr::Identifier(Ident::new_unchecked("v1"))),
3872            index: Box::new(Expr::Value(Value::Number("1".into()))),
3873        };
3874        assert_eq!("v1[1]", format!("{}", array_index));
3875
3876        let array_index2 = Expr::Index {
3877            obj: Box::new(array_index),
3878            index: Box::new(Expr::Value(Value::Number("1".into()))),
3879        };
3880        assert_eq!("v1[1][1]", format!("{}", array_index2));
3881    }
3882
3883    #[test]
3884    /// issue: https://github.com/risingwavelabs/risingwave/issues/7635
3885    fn test_nested_op_display() {
3886        let binary_op = Expr::BinaryOp {
3887            left: Box::new(Expr::Value(Value::Boolean(true))),
3888            op: BinaryOperator::Or,
3889            right: Box::new(Expr::IsNotFalse(Box::new(Expr::Value(Value::Boolean(
3890                true,
3891            ))))),
3892        };
3893        assert_eq!("true OR true IS NOT FALSE", format!("{}", binary_op));
3894
3895        let unary_op = Expr::UnaryOp {
3896            op: UnaryOperator::Not,
3897            expr: Box::new(Expr::IsNotFalse(Box::new(Expr::Value(Value::Boolean(
3898                true,
3899            ))))),
3900        };
3901        assert_eq!("NOT true IS NOT FALSE", format!("{}", unary_op));
3902    }
3903
3904    #[test]
3905    fn test_create_function_display() {
3906        let create_function = Statement::CreateFunction {
3907            or_replace: false,
3908            temporary: false,
3909            if_not_exists: false,
3910            name: ObjectName(vec![Ident::new_unchecked("foo")]),
3911            args: Some(vec![OperateFunctionArg::unnamed(DataType::Int)]),
3912            returns: Some(CreateFunctionReturns::Value(DataType::Int)),
3913            params: CreateFunctionBody {
3914                language: Some(Ident::new_unchecked("python")),
3915                runtime: None,
3916                behavior: Some(FunctionBehavior::Immutable),
3917                as_: Some(FunctionDefinition::SingleQuotedDef("SELECT 1".to_owned())),
3918                return_: None,
3919                using: None,
3920            },
3921            with_options: CreateFunctionWithOptions {
3922                always_retry_on_network_error: None,
3923                r#async: None,
3924                batch: None,
3925            },
3926        };
3927        assert_eq!(
3928            "CREATE FUNCTION foo(INT) RETURNS INT LANGUAGE python IMMUTABLE AS 'SELECT 1'",
3929            format!("{}", create_function)
3930        );
3931        let create_function = Statement::CreateFunction {
3932            or_replace: false,
3933            temporary: false,
3934            if_not_exists: false,
3935            name: ObjectName(vec![Ident::new_unchecked("foo")]),
3936            args: Some(vec![OperateFunctionArg::unnamed(DataType::Int)]),
3937            returns: Some(CreateFunctionReturns::Value(DataType::Int)),
3938            params: CreateFunctionBody {
3939                language: Some(Ident::new_unchecked("python")),
3940                runtime: None,
3941                behavior: Some(FunctionBehavior::Immutable),
3942                as_: Some(FunctionDefinition::SingleQuotedDef("SELECT 1".to_owned())),
3943                return_: None,
3944                using: None,
3945            },
3946            with_options: CreateFunctionWithOptions {
3947                always_retry_on_network_error: Some(true),
3948                r#async: None,
3949                batch: None,
3950            },
3951        };
3952        assert_eq!(
3953            "CREATE FUNCTION foo(INT) RETURNS INT LANGUAGE python IMMUTABLE AS 'SELECT 1' WITH ( always_retry_on_network_error = true )",
3954            format!("{}", create_function)
3955        );
3956    }
3957}