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