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