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