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