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