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