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!(
2154 f,
2155 " TABLE '{}'",
2156 value::escape_single_quote_string(&info.external_table_name)
2157 )?;
2158 }
2159 if let Some(info) = webhook_info
2160 && let Some(signature_expr) = &info.signature_expr
2161 {
2162 if let Some(secret) = &info.secret_ref {
2163 write!(f, " VALIDATE SECRET {}", secret.secret_name)?;
2164 } else {
2165 write!(f, " VALIDATE")?;
2166 }
2167 write!(f, " AS {}", signature_expr)?;
2168 }
2169 match engine {
2170 Engine::Hummock => {}
2171 Engine::Iceberg => {
2172 write!(f, " ENGINE = {}", engine)?;
2173 }
2174 }
2175 Ok(())
2176 }
2177 Statement::CreateIndex {
2178 name,
2179 table_name,
2180 columns,
2181 method,
2182 include,
2183 distributed_by,
2184 unique,
2185 if_not_exists,
2186 with_properties,
2187 } => write!(
2188 f,
2189 "CREATE {unique}INDEX {if_not_exists}{name} ON {table_name}{method}({columns}){include}{distributed_by}{with_properties}",
2190 unique = if *unique { "UNIQUE " } else { "" },
2191 if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
2192 name = name,
2193 table_name = table_name,
2194 method = if let Some(method) = method {
2195 format!(" USING {} ", method)
2196 } else {
2197 "".to_owned()
2198 },
2199 columns = display_comma_separated(columns),
2200 include = if include.is_empty() {
2201 "".to_owned()
2202 } else {
2203 format!(" INCLUDE({})", display_separated(include, ","))
2204 },
2205 distributed_by = if distributed_by.is_empty() {
2206 "".to_owned()
2207 } else {
2208 format!(
2209 " DISTRIBUTED BY({})",
2210 display_separated(distributed_by, ",")
2211 )
2212 },
2213 with_properties = if !with_properties.0.is_empty() {
2214 format!(" {}", with_properties)
2215 } else {
2216 "".to_owned()
2217 },
2218 ),
2219 Statement::CreateSource { stmt } => write!(f, "CREATE SOURCE {}", stmt,),
2220 Statement::CreateSink { stmt } => {
2221 if stmt.or_replace {
2222 write!(f, "REPLACE SINK {}", stmt)
2223 } else {
2224 write!(f, "CREATE SINK {}", stmt)
2225 }
2226 }
2227 Statement::CreateSubscription { stmt } => write!(f, "CREATE SUBSCRIPTION {}", stmt,),
2228 Statement::CreateConnection { stmt } => write!(f, "CREATE CONNECTION {}", stmt,),
2229 Statement::DeclareCursor { stmt } => write!(f, "DECLARE {}", stmt,),
2230 Statement::FetchCursor { stmt } => write!(f, "FETCH {}", stmt),
2231 Statement::CloseCursor { stmt } => write!(f, "CLOSE {}", stmt),
2232 Statement::CreateSecret { stmt } => write!(f, "CREATE SECRET {}", stmt),
2233 Statement::AlterDatabase { name, operation } => {
2234 write!(f, "ALTER DATABASE {} {}", name, operation)
2235 }
2236 Statement::AlterSchema { name, operation } => {
2237 write!(f, "ALTER SCHEMA {} {}", name, operation)
2238 }
2239 Statement::AlterTable { name, operation } => {
2240 write!(f, "ALTER TABLE {} {}", name, operation)
2241 }
2242 Statement::AlterIndex { name, operation } => {
2243 write!(f, "ALTER INDEX {} {}", name, operation)
2244 }
2245 Statement::AlterView {
2246 materialized,
2247 name,
2248 operation,
2249 } => {
2250 write!(
2251 f,
2252 "ALTER {}VIEW {} {}",
2253 if *materialized { "MATERIALIZED " } else { "" },
2254 name,
2255 operation
2256 )
2257 }
2258 Statement::AlterSink { name, operation } => {
2259 write!(f, "ALTER SINK {} {}", name, operation)
2260 }
2261 Statement::AlterSubscription { name, operation } => {
2262 write!(f, "ALTER SUBSCRIPTION {} {}", name, operation)
2263 }
2264 Statement::AlterSource { name, operation } => {
2265 write!(f, "ALTER SOURCE {} {}", name, operation)
2266 }
2267 Statement::AlterFunction {
2268 name,
2269 args,
2270 operation,
2271 } => {
2272 write!(f, "ALTER FUNCTION {}", name)?;
2273 if let Some(args) = args {
2274 write!(f, "({})", display_comma_separated(args))?;
2275 }
2276 write!(f, " {}", operation)
2277 }
2278 Statement::AlterConnection { name, operation } => {
2279 write!(f, "ALTER CONNECTION {} {}", name, operation)
2280 }
2281 Statement::AlterSecret { name, operation } => {
2282 write!(f, "ALTER SECRET {}", name)?;
2283 write!(f, "{}", operation)
2284 }
2285 Statement::Discard(t) => write!(f, "DISCARD {}", t),
2286 Statement::Drop(stmt) => write!(f, "DROP {}", stmt),
2287 Statement::DropFunction {
2288 if_exists,
2289 func_desc,
2290 option,
2291 } => {
2292 write!(
2293 f,
2294 "DROP FUNCTION{} {}",
2295 if *if_exists { " IF EXISTS" } else { "" },
2296 display_comma_separated(func_desc),
2297 )?;
2298 if let Some(op) = option {
2299 write!(f, " {}", op)?;
2300 }
2301 Ok(())
2302 }
2303 Statement::DropAggregate {
2304 if_exists,
2305 func_desc,
2306 option,
2307 } => {
2308 write!(
2309 f,
2310 "DROP AGGREGATE{} {}",
2311 if *if_exists { " IF EXISTS" } else { "" },
2312 display_comma_separated(func_desc),
2313 )?;
2314 if let Some(op) = option {
2315 write!(f, " {}", op)?;
2316 }
2317 Ok(())
2318 }
2319 Statement::SetVariable {
2320 local,
2321 variable,
2322 value,
2323 } => {
2324 f.write_str("SET ")?;
2325 if *local {
2326 f.write_str("LOCAL ")?;
2327 }
2328 write!(f, "{name} = {value}", name = variable,)
2329 }
2330 Statement::ShowVariable { variable } => {
2331 write!(f, "SHOW")?;
2332 if !variable.is_empty() {
2333 write!(f, " {}", display_separated(variable, " "))?;
2334 }
2335 Ok(())
2336 }
2337 Statement::StartTransaction { modes } => {
2338 write!(f, "START TRANSACTION")?;
2339 if !modes.is_empty() {
2340 write!(f, " {}", display_comma_separated(modes))?;
2341 }
2342 Ok(())
2343 }
2344 Statement::Abort => {
2345 write!(f, "ABORT")?;
2346 Ok(())
2347 }
2348 Statement::SetTransaction {
2349 modes,
2350 snapshot,
2351 session,
2352 } => {
2353 if *session {
2354 write!(f, "SET SESSION CHARACTERISTICS AS TRANSACTION")?;
2355 } else {
2356 write!(f, "SET TRANSACTION")?;
2357 }
2358 if !modes.is_empty() {
2359 write!(f, " {}", display_comma_separated(modes))?;
2360 }
2361 if let Some(snapshot_id) = snapshot {
2362 write!(f, " SNAPSHOT {}", snapshot_id)?;
2363 }
2364 Ok(())
2365 }
2366 Statement::SetTimeZone { local, value } => {
2367 write!(f, "SET")?;
2368 if *local {
2369 write!(f, " LOCAL")?;
2370 }
2371 write!(f, " TIME ZONE {}", value)?;
2372 Ok(())
2373 }
2374 Statement::Commit { chain } => {
2375 write!(f, "COMMIT{}", if *chain { " AND CHAIN" } else { "" },)
2376 }
2377 Statement::Rollback { chain } => {
2378 write!(f, "ROLLBACK{}", if *chain { " AND CHAIN" } else { "" },)
2379 }
2380 Statement::CreateSchema {
2381 schema_name,
2382 if_not_exists,
2383 owner,
2384 } => {
2385 write!(
2386 f,
2387 "CREATE SCHEMA {if_not_exists}{name}",
2388 if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
2389 name = schema_name
2390 )?;
2391 if let Some(user) = owner {
2392 write!(f, " AUTHORIZATION {}", user)?;
2393 }
2394 Ok(())
2395 }
2396 Statement::Grant {
2397 privileges,
2398 objects,
2399 grantees,
2400 with_grant_option,
2401 granted_by,
2402 } => {
2403 write!(f, "GRANT {} ", privileges)?;
2404 write!(f, "ON {} ", objects)?;
2405 write!(f, "TO {}", display_comma_separated(grantees))?;
2406 if *with_grant_option {
2407 write!(f, " WITH GRANT OPTION")?;
2408 }
2409 if let Some(grantor) = granted_by {
2410 write!(f, " GRANTED BY {}", grantor)?;
2411 }
2412 Ok(())
2413 }
2414 Statement::Revoke {
2415 privileges,
2416 objects,
2417 grantees,
2418 granted_by,
2419 revoke_grant_option,
2420 cascade,
2421 } => {
2422 write!(
2423 f,
2424 "REVOKE {}{} ",
2425 if *revoke_grant_option {
2426 "GRANT OPTION FOR "
2427 } else {
2428 ""
2429 },
2430 privileges
2431 )?;
2432 write!(f, "ON {} ", objects)?;
2433 write!(f, "FROM {}", display_comma_separated(grantees))?;
2434 if let Some(grantor) = granted_by {
2435 write!(f, " GRANTED BY {}", grantor)?;
2436 }
2437 write!(f, " {}", if *cascade { "CASCADE" } else { "RESTRICT" })?;
2438 Ok(())
2439 }
2440 Statement::Deallocate { name, prepare } => {
2441 if let Some(name) = name {
2442 write!(
2443 f,
2444 "DEALLOCATE {prepare}{name}",
2445 prepare = if *prepare { "PREPARE " } else { "" },
2446 name = name,
2447 )
2448 } else {
2449 write!(
2450 f,
2451 "DEALLOCATE {prepare}ALL",
2452 prepare = if *prepare { "PREPARE " } else { "" },
2453 )
2454 }
2455 }
2456 Statement::Execute { name, parameters } => {
2457 write!(f, "EXECUTE {}", name)?;
2458 if !parameters.is_empty() {
2459 write!(f, "({})", display_comma_separated(parameters))?;
2460 }
2461 Ok(())
2462 }
2463 Statement::Prepare {
2464 name,
2465 data_types,
2466 statement,
2467 } => {
2468 write!(f, "PREPARE {} ", name)?;
2469 if !data_types.is_empty() {
2470 write!(f, "({}) ", display_comma_separated(data_types))?;
2471 }
2472 write!(f, "AS ")?;
2473 statement.fmt_unchecked(f)
2474 }
2475 Statement::Comment {
2476 object_type,
2477 object_name,
2478 comment,
2479 } => {
2480 write!(f, "COMMENT ON {} {} IS ", object_type, object_name)?;
2481 if let Some(c) = comment {
2482 write!(f, "'{}'", c)
2483 } else {
2484 write!(f, "NULL")
2485 }
2486 }
2487 Statement::CreateUser(statement) => {
2488 write!(f, "CREATE USER {}", statement)
2489 }
2490 Statement::AlterUser(statement) => {
2491 write!(f, "ALTER USER {}", statement)
2492 }
2493 Statement::AlterSystem { param, value } => {
2494 f.write_str("ALTER SYSTEM SET ")?;
2495 write!(f, "{param} = {value}",)
2496 }
2497 Statement::AlterSystemClearFileCache { cache_type } => {
2498 f.write_str("ALTER SYSTEM CLEAR FILE CACHE ")?;
2499 match cache_type {
2500 FileCacheType::Meta => f.write_str("META"),
2501 FileCacheType::Data => f.write_str("DATA"),
2502 FileCacheType::All => f.write_str("ALL"),
2503 }
2504 }
2505 Statement::Flush => {
2506 write!(f, "FLUSH")
2507 }
2508 Statement::Wait(target) => match target {
2509 WaitTarget::All => write!(f, "WAIT"),
2510 WaitTarget::Table(name) => write!(f, "WAIT TABLE {name}"),
2511 WaitTarget::MaterializedView(name) => {
2512 write!(f, "WAIT MATERIALIZED VIEW {name}")
2513 }
2514 WaitTarget::Sink(name) => write!(f, "WAIT SINK {name}"),
2515 WaitTarget::Index(name) => write!(f, "WAIT INDEX {name}"),
2516 },
2517 Statement::Backup => {
2518 write!(f, "BACKUP")?;
2519 Ok(())
2520 }
2521 Statement::Begin { modes } => {
2522 write!(f, "BEGIN")?;
2523 if !modes.is_empty() {
2524 write!(f, " {}", display_comma_separated(modes))?;
2525 }
2526 Ok(())
2527 }
2528 Statement::CancelJobs(jobs) => {
2529 write!(f, "CANCEL JOBS {}", display_comma_separated(&jobs.0))?;
2530 Ok(())
2531 }
2532 Statement::Kill(worker_process_id) => {
2533 write!(f, "KILL '{}'", worker_process_id)?;
2534 Ok(())
2535 }
2536 Statement::Recover => {
2537 write!(f, "RECOVER")?;
2538 Ok(())
2539 }
2540 Statement::Use { db_name } => {
2541 write!(f, "USE {}", db_name)?;
2542 Ok(())
2543 }
2544 Statement::Vacuum { object_name, full } => {
2545 if *full {
2546 write!(f, "VACUUM FULL {}", object_name)?;
2547 } else {
2548 write!(f, "VACUUM {}", object_name)?;
2549 }
2550 Ok(())
2551 }
2552 Statement::AlterFragment {
2553 fragment_ids,
2554 operation,
2555 } => {
2556 write!(
2557 f,
2558 "ALTER FRAGMENT {} {}",
2559 display_comma_separated(fragment_ids),
2560 operation
2561 )
2562 }
2563 Statement::AlterCompactionGroup {
2564 group_ids,
2565 operation,
2566 } => {
2567 write!(
2568 f,
2569 "ALTER COMPACTION GROUP {} {}",
2570 display_comma_separated(group_ids),
2571 operation
2572 )
2573 }
2574 Statement::AlterDefaultPrivileges {
2575 target_users,
2576 schema_names,
2577 operation,
2578 } => {
2579 write!(f, "ALTER DEFAULT PRIVILEGES")?;
2580 if let Some(target_users) = target_users {
2581 write!(f, " FOR {}", display_comma_separated(target_users))?;
2582 }
2583 if let Some(schema_names) = schema_names {
2584 write!(f, " IN SCHEMA {}", display_comma_separated(schema_names))?;
2585 }
2586 write!(f, " {}", operation)
2587 }
2588 }
2589 }
2590
2591 pub fn is_create(&self) -> bool {
2592 matches!(
2593 self,
2594 Statement::CreateTable { .. }
2595 | Statement::CreateView { .. }
2596 | Statement::CreateSource { .. }
2597 | Statement::CreateSink { .. }
2598 | Statement::CreateSubscription { .. }
2599 | Statement::CreateConnection { .. }
2600 | Statement::CreateSecret { .. }
2601 | Statement::CreateUser { .. }
2602 | Statement::CreateDatabase { .. }
2603 | Statement::CreateFunction { .. }
2604 | Statement::CreateAggregate { .. }
2605 | Statement::CreateIndex { .. }
2606 | Statement::CreateSchema { .. }
2607 )
2608 }
2609}
2610
2611impl Display for IncludeOptionItem {
2612 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2613 let Self {
2614 column_type,
2615 inner_field,
2616 header_inner_expect_type,
2617 column_alias,
2618 } = self;
2619 write!(f, "INCLUDE {}", column_type)?;
2620 if let Some(inner_field) = inner_field {
2621 write!(f, " '{}'", value::escape_single_quote_string(inner_field))?;
2622 if let Some(expected_type) = header_inner_expect_type {
2623 write!(f, " {}", expected_type)?;
2624 }
2625 }
2626 if let Some(alias) = column_alias {
2627 write!(f, " AS {}", alias)?;
2628 }
2629 Ok(())
2630 }
2631}
2632
2633#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2634#[non_exhaustive]
2635pub enum OnInsert {
2636 DuplicateKeyUpdate(Vec<Assignment>),
2638}
2639
2640impl fmt::Display for OnInsert {
2641 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2642 match self {
2643 Self::DuplicateKeyUpdate(expr) => write!(
2644 f,
2645 " ON DUPLICATE KEY UPDATE {}",
2646 display_comma_separated(expr)
2647 ),
2648 }
2649 }
2650}
2651
2652#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2654pub enum Privileges {
2655 All {
2657 with_privileges_keyword: bool,
2659 },
2660 Actions(Vec<Action>),
2662}
2663
2664impl fmt::Display for Privileges {
2665 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2666 match self {
2667 Privileges::All {
2668 with_privileges_keyword,
2669 } => {
2670 write!(
2671 f,
2672 "ALL{}",
2673 if *with_privileges_keyword {
2674 " PRIVILEGES"
2675 } else {
2676 ""
2677 }
2678 )
2679 }
2680 Privileges::Actions(actions) => {
2681 write!(f, "{}", display_comma_separated(actions))
2682 }
2683 }
2684 }
2685}
2686
2687#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2689pub enum Action {
2690 Connect,
2691 Create,
2692 Delete,
2693 Execute,
2694 Insert { columns: Option<Vec<Ident>> },
2695 References { columns: Option<Vec<Ident>> },
2696 Select { columns: Option<Vec<Ident>> },
2697 Temporary,
2698 Trigger,
2699 Truncate,
2700 Update { columns: Option<Vec<Ident>> },
2701 Usage,
2702}
2703
2704impl fmt::Display for Action {
2705 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2706 match self {
2707 Action::Connect => f.write_str("CONNECT")?,
2708 Action::Create => f.write_str("CREATE")?,
2709 Action::Delete => f.write_str("DELETE")?,
2710 Action::Execute => f.write_str("EXECUTE")?,
2711 Action::Insert { .. } => f.write_str("INSERT")?,
2712 Action::References { .. } => f.write_str("REFERENCES")?,
2713 Action::Select { .. } => f.write_str("SELECT")?,
2714 Action::Temporary => f.write_str("TEMPORARY")?,
2715 Action::Trigger => f.write_str("TRIGGER")?,
2716 Action::Truncate => f.write_str("TRUNCATE")?,
2717 Action::Update { .. } => f.write_str("UPDATE")?,
2718 Action::Usage => f.write_str("USAGE")?,
2719 };
2720 match self {
2721 Action::Insert { columns }
2722 | Action::References { columns }
2723 | Action::Select { columns }
2724 | Action::Update { columns } => {
2725 if let Some(columns) = columns {
2726 write!(f, " ({})", display_comma_separated(columns))?;
2727 }
2728 }
2729 _ => (),
2730 };
2731 Ok(())
2732 }
2733}
2734
2735#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2737pub enum GrantObjects {
2738 AllSequencesInSchema { schemas: Vec<ObjectName> },
2740 AllTablesInSchema { schemas: Vec<ObjectName> },
2742 AllSourcesInSchema { schemas: Vec<ObjectName> },
2744 AllSinksInSchema { schemas: Vec<ObjectName> },
2746 AllMviewsInSchema { schemas: Vec<ObjectName> },
2748 AllViewsInSchema { schemas: Vec<ObjectName> },
2750 AllFunctionsInSchema { schemas: Vec<ObjectName> },
2752 AllSecretsInSchema { schemas: Vec<ObjectName> },
2754 AllSubscriptionsInSchema { schemas: Vec<ObjectName> },
2756 AllConnectionsInSchema { schemas: Vec<ObjectName> },
2758 Databases(Vec<ObjectName>),
2760 Schemas(Vec<ObjectName>),
2762 Sources(Vec<ObjectName>),
2764 Mviews(Vec<ObjectName>),
2766 Sequences(Vec<ObjectName>),
2768 Tables(Vec<ObjectName>),
2770 Sinks(Vec<ObjectName>),
2772 Views(Vec<ObjectName>),
2774 Connections(Vec<ObjectName>),
2776 Subscriptions(Vec<ObjectName>),
2778 Functions(Vec<FunctionDesc>),
2780 Secrets(Vec<ObjectName>),
2782}
2783
2784impl fmt::Display for GrantObjects {
2785 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2786 match self {
2787 GrantObjects::Sequences(sequences) => {
2788 write!(f, "SEQUENCE {}", display_comma_separated(sequences))
2789 }
2790 GrantObjects::Schemas(schemas) => {
2791 write!(f, "SCHEMA {}", display_comma_separated(schemas))
2792 }
2793 GrantObjects::Tables(tables) => {
2794 write!(f, "{}", display_comma_separated(tables))
2795 }
2796 GrantObjects::AllSequencesInSchema { schemas } => {
2797 write!(
2798 f,
2799 "ALL SEQUENCES IN SCHEMA {}",
2800 display_comma_separated(schemas)
2801 )
2802 }
2803 GrantObjects::AllTablesInSchema { schemas } => {
2804 write!(
2805 f,
2806 "ALL TABLES IN SCHEMA {}",
2807 display_comma_separated(schemas)
2808 )
2809 }
2810 GrantObjects::AllSourcesInSchema { schemas } => {
2811 write!(
2812 f,
2813 "ALL SOURCES IN SCHEMA {}",
2814 display_comma_separated(schemas)
2815 )
2816 }
2817 GrantObjects::AllMviewsInSchema { schemas } => {
2818 write!(
2819 f,
2820 "ALL MATERIALIZED VIEWS IN SCHEMA {}",
2821 display_comma_separated(schemas)
2822 )
2823 }
2824 GrantObjects::AllSinksInSchema { schemas } => {
2825 write!(
2826 f,
2827 "ALL SINKS IN SCHEMA {}",
2828 display_comma_separated(schemas)
2829 )
2830 }
2831 GrantObjects::AllViewsInSchema { schemas } => {
2832 write!(
2833 f,
2834 "ALL VIEWS IN SCHEMA {}",
2835 display_comma_separated(schemas)
2836 )
2837 }
2838 GrantObjects::AllFunctionsInSchema { schemas } => {
2839 write!(
2840 f,
2841 "ALL FUNCTIONS IN SCHEMA {}",
2842 display_comma_separated(schemas)
2843 )
2844 }
2845 GrantObjects::AllSecretsInSchema { schemas } => {
2846 write!(
2847 f,
2848 "ALL SECRETS IN SCHEMA {}",
2849 display_comma_separated(schemas)
2850 )
2851 }
2852 GrantObjects::AllSubscriptionsInSchema { schemas } => {
2853 write!(
2854 f,
2855 "ALL SUBSCRIPTIONS IN SCHEMA {}",
2856 display_comma_separated(schemas)
2857 )
2858 }
2859 GrantObjects::AllConnectionsInSchema { schemas } => {
2860 write!(
2861 f,
2862 "ALL CONNECTIONS IN SCHEMA {}",
2863 display_comma_separated(schemas)
2864 )
2865 }
2866 GrantObjects::Databases(databases) => {
2867 write!(f, "DATABASE {}", display_comma_separated(databases))
2868 }
2869 GrantObjects::Sources(sources) => {
2870 write!(f, "SOURCE {}", display_comma_separated(sources))
2871 }
2872 GrantObjects::Mviews(mviews) => {
2873 write!(f, "MATERIALIZED VIEW {}", display_comma_separated(mviews))
2874 }
2875 GrantObjects::Sinks(sinks) => {
2876 write!(f, "SINK {}", display_comma_separated(sinks))
2877 }
2878 GrantObjects::Views(views) => {
2879 write!(f, "VIEW {}", display_comma_separated(views))
2880 }
2881 GrantObjects::Connections(connections) => {
2882 write!(f, "CONNECTION {}", display_comma_separated(connections))
2883 }
2884 GrantObjects::Subscriptions(subscriptions) => {
2885 write!(f, "SUBSCRIPTION {}", display_comma_separated(subscriptions))
2886 }
2887 GrantObjects::Functions(func_descs) => {
2888 write!(f, "FUNCTION {}", display_comma_separated(func_descs))
2889 }
2890 GrantObjects::Secrets(secrets) => {
2891 write!(f, "SECRET {}", display_comma_separated(secrets))
2892 }
2893 }
2894 }
2895}
2896
2897#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2898pub enum PrivilegeObjectType {
2899 Tables,
2900 Sources,
2901 Sinks,
2902 Mviews,
2903 Views,
2904 Functions,
2905 Connections,
2906 Secrets,
2907 Subscriptions,
2908 Schemas,
2909}
2910
2911impl fmt::Display for PrivilegeObjectType {
2912 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2913 match self {
2914 PrivilegeObjectType::Tables => f.write_str("TABLES")?,
2915 PrivilegeObjectType::Sources => f.write_str("SOURCES")?,
2916 PrivilegeObjectType::Sinks => f.write_str("SINKS")?,
2917 PrivilegeObjectType::Mviews => f.write_str("MATERIALIZED VIEWS")?,
2918 PrivilegeObjectType::Views => f.write_str("VIEWS")?,
2919 PrivilegeObjectType::Functions => f.write_str("FUNCTIONS")?,
2920 PrivilegeObjectType::Connections => f.write_str("CONNECTIONS")?,
2921 PrivilegeObjectType::Secrets => f.write_str("SECRETS")?,
2922 PrivilegeObjectType::Subscriptions => f.write_str("SUBSCRIPTIONS")?,
2923 PrivilegeObjectType::Schemas => f.write_str("SCHEMAS")?,
2924 };
2925 Ok(())
2926 }
2927}
2928
2929#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2930pub enum DefaultPrivilegeOperation {
2931 Grant {
2932 privileges: Privileges,
2933 object_type: PrivilegeObjectType,
2934 grantees: Vec<Ident>,
2935 with_grant_option: bool,
2936 },
2937 Revoke {
2938 privileges: Privileges,
2939 object_type: PrivilegeObjectType,
2940 grantees: Vec<Ident>,
2941 revoke_grant_option: bool,
2942 cascade: bool,
2943 },
2944}
2945
2946impl fmt::Display for DefaultPrivilegeOperation {
2947 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2948 match self {
2949 DefaultPrivilegeOperation::Grant {
2950 privileges,
2951 object_type,
2952 grantees,
2953 with_grant_option,
2954 } => {
2955 write!(
2956 f,
2957 "GRANT {} ON {} TO {}",
2958 privileges,
2959 object_type,
2960 display_comma_separated(grantees)
2961 )?;
2962 if *with_grant_option {
2963 write!(f, " WITH GRANT OPTION")?;
2964 }
2965 }
2966 DefaultPrivilegeOperation::Revoke {
2967 privileges,
2968 object_type,
2969 grantees,
2970 revoke_grant_option,
2971 cascade,
2972 } => {
2973 write!(f, "REVOKE")?;
2974 if *revoke_grant_option {
2975 write!(f, " GRANT OPTION FOR")?;
2976 }
2977 write!(
2978 f,
2979 " {} ON {} FROM {}",
2980 privileges,
2981 object_type,
2982 display_comma_separated(grantees)
2983 )?;
2984 write!(f, " {}", if *cascade { "CASCADE" } else { "RESTRICT" })?;
2985 }
2986 }
2987 Ok(())
2988 }
2989}
2990
2991impl DefaultPrivilegeOperation {
2992 pub fn for_schemas(&self) -> bool {
2993 match &self {
2994 DefaultPrivilegeOperation::Grant { object_type, .. } => {
2995 object_type == &PrivilegeObjectType::Schemas
2996 }
2997 DefaultPrivilegeOperation::Revoke { object_type, .. } => {
2998 object_type == &PrivilegeObjectType::Schemas
2999 }
3000 }
3001 }
3002}
3003
3004#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3005pub enum AssignmentValue {
3006 Expr(Expr),
3008 Default,
3010}
3011
3012impl fmt::Display for AssignmentValue {
3013 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3014 match self {
3015 AssignmentValue::Expr(expr) => write!(f, "{}", expr),
3016 AssignmentValue::Default => f.write_str("DEFAULT"),
3017 }
3018 }
3019}
3020
3021#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3023pub struct Assignment {
3024 pub id: Vec<Ident>,
3025 pub value: AssignmentValue,
3026}
3027
3028impl fmt::Display for Assignment {
3029 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3030 write!(f, "{} = {}", display_separated(&self.id, "."), self.value)
3031 }
3032}
3033
3034#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3035pub enum FunctionArgExpr {
3036 Expr(Expr),
3037 ExprQualifiedWildcard(Expr, Vec<Ident>),
3041 QualifiedWildcard(ObjectName, Option<Vec<Expr>>),
3044 Wildcard(Option<Vec<Expr>>),
3046 SecretRef(SecretRefValue),
3048}
3049
3050impl fmt::Display for FunctionArgExpr {
3051 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3052 match self {
3053 FunctionArgExpr::Expr(expr) => write!(f, "{}", expr),
3054 FunctionArgExpr::ExprQualifiedWildcard(expr, prefix) => {
3055 write!(
3056 f,
3057 "({}){}.*",
3058 expr,
3059 prefix
3060 .iter()
3061 .format_with("", |i, f| f(&format_args!(".{i}")))
3062 )
3063 }
3064 FunctionArgExpr::QualifiedWildcard(prefix, except) => match except {
3065 Some(exprs) => write!(
3066 f,
3067 "{}.* EXCEPT ({})",
3068 prefix,
3069 exprs
3070 .iter()
3071 .map(|v| v.to_string())
3072 .collect::<Vec<String>>()
3073 .as_slice()
3074 .join(", ")
3075 ),
3076 None => write!(f, "{}.*", prefix),
3077 },
3078
3079 FunctionArgExpr::SecretRef(secret_ref) => write!(f, "SECRET {}", secret_ref),
3080 FunctionArgExpr::Wildcard(except) => match except {
3081 Some(exprs) => write!(
3082 f,
3083 "* EXCEPT ({})",
3084 exprs
3085 .iter()
3086 .map(|v| v.to_string())
3087 .collect::<Vec<String>>()
3088 .as_slice()
3089 .join(", ")
3090 ),
3091 None => f.write_str("*"),
3092 },
3093 }
3094 }
3095}
3096
3097#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3098pub enum FunctionArg {
3099 Named { name: Ident, arg: FunctionArgExpr },
3100 Unnamed(FunctionArgExpr),
3101}
3102
3103impl FunctionArg {
3104 pub fn get_expr(&self) -> FunctionArgExpr {
3105 match self {
3106 FunctionArg::Named { name: _, arg } => arg.clone(),
3107 FunctionArg::Unnamed(arg) => arg.clone(),
3108 }
3109 }
3110}
3111
3112impl fmt::Display for FunctionArg {
3113 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3114 match self {
3115 FunctionArg::Named { name, arg } => write!(f, "{} => {}", name, arg),
3116 FunctionArg::Unnamed(unnamed_arg) => write!(f, "{}", unnamed_arg),
3117 }
3118 }
3119}
3120
3121#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3124pub struct FunctionArgList {
3125 pub distinct: bool,
3127 pub args: Vec<FunctionArg>,
3128 pub variadic: bool,
3130 pub order_by: Vec<OrderByExpr>,
3132 pub ignore_nulls: bool,
3134}
3135
3136impl fmt::Display for FunctionArgList {
3137 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3138 write!(f, "(")?;
3139 if self.distinct {
3140 write!(f, "DISTINCT ")?;
3141 }
3142 if self.variadic {
3143 for arg in &self.args[0..self.args.len() - 1] {
3144 write!(f, "{}, ", arg)?;
3145 }
3146 write!(f, "VARIADIC {}", self.args.last().unwrap())?;
3147 } else {
3148 write!(f, "{}", display_comma_separated(&self.args))?;
3149 }
3150 if !self.order_by.is_empty() {
3151 write!(f, " ORDER BY {}", display_comma_separated(&self.order_by))?;
3152 }
3153 if self.ignore_nulls {
3154 write!(f, " IGNORE NULLS")?;
3155 }
3156 write!(f, ")")?;
3157 Ok(())
3158 }
3159}
3160
3161impl FunctionArgList {
3162 pub fn empty() -> Self {
3163 Self {
3164 distinct: false,
3165 args: vec![],
3166 variadic: false,
3167 order_by: vec![],
3168 ignore_nulls: false,
3169 }
3170 }
3171
3172 pub fn args_only(args: Vec<FunctionArg>) -> Self {
3173 Self {
3174 distinct: false,
3175 args,
3176 variadic: false,
3177 order_by: vec![],
3178 ignore_nulls: false,
3179 }
3180 }
3181
3182 pub fn is_args_only(&self) -> bool {
3183 !self.distinct && !self.variadic && self.order_by.is_empty() && !self.ignore_nulls
3184 }
3185
3186 pub fn for_agg(distinct: bool, args: Vec<FunctionArg>, order_by: Vec<OrderByExpr>) -> Self {
3187 Self {
3188 distinct,
3189 args,
3190 variadic: false,
3191 order_by,
3192 ignore_nulls: false,
3193 }
3194 }
3195}
3196
3197#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3199pub struct Function {
3200 pub scalar_as_agg: bool,
3202 pub name: ObjectName,
3204 pub arg_list: FunctionArgList,
3206 pub within_group: Option<Box<OrderByExpr>>,
3209 pub filter: Option<Box<Expr>>,
3211 pub over: Option<Window>,
3213}
3214
3215impl Function {
3216 pub fn no_arg(name: ObjectName) -> Self {
3217 Self {
3218 scalar_as_agg: false,
3219 name,
3220 arg_list: FunctionArgList::empty(),
3221 within_group: None,
3222 filter: None,
3223 over: None,
3224 }
3225 }
3226}
3227
3228impl fmt::Display for Function {
3229 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3230 if self.scalar_as_agg {
3231 write!(f, "AGGREGATE:")?;
3232 }
3233 write!(f, "{}{}", self.name, self.arg_list)?;
3234 if let Some(within_group) = &self.within_group {
3235 write!(f, " WITHIN GROUP (ORDER BY {})", within_group)?;
3236 }
3237 if let Some(filter) = &self.filter {
3238 write!(f, " FILTER (WHERE {})", filter)?;
3239 }
3240 if let Some(o) = &self.over {
3241 write!(f, " OVER {}", o)?;
3242 }
3243 Ok(())
3244 }
3245}
3246
3247#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3248pub enum ObjectType {
3249 Table,
3250 View,
3251 MaterializedView,
3252 Index,
3253 Schema,
3254 Source,
3255 Sink,
3256 Database,
3257 User,
3258 Connection,
3259 Secret,
3260 Subscription,
3261}
3262
3263impl fmt::Display for ObjectType {
3264 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3265 f.write_str(match self {
3266 ObjectType::Table => "TABLE",
3267 ObjectType::View => "VIEW",
3268 ObjectType::MaterializedView => "MATERIALIZED VIEW",
3269 ObjectType::Index => "INDEX",
3270 ObjectType::Schema => "SCHEMA",
3271 ObjectType::Source => "SOURCE",
3272 ObjectType::Sink => "SINK",
3273 ObjectType::Database => "DATABASE",
3274 ObjectType::User => "USER",
3275 ObjectType::Secret => "SECRET",
3276 ObjectType::Connection => "CONNECTION",
3277 ObjectType::Subscription => "SUBSCRIPTION",
3278 })
3279 }
3280}
3281
3282impl ParseTo for ObjectType {
3283 fn parse_to(parser: &mut Parser<'_>) -> ModalResult<Self> {
3284 let object_type = if parser.parse_keyword(Keyword::TABLE) {
3285 ObjectType::Table
3286 } else if parser.parse_keyword(Keyword::VIEW) {
3287 ObjectType::View
3288 } else if parser.parse_keywords(&[Keyword::MATERIALIZED, Keyword::VIEW]) {
3289 ObjectType::MaterializedView
3290 } else if parser.parse_keyword(Keyword::SOURCE) {
3291 ObjectType::Source
3292 } else if parser.parse_keyword(Keyword::SINK) {
3293 ObjectType::Sink
3294 } else if parser.parse_keyword(Keyword::INDEX) {
3295 ObjectType::Index
3296 } else if parser.parse_keyword(Keyword::SCHEMA) {
3297 ObjectType::Schema
3298 } else if parser.parse_keyword(Keyword::DATABASE) {
3299 ObjectType::Database
3300 } else if parser.parse_keyword(Keyword::USER) {
3301 ObjectType::User
3302 } else if parser.parse_keyword(Keyword::CONNECTION) {
3303 ObjectType::Connection
3304 } else if parser.parse_keyword(Keyword::SECRET) {
3305 ObjectType::Secret
3306 } else if parser.parse_keyword(Keyword::SUBSCRIPTION) {
3307 ObjectType::Subscription
3308 } else {
3309 return parser.expected(
3310 "TABLE, VIEW, INDEX, MATERIALIZED VIEW, SOURCE, SINK, SUBSCRIPTION, SCHEMA, DATABASE, USER, SECRET or CONNECTION after DROP",
3311 );
3312 };
3313 Ok(object_type)
3314 }
3315}
3316
3317#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3318pub struct SqlOption {
3319 pub name: ObjectName,
3320 pub value: SqlOptionValue,
3321}
3322
3323impl SqlOption {
3324 pub fn from_secret_ref(name: &str, secret_ref: SecretRefValue) -> Self {
3326 Self {
3327 name: ObjectName(name.split('.').map(Ident::from_real_value).collect()),
3328 value: SqlOptionValue::SecretRef(secret_ref),
3329 }
3330 }
3331}
3332
3333impl fmt::Display for SqlOption {
3334 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3335 let should_redact = REDACT_SQL_OPTION_KEYWORDS
3336 .try_with(|keywords| {
3337 let sql_option_name = self.name.real_value().to_lowercase();
3338 keywords.iter().any(|k| sql_option_name.contains(k))
3339 })
3340 .unwrap_or(false);
3341 if should_redact {
3342 write!(f, "{} = [REDACTED]", self.name)
3343 } else {
3344 write!(f, "{} = {}", self.name, self.value)
3345 }
3346 }
3347}
3348
3349impl TryFrom<(&String, &String)> for SqlOption {
3350 type Error = ParserError;
3351
3352 fn try_from((name, value): (&String, &String)) -> Result<Self, Self::Error> {
3353 let name_parts: Vec<&str> = name.split('.').collect();
3357 let object_name = ObjectName(name_parts.into_iter().map(Ident::from_real_value).collect());
3358
3359 let escaped_value = value.replace('\'', "''");
3363 let query = format!("{} = '{}'", object_name, escaped_value);
3364 let mut tokenizer = Tokenizer::new(query.as_str());
3365 let tokens = tokenizer.tokenize_with_location()?;
3366 let mut parser = Parser(&tokens);
3367 parser
3368 .parse_sql_option()
3369 .map_err(|e| ParserError::ParserError(e.to_string()))
3370 }
3371}
3372
3373#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3374pub enum SqlOptionValue {
3375 Value(Value),
3376 SecretRef(SecretRefValue),
3377 ConnectionRef(ConnectionRefValue),
3378 BackfillOrder(BackfillOrderStrategy),
3379}
3380
3381impl SqlOptionValue {
3382 pub const fn null() -> Self {
3384 Self::Value(Value::Null)
3385 }
3386}
3387
3388impl fmt::Display for SqlOptionValue {
3389 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3390 match self {
3391 SqlOptionValue::Value(value) => write!(f, "{}", value),
3392 SqlOptionValue::SecretRef(secret_ref) => write!(f, "secret {}", secret_ref),
3393 SqlOptionValue::ConnectionRef(connection_ref) => {
3394 write!(f, "{}", connection_ref)
3395 }
3396 SqlOptionValue::BackfillOrder(order) => {
3397 write!(f, "{}", order)
3398 }
3399 }
3400 }
3401}
3402
3403impl From<Value> for SqlOptionValue {
3404 fn from(value: Value) -> Self {
3405 SqlOptionValue::Value(value)
3406 }
3407}
3408
3409#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3410pub enum EmitMode {
3411 Immediately,
3412 OnWindowClose,
3413}
3414
3415impl fmt::Display for EmitMode {
3416 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3417 f.write_str(match self {
3418 EmitMode::Immediately => "IMMEDIATELY",
3419 EmitMode::OnWindowClose => "ON WINDOW CLOSE",
3420 })
3421 }
3422}
3423
3424#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
3425pub enum OnConflict {
3426 UpdateFull,
3427 Nothing,
3428 UpdateIfNotNull,
3429}
3430
3431impl fmt::Display for OnConflict {
3432 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3433 f.write_str(match self {
3434 OnConflict::UpdateFull => "DO UPDATE FULL",
3435 OnConflict::Nothing => "DO NOTHING",
3436 OnConflict::UpdateIfNotNull => "DO UPDATE IF NOT NULL",
3437 })
3438 }
3439}
3440
3441#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3442pub enum Engine {
3443 Hummock,
3444 Iceberg,
3445}
3446
3447impl fmt::Display for crate::ast::Engine {
3448 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3449 f.write_str(match self {
3450 crate::ast::Engine::Hummock => "HUMMOCK",
3451 crate::ast::Engine::Iceberg => "ICEBERG",
3452 })
3453 }
3454}
3455
3456#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3457pub enum SetTimeZoneValue {
3458 Ident(Ident),
3459 Literal(Value),
3460 Local,
3461 Default,
3462}
3463
3464impl fmt::Display for SetTimeZoneValue {
3465 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3466 match self {
3467 SetTimeZoneValue::Ident(ident) => write!(f, "{}", ident),
3468 SetTimeZoneValue::Literal(value) => write!(f, "{}", value),
3469 SetTimeZoneValue::Local => f.write_str("LOCAL"),
3470 SetTimeZoneValue::Default => f.write_str("DEFAULT"),
3471 }
3472 }
3473}
3474
3475#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3476pub enum TransactionMode {
3477 AccessMode(TransactionAccessMode),
3478 IsolationLevel(TransactionIsolationLevel),
3479}
3480
3481impl fmt::Display for TransactionMode {
3482 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3483 use TransactionMode::*;
3484 match self {
3485 AccessMode(access_mode) => write!(f, "{}", access_mode),
3486 IsolationLevel(iso_level) => write!(f, "ISOLATION LEVEL {}", iso_level),
3487 }
3488 }
3489}
3490
3491#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3492pub enum TransactionAccessMode {
3493 ReadOnly,
3494 ReadWrite,
3495}
3496
3497impl fmt::Display for TransactionAccessMode {
3498 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3499 use TransactionAccessMode::*;
3500 f.write_str(match self {
3501 ReadOnly => "READ ONLY",
3502 ReadWrite => "READ WRITE",
3503 })
3504 }
3505}
3506
3507#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3508pub enum TransactionIsolationLevel {
3509 ReadUncommitted,
3510 ReadCommitted,
3511 RepeatableRead,
3512 Serializable,
3513}
3514
3515impl fmt::Display for TransactionIsolationLevel {
3516 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3517 use TransactionIsolationLevel::*;
3518 f.write_str(match self {
3519 ReadUncommitted => "READ UNCOMMITTED",
3520 ReadCommitted => "READ COMMITTED",
3521 RepeatableRead => "REPEATABLE READ",
3522 Serializable => "SERIALIZABLE",
3523 })
3524 }
3525}
3526
3527#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3528pub enum ShowStatementFilter {
3529 Like(String),
3530 ILike(String),
3531 Where(Expr),
3532}
3533
3534impl fmt::Display for ShowStatementFilter {
3535 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3536 use ShowStatementFilter::*;
3537 match self {
3538 Like(pattern) => write!(f, "LIKE '{}'", value::escape_single_quote_string(pattern)),
3539 ILike(pattern) => write!(f, "ILIKE {}", value::escape_single_quote_string(pattern)),
3540 Where(expr) => write!(f, "WHERE {}", expr),
3541 }
3542 }
3543}
3544
3545#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3547pub enum DropFunctionOption {
3548 Restrict,
3549 Cascade,
3550}
3551
3552impl fmt::Display for DropFunctionOption {
3553 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3554 match self {
3555 DropFunctionOption::Restrict => write!(f, "RESTRICT "),
3556 DropFunctionOption::Cascade => write!(f, "CASCADE "),
3557 }
3558 }
3559}
3560
3561#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3563pub struct FunctionDesc {
3564 pub name: ObjectName,
3565 pub args: Option<Vec<OperateFunctionArg>>,
3566}
3567
3568impl fmt::Display for FunctionDesc {
3569 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3570 write!(f, "{}", self.name)?;
3571 if let Some(args) = &self.args {
3572 write!(f, "({})", display_comma_separated(args))?;
3573 }
3574 Ok(())
3575 }
3576}
3577
3578#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3580pub struct OperateFunctionArg {
3581 pub mode: Option<ArgMode>,
3582 pub name: Option<Ident>,
3583 pub data_type: DataType,
3584 pub default_expr: Option<Expr>,
3585}
3586
3587impl OperateFunctionArg {
3588 pub fn unnamed(data_type: DataType) -> Self {
3590 Self {
3591 mode: None,
3592 name: None,
3593 data_type,
3594 default_expr: None,
3595 }
3596 }
3597
3598 pub fn with_name(name: &str, data_type: DataType) -> Self {
3600 Self {
3601 mode: None,
3602 name: Some(name.into()),
3603 data_type,
3604 default_expr: None,
3605 }
3606 }
3607}
3608
3609impl fmt::Display for OperateFunctionArg {
3610 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3611 if let Some(mode) = &self.mode {
3612 write!(f, "{} ", mode)?;
3613 }
3614 if let Some(name) = &self.name {
3615 write!(f, "{} ", name)?;
3616 }
3617 write!(f, "{}", self.data_type)?;
3618 if let Some(default_expr) = &self.default_expr {
3619 write!(f, " = {}", default_expr)?;
3620 }
3621 Ok(())
3622 }
3623}
3624
3625#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3627pub enum ArgMode {
3628 In,
3629 Out,
3630 InOut,
3631}
3632
3633impl fmt::Display for ArgMode {
3634 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3635 match self {
3636 ArgMode::In => write!(f, "IN"),
3637 ArgMode::Out => write!(f, "OUT"),
3638 ArgMode::InOut => write!(f, "INOUT"),
3639 }
3640 }
3641}
3642
3643#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3645pub enum FunctionBehavior {
3646 Immutable,
3647 Stable,
3648 Volatile,
3649}
3650
3651impl fmt::Display for FunctionBehavior {
3652 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3653 match self {
3654 FunctionBehavior::Immutable => write!(f, "IMMUTABLE"),
3655 FunctionBehavior::Stable => write!(f, "STABLE"),
3656 FunctionBehavior::Volatile => write!(f, "VOLATILE"),
3657 }
3658 }
3659}
3660
3661#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3662pub enum FunctionDefinition {
3663 Identifier(String),
3664 SingleQuotedDef(String),
3665 DoubleDollarDef(String),
3666}
3667
3668impl fmt::Display for FunctionDefinition {
3669 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3670 match self {
3671 FunctionDefinition::Identifier(s) => write!(f, "{s}")?,
3672 FunctionDefinition::SingleQuotedDef(s) => write!(f, "'{s}'")?,
3673 FunctionDefinition::DoubleDollarDef(s) => write!(f, "$${s}$$")?,
3674 }
3675 Ok(())
3676 }
3677}
3678
3679impl FunctionDefinition {
3680 pub fn as_str(&self) -> &str {
3682 match self {
3683 FunctionDefinition::Identifier(s) => s,
3684 FunctionDefinition::SingleQuotedDef(s) => s,
3685 FunctionDefinition::DoubleDollarDef(s) => s,
3686 }
3687 }
3688
3689 pub fn into_string(self) -> String {
3691 match self {
3692 FunctionDefinition::Identifier(s) => s,
3693 FunctionDefinition::SingleQuotedDef(s) => s,
3694 FunctionDefinition::DoubleDollarDef(s) => s,
3695 }
3696 }
3697}
3698
3699#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3701pub enum CreateFunctionReturns {
3702 Value(DataType),
3704 Table(Vec<TableColumnDef>),
3706}
3707
3708impl fmt::Display for CreateFunctionReturns {
3709 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3710 match self {
3711 Self::Value(data_type) => write!(f, "RETURNS {}", data_type),
3712 Self::Table(columns) => {
3713 write!(f, "RETURNS TABLE ({})", display_comma_separated(columns))
3714 }
3715 }
3716 }
3717}
3718
3719#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3721pub struct TableColumnDef {
3722 pub name: Ident,
3723 pub data_type: DataType,
3724}
3725
3726impl fmt::Display for TableColumnDef {
3727 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3728 write!(f, "{} {}", self.name, self.data_type)
3729 }
3730}
3731
3732#[derive(Debug, Default, Clone, PartialEq, Eq, Hash)]
3737pub struct CreateFunctionBody {
3738 pub language: Option<Ident>,
3740 pub runtime: Option<Ident>,
3742
3743 pub behavior: Option<FunctionBehavior>,
3745 pub as_: Option<FunctionDefinition>,
3749 pub return_: Option<Expr>,
3751 pub using: Option<CreateFunctionUsing>,
3753}
3754
3755impl fmt::Display for CreateFunctionBody {
3756 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3757 if let Some(language) = &self.language {
3758 write!(f, " LANGUAGE {language}")?;
3759 }
3760 if let Some(runtime) = &self.runtime {
3761 write!(f, " RUNTIME {runtime}")?;
3762 }
3763 if let Some(behavior) = &self.behavior {
3764 write!(f, " {behavior}")?;
3765 }
3766 if let Some(definition) = &self.as_ {
3767 write!(f, " AS {definition}")?;
3768 }
3769 if let Some(expr) = &self.return_ {
3770 write!(f, " RETURN {expr}")?;
3771 }
3772 if let Some(using) = &self.using {
3773 write!(f, " {using}")?;
3774 }
3775 Ok(())
3776 }
3777}
3778
3779#[derive(Debug, Default, Clone, PartialEq, Eq, Hash)]
3780pub struct CreateFunctionWithOptions {
3781 pub always_retry_on_network_error: Option<bool>,
3783 pub r#async: Option<bool>,
3785 pub batch: Option<bool>,
3787}
3788
3789impl TryFrom<Vec<SqlOption>> for CreateFunctionWithOptions {
3791 type Error = StrError;
3792
3793 fn try_from(with_options: Vec<SqlOption>) -> Result<Self, Self::Error> {
3794 let mut options = Self::default();
3795 for option in with_options {
3796 match option.name.to_string().to_lowercase().as_str() {
3797 "always_retry_on_network_error" => {
3798 options.always_retry_on_network_error = Some(matches!(
3799 option.value,
3800 SqlOptionValue::Value(Value::Boolean(true))
3801 ));
3802 }
3803 "async" => {
3804 options.r#async = Some(matches!(
3805 option.value,
3806 SqlOptionValue::Value(Value::Boolean(true))
3807 ))
3808 }
3809 "batch" => {
3810 options.batch = Some(matches!(
3811 option.value,
3812 SqlOptionValue::Value(Value::Boolean(true))
3813 ))
3814 }
3815 _ => {
3816 return Err(StrError(format!("unknown option: {}", option.name)));
3817 }
3818 }
3819 }
3820 Ok(options)
3821 }
3822}
3823
3824impl Display for CreateFunctionWithOptions {
3825 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3826 if self == &Self::default() {
3827 return Ok(());
3828 }
3829 let mut options = vec![];
3830 if let Some(v) = self.always_retry_on_network_error {
3831 options.push(format!("always_retry_on_network_error = {}", v));
3832 }
3833 if let Some(v) = self.r#async {
3834 options.push(format!("async = {}", v));
3835 }
3836 if let Some(v) = self.batch {
3837 options.push(format!("batch = {}", v));
3838 }
3839 write!(f, " WITH ( {} )", display_comma_separated(&options))
3840 }
3841}
3842
3843#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3844pub enum CreateFunctionUsing {
3845 Link(String),
3846 Base64(String),
3847}
3848
3849impl fmt::Display for CreateFunctionUsing {
3850 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3851 write!(f, "USING ")?;
3852 match self {
3853 CreateFunctionUsing::Link(uri) => write!(f, "LINK '{uri}'"),
3854 CreateFunctionUsing::Base64(s) => {
3855 write!(f, "BASE64 '{s}'")
3856 }
3857 }
3858 }
3859}
3860
3861#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3862pub struct ConfigParam {
3863 pub param: Ident,
3864 pub value: SetVariableValue,
3865}
3866
3867impl fmt::Display for ConfigParam {
3868 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3869 write!(f, "SET {} = {}", self.param, self.value)
3870 }
3871}
3872
3873#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3874pub enum SetVariableValue {
3875 Single(SetVariableValueSingle),
3876 List(Vec<SetVariableValueSingle>),
3877 Default,
3878}
3879
3880impl From<SetVariableValueSingle> for SetVariableValue {
3881 fn from(value: SetVariableValueSingle) -> Self {
3882 SetVariableValue::Single(value)
3883 }
3884}
3885
3886impl fmt::Display for SetVariableValue {
3887 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3888 use SetVariableValue::*;
3889 match self {
3890 Single(val) => write!(f, "{}", val),
3891 List(list) => write!(f, "{}", display_comma_separated(list),),
3892 Default => write!(f, "DEFAULT"),
3893 }
3894 }
3895}
3896
3897#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3898pub enum SetVariableValueSingle {
3899 Ident(Ident),
3900 Literal(Value),
3901 Raw(String),
3902}
3903
3904impl SetVariableValueSingle {
3905 pub fn to_string_unquoted(&self) -> String {
3906 match self {
3907 Self::Literal(Value::SingleQuotedString(s))
3908 | Self::Literal(Value::DoubleQuotedString(s))
3909 | Self::Raw(s) => s.clone(),
3910 _ => self.to_string(),
3911 }
3912 }
3913}
3914
3915impl fmt::Display for SetVariableValueSingle {
3916 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3917 use SetVariableValueSingle::*;
3918 match self {
3919 Ident(ident) => write!(f, "{}", ident),
3920 Literal(literal) => write!(f, "{}", literal),
3921 Raw(raw) => write!(f, "{}", raw),
3922 }
3923 }
3924}
3925
3926#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3927pub enum AsOf {
3928 ProcessTime,
3929 ProcessTimeBroadcast,
3933 ProcessTimeWithInterval((String, DateTimeField)),
3935 TimestampNum(i64),
3937 TimestampString(String),
3938 VersionNum(i64),
3939 VersionString(String),
3940}
3941
3942impl fmt::Display for AsOf {
3943 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3944 use AsOf::*;
3945 match self {
3946 ProcessTime | ProcessTimeBroadcast => {
3947 write!(f, " FOR SYSTEM_TIME AS OF PROCTIME()")
3948 }
3949 ProcessTimeWithInterval((value, leading_field)) => write!(
3950 f,
3951 " FOR SYSTEM_TIME AS OF NOW() - '{}' {}",
3952 value, leading_field
3953 ),
3954 TimestampNum(ts) => write!(f, " FOR SYSTEM_TIME AS OF {}", ts),
3955 TimestampString(ts) => write!(f, " FOR SYSTEM_TIME AS OF '{}'", ts),
3956 VersionNum(v) => write!(f, " FOR SYSTEM_VERSION AS OF {}", v),
3957 VersionString(v) => write!(f, " FOR SYSTEM_VERSION AS OF '{}'", v),
3958 }
3959 }
3960}
3961
3962#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3963pub enum DiscardType {
3964 All,
3965}
3966
3967impl fmt::Display for DiscardType {
3968 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3969 use DiscardType::*;
3970 match self {
3971 All => write!(f, "ALL"),
3972 }
3973 }
3974}
3975
3976#[derive(Debug, Default, Clone, PartialEq, Eq, Hash)]
3979pub enum BackfillOrderStrategy {
3980 #[default]
3981 Default,
3982 None,
3983 Auto,
3984 Fixed(Vec<(ObjectName, ObjectName)>),
3985}
3986
3987impl fmt::Display for BackfillOrderStrategy {
3988 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3989 use BackfillOrderStrategy::*;
3990 match self {
3991 Default => write!(f, "DEFAULT"),
3992 None => write!(f, "NONE"),
3993 Auto => write!(f, "AUTO"),
3994 Fixed(map) => {
3995 let mut parts = vec![];
3996 for (start, end) in map {
3997 parts.push(format!("{} -> {}", start, end));
3998 }
3999 write!(f, "FIXED({})", display_comma_separated(&parts))
4000 }
4001 }
4002 }
4003}
4004
4005impl Statement {
4006 pub fn to_redacted_string(&self, keywords: RedactSqlOptionKeywordsRef) -> String {
4007 REDACT_SQL_OPTION_KEYWORDS.sync_scope(keywords, || self.to_string_unchecked())
4008 }
4009
4010 pub fn default_create_table(name: ObjectName) -> Self {
4012 Self::CreateTable {
4013 name,
4014 or_replace: false,
4015 temporary: false,
4016 if_not_exists: false,
4017 columns: Vec::new(),
4018 wildcard_idx: None,
4019 constraints: Vec::new(),
4020 with_options: Vec::new(),
4021 format_encode: None,
4022 source_watermarks: Vec::new(),
4023 append_only: false,
4024 on_conflict: None,
4025 with_version_columns: Vec::new(),
4026 query: None,
4027 cdc_table_info: None,
4028 include_column_options: Vec::new(),
4029 webhook_info: None,
4030 engine: Engine::Hummock,
4031 }
4032 }
4033}
4034
4035#[cfg(test)]
4036mod tests {
4037 use super::*;
4038
4039 #[test]
4040 fn test_grouping_sets_display() {
4041 let grouping_sets = Expr::GroupingSets(vec![
4043 vec![Expr::Identifier(Ident::new_unchecked("a"))],
4044 vec![Expr::Identifier(Ident::new_unchecked("b"))],
4045 ]);
4046 assert_eq!("GROUPING SETS ((a), (b))", format!("{}", grouping_sets));
4047
4048 let grouping_sets = Expr::GroupingSets(vec![vec![
4050 Expr::Identifier(Ident::new_unchecked("a")),
4051 Expr::Identifier(Ident::new_unchecked("b")),
4052 ]]);
4053 assert_eq!("GROUPING SETS ((a, b))", format!("{}", grouping_sets));
4054
4055 let grouping_sets = Expr::GroupingSets(vec![
4057 vec![
4058 Expr::Identifier(Ident::new_unchecked("a")),
4059 Expr::Identifier(Ident::new_unchecked("b")),
4060 ],
4061 vec![
4062 Expr::Identifier(Ident::new_unchecked("c")),
4063 Expr::Identifier(Ident::new_unchecked("d")),
4064 ],
4065 ]);
4066 assert_eq!(
4067 "GROUPING SETS ((a, b), (c, d))",
4068 format!("{}", grouping_sets)
4069 );
4070 }
4071
4072 #[test]
4073 fn test_rollup_display() {
4074 let rollup = Expr::Rollup(vec![vec![Expr::Identifier(Ident::new_unchecked("a"))]]);
4075 assert_eq!("ROLLUP (a)", format!("{}", rollup));
4076
4077 let rollup = Expr::Rollup(vec![vec![
4078 Expr::Identifier(Ident::new_unchecked("a")),
4079 Expr::Identifier(Ident::new_unchecked("b")),
4080 ]]);
4081 assert_eq!("ROLLUP ((a, b))", format!("{}", rollup));
4082
4083 let rollup = Expr::Rollup(vec![
4084 vec![Expr::Identifier(Ident::new_unchecked("a"))],
4085 vec![Expr::Identifier(Ident::new_unchecked("b"))],
4086 ]);
4087 assert_eq!("ROLLUP (a, b)", format!("{}", rollup));
4088
4089 let rollup = Expr::Rollup(vec![
4090 vec![Expr::Identifier(Ident::new_unchecked("a"))],
4091 vec![
4092 Expr::Identifier(Ident::new_unchecked("b")),
4093 Expr::Identifier(Ident::new_unchecked("c")),
4094 ],
4095 vec![Expr::Identifier(Ident::new_unchecked("d"))],
4096 ]);
4097 assert_eq!("ROLLUP (a, (b, c), d)", format!("{}", rollup));
4098 }
4099
4100 #[test]
4101 fn test_cube_display() {
4102 let cube = Expr::Cube(vec![vec![Expr::Identifier(Ident::new_unchecked("a"))]]);
4103 assert_eq!("CUBE (a)", format!("{}", cube));
4104
4105 let cube = Expr::Cube(vec![vec![
4106 Expr::Identifier(Ident::new_unchecked("a")),
4107 Expr::Identifier(Ident::new_unchecked("b")),
4108 ]]);
4109 assert_eq!("CUBE ((a, b))", format!("{}", cube));
4110
4111 let cube = Expr::Cube(vec![
4112 vec![Expr::Identifier(Ident::new_unchecked("a"))],
4113 vec![Expr::Identifier(Ident::new_unchecked("b"))],
4114 ]);
4115 assert_eq!("CUBE (a, b)", format!("{}", cube));
4116
4117 let cube = Expr::Cube(vec![
4118 vec![Expr::Identifier(Ident::new_unchecked("a"))],
4119 vec![
4120 Expr::Identifier(Ident::new_unchecked("b")),
4121 Expr::Identifier(Ident::new_unchecked("c")),
4122 ],
4123 vec![Expr::Identifier(Ident::new_unchecked("d"))],
4124 ]);
4125 assert_eq!("CUBE (a, (b, c), d)", format!("{}", cube));
4126 }
4127
4128 #[test]
4129 fn test_array_index_display() {
4130 let array_index = Expr::Index {
4131 obj: Box::new(Expr::Identifier(Ident::new_unchecked("v1"))),
4132 index: Box::new(Expr::Value(Value::Number("1".into()))),
4133 };
4134 assert_eq!("v1[1]", format!("{}", array_index));
4135
4136 let array_index2 = Expr::Index {
4137 obj: Box::new(array_index),
4138 index: Box::new(Expr::Value(Value::Number("1".into()))),
4139 };
4140 assert_eq!("v1[1][1]", format!("{}", array_index2));
4141 }
4142
4143 #[test]
4144 fn test_nested_op_display() {
4146 let binary_op = Expr::BinaryOp {
4147 left: Box::new(Expr::Value(Value::Boolean(true))),
4148 op: BinaryOperator::Or,
4149 right: Box::new(Expr::IsNotFalse(Box::new(Expr::Value(Value::Boolean(
4150 true,
4151 ))))),
4152 };
4153 assert_eq!("true OR true IS NOT FALSE", format!("{}", binary_op));
4154
4155 let unary_op = Expr::UnaryOp {
4156 op: UnaryOperator::Not,
4157 expr: Box::new(Expr::IsNotFalse(Box::new(Expr::Value(Value::Boolean(
4158 true,
4159 ))))),
4160 };
4161 assert_eq!("NOT true IS NOT FALSE", format!("{}", unary_op));
4162 }
4163
4164 #[test]
4165 fn test_create_function_display() {
4166 let create_function = Statement::CreateFunction {
4167 or_replace: false,
4168 temporary: false,
4169 if_not_exists: false,
4170 name: ObjectName(vec![Ident::new_unchecked("foo")]),
4171 args: Some(vec![OperateFunctionArg::unnamed(DataType::Int)]),
4172 returns: Some(CreateFunctionReturns::Value(DataType::Int)),
4173 params: CreateFunctionBody {
4174 language: Some(Ident::new_unchecked("python")),
4175 runtime: None,
4176 behavior: Some(FunctionBehavior::Immutable),
4177 as_: Some(FunctionDefinition::SingleQuotedDef("SELECT 1".to_owned())),
4178 return_: None,
4179 using: None,
4180 },
4181 with_options: CreateFunctionWithOptions {
4182 always_retry_on_network_error: None,
4183 r#async: None,
4184 batch: None,
4185 },
4186 };
4187 assert_eq!(
4188 "CREATE FUNCTION foo(INT) RETURNS INT LANGUAGE python IMMUTABLE AS 'SELECT 1'",
4189 format!("{}", create_function)
4190 );
4191 let create_function = Statement::CreateFunction {
4192 or_replace: false,
4193 temporary: false,
4194 if_not_exists: false,
4195 name: ObjectName(vec![Ident::new_unchecked("foo")]),
4196 args: Some(vec![OperateFunctionArg::unnamed(DataType::Int)]),
4197 returns: Some(CreateFunctionReturns::Value(DataType::Int)),
4198 params: CreateFunctionBody {
4199 language: Some(Ident::new_unchecked("python")),
4200 runtime: None,
4201 behavior: Some(FunctionBehavior::Immutable),
4202 as_: Some(FunctionDefinition::SingleQuotedDef("SELECT 1".to_owned())),
4203 return_: None,
4204 using: None,
4205 },
4206 with_options: CreateFunctionWithOptions {
4207 always_retry_on_network_error: Some(true),
4208 r#async: None,
4209 batch: None,
4210 },
4211 };
4212 assert_eq!(
4213 "CREATE FUNCTION foo(INT) RETURNS INT LANGUAGE python IMMUTABLE AS 'SELECT 1' WITH ( always_retry_on_network_error = true )",
4214 format!("{}", create_function)
4215 );
4216 }
4217
4218 #[test]
4219 fn test_sql_option_from_secret_ref() {
4220 let text_option = SqlOption::from_secret_ref(
4221 "password",
4222 SecretRefValue {
4223 secret_name: ObjectName(vec![
4224 Ident::from_real_value("public"),
4225 Ident::from_real_value("s2"),
4226 ]),
4227 ref_as: SecretRefAsType::Text,
4228 },
4229 );
4230
4231 assert!(matches!(text_option.value, SqlOptionValue::SecretRef(_)));
4232 assert_eq!(text_option.to_string(), "password = secret public.s2");
4233
4234 let file_option = SqlOption::from_secret_ref(
4235 "certificate",
4236 SecretRefValue {
4237 secret_name: ObjectName(vec![Ident::from_real_value("cert")]),
4238 ref_as: SecretRefAsType::File,
4239 },
4240 );
4241
4242 assert_eq!(file_option.to_string(), "certificate = secret cert AS FILE");
4243 }
4244}