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