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